summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@linaro.org>2011-07-07 13:39:47 +0200
committerUlf Hansson <ulf.hansson@stericsson.com>2011-09-19 15:15:43 +0200
commit31470a483d96caf4d439fe41e8144bde728cf286 (patch)
tree05d860463de00efee669d4630c2bf0d7150f8303
parentf39ddd4052704c60a950c055b6f18f5aeed0c40e (diff)
ux500: align u5500 PRCMU & CPUFREQ management with u8500 (multiple commits in one)
Signed-off-by: Philippe Langlais <philippe.langlais@linaro.org> Merge of following commits too: u5500: add support for sysclk basic sysclk support added in PRCMU driver and clock framework driver updated. Signed-off-by: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com> U5500: Support for ESRAM12 EPOD in PRCMU driver Signed-off-by: Vijaya Kumar Kilari <vijay.kilari@stericsson.com> ux500: regulator: handle different base offset of ePOD ID 5500 ePOD ids are offseted for some reason in the PRCMU driver. Adjust the ids to index the local arrays to avoid memory corruption. Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> ux500: pm: support PRCMU status check on 5500 This also removes unused 8500v1 code. Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> arm: ux500: prcmu_ac_wake_req workaround This patch adds a check in prcmu_ac_wake_req that the modem is awake (in terms of the value in the PRCM_MOD_AWAKE_STATUS register) after the AC_WAKE_ACK has been received from the PRCMU FW. If the check fails, a retry is made. This seems to be necessary, since the modem can generate an AC_WAKE_ACK, and then still go to sleep. Signed-off-by: Mattias Nilsson <mattias.i.nilsson@stericsson.com> U5500: Add support for PRCMU Mailbox0 Add PRCMU mailbox 0 support for irq wakeup enable and disable Signed-off-by: Vijaya Kumar K <vijay.kilari@stericsson.com> U5500: Add support for power state transition PRCMU driver is updated to provide API for system power state transition Signed-off-by: Vijaya Kumar K <vijay.kilari@stericsson.com> ARM: ux500: prcmu: Add A9 watchdog interface Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> U5500 : ab5500 core interrupt hander update AB5500 interrupts will be now handled by PRCMU and then routed to AB5500 core driver.AB5500 irq handler will no more read the latch registers to find the interrupt reason.Instead PRCMU will read the latch registers and provide the values to core driver. Signed-off-by: Bibek Basu <bibek.basu@stericsson.com> ARM: ux500: prcmu-dbg: Tiny code clean-up Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> u5500: add mailbox1 and related function support Add cpufreq-db5500.c file for db5500 CPUfreq support. PRCMU mailbox1 and related functions' support is added. List of functions implemented: - prcmu_get/set_arm_opp - read_mailbox_1 Signed-off-by: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com> Fix for PRCMU u5500: PRCMU IRQ should be NO_SUSPEND As on 8500. Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> ARM: u5500: PRCMU reset API Added API for rebooting the board and for getting the last reboot code. Signed-off-by: Pawel Szyszuk <pawel.szyszuk@stericsson.com>
-rw-r--r--arch/arm/mach-ux500/board-u5500-regulators.c82
-rw-r--r--arch/arm/mach-ux500/board-u5500.c5
-rw-r--r--arch/arm/mach-ux500/clock-db5500.c83
-rw-r--r--arch/arm/mach-ux500/cpu-db5500.c5
-rw-r--r--arch/arm/mach-ux500/cpu.c9
-rw-r--r--arch/arm/mach-ux500/devices-db5500.c5
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs-db5500.h29
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu-regs.h8
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu.h124
-rw-r--r--arch/arm/mach-ux500/include/mach/regulator.h16
-rw-r--r--arch/arm/mach-ux500/pm/Kconfig7
-rw-r--r--arch/arm/mach-ux500/pm/pm.c13
-rw-r--r--arch/arm/mach-ux500/pm/runtime.c2
-rw-r--r--arch/arm/mach-ux500/pm/suspend.c5
-rw-r--r--arch/arm/mach-ux500/prcmu-debug.c52
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/db5500-cpufreq.c172
-rw-r--r--drivers/cpufreq/db8500-cpufreq.c6
-rw-r--r--drivers/crypto/ux500/cryp/cryp_core.c2
-rw-r--r--drivers/crypto/ux500/hash/hash_core.c2
-rwxr-xr-xdrivers/mfd/ab5500-core.c42
-rw-r--r--drivers/mfd/db5500-prcmu.c821
-rw-r--r--drivers/mfd/db8500-prcmu.c149
-rw-r--r--drivers/regulator/db5500-prcmu.c43
-rw-r--r--drivers/regulator/dbx500-prcmu.c1
-rw-r--r--include/linux/mfd/db5500-prcmu.h70
-rw-r--r--include/linux/mfd/db8500-prcmu.h159
-rw-r--r--include/linux/regulator/db5500-prcmu.h14
28 files changed, 1458 insertions, 469 deletions
diff --git a/arch/arm/mach-ux500/board-u5500-regulators.c b/arch/arm/mach-ux500/board-u5500-regulators.c
index b345a72038b..f890ebebf10 100644
--- a/arch/arm/mach-ux500/board-u5500-regulators.c
+++ b/arch/arm/mach-ux500/board-u5500-regulators.c
@@ -9,7 +9,6 @@
#include <linux/platform_device.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/ab5500.h>
-#include <linux/regulator/db5500-prcmu.h>
#include "board-u5500.h"
@@ -146,83 +145,6 @@ struct ab5500_regulator_platform_data u5500_ab5500_regulator_data = {
.num_regulator = ARRAY_SIZE(ab5500_regulator_init_data),
};
-/*
- * Power state, ePOD, etc.
- */
-
-static struct regulator_consumer_supply u5500_vape_consumers[] = {
- REGULATOR_SUPPLY("v-ape", NULL),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.0"),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"),
- REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"),
- REGULATOR_SUPPLY("v-mmc", "sdi0"),
- REGULATOR_SUPPLY("v-mmc", "sdi1"),
- REGULATOR_SUPPLY("v-mmc", "sdi2"),
- REGULATOR_SUPPLY("v-mmc", "sdi3"),
- REGULATOR_SUPPLY("v-mmc", "sdi4"),
- REGULATOR_SUPPLY("v-uart", "uart0"),
- REGULATOR_SUPPLY("v-uart", "uart1"),
- REGULATOR_SUPPLY("v-uart", "uart2"),
- REGULATOR_SUPPLY("v-uart", "uart3"),
-};
-
-static struct regulator_consumer_supply u5500_sga_consumers[] = {
- REGULATOR_SUPPLY("debug", "reg-virt-consumer.0"),
- REGULATOR_SUPPLY("v-mali", NULL),
-};
-
-static struct regulator_consumer_supply u5500_hva_consumers[] = {
- REGULATOR_SUPPLY("debug", "reg-virt-consumer.1"),
- REGULATOR_SUPPLY("v-hva", NULL),
-};
-
-static struct regulator_consumer_supply u5500_sia_consumers[] = {
- REGULATOR_SUPPLY("debug", "reg-virt-consumer.2"),
- REGULATOR_SUPPLY("v-sia", "mmio_camera"),
-};
-
-static struct regulator_consumer_supply u5500_disp_consumers[] = {
- REGULATOR_SUPPLY("debug", "reg-virt-consumer.3"),
- REGULATOR_SUPPLY("vsupply", "b2r2_bus"),
- REGULATOR_SUPPLY("vsupply", "mcde"),
-};
-
-static struct regulator_consumer_supply u5500_esram12_consumers[] = {
- REGULATOR_SUPPLY("debug", "reg-virt-consumer.4"),
- REGULATOR_SUPPLY("v-esram12", "mcde"),
- REGULATOR_SUPPLY("esram12", "cm_control"),
-};
-
-#define U5500_REGULATOR_SWITCH(lower, upper) \
-[U5500_REGULATOR_SWITCH_##upper] = (struct regulator_init_data []) { \
-{ \
- .constraints = { \
- .valid_ops_mask = REGULATOR_CHANGE_STATUS, \
- }, \
- .consumer_supplies = u5500_##lower##_consumers, \
- .num_consumer_supplies = ARRAY_SIZE(u5500_##lower##_consumers),\
-} \
-}
-
-static struct regulator_init_data *
-u5500_regulator_init_data[U5500_NUM_REGULATORS] __initdata = {
- [U5500_REGULATOR_VAPE] = (struct regulator_init_data []) {
- {
- .constraints = {
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .consumer_supplies = u5500_vape_consumers,
- .num_consumer_supplies = ARRAY_SIZE(u5500_vape_consumers),
- }
- },
- U5500_REGULATOR_SWITCH(sga, SGA),
- U5500_REGULATOR_SWITCH(hva, HVA),
- U5500_REGULATOR_SWITCH(sia, SIA),
- U5500_REGULATOR_SWITCH(disp, DISP),
- U5500_REGULATOR_SWITCH(esram12, ESRAM12),
-};
-
static void __init u5500_regulators_init_debug(void)
{
const char data[] = "debug";
@@ -236,8 +158,4 @@ static void __init u5500_regulators_init_debug(void)
void __init u5500_regulators_init(void)
{
u5500_regulators_init_debug();
-
- platform_device_register_data(NULL, "u5500-regulators", -1,
- u5500_regulator_init_data,
- sizeof(u5500_regulator_init_data));
}
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 3759a815261..65fca58b364 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -303,9 +303,8 @@ static void __init u5500_spi_init(void)
static struct resource ab5500_resources[] = {
[0] = {
- /*TODO Change this when prcmu driver arrives */
- .start = IRQ_DB5500_AB5500,
- .end = IRQ_DB5500_AB5500,
+ .start = IRQ_DB5500_PRCMU_ABB,
+ .end = IRQ_DB5500_PRCMU_ABB,
.flags = IORESOURCE_IRQ
}
};
diff --git a/arch/arm/mach-ux500/clock-db5500.c b/arch/arm/mach-ux500/clock-db5500.c
index ee2ea8033bd..18583a52334 100644
--- a/arch/arm/mach-ux500/clock-db5500.c
+++ b/arch/arm/mach-ux500/clock-db5500.c
@@ -36,59 +36,16 @@ static DEFINE_MUTEX(ab_ulpclk_mutex);
static DEFINE_MUTEX(audioclk_mutex);
/* SysClk operations. */
-
-static int request_sysclk(bool enable)
-{
- static int requests;
-
- if ((enable && (requests++ == 0)) || (!enable && (--requests == 0)))
- return prcmu_request_clock(PRCMU_SYSCLK, enable);
- return 0;
-}
-
static int sysclk_enable(struct clk *clk)
{
- static bool swat_enable;
- int r;
-
- if (!swat_enable) {
- r = ab8500_sysctrl_set(AB8500_SWATCTRL,
- AB8500_SWATCTRL_SWATENABLE);
- if (r)
- return r;
-
- swat_enable = true;
- }
-
- r = request_sysclk(true);
- if (r)
- return r;
-
- if (clk->cg_sel) {
- r = ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1, (u8)clk->cg_sel);
- if (r)
- (void)request_sysclk(false);
- }
- return r;
+ return prcmu_request_clock(PRCMU_SYSCLK, true);
}
static void sysclk_disable(struct clk *clk)
{
- int r;
- if (clk->cg_sel) {
- r = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
- (u8)clk->cg_sel);
- if (r)
- goto disable_failed;
- }
- r = request_sysclk(false);
- if (r)
- goto disable_failed;
+ prcmu_request_clock(PRCMU_SYSCLK, false);
return;
-
-disable_failed:
- pr_err("clock: failed to disable %s.\n", clk->name);
}
static struct clkops sysclk_ops = {
@@ -324,27 +281,6 @@ static struct clk sysclk = {
.mutex = &sysclk_mutex,
};
-static struct clk sysclk2 = {
- .name = "sysclk2",
- .ops = &sysclk_ops,
- .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ,
- .mutex = &sysclk_mutex,
-};
-
-static struct clk sysclk3 = {
- .name = "sysclk3",
- .ops = &sysclk_ops,
- .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ,
- .mutex = &sysclk_mutex,
-};
-
-static struct clk sysclk4 = {
- .name = "sysclk4",
- .ops = &sysclk_ops,
- .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ,
- .mutex = &sysclk_mutex,
-};
-
static struct clk rtc32k = {
.name = "rtc32k",
.rate = 32768,
@@ -633,7 +569,6 @@ static struct clk *db5500_dbg_clks[] __initdata = {
&p6_pclk7,
/* Clock sources */
- &sysclk2,
&clkout0,
&clkout1,
&rtc_clk1,
@@ -655,12 +590,6 @@ static struct clk_lookup u8500_common_clock_sources[] = {
CLK_LOOKUP(audioclk, "ab8500-codec.0", "audioclk"),
};
-static struct clk_lookup u8500_v2_sysclks[] = {
- CLK_LOOKUP(sysclk2, NULL, "sysclk2"),
- CLK_LOOKUP(sysclk3, NULL, "sysclk3"),
- CLK_LOOKUP(sysclk4, NULL, "sysclk4"),
-};
-
static struct clk_lookup db5500_prcmu_clocks[] = {
CLK_LOOKUP(sgaclk, "mali", NULL),
CLK_LOOKUP(siaclk, "mmio_camera", "sia"),
@@ -793,9 +722,6 @@ static void __init db5500_boot_clk_enable(void)
int __init db5500_clk_init(void)
{
- sysclk_ops.enable = NULL;
- sysclk_ops.disable = NULL;
-
if (ux500_is_svp()) {
prcmu_clk_ops.enable = NULL;
prcmu_clk_ops.disable = NULL;
@@ -813,11 +739,6 @@ int __init db5500_clk_init(void)
clks_register(db5500_clkouts, ARRAY_SIZE(db5500_clkouts));
clks_register(u5500_clocks, ARRAY_SIZE(u5500_clocks));
- if (cpu_is_u8500v2()) {
- clks_register(u8500_v2_sysclks,
- ARRAY_SIZE(u8500_v2_sysclks));
- }
-
db5500_boot_clk_enable();
/*
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index 3b0fd471d80..8e20bc69efa 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -158,11 +158,16 @@ static struct platform_device mbox2_device = {
.num_resources = ARRAY_SIZE(mbox2_resources),
};
+static struct platform_device db5500_prcmu_device = {
+ .name = "db5500-prcmu",
+};
+
static struct platform_device *db5500_platform_devs[] __initdata = {
&db5500_pmu_device,
&mbox0_device,
&mbox1_device,
&mbox2_device,
+ &db5500_prcmu_device,
};
static resource_size_t __initdata db5500_gpio_base[] = {
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index a9b01188dc4..f28f7858040 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -64,13 +64,8 @@ void __init ux500_init_irq(void)
* Init clocks here so that they are available for system timer
* initialization.
*/
- if (cpu_is_u5500())
- db5500_prcmu_early_init();
- if (cpu_is_u8500()) {
- prcmu_early_init();
- arm_pm_restart = ux500_restart;
- }
-
+ prcmu_early_init();
+ arm_pm_restart = ux500_restart;
clk_init();
}
diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c
index aa6389a2c20..75ecfd7a881 100644
--- a/arch/arm/mach-ux500/devices-db5500.c
+++ b/arch/arm/mach-ux500/devices-db5500.c
@@ -40,6 +40,11 @@
.start = IRQ_DB5500_GPIO##block, \
.end = IRQ_DB5500_GPIO##block, \
.flags = IORESOURCE_IRQ, \
+ }, \
+ { \
+ .start = IRQ_DB5500_PRCMU_GPIO##block, \
+ .end = IRQ_DB5500_PRCMU_GPIO##block, \
+ .flags = IORESOURCE_IRQ, \
}
#define GPIO_DEVICE(block) \
diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
index 77239776a6f..d8d00b6c2ba 100644
--- a/arch/arm/mach-ux500/include/mach/irqs-db5500.h
+++ b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
@@ -85,6 +85,35 @@
#ifdef CONFIG_UX500_SOC_DB5500
+/* Virtual interrupts corresponding to the PRCMU wakeups. */
+#define IRQ_DB5500_PRCMU_BASE IRQ_SOC_START
+
+#define IRQ_DB5500_PRCMU_RTC (IRQ_DB5500_PRCMU_BASE)
+#define IRQ_DB5500_PRCMU_RTT0 (IRQ_DB5500_PRCMU_BASE + 1)
+#define IRQ_DB5500_PRCMU_RTT1 (IRQ_DB5500_PRCMU_BASE + 2)
+#define IRQ_DB5500_PRCMU_CD_IRQ (IRQ_DB5500_PRCMU_BASE + 3)
+#define IRQ_DB5500_PRCMU_SRP_TIM (IRQ_DB5500_PRCMU_BASE + 4)
+#define IRQ_DB5500_PRCMU_APE_REQ (IRQ_DB5500_PRCMU_BASE + 5)
+#define IRQ_DB5500_PRCMU_USB (IRQ_DB5500_PRCMU_BASE + 6)
+#define IRQ_DB5500_PRCMU_ABB (IRQ_DB5500_PRCMU_BASE + 7)
+#define IRQ_DB5500_PRCMU_ARM (IRQ_DB5500_PRCMU_BASE + 8)
+#define IRQ_DB5500_PRCMU_MODEM_SW_RESET_REQ (IRQ_DB5500_PRCMU_BASE + 9)
+#define IRQ_DB5500_PRCMU_AC_WAKE_ACK (IRQ_DB5500_PRCMU_BASE + 10)
+#define IRQ_DB5500_PRCMU_GPIO0 (IRQ_DB5500_PRCMU_BASE + 11)
+#define IRQ_DB5500_PRCMU_GPIO1 (IRQ_DB5500_PRCMU_BASE + 12)
+#define IRQ_DB5500_PRCMU_GPIO2 (IRQ_DB5500_PRCMU_BASE + 13)
+#define IRQ_DB5500_PRCMU_GPIO3 (IRQ_DB5500_PRCMU_BASE + 14)
+#define IRQ_DB5500_PRCMU_GPIO4 (IRQ_DB5500_PRCMU_BASE + 15)
+#define IRQ_DB5500_PRCMU_GPIO5 (IRQ_DB5500_PRCMU_BASE + 16)
+#define IRQ_DB5500_PRCMU_GPIO6 (IRQ_DB5500_PRCMU_BASE + 17)
+#define IRQ_DB5500_PRCMU_GPIO7 (IRQ_DB5500_PRCMU_BASE + 18)
+#define IRQ_DB5500_PRCMU_AC_REL_ACK (IRQ_DB5500_PRCMU_BASE + 19)
+#define IRQ_DB5500_PRCMU_LOW_POWER_AUDIO (IRQ_DB5500_PRCMU_BASE + 20)
+#define IRQ_DB5500_PRCMU_TEMP_SENSOR (IRQ_DB5500_PRCMU_BASE + 21)
+#define IRQ_DB5500_PRCMU_END (IRQ_DB5500_PRCMU_BASE + 22)
+
+#define NUM_DB5500_PRCMU_WAKEUPS (IRQ_DB5500_PRCMU_END - IRQ_DB5500_PRCMU_BASE)
+
/*
* After the GPIO ones we reserve a range of IRQ:s in which virtual
* IRQ:s representing modem IRQ:s can be allocated
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
index ec4663046e3..50c51b5605e 100644
--- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h
+++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
@@ -110,6 +110,11 @@
#define PRCM_ARM_IT1_VAL (_PRCMU_BASE + 0x494)
#define PRCM_HOLD_EVT (_PRCMU_BASE + 0x174)
+#define PRCM_MOD_AWAKE_STATUS (_PRCMU_BASE + 0x4A0)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE BIT(0)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE BIT(1)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_VMODEM_OFF_ISO BIT(2)
+
#define PRCM_ITSTATUS0 (_PRCMU_BASE + 0x148)
#define PRCM_ITSTATUS1 (_PRCMU_BASE + 0x150)
#define PRCM_ITSTATUS2 (_PRCMU_BASE + 0x158)
@@ -193,4 +198,7 @@
#define PRCM_RESOUTN_SET (_PRCMU_BASE + 0x214)
#define PRCM_RESOUTN_CLR (_PRCMU_BASE + 0x218)
+/* System reset register */
+#define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228)
+
#endif /* __MACH_PRCMU__REGS_H */
diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h
index 41f68f0f087..6c7584d69d8 100644
--- a/arch/arm/mach-ux500/include/mach/prcmu.h
+++ b/arch/arm/mach-ux500/include/mach/prcmu.h
@@ -23,6 +23,7 @@ enum prcmu_wakeup_index {
PRCMU_WAKEUP_INDEX_ABB,
PRCMU_WAKEUP_INDEX_ABB_FIFO,
PRCMU_WAKEUP_INDEX_ARM,
+ PRCMU_WAKEUP_INDEX_CD_IRQ,
NUM_PRCMU_WAKEUP_INDICES
};
#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name))
@@ -192,12 +193,38 @@ enum ddr_opp {
DDR_25_OPP = 0x02,
};
+/*
+ * Definitions for controlling ESRAM0 in deep sleep.
+ */
+#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
+#define ESRAM0_DEEP_SLEEP_STATE_RET 2
+
+/**
+ * enum ddr_pwrst - DDR power states definition
+ * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
+ * @DDR_PWR_STATE_ON:
+ * @DDR_PWR_STATE_OFFLOWLAT:
+ * @DDR_PWR_STATE_OFFHIGHLAT:
+ */
+enum ddr_pwrst {
+ DDR_PWR_STATE_UNCHANGED = 0x00,
+ DDR_PWR_STATE_ON = 0x01,
+ DDR_PWR_STATE_OFFLOWLAT = 0x02,
+ DDR_PWR_STATE_OFFHIGHLAT = 0x03
+};
+
#include <linux/mfd/db8500-prcmu.h>
#include <linux/mfd/db5500-prcmu.h>
#if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500)
-void __init prcmu_early_init(void);
+static inline void __init prcmu_early_init(void)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_early_init();
+ else
+ return db8500_prcmu_early_init();
+}
static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
bool keep_ap_pll)
@@ -231,6 +258,22 @@ static inline void prcmu_disable_wakeups(void)
prcmu_enable_wakeups(0);
}
+static inline void prcmu_config_abb_event_readout(u32 abb_events)
+{
+ if (machine_is_u5500())
+ db5500_prcmu_config_abb_event_readout(abb_events);
+ else
+ db8500_prcmu_config_abb_event_readout(abb_events);
+}
+
+static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
+{
+ if (machine_is_u5500())
+ db5500_prcmu_get_abb_event_buffer(buf);
+ else
+ db8500_prcmu_get_abb_event_buffer(buf);
+}
+
int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
@@ -246,11 +289,25 @@ static inline int prcmu_request_clock(u8 clock, bool enable)
int prcmu_set_ape_opp(u8 opp);
int prcmu_get_ape_opp(void);
-int prcmu_set_arm_opp(u8 opp);
-int prcmu_get_arm_opp(void);
int prcmu_set_ddr_opp(u8 opp);
int prcmu_get_ddr_opp(void);
+static inline int prcmu_set_arm_opp(u8 opp)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_set_arm_opp(opp);
+ else
+ return db8500_prcmu_set_arm_opp(opp);
+}
+
+static inline int prcmu_get_arm_opp(void)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_get_arm_opp();
+ else
+ return db8500_prcmu_get_arm_opp();
+}
+
static inline void prcmu_system_reset(u16 reset_code)
{
if (machine_is_u5500())
@@ -259,17 +316,56 @@ static inline void prcmu_system_reset(u16 reset_code)
return db8500_prcmu_system_reset(reset_code);
}
-u16 prcmu_get_reset_code(void);
+static inline u16 prcmu_get_reset_code(void)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_get_reset_code();
+ else
+ return db8500_prcmu_get_reset_code();
+}
void prcmu_ac_wake_req(void);
void prcmu_ac_sleep_req(void);
void prcmu_modem_reset(void);
-bool prcmu_is_ac_wake_requested(void);
+static inline bool prcmu_is_ac_wake_requested(void)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_is_ac_wake_requested();
+ else
+ return db8500_prcmu_is_ac_wake_requested();
+}
+
+static inline int prcmu_set_display_clocks(void)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_set_display_clocks();
+ else
+ return db8500_prcmu_set_display_clocks();
+}
+
+static inline int prcmu_disable_dsipll(void)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_disable_dsipll();
+ else
+ return db8500_prcmu_disable_dsipll();
+}
-int prcmu_set_display_clocks(void);
-int prcmu_disable_dsipll(void);
-int prcmu_enable_dsipll(void);
+static inline int prcmu_enable_dsipll(void)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_enable_dsipll();
+ else
+ return db8500_prcmu_enable_dsipll();
+}
+static inline int prcmu_config_esram0_deep_sleep(u8 state)
+{
+ if (machine_is_u5500())
+ return db5500_prcmu_config_esram0_deep_sleep(state);
+ else
+ return db8500_prcmu_config_esram0_deep_sleep(state);
+}
#else
static inline void __init prcmu_early_init(void) {}
@@ -372,6 +468,18 @@ static inline int prcmu_enable_dsipll(void)
return 0;
}
+static inline int prcmu_config_esram0_deep_sleep(u8 state)
+{
+ return 0;
+}
+
+static inline void prcmu_config_abb_event_readout(u32 abb_events) {}
+
+static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
+{
+ *buf = NULL;
+}
+
#endif
/* PRCMU QoS APE OPP class */
diff --git a/arch/arm/mach-ux500/include/mach/regulator.h b/arch/arm/mach-ux500/include/mach/regulator.h
deleted file mode 100644
index cacb6bf5277..00000000000
--- a/arch/arm/mach-ux500/include/mach/regulator.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Bengt Jonsson <bengt.jonsson@stericsson.com> for ST-Ericsson,
- * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
- *
- * License Terms: GNU General Public License v2
- *
- */
-
-#ifndef MACH_UX500_REGULATOR_H
-#define MACH_UX500_REGULATOR_H
-
-#include <linux/regulator/dbx500-prcmu.h>
-
-#endif
diff --git a/arch/arm/mach-ux500/pm/Kconfig b/arch/arm/mach-ux500/pm/Kconfig
index d6454eab2a5..03aeaea57a5 100644
--- a/arch/arm/mach-ux500/pm/Kconfig
+++ b/arch/arm/mach-ux500/pm/Kconfig
@@ -1,10 +1,3 @@
-config U8500_CPUFREQ
- tristate "CPUFreq support"
- depends on UX500_SOC_DB8500 && CPU_FREQ && PM
- default y
- help
- Add support for CPU Frequency scaling for U8500.
-
config U8500_CPUIDLE
tristate "CPUIdle support"
depends on UX500_SOC_DB8500 && CPU_IDLE && !RTC_DRV_PL031 && PM
diff --git a/arch/arm/mach-ux500/pm/pm.c b/arch/arm/mach-ux500/pm/pm.c
index 5324d715274..b6442212324 100644
--- a/arch/arm/mach-ux500/pm/pm.c
+++ b/arch/arm/mach-ux500/pm/pm.c
@@ -185,18 +185,21 @@ bool ux500_pm_other_cpu_wfi(void)
return false;
}
-#define PRCMU_STATUS_REGISTER_V1 0x8015fe08
-#define PRCMU_STATUS_REGISTER_V2 0x801b8e08
+/* PRCM_ACK_MB0_AP_PWRSTTR_STATUS */
+#define DB8500_PRCMU_STATUS_REGISTER 0x801b8e08
+#define DB5500_PRCMU_STATUS_REGISTER 0x80168f38
enum prcmu_idle_stat ux500_pm_prcmu_idle_stat(void)
{
u32 val;
void __iomem *prcmu_status_reg;
- if (cpu_is_u8500v20_or_later())
- prcmu_status_reg = (void *)IO_ADDRESS(PRCMU_STATUS_REGISTER_V2);
+ if (cpu_is_u8500())
+ prcmu_status_reg = __io_address(DB8500_PRCMU_STATUS_REGISTER);
+ else if (cpu_is_u5500())
+ prcmu_status_reg = __io_address(DB5500_PRCMU_STATUS_REGISTER);
else
- prcmu_status_reg = (void *)IO_ADDRESS(PRCMU_STATUS_REGISTER_V1);
+ ux500_unknown_soc();
val = readl(prcmu_status_reg) & 0xff;
diff --git a/arch/arm/mach-ux500/pm/runtime.c b/arch/arm/mach-ux500/pm/runtime.c
index 40b360b684b..265faf3085d 100644
--- a/arch/arm/mach-ux500/pm/runtime.c
+++ b/arch/arm/mach-ux500/pm/runtime.c
@@ -19,7 +19,7 @@
#include <linux/amba/bus.h>
#include <linux/clk.h>
#include <plat/pincfg.h>
-#include <mach/regulator.h>
+#include <linux/regulator/dbx500-prcmu.h>
#include "../pins.h"
diff --git a/arch/arm/mach-ux500/pm/suspend.c b/arch/arm/mach-ux500/pm/suspend.c
index 44cd2373cc4..021ee8f53b5 100644
--- a/arch/arm/mach-ux500/pm/suspend.c
+++ b/arch/arm/mach-ux500/pm/suspend.c
@@ -155,7 +155,7 @@ exit:
nmk_gpio_wakeups_resume();
ux500_suspend_dbg_remove_wake_on_uart();
- return 0;
+ return ret;
}
static int ux500_suspend_enter(suspend_state_t state)
@@ -168,7 +168,8 @@ static int ux500_suspend_enter(suspend_state_t state)
if (ux500_suspend_sleep_enabled())
return suspend(false);
/* For debugging, if Sleep and DeepSleep disabled, do Idle */
- prcmu_set_power_state(PRCMU_AP_IDLE, true, true);
+ if (!cpu_is_u5500())
+ prcmu_set_power_state(PRCMU_AP_IDLE, true, true);
}
dsb();
diff --git a/arch/arm/mach-ux500/prcmu-debug.c b/arch/arm/mach-ux500/prcmu-debug.c
index 44e7c15bbcf..8344ff36ffb 100644
--- a/arch/arm/mach-ux500/prcmu-debug.c
+++ b/arch/arm/mach-ux500/prcmu-debug.c
@@ -285,24 +285,19 @@ static ssize_t opp_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos, int prcmu_qos_class)
{
- char buf[32];
- ssize_t buf_size;
- long unsigned int i;
+ long unsigned i;
+ int err;
- /* Get userspace string and assure termination */
- buf_size = min(count, (sizeof(buf)-1));
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- buf[buf_size] = 0;
+ err = kstrtoul_from_user(user_buf, count, 0, &i);
- if (strict_strtoul(buf, 0, &i) != 0)
- return buf_size;
+ if (err)
+ return err;
prcmu_qos_force_opp(prcmu_qos_class, i);
pr_info("prcmu debug: forced OPP for %d to %d\n", prcmu_qos_class, (int)i);
- return buf_size;
+ return count;
}
static ssize_t ddr_opp_write(struct file *file,
@@ -335,20 +330,13 @@ static ssize_t ape_voltage_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
-
- char buf[32];
- ssize_t buf_size;
- long unsigned int i;
+ long unsigned i;
int err;
- /* Get userspace string and assure termination */
- buf_size = min(count, (sizeof(buf)-1));
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- buf[buf_size] = 0;
+ err = kstrtoul_from_user(user_buf, count, 0, &i);
- if (strict_strtoul(buf, 0, &i) != 0)
- return buf_size;
+ if (err)
+ return err;
switch (i) {
case 0:
@@ -372,33 +360,27 @@ static ssize_t ape_voltage_write(struct file *file,
default:
pr_info("prcmu debug: value not equal to 0 or 1\n");
}
- return buf_size;
+ return count;
}
static ssize_t cpufreq_delay_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
+ int err;
+ long unsigned i;
- char buf[32];
- ssize_t buf_size;
- long unsigned int i;
-
- /* Get userspace string and assure termination */
- buf_size = min(count, (sizeof(buf)-1));
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- buf[buf_size] = 0;
+ err = kstrtoul_from_user(user_buf, count, 0, &i);
- if (strict_strtoul(buf, 0, &i) != 0)
- return buf_size;
+ if (err)
+ return err;
prcmu_qos_set_cpufreq_opp_delay(i);
pr_info("prcmu debug: changed delay between cpufreq change and QoS "
"requirement to %lu.\n", i);
- return buf_size;
+ return count;
}
static int arm_opp_open_file(struct inode *inode, struct file *file)
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index e2fc2d21fa6..a01791e7566 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -41,3 +41,4 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
# ARM SoC drivers
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
+obj-$(CONFIG_UX500_SOC_DB5500) += db5500-cpufreq.o
diff --git a/drivers/cpufreq/db5500-cpufreq.c b/drivers/cpufreq/db5500-cpufreq.c
new file mode 100644
index 00000000000..7c78bcb4761
--- /dev/null
+++ b/drivers/cpufreq/db5500-cpufreq.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Author: Martin Persson <martin.persson@stericsson.com>
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <mach/prcmu.h>
+#include <mach/id.h>
+
+static struct cpufreq_frequency_table freq_table[] = {
+ [0] = {
+ .index = 0,
+ .frequency = 200000,
+ },
+ [1] = {
+ .index = 1,
+ .frequency = 300000,
+ },
+ [2] = {
+ .index = 2,
+ .frequency = 600000,
+ },
+ [3] = {
+ .index = 3,
+ .frequency = CPUFREQ_TABLE_END,
+ },
+};
+
+static enum arm_opp idx2opp[] = {
+ ARM_EXTCLK,
+ ARM_50_OPP,
+ ARM_100_OPP
+};
+
+/*
+ * Below is a temporary workaround for wlan performance issues
+ */
+
+#include <linux/kernel_stat.h>
+#include <linux/workqueue.h>
+#include <linux/cpu.h>
+
+#include <mach/irqs.h>
+
+static struct freq_attr *db5500_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static int db5500_cpufreq_verify_speed(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static int db5500_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ unsigned int idx;
+
+ /* scale the target frequency to one of the extremes supported */
+ if (target_freq < policy->cpuinfo.min_freq)
+ target_freq = policy->cpuinfo.min_freq;
+ if (target_freq > policy->cpuinfo.max_freq)
+ target_freq = policy->cpuinfo.max_freq;
+
+ /* Lookup the next frequency */
+ if (cpufreq_frequency_table_target
+ (policy, freq_table, target_freq, relation, &idx)) {
+ return -EINVAL;
+ }
+
+ freqs.old = policy->cur;
+ freqs.new = freq_table[idx].frequency;
+ freqs.cpu = policy->cpu;
+
+ if (freqs.old == freqs.new)
+ return 0;
+
+ /* pre-change notification */
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ /* request the PRCM unit for opp change */
+ if (prcmu_set_arm_opp(idx2opp[idx])) {
+ pr_err("db5500-cpufreq: Failed to set OPP level\n");
+ return -EINVAL;
+ }
+
+ /* post change notification */
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return 0;
+}
+
+static unsigned int db5500_cpufreq_getspeed(unsigned int cpu)
+{
+ int i;
+ /* request the prcm to get the current ARM opp */
+ for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++)
+ ;
+ return freq_table[i].frequency;
+}
+
+static int __cpuinit db5500_cpufreq_init(struct cpufreq_policy *policy)
+{
+ int res;
+ int i = 0;
+
+ BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
+
+ pr_info("db5500-cpufreq : Available frequencies:\n");
+ while (freq_table[i].frequency != CPUFREQ_TABLE_END)
+ pr_info(" %d Mhz\n", freq_table[i++].frequency/1000);
+
+ /* get policy fields based on the table */
+ res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ if (!res)
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+ else {
+ pr_err("db5500-cpufreq : Failed to read policy table\n");
+ return res;
+ }
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = db5500_cpufreq_getspeed(policy->cpu);
+
+ for (i = 0; freq_table[i].frequency != policy->cur; i++)
+ ;
+
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+
+ /*
+ * FIXME : Need to take time measurement across the target()
+ * function with no/some/all drivers in the notification
+ * list.
+ */
+ policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */
+
+ /* policy sharing between dual CPUs */
+ cpumask_copy(policy->cpus, &cpu_present_map);
+
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+
+ return 0;
+}
+
+static struct cpufreq_driver db5500_cpufreq_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = db5500_cpufreq_verify_speed,
+ .target = db5500_cpufreq_target,
+ .get = db5500_cpufreq_getspeed,
+ .init = db5500_cpufreq_init,
+ .name = "DB5500",
+ .attr = db5500_cpufreq_attr,
+};
+
+static int __init db5500_cpufreq_register(void)
+{
+ pr_info("cpufreq for DB5500 started\n");
+ return cpufreq_register_driver(&db5500_cpufreq_driver);
+}
+device_initcall(db5500_cpufreq_register);
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index 4943578f452..4b863110bd8 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -151,7 +151,7 @@ static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
{
int res;
- int i;
+ int i = 0;
BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
@@ -169,6 +169,10 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
&work_wlan_workaround,
msecs_to_jiffies(WLAN_PROBE_DELAY));
+ pr_info("db8500-cpufreq : Available frequencies:\n");
+ while (freq_table[i].frequency != CPUFREQ_TABLE_END)
+ pr_info(" %d Mhz\n", freq_table[i++].frequency/1000);
+
/* get policy fields based on the table */
res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
if (!res)
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index da168cb57f6..f0aed67f29a 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -20,7 +20,7 @@
#include <linux/klist.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <mach/regulator.h>
+#include <linux/regulator/dbx500-prcmu.h>
#include <linux/semaphore.h>
#include <crypto/aes.h>
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 3b472d0bfaa..aec6bcf5e1d 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -21,7 +21,7 @@
#include <linux/platform_device.h>
#include <linux/crypto.h>
-#include <mach/regulator.h>
+#include <linux/regulator/dbx500-prcmu.h>
#include <linux/bitops.h>
#include <crypto/internal/hash.h>
diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c
index 75c773b232f..df0ce72e585 100755
--- a/drivers/mfd/ab5500-core.c
+++ b/drivers/mfd/ab5500-core.c
@@ -28,7 +28,8 @@
#include <linux/spinlock.h>
#include <linux/mfd/core.h>
#include <linux/version.h>
-#include <linux/mfd/db5500-prcmu.h>
+#include <linux/io.h>
+#include <mach/prcmu.h>
#define AB5500_NAME_STRING "ab5500"
#define AB5500_ID_FORMAT_STRING "AB5500 %s"
@@ -48,7 +49,7 @@
#define AB5500_MASK_BASE (0x60)
#define AB5500_MASK_END (0x79)
#define AB5500_CHIP_ID (0x20)
-
+#define AB5500_INTERRUPTS 0x007FFFFF
/**
* struct ab5500_bank
* @slave_addr: I2C slave_addr found in AB5500 specification
@@ -1072,17 +1073,6 @@ static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = {
};
/*
- * This stubbed prcmu functionality should be removed when the prcmu driver
- * implements it.
- */
-static u8 prcmu_event_buf[AB5500_NUM_EVENT_REG];
-
-void prcmu_get_abb_event_buf(u8 **buf)
-{
- *buf = prcmu_event_buf;
-}
-
-/*
* Functionality for getting/setting register values.
*/
static int get_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg,
@@ -1355,19 +1345,20 @@ static irqreturn_t ab5500_irq(int irq, void *data)
{
struct ab5500 *ab = data;
u8 i;
+ u8 *pvalue;
+ u8 value;
- /*
- * TODO: use the ITMASTER registers to reduce the number of i2c reads.
- */
-
+ prcmu_get_abb_event_buffer((void **)&pvalue);
+ if (unlikely(pvalue == NULL)) {
+ dev_err(ab->dev, "PRCMU not enabled!!!\n");
+ goto error_irq;
+ }
for (i = 0; i < AB5500_NUM_EVENT_REG; i++) {
- int status;
- u8 value;
-
- status = get_register_interruptible(ab, AB5500_BANK_IT,
- AB5500_IT_LATCH0_REG + i, &value);
- if (status < 0 || value == 0)
+ value = readb(pvalue);
+ if (value == 0) {
+ pvalue++;
continue;
+ }
do {
int bit = __ffs(value);
@@ -1376,9 +1367,12 @@ static irqreturn_t ab5500_irq(int irq, void *data)
handle_nested_irq(ab->irq_base + line);
value &= ~(1 << bit);
} while (value);
+ pvalue++;
}
return IRQ_HANDLED;
+error_irq:
+ return IRQ_NONE;
}
#ifdef CONFIG_DEBUG_FS
@@ -2416,7 +2410,7 @@ static int __init ab5500_probe(struct platform_device *pdev)
goto exit_remove_irq;
}
-
+ prcmu_config_abb_event_readout(AB5500_INTERRUPTS);
/* This real unpredictable IRQ is of course sampled for entropy */
rand_initialize_irq(res->start);
diff --git a/drivers/mfd/db5500-prcmu.c b/drivers/mfd/db5500-prcmu.c
index 7bbd34c04ad..f5774493e7e 100644
--- a/drivers/mfd/db5500-prcmu.c
+++ b/drivers/mfd/db5500-prcmu.c
@@ -19,6 +19,11 @@
#include <linux/irq.h>
#include <linux/jiffies.h>
#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/mfd/core.h>
+#include <linux/regulator/db5500-prcmu.h>
+#include <linux/regulator/machine.h>
#include <linux/interrupt.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
@@ -26,6 +31,8 @@
#include <mach/db5500-regs.h>
#include <mach/prcmu-regs.h>
+#define PRCM_SW_RST_REASON (tcdm_base + 0xFF8) /* 2 bytes */
+
#define _PRCM_MB_HEADER (tcdm_base + 0xFE8)
#define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0)
#define PRCM_REQ_MB1_HEADER (_PRCM_MB_HEADER + 0x1)
@@ -64,6 +71,34 @@
#define PRCM_ACK_MB6 (tcdm_base + 0xF0C)
#define PRCM_ACK_MB7 (tcdm_base + 0xF08)
+/* 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)
+#define PRCM_REQ_MB0_AP_PLL_STATE (PRCM_REQ_MB0 + 0x2)
+#define PRCM_REQ_MB0_DDR_STATE (PRCM_REQ_MB0 + 0x3)
+#define PRCM_REQ_MB0_ESRAM0_STATE (PRCM_REQ_MB0 + 0x4)
+#define PRCM_REQ_MB0_WAKEUP_DBB (PRCM_REQ_MB0 + 0x8)
+#define PRCM_REQ_MB0_WAKEUP_ABB (PRCM_REQ_MB0 + 0xC)
+
+/* Mailbox 0 ACKs */
+#define PRCM_ACK_MB0_AP_PWRSTTR_STATUS (PRCM_ACK_MB0 + 0x0)
+#define PRCM_ACK_MB0_READ_POINTER (PRCM_ACK_MB0 + 0x1)
+#define PRCM_ACK_MB0_WAKEUP_0_DBB (PRCM_ACK_MB0 + 0x4)
+#define PRCM_ACK_MB0_WAKEUP_0_ABB (PRCM_ACK_MB0 + 0x8)
+#define PRCM_ACK_MB0_WAKEUP_1_DBB (PRCM_ACK_MB0 + 0x28)
+#define PRCM_ACK_MB0_WAKEUP_1_ABB (PRCM_ACK_MB0 + 0x2C)
+#define PRCM_ACK_MB0_EVENT_ABB_NUMBERS 20
+
+/* Request mailbox 1 fields. */
+#define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0)
+#define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1)
+
+/* Mailbox 1 ACKs */
+#define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0)
+#define PRCM_ACK_MB1_CURRENT_APE_OPP (PRCM_ACK_MB1 + 0x1)
+#define PRCM_ACK_MB1_ARM_VOLT_STATUS (PRCM_ACK_MB1 + 0x2)
+#define PRCM_ACK_MB1_APE_VOLT_STATUS (PRCM_ACK_MB1 + 0x3)
+
/* Mailbox 2 REQs */
#define PRCM_REQ_MB2_EPOD_CLIENT (PRCM_REQ_MB2 + 0x0)
#define PRCM_REQ_MB2_EPOD_STATE (PRCM_REQ_MB2 + 0x1)
@@ -84,31 +119,59 @@ enum mb_return_code {
/* Mailbox 0 headers. */
enum mb0_header {
- /* request */
- RMB0H_PWR_STATE_TRANS = 1,
- RMB0H_WAKE_UP_CFG,
- RMB0H_RD_WAKE_UP_ACK,
/* acknowledge */
- AMB0H_WAKE_UP = 1,
+ MB0H_WAKE_UP = 0,
+ /* request */
+ MB0H_PWR_STATE_TRANS,
+ MB0H_WAKE_UP_CFG,
+ MB0H_RD_WAKE_UP_ACK,
};
-/* Mailbox 5 headers. */
+/* Mailbox 1 headers.*/
+enum mb1_header {
+ MB1H_ARM_OPP = 1,
+ MB1H_APE_OPP,
+ MB1H_ARM_APE_OPP,
+};
+
+/* Mailbox 2 headers. */
enum mb2_header {
MB2H_EPOD_REQUEST = 1,
MB2H_CLK_REQUEST,
MB2H_PLL_REQUEST,
};
+/* Mailbox 3 headers. */
+enum mb3_header {
+ MB3H_REFCLK_REQUEST = 1,
+};
+
+enum sysclk_state {
+ SYSCLK_OFF,
+ SYSCLK_ON,
+};
+
/* Mailbox 5 headers. */
enum mb5_header {
MB5H_I2C_WRITE = 1,
MB5H_I2C_READ,
};
+enum db5500_arm_opp {
+ DB5500_ARM_100_OPP = 1,
+ DB5500_ARM_50_OPP,
+ DB5500_ARM_EXT_OPP,
+};
+
enum epod_state {
EPOD_OFF,
EPOD_ON,
};
+enum epod_onoffret_state {
+ EPOD_OOR_OFF,
+ EPOD_OOR_RET,
+ EPOD_OOR_ON,
+};
enum db5500_prcmu_pll {
DB5500_PLL_SOC0,
DB5500_PLL_SOC1,
@@ -116,6 +179,24 @@ enum db5500_prcmu_pll {
DB5500_NUM_PLL_ID,
};
+enum on_off_ret {
+ OFF_ST,
+ RET_ST,
+ ON_ST,
+};
+
+enum db5500_ap_pwr_state {
+ DB5500_AP_SLEEP = 2,
+ DB5500_AP_DEEP_SLEEP,
+ DB5500_AP_IDLE,
+};
+
+/* Request mailbox 3 fields */
+#define PRCM_REQ_MB3_REFCLK_MGT (PRCM_REQ_MB3 + 0x0)
+
+/* Ack. mailbox 3 fields */
+#define PRCM_ACK_MB3_REFCLK_REQ (PRCM_ACK_MB3 + 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)
@@ -156,13 +237,120 @@ enum db5500_prcmu_pll {
#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3
/*
+ * Wakeups/IRQs
+ */
+
+#define WAKEUP_BIT_RTC BIT(0)
+#define WAKEUP_BIT_RTT0 BIT(1)
+#define WAKEUP_BIT_RTT1 BIT(2)
+#define WAKEUP_BIT_CD_IRQ BIT(3)
+#define WAKEUP_BIT_SRP_TIM BIT(4)
+#define WAKEUP_BIT_APE_REQ BIT(5)
+#define WAKEUP_BIT_USB BIT(6)
+#define WAKEUP_BIT_ABB BIT(7)
+#define WAKEUP_BIT_LOW_POWER_AUDIO BIT(8)
+#define WAKEUP_BIT_TEMP_SENSOR BIT(9)
+#define WAKEUP_BIT_ARM BIT(10)
+#define WAKEUP_BIT_AC_WAKE_ACK BIT(11)
+#define WAKEUP_BIT_MODEM_SW_RESET_REQ BIT(20)
+#define WAKEUP_BIT_GPIO0 BIT(23)
+#define WAKEUP_BIT_GPIO1 BIT(24)
+#define WAKEUP_BIT_GPIO2 BIT(25)
+#define WAKEUP_BIT_GPIO3 BIT(26)
+#define WAKEUP_BIT_GPIO4 BIT(27)
+#define WAKEUP_BIT_GPIO5 BIT(28)
+#define WAKEUP_BIT_GPIO6 BIT(29)
+#define WAKEUP_BIT_GPIO7 BIT(30)
+#define WAKEUP_BIT_AC_REL_ACK BIT(30)
+
+/*
+ * This vector maps irq numbers to the bits in the bit field used in
+ * communication with the PRCMU firmware.
+ *
+ * The reason for having this is to keep the irq numbers contiguous even though
+ * the bits in the bit field are not. (The bits also have a tendency to move
+ * around, to further complicate matters.)
+ */
+#define IRQ_INDEX(_name) ((IRQ_DB5500_PRCMU_##_name) - IRQ_DB5500_PRCMU_BASE)
+#define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name)
+static u32 prcmu_irq_bit[NUM_DB5500_PRCMU_WAKEUPS] = {
+ IRQ_ENTRY(RTC),
+ IRQ_ENTRY(RTT0),
+ IRQ_ENTRY(RTT1),
+ IRQ_ENTRY(CD_IRQ),
+ IRQ_ENTRY(SRP_TIM),
+ IRQ_ENTRY(APE_REQ),
+ IRQ_ENTRY(USB),
+ IRQ_ENTRY(ABB),
+ IRQ_ENTRY(LOW_POWER_AUDIO),
+ IRQ_ENTRY(TEMP_SENSOR),
+ IRQ_ENTRY(ARM),
+ IRQ_ENTRY(AC_WAKE_ACK),
+ IRQ_ENTRY(MODEM_SW_RESET_REQ),
+ IRQ_ENTRY(GPIO0),
+ IRQ_ENTRY(GPIO1),
+ IRQ_ENTRY(GPIO2),
+ IRQ_ENTRY(GPIO3),
+ IRQ_ENTRY(GPIO4),
+ IRQ_ENTRY(GPIO5),
+ IRQ_ENTRY(GPIO6),
+ IRQ_ENTRY(GPIO7),
+ IRQ_ENTRY(AC_REL_ACK),
+};
+
+#define VALID_WAKEUPS (BIT(NUM_PRCMU_WAKEUP_INDICES) - 1)
+#define WAKEUP_ENTRY(_name)[PRCMU_WAKEUP_INDEX_##_name] = (WAKEUP_BIT_##_name)
+static u32 prcmu_wakeup_bit[NUM_PRCMU_WAKEUP_INDICES] = {
+ WAKEUP_ENTRY(RTC),
+ WAKEUP_ENTRY(RTT0),
+ WAKEUP_ENTRY(RTT1),
+ WAKEUP_ENTRY(CD_IRQ),
+ WAKEUP_ENTRY(USB),
+ WAKEUP_ENTRY(ABB),
+ WAKEUP_ENTRY(ARM)
+};
+
+/*
* mb0_transfer - state needed for mailbox 0 communication.
- * @lock: The transaction lock.
+ * @lock The transaction lock.
+ * @dbb_irqs_lock lock used for (un)masking DBB wakeup interrupts
+ * @mask_work: Work structure used for (un)masking wakeup interrupts.
+ * @req: Request data that need to persist between requests.
*/
static struct {
spinlock_t lock;
+ spinlock_t dbb_irqs_lock;
+ struct work_struct mask_work;
+ struct {
+ u32 dbb_irqs;
+ u32 dbb_wakeups;
+ u32 abb_events;
+ } req;
} mb0_transfer;
+
+/*
+ * mb1_transfer - state needed for mailbox 1 communication.
+ * @lock: The transaction lock.
+ * @work: The transaction completion structure.
+ * @req_arm_opp Requested arm opp
+ * @req_ape_opp Requested ape opp
+ * @ack: Reply ("acknowledge") data.
+ */
+static struct {
+ struct mutex lock;
+ struct completion work;
+ u8 req_arm_opp;
+ u8 req_ape_opp;
+ struct {
+ u8 header;
+ u8 arm_opp;
+ u8 ape_opp;
+ u8 arm_voltage_st;
+ u8 ape_voltage_st;
+ } ack;
+} mb1_transfer;
+
/*
* mb2_transfer - state needed for mailbox 2 communication.
* @lock: The transaction lock.
@@ -174,8 +362,8 @@ static struct {
struct mutex lock;
struct completion work;
struct {
- u8 epod_states[DB5500_NUM_EPOD_ID];
- u8 pll_states[DB5500_NUM_PLL_ID];
+ u8 epod_st[DB5500_NUM_EPOD_ID];
+ u8 pll_st[DB5500_NUM_PLL_ID];
} req;
struct {
u8 header;
@@ -184,6 +372,23 @@ static struct {
} mb2_transfer;
/*
+ * mb3_transfer - state needed for mailbox 3 communication.
+ * @sysclk_lock: A lock used to handle concurrent sysclk requests.
+ * @sysclk_work: Work structure used for sysclk requests.
+ * @req_st: Requested clock state.
+ * @ack: Acknowledgement data
+ */
+static struct {
+ struct mutex sysclk_lock;
+ struct completion sysclk_work;
+ enum sysclk_state req_st;
+ struct {
+ u8 header;
+ u8 status;
+ } ack;
+} mb3_transfer;
+
+/*
* mb5_transfer - state needed for mailbox 5 communication.
* @lock: The transaction lock.
* @work: The transaction completion structure.
@@ -239,6 +444,55 @@ static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
CLK_MGT_ENTRY(SVACLK),
};
+bool db5500_prcmu_is_ac_wake_requested(void)
+{
+ return false;
+}
+
+static int request_sysclk(bool enable)
+{
+ int r;
+
+ r = 0;
+ mutex_lock(&mb3_transfer.sysclk_lock);
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
+ cpu_relax();
+
+ if (enable)
+ mb3_transfer.req_st = SYSCLK_ON;
+ else
+ mb3_transfer.req_st = SYSCLK_OFF;
+
+ writeb(mb3_transfer.req_st, (PRCM_REQ_MB3_REFCLK_MGT));
+
+ writeb(MB3H_REFCLK_REQUEST, (PRCM_REQ_MB3_HEADER));
+ writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
+
+ /*
+ * The firmware only sends an ACK if we want to enable the
+ * SysClk, and it succeeds.
+ */
+ if (!wait_for_completion_timeout(&mb3_transfer.sysclk_work,
+ msecs_to_jiffies(20000))) {
+ pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ __func__);
+ r = -EIO;
+ WARN(1, "Failed to set sysclk");
+ goto unlock_and_return;
+ }
+
+ if ((mb3_transfer.ack.header != MB3H_REFCLK_REQUEST) ||
+ (mb3_transfer.ack.status != mb3_transfer.req_st)) {
+ r = -EIO;
+ }
+
+unlock_and_return:
+ mutex_unlock(&mb3_transfer.sysclk_lock);
+
+ return r;
+}
+
static int request_timclk(bool enable)
{
u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK);
@@ -298,11 +552,11 @@ static int request_pll(u8 pll, bool enable)
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
cpu_relax();
- mb2_transfer.req.pll_states[pll] = enable;
+ mb2_transfer.req.pll_st[pll] = enable;
/* fill in mailbox */
writeb(pll, PRCM_REQ_MB2_PLL_CLIENT);
- writeb(mb2_transfer.req.pll_states[pll], PRCM_REQ_MB2_PLL_STATE);
+ writeb(mb2_transfer.req.pll_st[pll], PRCM_REQ_MB2_PLL_STATE);
writeb(MB2H_PLL_REQUEST, PRCM_REQ_MB2_HEADER);
@@ -325,12 +579,8 @@ unlock_and_return:
return r;
}
-void db5500_prcmu_enable_wakeups(u32 wakeups)
-{
-}
-
/**
- * prcmu_request_clock() - Request for a clock to be enabled or disabled.
+ * db5500_prcmu_request_clock() - Request for a clock to be enabled or disabled.
* @clock: The clock for which the request is made.
* @enable: Whether the clock should be enabled (true) or disabled (false).
*
@@ -350,11 +600,144 @@ int db5500_prcmu_request_clock(u8 clock, bool enable)
else if (clock == PRCMU_PLLDDR)
return request_pll(DB5500_PLL_DDR, enable);
else if (clock == PRCMU_SYSCLK)
- return -EINVAL;
+ return request_sysclk(enable);
else
return -EINVAL;
}
+/* This function should only be called while mb0_transfer.lock is held. */
+static void config_wakeups(void)
+{
+ static u32 last_dbb_events;
+ static u32 last_abb_events;
+ u32 dbb_events;
+ u32 abb_events;
+
+ dbb_events = mb0_transfer.req.dbb_irqs | mb0_transfer.req.dbb_wakeups;
+
+ abb_events = mb0_transfer.req.abb_events;
+
+ if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events))
+ return;
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+ cpu_relax();
+
+ writel(dbb_events, PRCM_REQ_MB0_WAKEUP_DBB);
+ writel(abb_events, PRCM_REQ_MB0_WAKEUP_ABB);
+ writeb(MB0H_WAKE_UP_CFG, PRCM_REQ_MB0_HEADER);
+ writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
+
+ last_dbb_events = dbb_events;
+ last_abb_events = abb_events;
+}
+
+int db5500_prcmu_config_esram0_deep_sleep(u8 state)
+{
+ unsigned long flags;
+
+ if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) ||
+ (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
+ return -EINVAL;
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ if (state == ESRAM0_DEEP_SLEEP_STATE_RET)
+ writeb(RET_ST, PRCM_REQ_MB0_ESRAM0_STATE);
+ else
+ writeb(OFF_ST, PRCM_REQ_MB0_ESRAM0_STATE);
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+
+ return 0;
+}
+
+int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
+{
+ int r = 0;
+ unsigned long flags;
+
+ /* Deep Idle is not supported in DB5500 */
+ BUG_ON((state < PRCMU_AP_SLEEP) || (state >= PRCMU_AP_DEEP_IDLE));
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+ cpu_relax();
+
+ switch (state) {
+ case PRCMU_AP_IDLE:
+ writeb(DB5500_AP_IDLE, PRCM_REQ_MB0_AP_POWER_STATE);
+ /* TODO: Can be high latency */
+ writeb(DDR_PWR_STATE_UNCHANGED, PRCM_REQ_MB0_DDR_STATE);
+ break;
+ case PRCMU_AP_SLEEP:
+ writeb(DB5500_AP_SLEEP, PRCM_REQ_MB0_AP_POWER_STATE);
+ break;
+ case PRCMU_AP_DEEP_SLEEP:
+ writeb(DB5500_AP_DEEP_SLEEP, PRCM_REQ_MB0_AP_POWER_STATE);
+ break;
+ default:
+ r = -EINVAL;
+ goto unlock_return;
+ }
+ writeb((keep_ap_pll ? 1 : 0), PRCM_REQ_MB0_AP_PLL_STATE);
+ writeb((keep_ulp_clk ? 1 : 0), PRCM_REQ_MB0_ULP_CLOCK_STATE);
+
+ writeb(MB0H_PWR_STATE_TRANS, PRCM_REQ_MB0_HEADER);
+ writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
+
+unlock_return:
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+
+ return r;
+}
+
+void db5500_prcmu_enable_wakeups(u32 wakeups)
+{
+ unsigned long flags;
+ u32 bits;
+ int i;
+
+ BUG_ON(wakeups != (wakeups & VALID_WAKEUPS));
+
+ for (i = 0, bits = 0; i < NUM_PRCMU_WAKEUP_INDICES; i++) {
+ if (wakeups & BIT(i)) {
+ if (prcmu_wakeup_bit[i] == 0)
+ WARN(1, "WAKEUP NOT SUPPORTED");
+ else
+ bits |= prcmu_wakeup_bit[i];
+ }
+ }
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ mb0_transfer.req.dbb_wakeups = bits;
+ config_wakeups();
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+}
+
+void db5500_prcmu_config_abb_event_readout(u32 abb_events)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ mb0_transfer.req.abb_events = abb_events;
+ config_wakeups();
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+}
+
+void db5500_prcmu_get_abb_event_buffer(void __iomem **buf)
+{
+ if (readb(PRCM_ACK_MB0_READ_POINTER) & 1)
+ *buf = (PRCM_ACK_MB0_WAKEUP_1_ABB);
+ else
+ *buf = (PRCM_ACK_MB0_WAKEUP_0_ABB);
+}
+
/**
* db5500_prcmu_abb_read() - Read register value(s) from the ABB.
* @slave: The I2C slave address.
@@ -437,6 +820,75 @@ int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
return r;
}
+/**
+ * db5500_prcmu_set_arm_opp - set the appropriate ARM OPP
+ * @opp: The new ARM operating point to which transition is to be made
+ * Returns: 0 on success, non-zero on failure
+ *
+ * This function sets the the operating point of the ARM.
+ */
+int db5500_prcmu_set_arm_opp(u8 opp)
+{
+ int r;
+ u8 db5500_opp;
+
+ r = 0;
+
+ switch (opp) {
+ case ARM_EXTCLK:
+ db5500_opp = DB5500_ARM_EXT_OPP;
+ break;
+ case ARM_50_OPP:
+ db5500_opp = DB5500_ARM_50_OPP;
+ break;
+ case ARM_100_OPP:
+ db5500_opp = DB5500_ARM_100_OPP;
+ break;
+ default:
+ pr_err("prcmu: %s() received wrong opp value: %d\n",
+ __func__, opp);
+ r = -EINVAL;
+ goto bailout;
+ }
+
+ mutex_lock(&mb1_transfer.lock);
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+ cpu_relax();
+
+ writeb(MB1H_ARM_OPP, PRCM_REQ_MB1_HEADER);
+
+ writeb(db5500_opp, PRCM_REQ_MB1_ARM_OPP);
+ writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
+
+ if (!wait_for_completion_timeout(&mb1_transfer.work,
+ msecs_to_jiffies(500))) {
+ r = -EIO;
+ WARN(1, "prcmu: failed to set arm opp");
+ goto unlock_and_return;
+ }
+
+ if (mb1_transfer.ack.header != MB1H_ARM_OPP ||
+ (mb1_transfer.ack.arm_opp != db5500_opp) ||
+ (mb1_transfer.ack.arm_voltage_st != RC_SUCCESS))
+ r = -EIO;
+
+unlock_and_return:
+ mutex_unlock(&mb1_transfer.lock);
+bailout:
+ return r;
+}
+
+/**
+ * db5500_prcmu_get_arm_opp - get the current ARM OPP
+ *
+ * Returns: the current ARM OPP
+ */
+int db5500_prcmu_get_arm_opp(void)
+{
+ return readb(PRCM_ACK_MB1_CURRENT_ARM_OPP);
+}
+
int prcmu_resetout(u8 resoutn, u8 state)
{
int pin = -1;
@@ -511,6 +963,29 @@ int db5500_prcmu_set_display_clocks(void)
return 0;
}
+/**
+ * db5500_prcmu_system_reset - System reset
+ *
+ * Saves the reset reason code and then sets the APE_SOFTRST register which
+ * fires an interrupt to fw
+ */
+void db5500_prcmu_system_reset(u16 reset_code)
+{
+ writew(reset_code, PRCM_SW_RST_REASON);
+ writel(1, PRCM_APE_SOFTRST);
+}
+
+/**
+ * db5500_prcmu_get_reset_code - Retrieve SW reset reason code
+ *
+ * Retrieves the reset reason code stored by prcmu_system_reset() before
+ * last restart.
+ */
+u16 db5500_prcmu_get_reset_code(void)
+{
+ return readw(PRCM_SW_RST_REASON);
+}
+
static void ack_dbb_wakeup(void)
{
unsigned long flags;
@@ -520,34 +995,27 @@ static void ack_dbb_wakeup(void)
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
cpu_relax();
- writeb(RMB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER);
+ writeb(MB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER);
writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
spin_unlock_irqrestore(&mb0_transfer.lock, flags);
}
-int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state)
+int db5500_prcmu_set_epod(u16 epod, u8 epod_state)
{
int r = 0;
bool ram_retention = false;
/* check argument */
- BUG_ON(epod_id < DB5500_EPOD_ID_BASE);
+ BUG_ON(epod < DB5500_EPOD_ID_BASE);
BUG_ON(epod_state > EPOD_STATE_ON);
+ BUG_ON((epod - DB5500_EPOD_ID_BASE) >= DB5500_NUM_EPOD_ID);
- epod_id &= 0xFF;
- BUG_ON(epod_id > DB5500_NUM_EPOD_ID);
-
- /* TODO: FW does not take retention for ESRAM12?
- set flag if retention is possible */
- switch (epod_id) {
- case DB5500_EPOD_ID_ESRAM12:
+ if (epod == DB5500_EPOD_ID_ESRAM12)
ram_retention = true;
- break;
- }
/* check argument */
- /* BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention); */
+ BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention);
/* get lock */
mutex_lock(&mb2_transfer.lock);
@@ -556,19 +1024,42 @@ int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state)
while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
cpu_relax();
- /* PRCMU FW can only handle on or off */
- if (epod_state == EPOD_STATE_ON)
- mb2_transfer.req.epod_states[epod_id] = EPOD_ON;
- else if (epod_state == EPOD_STATE_OFF)
- mb2_transfer.req.epod_states[epod_id] = EPOD_OFF;
- else {
- r = -EINVAL;
- goto unlock_and_return;
+ /* Retention is allowed only for ESRAM12 */
+ if (epod == DB5500_EPOD_ID_ESRAM12) {
+ switch (epod_state) {
+ case EPOD_STATE_ON:
+ mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] =
+ EPOD_OOR_ON;
+ break;
+ case EPOD_STATE_OFF:
+ mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] =
+ EPOD_OOR_OFF;
+ break;
+ case EPOD_STATE_RAMRET:
+ mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] =
+ EPOD_OOR_RET;
+ break;
+ default:
+ r = -EINVAL;
+ goto unlock_and_return;
+ break;
+ }
+ } else {
+ if (epod_state == EPOD_STATE_ON)
+ mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] =
+ EPOD_ON;
+ else if (epod_state == EPOD_STATE_OFF)
+ mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] =
+ EPOD_OFF;
+ else {
+ r = -EINVAL;
+ goto unlock_and_return;
+ }
}
-
/* fill in mailbox */
- writeb(epod_id, PRCM_REQ_MB2_EPOD_CLIENT);
- writeb(mb2_transfer.req.epod_states[epod_id], PRCM_REQ_MB2_EPOD_STATE);
+ writeb((epod - DB5500_EPOD_ID_BASE), PRCM_REQ_MB2_EPOD_CLIENT);
+ writeb(mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE],
+ PRCM_REQ_MB2_EPOD_STATE);
writeb(MB2H_EPOD_REQUEST, PRCM_REQ_MB2_HEADER);
@@ -601,11 +1092,25 @@ static inline void print_unknown_header_warning(u8 n, u8 header)
static bool read_mailbox_0(void)
{
bool r;
+ u32 ev;
+ unsigned int n;
+
u8 header;
header = readb(PRCM_ACK_MB0_HEADER);
switch (header) {
- case AMB0H_WAKE_UP:
+ case MB0H_WAKE_UP:
+ if (readb(PRCM_ACK_MB0_READ_POINTER) & 1)
+ ev = readl(PRCM_ACK_MB0_WAKEUP_1_DBB);
+ else
+ ev = readl(PRCM_ACK_MB0_WAKEUP_0_DBB);
+
+ ev &= mb0_transfer.req.dbb_irqs;
+
+ for (n = 0; n < NUM_DB5500_PRCMU_WAKEUPS; n++) {
+ if (ev & prcmu_irq_bit[n])
+ generic_handle_irq(IRQ_DB5500_PRCMU_BASE + n);
+ }
r = true;
break;
default:
@@ -619,7 +1124,33 @@ static bool read_mailbox_0(void)
static bool read_mailbox_1(void)
{
+ u8 header;
+ bool do_complete = true;
+
+ header = mb1_transfer.ack.header = readb(PRCM_ACK_MB1_HEADER);
+
+ switch (header) {
+ case MB1H_ARM_OPP:
+ mb1_transfer.ack.arm_opp = readb(PRCM_ACK_MB1_CURRENT_ARM_OPP);
+ mb1_transfer.ack.arm_voltage_st =
+ readb(PRCM_ACK_MB1_ARM_VOLT_STATUS);
+ break;
+ case MB1H_ARM_APE_OPP:
+ mb1_transfer.ack.ape_opp = readb(PRCM_ACK_MB1_CURRENT_APE_OPP);
+ mb1_transfer.ack.ape_voltage_st =
+ readb(PRCM_ACK_MB1_APE_VOLT_STATUS);
+ break;
+ default:
+ print_unknown_header_warning(1, header);
+ do_complete = false;
+ break;
+ }
+
writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
+
+ if (do_complete)
+ complete(&mb1_transfer.work);
+
return false;
}
@@ -652,7 +1183,22 @@ static bool read_mailbox_2(void)
static bool read_mailbox_3(void)
{
- writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
+ u8 header;
+
+ header = readb(PRCM_ACK_MB3_HEADER);
+ mb3_transfer.ack.header = header;
+ switch (header) {
+ case MB3H_REFCLK_REQUEST:
+ mb3_transfer.ack.status = readb(PRCM_ACK_MB3_REFCLK_REQ);
+ writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
+ complete(&mb3_transfer.sysclk_work);
+ break;
+ default:
+ writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
+ pr_err("prcmu: wrong MB3 header\n");
+ break;
+ }
+
return false;
}
@@ -733,23 +1279,171 @@ static irqreturn_t prcmu_irq_thread_fn(int irq, void *data)
return IRQ_HANDLED;
}
+static void prcmu_mask_work(struct work_struct *work)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ config_wakeups();
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+}
+
+static void prcmu_irq_mask(struct irq_data *d)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
+
+ mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->irq - IRQ_DB5500_PRCMU_BASE];
+
+ spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
+ schedule_work(&mb0_transfer.mask_work);
+}
+
+static void prcmu_irq_unmask(struct irq_data *d)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
+
+ mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->irq - IRQ_DB5500_PRCMU_BASE];
+
+ spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
+ schedule_work(&mb0_transfer.mask_work);
+}
+
+static void noop(struct irq_data *d)
+{
+}
+
+static struct irq_chip prcmu_irq_chip = {
+ .name = "prcmu",
+ .irq_disable = prcmu_irq_mask,
+ .irq_ack = noop,
+ .irq_mask = prcmu_irq_mask,
+ .irq_unmask = prcmu_irq_unmask,
+};
+
void __init db5500_prcmu_early_init(void)
{
+ unsigned int i;
+
tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE);
spin_lock_init(&mb0_transfer.lock);
+ spin_lock_init(&mb0_transfer.dbb_irqs_lock);
+ mutex_init(&mb1_transfer.lock);
+ init_completion(&mb1_transfer.work);
mutex_init(&mb2_transfer.lock);
- mutex_init(&mb5_transfer.lock);
init_completion(&mb2_transfer.work);
+ mutex_init(&mb3_transfer.sysclk_lock);
+ init_completion(&mb3_transfer.sysclk_work);
+ mutex_init(&mb5_transfer.lock);
init_completion(&mb5_transfer.work);
+
+ INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
+
+ /* Initalize irqs. */
+ for (i = 0; i < NUM_DB5500_PRCMU_WAKEUPS; i++) {
+ unsigned int irq;
+
+ irq = IRQ_DB5500_PRCMU_BASE + i;
+ irq_set_chip_and_handler(irq, &prcmu_irq_chip,
+ handle_simple_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
}
+/*
+ * Power domain switches (ePODs) modeled as regulators for the DB5500 SoC
+ */
+static struct regulator_consumer_supply db5500_vape_consumers[] = {
+ REGULATOR_SUPPLY("v-ape", NULL),
+ REGULATOR_SUPPLY("v-i2c", "nmk-i2c.0"),
+ REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"),
+ REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"),
+ REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"),
+ REGULATOR_SUPPLY("v-mmc", "sdi0"),
+ REGULATOR_SUPPLY("v-mmc", "sdi1"),
+ REGULATOR_SUPPLY("v-mmc", "sdi2"),
+ REGULATOR_SUPPLY("v-mmc", "sdi3"),
+ REGULATOR_SUPPLY("v-mmc", "sdi4"),
+ REGULATOR_SUPPLY("v-uart", "uart0"),
+ REGULATOR_SUPPLY("v-uart", "uart1"),
+ REGULATOR_SUPPLY("v-uart", "uart2"),
+ REGULATOR_SUPPLY("v-uart", "uart3"),
+};
+
+static struct regulator_consumer_supply db5500_sga_consumers[] = {
+ REGULATOR_SUPPLY("debug", "reg-virt-consumer.0"),
+ REGULATOR_SUPPLY("v-mali", NULL),
+};
+
+static struct regulator_consumer_supply db5500_hva_consumers[] = {
+ REGULATOR_SUPPLY("debug", "reg-virt-consumer.1"),
+ REGULATOR_SUPPLY("v-hva", NULL),
+};
+
+static struct regulator_consumer_supply db5500_sia_consumers[] = {
+ REGULATOR_SUPPLY("debug", "reg-virt-consumer.2"),
+ REGULATOR_SUPPLY("v-sia", "mmio_camera"),
+};
+
+static struct regulator_consumer_supply db5500_disp_consumers[] = {
+ REGULATOR_SUPPLY("debug", "reg-virt-consumer.3"),
+ REGULATOR_SUPPLY("vsupply", "b2r2_bus"),
+ REGULATOR_SUPPLY("vsupply", "mcde"),
+};
+
+static struct regulator_consumer_supply db5500_esram12_consumers[] = {
+ REGULATOR_SUPPLY("debug", "reg-virt-consumer.4"),
+ REGULATOR_SUPPLY("v-esram12", "mcde"),
+ REGULATOR_SUPPLY("esram12", "cm_control"),
+};
+
+#define DB5500_REGULATOR_SWITCH(lower, upper) \
+[DB5500_REGULATOR_SWITCH_##upper] = { \
+ .constraints = { \
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \
+ }, \
+ .consumer_supplies = db5500_##lower##_consumers, \
+ .num_consumer_supplies = ARRAY_SIZE(db5500_##lower##_consumers),\
+}
+
+static struct regulator_init_data db5500_regulators[DB5500_NUM_REGULATORS] = {
+ [DB5500_REGULATOR_VAPE] = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = db5500_vape_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(db5500_vape_consumers),
+ },
+ DB5500_REGULATOR_SWITCH(sga, SGA),
+ DB5500_REGULATOR_SWITCH(hva, HVA),
+ DB5500_REGULATOR_SWITCH(sia, SIA),
+ DB5500_REGULATOR_SWITCH(disp, DISP),
+ DB5500_REGULATOR_SWITCH(esram12, ESRAM12),
+};
+
+static struct mfd_cell db5500_prcmu_devs[] = {
+ {
+ .name = "db5500-prcmu-regulators",
+ .platform_data = &db5500_regulators,
+ .pdata_size = sizeof(db5500_regulators),
+ },
+ {
+ .name = "cpufreq-u5500",
+ },
+};
+
/**
* prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
*
*/
-int __init db5500_prcmu_init(void)
+static int __init db5500_prcmu_probe(struct platform_device *pdev)
{
- int r = 0;
+ int err = 0;
if (ux500_is_svp() || !cpu_is_u5500())
return -ENODEV;
@@ -757,13 +1451,38 @@ int __init db5500_prcmu_init(void)
/* Clean up the mailbox interrupts after pre-kernel code. */
writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
- r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
- prcmu_irq_thread_fn, 0, "prcmu", NULL);
- if (r < 0) {
+ err = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
+ prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
+ if (err < 0) {
pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n");
- return -EBUSY;
+ err = -EBUSY;
+ goto no_irq_return;
}
- return 0;
+
+ err = mfd_add_devices(&pdev->dev, 0, db5500_prcmu_devs,
+ ARRAY_SIZE(db5500_prcmu_devs), NULL,
+ 0);
+
+ if (err)
+ pr_err("prcmu: Failed to add subdevices\n");
+ else
+ pr_info("DB5500 PRCMU initialized\n");
+
+no_irq_return:
+ return err;
+
+}
+
+static struct platform_driver db5500_prcmu_driver = {
+ .driver = {
+ .name = "db5500-prcmu",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init db5500_prcmu_init(void)
+{
+ return platform_driver_probe(&db5500_prcmu_driver, db5500_prcmu_probe);
}
arch_initcall(db5500_prcmu_init);
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 5a1283d1a83..a2926a9cc05 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -185,6 +185,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)
@@ -197,6 +202,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)
@@ -527,7 +539,7 @@ static struct {
} prcmu_version;
-int prcmu_enable_dsipll(void)
+int db8500_prcmu_enable_dsipll(void)
{
int i;
unsigned int plldsifreq;
@@ -562,7 +574,7 @@ int prcmu_enable_dsipll(void)
return 0;
}
-int prcmu_disable_dsipll(void)
+int db8500_prcmu_disable_dsipll(void)
{
/* Disable dsi pll */
writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
@@ -571,7 +583,7 @@ int prcmu_disable_dsipll(void)
return 0;
}
-int prcmu_set_display_clocks(void)
+int db8500_prcmu_set_display_clocks(void)
{
unsigned long flags;
unsigned int dsiclk;
@@ -832,7 +844,7 @@ void db8500_prcmu_enable_wakeups(u32 wakeups)
spin_unlock_irqrestore(&mb0_transfer.lock, flags);
}
-void prcmu_config_abb_event_readout(u32 abb_events)
+void db8500_prcmu_config_abb_event_readout(u32 abb_events)
{
unsigned long flags;
@@ -844,7 +856,7 @@ void prcmu_config_abb_event_readout(u32 abb_events)
spin_unlock_irqrestore(&mb0_transfer.lock, flags);
}
-void prcmu_get_abb_event_buffer(void __iomem **buf)
+void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
{
if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
*buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500);
@@ -853,13 +865,13 @@ void prcmu_get_abb_event_buffer(void __iomem **buf)
}
/**
- * prcmu_set_arm_opp - set the appropriate ARM OPP
+ * db8500_prcmu_set_arm_opp - set the appropriate ARM OPP
* @opp: The new ARM operating point to which transition is to be made
* Returns: 0 on success, non-zero on failure
*
* This function sets the the operating point of the ARM.
*/
-int prcmu_set_arm_opp(u8 opp)
+int db8500_prcmu_set_arm_opp(u8 opp)
{
int r;
@@ -890,11 +902,11 @@ int prcmu_set_arm_opp(u8 opp)
}
/**
- * prcmu_get_arm_opp - get the current ARM OPP
+ * db8500_prcmu_get_arm_opp - get the current ARM OPP
*
* Returns: the current ARM OPP
*/
-int prcmu_get_arm_opp(void)
+int db8500_prcmu_get_arm_opp(void)
{
return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
}
@@ -1438,7 +1450,7 @@ int db8500_prcmu_request_clock(u8 clock, bool enable)
return -EINVAL;
}
-int prcmu_config_esram0_deep_sleep(u8 state)
+int db8500_prcmu_config_esram0_deep_sleep(u8 state)
{
if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) ||
(state < ESRAM0_DEEP_SLEEP_STATE_OFF))
@@ -1534,6 +1546,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(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), 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.
@@ -1664,6 +1748,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
void prcmu_ac_wake_req(void)
{
u32 val;
+ u32 status;
mutex_lock(&mb0_transfer.ac_wake_lock);
@@ -1673,11 +1758,34 @@ void prcmu_ac_wake_req(void)
atomic_set(&ac_wake_req_state, 1);
+retry:
writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), PRCM_HOSTACCESS_REQ);
if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
- msecs_to_jiffies(20000))) {
- pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ msecs_to_jiffies(5000))) {
+ panic("prcmu: %s timed out (5 s) waiting for a reply.\n",
+ __func__);
+ goto unlock_and_return;
+ }
+
+ /*
+ * The modem can generate an AC_WAKE_ACK, and then still go to sleep.
+ * As a workaround, we wait, and then check that the modem is indeed
+ * awake (in terms of the value of the PRCM_MOD_AWAKE_STATUS
+ * register, which may not be the whole truth).
+ */
+ udelay(400);
+ status = (readl(PRCM_MOD_AWAKE_STATUS) & BITS(0, 2));
+ if (status != (PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE |
+ PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE)) {
+ pr_err("prcmu: %s received ack, but modem not awake (0x%X).\n",
+ __func__, status);
+ udelay(1200);
+ writel(val, PRCM_HOSTACCESS_REQ);
+ if (wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
+ msecs_to_jiffies(5000)))
+ goto retry;
+ panic("prcmu: %s timed out (5 s) waiting for AC_SLEEP_ACK.\n",
__func__);
}
@@ -1702,8 +1810,8 @@ void prcmu_ac_sleep_req()
PRCM_HOSTACCESS_REQ);
if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
- msecs_to_jiffies(20000))) {
- pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ msecs_to_jiffies(5000))) {
+ panic("prcmu: %s timed out (5 s) waiting for a reply.\n",
__func__);
}
@@ -1713,7 +1821,7 @@ unlock_and_return:
mutex_unlock(&mb0_transfer.ac_wake_lock);
}
-bool prcmu_is_ac_wake_requested(void)
+bool db8500_prcmu_is_ac_wake_requested(void)
{
return (atomic_read(&ac_wake_req_state) != 0);
}
@@ -1731,12 +1839,12 @@ void db8500_prcmu_system_reset(u16 reset_code)
}
/**
- * prcmu_get_reset_code - Retrieve SW reset reason code
+ * db8500_prcmu_get_reset_code - Retrieve SW reset reason code
*
* Retrieves the reset reason code stored by prcmu_system_reset() before
* last restart.
*/
-u16 prcmu_get_reset_code(void)
+u16 db8500_prcmu_get_reset_code(void)
{
return readw(tcdm_base + PRCM_SW_RST_REASON);
}
@@ -1861,6 +1969,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);
@@ -1986,7 +2099,7 @@ static struct irq_chip prcmu_irq_chip = {
.irq_unmask = prcmu_irq_unmask,
};
-void __init prcmu_early_init(void)
+void __init db8500_prcmu_early_init(void)
{
unsigned int i;
diff --git a/drivers/regulator/db5500-prcmu.c b/drivers/regulator/db5500-prcmu.c
index a6884ca8942..d52f459fc3c 100644
--- a/drivers/regulator/db5500-prcmu.c
+++ b/drivers/regulator/db5500-prcmu.c
@@ -102,22 +102,28 @@ static struct regulator_ops db5500_regulator_ops = {
static bool epod_on[NUM_EPOD_ID];
static bool epod_ramret[NUM_EPOD_ID];
+static inline int epod_id_to_index(u16 epod_id)
+{
+ return epod_id - DB5500_EPOD_ID_BASE;
+}
+
static int enable_epod(u16 epod_id, bool ramret)
{
+ int idx = epod_id_to_index(epod_id);
int ret;
if (ramret) {
- if (!epod_on[epod_id]) {
+ if (!epod_on[idx]) {
ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
if (ret < 0)
return ret;
}
- epod_ramret[epod_id] = true;
+ epod_ramret[idx] = true;
} else {
ret = prcmu_set_epod(epod_id, EPOD_STATE_ON);
if (ret < 0)
return ret;
- epod_on[epod_id] = true;
+ epod_on[idx] = true;
}
return 0;
@@ -125,17 +131,18 @@ static int enable_epod(u16 epod_id, bool ramret)
static int disable_epod(u16 epod_id, bool ramret)
{
+ int idx = epod_id_to_index(epod_id);
int ret;
if (ramret) {
- if (!epod_on[epod_id]) {
+ if (!epod_on[idx]) {
ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
if (ret < 0)
return ret;
}
- epod_ramret[epod_id] = false;
+ epod_ramret[idx] = false;
} else {
- if (epod_ramret[epod_id]) {
+ if (epod_ramret[idx]) {
ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
if (ret < 0)
return ret;
@@ -144,7 +151,7 @@ static int disable_epod(u16 epod_id, bool ramret)
if (ret < 0)
return ret;
}
- epod_on[epod_id] = false;
+ epod_on[idx] = false;
}
return 0;
@@ -224,11 +231,11 @@ static struct regulator_ops db5500_regulator_switch_ops = {
/*
* Regulator information
*/
-#define U5500_REGULATOR_SWITCH(_name, reg) \
- [U5500_REGULATOR_SWITCH_##reg] = { \
+#define DB5500_REGULATOR_SWITCH(_name, reg) \
+ [DB5500_REGULATOR_SWITCH_##reg] = { \
.desc = { \
.name = _name, \
- .id = U5500_REGULATOR_SWITCH_##reg, \
+ .id = DB5500_REGULATOR_SWITCH_##reg, \
.ops = &db5500_regulator_switch_ops, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
@@ -237,21 +244,21 @@ static struct regulator_ops db5500_regulator_switch_ops = {
}
static struct db5500_regulator_info
- db5500_regulator_info[U5500_NUM_REGULATORS] = {
- [U5500_REGULATOR_VAPE] = {
+ db5500_regulator_info[DB5500_NUM_REGULATORS] = {
+ [DB5500_REGULATOR_VAPE] = {
.desc = {
.name = "db5500-vape",
- .id = U5500_REGULATOR_VAPE,
+ .id = DB5500_REGULATOR_VAPE,
.ops = &db5500_regulator_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
},
},
- U5500_REGULATOR_SWITCH("u5500-sga", SGA),
- U5500_REGULATOR_SWITCH("u5500-hva", HVA),
- U5500_REGULATOR_SWITCH("u5500-sia", SIA),
- U5500_REGULATOR_SWITCH("u5500-disp", DISP),
- U5500_REGULATOR_SWITCH("u5500-esram12", ESRAM12),
+ DB5500_REGULATOR_SWITCH("db5500-sga", SGA),
+ DB5500_REGULATOR_SWITCH("db5500-hva", HVA),
+ DB5500_REGULATOR_SWITCH("db5500-sia", SIA),
+ DB5500_REGULATOR_SWITCH("db5500-disp", DISP),
+ DB5500_REGULATOR_SWITCH("db5500-esram12", ESRAM12),
};
static int __devinit db5500_regulator_probe(struct platform_device *pdev)
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
index 3df5fcd454a..1ee6f6a7c4a 100644
--- a/drivers/regulator/dbx500-prcmu.c
+++ b/drivers/regulator/dbx500-prcmu.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/regulator/driver.h>
+#include <linux/regulator/dbx500-prcmu.h>
/*
* power state reference count
diff --git a/include/linux/mfd/db5500-prcmu.h b/include/linux/mfd/db5500-prcmu.h
index 5be46a7157b..9890687f582 100644
--- a/include/linux/mfd/db5500-prcmu.h
+++ b/include/linux/mfd/db5500-prcmu.h
@@ -5,35 +5,36 @@
*
* U5500 PRCMU API.
*/
-#ifndef __MACH_PRCMU_U5500_H
-#define __MACH_PRCMU_U5500_H
+#ifndef __MFD_DB5500_PRCMU_H
+#define __MFD_DB5500_PRCMU_H
-#ifdef CONFIG_UX500_SOC_DB5500
+#ifdef CONFIG_MFD_DB5500_PRCMU
void db5500_prcmu_early_init(void);
int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state);
+int db5500_prcmu_set_display_clocks(void);
+int db5500_prcmu_disable_dsipll(void);
+int db5500_prcmu_enable_dsipll(void);
int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
void db5500_prcmu_enable_wakeups(u32 wakeups);
-
int db5500_prcmu_request_clock(u8 clock, bool enable);
-
+void db5500_prcmu_config_abb_event_readout(u32 abb_events);
+void db5500_prcmu_get_abb_event_buffer(void __iomem **buf);
int prcmu_resetout(u8 resoutn, u8 state);
-
-static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
- bool keep_ap_pll)
-{
- return 0;
-}
-
-static inline void db5500_prcmu_system_reset(u16 reset_code) {}
+int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+ bool keep_ap_pll);
+int db5500_prcmu_config_esram0_deep_sleep(u8 state);
+void db5500_prcmu_system_reset(u16 reset_code);
+u16 db5500_prcmu_get_reset_code(void);
+bool db5500_prcmu_is_ac_wake_requested(void);
+int db5500_prcmu_set_arm_opp(u8 opp);
+int db5500_prcmu_get_arm_opp(void);
#else /* !CONFIG_UX500_SOC_DB5500 */
static inline void db5500_prcmu_early_init(void) {}
-static inline void db5500_prcmu_system_reset(u16 reset_code) {}
-
static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
{
return -ENOSYS;
@@ -49,7 +50,13 @@ static inline int db5500_prcmu_request_clock(u8 clock, bool enable)
return 0;
}
+static inline int db5500_prcmu_set_display_clocks(void)
+{
+ return 0;
+}
+static inline int db5500_prcmu_disable_dsipll(void)
+{
return 0;
}
@@ -65,31 +72,48 @@ static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state)
static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {}
+static inline int prcmu_resetout(u8 resoutn, u8 state)
+{
+ return 0;
+}
+
static inline int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state)
{
return 0;
}
+static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
+static inline void db5500_prcmu_config_abb_event_readout(u32 abb_events) {}
+
static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
bool keep_ap_pll)
{
return 0;
}
-static inline int prcmu_resetout(u8 resoutn, u8 state)
+static inline void db5500_prcmu_system_reset(u16 reset_code) {}
+
+static inline u16 db5500_prcmu_get_reset_code(void)
{
return 0;
}
-#endif /* CONFIG_UX500_SOC_DB5500 */
+static inline bool db5500_prcmu_is_ac_wake_requested(void)
+{
+ return 0;
+}
+
+static inline int db5500_prcmu_set_arm_opp(u8 opp)
+{
+ return 0;
+}
-static inline int db5500_prcmu_config_abb_event_readout(u32 abb_events)
+static inline int db5500_prcmu_get_arm_opp(void)
{
-#ifdef CONFIG_MACH_U5500_SIMULATOR
return 0;
-#else
- return -1;
-#endif
}
-#endif /* __MACH_PRCMU_U5500_H */
+
+#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 a03b51e991a..60d27f7bfc1 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -145,20 +145,6 @@ enum ap_pwrst_trans {
};
/**
- * enum ddr_pwrst - DDR power states definition
- * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
- * @DDR_PWR_STATE_ON:
- * @DDR_PWR_STATE_OFFLOWLAT:
- * @DDR_PWR_STATE_OFFHIGHLAT:
- */
-enum ddr_pwrst {
- DDR_PWR_STATE_UNCHANGED = 0x00,
- DDR_PWR_STATE_ON = 0x01,
- DDR_PWR_STATE_OFFLOWLAT = 0x02,
- DDR_PWR_STATE_OFFHIGHLAT = 0x03
-};
-
-/**
* enum hw_acc_state - State definition for hardware accelerator
* @HW_NO_CHANGE: The hardware accelerator state must remain unchanged
* @HW_OFF: The hardware accelerator must be switched off
@@ -507,30 +493,12 @@ struct prcmu_auto_pm_config {
u8 sva_policy;
};
-/*
- * Definitions for controlling ESRAM0 in deep sleep.
- */
-#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
-#define ESRAM0_DEEP_SLEEP_STATE_RET 2
-
-#ifdef CONFIG_MFD_DB8500_PRCMU
-void __init prcmu_early_init(void);
-int prcmu_set_display_clocks(void);
-int prcmu_disable_dsipll(void);
-int prcmu_enable_dsipll(void);
-#else
-static inline void __init prcmu_early_init(void) {}
-#endif
-
#ifdef CONFIG_MFD_DB8500_PRCMU
+void db8500_prcmu_early_init(void);
int prcmu_set_rc_a2p(enum romcode_write);
enum romcode_read prcmu_get_rc_p2a(void);
enum ap_pwrst prcmu_get_xp70_current_state(void);
-void prcmu_config_abb_event_readout(u32 abb_events);
-void prcmu_get_abb_event_buffer(void __iomem **buf);
-int prcmu_set_arm_opp(u8 opp);
-int prcmu_get_arm_opp(void);
bool prcmu_has_arm_maxopp(void);
bool prcmu_is_u8400(void);
int prcmu_set_ape_opp(u8 opp);
@@ -539,8 +507,6 @@ int prcmu_request_ape_opp_100_voltage(bool enable);
int prcmu_release_usb_wakeup_state(void);
int prcmu_set_ddr_opp(u8 opp);
int prcmu_get_ddr_opp(void);
-unsigned long prcmu_qos_get_cpufreq_opp_delay(void);
-void prcmu_qos_set_cpufreq_opp_delay(unsigned long);
/* NOTE! Use regulator framework instead */
int prcmu_set_hwacc(u16 hw_acc_dev, u8 state);
void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
@@ -549,7 +515,6 @@ bool prcmu_is_auto_pm_enabled(void);
int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
int prcmu_set_clock_divider(u8 clock, u8 divider);
-int prcmu_config_esram0_deep_sleep(u8 state);
int prcmu_config_hotdog(u8 threshold);
int prcmu_config_hotmon(u8 low, u8 high);
int prcmu_start_temp_sense(u16 cycles32k);
@@ -560,18 +525,35 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
void prcmu_ac_wake_req(void);
void prcmu_ac_sleep_req(void);
void prcmu_modem_reset(void);
-bool prcmu_is_ac_wake_requested(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);
void db8500_prcmu_enable_wakeups(u32 wakeups);
int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state);
int db8500_prcmu_request_clock(u8 clock, bool enable);
+int db8500_prcmu_set_display_clocks(void);
+int db8500_prcmu_disable_dsipll(void);
+int db8500_prcmu_enable_dsipll(void);
+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);
+bool db8500_prcmu_is_ac_wake_requested(void);
+int db8500_prcmu_set_arm_opp(u8 opp);
+int db8500_prcmu_get_arm_opp(void);
#else /* !CONFIG_MFD_DB8500_PRCMU */
+static inline void db8500_prcmu_early_init(void) {}
+
static inline int prcmu_set_rc_a2p(enum romcode_write code)
{
return 0;
@@ -587,20 +569,6 @@ static inline enum ap_pwrst prcmu_get_xp70_current_state(void)
return AP_EXECUTE;
}
-static inline void prcmu_disable_wakeups(void) {}
-
-static inline void prcmu_config_abb_event_readout(u32 abb_events) {}
-
-static inline int prcmu_set_arm_opp(u8 opp)
-{
- return 0;
-}
-
-static inline int prcmu_get_arm_opp(void)
-{
- return ARM_100_OPP;
-}
-
static inline bool prcmu_has_arm_maxopp(void)
{
return false;
@@ -641,13 +609,6 @@ static inline int prcmu_get_ddr_opp(void)
return DDR_100_OPP;
}
-static inline unsigned long prcmu_qos_get_cpufreq_opp_delay(void)
-{
- return 0;
-}
-
-static inline void prcmu_qos_set_cpufreq_opp_delay(unsigned long n) {}
-
static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state)
{
return 0;
@@ -673,11 +634,6 @@ static inline int prcmu_set_clock_divider(u8 clock, u8 divider)
return 0;
}
-int prcmu_config_esram0_deep_sleep(u8 state)
-{
- return 0;
-}
-
static inline int prcmu_config_hotdog(u8 threshold)
{
return 0;
@@ -714,54 +670,101 @@ static inline void prcmu_ac_sleep_req(void) {}
static inline void prcmu_modem_reset(void) {}
-static inline bool prcmu_is_ac_wake_requested(void)
+static inline int prcmu_enable_spi2(void)
{
- return false;
+ return 0;
}
-#ifndef CONFIG_UX500_SOC_DB5500
-static inline int prcmu_set_display_clocks(void)
+static inline int prcmu_disable_spi2(void)
{
return 0;
}
-static inline int prcmu_disable_dsipll(void)
+static inline void db8500_prcmu_system_reset(u16 reset_code) {}
+
+static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+ bool keep_ap_pll)
{
return 0;
}
-static inline int prcmu_enable_dsipll(void)
+static inline void db8500_prcmu_enable_wakeups(u32 wakeups) {}
+
+static inline int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
{
return 0;
}
-#endif
-static inline int prcmu_enable_spi2(void)
+static inline int db8500_prcmu_request_clock(u8 clock, bool enable)
{
return 0;
}
-static inline int prcmu_disable_spi2(void)
+static inline int db8500_prcmu_set_display_clocks(void)
{
return 0;
}
-static inline void db8500_prcmu_system_reset(u16 reset_code) {}
+static inline int db8500_prcmu_disable_dsipll(void)
+{
+ return 0;
+}
-static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
- bool keep_ap_pll)
+static inline int db8500_prcmu_enable_dsipll(void)
{
return 0;
}
-static inline void db8500_prcmu_enable_wakeups(u32 wakeups) {}
+static inline int db8500_prcmu_config_esram0_deep_sleep(u8 state)
+{
+ return 0;
+}
-static inline int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
+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 u16 db8500_prcmu_get_reset_code(void)
{
return 0;
}
-static inline int db8500_prcmu_request_clock(u8 clock, bool enable)
+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;
+}
+
+static inline bool db8500_prcmu_is_ac_wake_requested(void)
+{
+ return 0;
+}
+
+static inline int db8500_prcmu_set_arm_opp(u8 opp)
+{
+ return 0;
+}
+
+static inline int db8500_prcmu_get_arm_opp(void)
{
return 0;
}
diff --git a/include/linux/regulator/db5500-prcmu.h b/include/linux/regulator/db5500-prcmu.h
index 52950287c09..fee68795867 100644
--- a/include/linux/regulator/db5500-prcmu.h
+++ b/include/linux/regulator/db5500-prcmu.h
@@ -15,13 +15,13 @@
/* Number of DB5500 regulators and regulator enumeration */
enum db5500_regulator_id {
- U5500_REGULATOR_VAPE,
- U5500_REGULATOR_SWITCH_SGA,
- U5500_REGULATOR_SWITCH_HVA,
- U5500_REGULATOR_SWITCH_SIA,
- U5500_REGULATOR_SWITCH_DISP,
- U5500_REGULATOR_SWITCH_ESRAM12,
- U5500_NUM_REGULATORS
+ DB5500_REGULATOR_VAPE,
+ DB5500_REGULATOR_SWITCH_SGA,
+ DB5500_REGULATOR_SWITCH_HVA,
+ DB5500_REGULATOR_SWITCH_SIA,
+ DB5500_REGULATOR_SWITCH_DISP,
+ DB5500_REGULATOR_SWITCH_ESRAM12,
+ DB5500_NUM_REGULATORS
};
#endif