aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can/c_can
diff options
context:
space:
mode:
authorPavel Machek <pavel@denx.de>2014-05-13 09:09:14 -0400
committerMarc Kleine-Budde <mkl@pengutronix.de>2014-05-19 03:38:23 -0400
commita9c692099e2c6f85d2213be75095593311074ce1 (patch)
tree1d3e10ae69fb464ec2893ca7f9a4f8f70781326b /drivers/net/can/c_can
parentccbc5357db3098c57176945f677b0af37f5e87e6 (diff)
can: c_can: add hwinit support for non-TI devices
Non-TI chips (including socfpga) needs different raminit sequence. Implement it. Tested-by: Thor Thayer <tthayer@altera.com> Signed-off-by: Thor Thayer <tthayer@altera.com> Signed-off-by: Pavel Machek <pavel@denx.de> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/c_can')
-rw-r--r--drivers/net/can/c_can/c_can.h2
-rw-r--r--drivers/net/can/c_can/c_can_platform.c40
2 files changed, 38 insertions, 4 deletions
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 44433e1ebe00..99ad1aa576b0 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -78,6 +78,7 @@ enum reg {
78 C_CAN_INTPND2_REG, 78 C_CAN_INTPND2_REG,
79 C_CAN_MSGVAL1_REG, 79 C_CAN_MSGVAL1_REG,
80 C_CAN_MSGVAL2_REG, 80 C_CAN_MSGVAL2_REG,
81 C_CAN_FUNCTION_REG,
81}; 82};
82 83
83static const u16 reg_map_c_can[] = { 84static const u16 reg_map_c_can[] = {
@@ -129,6 +130,7 @@ static const u16 reg_map_d_can[] = {
129 [C_CAN_BRPEXT_REG] = 0x0E, 130 [C_CAN_BRPEXT_REG] = 0x0E,
130 [C_CAN_INT_REG] = 0x10, 131 [C_CAN_INT_REG] = 0x10,
131 [C_CAN_TEST_REG] = 0x14, 132 [C_CAN_TEST_REG] = 0x14,
133 [C_CAN_FUNCTION_REG] = 0x18,
132 [C_CAN_TXRQST1_REG] = 0x88, 134 [C_CAN_TXRQST1_REG] = 0x88,
133 [C_CAN_TXRQST2_REG] = 0x8A, 135 [C_CAN_TXRQST2_REG] = 0x8A,
134 [C_CAN_NEWDAT1_REG] = 0x9C, 136 [C_CAN_NEWDAT1_REG] = 0x9C,
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 0db3625b691f..824108cd9fd5 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -40,6 +40,7 @@
40#define CAN_RAMINIT_START_MASK(i) (0x001 << (i)) 40#define CAN_RAMINIT_START_MASK(i) (0x001 << (i))
41#define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i)) 41#define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i))
42#define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i)) 42#define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i))
43#define DCAN_RAM_INIT_BIT (1 << 3)
43static DEFINE_SPINLOCK(raminit_lock); 44static DEFINE_SPINLOCK(raminit_lock);
44/* 45/*
45 * 16-bit c_can registers can be arranged differently in the memory 46 * 16-bit c_can registers can be arranged differently in the memory
@@ -80,7 +81,7 @@ static void c_can_hw_raminit_wait_ti(const struct c_can_priv *priv, u32 mask,
80 udelay(1); 81 udelay(1);
81} 82}
82 83
83static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) 84static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable)
84{ 85{
85 u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance); 86 u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance);
86 u32 ctrl; 87 u32 ctrl;
@@ -96,14 +97,14 @@ static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
96 ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); 97 ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
97 writel(ctrl, priv->raminit_ctrlreg); 98 writel(ctrl, priv->raminit_ctrlreg);
98 ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance); 99 ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance);
99 c_can_hw_raminit_wait(priv, ctrl, mask); 100 c_can_hw_raminit_wait_ti(priv, ctrl, mask);
100 101
101 if (enable) { 102 if (enable) {
102 /* Set start bit and wait for the done bit. */ 103 /* Set start bit and wait for the done bit. */
103 ctrl |= CAN_RAMINIT_START_MASK(priv->instance); 104 ctrl |= CAN_RAMINIT_START_MASK(priv->instance);
104 writel(ctrl, priv->raminit_ctrlreg); 105 writel(ctrl, priv->raminit_ctrlreg);
105 ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); 106 ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
106 c_can_hw_raminit_wait(priv, ctrl, mask); 107 c_can_hw_raminit_wait_ti(priv, ctrl, mask);
107 } 108 }
108 spin_unlock(&raminit_lock); 109 spin_unlock(&raminit_lock);
109} 110}
@@ -136,6 +137,28 @@ static void d_can_plat_write_reg32(const struct c_can_priv *priv, enum reg index
136 writel(val, priv->base + priv->regs[index]); 137 writel(val, priv->base + priv->regs[index]);
137} 138}
138 139
140static 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
146static 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
139static struct platform_device_id c_can_id_table[] = { 162static struct platform_device_id c_can_id_table[] = {
140 [BOSCH_C_CAN_PLATFORM] = { 163 [BOSCH_C_CAN_PLATFORM] = {
141 .name = KBUILD_MODNAME, 164 .name = KBUILD_MODNAME,
@@ -255,11 +278,20 @@ static int c_can_plat_probe(struct platform_device *pdev)
255 priv->instance = pdev->id; 278 priv->instance = pdev->id;
256 279
257 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 280 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
281 /* Not all D_CAN modules have a separate register for the D_CAN
282 * RAM initialization. Use default RAM init bit in D_CAN module
283 * if not specified in DT.
284 */
285 if (!res) {
286 priv->raminit = c_can_hw_raminit;
287 break;
288 }
289
258 priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res); 290 priv->raminit_ctrlreg = devm_ioremap_resource(&pdev->dev, res);
259 if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0) 291 if (IS_ERR(priv->raminit_ctrlreg) || priv->instance < 0)
260 dev_info(&pdev->dev, "control memory is not used for raminit\n"); 292 dev_info(&pdev->dev, "control memory is not used for raminit\n");
261 else 293 else
262 priv->raminit = c_can_hw_raminit; 294 priv->raminit = c_can_hw_raminit_ti;
263 break; 295 break;
264 default: 296 default:
265 ret = -EINVAL; 297 ret = -EINVAL;