summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVijaya Kumar Kilari <vijay.kilari@stericsson.com>2011-09-16 16:02:41 +0530
committerRabin VINCENT <rabin.vincent@stericsson.com>2011-10-03 09:21:33 +0200
commit869fca5fdba5e63dfdcbf60141fe7a3225e1d0b4 (patch)
tree7cafcfd75ee798666f561d45c9f94f2dd19418a7
parent36fe5ea2a6ce0c8c0b2c007ca54b6ac8167cff45 (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.c166
-rw-r--r--drivers/mfd/db8500-prcmu.c8
-rw-r--r--include/linux/mfd/db5500-prcmu.h28
-rw-r--r--include/linux/mfd/db8500-prcmu.h16
-rw-r--r--include/linux/mfd/dbx500-prcmu.h53
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 */