diff options
author | Pavel Machek <pavel@denx.de> | 2014-05-13 09:09:14 -0400 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2014-05-19 03:38:23 -0400 |
commit | a9c692099e2c6f85d2213be75095593311074ce1 (patch) | |
tree | 1d3e10ae69fb464ec2893ca7f9a4f8f70781326b /drivers/net/can/c_can | |
parent | ccbc5357db3098c57176945f677b0af37f5e87e6 (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.h | 2 | ||||
-rw-r--r-- | drivers/net/can/c_can/c_can_platform.c | 40 |
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 | ||
83 | static const u16 reg_map_c_can[] = { | 84 | static 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) | ||
43 | static DEFINE_SPINLOCK(raminit_lock); | 44 | static 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 | ||
83 | static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) | 84 | static 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 | ||
140 | static 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 | |||
146 | static 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 | |||
139 | static struct platform_device_id c_can_id_table[] = { | 162 | static 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; |