summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/db8500-prcmu.c33
-rw-r--r--drivers/mfd/dbx500-prcmu-regs.h14
-rw-r--r--include/linux/mfd/db8500-prcmu.h6
-rw-r--r--include/linux/mfd/dbx500-prcmu.h13
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) {}