#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
  * architecture of different implementations. For example: 16-bit
        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)
 {
-       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[] = {