aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
authorAnilKumar Ch <anilkumar@ti.com>2012-05-29 01:43:16 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2012-06-07 04:02:27 -0400
commit69927fccd96b15bd228bb82d356a7a2a0cfaeefb (patch)
treeef9487a9cab32ed0baa50749b4dbbe2232e0af99 /drivers/net/can
parent33f8100977693fa09c2a32b1ca6dbf4d6eabdd0c (diff)
can: c_can: Add support for Bosch D_CAN controller
This patch adds the support for D_CAN controller driver to the existing C_CAN driver. Bosch D_CAN controller is a full-CAN implementation which is compliant to CAN protocol version 2.0 part A and B. Bosch D_CAN user manual can be obtained from: http://www.semiconductors.bosch.de/media/en/pdf/ ipmodules_1/can/d_can_users_manual_111.pdf A new array is added for accessing the d_can registers, according to d_can controller register space. Current D_CAN implementation has following limitations, this is done to avoid large changes to the C_CAN driver. 1. Message objects are limited to 32, 16 for RX and 16 for TX. C_CAN IP supports upto 32 message objects but in case of D_CAN we can configure upto 128 message objects. 2. Using two 16bit reads/writes for accessing the 32bit D_CAN registers. 3. These patches have been tested on little endian machine, there might be some hidden endian-related issues due to the nature of the accesses (32-bit registers accessed as 2 16-bit registers). However, I do not have a big-endian D_CAN implementation to confirm. Signed-off-by: AnilKumar Ch <anilkumar@ti.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/c_can/Kconfig13
-rw-r--r--drivers/net/can/c_can/c_can.h45
-rw-r--r--drivers/net/can/c_can/c_can_platform.c55
3 files changed, 94 insertions, 19 deletions
diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig
index ffb9773d102d..25d371cf98dd 100644
--- a/drivers/net/can/c_can/Kconfig
+++ b/drivers/net/can/c_can/Kconfig
@@ -1,15 +1,16 @@
1menuconfig CAN_C_CAN 1menuconfig CAN_C_CAN
2 tristate "Bosch C_CAN devices" 2 tristate "Bosch C_CAN/D_CAN devices"
3 depends on CAN_DEV && HAS_IOMEM 3 depends on CAN_DEV && HAS_IOMEM
4 4
5if CAN_C_CAN 5if CAN_C_CAN
6 6
7config CAN_C_CAN_PLATFORM 7config CAN_C_CAN_PLATFORM
8 tristate "Generic Platform Bus based C_CAN driver" 8 tristate "Generic Platform Bus based C_CAN/D_CAN driver"
9 ---help--- 9 ---help---
10 This driver adds support for the C_CAN chips connected to 10 This driver adds support for the C_CAN/D_CAN chips connected
11 the "platform bus" (Linux abstraction for directly to the 11 to the "platform bus" (Linux abstraction for directly to the
12 processor attached devices) which can be found on various 12 processor attached devices) which can be found on various
13 boards from ST Microelectronics (http://www.st.com) 13 boards from ST Microelectronics (http://www.st.com) like the
14 like the SPEAr1310 and SPEAr320 evaluation boards. 14 SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com)
15 boards like am335x, dm814x, dm813x and dm811x.
15endif 16endif
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index d1e141e3b99c..01a7049ab990 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -102,6 +102,51 @@ static const u16 reg_map_c_can[] = {
102 [C_CAN_MSGVAL2_REG] = 0xB2, 102 [C_CAN_MSGVAL2_REG] = 0xB2,
103}; 103};
104 104
105static const u16 reg_map_d_can[] = {
106 [C_CAN_CTRL_REG] = 0x00,
107 [C_CAN_STS_REG] = 0x04,
108 [C_CAN_ERR_CNT_REG] = 0x08,
109 [C_CAN_BTR_REG] = 0x0C,
110 [C_CAN_BRPEXT_REG] = 0x0E,
111 [C_CAN_INT_REG] = 0x10,
112 [C_CAN_TEST_REG] = 0x14,
113 [C_CAN_TXRQST1_REG] = 0x88,
114 [C_CAN_TXRQST2_REG] = 0x8A,
115 [C_CAN_NEWDAT1_REG] = 0x9C,
116 [C_CAN_NEWDAT2_REG] = 0x9E,
117 [C_CAN_INTPND1_REG] = 0xB0,
118 [C_CAN_INTPND2_REG] = 0xB2,
119 [C_CAN_MSGVAL1_REG] = 0xC4,
120 [C_CAN_MSGVAL2_REG] = 0xC6,
121 [C_CAN_IF1_COMREQ_REG] = 0x100,
122 [C_CAN_IF1_COMMSK_REG] = 0x102,
123 [C_CAN_IF1_MASK1_REG] = 0x104,
124 [C_CAN_IF1_MASK2_REG] = 0x106,
125 [C_CAN_IF1_ARB1_REG] = 0x108,
126 [C_CAN_IF1_ARB2_REG] = 0x10A,
127 [C_CAN_IF1_MSGCTRL_REG] = 0x10C,
128 [C_CAN_IF1_DATA1_REG] = 0x110,
129 [C_CAN_IF1_DATA2_REG] = 0x112,
130 [C_CAN_IF1_DATA3_REG] = 0x114,
131 [C_CAN_IF1_DATA4_REG] = 0x116,
132 [C_CAN_IF2_COMREQ_REG] = 0x120,
133 [C_CAN_IF2_COMMSK_REG] = 0x122,
134 [C_CAN_IF2_MASK1_REG] = 0x124,
135 [C_CAN_IF2_MASK2_REG] = 0x126,
136 [C_CAN_IF2_ARB1_REG] = 0x128,
137 [C_CAN_IF2_ARB2_REG] = 0x12A,
138 [C_CAN_IF2_MSGCTRL_REG] = 0x12C,
139 [C_CAN_IF2_DATA1_REG] = 0x130,
140 [C_CAN_IF2_DATA2_REG] = 0x132,
141 [C_CAN_IF2_DATA3_REG] = 0x134,
142 [C_CAN_IF2_DATA4_REG] = 0x136,
143};
144
145enum c_can_dev_id {
146 C_CAN_DEVTYPE,
147 D_CAN_DEVTYPE,
148};
149
105/* c_can private data structure */ 150/* c_can private data structure */
106struct c_can_priv { 151struct c_can_priv {
107 struct can_priv can; /* must be the first member */ 152 struct can_priv can; /* must be the first member */
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index a6e9b937683a..f0921d16f0a9 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -71,6 +71,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
71 void __iomem *addr; 71 void __iomem *addr;
72 struct net_device *dev; 72 struct net_device *dev;
73 struct c_can_priv *priv; 73 struct c_can_priv *priv;
74 const struct platform_device_id *id;
74 struct resource *mem; 75 struct resource *mem;
75 int irq; 76 int irq;
76#ifdef CONFIG_HAVE_CLK 77#ifdef CONFIG_HAVE_CLK
@@ -115,7 +116,32 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
115 } 116 }
116 117
117 priv = netdev_priv(dev); 118 priv = netdev_priv(dev);
118 priv->regs = reg_map_c_can; 119 id = platform_get_device_id(pdev);
120 switch (id->driver_data) {
121 case C_CAN_DEVTYPE:
122 priv->regs = reg_map_c_can;
123 switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
124 case IORESOURCE_MEM_32BIT:
125 priv->read_reg = c_can_plat_read_reg_aligned_to_32bit;
126 priv->write_reg = c_can_plat_write_reg_aligned_to_32bit;
127 break;
128 case IORESOURCE_MEM_16BIT:
129 default:
130 priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
131 priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
132 break;
133 }
134 break;
135 case D_CAN_DEVTYPE:
136 priv->regs = reg_map_d_can;
137 priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
138 priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
139 priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
140 break;
141 default:
142 ret = -EINVAL;
143 goto exit_free_device;
144 }
119 145
120 dev->irq = irq; 146 dev->irq = irq;
121 priv->base = addr; 147 priv->base = addr;
@@ -124,18 +150,6 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
124 priv->priv = clk; 150 priv->priv = clk;
125#endif 151#endif
126 152
127 switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
128 case IORESOURCE_MEM_32BIT:
129 priv->read_reg = c_can_plat_read_reg_aligned_to_32bit;
130 priv->write_reg = c_can_plat_write_reg_aligned_to_32bit;
131 break;
132 case IORESOURCE_MEM_16BIT:
133 default:
134 priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
135 priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
136 break;
137 }
138
139 platform_set_drvdata(pdev, dev); 153 platform_set_drvdata(pdev, dev);
140 SET_NETDEV_DEV(dev, &pdev->dev); 154 SET_NETDEV_DEV(dev, &pdev->dev);
141 155
@@ -189,6 +203,20 @@ static int __devexit c_can_plat_remove(struct platform_device *pdev)
189 return 0; 203 return 0;
190} 204}
191 205
206static const struct platform_device_id c_can_id_table[] = {
207 {
208 .name = KBUILD_MODNAME,
209 .driver_data = C_CAN_DEVTYPE,
210 }, {
211 .name = "c_can",
212 .driver_data = C_CAN_DEVTYPE,
213 }, {
214 .name = "d_can",
215 .driver_data = D_CAN_DEVTYPE,
216 }, {
217 }
218};
219
192static struct platform_driver c_can_plat_driver = { 220static struct platform_driver c_can_plat_driver = {
193 .driver = { 221 .driver = {
194 .name = KBUILD_MODNAME, 222 .name = KBUILD_MODNAME,
@@ -196,6 +224,7 @@ static struct platform_driver c_can_plat_driver = {
196 }, 224 },
197 .probe = c_can_plat_probe, 225 .probe = c_can_plat_probe,
198 .remove = __devexit_p(c_can_plat_remove), 226 .remove = __devexit_p(c_can_plat_remove),
227 .id_table = c_can_id_table,
199}; 228};
200 229
201module_platform_driver(c_can_plat_driver); 230module_platform_driver(c_can_plat_driver);