|
@@ -37,8 +37,10 @@
|
|
|
|
|
|
#include "c_can.h"
|
|
#include "c_can.h"
|
|
|
|
|
|
-#define CAN_RAMINIT_START_MASK(i) (1 << (i))
|
|
|
|
-
|
|
|
|
|
|
+#define CAN_RAMINIT_START_MASK(i) (0x001 << (i))
|
|
|
|
+#define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i))
|
|
|
|
+#define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i))
|
|
|
|
+static DEFINE_SPINLOCK(raminit_lock);
|
|
/*
|
|
/*
|
|
* 16-bit c_can registers can be arranged differently in the memory
|
|
* 16-bit c_can registers can be arranged differently in the memory
|
|
* architecture of different implementations. For example: 16-bit
|
|
* architecture of different implementations. For example: 16-bit
|
|
@@ -69,16 +71,41 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv,
|
|
writew(val, priv->base + 2 * priv->regs[index]);
|
|
writew(val, priv->base + 2 * priv->regs[index]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void c_can_hw_raminit_wait(const struct c_can_priv *priv, u32 mask,
|
|
|
|
+ u32 val)
|
|
|
|
+{
|
|
|
|
+ /* We look only at the bits of our instance. */
|
|
|
|
+ val &= mask;
|
|
|
|
+ while ((readl(priv->raminit_ctrlreg) & mask) != val)
|
|
|
|
+ udelay(1);
|
|
|
|
+}
|
|
|
|
+
|
|
static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
|
|
static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
|
|
{
|
|
{
|
|
- u32 val;
|
|
|
|
-
|
|
|
|
- val = readl(priv->raminit_ctrlreg);
|
|
|
|
- if (enable)
|
|
|
|
- val |= CAN_RAMINIT_START_MASK(priv->instance);
|
|
|
|
- else
|
|
|
|
- val &= ~CAN_RAMINIT_START_MASK(priv->instance);
|
|
|
|
- writel(val, priv->raminit_ctrlreg);
|
|
|
|
|
|
+ u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance);
|
|
|
|
+ u32 ctrl;
|
|
|
|
+
|
|
|
|
+ spin_lock(&raminit_lock);
|
|
|
|
+
|
|
|
|
+ ctrl = readl(priv->raminit_ctrlreg);
|
|
|
|
+ /* We clear the done and start bit first. The start bit is
|
|
|
|
+ * looking at the 0 -> transition, but is not self clearing;
|
|
|
|
+ * And we clear the init done bit as well.
|
|
|
|
+ */
|
|
|
|
+ ctrl &= ~CAN_RAMINIT_START_MASK(priv->instance);
|
|
|
|
+ ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
|
|
|
|
+ writel(ctrl, priv->raminit_ctrlreg);
|
|
|
|
+ ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance);
|
|
|
|
+ c_can_hw_raminit_wait(priv, ctrl, mask);
|
|
|
|
+
|
|
|
|
+ if (enable) {
|
|
|
|
+ /* Set start bit and wait for the done bit. */
|
|
|
|
+ ctrl |= CAN_RAMINIT_START_MASK(priv->instance);
|
|
|
|
+ writel(ctrl, priv->raminit_ctrlreg);
|
|
|
|
+ ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
|
|
|
|
+ c_can_hw_raminit_wait(priv, ctrl, mask);
|
|
|
|
+ }
|
|
|
|
+ spin_unlock(&raminit_lock);
|
|
}
|
|
}
|
|
|
|
|
|
static struct platform_device_id c_can_id_table[] = {
|
|
static struct platform_device_id c_can_id_table[] = {
|