From b56ccf8470273e5a069cc5e76d32f24efd5963d0 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Mon, 13 Jun 2011 16:45:53 +0200 Subject: ARM: ux500: prcmu: Add A9 watchdog interface ST-Ericsson Linux next: Not tested, ask SSM for ER ST-Ericsson ID: 339924 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I6b1d9aa38b547673355f0277dd233ce964c88df1 Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25028 --- arch/arm/mach-ux500/include/mach/prcmu-db8500.h | 31 +++++++++ arch/arm/mach-ux500/prcmu-db8500.c | 89 +++++++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/arch/arm/mach-ux500/include/mach/prcmu-db8500.h b/arch/arm/mach-ux500/include/mach/prcmu-db8500.h index 4ba3b15d8fa..659f9205d2e 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu-db8500.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-db8500.h @@ -186,6 +186,12 @@ int prcmu_stop_temp_sense(void); void prcmu_enable_spi2(void); void prcmu_disable_spi2(void); +int prcmu_config_a9wdog(u8 num, bool sleep_auto_off); +int prcmu_enable_a9wdog(u8 id); +int prcmu_disable_a9wdog(u8 id); +int prcmu_kick_a9wdog(u8 id); +int prcmu_load_a9wdog(u8 id, u32 val); + void db8500_prcmu_system_reset(u16 reset_code); int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll); @@ -329,6 +335,31 @@ static inline void db8500_prcmu_config_abb_event_readout(u32 abb_events) {} static inline void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) {} +static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) +{ + return 0; +} + +static inline int prcmu_enable_a9wdog(u8 id) +{ + return 0; +} + +static inline int prcmu_disable_a9wdog(u8 id) +{ + return 0; +} + +static inline int prcmu_kick_a9wdog(u8 id) +{ + return 0; +} + +static inline int prcmu_load_a9wdog(u8 id, u32 val) +{ + return 0; +} + #endif /* CONFIG_UX500_SOC_DB8500 */ #endif /* __MACH_PRCMU_DB8500_H */ diff --git a/arch/arm/mach-ux500/prcmu-db8500.c b/arch/arm/mach-ux500/prcmu-db8500.c index 58f5ec330f7..8ba0ac315f2 100644 --- a/arch/arm/mach-ux500/prcmu-db8500.c +++ b/arch/arm/mach-ux500/prcmu-db8500.c @@ -193,6 +193,11 @@ #define MB4H_HOTDOG 0x12 #define MB4H_HOTMON 0x13 #define MB4H_HOT_PERIOD 0x14 +#define MB4H_A9WDOG_CONF 0x16 +#define MB4H_A9WDOG_EN 0x17 +#define MB4H_A9WDOG_DIS 0x18 +#define MB4H_A9WDOG_LOAD 0x19 +#define MB4H_A9WDOG_KICK 0x20 /* Mailbox 4 Requests */ #define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0) @@ -205,6 +210,13 @@ #define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0) #define HOTMON_CONFIG_LOW BIT(0) #define HOTMON_CONFIG_HIGH BIT(1) +#define PRCM_REQ_MB4_A9WDOG_0 (PRCM_REQ_MB4 + 0x0) +#define PRCM_REQ_MB4_A9WDOG_1 (PRCM_REQ_MB4 + 0x1) +#define PRCM_REQ_MB4_A9WDOG_2 (PRCM_REQ_MB4 + 0x2) +#define PRCM_REQ_MB4_A9WDOG_3 (PRCM_REQ_MB4 + 0x3) +#define A9WDOG_AUTO_OFF_EN BIT(7) +#define A9WDOG_AUTO_OFF_DIS 0 +#define A9WDOG_ID_MASK 0xf /* Mailbox 5 Requests */ #define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0) @@ -1546,6 +1558,78 @@ int prcmu_stop_temp_sense(void) return config_hot_period(0xFFFF); } +static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) +{ + + mutex_lock(&mb4_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + cpu_relax(); + + writeb(d0, (tcdm_base + PRCM_REQ_MB4_A9WDOG_0)); + writeb(d1, (tcdm_base + PRCM_REQ_MB4_A9WDOG_1)); + writeb(d2, (tcdm_base + PRCM_REQ_MB4_A9WDOG_2)); + writeb(d3, (tcdm_base + PRCM_REQ_MB4_A9WDOG_3)); + + writeb(cmd, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); + + writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + wait_for_completion(&mb4_transfer.work); + + mutex_unlock(&mb4_transfer.lock); + + return 0; + +} + +int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) +{ + BUG_ON(num == 0 || num > 0xf); + return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, + sleep_auto_off ? A9WDOG_AUTO_OFF_EN : + A9WDOG_AUTO_OFF_DIS); +} + +int prcmu_enable_a9wdog(u8 id) +{ + return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); +} + +int prcmu_disable_a9wdog(u8 id) +{ + return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); +} + +int prcmu_kick_a9wdog(u8 id) +{ + return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); +} + +/* + * timeout is 28 bit, in ms. + */ +#define MAX_WATCHDOG_TIMEOUT 131000 +int prcmu_load_a9wdog(u8 id, u32 timeout) +{ + if (timeout > MAX_WATCHDOG_TIMEOUT) + /* + * Due to calculation bug in prcmu fw, timeouts + * can't be bigger than 131 seconds. + */ + return -EINVAL; + + return prcmu_a9wdog(MB4H_A9WDOG_LOAD, + (id & A9WDOG_ID_MASK) | + /* + * Put the lowest 28 bits of timeout at + * offset 4. Four first bits are used for id. + */ + (u8)((timeout << 4) & 0xf0), + (u8)((timeout >> 4) & 0xff), + (u8)((timeout >> 12) & 0xff), + (u8)((timeout >> 20) & 0xff)); +} + /** * prcmu_set_clock_divider() - Configure the clock divider. * @clock: The clock for which the request is made. @@ -1898,6 +1982,11 @@ static bool read_mailbox_4(void) case MB4H_HOTDOG: case MB4H_HOTMON: case MB4H_HOT_PERIOD: + case MB4H_A9WDOG_CONF: + case MB4H_A9WDOG_EN: + case MB4H_A9WDOG_DIS: + case MB4H_A9WDOG_LOAD: + case MB4H_A9WDOG_KICK: break; default: print_unknown_header_warning(4, header); -- cgit v1.2.3