diff options
author | AnilKumar Ch <anilkumar@ti.com> | 2012-08-02 09:13:10 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2012-09-21 17:58:47 -0400 |
commit | 2469627d175c1d6d7812a1395dd3ef053a0e65b3 (patch) | |
tree | 8ee10f2f87ddccc8fa6160e9d73bfd93b33b57ac | |
parent | f27b1db95d047d05e8d4dd22813b1078267892f2 (diff) |
can: c_can: Add device tree support to Bosch C_CAN/D_CAN controller
Add device tree support to C_CAN/D_CAN controller and usage details
are added to device tree documentation. Driver was tested on AM335x
EVM.
Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
For the of binding doc:
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r-- | Documentation/devicetree/bindings/net/can/c_can.txt | 49 | ||||
-rw-r--r-- | drivers/net/can/c_can/c_can_platform.c | 55 |
2 files changed, 87 insertions, 17 deletions
diff --git a/Documentation/devicetree/bindings/net/can/c_can.txt b/Documentation/devicetree/bindings/net/can/c_can.txt new file mode 100644 index 00000000000..8f1ae81228e --- /dev/null +++ b/Documentation/devicetree/bindings/net/can/c_can.txt | |||
@@ -0,0 +1,49 @@ | |||
1 | Bosch C_CAN/D_CAN controller Device Tree Bindings | ||
2 | ------------------------------------------------- | ||
3 | |||
4 | Required properties: | ||
5 | - compatible : Should be "bosch,c_can" for C_CAN controllers and | ||
6 | "bosch,d_can" for D_CAN controllers. | ||
7 | - reg : physical base address and size of the C_CAN/D_CAN | ||
8 | registers map | ||
9 | - interrupts : property with a value describing the interrupt | ||
10 | number | ||
11 | |||
12 | Optional properties: | ||
13 | - ti,hwmods : Must be "d_can<n>" or "c_can<n>", n being the | ||
14 | instance number | ||
15 | |||
16 | Note: "ti,hwmods" field is used to fetch the base address and irq | ||
17 | resources from TI, omap hwmod data base during device registration. | ||
18 | Future plan is to migrate hwmod data base contents into device tree | ||
19 | blob so that, all the required data will be used from device tree dts | ||
20 | file. | ||
21 | |||
22 | Example: | ||
23 | |||
24 | Step1: SoC common .dtsi file | ||
25 | |||
26 | dcan1: d_can@481d0000 { | ||
27 | compatible = "bosch,d_can"; | ||
28 | reg = <0x481d0000 0x2000>; | ||
29 | interrupts = <55>; | ||
30 | interrupt-parent = <&intc>; | ||
31 | status = "disabled"; | ||
32 | }; | ||
33 | |||
34 | (or) | ||
35 | |||
36 | dcan1: d_can@481d0000 { | ||
37 | compatible = "bosch,d_can"; | ||
38 | ti,hwmods = "d_can1"; | ||
39 | reg = <0x481d0000 0x2000>; | ||
40 | interrupts = <55>; | ||
41 | interrupt-parent = <&intc>; | ||
42 | status = "disabled"; | ||
43 | }; | ||
44 | |||
45 | Step 2: board specific .dts file | ||
46 | |||
47 | &dcan1 { | ||
48 | status = "okay"; | ||
49 | }; | ||
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 5c46d1cc5cf..d0a66cf298b 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/clk.h> | 32 | #include <linux/clk.h> |
33 | #include <linux/of.h> | ||
34 | #include <linux/of_device.h> | ||
33 | 35 | ||
34 | #include <linux/can/dev.h> | 36 | #include <linux/can/dev.h> |
35 | 37 | ||
@@ -65,17 +67,52 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv, | |||
65 | writew(val, priv->base + 2 * priv->regs[index]); | 67 | writew(val, priv->base + 2 * priv->regs[index]); |
66 | } | 68 | } |
67 | 69 | ||
70 | static struct platform_device_id c_can_id_table[] = { | ||
71 | [BOSCH_C_CAN_PLATFORM] = { | ||
72 | .name = KBUILD_MODNAME, | ||
73 | .driver_data = BOSCH_C_CAN, | ||
74 | }, | ||
75 | [BOSCH_C_CAN] = { | ||
76 | .name = "c_can", | ||
77 | .driver_data = BOSCH_C_CAN, | ||
78 | }, | ||
79 | [BOSCH_D_CAN] = { | ||
80 | .name = "d_can", | ||
81 | .driver_data = BOSCH_D_CAN, | ||
82 | }, { | ||
83 | } | ||
84 | }; | ||
85 | |||
86 | static const struct of_device_id c_can_of_table[] = { | ||
87 | { .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] }, | ||
88 | { .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] }, | ||
89 | { /* sentinel */ }, | ||
90 | }; | ||
91 | |||
68 | static int __devinit c_can_plat_probe(struct platform_device *pdev) | 92 | static int __devinit c_can_plat_probe(struct platform_device *pdev) |
69 | { | 93 | { |
70 | int ret; | 94 | int ret; |
71 | void __iomem *addr; | 95 | void __iomem *addr; |
72 | struct net_device *dev; | 96 | struct net_device *dev; |
73 | struct c_can_priv *priv; | 97 | struct c_can_priv *priv; |
98 | const struct of_device_id *match; | ||
74 | const struct platform_device_id *id; | 99 | const struct platform_device_id *id; |
75 | struct resource *mem; | 100 | struct resource *mem; |
76 | int irq; | 101 | int irq; |
77 | struct clk *clk; | 102 | struct clk *clk; |
78 | 103 | ||
104 | if (pdev->dev.of_node) { | ||
105 | match = of_match_device(c_can_of_table, &pdev->dev); | ||
106 | if (!match) { | ||
107 | dev_err(&pdev->dev, "Failed to find matching dt id\n"); | ||
108 | ret = -EINVAL; | ||
109 | goto exit; | ||
110 | } | ||
111 | id = match->data; | ||
112 | } else { | ||
113 | id = platform_get_device_id(pdev); | ||
114 | } | ||
115 | |||
79 | /* get the appropriate clk */ | 116 | /* get the appropriate clk */ |
80 | clk = clk_get(&pdev->dev, NULL); | 117 | clk = clk_get(&pdev->dev, NULL); |
81 | if (IS_ERR(clk)) { | 118 | if (IS_ERR(clk)) { |
@@ -114,7 +151,6 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) | |||
114 | } | 151 | } |
115 | 152 | ||
116 | priv = netdev_priv(dev); | 153 | priv = netdev_priv(dev); |
117 | id = platform_get_device_id(pdev); | ||
118 | switch (id->driver_data) { | 154 | switch (id->driver_data) { |
119 | case BOSCH_C_CAN: | 155 | case BOSCH_C_CAN: |
120 | priv->regs = reg_map_c_can; | 156 | priv->regs = reg_map_c_can; |
@@ -195,26 +231,11 @@ static int __devexit c_can_plat_remove(struct platform_device *pdev) | |||
195 | return 0; | 231 | return 0; |
196 | } | 232 | } |
197 | 233 | ||
198 | static const struct platform_device_id c_can_id_table[] = { | ||
199 | [BOSCH_C_CAN_PLATFORM] = { | ||
200 | .name = KBUILD_MODNAME, | ||
201 | .driver_data = BOSCH_C_CAN, | ||
202 | }, | ||
203 | [BOSCH_C_CAN] = { | ||
204 | .name = "c_can", | ||
205 | .driver_data = BOSCH_C_CAN, | ||
206 | }, | ||
207 | [BOSCH_D_CAN] = { | ||
208 | .name = "d_can", | ||
209 | .driver_data = BOSCH_D_CAN, | ||
210 | }, { | ||
211 | } | ||
212 | }; | ||
213 | |||
214 | static struct platform_driver c_can_plat_driver = { | 234 | static struct platform_driver c_can_plat_driver = { |
215 | .driver = { | 235 | .driver = { |
216 | .name = KBUILD_MODNAME, | 236 | .name = KBUILD_MODNAME, |
217 | .owner = THIS_MODULE, | 237 | .owner = THIS_MODULE, |
238 | .of_match_table = of_match_ptr(c_can_of_table), | ||
218 | }, | 239 | }, |
219 | .probe = c_can_plat_probe, | 240 | .probe = c_can_plat_probe, |
220 | .remove = __devexit_p(c_can_plat_remove), | 241 | .remove = __devexit_p(c_can_plat_remove), |