diff options
author | David S. Miller <davem@davemloft.net> | 2014-04-26 12:32:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-04-26 12:32:27 -0400 |
commit | 98a20b735bb4ba5d97d35cf69eb0d8a2ee505de2 (patch) | |
tree | 10e37c1008d30a1494c0aa7282de33d0ed4d24df /drivers/net/can/c_can/c_can_pci.c | |
parent | 16b463061c9f27d00f6bb4cb0b7b29e06c4437f1 (diff) | |
parent | 0f8dced5ef49159698a98f744e809a3fff32b827 (diff) |
Merge tag 'linux-can-next-for-3.16-20140425' of git://gitorious.org/linux-can/linux-can-next
Marc Kleine-Budde says:
====================
this is a pull request of 10 patches for net-next/master.
It consists of three patches by Alexander Shiyan, which improve the
mcp251x driver. Stefano Babic's patch move the SPI driver into a sub
folder. The three patches by Olivier Sobrie add support for the Kvaser
Leaf v2 and usb mini PCIe hardware to the existing driver. Alexander
Stein contributes eg20t support to the c_can pci driver. Together with
the patches on the net-tree, we'll be able to remove the pch_can driver
soon. Kurt Van Dijck's two patches clean up the sysfs attributes of the
softing driver.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can/c_can/c_can_pci.c')
-rw-r--r-- | drivers/net/can/c_can/c_can_pci.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index bce0be54c2f5..7ab384f59e7e 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -19,9 +19,13 @@ #include "c_can.h" +#define PCI_DEVICE_ID_PCH_CAN 0x8818 +#define PCH_PCI_SOFT_RESET 0x01fc + enum c_can_pci_reg_align { C_CAN_REG_ALIGN_16, C_CAN_REG_ALIGN_32, + C_CAN_REG_32, }; struct c_can_pci_data { @@ -31,6 +35,10 @@ struct c_can_pci_data { enum c_can_pci_reg_align reg_align; /* Set the frequency */ 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]); } +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, 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_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) { dev_err(&pdev->dev, "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->write_reg = c_can_pci_write_reg_aligned_to_16bit; 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: ret = -EINVAL; goto out_free_c_can; } + priv->raminit = c_can_pci_data->init; + ret = register_c_can_dev(dev); if (ret) { 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, .reg_align = C_CAN_REG_ALIGN_32, .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) { \ @@ -202,6 +249,8 @@ static struct c_can_pci_data c_can_sta2x11= { static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = { C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN, 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 = { |