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

