[PATCH 13/17] mfd: prcmu: make legacy mailbox services configurable

Loic Pallardy loic.pallardy-ext at stericsson.com
Wed Sep 5 05:59:09 EDT 2012


8500 and x540 are using same services based on prcmu legacy
mailbox but with different base address and different arguments.

Signed-off-by: Loic Pallardy <loic.pallardy at stericsson.com>
Acked-by: Linus Walleij <linus.walleij at linaro.org>
---
 drivers/mfd/db8500-prcmu.c | 371 +++++++++++++++++++++++++++------------------
 drivers/mfd/dbx500-prcmu.h |  16 ++
 2 files changed, 243 insertions(+), 144 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 327e9f6..73c98e5 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -137,13 +137,21 @@ static DEFINE_SPINLOCK(clkout_lock);
 static __iomem void *tcdm_legacy_base;
 static __iomem void *tcdm_base;
 
+/* mailbox pointers */
+static struct mb0_transfer *mb0;
+static struct mb1_transfer *mb1;
+static struct mb2_transfer *mb2;
+static struct mb3_transfer *mb3;
+static struct mb4_transfer *mb4;
+static struct mb5_transfer *mb5;
+
 /* mailbox definition */
-static struct mb0_transfer mb0;
-static struct mb1_transfer mb1;
-static struct mb2_transfer mb2;
-static struct mb3_transfer mb3;
-static struct mb4_transfer mb4;
-static struct mb5_transfer mb5;
+static struct mb0_transfer db8500_mb0;
+static struct mb1_transfer db8500_mb1;
+static struct mb2_transfer db8500_mb2;
+static struct mb3_transfer db8500_mb3;
+static struct mb4_transfer db8500_mb4;
+static struct mb5_transfer db8500_mb5;
 
 static DEFINE_SPINLOCK(clk_mgt_lock);
 
@@ -472,20 +480,31 @@ unlock_and_return:
 	return r;
 }
 
+static u8 db8500_fw_trans[] = {
+	0x00,/* PRCMU_AP_NO_CHANGE */
+	0x01,/* PRCMU_AP_SLEEP */
+	0x04,/*	PRCMU_AP_DEEP_SLEEP */
+	0x05,/*	PRCMU_AP_IDLE */
+	0x07,/*	PRCMU_AP_DEEP_IDLE*/
+};
+
+static u8 *fw_trans;
+static u32 fw_trans_nb;
+
 int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 {
 	unsigned long flags;
 
-	BUG_ON((state < PRCMU_AP_SLEEP) || (PRCMU_AP_DEEP_IDLE < state));
-
-	spin_lock_irqsave(&mb0.lock, flags);
+	BUG_ON((state == PRCMU_AP_NO_CHANGE) ||
+			(state >= fw_trans_nb));
+	spin_lock_irqsave(&mb0->lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
 
 	writeb(MB0H_POWER_STATE_TRANS,
 			tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB0);
-	writeb(state, (tcdm_legacy_base + PRCM_REQ_MB0_AP_POWER_STATE));
+	writeb(fw_trans[state], tcdm_legacy_base + PRCM_REQ_MB0_AP_POWER_STATE);
 	writeb((keep_ap_pll ? 1 : 0),
 			tcdm_legacy_base + PRCM_REQ_MB0_AP_PLL_STATE);
 	writeb((keep_ulp_clk ? 1 : 0),
@@ -493,7 +512,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 	writeb(0, (tcdm_legacy_base + PRCM_REQ_MB0_DO_NOT_WFI));
 	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 
 	return 0;
 }
@@ -616,7 +635,7 @@ int db8500_prcmu_copy_gic_settings(void)
 	return 0;
 }
 
-/* This function should only be called while mb0.lock is held. */
+/* This function should only be called while mb0->lock is held. */
 static void config_wakeups(void)
 {
 	const u8 header[2] = {
@@ -629,10 +648,10 @@ static void config_wakeups(void)
 	u32 abb_events;
 	unsigned int i;
 
-	dbb_events = mb0.req.dbb_irqs | mb0.req.dbb_wakeups;
+	dbb_events = mb0->req.dbb_irqs | mb0->req.dbb_wakeups;
 	dbb_events |= (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK);
 
-	abb_events = mb0.req.abb_events;
+	abb_events = mb0->req.abb_events;
 
 	if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events))
 		return;
@@ -662,24 +681,24 @@ static void db8500_prcmu_enable_wakeups(u32 wakeups)
 			bits |= prcmu_wakeup_bit[i];
 	}
 
-	spin_lock_irqsave(&mb0.lock, flags);
+	spin_lock_irqsave(&mb0->lock, flags);
 
-	mb0.req.dbb_wakeups = bits;
+	mb0->req.dbb_wakeups = bits;
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
 static void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.lock, flags);
+	spin_lock_irqsave(&mb0->lock, flags);
 
-	mb0.req.abb_events = abb_events;
+	mb0->req.abb_events = abb_events;
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
 static void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
@@ -706,7 +725,7 @@ static int db8500_prcmu_set_arm_opp(u8 opp)
 
 	r = 0;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -716,13 +735,13 @@ static int db8500_prcmu_set_arm_opp(u8 opp)
 	writeb(APE_NO_CHANGE, (tcdm_legacy_base + PRCM_REQ_MB1_APE_OPP));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if ((mb1.ack.header != MB1H_ARM_APE_OPP) ||
-		(mb1.ack.arm_opp != opp))
+	if ((mb1->ack.header != MB1H_ARM_APE_OPP) ||
+		(mb1->ack.arm_opp != opp))
 		r = -EIO;
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -822,15 +841,15 @@ static int db8500_prcmu_set_ape_opp(u8 opp)
 {
 	int r = 0;
 
-	if (opp == mb1.ape_opp)
+	if (opp == mb1->ape_opp)
 		return 0;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
-	if (mb1.ape_opp == APE_50_PARTLY_25_OPP)
+	if (mb1->ape_opp == APE_50_PARTLY_25_OPP)
 		request_even_slower_clocks(false);
 
-	if ((opp != APE_100_OPP) && (mb1.ape_opp != APE_100_OPP))
+	if ((opp != APE_100_OPP) && (mb1->ape_opp != APE_100_OPP))
 		goto skip_message;
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
@@ -842,20 +861,20 @@ static int db8500_prcmu_set_ape_opp(u8 opp)
 		(tcdm_legacy_base + PRCM_REQ_MB1_APE_OPP));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if ((mb1.ack.header != MB1H_ARM_APE_OPP) ||
-		(mb1.ack.ape_opp != opp))
+	if ((mb1->ack.header != MB1H_ARM_APE_OPP) ||
+		(mb1->ack.ape_opp != opp))
 		r = -EIO;
 
 skip_message:
 	if ((!r && (opp == APE_50_PARTLY_25_OPP)) ||
-		(r && (mb1.ape_opp == APE_50_PARTLY_25_OPP)))
+		(r && (mb1->ape_opp == APE_50_PARTLY_25_OPP)))
 		request_even_slower_clocks(true);
 	if (!r)
-		mb1.ape_opp = opp;
+		mb1->ape_opp = opp;
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -882,7 +901,7 @@ static int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 	u8 header;
 	static unsigned int requests;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	if (enable) {
 		if (0 != requests++)
@@ -904,14 +923,14 @@ static int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 	writeb(header, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if ((mb1.ack.header != header) ||
-		((mb1.ack.ape_voltage_status & BIT(0)) != 0))
+	if ((mb1->ack.header != header) ||
+		((mb1->ack.ape_voltage_status & BIT(0)) != 0))
 		r = -EIO;
 
 unlock_and_return:
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -925,7 +944,7 @@ int prcmu_release_usb_wakeup_state(void)
 {
 	int r = 0;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -934,13 +953,13 @@ int prcmu_release_usb_wakeup_state(void)
 		(tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if ((mb1.ack.header != MB1H_RELEASE_USB_WAKEUP) ||
-		((mb1.ack.ape_voltage_status & BIT(0)) != 0))
+	if ((mb1->ack.header != MB1H_RELEASE_USB_WAKEUP) ||
+		((mb1->ack.ape_voltage_status & BIT(0)) != 0))
 		r = -EIO;
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -956,7 +975,7 @@ static int request_pll(u8 clock, bool enable)
 	else
 		return -EINVAL;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -965,12 +984,12 @@ static int request_pll(u8 clock, bool enable)
 	writeb(clock, (tcdm_legacy_base + PRCM_REQ_MB1_PLL_ON_OFF));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if (mb1.ack.header != MB1H_PLL_ON_OFF)
+	if (mb1->ack.header != MB1H_PLL_ON_OFF)
 		r = -EIO;
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -1007,7 +1026,7 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 	BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention);
 
 	/* get lock */
-	mutex_lock(&mb2.lock);
+	mutex_lock(&mb2->lock);
 
 	/* wait for mailbox */
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
@@ -1028,7 +1047,7 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 	 * and we cannot recover if there is an error.
 	 * This is expected to change when the firmware is updated.
 	 */
-	if (!wait_for_completion_timeout(&mb2.work,
+	if (!wait_for_completion_timeout(&mb2->work,
 			msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
@@ -1036,11 +1055,11 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 		goto unlock_and_return;
 	}
 
-	if (mb2.ack.status != HWACC_PWR_ST_OK)
+	if (mb2->ack.status != HWACC_PWR_ST_OK)
 		r = -EIO;
 
 unlock_and_return:
-	mutex_unlock(&mb2.lock);
+	mutex_unlock(&mb2->lock);
 	return r;
 }
 
@@ -1072,7 +1091,7 @@ static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	idle_cfg = ((idle_cfg << 4) | (idle->sva_policy & 0xF));
 	idle_cfg = ((idle_cfg << 4) | (idle->sia_policy & 0xF));
 
-	spin_lock_irqsave(&mb2.auto_pm_lock, flags);
+	spin_lock_irqsave(&mb2->auto_pm_lock, flags);
 
 	/*
 	 * The autonomous power management configuration is done through
@@ -1082,18 +1101,18 @@ static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	writel(sleep_cfg, (tcdm_legacy_base + PRCM_REQ_MB2_AUTO_PM_SLEEP));
 	writel(idle_cfg, (tcdm_legacy_base + PRCM_REQ_MB2_AUTO_PM_IDLE));
 
-	mb2.auto_pm_enabled =
+	mb2->auto_pm_enabled =
 		((sleep->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (sleep->sia_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (idle->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (idle->sia_auto_pm_enable == PRCMU_AUTO_PM_ON));
 
-	spin_unlock_irqrestore(&mb2.auto_pm_lock, flags);
+	spin_unlock_irqrestore(&mb2->auto_pm_lock, flags);
 }
 
 bool prcmu_is_auto_pm_enabled(void)
 {
-	return mb2.auto_pm_enabled;
+	return mb2->auto_pm_enabled;
 }
 
 static int request_sysclk(bool enable)
@@ -1103,9 +1122,9 @@ static int request_sysclk(bool enable)
 
 	r = 0;
 
-	mutex_lock(&mb3.sysclk_lock);
+	mutex_lock(&mb3->sysclk_lock);
 
-	spin_lock_irqsave(&mb3.lock, flags);
+	spin_lock_irqsave(&mb3->lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
 		cpu_relax();
@@ -1115,20 +1134,20 @@ static int request_sysclk(bool enable)
 	writeb(MB3H_SYSCLK, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB3));
 	writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb3.lock, flags);
+	spin_unlock_irqrestore(&mb3->lock, flags);
 
 	/*
 	 * The firmware only sends an ACK if we want to enable the
 	 * SysClk, and it succeeds.
 	 */
-	if (enable && !wait_for_completion_timeout(&mb3.sysclk_work,
+	if (enable && !wait_for_completion_timeout(&mb3->sysclk_work,
 			msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	}
 
-	mutex_unlock(&mb3.sysclk_lock);
+	mutex_unlock(&mb3->sysclk_lock);
 
 	return r;
 }
@@ -1711,7 +1730,7 @@ static int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 	    (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
 		return -EINVAL;
 
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1724,16 +1743,16 @@ static int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 	writeb(state, (tcdm_legacy_base + PRCM_REQ_MB4_ESRAM0_ST));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 }
 
 int db8500_prcmu_config_hotdog(u8 threshold)
 {
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1742,16 +1761,16 @@ int db8500_prcmu_config_hotdog(u8 threshold)
 	writeb(MB4H_HOTDOG, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 }
 
 int db8500_prcmu_config_hotmon(u8 low, u8 high)
 {
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1763,16 +1782,16 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high)
 	writeb(MB4H_HOTMON, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 }
 
 static int config_hot_period(u16 val)
 {
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1781,9 +1800,9 @@ static int config_hot_period(u16 val)
 	writeb(MB4H_HOT_PERIOD, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 }
@@ -1804,7 +1823,7 @@ int db8500_prcmu_stop_temp_sense(void)
 static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 {
 
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1817,9 +1836,9 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 	writeb(cmd, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 
@@ -1882,7 +1901,7 @@ static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 	if (size != 1)
 		return -EINVAL;
 
-	mutex_lock(&mb5.lock);
+	mutex_lock(&mb5->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
@@ -1896,19 +1915,19 @@ static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 
 	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
-	if (!wait_for_completion_timeout(&mb5.work,
+	if (!wait_for_completion_timeout(&mb5->work,
 				msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	} else {
-		r = ((mb5.ack.status == I2C_RD_OK) ? 0 : -EIO);
+		r = ((mb5->ack.status == I2C_RD_OK) ? 0 : -EIO);
 	}
 
 	if (!r)
-		*value = mb5.ack.value;
+		*value = mb5->ack.value;
 
-	mutex_unlock(&mb5.lock);
+	mutex_unlock(&mb5->lock);
 
 	return r;
 }
@@ -1934,7 +1953,7 @@ static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
 	if (size != 1)
 		return -EINVAL;
 
-	mutex_lock(&mb5.lock);
+	mutex_lock(&mb5->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
@@ -1948,16 +1967,16 @@ static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
 
 	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
-	if (!wait_for_completion_timeout(&mb5.work,
+	if (!wait_for_completion_timeout(&mb5->work,
 				msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	} else {
-		r = ((mb5.ack.status == I2C_WR_OK) ? 0 : -EIO);
+		r = ((mb5->ack.status == I2C_WR_OK) ? 0 : -EIO);
 	}
 
-	mutex_unlock(&mb5.lock);
+	mutex_unlock(&mb5->lock);
 
 	return r;
 }
@@ -1987,7 +2006,7 @@ int prcmu_ac_wake_req(void)
 	u32 val;
 	int ret = 0;
 
-	mutex_lock(&mb0.ac_wake_lock);
+	mutex_lock(&mb0->ac_wake_lock);
 
 	val = readl(PRCM_HOSTACCESS_REQ);
 	if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)
@@ -2008,7 +2027,7 @@ int prcmu_ac_wake_req(void)
 	val |= PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ;
 	writel(val, PRCM_HOSTACCESS_REQ);
 
-	if (!wait_for_completion_timeout(&mb0.ac_wake_work,
+	if (!wait_for_completion_timeout(&mb0->ac_wake_work,
 			msecs_to_jiffies(5000))) {
 #if defined(CONFIG_DBX500_PRCMU_DEBUG)
 		db8500_prcmu_debug_dump(__func__, true, true);
@@ -2019,7 +2038,7 @@ int prcmu_ac_wake_req(void)
 	}
 
 unlock_and_return:
-	mutex_unlock(&mb0.ac_wake_lock);
+	mutex_unlock(&mb0->ac_wake_lock);
 	return ret;
 }
 
@@ -2030,7 +2049,7 @@ void prcmu_ac_sleep_req()
 {
 	u32 val;
 
-	mutex_lock(&mb0.ac_wake_lock);
+	mutex_lock(&mb0->ac_wake_lock);
 
 	val = readl(PRCM_HOSTACCESS_REQ);
 	if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ))
@@ -2039,7 +2058,7 @@ void prcmu_ac_sleep_req()
 	writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
 		PRCM_HOSTACCESS_REQ);
 
-	if (!wait_for_completion_timeout(&mb0.ac_wake_work,
+	if (!wait_for_completion_timeout(&mb0->ac_wake_work,
 			msecs_to_jiffies(5000))) {
 		pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
 			__func__);
@@ -2048,7 +2067,7 @@ void prcmu_ac_sleep_req()
 	atomic_set(&ac_wake_req_state, 0);
 
 unlock_and_return:
-	mutex_unlock(&mb0.ac_wake_lock);
+	mutex_unlock(&mb0->ac_wake_lock);
 }
 
 static bool db8500_prcmu_is_ac_wake_requested(void)
@@ -2084,28 +2103,28 @@ static u16 db8500_prcmu_get_reset_code(void)
  */
 static void db8500_prcmu_modem_reset(void)
 {
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
 	writeb(MB1H_RESET_MODEM, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
 	/*
 	 * No need to check return from PRCMU as modem should go in reset state
 	 * This state is already managed by upper layer
 	 */
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 }
 
 static void ack_dbb_wakeup(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.lock, flags);
+	spin_lock_irqsave(&mb0->lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
@@ -2114,7 +2133,7 @@ static void ack_dbb_wakeup(void)
 			tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB0);
 	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
 static inline void print_unknown_header_warning(u8 n, u8 header)
@@ -2142,11 +2161,11 @@ static bool read_mailbox_0(void)
 					PRCM_ACK_MB0_WAKEUP_0_8500);
 
 		if (ev & (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK))
-			complete(&mb0.ac_wake_work);
+			complete(&mb0->ac_wake_work);
 		if (ev & WAKEUP_BIT_SYSCLK_OK)
-			complete(&mb3.sysclk_work);
+			complete(&mb3->sysclk_work);
 
-		ev &= mb0.req.dbb_irqs;
+		ev &= mb0->req.dbb_irqs;
 
 		for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
 			if (ev & prcmu_irq_bit[n])
@@ -2165,25 +2184,25 @@ static bool read_mailbox_0(void)
 
 static bool read_mailbox_1(void)
 {
-	mb1.ack.header = readb(tcdm_legacy_base +
+	mb1->ack.header = readb(tcdm_legacy_base +
 			PRCM_MBOX_HEADER_REQ_MB1);
-	mb1.ack.arm_opp = readb(tcdm_legacy_base +
+	mb1->ack.arm_opp = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_CURRENT_ARM_OPP);
-	mb1.ack.ape_opp = readb(tcdm_legacy_base +
+	mb1->ack.ape_opp = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_CURRENT_APE_OPP);
-	mb1.ack.ape_voltage_status = readb(tcdm_legacy_base +
+	mb1->ack.ape_voltage_status = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_APE_VOLTAGE_STATUS);
 	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
-	complete(&mb1.work);
+	complete(&mb1->work);
 	return false;
 }
 
 static bool read_mailbox_2(void)
 {
-	mb2.ack.status = readb(tcdm_legacy_base
+	mb2->ack.status = readb(tcdm_legacy_base
 			+ PRCM_ACK_MB2_DPS_STATUS);
 	writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
-	complete(&mb2.work);
+	complete(&mb2->work);
 	return false;
 }
 
@@ -2219,18 +2238,18 @@ static bool read_mailbox_4(void)
 	writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
 
 	if (do_complete)
-		complete(&mb4.work);
+		complete(&mb4->work);
 
 	return false;
 }
 
 static bool read_mailbox_5(void)
 {
-	mb5.ack.status = readb(tcdm_legacy_base
+	mb5->ack.status = readb(tcdm_legacy_base
 			+ PRCM_ACK_MB5_I2C_STATUS);
-	mb5.ack.value = readb(tcdm_legacy_base + PRCM_ACK_MB5_I2C_VAL);
+	mb5->ack.value = readb(tcdm_legacy_base + PRCM_ACK_MB5_I2C_VAL);
 	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
-	complete(&mb5.work);
+	complete(&mb5->work);
 	return false;
 }
 
@@ -2246,7 +2265,7 @@ static bool read_mailbox_7(void)
 	return false;
 }
 
-static bool (* const read_mailbox[NUM_MB])(void) = {
+static bool (*db8500_read_mailbox[NUM_MB])(void) = {
 	read_mailbox_0,
 	read_mailbox_1,
 	read_mailbox_2,
@@ -2257,6 +2276,8 @@ static bool (* const read_mailbox[NUM_MB])(void) = {
 	read_mailbox_7
 };
 
+static bool (**read_mailbox)(void);
+
 static irqreturn_t prcmu_irq_handler(int irq, void *data)
 {
 	u32 bits;
@@ -2288,39 +2309,39 @@ static void prcmu_mask_work(struct work_struct *work)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.lock, flags);
+	spin_lock_irqsave(&mb0->lock, flags);
 
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
 static void prcmu_irq_mask(struct irq_data *d)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.dbb_irqs_lock, flags);
+	spin_lock_irqsave(&mb0->dbb_irqs_lock, flags);
 
-	mb0.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
+	mb0->req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
 
-	spin_unlock_irqrestore(&mb0.dbb_irqs_lock, flags);
+	spin_unlock_irqrestore(&mb0->dbb_irqs_lock, flags);
 
 	if (d->irq != IRQ_PRCMU_CA_SLEEP)
-		schedule_work(&mb0.mask_work);
+		schedule_work(&mb0->mask_work);
 }
 
 static void prcmu_irq_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.dbb_irqs_lock, flags);
+	spin_lock_irqsave(&mb0->dbb_irqs_lock, flags);
 
-	mb0.req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
+	mb0->req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
 
-	spin_unlock_irqrestore(&mb0.dbb_irqs_lock, flags);
+	spin_unlock_irqrestore(&mb0->dbb_irqs_lock, flags);
 
 	if (d->irq != IRQ_PRCMU_CA_SLEEP)
-		schedule_work(&mb0.mask_work);
+		schedule_work(&mb0->mask_work);
 }
 
 static void noop(struct irq_data *d)
@@ -2553,6 +2574,62 @@ struct prcmu_fops_register_data db8500_probe_data = {
 	.tab = db8500_probe_tab,
 };
 
+int __init db8500_prcmu_init_mb0(struct mb0_transfer *mb)
+{
+	mb0 = mb;
+	spin_lock_init(&mb0->lock);
+	spin_lock_init(&mb0->dbb_irqs_lock);
+	mutex_init(&mb0->ac_wake_lock);
+	init_completion(&mb0->ac_wake_work);
+	INIT_WORK(&mb0->mask_work, prcmu_mask_work);
+
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb1(struct mb1_transfer *mb)
+{
+	mb1 = mb;
+	mutex_init(&mb1->lock);
+	init_completion(&mb1->work);
+	mb1->ape_opp = APE_NO_CHANGE;
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb2(struct mb2_transfer *mb)
+{
+	mb2 = mb;
+	mutex_init(&mb2->lock);
+	init_completion(&mb2->work);
+	spin_lock_init(&mb2->auto_pm_lock);
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb3(struct mb3_transfer *mb)
+{
+	mb3 = mb;
+	spin_lock_init(&mb3->lock);
+	mutex_init(&mb3->sysclk_lock);
+	init_completion(&mb3->sysclk_work);
+	spin_lock_init(&mb3->fw_log_lock);
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb4(struct mb4_transfer *mb)
+{
+	mb4 = mb;
+	mutex_init(&mb4->lock);
+	init_completion(&mb4->work);
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb5(struct mb5_transfer *mb)
+{
+	mb5 = mb;
+	mutex_init(&mb5->lock);
+	init_completion(&mb5->work);
+	return 0;
+}
+
 static int db8500_irq_map(struct irq_domain *d, unsigned int virq,
 				irq_hw_number_t hwirq)
 {
@@ -2582,10 +2659,23 @@ static int db8500_irq_init(struct device_node *np)
 	return 0;
 }
 
+int __init db8500_prcmu_context_init(struct prcmu_context *context)
+{
+	/* initialize PRCMU driver context */
+	tcdm_base = context->tcdm_base;
+	tcdm_legacy_base = context->tcdm_legacy_base;
+	fw_trans = context->fw_trans;
+	fw_trans_nb = context->fw_trans_nb;
+	read_mailbox = context->read_mbox;
+
+	return 0;
+}
+
 struct prcmu_fops_register_data *__init
 			db8500_prcmu_early_init(struct prcmu_tcdm_map *map)
 {
 		void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
+	struct prcmu_context context;
 
 	if (tcpm_base != NULL) {
 		u32 version;
@@ -2601,28 +2691,21 @@ struct prcmu_fops_register_data *__init
 			(version >> 24) & 0xFF);
 		iounmap(tcpm_base);
 	}
-	tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE, map->tcdm_size);
-	tcdm_legacy_base = tcdm_base + map->legacy_offset;
-
-	spin_lock_init(&mb0.lock);
-	spin_lock_init(&mb0.dbb_irqs_lock);
-	mutex_init(&mb0.ac_wake_lock);
-	init_completion(&mb0.ac_wake_work);
-	mutex_init(&mb1.lock);
-	init_completion(&mb1.work);
-	mb1.ape_opp = APE_NO_CHANGE;
-	mutex_init(&mb2.lock);
-	init_completion(&mb2.work);
-	spin_lock_init(&mb2.auto_pm_lock);
-	spin_lock_init(&mb3.lock);
-	mutex_init(&mb3.sysclk_lock);
-	init_completion(&mb3.sysclk_work);
-	mutex_init(&mb4.lock);
-	init_completion(&mb4.work);
-	mutex_init(&mb5.lock);
-	init_completion(&mb5.work);
-
-	INIT_WORK(&mb0.mask_work, prcmu_mask_work);
+
+	context.tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE,
+			map->tcdm_size);
+	context.tcdm_legacy_base = context.tcdm_base + map->legacy_offset;
+	context.fw_trans = db8500_fw_trans;
+	context.fw_trans_nb = ARRAY_SIZE(db8500_fw_trans);
+	context.read_mbox = db8500_read_mailbox;
+	db8500_prcmu_context_init(&context);
+
+	db8500_prcmu_init_mb0(&db8500_mb0);
+	db8500_prcmu_init_mb1(&db8500_mb1);
+	db8500_prcmu_init_mb2(&db8500_mb2);
+	db8500_prcmu_init_mb3(&db8500_mb3);
+	db8500_prcmu_init_mb4(&db8500_mb4);
+	db8500_prcmu_init_mb5(&db8500_mb5);
 
 	/*  early init of dbx500-prcmu */
 	return &db8500_early_data;
diff --git a/drivers/mfd/dbx500-prcmu.h b/drivers/mfd/dbx500-prcmu.h
index 79cba24..ce0e519 100644
--- a/drivers/mfd/dbx500-prcmu.h
+++ b/drivers/mfd/dbx500-prcmu.h
@@ -376,3 +376,19 @@ struct mb5_transfer {
 	} ack;
 };
 
+/*
+ * prcmu_context - PRCMU common layer need to be configured
+ * @tcdm_base:	PRCMU TCDM base address
+ * @tcdm_legacy_base:	Base address for legacy mailbox
+ * @fw_trans:  Firmware power transition list
+ * @fw_trans_nb: Nb of firmware power transitions
+ * @read_mbox: Pointer on mailbox interrupt management
+ */
+struct prcmu_context {
+	void *tcdm_base;
+	void *tcdm_legacy_base;
+	u8 *fw_trans;
+	u32 fw_trans_nb;
+	bool (**read_mbox)(void);
+};
+
-- 
1.7.11.1




More information about the linux-arm-kernel mailing list