aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Stein <alexander.stein@systec-electronic.com>2014-04-07 02:52:03 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2014-04-24 18:08:43 -0400
commitabcd7f750a7e978a60c745e7c41dc468949365c2 (patch)
tree2cd1b51eec4c9ad827c0ec578457b7623bcba194
parent8e964fe21d8186d410353c295df14623a5ed8745 (diff)
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>
-rw-r--r--drivers/net/can/c_can/c_can_pci.c51
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 @@
19 19
20#include "c_can.h" 20#include "c_can.h"
21 21
22#define PCI_DEVICE_ID_PCH_CAN 0x8818
23#define PCH_PCI_SOFT_RESET 0x01fc
24
22enum c_can_pci_reg_align { 25enum c_can_pci_reg_align {
23 C_CAN_REG_ALIGN_16, 26 C_CAN_REG_ALIGN_16,
24 C_CAN_REG_ALIGN_32, 27 C_CAN_REG_ALIGN_32,
28 C_CAN_REG_32,
25}; 29};
26 30
27struct c_can_pci_data { 31struct c_can_pci_data {
@@ -31,6 +35,10 @@ struct c_can_pci_data {
31 enum c_can_pci_reg_align reg_align; 35 enum c_can_pci_reg_align reg_align;
32 /* Set the frequency */ 36 /* Set the frequency */
33 unsigned int freq; 37 unsigned int freq;
38 /* PCI bar number */
39 int bar;
40 /* Callback for reset */
41 void (*init)(const struct c_can_priv *priv, bool enable);
34}; 42};
35 43
36/* 44/*
@@ -63,6 +71,29 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
63 writew(val, priv->base + 2 * priv->regs[index]); 71 writew(val, priv->base + 2 * priv->regs[index]);
64} 72}
65 73
74static u16 c_can_pci_read_reg_32bit(struct c_can_priv *priv,
75 enum reg index)
76{
77 return (u16)ioread32(priv->base + 2 * priv->regs[index]);
78}
79
80static void c_can_pci_write_reg_32bit(struct c_can_priv *priv,
81 enum reg index, u16 val)
82{
83 iowrite32((u32)val, priv->base + 2 * priv->regs[index]);
84}
85
86static void c_can_pci_reset_pch(const struct c_can_priv *priv, bool enable)
87{
88 if (enable) {
89 u32 __iomem *addr = priv->base + PCH_PCI_SOFT_RESET;
90
91 /* write to sw reset register */
92 iowrite32(1, addr);
93 iowrite32(0, addr);
94 }
95}
96
66static int c_can_pci_probe(struct pci_dev *pdev, 97static int c_can_pci_probe(struct pci_dev *pdev,
67 const struct pci_device_id *ent) 98 const struct pci_device_id *ent)
68{ 99{
@@ -87,7 +118,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,
87 pci_set_master(pdev); 118 pci_set_master(pdev);
88 pci_enable_msi(pdev); 119 pci_enable_msi(pdev);
89 120
90 addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); 121 addr = pci_iomap(pdev, c_can_pci_data->bar,
122 pci_resource_len(pdev, c_can_pci_data->bar));
91 if (!addr) { 123 if (!addr) {
92 dev_err(&pdev->dev, 124 dev_err(&pdev->dev,
93 "device has no PCI memory resources, " 125 "device has no PCI memory resources, "
@@ -142,11 +174,17 @@ static int c_can_pci_probe(struct pci_dev *pdev,
142 priv->read_reg = c_can_pci_read_reg_aligned_to_16bit; 174 priv->read_reg = c_can_pci_read_reg_aligned_to_16bit;
143 priv->write_reg = c_can_pci_write_reg_aligned_to_16bit; 175 priv->write_reg = c_can_pci_write_reg_aligned_to_16bit;
144 break; 176 break;
177 case C_CAN_REG_32:
178 priv->read_reg = c_can_pci_read_reg_32bit;
179 priv->write_reg = c_can_pci_write_reg_32bit;
180 break;
145 default: 181 default:
146 ret = -EINVAL; 182 ret = -EINVAL;
147 goto out_free_c_can; 183 goto out_free_c_can;
148 } 184 }
149 185
186 priv->raminit = c_can_pci_data->init;
187
150 ret = register_c_can_dev(dev); 188 ret = register_c_can_dev(dev);
151 if (ret) { 189 if (ret) {
152 dev_err(&pdev->dev, "registering %s failed (err=%d)\n", 190 dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
@@ -193,6 +231,15 @@ static struct c_can_pci_data c_can_sta2x11= {
193 .type = BOSCH_C_CAN, 231 .type = BOSCH_C_CAN,
194 .reg_align = C_CAN_REG_ALIGN_32, 232 .reg_align = C_CAN_REG_ALIGN_32,
195 .freq = 52000000, /* 52 Mhz */ 233 .freq = 52000000, /* 52 Mhz */
234 .bar = 0,
235};
236
237static struct c_can_pci_data c_can_pch = {
238 .type = BOSCH_C_CAN,
239 .reg_align = C_CAN_REG_32,
240 .freq = 50000000, /* 50 MHz */
241 .init = c_can_pci_reset_pch,
242 .bar = 1,
196}; 243};
197 244
198#define C_CAN_ID(_vend, _dev, _driverdata) { \ 245#define C_CAN_ID(_vend, _dev, _driverdata) { \
@@ -202,6 +249,8 @@ static struct c_can_pci_data c_can_sta2x11= {
202static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = { 249static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {
203 C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN, 250 C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,
204 c_can_sta2x11), 251 c_can_sta2x11),
252 C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN,
253 c_can_pch),
205 {}, 254 {},
206}; 255};
207static struct pci_driver c_can_pci_driver = { 256static struct pci_driver c_can_pci_driver = {