diff options
author | AnilKumar Ch <anilkumar@ti.com> | 2012-11-21 00:44:10 -0500 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2012-11-27 03:49:31 -0500 |
commit | 52cde85acc23f61b09dd0376c61eb891125c6990 (patch) | |
tree | b44c83102549a37b8bd4abae7ace6989e1e6f0c5 /drivers/net/can | |
parent | 03f52a0a554210d5049eeed9f1bb29047dc807cb (diff) |
can: c_can: Add d_can raminit support
Add D_CAN raminit support to C_CAN driver to enable D_CAN RAM,
which holds all the message objects during transmission or
receiving of data. This initialization/de-initialization should
be done in synchronous with D_CAN clock.
In case of AM335X-EVM (current user of D_CAN driver) message RAM is
controlled through control module register for both instances. So
control module register details is required to initialization or
de-initialization of message RAM according to instance number.
Control module memory resource is obtained from D_CAN dt node and
instance number obtained from device tree aliases node.
This patch was tested on AM335x-EVM along with pinctrl data addition
patch, d_can dt aliases addition and control module data addition.
pinctrl data addition is not added to am335x-evm.dts (only supports
CPLD profile#0) because d_can1 is supported under CPLD profile#1.
Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
[mkl: fix instance for non DT in probe, cleaned up raminit]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/c_can/c_can.c | 12 | ||||
-rw-r--r-- | drivers/net/can/c_can/c_can.h | 3 | ||||
-rw-r--r-- | drivers/net/can/c_can/c_can_platform.c | 28 |
3 files changed, 42 insertions, 1 deletions
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index e5180dfddba5..5233b8f58d77 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c | |||
@@ -233,6 +233,12 @@ static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv) | |||
233 | pm_runtime_put_sync(priv->device); | 233 | pm_runtime_put_sync(priv->device); |
234 | } | 234 | } |
235 | 235 | ||
236 | static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable) | ||
237 | { | ||
238 | if (priv->raminit) | ||
239 | priv->raminit(priv, enable); | ||
240 | } | ||
241 | |||
236 | static inline int get_tx_next_msg_obj(const struct c_can_priv *priv) | 242 | static inline int get_tx_next_msg_obj(const struct c_can_priv *priv) |
237 | { | 243 | { |
238 | return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) + | 244 | return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) + |
@@ -1090,6 +1096,7 @@ static int c_can_open(struct net_device *dev) | |||
1090 | struct c_can_priv *priv = netdev_priv(dev); | 1096 | struct c_can_priv *priv = netdev_priv(dev); |
1091 | 1097 | ||
1092 | c_can_pm_runtime_get_sync(priv); | 1098 | c_can_pm_runtime_get_sync(priv); |
1099 | c_can_reset_ram(priv, true); | ||
1093 | 1100 | ||
1094 | /* open the can device */ | 1101 | /* open the can device */ |
1095 | err = open_candev(dev); | 1102 | err = open_candev(dev); |
@@ -1118,6 +1125,7 @@ static int c_can_open(struct net_device *dev) | |||
1118 | exit_irq_fail: | 1125 | exit_irq_fail: |
1119 | close_candev(dev); | 1126 | close_candev(dev); |
1120 | exit_open_fail: | 1127 | exit_open_fail: |
1128 | c_can_reset_ram(priv, false); | ||
1121 | c_can_pm_runtime_put_sync(priv); | 1129 | c_can_pm_runtime_put_sync(priv); |
1122 | return err; | 1130 | return err; |
1123 | } | 1131 | } |
@@ -1131,6 +1139,8 @@ static int c_can_close(struct net_device *dev) | |||
1131 | c_can_stop(dev); | 1139 | c_can_stop(dev); |
1132 | free_irq(dev->irq, dev); | 1140 | free_irq(dev->irq, dev); |
1133 | close_candev(dev); | 1141 | close_candev(dev); |
1142 | |||
1143 | c_can_reset_ram(priv, false); | ||
1134 | c_can_pm_runtime_put_sync(priv); | 1144 | c_can_pm_runtime_put_sync(priv); |
1135 | 1145 | ||
1136 | return 0; | 1146 | return 0; |
@@ -1188,6 +1198,7 @@ int c_can_power_down(struct net_device *dev) | |||
1188 | 1198 | ||
1189 | c_can_stop(dev); | 1199 | c_can_stop(dev); |
1190 | 1200 | ||
1201 | c_can_reset_ram(priv, false); | ||
1191 | c_can_pm_runtime_put_sync(priv); | 1202 | c_can_pm_runtime_put_sync(priv); |
1192 | 1203 | ||
1193 | return 0; | 1204 | return 0; |
@@ -1206,6 +1217,7 @@ int c_can_power_up(struct net_device *dev) | |||
1206 | WARN_ON(priv->type != BOSCH_D_CAN); | 1217 | WARN_ON(priv->type != BOSCH_D_CAN); |
1207 | 1218 | ||
1208 | c_can_pm_runtime_get_sync(priv); | 1219 | c_can_pm_runtime_get_sync(priv); |
1220 | c_can_reset_ram(priv, true); | ||
1209 | 1221 | ||
1210 | /* Clear PDR and INIT bits */ | 1222 | /* Clear PDR and INIT bits */ |
1211 | val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); | 1223 | val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); |
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index e5ed41dafa1b..d2e1c21b143f 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h | |||
@@ -169,6 +169,9 @@ struct c_can_priv { | |||
169 | void *priv; /* for board-specific data */ | 169 | void *priv; /* for board-specific data */ |
170 | u16 irqstatus; | 170 | u16 irqstatus; |
171 | enum c_can_dev_id type; | 171 | enum c_can_dev_id type; |
172 | u32 __iomem *raminit_ctrlreg; | ||
173 | unsigned int instance; | ||
174 | void (*raminit) (const struct c_can_priv *priv, bool enable); | ||
172 | }; | 175 | }; |
173 | 176 | ||
174 | struct net_device *alloc_c_can_dev(void); | 177 | struct net_device *alloc_c_can_dev(void); |
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index ee1416132aba..75c3f472a023 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c | |||
@@ -38,6 +38,8 @@ | |||
38 | 38 | ||
39 | #include "c_can.h" | 39 | #include "c_can.h" |
40 | 40 | ||
41 | #define CAN_RAMINIT_START_MASK(i) (1 << (i)) | ||
42 | |||
41 | /* | 43 | /* |
42 | * 16-bit c_can registers can be arranged differently in the memory | 44 | * 16-bit c_can registers can be arranged differently in the memory |
43 | * architecture of different implementations. For example: 16-bit | 45 | * architecture of different implementations. For example: 16-bit |
@@ -68,6 +70,18 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv, | |||
68 | writew(val, priv->base + 2 * priv->regs[index]); | 70 | writew(val, priv->base + 2 * priv->regs[index]); |
69 | } | 71 | } |
70 | 72 | ||
73 | static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) | ||
74 | { | ||
75 | u32 val; | ||
76 | |||
77 | val = readl(priv->raminit_ctrlreg); | ||
78 | if (enable) | ||
79 | val |= CAN_RAMINIT_START_MASK(priv->instance); | ||
80 | else | ||
81 | val &= ~CAN_RAMINIT_START_MASK(priv->instance); | ||
82 | writel(val, priv->raminit_ctrlreg); | ||
83 | } | ||
84 | |||
71 | static struct platform_device_id c_can_id_table[] = { | 85 | static struct platform_device_id c_can_id_table[] = { |
72 | [BOSCH_C_CAN_PLATFORM] = { | 86 | [BOSCH_C_CAN_PLATFORM] = { |
73 | .name = KBUILD_MODNAME, | 87 | .name = KBUILD_MODNAME, |
@@ -99,7 +113,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) | |||
99 | const struct of_device_id *match; | 113 | const struct of_device_id *match; |
100 | const struct platform_device_id *id; | 114 | const struct platform_device_id *id; |
101 | struct pinctrl *pinctrl; | 115 | struct pinctrl *pinctrl; |
102 | struct resource *mem; | 116 | struct resource *mem, *res; |
103 | int irq; | 117 | int irq; |
104 | struct clk *clk; | 118 | struct clk *clk; |
105 | 119 | ||
@@ -178,6 +192,18 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev) | |||
178 | priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; | 192 | priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; |
179 | priv->read_reg = c_can_plat_read_reg_aligned_to_16bit; | 193 | priv->read_reg = c_can_plat_read_reg_aligned_to_16bit; |
180 | priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; | 194 | priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; |
195 | |||
196 | if (pdev->dev.of_node) | ||
197 | priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can"); | ||
198 | else | ||
199 | priv->instance = pdev->id; | ||
200 | |||
201 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
202 | priv->raminit_ctrlreg = devm_request_and_ioremap(&pdev->dev, res); | ||
203 | if (!priv->raminit_ctrlreg || priv->instance < 0) | ||
204 | dev_info(&pdev->dev, "control memory is not used for raminit\n"); | ||
205 | else | ||
206 | priv->raminit = c_can_hw_raminit; | ||
181 | break; | 207 | break; |
182 | default: | 208 | default: |
183 | ret = -EINVAL; | 209 | ret = -EINVAL; |