aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDong Aisheng <b29396@freescale.com>2014-02-24 01:25:12 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:57:45 -0400
commit86b9f774641a71883e02fcad8562bb8432ac7ce9 (patch)
tree9d29190cf7734d88db1faaef879403c2bc54d7e2
parent43486fbef10c525fb5c23f4de11811c48fe0db46 (diff)
ENGR00300439-5 can: flexcan: parse stop mode control bits from device tree
Starting from IMX6, the flexcan stop mode control bits is SoC specific, move it out of IP driver and parse it from devicetree. It's good from maintain perspective and can avoid adding too many SoC specifi bits in driver but with no IP changes when the IMX SoC series keep growing. Signed-off-by: Dong Aisheng <b29396@freescale.com>
-rw-r--r--Documentation/devicetree/bindings/net/can/fsl-flexcan.txt9
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi6
-rw-r--r--drivers/net/can/flexcan.c94
3 files changed, 76 insertions, 33 deletions
diff --git a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
index 487e8a63eff1..0a4dfaab4a54 100644
--- a/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
+++ b/Documentation/devicetree/bindings/net/can/fsl-flexcan.txt
@@ -15,8 +15,13 @@ Required properties:
15Optional properties: 15Optional properties:
16 16
17- clock-frequency : The oscillator frequency driving the flexcan device 17- clock-frequency : The oscillator frequency driving the flexcan device
18- gpr: phandle to general purpose register node. The remote wakeup control 18- stop-mode: register bits of stop mode control, the format is
19 bits is stored here. 19 <&gpr req_gpr req_bit ack_gpr ack_bit>.
20 gpr is the phandle to general purpose register node.
21 req_gpr is the gpr register offset of CAN stop request.
22 req_bit is the bit offset of CAN stop request.
23 ack_gpr is the gpr register offset of CAN stop acknowledge.
24 ack_bit is the bit offset of CAN stop acknowledge.
20 25
21Below are gpios for tranceiver: 26Below are gpios for tranceiver:
22- trx_en_gpio : enable gpio 27- trx_en_gpio : enable gpio
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index ea8ec2a501d0..847310166f60 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -15,8 +15,6 @@
15 15
16/ { 16/ {
17 aliases { 17 aliases {
18 flexcan0 = &flexcan1;
19 flexcan1 = &flexcan2;
20 gpio0 = &gpio1; 18 gpio0 = &gpio1;
21 gpio1 = &gpio2; 19 gpio1 = &gpio2;
22 gpio2 = &gpio3; 20 gpio2 = &gpio3;
@@ -382,7 +380,7 @@
382 interrupts = <0 110 0x04>; 380 interrupts = <0 110 0x04>;
383 clocks = <&clks 108>, <&clks 109>; 381 clocks = <&clks 108>, <&clks 109>;
384 clock-names = "ipg", "per"; 382 clock-names = "ipg", "per";
385 gpr = <&gpr>; 383 stop-mode = <&gpr 0x34 28 0x10 17>;
386 status = "disabled"; 384 status = "disabled";
387 }; 385 };
388 386
@@ -392,7 +390,7 @@
392 interrupts = <0 111 0x04>; 390 interrupts = <0 111 0x04>;
393 clocks = <&clks 110>, <&clks 111>; 391 clocks = <&clks 110>, <&clks 111>;
394 clock-names = "ipg", "per"; 392 clock-names = "ipg", "per";
395 gpr = <&gpr>; 393 stop-mode = <&gpr 0x34 29 0x10 18>;
396 status = "disabled"; 394 status = "disabled";
397 }; 395 };
398 396
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index a89765b81df5..82c022b313cd 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -205,6 +205,13 @@ struct flexcan_devtype_data {
205 u32 features; /* hardware controller features */ 205 u32 features; /* hardware controller features */
206}; 206};
207 207
208struct flexcan_stop_mode {
209 struct regmap *gpr;
210 u8 req_gpr;
211 u8 req_bit;
212 u8 ack_gpr;
213 u8 ack_bit;
214};
208struct flexcan_priv { 215struct flexcan_priv {
209 struct can_priv can; 216 struct can_priv can;
210 struct net_device *dev; 217 struct net_device *dev;
@@ -218,7 +225,7 @@ struct flexcan_priv {
218 struct clk *clk_per; 225 struct clk *clk_per;
219 struct flexcan_platform_data *pdata; 226 struct flexcan_platform_data *pdata;
220 const struct flexcan_devtype_data *devtype_data; 227 const struct flexcan_devtype_data *devtype_data;
221 struct regmap *gpr; 228 struct flexcan_stop_mode stm;
222 int id; 229 int id;
223}; 230};
224 231
@@ -269,28 +276,18 @@ static inline void flexcan_write(u32 val, void __iomem *addr)
269 276
270static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv) 277static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
271{ 278{
272 int val;
273
274 /* enable stop request */ 279 /* enable stop request */
275 if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) { 280 if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
276 val = priv->id ? IMX6Q_GPR13_CAN2_STOP_REQ : 281 regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
277 IMX6Q_GPR13_CAN1_STOP_REQ; 282 1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
278 regmap_update_bits(priv->gpr, IOMUXC_GPR13,
279 val, val);
280 }
281} 283}
282 284
283static inline void flexcan_exit_stop_mode(struct flexcan_priv *priv) 285static inline void flexcan_exit_stop_mode(struct flexcan_priv *priv)
284{ 286{
285 int val;
286
287 /* remove stop request */ 287 /* remove stop request */
288 if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) { 288 if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
289 val = priv->id ? IMX6Q_GPR13_CAN2_STOP_REQ : 289 regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
290 IMX6Q_GPR13_CAN1_STOP_REQ; 290 1 << priv->stm.req_bit, 0);
291 regmap_update_bits(priv->gpr, IOMUXC_GPR13,
292 val, 0);
293 }
294} 291}
295 292
296/* 293/*
@@ -1019,6 +1016,56 @@ static void unregister_flexcandev(struct net_device *dev)
1019 unregister_candev(dev); 1016 unregister_candev(dev);
1020} 1017}
1021 1018
1019static int flexcan_of_parse_stop_mode(struct platform_device *pdev)
1020{
1021 struct net_device *dev = platform_get_drvdata(pdev);
1022 struct device_node *np = pdev->dev.of_node;
1023 struct device_node *node;
1024 struct flexcan_priv *priv;
1025 phandle phandle;
1026 u32 out_val[5];
1027 int ret;
1028
1029 if (!np)
1030 return -EINVAL;
1031 /*
1032 * stop mode property format is:
1033 * <&gpr req_gpr req_bit ack_gpr ack_bit>.
1034 */
1035 ret = of_property_read_u32_array(np, "stop-mode", out_val, 5);
1036 if (ret) {
1037 dev_dbg(&pdev->dev, "no stop-mode property\n");
1038 return ret;
1039 }
1040 phandle = *out_val;
1041
1042 node = of_find_node_by_phandle(phandle);
1043 if (!node) {
1044 dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
1045 return PTR_ERR(node);
1046 }
1047
1048 priv = netdev_priv(dev);
1049 priv->stm.gpr = syscon_node_to_regmap(node);
1050 if (IS_ERR(priv->stm.gpr)) {
1051 dev_dbg(&pdev->dev, "could not find gpr regmap\n");
1052 return PTR_ERR(priv->stm.gpr);
1053 }
1054
1055 of_node_put(node);
1056
1057 priv->stm.req_gpr = out_val[1];
1058 priv->stm.req_bit = out_val[2];
1059 priv->stm.ack_gpr = out_val[3];
1060 priv->stm.ack_bit = out_val[4];
1061
1062 dev_dbg(&pdev->dev, "gpr %s req_gpr 0x%x req_bit %u ack_gpr 0x%x ack_bit %u\n",
1063 node->full_name, priv->stm.req_gpr,
1064 priv->stm.req_bit, priv->stm.ack_gpr,
1065 priv->stm.ack_bit);
1066 return 0;
1067}
1068
1022static const struct of_device_id flexcan_of_match[] = { 1069static const struct of_device_id flexcan_of_match[] = {
1023 { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, 1070 { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
1024 { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, 1071 { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
@@ -1143,17 +1190,10 @@ static int flexcan_probe(struct platform_device *pdev)
1143 devm_can_led_init(dev); 1190 devm_can_led_init(dev);
1144 1191
1145 if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) { 1192 if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) {
1146 priv->gpr = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 1193 err = flexcan_of_parse_stop_mode(pdev);
1147 "gpr"); 1194 if (err) {
1148 if (IS_ERR(priv->gpr)) {
1149 wakeup = 0;
1150 dev_dbg(&pdev->dev, "can not get grp\n");
1151 }
1152
1153 priv->id = of_alias_get_id(pdev->dev.of_node, "flexcan");
1154 if (priv->id < 0) {
1155 wakeup = 0; 1195 wakeup = 0;
1156 dev_dbg(&pdev->dev, "can not get alias id\n"); 1196 dev_dbg(&pdev->dev, "failed to parse stop-mode\n");
1157 } 1197 }
1158 } 1198 }
1159 1199