After leaving the Partial-IO mode or other deep sleep states, the IO
isolation needs to be removed. This routine is shared by at least am62,
am62a and am62p.

The original function for testing was developed by
Akashdeep Kaur <[email protected]>

Signed-off-by: Markus Schneider-Pargmann (TI.com) <[email protected]>
---
 arch/arm/mach-k3/am62ax/am62a7_init.c |  5 +++
 arch/arm/mach-k3/am62px/am62p5_init.c |  5 +++
 arch/arm/mach-k3/am62x/am625_init.c   |  5 +++
 arch/arm/mach-k3/am62xx-lpm-common.c  | 85 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-k3/am62xx-lpm-common.h  |  1 +
 5 files changed, 101 insertions(+)

diff --git a/arch/arm/mach-k3/am62ax/am62a7_init.c 
b/arch/arm/mach-k3/am62ax/am62a7_init.c
index 
7de234611639d119db5c7a718738a02cedf8028c..c1c7d669a45f53b7528c80d44bf9b914fed1cc10
 100644
--- a/arch/arm/mach-k3/am62ax/am62a7_init.c
+++ b/arch/arm/mach-k3/am62ax/am62a7_init.c
@@ -14,6 +14,7 @@
 
 #include "../sysfw-loader.h"
 #include "../common.h"
+#include "../am62xx-lpm-common.h"
 
 #define CTRLMMR_MCU_RST_CTRL             0x04518170
 #define RST_CTRL_ESM_ERROR_RST_EN_Z_MASK 0xFFFDFFFF
@@ -101,6 +102,10 @@ void board_init_f(ulong dummy)
        /* Init DM early */
        spl_early_init();
 
+       ret = wkup_ctrl_remove_can_io_isolation_if_set();
+       if (ret)
+               panic("Failed to remove can IO isolation when set %d\n", ret);
+
        /*
         * Process pinctrl for the serial0 and serial3, aka WKUP_UART0 and
         * MAIN_UART1 modules and continue regardless of the result of pinctrl.
diff --git a/arch/arm/mach-k3/am62px/am62p5_init.c 
b/arch/arm/mach-k3/am62px/am62p5_init.c
index 
4c215d5cebed5930bce70bdc975fe31c437ce82b..a74fe3d23d7c4b66ac95aa5a01c2a32a586e9ced
 100644
--- a/arch/arm/mach-k3/am62px/am62p5_init.c
+++ b/arch/arm/mach-k3/am62px/am62p5_init.c
@@ -15,6 +15,7 @@
 
 #include "../sysfw-loader.h"
 #include "../common.h"
+#include "../am62xx-lpm-common.h"
 
 /* TISCI DEV ID for A53 Clock */
 #define AM62PX_DEV_A53SS0_CORE_0_DEV_ID 135
@@ -160,6 +161,10 @@ void board_init_f(ulong dummy)
        if (ret)
                panic("spl_early_init() failed: %d\n", ret);
 
+       ret = wkup_ctrl_remove_can_io_isolation_if_set();
+       if (ret)
+               panic("Failed to remove can IO isolation when set %d\n", ret);
+
        /*
         * Process pinctrl for the serial0 and serial3, aka WKUP_UART0 and
         * MAIN_UART1 modules and continue regardless of the result of pinctrl.
diff --git a/arch/arm/mach-k3/am62x/am625_init.c 
b/arch/arm/mach-k3/am62x/am625_init.c
index 
02b7414e21cd56faab795fe7b39eefcc67cb044a..d2deecb16670739cee20e2e525688ba61a434872
 100644
--- a/arch/arm/mach-k3/am62x/am625_init.c
+++ b/arch/arm/mach-k3/am62x/am625_init.c
@@ -16,6 +16,7 @@
 
 #include "../sysfw-loader.h"
 #include "../common.h"
+#include "../am62xx-lpm-common.h"
 
 #define RTC_BASE_ADDRESS               0x2b1f0000
 #define REG_K3RTC_S_CNT_LSW            (RTC_BASE_ADDRESS + 0x18)
@@ -201,6 +202,10 @@ void board_init_f(ulong dummy)
        /* Init DM early */
        spl_early_init();
 
+       ret = wkup_ctrl_remove_can_io_isolation_if_set();
+       if (ret)
+               panic("Failed to remove can IO isolation when set %d\n", ret);
+
        /*
         * Process pinctrl for the serial0 and serial3, aka WKUP_UART0 and
         * MAIN_UART1 modules and continue regardless of the result of pinctrl.
diff --git a/arch/arm/mach-k3/am62xx-lpm-common.c 
b/arch/arm/mach-k3/am62xx-lpm-common.c
index 
424d7457c596290ef48acd7f7aec3fd192dd3000..54d86b0474df691e8568a9c38530c56cc1eb3a0a
 100644
--- a/arch/arm/mach-k3/am62xx-lpm-common.c
+++ b/arch/arm/mach-k3/am62xx-lpm-common.c
@@ -9,15 +9,93 @@
 #include <config.h>
 #include <asm/arch/hardware.h>
 #include <asm/io.h>
+#include <wait_bit.h>
 
 #include "am62xx-lpm-common.h"
 
+/*
+ * Shared WKUP_CTRL_MMR0 definitions used to remove IO isolation
+ */
+#define WKUP_CTRL_MMR_PMCTRL_IO_0                              0x18084
+#define WKUP_CTRL_MMR_PMCTRL_IO_0_ISOCLK_OVRD_0                        BIT(0)
+#define WKUP_CTRL_MMR_PMCTRL_IO_0_ISOOVR_EXTEND_0              BIT(4)
+#define WKUP_CTRL_MMR_PMCTRL_IO_0_ISO_BYPASS_OVR_0             BIT(6)
+#define WKUP_CTRL_MMR_PMCTRL_IO_0_WUCLK_CTRL_0                 BIT(8)
+#define WKUP_CTRL_MMR_PMCTRL_IO_0_GLOBAL_WUEN_0                        BIT(16)
+#define WKUP_CTRL_MMR_PMCTRL_IO_0_IO_ISO_CTRL_0                        BIT(24)
+#define WKUP_CTRL_MMR_PMCTRL_IO_0_WRITE_MASK ( \
+               WKUP_CTRL_MMR_PMCTRL_IO_0_ISOCLK_OVRD_0 |       \
+               WKUP_CTRL_MMR_PMCTRL_IO_0_ISOOVR_EXTEND_0 |     \
+               WKUP_CTRL_MMR_PMCTRL_IO_0_ISO_BYPASS_OVR_0 |    \
+               WKUP_CTRL_MMR_PMCTRL_IO_0_WUCLK_CTRL_0 |        \
+               WKUP_CTRL_MMR_PMCTRL_IO_0_GLOBAL_WUEN_0 |       \
+               WKUP_CTRL_MMR_PMCTRL_IO_0_IO_ISO_CTRL_0)
+
+#define WKUP_CTRL_MMR_PMCTRL_IO_GLB                            0x1809c
+#define WKUP_CTRL_MMR_DEEPSLEEP_CTRL                           0x18160
+
+#define WKUP_CTRL_MMR_CANUART_WAKE_CTRL                                0x18300
+#define WKUP_CTRL_MMR_CANUART_WAKE_CTRL_MW                     0x2aaaaaaa
+#define WKUP_CTRL_MMR_CANUART_WAKE_CTRL_MW_SHIFT               1
+#define WKUP_CTRL_MMR_CANUART_WAKE_CTRL_MW_LOAD_EN             BIT(0)
+
 #define WKUP_CTRL_MMR_CANUART_WAKE_STAT1                       0x1830c
 #define WKUP_CTRL_MMR_CANUART_WAKE_STAT1_CANUART_IO_MODE       BIT(0)
 
 #define WKUP_CTRL_MMR_CANUART_WAKE_OFF_MODE_STAT               0x18318
 #define WKUP_CTRL_MMR_CANUART_WAKE_OFF_MODE_STAT_MW            0x555555
 
+#define CLKSTOP_TRANSITION_TIMEOUT_MS  10
+
+static int wkup_ctrl_remove_can_io_isolation(void)
+{
+       const void *wait_reg = (const void *)(WKUP_CTRL_MMR0_BASE +
+                                             WKUP_CTRL_MMR_CANUART_WAKE_STAT1);
+       int ret;
+       u32 reg = 0;
+
+       /* Program magic word */
+       reg = readl(WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_CANUART_WAKE_CTRL);
+       reg |= WKUP_CTRL_MMR_CANUART_WAKE_CTRL_MW << 
WKUP_CTRL_MMR_CANUART_WAKE_CTRL_MW_SHIFT;
+       writel(reg, WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_CANUART_WAKE_CTRL);
+
+       /* Set enable bit. */
+       reg |= WKUP_CTRL_MMR_CANUART_WAKE_CTRL_MW_LOAD_EN;
+       writel(reg, WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_CANUART_WAKE_CTRL);
+
+       /* Clear enable bit. */
+       reg &= ~WKUP_CTRL_MMR_CANUART_WAKE_CTRL_MW_LOAD_EN;
+       writel(reg, WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_CANUART_WAKE_CTRL);
+
+       /* wait for CAN_ONLY_IO signal to be 0 */
+       ret = wait_for_bit_32(wait_reg,
+                             WKUP_CTRL_MMR_CANUART_WAKE_STAT1_CANUART_IO_MODE,
+                             false,
+                             CLKSTOP_TRANSITION_TIMEOUT_MS,
+                             false);
+       if (ret < 0)
+               return ret;
+
+       /* Reset magic word */
+       writel(0, WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_CANUART_WAKE_CTRL);
+
+       /* Remove WKUP IO isolation */
+       reg = readl(WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_PMCTRL_IO_0);
+       reg = reg & WKUP_CTRL_MMR_PMCTRL_IO_0_WRITE_MASK & 
~WKUP_CTRL_MMR_PMCTRL_IO_0_GLOBAL_WUEN_0;
+       writel(reg, WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_PMCTRL_IO_0);
+
+       /* clear global IO isolation */
+       reg = readl(WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_PMCTRL_IO_0);
+       reg = reg & WKUP_CTRL_MMR_PMCTRL_IO_0_WRITE_MASK & 
~WKUP_CTRL_MMR_PMCTRL_IO_0_IO_ISO_CTRL_0;
+       writel(reg, WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_PMCTRL_IO_0);
+
+       /* Release all IOs from deepsleep mode and clear IO daisy chain control 
*/
+       writel(0, WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_DEEPSLEEP_CTRL);
+       writel(0, WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_PMCTRL_IO_GLB);
+
+       return 0;
+}
+
 static bool wkup_ctrl_canuart_wakeup_active(void)
 {
        return !!(readl(WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_CANUART_WAKE_STAT1) 
&
@@ -36,3 +114,10 @@ bool wkup_ctrl_is_lpm_exit(void)
                wkup_ctrl_canuart_wakeup_active() &&
                wkup_ctrl_canuart_magic_word_set();
 }
+
+int __maybe_unused wkup_ctrl_remove_can_io_isolation_if_set(void)
+{
+       if (wkup_ctrl_canuart_wakeup_active() && 
!wkup_ctrl_canuart_magic_word_set())
+               return wkup_ctrl_remove_can_io_isolation();
+       return 0;
+}
diff --git a/arch/arm/mach-k3/am62xx-lpm-common.h 
b/arch/arm/mach-k3/am62xx-lpm-common.h
index 
36dcd20a9b802bb0eae8dfa56836e7da70107e62..2d110bcca0fc74ecd5424ae288d43519d0c05908
 100644
--- a/arch/arm/mach-k3/am62xx-lpm-common.h
+++ b/arch/arm/mach-k3/am62xx-lpm-common.h
@@ -12,5 +12,6 @@
 #include <asm/io.h>
 
 bool wkup_ctrl_is_lpm_exit(void);
+int wkup_ctrl_remove_can_io_isolation_if_set(void);
 
 #endif  /* _AM62XX_LPM_COMMON_H_ */

-- 
2.51.0

Reply via email to