diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-07-05 14:40:21 +0200 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-10-05 12:16:58 +0200 |
commit | ab308528c924d33fe34d14c8cbf50f8ed6a3a380 (patch) | |
tree | 7eadc2bf1b1ff9bf4c943bd9fc558bb25a74b55b | |
parent | a60dd09403b6289b760fa39dcf5318c9fad80654 (diff) |
ux500: fix PRCMU boot problem, use new MFD driver & code cleanup
Signed-off-by: Philippe Langlais <philippe.langlais@linaro.org>
21 files changed, 848 insertions, 4445 deletions
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index b360330c9e0..2e7a2a4639b 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -101,7 +101,7 @@ static struct ab8500_gpio_platform_data ab8500_gpio_pdata = { * on value present in GpioSel1 to GpioSel6 and AlternatFunction * register. This is the array of 7 configuration settings. * One has to compile time decide these settings. Below is the - * explaination of these setting + * explanation of these setting * GpioSel1 = 0x0F => Pin GPIO1 (SysClkReq2) * Pin GPIO2 (SysClkReq3) * Pin GPIO3 (SysClkReq4) @@ -659,7 +659,6 @@ static struct platform_device *mop500_platform_devs[] __initdata = { #endif &ux500_cryp1_device, &mop500_gpio_keys_device, - &ab8500_device, #ifdef CONFIG_LEDS_PWM &ux500_leds_device, #endif @@ -878,7 +877,6 @@ static struct platform_device *snowball_platform_devs[] __initdata = { &snowball_led_dev, &snowball_key_dev, &snowball_sbnet_dev, - &ab8500_device, &snowball_gpio_wlan_vbat_regulator_device, &u8500_mcde_device, &u8500_b2r2_device, @@ -942,6 +940,8 @@ static void __init mop500_init_machine(void) mop500_uart_init(); mop500_wlan_init(); + platform_device_register(&ab8500_device); + i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); if (machine_is_hrefv60()) i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 679ec31ed32..17289c66107 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -17,7 +17,6 @@ #include <linux/gpio/nomadik.h> #include <linux/platform_device.h> #include <linux/io.h> -#include <linux/regulator/machine.h> #include <linux/sys_soc.h> #include <asm/mach/map.h> @@ -31,7 +30,6 @@ #include <mach/ste-dma40-db8500.h> #include "devices-db8500.h" -#include "regulator-db8500.h" /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_uart_io_desc[] __initdata = { @@ -138,242 +136,14 @@ static struct platform_device db8500_pmu_device = { .dev.platform_data = &db8500_pmu_platdata, }; -/* - * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC - */ - -static struct regulator_consumer_supply db8500_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"), - /* "v-mmc" changed to "vcore" in the mainline kernel */ - REGULATOR_SUPPLY("vcore", "sdi0"), - REGULATOR_SUPPLY("vcore", "sdi1"), - REGULATOR_SUPPLY("vcore", "sdi2"), - REGULATOR_SUPPLY("vcore", "sdi3"), - REGULATOR_SUPPLY("vcore", "sdi4"), - REGULATOR_SUPPLY("v-dma", "dma40.0"), - REGULATOR_SUPPLY("v-ape", "ab8500-usb.0"), - /* "v-uart" changed to "vcore" in the mainline kernel */ - REGULATOR_SUPPLY("vcore", "uart0"), - REGULATOR_SUPPLY("vcore", "uart1"), - REGULATOR_SUPPLY("vcore", "uart2"), - REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"), -}; - -static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { - REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), - /* AV8100 regulator */ - REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), -}; - -static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { - REGULATOR_SUPPLY("vsupply", "b2r2.0"), - REGULATOR_SUPPLY("vsupply", "mcde"), -}; - -/* SVA MMDSP regulator switch */ -static struct regulator_consumer_supply db8500_svammdsp_consumers[] = { - REGULATOR_SUPPLY("sva-mmdsp", "cm_control"), -}; - -/* SVA pipe regulator switch */ -static struct regulator_consumer_supply db8500_svapipe_consumers[] = { - REGULATOR_SUPPLY("sva-pipe", "cm_control"), -}; - -/* SIA MMDSP regulator switch */ -static struct regulator_consumer_supply db8500_siammdsp_consumers[] = { - REGULATOR_SUPPLY("sia-mmdsp", "cm_control"), -}; - -/* SIA pipe regulator switch */ -static struct regulator_consumer_supply db8500_siapipe_consumers[] = { - REGULATOR_SUPPLY("sia-pipe", "cm_control"), -}; - -static struct regulator_consumer_supply db8500_sga_consumers[] = { - REGULATOR_SUPPLY("v-mali", NULL), -}; - -/* ESRAM1 and 2 regulator switch */ -static struct regulator_consumer_supply db8500_esram12_consumers[] = { - REGULATOR_SUPPLY("esram12", "cm_control"), -}; - -/* ESRAM3 and 4 regulator switch */ -static struct regulator_consumer_supply db8500_esram34_consumers[] = { - REGULATOR_SUPPLY("v-esram34", "mcde"), - REGULATOR_SUPPLY("esram34", "cm_control"), -}; - -static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { - [DB8500_REGULATOR_VAPE] = { - .constraints = { - .name = "db8500-vape", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_vape_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers), - }, - [DB8500_REGULATOR_VARM] = { - .constraints = { - .name = "db8500-varm", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_VMODEM] = { - .constraints = { - .name = "db8500-vmodem", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_VPLL] = { - .constraints = { - .name = "db8500-vpll", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_VSMPS1] = { - .constraints = { - .name = "db8500-vsmps1", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_VSMPS2] = { - .constraints = { - .name = "db8500-vsmps2", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_vsmps2_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_vsmps2_consumers), - }, - [DB8500_REGULATOR_VSMPS3] = { - .constraints = { - .name = "db8500-vsmps3", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_VRF1] = { - .constraints = { - .name = "db8500-vrf1", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_SWITCH_SVAMMDSP] = { - .supply_regulator = "db8500-vape", - .constraints = { - .name = "db8500-sva-mmdsp", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_svammdsp_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers), - }, - [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { - .constraints = { - /* "ret" means "retention" */ - .name = "db8500-sva-mmdsp-ret", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_SWITCH_SVAPIPE] = { - .supply_regulator = "db8500-vape", - .constraints = { - .name = "db8500-sva-pipe", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_svapipe_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers), - }, - [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { - .supply_regulator = "db8500-vape", - .constraints = { - .name = "db8500-sia-mmdsp", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_siammdsp_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers), - }, - [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { - .constraints = { - .name = "db8500-sia-mmdsp-ret", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_SWITCH_SIAPIPE] = { - .supply_regulator = "db8500-vape", - .constraints = { - .name = "db8500-sia-pipe", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_siapipe_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers), - }, - [DB8500_REGULATOR_SWITCH_SGA] = { - .supply_regulator = "db8500-vape", - .constraints = { - .name = "db8500-sga", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_sga_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers), - - }, - [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { - .supply_regulator = "db8500-vape", - .constraints = { - .name = "db8500-b2r2-mcde", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_b2r2_mcde_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers), - }, - [DB8500_REGULATOR_SWITCH_ESRAM12] = { - .supply_regulator = "db8500-vape", - .constraints = { - .name = "db8500-esram12", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_esram12_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers), - }, - [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { - .constraints = { - .name = "db8500-esram12-ret", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, - [DB8500_REGULATOR_SWITCH_ESRAM34] = { - .supply_regulator = "db8500-vape", - .constraints = { - .name = "db8500-esram34", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - .consumer_supplies = db8500_esram34_consumers, - .num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers), - }, - [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { - .constraints = { - .name = "db8500-esram34-ret", - .valid_ops_mask = REGULATOR_CHANGE_STATUS, - }, - }, -}; - -static struct platform_device db8500_regulator_device = { - .name = "db8500-regulators", - .id = 0, - .dev = { - .platform_data = &db8500_regulators, - }, +static struct platform_device db8500_prcmu_device = { + .name = "db8500-prcmu", }; static struct platform_device *platform_devs[] __initdata = { &u8500_dma40_device, &db8500_pmu_device, - &db8500_regulator_device, + &db8500_prcmu_device, }; static resource_size_t __initdata db8500_gpio_base[] = { diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 7ad3861aa50..a9b01188dc4 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -8,8 +8,6 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/clk.h> -#include <linux/mfd/db8500-prcmu.h> -#include <linux/mfd/db5500-prcmu.h> #include <linux/delay.h> #include <asm/cacheflush.h> diff --git a/arch/arm/mach-ux500/include/mach/prcmu-db5500.h b/arch/arm/mach-ux500/include/mach/prcmu-db5500.h deleted file mode 100644 index 0d26f72230e..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-db5500.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * - * U5500 PRCMU API. - */ -#ifndef __MACH_PRCMU_U5500_H -#define __MACH_PRCMU_U5500_H - -#ifdef CONFIG_UX500_SOC_DB5500 - -void db5500_prcmu_early_init(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); - -int db5500_prcmu_request_clock(u8 clock, bool enable); - -int prcmu_resetout(u8 resoutn, u8 state); - -static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, - bool keep_ap_pll) -{ - return 0; -} - -static inline void prcmu_system_reset(u16 reset_code) {} - -#else /* !CONFIG_UX500_SOC_DB5500 */ - -static inline void db5500_prcmu_early_init(void) -{ -} - -static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) -{ - return -ENOSYS; -} - -static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) -{ - return -ENOSYS; -} - -static inline int prcmu_resetout(u8 resoutn, u8 state) -{ - return 0; -} - -#endif /* CONFIG_UX500_SOC_DB5500 */ - -static inline int db5500_prcmu_config_abb_event_readout(u32 abb_events) -{ -#ifdef CONFIG_MACH_U5500_SIMULATOR - return 0; -#else - return -1; -#endif -} - -#endif /* __MACH_PRCMU_U5500_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu-db8500.h b/arch/arm/mach-ux500/include/mach/prcmu-db8500.h deleted file mode 100644 index f5efd0d369c..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-db8500.h +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * - * U8500 specific PRCMU API. - */ -#ifndef __MACH_PRCMU_DB8500_H -#define __MACH_PRCMU_DB8500_H - -/* - * Definitions for autonomous power management configuration. - */ - -#define PRCMU_AUTO_PM_OFF 0 -#define PRCMU_AUTO_PM_ON 1 - -#define PRCMU_AUTO_PM_POWER_ON_HSEM BIT(0) -#define PRCMU_AUTO_PM_POWER_ON_ABB_FIFO_IT BIT(1) - -enum prcmu_auto_pm_policy { - PRCMU_AUTO_PM_POLICY_NO_CHANGE, - PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF, - PRCMU_AUTO_PM_POLICY_DSP_OFF_RAMRET_HWP_OFF, - PRCMU_AUTO_PM_POLICY_DSP_CLK_OFF_HWP_OFF, - PRCMU_AUTO_PM_POLICY_DSP_CLK_OFF_HWP_CLK_OFF, -}; - -/** - * struct prcmu_auto_pm_config - Autonomous power management configuration. - * @sia_auto_pm_enable: SIA autonomous pm enable. (PRCMU_AUTO_PM_{OFF,ON}) - * @sia_power_on: SIA power ON enable. (PRCMU_AUTO_PM_POWER_ON_* bitmask) - * @sia_policy: SIA power policy. (enum prcmu_auto_pm_policy) - * @sva_auto_pm_enable: SVA autonomous pm enable. (PRCMU_AUTO_PM_{OFF,ON}) - * @sva_power_on: SVA power ON enable. (PRCMU_AUTO_PM_POWER_ON_* bitmask) - * @sva_policy: SVA power policy. (enum prcmu_auto_pm_policy) - */ -struct prcmu_auto_pm_config { - u8 sia_auto_pm_enable; - u8 sia_power_on; - u8 sia_policy; - u8 sva_auto_pm_enable; - u8 sva_power_on; - u8 sva_policy; -}; - -/** - * enum hw_acc_dev - enum for hw accelerators - * @HW_ACC_SVAMMDSP: for SVAMMDSP - * @HW_ACC_SVAPIPE: for SVAPIPE - * @HW_ACC_SIAMMDSP: for SIAMMDSP - * @HW_ACC_SIAPIPE: for SIAPIPE - * @HW_ACC_SGA: for SGA - * @HW_ACC_B2R2: for B2R2 - * @HW_ACC_MCDE: for MCDE - * @HW_ACC_ESRAM1: for ESRAM1 - * @HW_ACC_ESRAM2: for ESRAM2 - * @HW_ACC_ESRAM3: for ESRAM3 - * @HW_ACC_ESRAM4: for ESRAM4 - * @NUM_HW_ACC: number of hardware accelerators - * - * Different hw accelerators which can be turned ON/ - * OFF or put into retention (MMDSPs and ESRAMs). - * Used with EPOD API. - * - * NOTE! Deprecated, to be removed when all users switched over to use the - * regulator API. - */ -enum hw_acc_dev{ - HW_ACC_SVAMMDSP, - HW_ACC_SVAPIPE, - HW_ACC_SIAMMDSP, - HW_ACC_SIAPIPE, - HW_ACC_SGA, - HW_ACC_B2R2, - HW_ACC_MCDE, - HW_ACC_ESRAM1, - HW_ACC_ESRAM2, - HW_ACC_ESRAM3, - HW_ACC_ESRAM4, - NUM_HW_ACC -}; - -/* - * 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 -}; - -/** - * 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 - * @HW_OFF_RAMRET: The hardware accelerator must be switched off with its - * internal RAM in retention - * @HW_ON: The hwa hardware accelerator hwa must be switched on - * - * NOTE! Deprecated, to be removed when all users switched over to use the - * regulator API. - */ -enum hw_acc_state { - HW_NO_CHANGE = 0x00, - HW_OFF = 0x01, - HW_OFF_RAMRET = 0x02, - HW_ON = 0x04 -}; - -/** - * enum romcode_write - Romcode message written by A9 AND read by XP70 - * @RDY_2_DS: Value set when ApDeepSleep state can be executed by XP70 - * @RDY_2_XP70_RST: Value set when 0x0F has been successfully polled by the - * romcode. The xp70 will go into self-reset - */ -enum romcode_write { - RDY_2_DS = 0x09, - RDY_2_XP70_RST = 0x10 -}; - -/** - * enum romcode_read - Romcode message written by XP70 and read by A9 - * @INIT: Init value when romcode field is not used - * @FS_2_DS: Value set when power state is going from ApExecute to - * ApDeepSleep - * @END_DS: Value set when ApDeepSleep power state is reached coming from - * ApExecute state - * @DS_TO_FS: Value set when power state is going from ApDeepSleep to - * ApExecute - * @END_FS: Value set when ApExecute power state is reached coming from - * ApDeepSleep state - * @SWR: Value set when power state is going to ApReset - * @END_SWR: Value set when the xp70 finished executing ApReset actions and - * waits for romcode acknowledgment to go to self-reset - */ -enum romcode_read { - INIT = 0x00, - FS_2_DS = 0x0A, - END_DS = 0x0B, - DS_TO_FS = 0x0C, - END_FS = 0x0D, - SWR = 0x0E, - END_SWR = 0x0F -}; - -/** - * enum ap_pwrst - current power states defined in PRCMU firmware - * @NO_PWRST: Current power state init - * @AP_BOOT: Current power state is apBoot - * @AP_EXECUTE: Current power state is apExecute - * @AP_DEEP_SLEEP: Current power state is apDeepSleep - * @AP_SLEEP: Current power state is apSleep - * @AP_IDLE: Current power state is apIdle - * @AP_RESET: Current power state is apReset - */ -enum ap_pwrst { - NO_PWRST = 0x00, - AP_BOOT = 0x01, - AP_EXECUTE = 0x02, - AP_DEEP_SLEEP = 0x03, - AP_SLEEP = 0x04, - AP_IDLE = 0x05, - AP_RESET = 0x06 -}; - -#ifdef CONFIG_UX500_SOC_DB8500 - -bool prcmu_is_u8400(void); - -int prcmu_request_ape_opp_100_voltage(bool enable); - -int prcmu_release_usb_wakeup_state(void); - -int prcmu_set_clock_divider(u8 clock, u8 divider); - -void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, - struct prcmu_auto_pm_config *idle); -bool prcmu_is_auto_pm_enabled(void); - -/* NOTE! Use regulator framework instead */ -int prcmu_set_hwacc(u16 hw_acc_dev, u8 state); - -/* TODO: Check if anyone is using these. */ -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); - -/* TODO: Common API with DB5500? */ -int prcmu_config_esram0_deep_sleep(u8 state); -bool prcmu_has_arm_maxopp(void); -void prcmu_config_abb_event_readout(u32 abb_events); -void prcmu_get_abb_event_buffer(void __iomem **buf); -int prcmu_config_hotdog(u8 threshold); -int prcmu_config_hotmon(u8 low, u8 high); -int prcmu_start_temp_sense(u16 cycles32k); -int prcmu_stop_temp_sense(void); -void prcmu_enable_spi2(void); -void prcmu_disable_spi2(void); - -#else /* !CONFIG_UX500_SOC_DB8500 */ - -static inline bool prcmu_is_u8400(void) -{ - return false; -} - -static inline int prcmu_request_ape_opp_100_voltage(bool enable) -{ - return 0; -} - -static inline int prcmu_release_usb_wakeup_state(void) -{ - return 0; -} - -static inline int prcmu_set_clock_divider(u8 clock, u8 divider) -{ - return 0; -} - -static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, - struct prcmu_auto_pm_config *idle) -{ -} - -static inline bool prcmu_is_auto_pm_enabled(void) -{ - return false; -} - -static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state) -{ - return 0; -} - -static inline int prcmu_set_rc_a2p(enum romcode_write code) -{ - return 0; -} - -static inline enum romcode_read prcmu_get_rc_p2a(void) -{ - return INIT; -} - -static inline enum ap_pwrst prcmu_get_xp70_current_state(void) -{ - return AP_EXECUTE; -} - -static inline int prcmu_config_esram0_deep_sleep(u8 state) -{ - return 0; -} - -static inline bool prcmu_has_arm_maxopp(void) -{ - return false; -} - -static inline void prcmu_config_abb_event_readout(u32 abb_events) {} - -static inline int prcmu_config_hotdog(u8 threshold) -{ - return 0; -} - -static inline int prcmu_config_hotmon(u8 low, u8 high) -{ - return 0; -} - -static inline int prcmu_start_temp_sense(u16 cycles32k) -{ - return 0; -} - -static inline int prcmu_stop_temp_sense(void) -{ - return 0; -} - -static inline int prcmu_enable_spi2(void) -{ - return 0; -} - -static inline int prcmu_disable_spi2(void) -{ - return 0; -} - -#endif /* CONFIG_UX500_SOC_DB8500 */ - -#endif /* __MACH_PRCMU_DB8500_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h b/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h deleted file mode 100644 index 7995ed1f77f..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> - * - * PRCMU f/w APIs - */ -#ifndef __MACH_PRCMU_FW_API_H -#define __MACH_PRCMU_FW_API_H - -#warning <mach/prcmu-fw-api.h> has been replaced by <mach/prcmu.h> -#include <mach/prcmu.h> - -#endif /* __MACH_PRCMU_FW_API_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu-qos.h b/arch/arm/mach-ux500/include/mach/prcmu-qos.h deleted file mode 100644 index 23bda305c5f..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-qos.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) ST Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - * - * PRCMU QoS - */ -#ifndef __MACH_PRCMU_QOS_H -#define __MACH_PRCMU_QOS_H - -#include <linux/notifier.h> - -/* PRCMU QoS APE OPP class */ -#define PRCMU_QOS_APE_OPP 1 -#define PRCMU_QOS_DDR_OPP 2 -#define PRCMU_QOS_DEFAULT_VALUE -1 - -#ifdef CONFIG_UX500_PRCMU_QOS_POWER - -unsigned long prcmu_qos_get_cpufreq_opp_delay(void); -void prcmu_qos_set_cpufreq_opp_delay(unsigned long); -void prcmu_qos_force_opp(int, s32); - -#else - -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 void prcmu_qos_force_opp(int prcmu_qos_class, s32 i) {} - -#endif - -#ifdef CONFIG_UX500_PRCMU_QOS_POWER - -int prcmu_qos_requirement(int pm_qos_class); -int prcmu_qos_add_requirement(int pm_qos_class, char *name, s32 value); -int prcmu_qos_update_requirement(int pm_qos_class, char *name, s32 new_value); -void prcmu_qos_remove_requirement(int pm_qos_class, char *name); -int prcmu_qos_add_notifier(int prcmu_qos_class, - struct notifier_block *notifier); -int prcmu_qos_remove_notifier(int prcmu_qos_class, - struct notifier_block *notifier); - -#else - -static inline int prcmu_qos_requirement(int prcmu_qos_class) -{ - return 0; -} - -static inline int prcmu_qos_add_requirement(int prcmu_qos_class, - char *name, s32 value) -{ - return 0; -} - -static inline int prcmu_qos_update_requirement(int prcmu_qos_class, - char *name, s32 new_value) -{ - return 0; -} - -static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name) -{ -} - -static inline int prcmu_qos_add_notifier(int prcmu_qos_class, - struct notifier_block *notifier) -{ - return 0; -} -static inline int prcmu_qos_remove_notifier(int prcmu_qos_class, - struct notifier_block *notifier) -{ - return 0; -} - -#endif - -#endif /* __MACH_PRCMU_QOS_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h index 9a8e9e4ddd3..121a5178f67 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h @@ -15,6 +15,39 @@ #include <mach/hardware.h> +#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) + +#define PRCM_SGACLK_MGT_OFF 0x014 +#define PRCM_UARTCLK_MGT_OFF 0x018 +#define PRCM_MSP02CLK_MGT_OFF 0x01C +#define PRCM_MSP1CLK_MGT_OFF 0x288 +#define PRCM_I2CCLK_MGT_OFF 0x020 +#define PRCM_SDMMCCLK_MGT_OFF 0x024 +#define PRCM_SLIMCLK_MGT_OFF 0x028 +#define PRCM_PER1CLK_MGT_OFF 0x02C +#define PRCM_PER2CLK_MGT_OFF 0x030 +#define PRCM_PER3CLK_MGT_OFF 0x034 +#define PRCM_PER5CLK_MGT_OFF 0x038 +#define PRCM_PER6CLK_MGT_OFF 0x03C +#define PRCM_PER7CLK_MGT_OFF 0x040 +#define PRCM_LCDCLK_MGT_OFF 0x044 +#define PRCM_BMLCLK_MGT_OFF 0x04C +#define PRCM_HSITXCLK_MGT_OFF 0x050 +#define PRCM_HSIRXCLK_MGT_OFF 0x054 +#define PRCM_HDMICLK_MGT_OFF 0x058 +#define PRCM_APEATCLK_MGT_OFF 0x05C +#define PRCM_APETRACECLK_MGT_OFF 0x060 +#define PRCM_MCDECLK_MGT_OFF 0x064 +#define PRCM_IPI2CCLK_MGT_OFF 0x068 +#define PRCM_DSIALTCLK_MGT_OFF 0x06C +#define PRCM_DMACLK_MGT_OFF 0x074 +#define PRCM_B2R2CLK_MGT_OFF 0x078 +#define PRCM_TVCLK_MGT_OFF 0x07C +#define PRCM_UNIPROCLK_MGT_OFF 0x278 +#define PRCM_SSPCLK_MGT_OFF 0x280 +#define PRCM_RNGCLK_MGT_OFF 0x284 +#define PRCM_UICCCLK_MGT_OFF 0x27C + #define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118) #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f #define PRCM_ARM_PLLDIVPS_MAX_MASK 0xf @@ -30,11 +63,15 @@ #define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON 0x100 #define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0) +#define PRCM_A9PL_FORCE_CLKEN (_PRCMU_BASE + 0x19C) #define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4) #define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0) #define PRCM_ARM_LS_CLAMP (_PRCMU_BASE + 0x30c) #define PRCM_SRAM_A9 (_PRCMU_BASE + 0x308) +#define PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN BIT(0) +#define PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN BIT(1) + /* ARM WFI Standby signal register */ #define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130) #define PRCM_IOCR (_PRCMU_BASE + 0x310) @@ -61,9 +98,10 @@ #define PRCM_ARMITVAL127TO96 (_PRCMU_BASE + 0x26C) #define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334) +#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ 0x1 #define ARM_WAKEUP_MODEM 0x1 -#define PRCM_ARM_IT1_CLEAR (_PRCMU_BASE + 0x48C) +#define PRCM_ARM_IT1_CLR (_PRCMU_BASE + 0x48C) #define PRCM_ARM_IT1_VAL (_PRCMU_BASE + 0x494) #define PRCM_HOLD_EVT (_PRCMU_BASE + 0x174) @@ -87,10 +125,10 @@ #define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) #define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) -#define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044) -#define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064) -#define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058) -#define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c) +#define PRCM_LCDCLK_MGT (_PRCMU_BASE + PRCM_LCDCLK_MGT_OFF) +#define PRCM_MCDECLK_MGT (_PRCMU_BASE + PRCM_MCDECLK_MGT_OFF) +#define PRCM_HDMICLK_MGT (_PRCMU_BASE + PRCM_HDMICLK_MGT_OFF) +#define PRCM_TVCLK_MGT (_PRCMU_BASE + PRCM_TVCLK_MGT_OFF) #define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) #define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) #define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) @@ -111,5 +149,34 @@ #define PRCM_GPIOCR_DBG_STM_MOD_CMD1 0x800 #define PRCM_GPIOCR_DBG_UARTMOD_CMD0 0x1 +/* PRCMU HW semaphore */ +#define PRCM_SEM (_PRCMU_BASE + 0x400) +#define PRCM_SEM_PRCM_SEM BIT(0) + +#define PRCM_TCR (_PRCMU_BASE + 0x1C8) +#define PRCM_TCR_TENSEL_MASK BITS(0, 7) +#define PRCM_TCR_STOP_TIMERS BIT(16) +#define PRCM_TCR_DOZE_MODE BIT(17) + +#define PRCM_CLKOCR_CLKODIV0_SHIFT 0 +#define PRCM_CLKOCR_CLKODIV0_MASK BITS(0, 5) +#define PRCM_CLKOCR_CLKOSEL0_SHIFT 6 +#define PRCM_CLKOCR_CLKOSEL0_MASK BITS(6, 8) +#define PRCM_CLKOCR_CLKODIV1_SHIFT 16 +#define PRCM_CLKOCR_CLKODIV1_MASK BITS(16, 21) +#define PRCM_CLKOCR_CLKOSEL1_SHIFT 22 +#define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24) +#define PRCM_CLKOCR_CLK1TYPE BIT(28) + +#define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) +#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) +#define PRCM_CLK_MGT_CLKEN BIT(8) + +/* GPIOCR register */ +#define PRCM_GPIOCR_SPI2_SELECT BIT(23) + +#define PRCM_DDR_SUBSYS_APE_MINBW (_PRCMU_BASE + 0x438) +#define PRCM_CGATING_BYPASS (_PRCMU_BASE + 0x134) +#define PRCM_CGATING_BYPASS_ICN2 BIT(6) #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 1c608c35f96..71d9dee80ce 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu.h +++ b/arch/arm/mach-ux500/include/mach/prcmu.h @@ -9,9 +9,8 @@ #define __MACH_PRCMU_H #include <linux/interrupt.h> -//#include <mach/prcmu-qos.h> +#include <linux/notifier.h> -#if 0 /* PRCMU Wakeup defines */ enum prcmu_wakeup_index { PRCMU_WAKEUP_INDEX_RTC, @@ -27,15 +26,6 @@ enum prcmu_wakeup_index { }; #define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name)) -/* Low power states */ -#define PRCMU_AP_NO_CHANGE 0x00 -#define PRCMU_AP_SLEEP 0x01 -#define PRCMU_AP_DEEP_SLEEP 0x04 -#define PRCMU_AP_IDLE 0x05 -#define PRCMU_AP_DEEP_IDLE 0x07 -/* Legacy names */ -#define APEXECUTE_TO_APSLEEP PRCMU_AP_SLEEP - /* EPOD (power domain) IDs */ /* @@ -201,13 +191,9 @@ enum ddr_opp { DDR_25_OPP = 0x02, }; -#endif - #include <linux/mfd/db8500-prcmu.h> #include <linux/mfd/db5500-prcmu.h> -#if 0 - #if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500) void __init prcmu_early_init(void); @@ -352,6 +338,68 @@ static inline int prcmu_enable_dsipll(void) #endif +/* PRCMU QoS APE OPP class */ +#define PRCMU_QOS_APE_OPP 1 +#define PRCMU_QOS_DDR_OPP 2 +#define PRCMU_QOS_DEFAULT_VALUE -1 + +#ifdef CONFIG_UX500_PRCMU_QOS_POWER + +unsigned long prcmu_qos_get_cpufreq_opp_delay(void); +void prcmu_qos_set_cpufreq_opp_delay(unsigned long); +void prcmu_qos_force_opp(int, s32); +int prcmu_qos_requirement(int pm_qos_class); +int prcmu_qos_add_requirement(int pm_qos_class, char *name, s32 value); +int prcmu_qos_update_requirement(int pm_qos_class, char *name, s32 new_value); +void prcmu_qos_remove_requirement(int pm_qos_class, char *name); +int prcmu_qos_add_notifier(int prcmu_qos_class, + struct notifier_block *notifier); +int prcmu_qos_remove_notifier(int prcmu_qos_class, + struct notifier_block *notifier); + +#else + +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 void prcmu_qos_force_opp(int prcmu_qos_class, s32 i) {} + +static inline int prcmu_qos_requirement(int prcmu_qos_class) +{ + return 0; +} + +static inline int prcmu_qos_add_requirement(int prcmu_qos_class, + char *name, s32 value) +{ + return 0; +} + +static inline int prcmu_qos_update_requirement(int prcmu_qos_class, + char *name, s32 new_value) +{ + return 0; +} + +static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name) +{ +} + +static inline int prcmu_qos_add_notifier(int prcmu_qos_class, + struct notifier_block *notifier) +{ + return 0; +} +static inline int prcmu_qos_remove_notifier(int prcmu_qos_class, + struct notifier_block *notifier) +{ + return 0; +} + #endif #endif /* __MACH_PRCMU_H */ diff --git a/arch/arm/mach-ux500/prcmu-db5500.c b/arch/arm/mach-ux500/prcmu-db5500.c deleted file mode 100644 index fc6814f9196..00000000000 --- a/arch/arm/mach-ux500/prcmu-db5500.c +++ /dev/null @@ -1,773 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> - * - * U5500 PRCM Unit interface driver - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/completion.h> -#include <linux/irq.h> -#include <linux/jiffies.h> -#include <linux/bitops.h> -#include <linux/interrupt.h> - -#include <mach/hardware.h> -#include <mach/irqs.h> -#include <mach/prcmu.h> -#include <mach/db5500-regs.h> - -#include "prcmu-regs-db5500.h" - -#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) -#define PRCM_REQ_MB2_HEADER (_PRCM_MB_HEADER + 0x2) -#define PRCM_REQ_MB3_HEADER (_PRCM_MB_HEADER + 0x3) -#define PRCM_REQ_MB4_HEADER (_PRCM_MB_HEADER + 0x4) -#define PRCM_REQ_MB5_HEADER (_PRCM_MB_HEADER + 0x5) -#define PRCM_REQ_MB6_HEADER (_PRCM_MB_HEADER + 0x6) -#define PRCM_REQ_MB7_HEADER (_PRCM_MB_HEADER + 0x7) -#define PRCM_ACK_MB0_HEADER (_PRCM_MB_HEADER + 0x8) -#define PRCM_ACK_MB1_HEADER (_PRCM_MB_HEADER + 0x9) -#define PRCM_ACK_MB2_HEADER (_PRCM_MB_HEADER + 0xa) -#define PRCM_ACK_MB3_HEADER (_PRCM_MB_HEADER + 0xb) -#define PRCM_ACK_MB4_HEADER (_PRCM_MB_HEADER + 0xc) -#define PRCM_ACK_MB5_HEADER (_PRCM_MB_HEADER + 0xd) -#define PRCM_ACK_MB6_HEADER (_PRCM_MB_HEADER + 0xe) -#define PRCM_ACK_MB7_HEADER (_PRCM_MB_HEADER + 0xf) - -/* Req Mailboxes */ -#define PRCM_REQ_MB0 (tcdm_base + 0xFD8) -#define PRCM_REQ_MB1 (tcdm_base + 0xFCC) -#define PRCM_REQ_MB2 (tcdm_base + 0xFC4) -#define PRCM_REQ_MB3 (tcdm_base + 0xFC0) -#define PRCM_REQ_MB4 (tcdm_base + 0xF98) -#define PRCM_REQ_MB5 (tcdm_base + 0xF90) -#define PRCM_REQ_MB6 (tcdm_base + 0xF8C) -#define PRCM_REQ_MB7 (tcdm_base + 0xF84) - -/* Ack Mailboxes */ -#define PRCM_ACK_MB0 (tcdm_base + 0xF38) -#define PRCM_ACK_MB1 (tcdm_base + 0xF30) -#define PRCM_ACK_MB2 (tcdm_base + 0xF24) -#define PRCM_ACK_MB3 (tcdm_base + 0xF20) -#define PRCM_ACK_MB4 (tcdm_base + 0xF1C) -#define PRCM_ACK_MB5 (tcdm_base + 0xF14) -#define PRCM_ACK_MB6 (tcdm_base + 0xF0C) -#define PRCM_ACK_MB7 (tcdm_base + 0xF08) - -/* Mailbox 2 REQs */ -#define PRCM_REQ_MB2_EPOD_CLIENT (PRCM_REQ_MB2 + 0x0) -#define PRCM_REQ_MB2_EPOD_STATE (PRCM_REQ_MB2 + 0x1) -#define PRCM_REQ_MB2_CLK_CLIENT (PRCM_REQ_MB2 + 0x2) -#define PRCM_REQ_MB2_CLK_STATE (PRCM_REQ_MB2 + 0x3) -#define PRCM_REQ_MB2_PLL_CLIENT (PRCM_REQ_MB2 + 0x4) -#define PRCM_REQ_MB2_PLL_STATE (PRCM_REQ_MB2 + 0x5) - -/* Mailbox 2 ACKs */ -#define PRCM_ACK_MB2_EPOD_STATUS (PRCM_ACK_MB2 + 0x2) -#define PRCM_ACK_MB2_CLK_STATUS (PRCM_ACK_MB2 + 0x6) -#define PRCM_ACK_MB2_PLL_STATUS (PRCM_ACK_MB2 + 0xA) - -enum mb_return_code { - RC_SUCCESS, - RC_FAIL, -}; - -/* 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, -}; - -/* Mailbox 2 headers. */ -enum mb2_header { - MB2H_EPOD_REQUEST = 1, - MB2H_CLK_REQUEST, - MB2H_PLL_REQUEST, -}; - -/* Mailbox 5 headers. */ -enum mb5_header { - MB5H_I2C_WRITE = 1, - MB5H_I2C_READ, -}; - -enum epod_state { - EPOD_OFF, - EPOD_ON, -}; -enum db5500_prcmu_pll { - DB5500_PLL_SOC0, - DB5500_PLL_SOC1, - DB5500_PLL_DDR, - DB5500_NUM_PLL_ID, -}; - -/* Request mailbox 5 fields. */ -#define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0) -#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1) -#define PRCM_REQ_MB5_I2C_SIZE (PRCM_REQ_MB5 + 2) -#define PRCM_REQ_MB5_I2C_DATA (PRCM_REQ_MB5 + 4) - -/* Acknowledge mailbox 5 fields. */ -#define PRCM_ACK_MB5_RETURN_CODE (PRCM_ACK_MB5 + 0) -#define PRCM_ACK_MB5_I2C_DATA (PRCM_ACK_MB5 + 4) - -#define NUM_MB 8 -#define MBOX_BIT BIT -#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1) - -/* -* Used by MCDE to setup all necessary PRCMU registers -*/ -#define PRCMU_RESET_DSIPLL 0x00004000 -#define PRCMU_UNCLAMP_DSIPLL 0x00400800 - -/* HDMI CLK MGT PLLSW=001 (PLLSOC0), PLLDIV=0x8, = 50 Mhz*/ -#define PRCMU_DSI_CLOCK_SETTING 0x00000128 -/* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */ -#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135 -#define PRCMU_PLLDSI_FREQ_SETTING 0x00020121 -#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002 -#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000201 -#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101 - -#define PRCMU_ENABLE_PLLDSI 0x00000001 -#define PRCMU_DISABLE_PLLDSI 0x00000000 - -#define PRCMU_DSI_RESET_SW 0x00000003 -#define PRCMU_RESOUTN0_PIN 0x00000001 -#define PRCMU_RESOUTN1_PIN 0x00000002 -#define PRCMU_RESOUTN2_PIN 0x00000004 - -#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 - -/* - * mb0_transfer - state needed for mailbox 0 communication. - * @lock: The transaction lock. - */ -static struct { - spinlock_t lock; -} mb0_transfer; - -/* - * mb2_transfer - state needed for mailbox 2 communication. - * @lock: The transaction lock. - * @work: The transaction completion structure. - * @req: Request data that need to persist between requests. - * @ack: Reply ("acknowledge") data. - */ -static struct { - struct mutex lock; - struct completion work; - struct { - u8 epod_states[DB5500_NUM_EPOD_ID]; - u8 pll_states[DB5500_NUM_PLL_ID]; - } req; - struct { - u8 header; - u8 status; - } ack; -} mb2_transfer; - -/* - * mb5_transfer - state needed for mailbox 5 communication. - * @lock: The transaction lock. - * @work: The transaction completion structure. - * @ack: Reply ("acknowledge") data. - */ -static struct { - struct mutex lock; - struct completion work; - struct { - u8 header; - u8 status; - u8 value[4]; - } ack; -} mb5_transfer; - -/* PRCMU TCDM base IO address. */ -static __iomem void *tcdm_base; - -struct clk_mgt { - unsigned int offset; - u32 pllsw; -}; - -static DEFINE_SPINLOCK(clk_mgt_lock); - -#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { \ - (DB5500_PRCM_##_name##_MGT), 0 \ -} -static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { - CLK_MGT_ENTRY(SGACLK), - CLK_MGT_ENTRY(UARTCLK), - CLK_MGT_ENTRY(MSP02CLK), - CLK_MGT_ENTRY(I2CCLK), - CLK_MGT_ENTRY(SDMMCCLK), - CLK_MGT_ENTRY(PER1CLK), - CLK_MGT_ENTRY(PER2CLK), - CLK_MGT_ENTRY(PER3CLK), - CLK_MGT_ENTRY(PER5CLK), - CLK_MGT_ENTRY(PER6CLK), - CLK_MGT_ENTRY(PWMCLK), - CLK_MGT_ENTRY(IRDACLK), - CLK_MGT_ENTRY(IRRCCLK), - CLK_MGT_ENTRY(HDMICLK), - CLK_MGT_ENTRY(APEATCLK), - CLK_MGT_ENTRY(APETRACECLK), - CLK_MGT_ENTRY(MCDECLK), - CLK_MGT_ENTRY(DSIALTCLK), - CLK_MGT_ENTRY(DMACLK), - CLK_MGT_ENTRY(B2R2CLK), - CLK_MGT_ENTRY(TVCLK), - CLK_MGT_ENTRY(RNGCLK), - CLK_MGT_ENTRY(SIACLK), - CLK_MGT_ENTRY(SVACLK), -}; - -static int request_timclk(bool enable) -{ - u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); - - if (!enable) - val |= PRCM_TCR_STOP_TIMERS; - writel(val, (_PRCMU_BASE + PRCM_TCR)); - - return 0; -} - -static int request_reg_clock(u8 clock, bool enable) -{ - u32 val; - unsigned long flags; - - WARN_ON(!clk_mgt[clock].offset); - - spin_lock_irqsave(&clk_mgt_lock, flags); - - /* Grab the HW semaphore. */ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) - cpu_relax(); - - val = readl(_PRCMU_BASE + clk_mgt[clock].offset); - if (enable) { - val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); - } else { - clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); - val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); - } - writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); - - /* Release the HW semaphore. */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); - - spin_unlock_irqrestore(&clk_mgt_lock, flags); - - return 0; -} - -/* - * request_pll() - Request for a pll to be enabled or disabled. - * @pll: The pll for which the request is made. - * @enable: Whether the clock should be enabled (true) or disabled (false). - * - * This function should only be used by the clock implementation. - * Do not use it from any other place! - */ -static int request_pll(u8 pll, bool enable) -{ - int r = 0; - - BUG_ON(pll >= DB5500_NUM_PLL_ID); - mutex_lock(&mb2_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) - cpu_relax(); - - mb2_transfer.req.pll_states[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(MB2H_PLL_REQUEST, PRCM_REQ_MB2_HEADER); - - writel(MBOX_BIT(2), _PRCMU_BASE + PRCM_MBOX_CPU_SET); - if (!wait_for_completion_timeout(&mb2_transfer.work, - msecs_to_jiffies(500))) { - pr_err("prcmu: set_pll() failed.\n" - "prcmu: Please check your firmware version.\n"); - r = -EIO; - WARN(1, "Failed to set pll"); - goto unlock_and_return; - } - if (mb2_transfer.ack.status != RC_SUCCESS || - mb2_transfer.ack.header != MB2H_PLL_REQUEST) - r = -EIO; - -unlock_and_return: - mutex_unlock(&mb2_transfer.lock); - - return r; -} - -void prcmu_enable_wakeups(u32 wakeups) -{ -} - -/** - * 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). - * - * This function should only be used by the clock implementation. - * Do not use it from any other place! - */ -int prcmu_request_clock(u8 clock, bool enable) -{ - if (clock < PRCMU_NUM_REG_CLOCKS) - return request_reg_clock(clock, enable); - else if (clock == PRCMU_TIMCLK) - return request_timclk(enable); - else if (clock == PRCMU_PLLSOC0) - return request_pll(DB5500_PLL_SOC0, enable); - else if (clock == PRCMU_PLLSOC1) - return request_pll(DB5500_PLL_SOC1, enable); - else if (clock == PRCMU_PLLDDR) - return request_pll(DB5500_PLL_DDR, enable); - else if (clock == PRCMU_SYSCLK) - return -EINVAL; - else - return -EINVAL; -} - -/** - * db5500_prcmu_abb_read() - Read register value(s) from the ABB. - * @slave: The I2C slave address. - * @reg: The (start) register address. - * @value: The read out value(s). - * @size: The number of registers to read. - * - * Reads register value(s) from the ABB. - * @size has to be <= 4. - */ -int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) -{ - int r; - - if ((size < 1) || (4 < size)) - return -EINVAL; - - mutex_lock(&mb5_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) - cpu_relax(); - writeb(slave, PRCM_REQ_MB5_I2C_SLAVE); - writeb(reg, PRCM_REQ_MB5_I2C_REG); - writeb(size, PRCM_REQ_MB5_I2C_SIZE); - writeb(MB5H_I2C_READ, PRCM_REQ_MB5_HEADER); - - writel(MBOX_BIT(5), _PRCMU_BASE + PRCM_MBOX_CPU_SET); - wait_for_completion(&mb5_transfer.work); - - r = 0; - if ((mb5_transfer.ack.header == MB5H_I2C_READ) && - (mb5_transfer.ack.status == RC_SUCCESS)) - memcpy(value, mb5_transfer.ack.value, (size_t)size); - else - r = -EIO; - - mutex_unlock(&mb5_transfer.lock); - - return r; -} - -/** - * db5500_prcmu_abb_write() - Write register value(s) to the ABB. - * @slave: The I2C slave address. - * @reg: The (start) register address. - * @value: The value(s) to write. - * @size: The number of registers to write. - * - * Writes register value(s) to the ABB. - * @size has to be <= 4. - */ -int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) -{ - int r; - - if ((size < 1) || (4 < size)) - return -EINVAL; - - mutex_lock(&mb5_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) - cpu_relax(); - writeb(slave, PRCM_REQ_MB5_I2C_SLAVE); - writeb(reg, PRCM_REQ_MB5_I2C_REG); - writeb(size, PRCM_REQ_MB5_I2C_SIZE); - memcpy_toio(PRCM_REQ_MB5_I2C_DATA, value, size); - writeb(MB5H_I2C_WRITE, PRCM_REQ_MB5_HEADER); - - writel(MBOX_BIT(5), _PRCMU_BASE + PRCM_MBOX_CPU_SET); - wait_for_completion(&mb5_transfer.work); - - if ((mb5_transfer.ack.header == MB5H_I2C_WRITE) && - (mb5_transfer.ack.status == RC_SUCCESS)) - r = 0; - else - r = -EIO; - - mutex_unlock(&mb5_transfer.lock); - - return r; -} - -int prcmu_resetout(u8 resoutn, u8 state) -{ - int offset; - int pin = -1; - - offset = state > 0 ? PRCM_RESOUTN_SET_OFFSET : PRCM_RESOUTN_CLR_OFFSET; - - switch (resoutn) { - case 0: - pin = PRCMU_RESOUTN0_PIN; - break; - case 1: - pin = PRCMU_RESOUTN1_PIN; - break; - case 2: - pin = PRCMU_RESOUTN2_PIN; - default: - break; - } - - if (pin > 0) - writel(pin, _PRCMU_BASE + offset); - else - return -EINVAL; - - return 0; -} - -int db5500_prcmu_enable_dsipll(void) -{ - int i; - - /* Enable DSIPLL_RESETN resets */ - writel(PRCMU_RESET_DSIPLL, _PRCMU_BASE + PRCM_APE_RESETN_CLR); - /* Unclamp DSIPLL in/out */ - writel(PRCMU_UNCLAMP_DSIPLL, _PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR); - /* Set DSI PLL FREQ */ - writel(PRCMU_PLLDSI_FREQ_SETTING, _PRCMU_BASE + PRCM_PLLDSI_FREQ); - writel(PRCMU_DSI_PLLOUT_SEL_SETTING, - _PRCMU_BASE + PRCM_DSI_PLLOUT_SEL); - /* Enable Escape clocks */ - writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, _PRCMU_BASE + PRCM_DSITVCLK_DIV); - - /* Start DSI PLL */ - writel(PRCMU_ENABLE_PLLDSI, _PRCMU_BASE + PRCM_PLLDSI_ENABLE); - /* Reset DSI PLL */ - writel(PRCMU_DSI_RESET_SW, _PRCMU_BASE + PRCM_DSI_SW_RESET); - for (i = 0; i < 10; i++) { - if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) & - PRCMU_PLLDSI_LOCKP_LOCKED) == PRCMU_PLLDSI_LOCKP_LOCKED) - break; - udelay(100); - } - /* Release DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, _PRCMU_BASE + PRCM_APE_RESETN_SET); - return 0; -} - -int db5500_prcmu_disable_dsipll(void) -{ - /* Disable dsi pll */ - writel(PRCMU_DISABLE_PLLDSI, _PRCMU_BASE + PRCM_PLLDSI_ENABLE); - /* Disable escapeclock */ - writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, - _PRCMU_BASE + PRCM_DSITVCLK_DIV); - return 0; -} - -int db5500_prcmu_set_display_clocks(void) -{ - writel(PRCMU_DSI_CLOCK_SETTING, _PRCMU_BASE + DB5500_PRCM_HDMICLK_MGT); - writel(PRCMU_DSI_LP_CLOCK_SETTING, _PRCMU_BASE + DB5500_PRCM_TVCLK_MGT); - return 0; -} - -static void ack_dbb_wakeup(void) -{ - unsigned long flags; - - spin_lock_irqsave(&mb0_transfer.lock, flags); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) - cpu_relax(); - - writeb(RMB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER); - writel(MBOX_BIT(0), _PRCMU_BASE + PRCM_MBOX_CPU_SET); - - spin_unlock_irqrestore(&mb0_transfer.lock, flags); -} - -int prcmu_set_epod(u16 epod_id, u8 epod_state) -{ - int r = 0; - bool ram_retention = false; - - /* check argument */ - BUG_ON(epod_id < DB5500_EPOD_ID_BASE); - BUG_ON(epod_state > EPOD_STATE_ON); - - 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: - ram_retention = true; - break; - } - - /* check argument */ - /* BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention); */ - - /* get lock */ - mutex_lock(&mb2_transfer.lock); - - /* wait for mailbox */ - while (readl(_PRCMU_BASE + 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; - } - - /* 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(MB2H_EPOD_REQUEST, PRCM_REQ_MB2_HEADER); - - writel(MBOX_BIT(2), _PRCMU_BASE + PRCM_MBOX_CPU_SET); - - if (!wait_for_completion_timeout(&mb2_transfer.work, - msecs_to_jiffies(500))) { - pr_err("prcmu: set_epod() failed.\n" - "prcmu: Please check your firmware version.\n"); - r = -EIO; - WARN(1, "Failed to set epod"); - goto unlock_and_return; - } - - if (mb2_transfer.ack.status != RC_SUCCESS || - mb2_transfer.ack.header != MB2H_EPOD_REQUEST) - r = -EIO; - -unlock_and_return: - mutex_unlock(&mb2_transfer.lock); - return r; -} - -static inline void print_unknown_header_warning(u8 n, u8 header) -{ - pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n", - header, n); -} - -static bool read_mailbox_0(void) -{ - bool r; - u8 header; - - header = readb(PRCM_ACK_MB0_HEADER); - switch (header) { - case AMB0H_WAKE_UP: - r = true; - break; - default: - print_unknown_header_warning(0, header); - r = false; - break; - } - writel(MBOX_BIT(0), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - return r; -} - -static bool read_mailbox_1(void) -{ - writel(MBOX_BIT(1), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - return false; -} - -static bool read_mailbox_2(void) -{ - u8 header; - - header = readb(PRCM_ACK_MB2_HEADER); - mb2_transfer.ack.header = header; - switch (header) { - case MB2H_EPOD_REQUEST: - mb2_transfer.ack.status = readb(PRCM_ACK_MB2_EPOD_STATUS); - break; - case MB2H_CLK_REQUEST: - mb2_transfer.ack.status = readb(PRCM_ACK_MB2_CLK_STATUS); - break; - case MB2H_PLL_REQUEST: - mb2_transfer.ack.status = readb(PRCM_ACK_MB2_PLL_STATUS); - break; - default: - writel(MBOX_BIT(2), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - pr_err("prcmu: Wrong ACK received for MB2 request \n"); - return false; - break; - } - writel(MBOX_BIT(2), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - complete(&mb2_transfer.work); - return false; -} - -static bool read_mailbox_3(void) -{ - writel(MBOX_BIT(3), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - return false; -} - -static bool read_mailbox_4(void) -{ - writel(MBOX_BIT(4), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - return false; -} - -static bool read_mailbox_5(void) -{ - u8 header; - - header = readb(PRCM_ACK_MB5_HEADER); - switch (header) { - case MB5H_I2C_READ: - memcpy_fromio(mb5_transfer.ack.value, PRCM_ACK_MB5_I2C_DATA, 4); - case MB5H_I2C_WRITE: - mb5_transfer.ack.header = header; - mb5_transfer.ack.status = readb(PRCM_ACK_MB5_RETURN_CODE); - writel(MBOX_BIT(5), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - complete(&mb5_transfer.work); - break; - default: - writel(MBOX_BIT(5), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - print_unknown_header_warning(5, header); - break; - } - return false; -} - -static bool read_mailbox_6(void) -{ - writel(MBOX_BIT(6), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - return false; -} - -static bool read_mailbox_7(void) -{ - writel(MBOX_BIT(7), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - return false; -} - -static bool (* const read_mailbox[NUM_MB])(void) = { - read_mailbox_0, - read_mailbox_1, - read_mailbox_2, - read_mailbox_3, - read_mailbox_4, - read_mailbox_5, - read_mailbox_6, - read_mailbox_7 -}; - -static irqreturn_t prcmu_irq_handler(int irq, void *data) -{ - u32 bits; - u8 n; - irqreturn_t r; - - bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); - if (unlikely(!bits)) - return IRQ_NONE; - - r = IRQ_HANDLED; - for (n = 0; bits; n++) { - if (bits & MBOX_BIT(n)) { - bits -= MBOX_BIT(n); - if (read_mailbox[n]()) - r = IRQ_WAKE_THREAD; - } - } - return r; -} - -static irqreturn_t prcmu_irq_thread_fn(int irq, void *data) -{ - ack_dbb_wakeup(); - return IRQ_HANDLED; -} - -void __init db5500_prcmu_early_init(void) -{ - tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE); - spin_lock_init(&mb0_transfer.lock); - mutex_init(&mb2_transfer.lock); - mutex_init(&mb5_transfer.lock); - init_completion(&mb2_transfer.work); - init_completion(&mb5_transfer.work); -} - -/** - * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic - * - */ -int __init db5500_prcmu_init(void) -{ - int r = 0; - - if (ux500_is_svp() || !cpu_is_u5500()) - return -ENODEV; - - /* Clean up the mailbox interrupts after pre-kernel code. */ - writel(ALL_MBOX_BITS, _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - - r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler, - prcmu_irq_thread_fn, 0, "prcmu", NULL); - if (r < 0) { - pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n"); - return -EBUSY; - } - return 0; -} - -arch_initcall(db5500_prcmu_init); diff --git a/arch/arm/mach-ux500/prcmu-db8500.c b/arch/arm/mach-ux500/prcmu-db8500.c deleted file mode 100644 index 5e6ff1b9601..00000000000 --- a/arch/arm/mach-ux500/prcmu-db8500.c +++ /dev/null @@ -1,2098 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> - * Author: Sundar Iyer <sundar.iyer@stericsson.com> - * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> - * - * U8500 PRCM Unit interface driver - * - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/completion.h> -#include <linux/irq.h> -#include <linux/jiffies.h> -#include <linux/bitops.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/uaccess.h> - -/* - * NOTE! Temporary until all users of set_hwacc() are using the regulator - * framework API - */ -#include <linux/regulator/consumer.h> - -#include <mach/hardware.h> -#include <mach/irqs.h> - -#include "prcmu-regs-db8500.h" -#include "prcmu-debug.h" - -#include <mach/prcmu.h> -#include <mach/db8500-regs.h> -#include <mach/id.h> - -/* Offset for the firmware version within the TCPM */ -#define PRCMU_FW_VERSION_OFFSET 0xA4 - -/* PRCMU project numbers, defined by PRCMU FW */ -#define PRCMU_PROJECT_ID_8500V1_0 1 -#define PRCMU_PROJECT_ID_8500V2_0 2 -#define PRCMU_PROJECT_ID_8400V2_0 3 - -/* Index of different voltages to be used when accessing AVSData */ -#define PRCM_AVS_BASE 0x2FC -#define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0) -#define PRCM_AVS_VBB_MAX_OPP (PRCM_AVS_BASE + 0x1) -#define PRCM_AVS_VBB_100_OPP (PRCM_AVS_BASE + 0x2) -#define PRCM_AVS_VBB_50_OPP (PRCM_AVS_BASE + 0x3) -#define PRCM_AVS_VARM_MAX_OPP (PRCM_AVS_BASE + 0x4) -#define PRCM_AVS_VARM_100_OPP (PRCM_AVS_BASE + 0x5) -#define PRCM_AVS_VARM_50_OPP (PRCM_AVS_BASE + 0x6) -#define PRCM_AVS_VARM_RET (PRCM_AVS_BASE + 0x7) -#define PRCM_AVS_VAPE_100_OPP (PRCM_AVS_BASE + 0x8) -#define PRCM_AVS_VAPE_50_OPP (PRCM_AVS_BASE + 0x9) -#define PRCM_AVS_VMOD_100_OPP (PRCM_AVS_BASE + 0xA) -#define PRCM_AVS_VMOD_50_OPP (PRCM_AVS_BASE + 0xB) -#define PRCM_AVS_VSAFE (PRCM_AVS_BASE + 0xC) - -#define PRCM_AVS_VOLTAGE 0 -#define PRCM_AVS_VOLTAGE_MASK 0x3f -#define PRCM_AVS_ISSLOWSTARTUP 6 -#define PRCM_AVS_ISSLOWSTARTUP_MASK (1 << PRCM_AVS_ISSLOWSTARTUP) -#define PRCM_AVS_ISMODEENABLE 7 -#define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE) - -#define PRCM_BOOT_STATUS 0xFFF -#define PRCM_ROMCODE_A2P 0xFFE -#define PRCM_ROMCODE_P2A 0xFFD -#define PRCM_XP70_CUR_PWR_STATE 0xFFC /* 4 BYTES */ - -#define PRCM_SW_RST_REASON 0xFF8 /* 2 bytes */ - -#define _PRCM_MBOX_HEADER 0xFE8 /* 16 bytes */ -#define PRCM_MBOX_HEADER_REQ_MB0 (_PRCM_MBOX_HEADER + 0x0) -#define PRCM_MBOX_HEADER_REQ_MB1 (_PRCM_MBOX_HEADER + 0x1) -#define PRCM_MBOX_HEADER_REQ_MB2 (_PRCM_MBOX_HEADER + 0x2) -#define PRCM_MBOX_HEADER_REQ_MB3 (_PRCM_MBOX_HEADER + 0x3) -#define PRCM_MBOX_HEADER_REQ_MB4 (_PRCM_MBOX_HEADER + 0x4) -#define PRCM_MBOX_HEADER_REQ_MB5 (_PRCM_MBOX_HEADER + 0x5) -#define PRCM_MBOX_HEADER_ACK_MB0 (_PRCM_MBOX_HEADER + 0x8) - -/* Req Mailboxes */ -#define PRCM_REQ_MB0 0xFDC /* 12 bytes */ -#define PRCM_REQ_MB1 0xFD0 /* 12 bytes */ -#define PRCM_REQ_MB2 0xFC0 /* 16 bytes */ -#define PRCM_REQ_MB3 0xE4C /* 372 bytes */ -#define PRCM_REQ_MB4 0xE48 /* 4 bytes */ -#define PRCM_REQ_MB5 0xE44 /* 4 bytes */ - -/* Ack Mailboxes */ -#define PRCM_ACK_MB0 0xE08 /* 52 bytes */ -#define PRCM_ACK_MB1 0xE04 /* 4 bytes */ -#define PRCM_ACK_MB2 0xE00 /* 4 bytes */ -#define PRCM_ACK_MB3 0xDFC /* 4 bytes */ -#define PRCM_ACK_MB4 0xDF8 /* 4 bytes */ -#define PRCM_ACK_MB5 0xDF4 /* 4 bytes */ - -/* Mailbox 0 headers */ -#define MB0H_POWER_STATE_TRANS 0 -#define MB0H_CONFIG_WAKEUPS_EXE 1 -#define MB0H_READ_WAKEUP_ACK 3 -#define MB0H_CONFIG_WAKEUPS_SLEEP 4 - -#define MB0H_WAKEUP_EXE 2 -#define MB0H_WAKEUP_SLEEP 5 - -/* Mailbox 0 REQs */ -#define PRCM_REQ_MB0_AP_POWER_STATE (PRCM_REQ_MB0 + 0x0) -#define PRCM_REQ_MB0_AP_PLL_STATE (PRCM_REQ_MB0 + 0x1) -#define PRCM_REQ_MB0_ULP_CLOCK_STATE (PRCM_REQ_MB0 + 0x2) -#define PRCM_REQ_MB0_DO_NOT_WFI (PRCM_REQ_MB0 + 0x3) -#define PRCM_REQ_MB0_WAKEUP_8500 (PRCM_REQ_MB0 + 0x4) -#define PRCM_REQ_MB0_WAKEUP_4500 (PRCM_REQ_MB0 + 0x8) - -/* 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_8500 (PRCM_ACK_MB0 + 0x4) -#define PRCM_ACK_MB0_WAKEUP_0_4500 (PRCM_ACK_MB0 + 0x8) -#define PRCM_ACK_MB0_WAKEUP_1_8500 (PRCM_ACK_MB0 + 0x1C) -#define PRCM_ACK_MB0_WAKEUP_1_4500 (PRCM_ACK_MB0 + 0x20) -#define PRCM_ACK_MB0_EVENT_4500_NUMBERS 20 - -/* Mailbox 1 headers */ -#define MB1H_ARM_APE_OPP 0x0 -#define MB1H_RESET_MODEM 0x2 -#define MB1H_REQUEST_APE_OPP_100_VOLT 0x3 -#define MB1H_RELEASE_APE_OPP_100_VOLT 0x4 -#define MB1H_RELEASE_USB_WAKEUP 0x5 -#define MB1H_PLL_ON_OFF 0x6 - -/* Mailbox 1 Requests */ -#define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) -#define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) -#define PRCM_REQ_MB1_APE_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x4) -#define PRCM_REQ_MB1_ARM_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x8) -#define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) -#define PLL_SOC1_OFF 0x4 -#define PLL_SOC1_ON 0x8 - -/* 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_APE_VOLTAGE_STATUS (PRCM_ACK_MB1 + 0x2) -#define PRCM_ACK_MB1_DVFS_STATUS (PRCM_ACK_MB1 + 0x3) - -/* Mailbox 2 headers */ -#define MB2H_DPS 0x0 -#define MB2H_AUTO_PWR 0x1 - -/* Mailbox 2 REQs */ -#define PRCM_REQ_MB2_SVA_MMDSP (PRCM_REQ_MB2 + 0x0) -#define PRCM_REQ_MB2_SVA_PIPE (PRCM_REQ_MB2 + 0x1) -#define PRCM_REQ_MB2_SIA_MMDSP (PRCM_REQ_MB2 + 0x2) -#define PRCM_REQ_MB2_SIA_PIPE (PRCM_REQ_MB2 + 0x3) -#define PRCM_REQ_MB2_SGA (PRCM_REQ_MB2 + 0x4) -#define PRCM_REQ_MB2_B2R2_MCDE (PRCM_REQ_MB2 + 0x5) -#define PRCM_REQ_MB2_ESRAM12 (PRCM_REQ_MB2 + 0x6) -#define PRCM_REQ_MB2_ESRAM34 (PRCM_REQ_MB2 + 0x7) -#define PRCM_REQ_MB2_AUTO_PM_SLEEP (PRCM_REQ_MB2 + 0x8) -#define PRCM_REQ_MB2_AUTO_PM_IDLE (PRCM_REQ_MB2 + 0xC) - -/* Mailbox 2 ACKs */ -#define PRCM_ACK_MB2_DPS_STATUS (PRCM_ACK_MB2 + 0x0) -#define HWACC_PWR_ST_OK 0xFE - -/* Mailbox 3 headers */ -#define MB3H_ANC 0x0 -#define MB3H_SIDETONE 0x1 -#define MB3H_SYSCLK 0xE - -/* Mailbox 3 Requests */ -#define PRCM_REQ_MB3_ANC_FIR_COEFF (PRCM_REQ_MB3 + 0x0) -#define PRCM_REQ_MB3_ANC_IIR_COEFF (PRCM_REQ_MB3 + 0x20) -#define PRCM_REQ_MB3_ANC_SHIFTER (PRCM_REQ_MB3 + 0x60) -#define PRCM_REQ_MB3_ANC_WARP (PRCM_REQ_MB3 + 0x64) -#define PRCM_REQ_MB3_SIDETONE_FIR_GAIN (PRCM_REQ_MB3 + 0x68) -#define PRCM_REQ_MB3_SIDETONE_FIR_COEFF (PRCM_REQ_MB3 + 0x6C) -#define PRCM_REQ_MB3_SYSCLK_MGT (PRCM_REQ_MB3 + 0x16C) - -/* Mailbox 4 headers */ -#define MB4H_DDR_INIT 0x0 -#define MB4H_MEM_ST 0x1 -#define MB4H_HOTDOG 0x12 -#define MB4H_HOTMON 0x13 -#define MB4H_HOT_PERIOD 0x14 - -/* Mailbox 4 Requests */ -#define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0) -#define PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE (PRCM_REQ_MB4 + 0x1) -#define PRCM_REQ_MB4_ESRAM0_ST (PRCM_REQ_MB4 + 0x3) -#define PRCM_REQ_MB4_HOTDOG_THRESHOLD (PRCM_REQ_MB4 + 0x0) -#define PRCM_REQ_MB4_HOTMON_LOW (PRCM_REQ_MB4 + 0x0) -#define PRCM_REQ_MB4_HOTMON_HIGH (PRCM_REQ_MB4 + 0x1) -#define PRCM_REQ_MB4_HOTMON_CONFIG (PRCM_REQ_MB4 + 0x2) -#define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0) -#define HOTMON_CONFIG_LOW BIT(0) -#define HOTMON_CONFIG_HIGH BIT(1) - -/* Mailbox 5 Requests */ -#define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0) -#define PRCM_REQ_MB5_I2C_HW_BITS (PRCM_REQ_MB5 + 0x1) -#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 0x2) -#define PRCM_REQ_MB5_I2C_VAL (PRCM_REQ_MB5 + 0x3) -#define PRCMU_I2C_WRITE(slave) (((slave) << 1) | BIT(6)) -#define PRCMU_I2C_READ(slave) (((slave) << 1) | BIT(0) | BIT(6)) -#define PRCMU_I2C_STOP_EN BIT(3) - -/* Mailbox 5 ACKs */ -#define PRCM_ACK_MB5_I2C_STATUS (PRCM_ACK_MB5 + 0x1) -#define PRCM_ACK_MB5_I2C_VAL (PRCM_ACK_MB5 + 0x3) -#define I2C_WR_OK 0x1 -#define I2C_RD_OK 0x2 - -#define NUM_MB 8 -#define MBOX_BIT BIT -#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1) - -/* - * Wakeups/IRQs - */ - -#define WAKEUP_BIT_RTC BIT(0) -#define WAKEUP_BIT_RTT0 BIT(1) -#define WAKEUP_BIT_RTT1 BIT(2) -#define WAKEUP_BIT_HSI0 BIT(3) -#define WAKEUP_BIT_HSI1 BIT(4) -#define WAKEUP_BIT_CA_WAKE BIT(5) -#define WAKEUP_BIT_USB BIT(6) -#define WAKEUP_BIT_ABB BIT(7) -#define WAKEUP_BIT_ABB_FIFO BIT(8) -#define WAKEUP_BIT_SYSCLK_OK BIT(9) -#define WAKEUP_BIT_CA_SLEEP BIT(10) -#define WAKEUP_BIT_AC_WAKE_ACK BIT(11) -#define WAKEUP_BIT_SIDE_TONE_OK BIT(12) -#define WAKEUP_BIT_ANC_OK BIT(13) -#define WAKEUP_BIT_SW_ERROR BIT(14) -#define WAKEUP_BIT_AC_SLEEP_ACK BIT(15) -#define WAKEUP_BIT_ARM BIT(17) -#define WAKEUP_BIT_HOTMON_LOW BIT(18) -#define WAKEUP_BIT_HOTMON_HIGH BIT(19) -#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_GPIO8 BIT(31) - -/* - * 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_PRCMU_##_name) - IRQ_PRCMU_BASE) -#define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name) -static u32 prcmu_irq_bit[NUM_PRCMU_WAKEUPS] = { - IRQ_ENTRY(RTC), - IRQ_ENTRY(RTT0), - IRQ_ENTRY(RTT1), - IRQ_ENTRY(HSI0), - IRQ_ENTRY(HSI1), - IRQ_ENTRY(CA_WAKE), - IRQ_ENTRY(USB), - IRQ_ENTRY(ABB), - IRQ_ENTRY(ABB_FIFO), - IRQ_ENTRY(CA_SLEEP), - IRQ_ENTRY(ARM), - IRQ_ENTRY(HOTMON_LOW), - IRQ_ENTRY(HOTMON_HIGH), - 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(GPIO8) -}; - -#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(HSI0), - WAKEUP_ENTRY(HSI1), - WAKEUP_ENTRY(USB), - WAKEUP_ENTRY(ABB), - WAKEUP_ENTRY(ABB_FIFO), - WAKEUP_ENTRY(ARM) -}; - -/* - * mb0_transfer - state needed for mailbox 0 communication. - * @lock: The transaction lock. - * @dbb_events_lock: A lock used to handle concurrent access to (parts of) - * the request data. - * @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 mutex ac_wake_lock; - struct completion ac_wake_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. - * @ack: Reply ("acknowledge") data. - */ -static struct { - struct mutex lock; - struct completion work; - struct { - u8 header; - u8 arm_opp; - u8 ape_opp; - u8 ape_voltage_status; - } ack; -} mb1_transfer; - -/* - * mb2_transfer - state needed for mailbox 2 communication. - * @lock: The transaction lock. - * @work: The transaction completion structure. - * @auto_pm_lock: The autonomous power management configuration lock. - * @auto_pm_enabled: A flag indicating whether autonomous PM is enabled. - * @req: Request data that need to persist between requests. - * @ack: Reply ("acknowledge") data. - */ -static struct { - struct mutex lock; - struct completion work; - spinlock_t auto_pm_lock; - bool auto_pm_enabled; - struct { - u8 status; - } ack; -} mb2_transfer; - -/* - * mb3_transfer - state needed for mailbox 3 communication. - * @lock: The request lock. - * @sysclk_lock: A lock used to handle concurrent sysclk requests. - * @sysclk_work: Work structure used for sysclk requests. - */ -static struct { - spinlock_t lock; - struct mutex sysclk_lock; - struct completion sysclk_work; -} mb3_transfer; - -/* - * mb4_transfer - state needed for mailbox 4 communication. - * @lock: The transaction lock. - * @work: The transaction completion structure. - */ -static struct { - struct mutex lock; - struct completion work; -} mb4_transfer; - -/* - * mb5_transfer - state needed for mailbox 5 communication. - * @lock: The transaction lock. - * @work: The transaction completion structure. - * @ack: Reply ("acknowledge") data. - */ -static struct { - struct mutex lock; - struct completion work; - struct { - u8 status; - u8 value; - } ack; -} mb5_transfer; - -static atomic_t ac_wake_req_state = ATOMIC_INIT(0); - -/* Spinlocks */ -static DEFINE_SPINLOCK(clkout_lock); -static DEFINE_SPINLOCK(gpiocr_lock); - -/* Global var to runtime determine TCDM base for v2 or v1 */ -static __iomem void *tcdm_base; - -struct clk_mgt { - unsigned int offset; - u32 pllsw; -}; - -static DEFINE_SPINLOCK(clk_mgt_lock); - -#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT), 0 } -struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { - CLK_MGT_ENTRY(SGACLK), - CLK_MGT_ENTRY(UARTCLK), - CLK_MGT_ENTRY(MSP02CLK), - CLK_MGT_ENTRY(MSP1CLK), - CLK_MGT_ENTRY(I2CCLK), - CLK_MGT_ENTRY(SDMMCCLK), - CLK_MGT_ENTRY(SLIMCLK), - CLK_MGT_ENTRY(PER1CLK), - CLK_MGT_ENTRY(PER2CLK), - CLK_MGT_ENTRY(PER3CLK), - CLK_MGT_ENTRY(PER5CLK), - CLK_MGT_ENTRY(PER6CLK), - CLK_MGT_ENTRY(PER7CLK), - CLK_MGT_ENTRY(LCDCLK), - CLK_MGT_ENTRY(BMLCLK), - CLK_MGT_ENTRY(HSITXCLK), - CLK_MGT_ENTRY(HSIRXCLK), - CLK_MGT_ENTRY(HDMICLK), - CLK_MGT_ENTRY(APEATCLK), - CLK_MGT_ENTRY(APETRACECLK), - CLK_MGT_ENTRY(MCDECLK), - CLK_MGT_ENTRY(IPI2CCLK), - CLK_MGT_ENTRY(DSIALTCLK), - CLK_MGT_ENTRY(DMACLK), - CLK_MGT_ENTRY(B2R2CLK), - CLK_MGT_ENTRY(TVCLK), - CLK_MGT_ENTRY(SSPCLK), - CLK_MGT_ENTRY(RNGCLK), - CLK_MGT_ENTRY(UICCCLK), -}; - -/* - * NOTE! Temporary until all users of set_hwacc() are using the regulator - * framework API - */ -static struct regulator *hwacc_regulator[NUM_HW_ACC]; -static struct regulator *hwacc_ret_regulator[NUM_HW_ACC]; - -static bool hwacc_enabled[NUM_HW_ACC]; -static bool hwacc_ret_enabled[NUM_HW_ACC]; - -static const char *hwacc_regulator_name[NUM_HW_ACC] = { - [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp", - [HW_ACC_SVAPIPE] = "hwacc-sva-pipe", - [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp", - [HW_ACC_SIAPIPE] = "hwacc-sia-pipe", - [HW_ACC_SGA] = "hwacc-sga", - [HW_ACC_B2R2] = "hwacc-b2r2", - [HW_ACC_MCDE] = "hwacc-mcde", - [HW_ACC_ESRAM1] = "hwacc-esram1", - [HW_ACC_ESRAM2] = "hwacc-esram2", - [HW_ACC_ESRAM3] = "hwacc-esram3", - [HW_ACC_ESRAM4] = "hwacc-esram4", -}; - -static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { - [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp-ret", - [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp-ret", - [HW_ACC_ESRAM1] = "hwacc-esram1-ret", - [HW_ACC_ESRAM2] = "hwacc-esram2-ret", - [HW_ACC_ESRAM3] = "hwacc-esram3-ret", - [HW_ACC_ESRAM4] = "hwacc-esram4-ret", -}; - -/* -* Used by MCDE to setup all necessary PRCMU registers -*/ -#define PRCMU_RESET_DSIPLL 0x00004000 -#define PRCMU_UNCLAMP_DSIPLL 0x00400800 - -#define PRCMU_CLK_PLL_DIV_SHIFT 0 -#define PRCMU_CLK_PLL_SW_SHIFT 5 -#define PRCMU_CLK_38 (1 << 9) -#define PRCMU_CLK_38_SRC (1 << 10) -#define PRCMU_CLK_38_DIV (1 << 11) - -/* PLLDIV=12, PLLSW=4 (PLLDDR) */ -#define PRCMU_DSI_CLOCK_SETTING 0x0000008C - -/* PLLDIV=8, PLLSW=4 (PLLDDR) */ -#define PRCMU_DSI_CLOCK_SETTING_U8400 0x00000088 - -/* DPI 50000000 Hz */ -#define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \ - (16 << PRCMU_CLK_PLL_DIV_SHIFT)) -#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000E00 - -/* D=101, N=1, R=4, SELDIV2=0 */ -#define PRCMU_PLLDSI_FREQ_SETTING 0x00040165 - -/* D=70, N=1, R=3, SELDIV2=0 */ -#define PRCMU_PLLDSI_FREQ_SETTING_U8400 0x00030146 - -#define PRCMU_ENABLE_PLLDSI 0x00000001 -#define PRCMU_DISABLE_PLLDSI 0x00000000 -#define PRCMU_RELEASE_RESET_DSS 0x0000400C -#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000202 -/* ESC clk, div0=1, div1=1, div2=3 */ -#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x07030101 -#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00030101 -#define PRCMU_DSI_RESET_SW 0x00000007 - -#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 - -static struct { - u8 project_number; - u8 api_version; - u8 func_version; - u8 errata; -} prcmu_version; - - -int prcmu_enable_dsipll(void) -{ - int i; - unsigned int plldsifreq; - - /* Clear DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_CLR)); - /* Unclamp DSIPLL in/out */ - writel(PRCMU_UNCLAMP_DSIPLL, (_PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR)); - - if (prcmu_is_u8400()) - plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400; - else - plldsifreq = PRCMU_PLLDSI_FREQ_SETTING; - /* Set DSI PLL FREQ */ - writel(plldsifreq, (_PRCMU_BASE + PRCM_PLLDSI_FREQ)); - writel(PRCMU_DSI_PLLOUT_SEL_SETTING, - (_PRCMU_BASE + PRCM_DSI_PLLOUT_SEL)); - /* Enable Escape clocks */ - writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, - (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); - - /* Start DSI PLL */ - writel(PRCMU_ENABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); - /* Reset DSI PLL */ - writel(PRCMU_DSI_RESET_SW, (_PRCMU_BASE + PRCM_DSI_SW_RESET)); - for (i = 0; i < 10; i++) { - if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) & - PRCMU_PLLDSI_LOCKP_LOCKED) - == PRCMU_PLLDSI_LOCKP_LOCKED) - break; - udelay(100); - } - /* Set DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET)); - return 0; -} - -int prcmu_disable_dsipll(void) -{ - /* Disable dsi pll */ - writel(PRCMU_DISABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); - /* Disable escapeclock */ - writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, - (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); - return 0; -} - -int prcmu_set_display_clocks(void) -{ - unsigned long flags; - unsigned int dsiclk; - - if (prcmu_is_u8400()) - dsiclk = PRCMU_DSI_CLOCK_SETTING_U8400; - else - dsiclk = PRCMU_DSI_CLOCK_SETTING; - - spin_lock_irqsave(&clk_mgt_lock, flags); - - /* Grab the HW semaphore. */ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) - cpu_relax(); - - writel(dsiclk, (_PRCMU_BASE + PRCM_HDMICLK_MGT)); - writel(PRCMU_DSI_LP_CLOCK_SETTING, (_PRCMU_BASE + PRCM_TVCLK_MGT)); - writel(PRCMU_DPI_CLOCK_SETTING, (_PRCMU_BASE + PRCM_LCDCLK_MGT)); - - /* Release the HW semaphore. */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); - - spin_unlock_irqrestore(&clk_mgt_lock, flags); - - return 0; -} - -/** - * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1. - */ -void prcmu_enable_spi2(void) -{ - u32 reg; - unsigned long flags; - - spin_lock_irqsave(&gpiocr_lock, flags); - reg = readl(_PRCMU_BASE + PRCM_GPIOCR); - writel(reg | PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); - spin_unlock_irqrestore(&gpiocr_lock, flags); -} - -/** - * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1. - */ -void prcmu_disable_spi2(void) -{ - u32 reg; - unsigned long flags; - - spin_lock_irqsave(&gpiocr_lock, flags); - reg = readl(_PRCMU_BASE + PRCM_GPIOCR); - writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); - spin_unlock_irqrestore(&gpiocr_lock, flags); -} - -bool prcmu_has_arm_maxopp(void) -{ - return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) & - PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK; -} - -bool prcmu_is_u8400(void) -{ - return prcmu_version.project_number == PRCMU_PROJECT_ID_8400V2_0; -} - -/** - * prcmu_get_boot_status - PRCMU boot status checking - * Returns: the current PRCMU boot status - */ -int prcmu_get_boot_status(void) -{ - return readb(tcdm_base + PRCM_BOOT_STATUS); -} - -/** - * prcmu_set_rc_a2p - This function is used to run few power state sequences - * @val: Value to be set, i.e. transition requested - * Returns: 0 on success, -EINVAL on invalid argument - * - * This function is used to run the following power state sequences - - * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep - */ -int prcmu_set_rc_a2p(enum romcode_write val) -{ - if (val < RDY_2_DS || val > RDY_2_XP70_RST) - return -EINVAL; - writeb(val, (tcdm_base + PRCM_ROMCODE_A2P)); - return 0; -} - -/** - * prcmu_get_rc_p2a - This function is used to get power state sequences - * Returns: the power transition that has last happened - * - * This function can return the following transitions- - * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep - */ -enum romcode_read prcmu_get_rc_p2a(void) -{ - return readb(tcdm_base + PRCM_ROMCODE_P2A); -} - -/** - * prcmu_get_current_mode - Return the current XP70 power mode - * Returns: Returns the current AP(ARM) power mode: init, - * apBoot, apExecute, apDeepSleep, apSleep, apIdle, apReset - */ -enum ap_pwrst prcmu_get_xp70_current_state(void) -{ - return readb(tcdm_base + PRCM_XP70_CUR_PWR_STATE); -} - -/** - * prcmu_config_clkout - Configure one of the programmable clock outputs. - * @clkout: The CLKOUT number (0 or 1). - * @source: The clock to be used (one of the PRCMU_CLKSRC_*). - * @div: The divider to be applied. - * - * Configures one of the programmable clock outputs (CLKOUTs). - * @div should be in the range [1,63] to request a configuration, or 0 to - * inform that the configuration is no longer requested. - */ -int prcmu_config_clkout(u8 clkout, u8 source, u8 div) -{ - static int requests[2]; - int r = 0; - unsigned long flags; - u32 val; - u32 bits; - u32 mask; - u32 div_mask; - - BUG_ON(clkout > 1); - BUG_ON(div > 63); - BUG_ON((clkout == 0) && (source > PRCMU_CLKSRC_CLK009)); - - if (!div && !requests[clkout]) - return -EINVAL; - - switch (clkout) { - case 0: - div_mask = PRCM_CLKOCR_CLKODIV0_MASK; - mask = (PRCM_CLKOCR_CLKODIV0_MASK | PRCM_CLKOCR_CLKOSEL0_MASK); - bits = ((source << PRCM_CLKOCR_CLKOSEL0_SHIFT) | - (div << PRCM_CLKOCR_CLKODIV0_SHIFT)); - break; - case 1: - div_mask = PRCM_CLKOCR_CLKODIV1_MASK; - mask = (PRCM_CLKOCR_CLKODIV1_MASK | PRCM_CLKOCR_CLKOSEL1_MASK | - PRCM_CLKOCR_CLK1TYPE); - bits = ((source << PRCM_CLKOCR_CLKOSEL1_SHIFT) | - (div << PRCM_CLKOCR_CLKODIV1_SHIFT)); - break; - } - bits &= mask; - - spin_lock_irqsave(&clkout_lock, flags); - - val = readl(_PRCMU_BASE + PRCM_CLKOCR); - if (val & div_mask) { - if (div) { - if ((val & mask) != bits) { - r = -EBUSY; - goto unlock_and_return; - } - } else { - if ((val & mask & ~div_mask) != bits) { - r = -EINVAL; - goto unlock_and_return; - } - } - } - writel((bits | (val & ~mask)), (_PRCMU_BASE + PRCM_CLKOCR)); - requests[clkout] += (div ? 1 : -1); - -unlock_and_return: - spin_unlock_irqrestore(&clkout_lock, flags); - - return r; -} - -int 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_transfer.lock, flags); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) - cpu_relax(); - - writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); - writeb(state, (tcdm_base + PRCM_REQ_MB0_AP_POWER_STATE)); - writeb((keep_ap_pll ? 1 : 0), (tcdm_base + PRCM_REQ_MB0_AP_PLL_STATE)); - writeb((keep_ulp_clk ? 1 : 0), - (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE)); - writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI)); - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - spin_unlock_irqrestore(&mb0_transfer.lock, flags); - - return 0; -} - -/* This function should only be called while mb0_transfer.lock is held. */ -static void config_wakeups(void) -{ - const u8 header[2] = { - MB0H_CONFIG_WAKEUPS_EXE, - MB0H_CONFIG_WAKEUPS_SLEEP - }; - static u32 last_dbb_events; - static u32 last_abb_events; - u32 dbb_events; - u32 abb_events; - unsigned int i; - - dbb_events = mb0_transfer.req.dbb_irqs | mb0_transfer.req.dbb_wakeups; - dbb_events |= (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK); - - abb_events = mb0_transfer.req.abb_events; - - if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events)) - return; - - for (i = 0; i < 2; i++) { - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) - cpu_relax(); - writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500)); - writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500)); - writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - } - last_dbb_events = dbb_events; - last_abb_events = abb_events; -} - -void 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)) - 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 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 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); - else - *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_0_4500); -} - -/** - * 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 r; - - if (opp < ARM_NO_CHANGE || opp > ARM_EXTCLK) - return -EINVAL; - - r = 0; - - mutex_lock(&mb1_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); - writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); - - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb1_transfer.work); - - if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || - (mb1_transfer.ack.arm_opp != opp)) - r = -EIO; - - mutex_unlock(&mb1_transfer.lock); - - return r; -} - -/** - * prcmu_get_arm_opp - get the current ARM OPP - * - * Returns: the current ARM OPP - */ -int prcmu_get_arm_opp(void) -{ - return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP); -} - -/** - * prcmu_get_ddr_opp - get the current DDR OPP - * - * Returns: the current DDR OPP - */ -int prcmu_get_ddr_opp(void) -{ - return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW); -} - -/** - * set_ddr_opp - set the appropriate DDR OPP - * @opp: The new DDR operating point to which transition is to be made - * Returns: 0 on success, non-zero on failure - * - * This function sets the operating point of the DDR. - */ -int prcmu_set_ddr_opp(u8 opp) -{ - if (opp < DDR_100_OPP || opp > DDR_25_OPP) - return -EINVAL; - /* Changing the DDR OPP can hang the hardware pre-v21 */ - if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) - writeb(opp, (_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW)); - - return 0; -} -/** - * set_ape_opp - set the appropriate APE OPP - * @opp: The new APE operating point to which transition is to be made - * Returns: 0 on success, non-zero on failure - * - * This function sets the operating point of the APE. - */ -int prcmu_set_ape_opp(u8 opp) -{ - int r = 0; - - mutex_lock(&mb1_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); - writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); - - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb1_transfer.work); - - if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || - (mb1_transfer.ack.ape_opp != opp)) - r = -EIO; - - mutex_unlock(&mb1_transfer.lock); - - return r; -} - -/** - * prcmu_get_ape_opp - get the current APE OPP - * - * Returns: the current APE OPP - */ -int prcmu_get_ape_opp(void) -{ - return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP); -} - -/** - * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage - * @enable: true to request the higher voltage, false to drop a request. - * - * Calls to this function to enable and disable requests must be balanced. - */ -int prcmu_request_ape_opp_100_voltage(bool enable) -{ - int r = 0; - u8 header; - static unsigned int requests; - - mutex_lock(&mb1_transfer.lock); - - if (enable) { - if (0 != requests++) - goto unlock_and_return; - header = MB1H_REQUEST_APE_OPP_100_VOLT; - } else { - if (requests == 0) { - r = -EIO; - goto unlock_and_return; - } else if (1 != requests--) { - goto unlock_and_return; - } - header = MB1H_RELEASE_APE_OPP_100_VOLT; - } - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb1_transfer.work); - - if ((mb1_transfer.ack.header != header) || - ((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0)) - r = -EIO; - -unlock_and_return: - mutex_unlock(&mb1_transfer.lock); - - return r; -} - -/** - * prcmu_release_usb_wakeup_state - release the state required by a USB wakeup - * - * This function releases the power state requirements of a USB wakeup. - */ -int prcmu_release_usb_wakeup_state(void) -{ - int r = 0; - - mutex_lock(&mb1_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(MB1H_RELEASE_USB_WAKEUP, - (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb1_transfer.work); - - if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) || - ((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0)) - r = -EIO; - - mutex_unlock(&mb1_transfer.lock); - - return r; -} - -static int request_pll(u8 clock, bool enable) -{ - int r = 0; - - if (clock == PRCMU_PLLSOC1) - clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); - else - return -EINVAL; - - mutex_lock(&mb1_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF)); - - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb1_transfer.work); - - if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF) - r = -EIO; - - mutex_unlock(&mb1_transfer.lock); - - return r; -} - -/** - * prcmu_set_hwacc - set the power state of a h/w accelerator - * @hwacc_dev: The hardware accelerator (enum hw_acc_dev). - * @state: The new power state (enum hw_acc_state). - * - * This function sets the power state of a hardware accelerator. - * This function should not be called from interrupt context. - * - * NOTE! Deprecated, to be removed when all users switched over to use the - * regulator framework API. - */ -int prcmu_set_hwacc(u16 hwacc_dev, u8 state) -{ - int r = 0; - bool ram_retention = false; - bool enable, enable_ret; - - /* check argument */ - BUG_ON(hwacc_dev >= NUM_HW_ACC); - - /* get state of switches */ - enable = hwacc_enabled[hwacc_dev]; - enable_ret = hwacc_ret_enabled[hwacc_dev]; - - /* set flag if retention is possible */ - switch (hwacc_dev) { - case HW_ACC_SVAMMDSP: - case HW_ACC_SIAMMDSP: - case HW_ACC_ESRAM1: - case HW_ACC_ESRAM2: - case HW_ACC_ESRAM3: - case HW_ACC_ESRAM4: - ram_retention = true; - break; - } - - /* check argument */ - BUG_ON(state > HW_ON); - BUG_ON(state == HW_OFF_RAMRET && !ram_retention); - - /* modify enable flags */ - switch (state) { - case HW_OFF: - enable_ret = false; - enable = false; - break; - case HW_ON: - enable = true; - break; - case HW_OFF_RAMRET: - enable_ret = true; - enable = false; - break; - } - - /* get regulator (lazy) */ - if (hwacc_regulator[hwacc_dev] == NULL) { - hwacc_regulator[hwacc_dev] = regulator_get(NULL, - hwacc_regulator_name[hwacc_dev]); - if (IS_ERR(hwacc_regulator[hwacc_dev])) { - pr_err("prcmu: failed to get supply %s\n", - hwacc_regulator_name[hwacc_dev]); - r = PTR_ERR(hwacc_regulator[hwacc_dev]); - goto out; - } - } - - if (ram_retention) { - if (hwacc_ret_regulator[hwacc_dev] == NULL) { - hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL, - hwacc_ret_regulator_name[hwacc_dev]); - if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) { - pr_err("prcmu: failed to get supply %s\n", - hwacc_ret_regulator_name[hwacc_dev]); - r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]); - goto out; - } - } - } - - /* set regulators */ - if (ram_retention) { - if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) { - r = regulator_enable(hwacc_ret_regulator[hwacc_dev]); - if (r < 0) { - pr_err("prcmu_set_hwacc: ret enable failed\n"); - goto out; - } - hwacc_ret_enabled[hwacc_dev] = true; - } - } - - if (enable && !hwacc_enabled[hwacc_dev]) { - r = regulator_enable(hwacc_regulator[hwacc_dev]); - if (r < 0) { - pr_err("prcmu_set_hwacc: enable failed\n"); - goto out; - } - hwacc_enabled[hwacc_dev] = true; - } - - if (!enable && hwacc_enabled[hwacc_dev]) { - r = regulator_disable(hwacc_regulator[hwacc_dev]); - if (r < 0) { - pr_err("prcmu_set_hwacc: disable failed\n"); - goto out; - } - hwacc_enabled[hwacc_dev] = false; - } - - if (ram_retention) { - if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) { - r = regulator_disable(hwacc_ret_regulator[hwacc_dev]); - if (r < 0) { - pr_err("prcmu_set_hwacc: ret disable failed\n"); - goto out; - } - hwacc_ret_enabled[hwacc_dev] = false; - } - } - -out: - return r; -} -EXPORT_SYMBOL(prcmu_set_hwacc); - -/** - * prcmu_set_epod - set the state of a EPOD (power domain) - * @epod_id: The EPOD to set - * @epod_state: The new EPOD state - * - * This function sets the state of a EPOD (power domain). It may not be called - * from interrupt context. - */ -int prcmu_set_epod(u16 epod_id, u8 epod_state) -{ - int r = 0; - bool ram_retention = false; - int i; - - /* check argument */ - BUG_ON(epod_id >= NUM_EPOD_ID); - - /* set flag if retention is possible */ - switch (epod_id) { - case EPOD_ID_SVAMMDSP: - case EPOD_ID_SIAMMDSP: - case EPOD_ID_ESRAM12: - case EPOD_ID_ESRAM34: - ram_retention = true; - break; - } - - /* check argument */ - BUG_ON(epod_state > EPOD_STATE_ON); - BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention); - - /* get lock */ - mutex_lock(&mb2_transfer.lock); - - /* wait for mailbox */ - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) - cpu_relax(); - - /* fill in mailbox */ - for (i = 0; i < NUM_EPOD_ID; i++) - writeb(EPOD_STATE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB2 + i)); - writeb(epod_state, (tcdm_base + PRCM_REQ_MB2 + epod_id)); - - writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2)); - - writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - /* - * The current firmware version does not handle errors correctly, - * 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_transfer.work, - msecs_to_jiffies(20000))) { - pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", - __func__); - r = -EIO; - goto unlock_and_return; - } - - if (mb2_transfer.ack.status != HWACC_PWR_ST_OK) - r = -EIO; - -unlock_and_return: - mutex_unlock(&mb2_transfer.lock); - return r; -} - -/** - * prcmu_configure_auto_pm - Configure autonomous power management. - * @sleep: Configuration for ApSleep. - * @idle: Configuration for ApIdle. - */ -void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep, - struct prcmu_auto_pm_config *idle) -{ - u32 sleep_cfg; - u32 idle_cfg; - unsigned long flags; - - BUG_ON((sleep == NULL) || (idle == NULL)); - - sleep_cfg = (sleep->sva_auto_pm_enable & 0xF); - sleep_cfg = ((sleep_cfg << 4) | (sleep->sia_auto_pm_enable & 0xF)); - sleep_cfg = ((sleep_cfg << 8) | (sleep->sva_power_on & 0xFF)); - sleep_cfg = ((sleep_cfg << 8) | (sleep->sia_power_on & 0xFF)); - sleep_cfg = ((sleep_cfg << 4) | (sleep->sva_policy & 0xF)); - sleep_cfg = ((sleep_cfg << 4) | (sleep->sia_policy & 0xF)); - - idle_cfg = (idle->sva_auto_pm_enable & 0xF); - idle_cfg = ((idle_cfg << 4) | (idle->sia_auto_pm_enable & 0xF)); - idle_cfg = ((idle_cfg << 8) | (idle->sva_power_on & 0xFF)); - idle_cfg = ((idle_cfg << 8) | (idle->sia_power_on & 0xFF)); - idle_cfg = ((idle_cfg << 4) | (idle->sva_policy & 0xF)); - idle_cfg = ((idle_cfg << 4) | (idle->sia_policy & 0xF)); - - spin_lock_irqsave(&mb2_transfer.auto_pm_lock, flags); - - /* - * The autonomous power management configuration is done through - * fields in mailbox 2, but these fields are only used as shared - * variables - i.e. there is no need to send a message. - */ - writel(sleep_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_SLEEP)); - writel(idle_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_IDLE)); - - mb2_transfer.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_transfer.auto_pm_lock, flags); -} -EXPORT_SYMBOL(prcmu_configure_auto_pm); - -bool prcmu_is_auto_pm_enabled(void) -{ - return mb2_transfer.auto_pm_enabled; -} - -static int request_sysclk(bool enable) -{ - int r; - unsigned long flags; - - r = 0; - - mutex_lock(&mb3_transfer.sysclk_lock); - - spin_lock_irqsave(&mb3_transfer.lock, flags); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) - cpu_relax(); - - writeb((enable ? 1 : 0), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT)); - - writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3)); - writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - spin_unlock_irqrestore(&mb3_transfer.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_transfer.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_transfer.sysclk_lock); - - return r; -} - -static int request_timclk(bool enable) -{ - u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); - - if (!enable) - val |= PRCM_TCR_STOP_TIMERS; - writel(val, (_PRCMU_BASE + PRCM_TCR)); - - return 0; -} - -static int request_reg_clock(u8 clock, bool enable) -{ - u32 val; - unsigned long flags; - - spin_lock_irqsave(&clk_mgt_lock, flags); - - /* Grab the HW semaphore. */ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) - cpu_relax(); - - val = readl(_PRCMU_BASE + clk_mgt[clock].offset); - if (enable) { - val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); - } else { - clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); - val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); - } - writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); - - /* Release the HW semaphore. */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); - - spin_unlock_irqrestore(&clk_mgt_lock, flags); - - return 0; -} - -static int request_sga_clock(u8 clock, bool enable) -{ - u32 val; - int ret; - - if (enable) { - val = readl(_PRCMU_BASE + PRCM_CGATING_BYPASS); - writel(val | PRCM_CGATING_BYPASS_ICN2, - _PRCMU_BASE + PRCM_CGATING_BYPASS); - } - - ret = request_reg_clock(clock, enable); - - if (!ret && !enable) { - val = readl(_PRCMU_BASE + PRCM_CGATING_BYPASS); - writel(val & ~PRCM_CGATING_BYPASS_ICN2, - _PRCMU_BASE + PRCM_CGATING_BYPASS); - } - - return ret; -} - -/** - * 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). - * - * This function should only be used by the clock implementation. - * Do not use it from any other place! - */ -int prcmu_request_clock(u8 clock, bool enable) -{ - if (clock == PRCMU_SGACLK) - return request_sga_clock(clock, enable); - else if (clock < PRCMU_NUM_REG_CLOCKS) - return request_reg_clock(clock, enable); - else if (clock == PRCMU_TIMCLK) - return request_timclk(enable); - else if (clock == PRCMU_SYSCLK) - return request_sysclk(enable); - else if (clock == PRCMU_PLLSOC1) - return request_pll(clock, enable); - else - return -EINVAL; -} - -int prcmu_config_esram0_deep_sleep(u8 state) -{ - if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || - (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) - return -EINVAL; - - mutex_lock(&mb4_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) - cpu_relax(); - - writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); - writeb(((DDR_PWR_STATE_OFFHIGHLAT << 4) | DDR_PWR_STATE_ON), - (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE)); - writeb(DDR_PWR_STATE_ON, - (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE)); - writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST)); - - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb4_transfer.work); - - mutex_unlock(&mb4_transfer.lock); - - return 0; -} - -int prcmu_config_hotdog(u8 threshold) -{ - mutex_lock(&mb4_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) - cpu_relax(); - - writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD)); - writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); - - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb4_transfer.work); - - mutex_unlock(&mb4_transfer.lock); - - return 0; -} - -int prcmu_config_hotmon(u8 low, u8 high) -{ - mutex_lock(&mb4_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) - cpu_relax(); - - writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW)); - writeb(high, (tcdm_base + PRCM_REQ_MB4_HOTMON_HIGH)); - writeb((HOTMON_CONFIG_LOW | HOTMON_CONFIG_HIGH), - (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG)); - writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); - - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb4_transfer.work); - - mutex_unlock(&mb4_transfer.lock); - - return 0; -} - -static int config_hot_period(u16 val) -{ - mutex_lock(&mb4_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) - cpu_relax(); - - writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD)); - writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); - - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb4_transfer.work); - - mutex_unlock(&mb4_transfer.lock); - - return 0; -} - -int prcmu_start_temp_sense(u16 cycles32k) -{ - if (cycles32k == 0xFFFF) - return -EINVAL; - - return config_hot_period(cycles32k); -} - -int prcmu_stop_temp_sense(void) -{ - return config_hot_period(0xFFFF); -} - -/** - * prcmu_set_clock_divider() - Configure the clock divider. - * @clock: The clock for which the request is made. - * @divider: The clock divider. (< 32) - * - * This function should only be used by the clock implementation. - * Do not use it from any other place! - */ -int prcmu_set_clock_divider(u8 clock, u8 divider) -{ - u32 val; - unsigned long flags; - - if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider)) - return -EINVAL; - - spin_lock_irqsave(&clk_mgt_lock, flags); - - /* Grab the HW semaphore. */ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) - cpu_relax(); - - val = readl(_PRCMU_BASE + clk_mgt[clock].offset); - val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK); - val |= (u32)divider; - writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); - - /* Release the HW semaphore. */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); - - spin_unlock_irqrestore(&clk_mgt_lock, flags); - - return 0; -} - -/** - * prcmu_abb_read() - Read register value(s) from the ABB. - * @slave: The I2C slave address. - * @reg: The (start) register address. - * @value: The read out value(s). - * @size: The number of registers to read. - * - * Reads register value(s) from the ABB. - * @size has to be 1 for the current firmware version. - */ -int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) -{ - int r; - - if (size != 1) - return -EINVAL; - - mutex_lock(&mb5_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) - cpu_relax(); - - writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); - writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); - writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); - writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); - - writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - if (!wait_for_completion_timeout(&mb5_transfer.work, - msecs_to_jiffies(20000))) { - pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", - __func__); - r = -EIO; - } else { - r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO); - } - - if (!r) - *value = mb5_transfer.ack.value; - - mutex_unlock(&mb5_transfer.lock); - - return r; -} - -/** - * prcmu_abb_write() - Write register value(s) to the ABB. - * @slave: The I2C slave address. - * @reg: The (start) register address. - * @value: The value(s) to write. - * @size: The number of registers to write. - * - * Reads register value(s) from the ABB. - * @size has to be 1 for the current firmware version. - */ -int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) -{ - int r; - - if (size != 1) - return -EINVAL; - - mutex_lock(&mb5_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) - cpu_relax(); - - writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); - writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS)); - writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); - writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); - - writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - if (!wait_for_completion_timeout(&mb5_transfer.work, - msecs_to_jiffies(20000))) { - pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", - __func__); - r = -EIO; - } else { - r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO); - } - - mutex_unlock(&mb5_transfer.lock); - - return r; -} - -/** - * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem - */ -void prcmu_ac_wake_req(void) -{ - u32 val; - - mutex_lock(&mb0_transfer.ac_wake_lock); - - val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); - if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ) - goto unlock_and_return; - - atomic_set(&ac_wake_req_state, 1); - - writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), - (_PRCMU_BASE + 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", - __func__); - } - -unlock_and_return: - mutex_unlock(&mb0_transfer.ac_wake_lock); -} - -/** - * prcmu_ac_sleep_req - called when ARM no longer needs to talk to modem - */ -void prcmu_ac_sleep_req() -{ - u32 val; - - mutex_lock(&mb0_transfer.ac_wake_lock); - - val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); - if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)) - goto unlock_and_return; - - writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), - (_PRCMU_BASE + 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", - __func__); - } - - atomic_set(&ac_wake_req_state, 0); - -unlock_and_return: - mutex_unlock(&mb0_transfer.ac_wake_lock); -} - -bool prcmu_is_ac_wake_requested(void) -{ - return (atomic_read(&ac_wake_req_state) != 0); -} - -/** - * prcmu_system_reset - System reset - * - * Saves the reset reason code and then sets the APE_SOFTRST register which - * fires interrupt to fw - */ -void prcmu_system_reset(u16 reset_code) -{ - writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON)); - writel(1, (_PRCMU_BASE + PRCM_APE_SOFTRST)); -} - -/** - * 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) -{ - return readw(tcdm_base + PRCM_SW_RST_REASON); -} - -/** - * prcmu_reset_modem - ask the PRCMU to reset modem - */ -void prcmu_modem_reset(void) -{ - mutex_lock(&mb1_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb1_transfer.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_transfer.lock); -} - -static void ack_dbb_wakeup(void) -{ - unsigned long flags; - - spin_lock_irqsave(&mb0_transfer.lock, flags); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) - cpu_relax(); - - writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - spin_unlock_irqrestore(&mb0_transfer.lock, flags); -} - -static inline void print_unknown_header_warning(u8 n, u8 header) -{ - pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n", - header, n); -} - -static bool read_mailbox_0(void) -{ - bool r; - u32 ev; - unsigned int n; - u8 header; - - header = readb(tcdm_base + PRCM_MBOX_HEADER_ACK_MB0); - switch (header) { - case MB0H_WAKEUP_EXE: - case MB0H_WAKEUP_SLEEP: - if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1) - ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_1_8500); - else - ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_0_8500); - - if (ev & (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK)) - complete(&mb0_transfer.ac_wake_work); - if (ev & WAKEUP_BIT_SYSCLK_OK) - complete(&mb3_transfer.sysclk_work); - - ev &= mb0_transfer.req.dbb_irqs; - - for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) { - if (ev & prcmu_irq_bit[n]) - generic_handle_irq(IRQ_PRCMU_BASE + n); - } - r = true; - break; - default: - print_unknown_header_warning(0, header); - r = false; - break; - } - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - return r; -} - -static bool read_mailbox_1(void) -{ - mb1_transfer.ack.header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB1); - mb1_transfer.ack.arm_opp = readb(tcdm_base + - PRCM_ACK_MB1_CURRENT_ARM_OPP); - mb1_transfer.ack.ape_opp = readb(tcdm_base + - PRCM_ACK_MB1_CURRENT_APE_OPP); - mb1_transfer.ack.ape_voltage_status = readb(tcdm_base + - PRCM_ACK_MB1_APE_VOLTAGE_STATUS); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - complete(&mb1_transfer.work); - return false; -} - -static bool read_mailbox_2(void) -{ - mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS); - writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - complete(&mb2_transfer.work); - return false; -} - -static bool read_mailbox_3(void) -{ - writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - return false; -} - -static bool read_mailbox_4(void) -{ - u8 header; - bool do_complete = true; - - header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB4); - switch (header) { - case MB4H_MEM_ST: - case MB4H_HOTDOG: - case MB4H_HOTMON: - case MB4H_HOT_PERIOD: - break; - default: - print_unknown_header_warning(4, header); - do_complete = false; - break; - } - - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - - if (do_complete) - complete(&mb4_transfer.work); - - return false; -} - -static bool read_mailbox_5(void) -{ - mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS); - mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL); - writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - complete(&mb5_transfer.work); - return false; -} - -static bool read_mailbox_6(void) -{ - writel(MBOX_BIT(6), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - return false; -} - -static bool read_mailbox_7(void) -{ - writel(MBOX_BIT(7), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - return false; -} - -static bool (* const read_mailbox[NUM_MB])(void) = { - read_mailbox_0, - read_mailbox_1, - read_mailbox_2, - read_mailbox_3, - read_mailbox_4, - read_mailbox_5, - read_mailbox_6, - read_mailbox_7 -}; - -static irqreturn_t prcmu_irq_handler(int irq, void *data) -{ - u32 bits; - u8 n; - irqreturn_t r; - - bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); - if (unlikely(!bits)) - return IRQ_NONE; - - r = IRQ_HANDLED; - for (n = 0; bits; n++) { - if (bits & MBOX_BIT(n)) { - bits -= MBOX_BIT(n); - if (read_mailbox[n]()) - r = IRQ_WAKE_THREAD; - } - } - return r; -} - -static irqreturn_t prcmu_irq_thread_fn(int irq, void *data) -{ - ack_dbb_wakeup(); - 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_PRCMU_BASE]; - - spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); - - if (d->irq != IRQ_PRCMU_CA_SLEEP) - 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_PRCMU_BASE]; - - spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); - - if (d->irq != IRQ_PRCMU_CA_SLEEP) - 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 prcmu_early_init(void) -{ - unsigned int i; - - void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K); - - if (tcpm_base != NULL) { - int version; - version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); - prcmu_version.project_number = version & 0xFF; - prcmu_version.api_version = (version >> 8) & 0xFF; - prcmu_version.func_version = (version >> 16) & 0xFF; - prcmu_version.errata = (version >> 24) & 0xFF; - pr_info("PRCMU firmware version %d.%d.%d\n", - (version >> 8) & 0xFF, (version >> 16) & 0xFF, - (version >> 24) & 0xFF); - iounmap(tcpm_base); - } - tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); - - spin_lock_init(&mb0_transfer.lock); - spin_lock_init(&mb0_transfer.dbb_irqs_lock); - mutex_init(&mb0_transfer.ac_wake_lock); - init_completion(&mb0_transfer.ac_wake_work); - mutex_init(&mb1_transfer.lock); - init_completion(&mb1_transfer.work); - mutex_init(&mb2_transfer.lock); - init_completion(&mb2_transfer.work); - spin_lock_init(&mb2_transfer.auto_pm_lock); - spin_lock_init(&mb3_transfer.lock); - mutex_init(&mb3_transfer.sysclk_lock); - init_completion(&mb3_transfer.sysclk_work); - mutex_init(&mb4_transfer.lock); - init_completion(&mb4_transfer.work); - mutex_init(&mb5_transfer.lock); - init_completion(&mb5_transfer.work); - - INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); - - /* Initalize irqs. */ - for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) { - unsigned int irq; - - irq = IRQ_PRCMU_BASE + i; - set_irq_chip(irq, &prcmu_irq_chip); - set_irq_flags(irq, IRQF_VALID); - set_irq_handler(irq, handle_simple_irq); - } -} - -static void __init init_prcm_registers(void) -{ - u32 val; - - val = readl(_PRCMU_BASE + PRCM_A9PL_FORCE_CLKEN); - val &= ~(PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN | - PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN); - writel(val, (_PRCMU_BASE + PRCM_A9PL_FORCE_CLKEN)); -} - -/** - * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic - * - */ -int __init prcmu_init(void) -{ - int err = 0; - - if (ux500_is_svp()) - return -ENODEV; - - init_prcm_registers(); - - /* Clean up the mailbox interrupts after pre-kernel code. */ - writel(ALL_MBOX_BITS, (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); - - err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, - prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); - if (err < 0) { - pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n"); - err = -EBUSY; - goto no_irq_return; - } - - if (cpu_is_u8500v20_or_later()) - prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); - - if (prcmu_debug_init()) - pr_err("prcmu: Failed to initialize debugfs\n"); - -no_irq_return: - return err; -} - -arch_initcall(prcmu_init); diff --git a/arch/arm/mach-ux500/prcmu-regs-db5500.h b/arch/arm/mach-ux500/prcmu-regs-db5500.h deleted file mode 100644 index 331609a918c..00000000000 --- a/arch/arm/mach-ux500/prcmu-regs-db5500.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - */ - -#ifndef __MACH_PRCMU_REGS_DB5500_H -#define __MACH_PRCMU_REGS_DB5500_H - -#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) - -#define PRCM_TCR 0x1C8 -#define PRCM_TCR_TENSEL_MASK BITS(0, 7) -#define PRCM_TCR_STOP_TIMERS BIT(16) -#define PRCM_TCR_DOZE_MODE BIT(17) - -/* PRCMU HW semaphore */ -#define PRCM_SEM 0x400 -#define PRCM_SEM_PRCM_SEM BIT(0) - -#define DB5500_PRCM_SVACLK_MGT 0x008 -#define DB5500_PRCM_SIACLK_MGT 0x00C -#define DB5500_PRCM_SGACLK_MGT 0x014 -#define DB5500_PRCM_UARTCLK_MGT 0x018 -#define DB5500_PRCM_MSP02CLK_MGT 0x01C -#define DB5500_PRCM_I2CCLK_MGT 0x020 -#define DB5500_PRCM_SDMMCCLK_MGT 0x024 -#define DB5500_PRCM_PER1CLK_MGT 0x02C -#define DB5500_PRCM_PER2CLK_MGT 0x030 -#define DB5500_PRCM_PER3CLK_MGT 0x034 -#define DB5500_PRCM_PER5CLK_MGT 0x038 -#define DB5500_PRCM_PER6CLK_MGT 0x03C -#define DB5500_PRCM_PWMCLK_MGT 0x044 -#define DB5500_PRCM_IRDACLK_MGT 0x048 -#define DB5500_PRCM_IRRCCLK_MGT 0x04C -#define DB5500_PRCM_HDMICLK_MGT 0x058 -#define DB5500_PRCM_APEATCLK_MGT 0x05C -#define DB5500_PRCM_APETRACECLK_MGT 0x060 -#define DB5500_PRCM_MCDECLK_MGT 0x064 -#define DB5500_PRCM_DSIALTCLK_MGT 0x06C -#define DB5500_PRCM_DMACLK_MGT 0x074 -#define DB5500_PRCM_B2R2CLK_MGT 0x078 -#define DB5500_PRCM_TVCLK_MGT 0x07C -#define DB5500_PRCM_RNGCLK_MGT 0x284 - -#define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) -#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) -#define PRCM_CLK_MGT_CLKEN BIT(8) - -#define PRCM_CLKOCR 0x1CC -#define PRCM_CLKOCR_CLKOUT0_REF_CLK (1 << 0) -#define PRCM_CLKOCR_CLKOUT0_MASK BITS(0, 13) -#define PRCM_CLKOCR_CLKOUT1_REF_CLK (1 << 16) -#define PRCM_CLKOCR_CLKOUT1_MASK BITS(16, 29) - -#define PRCM_ARM_IT1_CLEAR 0x48C -#define PRCM_ARM_IT1_VAL 0x494 - -/* CPU mailbox registers */ -#define PRCM_MBOX_CPU_VAL 0x0FC -#define PRCM_MBOX_CPU_SET 0x100 - -/* PRCMU clock/PLL/reset registers */ -#define PRCM_PLLDSI_FREQ 0x500 -#define PRCM_PLLDSI_ENABLE 0x504 -#define PRCM_PLLDSI_LOCKP 0x508 -#define PRCM_DSI_PLLOUT_SEL 0x530 -#define PRCM_DSITVCLK_DIV 0x52C -#define PRCM_APE_RESETN_SET 0x1E4 -#define PRCM_APE_RESETN_CLR 0x1E8 - -#define PRCM_MMIP_LS_CLAMP_SET 0x420 -#define PRCM_MMIP_LS_CLAMP_CLR 0x424 - -/* Miscellaneous unit registers */ -#define PRCM_DSI_SW_RESET 0x324 -#define PRCM_RESOUTN_SET_OFFSET 0x214 -#define PRCM_RESOUTN_CLR_OFFSET 0x218 - -#endif diff --git a/arch/arm/mach-ux500/prcmu-regs-db8500.h b/arch/arm/mach-ux500/prcmu-regs-db8500.h deleted file mode 100644 index 1014ea340cf..00000000000 --- a/arch/arm/mach-ux500/prcmu-regs-db8500.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2009 ST-Ericsson SA - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - */ -#ifndef __MACH_PRCMU_REGS_H -#define __MACH_PRCMU_REGS_H - -#include <linux/bitops.h> -#include <mach/hardware.h> - -#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) - -#define PRCM_ARM_PLLDIVPS 0x118 -#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE BITS(0, 5) -#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xF - -#define PRCM_PLLARM_LOCKP 0x0A8 -#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 BIT(1) - -#define PRCM_ARM_CHGCLKREQ 0x114 -#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0) - -#define PRCM_PLLARM_ENABLE 0x98 -#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE BIT(0) -#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON BIT(8) - -#define PRCM_ARMCLKFIX_MGT 0x0 -#define PRCM_A9PL_FORCE_CLKEN 0x19C -#define PRCM_A9_RESETN_CLR 0x1f4 -#define PRCM_A9_RESETN_SET 0x1f0 -#define PRCM_ARM_LS_CLAMP 0x30C -#define PRCM_SRAM_A9 0x308 - -#define PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN BIT(0) -#define PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN BIT(1) - -/* ARM WFI Standby signal register */ -#define PRCM_ARM_WFI_STANDBY 0x130 -#define PRCM_IOCR 0x310 -#define PRCM_IOCR_IOFORCE BIT(0) - -/* CPU mailbox registers */ -#define PRCM_MBOX_CPU_VAL 0x0FC -#define PRCM_MBOX_CPU_SET 0x100 - -/* Dual A9 core interrupt management unit registers */ -#define PRCM_A9_MASK_REQ 0x328 -#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ BIT(0) - -#define PRCM_A9_MASK_ACK 0x32C -#define PRCM_ARMITMSK31TO0 0x11C -#define PRCM_ARMITMSK63TO32 0x120 -#define PRCM_ARMITMSK95TO64 0x124 -#define PRCM_ARMITMSK127TO96 0x128 -#define PRCM_POWER_STATE_VAL 0x25C -#define PRCM_ARMITVAL31TO0 0x260 -#define PRCM_ARMITVAL63TO32 0x264 -#define PRCM_ARMITVAL95TO64 0x268 -#define PRCM_ARMITVAL127TO96 0x26C - -#define PRCM_HOSTACCESS_REQ 0x334 -#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ BIT(0) - -#define PRCM_ARM_IT1_CLR 0x48C -#define PRCM_ARM_IT1_VAL 0x494 - -#define PRCM_ITSTATUS0 0x148 -#define PRCM_ITSTATUS1 0x150 -#define PRCM_ITSTATUS2 0x158 -#define PRCM_ITSTATUS3 0x160 -#define PRCM_ITSTATUS4 0x168 -#define PRCM_ITSTATUS5 0x484 -#define PRCM_ITCLEAR5 0x488 -#define PRCM_ARMIT_MASKXP70_IT 0x1018 - -/* System reset register */ -#define PRCM_APE_SOFTRST 0x228 - -/* Level shifter and clamp control registers */ -#define PRCM_MMIP_LS_CLAMP_SET 0x420 -#define PRCM_MMIP_LS_CLAMP_CLR 0x424 - -/* PRCMU HW semaphore */ -#define PRCM_SEM 0x400 -#define PRCM_SEM_PRCM_SEM BIT(0) - -/* PRCMU clock/PLL/reset registers */ -#define PRCM_PLLDSI_FREQ 0x500 -#define PRCM_PLLDSI_ENABLE 0x504 -#define PRCM_PLLDSI_LOCKP 0x508 -#define PRCM_DSI_PLLOUT_SEL 0x530 -#define PRCM_DSITVCLK_DIV 0x52C -#define PRCM_APE_RESETN_SET 0x1E4 -#define PRCM_APE_RESETN_CLR 0x1E8 - -#define PRCM_TCR 0x1C8 -#define PRCM_TCR_TENSEL_MASK BITS(0, 7) -#define PRCM_TCR_STOP_TIMERS BIT(16) -#define PRCM_TCR_DOZE_MODE BIT(17) - -#define PRCM_CLKOCR 0x1CC -#define PRCM_CLKOCR_CLKODIV0_SHIFT 0 -#define PRCM_CLKOCR_CLKODIV0_MASK BITS(0, 5) -#define PRCM_CLKOCR_CLKOSEL0_SHIFT 6 -#define PRCM_CLKOCR_CLKOSEL0_MASK BITS(6, 8) -#define PRCM_CLKOCR_CLKODIV1_SHIFT 16 -#define PRCM_CLKOCR_CLKODIV1_MASK BITS(16, 21) -#define PRCM_CLKOCR_CLKOSEL1_SHIFT 22 -#define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24) -#define PRCM_CLKOCR_CLK1TYPE BIT(28) - -#define PRCM_SGACLK_MGT 0x014 -#define PRCM_UARTCLK_MGT 0x018 -#define PRCM_MSP02CLK_MGT 0x01C -#define PRCM_MSP1CLK_MGT 0x288 -#define PRCM_I2CCLK_MGT 0x020 -#define PRCM_SDMMCCLK_MGT 0x024 -#define PRCM_SLIMCLK_MGT 0x028 -#define PRCM_PER1CLK_MGT 0x02C -#define PRCM_PER2CLK_MGT 0x030 -#define PRCM_PER3CLK_MGT 0x034 -#define PRCM_PER5CLK_MGT 0x038 -#define PRCM_PER6CLK_MGT 0x03C -#define PRCM_PER7CLK_MGT 0x040 -#define PRCM_LCDCLK_MGT 0x044 -#define PRCM_BMLCLK_MGT 0x04C -#define PRCM_HSITXCLK_MGT 0x050 -#define PRCM_HSIRXCLK_MGT 0x054 -#define PRCM_HDMICLK_MGT 0x058 -#define PRCM_APEATCLK_MGT 0x05C -#define PRCM_APETRACECLK_MGT 0x060 -#define PRCM_MCDECLK_MGT 0x064 -#define PRCM_IPI2CCLK_MGT 0x068 -#define PRCM_DSIALTCLK_MGT 0x06C -#define PRCM_DMACLK_MGT 0x074 -#define PRCM_B2R2CLK_MGT 0x078 -#define PRCM_TVCLK_MGT 0x07C -#define PRCM_UNIPROCLK_MGT 0x278 -#define PRCM_SSPCLK_MGT 0x280 -#define PRCM_RNGCLK_MGT 0x284 -#define PRCM_UICCCLK_MGT 0x27C - -#define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) -#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) -#define PRCM_CLK_MGT_CLKEN BIT(8) - -/* ePOD and memory power signal control registers */ -#define PRCM_EPOD_C_SET 0x410 -#define PRCM_SRAM_LS_SLEEP 0x304 - -/* Debug power control unit registers */ -#define PRCM_POWER_STATE_SET 0x254 - -/* Miscellaneous unit registers */ -#define PRCM_DSI_SW_RESET 0x324 -#define PRCM_GPIOCR 0x138 - -/* GPIOCR register */ -#define PRCM_GPIOCR_SPI2_SELECT BIT(23) - -#define PRCM_DDR_SUBSYS_APE_MINBW 0x438 - -#define PRCM_CGATING_BYPASS 0x134 -#define PRCM_CGATING_BYPASS_ICN2 BIT(6) - -#endif /* __MACH_PRCMU__REGS_H */ diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index 298962fd5ee..4943578f452 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -12,7 +12,7 @@ #include <linux/cpufreq.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/mfd/db8500-prcmu.h> +#include <mach/prcmu.h> #include <mach/id.h> static struct cpufreq_frequency_table freq_table[] = { diff --git a/drivers/mfd/ab8500-i2c.c b/drivers/mfd/ab8500-i2c.c index 5d44b82d1c0..dda0745a471 100644 --- a/drivers/mfd/ab8500-i2c.c +++ b/drivers/mfd/ab8500-i2c.c @@ -11,8 +11,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/mfd/ab8500.h> -#include <linux/mfd/db8500-prcmu.h> -#include <mach/prcmu-fw-api.h> +#include <mach/prcmu.h> static int ab8500_i2c_write(struct ab8500 *ab8500, u16 addr, u8 data) diff --git a/drivers/mfd/db5500-prcmu-regs.h b/drivers/mfd/db5500-prcmu-regs.h deleted file mode 100644 index 9a8e9e4ddd3..00000000000 --- a/drivers/mfd/db5500-prcmu-regs.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> - * Author: Sundar Iyer <sundar.iyer@stericsson.com> - * - * License Terms: GNU General Public License v2 - * - * PRCM Unit registers - */ - -#ifndef __MACH_PRCMU_REGS_H -#define __MACH_PRCMU_REGS_H - -#include <mach/hardware.h> - -#define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118) -#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f -#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xf - -#define PRCM_PLLARM_LOCKP (_PRCMU_BASE + 0x0a8) -#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 0x2 - -#define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114) -#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ 0x1 - -#define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98) -#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE 0x1 -#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON 0x100 - -#define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0) -#define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4) -#define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0) -#define PRCM_ARM_LS_CLAMP (_PRCMU_BASE + 0x30c) -#define PRCM_SRAM_A9 (_PRCMU_BASE + 0x308) - -/* ARM WFI Standby signal register */ -#define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130) -#define PRCM_IOCR (_PRCMU_BASE + 0x310) -#define PRCM_IOCR_IOFORCE 0x1 - -/* CPU mailbox registers */ -#define PRCM_MBOX_CPU_VAL (_PRCMU_BASE + 0x0fc) -#define PRCM_MBOX_CPU_SET (_PRCMU_BASE + 0x100) -#define PRCM_MBOX_CPU_CLR (_PRCMU_BASE + 0x104) - -/* Dual A9 core interrupt management unit registers */ -#define PRCM_A9_MASK_REQ (_PRCMU_BASE + 0x328) -#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ 0x1 - -#define PRCM_A9_MASK_ACK (_PRCMU_BASE + 0x32c) -#define PRCM_ARMITMSK31TO0 (_PRCMU_BASE + 0x11c) -#define PRCM_ARMITMSK63TO32 (_PRCMU_BASE + 0x120) -#define PRCM_ARMITMSK95TO64 (_PRCMU_BASE + 0x124) -#define PRCM_ARMITMSK127TO96 (_PRCMU_BASE + 0x128) -#define PRCM_POWER_STATE_VAL (_PRCMU_BASE + 0x25C) -#define PRCM_ARMITVAL31TO0 (_PRCMU_BASE + 0x260) -#define PRCM_ARMITVAL63TO32 (_PRCMU_BASE + 0x264) -#define PRCM_ARMITVAL95TO64 (_PRCMU_BASE + 0x268) -#define PRCM_ARMITVAL127TO96 (_PRCMU_BASE + 0x26C) - -#define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334) -#define ARM_WAKEUP_MODEM 0x1 - -#define PRCM_ARM_IT1_CLEAR (_PRCMU_BASE + 0x48C) -#define PRCM_ARM_IT1_VAL (_PRCMU_BASE + 0x494) -#define PRCM_HOLD_EVT (_PRCMU_BASE + 0x174) - -#define PRCM_ITSTATUS0 (_PRCMU_BASE + 0x148) -#define PRCM_ITSTATUS1 (_PRCMU_BASE + 0x150) -#define PRCM_ITSTATUS2 (_PRCMU_BASE + 0x158) -#define PRCM_ITSTATUS3 (_PRCMU_BASE + 0x160) -#define PRCM_ITSTATUS4 (_PRCMU_BASE + 0x168) -#define PRCM_ITSTATUS5 (_PRCMU_BASE + 0x484) -#define PRCM_ITCLEAR5 (_PRCMU_BASE + 0x488) -#define PRCM_ARMIT_MASKXP70_IT (_PRCMU_BASE + 0x1018) - -/* System reset register */ -#define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228) - -/* Level shifter and clamp control registers */ -#define PRCM_MMIP_LS_CLAMP_SET (_PRCMU_BASE + 0x420) -#define PRCM_MMIP_LS_CLAMP_CLR (_PRCMU_BASE + 0x424) - -/* PRCMU clock/PLL/reset registers */ -#define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500) -#define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504) -#define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) -#define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044) -#define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064) -#define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058) -#define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c) -#define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530) -#define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C) -#define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508) -#define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4) -#define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8) -#define PRCM_CLKOCR (_PRCMU_BASE + 0x1CC) - -/* ePOD and memory power signal control registers */ -#define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410) -#define PRCM_SRAM_LS_SLEEP (_PRCMU_BASE + 0x304) - -/* Debug power control unit registers */ -#define PRCM_POWER_STATE_SET (_PRCMU_BASE + 0x254) - -/* Miscellaneous unit registers */ -#define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324) -#define PRCM_GPIOCR (_PRCMU_BASE + 0x138) -#define PRCM_GPIOCR_DBG_STM_MOD_CMD1 0x800 -#define PRCM_GPIOCR_DBG_UARTMOD_CMD0 0x1 - - -#endif /* __MACH_PRCMU__REGS_H */ diff --git a/drivers/mfd/db5500-prcmu.c b/drivers/mfd/db5500-prcmu.c index 9dbb3cab4a6..9cd9da40d87 100644 --- a/drivers/mfd/db5500-prcmu.c +++ b/drivers/mfd/db5500-prcmu.c @@ -20,9 +20,9 @@ #include <linux/jiffies.h> #include <linux/bitops.h> #include <linux/interrupt.h> -#include <linux/mfd/db5500-prcmu.h> #include <mach/hardware.h> #include <mach/irqs.h> +#include <mach/prcmu.h> #include <mach/db5500-regs.h> #include "db5500-prcmu-regs.h" @@ -64,6 +64,19 @@ #define PRCM_ACK_MB6 (tcdm_base + 0xF0C) #define PRCM_ACK_MB7 (tcdm_base + 0xF08) +/* Mailbox 2 REQs */ +#define PRCM_REQ_MB2_EPOD_CLIENT (PRCM_REQ_MB2 + 0x0) +#define PRCM_REQ_MB2_EPOD_STATE (PRCM_REQ_MB2 + 0x1) +#define PRCM_REQ_MB2_CLK_CLIENT (PRCM_REQ_MB2 + 0x2) +#define PRCM_REQ_MB2_CLK_STATE (PRCM_REQ_MB2 + 0x3) +#define PRCM_REQ_MB2_PLL_CLIENT (PRCM_REQ_MB2 + 0x4) +#define PRCM_REQ_MB2_PLL_STATE (PRCM_REQ_MB2 + 0x5) + +/* Mailbox 2 ACKs */ +#define PRCM_ACK_MB2_EPOD_STATUS (PRCM_ACK_MB2 + 0x2) +#define PRCM_ACK_MB2_CLK_STATUS (PRCM_ACK_MB2 + 0x6) +#define PRCM_ACK_MB2_PLL_STATUS (PRCM_ACK_MB2 + 0xA) + enum mb_return_code { RC_SUCCESS, RC_FAIL, @@ -80,11 +93,29 @@ enum mb0_header { }; /* Mailbox 5 headers. */ +enum mb2_header { + MB2H_EPOD_REQUEST = 1, + MB2H_CLK_REQUEST, + MB2H_PLL_REQUEST, +}; + +/* Mailbox 5 headers. */ enum mb5_header { MB5H_I2C_WRITE = 1, MB5H_I2C_READ, }; +enum epod_state { + EPOD_OFF, + EPOD_ON, +}; +enum db5500_prcmu_pll { + DB5500_PLL_SOC0, + DB5500_PLL_SOC1, + DB5500_PLL_DDR, + DB5500_NUM_PLL_ID, +}; + /* Request mailbox 5 fields. */ #define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0) #define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1) @@ -109,15 +140,18 @@ enum mb5_header { #define PRCMU_DSI_CLOCK_SETTING 0x00000128 /* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */ #define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135 -#define PRCMU_PLLDSI_FREQ_SETTING 0x0004013C +#define PRCMU_PLLDSI_FREQ_SETTING 0x00020121 #define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002 -#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000101 +#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000201 #define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101 #define PRCMU_ENABLE_PLLDSI 0x00000001 #define PRCMU_DISABLE_PLLDSI 0x00000000 #define PRCMU_DSI_RESET_SW 0x00000003 +#define PRCMU_RESOUTN0_PIN 0x00000001 +#define PRCMU_RESOUTN1_PIN 0x00000002 +#define PRCMU_RESOUTN2_PIN 0x00000004 #define PRCMU_PLLDSI_LOCKP_LOCKED 0x3 @@ -130,6 +164,26 @@ static struct { } mb0_transfer; /* + * mb2_transfer - state needed for mailbox 2 communication. + * @lock: The transaction lock. + * @work: The transaction completion structure. + * @req: Request data that need to persist between requests. + * @ack: Reply ("acknowledge") data. + */ +static struct { + struct mutex lock; + struct completion work; + struct { + u8 epod_states[DB5500_NUM_EPOD_ID]; + u8 pll_states[DB5500_NUM_PLL_ID]; + } req; + struct { + u8 header; + u8 status; + } ack; +} mb2_transfer; + +/* * mb5_transfer - state needed for mailbox 5 communication. * @lock: The transaction lock. * @work: The transaction completion structure. @@ -148,6 +202,159 @@ static struct { /* PRCMU TCDM base IO address. */ static __iomem void *tcdm_base; +struct clk_mgt { + unsigned int offset; + u32 pllsw; +}; + +static DEFINE_SPINLOCK(clk_mgt_lock); + +#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { \ + (PRCM_##_name##_MGT_OFF), 0 \ +} +static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { + CLK_MGT_ENTRY(SGACLK), + CLK_MGT_ENTRY(UARTCLK), + CLK_MGT_ENTRY(MSP02CLK), + CLK_MGT_ENTRY(I2CCLK), + CLK_MGT_ENTRY(SDMMCCLK), + CLK_MGT_ENTRY(PER1CLK), + CLK_MGT_ENTRY(PER2CLK), + CLK_MGT_ENTRY(PER3CLK), + CLK_MGT_ENTRY(PER5CLK), + CLK_MGT_ENTRY(PER6CLK), + CLK_MGT_ENTRY(PWMCLK), + CLK_MGT_ENTRY(IRDACLK), + CLK_MGT_ENTRY(IRRCCLK), + CLK_MGT_ENTRY(HDMICLK), + CLK_MGT_ENTRY(APEATCLK), + CLK_MGT_ENTRY(APETRACECLK), + CLK_MGT_ENTRY(MCDECLK), + CLK_MGT_ENTRY(DSIALTCLK), + CLK_MGT_ENTRY(DMACLK), + CLK_MGT_ENTRY(B2R2CLK), + CLK_MGT_ENTRY(TVCLK), + CLK_MGT_ENTRY(RNGCLK), + CLK_MGT_ENTRY(SIACLK), + CLK_MGT_ENTRY(SVACLK), +}; + +static int request_timclk(bool enable) +{ + u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); + + if (!enable) + val |= PRCM_TCR_STOP_TIMERS; + writel(val, (_PRCMU_BASE + PRCM_TCR)); + + return 0; +} + +static int request_reg_clock(u8 clock, bool enable) +{ + u32 val; + unsigned long flags; + + WARN_ON(!clk_mgt[clock].offset); + + spin_lock_irqsave(&clk_mgt_lock, flags); + + /* Grab the HW semaphore. */ + while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) + cpu_relax(); + + val = readl(_PRCMU_BASE + clk_mgt[clock].offset); + if (enable) { + val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw); + } else { + clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); + val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK); + } + writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); + + /* Release the HW semaphore. */ + writel(0, (_PRCMU_BASE + PRCM_SEM)); + + spin_unlock_irqrestore(&clk_mgt_lock, flags); + + return 0; +} + +/* + * request_pll() - Request for a pll to be enabled or disabled. + * @pll: The pll for which the request is made. + * @enable: Whether the clock should be enabled (true) or disabled (false). + * + * This function should only be used by the clock implementation. + * Do not use it from any other place! + */ +static int request_pll(u8 pll, bool enable) +{ + int r = 0; + + BUG_ON(pll >= DB5500_NUM_PLL_ID); + mutex_lock(&mb2_transfer.lock); + + while (readl(PRCM_MBOX_CPU_VAL & MBOX_BIT(2)) + cpu_relax(); + + mb2_transfer.req.pll_states[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(MB2H_PLL_REQUEST, PRCM_REQ_MB2_HEADER); + + writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET); + if (!wait_for_completion_timeout(&mb2_transfer.work, + msecs_to_jiffies(500))) { + pr_err("prcmu: set_pll() failed.\n" + "prcmu: Please check your firmware version.\n"); + r = -EIO; + WARN(1, "Failed to set pll"); + goto unlock_and_return; + } + if (mb2_transfer.ack.status != RC_SUCCESS || + mb2_transfer.ack.header != MB2H_PLL_REQUEST) + r = -EIO; + +unlock_and_return: + mutex_unlock(&mb2_transfer.lock); + + return r; +} + +void prcmu_enable_wakeups(u32 wakeups) +{ +} + +/** + * 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). + * + * This function should only be used by the clock implementation. + * Do not use it from any other place! + */ +int prcmu_request_clock(u8 clock, bool enable) +{ + if (clock < PRCMU_NUM_REG_CLOCKS) + return request_reg_clock(clock, enable); + else if (clock == PRCMU_TIMCLK) + return request_timclk(enable); + else if (clock == PRCMU_PLLSOC0) + return request_pll(DB5500_PLL_SOC0, enable); + else if (clock == PRCMU_PLLSOC1) + return request_pll(DB5500_PLL_SOC1, enable); + else if (clock == PRCMU_PLLDDR) + return request_pll(DB5500_PLL_DDR, enable); + else if (clock == PRCMU_SYSCLK) + return -EINVAL; + else + return -EINVAL; +} + /** * db5500_prcmu_abb_read() - Read register value(s) from the ABB. * @slave: The I2C slave address. @@ -230,6 +437,34 @@ int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) return r; } +int prcmu_resetout(u8 resoutn, u8 state) +{ + int offset; + int pin = -1; + + offset = state > 0 ? PRCM_RESOUTN_SET_OFFSET : PRCM_RESOUTN_CLR_OFFSET; + + switch (resoutn) { + case 0: + pin = PRCMU_RESOUTN0_PIN; + break; + case 1: + pin = PRCMU_RESOUTN1_PIN; + break; + case 2: + pin = PRCMU_RESOUTN2_PIN; + default: + break; + } + + if (pin > 0) + writel(pin, _PRCMU_BASE + offset); + else + return -EINVAL; + + return 0; +} + int db5500_prcmu_enable_dsipll(void) { int i; @@ -294,6 +529,72 @@ static void ack_dbb_wakeup(void) spin_unlock_irqrestore(&mb0_transfer.lock, flags); } +int prcmu_set_epod(u16 epod_id, u8 epod_state) +{ + int r = 0; + bool ram_retention = false; + + /* check argument */ + BUG_ON(epod_id < DB5500_EPOD_ID_BASE); + BUG_ON(epod_state > EPOD_STATE_ON); + + 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: + ram_retention = true; + break; + } + + /* check argument */ + /* BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention); */ + + /* get lock */ + mutex_lock(&mb2_transfer.lock); + + /* wait for mailbox */ + 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; + } + + /* 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(MB2H_EPOD_REQUEST, PRCM_REQ_MB2_HEADER); + + writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET); + + if (!wait_for_completion_timeout(&mb2_transfer.work, + msecs_to_jiffies(500))) { + pr_err("prcmu: set_epod() failed.\n" + "prcmu: Please check your firmware version.\n"); + r = -EIO; + WARN(1, "Failed to set epod"); + goto unlock_and_return; + } + + if (mb2_transfer.ack.status != RC_SUCCESS || + mb2_transfer.ack.header != MB2H_EPOD_REQUEST) + r = -EIO; + +unlock_and_return: + mutex_unlock(&mb2_transfer.lock); + return r; +} + static inline void print_unknown_header_warning(u8 n, u8 header) { pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n", @@ -327,7 +628,28 @@ static bool read_mailbox_1(void) static bool read_mailbox_2(void) { + u8 header; + + header = readb(PRCM_ACK_MB2_HEADER); + mb2_transfer.ack.header = header; + switch (header) { + case MB2H_EPOD_REQUEST: + mb2_transfer.ack.status = readb(PRCM_ACK_MB2_EPOD_STATUS); + break; + case MB2H_CLK_REQUEST: + mb2_transfer.ack.status = readb(PRCM_ACK_MB2_CLK_STATUS); + break; + case MB2H_PLL_REQUEST: + mb2_transfer.ack.status = readb(PRCM_ACK_MB2_PLL_STATUS); + break; + default: + writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR); + pr_err("prcmu: Wrong ACK received for MB2 request \n"); + return false; + break; + } writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR); + complete(&mb2_transfer.work); return false; } @@ -418,7 +740,9 @@ void __init db5500_prcmu_early_init(void) { tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE); spin_lock_init(&mb0_transfer.lock); + mutex_init(&mb2_transfer.lock); mutex_init(&mb5_transfer.lock); + init_completion(&mb2_transfer.work); init_completion(&mb5_transfer.work); } diff --git a/drivers/mfd/db8500-prcmu-regs.h b/drivers/mfd/db8500-prcmu-regs.h deleted file mode 100644 index 3bbf04d5804..00000000000 --- a/drivers/mfd/db8500-prcmu-regs.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> - * Author: Sundar Iyer <sundar.iyer@stericsson.com> - * - * License Terms: GNU General Public License v2 - * - * PRCM Unit registers - */ -#ifndef __DB8500_PRCMU_REGS_H -#define __DB8500_PRCMU_REGS_H - -#include <linux/bitops.h> -#include <mach/hardware.h> - -#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end)) - -#define PRCM_ARM_PLLDIVPS 0x118 -#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE BITS(0, 5) -#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xF - -#define PRCM_PLLARM_LOCKP 0x0A8 -#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 BIT(1) - -#define PRCM_ARM_CHGCLKREQ 0x114 -#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0) - -#define PRCM_PLLARM_ENABLE 0x98 -#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE BIT(0) -#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON BIT(8) - -#define PRCM_ARMCLKFIX_MGT 0x0 -#define PRCM_A9_RESETN_CLR 0x1f4 -#define PRCM_A9_RESETN_SET 0x1f0 -#define PRCM_ARM_LS_CLAMP 0x30C -#define PRCM_SRAM_A9 0x308 - -/* ARM WFI Standby signal register */ -#define PRCM_ARM_WFI_STANDBY 0x130 -#define PRCM_IOCR 0x310 -#define PRCM_IOCR_IOFORCE BIT(0) - -/* CPU mailbox registers */ -#define PRCM_MBOX_CPU_VAL 0x0FC -#define PRCM_MBOX_CPU_SET 0x100 - -/* Dual A9 core interrupt management unit registers */ -#define PRCM_A9_MASK_REQ 0x328 -#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ BIT(0) - -#define PRCM_A9_MASK_ACK 0x32C -#define PRCM_ARMITMSK31TO0 0x11C -#define PRCM_ARMITMSK63TO32 0x120 -#define PRCM_ARMITMSK95TO64 0x124 -#define PRCM_ARMITMSK127TO96 0x128 -#define PRCM_POWER_STATE_VAL 0x25C -#define PRCM_ARMITVAL31TO0 0x260 -#define PRCM_ARMITVAL63TO32 0x264 -#define PRCM_ARMITVAL95TO64 0x268 -#define PRCM_ARMITVAL127TO96 0x26C - -#define PRCM_HOSTACCESS_REQ 0x334 -#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ BIT(0) - -#define PRCM_ARM_IT1_CLR 0x48C -#define PRCM_ARM_IT1_VAL 0x494 - -#define PRCM_ITSTATUS0 0x148 -#define PRCM_ITSTATUS1 0x150 -#define PRCM_ITSTATUS2 0x158 -#define PRCM_ITSTATUS3 0x160 -#define PRCM_ITSTATUS4 0x168 -#define PRCM_ITSTATUS5 0x484 -#define PRCM_ITCLEAR5 0x488 -#define PRCM_ARMIT_MASKXP70_IT 0x1018 - -/* System reset register */ -#define PRCM_APE_SOFTRST 0x228 - -/* Level shifter and clamp control registers */ -#define PRCM_MMIP_LS_CLAMP_SET 0x420 -#define PRCM_MMIP_LS_CLAMP_CLR 0x424 - -/* PRCMU HW semaphore */ -#define PRCM_SEM 0x400 -#define PRCM_SEM_PRCM_SEM BIT(0) - -/* PRCMU clock/PLL/reset registers */ -#define PRCM_PLLDSI_FREQ 0x500 -#define PRCM_PLLDSI_ENABLE 0x504 -#define PRCM_PLLDSI_LOCKP 0x508 -#define PRCM_DSI_PLLOUT_SEL 0x530 -#define PRCM_DSITVCLK_DIV 0x52C -#define PRCM_APE_RESETN_SET 0x1E4 -#define PRCM_APE_RESETN_CLR 0x1E8 - -#define PRCM_TCR 0x1C8 -#define PRCM_TCR_TENSEL_MASK BITS(0, 7) -#define PRCM_TCR_STOP_TIMERS BIT(16) -#define PRCM_TCR_DOZE_MODE BIT(17) - -#define PRCM_CLKOCR 0x1CC -#define PRCM_CLKOCR_CLKODIV0_SHIFT 0 -#define PRCM_CLKOCR_CLKODIV0_MASK BITS(0, 5) -#define PRCM_CLKOCR_CLKOSEL0_SHIFT 6 -#define PRCM_CLKOCR_CLKOSEL0_MASK BITS(6, 8) -#define PRCM_CLKOCR_CLKODIV1_SHIFT 16 -#define PRCM_CLKOCR_CLKODIV1_MASK BITS(16, 21) -#define PRCM_CLKOCR_CLKOSEL1_SHIFT 22 -#define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24) -#define PRCM_CLKOCR_CLK1TYPE BIT(28) - -#define PRCM_SGACLK_MGT 0x014 -#define PRCM_UARTCLK_MGT 0x018 -#define PRCM_MSP02CLK_MGT 0x01C -#define PRCM_MSP1CLK_MGT 0x288 -#define PRCM_I2CCLK_MGT 0x020 -#define PRCM_SDMMCCLK_MGT 0x024 -#define PRCM_SLIMCLK_MGT 0x028 -#define PRCM_PER1CLK_MGT 0x02C -#define PRCM_PER2CLK_MGT 0x030 -#define PRCM_PER3CLK_MGT 0x034 -#define PRCM_PER5CLK_MGT 0x038 -#define PRCM_PER6CLK_MGT 0x03C -#define PRCM_PER7CLK_MGT 0x040 -#define PRCM_LCDCLK_MGT 0x044 -#define PRCM_BMLCLK_MGT 0x04C -#define PRCM_HSITXCLK_MGT 0x050 -#define PRCM_HSIRXCLK_MGT 0x054 -#define PRCM_HDMICLK_MGT 0x058 -#define PRCM_APEATCLK_MGT 0x05C -#define PRCM_APETRACECLK_MGT 0x060 -#define PRCM_MCDECLK_MGT 0x064 -#define PRCM_IPI2CCLK_MGT 0x068 -#define PRCM_DSIALTCLK_MGT 0x06C -#define PRCM_DMACLK_MGT 0x074 -#define PRCM_B2R2CLK_MGT 0x078 -#define PRCM_TVCLK_MGT 0x07C -#define PRCM_UNIPROCLK_MGT 0x278 -#define PRCM_SSPCLK_MGT 0x280 -#define PRCM_RNGCLK_MGT 0x284 -#define PRCM_UICCCLK_MGT 0x27C - -#define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4) -#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) -#define PRCM_CLK_MGT_CLKEN BIT(8) - -/* ePOD and memory power signal control registers */ -#define PRCM_EPOD_C_SET 0x410 -#define PRCM_SRAM_LS_SLEEP 0x304 - -/* Debug power control unit registers */ -#define PRCM_POWER_STATE_SET 0x254 - -/* Miscellaneous unit registers */ -#define PRCM_DSI_SW_RESET 0x324 -#define PRCM_GPIOCR 0x138 - -/* GPIOCR register */ -#define PRCM_GPIOCR_SPI2_SELECT BIT(23) - -#define PRCM_DDR_SUBSYS_APE_MINBW 0x438 - -#endif /* __DB8500_PRCMU_REGS_H */ diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index 57939be17ed..f018c3fa604 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -27,14 +27,13 @@ #include <linux/platform_device.h> #include <linux/uaccess.h> #include <linux/mfd/core.h> -#include <linux/mfd/db8500-prcmu.h> #include <linux/regulator/db8500-prcmu.h> #include <linux/regulator/machine.h> #include <mach/hardware.h> #include <mach/irqs.h> -#include <mach/db8500-regs.h> +#include <mach/prcmu-regs.h> #include <mach/id.h> -#include "db8500-prcmu-regs.h" +#include <mach/prcmu.h> /* Offset for the firmware version within the TCPM */ #define PRCMU_FW_VERSION_OFFSET 0xA4 @@ -131,12 +130,14 @@ #define MB1H_REQUEST_APE_OPP_100_VOLT 0x3 #define MB1H_RELEASE_APE_OPP_100_VOLT 0x4 #define MB1H_RELEASE_USB_WAKEUP 0x5 +#define MB1H_PLL_ON_OFF 0x6 /* Mailbox 1 Requests */ #define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) #define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) -#define PRCM_REQ_MB1_APE_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x4) -#define PRCM_REQ_MB1_ARM_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x8) +#define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4) +#define PLL_SOC1_OFF 0x4 +#define PLL_SOC1_ON 0x8 /* Mailbox 1 ACKs */ #define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0) @@ -412,7 +413,7 @@ struct clk_mgt { static DEFINE_SPINLOCK(clk_mgt_lock); -#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT), 0 } +#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 } struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { CLK_MGT_ENTRY(SGACLK), CLK_MGT_ENTRY(UARTCLK), @@ -446,6 +447,39 @@ struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { }; /* + * NOTE! Temporary until all users of set_hwacc() are using the regulator + * framework API + */ +static struct regulator *hwacc_regulator[NUM_HW_ACC]; +static struct regulator *hwacc_ret_regulator[NUM_HW_ACC]; + +static bool hwacc_enabled[NUM_HW_ACC]; +static bool hwacc_ret_enabled[NUM_HW_ACC]; + +static const char *hwacc_regulator_name[NUM_HW_ACC] = { + [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp", + [HW_ACC_SVAPIPE] = "hwacc-sva-pipe", + [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp", + [HW_ACC_SIAPIPE] = "hwacc-sia-pipe", + [HW_ACC_SGA] = "hwacc-sga", + [HW_ACC_B2R2] = "hwacc-b2r2", + [HW_ACC_MCDE] = "hwacc-mcde", + [HW_ACC_ESRAM1] = "hwacc-esram1", + [HW_ACC_ESRAM2] = "hwacc-esram2", + [HW_ACC_ESRAM3] = "hwacc-esram3", + [HW_ACC_ESRAM4] = "hwacc-esram4", +}; + +static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = { + [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp-ret", + [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp-ret", + [HW_ACC_ESRAM1] = "hwacc-esram1-ret", + [HW_ACC_ESRAM2] = "hwacc-esram2-ret", + [HW_ACC_ESRAM3] = "hwacc-esram3-ret", + [HW_ACC_ESRAM4] = "hwacc-esram4-ret", +}; + +/* * Used by MCDE to setup all necessary PRCMU registers */ #define PRCMU_RESET_DSIPLL 0x00004000 @@ -499,45 +533,41 @@ int prcmu_enable_dsipll(void) unsigned int plldsifreq; /* Clear DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_CLR)); + writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR); /* Unclamp DSIPLL in/out */ - writel(PRCMU_UNCLAMP_DSIPLL, (_PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR)); + writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR); if (prcmu_is_u8400()) plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400; else plldsifreq = PRCMU_PLLDSI_FREQ_SETTING; /* Set DSI PLL FREQ */ - writel(plldsifreq, (_PRCMU_BASE + PRCM_PLLDSI_FREQ)); - writel(PRCMU_DSI_PLLOUT_SEL_SETTING, - (_PRCMU_BASE + PRCM_DSI_PLLOUT_SEL)); + writel(plldsifreq, PRCM_PLLDSI_FREQ); + writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL); /* Enable Escape clocks */ - writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, - (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); + writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); /* Start DSI PLL */ - writel(PRCMU_ENABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); + writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE); /* Reset DSI PLL */ - writel(PRCMU_DSI_RESET_SW, (_PRCMU_BASE + PRCM_DSI_SW_RESET)); + writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET); for (i = 0; i < 10; i++) { - if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) & - PRCMU_PLLDSI_LOCKP_LOCKED) + if ((readl(PRCM_PLLDSI_LOCKP) & PRCMU_PLLDSI_LOCKP_LOCKED) == PRCMU_PLLDSI_LOCKP_LOCKED) break; udelay(100); } /* Set DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET)); + writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET); return 0; } int prcmu_disable_dsipll(void) { /* Disable dsi pll */ - writel(PRCMU_DISABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE)); + writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE); /* Disable escapeclock */ - writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, - (_PRCMU_BASE + PRCM_DSITVCLK_DIV)); + writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV); return 0; } @@ -554,15 +584,15 @@ int prcmu_set_display_clocks(void) spin_lock_irqsave(&clk_mgt_lock, flags); /* Grab the HW semaphore. */ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) + while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) cpu_relax(); - writel(dsiclk, (_PRCMU_BASE + PRCM_HDMICLK_MGT)); - writel(PRCMU_DSI_LP_CLOCK_SETTING, (_PRCMU_BASE + PRCM_TVCLK_MGT)); - writel(PRCMU_DPI_CLOCK_SETTING, (_PRCMU_BASE + PRCM_LCDCLK_MGT)); + writel(dsiclk, PRCM_HDMICLK_MGT); + writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT); + writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT); /* Release the HW semaphore. */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); + writel(0, PRCM_SEM); spin_unlock_irqrestore(&clk_mgt_lock, flags); @@ -578,8 +608,8 @@ void prcmu_enable_spi2(void) unsigned long flags; spin_lock_irqsave(&gpiocr_lock, flags); - reg = readl(_PRCMU_BASE + PRCM_GPIOCR); - writel(reg | PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); + reg = readl(PRCM_GPIOCR); + writel(reg | PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR); spin_unlock_irqrestore(&gpiocr_lock, flags); } @@ -592,8 +622,8 @@ void prcmu_disable_spi2(void) unsigned long flags; spin_lock_irqsave(&gpiocr_lock, flags); - reg = readl(_PRCMU_BASE + PRCM_GPIOCR); - writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR); + reg = readl(PRCM_GPIOCR); + writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR); spin_unlock_irqrestore(&gpiocr_lock, flags); } @@ -701,7 +731,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div) spin_lock_irqsave(&clkout_lock, flags); - val = readl(_PRCMU_BASE + PRCM_CLKOCR); + val = readl(PRCM_CLKOCR); if (val & div_mask) { if (div) { if ((val & mask) != bits) { @@ -715,7 +745,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div) } } } - writel((bits | (val & ~mask)), (_PRCMU_BASE + PRCM_CLKOCR)); + writel((bits | (val & ~mask)), PRCM_CLKOCR); requests[clkout] += (div ? 1 : -1); unlock_and_return: @@ -732,7 +762,7 @@ int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) spin_lock_irqsave(&mb0_transfer.lock, flags); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) cpu_relax(); writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); @@ -741,7 +771,7 @@ int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) writeb((keep_ulp_clk ? 1 : 0), (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE)); writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI)); - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); spin_unlock_irqrestore(&mb0_transfer.lock, flags); @@ -770,12 +800,12 @@ static void config_wakeups(void) return; for (i = 0; i < 2; i++) { - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) cpu_relax(); writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500)); writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500)); writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); } last_dbb_events = dbb_events; last_abb_events = abb_events; @@ -840,14 +870,14 @@ int prcmu_set_arm_opp(u8 opp) mutex_lock(&mb1_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) cpu_relax(); writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); wait_for_completion(&mb1_transfer.work); if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || @@ -876,7 +906,7 @@ int prcmu_get_arm_opp(void) */ int prcmu_get_ddr_opp(void) { - return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW); + return readb(PRCM_DDR_SUBSYS_APE_MINBW); } /** @@ -892,7 +922,7 @@ int prcmu_set_ddr_opp(u8 opp) return -EINVAL; /* Changing the DDR OPP can hang the hardware pre-v21 */ if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20()) - writeb(opp, (_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW)); + writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW); return 0; } @@ -909,14 +939,14 @@ int prcmu_set_ape_opp(u8 opp) mutex_lock(&mb1_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) cpu_relax(); writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP)); writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP)); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); wait_for_completion(&mb1_transfer.work); if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) || @@ -966,12 +996,12 @@ int prcmu_request_ape_opp_100_voltage(bool enable) header = MB1H_RELEASE_APE_OPP_100_VOLT; } - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) cpu_relax(); writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); wait_for_completion(&mb1_transfer.work); if ((mb1_transfer.ack.header != header) || @@ -995,13 +1025,13 @@ int prcmu_release_usb_wakeup_state(void) mutex_lock(&mb1_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) cpu_relax(); writeb(MB1H_RELEASE_USB_WAKEUP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); wait_for_completion(&mb1_transfer.work); if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) || @@ -1013,6 +1043,160 @@ int prcmu_release_usb_wakeup_state(void) return r; } +static int request_pll(u8 clock, bool enable) +{ + int r = 0; + + if (clock == PRCMU_PLLSOC1) + clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF); + else + return -EINVAL; + + mutex_lock(&mb1_transfer.lock); + + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + cpu_relax(); + + writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); + writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF)); + + writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); + wait_for_completion(&mb1_transfer.work); + + if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF) + r = -EIO; + + mutex_unlock(&mb1_transfer.lock); + + return r; +} + +/** + * prcmu_set_hwacc - set the power state of a h/w accelerator + * @hwacc_dev: The hardware accelerator (enum hw_acc_dev). + * @state: The new power state (enum hw_acc_state). + * + * This function sets the power state of a hardware accelerator. + * This function should not be called from interrupt context. + * + * NOTE! Deprecated, to be removed when all users switched over to use the + * regulator framework API. + */ +int prcmu_set_hwacc(u16 hwacc_dev, u8 state) +{ + int r = 0; + bool ram_retention = false; + bool enable, enable_ret; + + /* check argument */ + BUG_ON(hwacc_dev >= NUM_HW_ACC); + + /* get state of switches */ + enable = hwacc_enabled[hwacc_dev]; + enable_ret = hwacc_ret_enabled[hwacc_dev]; + + /* set flag if retention is possible */ + switch (hwacc_dev) { + case HW_ACC_SVAMMDSP: + case HW_ACC_SIAMMDSP: + case HW_ACC_ESRAM1: + case HW_ACC_ESRAM2: + case HW_ACC_ESRAM3: + case HW_ACC_ESRAM4: + ram_retention = true; + break; + } + + /* check argument */ + BUG_ON(state > HW_ON); + BUG_ON(state == HW_OFF_RAMRET && !ram_retention); + + /* modify enable flags */ + switch (state) { + case HW_OFF: + enable_ret = false; + enable = false; + break; + case HW_ON: + enable = true; + break; + case HW_OFF_RAMRET: + enable_ret = true; + enable = false; + break; + } + + /* get regulator (lazy) */ + if (hwacc_regulator[hwacc_dev] == NULL) { + hwacc_regulator[hwacc_dev] = regulator_get(NULL, + hwacc_regulator_name[hwacc_dev]); + if (IS_ERR(hwacc_regulator[hwacc_dev])) { + pr_err("prcmu: failed to get supply %s\n", + hwacc_regulator_name[hwacc_dev]); + r = PTR_ERR(hwacc_regulator[hwacc_dev]); + goto out; + } + } + + if (ram_retention) { + if (hwacc_ret_regulator[hwacc_dev] == NULL) { + hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL, + hwacc_ret_regulator_name[hwacc_dev]); + if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) { + pr_err("prcmu: failed to get supply %s\n", + hwacc_ret_regulator_name[hwacc_dev]); + r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]); + goto out; + } + } + } + + /* set regulators */ + if (ram_retention) { + if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) { + r = regulator_enable(hwacc_ret_regulator[hwacc_dev]); + if (r < 0) { + pr_err("prcmu_set_hwacc: ret enable failed\n"); + goto out; + } + hwacc_ret_enabled[hwacc_dev] = true; + } + } + + if (enable && !hwacc_enabled[hwacc_dev]) { + r = regulator_enable(hwacc_regulator[hwacc_dev]); + if (r < 0) { + pr_err("prcmu_set_hwacc: enable failed\n"); + goto out; + } + hwacc_enabled[hwacc_dev] = true; + } + + if (!enable && hwacc_enabled[hwacc_dev]) { + r = regulator_disable(hwacc_regulator[hwacc_dev]); + if (r < 0) { + pr_err("prcmu_set_hwacc: disable failed\n"); + goto out; + } + hwacc_enabled[hwacc_dev] = false; + } + + if (ram_retention) { + if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) { + r = regulator_disable(hwacc_ret_regulator[hwacc_dev]); + if (r < 0) { + pr_err("prcmu_set_hwacc: ret disable failed\n"); + goto out; + } + hwacc_ret_enabled[hwacc_dev] = false; + } + } + +out: + return r; +} +EXPORT_SYMBOL(prcmu_set_hwacc); + /** * prcmu_set_epod - set the state of a EPOD (power domain) * @epod_id: The EPOD to set @@ -1048,7 +1232,7 @@ int prcmu_set_epod(u16 epod_id, u8 epod_state) mutex_lock(&mb2_transfer.lock); /* wait for mailbox */ - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) cpu_relax(); /* fill in mailbox */ @@ -1058,7 +1242,7 @@ int prcmu_set_epod(u16 epod_id, u8 epod_state) writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2)); - writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET); /* * The current firmware version does not handle errors correctly, @@ -1145,13 +1329,13 @@ static int request_sysclk(bool enable) spin_lock_irqsave(&mb3_transfer.lock, flags); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) cpu_relax(); writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT)); writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3)); - writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET); spin_unlock_irqrestore(&mb3_transfer.lock, flags); @@ -1177,7 +1361,7 @@ static int request_timclk(bool enable) if (!enable) val |= PRCM_TCR_STOP_TIMERS; - writel(val, (_PRCMU_BASE + PRCM_TCR)); + writel(val, PRCM_TCR); return 0; } @@ -1190,7 +1374,7 @@ static int request_reg_clock(u8 clock, bool enable) spin_lock_irqsave(&clk_mgt_lock, flags); /* Grab the HW semaphore. */ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) + while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) cpu_relax(); val = readl(_PRCMU_BASE + clk_mgt[clock].offset); @@ -1203,13 +1387,33 @@ static int request_reg_clock(u8 clock, bool enable) writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); /* Release the HW semaphore. */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); + writel(0, PRCM_SEM); spin_unlock_irqrestore(&clk_mgt_lock, flags); return 0; } +static int request_sga_clock(u8 clock, bool enable) +{ + u32 val; + int ret; + + if (enable) { + val = readl(PRCM_CGATING_BYPASS); + writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); + } + + ret = request_reg_clock(clock, enable); + + if (!ret && !enable) { + val = readl(PRCM_CGATING_BYPASS); + writel(val & ~PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS); + } + + return ret; +} + /** * prcmu_request_clock() - Request for a clock to be enabled or disabled. * @clock: The clock for which the request is made. @@ -1220,12 +1424,16 @@ static int request_reg_clock(u8 clock, bool enable) */ int prcmu_request_clock(u8 clock, bool enable) { - if (clock < PRCMU_NUM_REG_CLOCKS) + if (clock == PRCMU_SGACLK) + return request_sga_clock(clock, enable); + else if (clock < PRCMU_NUM_REG_CLOCKS) return request_reg_clock(clock, enable); else if (clock == PRCMU_TIMCLK) return request_timclk(enable); else if (clock == PRCMU_SYSCLK) return request_sysclk(enable); + else if (clock == PRCMU_PLLSOC1) + return request_pll(clock, enable); else return -EINVAL; } @@ -1238,7 +1446,7 @@ int prcmu_config_esram0_deep_sleep(u8 state) mutex_lock(&mb4_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) cpu_relax(); writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); @@ -1248,7 +1456,7 @@ int prcmu_config_esram0_deep_sleep(u8 state) (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE)); writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST)); - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); wait_for_completion(&mb4_transfer.work); mutex_unlock(&mb4_transfer.lock); @@ -1260,13 +1468,13 @@ int prcmu_config_hotdog(u8 threshold) { mutex_lock(&mb4_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) cpu_relax(); writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD)); writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); wait_for_completion(&mb4_transfer.work); mutex_unlock(&mb4_transfer.lock); @@ -1278,7 +1486,7 @@ int prcmu_config_hotmon(u8 low, u8 high) { mutex_lock(&mb4_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) cpu_relax(); writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW)); @@ -1287,7 +1495,7 @@ int prcmu_config_hotmon(u8 low, u8 high) (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG)); writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); wait_for_completion(&mb4_transfer.work); mutex_unlock(&mb4_transfer.lock); @@ -1299,13 +1507,13 @@ static int config_hot_period(u16 val) { mutex_lock(&mb4_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) cpu_relax(); writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD)); writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET); wait_for_completion(&mb4_transfer.work); mutex_unlock(&mb4_transfer.lock); @@ -1345,7 +1553,7 @@ int prcmu_set_clock_divider(u8 clock, u8 divider) spin_lock_irqsave(&clk_mgt_lock, flags); /* Grab the HW semaphore. */ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) + while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) cpu_relax(); val = readl(_PRCMU_BASE + clk_mgt[clock].offset); @@ -1354,7 +1562,7 @@ int prcmu_set_clock_divider(u8 clock, u8 divider) writel(val, (_PRCMU_BASE + clk_mgt[clock].offset)); /* Release the HW semaphore. */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); + writel(0, PRCM_SEM); spin_unlock_irqrestore(&clk_mgt_lock, flags); @@ -1380,7 +1588,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) mutex_lock(&mb5_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) cpu_relax(); writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); @@ -1388,7 +1596,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); - writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); if (!wait_for_completion_timeout(&mb5_transfer.work, msecs_to_jiffies(20000))) { @@ -1426,7 +1634,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) mutex_lock(&mb5_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5)) cpu_relax(); writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP)); @@ -1434,7 +1642,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG)); writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL)); - writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET); if (!wait_for_completion_timeout(&mb5_transfer.work, msecs_to_jiffies(20000))) { @@ -1459,14 +1667,13 @@ void prcmu_ac_wake_req(void) mutex_lock(&mb0_transfer.ac_wake_lock); - val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); + val = readl(PRCM_HOSTACCESS_REQ); if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ) goto unlock_and_return; atomic_set(&ac_wake_req_state, 1); - writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), - (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); + writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), PRCM_HOSTACCESS_REQ); if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, msecs_to_jiffies(20000))) { @@ -1487,12 +1694,12 @@ void prcmu_ac_sleep_req() mutex_lock(&mb0_transfer.ac_wake_lock); - val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ); + val = readl(PRCM_HOSTACCESS_REQ); if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)) goto unlock_and_return; writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), - (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); + PRCM_HOSTACCESS_REQ); if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work, msecs_to_jiffies(20000))) { @@ -1520,7 +1727,7 @@ bool prcmu_is_ac_wake_requested(void) void prcmu_system_reset(u16 reset_code) { writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON)); - writel(1, (_PRCMU_BASE + PRCM_APE_SOFTRST)); + writel(1, PRCM_APE_SOFTRST); } /** @@ -1541,11 +1748,11 @@ void prcmu_modem_reset(void) { mutex_lock(&mb1_transfer.lock); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) cpu_relax(); writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1)); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); wait_for_completion(&mb1_transfer.work); /* @@ -1562,11 +1769,11 @@ static void ack_dbb_wakeup(void) spin_lock_irqsave(&mb0_transfer.lock, flags); - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) cpu_relax(); writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0)); - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); + writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET); spin_unlock_irqrestore(&mb0_transfer.lock, flags); } @@ -1611,7 +1818,7 @@ static bool read_mailbox_0(void) r = false; break; } - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR); return r; } @@ -1624,7 +1831,7 @@ static bool read_mailbox_1(void) PRCM_ACK_MB1_CURRENT_APE_OPP); mb1_transfer.ack.ape_voltage_status = readb(tcdm_base + PRCM_ACK_MB1_APE_VOLTAGE_STATUS); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR); complete(&mb1_transfer.work); return false; } @@ -1632,14 +1839,14 @@ static bool read_mailbox_1(void) static bool read_mailbox_2(void) { mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS); - writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR); complete(&mb2_transfer.work); return false; } static bool read_mailbox_3(void) { - writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR); return false; } @@ -1661,7 +1868,7 @@ static bool read_mailbox_4(void) break; } - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR); if (do_complete) complete(&mb4_transfer.work); @@ -1673,20 +1880,20 @@ static bool read_mailbox_5(void) { mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS); mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL); - writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR); complete(&mb5_transfer.work); return false; } static bool read_mailbox_6(void) { - writel(MBOX_BIT(6), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR); return false; } static bool read_mailbox_7(void) { - writel(MBOX_BIT(7), (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR); return false; } @@ -1707,7 +1914,7 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data) u8 n; irqreturn_t r; - bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); + bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS); if (unlikely(!bits)) return IRQ_NONE; @@ -1837,6 +2044,16 @@ void __init prcmu_early_init(void) } } +static void __init init_prcm_registers(void) +{ + u32 val; + + val = readl(PRCM_A9PL_FORCE_CLKEN); + val &= ~(PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN | + PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN); + writel(val, (PRCM_A9PL_FORCE_CLKEN)); +} + /* * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC */ @@ -1863,8 +2080,6 @@ static struct regulator_consumer_supply db8500_vape_consumers[] = { static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { /* CG2900 and CW1200 power to off-chip peripherals */ - REGULATOR_SUPPLY("gbf_1v8", "cg2900-uart.0"), - REGULATOR_SUPPLY("wlan_1v8", "cw1200.0"), REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"), /* AV8100 regulator */ REGULATOR_SUPPLY("hdmi_1v8", "0-0070"), @@ -1872,7 +2087,42 @@ static struct regulator_consumer_supply db8500_vsmps2_consumers[] = { static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = { REGULATOR_SUPPLY("vsupply", "b2r2.0"), - REGULATOR_SUPPLY("vsupply", "mcde.0"), + REGULATOR_SUPPLY("vsupply", "mcde"), +}; + +/* SVA MMDSP regulator switch */ +static struct regulator_consumer_supply db8500_svammdsp_consumers[] = { + REGULATOR_SUPPLY("sva-mmdsp", "cm_control"), +}; + +/* SVA pipe regulator switch */ +static struct regulator_consumer_supply db8500_svapipe_consumers[] = { + REGULATOR_SUPPLY("sva-pipe", "cm_control"), +}; + +/* SIA MMDSP regulator switch */ +static struct regulator_consumer_supply db8500_siammdsp_consumers[] = { + REGULATOR_SUPPLY("sia-mmdsp", "cm_control"), +}; + +/* SIA pipe regulator switch */ +static struct regulator_consumer_supply db8500_siapipe_consumers[] = { + REGULATOR_SUPPLY("sia-pipe", "cm_control"), +}; + +static struct regulator_consumer_supply db8500_sga_consumers[] = { + REGULATOR_SUPPLY("v-mali", NULL), +}; + +/* ESRAM1 and 2 regulator switch */ +static struct regulator_consumer_supply db8500_esram12_consumers[] = { + REGULATOR_SUPPLY("esram12", "cm_control"), +}; + +/* ESRAM3 and 4 regulator switch */ +static struct regulator_consumer_supply db8500_esram34_consumers[] = { + REGULATOR_SUPPLY("v-esram34", "mcde"), + REGULATOR_SUPPLY("esram34", "cm_control"), }; static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { @@ -1934,6 +2184,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { .name = "db8500-sva-mmdsp", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .consumer_supplies = db8500_svammdsp_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers), }, [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = { .constraints = { @@ -1948,6 +2200,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { .name = "db8500-sva-pipe", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .consumer_supplies = db8500_svapipe_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers), }, [DB8500_REGULATOR_SWITCH_SIAMMDSP] = { .supply_regulator = "db8500-vape", @@ -1955,6 +2209,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { .name = "db8500-sia-mmdsp", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .consumer_supplies = db8500_siammdsp_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers), }, [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = { .constraints = { @@ -1968,6 +2224,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { .name = "db8500-sia-pipe", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .consumer_supplies = db8500_siapipe_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers), }, [DB8500_REGULATOR_SWITCH_SGA] = { .supply_regulator = "db8500-vape", @@ -1975,6 +2233,9 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { .name = "db8500-sga", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .consumer_supplies = db8500_sga_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers), + }, [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = { .supply_regulator = "db8500-vape", @@ -1991,6 +2252,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { .name = "db8500-esram12", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .consumer_supplies = db8500_esram12_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers), }, [DB8500_REGULATOR_SWITCH_ESRAM12RET] = { .constraints = { @@ -2004,6 +2267,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = { .name = "db8500-esram34", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .consumer_supplies = db8500_esram34_consumers, + .num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers), }, [DB8500_REGULATOR_SWITCH_ESRAM34RET] = { .constraints = { @@ -2035,8 +2300,10 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev) if (ux500_is_svp()) return -ENODEV; + init_prcm_registers(); + /* Clean up the mailbox interrupts after pre-kernel code. */ - writel(ALL_MBOX_BITS, (_PRCMU_BASE + PRCM_ARM_IT1_CLR)); + writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR); err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL); diff --git a/include/linux/mfd/db5500-prcmu.h b/include/linux/mfd/db5500-prcmu.h index f0977986402..0d26f72230e 100644 --- a/include/linux/mfd/db5500-prcmu.h +++ b/include/linux/mfd/db5500-prcmu.h @@ -15,6 +15,18 @@ void db5500_prcmu_early_init(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); +int db5500_prcmu_request_clock(u8 clock, bool enable); + +int prcmu_resetout(u8 resoutn, u8 state); + +static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, + bool keep_ap_pll) +{ + return 0; +} + +static inline void prcmu_system_reset(u16 reset_code) {} + #else /* !CONFIG_UX500_SOC_DB5500 */ static inline void db5500_prcmu_early_init(void) @@ -31,6 +43,11 @@ static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) return -ENOSYS; } +static inline int prcmu_resetout(u8 resoutn, u8 state) +{ + return 0; +} + #endif /* CONFIG_UX500_SOC_DB5500 */ static inline int db5500_prcmu_config_abb_event_readout(u32 abb_events) diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h index f56d1171269..b07b8159195 100644 --- a/include/linux/mfd/db8500-prcmu.h +++ b/include/linux/mfd/db8500-prcmu.h @@ -11,7 +11,6 @@ #define __MFD_DB8500_PRCMU_H #include <linux/interrupt.h> -#include <linux/notifier.h> /* This portion previously known as <mach/prcmu-fw-defs_v1.h> */ @@ -133,7 +132,7 @@ enum ap_pwrst { * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle */ enum ap_pwrst_trans { - NO_TRANSITION = 0x00, + PRCMU_AP_NO_CHANGE = 0x00, APEXECUTE_TO_APSLEEP = 0x01, APIDLE_TO_APSLEEP = 0x02, /* To be removed */ PRCMU_AP_SLEEP = 0x01, @@ -160,40 +159,6 @@ enum ddr_pwrst { }; /** - * enum arm_opp - ARM OPP states definition - * @ARM_OPP_INIT: - * @ARM_NO_CHANGE: The ARM operating point is unchanged - * @ARM_100_OPP: The new ARM operating point is arm100opp - * @ARM_50_OPP: The new ARM operating point is arm50opp - * @ARM_MAX_OPP: Operating point is "max" (more than 100) - * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100 - * @ARM_EXTCLK: The new ARM operating point is armExtClk - */ -enum arm_opp { - ARM_OPP_INIT = 0x00, - ARM_NO_CHANGE = 0x01, - ARM_100_OPP = 0x02, - ARM_50_OPP = 0x03, - ARM_MAX_OPP = 0x04, - ARM_MAX_FREQ100OPP = 0x05, - ARM_EXTCLK = 0x07 -}; - -/** - * enum ape_opp - APE OPP states definition - * @APE_OPP_INIT: - * @APE_NO_CHANGE: The APE operating point is unchanged - * @APE_100_OPP: The new APE operating point is ape100opp - * @APE_50_OPP: 50% - */ -enum ape_opp { - APE_OPP_INIT = 0x00, - APE_NO_CHANGE = 0x01, - APE_100_OPP = 0x02, - APE_50_OPP = 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 @@ -469,26 +434,6 @@ enum auto_enable { /* End of file previously known as prcmu-fw-defs_v1.h */ -/* PRCMU Wakeup defines */ -enum prcmu_wakeup_index { - PRCMU_WAKEUP_INDEX_RTC, - PRCMU_WAKEUP_INDEX_RTT0, - PRCMU_WAKEUP_INDEX_RTT1, - PRCMU_WAKEUP_INDEX_HSI0, - PRCMU_WAKEUP_INDEX_HSI1, - PRCMU_WAKEUP_INDEX_USB, - PRCMU_WAKEUP_INDEX_ABB, - PRCMU_WAKEUP_INDEX_ABB_FIFO, - PRCMU_WAKEUP_INDEX_ARM, - NUM_PRCMU_WAKEUP_INDICES -}; -#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name)) - -/* PRCMU QoS APE OPP class */ -#define PRCMU_QOS_APE_OPP 1 -#define PRCMU_QOS_DDR_OPP 2 -#define PRCMU_QOS_DEFAULT_VALUE -1 - /** * enum hw_acc_dev - enum for hw accelerators * @HW_ACC_SVAMMDSP: for SVAMMDSP @@ -527,64 +472,6 @@ enum hw_acc_dev { }; /* - * Ids for all EPODs (power domains) - * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP - * - EPOD_ID_SVAPIPE: power domain for SVA pipe - * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP - * - EPOD_ID_SIAPIPE: power domain for SIA pipe - * - EPOD_ID_SGA: power domain for SGA - * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE - * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2 - * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4 - * - NUM_EPOD_ID: number of power domains - */ -#define EPOD_ID_SVAMMDSP 0 -#define EPOD_ID_SVAPIPE 1 -#define EPOD_ID_SIAMMDSP 2 -#define EPOD_ID_SIAPIPE 3 -#define EPOD_ID_SGA 4 -#define EPOD_ID_B2R2_MCDE 5 -#define EPOD_ID_ESRAM12 6 -#define EPOD_ID_ESRAM34 7 -#define NUM_EPOD_ID 8 - -/* - * state definition for EPOD (power domain) - * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged - * - EPOD_STATE_OFF: The EPOD is switched off - * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in - * retention - * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off - * - EPOD_STATE_ON: Same as above, but with clock enabled - */ -#define EPOD_STATE_NO_CHANGE 0x00 -#define EPOD_STATE_OFF 0x01 -#define EPOD_STATE_RAMRET 0x02 -#define EPOD_STATE_ON_CLK_OFF 0x03 -#define EPOD_STATE_ON 0x04 - -/* - * CLKOUT sources - */ -#define PRCMU_CLKSRC_CLK38M 0x00 -#define PRCMU_CLKSRC_ACLK 0x01 -#define PRCMU_CLKSRC_SYSCLK 0x02 -#define PRCMU_CLKSRC_LCDCLK 0x03 -#define PRCMU_CLKSRC_SDMMCCLK 0x04 -#define PRCMU_CLKSRC_TVCLK 0x05 -#define PRCMU_CLKSRC_TIMCLK 0x06 -#define PRCMU_CLKSRC_CLK009 0x07 -/* These are only valid for CLKOUT1: */ -#define PRCMU_CLKSRC_SIAMMDSPCLK 0x40 -#define PRCMU_CLKSRC_I2CCLK 0x41 -#define PRCMU_CLKSRC_MSP02CLK 0x42 -#define PRCMU_CLKSRC_ARMPLL_OBSCLK 0x43 -#define PRCMU_CLKSRC_HSIRXCLK 0x44 -#define PRCMU_CLKSRC_HSITXCLK 0x45 -#define PRCMU_CLKSRC_ARMCLKFIX 0x46 -#define PRCMU_CLKSRC_HDMICLK 0x47 - -/* * Definitions for autonomous power management configuration. */ @@ -620,59 +507,6 @@ struct prcmu_auto_pm_config { u8 sva_policy; }; -/** - * enum ddr_opp - DDR OPP states definition - * @DDR_100_OPP: The new DDR operating point is ddr100opp - * @DDR_50_OPP: The new DDR operating point is ddr50opp - * @DDR_25_OPP: The new DDR operating point is ddr25opp - */ -enum ddr_opp { - DDR_100_OPP = 0x00, - DDR_50_OPP = 0x01, - DDR_25_OPP = 0x02, -}; - -/* - * Clock identifiers. - */ -enum prcmu_clock { - PRCMU_SGACLK, - PRCMU_UARTCLK, - PRCMU_MSP02CLK, - PRCMU_MSP1CLK, - PRCMU_I2CCLK, - PRCMU_SDMMCCLK, - PRCMU_SLIMCLK, - PRCMU_PER1CLK, - PRCMU_PER2CLK, - PRCMU_PER3CLK, - PRCMU_PER5CLK, - PRCMU_PER6CLK, - PRCMU_PER7CLK, - PRCMU_LCDCLK, - PRCMU_BMLCLK, - PRCMU_HSITXCLK, - PRCMU_HSIRXCLK, - PRCMU_HDMICLK, - PRCMU_APEATCLK, - PRCMU_APETRACECLK, - PRCMU_MCDECLK, - PRCMU_IPI2CCLK, - PRCMU_DSIALTCLK, - PRCMU_DMACLK, - PRCMU_B2R2CLK, - PRCMU_TVCLK, - PRCMU_SSPCLK, - PRCMU_RNGCLK, - PRCMU_UICCCLK, - PRCMU_NUM_REG_CLOCKS, - PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS, - PRCMU_TIMCLK, - PRCMU_PLLSOC0, - PRCMU_PLLSOC1, - PRCMU_PLLDDR, -}; - /* * Definitions for controlling ESRAM0 in deep sleep. */ @@ -694,13 +528,7 @@ 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); int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll); - void prcmu_enable_wakeups(u32 wakeups); -static inline void prcmu_disable_wakeups(void) -{ - prcmu_enable_wakeups(0); -} - 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); @@ -780,12 +608,12 @@ static inline int prcmu_get_arm_opp(void) return ARM_100_OPP; } -static bool prcmu_has_arm_maxopp(void) +static inline bool prcmu_has_arm_maxopp(void) { return false; } -static bool prcmu_is_u8400(void) +static inline bool prcmu_is_u8400(void) { return false; } @@ -934,48 +762,4 @@ static inline int prcmu_disable_spi2(void) #endif /* !CONFIG_MFD_DB8500_PRCMU */ -#ifdef CONFIG_UX500_PRCMU_QOS_POWER -int prcmu_qos_requirement(int pm_qos_class); -int prcmu_qos_add_requirement(int pm_qos_class, char *name, s32 value); -int prcmu_qos_update_requirement(int pm_qos_class, char *name, s32 new_value); -void prcmu_qos_remove_requirement(int pm_qos_class, char *name); -int prcmu_qos_add_notifier(int prcmu_qos_class, - struct notifier_block *notifier); -int prcmu_qos_remove_notifier(int prcmu_qos_class, - struct notifier_block *notifier); -#else -static inline int prcmu_qos_requirement(int prcmu_qos_class) -{ - return 0; -} - -static inline int prcmu_qos_add_requirement(int prcmu_qos_class, - char *name, s32 value) -{ - return 0; -} - -static inline int prcmu_qos_update_requirement(int prcmu_qos_class, - char *name, s32 new_value) -{ - return 0; -} - -static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name) -{ -} - -static inline int prcmu_qos_add_notifier(int prcmu_qos_class, - struct notifier_block *notifier) -{ - return 0; -} -static inline int prcmu_qos_remove_notifier(int prcmu_qos_class, - struct notifier_block *notifier) -{ - return 0; -} - -#endif - #endif /* __MFD_DB8500_PRCMU_H */ |