diff options
author | Vijaya Kumar Kilari <vijay.kilari@stericsson.com> | 2011-09-16 16:02:41 +0530 |
---|---|---|
committer | Rabin VINCENT <rabin.vincent@stericsson.com> | 2011-10-03 09:21:33 +0200 |
commit | 869fca5fdba5e63dfdcbf60141fe7a3225e1d0b4 (patch) | |
tree | 7cafcfd75ee798666f561d45c9f94f2dd19418a7 | |
parent | 36fe5ea2a6ce0c8c0b2c007ca54b6ac8167cff45 (diff) |
U5500: PRCMU MBOX4 support for Hotdog and hotmon
PRCMU driver interface for thermal management
of DB5500. MBOX4 supports to
- configure hotmon period
- configure hotdog ranges
- read current temperature
ST-Ericsson Linux next: -
ST-Ericsson ID: 334775
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: If25acd1d500800053bd6c511a64c9e5726c69647
Signed-off-by: Vijaya Kumar Kilari <vijay.kilari@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/28334
Reviewed-by: QABUILD
Reviewed-by: QATEST
Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32788
Tested-by: Venkata Biswanath DEVARASETTY <venkata.biswanath@stericsson.com>
Reviewed-by: Rabin VINCENT <rabin.vincent@stericsson.com>
-rw-r--r-- | drivers/mfd/db5500-prcmu.c | 166 | ||||
-rw-r--r-- | drivers/mfd/db8500-prcmu.c | 8 | ||||
-rw-r--r-- | include/linux/mfd/db5500-prcmu.h | 28 | ||||
-rw-r--r-- | include/linux/mfd/db8500-prcmu.h | 16 | ||||
-rw-r--r-- | include/linux/mfd/dbx500-prcmu.h | 53 |
5 files changed, 258 insertions, 13 deletions
diff --git a/drivers/mfd/db5500-prcmu.c b/drivers/mfd/db5500-prcmu.c index 3b54088a6e0..8594f5d528c 100644 --- a/drivers/mfd/db5500-prcmu.c +++ b/drivers/mfd/db5500-prcmu.c @@ -73,6 +73,11 @@ #define PRCM_ACK_MB6 (tcdm_base + 0xF0C) #define PRCM_ACK_MB7 (tcdm_base + 0xF08) +/* Share info */ +#define PRCM_SHARE_INFO (tcdm_base + 0xEC8) + +#define PRCM_SHARE_INFO_HOTDOG (PRCM_SHARE_INFO + 62) + /* Mailbox 0 REQs */ #define PRCM_REQ_MB0_AP_POWER_STATE (PRCM_REQ_MB0 + 0x0) #define PRCM_REQ_MB0_ULP_CLOCK_STATE (PRCM_REQ_MB0 + 0x1) @@ -153,6 +158,20 @@ enum sysclk_state { SYSCLK_ON, }; +/* Mailbox 4 headers */ +enum mb4_header { + MB4H_CFG_HOTDOG = 7, + MB4H_CFG_HOTMON = 8, + MB4H_CFG_HOTPERIOD = 10, +}; + +/* Mailbox 4 ACK headers */ +enum mb4_ack_header { + MB4H_ACK_CFG_HOTDOG = 5, + MB4H_ACK_CFG_HOTMON = 6, + MB4H_ACK_CFG_HOTPERIOD = 8, +}; + /* Mailbox 5 headers. */ enum mb5_header { MB5H_I2C_WRITE = 1, @@ -212,6 +231,16 @@ enum db5500_ap_pwr_state { /* Ack. mailbox 3 fields */ #define PRCM_ACK_MB3_REFCLK_REQ (PRCM_ACK_MB3 + 0x0) + +/* Request mailbox 4 fields */ +#define PRCM_REQ_MB4_HOTDOG_THRESHOLD (PRCM_REQ_MB4 + 32) +#define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 34) +#define PRCM_REQ_MB4_HOTMON_LOW (PRCM_REQ_MB4 + 36) +#define PRCM_REQ_MB4_HOTMON_HIGH (PRCM_REQ_MB4 + 38) + +/* Ack. mailbox 4 field */ +#define PRCM_ACK_MB4_REQUESTS (PRCM_ACK_MB4 + 0x0) + /* Request mailbox 5 fields. */ #define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0) #define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1) @@ -406,6 +435,21 @@ static struct { } mb3_transfer; /* + * mb4_transfer - state needed for mailbox 4 communication. + * @lock: The transaction lock. + * @work: The transaction completion structure. + * @ack: Acknowledgement data + */ +static struct { + struct mutex lock; + struct completion work; + struct { + u8 header; + u8 status; + } ack; +} mb4_transfer; + +/* * mb5_transfer - state needed for mailbox 5 communication. * @lock: The transaction lock. * @work: The transaction completion structure. @@ -930,6 +974,103 @@ void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) *buf = (PRCM_ACK_MB0_WAKEUP_0_ABB); } +/* This function should be called with lock */ +static int mailbox4_request(u8 mb4_request, u8 ack_request) +{ + int ret = 0; + + writeb(mb4_request, PRCM_REQ_MB4_HEADER); + writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + + if (!wait_for_completion_timeout(&mb4_transfer.work, + msecs_to_jiffies(500))) { + pr_err("prcmu: MB4 request %d failed", mb4_request); + ret = -EIO; + WARN(1, "prcmu: failed mb4 request"); + goto failed; + } + + if (mb4_transfer.ack.header != ack_request || + mb4_transfer.ack.status != RC_SUCCESS) + ret = -EIO; +failed: + return ret; +} + +int db5500_prcmu_get_hotdog(void) +{ + return readw(PRCM_SHARE_INFO_HOTDOG); +} + +int db5500_prcmu_config_hotdog(u8 threshold) +{ + int r = 0; + + mutex_lock(&mb4_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + cpu_relax(); + + writew(threshold, PRCM_REQ_MB4_HOTDOG_THRESHOLD); + r = mailbox4_request(MB4H_CFG_HOTDOG, MB4H_ACK_CFG_HOTDOG); + + mutex_unlock(&mb4_transfer.lock); + + return r; +} + +int db5500_prcmu_config_hotmon(u8 low, u8 high) +{ + int r = 0; + + mutex_lock(&mb4_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + cpu_relax(); + + writew(low, PRCM_REQ_MB4_HOTMON_LOW); + writew(high, PRCM_REQ_MB4_HOTMON_HIGH); + + r = mailbox4_request(MB4H_CFG_HOTMON, MB4H_ACK_CFG_HOTMON); + + mutex_unlock(&mb4_transfer.lock); + + return r; +} + +static int config_hot_period(u16 val) +{ + int r = 0; + + mutex_lock(&mb4_transfer.lock); + + while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + cpu_relax(); + + writew(val, PRCM_REQ_MB4_HOT_PERIOD); + r = mailbox4_request(MB4H_CFG_HOTPERIOD, MB4H_ACK_CFG_HOTPERIOD); + + mutex_unlock(&mb4_transfer.lock); + + return r; +} + +/* + * period in milli seconds + */ +int db5500_prcmu_start_temp_sense(u16 period) +{ + if (period == 0xFFFF) + return -EINVAL; + + return config_hot_period(period); +} + +int db5500_prcmu_stop_temp_sense(void) +{ + return config_hot_period(0xFFFF); +} + /** * db5500_prcmu_abb_read() - Read register value(s) from the ABB. * @slave: The I2C slave address. @@ -1596,7 +1737,28 @@ static bool read_mailbox_3(void) static bool read_mailbox_4(void) { - writel(MBOX_BIT(4), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); + u8 header; + bool do_complete = true; + + header = readb(PRCM_ACK_MB4_HEADER); + mb4_transfer.ack.header = header; + switch (header) { + case MB4H_ACK_CFG_HOTDOG: + case MB4H_ACK_CFG_HOTMON: + case MB4H_ACK_CFG_HOTPERIOD: + mb4_transfer.ack.status = readb(PRCM_ACK_MB4_REQUESTS); + break; + default: + print_unknown_header_warning(4, header); + do_complete = false; + break; + } + + writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLEAR)); + + if (do_complete) + complete(&mb4_transfer.work); + return false; } @@ -1749,6 +1911,8 @@ void __init db5500_prcmu_early_init(void) init_completion(&mb2_transfer.work); mutex_init(&mb3_transfer.sysclk_lock); init_completion(&mb3_transfer.sysclk_work); + mutex_init(&mb4_transfer.lock); + init_completion(&mb4_transfer.work); mutex_init(&mb5_transfer.lock); init_completion(&mb5_transfer.work); diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index fe09270a4d2..ec6c65643a0 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -1770,7 +1770,7 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state) return 0; } -int prcmu_config_hotdog(u8 threshold) +int db8500_prcmu_config_hotdog(u8 threshold) { mutex_lock(&mb4_transfer.lock); @@ -1788,7 +1788,7 @@ int prcmu_config_hotdog(u8 threshold) return 0; } -int prcmu_config_hotmon(u8 low, u8 high) +int db8500_prcmu_config_hotmon(u8 low, u8 high) { mutex_lock(&mb4_transfer.lock); @@ -1827,7 +1827,7 @@ static int config_hot_period(u16 val) return 0; } -int prcmu_start_temp_sense(u16 cycles32k) +int db8500_prcmu_start_temp_sense(u16 cycles32k) { if (cycles32k == 0xFFFF) return -EINVAL; @@ -1835,7 +1835,7 @@ int prcmu_start_temp_sense(u16 cycles32k) return config_hot_period(cycles32k); } -int prcmu_stop_temp_sense(void) +int db8500_prcmu_stop_temp_sense(void) { return config_hot_period(0xFFFF); } diff --git a/include/linux/mfd/db5500-prcmu.h b/include/linux/mfd/db5500-prcmu.h index b70811dc563..ffbd415e6c7 100644 --- a/include/linux/mfd/db5500-prcmu.h +++ b/include/linux/mfd/db5500-prcmu.h @@ -49,6 +49,11 @@ static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate) { return 0; } +int db5500_prcmu_get_hotdog(void); +int db5500_prcmu_config_hotdog(u8 threshold); +int db5500_prcmu_config_hotmon(u8 low, u8 high); +int db5500_prcmu_start_temp_sense(u16 cycles32k); +int db5500_prcmu_stop_temp_sense(void); #else /* !CONFIG_UX500_SOC_DB5500 */ static inline void db5500_prcmu_early_init(void) {} @@ -166,6 +171,29 @@ static inline int db5500_prcmu_get_ddr_opp(void) return 0; } +static inline int db5500_prcmu_get_hotdog(void) +{ + return -ENOSYS; +} +static inline int db5500_prcmu_config_hotdog(u8 threshold) +{ + return 0; +} + +static inline int db5500_prcmu_config_hotmon(u8 low, u8 high) +{ + return 0; +} + +static inline int db5500_prcmu_start_temp_sense(u16 cycles32k) +{ + return 0; +} +static inline int db5500_prcmu_stop_temp_sense(void) +{ + return 0; +} + #endif /* CONFIG_MFD_DB5500_PRCMU */ #endif /* __MFD_DB5500_PRCMU_H */ diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index 1b92aabf0bc..06623d44948 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -510,10 +510,10 @@ void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, bool prcmu_is_auto_pm_enabled(void); -int prcmu_config_hotdog(u8 threshold); -int prcmu_config_hotmon(u8 low, u8 high); -int prcmu_start_temp_sense(u16 cycles32k); -int prcmu_stop_temp_sense(void); +int db8500_prcmu_config_hotdog(u8 threshold); +int db8500_prcmu_config_hotmon(u8 low, u8 high); +int db8500_prcmu_start_temp_sense(u16 cycles32k); +int db8500_prcmu_stop_temp_sense(void); int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); @@ -622,22 +622,22 @@ static inline bool prcmu_is_auto_pm_enabled(void) return false; } -static inline int prcmu_config_hotdog(u8 threshold) +static inline int db8500_prcmu_config_hotdog(u8 threshold) { return 0; } -static inline int prcmu_config_hotmon(u8 low, u8 high) +static inline int db8500_prcmu_config_hotmon(u8 low, u8 high) { return 0; } -static inline int prcmu_start_temp_sense(u16 cycles32k) +static inline int db8500_prcmu_start_temp_sense(u16 cycles32k) { return 0; } -static inline int prcmu_stop_temp_sense(void) +static inline int db8500_prcmu_stop_temp_sense(void) { return 0; } diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 73d6a52d731..4cbd6a8aeed 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -425,6 +425,39 @@ static inline int prcmu_config_esram0_deep_sleep(u8 state) else return db8500_prcmu_config_esram0_deep_sleep(state); } + +static inline int prcmu_config_hotdog(u8 threshold) +{ + if (cpu_is_u5500()) + return db5500_prcmu_config_hotdog(threshold); + else + return db8500_prcmu_config_hotdog(threshold); +} + +static inline int prcmu_config_hotmon(u8 low, u8 high) +{ + if (cpu_is_u5500()) + return db5500_prcmu_config_hotmon(low, high); + else + return db8500_prcmu_config_hotmon(low, high); +} + +static inline int prcmu_start_temp_sense(u16 cycles32k) +{ + if (cpu_is_u5500()) + return db5500_prcmu_start_temp_sense(cycles32k); + else + return db8500_prcmu_start_temp_sense(cycles32k); +} + +static inline int prcmu_stop_temp_sense(void) +{ + if (cpu_is_u5500()) + return db5500_prcmu_stop_temp_sense(); + else + return db8500_prcmu_stop_temp_sense(); +} + #else static inline void __init prcmu_early_init(void) {} @@ -554,6 +587,26 @@ static inline void prcmu_get_abb_event_buffer(void __iomem **buf) *buf = NULL; } +static inline int prcmu_config_hotdog(u8 threshold) +{ + return 0; +} + +static inline int prcmu_config_hotmon(u8 low, u8 high) +{ + return 0; +} + +static inline int prcmu_start_temp_sense(u16 cycles32k) +{ + return 0; +} + +static inline int prcmu_stop_temp_sense(void) +{ + return 0; +} + #endif /* PRCMU QoS APE OPP class */ |