can: c_can: Add support for eg20t (pch_can)

Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Alexander Stein 2014-04-07 08:52:03 +02:00 коммит произвёл Marc Kleine-Budde
Родитель 8e964fe21d
Коммит abcd7f750a
1 изменённых файлов: 50 добавлений и 1 удалений

Просмотреть файл

@ -19,9 +19,13 @@
#include "c_can.h" #include "c_can.h"
#define PCI_DEVICE_ID_PCH_CAN 0x8818
#define PCH_PCI_SOFT_RESET 0x01fc
enum c_can_pci_reg_align { enum c_can_pci_reg_align {
C_CAN_REG_ALIGN_16, C_CAN_REG_ALIGN_16,
C_CAN_REG_ALIGN_32, C_CAN_REG_ALIGN_32,
C_CAN_REG_32,
}; };
struct c_can_pci_data { struct c_can_pci_data {
@ -31,6 +35,10 @@ struct c_can_pci_data {
enum c_can_pci_reg_align reg_align; enum c_can_pci_reg_align reg_align;
/* Set the frequency */ /* Set the frequency */
unsigned int freq; unsigned int freq;
/* PCI bar number */
int bar;
/* Callback for reset */
void (*init)(const struct c_can_priv *priv, bool enable);
}; };
/* /*
@ -63,6 +71,29 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]); writew(val, priv->base + 2 * priv->regs[index]);
} }
static u16 c_can_pci_read_reg_32bit(struct c_can_priv *priv,
enum reg index)
{
return (u16)ioread32(priv->base + 2 * priv->regs[index]);
}
static void c_can_pci_write_reg_32bit(struct c_can_priv *priv,
enum reg index, u16 val)
{
iowrite32((u32)val, priv->base + 2 * priv->regs[index]);
}
static void c_can_pci_reset_pch(const struct c_can_priv *priv, bool enable)
{
if (enable) {
u32 __iomem *addr = priv->base + PCH_PCI_SOFT_RESET;
/* write to sw reset register */
iowrite32(1, addr);
iowrite32(0, addr);
}
}
static int c_can_pci_probe(struct pci_dev *pdev, static int c_can_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
@ -87,7 +118,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev); pci_set_master(pdev);
pci_enable_msi(pdev); pci_enable_msi(pdev);
addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); addr = pci_iomap(pdev, c_can_pci_data->bar,
pci_resource_len(pdev, c_can_pci_data->bar));
if (!addr) { if (!addr) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"device has no PCI memory resources, " "device has no PCI memory resources, "
@ -142,11 +174,17 @@ static int c_can_pci_probe(struct pci_dev *pdev,
priv->read_reg = c_can_pci_read_reg_aligned_to_16bit; priv->read_reg = c_can_pci_read_reg_aligned_to_16bit;
priv->write_reg = c_can_pci_write_reg_aligned_to_16bit; priv->write_reg = c_can_pci_write_reg_aligned_to_16bit;
break; break;
case C_CAN_REG_32:
priv->read_reg = c_can_pci_read_reg_32bit;
priv->write_reg = c_can_pci_write_reg_32bit;
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
goto out_free_c_can; goto out_free_c_can;
} }
priv->raminit = c_can_pci_data->init;
ret = register_c_can_dev(dev); ret = register_c_can_dev(dev);
if (ret) { if (ret) {
dev_err(&pdev->dev, "registering %s failed (err=%d)\n", dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
@ -193,6 +231,15 @@ static struct c_can_pci_data c_can_sta2x11= {
.type = BOSCH_C_CAN, .type = BOSCH_C_CAN,
.reg_align = C_CAN_REG_ALIGN_32, .reg_align = C_CAN_REG_ALIGN_32,
.freq = 52000000, /* 52 Mhz */ .freq = 52000000, /* 52 Mhz */
.bar = 0,
};
static struct c_can_pci_data c_can_pch = {
.type = BOSCH_C_CAN,
.reg_align = C_CAN_REG_32,
.freq = 50000000, /* 50 MHz */
.init = c_can_pci_reset_pch,
.bar = 1,
}; };
#define C_CAN_ID(_vend, _dev, _driverdata) { \ #define C_CAN_ID(_vend, _dev, _driverdata) { \
@ -202,6 +249,8 @@ static struct c_can_pci_data c_can_sta2x11= {
static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = { static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {
C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN, C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,
c_can_sta2x11), c_can_sta2x11),
C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN,
c_can_pch),
{}, {},
}; };
static struct pci_driver c_can_pci_driver = { static struct pci_driver c_can_pci_driver = {