Commit | Line | Data |
---|---|---|
881ff67a BS |
1 | /* |
2 | * Platform CAN bus driver for Bosch C_CAN controller | |
3 | * | |
4 | * Copyright (C) 2010 ST Microelectronics | |
5 | * Bhupesh Sharma <bhupesh.sharma@st.com> | |
6 | * | |
7 | * Borrowed heavily from the C_CAN driver originally written by: | |
8 | * Copyright (C) 2007 | |
9 | * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de> | |
10 | * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch> | |
11 | * | |
12 | * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B. | |
13 | * Bosch C_CAN user manual can be obtained from: | |
14 | * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/ | |
15 | * users_manual_c_can.pdf | |
16 | * | |
17 | * This file is licensed under the terms of the GNU General Public | |
18 | * License version 2. This program is licensed "as is" without any | |
19 | * warranty of any kind, whether express or implied. | |
20 | */ | |
21 | ||
22 | #include <linux/kernel.h> | |
881ff67a BS |
23 | #include <linux/module.h> |
24 | #include <linux/interrupt.h> | |
25 | #include <linux/delay.h> | |
26 | #include <linux/netdevice.h> | |
27 | #include <linux/if_arp.h> | |
28 | #include <linux/if_ether.h> | |
29 | #include <linux/list.h> | |
881ff67a BS |
30 | #include <linux/io.h> |
31 | #include <linux/platform_device.h> | |
32 | #include <linux/clk.h> | |
2469627d AC |
33 | #include <linux/of.h> |
34 | #include <linux/of_device.h> | |
881ff67a BS |
35 | |
36 | #include <linux/can/dev.h> | |
37 | ||
38 | #include "c_can.h" | |
39 | ||
5bb9cbaa TG |
40 | #define CAN_RAMINIT_START_MASK(i) (0x001 << (i)) |
41 | #define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i)) | |
42 | #define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i)) | |
a9c69209 | 43 | #define DCAN_RAM_INIT_BIT (1 << 3) |
5bb9cbaa | 44 | static DEFINE_SPINLOCK(raminit_lock); |
881ff67a BS |
45 | /* |
46 | * 16-bit c_can registers can be arranged differently in the memory | |
47 | * architecture of different implementations. For example: 16-bit | |
48 | * registers can be aligned to a 16-bit boundary or 32-bit boundary etc. | |
49 | * Handle the same by providing a common read/write interface. | |
50 | */ | |
e07e83ae | 51 | static u16 c_can_plat_read_reg_aligned_to_16bit(const struct c_can_priv *priv, |
33f81009 | 52 | enum reg index) |
881ff67a | 53 | { |
33f81009 | 54 | return readw(priv->base + priv->regs[index]); |
881ff67a BS |
55 | } |
56 | ||
e07e83ae | 57 | static void c_can_plat_write_reg_aligned_to_16bit(const struct c_can_priv *priv, |
33f81009 | 58 | enum reg index, u16 val) |
881ff67a | 59 | { |
33f81009 | 60 | writew(val, priv->base + priv->regs[index]); |
881ff67a BS |
61 | } |
62 | ||
e07e83ae | 63 | static u16 c_can_plat_read_reg_aligned_to_32bit(const struct c_can_priv *priv, |
33f81009 | 64 | enum reg index) |
881ff67a | 65 | { |
33f81009 | 66 | return readw(priv->base + 2 * priv->regs[index]); |
881ff67a BS |
67 | } |
68 | ||
e07e83ae | 69 | static void c_can_plat_write_reg_aligned_to_32bit(const struct c_can_priv *priv, |
33f81009 | 70 | enum reg index, u16 val) |
881ff67a | 71 | { |
33f81009 | 72 | writew(val, priv->base + 2 * priv->regs[index]); |
881ff67a BS |
73 | } |
74 | ||
e07e83ae | 75 | static void c_can_hw_raminit_wait_ti(const struct c_can_priv *priv, u32 mask, |
5bb9cbaa TG |
76 | u32 val) |
77 | { | |
78 | /* We look only at the bits of our instance. */ | |
79 | val &= mask; | |
80 | while ((readl(priv->raminit_ctrlreg) & mask) != val) | |
81 | udelay(1); | |
82 | } | |
83 | ||
a9c69209 | 84 | static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable) |
52cde85a | 85 | { |
5bb9cbaa TG |
86 | u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance); |
87 | u32 ctrl; | |
52cde85a | 88 | |
5bb9cbaa TG |
89 | spin_lock(&raminit_lock); |
90 | ||
91 | ctrl = readl(priv->raminit_ctrlreg); | |
92 | /* We clear the done and start bit first. The start bit is | |
93 | * looking at the 0 -> transition, but is not self clearing; | |
94 | * And we clear the init done bit as well. | |
95 | */ | |
96 | ctrl &= ~CAN_RAMINIT_START_MASK(priv->instance); | |
97 | ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); | |
98 | writel(ctrl, priv->raminit_ctrlreg); | |
99 | ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance); | |
a9c69209 | 100 | c_can_hw_raminit_wait_ti(priv, ctrl, mask); |
5bb9cbaa TG |
101 | |
102 | if (enable) { | |
103 | /* Set start bit and wait for the done bit. */ | |
104 | ctrl |= CAN_RAMINIT_START_MASK(priv->instance); | |
105 | writel(ctrl, priv->raminit_ctrlreg); | |
106 | ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); | |
a9c69209 | 107 | c_can_hw_raminit_wait_ti(priv, ctrl, mask); |
5bb9cbaa TG |
108 | } |
109 | spin_unlock(&raminit_lock); | |
52cde85a AC |
110 | } |
111 | ||
ccbc5357 PM |
112 | static u32 c_can_plat_read_reg32(const struct c_can_priv *priv, enum reg index) |
113 | { | |
114 | u32 val; | |
115 | ||
116 | val = priv->read_reg(priv, index); | |
117 | val |= ((u32) priv->read_reg(priv, index + 1)) << 16; | |
118 | ||
119 | return val; | |
120 | } | |
121 | ||
122 | static void c_can_plat_write_reg32(const struct c_can_priv *priv, enum reg index, | |
123 | u32 val) | |
124 | { | |
125 | priv->write_reg(priv, index + 1, val >> 16); | |
126 | priv->write_reg(priv, index, val); | |
127 | } | |
128 | ||
129 | static u32 d_can_plat_read_reg32(const struct c_can_priv *priv, enum reg index) | |
130 | { | |
131 | return readl(priv->base + priv->regs[index]); | |
132 | } | |
133 | ||
134 | static void d_can_plat_write_reg32(const struct c_can_priv *priv, enum reg index, | |
135 | u32 val) | |
136 | { | |
137 | writel(val, priv->base + priv->regs[index]); | |
138 | } | |
139 | ||
a9c69209 PM |
140 | static void c_can_hw_raminit_wait(const struct c_can_priv *priv, u32 mask) |
141 | { | |
142 | while (priv->read_reg32(priv, C_CAN_FUNCTION_REG) & mask) | |
143 | udelay(1); | |
144 | } | |
145 | ||
146 | static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) | |
147 | { | |
148 | u32 ctrl; | |
149 | ||
150 | ctrl = priv->read_reg32(priv, C_CAN_FUNCTION_REG); | |
151 | ctrl &= ~DCAN_RAM_INIT_BIT; | |
152 | priv->write_reg32(priv, C_CAN_FUNCTION_REG, ctrl); | |
153 | c_can_hw_raminit_wait(priv, ctrl); | |
154 | ||
155 | if (enable) { | |
156 | ctrl |= DCAN_RAM_INIT_BIT; | |
157 | priv->write_reg32(priv, C_CAN_FUNCTION_REG, ctrl); | |
158 | c_can_hw_raminit_wait(priv, ctrl); | |
159 | } | |
160 | } | |
161 | ||
2469627d AC |
162 | static struct platform_device_id c_can_id_table[] = { |
163 | [BOSCH_C_CAN_PLATFORM] = { | |
164 | .name = KBUILD_MODNAME, | |
165 | .driver_data = BOSCH_C_CAN, | |
166 | }, | |
167 | [BOSCH_C_CAN] = { | |
168 | .name = "c_can", | |
169 | .driver_data = BOSCH_C_CAN, | |
170 | }, | |
171 | [BOSCH_D_CAN] = { | |
172 | .name = "d_can", | |
173 | .driver_data = BOSCH_D_CAN, | |
174 | }, { | |
175 | } | |
176 | }; | |
69c0c5b1 | 177 | MODULE_DEVICE_TABLE(platform, c_can_id_table); |
2469627d AC |
178 | |
179 | static const struct of_device_id c_can_of_table[] = { | |
180 | { .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] }, | |
181 | { .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] }, | |
182 | { /* sentinel */ }, | |
183 | }; | |
69c0c5b1 | 184 | MODULE_DEVICE_TABLE(of, c_can_of_table); |
2469627d | 185 | |
3c8ac0f2 | 186 | static int c_can_plat_probe(struct platform_device *pdev) |
881ff67a BS |
187 | { |
188 | int ret; | |
189 | void __iomem *addr; | |
190 | struct net_device *dev; | |
191 | struct c_can_priv *priv; | |
2469627d | 192 | const struct of_device_id *match; |
69927fcc | 193 | const struct platform_device_id *id; |
52cde85a | 194 | struct resource *mem, *res; |
b0052b08 | 195 | int irq; |
881ff67a BS |
196 | struct clk *clk; |
197 | ||
2469627d AC |
198 | if (pdev->dev.of_node) { |
199 | match = of_match_device(c_can_of_table, &pdev->dev); | |
200 | if (!match) { | |
201 | dev_err(&pdev->dev, "Failed to find matching dt id\n"); | |
202 | ret = -EINVAL; | |
203 | goto exit; | |
204 | } | |
205 | id = match->data; | |
206 | } else { | |
207 | id = platform_get_device_id(pdev); | |
208 | } | |
209 | ||
881ff67a | 210 | /* get the appropriate clk */ |
c6bf7e5f | 211 | clk = devm_clk_get(&pdev->dev, NULL); |
881ff67a | 212 | if (IS_ERR(clk)) { |
c6bf7e5f | 213 | ret = PTR_ERR(clk); |
881ff67a BS |
214 | goto exit; |
215 | } | |
881ff67a BS |
216 | |
217 | /* get the platform data */ | |
b0052b08 | 218 | irq = platform_get_irq(pdev, 0); |
c6bf7e5f | 219 | if (irq <= 0) { |
881ff67a | 220 | ret = -ENODEV; |
c6bf7e5f | 221 | goto exit; |
881ff67a BS |
222 | } |
223 | ||
c6bf7e5f LP |
224 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
225 | addr = devm_ioremap_resource(&pdev->dev, mem); | |
226 | if (IS_ERR(addr)) { | |
227 | ret = PTR_ERR(addr); | |
228 | goto exit; | |
881ff67a BS |
229 | } |
230 | ||
231 | /* allocate the c_can device */ | |
232 | dev = alloc_c_can_dev(); | |
233 | if (!dev) { | |
234 | ret = -ENOMEM; | |
c6bf7e5f | 235 | goto exit; |
881ff67a BS |
236 | } |
237 | ||
238 | priv = netdev_priv(dev); | |
69927fcc | 239 | switch (id->driver_data) { |
f27b1db9 | 240 | case BOSCH_C_CAN: |
69927fcc AC |
241 | priv->regs = reg_map_c_can; |
242 | switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) { | |
243 | case IORESOURCE_MEM_32BIT: | |
244 | priv->read_reg = c_can_plat_read_reg_aligned_to_32bit; | |
245 | priv->write_reg = c_can_plat_write_reg_aligned_to_32bit; | |
ccbc5357 PM |
246 | priv->read_reg32 = c_can_plat_read_reg32; |
247 | priv->write_reg32 = c_can_plat_write_reg32; | |
69927fcc AC |
248 | break; |
249 | case IORESOURCE_MEM_16BIT: | |
250 | default: | |
251 | priv->read_reg = c_can_plat_read_reg_aligned_to_16bit; | |
252 | priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; | |
ccbc5357 PM |
253 | priv->read_reg32 = c_can_plat_read_reg32; |
254 | priv->write_reg32 = c_can_plat_write_reg32; | |
69927fcc AC |
255 | break; |
256 | } | |
257 | break; | |
f27b1db9 | 258 | case BOSCH_D_CAN: |
69927fcc AC |
259 | priv->regs = reg_map_d_can; |
260 | priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; | |
261 | priv->read_reg = c_can_plat_read_reg_aligned_to_16bit; | |
262 | priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; | |
ccbc5357 PM |
263 | priv->read_reg32 = d_can_plat_read_reg32; |
264 | priv->write_reg32 = d_can_plat_write_reg32; | |
52cde85a AC |
265 | |
266 | if (pdev->dev.of_node) | |
267 | priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can"); | |
268 | else | |
269 | priv->instance = pdev->id; | |
270 | ||
271 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | |
a9c69209 PM |
272 | /* Not all D_CAN modules have a separate register for the D_CAN |
273 | * RAM initialization. Use default RAM init bit in D_CAN module | |
274 | * if not specified in DT. | |
275 | */ | |
276 | if (!res) { | |
277 | priv->raminit = c_can_hw_raminit; | |
278 | break; | |
279 | } | |
280 | ||
33cf7565 GC |
281 | priv->raminit_ctrlreg = devm_ioremap(&pdev->dev, res->start, |
282 | resource_size(res)); | |
37b75a3a | 283 | if (!priv->raminit_ctrlreg || priv->instance < 0) |
52cde85a AC |
284 | dev_info(&pdev->dev, "control memory is not used for raminit\n"); |
285 | else | |
a9c69209 | 286 | priv->raminit = c_can_hw_raminit_ti; |
69927fcc AC |
287 | break; |
288 | default: | |
289 | ret = -EINVAL; | |
290 | goto exit_free_device; | |
291 | } | |
881ff67a | 292 | |
b0052b08 | 293 | dev->irq = irq; |
33f81009 | 294 | priv->base = addr; |
4cdd34b2 | 295 | priv->device = &pdev->dev; |
881ff67a BS |
296 | priv->can.clock.freq = clk_get_rate(clk); |
297 | priv->priv = clk; | |
82120032 | 298 | priv->type = id->driver_data; |
881ff67a | 299 | |
881ff67a BS |
300 | platform_set_drvdata(pdev, dev); |
301 | SET_NETDEV_DEV(dev, &pdev->dev); | |
302 | ||
303 | ret = register_c_can_dev(dev); | |
304 | if (ret) { | |
305 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", | |
306 | KBUILD_MODNAME, ret); | |
307 | goto exit_free_device; | |
308 | } | |
309 | ||
310 | dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n", | |
33f81009 | 311 | KBUILD_MODNAME, priv->base, dev->irq); |
881ff67a BS |
312 | return 0; |
313 | ||
314 | exit_free_device: | |
881ff67a | 315 | free_c_can_dev(dev); |
881ff67a | 316 | exit: |
881ff67a BS |
317 | dev_err(&pdev->dev, "probe failed\n"); |
318 | ||
319 | return ret; | |
320 | } | |
321 | ||
3c8ac0f2 | 322 | static int c_can_plat_remove(struct platform_device *pdev) |
881ff67a BS |
323 | { |
324 | struct net_device *dev = platform_get_drvdata(pdev); | |
881ff67a BS |
325 | |
326 | unregister_c_can_dev(dev); | |
881ff67a BS |
327 | |
328 | free_c_can_dev(dev); | |
881ff67a BS |
329 | |
330 | return 0; | |
331 | } | |
332 | ||
82120032 AC |
333 | #ifdef CONFIG_PM |
334 | static int c_can_suspend(struct platform_device *pdev, pm_message_t state) | |
335 | { | |
336 | int ret; | |
337 | struct net_device *ndev = platform_get_drvdata(pdev); | |
338 | struct c_can_priv *priv = netdev_priv(ndev); | |
339 | ||
340 | if (priv->type != BOSCH_D_CAN) { | |
341 | dev_warn(&pdev->dev, "Not supported\n"); | |
342 | return 0; | |
343 | } | |
344 | ||
345 | if (netif_running(ndev)) { | |
346 | netif_stop_queue(ndev); | |
347 | netif_device_detach(ndev); | |
348 | } | |
349 | ||
350 | ret = c_can_power_down(ndev); | |
351 | if (ret) { | |
352 | netdev_err(ndev, "failed to enter power down mode\n"); | |
353 | return ret; | |
354 | } | |
355 | ||
356 | priv->can.state = CAN_STATE_SLEEPING; | |
357 | ||
358 | return 0; | |
359 | } | |
360 | ||
361 | static int c_can_resume(struct platform_device *pdev) | |
362 | { | |
363 | int ret; | |
364 | struct net_device *ndev = platform_get_drvdata(pdev); | |
365 | struct c_can_priv *priv = netdev_priv(ndev); | |
366 | ||
367 | if (priv->type != BOSCH_D_CAN) { | |
368 | dev_warn(&pdev->dev, "Not supported\n"); | |
369 | return 0; | |
370 | } | |
371 | ||
372 | ret = c_can_power_up(ndev); | |
373 | if (ret) { | |
374 | netdev_err(ndev, "Still in power down mode\n"); | |
375 | return ret; | |
376 | } | |
377 | ||
378 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | |
379 | ||
380 | if (netif_running(ndev)) { | |
381 | netif_device_attach(ndev); | |
382 | netif_start_queue(ndev); | |
383 | } | |
384 | ||
385 | return 0; | |
386 | } | |
387 | #else | |
388 | #define c_can_suspend NULL | |
389 | #define c_can_resume NULL | |
390 | #endif | |
391 | ||
881ff67a BS |
392 | static struct platform_driver c_can_plat_driver = { |
393 | .driver = { | |
394 | .name = KBUILD_MODNAME, | |
395 | .owner = THIS_MODULE, | |
b85f75ea | 396 | .of_match_table = c_can_of_table, |
881ff67a BS |
397 | }, |
398 | .probe = c_can_plat_probe, | |
3c8ac0f2 | 399 | .remove = c_can_plat_remove, |
82120032 AC |
400 | .suspend = c_can_suspend, |
401 | .resume = c_can_resume, | |
69927fcc | 402 | .id_table = c_can_id_table, |
881ff67a BS |
403 | }; |
404 | ||
871d3372 | 405 | module_platform_driver(c_can_plat_driver); |
881ff67a BS |
406 | |
407 | MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>"); | |
408 | MODULE_LICENSE("GPL v2"); | |
409 | MODULE_DESCRIPTION("Platform CAN bus driver for Bosch C_CAN controller"); |