diff options
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 33 | ||||
-rw-r--r-- | drivers/mfd/dbx500-prcmu-regs.h | 14 | ||||
-rw-r--r-- | include/linux/mfd/db8500-prcmu.h | 6 | ||||
-rw-r--r-- | include/linux/mfd/dbx500-prcmu.h | 13 |
4 files changed, 64 insertions, 2 deletions
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 536566a890d..186206daab7 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -426,6 +426,13 @@ static DEFINE_SPINLOCK(clkout_lock); /* Global var to runtime determine TCDM base for v2 or v1 */ static __iomem void *tcdm_base; +/* + * Copies of the startup values of the reset status register and the SW reset + * code. + */ +static u32 reset_status_copy; +static u16 reset_code_copy; + struct clk_mgt { void __iomem *reg; u32 pllsw; @@ -2404,7 +2411,17 @@ void db8500_prcmu_system_reset(u16 reset_code) */ u16 db8500_prcmu_get_reset_code(void) { - return readw(tcdm_base + PRCM_SW_RST_REASON); + return reset_code_copy; +} + +/** + * db8500_prcmu_get_reset_status - Retrieve reset status + * + * Retrieves the value of the reset status register as read at startup. + */ +u32 db8500_prcmu_get_reset_status(void) +{ + return reset_status_copy; } /** @@ -2689,6 +2706,7 @@ void __init db8500_prcmu_early_init(void) { unsigned int i; void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); + void __iomem *sec_base; if (tcpm_base != NULL) { u32 version; @@ -2707,6 +2725,19 @@ void __init db8500_prcmu_early_init(void) tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); + /* + * Copy the value of the reset status register and if needed also + * the software reset code. + */ + sec_base = ioremap_nocache(U8500_PRCMU_SEC_BASE, SZ_4K); + if (sec_base != NULL) { + reset_status_copy = readl(sec_base + + DB8500_SEC_PRCM_RESET_STATUS); + iounmap(sec_base); + } + if (reset_status_copy & DB8500_SEC_PRCM_RESET_STATUS_APE_SOFTWARE_RESET) + reset_code_copy = readw(tcdm_base + PRCM_SW_RST_REASON); + spin_lock_init(&mb0_transfer.lock); spin_lock_init(&mb0_transfer.dbb_irqs_lock); mutex_init(&mb0_transfer.ac_wake_lock); diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h index 48b84061db0..0835a57dac1 100644 --- a/drivers/mfd/dbx500-prcmu-regs.h +++ b/drivers/mfd/dbx500-prcmu-regs.h @@ -127,7 +127,6 @@ #define PRCM_ITSTATUS4 (_PRCMU_BASE + 0x168) #define PRCM_ITSTATUS5 (_PRCMU_BASE + 0x484) #define PRCM_ITCLEAR5 (_PRCMU_BASE + 0x488) -#define PRCM_ARMIT_MASKXP70_IT (_PRCMU_BASE + 0x1018) /* System reset register */ #define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228) @@ -250,4 +249,17 @@ /* System reset register */ #define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228) +/* Secure read-only registers */ +#define DB8500_SEC_PRCM_RESET_STATUS 0x03C +#define DB8500_SEC_PRCM_RESET_STATUS_A9_CPU0_WATCHDOG_RESET BIT(0) +#define DB8500_SEC_PRCM_RESET_STATUS_A9_CPU1_WATCHDOG_RESET BIT(1) +#define DB8500_SEC_PRCM_RESET_STATUS_APE_SOFTWARE_RESET BIT(2) +#define DB8500_SEC_PRCM_RESET_STATUS_APE_RESET BIT(3) +#define DB8500_SEC_PRCM_RESET_STATUS_SECURE_WATCHDOG BIT(4) +#define DB8500_SEC_PRCM_RESET_STATUS_POWER_ON_RESET BIT(5) +#define DB8500_SEC_PRCM_RESET_STATUS_A9_RESTART BIT(6) +#define DB8500_SEC_PRCM_RESET_STATUS_APE_RESTART BIT(7) +#define DB8500_SEC_PRCM_RESET_STATUS_MODEM_SOFTWARE_RESET BIT(8) +#define DB8500_SEC_PRCM_RESET_STATUS_BOOT_ENGI BIT(16) + #endif /* __DB8500_PRCMU_REGS_H */ diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index 0ef481f7edc..705af54b89f 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -486,6 +486,7 @@ void db8500_prcmu_config_abb_event_readout(u32 abb_events); void db8500_prcmu_get_abb_event_buffer(void __iomem **buf); int db8500_prcmu_config_esram0_deep_sleep(u8 state); u16 db8500_prcmu_get_reset_code(void); +u32 db8500_prcmu_get_reset_status(void); bool db8500_prcmu_is_ac_wake_requested(void); int db8500_prcmu_set_arm_opp(u8 opp); int db8500_prcmu_get_arm_opp(void); @@ -669,6 +670,11 @@ static inline u16 db8500_prcmu_get_reset_code(void) return 0; } +static inline u32 db8500_prcmu_get_reset_status(void) +{ + return 0; +} + static inline int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off) { return 0; diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 90fed71c29e..818209b84c0 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -447,6 +447,14 @@ static inline u16 prcmu_get_reset_code(void) return db8500_prcmu_get_reset_code(); } +static inline u32 prcmu_get_reset_status(void) +{ + if (cpu_is_u8500()) + return db8500_prcmu_get_reset_status(); + else + return 0; +} + void prcmu_ac_wake_req(void); void prcmu_ac_sleep_req(void); static inline void prcmu_modem_reset(void) @@ -696,6 +704,11 @@ static inline u16 prcmu_get_reset_code(void) return 0; } +static inline u32 prcmu_get_reset_status(void) +{ + return 0; +} + static inline void prcmu_ac_wake_req(void) {} static inline void prcmu_ac_sleep_req(void) {} |