Commit 2469627d175c1d6d7812a1395dd3ef053a0e65b3

Authored by AnilKumar Ch
Committed by Marc Kleine-Budde
1 parent f27b1db95d

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>

Showing 2 changed files with 87 additions and 17 deletions Side-by-side Diff

Documentation/devicetree/bindings/net/can/c_can.txt
  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 + };
drivers/net/can/c_can/c_can_platform.c
... ... @@ -30,6 +30,8 @@
30 30 #include <linux/io.h>
31 31 #include <linux/platform_device.h>
32 32 #include <linux/clk.h>
  33 +#include <linux/of.h>
  34 +#include <linux/of_device.h>
33 35  
34 36 #include <linux/can/dev.h>
35 37  
36 38  
37 39  
... ... @@ -65,17 +67,52 @@
65 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 92 static int __devinit c_can_plat_probe(struct platform_device *pdev)
69 93 {
70 94 int ret;
71 95 void __iomem *addr;
72 96 struct net_device *dev;
73 97 struct c_can_priv *priv;
  98 + const struct of_device_id *match;
74 99 const struct platform_device_id *id;
75 100 struct resource *mem;
76 101 int irq;
77 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 116 /* get the appropriate clk */
80 117 clk = clk_get(&pdev->dev, NULL);
81 118 if (IS_ERR(clk)) {
... ... @@ -114,7 +151,6 @@
114 151 }
115 152  
116 153 priv = netdev_priv(dev);
117   - id = platform_get_device_id(pdev);
118 154 switch (id->driver_data) {
119 155 case BOSCH_C_CAN:
120 156 priv->regs = reg_map_c_can;
121 157  
... ... @@ -195,26 +231,11 @@
195 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 234 static struct platform_driver c_can_plat_driver = {
215 235 .driver = {
216 236 .name = KBUILD_MODNAME,
217 237 .owner = THIS_MODULE,
  238 + .of_match_table = of_match_ptr(c_can_of_table),
218 239 },
219 240 .probe = c_can_plat_probe,
220 241 .remove = __devexit_p(c_can_plat_remove),