diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2011-09-15 08:07:10 +0200 |
---|---|---|
committer | Jonas ABERG <jonas.aberg@stericsson.com> | 2011-09-29 08:37:38 +0200 |
commit | 4f7f69516c999833450c04752c24722f9b9d63b9 (patch) | |
tree | 1fde4744e012e16697a8eb1dec1773790277006b /arch | |
parent | e77cfe48e06393c94a6e14e84820144c4f2426ba (diff) |
ARM: ux500: Replace mach prcmu driver with mainlined version
The prcmu driver now exists in drivers/mfd
Change-Id: I0c8d97679ee186ca8205aeeafa0030568f540d2e
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32057
Diffstat (limited to 'arch')
23 files changed, 25 insertions, 5849 deletions
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index c839b667ffa..cb300313063 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -24,7 +24,6 @@ CONFIG_ARCH_U8500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y -CONFIG_U8500_PRCMU=y CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y CONFIG_DISPLAY_GENERIC_PRIMARY=y @@ -190,6 +189,7 @@ CONFIG_SENSORS_L3G4200D=y CONFIG_WATCHDOG=y CONFIG_MFD_STMPE=y CONFIG_MFD_TC3589X=y +CONFIG_MFD_DB8500_PRCMU=y CONFIG_TPS6105X=y CONFIG_AB5500_CORE=y CONFIG_AB8500_CORE=y diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index f015ab84eec..ef1ad788fed 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -73,20 +73,6 @@ config KEYLAYOUT_LAYOUT2 endchoice -config U8500_PRCMU - bool "U8500 PRCMU support" - depends on UX500_SOC_DB8500 - default n - help - Add support for PRCMU for U8500 - -config U5500_PRCMU - bool "U5500 PRCMU support" - depends on UX500_SOC_DB5500 - default y - help - Add support for PRCMU for U5500 - config UX500_DEBUG_UART int "Ux500 UART to use for low-level debug" default 2 diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 4ae7dfdd937..dfcdd2a4b8d 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -48,8 +48,6 @@ obj-$(CONFIG_TEE_SVP) += tee_service_svp.o obj-$(CONFIG_TEE_SVP) += tee_ta_start_modem_svp.o obj-$(CONFIG_DB8500_MLOADER) += mloader-db8500.o obj-$(CONFIG_U5500_MLOADER) += mloader-db5500.o -obj-$(CONFIG_U5500_PRCMU) += prcmu-db5500.o -obj-$(CONFIG_U8500_PRCMU) += prcmu-db8500.o obj-$(CONFIG_U8500_REGULATOR_DEBUG) += virt-regulator-u8500.o obj-$(CONFIG_UX500_DEBUG_HWREG) += hwreg.o obj-$(CONFIG_HWMEM) += hwmem-int.o diff --git a/arch/arm/mach-ux500/board-mop500-cyttsp.c b/arch/arm/mach-ux500/board-mop500-cyttsp.c index 9723ee21f16..3a0e23e6d94 100755 --- a/arch/arm/mach-ux500/board-mop500-cyttsp.c +++ b/arch/arm/mach-ux500/board-mop500-cyttsp.c @@ -14,7 +14,7 @@ #include <mach/hardware.h> #include <mach/irqs.h> #include <mach/irqs-db8500.h> -#include "include/mach/prcmu-db8500.h" +#include <linux/mfd/dbx500-prcmu.h> #include "pins-db8500.h" #include "board-mop500.h" #include "devices-db8500.h" diff --git a/arch/arm/mach-ux500/clock-db8500.c b/arch/arm/mach-ux500/clock-db8500.c index 0130172f048..b3d9c0ba242 100644 --- a/arch/arm/mach-ux500/clock-db8500.c +++ b/arch/arm/mach-ux500/clock-db8500.c @@ -27,7 +27,7 @@ #include <plat/pincfg.h> #include <mach/hardware.h> -#include <mach/prcmu.h> +#include <linux/mfd/dbx500-prcmu.h> #include "clock.h" #include "pins-db8500.h" diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 95e6a8e705d..b623ee8d864 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -11,8 +11,7 @@ #include <linux/io.h> #include <linux/spinlock.h> #include <linux/mfd/ab8500/sysctrl.h> -#include <mach/prcmu.h> -#include <mach/prcmu-regs.h> +#include <linux/mfd/dbx500-prcmu.h> #include "clock.h" @@ -436,6 +435,8 @@ void clks_register(struct clk_lookup *clks, size_t num) for (i = 0; i < num; i++) clkdev_add(&clks[i]); } +/* TODO: Move to proper place */ +#define PRCM_DBG_PWRCTL 0x4AC int __init clk_init(void) { @@ -450,14 +451,14 @@ int __init clk_init(void) if (cpu_is_u8500()) db8500_clk_init(); - else if (cpu_is_u5500()) { - unsigned int temp = 0; - db5500_clk_init(); - if (cpu_is_u5500v1()) - temp = readl(prcmu_base + PRCM_DBG_PWRCTL); - temp |= 0x18; - writel(temp, (prcmu_base + PRCM_DBG_PWRCTL)); - } + else if (cpu_is_u5500()) { + unsigned int temp = 0; + db5500_clk_init(); + if (cpu_is_u5500v1()) + temp = readl(prcmu_base + PRCM_DBG_PWRCTL); + temp |= 0x18; + writel(temp, (prcmu_base + PRCM_DBG_PWRCTL)); + } return 0; } diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index e06e400c16a..f005d808b4d 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -24,7 +24,7 @@ #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> -#include <mach/prcmu.h> +#include <linux/mfd/dbx500-prcmu.h> #include <mach/reboot_reasons.h> #include <mach/usb.h> #include <mach/ste-dma40-db8500.h> diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 76d8d095189..360b3b9aa18 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/clksrc-dbx500-prcmu.h> +#include <linux/mfd/dbx500-prcmu.h> #include <asm/cacheflush.h> #include <asm/hardware/cache-l2x0.h> @@ -20,7 +21,6 @@ #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> -#include <mach/prcmu.h> #include <mach/reboot_reasons.h> #include "clock.h" diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 47124f5c7a5..86e371f444b 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -25,8 +25,7 @@ #include <mach/hardware.h> #include <mach/setup.h> #include <video/mcde.h> -#include <mach/prcmu.h> -#include <mach/prcmu-regs.h> +#include <linux/mfd/dbx500-prcmu.h> #include <mach/hsi.h> #include <mach/ste-dma40-db8500.h> #include <trace/stm.h> @@ -522,6 +521,11 @@ static int stm_ste_disable_ape_on_mipi60(void) /* * Manage STM output pins connection (MIP34/MIPI60 connectors) */ +#define PRCM_GPIOCR (_PRCMU_BASE + 0x138) +#define PRCM_GPIOCR_DBG_STM_MOD_CMD1 0x800 +#define PRCM_GPIOCR_DBG_UARTMOD_CMD0 0x1 + + static int stm_ste_connection(enum stm_connection_type con_type) { int retval = -EINVAL; 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 ef1d7b7964f..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-db5500.h +++ /dev/null @@ -1,67 +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_U5500_PRCMU - -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); - -static inline unsigned long prcmu_clock_rate(u8 clock) -{ - return 0; -} - -static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate) -{ - return 0; -} - -static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate) -{ - return 0; -} - -int prcmu_resetout(u8 resoutn, u8 state); - -unsigned int prcmu_get_ddr_freq(void); -int prcmu_get_hotdog(void); - -#else /* !CONFIG_U5500_PRCMU */ - -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; -} - -static inline unsigned int prcmu_get_ddr_freq(void) -{ - return 0; -} - -static inline int prcmu_get_hotdog(void) -{ - return -ENOSYS; -} - -#endif /* CONFIG_U5500_PRCMU */ - -#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 c3c3fc957c6..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-db8500.h +++ /dev/null @@ -1,278 +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 -}; - -/** - * 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_U8500_PRCMU - -bool prcmu_is_u8400(void); - -int prcmu_request_ape_opp_100_voltage(bool enable); - -int prcmu_release_usb_wakeup_state(void); - -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? */ -bool prcmu_has_arm_maxopp(void); -void prcmu_enable_spi2(void); -void prcmu_disable_spi2(void); - -int prcmu_config_a9wdog(u8 num, bool sleep_auto_off); -int prcmu_enable_a9wdog(u8 id); -int prcmu_disable_a9wdog(u8 id); -int prcmu_kick_a9wdog(u8 id); -int prcmu_load_a9wdog(u8 id, u32 val); - -#else /* !CONFIG_U8500_PRCMU */ - -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 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 bool prcmu_has_arm_maxopp(void) -{ - return false; -} - -static inline int prcmu_enable_spi2(void) -{ - return 0; -} - -static inline int prcmu_disable_spi2(void) -{ - return 0; -} - -static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) -{ - return 0; -} - -static inline int prcmu_enable_a9wdog(u8 id) -{ - return 0; -} - -static inline int prcmu_disable_a9wdog(u8 id) -{ - return 0; -} - -static inline int prcmu_kick_a9wdog(u8 id) -{ - return 0; -} - -static inline int prcmu_load_a9wdog(u8 id, u32 val) -{ - return 0; -} - -#endif /* CONFIG_U8500_PRCMU */ - -#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 915ed52a593..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-qos.h +++ /dev/null @@ -1,88 +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_ARM_OPP 3 -#define PRCMU_QOS_DEFAULT_VALUE -1 - -#if defined(CONFIG_U8500_PRCMU) || defined(CONFIG_U5500_PRCMU) - -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); -void prcmu_qos_voice_call_override(bool enable); - -#else /* !CONFIG_U8500_PRCMU */ - -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 void prcmu_qos_voice_call_override(bool enable) {} - -#endif /* CONFIG_U8500_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 /* __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 deleted file mode 100644 index 5eed1771880..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h +++ /dev/null @@ -1,111 +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 <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 - -#define PRCM_DBG_PWRCTL 0x4AC - -#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 deleted file mode 100644 index 53e08d6bfdd..00000000000 --- a/arch/arm/mach-ux500/include/mach/prcmu.h +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (C) ST Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - * - * STE Ux500 PRCMU API - */ -#ifndef __MACH_PRCMU_H -#define __MACH_PRCMU_H - -#include <linux/interrupt.h> -#include <mach/prcmu-qos.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, - PRCMU_WAKEUP_INDEX_CD_IRQ, - NUM_PRCMU_WAKEUP_INDICES -}; -#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 */ - -/* - * DB8500 EPODs - * - 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 - * - * TODO: These should be prefixed. - */ -#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 - -/* - * DB5500 EPODs - */ -#define DB5500_EPOD_ID_BASE 0x0100 -#define DB5500_EPOD_ID_SGA (DB5500_EPOD_ID_BASE + 0) -#define DB5500_EPOD_ID_HVA (DB5500_EPOD_ID_BASE + 1) -#define DB5500_EPOD_ID_SIA (DB5500_EPOD_ID_BASE + 2) -#define DB5500_EPOD_ID_DISP (DB5500_EPOD_ID_BASE + 3) -#define DB5500_EPOD_ID_ESRAM12 (DB5500_EPOD_ID_BASE + 6) -#define DB5500_NUM_EPOD_ID 7 - -/* - * 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 - -/* DB5500 CLKOUT IDs */ -enum { - DB5500_CLKOUT0 = 0, - DB5500_CLKOUT1, -}; - -/* DB5500 CLKOUTx sources */ -enum { - DB5500_CLKOUT_REF_CLK_SEL0, - DB5500_CLKOUT_RTC_CLK0_SEL0, - DB5500_CLKOUT_ULP_CLK_SEL0, - DB5500_CLKOUT_STATIC0, - DB5500_CLKOUT_REFCLK, - DB5500_CLKOUT_ULPCLK, - DB5500_CLKOUT_ARMCLK, - DB5500_CLKOUT_SYSACC0CLK, - DB5500_CLKOUT_SOC0PLLCLK, - DB5500_CLKOUT_SOC1PLLCLK, - DB5500_CLKOUT_DDRPLLCLK, - DB5500_CLKOUT_TVCLK, - DB5500_CLKOUT_IRDACLK, -}; - -/* - * DB8500 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 - -/* - * Clock identifiers. - */ -enum prcmu_clock { - PRCMU_SGACLK, - PRCMU_UARTCLK, - PRCMU_MSP02CLK, - PRCMU_MSP1CLK, - PRCMU_I2CCLK, - PRCMU_SDMMCCLK, - PRCMU_SPARE1CLK, - 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_PWMCLK, - PRCMU_IRDACLK, - PRCMU_IRRCCLK, - PRCMU_SIACLK, - PRCMU_SVACLK, - PRCMU_NUM_REG_CLOCKS, - PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS, - PRCMU_CDCLK, - PRCMU_TIMCLK, - PRCMU_PLLSOC0, - PRCMU_PLLSOC1, - PRCMU_PLLDDR, -}; - -/** - * 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% - * @APE_50_PARTLY_25_OPP: 50%, except some clocks at 25%. - */ -enum ape_opp { - APE_OPP_INIT = 0x00, - APE_NO_CHANGE = 0x01, - APE_100_OPP = 0x02, - APE_50_OPP = 0x03, - APE_50_PARTLY_25_OPP = 0xFF, -}; - -/** - * 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 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, -}; - -/* - * Definitions for controlling ESRAM0 in deep sleep. - */ -#define ESRAM0_DEEP_SLEEP_STATE_OFF 1 -#define ESRAM0_DEEP_SLEEP_STATE_RET 2 - -/** - * enum ddr_pwrst - DDR power states definition - * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged - * @DDR_PWR_STATE_ON: - * @DDR_PWR_STATE_OFFLOWLAT: - * @DDR_PWR_STATE_OFFHIGHLAT: - */ -enum ddr_pwrst { - DDR_PWR_STATE_UNCHANGED = 0x00, - DDR_PWR_STATE_ON = 0x01, - DDR_PWR_STATE_OFFLOWLAT = 0x02, - DDR_PWR_STATE_OFFHIGHLAT = 0x03 -}; - -#include <mach/prcmu-db8500.h> -#include <mach/prcmu-db5500.h> - -#if defined(CONFIG_U8500_PRCMU) || defined(CONFIG_U5500_PRCMU) - -void __init prcmu_early_init(void); - -int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll); - -int prcmu_set_epod(u16 epod_id, u8 epod_state); - -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_abb_read(u8 slave, u8 reg, u8 *value, u8 size); -int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); - -int prcmu_config_clkout(u8 clkout, u8 source, u8 div); - -int prcmu_request_clock(u8 clock, bool enable); -unsigned long prcmu_clock_rate(u8 clock); -long prcmu_round_clock_rate(u8 clock, unsigned long rate); -int prcmu_set_clock_rate(u8 clock, unsigned long rate); - -int prcmu_set_ape_opp(u8 opp); -int prcmu_get_ape_opp(void); -int prcmu_set_arm_opp(u8 opp); -int prcmu_get_arm_opp(void); -int prcmu_set_ddr_opp(u8 opp); -int prcmu_get_ddr_opp(void); - -void prcmu_system_reset(u16 reset_code); -u16 prcmu_get_reset_code(void); - -void prcmu_ac_wake_req(void); -void prcmu_ac_sleep_req(void); -void prcmu_modem_reset(void); -bool prcmu_is_ac_wake_requested(void); - -int prcmu_set_display_clocks(void); -int prcmu_disable_dsipll(void); -int prcmu_enable_dsipll(void); -int prcmu_config_esram0_deep_sleep(u8 state); - -int prcmu_config_hotdog(u8 threshold); -int prcmu_config_hotmon(u8 low, u8 high); -int prcmu_start_temp_sense(u16 cycles32k); -int prcmu_stop_temp_sense(void); - -#else - -static inline void __init prcmu_early_init(void) {} - -static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk, - bool keep_ap_pll) -{ - return 0; -} - -static inline int prcmu_set_epod(u16 epod_id, u8 epod_state) -{ - return 0; -} - -static inline void prcmu_enable_wakeups(u32 wakeups) {} - -static inline void prcmu_disable_wakeups(void) {} - -static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size) -{ - return -ENOSYS; -} - -static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size) -{ - return -ENOSYS; -} - -static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div) -{ - return 0; -} - -static inline int prcmu_request_clock(u8 clock, bool enable) -{ - return 0; -} - -static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate) -{ - return 0; -} - -static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate) -{ - return 0; -} - -static inline unsigned long prcmu_clock_rate(u8 clock) -{ - return 0; -} - -static inline int prcmu_set_ape_opp(u8 opp) -{ - return 0; -} - -static inline int prcmu_get_ape_opp(void) -{ - return APE_100_OPP; -} - -static inline int prcmu_set_arm_opp(u8 opp) -{ - return 0; -} - -static inline int prcmu_get_arm_opp(void) -{ - return ARM_100_OPP; -} - -static inline int prcmu_set_ddr_opp(u8 opp) -{ - return 0; -} - -static inline int prcmu_get_ddr_opp(void) -{ - return DDR_100_OPP; -} - -static inline void prcmu_system_reset(u16 reset_code) {} - -static inline u16 prcmu_get_reset_code(void) -{ - return 0; -} - -static inline void prcmu_ac_wake_req(void) {} - -static inline void prcmu_ac_sleep_req(void) {} - -static inline void prcmu_modem_reset(void) {} - -static inline bool prcmu_is_ac_wake_requested(void) -{ - return false; -} - -static inline int prcmu_set_display_clocks(void) -{ - return 0; -} - -static inline int prcmu_disable_dsipll(void) -{ - return 0; -} - -static inline int prcmu_enable_dsipll(void) -{ - return 0; -} - -static inline int prcmu_config_esram0_deep_sleep(u8 state) -{ - return 0; -} - -static inline void prcmu_config_abb_event_readout(u32 abb_events) {} - -static inline void prcmu_get_abb_event_buffer(void __iomem **buf) -{ - *buf = NULL; -} - -static int prcmu_config_hotdog(u8 threshold) -{ - return 0; -} - -static int prcmu_config_hotmon(u8 low, u8 high) -{ - return 0; -} - -static int prcmu_start_temp_sense(u16 cycles32k) -{ - return 0; -} -static int prcmu_stop_temp_sense(void) -{ - return 0; -} - -#endif - -#endif /* __MACH_PRCMU_H */ diff --git a/arch/arm/mach-ux500/include/mach/system.h b/arch/arm/mach-ux500/include/mach/system.h index 89699238681..42bc8c72a79 100644 --- a/arch/arm/mach-ux500/include/mach/system.h +++ b/arch/arm/mach-ux500/include/mach/system.h @@ -8,7 +8,7 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H -#include <mach/prcmu.h> +#include <linux/mfd/dbx500-prcmu.h> #include <mach/reboot_reasons.h> static inline void arch_idle(void) diff --git a/arch/arm/mach-ux500/prcmu-db5500.c b/arch/arm/mach-ux500/prcmu-db5500.c deleted file mode 100644 index 6c71981912b..00000000000 --- a/arch/arm/mach-ux500/prcmu-db5500.c +++ /dev/null @@ -1,1972 +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-debug.h" -#include "prcmu-regs-db5500.h" - -#define PRCMU_FW_VERSION_OFFSET 0xA4 -#define PRCM_DDR_FREQUENCY (tcdm_base + 0x268) /* 4 bytes */ -#define PRCM_SW_RST_REASON (tcdm_base + 0xFF8) /* 2 bytes */ - -#define _PRCM_MB_HEADER (tcdm_base + 0xFE8) -#define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0) -#define PRCM_REQ_MB1_HEADER (_PRCM_MB_HEADER + 0x1) -#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) - -/* Share info */ -#define PRCM_SHARE_INFO (tcdm_base + 0xEC8) - -#define PRCM_SHARE_INFO_HOTDOG (PRCM_SHARE_INFO + 62) - -/* Mailbox 0 REQs */ -#define PRCM_REQ_MB0_AP_POWER_STATE (PRCM_REQ_MB0 + 0x0) -#define PRCM_REQ_MB0_ULP_CLOCK_STATE (PRCM_REQ_MB0 + 0x1) -#define PRCM_REQ_MB0_AP_PLL_STATE (PRCM_REQ_MB0 + 0x2) -#define PRCM_REQ_MB0_DDR_STATE (PRCM_REQ_MB0 + 0x3) -#define PRCM_REQ_MB0_ESRAM0_STATE (PRCM_REQ_MB0 + 0x4) -#define PRCM_REQ_MB0_WAKEUP_DBB (PRCM_REQ_MB0 + 0x8) -#define PRCM_REQ_MB0_WAKEUP_ABB (PRCM_REQ_MB0 + 0xC) - -/* Mailbox 0 ACKs */ -#define PRCM_ACK_MB0_AP_PWRSTTR_STATUS (PRCM_ACK_MB0 + 0x0) -#define PRCM_ACK_MB0_READ_POINTER (PRCM_ACK_MB0 + 0x1) -#define PRCM_ACK_MB0_WAKEUP_0_DBB (PRCM_ACK_MB0 + 0x4) -#define PRCM_ACK_MB0_WAKEUP_0_ABB (PRCM_ACK_MB0 + 0x8) -#define PRCM_ACK_MB0_WAKEUP_1_DBB (PRCM_ACK_MB0 + 0x28) -#define PRCM_ACK_MB0_WAKEUP_1_ABB (PRCM_ACK_MB0 + 0x2C) -#define PRCM_ACK_MB0_EVENT_ABB_NUMBERS 20 - -/* Request mailbox 1 fields. */ -#define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0) -#define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1) - -/* Mailbox 1 ACKs */ -#define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0) -#define PRCM_ACK_MB1_CURRENT_APE_OPP (PRCM_ACK_MB1 + 0x1) -#define PRCM_ACK_MB1_ARM_VOLT_STATUS (PRCM_ACK_MB1 + 0x2) -#define PRCM_ACK_MB1_APE_VOLT_STATUS (PRCM_ACK_MB1 + 0x3) - -/* Mailbox 2 REQs */ -#define PRCM_REQ_MB2_EPOD_CLIENT (PRCM_REQ_MB2 + 0x0) -#define PRCM_REQ_MB2_EPOD_STATE (PRCM_REQ_MB2 + 0x1) -#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 { - /* acknowledge */ - MB0H_WAKE_UP = 0, - /* request */ - MB0H_PWR_STATE_TRANS, - MB0H_WAKE_UP_CFG, - MB0H_RD_WAKE_UP_ACK, -}; - -/* Mailbox 1 headers.*/ -enum mb1_header { - MB1H_ARM_OPP = 1, - MB1H_APE_OPP, - MB1H_ARM_APE_OPP, -}; - -/* Mailbox 2 headers. */ -enum mb2_header { - MB2H_EPOD_REQUEST = 1, - MB2H_CLK_REQUEST, - MB2H_PLL_REQUEST, -}; - -/* Mailbox 3 headers */ -enum mb3_header { - MB3H_REFCLK_REQUEST = 1, -}; - -enum sysclk_state { - SYSCLK_OFF, - SYSCLK_ON, -}; - -/* Mailbox 4 headers */ -enum mb4_header { - MB4H_CFG_HOTDOG = 7, - MB4H_CFG_HOTMON = 8, - MB4H_CFG_HOTPERIOD = 10, -}; - -/* Mailbox 4 ACK headers */ -enum mb4_ack_header { - MB4H_ACK_CFG_HOTDOG = 5, - MB4H_ACK_CFG_HOTMON = 6, - MB4H_ACK_CFG_HOTPERIOD = 8, -}; - -/* Mailbox 5 headers. */ -enum mb5_header { - MB5H_I2C_WRITE = 1, - MB5H_I2C_READ, -}; - -enum db5500_arm_opp { - DB5500_ARM_100_OPP = 1, - DB5500_ARM_50_OPP, - DB5500_ARM_EXT_OPP, -}; - -enum db5500_ape_opp { - DB5500_APE_100_OPP = 1, - DB5500_APE_50_OPP -}; - -enum epod_state { - EPOD_OFF, - EPOD_ON, -}; -enum epod_onoffret_state { - EPOD_OOR_OFF, - EPOD_OOR_RET, - EPOD_OOR_ON, -}; -enum db5500_prcmu_pll { - DB5500_PLL_SOC0, - DB5500_PLL_SOC1, - DB5500_PLL_DDR, - DB5500_NUM_PLL_ID, -}; - -enum db5500_prcmu_clk { - DB5500_MSP1CLK, - DB5500_CDCLK, - DB5500_IRDACLK, - DB5500_TVCLK, - DB5500_NUM_CLK_CLIENTS, -}; - -enum on_off_ret { - OFF_ST, - RET_ST, - ON_ST, -}; - -enum db5500_ap_pwr_state { - DB5500_AP_SLEEP = 2, - DB5500_AP_DEEP_SLEEP, - DB5500_AP_IDLE, -}; - -/* Request mailbox 3 fields */ -#define PRCM_REQ_MB3_REFCLK_MGT (PRCM_REQ_MB3 + 0x0) - -/* Ack. mailbox 3 fields */ -#define PRCM_ACK_MB3_REFCLK_REQ (PRCM_ACK_MB3 + 0x0) - - -/* Request mailbox 4 fields */ -#define PRCM_REQ_MB4_HOTDOG_THRESHOLD (PRCM_REQ_MB4 + 32) -#define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 34) -#define PRCM_REQ_MB4_HOTMON_LOW (PRCM_REQ_MB4 + 36) -#define PRCM_REQ_MB4_HOTMON_HIGH (PRCM_REQ_MB4 + 38) - -/* Ack. mailbox 4 field */ -#define PRCM_ACK_MB4_REQUESTS (PRCM_ACK_MB4 + 0x0) - -/* Request mailbox 5 fields. */ -#define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0) -#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1) -#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 - -/* - * Wakeups/IRQs - */ - -#define WAKEUP_BIT_RTC BIT(0) -#define WAKEUP_BIT_RTT0 BIT(1) -#define WAKEUP_BIT_RTT1 BIT(2) -#define WAKEUP_BIT_CD_IRQ BIT(3) -#define WAKEUP_BIT_SRP_TIM BIT(4) -#define WAKEUP_BIT_APE_REQ BIT(5) -#define WAKEUP_BIT_USB BIT(6) -#define WAKEUP_BIT_ABB BIT(7) -#define WAKEUP_BIT_LOW_POWER_AUDIO BIT(8) -#define WAKEUP_BIT_TEMP_SENSOR_LOW BIT(9) -#define WAKEUP_BIT_ARM BIT(10) -#define WAKEUP_BIT_AC_WAKE_ACK BIT(11) -#define WAKEUP_BIT_TEMP_SENSOR_HIGH BIT(12) -#define WAKEUP_BIT_MODEM_SW_RESET_REQ BIT(20) -#define WAKEUP_BIT_GPIO0 BIT(23) -#define WAKEUP_BIT_GPIO1 BIT(24) -#define WAKEUP_BIT_GPIO2 BIT(25) -#define WAKEUP_BIT_GPIO3 BIT(26) -#define WAKEUP_BIT_GPIO4 BIT(27) -#define WAKEUP_BIT_GPIO5 BIT(28) -#define WAKEUP_BIT_GPIO6 BIT(29) -#define WAKEUP_BIT_GPIO7 BIT(30) -#define WAKEUP_BIT_AC_REL_ACK BIT(30) - -/* - * This vector maps irq numbers to the bits in the bit field used in - * communication with the PRCMU firmware. - * - * The reason for having this is to keep the irq numbers contiguous even though - * the bits in the bit field are not. (The bits also have a tendency to move - * around, to further complicate matters.) - */ -#define IRQ_INDEX(_name) ((IRQ_DB5500_PRCMU_##_name) - IRQ_DB5500_PRCMU_BASE) -#define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name) -static u32 prcmu_irq_bit[NUM_DB5500_PRCMU_WAKEUPS] = { - IRQ_ENTRY(RTC), - IRQ_ENTRY(RTT0), - IRQ_ENTRY(RTT1), - IRQ_ENTRY(CD_IRQ), - IRQ_ENTRY(SRP_TIM), - IRQ_ENTRY(APE_REQ), - IRQ_ENTRY(USB), - IRQ_ENTRY(ABB), - IRQ_ENTRY(LOW_POWER_AUDIO), - IRQ_ENTRY(TEMP_SENSOR_LOW), - IRQ_ENTRY(TEMP_SENSOR_HIGH), - IRQ_ENTRY(ARM), - IRQ_ENTRY(AC_WAKE_ACK), - IRQ_ENTRY(MODEM_SW_RESET_REQ), - IRQ_ENTRY(GPIO0), - IRQ_ENTRY(GPIO1), - IRQ_ENTRY(GPIO2), - IRQ_ENTRY(GPIO3), - IRQ_ENTRY(GPIO4), - IRQ_ENTRY(GPIO5), - IRQ_ENTRY(GPIO6), - IRQ_ENTRY(GPIO7), - IRQ_ENTRY(AC_REL_ACK), -}; - -#define VALID_WAKEUPS (BIT(NUM_PRCMU_WAKEUP_INDICES) - 1) -#define WAKEUP_ENTRY(_name)[PRCMU_WAKEUP_INDEX_##_name] = (WAKEUP_BIT_##_name) -static u32 prcmu_wakeup_bit[NUM_PRCMU_WAKEUP_INDICES] = { - WAKEUP_ENTRY(RTC), - WAKEUP_ENTRY(RTT0), - WAKEUP_ENTRY(RTT1), - WAKEUP_ENTRY(CD_IRQ), - WAKEUP_ENTRY(USB), - WAKEUP_ENTRY(ABB), - WAKEUP_ENTRY(ARM) -}; - -/* - * mb0_transfer - state needed for mailbox 0 communication. - * @lock The transaction lock. - * @dbb_irqs_lock lock used for (un)masking DBB wakeup interrupts - * @mask_work: Work structure used for (un)masking wakeup interrupts. - * @req: Request data that need to persist between requests. - */ -static struct { - spinlock_t lock; - spinlock_t dbb_irqs_lock; - struct work_struct mask_work; - struct { - u32 dbb_irqs; - u32 dbb_wakeups; - u32 abb_events; - } req; -} mb0_transfer; - - -/* - * mb1_transfer - state needed for mailbox 1 communication. - * @lock: The transaction lock. - * @work: The transaction completion structure. - * @req_arm_opp Requested arm opp - * @req_ape_opp Requested ape opp - * @ack: Reply ("acknowledge") data. - */ -static struct { - struct mutex lock; - struct completion work; - u8 req_arm_opp; - u8 req_ape_opp; - struct { - u8 header; - u8 arm_opp; - u8 ape_opp; - u8 arm_voltage_st; - u8 ape_voltage_st; - } ack; -} mb1_transfer; - -/* - * mb2_transfer - state needed for mailbox 2 communication. - * @lock: The transaction lock. - * @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_st[DB5500_NUM_EPOD_ID]; - u8 pll_st[DB5500_NUM_PLL_ID]; - } req; - struct { - u8 header; - u8 status; - } ack; -} mb2_transfer; - -/* - * mb3_transfer - state needed for mailbox 3 communication. - * @sysclk_lock: A lock used to handle concurrent sysclk requests. - * @sysclk_work: Work structure used for sysclk requests. - * @req_st: Requested clock state. - * @ack: Acknowledgement data - */ -static struct { - struct mutex sysclk_lock; - struct completion sysclk_work; - enum sysclk_state req_st; - struct { - u8 header; - u8 status; - } ack; -} mb3_transfer; - -/* - * mb4_transfer - state needed for mailbox 4 communication. - * @lock: The transaction lock. - * @work: The transaction completion structure. - * @ack: Acknowledgement data - */ -static struct { - struct mutex lock; - struct completion work; - struct { - u8 header; - u8 status; - } ack; -} mb4_transfer; - -/* - * mb5_transfer - state needed for mailbox 5 communication. - * @lock: The transaction lock. - * @work: The transaction completion structure. - * @ack: Reply ("acknowledge") data. - */ -static struct { - struct mutex lock; - struct completion work; - struct { - u8 header; - u8 status; - u8 value[4]; - } ack; -} mb5_transfer; - -/* Spinlocks */ -static DEFINE_SPINLOCK(clkout_lock); - -/* PRCMU TCDM base IO address. */ -static __iomem void *tcdm_base; - -struct clk_mgt { - unsigned int offset; - u32 pllsw; - u32 div; - bool scalable; - bool force50; -}; - -/* PRCMU Firmware Details */ -static struct { - u16 board; - u8 fw_version; - u8 api_version; -} prcmu_version; - -static DEFINE_SPINLOCK(clk_mgt_lock); - -#define CLK_MGT_ENTRY(_name, _scalable)[PRCMU_##_name] = { \ - .offset = DB5500_PRCM_##_name##_MGT, \ - .scalable = _scalable, \ -} - -static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { - CLK_MGT_ENTRY(SGACLK, true), - CLK_MGT_ENTRY(UARTCLK, false), - CLK_MGT_ENTRY(MSP02CLK, false), - CLK_MGT_ENTRY(I2CCLK, false), - [PRCMU_SDMMCCLK] { - .offset = DB5500_PRCM_SDMMCCLK_MGT, - .force50 = true, - .scalable = false, - - }, - [PRCMU_SPARE1CLK] { - .offset = DB5500_PRCM_SPARE1CLK_MGT, - .force50 = true, - .scalable = false, - - }, - CLK_MGT_ENTRY(PER1CLK, false), - CLK_MGT_ENTRY(PER2CLK, true), - CLK_MGT_ENTRY(PER3CLK, true), - CLK_MGT_ENTRY(PER5CLK, false), /* used for SPI */ - CLK_MGT_ENTRY(PER6CLK, true), - CLK_MGT_ENTRY(PWMCLK, false), - CLK_MGT_ENTRY(IRDACLK, false), - CLK_MGT_ENTRY(IRRCCLK, false), - CLK_MGT_ENTRY(HDMICLK, false), - CLK_MGT_ENTRY(APEATCLK, false), - CLK_MGT_ENTRY(APETRACECLK, true), - CLK_MGT_ENTRY(MCDECLK, true), - CLK_MGT_ENTRY(DSIALTCLK, false), - CLK_MGT_ENTRY(DMACLK, true), - CLK_MGT_ENTRY(B2R2CLK, true), - CLK_MGT_ENTRY(TVCLK, false), - CLK_MGT_ENTRY(RNGCLK, false), - CLK_MGT_ENTRY(SIACLK, false), - CLK_MGT_ENTRY(SVACLK, false), -}; - -bool prcmu_is_ac_wake_requested(void) -{ - return false; -} - -/** - * prcmu_config_clkout - Configure one of the programmable clock outputs. - * @clkout: The CLKOUT number (0 or 1). - * @source: Clock source. - * @div: The divider to be applied. - * - * Configures one of the programmable clock outputs (CLKOUTs). - */ -int prcmu_config_clkout(u8 clkout, u8 source, u8 div) -{ - static bool configured[2] = {false, false}; - int r = 0; - unsigned long flags; - u32 sel_val; - u32 div_val; - u32 sel_bits; - u32 div_bits; - u32 sel_mask; - u32 div_mask; - u8 sel0 = CLKOUT_SEL0_SEL_CLK; - u16 sel = 0; - - BUG_ON(clkout > DB5500_CLKOUT1); - BUG_ON(source > DB5500_CLKOUT_IRDACLK); - BUG_ON(div > 7); - - switch (source) { - case DB5500_CLKOUT_REF_CLK_SEL0: - sel0 = CLKOUT_SEL0_REF_CLK; - break; - case DB5500_CLKOUT_RTC_CLK0_SEL0: - sel0 = CLKOUT_SEL0_RTC_CLK0; - break; - case DB5500_CLKOUT_ULP_CLK_SEL0: - sel0 = CLKOUT_SEL0_ULP_CLK; - break; - case DB5500_CLKOUT_STATIC0: - sel = CLKOUT_SEL_STATIC0; - break; - case DB5500_CLKOUT_REFCLK: - sel = CLKOUT_SEL_REFCLK; - break; - case DB5500_CLKOUT_ULPCLK: - sel = CLKOUT_SEL_ULPCLK; - break; - case DB5500_CLKOUT_ARMCLK: - sel = CLKOUT_SEL_ARMCLK; - break; - case DB5500_CLKOUT_SYSACC0CLK: - sel = CLKOUT_SEL_SYSACC0CLK; - break; - case DB5500_CLKOUT_SOC0PLLCLK: - sel = CLKOUT_SEL_SOC0PLLCLK; - break; - case DB5500_CLKOUT_SOC1PLLCLK: - sel = CLKOUT_SEL_SOC1PLLCLK; - break; - case DB5500_CLKOUT_DDRPLLCLK: - sel = CLKOUT_SEL_DDRPLLCLK; - break; - case DB5500_CLKOUT_TVCLK: - sel = CLKOUT_SEL_TVCLK; - break; - case DB5500_CLKOUT_IRDACLK: - sel = CLKOUT_SEL_IRDACLK; - break; - } - - switch (clkout) { - case DB5500_CLKOUT0: - sel_mask = PRCM_CLKOCR_CLKOUT0_SEL0_MASK | - PRCM_CLKOCR_CLKOUT0_SEL_MASK; - sel_bits = ((sel0 << PRCM_CLKOCR_CLKOUT0_SEL0_SHIFT) | - (sel << PRCM_CLKOCR_CLKOUT0_SEL_SHIFT)); - div_mask = PRCM_CLKODIV_CLKOUT0_DIV_MASK; - div_bits = div << PRCM_CLKODIV_CLKOUT0_DIV_SHIFT; - break; - case DB5500_CLKOUT1: - sel_mask = PRCM_CLKOCR_CLKOUT1_SEL0_MASK | - PRCM_CLKOCR_CLKOUT1_SEL_MASK; - sel_bits = ((sel0 << PRCM_CLKOCR_CLKOUT1_SEL0_SHIFT) | - (sel << PRCM_CLKOCR_CLKOUT1_SEL_SHIFT)); - div_mask = PRCM_CLKODIV_CLKOUT1_DIV_MASK; - div_bits = div << PRCM_CLKODIV_CLKOUT1_DIV_SHIFT; - break; - } - - spin_lock_irqsave(&clkout_lock, flags); - - if (configured[clkout]) { - r = -EINVAL; - goto unlock_and_return; - } - - sel_val = readl(_PRCMU_BASE + PRCM_CLKOCR); - writel((sel_bits | (sel_val & ~sel_mask)), - (_PRCMU_BASE + PRCM_CLKOCR)); - - div_val = readl(_PRCMU_BASE + PRCM_CLKODIV); - writel((div_bits | (div_val & ~div_mask)), - (_PRCMU_BASE + PRCM_CLKODIV)); - - configured[clkout] = true; - -unlock_and_return: - spin_unlock_irqrestore(&clkout_lock, flags); - - return r; -} - -static int request_sysclk(bool enable) -{ - int r; - - r = 0; - mutex_lock(&mb3_transfer.sysclk_lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3)) - cpu_relax(); - - if (enable) - mb3_transfer.req_st = SYSCLK_ON; - else - mb3_transfer.req_st = SYSCLK_OFF; - - writeb(mb3_transfer.req_st, (PRCM_REQ_MB3_REFCLK_MGT)); - - writeb(MB3H_REFCLK_REQUEST, (PRCM_REQ_MB3_HEADER)); - writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - /* - * The firmware only sends an ACK if we want to enable the - * SysClk, and it succeeds. - */ - if (!wait_for_completion_timeout(&mb3_transfer.sysclk_work, - msecs_to_jiffies(20000))) { - pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n", - __func__); - r = -EIO; - WARN(1, "Failed to set sysclk"); - goto unlock_and_return; - } - - if ((mb3_transfer.ack.header != MB3H_REFCLK_REQUEST) || - (mb3_transfer.ack.status != mb3_transfer.req_st)) { - r = -EIO; - } - -unlock_and_return: - mutex_unlock(&mb3_transfer.sysclk_lock); - - return r; -} - -static int request_timclk(bool enable) -{ - u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK); - - if (!enable) - val |= PRCM_TCR_STOP_TIMERS; - writel(val, (_PRCMU_BASE + PRCM_TCR)); - - return 0; -} - -static int request_clk(u8 clock, bool enable) -{ - int r = 0; - - BUG_ON(clock >= DB5500_NUM_CLK_CLIENTS); - - mutex_lock(&mb2_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2)) - cpu_relax(); - - /* fill in mailbox */ - writeb(clock, PRCM_REQ_MB2_CLK_CLIENT); - writeb(enable, PRCM_REQ_MB2_CLK_STATE); - - writeb(MB2H_CLK_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: request_clk() failed.\n"); - r = -EIO; - WARN(1, "Failed in request_clk"); - goto unlock_and_return; - } - if (mb2_transfer.ack.status != RC_SUCCESS || - mb2_transfer.ack.header != MB2H_CLK_REQUEST) - r = -EIO; - -unlock_and_return: - mutex_unlock(&mb2_transfer.lock); - return r; -} - -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_st[pll] = enable; - - /* fill in mailbox */ - writeb(pll, PRCM_REQ_MB2_PLL_CLIENT); - writeb(mb2_transfer.req.pll_st[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; -} - -/** - * 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) -{ - /* MSP1 & CD clocks are handled by FW */ - if (clock == PRCMU_MSP1CLK) - return request_clk(DB5500_MSP1CLK, enable); - else if (clock == PRCMU_CDCLK) - return request_clk(DB5500_CDCLK, 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_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 request_sysclk(enable); - else - return -EINVAL; -} - -/* This function should only be called while mb0_transfer.lock is held. */ -static void config_wakeups(void) -{ - static u32 last_dbb_events; - static u32 last_abb_events; - u32 dbb_events; - u32 abb_events; - - dbb_events = mb0_transfer.req.dbb_irqs | mb0_transfer.req.dbb_wakeups; - - abb_events = mb0_transfer.req.abb_events; - - if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events)) - return; - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) - cpu_relax(); - - writel(dbb_events, PRCM_REQ_MB0_WAKEUP_DBB); - writel(abb_events, PRCM_REQ_MB0_WAKEUP_ABB); - writeb(MB0H_WAKE_UP_CFG, PRCM_REQ_MB0_HEADER); - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - last_dbb_events = dbb_events; - last_abb_events = abb_events; -} - -int prcmu_config_esram0_deep_sleep(u8 state) -{ - unsigned long flags; - - if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) || - (state < ESRAM0_DEEP_SLEEP_STATE_OFF)) - return -EINVAL; - - spin_lock_irqsave(&mb0_transfer.lock, flags); - - if (state == ESRAM0_DEEP_SLEEP_STATE_RET) - writeb(RET_ST, PRCM_REQ_MB0_ESRAM0_STATE); - else - writeb(OFF_ST, PRCM_REQ_MB0_ESRAM0_STATE); - - spin_unlock_irqrestore(&mb0_transfer.lock, flags); - - return 0; -} - -int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll) -{ - int r = 0; - unsigned long flags; - - /* Deep Idle is not supported in U5500 */ - BUG_ON((state < PRCMU_AP_SLEEP) || (state >= PRCMU_AP_DEEP_IDLE)); - - spin_lock_irqsave(&mb0_transfer.lock, flags); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0)) - cpu_relax(); - - switch (state) { - case PRCMU_AP_IDLE: - writeb(DB5500_AP_IDLE, PRCM_REQ_MB0_AP_POWER_STATE); - /* TODO: Can be high latency */ - writeb(DDR_PWR_STATE_UNCHANGED, PRCM_REQ_MB0_DDR_STATE); - break; - case PRCMU_AP_SLEEP: - writeb(DB5500_AP_SLEEP, PRCM_REQ_MB0_AP_POWER_STATE); - break; - case PRCMU_AP_DEEP_SLEEP: - writeb(DB5500_AP_DEEP_SLEEP, PRCM_REQ_MB0_AP_POWER_STATE); - break; - default: - r = -EINVAL; - goto unlock_return; - } - writeb((keep_ap_pll ? 1 : 0), PRCM_REQ_MB0_AP_PLL_STATE); - writeb((keep_ulp_clk ? 1 : 0), PRCM_REQ_MB0_ULP_CLOCK_STATE); - - writeb(MB0H_PWR_STATE_TRANS, PRCM_REQ_MB0_HEADER); - writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - -unlock_return: - spin_unlock_irqrestore(&mb0_transfer.lock, flags); - - return r; -} - -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)) { - if (prcmu_wakeup_bit[i] == 0) - WARN(1, "WAKEUP NOT SUPPORTED"); - else - bits |= prcmu_wakeup_bit[i]; - } - } - - spin_lock_irqsave(&mb0_transfer.lock, flags); - - mb0_transfer.req.dbb_wakeups = bits; - config_wakeups(); - - spin_unlock_irqrestore(&mb0_transfer.lock, flags); -} - -void 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(PRCM_ACK_MB0_READ_POINTER) & 1) - *buf = (PRCM_ACK_MB0_WAKEUP_1_ABB); - else - *buf = (PRCM_ACK_MB0_WAKEUP_0_ABB); -} - -/* This function should be called with lock */ -static int mailbox4_request(u8 mb4_request, u8 ack_request) -{ - int ret = 0; - - writeb(mb4_request, PRCM_REQ_MB4_HEADER); - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - if (!wait_for_completion_timeout(&mb4_transfer.work, - msecs_to_jiffies(500))) { - pr_err("prcmu: MB4 request %d failed", mb4_request); - ret = -EIO; - WARN(1, "prcmu: failed mb4 request"); - goto failed; - } - - if (mb4_transfer.ack.header != ack_request || - mb4_transfer.ack.status != RC_SUCCESS) - ret = -EIO; -failed: - return ret; -} - -int prcmu_get_hotdog(void) -{ - return readw(PRCM_SHARE_INFO_HOTDOG); -} - -int prcmu_config_hotdog(u8 threshold) -{ - int r = 0; - - mutex_lock(&mb4_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) - cpu_relax(); - - writew(threshold, PRCM_REQ_MB4_HOTDOG_THRESHOLD); - r = mailbox4_request(MB4H_CFG_HOTDOG, MB4H_ACK_CFG_HOTDOG); - - mutex_unlock(&mb4_transfer.lock); - - return r; -} - -int prcmu_config_hotmon(u8 low, u8 high) -{ - int r = 0; - - mutex_lock(&mb4_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) - cpu_relax(); - - writew(low, PRCM_REQ_MB4_HOTMON_LOW); - writew(high, PRCM_REQ_MB4_HOTMON_HIGH); - - r = mailbox4_request(MB4H_CFG_HOTMON, MB4H_ACK_CFG_HOTMON); - - mutex_unlock(&mb4_transfer.lock); - - return r; -} - -static int config_hot_period(u16 val) -{ - int r = 0; - - mutex_lock(&mb4_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) - cpu_relax(); - - writew(val, PRCM_REQ_MB4_HOT_PERIOD); - r = mailbox4_request(MB4H_CFG_HOTPERIOD, MB4H_ACK_CFG_HOTPERIOD); - - mutex_unlock(&mb4_transfer.lock); - - return r; -} - -/* - * period in milli seconds - */ -int prcmu_start_temp_sense(u16 period) -{ - if (period == 0xFFFF) - return -EINVAL; - - return config_hot_period(period); -} - -int prcmu_stop_temp_sense(void) -{ - return config_hot_period(0xFFFF); -} - -/** - * db5500_prcmu_abb_read() - Read register value(s) from the ABB. - * @slave: The I2C slave address. - * @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; -} - -/** - * 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; - u8 db5500_opp; - - r = 0; - - switch (opp) { - case ARM_EXTCLK: - db5500_opp = DB5500_ARM_EXT_OPP; - break; - case ARM_50_OPP: - db5500_opp = DB5500_ARM_50_OPP; - break; - case ARM_100_OPP: - db5500_opp = DB5500_ARM_100_OPP; - break; - default: - pr_err("prcmu: %s() received wrong opp value: %d\n", - __func__, opp); - r = -EINVAL; - goto bailout; - } - - mutex_lock(&mb1_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(MB1H_ARM_OPP, PRCM_REQ_MB1_HEADER); - - writeb(db5500_opp, PRCM_REQ_MB1_ARM_OPP); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - if (!wait_for_completion_timeout(&mb1_transfer.work, - msecs_to_jiffies(500))) { - r = -EIO; - WARN(1, "prcmu: failed to set arm opp"); - goto unlock_and_return; - } - - if (mb1_transfer.ack.header != MB1H_ARM_OPP || - (mb1_transfer.ack.arm_opp != db5500_opp) || - (mb1_transfer.ack.arm_voltage_st != RC_SUCCESS)) - r = -EIO; - - prcmu_debug_arm_opp_log(opp); - -unlock_and_return: - mutex_unlock(&mb1_transfer.lock); -bailout: - return r; -} - -static void __init prcmu_ape_clocks_init(void) -{ - u8 opp = prcmu_get_ape_opp(); - unsigned long flags; - int i; - - WARN(opp != APE_100_OPP, "%s: Initial APE OPP (%u) not 100%%?\n", - __func__, opp); - - for (i = 0; i < PRCMU_NUM_REG_CLOCKS; i++) { - struct clk_mgt *clkmgt = &clk_mgt[i]; - u32 clkval; - u32 div; - - if (!clkmgt->scalable && !clkmgt->force50) - continue; - - spin_lock_irqsave(&clk_mgt_lock, flags); - - clkval = readl(_PRCMU_BASE + clkmgt->offset); - div = clkval & PRCM_CLK_MGT_CLKPLLDIV_MASK; - div >>= PRCM_CLK_MGT_CLKPLLDIV_SHIFT; - - if (clkmgt->force50) { - div *= 2; - - clkval &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK; - clkval |= div << PRCM_CLK_MGT_CLKPLLDIV_SHIFT; - writel(clkval, _PRCMU_BASE + clkmgt->offset); - - spin_unlock_irqrestore(&clk_mgt_lock, flags); - continue; - } - - spin_unlock_irqrestore(&clk_mgt_lock, flags); - - clkmgt->div = div; - if (!div) - pr_err("%s: scalable clock at offset %#x has zero divisor\n", - __func__, clkmgt->offset); - } -} - -static void prcmu_ape_clocks_scale(u8 opp) -{ - unsigned long irqflags; - unsigned int i; - u32 clkval; - - /* - * Note: calling printk() under the following lock can cause lock - * recursion via clk_enable() for the console UART! - */ - spin_lock_irqsave(&clk_mgt_lock, irqflags); - - /* take a lock on HW (HWSEM)*/ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) - cpu_relax(); - - for (i = 0; i < PRCMU_NUM_REG_CLOCKS; i++) { - u32 divval; - - if (!clk_mgt[i].scalable) - continue; - - clkval = readl(_PRCMU_BASE + clk_mgt[i].offset); - divval = clk_mgt[i].div; - - pr_debug("PRCMU: reg %#x prev clk = 0x%x stored div = 0x%x\n", - clk_mgt[i].offset, clkval, divval); - - if (opp == DB5500_APE_50_OPP) - divval *= 2; - - clkval &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK; - clkval |= divval << PRCM_CLK_MGT_CLKPLLDIV_SHIFT; - - pr_debug("PRCMU: wr 0x%x in reg 0x%x\n", - clkval, clk_mgt[i].offset); - - writel(clkval, _PRCMU_BASE + clk_mgt[i].offset); - } - - /* release lock */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); - - spin_unlock_irqrestore(&clk_mgt_lock, irqflags); -} - -int prcmu_set_ape_opp(u8 opp) -{ - int ret = 0; - u8 db5500_opp; - - if (opp == prcmu_get_ape_opp()) - return ret; - - if (cpu_is_u5500v1()) - return -EINVAL; - - switch (opp) { - case APE_100_OPP: - db5500_opp = DB5500_APE_100_OPP; - break; - case APE_50_OPP: - db5500_opp = DB5500_APE_50_OPP; - break; - default: - pr_err("prcmu: %s() received wrong opp value: %d\n", - __func__, opp); - ret = -EINVAL; - goto bailout; - } - - mutex_lock(&mb1_transfer.lock); - - prcmu_ape_clocks_scale(db5500_opp); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) - cpu_relax(); - - writeb(MB1H_APE_OPP, PRCM_REQ_MB1_HEADER); - writeb(db5500_opp, PRCM_REQ_MB1_APE_OPP); - writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - - if (!wait_for_completion_timeout(&mb1_transfer.work, - msecs_to_jiffies(500))) { - ret = -EIO; - WARN(1, "prcmu: failed to set ape opp to %u", opp); - goto unlock_and_return; - } - - if (mb1_transfer.ack.header != MB1H_APE_OPP || - (mb1_transfer.ack.ape_opp != db5500_opp) || - (mb1_transfer.ack.arm_voltage_st != RC_SUCCESS)) - ret = -EIO; - -unlock_and_return: - mutex_unlock(&mb1_transfer.lock); -bailout: - return ret; -} - -int prcmu_get_ape_opp(void) -{ - u8 opp = readb(PRCM_ACK_MB1_CURRENT_APE_OPP); - - switch (opp) { - case DB5500_APE_100_OPP: - return APE_100_OPP; - case DB5500_APE_50_OPP: - return APE_50_OPP; - default: - pr_err("prcmu: %s() read unknown opp value: %d\n", - __func__, opp); - return APE_100_OPP; - } -} - -int prcmu_get_ddr_opp(void) -{ - return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW); -} - -int prcmu_set_ddr_opp(u8 opp) -{ - if (cpu_is_u5500v1()) - return -EINVAL; - - if (opp != DDR_100_OPP && opp != DDR_50_OPP) - return -EINVAL; - - writeb(opp, _PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW); - - return 0; -} - -/** - * prcmu_get_arm_opp - get the current ARM OPP - * - * Returns: the current ARM OPP - */ -int prcmu_get_arm_opp(void) -{ - u8 opp = readb(PRCM_ACK_MB1_CURRENT_ARM_OPP); - - switch (opp) { - case DB5500_ARM_EXT_OPP: - return ARM_EXTCLK; - case DB5500_ARM_50_OPP: - return ARM_50_OPP; - case DB5500_ARM_100_OPP: - return ARM_100_OPP; - default: - pr_err("prcmu: %s() read unknown opp value: %d\n", - __func__, opp); - return ARM_100_OPP; - } -} - -unsigned int prcmu_get_ddr_freq(void) -{ - return readl(PRCM_DDR_FREQUENCY); -} - -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 prcmu_enable_dsipll(void) -{ - int i; - int ret = 0; - - /* 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); - } - - if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) & - PRCMU_PLLDSI_LOCKP_LOCKED) - != PRCMU_PLLDSI_LOCKP_LOCKED) - ret = -EIO; - /* Release DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, _PRCMU_BASE + PRCM_APE_RESETN_SET); - return ret; -} - -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) -{ - 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; -} - -/** - * prcmu_system_reset - System reset - * - * Saves the reset reason code and then sets the APE_SOFTRST register which - * fires an interrupt to fw - */ -void prcmu_system_reset(u16 reset_code) -{ - writew(reset_code, 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(PRCM_SW_RST_REASON); -} - -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_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, u8 epod_state) -{ - int r = 0; - bool ram_retention = false; - - /* check argument */ - BUG_ON(epod < DB5500_EPOD_ID_BASE); - BUG_ON(epod_state > EPOD_STATE_ON); - BUG_ON((epod - DB5500_EPOD_ID_BASE) >= DB5500_NUM_EPOD_ID); - - if (epod == DB5500_EPOD_ID_ESRAM12) - ram_retention = true; - - /* 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(); - - /* Retention is allowed only for ESRAM12 */ - if (epod == DB5500_EPOD_ID_ESRAM12) { - switch (epod_state) { - case EPOD_STATE_ON: - mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] = - EPOD_OOR_ON; - break; - case EPOD_STATE_OFF: - mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] = - EPOD_OOR_OFF; - break; - case EPOD_STATE_RAMRET: - mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] = - EPOD_OOR_RET; - break; - default: - r = -EINVAL; - goto unlock_and_return; - break; - } - } else { - if (epod_state == EPOD_STATE_ON) - mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] = - EPOD_ON; - else if (epod_state == EPOD_STATE_OFF) - mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE] = - EPOD_OFF; - else { - r = -EINVAL; - goto unlock_and_return; - } - } - /* fill in mailbox */ - writeb((epod - DB5500_EPOD_ID_BASE), PRCM_REQ_MB2_EPOD_CLIENT); - writeb(mb2_transfer.req.epod_st[epod - DB5500_EPOD_ID_BASE], - PRCM_REQ_MB2_EPOD_STATE); - - writeb(MB2H_EPOD_REQUEST, PRCM_REQ_MB2_HEADER); - - 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; - u32 ev; - unsigned int n; - - u8 header; - - header = readb(PRCM_ACK_MB0_HEADER); - switch (header) { - case MB0H_WAKE_UP: - if (readb(PRCM_ACK_MB0_READ_POINTER) & 1) - ev = readl(PRCM_ACK_MB0_WAKEUP_1_DBB); - else - ev = readl(PRCM_ACK_MB0_WAKEUP_0_DBB); - - ev &= mb0_transfer.req.dbb_irqs; - - for (n = 0; n < NUM_DB5500_PRCMU_WAKEUPS; n++) { - if (ev & prcmu_irq_bit[n]) - generic_handle_irq(IRQ_DB5500_PRCMU_BASE + n); - } - r = true; - break; - default: - 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) -{ - u8 header; - bool do_complete = true; - - header = mb1_transfer.ack.header = readb(PRCM_ACK_MB1_HEADER); - - switch (header) { - case MB1H_ARM_OPP: - mb1_transfer.ack.arm_opp = readb(PRCM_ACK_MB1_CURRENT_ARM_OPP); - mb1_transfer.ack.arm_voltage_st = - readb(PRCM_ACK_MB1_ARM_VOLT_STATUS); - break; - case MB1H_APE_OPP: - mb1_transfer.ack.ape_opp = readb(PRCM_ACK_MB1_CURRENT_APE_OPP); - mb1_transfer.ack.ape_voltage_st = - readb(PRCM_ACK_MB1_APE_VOLT_STATUS); - break; - case MB1H_ARM_APE_OPP: - mb1_transfer.ack.ape_opp = readb(PRCM_ACK_MB1_CURRENT_APE_OPP); - mb1_transfer.ack.ape_voltage_st = - readb(PRCM_ACK_MB1_APE_VOLT_STATUS); - break; - default: - print_unknown_header_warning(1, header); - do_complete = false; - break; - } - - writel(MBOX_BIT(1), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - - if (do_complete) - complete(&mb1_transfer.work); - - 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) -{ - u8 header; - - header = readb(PRCM_ACK_MB3_HEADER); - mb3_transfer.ack.header = header; - switch (header) { - case MB3H_REFCLK_REQUEST: - mb3_transfer.ack.status = readb(PRCM_ACK_MB3_REFCLK_REQ); - writel(MBOX_BIT(3), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - complete(&mb3_transfer.sysclk_work); - break; - default: - writel(MBOX_BIT(3), _PRCMU_BASE + PRCM_ARM_IT1_CLEAR); - pr_err("prcmu: wrong MB3 header\n"); - break; - } - - return false; -} - -static bool read_mailbox_4(void) -{ - u8 header; - bool do_complete = true; - - header = readb(PRCM_ACK_MB4_HEADER); - mb4_transfer.ack.header = header; - switch (header) { - case MB4H_ACK_CFG_HOTDOG: - case MB4H_ACK_CFG_HOTMON: - case MB4H_ACK_CFG_HOTPERIOD: - mb4_transfer.ack.status = readb(PRCM_ACK_MB4_REQUESTS); - break; - default: - print_unknown_header_warning(4, header); - do_complete = false; - break; - } - - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLEAR)); - - if (do_complete) - complete(&mb4_transfer.work); - - return false; -} - -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; -} - -static void prcmu_mask_work(struct work_struct *work) -{ - unsigned long flags; - - spin_lock_irqsave(&mb0_transfer.lock, flags); - - config_wakeups(); - - spin_unlock_irqrestore(&mb0_transfer.lock, flags); -} - -static void prcmu_irq_mask(struct irq_data *d) -{ - unsigned long flags; - - spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); - - mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->irq - IRQ_DB5500_PRCMU_BASE]; - - spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); - schedule_work(&mb0_transfer.mask_work); -} - -static void prcmu_irq_unmask(struct irq_data *d) -{ - unsigned long flags; - - spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags); - - mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->irq - IRQ_DB5500_PRCMU_BASE]; - - spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags); - schedule_work(&mb0_transfer.mask_work); -} - -static void noop(struct irq_data *d) -{ -} - -static struct irq_chip prcmu_irq_chip = { - .name = "prcmu", - .irq_disable = prcmu_irq_mask, - .irq_ack = noop, - .irq_mask = prcmu_irq_mask, - .irq_unmask = prcmu_irq_unmask, -}; -void __init prcmu_early_init(void) -{ - unsigned int i; - void *tcpm_base = ioremap_nocache(U5500_PRCMU_TCPM_BASE, SZ_4K); - - if (tcpm_base != NULL) { - int version_high , version_low; - - version_high = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET); - version_low = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET + 4); - prcmu_version.board = (version_high >> 24) & 0xFF; - prcmu_version.fw_version = version_high & 0xFF; - prcmu_version.api_version = (version_low) & 0xFF; - - if (prcmu_version.board == 0x20) - pr_info("Board Version : V2\n"); - else - pr_info("Board Version : V1\n"); - - pr_info("PRCMU Firmware Version : 0x%x\n", - prcmu_version.fw_version); - pr_info("PRCMU API Version : 0x%x\n", - prcmu_version.api_version); - iounmap(tcpm_base); - } - - tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE); - spin_lock_init(&mb0_transfer.lock); - spin_lock_init(&mb0_transfer.dbb_irqs_lock); - mutex_init(&mb1_transfer.lock); - init_completion(&mb1_transfer.work); - mutex_init(&mb2_transfer.lock); - init_completion(&mb2_transfer.work); - mutex_init(&mb3_transfer.sysclk_lock); - init_completion(&mb3_transfer.sysclk_work); - mutex_init(&mb4_transfer.lock); - init_completion(&mb4_transfer.work); - mutex_init(&mb5_transfer.lock); - init_completion(&mb5_transfer.work); - - INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work); - - /* Initalize irqs. */ - for (i = 0; i < NUM_DB5500_PRCMU_WAKEUPS; i++) { - unsigned int irq; - - irq = IRQ_DB5500_PRCMU_BASE + i; - set_irq_flags(irq, IRQF_VALID); - irq_set_chip_and_handler(irq, &prcmu_irq_chip, - handle_simple_irq); - } - - prcmu_ape_clocks_init(); -} - -/** - * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic - * - */ -int __init 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, IRQF_NO_SUSPEND, "prcmu", NULL); - if (r < 0) { - pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n"); - return -EBUSY; - } - - if (prcmu_debug_init()) - pr_err("prcmu: Failed to initialize debugfs\n"); - - return 0; -} - -arch_initcall(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 b19b334d234..00000000000 --- a/arch/arm/mach-ux500/prcmu-db8500.c +++ /dev/null @@ -1,2479 +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> - -/* 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_SIZE 14 - -#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 -#define MB4H_A9WDOG_CONF 0x16 -#define MB4H_A9WDOG_EN 0x17 -#define MB4H_A9WDOG_DIS 0x18 -#define MB4H_A9WDOG_LOAD 0x19 -#define MB4H_A9WDOG_KICK 0x20 - -/* Mailbox 4 Requests */ -#define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0) -#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) -#define PRCM_REQ_MB4_A9WDOG_0 (PRCM_REQ_MB4 + 0x0) -#define PRCM_REQ_MB4_A9WDOG_1 (PRCM_REQ_MB4 + 0x1) -#define PRCM_REQ_MB4_A9WDOG_2 (PRCM_REQ_MB4 + 0x2) -#define PRCM_REQ_MB4_A9WDOG_3 (PRCM_REQ_MB4 + 0x3) -#define A9WDOG_AUTO_OFF_EN BIT(7) -#define A9WDOG_AUTO_OFF_DIS 0 -#define A9WDOG_ID_MASK 0xf - -/* Mailbox 5 Requests */ -#define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0) -#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. - * @ape_opp: The current APE OPP. - * @ack: Reply ("acknowledge") data. - */ -static struct { - struct mutex lock; - struct completion work; - u8 ape_opp; - 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; - int branch; - bool clk38div; -}; - -enum { - PLL_RAW, - PLL_FIX, - PLL_DIV -}; - -static DEFINE_SPINLOCK(clk_mgt_lock); - -#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \ - { (PRCM_##_name##_MGT), 0 , _branch, _clk38div} -struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = { - CLK_MGT_ENTRY(SGACLK, PLL_DIV, false), - CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true), - CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true), - CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true), - CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true), - CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true), - CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true), - CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true), - CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true), - CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true), - CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true), - CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true), - CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true), - CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true), - CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true), - CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true), - CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true), - CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false), - CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true), - CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true), - CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true), - CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true), - CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false), - CLK_MGT_ENTRY(DMACLK, PLL_DIV, true), - CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true), - CLK_MGT_ENTRY(TVCLK, PLL_FIX, false), - CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true), - CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true), - CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false), -}; - -/* - * 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; - int ret = 0; - 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); - } - - if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) & - PRCMU_PLLDSI_LOCKP_LOCKED) - != PRCMU_PLLDSI_LOCKP_LOCKED) - ret = -EIO; - - /* Set DSIPLL_RESETN */ - writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET)); - return ret; -} - -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; -} - -/* This is just for showing AVS settings in debugfs, never use otherwise */ -#ifdef CONFIG_UX500_PRCMU_DEBUG -void prcmu_dump_avs(u8 *avs, int s) -{ - BUG_ON(s != PRCM_AVS_SIZE); - - memcpy_fromio(avs, tcdm_base + PRCM_AVS_BASE, - PRCM_AVS_SIZE); -} -#endif - -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); - - prcmu_debug_arm_opp_log(opp); - - 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; -} - -/* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */ -static void request_even_slower_clocks(bool enable) -{ - const u8 clock_reg[] = { - PRCM_ACLK_MGT, - PRCM_DMACLK_MGT - }; - unsigned long flags; - unsigned int i; - - spin_lock_irqsave(&clk_mgt_lock, flags); - - /* Grab the HW semaphore. */ - while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0) - cpu_relax(); - - for (i = 0; i < ARRAY_SIZE(clock_reg); i++) { - u32 val; - u32 div; - - val = readl(_PRCMU_BASE + clock_reg[i]); - div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK); - if (enable) { - if ((div <= 1) || (div > 15)) { - pr_err("prcmu: Bad clock divider %d in %s\n", - div, __func__); - goto unlock_and_return; - } - div <<= 1; - } else { - if (div <= 2) - goto unlock_and_return; - div >>= 1; - } - val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) | - (div & PRCM_CLK_MGT_CLKPLLDIV_MASK)); - writel(val, (_PRCMU_BASE + clock_reg[i])); - } - -unlock_and_return: - /* Release the HW semaphore. */ - writel(0, (_PRCMU_BASE + PRCM_SEM)); - - spin_unlock_irqrestore(&clk_mgt_lock, flags); -} - -/** - * 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; - - if (opp == mb1_transfer.ape_opp) - return 0; - - mutex_lock(&mb1_transfer.lock); - - if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP) - request_even_slower_clocks(false); - - if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP)) - goto skip_message; - - 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 == APE_50_PARTLY_25_OPP) ? APE_50_OPP : 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; - -skip_message: - if ((!r && (opp == APE_50_PARTLY_25_OPP)) || - (r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP))) - request_even_slower_clocks(true); - if (!r) - mb1_transfer.ape_opp = opp; - - 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_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_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_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; -} - -static unsigned long pll_rate(unsigned int reg_offset, unsigned long src_rate, - int branch) -{ - u64 rate; - u32 val; - u32 d; - u32 div = 1; - - val = readl(_PRCMU_BASE + reg_offset); - - rate = src_rate; - rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT); - - d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT); - if (d > 1) - div *= d; - - d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT); - if (d > 1) - div *= d; - - if (val & PRCM_PLL_FREQ_SELDIV2) - div *= 2; - - if ((branch == PLL_FIX) || ((branch == PLL_DIV) && - (val & PRCM_PLL_FREQ_DIV2EN) && - ((reg_offset == PRCM_PLLSOC0_FREQ) || - (reg_offset == PRCM_PLLDDR_FREQ)))) - div *= 2; - - (void)do_div(rate, div); - - return (unsigned long)rate; -} - -#define ROOT_CLOCK_RATE 38400000 - -static unsigned long clock_rate(u8 clock) -{ - u32 val; - u32 pllsw; - unsigned long rate = ROOT_CLOCK_RATE; - - val = readl(_PRCMU_BASE + clk_mgt[clock].offset); - - if (val & PRCM_CLK_MGT_CLK38) { - if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV)) - rate /= 2; - return rate; - } - - val |= clk_mgt[clock].pllsw; - pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK); - - if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0) - rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch); - else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1) - rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch); - else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR) - rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch); - else - return 0; - - if ((clock == PRCMU_SGACLK) && - (val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) { - u64 r = (rate * 10); - - (void)do_div(r, 25); - return (unsigned long)r; - } - val &= PRCM_CLK_MGT_CLKPLLDIV_MASK; - if (val) - return rate / val; - else - return 0; -} - -unsigned long prcmu_clock_rate(u8 clock) -{ - if (clock < PRCMU_NUM_REG_CLOCKS) - return clock_rate(clock); - else if (clock == PRCMU_TIMCLK) - return ROOT_CLOCK_RATE / 16; - else if (clock == PRCMU_SYSCLK) - return ROOT_CLOCK_RATE; - else if (clock == PRCMU_PLLSOC0) - return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW); - else if (clock == PRCMU_PLLSOC1) - return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW); - else if (clock == PRCMU_PLLDDR) - return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW); - else - return 0; -} - -static unsigned long clock_source_rate(u32 clk_mgt_val, int branch) -{ - if (clk_mgt_val & PRCM_CLK_MGT_CLK38) - return ROOT_CLOCK_RATE; - clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK; - if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0) - return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch); - else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1) - return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch); - else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR) - return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch); - else - return 0; -} - -static u32 clock_divider(unsigned long src_rate, unsigned long rate) -{ - u32 div; - - div = (src_rate / rate); - if (div == 0) - return 1; - if (rate < (src_rate / div)) - div++; - if (div > 31) - div = 31; - return div; -} - -static long round_clock_rate(u8 clock, unsigned long rate) -{ - u32 val; - u32 div; - unsigned long src_rate; - long rounded_rate; - - val = readl(_PRCMU_BASE + clk_mgt[clock].offset); - src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), - clk_mgt[clock].branch); - div = clock_divider(src_rate, rate); - if (val & PRCM_CLK_MGT_CLK38) { - if (clk_mgt[clock].clk38div) { - if (div > 2) - div = 2; - } else { - div = 1; - } - } else if ((clock == PRCMU_SGACLK) && (div == 3)) { - u64 r = (src_rate * 10); - - (void)do_div(r, 25); - if (r <= rate) - return (unsigned long)r; - } - rounded_rate = (src_rate / div); - - return rounded_rate; -} - -long prcmu_round_clock_rate(u8 clock, unsigned long rate) -{ - if (clock < PRCMU_NUM_REG_CLOCKS) - return round_clock_rate(clock, rate); - else - return (long)prcmu_clock_rate(clock); -} - -static void set_clock_rate(u8 clock, unsigned long rate) -{ - u32 val; - u32 div; - unsigned long src_rate; - 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); - src_rate = clock_source_rate((val | clk_mgt[clock].pllsw), - clk_mgt[clock].branch); - div = clock_divider(src_rate, rate); - if (val & PRCM_CLK_MGT_CLK38) { - if (clk_mgt[clock].clk38div) { - if (div > 1) - val |= PRCM_CLK_MGT_CLK38DIV; - else - val &= ~PRCM_CLK_MGT_CLK38DIV; - } - } else if (clock == PRCMU_SGACLK) { - val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK | - PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN); - if (div == 3) { - u64 r = (src_rate * 10); - - (void)do_div(r, 25); - if (r <= rate) { - val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN; - div = 0; - } - } - val |= div; - } else { - val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK; - val |= div; - } - 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); -} - -int prcmu_set_clock_rate(u8 clock, unsigned long rate) -{ - if (clock < PRCMU_NUM_REG_CLOCKS) - set_clock_rate(clock, rate); - return 0; -} - -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); -} - -static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3) -{ - - mutex_lock(&mb4_transfer.lock); - - while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4)) - cpu_relax(); - - writeb(d0, (tcdm_base + PRCM_REQ_MB4_A9WDOG_0)); - writeb(d1, (tcdm_base + PRCM_REQ_MB4_A9WDOG_1)); - writeb(d2, (tcdm_base + PRCM_REQ_MB4_A9WDOG_2)); - writeb(d3, (tcdm_base + PRCM_REQ_MB4_A9WDOG_3)); - - writeb(cmd, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4)); - - writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET)); - wait_for_completion(&mb4_transfer.work); - - mutex_unlock(&mb4_transfer.lock); - - return 0; - -} - -int prcmu_config_a9wdog(u8 num, bool sleep_auto_off) -{ - BUG_ON(num == 0 || num > 0xf); - return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0, - sleep_auto_off ? A9WDOG_AUTO_OFF_EN : - A9WDOG_AUTO_OFF_DIS); -} - -int prcmu_enable_a9wdog(u8 id) -{ - return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0); -} - -int prcmu_disable_a9wdog(u8 id) -{ - return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0); -} - -int prcmu_kick_a9wdog(u8 id) -{ - return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0); -} - -/* - * timeout is 28 bit, in ms. - */ -int prcmu_load_a9wdog(u8 id, u32 timeout) -{ - return prcmu_a9wdog(MB4H_A9WDOG_LOAD, - (id & A9WDOG_ID_MASK) | - /* - * Put the lowest 28 bits of timeout at - * offset 4. Four first bits are used for id. - */ - (u8)((timeout << 4) & 0xf0), - (u8)((timeout >> 4) & 0xff), - (u8)((timeout >> 12) & 0xff), - (u8)((timeout >> 20) & 0xff)); -} - -/** - * prcmu_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; - u32 status; - - 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); - -retry: - 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(5000))) { - panic("prcmu: %s timed out (5 s) waiting for a reply.\n", - __func__); - goto unlock_and_return; - } - - /* - * The modem can generate an AC_WAKE_ACK, and then still go to sleep. - * As a workaround, we wait, and then check that the modem is indeed - * awake (in terms of the value of the PRCM_MOD_AWAKE_STATUS - * register, which may not be the whole truth). - */ - udelay(400); - status = (readl(_PRCMU_BASE + PRCM_MOD_AWAKE_STATUS) & BITS(0, 2)); - if (status != (PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE | - PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE)) { - pr_err("prcmu: %s received ack, but modem not awake (0x%X).\n", - __func__, status); - udelay(1200); - writel(val, (_PRCMU_BASE + PRCM_HOSTACCESS_REQ)); - if (wait_for_completion_timeout(&mb0_transfer.ac_wake_work, - msecs_to_jiffies(5000))) - goto retry; - panic("prcmu: %s timed out (5 s) waiting for AC_SLEEP_ACK.\n", - __func__); - } - -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(5000))) { - panic("prcmu: %s timed out (5 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: - case MB4H_A9WDOG_CONF: - case MB4H_A9WDOG_EN: - case MB4H_A9WDOG_DIS: - case MB4H_A9WDOG_LOAD: - case MB4H_A9WDOG_KICK: - break; - default: - print_unknown_header_warning(4, header); - 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); - mb1_transfer.ape_opp = APE_NO_CHANGE; - 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_flags(irq, IRQF_VALID); - irq_set_chip_and_handler(irq, &prcmu_irq_chip, - 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; - } - - 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-debug.h b/arch/arm/mach-ux500/prcmu-debug.h deleted file mode 100644 index aeffec69972..00000000000 --- a/arch/arm/mach-ux500/prcmu-debug.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - * - * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson - * Etienne Carriere <etienne.carriere@stericsson.com> for ST-Ericsson - * - */ - -#ifndef PRCMU_DEBUG_H -#define PRCMU_DEBUG_H - -#ifdef CONFIG_UX500_PRCMU_DEBUG -void prcmu_debug_arm_opp_log(u8 opp); -void prcmu_debug_ape_opp_log(u8 opp); -void prcmu_debug_ddr_opp_log(u8 opp); -int prcmu_debug_init(void); -#else -static inline void prcmu_debug_arm_opp_log(u8 opp) {} -static inline void prcmu_debug_ape_opp_log(u8 opp) {} -static inline void prcmu_debug_ddr_opp_log(u8 opp) {} -static inline int prcmu_debug_init(void) {return 0;} -#endif -#endif 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 e8aa2901478..00000000000 --- a/arch/arm/mach-ux500/prcmu-regs-db5500.h +++ /dev/null @@ -1,126 +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_ACLK_MGT 0x004 -#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_IRDACLK_MGT 0x040 -#define DB5500_PRCM_PWMCLK_MGT 0x044 -#define DB5500_PRCM_SPARE1CLK_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_CLKPLLDIV_SHIFT 0 -#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) -#define PRCM_CLK_MGT_CLKEN BIT(8) - -#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 - -/* System reset register */ -#define PRCM_APE_SOFTRST 0x228 - -/* 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 - -/* CLKOUTx SEL0 settings */ -#define CLKOUT_SEL0_REF_CLK 0x01 /* 0b 0001 */ -#define CLKOUT_SEL0_RTC_CLK0 0x02 /* 0b 0010 */ -#define CLKOUT_SEL0_ULP_CLK 0x04 /* 0b 0100 */ -#define CLKOUT_SEL0_SEL_CLK 0x08 /* 0b 1000 */ - -/* CLKOUTx SEL settings */ -#define CLKOUT_SEL_STATIC0 0x0001 /* 0b 00 0000 0001 */ -#define CLKOUT_SEL_REFCLK 0x0002 /* 0b 00 0000 0010 */ -#define CLKOUT_SEL_ULPCLK 0x0004 /* 0b 00 0000 0100 */ -#define CLKOUT_SEL_ARMCLK 0x0008 /* 0b 00 0000 1000 */ -#define CLKOUT_SEL_SYSACC0CLK 0x0010 /* 0b 00 0001 0000 */ -#define CLKOUT_SEL_SOC0PLLCLK 0x0020 /* 0b 00 0010 0000 */ -#define CLKOUT_SEL_SOC1PLLCLK 0x0040 /* 0b 00 0100 0000 */ -#define CLKOUT_SEL_DDRPLLCLK 0x0080 /* 0b 00 1000 0000 */ -#define CLKOUT_SEL_TVCLK 0x0100 /* 0b 01 0000 0000 */ -#define CLKOUT_SEL_IRDACLK 0x0200 /* 0b 10 0000 0000 */ - -/* CLKOUTx dividers */ -#define CLKOUT_DIV_2 0x00 /* 0b 000 */ -#define CLKOUT_DIV_4 0x01 /* 0b 001 */ -#define CLKOUT_DIV_8 0x02 /* 0b 010 */ -#define CLKOUT_DIV_16 0x03 /* 0b 011 */ -#define CLKOUT_DIV_32 0x04 /* 0b 100 */ -#define CLKOUT_DIV_64 0x05 /* 0b 101 */ -/* Values 0x06 and 0x07 will also set the CLKOUTx divider to 64. */ - -/* PRCM_CLKOCR CLKOUTx Control registers */ -#define PRCM_CLKOCR 0x1CC -#define PRCM_CLKOCR_CLKOUT0_SEL0_SHIFT 0 -#define PRCM_CLKOCR_CLKOUT0_SEL0_MASK BITS(0, 3) -#define PRCM_CLKOCR_CLKOUT0_SEL_SHIFT 4 -#define PRCM_CLKOCR_CLKOUT0_SEL_MASK BITS(4, 13) -#define PRCM_CLKOCR_CLKOUT1_SEL0_SHIFT 16 -#define PRCM_CLKOCR_CLKOUT1_SEL0_MASK BITS(16, 19) -#define PRCM_CLKOCR_CLKOUT1_SEL_SHIFT 20 -#define PRCM_CLKOCR_CLKOUT1_SEL_MASK BITS(20, 29) - -/* PRCM_CLKODIV CLKOUTx Dividers */ -#define PRCM_CLKODIV 0x188 -#define PRCM_CLKODIV_CLKOUT0_DIV_SHIFT 0 -#define PRCM_CLKODIV_CLKOUT0_DIV_MASK BITS(0, 2) -#define PRCM_CLKODIV_CLKOUT1_DIV_SHIFT 16 -#define PRCM_CLKODIV_CLKOUT1_DIV_MASK BITS(16, 18) - -#define PRCM_MMIP_LS_CLAMP_SET 0x420 -#define PRCM_MMIP_LS_CLAMP_CLR 0x424 -#define PRCM_DDR_SUBSYS_APE_MINBW 0x438 - -/* 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 4e84232a4cd..00000000000 --- a/arch/arm/mach-ux500/prcmu-regs-db8500.h +++ /dev/null @@ -1,194 +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_MOD_AWAKE_STATUS 0x4A0 -#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE BIT(0) -#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE BIT(1) -#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_VMODEM_OFF_ISO BIT(2) - -#define PRCM_ITSTATUS0 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_PLLSOC0_FREQ 0x080 -#define PRCM_PLLSOC1_FREQ 0x084 -#define PRCM_PLLDDR_FREQ 0x08C -#define PRCM_PLLDSI_FREQ 0x500 - -#define PRCM_PLL_FREQ_D_SHIFT 0 -#define PRCM_PLL_FREQ_D_MASK BITS(0, 7) -#define PRCM_PLL_FREQ_N_SHIFT 8 -#define PRCM_PLL_FREQ_N_MASK BITS(8, 13) -#define PRCM_PLL_FREQ_R_SHIFT 16 -#define PRCM_PLL_FREQ_R_MASK BITS(16, 18) -#define PRCM_PLL_FREQ_SELDIV2 BIT(24) -#define PRCM_PLL_FREQ_DIV2EN BIT(25) - -#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_ACLK_MGT 0x004 -#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_SOC0 BIT(5) -#define PRCM_CLK_MGT_CLKPLLSW_SOC1 BIT(6) -#define PRCM_CLK_MGT_CLKPLLSW_DDR BIT(7) -#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7) -#define PRCM_CLK_MGT_CLKEN BIT(8) -#define PRCM_CLK_MGT_CLK38 BIT(9) -#define PRCM_CLK_MGT_CLK38DIV BIT(11) -#define PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN BIT(12) - -/* 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/arch/arm/mach-ux500/regulator-u8500.c b/arch/arm/mach-ux500/regulator-u8500.c index 2244f084822..49900251b06 100644 --- a/arch/arm/mach-ux500/regulator-u8500.c +++ b/arch/arm/mach-ux500/regulator-u8500.c @@ -11,8 +11,7 @@ #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> - -#include <mach/prcmu.h> +#include <linux/mfd/dbx500-prcmu.h> #include "regulator-ux500.h" #include "regulator-u8500.h" diff --git a/arch/arm/mach-ux500/regulator-ux500.c b/arch/arm/mach-ux500/regulator-ux500.c index f0abe605941..4f84b9ac48d 100644 --- a/arch/arm/mach-ux500/regulator-ux500.c +++ b/arch/arm/mach-ux500/regulator-ux500.c @@ -18,14 +18,13 @@ #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <linux/mfd/dbx500-prcmu.h> #include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/slab.h> #include "regulator-ux500.h" -#include <mach/prcmu.h> - #ifdef CONFIG_REGULATOR_DEBUG static struct ux500_regulator_debug { |