]> git.sur5r.net Git - u-boot/blobdiff - arch/arm/mach-keystone/psc.c
ARM: keystone2: psc: introduce function to hold and release module in reset.
[u-boot] / arch / arm / mach-keystone / psc.c
index 8991e237735e4cd00b1595efd27380247d3f4025..ff042a6db2dd158272b9509aa47ead5b89ee5784 100644 (file)
@@ -233,3 +233,107 @@ int psc_disable_domain(u32 domain_num)
 
        return psc_wait(domain_num);
 }
+
+/**
+ * psc_module_keep_in_reset_enabled() - Keep module in enabled,in-reset state
+ * @mod_num:   LPSC module number
+ * @gate_clocks: Can the clocks be gated on this module?
+ *
+ * Enable the module, but do not release the module from local reset. This is
+ * necessary for many processor systems on keystone SoCs to allow for system
+ * initialization from a master processor prior to releasing the processor
+ * from reset.
+ */
+int psc_module_keep_in_reset_enabled(u32 mod_num, bool gate_clocks)
+{
+       u32 mdctl, ptcmd, mdstat;
+       u32 next_state;
+       int domain_num = psc_get_domain_num(mod_num);
+       int timeout = 100000;
+
+       /* Wait for any previous transitions to complete */
+       psc_wait(domain_num);
+       mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
+       /* Should be set 0 to assert Local reset */
+       if ((mdctl & PSC_REG_MDCTL_SET_LRSTZ(mdctl, 1))) {
+               mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0);
+               __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
+               /* Wait for transition to take place */
+               psc_wait(domain_num);
+       }
+
+       /* Clear Module reset */
+       mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
+       next_state = gate_clocks ? PSC_REG_VAL_MDCTL_NEXT_OFF :
+                       PSC_REG_VAL_MDCTL_NEXT_ON;
+       mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, next_state);
+       __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
+       /* Trigger PD transition */
+       ptcmd = __raw_readl(KS2_PSC_BASE + PSC_REG_PTCMD);
+       ptcmd |= (u32)(1 << domain_num);
+       __raw_writel(ptcmd, KS2_PSC_BASE + PSC_REG_PTCMD);
+       psc_wait(domain_num);
+
+       mdstat = __raw_readl(KS2_PSC_BASE + PSC_REG_MDSTAT(mod_num));
+       while (timeout) {
+               mdstat = __raw_readl(KS2_PSC_BASE + PSC_REG_MDSTAT(mod_num));
+
+               if (!(PSC_REG_MDSTAT_GET_STATUS(mdstat) & 0x30) &&
+                   PSC_REG_MDSTAT_GET_MRSTDONE(mdstat) &&
+                   PSC_REG_MDSTAT_GET_LRSTDONE(mdstat))
+                       break;
+               timeout--;
+       }
+
+       if (!timeout) {
+               printf("%s: Timedout waiting for mdstat(0x%08x) to change\n",
+                      __func__, mdstat);
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+/**
+ * psc_module_release_from_reset() - Release the module from reset
+ * @mod_num:   LPSC module number
+ *
+ * This is the follow through for the command 'psc_module_keep_in_reset_enabled'
+ * Allowing the module to be released from reset once all required inits are
+ * complete for the module. Typically, this allows the processor module to start
+ * execution.
+ */
+int psc_module_release_from_reset(u32 mod_num)
+{
+       u32 mdctl, mdstat;
+       int domain_num = psc_get_domain_num(mod_num);
+       int timeout = 100000;
+
+       /* Wait for any previous transitions to complete */
+       psc_wait(domain_num);
+       mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
+       /* Should be set to 1 to de-assert Local reset */
+       if ((mdctl & PSC_REG_MDCTL_SET_LRSTZ(mdctl, 0))) {
+               mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl, 1);
+               __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num));
+               /* Wait for transition to take place */
+               psc_wait(domain_num);
+       }
+       mdstat = __raw_readl(KS2_PSC_BASE + PSC_REG_MDSTAT(mod_num));
+       while (timeout) {
+               mdstat = __raw_readl(KS2_PSC_BASE + PSC_REG_MDSTAT(mod_num));
+
+               if (!(PSC_REG_MDSTAT_GET_STATUS(mdstat) & 0x30) &&
+                   PSC_REG_MDSTAT_GET_MRSTDONE(mdstat) &&
+                   PSC_REG_MDSTAT_GET_LRSTDONE(mdstat))
+                       break;
+               timeout--;
+       }
+
+       if (!timeout) {
+               printf("%s: Timedout waiting for mdstat(0x%08x) to change\n",
+                      __func__, mdstat);
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}