diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2011-09-13 13:32:39 +0200 |
---|---|---|
committer | Jonas ABERG <jonas.aberg@stericsson.com> | 2011-09-29 08:34:43 +0200 |
commit | 0cddfb2b35dbb6f054bfdbc486a4f84dfe8efd1a (patch) | |
tree | 92f5496786ff9c69b70863cab991792d81e0bfee | |
parent | 2c1d6edf73274e56e3194dac75c59e82e88688bd (diff) |
ARM: ux500: Remove powersave
Since we don't know really the status of powersave related
feature on this development track, let's remove everything,
except:
- prcmu driver: New location, which is the same as linux-next
- cpufreq: new location, same as linux-next
- regulator: keep as is for the moment, needed for the system to work.
- clocks: same as for regulator.
- pm-runtime: keep it as is.
Later patches will re-add powersave, based upon what exists on SI
u8500-android-2.3_v3.15
MTU from plat-nomadik is now used instead of own copy in mach.
Change-Id: I8ceaa65e5e0905fcd85bf8e793b4a5ab2d2df64c
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32048
47 files changed, 53 insertions, 9565 deletions
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 0c935bc0dfd..c839b667ffa 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -24,9 +24,7 @@ CONFIG_ARCH_U8500=y CONFIG_UX500_SOC_DB8500=y CONFIG_MACH_HREFV60=y CONFIG_MACH_SNOWBALL=y -CONFIG_UX500_PRCMU_TIMER=y CONFIG_U8500_PRCMU=y -CONFIG_UX500_PRCMU_DEBUG=y CONFIG_U8500_REGULATOR_DEBUG=y CONFIG_DB8500_MLOADER=y CONFIG_DISPLAY_GENERIC_PRIMARY=y @@ -37,13 +35,6 @@ CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE=90 CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC=y CONFIG_DISPLAY_AV8100_TERTIARY=y CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER=y -CONFIG_U8500_CPUIDLE_DEEPEST_STATE=2 -CONFIG_U8500_CPUIDLE_DEBUG=y -CONFIG_UX500_SUSPEND=y -CONFIG_UX500_SUSPEND_STANDBY=y -CONFIG_UX500_SUSPEND_MEM=y -CONFIG_UX500_SUSPEND_DBG=y -CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y @@ -54,13 +45,6 @@ CONFIG_HIGHMEM=y CONFIG_CMDLINE="root=/dev/ram0 init=init rw console=ttyAMA2,115200n8 mem=256M initrd=0x800000,72M" CONFIG_KEXEC=y CONFIG_CRASH_DUMP=y -CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_STAT_DETAILS=y -CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_IDLE=y CONFIG_FPE_NWFPE=y CONFIG_VFP=y CONFIG_NEON=y diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 29fbc168bae..f015ab84eec 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -8,6 +8,7 @@ config UX500_SOC_COMMON select ARM_ERRATA_753970 select ARM_ERRATA_754322 select SYS_SOC + select HAS_MTU config UX500_SOC_DBX500 depends on UX500_SOC_DB5500 || UX500_SOC_DB8500 @@ -72,26 +73,6 @@ config KEYLAYOUT_LAYOUT2 endchoice -choice - prompt "Ux500 sched_clock timer" - default UX500_MTU_TIMER - -config UX500_PRCMU_TIMER - bool "PRCMU Timer sched_clock" - depends on !HAS_MTU - help - Add support for an always on sched_clock, required for - proper cpuidle and suspend. - -config UX500_MTU_TIMER - bool "Multi Timer Unit sched_clock" - help - Add sched_clock support for the Multi Timer Unit. - Since mtu isn't always on cpuidle will not - work with this clock. - -endchoice - config U8500_PRCMU bool "U8500 PRCMU support" depends on UX500_SOC_DB8500 @@ -106,20 +87,6 @@ config U5500_PRCMU help Add support for PRCMU for U5500 -config UX500_PRCMU_QOS_POWER - bool "UX500 PRCMU power QoS support" - depends on (U5500_PRCMU || U8500_PRCMU) - default y - help - Add support for PRCMU power Quality of Service - -config UX500_PRCMU_DEBUG - bool "PRCMU debug" - depends on ((U5500_PRCMU || U8500_PRCMU) && DEBUG_FS) - default n - help - Add support for PRCMU debug - config UX500_DEBUG_UART int "Ux500 UART to use for low-level debug" default 2 @@ -133,7 +100,6 @@ config U8500_REGULATOR_DEBUG help Add support for U8500 regulator debug - config SENSORS1P_MOP tristate "HAL and Proximity sensors support" depends on REGULATOR && (GPIO_STMPE2401 || GPIO_TC35892) @@ -199,5 +165,4 @@ config UX500_L2X0_PREFETCH_CTRL Communication with Trustzone is done through TEE driver. source "arch/arm/mach-ux500/Kconfig-arch" -source "arch/arm/mach-ux500/pm/Kconfig" endif diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 2f8a09be521..fb6c40c2e49 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -1,11 +1,10 @@ # -# Makefile for the linux kernel, U8500 machine. +# Makefile for the linux kernel, UX500 machine. # obj-y := clock.o cpu.o devices.o dcache.o \ devices-common.o id.o pins.o \ - timer.o timer-mtu.o usb.o reboot_reasons.o \ - uart-db8500.o + usb.o reboot_reasons.o obj-y += pm/ obj-$(CONFIG_REGULATOR) += regulator-ux500.o @@ -51,10 +50,7 @@ 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_UX500_PRCMU_TIMER) += timer-prcmu.o obj-$(CONFIG_U8500_REGULATOR_DEBUG) += virt-regulator-u8500.o -obj-$(CONFIG_UX500_PRCMU_DEBUG) += prcmu-debug.o -obj-$(CONFIG_UX500_PRCMU_QOS_POWER) += prcmu-qos-power.o obj-$(CONFIG_UX500_DEBUG_HWREG) += hwreg.o obj-$(CONFIG_HWMEM) += hwmem-int.o obj-$(CONFIG_UX500_L2X0_PREFETCH_CTRL) += l2x0-prefetch.o diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index 18fe33ec4ce..12f65069022 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -15,7 +15,6 @@ #include <linux/gpio/nomadik.h> #include <mach/hardware.h> -#include <mach/suspend.h> #include "pins-db8500.h" #include "pins.h" @@ -431,479 +430,6 @@ static struct ux500_pin_lookup mop500_pins[] = { }; /* - * Sleep pin configuration for u8500 platform. - * If another HW is used the GPIO's must be configured - * correctly when entering sleep for optimal power - * consumption. - */ -static pin_cfg_t mop500_pins_common_power_save_bank0[] = { - GPIO0_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO1_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO2_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO3_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO4_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO5_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO6_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO7_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO8_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO9_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO10_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO11_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO12_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO13_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO14_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO15_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO16_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO17_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO18_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO19_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO20_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO21_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO22_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO23_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO24_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO25_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO26_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO27_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO28_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO29_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO30_U2_TXD | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO31_U2_CTSn | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank0_href60[] = { - GPIO0_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO1_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO2_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO3_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO4_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO5_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO6_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO7_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO8_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO9_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO10_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO11_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO12_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO13_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO14_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO15_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO16_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO17_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO18_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO19_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO20_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO21_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO22_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO23_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO24_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO25_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO26_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO27_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO28_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO29_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO30_U2_TXD | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO31_U2_CTSn | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank1[] = { - GPIO32_U2_RTSn | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO33_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO34_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO35_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO36_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank2[] = { - GPIO64_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO65_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO66_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO67_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO68_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO69_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO70_STMAPE_CLK | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - GPIO71_STMAPE_DAT3 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO72_STMAPE_DAT2 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - GPIO73_STMAPE_DAT1 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - GPIO74_STMAPE_DAT0 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - GPIO75_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO76_U2_TXD | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO77_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO78_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO79_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO80_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO81_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO82_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO83_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO84_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO85_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO86_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO87_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO88_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO89_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO90_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO91_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO92_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO93_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO94_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO95_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank2_href60[] = { - GPIO64_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO65_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO66_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO67_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO68_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO69_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO70_STMAPE_CLK | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - GPIO71_STMAPE_DAT3 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO72_STMAPE_DAT2 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - GPIO73_STMAPE_DAT1 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - GPIO74_STMAPE_DAT0 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, - GPIO75_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO76_U2_TXD | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO77_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO78_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO79_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO80_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO81_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO82_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO83_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO84_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO85_GPIO, - GPIO86_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO87_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO88_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO89_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO90_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO91_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO92_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO93_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO94_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO95_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank3[] = { - GPIO96_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO97_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank4[] = { - GPIO128_MC2_CLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO129_MC2_CMD | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO130_MC2_FBCLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO131_MC2_DAT0 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO132_MC2_DAT1 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO133_MC2_DAT2 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO134_MC2_DAT3 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO135_MC2_DAT4 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO136_MC2_DAT5 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO137_MC2_DAT6 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO138_MC2_DAT7 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO139_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO140_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO141_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO142_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO143_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO144_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO145_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO146_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO147_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO148_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO149_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO150_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO151_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO152_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO153_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO154_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO155_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO156_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO157_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO158_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO159_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank5[] = { - GPIO160_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO161_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO162_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO163_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO164_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO165_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO166_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO167_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO168_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO169_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO170_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO171_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank5_href60[] = { - GPIO160_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO161_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO162_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO163_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO164_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO165_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO166_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO167_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO168_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO169_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO170_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO171_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank6[] = { - GPIO192_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO193_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO194_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO195_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO196_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO197_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO198_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO199_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO200_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO201_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO202_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO203_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO204_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO205_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO206_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO207_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO208_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO209_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO210_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO211_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO212_GPIO, - GPIO213_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO214_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO215_GPIO, - - GPIO216_GPIO, - GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO219_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO220_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO221_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO222_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO223_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank6_href60[] = { - GPIO192_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO193_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO194_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO195_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO196_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO197_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO198_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO199_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO200_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO201_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO202_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO203_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO204_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO205_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO206_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO207_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO208_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO209_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO210_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO211_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO212_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO213_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO214_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO215_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO216_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO219_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO220_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO221_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO222_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO223_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank7[] = { - GPIO224_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO225_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO226_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO227_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO228_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO229_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO230_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank7_href60[] = { - GPIO224_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO225_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO226_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO227_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - - GPIO228_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO229_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO230_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, -}; - -static pin_cfg_t mop500_pins_common_power_save_bank8[] = { - GPIO256_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO257_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, - GPIO258_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO259_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - - GPIO260_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO261_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO262_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO263_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - - GPIO264_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO265_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO266_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, - GPIO267_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, -}; - -void mop500_pins_suspend_force(void) -{ - if (machine_is_hrefv60()) - sleep_pins_config_pm(mop500_pins_common_power_save_bank0_href60, - ARRAY_SIZE(mop500_pins_common_power_save_bank0_href60)); - else - sleep_pins_config_pm(mop500_pins_common_power_save_bank0, - ARRAY_SIZE(mop500_pins_common_power_save_bank0)); - - sleep_pins_config_pm(mop500_pins_common_power_save_bank1, - ARRAY_SIZE(mop500_pins_common_power_save_bank1)); - - if (machine_is_hrefv60()) - sleep_pins_config_pm(mop500_pins_common_power_save_bank2_href60, - ARRAY_SIZE(mop500_pins_common_power_save_bank2_href60)); - else - sleep_pins_config_pm(mop500_pins_common_power_save_bank2, - ARRAY_SIZE(mop500_pins_common_power_save_bank2)); - - sleep_pins_config_pm(mop500_pins_common_power_save_bank3, - ARRAY_SIZE(mop500_pins_common_power_save_bank3)); - - sleep_pins_config_pm(mop500_pins_common_power_save_bank4, - ARRAY_SIZE(mop500_pins_common_power_save_bank4)); - - if (machine_is_hrefv60()) - sleep_pins_config_pm(mop500_pins_common_power_save_bank5_href60, - ARRAY_SIZE(mop500_pins_common_power_save_bank5_href60)); - else - sleep_pins_config_pm(mop500_pins_common_power_save_bank5, - ARRAY_SIZE(mop500_pins_common_power_save_bank5)); - - if (machine_is_hrefv60()) - sleep_pins_config_pm(mop500_pins_common_power_save_bank6_href60, - ARRAY_SIZE(mop500_pins_common_power_save_bank6_href60)); - else - sleep_pins_config_pm(mop500_pins_common_power_save_bank6, - ARRAY_SIZE(mop500_pins_common_power_save_bank6)); - - if (machine_is_hrefv60()) - sleep_pins_config_pm(mop500_pins_common_power_save_bank7_href60, - ARRAY_SIZE(mop500_pins_common_power_save_bank7_href60)); - else - sleep_pins_config_pm(mop500_pins_common_power_save_bank7, - ARRAY_SIZE(mop500_pins_common_power_save_bank7)); - - sleep_pins_config_pm(mop500_pins_common_power_save_bank8, - ARRAY_SIZE(mop500_pins_common_power_save_bank8)); -} - -/* - * This function is called to force gpio power save - * mux settings during suspend. - * This is a temporary solution until all drivers are - * controlling their pin settings when in inactive mode. - */ -static void mop500_pins_suspend_force_mux(void) -{ - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank0, - ARRAY_SIZE(mop500_pins_common_power_save_bank0)); - - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank1, - ARRAY_SIZE(mop500_pins_common_power_save_bank1)); - - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank2, - ARRAY_SIZE(mop500_pins_common_power_save_bank2)); - - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank3, - ARRAY_SIZE(mop500_pins_common_power_save_bank3)); - - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank4, - ARRAY_SIZE(mop500_pins_common_power_save_bank4)); - - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank5, - ARRAY_SIZE(mop500_pins_common_power_save_bank5)); - - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank6, - ARRAY_SIZE(mop500_pins_common_power_save_bank6)); - - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank7, - ARRAY_SIZE(mop500_pins_common_power_save_bank7)); - - sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank8, - ARRAY_SIZE(mop500_pins_common_power_save_bank8)); -} - -/* * passing "pinsfor=" in kernel cmdline allows for custom * configuration of GPIOs on u8500 derived boards. */ @@ -953,8 +479,5 @@ void __init mop500_pins_init(void) default: break; } - - suspend_set_pins_force_fn(mop500_pins_suspend_force, - mop500_pins_suspend_force_mux); } diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 96c42e06ea4..700fd5256bf 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -31,6 +31,31 @@ void __iomem *_PRCMU_BASE; static void __iomem *l2x0_base; #endif +static void __init ux500_timer_init(void) +{ +#ifdef CONFIG_LOCAL_TIMERS + /* Setup the local timer base */ + if (cpu_is_u5500()) + twd_base = __io_address(U5500_TWD_BASE); + else if (cpu_is_u8500()) + twd_base = __io_address(U8500_TWD_BASE); + else + ux500_unknown_soc(); +#endif + if (cpu_is_u5500()) + mtu_base = __io_address(U5500_MTU0_BASE); + else if (cpu_is_u8500()) + mtu_base = __io_address(U8500_MTU0_BASE); + else + ux500_unknown_soc(); + + nmdk_timer_init(); +} + +struct sys_timer ux500_timer = { + .init = ux500_timer_init, +}; + void __init ux500_init_devices(void) { #ifdef CONFIG_CACHE_L2X0 diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c index 3f614b493b7..ee6050263f5 100644 --- a/arch/arm/mach-ux500/devices-db5500.c +++ b/arch/arm/mach-ux500/devices-db5500.c @@ -22,16 +22,12 @@ #include <mach/prcmu.h> -#include "pm/pm.h" - #define GPIO_DATA(_name, first, num) \ { \ .name = _name, \ .first_gpio = first, \ .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ .num_gpio = num, \ - .get_secondary_status = ux500_pm_gpio_read_wake_up_status, \ - .set_ioforce = ux500_pm_prcmu_set_ioforce, \ } #define GPIO_RESOURCE(block) \ diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 5578d1f612b..47124f5c7a5 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -40,8 +40,6 @@ .first_gpio = first, \ .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ .num_gpio = num, \ - .get_secondary_status = ux500_pm_gpio_read_wake_up_status, \ - .set_ioforce = ux500_pm_prcmu_set_ioforce, \ .supports_sleepmode = true, \ } diff --git a/arch/arm/mach-ux500/dma-db8500.c b/arch/arm/mach-ux500/dma-db8500.c index d7dcc9147ed..e17eb7a3d8a 100644 --- a/arch/arm/mach-ux500/dma-db8500.c +++ b/arch/arm/mach-ux500/dma-db8500.c @@ -16,7 +16,6 @@ #include <mach/setup.h> #include <mach/ste-dma40-db8500.h> -#include "pm/context.h" #include "pm/pm.h" static struct resource dma40_resources[] = { @@ -232,54 +231,6 @@ static struct stedma40_platform_data dma40_plat_data = { .use_esram_lcla = false, }; -#ifdef CONFIG_UX500_CONTEXT -#define D40_DREG_GCC 0x000 -#define D40_DREG_LCPA 0x020 -#define D40_DREG_LCLA 0x024 - -static void __iomem *base; - -static int dma_context_notifier_call(struct notifier_block *this, - unsigned long event, void *data) -{ - static unsigned long lcpa; - static unsigned long lcla; - static unsigned long gcc; - - switch (event) { - case CONTEXT_APE_SAVE: - lcla = readl(base + D40_DREG_LCLA); - lcpa = readl(base + D40_DREG_LCPA); - gcc = readl(base + D40_DREG_GCC); - break; - - case CONTEXT_APE_RESTORE: - writel(gcc, base + D40_DREG_GCC); - writel(lcpa, base + D40_DREG_LCPA); - writel(lcla, base + D40_DREG_LCLA); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block dma_context_notifier = { - .notifier_call = dma_context_notifier_call, -}; - -static void dma_context_notifier_init(void) -{ - base = ioremap(dma40_resources[0].start, resource_size(&dma40_resources[0])); - if (WARN_ON(!base)) - return; - - WARN_ON(context_ape_notifier_register(&dma_context_notifier)); -} -#else -static void dma_context_notifier_init(void) -{ -} -#endif - static struct platform_device dma40_device = { .dev = { .platform_data = &dma40_plat_data, @@ -301,5 +252,4 @@ void __init db8500_dma_init(void) if (ret) dev_err(&dma40_device.dev, "unable to register device: %d\n", ret); - dma_context_notifier_init(); } diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c index 8d64534bbe7..5a05b15cc87 100644 --- a/arch/arm/mach-ux500/hotplug.c +++ b/arch/arm/mach-ux500/hotplug.c @@ -15,8 +15,6 @@ #include <asm/cacheflush.h> -#include "pm/context.h" - extern volatile int pen_release; static inline void platform_do_lowpower(unsigned int cpu) @@ -25,13 +23,8 @@ static inline void platform_do_lowpower(unsigned int cpu) for (;;) { - context_varm_save_core(); - context_save_cpu_registers(); - - context_save_to_sram_and_wfi(false); - - context_restore_cpu_registers(); - context_varm_restore_core(); + __asm__ __volatile__("dsb\n\t" "wfi\n\t" + : : : "memory"); if (pen_release == cpu) { /* @@ -66,4 +59,3 @@ int platform_cpu_disable(unsigned int cpu) */ return cpu == 0 ? -EPERM : 0; } - diff --git a/arch/arm/mach-ux500/include/mach/scu.h b/arch/arm/mach-ux500/include/mach/scu.h deleted file mode 100644 index a09e86a9d3c..00000000000 --- a/arch/arm/mach-ux500/include/mach/scu.h +++ /dev/null @@ -1,25 +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 as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __ASMARM_ARCH_SCU_H -#define __ASMARM_ARCH_SCU_H - -#include <mach/hardware.h> - -#define SCU_BASE U8500_SCU_BASE -/* - * * SCU registers - * */ -#define SCU_CTRL 0x00 -#define SCU_CONFIG 0x04 -#define SCU_CPU_STATUS 0x08 -#define SCU_INVALIDATE 0x0c -#define SCU_FPGA_REVISION 0x10 - -#endif diff --git a/arch/arm/mach-ux500/include/mach/suspend.h b/arch/arm/mach-ux500/include/mach/suspend.h deleted file mode 100644 index 5c9e1c48605..00000000000 --- a/arch/arm/mach-ux500/include/mach/suspend.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License terms: GNU General Public License (GPL) version 2 - */ -#ifndef __MACH_SUSPEND_H -#define __MACH_SUSPEND_H - -void suspend_block_sleep(void); -void suspend_unblock_sleep(void); - -#ifdef CONFIG_UX500_SUSPEND -void suspend_set_pins_force_fn(void (*force)(void), void (*force_mux)(void)); -#else -static inline void suspend_set_pins_force_fn(void (*force)(void), - void (*force_mux)(void)) { } -#endif - -#endif /* __MACH_SUSPEND_H */ diff --git a/arch/arm/mach-ux500/include/mach/timex.h b/arch/arm/mach-ux500/include/mach/timex.h index 0ba497bd9d7..d0942c17401 100644 --- a/arch/arm/mach-ux500/include/mach/timex.h +++ b/arch/arm/mach-ux500/include/mach/timex.h @@ -2,6 +2,5 @@ #define __ASM_ARCH_TIMEX_H #define CLOCK_TICK_RATE 110000000 -#define ARCH_HAS_READ_CURRENT_TIMER #endif diff --git a/arch/arm/mach-ux500/pm/Kconfig b/arch/arm/mach-ux500/pm/Kconfig deleted file mode 100644 index 22a677b4f0c..00000000000 --- a/arch/arm/mach-ux500/pm/Kconfig +++ /dev/null @@ -1,101 +0,0 @@ -config UX500_CPUFREQ - tristate "CPUFreq support" - depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && CPU_FREQ && PM - default y - help - Add support for CPU Frequency scaling for Ux500 SOCs. - ARM power domains operating points can be set - dynamically. It depends on CPUfreq and PM subsystem. - -config U8500_CPUIDLE - tristate "CPUIdle support" - depends on CPU_IDLE && (U5500_PRCMU || U8500_PRCMU) && !RTC_DRV_PL031 && PM - default y - select GENERIC_CLOCKEVENTS_BROADCAST - select UX500_CONTEXT - help - Add support for CPUIdle for U8500. - -config U8500_CPUIDLE_DEEPEST_STATE - int "Deepest sleep state" - default 4 if UX500_SOC_DB8500 - default 1 if UX500_SOC_DB5500 - depends on U8500_CPUIDLE - help - Set deepest sleep state. See the cstate struct in cpuidle.c. - Default is ApSleep. - -config U8500_CPUIDLE_APDEEPIDLE - bool "CPUIdle ApDeepIdle" - depends on U8500_CPUIDLE - help - Adds the power level ApDeepIdle, where APE is powered on while - ARM is powered off. Default n. - -config U8500_CPUIDLE_DEBUG - bool "CPUIdle debug" - depends on U8500_CPUIDLE && DEBUG_FS - help - Add debugging support for CPUIdle for U8500. - -config UX500_SUSPEND - bool "Suspend to mem and standby support" - depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && PM - select UX500_CONTEXT - help - Add support for suspend. - -config UX500_SUSPEND_STANDBY - bool "Suspend Standby goes to ApSleep" - depends on UX500_SUSPEND - help - If yes, echo standby > /sys/power/state puts the system into ApSleep. - -config UX500_SUSPEND_MEM - bool "Suspend Mem goes to ApDeepSleep" - depends on UX500_SUSPEND - help - If yes, echo mem > /sys/power/state puts the system into ApDeepSleep else - it will do the same as echo standby > /sys/power/state. - -config UX500_SUSPEND_DBG - bool "Suspend debug" - depends on UX500_SUSPEND && DEBUG_FS - help - Add debug support for suspend. - -config UX500_SUSPEND_DBG_WAKE_ON_UART - bool "Suspend wakes on console UART" - depends on UX500_SUSPEND_DBG - help - Wake up on uart interrupts. Makes it possible for the console to wake up system. - -config UX500_CONSOLE_UART_GPIO_PIN - int "The pin number of the console UART GPIO pin" - default 29 - depends on UX500_SUSPEND_DBG_WAKE_ON_UART || U8500_CPUIDLE_DEBUG - help - GPIO pin number of the GPIO pin connected to the console UART RX line. - -config UX500_CONTEXT - bool "Context save/restore support for UX500" - depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && PM - help - This is needed for ApSleep and deeper sleep states. - -config UX500_USECASE_GOVERNOR - bool "UX500 use-case governor" - depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && \ - (CPU_FREQ && CPU_IDLE && HOTPLUG_CPU && \ - EARLYSUSPEND && UX500_L2X0_PREFETCH_CTRL && PM) - default y - help - Adjusts CPU_IDLE, CPU_FREQ, HOTPLUG_CPU and L2 cache parameters - -config UX500_PM_PERFORMANCE - bool "Performance supervision" - depends on UX500_PRCMU_QOS_POWER - default y - help - Enable supervision of events which may require a boost - of platform performance. diff --git a/arch/arm/mach-ux500/pm/Makefile b/arch/arm/mach-ux500/pm/Makefile index 2d191ff8081..1bf6415307b 100644 --- a/arch/arm/mach-ux500/pm/Makefile +++ b/arch/arm/mach-ux500/pm/Makefile @@ -1,22 +1,4 @@ # # Power save related files # -obj-y := pm.o runtime.o no_suspend.o - -obj-$(CONFIG_U8500_CPUIDLE) += cpuidle.o timer.o -obj-$(CONFIG_U8500_CPUIDLE_DEBUG) += cpuidle_dbg.o -obj-$(CONFIG_UX500_CONTEXT) += context.o context_arm.o context-db8500.o context-db5500.o -obj-$(CONFIG_UX500_CPUFREQ) += cpufreq.o -obj-$(CONFIG_UX500_SUSPEND) += suspend.o -obj-$(CONFIG_UX500_SUSPEND_DBG) += suspend_dbg.o -obj-$(CONFIG_UX500_USECASE_GOVERNOR) += usecase_gov.o - -ifeq ($(CONFIG_UX500_SOC_DB8500), y) -obj-$(CONFIG_UX500_CPUFREQ) += cpufreq-db8500.o -endif - -ifeq ($(CONFIG_UX500_SOC_DB5500), y) -obj-$(CONFIG_UX500_CPUFREQ) += cpufreq-db5500.o -endif - -obj-$(CONFIG_UX500_PM_PERFORMANCE) += performance.o +obj-y := runtime.o no_suspend.o diff --git a/arch/arm/mach-ux500/pm/context-db5500.c b/arch/arm/mach-ux500/pm/context-db5500.c deleted file mode 100644 index 78904d3486e..00000000000 --- a/arch/arm/mach-ux500/pm/context-db5500.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>, - * Rickard Andersson <rickard.andersson@stericsson.com>, - * Sundar Iyer <sundar.iyer@stericsson.com>, - * ST-Ericsson. - * License terms: GNU General Public License (GPL) version 2 - * - */ - -#include <linux/io.h> - -#include <mach/hardware.h> - -#include "context.h" - -/* These registers are DB5500 specific */ -#define NODE_HIBW1_ESRAM_IN_0_PRIORITY 0x0 -#define NODE_HIBW1_ESRAM_IN_1_PRIORITY 0x4 - -#define NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT 0x18 -#define NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT 0x1C -#define NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT 0x20 - -#define NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT 0x24 -#define NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT 0x28 -#define NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT 0x2C - -#define NODE_HIBW1_DDR_IN_0_PRIORITY 0x400 -#define NODE_HIBW1_DDR_IN_1_PRIORITY 0x404 -#define NODE_HIBW1_DDR_IN_2_PRIORITY 0x408 - -#define NODE_HIBW1_DDR_IN_0_LIMIT 0x424 -#define NODE_HIBW1_DDR_IN_1_LIMIT 0x428 -#define NODE_HIBW1_DDR_IN_2_LIMIT 0x42C - -#define NODE_HIBW1_DDR_OUT_0_PRIORITY 0x430 - -#define NODE_HIBW2_ESRAM_IN_0_PRIORITY 0x800 -#define NODE_HIBW2_ESRAM_IN_1_PRIORITY 0x804 - -#define NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT 0x818 -#define NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT 0x81C -#define NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT 0x820 - -#define NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT 0x824 -#define NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT 0x828 -#define NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT 0x82C - -#define NODE_HIBW2_DDR_IN_0_PRIORITY 0xC00 -#define NODE_HIBW2_DDR_IN_1_PRIORITY 0xC04 -#define NODE_HIBW2_DDR_IN_2_PRIORITY 0xC08 -#define NODE_HIBW2_DDR_IN_3_PRIORITY 0xC0C - -#define NODE_HIBW2_DDR_IN_0_LIMIT 0xC30 -#define NODE_HIBW2_DDR_IN_1_LIMIT 0xC34 -#define NODE_HIBW2_DDR_IN_2_LIMIT 0xC38 -#define NODE_HIBW2_DDR_IN_3_LIMIT 0xC3C - -#define NODE_HIBW2_DDR_OUT_0_PRIORITY 0xC40 - -#define NODE_ESRAM0_IN_0_PRIORITY 0x1000 -#define NODE_ESRAM0_IN_1_PRIORITY 0x1004 -#define NODE_ESRAM0_IN_2_PRIORITY 0x1008 - -#define NODE_ESRAM0_IN_0_LIMIT 0x1024 -#define NODE_ESRAM0_IN_1_LIMIT 0x1028 -#define NODE_ESRAM0_IN_2_LIMIT 0x102C -#define NODE_ESRAM0_OUT_0_PRIORITY 0x1030 - -#define NODE_ESRAM1_2_IN_0_PRIORITY 0x1400 -#define NODE_ESRAM1_2_IN_1_PRIORITY 0x1404 -#define NODE_ESRAM1_2_IN_2_PRIORITY 0x1408 - -#define NODE_ESRAM1_2_IN_0_ARB_1_LIMIT 0x1424 -#define NODE_ESRAM1_2_IN_1_ARB_1_LIMIT 0x1428 -#define NODE_ESRAM1_2_IN_2_ARB_1_LIMIT 0x142C -#define NODE_ESRAM1_2_OUT_0_PRIORITY 0x1430 - -#define NODE_ESRAM3_4_IN_0_PRIORITY 0x1800 -#define NODE_ESRAM3_4_IN_1_PRIORITY 0x1804 -#define NODE_ESRAM3_4_IN_2_PRIORITY 0x1808 - -#define NODE_ESRAM3_4_IN_0_ARB_1_LIMIT 0x1824 -#define NODE_ESRAM3_4_IN_1_ARB_1_LIMIT 0x1828 -#define NODE_ESRAM3_4_IN_2_ARB_1_LIMIT 0x182C -#define NODE_ESRAM3_4_OUT_0_PRIORITY 0x1830 - -/* - * Save ICN (Interconnect or Interconnect nodes) configuration registers - * TODO: This can be optimized, for example if we have - * a static ICN configuration. - */ - -static struct { - void __iomem *base; - u32 hibw1_esram_in_pri[2]; - u32 hibw1_esram_in0_arb[3]; - u32 hibw1_esram_in1_arb[3]; - u32 hibw1_ddr_in_prio[3]; - u32 hibw1_ddr_in_limit[3]; - u32 hibw1_ddr_out_prio_reg; - - /* HiBw2 node registers */ - u32 hibw2_esram_in_pri[2]; - u32 hibw2_esram_in0_arblimit[3]; - u32 hibw2_esram_in1_arblimit[3]; - u32 hibw2_ddr_in_prio[4]; - u32 hibw2_ddr_in_limit[4]; - u32 hibw2_ddr_out_prio_reg; - - /* ESRAM node registers */ - u32 esram_in_prio[3]; - u32 esram_in_lim[3]; - u32 esram_out_prio_reg; - - u32 esram12_in_prio[3]; - u32 esram12_in_arb_lim[3]; - u32 esram12_out_prio_reg; - - u32 esram34_in_prio[3]; - u32 esram34_in_arb_lim[3]; - u32 esram34_out_prio; -} context_icn; - - -void u5500_context_save_icn(void) -{ - /* hibw1 */ - context_icn.hibw1_esram_in_pri[0] = - readl(context_icn.base + NODE_HIBW1_ESRAM_IN_0_PRIORITY); - context_icn.hibw1_esram_in_pri[1] = - readl(context_icn.base + NODE_HIBW1_ESRAM_IN_1_PRIORITY); - - context_icn.hibw1_esram_in0_arb[0] = - readl(context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); - context_icn.hibw1_esram_in0_arb[1] = - readl(context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); - context_icn.hibw1_esram_in0_arb[2] = - readl(context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); - - context_icn.hibw1_esram_in1_arb[0] = - readl(context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); - context_icn.hibw1_esram_in1_arb[1] = - readl(context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); - context_icn.hibw1_esram_in1_arb[2] = - readl(context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); - - context_icn.hibw1_ddr_in_prio[0] = - readl(context_icn.base + NODE_HIBW1_DDR_IN_0_PRIORITY); - context_icn.hibw1_ddr_in_prio[1] = - readl(context_icn.base + NODE_HIBW1_DDR_IN_1_PRIORITY); - context_icn.hibw1_ddr_in_prio[2] = - readl(context_icn.base + NODE_HIBW1_DDR_IN_2_PRIORITY); - - context_icn.hibw1_ddr_in_limit[0] = - readl(context_icn.base + NODE_HIBW1_DDR_IN_0_LIMIT); - context_icn.hibw1_ddr_in_limit[1] = - readl(context_icn.base + NODE_HIBW1_DDR_IN_1_LIMIT); - context_icn.hibw1_ddr_in_limit[2] = - readl(context_icn.base + NODE_HIBW1_DDR_IN_2_LIMIT); - - context_icn.hibw1_ddr_out_prio_reg = - readl(context_icn.base + NODE_HIBW1_DDR_OUT_0_PRIORITY); - - /* hibw2 */ - context_icn.hibw2_esram_in_pri[0] = - readl(context_icn.base + NODE_HIBW2_ESRAM_IN_0_PRIORITY); - context_icn.hibw2_esram_in_pri[1] = - readl(context_icn.base + NODE_HIBW2_ESRAM_IN_1_PRIORITY); - - context_icn.hibw2_esram_in0_arblimit[0] = - readl(context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); - context_icn.hibw2_esram_in0_arblimit[1] = - readl(context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); - context_icn.hibw2_esram_in0_arblimit[2] = - readl(context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); - - context_icn.hibw2_esram_in1_arblimit[0] = - readl(context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); - context_icn.hibw2_esram_in1_arblimit[1] = - readl(context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); - context_icn.hibw2_esram_in1_arblimit[2] = - readl(context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); - - context_icn.hibw2_ddr_in_prio[0] = - readl(context_icn.base + NODE_HIBW2_DDR_IN_0_PRIORITY); - context_icn.hibw2_ddr_in_prio[1] = - readl(context_icn.base + NODE_HIBW2_DDR_IN_1_PRIORITY); - context_icn.hibw2_ddr_in_prio[2] = - readl(context_icn.base + NODE_HIBW2_DDR_IN_2_PRIORITY); - context_icn.hibw2_ddr_in_prio[3] = - readl(context_icn.base + NODE_HIBW2_DDR_IN_3_PRIORITY); - - context_icn.hibw2_ddr_in_limit[0] = - readl(context_icn.base + NODE_HIBW2_DDR_IN_0_LIMIT); - context_icn.hibw2_ddr_in_limit[1] = - readl(context_icn.base + NODE_HIBW2_DDR_IN_1_LIMIT); - context_icn.hibw2_ddr_in_limit[2] = - readl(context_icn.base + NODE_HIBW2_DDR_IN_2_LIMIT); - context_icn.hibw2_ddr_in_limit[3] = - readl(context_icn.base + NODE_HIBW2_DDR_IN_3_LIMIT); - - context_icn.hibw2_ddr_out_prio_reg = - readl(context_icn.base + NODE_HIBW2_DDR_OUT_0_PRIORITY); - - /* ESRAM0 */ - context_icn.esram_in_prio[0] = - readl(context_icn.base + NODE_ESRAM0_IN_0_PRIORITY); - context_icn.esram_in_prio[1] = - readl(context_icn.base + NODE_ESRAM0_IN_1_PRIORITY); - context_icn.esram_in_prio[2] = - readl(context_icn.base + NODE_ESRAM0_IN_2_PRIORITY); - - context_icn.esram_in_lim[0] = - readl(context_icn.base + NODE_ESRAM0_IN_0_LIMIT); - context_icn.esram_in_lim[1] = - readl(context_icn.base + NODE_ESRAM0_IN_1_LIMIT); - context_icn.esram_in_lim[2] = - readl(context_icn.base + NODE_ESRAM0_IN_2_LIMIT); - - context_icn.esram_out_prio_reg = - readl(context_icn.base + NODE_ESRAM0_OUT_0_PRIORITY); - - /* ESRAM1-2 */ - context_icn.esram12_in_prio[0] = - readl(context_icn.base + NODE_ESRAM1_2_IN_0_PRIORITY); - context_icn.esram12_in_prio[1] = - readl(context_icn.base + NODE_ESRAM1_2_IN_1_PRIORITY); - context_icn.esram12_in_prio[2] = - readl(context_icn.base + NODE_ESRAM1_2_IN_2_PRIORITY); - - context_icn.esram12_in_arb_lim[0] = - readl(context_icn.base + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); - context_icn.esram12_in_arb_lim[1] = - readl(context_icn.base + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); - context_icn.esram12_in_arb_lim[2] = - readl(context_icn.base + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); - - context_icn.esram12_out_prio_reg = - readl(context_icn.base + NODE_ESRAM1_2_OUT_0_PRIORITY); - - /* ESRAM3-4 */ - context_icn.esram34_in_prio[0] = - readl(context_icn.base + NODE_ESRAM3_4_IN_0_PRIORITY); - context_icn.esram34_in_prio[1] = - readl(context_icn.base + NODE_ESRAM3_4_IN_1_PRIORITY); - context_icn.esram34_in_prio[2] = - readl(context_icn.base + NODE_ESRAM3_4_IN_2_PRIORITY); - - context_icn.esram34_in_arb_lim[0] = - readl(context_icn.base + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); - context_icn.esram34_in_arb_lim[1] = - readl(context_icn.base + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); - context_icn.esram34_in_arb_lim[2] = - readl(context_icn.base + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); - - context_icn.esram34_out_prio = - readl(context_icn.base + NODE_ESRAM3_4_OUT_0_PRIORITY); -} - -/* - * Restore ICN configuration registers - */ -void u5500_context_restore_icn(void) -{ - - /* hibw1 */ - writel(context_icn.hibw1_esram_in_pri[0], - context_icn.base + NODE_HIBW1_ESRAM_IN_0_PRIORITY); - writel(context_icn.hibw1_esram_in_pri[1], - context_icn.base + NODE_HIBW1_ESRAM_IN_1_PRIORITY); - - writel(context_icn.hibw1_esram_in0_arb[0], - context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); - writel(context_icn.hibw1_esram_in0_arb[1], - context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); - writel(context_icn.hibw1_esram_in0_arb[2], - context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); - - writel(context_icn.hibw1_esram_in1_arb[0], - context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); - writel(context_icn.hibw1_esram_in1_arb[1], - context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); - writel(context_icn.hibw1_esram_in1_arb[2], - context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); - - writel(context_icn.hibw1_ddr_in_prio[0], - context_icn.base + NODE_HIBW1_DDR_IN_0_PRIORITY); - writel(context_icn.hibw1_ddr_in_prio[1], - context_icn.base + NODE_HIBW1_DDR_IN_1_PRIORITY); - writel(context_icn.hibw1_ddr_in_prio[2], - context_icn.base + NODE_HIBW1_DDR_IN_2_PRIORITY); - - writel(context_icn.hibw1_ddr_in_limit[0], - context_icn.base + NODE_HIBW1_DDR_IN_0_LIMIT); - writel(context_icn.hibw1_ddr_in_limit[1], - context_icn.base + NODE_HIBW1_DDR_IN_1_LIMIT); - writel(context_icn.hibw1_ddr_in_limit[2], - context_icn.base + NODE_HIBW1_DDR_IN_2_LIMIT); - - writel(context_icn.hibw1_ddr_out_prio_reg, - context_icn.base + NODE_HIBW1_DDR_OUT_0_PRIORITY); - - /* hibw2 */ - writel(context_icn.hibw2_esram_in_pri[0], - context_icn.base + NODE_HIBW2_ESRAM_IN_0_PRIORITY); - writel(context_icn.hibw2_esram_in_pri[1], - context_icn.base + NODE_HIBW2_ESRAM_IN_1_PRIORITY); - - writel(context_icn.hibw2_esram_in0_arblimit[0], - context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); - writel(context_icn.hibw2_esram_in0_arblimit[1], - context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); - writel(context_icn.hibw2_esram_in0_arblimit[2], - context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); - - writel(context_icn.hibw2_esram_in1_arblimit[0], - context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); - writel(context_icn.hibw2_esram_in1_arblimit[1], - context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); - writel(context_icn.hibw2_esram_in1_arblimit[2], - context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); - - writel(context_icn.hibw2_ddr_in_prio[0], - context_icn.base + NODE_HIBW2_DDR_IN_0_PRIORITY); - writel(context_icn.hibw2_ddr_in_prio[1], - context_icn.base + NODE_HIBW2_DDR_IN_1_PRIORITY); - writel(context_icn.hibw2_ddr_in_prio[2], - context_icn.base + NODE_HIBW2_DDR_IN_2_PRIORITY); - writel(context_icn.hibw2_ddr_in_prio[3], - context_icn.base + NODE_HIBW2_DDR_IN_3_PRIORITY); - - writel(context_icn.hibw2_ddr_in_limit[0], - context_icn.base + NODE_HIBW2_DDR_IN_0_LIMIT); - writel(context_icn.hibw2_ddr_in_limit[1], - context_icn.base + NODE_HIBW2_DDR_IN_1_LIMIT); - writel(context_icn.hibw2_ddr_in_limit[2], - context_icn.base + NODE_HIBW2_DDR_IN_2_LIMIT); - writel(context_icn.hibw2_ddr_in_limit[3], - context_icn.base + NODE_HIBW2_DDR_IN_3_LIMIT); - - writel(context_icn.hibw2_ddr_out_prio_reg, - context_icn.base + NODE_HIBW2_DDR_OUT_0_PRIORITY); - - /* ESRAM0 */ - writel(context_icn.esram_in_prio[0], - context_icn.base + NODE_ESRAM0_IN_0_PRIORITY); - writel(context_icn.esram_in_prio[1], - context_icn.base + NODE_ESRAM0_IN_1_PRIORITY); - writel(context_icn.esram_in_prio[2], - context_icn.base + NODE_ESRAM0_IN_2_PRIORITY); - - writel(context_icn.esram_in_lim[0], - context_icn.base + NODE_ESRAM0_IN_0_LIMIT); - writel(context_icn.esram_in_lim[1], - context_icn.base + NODE_ESRAM0_IN_1_LIMIT); - writel(context_icn.esram_in_lim[2], - context_icn.base + NODE_ESRAM0_IN_2_LIMIT); - - writel(context_icn.esram_out_prio_reg, - context_icn.base + NODE_ESRAM0_OUT_0_PRIORITY); - - /* ESRAM1-2 */ - writel(context_icn.esram12_in_prio[0], - context_icn.base + NODE_ESRAM1_2_IN_0_PRIORITY); - writel(context_icn.esram12_in_prio[1], - context_icn.base + NODE_ESRAM1_2_IN_1_PRIORITY); - writel(context_icn.esram12_in_prio[2], - context_icn.base + NODE_ESRAM1_2_IN_2_PRIORITY); - - writel(context_icn.esram12_in_arb_lim[0], - context_icn.base + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); - writel(context_icn.esram12_in_arb_lim[1], - context_icn.base + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); - writel(context_icn.esram12_in_arb_lim[2], - context_icn.base + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); - - writel(context_icn.esram12_out_prio_reg, - context_icn.base + NODE_ESRAM1_2_OUT_0_PRIORITY); - - /* ESRAM3-4 */ - writel(context_icn.esram34_in_prio[0], - context_icn.base + NODE_ESRAM3_4_IN_0_PRIORITY); - writel(context_icn.esram34_in_prio[1], - context_icn.base + NODE_ESRAM3_4_IN_1_PRIORITY); - writel(context_icn.esram34_in_prio[2], - context_icn.base + NODE_ESRAM3_4_IN_2_PRIORITY); - - writel(context_icn.esram34_in_arb_lim[0], - context_icn.base + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); - writel(context_icn.esram34_in_arb_lim[1], - context_icn.base + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); - writel(context_icn.esram34_in_arb_lim[2], - context_icn.base + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); - - writel(context_icn.esram34_out_prio, - context_icn.base + NODE_ESRAM3_4_OUT_0_PRIORITY); - -} - -void u5500_context_init(void) -{ - context_icn.base = ioremap(U5500_ICN_BASE, SZ_8K); -} diff --git a/arch/arm/mach-ux500/pm/context-db8500.c b/arch/arm/mach-ux500/pm/context-db8500.c deleted file mode 100644 index ad21163917d..00000000000 --- a/arch/arm/mach-ux500/pm/context-db8500.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010-2011 - * - * License Terms: GNU General Public License v2 - * Author: Sundar Iyer for ST-Ericsson - * - */ - -#include <linux/io.h> - -#include <mach/hardware.h> - -#include "context.h" - -/* - * ST-Interconnect context - */ - -/* priority, bw limiter register offsets */ -#define NODE_HIBW1_ESRAM_IN_0_PRIORITY 0x00 -#define NODE_HIBW1_ESRAM_IN_1_PRIORITY 0x04 -#define NODE_HIBW1_ESRAM_IN_2_PRIORITY 0x08 -#define NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT 0x24 -#define NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT 0x28 -#define NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT 0x2C -#define NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT 0x30 -#define NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT 0x34 -#define NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT 0x38 -#define NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT 0x3C -#define NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT 0x40 -#define NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT 0x44 -#define NODE_HIBW1_DDR_IN_0_PRIORITY 0x400 -#define NODE_HIBW1_DDR_IN_1_PRIORITY 0x404 -#define NODE_HIBW1_DDR_IN_2_PRIORITY 0x408 -#define NODE_HIBW1_DDR_IN_0_LIMIT 0x424 -#define NODE_HIBW1_DDR_IN_1_LIMIT 0x428 -#define NODE_HIBW1_DDR_IN_2_LIMIT 0x42C -#define NODE_HIBW1_DDR_OUT_0_PRIORITY 0x430 -#define NODE_HIBW2_ESRAM_IN_0_PRIORITY 0x800 -#define NODE_HIBW2_ESRAM_IN_1_PRIORITY 0x804 -#define NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT 0x818 -#define NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT 0x81C -#define NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT 0x820 -#define NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT 0x824 -#define NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT 0x828 -#define NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT 0x82C -#define NODE_HIBW2_DDR_IN_0_PRIORITY 0xC00 -#define NODE_HIBW2_DDR_IN_1_PRIORITY 0xC04 -#define NODE_HIBW2_DDR_IN_2_PRIORITY 0xC08 - -#define NODE_HIBW2_DDR_IN_0_LIMIT 0xC24 -#define NODE_HIBW2_DDR_IN_1_LIMIT 0xC28 -#define NODE_HIBW2_DDR_IN_2_LIMIT 0xC2C -#define NODE_HIBW2_DDR_OUT_0_PRIORITY 0xC30 - -/* - * Note the following addresses are presented in - * db8500 design spec v3.1 and v3.3, table 10. - * But their addresses are not the same as in the - * description. The addresses in the description - * of each registers are correct. - * NODE_HIBW2_DDR_IN_3_LIMIT is only present in v1. - * - * Faulty registers addresses in table 10: - * NODE_HIBW2_DDR_IN_2_LIMIT 0xC38 - * NODE_HIBW2_DDR_IN_3_LIMIT 0xC3C - * NODE_HIBW2_DDR_OUT_0_PRIORITY 0xC40 - */ - -#define NODE_ESRAM0_IN_0_PRIORITY 0x1000 -#define NODE_ESRAM0_IN_1_PRIORITY 0x1004 -#define NODE_ESRAM0_IN_2_PRIORITY 0x1008 -#define NODE_ESRAM0_IN_3_PRIORITY 0x100C -#define NODE_ESRAM0_IN_0_LIMIT 0x1030 -#define NODE_ESRAM0_IN_1_LIMIT 0x1034 -#define NODE_ESRAM0_IN_2_LIMIT 0x1038 -#define NODE_ESRAM0_IN_3_LIMIT 0x103C -/* common */ -#define NODE_ESRAM1_2_IN_0_PRIORITY 0x1400 -#define NODE_ESRAM1_2_IN_1_PRIORITY 0x1404 -#define NODE_ESRAM1_2_IN_2_PRIORITY 0x1408 -#define NODE_ESRAM1_2_IN_3_PRIORITY 0x140C -#define NODE_ESRAM1_2_IN_0_ARB_1_LIMIT 0x1430 -#define NODE_ESRAM1_2_IN_0_ARB_2_LIMIT 0x1434 -#define NODE_ESRAM1_2_IN_1_ARB_1_LIMIT 0x1438 -#define NODE_ESRAM1_2_IN_1_ARB_2_LIMIT 0x143C -#define NODE_ESRAM1_2_IN_2_ARB_1_LIMIT 0x1440 -#define NODE_ESRAM1_2_IN_2_ARB_2_LIMIT 0x1444 -#define NODE_ESRAM1_2_IN_3_ARB_1_LIMIT 0x1448 -#define NODE_ESRAM1_2_IN_3_ARB_2_LIMIT 0x144C - -#define NODE_ESRAM3_4_IN_0_PRIORITY 0x1800 -#define NODE_ESRAM3_4_IN_1_PRIORITY 0x1804 -#define NODE_ESRAM3_4_IN_2_PRIORITY 0x1808 -#define NODE_ESRAM3_4_IN_3_PRIORITY 0x180C -#define NODE_ESRAM3_4_IN_0_ARB_1_LIMIT 0x1830 -#define NODE_ESRAM3_4_IN_0_ARB_2_LIMIT 0x1834 -#define NODE_ESRAM3_4_IN_1_ARB_1_LIMIT 0x1838 -#define NODE_ESRAM3_4_IN_1_ARB_2_LIMIT 0x183C -#define NODE_ESRAM3_4_IN_2_ARB_1_LIMIT 0x1840 -#define NODE_ESRAM3_4_IN_2_ARB_2_LIMIT 0x1844 -#define NODE_ESRAM3_4_IN_3_ARB_1_LIMIT 0x1848 -#define NODE_ESRAM3_4_IN_3_ARB_2_LIMIT 0x184C - -static struct { - void __iomem *base; - u32 hibw1_esram_in_pri[3]; - u32 hibw1_esram_in0_arb[3]; - u32 hibw1_esram_in1_arb[3]; - u32 hibw1_esram_in2_arb[3]; - u32 hibw1_ddr_in_prio[3]; - u32 hibw1_ddr_in_limit[3]; - u32 hibw1_ddr_out_prio; - - /* HiBw2 node registers */ - u32 hibw2_esram_in_pri[2]; - u32 hibw2_esram_in0_arblimit[3]; - u32 hibw2_esram_in1_arblimit[3]; - u32 hibw2_ddr_in_prio[4]; - u32 hibw2_ddr_in_limit[4]; - u32 hibw2_ddr_out_prio; - - /* ESRAM node registers */ - u32 esram_in_prio[4]; - u32 esram_in_lim[4]; - u32 esram0_in_prio[4]; - u32 esram0_in_lim[4]; - u32 esram12_in_prio[4]; - u32 esram12_in_arb_lim[8]; - u32 esram34_in_prio[4]; - u32 esram34_in_arb_lim[8]; -} context_icn; - -/** - * u8500_context_save_icn() - save ICN context - * - */ -void u8500_context_save_icn(void) -{ - void __iomem *b = context_icn.base; - - context_icn.hibw1_esram_in_pri[0] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_PRIORITY); - context_icn.hibw1_esram_in_pri[1] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_PRIORITY); - context_icn.hibw1_esram_in_pri[2] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_PRIORITY); - - context_icn.hibw1_esram_in0_arb[0] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); - context_icn.hibw1_esram_in0_arb[1] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); - context_icn.hibw1_esram_in0_arb[2] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); - - context_icn.hibw1_esram_in1_arb[0] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); - context_icn.hibw1_esram_in1_arb[1] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); - context_icn.hibw1_esram_in1_arb[2] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); - - context_icn.hibw1_esram_in2_arb[0] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT); - context_icn.hibw1_esram_in2_arb[1] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT); - context_icn.hibw1_esram_in2_arb[2] = - readl_relaxed(b + NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT); - - context_icn.hibw1_ddr_in_prio[0] = - readl_relaxed(b + NODE_HIBW1_DDR_IN_0_PRIORITY); - context_icn.hibw1_ddr_in_prio[1] = - readl_relaxed(b + NODE_HIBW1_DDR_IN_1_PRIORITY); - context_icn.hibw1_ddr_in_prio[2] = - readl_relaxed(b + NODE_HIBW1_DDR_IN_2_PRIORITY); - - context_icn.hibw1_ddr_in_limit[0] = - readl_relaxed(b + NODE_HIBW1_DDR_IN_0_LIMIT); - context_icn.hibw1_ddr_in_limit[1] = - readl_relaxed(b + NODE_HIBW1_DDR_IN_1_LIMIT); - context_icn.hibw1_ddr_in_limit[2] = - readl_relaxed(b + NODE_HIBW1_DDR_IN_2_LIMIT); - - context_icn.hibw1_ddr_out_prio = - readl_relaxed(b + NODE_HIBW1_DDR_OUT_0_PRIORITY); - - context_icn.hibw2_esram_in_pri[0] = - readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_PRIORITY); - context_icn.hibw2_esram_in_pri[1] = - readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_PRIORITY); - - context_icn.hibw2_esram_in0_arblimit[0] = - readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); - context_icn.hibw2_esram_in0_arblimit[1] = - readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); - context_icn.hibw2_esram_in0_arblimit[2] = - readl_relaxed(b + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); - - context_icn.hibw2_esram_in1_arblimit[0] = - readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); - context_icn.hibw2_esram_in1_arblimit[1] = - readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); - context_icn.hibw2_esram_in1_arblimit[2] = - readl_relaxed(b + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); - - context_icn.hibw2_ddr_in_prio[0] = - readl_relaxed(b + NODE_HIBW2_DDR_IN_0_PRIORITY); - context_icn.hibw2_ddr_in_prio[1] = - readl_relaxed(b + NODE_HIBW2_DDR_IN_1_PRIORITY); - context_icn.hibw2_ddr_in_prio[2] = - readl_relaxed(b + NODE_HIBW2_DDR_IN_2_PRIORITY); - - context_icn.hibw2_ddr_in_limit[0] = - readl_relaxed(b + NODE_HIBW2_DDR_IN_0_LIMIT); - context_icn.hibw2_ddr_in_limit[1] = - readl_relaxed(b + NODE_HIBW2_DDR_IN_1_LIMIT); - - context_icn.hibw2_ddr_in_limit[2] = - readl_relaxed(b + NODE_HIBW2_DDR_IN_2_LIMIT); - - context_icn.hibw2_ddr_out_prio = - readl_relaxed(b + NODE_HIBW2_DDR_OUT_0_PRIORITY); - - context_icn.esram0_in_prio[0] = - readl_relaxed(b + NODE_ESRAM0_IN_0_PRIORITY); - context_icn.esram0_in_prio[1] = - readl_relaxed(b + NODE_ESRAM0_IN_1_PRIORITY); - context_icn.esram0_in_prio[2] = - readl_relaxed(b + NODE_ESRAM0_IN_2_PRIORITY); - context_icn.esram0_in_prio[3] = - readl_relaxed(b + NODE_ESRAM0_IN_3_PRIORITY); - - context_icn.esram0_in_lim[0] = - readl_relaxed(b + NODE_ESRAM0_IN_0_LIMIT); - context_icn.esram0_in_lim[1] = - readl_relaxed(b + NODE_ESRAM0_IN_1_LIMIT); - context_icn.esram0_in_lim[2] = - readl_relaxed(b + NODE_ESRAM0_IN_2_LIMIT); - context_icn.esram0_in_lim[3] = - readl_relaxed(b + NODE_ESRAM0_IN_3_LIMIT); - - context_icn.esram12_in_prio[0] = - readl_relaxed(b + NODE_ESRAM1_2_IN_0_PRIORITY); - context_icn.esram12_in_prio[1] = - readl_relaxed(b + NODE_ESRAM1_2_IN_1_PRIORITY); - context_icn.esram12_in_prio[2] = - readl_relaxed(b + NODE_ESRAM1_2_IN_2_PRIORITY); - context_icn.esram12_in_prio[3] = - readl_relaxed(b + NODE_ESRAM1_2_IN_3_PRIORITY); - - context_icn.esram12_in_arb_lim[0] = - readl_relaxed(b + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); - context_icn.esram12_in_arb_lim[1] = - readl_relaxed(b + NODE_ESRAM1_2_IN_0_ARB_2_LIMIT); - context_icn.esram12_in_arb_lim[2] = - readl_relaxed(b + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); - context_icn.esram12_in_arb_lim[3] = - readl_relaxed(b + NODE_ESRAM1_2_IN_1_ARB_2_LIMIT); - context_icn.esram12_in_arb_lim[4] = - readl_relaxed(b + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); - context_icn.esram12_in_arb_lim[5] = - readl_relaxed(b + NODE_ESRAM1_2_IN_2_ARB_2_LIMIT); - context_icn.esram12_in_arb_lim[6] = - readl_relaxed(b + NODE_ESRAM1_2_IN_3_ARB_1_LIMIT); - context_icn.esram12_in_arb_lim[7] = - readl_relaxed(b + NODE_ESRAM1_2_IN_3_ARB_2_LIMIT); - - context_icn.esram34_in_prio[0] = - readl_relaxed(b + NODE_ESRAM3_4_IN_0_PRIORITY); - context_icn.esram34_in_prio[1] = - readl_relaxed(b + NODE_ESRAM3_4_IN_1_PRIORITY); - context_icn.esram34_in_prio[2] = - readl_relaxed(b + NODE_ESRAM3_4_IN_2_PRIORITY); - context_icn.esram34_in_prio[3] = - readl_relaxed(b + NODE_ESRAM3_4_IN_3_PRIORITY); - - context_icn.esram34_in_arb_lim[0] = - readl_relaxed(b + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); - context_icn.esram34_in_arb_lim[1] = - readl_relaxed(b + NODE_ESRAM3_4_IN_0_ARB_2_LIMIT); - context_icn.esram34_in_arb_lim[2] = - readl_relaxed(b + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); - context_icn.esram34_in_arb_lim[3] = - readl_relaxed(b + NODE_ESRAM3_4_IN_1_ARB_2_LIMIT); - context_icn.esram34_in_arb_lim[4] = - readl_relaxed(b + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); - context_icn.esram34_in_arb_lim[5] = - readl_relaxed(b + NODE_ESRAM3_4_IN_2_ARB_2_LIMIT); - context_icn.esram34_in_arb_lim[6] = - readl_relaxed(b + NODE_ESRAM3_4_IN_3_ARB_1_LIMIT); - context_icn.esram34_in_arb_lim[7] = - readl_relaxed(b + NODE_ESRAM3_4_IN_3_ARB_2_LIMIT); -} - -/** - * u8500_context_restore_icn() - restore ICN context - * - */ -void u8500_context_restore_icn(void) -{ - void __iomem *b = context_icn.base; - - writel_relaxed(context_icn.hibw1_esram_in_pri[0], - b + NODE_HIBW1_ESRAM_IN_0_PRIORITY); - writel_relaxed(context_icn.hibw1_esram_in_pri[1], - b + NODE_HIBW1_ESRAM_IN_1_PRIORITY); - writel_relaxed(context_icn.hibw1_esram_in_pri[2], - b + NODE_HIBW1_ESRAM_IN_2_PRIORITY); - - writel_relaxed(context_icn.hibw1_esram_in0_arb[0], - b + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT); - writel_relaxed(context_icn.hibw1_esram_in0_arb[1], - b + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT); - writel_relaxed(context_icn.hibw1_esram_in0_arb[2], - b + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT); - - writel_relaxed(context_icn.hibw1_esram_in1_arb[0], - b + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT); - writel_relaxed(context_icn.hibw1_esram_in1_arb[1], - b + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT); - writel_relaxed(context_icn.hibw1_esram_in1_arb[2], - b + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT); - - writel_relaxed(context_icn.hibw1_esram_in2_arb[0], - b + NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT); - writel_relaxed(context_icn.hibw1_esram_in2_arb[1], - b + NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT); - writel_relaxed(context_icn.hibw1_esram_in2_arb[2], - b + NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT); - - writel_relaxed(context_icn.hibw1_ddr_in_prio[0], - b + NODE_HIBW1_DDR_IN_0_PRIORITY); - writel_relaxed(context_icn.hibw1_ddr_in_prio[1], - b + NODE_HIBW1_DDR_IN_1_PRIORITY); - writel_relaxed(context_icn.hibw1_ddr_in_prio[2], - b + NODE_HIBW1_DDR_IN_2_PRIORITY); - - writel_relaxed(context_icn.hibw1_ddr_in_limit[0], - b + NODE_HIBW1_DDR_IN_0_LIMIT); - writel_relaxed(context_icn.hibw1_ddr_in_limit[1], - b + NODE_HIBW1_DDR_IN_1_LIMIT); - writel_relaxed(context_icn.hibw1_ddr_in_limit[2], - b + NODE_HIBW1_DDR_IN_2_LIMIT); - - writel_relaxed(context_icn.hibw1_ddr_out_prio, - b + NODE_HIBW1_DDR_OUT_0_PRIORITY); - - writel_relaxed(context_icn.hibw2_esram_in_pri[0], - b + NODE_HIBW2_ESRAM_IN_0_PRIORITY); - writel_relaxed(context_icn.hibw2_esram_in_pri[1], - b + NODE_HIBW2_ESRAM_IN_1_PRIORITY); - - writel_relaxed(context_icn.hibw2_esram_in0_arblimit[0], - b + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT); - writel_relaxed(context_icn.hibw2_esram_in0_arblimit[1], - b + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT); - writel_relaxed(context_icn.hibw2_esram_in0_arblimit[2], - b + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT); - - writel_relaxed(context_icn.hibw2_esram_in1_arblimit[0], - b + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT); - writel_relaxed(context_icn.hibw2_esram_in1_arblimit[1], - b + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT); - writel_relaxed(context_icn.hibw2_esram_in1_arblimit[2], - b + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT); - - writel_relaxed(context_icn.hibw2_ddr_in_prio[0], - b + NODE_HIBW2_DDR_IN_0_PRIORITY); - writel_relaxed(context_icn.hibw2_ddr_in_prio[1], - b + NODE_HIBW2_DDR_IN_1_PRIORITY); - writel_relaxed(context_icn.hibw2_ddr_in_prio[2], - b + NODE_HIBW2_DDR_IN_2_PRIORITY); - writel_relaxed(context_icn.hibw2_ddr_in_limit[0], - b + NODE_HIBW2_DDR_IN_0_LIMIT); - writel_relaxed(context_icn.hibw2_ddr_in_limit[1], - b + NODE_HIBW2_DDR_IN_1_LIMIT); - writel_relaxed(context_icn.hibw2_ddr_in_limit[2], - b + NODE_HIBW2_DDR_IN_2_LIMIT); - writel_relaxed(context_icn.hibw2_ddr_out_prio, - b + NODE_HIBW2_DDR_OUT_0_PRIORITY); - - writel_relaxed(context_icn.esram0_in_prio[0], - b + NODE_ESRAM0_IN_0_PRIORITY); - writel_relaxed(context_icn.esram0_in_prio[1], - b + NODE_ESRAM0_IN_1_PRIORITY); - writel_relaxed(context_icn.esram0_in_prio[2], - b + NODE_ESRAM0_IN_2_PRIORITY); - writel_relaxed(context_icn.esram0_in_prio[3], - b + NODE_ESRAM0_IN_3_PRIORITY); - - writel_relaxed(context_icn.esram0_in_lim[0], - b + NODE_ESRAM0_IN_0_LIMIT); - writel_relaxed(context_icn.esram0_in_lim[1], - b + NODE_ESRAM0_IN_1_LIMIT); - writel_relaxed(context_icn.esram0_in_lim[2], - b + NODE_ESRAM0_IN_2_LIMIT); - writel_relaxed(context_icn.esram0_in_lim[3], - b + NODE_ESRAM0_IN_3_LIMIT); - - writel_relaxed(context_icn.esram12_in_prio[0], - b + NODE_ESRAM1_2_IN_0_PRIORITY); - writel_relaxed(context_icn.esram12_in_prio[1], - b + NODE_ESRAM1_2_IN_1_PRIORITY); - writel_relaxed(context_icn.esram12_in_prio[2], - b + NODE_ESRAM1_2_IN_2_PRIORITY); - writel_relaxed(context_icn.esram12_in_prio[3], - b + NODE_ESRAM1_2_IN_3_PRIORITY); - - writel_relaxed(context_icn.esram12_in_arb_lim[0], - b + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT); - writel_relaxed(context_icn.esram12_in_arb_lim[1], - b + NODE_ESRAM1_2_IN_0_ARB_2_LIMIT); - writel_relaxed(context_icn.esram12_in_arb_lim[2], - b + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT); - writel_relaxed(context_icn.esram12_in_arb_lim[3], - b + NODE_ESRAM1_2_IN_1_ARB_2_LIMIT); - writel_relaxed(context_icn.esram12_in_arb_lim[4], - b + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT); - writel_relaxed(context_icn.esram12_in_arb_lim[5], - b + NODE_ESRAM1_2_IN_2_ARB_2_LIMIT); - writel_relaxed(context_icn.esram12_in_arb_lim[6], - b + NODE_ESRAM1_2_IN_3_ARB_1_LIMIT); - writel_relaxed(context_icn.esram12_in_arb_lim[7], - b + NODE_ESRAM1_2_IN_3_ARB_2_LIMIT); - - writel_relaxed(context_icn.esram34_in_prio[0], - b + NODE_ESRAM3_4_IN_0_PRIORITY); - writel_relaxed(context_icn.esram34_in_prio[1], - b + NODE_ESRAM3_4_IN_1_PRIORITY); - writel_relaxed(context_icn.esram34_in_prio[2], - b + NODE_ESRAM3_4_IN_2_PRIORITY); - writel_relaxed(context_icn.esram34_in_prio[3], - b + NODE_ESRAM3_4_IN_3_PRIORITY); - - writel_relaxed(context_icn.esram34_in_arb_lim[0], - b + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT); - writel_relaxed(context_icn.esram34_in_arb_lim[1], - b + NODE_ESRAM3_4_IN_0_ARB_2_LIMIT); - writel_relaxed(context_icn.esram34_in_arb_lim[2], - b + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT); - writel_relaxed(context_icn.esram34_in_arb_lim[3], - b + NODE_ESRAM3_4_IN_1_ARB_2_LIMIT); - writel_relaxed(context_icn.esram34_in_arb_lim[4], - b + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT); - writel_relaxed(context_icn.esram34_in_arb_lim[5], - b + NODE_ESRAM3_4_IN_2_ARB_2_LIMIT); - writel_relaxed(context_icn.esram34_in_arb_lim[6], - b + NODE_ESRAM3_4_IN_3_ARB_1_LIMIT); - writel_relaxed(context_icn.esram34_in_arb_lim[7], - b + NODE_ESRAM3_4_IN_3_ARB_2_LIMIT); -} - -void u8500_context_init(void) -{ - context_icn.base = ioremap(U8500_ICN_BASE, SZ_8K); -} diff --git a/arch/arm/mach-ux500/pm/context.c b/arch/arm/mach-ux500/pm/context.c deleted file mode 100644 index 7e4687eb6f4..00000000000 --- a/arch/arm/mach-ux500/pm/context.c +++ /dev/null @@ -1,986 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010-2011 - * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>, - * Rickard Andersson <rickard.andersson@stericsson.com>, - * Jonas Aaberg <jonas.aberg@stericsson.com>, - * Sundar Iyer for ST-Ericsson. - * License terms: GNU General Public License (GPL) version 2 - * - */ - -#include <linux/init.h> -#include <linux/io.h> -#include <linux/smp.h> -#include <linux/percpu.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/device.h> -#include <linux/notifier.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/gpio/nomadik.h> -#include <asm/hardware/gic.h> - -#include <mach/hardware.h> -#include <mach/irqs.h> -#include <mach/scu.h> - -#include "context.h" -#include "pm.h" -#include "../product.h" - -#define GPIO_NUM_BANKS 9 -#define GPIO_NUM_SAVE_REGISTERS 7 - -/* - * TODO: - * - Use the "UX500*"-macros instead where possible - */ - -#define U8500_BACKUPRAM_SIZE SZ_64K - -#define U8500_PUBLIC_BOOT_ROM_BASE (U8500_BOOT_ROM_BASE + 0x17000) -#define U5500_PUBLIC_BOOT_ROM_BASE (U5500_BOOT_ROM_BASE + 0x18000) - -/* - * Special dedicated addresses in backup RAM. The 5500 addresses are identical - * to the 8500 ones. - */ -#define U8500_EXT_RAM_LOC_BACKUPRAM_ADDR 0x80151FDC -#define U8500_CPU0_CP15_CR_BACKUPRAM_ADDR 0x80151F80 -#define U8500_CPU1_CP15_CR_BACKUPRAM_ADDR 0x80151FA0 - -#define U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR 0x80151FD8 -#define U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR 0x80151FE0 - -#define GIC_DIST_ENABLE_NS 0x0 - -/* 32 interrupts fits in 4 bytes */ -#define GIC_DIST_ENABLE_SET_COMMON_NUM ((DBX500_NR_INTERNAL_IRQS - \ - IRQ_SHPI_START) / 32) -#define GIC_DIST_ENABLE_SET_CPU_NUM (IRQ_SHPI_START / 32) -#define GIC_DIST_ENABLE_SET_SPI0 GIC_DIST_ENABLE_SET -#define GIC_DIST_ENABLE_SET_SPI32 (GIC_DIST_ENABLE_SET + IRQ_SHPI_START / 8) - -#define GIC_DIST_ENABLE_CLEAR_0 GIC_DIST_ENABLE_CLEAR -#define GIC_DIST_ENABLE_CLEAR_32 (GIC_DIST_ENABLE_CLEAR + 4) -#define GIC_DIST_ENABLE_CLEAR_64 (GIC_DIST_ENABLE_CLEAR + 8) -#define GIC_DIST_ENABLE_CLEAR_96 (GIC_DIST_ENABLE_CLEAR + 12) -#define GIC_DIST_ENABLE_CLEAR_128 (GIC_DIST_ENABLE_CLEAR + 16) - -#define GIC_DIST_PRI_COMMON_NUM ((DBX500_NR_INTERNAL_IRQS - IRQ_SHPI_START) / 4) -#define GIC_DIST_PRI_CPU_NUM (IRQ_SHPI_START / 4) -#define GIC_DIST_PRI_SPI0 GIC_DIST_PRI -#define GIC_DIST_PRI_SPI32 (GIC_DIST_PRI + IRQ_SHPI_START) - -#define GIC_DIST_SPI_TARGET_COMMON_NUM ((DBX500_NR_INTERNAL_IRQS - \ - IRQ_SHPI_START) / 4) -#define GIC_DIST_SPI_TARGET_CPU_NUM (IRQ_SHPI_START / 4) -#define GIC_DIST_SPI_TARGET_SPI0 GIC_DIST_TARGET -#define GIC_DIST_SPI_TARGET_SPI32 (GIC_DIST_TARGET + IRQ_SHPI_START) - -/* 16 interrupts per 4 bytes */ -#define GIC_DIST_CONFIG_COMMON_NUM ((DBX500_NR_INTERNAL_IRQS - IRQ_SHPI_START) \ - / 16) -#define GIC_DIST_CONFIG_CPU_NUM (IRQ_SHPI_START / 16) -#define GIC_DIST_CONFIG_SPI0 GIC_DIST_CONFIG -#define GIC_DIST_CONFIG_SPI32 (GIC_DIST_CONFIG + IRQ_SHPI_START / 4) - -/* TODO! Move STM reg offsets to suitable place */ -#define STM_CR_OFFSET 0x00 -#define STM_MMC_OFFSET 0x08 -#define STM_TER_OFFSET 0x10 - -#define U5500_PRCMU_DBG_PWRCTRL (U5500_PRCMU_BASE + 0x4AC) -#define PRCMU_DBG_PWRCTRL_A9DBGCLKEN (1 << 4) - -#define TPIU_PORT_SIZE 0x4 -#define TPIU_TRIGGER_COUNTER 0x104 -#define TPIU_TRIGGER_MULTIPLIER 0x108 -#define TPIU_CURRENT_TEST_PATTERN 0x204 -#define TPIU_TEST_PATTERN_REPEAT 0x208 -#define TPIU_FORMATTER 0x304 -#define TPIU_FORMATTER_SYNC 0x308 -#define TPIU_LOCK_ACCESS_REGISTER 0xFB0 - -#define TPIU_UNLOCK_CODE 0xc5acce55 - -#define SCU_FILTER_STARTADDR 0x40 -#define SCU_FILTER_ENDADDR 0x44 -#define SCU_ACCESS_CTRL_SAC 0x50 - -/* - * Periph clock cluster context - */ -#define PRCC_BCK_EN 0x00 -#define PRCC_KCK_EN 0x08 -#define PRCC_BCK_STATUS 0x10 -#define PRCC_KCK_STATUS 0x14 - -/* The context of the Trace Port Interface Unit (TPIU) */ -static struct { - void __iomem *base; - u32 port_size; - u32 trigger_counter; - u32 trigger_multiplier; - u32 current_test_pattern; - u32 test_pattern_repeat; - u32 formatter; - u32 formatter_sync; -} context_tpiu; - -static struct { - void __iomem *base; - u32 cr; - u32 mmc; - u32 ter; -} context_stm_ape; - -struct context_gic_cpu { - void __iomem *base; - u32 ctrl; - u32 primask; - u32 binpoint; -}; -static DEFINE_PER_CPU(struct context_gic_cpu, context_gic_cpu); - -static struct { - void __iomem *base; - u32 ns; - u32 enable_set[GIC_DIST_ENABLE_SET_COMMON_NUM]; /* IRQ 32 to 160 */ - u32 priority_level[GIC_DIST_PRI_COMMON_NUM]; - u32 spi_target[GIC_DIST_SPI_TARGET_COMMON_NUM]; - u32 config[GIC_DIST_CONFIG_COMMON_NUM]; -} context_gic_dist_common; - -struct context_gic_dist_cpu { - void __iomem *base; - u32 enable_set[GIC_DIST_ENABLE_SET_CPU_NUM]; /* IRQ 0 to 31 */ - u32 priority_level[GIC_DIST_PRI_CPU_NUM]; - u32 spi_target[GIC_DIST_SPI_TARGET_CPU_NUM]; - u32 config[GIC_DIST_CONFIG_CPU_NUM]; -}; -static DEFINE_PER_CPU(struct context_gic_dist_cpu, context_gic_dist_cpu); - -static struct { - void __iomem *base; - u32 ctrl; - u32 cpu_pwrstatus; - u32 inv_all_nonsecure; - u32 filter_start_addr; - u32 filter_end_addr; - u32 access_ctrl_sac; -} context_scu; - -#define UX500_NR_PRCC_BANKS 5 -static struct { - void __iomem *base; - struct clk *clk; - u32 bus_clk; - u32 kern_clk; -} context_prcc[UX500_NR_PRCC_BANKS]; - -static u32 backup_sram_storage[NR_CPUS] = { - IO_ADDRESS(U8500_CPU0_CP15_CR_BACKUPRAM_ADDR), - IO_ADDRESS(U8500_CPU1_CP15_CR_BACKUPRAM_ADDR), -}; - -static u32 gpio_bankaddr[GPIO_NUM_BANKS] = {IO_ADDRESS(U8500_GPIOBANK0_BASE), - IO_ADDRESS(U8500_GPIOBANK1_BASE), - IO_ADDRESS(U8500_GPIOBANK2_BASE), - IO_ADDRESS(U8500_GPIOBANK3_BASE), - IO_ADDRESS(U8500_GPIOBANK4_BASE), - IO_ADDRESS(U8500_GPIOBANK5_BASE), - IO_ADDRESS(U8500_GPIOBANK6_BASE), - IO_ADDRESS(U8500_GPIOBANK7_BASE), - IO_ADDRESS(U8500_GPIOBANK8_BASE) -}; - -static u32 gpio_save[GPIO_NUM_BANKS][GPIO_NUM_SAVE_REGISTERS]; - -/* - * Stacks and stack pointers - */ -static DEFINE_PER_CPU(u32[128], varm_registers_backup_stack); -static DEFINE_PER_CPU(u32 *, varm_registers_pointer); - -static DEFINE_PER_CPU(u32[128], varm_cp15_backup_stack); -static DEFINE_PER_CPU(u32 *, varm_cp15_pointer); - - -static ATOMIC_NOTIFIER_HEAD(context_ape_notifier_list); -static ATOMIC_NOTIFIER_HEAD(context_arm_notifier_list); - -/* - * Register a simple callback for handling vape context save/restore - */ -int context_ape_notifier_register(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&context_ape_notifier_list, nb); -} -EXPORT_SYMBOL(context_ape_notifier_register); - -/* - * Remove a previously registered callback - */ -int context_ape_notifier_unregister(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&context_ape_notifier_list, - nb); -} -EXPORT_SYMBOL(context_ape_notifier_unregister); - -/* - * Register a simple callback for handling varm context save/restore - */ -int context_arm_notifier_register(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&context_arm_notifier_list, nb); -} -EXPORT_SYMBOL(context_arm_notifier_register); - -/* - * Remove a previously registered callback - */ -int context_arm_notifier_unregister(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&context_arm_notifier_list, - nb); -} -EXPORT_SYMBOL(context_arm_notifier_unregister); - -static void save_prcc(void) -{ - int i; - - for (i = 0; i < UX500_NR_PRCC_BANKS; i++) { - clk_enable(context_prcc[i].clk); - - context_prcc[i].bus_clk = - readl(context_prcc[i].base + PRCC_BCK_STATUS); - context_prcc[i].kern_clk = - readl(context_prcc[i].base + PRCC_KCK_STATUS); - - clk_disable(context_prcc[i].clk); - } -} - -static void restore_prcc(void) -{ - int i; - - for (i = 0; i < UX500_NR_PRCC_BANKS; i++) { - clk_enable(context_prcc[i].clk); - - writel(context_prcc[i].bus_clk, - context_prcc[i].base + PRCC_BCK_EN); - writel(context_prcc[i].kern_clk, - context_prcc[i].base + PRCC_KCK_EN); - - clk_disable(context_prcc[i].clk); - } -} - -static void save_stm_ape(void) -{ - /* - * TODO: Check with PRCMU developers how STM is handled by PRCMU - * firmware. According to DB5500 design spec there is a "flush" - * mechanism supposed to be used by the PRCMU before power down, - * PRCMU fw might save/restore the following three registers - * at the same time. - */ - context_stm_ape.cr = readl(context_stm_ape.base + - STM_CR_OFFSET); - context_stm_ape.mmc = readl(context_stm_ape.base + - STM_MMC_OFFSET); - context_stm_ape.ter = readl(context_stm_ape.base + - STM_TER_OFFSET); -} - -static void restore_stm_ape(void) -{ - writel(context_stm_ape.ter, - context_stm_ape.base + STM_TER_OFFSET); - writel(context_stm_ape.mmc, - context_stm_ape.base + STM_MMC_OFFSET); - writel(context_stm_ape.cr, - context_stm_ape.base + STM_CR_OFFSET); -} - -static bool tpiu_clocked(void) -{ -#ifdef CONFIG_UX500_DEBUG_NO_LAUTERBACH - return false; -#else - if (cpu_is_u5500()) - return readl_relaxed(__io_address(U5500_PRCMU_DBG_PWRCTRL)) - & PRCMU_DBG_PWRCTRL_A9DBGCLKEN; - - if (cpu_is_u8500()) - return ux500_jtag_enabled(); - - return true; -#endif -} - -/* - * Save the context of the Trace Port Interface Unit (TPIU). - * Saving/restoring is needed for the PTM tracing to work together - * with the sleep states ApSleep and ApDeepSleep. - */ -static void save_tpiu(void) -{ - if (!tpiu_clocked()) - return; - - context_tpiu.port_size = readl(context_tpiu.base + - TPIU_PORT_SIZE); - context_tpiu.trigger_counter = readl(context_tpiu.base + - TPIU_TRIGGER_COUNTER); - context_tpiu.trigger_multiplier = readl(context_tpiu.base + - TPIU_TRIGGER_MULTIPLIER); - context_tpiu.current_test_pattern = readl(context_tpiu.base + - TPIU_CURRENT_TEST_PATTERN); - context_tpiu.test_pattern_repeat = readl(context_tpiu.base + - TPIU_TEST_PATTERN_REPEAT); - context_tpiu.formatter = readl(context_tpiu.base + - TPIU_FORMATTER); - context_tpiu.formatter_sync = readl(context_tpiu.base + - TPIU_FORMATTER_SYNC); -} - -/* - * Restore the context of the Trace Port Interface Unit (TPIU). - * Saving/restoring is needed for the PTM tracing to work together - * with the sleep states ApSleep and ApDeepSleep. - */ -static void restore_tpiu(void) -{ - if (!tpiu_clocked()) - return; - - writel(TPIU_UNLOCK_CODE, - context_tpiu.base + TPIU_LOCK_ACCESS_REGISTER); - - writel(context_tpiu.port_size, - context_tpiu.base + TPIU_PORT_SIZE); - writel(context_tpiu.trigger_counter, - context_tpiu.base + TPIU_TRIGGER_COUNTER); - writel(context_tpiu.trigger_multiplier, - context_tpiu.base + TPIU_TRIGGER_MULTIPLIER); - writel(context_tpiu.current_test_pattern, - context_tpiu.base + TPIU_CURRENT_TEST_PATTERN); - writel(context_tpiu.test_pattern_repeat, - context_tpiu.base + TPIU_TEST_PATTERN_REPEAT); - writel(context_tpiu.formatter, - context_tpiu.base + TPIU_FORMATTER); - writel(context_tpiu.formatter_sync, - context_tpiu.base + TPIU_FORMATTER_SYNC); -} - -/* - * Save GIC CPU IF registers - * - * This is per cpu so it needs to be called for each one. - */ - -static void save_gic_if_cpu(struct context_gic_cpu *c_gic_cpu) -{ - c_gic_cpu->ctrl = readl_relaxed(c_gic_cpu->base + GIC_CPU_CTRL); - c_gic_cpu->primask = readl_relaxed(c_gic_cpu->base + GIC_CPU_PRIMASK); - c_gic_cpu->binpoint = readl_relaxed(c_gic_cpu->base + GIC_CPU_BINPOINT); -} - -/* - * Restore GIC CPU IF registers - * - * This is per cpu so it needs to be called for each one. - */ -static void restore_gic_if_cpu(struct context_gic_cpu *c_gic_cpu) -{ - writel_relaxed(c_gic_cpu->ctrl, c_gic_cpu->base + GIC_CPU_CTRL); - writel_relaxed(c_gic_cpu->primask, c_gic_cpu->base + GIC_CPU_PRIMASK); - writel_relaxed(c_gic_cpu->binpoint, c_gic_cpu->base + GIC_CPU_BINPOINT); -} - -/* - * Save GIC Distributor Common registers - * - * This context is common. Only one CPU needs to call. - * - * Save SPI (Shared Peripheral Interrupt) settings, IRQ 32-159. - */ - -static void save_gic_dist_common(void) -{ - int i; - - context_gic_dist_common.ns = readl_relaxed(context_gic_dist_common.base - + GIC_DIST_ENABLE_NS); - - for (i = 0; i < GIC_DIST_ENABLE_SET_COMMON_NUM; i++) - context_gic_dist_common.enable_set[i] = - readl_relaxed(context_gic_dist_common.base + - GIC_DIST_ENABLE_SET_SPI32 + i * 4); - - for (i = 0; i < GIC_DIST_PRI_COMMON_NUM; i++) - context_gic_dist_common.priority_level[i] = - readl_relaxed(context_gic_dist_common.base + - GIC_DIST_PRI_SPI32 + i * 4); - - for (i = 0; i < GIC_DIST_SPI_TARGET_COMMON_NUM; i++) - context_gic_dist_common.spi_target[i] = - readl_relaxed(context_gic_dist_common.base + - GIC_DIST_SPI_TARGET_SPI32 + i * 4); - - for (i = 0; i < GIC_DIST_CONFIG_COMMON_NUM; i++) - context_gic_dist_common.config[i] = - readl_relaxed(context_gic_dist_common.base + - GIC_DIST_CONFIG_SPI32 + i * 4); -} - -/* - * Restore GIC Distributor Common registers - * - * This context is common. Only one CPU needs to call. - * - * Save SPI (Shared Peripheral Interrupt) settings, IRQ 32-159. - */ -static void restore_gic_dist_common(void) -{ - - int i; - - for (i = 0; i < GIC_DIST_CONFIG_COMMON_NUM; i++) - writel_relaxed(context_gic_dist_common.config[i], - context_gic_dist_common.base + - GIC_DIST_CONFIG_SPI32 + i * 4); - - for (i = 0; i < GIC_DIST_SPI_TARGET_COMMON_NUM; i++) - writel_relaxed(context_gic_dist_common.spi_target[i], - context_gic_dist_common.base + - GIC_DIST_SPI_TARGET_SPI32 + i * 4); - - for (i = 0; i < GIC_DIST_PRI_COMMON_NUM; i++) - writel_relaxed(context_gic_dist_common.priority_level[i], - context_gic_dist_common.base + - GIC_DIST_PRI_SPI32 + i * 4); - - for (i = 0; i < GIC_DIST_ENABLE_SET_COMMON_NUM; i++) - writel_relaxed(context_gic_dist_common.enable_set[i], - context_gic_dist_common.base + - GIC_DIST_ENABLE_SET_SPI32 + i * 4); - - writel_relaxed(context_gic_dist_common.ns, - context_gic_dist_common.base + GIC_DIST_ENABLE_NS); -} - - - -/* - * Save GIC Dist CPU registers - * - * This needs to be called by all cpu:s which will not call - * save_gic_dist_common(). Only the registers of the GIC which are - * banked will be saved. - */ -static void save_gic_dist_cpu(struct context_gic_dist_cpu *c_gic) -{ - int i; - - for (i = 0; i < GIC_DIST_ENABLE_SET_CPU_NUM; i++) - c_gic->enable_set[i] = - readl_relaxed(c_gic->base + - GIC_DIST_ENABLE_SET_SPI0 + i * 4); - - for (i = 0; i < GIC_DIST_PRI_CPU_NUM; i++) - c_gic->priority_level[i] = - readl_relaxed(c_gic->base + - GIC_DIST_PRI_SPI0 + i * 4); - - for (i = 0; i < GIC_DIST_SPI_TARGET_CPU_NUM; i++) - c_gic->spi_target[i] = - readl_relaxed(c_gic->base + - GIC_DIST_SPI_TARGET_SPI0 + i * 4); - - for (i = 0; i < GIC_DIST_CONFIG_CPU_NUM; i++) - c_gic->config[i] = - readl_relaxed(c_gic->base + - GIC_DIST_CONFIG_SPI0 + i * 4); -} - -/* - * Restore GIC Dist CPU registers - * - * This needs to be called by all cpu:s which will not call - * restore_gic_dist_common(). Only the registers of the GIC which are - * banked will be saved. - */ -static void restore_gic_dist_cpu(struct context_gic_dist_cpu *c_gic) -{ - - int i; - - for (i = 0; i < GIC_DIST_CONFIG_CPU_NUM; i++) - writel_relaxed(c_gic->config[i], - c_gic->base + - GIC_DIST_CONFIG_SPI0 + i * 4); - - for (i = 0; i < GIC_DIST_SPI_TARGET_CPU_NUM; i++) - writel_relaxed(c_gic->spi_target[i], - c_gic->base + - GIC_DIST_SPI_TARGET_SPI0 + i * 4); - - for (i = 0; i < GIC_DIST_PRI_CPU_NUM; i++) - writel_relaxed(c_gic->priority_level[i], - c_gic->base + - GIC_DIST_PRI_SPI0 + i * 4); - - for (i = 0; i < GIC_DIST_ENABLE_SET_CPU_NUM; i++) - writel_relaxed(c_gic->enable_set[i], - c_gic->base + - GIC_DIST_ENABLE_SET_SPI0 + i * 4); -} - -/* - * Disable interrupts that are not necessary - * to have turned on during ApDeepSleep. - */ -void context_gic_dist_disable_unneeded_irqs(void) -{ - - writel(0xffffffff, - context_gic_dist_common.base + - GIC_DIST_ENABLE_CLEAR_0); - - writel(0xffffffff, - context_gic_dist_common.base + - GIC_DIST_ENABLE_CLEAR_32); - - /* Leave PRCMU IRQ 0 and 1 enabled */ - writel(0xffff3fff, - context_gic_dist_common.base + - GIC_DIST_ENABLE_CLEAR_64); - - writel(0xffffffff, - context_gic_dist_common.base + - GIC_DIST_ENABLE_CLEAR_96); - - writel(0xffffffff, - context_gic_dist_common.base + - GIC_DIST_ENABLE_CLEAR_128); - -} - -static void save_scu(void) -{ - context_scu.ctrl = - readl_relaxed(context_scu.base + SCU_CTRL); - context_scu.cpu_pwrstatus = - readl_relaxed(context_scu.base + SCU_CPU_STATUS); - context_scu.inv_all_nonsecure = - readl_relaxed(context_scu.base + SCU_INVALIDATE); - context_scu.filter_start_addr = - readl_relaxed(context_scu.base + SCU_FILTER_STARTADDR); - context_scu.filter_end_addr = - readl_relaxed(context_scu.base + SCU_FILTER_ENDADDR); - context_scu.access_ctrl_sac = - readl_relaxed(context_scu.base + SCU_ACCESS_CTRL_SAC); -} - -static void restore_scu(void) -{ - writel_relaxed(context_scu.ctrl, - context_scu.base + SCU_CTRL); - writel_relaxed(context_scu.cpu_pwrstatus, - context_scu.base + SCU_CPU_STATUS); - writel_relaxed(context_scu.inv_all_nonsecure, - context_scu.base + SCU_INVALIDATE); - writel_relaxed(context_scu.filter_start_addr, - context_scu.base + SCU_FILTER_STARTADDR); - writel_relaxed(context_scu.filter_end_addr, - context_scu.base + SCU_FILTER_ENDADDR); - writel_relaxed(context_scu.access_ctrl_sac, - context_scu.base + SCU_ACCESS_CTRL_SAC); -} - -/* - * Save VAPE context - */ -void context_vape_save(void) -{ - atomic_notifier_call_chain(&context_ape_notifier_list, - CONTEXT_APE_SAVE, NULL); - - if (cpu_is_u5500()) - u5500_context_save_icn(); - if (cpu_is_u8500()) - u8500_context_save_icn(); - - save_stm_ape(); - - save_tpiu(); - - save_prcc(); - -} - -/* - * Restore VAPE context - */ -void context_vape_restore(void) -{ - restore_prcc(); - - restore_tpiu(); - - restore_stm_ape(); - - if (cpu_is_u5500()) - u5500_context_restore_icn(); - if (cpu_is_u8500()) - u8500_context_restore_icn(); - - atomic_notifier_call_chain(&context_ape_notifier_list, - CONTEXT_APE_RESTORE, NULL); -} - -/* - * Save GPIO registers that might be modified - * for power save reasons. - */ -void context_gpio_save(void) -{ - int i; - - for (i = 0; i < GPIO_NUM_BANKS; i++) { - gpio_save[i][0] = readl(gpio_bankaddr[i] + NMK_GPIO_AFSLA); - gpio_save[i][1] = readl(gpio_bankaddr[i] + NMK_GPIO_AFSLB); - gpio_save[i][2] = readl(gpio_bankaddr[i] + NMK_GPIO_PDIS); - gpio_save[i][3] = readl(gpio_bankaddr[i] + NMK_GPIO_DIR); - gpio_save[i][4] = readl(gpio_bankaddr[i] + NMK_GPIO_DAT); - gpio_save[i][6] = readl(gpio_bankaddr[i] + NMK_GPIO_SLPC); - } -} - -/* - * Restore GPIO registers that might be modified - * for power save reasons. - */ -void context_gpio_restore(void) -{ - int i; - u32 output_state; - u32 pull_up; - u32 pull_down; - u32 pull; - - for (i = 0; i < GPIO_NUM_BANKS; i++) { - writel(gpio_save[i][2], gpio_bankaddr[i] + NMK_GPIO_PDIS); - - writel(gpio_save[i][3], gpio_bankaddr[i] + NMK_GPIO_DIR); - - /* Set the high outputs. outpute_state = GPIO_DIR & GPIO_DAT */ - output_state = gpio_save[i][3] & gpio_save[i][4]; - writel(output_state, gpio_bankaddr[i] + NMK_GPIO_DATS); - - /* - * Set the low outputs. - * outpute_state = ~(GPIO_DIR & GPIO_DAT) & GPIO_DIR - */ - output_state = ~(gpio_save[i][3] & gpio_save[i][4]) & - gpio_save[i][3]; - writel(output_state, gpio_bankaddr[i] + NMK_GPIO_DATC); - - /* - * Restore pull up/down. - * Only write pull up/down settings on inputs where - * PDIS is not set. - * pull = (~GPIO_DIR & ~GPIO_PDIS) - */ - pull = (~gpio_save[i][3] & ~gpio_save[i][2]); - nmk_gpio_read_pull(i, &pull_up); - - pull_down = pull & ~pull_up; - pull_up = pull & pull_up; - /* Set pull ups */ - writel(pull_up, gpio_bankaddr[i] + NMK_GPIO_DATS); - /* Set pull downs */ - writel(pull_down, gpio_bankaddr[i] + NMK_GPIO_DATC); - - writel(gpio_save[i][6], gpio_bankaddr[i] + NMK_GPIO_SLPC); - - } - -} - -/* - * Restore GPIO mux registers that might be modified - * for power save reasons. - */ -void context_gpio_restore_mux(void) -{ - int i; - - /* Change mux settings */ - for (i = 0; i < GPIO_NUM_BANKS; i++) { - writel(gpio_save[i][0], gpio_bankaddr[i] + NMK_GPIO_AFSLA); - writel(gpio_save[i][1], gpio_bankaddr[i] + NMK_GPIO_AFSLB); - } -} - -/* - * Safe sequence used to switch IOs between GPIO and Alternate-C mode: - * - Save SLPM registers (Not done.) - * - Set SLPM=0 for the IOs you want to switch. (We assume that all - * SLPM registers already are 0 except for the ones that wants to - * have the mux connected in sleep (e.g modem STM)). - * - Configure the GPIO registers for the IOs that are being switched - * - Set IOFORCE=1 - * - Modify the AFLSA/B registers for the IOs that are being switched - * - Set IOFORCE=0 - * - Restore SLPM registers (Not done.) - * - Any spurious wake up event during switch sequence to be ignored - * and cleared - */ -void context_gpio_mux_safe_switch(bool begin) -{ - int i; - - static u32 rwimsc[GPIO_NUM_BANKS]; - static u32 fwimsc[GPIO_NUM_BANKS]; - - if (begin) { - for (i = 0; i < GPIO_NUM_BANKS; i++) { - /* Save registers */ - rwimsc[i] = readl(gpio_bankaddr[i] + NMK_GPIO_RWIMSC); - fwimsc[i] = readl(gpio_bankaddr[i] + NMK_GPIO_FWIMSC); - - /* Prevent spurious wakeups */ - writel(0, gpio_bankaddr[i] + NMK_GPIO_RWIMSC); - writel(0, gpio_bankaddr[i] + NMK_GPIO_FWIMSC); - } - - ux500_pm_prcmu_set_ioforce(true); - } else { - ux500_pm_prcmu_set_ioforce(false); - - /* Restore wake up settings */ - for (i = 0; i < GPIO_NUM_BANKS; i++) { - writel(rwimsc[i], gpio_bankaddr[i] + NMK_GPIO_RWIMSC); - writel(fwimsc[i], gpio_bankaddr[i] + NMK_GPIO_FWIMSC); - } - - } - -} - -/* - * Save common - * - * This function must be called once for all cores before going to deep sleep. - */ -void context_varm_save_common(void) -{ - atomic_notifier_call_chain(&context_arm_notifier_list, - CONTEXT_ARM_COMMON_SAVE, NULL); - - /* Save common parts */ - save_gic_dist_common(); - save_scu(); -} - -/* - * Restore common - * - * This function must be called once for all cores when waking up from deep - * sleep. - */ -void context_varm_restore_common(void) -{ - /* Restore common parts */ - restore_scu(); - restore_gic_dist_common(); - - atomic_notifier_call_chain(&context_arm_notifier_list, - CONTEXT_ARM_COMMON_RESTORE, NULL); -} - -/* - * Save core - * - * This function must be called once for each cpu core before going to deep - * sleep. - */ -void context_varm_save_core(void) -{ - - int cpu = smp_processor_id(); - - atomic_notifier_call_chain(&context_arm_notifier_list, - CONTEXT_ARM_CORE_SAVE, NULL); - - per_cpu(varm_cp15_pointer, cpu) = per_cpu(varm_cp15_backup_stack, cpu); - - /* Save core */ - save_gic_if_cpu(&per_cpu(context_gic_cpu, cpu)); - save_gic_dist_cpu(&per_cpu(context_gic_dist_cpu, cpu)); - context_save_cp15_registers(&per_cpu(varm_cp15_pointer, cpu)); -} - -/* - * Restore core - * - * This function must be called once for each cpu core when waking up from - * deep sleep. - */ -void context_varm_restore_core(void) -{ - int cpu = smp_processor_id(); - - /* Restore core */ - context_restore_cp15_registers(&per_cpu(varm_cp15_pointer, cpu)); - restore_gic_dist_cpu(&per_cpu(context_gic_dist_cpu, cpu)); - restore_gic_if_cpu(&per_cpu(context_gic_cpu, cpu)); - - atomic_notifier_call_chain(&context_arm_notifier_list, - CONTEXT_ARM_CORE_RESTORE, NULL); - -} - -/* - * Save CPU registers - * - * This function saves ARM registers. - */ -void context_save_cpu_registers(void) -{ - int cpu = smp_processor_id(); - - per_cpu(varm_registers_pointer, cpu) = - per_cpu(varm_registers_backup_stack, cpu); - context_save_arm_registers(&per_cpu(varm_registers_pointer, cpu)); -} - -/* - * Restore CPU registers - * - * This function restores ARM registers. - */ -void context_restore_cpu_registers(void) -{ - int cpu = smp_processor_id(); - - context_restore_arm_registers(&per_cpu(varm_registers_pointer, cpu)); -} - -/* - * This function stores CP15 registers related to cache and mmu - * in backup SRAM. It also stores stack pointer, CPSR - * and return address for the PC in backup SRAM and - * does wait for interrupt. - */ -void context_save_to_sram_and_wfi(bool cleanL2cache) -{ - int cpu = smp_processor_id(); - - context_save_to_sram_and_wfi_internal(backup_sram_storage[cpu], - cleanL2cache); -} - -static int __init context_init(void) -{ - int i; - void __iomem *ux500_backup_ptr; - - /* allocate backup pointer for RAM data */ - ux500_backup_ptr = (void *)__get_free_pages(GFP_KERNEL, - get_order(U8500_BACKUPRAM_SIZE)); - - if (!ux500_backup_ptr) { - pr_warning("context: could not allocate backup memory\n"); - return -ENOMEM; - } - - /* - * ROM code addresses to store backup contents, - * pass the physical address of back up to ROM code - */ - writel(virt_to_phys(ux500_backup_ptr), - IO_ADDRESS(U8500_EXT_RAM_LOC_BACKUPRAM_ADDR)); - - - if (cpu_is_u5500()) { - writel(IO_ADDRESS(U5500_PUBLIC_BOOT_ROM_BASE), - IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); - - writel(IO_ADDRESS(U5500_PUBLIC_BOOT_ROM_BASE), - IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); - - context_tpiu.base = ioremap(U5500_TPIU_BASE, SZ_4K); - context_stm_ape.base = ioremap(U5500_STM_REG_BASE, SZ_4K); - context_scu.base = ioremap(U5500_SCU_BASE, SZ_4K); - - context_prcc[0].base = ioremap(U5500_CLKRST1_BASE, SZ_4K); - context_prcc[1].base = ioremap(U5500_CLKRST2_BASE, SZ_4K); - context_prcc[2].base = ioremap(U5500_CLKRST3_BASE, SZ_4K); - context_prcc[3].base = ioremap(U5500_CLKRST5_BASE, SZ_4K); - context_prcc[4].base = ioremap(U5500_CLKRST6_BASE, SZ_4K); - - context_gic_dist_common.base = ioremap(U5500_GIC_DIST_BASE, SZ_4K); - per_cpu(context_gic_cpu, 0).base = ioremap(U5500_GIC_CPU_BASE, SZ_4K); - } else if (cpu_is_u8500()) { - /* Give logical address to backup RAM. For both CPUs */ - writel(IO_ADDRESS(U8500_PUBLIC_BOOT_ROM_BASE), - IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); - - writel(IO_ADDRESS(U8500_PUBLIC_BOOT_ROM_BASE), - IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_PUBLIC_BOOT_ROM_LOG_ADDR)); - - context_tpiu.base = ioremap(U8500_TPIU_BASE, SZ_4K); - context_stm_ape.base = ioremap(U8500_STM_REG_BASE, SZ_4K); - context_scu.base = ioremap(U8500_SCU_BASE, SZ_4K); - - /* PERIPH4 is always on, so no need saving prcc */ - context_prcc[0].base = ioremap(U8500_CLKRST1_BASE, SZ_4K); - context_prcc[1].base = ioremap(U8500_CLKRST2_BASE, SZ_4K); - context_prcc[2].base = ioremap(U8500_CLKRST3_BASE, SZ_4K); - context_prcc[3].base = ioremap(U8500_CLKRST5_BASE, SZ_4K); - context_prcc[4].base = ioremap(U8500_CLKRST6_BASE, SZ_4K); - - context_gic_dist_common.base = ioremap(U8500_GIC_DIST_BASE, SZ_4K); - per_cpu(context_gic_cpu, 0).base = ioremap(U8500_GIC_CPU_BASE, SZ_4K); - } - - per_cpu(context_gic_dist_cpu, 0).base = context_gic_dist_common.base; - - for (i = 1; i < num_possible_cpus(); i++) { - per_cpu(context_gic_cpu, i).base - = per_cpu(context_gic_cpu, 0).base; - per_cpu(context_gic_dist_cpu, i).base - = per_cpu(context_gic_dist_cpu, 0).base; - } - - for (i = 0; i < ARRAY_SIZE(context_prcc); i++) { - const int clusters[] = {1, 2, 3, 5, 6}; - char clkname[10]; - - snprintf(clkname, sizeof(clkname), "PERIPH%d", clusters[i]); - - context_prcc[i].clk = clk_get_sys(clkname, NULL); - BUG_ON(IS_ERR(context_prcc[i].clk)); - } - - if (cpu_is_u8500()) { - u8500_context_init(); - } else if (cpu_is_u5500()) { - u5500_context_init(); - } else { - printk(KERN_ERR "context: unknown hardware!\n"); - return -EINVAL; - } - - return 0; -} -subsys_initcall(context_init); diff --git a/arch/arm/mach-ux500/pm/context.h b/arch/arm/mach-ux500/pm/context.h deleted file mode 100644 index 22b56351284..00000000000 --- a/arch/arm/mach-ux500/pm/context.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> - * Rickard Andersson <rickard.andersson@stericsson.com> for - * ST-Ericsson. - * License terms: GNU General Public License (GPL) version 2 - * - */ -#ifndef CONTEXT_H -#define CONTEXT_H - -#include <linux/notifier.h> - -#ifdef CONFIG_UX500_CONTEXT - -/* Defines to be with - * context_ape_notifier_register - */ -#define CONTEXT_APE_SAVE 0 /* APE save */ -#define CONTEXT_APE_RESTORE 1 /* APE restore */ - -/* Defines to be with - * context_arm_notifier_register - */ -#define CONTEXT_ARM_CORE_SAVE 0 /* Called for each ARM core */ -#define CONTEXT_ARM_CORE_RESTORE 1 /* Called for each ARM core */ -#define CONTEXT_ARM_COMMON_SAVE 2 /* Called when ARM common is saved */ -#define CONTEXT_ARM_COMMON_RESTORE 3 /* Called when ARM common is restored */ - -int context_ape_notifier_register(struct notifier_block *nb); -int context_ape_notifier_unregister(struct notifier_block *nb); - -int context_arm_notifier_register(struct notifier_block *nb); -int context_arm_notifier_unregister(struct notifier_block *nb); - -void context_vape_save(void); -void context_vape_restore(void); - -void context_gpio_save(void); -void context_gpio_restore(void); -void context_gpio_restore_mux(void); -void context_gpio_mux_safe_switch(bool begin); - -void context_gic_dist_disable_unneeded_irqs(void); - -void context_varm_save_common(void); -void context_varm_restore_common(void); - -void context_varm_save_core(void); -void context_varm_restore_core(void); - -void context_save_cpu_registers(void); -void context_restore_cpu_registers(void); - -void context_save_to_sram_and_wfi(bool cleanL2cache); - -void context_clean_l1_cache_all(void); -void context_save_arm_registers(u32 **backup_stack); -void context_restore_arm_registers(u32 **backup_stack); - -void context_save_cp15_registers(u32 **backup_stack); -void context_restore_cp15_registers(u32 **backup_stack); - -void context_save_to_sram_and_wfi_internal(u32 backup_sram_storage, - bool cleanL2cache); - -/* DB specific functions in either context-db8500 or context-db5500 */ -void u8500_context_save_icn(void); -void u8500_context_restore_icn(void); -void u8500_context_init(void); - -void u5500_context_save_icn(void); -void u5500_context_restore_icn(void); -void u5500_context_init(void); - -#else - -static inline void context_varm_save_core(void) {} -static inline void context_save_cpu_registers(void) {} -static inline void context_save_to_sram_and_wfi(bool cleanL2cache) {} -static inline void context_restore_cpu_registers(void) {} -static inline void context_varm_restore_core(void) {} - -#endif - -#endif diff --git a/arch/arm/mach-ux500/pm/context_arm.S b/arch/arm/mach-ux500/pm/context_arm.S deleted file mode 100644 index 55e2accc85f..00000000000 --- a/arch/arm/mach-ux500/pm/context_arm.S +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> - * Rickard Andersson <rickard.andersson@stericsson.com> for - * ST-Ericsson. - * License terms: GNU General Public License (GPL) version 2 - * - */ - -#include <linux/linkage.h> -#include <mach/hardware.h> -#include <asm/hardware/cache-l2x0.h> - -/* - * Save and increment macro - */ -.macro SAVE_AND_INCREMENT FROM_REG TO_REG - str \FROM_REG, [\TO_REG], #+4 -.endm - -/* - * Decrement and restore macro - */ -.macro DECREMENT_AND_RESTORE FROM_REG TO_REG - ldr \TO_REG, [\FROM_REG, #-4]! -.endm - -/* - * Save ARM registers - * - * This function must be called in supervisor mode. - * - * r0 = address to backup stack pointer - * - * Backup stack operations: - * + {sp, lr}^ - * + cpsr - * + {r3, r8-r14} (FIQ mode: r3=spsr) - * + {r3, r13, r14} (IRQ mode: r3=spsr) - * + {r3, r13, r14} (abort mode: r3=spsr) - * + {r3, r13, r14} (undef mode: r3=spsr) - */ - .align - .section ".text", "ax" -ENTRY(context_save_arm_registers) - stmfd sp!, {r1, r2, r3, lr} @ Save on stack - ldr r1, [r0] @ Read backup stack pointer - - stmia r1, {sp, lr}^ @ Store user mode sp and lr - @ registers - add r1, r1, #8 @ Update backup pointer (not - @ done in previous instruction) - - mrs r2, cpsr @ Get CPSR - SAVE_AND_INCREMENT r2 r1 @ Save CPSR register - orr r2, r2, #0xc0 @ Disable FIQ and IRQ - bic r2, r2, #0x1f @ Setup r2 to change mode - - @ The suffix to CPSR refers to which field(s) of the CPSR is - @ rereferenced (you can specify one or more). Defined fields are: - @ - @ c - control - @ x - extension - @ s - status - @ f - flags - - orr r3, r2, #0x11 @ Save FIQ mode registers - msr cpsr_cxsf, r3 - mrs r3, spsr - stmia r1!, {r3, r8-r14} - - orr r3, r2, #0x12 @ Save IRQ mode registers - msr cpsr_cxsf, r3 - mrs r3, spsr - stmia r1!, {r3, r13, r14} - - orr r3, r2, #0x17 @ Save abort mode registers + - @ common mode registers - msr cpsr_cxsf, r3 - mrs r3, spsr - stmia r1!, {r3, r13, r14} - - orr r3, r2, #0x1B @ Save undef mode registers - msr cpsr_cxsf, r3 - mrs r3, spsr - stmia r1!, {r3, r13, r14} - - orr r3, r2, #0x13 @ Return to supervisor mode - msr cpsr_cxsf, r3 - - str r1, [r0] @ Write backup stack pointer - ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return - - - -/* - * Restore ARM registers - * - * This function must be called in supervisor mode. - * - * r0 = address to backup stack pointer - * - * Backup stack operations: - * - {r3, r13, r14} (undef mode: spsr=r3) - * - {r3, r13, r14} (abort mode: spsr=r3) - * - {r3, r13, r14} (IRQ mode: spsr=r3) - * - {r3, r8-r14} (FIQ mode: spsr=r3) - * - cpsr - * - {sp, lr}^ - */ - .align - .section ".text", "ax" -ENTRY(context_restore_arm_registers) - stmfd sp!, {r1, r2, r3, lr} @ Save on stack - ldr r1, [r0] @ Read backup stack pointer - - mrs r2, cpsr @ Get CPSR - orr r2, r2, #0xc0 @ Disable FIQ and IRQ - bic r2, r2, #0x1f @ Setup r2 to change mode - - orr r3, r2, #0x1b @ Restore undef mode registers - msr cpsr_cxsf, r3 - ldmdb r1!, {r3, r13, r14} - msr spsr_cxsf, r3 - - orr r3, r2, #0x17 @ Restore abort mode registers - msr cpsr_cxsf, r3 - ldmdb r1!, {r3, r13, r14} - msr spsr_cxsf, r3 - - orr r3, r2, #0x12 @ Restore IRQ mode registers - msr cpsr_cxsf, r3 - ldmdb r1!, {r3, r13, r14} - msr spsr_cxsf, r3 - - orr r3, r2, #0x11 @ Restore FIQ mode registers - msr cpsr_cxsf, r3 - ldmdb r1!, {r3, r8-r14} - msr spsr_cxsf, r3 - - DECREMENT_AND_RESTORE r1 r3 @ Restore cpsr register - msr cpsr_cxsf, r3 - - ldmdb r1, {sp, lr}^ @ Restore sp and lr registers - sub r1, r1, #8 @ Update backup pointer (not - @ done in previous instruction) - - str r1, [r0] @ Write backup stack pointer - ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return - - - -/* - * Save CP15 registers - * - * This function must be called in supervisor mode. - * - * r0 = address to backup stack pointer - * - * TTBR0, TTBR1, TTBRC, DACR CP15 registers are restored by boot ROM from SRAM. - */ - .align 4 - .section ".text", "ax" -ENTRY(context_save_cp15_registers) - stmfd sp!, {r1, r2, r3, lr} @ Save on stack (r3 is saved due - @ to 8 byte aligned stack) - ldr r1, [r0] @ Read backup stack pointer - - mrc p15, 0, r2, c12, c0, 0 @ Read Non-secure Vector Base - @ Address Register - SAVE_AND_INCREMENT r2 r1 - - mrc p15, 0, r2, c10, c2, 0 @ Access primary memory region - @ remap register - SAVE_AND_INCREMENT r2 r1 - - mrc p15, 0, r2, c10, c2, 1 @ Access normal memory region - @ remap register - SAVE_AND_INCREMENT r2 r1 - - mrc p15, 0, r2, c13, c0, 1 @ Read Context ID Register - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c13, c0, 2 @ Read Thread ID registers, - @ this register is both user - @ and privileged R/W accessible - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c13, c0, 3 @ Read Thread ID registers, - @ this register is user - @ read-only and privileged R/W - @ accessible. - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c13, c0, 4 @ Read Thread ID registers, - @ this register is privileged - @ R/W accessible only. - SAVE_AND_INCREMENT r2 r1 - - mrc p15, 2, r2, c0, c0, 0 @ Cache Size Selection Register - SAVE_AND_INCREMENT r2 r1 - - mrc p15, 0, r2, c9, c12, 0 @ Read PMNC Register - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c9, c12, 1 @ Read PMCNTENSET Register - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c9, c12, 5 @ Read PMSELR Register - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c9, c13, 0 @ Read PMCCNTR Register - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c9, c13, 1 @ Read PMXEVTYPER Register - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c9, c14, 0 @ Read PMUSERENR Register - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c9, c14, 1 @ Read PMINTENSET Register - SAVE_AND_INCREMENT r2 r1 - mrc p15, 0, r2, c9, c14, 2 @ Read PMINTENCLR Register - SAVE_AND_INCREMENT r2 r1 - - mrc p15, 0, r2, c1, c0, 2 @ Read CPACR Register - SAVE_AND_INCREMENT r2 r1 - - str r1, [r0] @ Write backup stack pointer - ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return - - - -/* - * Restore CP15 registers - * - * This function must be called in supervisor mode. - * - * r0 = address to backup stack pointer - */ - .align 4 - .section ".text", "ax" -ENTRY(context_restore_cp15_registers) - stmfd sp!, {r1, r2, r3, lr} @ Save on stack (r3 is saved due - @ to 8 byte aligned stack) - ldr r1, [r0] @ Read backup stack pointer - - DECREMENT_AND_RESTORE r1 r2 @ Write CPACR register - mcr p15, 0, r2, c1, c0, 2 - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c9, c14, 2 @ Write PMINTENCLR Register - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c9, c14, 1 @ Write PMINTENSET Register - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c9, c14, 0 @ Write PMUSERENR Register - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c9, c13, 1 @ Write PMXEVTYPER Register - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c9, c13, 0 @ Write PMCCNTR Register - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c9, c12, 5 @ Write PMSELR Register - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c9, c12, 1 @ Write PMCNTENSET Register - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c9, c12, 0 @ Write PMNC Register - - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 2, r2, c0, c0, 0 @ Cache Size Selection Register - - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c13, c0, 4 @ Write Thread ID registers, - @ this register is privileged - @ R/W accessible only - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c13, c0, 3 @ Write Thread ID registers, - @ this register is user - @ read-only and privileged R/W - @ accessible - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c13, c0, 2 @ Write Thread ID registers, - @ this register is both user - @ and privileged R/W accessible - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c13, c0, 1 @ Write Context ID Register - - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c10, c2, 1 @ Access normal memory region - @ remap register - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c10, c2, 0 @ Access primary memory region - @ remap register - - DECREMENT_AND_RESTORE r1 r2 - mcr p15, 0, r2, c12, c0, 0 @ Write Non-secure Vector Base - @ Address Register - - str r1, [r0] @ Write backup stack pointer - ldmfd sp!, {r1, r2, r3, pc} @ Restore registers and return - - -/* - * L1 cache clean function. Commit 'dirty' data from L1 - * to L2 cache. - * - * r0, r1, r2, used locally - * - */ - .align 4 - .section ".text", "ax" -ENTRY(context_clean_l1_cache_all) - - mov r0, #0 @ swith to cache level 0 - @ (L1 cache) - mcr p15, 2, r0, c0, c0, 0 @ select current cache level - @ in cssr - - dmb - mov r1, #0 @ r1 = way index -wayLoopL1clean: - mov r0, #0 @ r0 = line index -lineLoopL1clean: - mov r2, r1, lsl #30 @ TODO: OK to hard-code - @ SoC-specific L1 cache details? - add r2, r0, lsl #5 - mcr p15, 0, r2, c7, c10, 2 @ Clean cache by set/way - add r0, r0, #1 - cmp r0, #256 @ TODO: Ok with hard-coded - @ set/way sizes or do we have to - @ read them from ARM regs? Is it - @ set correctly in silicon? - bne lineLoopL1clean - add r1, r1, #1 - cmp r1, #4 @ TODO: Ditto, sizes... - bne wayLoopL1clean - - dsb - isb - mov pc, lr - -ENDPROC(context_clean_l1_cache_all) - -/* - * Last saves to backup RAM, cache clean and WFI - * - * r0 = address to backup_sram_storage base adress - * r1 = indicate whether also L2 cache should be cleaned - */ - .align 4 - .section ".text", "ax" -ENTRY(context_save_to_sram_and_wfi_internal) - - stmfd sp!, {r2-r12, lr} @ save on stack. - - mrc p15, 0, r2, c1, c0, 0 @ read cp15 system control - @ register - str r2, [r0, #0x00] - mrc p15, 0, r2, c2, c0, 0 @ read cp15 ttb0 register - str r2, [r0, #0x04] - mrc p15, 0, r2, c2, c0, 1 @ read cp15 ttb1 register - str r2, [r0, #0x08] - mrc p15, 0, r2, c2, c0, 2 @ read cp15 ttb control register - str r2, [r0, #0x0C] - mrc p15, 0, r2, c3, c0, 0 @ read domain access control - @ register - str r2, [r0, #0x10] - - ldr r2, =return_here - str r2, [r0, #0x14] @ save program counter restore - @ value to backup_sram_storage - mrs r2, cpsr - str r2, [r0, #0x18] @ save cpsr to - @ backup_sram_storage - str sp, [r0, #0x1c] @ save sp to backup_sram_storage - - mov r4, r1 @ Set r4 = cleanL2cache, r1 - @ will be destroyed by - @ v7_clean_l1_cache_all - - bl context_clean_l1_cache_all @ Commit all dirty data in L1 - @ cache to L2 without - @ invalidating - - dsb @ data synchronization barrier - isb @ instruction synchronization - @ barrier - wfi @ wait for interrupt - -return_here: @ both cores return here - @ now we are out deep sleep - @ with all the context lost - @ except pc, sp and cpsr - - ldmfd sp!, {r2-r12, pc} @ restore from stack - diff --git a/arch/arm/mach-ux500/pm/cpufreq-db5500.c b/arch/arm/mach-ux500/pm/cpufreq-db5500.c deleted file mode 100644 index 2830615f8b4..00000000000 --- a/arch/arm/mach-ux500/pm/cpufreq-db5500.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - */ - -#include <linux/kernel.h> -#include <linux/cpufreq.h> - -#include <mach/prcmu.h> - -#include "cpufreq.h" - -static struct cpufreq_frequency_table freq_table[] = { - [0] = { - .index = 0, - .frequency = 200000, - }, - [1] = { - .index = 1, - .frequency = 396500, - }, - [2] = { - .index = 2, - .frequency = 793000, - }, - [3] = { - .index = 3, - .frequency = CPUFREQ_TABLE_END, - }, -}; - -static enum arm_opp idx2opp[] = { - ARM_EXTCLK, - ARM_50_OPP, - ARM_100_OPP, -}; - -int u5500_cpufreq_limits(int cpu, int r, unsigned int *min, unsigned int *max) -{ - struct cpufreq_policy p; - int ret; - - ret = cpufreq_get_policy(&p, cpu); - if (ret) { - pr_err("cpufreq-db8500: Failed to get policy.\n"); - return -EINVAL; - } - - (*max) = p.max; - (*min) = p.min; - - return 0; -} - -static int __init u5500_cpufreq_register(void) -{ - int i = 0; - - BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); - - if (cpu_is_u5500v1()) - return -ENODEV; - pr_info("u5500-cpufreq : Available frequencies:\n"); - while (freq_table[i].frequency != CPUFREQ_TABLE_END) - pr_info(" %d Mhz\n", freq_table[i++].frequency/1000); - - return ux500_cpufreq_register(freq_table, idx2opp); -} -device_initcall(u5500_cpufreq_register); diff --git a/arch/arm/mach-ux500/pm/cpufreq-db8500.c b/arch/arm/mach-ux500/pm/cpufreq-db8500.c deleted file mode 100644 index 294af62ff37..00000000000 --- a/arch/arm/mach-ux500/pm/cpufreq-db8500.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - */ - -#include <linux/kernel.h> -#include <linux/cpufreq.h> - -#include <mach/prcmu.h> - -#include "cpufreq.h" - -static struct cpufreq_frequency_table freq_table[] = { - [0] = { - .index = 0, - .frequency = 200000, - }, - [1] = { - .index = 1, - .frequency = 300000, - }, - [2] = { - .index = 2, - .frequency = 600000, - }, - [3] = { - /* Used for MAX_OPP, if available */ - .index = 3, - .frequency = CPUFREQ_TABLE_END, - }, - [4] = { - .index = 4, - .frequency = CPUFREQ_TABLE_END, - }, -}; - -static enum arm_opp idx2opp[] = { - ARM_EXTCLK, - ARM_50_OPP, - ARM_100_OPP, - ARM_MAX_OPP -}; - -/* - * Below is a temporary workaround for wlan performance issues - */ - -#include <linux/kernel_stat.h> -#include <linux/workqueue.h> -#include <linux/cpu.h> - -#include <mach/irqs.h> -#include <mach/prcmu-qos.h> - -#define WLAN_PROBE_DELAY 3000 /* 3 seconds */ -#define WLAN_LIMIT (3000/3) /* If we have more than 1000 irqs per second */ -static struct delayed_work work_wlan_workaround; - -static void wlan_load(struct work_struct *work) -{ - int cpu; - unsigned int num_irqs = 0; - static unsigned int old_num_irqs = UINT_MAX; - - for_each_online_cpu(cpu) - num_irqs += kstat_irqs_cpu(IRQ_DB8500_SDMMC1, cpu); - - if ((num_irqs > old_num_irqs) && - (num_irqs - old_num_irqs) > WLAN_LIMIT) - prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, - "wlan", 125); - else - prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, - "wlan", 25); - - old_num_irqs = num_irqs; - - schedule_delayed_work_on(0, - &work_wlan_workaround, - msecs_to_jiffies(WLAN_PROBE_DELAY)); -} - -int u8500_cpufreq_limits(int cpu, int r, unsigned int *min, unsigned int *max) -{ - int op; - int i; - int ret; - static int old_freq; - struct cpufreq_policy p; - - switch (r) { - case 0: - /* Fall through */ - case 25: - op = ARM_EXTCLK; - break; - case 50: - op = ARM_50_OPP; - break; - case 100: - op = ARM_100_OPP; - break; - case 125: - if (prcmu_has_arm_maxopp()) - op = ARM_MAX_OPP; - else - op = ARM_100_OPP; - break; - default: - pr_err("cpufreq-db8500: Incorrect arm target value (%d).\n", - r); - BUG(); - break; - } - - - for (i = 0; idx2opp[i] != op; i++) - ; - - if (freq_table[i].frequency == CPUFREQ_TABLE_END) { - pr_err("cpufreq-u8500: Minimum frequency does not exist!\n"); - BUG(); - } - - if (freq_table[i].frequency != old_freq) - pr_debug("cpufreq-db8500: set min arm freq to %d\n", - freq_table[i].frequency); - - (*min) = freq_table[i].frequency; - - ret = cpufreq_get_policy(&p, cpu); - if (ret) { - pr_err("cpufreq-db8500: Failed to get policy.\n"); - return -EINVAL; - } - - (*max) = p.max; - return 0; -} - -static int __init u8500_cpufreq_register(void) -{ - int i = 0; - - BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table)); - - if (!prcmu_is_u8400()) { - freq_table[1].frequency = 400000; - freq_table[2].frequency = 800000; - if (prcmu_has_arm_maxopp()) - freq_table[3].frequency = 1000000; - } - - INIT_DELAYED_WORK_DEFERRABLE(&work_wlan_workaround, - wlan_load); - - prcmu_qos_add_requirement(PRCMU_QOS_ARM_OPP, "wlan", 25); - - schedule_delayed_work_on(0, - &work_wlan_workaround, - msecs_to_jiffies(WLAN_PROBE_DELAY)); - - pr_info("u8500-cpufreq : Available frequencies:\n"); - while (freq_table[i].frequency != CPUFREQ_TABLE_END) - pr_info(" %d Mhz\n", freq_table[i++].frequency/1000); - - return ux500_cpufreq_register(freq_table, idx2opp); -} -device_initcall(u8500_cpufreq_register); diff --git a/arch/arm/mach-ux500/pm/cpufreq-dbx500.h b/arch/arm/mach-ux500/pm/cpufreq-dbx500.h deleted file mode 100644 index 2777336ef4e..00000000000 --- a/arch/arm/mach-ux500/pm/cpufreq-dbx500.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - */ -#ifndef __UX500_PM_CPUFREQ_DBX500_H -#define __UX500_PM_CPUFREQ_DBX500_H - -int u8500_cpufreq_limits(int cpu, int r, unsigned int *min, unsigned int *max); - -int u5500_cpufreq_limits(int cpu, int r, unsigned int *min, unsigned int *max); - -#endif diff --git a/arch/arm/mach-ux500/pm/cpufreq.c b/arch/arm/mach-ux500/pm/cpufreq.c deleted file mode 100644 index fdb3ae8461a..00000000000 --- a/arch/arm/mach-ux500/pm/cpufreq.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * Author: Sundar Iyer <sundar.iyer@stericsson.com> - * - */ -#include <linux/kernel.h> -#include <linux/cpufreq.h> -#include <linux/delay.h> -#include <linux/slab.h> - -#include <mach/hardware.h> -#include <mach/prcmu.h> -#include <mach/prcmu-regs.h> - -#include "cpufreq-dbx500.h" - -static struct cpufreq_frequency_table *freq_table; -static enum arm_opp *idx2opp; - -static struct freq_attr *ux500_cpufreq_attr[] = { - &cpufreq_freq_attr_scaling_available_freqs, - NULL, -}; - -static int ux500_cpufreq_verify_speed(struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, freq_table); -} - -static int ux500_cpufreq_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - struct cpufreq_freqs freqs; - unsigned int idx; - - /* scale the target frequency to one of the extremes supported */ - if (target_freq < policy->cpuinfo.min_freq) - target_freq = policy->cpuinfo.min_freq; - if (target_freq > policy->cpuinfo.max_freq) - target_freq = policy->cpuinfo.max_freq; - - /* Lookup the next frequency */ - if (cpufreq_frequency_table_target - (policy, freq_table, target_freq, relation, &idx)) { - return -EINVAL; - } - - freqs.old = policy->cur; - freqs.new = freq_table[idx].frequency; - freqs.cpu = policy->cpu; - - if (freqs.old == freqs.new) - return 0; - - /* pre-change notification */ - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - - /* request the PRCM unit for opp change */ - if (prcmu_set_arm_opp(idx2opp[idx])) { - pr_err("ux500-cpufreq: Failed to set OPP level\n"); - return -EINVAL; - } - - /* post change notification */ - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - return 0; -} - -static unsigned int ux500_cpufreq_getspeed(unsigned int cpu) -{ - int i; - /* request the prcm to get the current ARM opp */ - for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++) - ; - return freq_table[i].frequency; -} - -int ux500_cpufreq_limits(int cpu, int r, unsigned int *min, unsigned int *max) -{ - if (cpu_is_u5500()) - return u5500_cpufreq_limits(cpu, r, min, max); - if (cpu_is_u8500()) - return u8500_cpufreq_limits(cpu, r, min, max); - return -EINVAL; -} - -static int __cpuinit ux500_cpufreq_init(struct cpufreq_policy *policy) -{ - int res; - int i; - - /* get policy fields based on the table */ - res = cpufreq_frequency_table_cpuinfo(policy, freq_table); - if (!res) - cpufreq_frequency_table_get_attr(freq_table, policy->cpu); - else { - pr_err("ux500-cpufreq : Failed to read policy table\n"); - return res; - } - - policy->min = policy->cpuinfo.min_freq; - policy->max = policy->cpuinfo.max_freq; - policy->cur = ux500_cpufreq_getspeed(policy->cpu); - - for (i = 0; freq_table[i].frequency != policy->cur; i++) - ; - - policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - - /* - * FIXME : Need to take time measurement across the target() - * function with no/some/all drivers in the notification - * list. - */ - policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */ - - /* policy sharing between dual CPUs */ - cpumask_copy(policy->cpus, &cpu_present_map); - - policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; - - return 0; -} - -static struct cpufreq_driver ux500_cpufreq_driver = { - .flags = CPUFREQ_STICKY, - .verify = ux500_cpufreq_verify_speed, - .target = ux500_cpufreq_target, - .get = ux500_cpufreq_getspeed, - .init = ux500_cpufreq_init, - .name = "UX500", - .attr = ux500_cpufreq_attr, -}; - -int __init -ux500_cpufreq_register(struct cpufreq_frequency_table *table, - enum arm_opp *idx2opplist) -{ - freq_table = table; - idx2opp = idx2opplist; - - if (ux500_is_svp()) - return -ENODEV; - - pr_info("cpufreq for ux500 started\n"); - return cpufreq_register_driver(&ux500_cpufreq_driver); -} diff --git a/arch/arm/mach-ux500/pm/cpufreq.h b/arch/arm/mach-ux500/pm/cpufreq.h deleted file mode 100644 index eaf5eab3ab3..00000000000 --- a/arch/arm/mach-ux500/pm/cpufreq.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - */ -#ifndef __UX500_PM_CPUFREQ_H -#define __UX500_PM_CPUFREQ_H - -#include <linux/cpufreq.h> - -extern int ux500_cpufreq_register(struct cpufreq_frequency_table *freq_table, - enum arm_opp *idx2opp); - -/* This function lives in drivers/cpufreq/cpufreq.c */ -int cpufreq_update_freq(int cpu, unsigned int min, unsigned int max); - -int ux500_cpufreq_limits(int cpu, int r, unsigned int *min, unsigned int *max); - -#endif diff --git a/arch/arm/mach-ux500/pm/cpuidle.c b/arch/arm/mach-ux500/pm/cpuidle.c deleted file mode 100644 index eddd2849a16..00000000000 --- a/arch/arm/mach-ux500/pm/cpuidle.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010-2011 - * - * Author: Rickard Andersson <rickard.andersson@stericsson.com>, - * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson. - * - * Loosely based on cpuidle.c by Sundar Iyer. - * - * License terms: GNU General Public License (GPL) version 2 - * - */ -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/sched.h> -#include <linux/tick.h> -#include <linux/clockchips.h> -#include <linux/gpio/nomadik.h> - -#include <mach/prcmu.h> - -#include "cpuidle.h" -#include "cpuidle_dbg.h" -#include "context.h" -#include "pm.h" -#include "timer.h" -#include "../regulator-u8500.h" - -/* - * All measurements are with two cpus online (worst case) and at - * 200 MHz (worst case) - * - * Enter latency depends on cpu frequency, and is only depending on - * code executing on the ARM. - * Exit latency is both depending on "wake latency" which is the - * time between the PRCMU has gotten the interrupt and the ARM starts - * to execute and the time before everything is done on the ARM. - * The wake latency is more or less constant related to cpu frequency, - * but can differ depending on what the modem does. - * Wake latency is not included for plain WFI. - * For states that uses RTC (Sleep & DeepSleep), wake latency is reduced - * from clock programming timeout. - * - */ -#define DEEP_SLEEP_WAKE_UP_LATENCY 8500 -/* Wake latency from ApSleep is measured to be around 1.0 to 1.5 ms */ -#define MIN_SLEEP_WAKE_UP_LATENCY 1000 -#define MAX_SLEEP_WAKE_UP_LATENCY 1500 - -#define UL_PLL_START_UP_LATENCY 8000 /* us */ - -static struct cstate cstates[] = { - { - .enter_latency = 0, - .exit_latency = 0, - .threshold = 0, - .power_usage = 1000, - .APE = APE_ON, - .ARM = ARM_ON, - .UL_PLL = UL_PLL_ON, - .ESRAM = ESRAM_RET, - .pwrst = PRCMU_AP_NO_CHANGE, - .state = CI_RUNNING, - .desc = "Running ", - }, - { - /* These figures are not really true. There is a cost for WFI */ - .enter_latency = 0, - .exit_latency = 0, - .threshold = 0, - .power_usage = 10, - .APE = APE_ON, - .ARM = ARM_ON, - .UL_PLL = UL_PLL_ON, - .ESRAM = ESRAM_RET, - .pwrst = PRCMU_AP_NO_CHANGE, - .flags = CPUIDLE_FLAG_TIME_VALID, - .state = CI_WFI, - .desc = "Wait for interrupt ", - }, - { - .enter_latency = 170, - .exit_latency = 70, - .threshold = 260, - .power_usage = 4, - .APE = APE_ON, - .ARM = ARM_RET, - .UL_PLL = UL_PLL_ON, - .ESRAM = ESRAM_RET, - .pwrst = PRCMU_AP_IDLE, - .flags = CPUIDLE_FLAG_TIME_VALID, - .state = CI_IDLE, - .desc = "ApIdle ", - }, - { - .enter_latency = 350, - .exit_latency = MAX_SLEEP_WAKE_UP_LATENCY + 200, - /* - * Note: Sleep time must be longer than 120 us or else - * there might be issues with the RTC-RTT block. - */ - .threshold = MAX_SLEEP_WAKE_UP_LATENCY + 350 + 200, - .power_usage = 3, - .APE = APE_OFF, - .ARM = ARM_RET, - .UL_PLL = UL_PLL_ON, - .ESRAM = ESRAM_RET, - .pwrst = PRCMU_AP_SLEEP, - .flags = CPUIDLE_FLAG_TIME_VALID, - .state = CI_SLEEP, - .desc = "ApSleep ", - }, - { - .enter_latency = 350, - .exit_latency = (MAX_SLEEP_WAKE_UP_LATENCY + - UL_PLL_START_UP_LATENCY + 200), - .threshold = (MAX_SLEEP_WAKE_UP_LATENCY + - UL_PLL_START_UP_LATENCY + 350 + 200), - .power_usage = 2, - .APE = APE_OFF, - .ARM = ARM_RET, - .UL_PLL = UL_PLL_OFF, - .ESRAM = ESRAM_RET, - .pwrst = PRCMU_AP_SLEEP, - .flags = CPUIDLE_FLAG_TIME_VALID, - .state = CI_SLEEP, - .desc = "ApSleep, UL PLL off ", - }, -#ifdef CONFIG_U8500_CPUIDLE_APDEEPIDLE - { - .enter_latency = 400, - .exit_latency = DEEP_SLEEP_WAKE_UP_LATENCY + 400, - .threshold = DEEP_SLEEP_WAKE_UP_LATENCY + 400 + 400, - .power_usage = 2, - .APE = APE_ON, - .ARM = ARM_OFF, - .UL_PLL = UL_PLL_ON, - .ESRAM = ESRAM_RET, - .pwrst = PRCMU_AP_DEEP_IDLE, - .flags = CPUIDLE_FLAG_TIME_VALID, - .state = CI_DEEP_IDLE, - .desc = "ApDeepIdle, UL PLL off ", - }, -#endif - { - .enter_latency = 410, - .exit_latency = DEEP_SLEEP_WAKE_UP_LATENCY + 420, - .threshold = DEEP_SLEEP_WAKE_UP_LATENCY + 410 + 420, - .power_usage = 1, - .APE = APE_OFF, - .ARM = ARM_OFF, - .UL_PLL = UL_PLL_OFF, - .ESRAM = ESRAM_RET, - .pwrst = PRCMU_AP_DEEP_SLEEP, - .flags = CPUIDLE_FLAG_TIME_VALID, - .state = CI_DEEP_SLEEP, - .desc = "ApDeepsleep, UL PLL off", - }, -}; - -struct cpu_state { - int gov_cstate; - ktime_t sched_wake_up; - struct cpuidle_device dev; - bool restore_arm_core; -}; - -static DEFINE_PER_CPU(struct cpu_state, *cpu_state); - -static DEFINE_SPINLOCK(cpuidle_lock); -static bool restore_ape; /* protected by cpuidle_lock */ -static bool restore_arm; /* protected by cpuidle_lock */ -static ktime_t time_next; /* protected by cpuidle_lock */ - -extern struct clock_event_device u8500_mtu_clkevt; - -static atomic_t idle_cpus_counter = ATOMIC_INIT(0); -static atomic_t master_counter = ATOMIC_INIT(0); - -struct cstate *ux500_ci_get_cstates(int *len) -{ - if (len != NULL) - (*len) = ARRAY_SIZE(cstates); - return cstates; -} - -static void restore_sequence(struct cpu_state *state, ktime_t now) -{ - spin_lock(&cpuidle_lock); - - smp_rmb(); - if (state->restore_arm_core) { - state->restore_arm_core = false; - smp_wmb(); - - context_restore_cpu_registers(); - context_varm_restore_core(); - } - - smp_rmb(); - if (restore_arm) { - - restore_arm = false; - smp_wmb(); - - /* Restore gic settings */ - context_varm_restore_common(); - } - - smp_rmb(); - if (restore_ape) { - restore_ape = false; - smp_wmb(); - - /* - * APE has been turned off. Save GPIO wake up cause before - * clearing ioforce. - */ - context_vape_restore(); - - ux500_pm_gpio_save_wake_up_status(); - - /* Restore IO ring */ - ux500_pm_prcmu_set_ioforce(false); - - ux500_ci_dbg_console_handle_ape_resume(); - - ux500_rtcrtt_off(); - - /* - * If we're returning from ApSleep and the RTC timer - * caused the wake up, program the MTU to trigger. - */ - if ((ktime_to_us(now) >= ktime_to_us(time_next))) - time_next = ktime_add(now, ktime_set(0, 1000)); - - /* Make sure have an MTU interrupt waiting for us */ - WARN_ON(clockevents_program_event(&u8500_mtu_clkevt, - time_next, - now)); - } - - spin_unlock(&cpuidle_lock); - -} - -/** - * get_remaining_sleep_time() - returns remaining sleep time in - * microseconds (us) - */ -static u32 get_remaining_sleep_time(ktime_t *next, int *on_cpu) -{ - ktime_t now, t; - int cpu; - int delta; - u32 remaining_sleep_time = UINT_MAX; - - now = ktime_get(); - - /* Check next schedule to expire considering both cpus */ - - spin_lock(&cpuidle_lock); - for_each_online_cpu(cpu) { - t = per_cpu(cpu_state, cpu)->sched_wake_up; - - delta = ktime_to_us(ktime_sub(t, now)); - if ((delta < remaining_sleep_time) && (delta > 0)) { - remaining_sleep_time = (u32)delta; - if (next) - (*next) = t; - if (on_cpu) - (*on_cpu) = cpu; - } - } - spin_unlock(&cpuidle_lock); - - return remaining_sleep_time; -} - -static bool is_last_cpu_running(void) -{ - smp_rmb(); - return atomic_read(&idle_cpus_counter) == num_online_cpus(); -} - -static int determine_sleep_state(u32 *sleep_time) -{ - int i; - - int cpu; - int max_depth; - bool power_state_req; - - /* If first cpu to sleep, go to most shallow sleep state */ - if (!is_last_cpu_running()) - return CI_WFI; - - /* If other CPU is going to WFI, but not yet there wait. */ - while (1) { - if (ux500_pm_other_cpu_wfi()) - break; - - if (ux500_pm_gic_pending_interrupt()) - return -1; - - if (!is_last_cpu_running()) - return CI_WFI; - } - - power_state_req = power_state_active_is_enabled() || - prcmu_is_ac_wake_requested(); - - (*sleep_time) = get_remaining_sleep_time(NULL, NULL); - - if ((*sleep_time) == UINT_MAX) - return CI_WFI; - /* - * Never go deeper than the governor recommends even though it might be - * possible from a scheduled wake up point of view - */ - max_depth = ux500_ci_dbg_deepest_state(); - - for_each_online_cpu(cpu) { - if (max_depth > per_cpu(cpu_state, cpu)->gov_cstate) - max_depth = per_cpu(cpu_state, cpu)->gov_cstate; - } - - for (i = max_depth; i > 0; i--) { - - if ((*sleep_time) <= cstates[i].threshold) - continue; - - if (cstates[i].APE == APE_OFF) { - /* This state says APE should be off */ - if (power_state_req || - ux500_ci_dbg_force_ape_on()) - continue; - } - - /* OK state */ - break; - } - - ux500_ci_dbg_register_reason(i, power_state_req, - (*sleep_time), - max_depth); - - return max(CI_WFI, i); -} - -static int enter_sleep(struct cpuidle_device *dev, - struct cpuidle_state *ci_state) -{ - ktime_t time_enter, time_exit, time_wake; - ktime_t wake_up; - int sleep_time = 0; - s64 diff; - int ret; - int target; - struct cpu_state *state; - bool slept_well = false; - int this_cpu = smp_processor_id(); - bool migrate_timer; - bool master = false; - - local_irq_disable(); - - time_enter = ktime_get(); /* Time now */ - - state = per_cpu(cpu_state, smp_processor_id()); - - wake_up = ktime_add(time_enter, tick_nohz_get_sleep_length()); - - spin_lock(&cpuidle_lock); - - /* Save scheduled wake up for this cpu */ - state->sched_wake_up = wake_up; - - /* Retrive the cstate that the governor recommends for this CPU */ - state->gov_cstate = (int) cpuidle_get_statedata(ci_state); - - if (state->gov_cstate > ux500_ci_dbg_deepest_state()) - state->gov_cstate = ux500_ci_dbg_deepest_state(); - - if (cstates[state->gov_cstate].ARM != ARM_ON) - migrate_timer = true; - else - migrate_timer = false; - - spin_unlock(&cpuidle_lock); - - atomic_inc(&idle_cpus_counter); - - /* - * Determine sleep state considering both CPUs and - * shared resources like e.g. VAPE - */ - target = determine_sleep_state(&sleep_time); - - if (target < 0) - /* "target" will be last_state in the cpuidle framework */ - goto exit_fast; - - /* Only one CPU should master the sleeping sequence */ - if (cstates[target].ARM != ARM_ON) { - smp_mb(); - if (atomic_inc_return(&master_counter) == 1) - master = true; - else - atomic_dec(&master_counter); - smp_mb(); - } - - if (migrate_timer) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, - &this_cpu); - - - if (master && (cstates[target].ARM != ARM_ON)) { - - ux500_pm_gic_decouple(); - - /* - * Check if sleep state has changed after GIC has been frozen - */ - if (target != determine_sleep_state(&sleep_time)) { - atomic_dec(&master_counter); - goto exit; - } - - /* Copy GIC interrupt settings to PRCMU interrupt settings */ - ux500_pm_prcmu_copy_gic_settings(); - - if (ux500_pm_gic_pending_interrupt()) { - /* An interrupt found => abort */ - atomic_dec(&master_counter); - goto exit; - } - - if (ux500_pm_prcmu_pending_interrupt()) { - /* An interrupt found => abort */ - atomic_dec(&master_counter); - goto exit; - - } - /* - * No PRCMU interrupt was pending => continue the - * sleeping stages - */ - } - - if (master && (cstates[target].APE == APE_OFF)) { - ktime_t est_wake_time; - int wake_cpu; - - /* We are going to sleep or deep sleep => prepare for it */ - - /* Program the only timer that is available when APE is off */ - - sleep_time = get_remaining_sleep_time(&est_wake_time, - &wake_cpu); - - if (sleep_time == UINT_MAX) { - atomic_dec(&master_counter); - goto exit; - } - - if (cstates[target].UL_PLL == UL_PLL_OFF) - /* Compensate for ULPLL start up time */ - sleep_time -= UL_PLL_START_UP_LATENCY; - - /* - * Not checking for negative sleep time since - * determine_sleep_state has already checked that - * there is enough time. - */ - - /* Adjust for exit latency */ - sleep_time -= MIN_SLEEP_WAKE_UP_LATENCY; - - ux500_rtcrtt_next(sleep_time); - - /* - * Make sure the cpu that is scheduled first gets - * the prcmu interrupt. - */ - irq_set_affinity(IRQ_DB8500_PRCMU1, cpumask_of(wake_cpu)); - - context_vape_save(); - - ux500_ci_dbg_console_handle_ape_suspend(); - ux500_pm_prcmu_set_ioforce(true); - - spin_lock(&cpuidle_lock); - restore_ape = true; - time_next = est_wake_time; - spin_unlock(&cpuidle_lock); - } - - if (master && (cstates[target].ARM == ARM_OFF)) { - int cpu; - - context_varm_save_common(); - - spin_lock(&cpuidle_lock); - restore_arm = true; - for_each_possible_cpu(cpu) { - (per_cpu(cpu_state, cpu))->restore_arm_core = true; - } - spin_unlock(&cpuidle_lock); - } - - if (cstates[state->gov_cstate].ARM == ARM_OFF) { - context_varm_save_core(); - - if (master && (cstates[target].ARM == ARM_OFF)) - context_gic_dist_disable_unneeded_irqs(); - - context_save_cpu_registers(); - - /* - * Due to we have only 100us between requesting a - * powerstate and wfi, we clean the cache before as - * well to assure the final cache clean before wfi - * has as little as possible to do. - */ - context_clean_l1_cache_all(); - } - - ux500_ci_dbg_log(target, time_enter); - - if (master && cstates[target].ARM != ARM_ON) - prcmu_set_power_state(cstates[target].pwrst, - cstates[target].UL_PLL, - /* Is actually the AP PLL */ - cstates[target].UL_PLL); - - if (master) - atomic_dec(&master_counter); - - /* - * If deepsleep/deepidle, Save return address to SRAM and set - * this CPU in WFI. This is last core to enter sleep, so we need to - * clean both L2 and L1 caches - */ - if (cstates[state->gov_cstate].ARM == ARM_OFF) - context_save_to_sram_and_wfi(cstates[target].ARM == ARM_OFF); - else - __asm__ __volatile__ - ("dsb\n\t" "wfi\n\t" : : : "memory"); - - if (is_last_cpu_running()) - ux500_ci_dbg_wake_latency(target, sleep_time); - - time_wake = ktime_get(); - - slept_well = true; - - restore_sequence(state, time_wake); - -exit: - if (!slept_well) - /* Recouple GIC with the interrupt bus */ - ux500_pm_gic_recouple(); - - /* Use the ARM local timer for this cpu */ - if (migrate_timer) - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, - &this_cpu); -exit_fast: - - atomic_dec(&idle_cpus_counter); - - if (target < 0) - target = CI_RUNNING; - - /* 16 minutes ahead */ - wake_up = ktime_add_us(time_enter, - 1000000000); - - spin_lock(&cpuidle_lock); - /* Remove wake up time i.e. set wake up far ahead */ - state->sched_wake_up = wake_up; - spin_unlock(&cpuidle_lock); - - /* - * We might have chosen another state than what the - * governor recommended - */ - if (target != state->gov_cstate) - /* Update last state pointer used by CPUIDLE subsystem */ - dev->last_state = &(dev->states[target]); - - time_exit = ktime_get(); - diff = ktime_to_us(ktime_sub(time_exit, time_enter)); - if (diff > INT_MAX) - diff = INT_MAX; - - ret = (int)diff; - - ux500_ci_dbg_console_check_uart(); - if (slept_well) - ux500_ci_dbg_exit_latency(target, - time_exit, /* now */ - time_wake, /* exit from wfi */ - time_enter); /* enter cpuidle */ - - ux500_ci_dbg_log(CI_RUNNING, time_exit); - - local_irq_enable(); - - ux500_ci_dbg_console(); - - return ret; -} - -static int init_cstates(int cpu, struct cpu_state *state) -{ - int i; - struct cpuidle_state *ci_state; - struct cpuidle_device *dev; - - dev = &state->dev; - dev->cpu = cpu; - - for (i = 0; i < ARRAY_SIZE(cstates); i++) { - - ci_state = &dev->states[i]; - - cpuidle_set_statedata(ci_state, (void *)i); - - ci_state->exit_latency = cstates[i].exit_latency; - ci_state->target_residency = cstates[i].threshold; - ci_state->flags = cstates[i].flags; - ci_state->enter = enter_sleep; - ci_state->power_usage = cstates[i].power_usage; - snprintf(ci_state->name, CPUIDLE_NAME_LEN, "C%d", i); - strncpy(ci_state->desc, cstates[i].desc, CPUIDLE_DESC_LEN); - } - - dev->state_count = ARRAY_SIZE(cstates); - - dev->safe_state = &dev->states[0]; /* Currently not used */ - - return cpuidle_register_device(dev); -} - -struct cpuidle_driver cpuidle_drv = { - .name = "cpuidle_driver", - .owner = THIS_MODULE, -}; - -static int __init cpuidle_driver_init(void) -{ - int res = -ENODEV; - int cpu; - - if (ux500_is_svp()) - goto out; - - /* Configure wake up reasons */ - prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | - PRCMU_WAKEUP(ABB)); - - ux500_ci_dbg_init(); - - for_each_possible_cpu(cpu) - per_cpu(cpu_state, cpu) = kzalloc(sizeof(struct cpu_state), - GFP_KERNEL); - - res = cpuidle_register_driver(&cpuidle_drv); - if (res) - goto out; - - for_each_possible_cpu(cpu) { - res = init_cstates(cpu, per_cpu(cpu_state, cpu)); - if (res) - goto out; - pr_info("cpuidle: initiated for CPU%d.\n", cpu); - } - return 0; -out: - pr_err("cpuidle: initialization failed.\n"); - return res; -} - -static void __exit cpuidle_driver_exit(void) -{ - int cpu; - struct cpuidle_device *dev; - - ux500_ci_dbg_remove(); - - for_each_possible_cpu(cpu) { - dev = &per_cpu(cpu_state, cpu)->dev; - cpuidle_unregister_device(dev); - } - - for_each_possible_cpu(cpu) - kfree(per_cpu(cpu_state, cpu)); - - cpuidle_unregister_driver(&cpuidle_drv); -} - -late_initcall(cpuidle_driver_init); -module_exit(cpuidle_driver_exit); - -MODULE_DESCRIPTION("U8500 cpuidle driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Rickard Andersson <rickard.andersson@stericsson.com>"); diff --git a/arch/arm/mach-ux500/pm/cpuidle.h b/arch/arm/mach-ux500/pm/cpuidle.h deleted file mode 100644 index 265cce7de59..00000000000 --- a/arch/arm/mach-ux500/pm/cpuidle.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Rickard Andersson <rickard.andersson@stericsson.com> for - * ST-Ericsson. Loosly based on cpuidle.c by Sundar Iyer. - * License terms: GNU General Public License (GPL) version 2 - * - */ - -#ifndef __CPUIDLE_H -#define __CPUIDLE_H - -#include <linux/cpuidle.h> - -enum ARM { - ARM_OFF, - ARM_RET, - ARM_ON -}; - -enum APE { - APE_OFF, - APE_ON -}; - -enum UL_PLL { - UL_PLL_OFF, - UL_PLL_ON -}; - -enum ESRAM { - ESRAM_OFF, - ESRAM_RET -}; - -enum ci_pwrst { - CI_RUNNING = 0, /* Must be the same number as entry in cstates */ - CI_WFI = 1, /* Must be the same number as entry in cstates */ - CI_IDLE, - CI_SLEEP, - CI_DEEP_IDLE, - CI_DEEP_SLEEP, -}; - -struct cstate { - /* Required state of different hardwares */ - enum ARM ARM; - enum APE APE; - enum UL_PLL UL_PLL; - /* ESRAM = ESRAM_RET means that ESRAM context to be kept */ - enum ESRAM ESRAM; - - u32 enter_latency; - u32 exit_latency; - u32 power_usage; - u32 threshold; - u32 flags; - u8 pwrst; - - /* Only used for debugging purpose */ - enum ci_pwrst state; - char desc[CPUIDLE_DESC_LEN]; -}; - -struct cstate *ux500_ci_get_cstates(int *len); - -#endif diff --git a/arch/arm/mach-ux500/pm/cpuidle_dbg.c b/arch/arm/mach-ux500/pm/cpuidle_dbg.c deleted file mode 100644 index 344d7b8a0ed..00000000000 --- a/arch/arm/mach-ux500/pm/cpuidle_dbg.c +++ /dev/null @@ -1,950 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010-2011 - * - * License Terms: GNU General Public License v2 - * Author: Rickard Andersson <rickard.andersson@stericsson.com>, - * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson - */ - -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/delay.h> -#include <linux/workqueue.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/uaccess.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/gpio/nomadik.h> -#include <linux/amba/serial.h> - -#include <asm/hardware/gic.h> - -#include "cpuidle.h" -#include "pm.h" -#include "timer.h" - -#define APE_ON_TIMER_INTERVAL 5 /* Seconds */ - -#define UART_RX_GPIO_PIN_MASK (1 << (CONFIG_UX500_CONSOLE_UART_GPIO_PIN % 32)) - -#define UART011_MIS_RTIS (1 << 6) /* receive timeout interrupt status */ -#define UART011_MIS_RXIS (1 << 4) /* receive interrupt status */ -#define UART011_MIS 0x40 /* Masked interrupt status register */ - -enum latency_type { - LATENCY_ENTER = 0, - LATENCY_EXIT, - LATENCY_WAKE, - NUM_LATENCY, -}; - -struct state_history_state { - u32 counter; - ktime_t time; - u32 hit_rate; - u32 state_ok; - u32 state_error; - u32 prcmu_int; - u32 pending_int; - - u32 latency_count[NUM_LATENCY]; - ktime_t latency_sum[NUM_LATENCY]; - ktime_t latency_min[NUM_LATENCY]; - ktime_t latency_max[NUM_LATENCY]; -}; - -struct state_history { - ktime_t start; - u32 state; - u32 exit_counter; - ktime_t measure_begin; - int ape_blocked; - int time_blocked; - int both_blocked; - int gov_blocked; - struct state_history_state *states; -}; -static DEFINE_PER_CPU(struct state_history, *state_history); - -static struct delayed_work cpuidle_work; -static u32 dbg_console_enable = 1; -static void __iomem *uart_base; -static struct clk *uart_clk; - -/* Blocks ApSleep and ApDeepSleep */ -static bool force_APE_on; -static bool reset_timer; -static int deepest_allowed_state = CONFIG_U8500_CPUIDLE_DEEPEST_STATE; -static u32 measure_latency; -static bool wake_latency; -static int verbose; - -static bool apidle_both_blocked; -static bool apidle_ape_blocked; -static bool apidle_time_blocked; -static bool apidle_gov_blocked; - -static struct cstate *cstates; -static int cstates_len; -static DEFINE_SPINLOCK(dbg_lock); - -bool ux500_ci_dbg_force_ape_on(void) -{ - clk_enable(uart_clk); - if (readw(uart_base + UART01x_FR) & UART01x_FR_BUSY) { - clk_disable(uart_clk); - return true; - } - clk_disable(uart_clk); - - return force_APE_on; -} - -int ux500_ci_dbg_deepest_state(void) -{ - return deepest_allowed_state; -} - -void ux500_ci_dbg_console_handle_ape_suspend(void) -{ - if (!dbg_console_enable) - return; - - irq_set_irq_wake(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), 1); - irq_set_irq_type(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), - IRQ_TYPE_EDGE_BOTH); -} - -void ux500_ci_dbg_console_handle_ape_resume(void) -{ - unsigned long flags; - u32 WKS_reg_value; - - if (!dbg_console_enable) - return; - - WKS_reg_value = ux500_pm_gpio_read_wake_up_status(0); - - if (WKS_reg_value & UART_RX_GPIO_PIN_MASK) { - spin_lock_irqsave(&dbg_lock, flags); - reset_timer = true; - spin_unlock_irqrestore(&dbg_lock, flags); - } - irq_set_irq_wake(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), 0); - -} - -void ux500_ci_dbg_console_check_uart(void) -{ - unsigned long flags; - u32 status; - - if (!dbg_console_enable) - return; - - clk_enable(uart_clk); - spin_lock_irqsave(&dbg_lock, flags); - status = readw(uart_base + UART011_MIS); - - if (status & (UART011_MIS_RTIS | UART011_MIS_RXIS)) - reset_timer = true; - - spin_unlock_irqrestore(&dbg_lock, flags); - clk_disable(uart_clk); -} - -void ux500_ci_dbg_console(void) -{ - unsigned long flags; - - if (!dbg_console_enable) - return; - - spin_lock_irqsave(&dbg_lock, flags); - if (reset_timer) { - reset_timer = false; - spin_unlock_irqrestore(&dbg_lock, flags); - - cancel_delayed_work(&cpuidle_work); - force_APE_on = true; - schedule_delayed_work(&cpuidle_work, - msecs_to_jiffies(APE_ON_TIMER_INTERVAL * - 1000)); - } else { - spin_unlock_irqrestore(&dbg_lock, flags); - } -} - -static void dbg_cpuidle_work_function(struct work_struct *work) -{ - force_APE_on = false; -} - -static void store_latency(struct state_history *sh, - int ctarget, - enum latency_type type, - ktime_t d, - bool lock) -{ - unsigned long flags = 0; - - if (lock) - spin_lock_irqsave(&dbg_lock, flags); - - sh->states[ctarget].latency_count[type]++; - - sh->states[ctarget].latency_sum[type] = - ktime_add(sh->states[ctarget].latency_sum[type], d); - - if (ktime_to_us(d) > ktime_to_us(sh->states[ctarget].latency_max[type])) - sh->states[ctarget].latency_max[type] = d; - - if (ktime_to_us(d) < ktime_to_us(sh->states[ctarget].latency_min[type])) - sh->states[ctarget].latency_min[type] = d; - - if (lock) - spin_unlock_irqrestore(&dbg_lock, flags); -} - -void ux500_ci_dbg_exit_latency(int ctarget, ktime_t now, ktime_t exit, - ktime_t enter) -{ - struct state_history *sh; - bool hit = true; - enum prcmu_idle_stat prcmu_status; - unsigned int d; - - if (!verbose) - return; - - sh = per_cpu(state_history, smp_processor_id()); - - sh->exit_counter++; - - d = ktime_to_us(ktime_sub(now, enter)); - - if ((ctarget + 1) < deepest_allowed_state) - hit = d < cstates[ctarget + 1].threshold; - if (d < cstates[ctarget].threshold) - hit = false; - - if (hit) - sh->states[ctarget].hit_rate++; - - if (cstates[ctarget].state < CI_IDLE) - return; - - prcmu_status = ux500_pm_prcmu_idle_stat(); - - switch (prcmu_status) { - - case DEEP_SLEEP_OK: - if (cstates[ctarget].state == CI_DEEP_SLEEP) - sh->states[ctarget].state_ok++; - break; - case SLEEP_OK: - if (cstates[ctarget].state == CI_SLEEP) - sh->states[ctarget].state_ok++; - break; - case IDLE_OK: - if (cstates[ctarget].state == CI_IDLE) - sh->states[ctarget].state_ok++; - break; - case DEEPIDLE_OK: - if (cstates[ctarget].state == CI_DEEP_IDLE) - sh->states[ctarget].state_ok++; - break; - case PRCMU2ARMPENDINGIT_ER: - sh->states[ctarget].prcmu_int++; - break; - case ARMPENDINGIT_ER: - sh->states[ctarget].pending_int++; - break; - default: - pr_info("cpuidle: unknown prcmu exit code: 0x%x state: %d\n", - prcmu_status, cstates[ctarget].state); - sh->states[ctarget].state_error++; - break; - } - - if (!measure_latency) - return; - - store_latency(sh, - ctarget, - LATENCY_EXIT, - ktime_sub(now, exit), - true); -} - -void ux500_ci_dbg_wake_latency(int ctarget, int sleep_time) -{ - struct state_history *sh; - ktime_t l; - ktime_t zero_time; - - if (!wake_latency || cstates[ctarget].state < CI_IDLE) - return; - - l = zero_time = ktime_set(0, 0); - sh = per_cpu(state_history, smp_processor_id()); - - if (cstates[ctarget].state >= CI_SLEEP) - l = u8500_rtc_exit_latency_get(); - - if (cstates[ctarget].state == CI_IDLE) { - ktime_t d = ktime_set(0, sleep_time * 1000); - ktime_t now = ktime_get(); - - d = ktime_add(d, sh->start); - if (ktime_to_us(now) > ktime_to_us(d)) - l = ktime_sub(now, d); - else - l = zero_time; - } - - if (!ktime_equal(zero_time, l)) - store_latency(sh, - ctarget, - LATENCY_WAKE, - l, - true); -} - -static void state_record_time(struct state_history *sh, int ctarget, - ktime_t now, ktime_t start, bool latency) -{ - ktime_t dtime; - - dtime = ktime_sub(now, sh->start); - sh->states[sh->state].time = ktime_add(sh->states[sh->state].time, - dtime); - - sh->start = now; - sh->state = ctarget; - - if (latency && cstates[ctarget].state != CI_RUNNING && measure_latency) - store_latency(sh, - ctarget, - LATENCY_ENTER, - ktime_sub(now, start), - false); - - sh->states[sh->state].counter++; -} - -void ux500_ci_dbg_register_reason(int idx, bool power_state_req, - u32 time, u32 max_depth) -{ - if (cstates[idx].state == CI_IDLE && verbose) { - apidle_ape_blocked = power_state_req; - apidle_time_blocked = time < cstates[idx + 1].threshold; - apidle_both_blocked = power_state_req && apidle_time_blocked; - apidle_gov_blocked = cstates[max_depth].state == CI_IDLE; - } -} - -void ux500_ci_dbg_log(int ctarget, ktime_t enter_time) -{ - int i; - ktime_t now; - unsigned long flags; - struct state_history *sh; - struct state_history *sh_other; - int this_cpu; - - this_cpu = smp_processor_id(); - - now = ktime_get(); - - sh = per_cpu(state_history, this_cpu); - - spin_lock_irqsave(&dbg_lock, flags); - - if (cstates[ctarget].state == CI_IDLE && verbose) { - if (apidle_both_blocked) - sh->both_blocked++; - if (apidle_ape_blocked) - sh->ape_blocked++; - if (apidle_time_blocked) - sh->time_blocked++; - if (apidle_gov_blocked) - sh->gov_blocked++; - } - - /* - * Check if current state is just a repeat of - * the state we're already in, then just quit. - */ - if (ctarget == sh->state) - goto done; - - state_record_time(sh, ctarget, now, enter_time, true); - - /* - * Update other cpus, (this_cpu = A, other cpus = B) if: - * - A = running and B != WFI | running: Set B to WFI - * - A = WFI and then B must be running: No changes - * - A = !WFI && !RUNNING and then B must be WFI: B sets to A - */ - - if (sh->state == CI_WFI) - goto done; - - for_each_possible_cpu(i) { - - if (this_cpu == i) - continue; - - sh_other = per_cpu(state_history, i); - - /* Same state, continue */ - if (sh_other->state == sh->state) - continue; - - if (cstates[ctarget].state == CI_RUNNING && - cstates[sh_other->state].state != CI_WFI) { - state_record_time(sh_other, CI_WFI, now, - enter_time, false); - continue; - } - /* - * This cpu is something else than running or wfi, both must be - * in the same state. - */ - state_record_time(sh_other, ctarget, now, enter_time, true); - } -done: - spin_unlock_irqrestore(&dbg_lock, flags); -} - -static void state_history_reset(void) -{ - unsigned long flags; - unsigned int cpu; - int i, j; - struct state_history *sh; - - spin_lock_irqsave(&dbg_lock, flags); - - for_each_possible_cpu(cpu) { - sh = per_cpu(state_history, cpu); - for (i = 0; i < cstates_len; i++) { - sh->states[i].counter = 0; - sh->states[i].hit_rate = 0; - sh->states[i].state_ok = 0; - sh->states[i].state_error = 0; - sh->states[i].prcmu_int = 0; - sh->states[i].pending_int = 0; - - sh->states[i].time = ktime_set(0, 0); - - for (j = 0; j < NUM_LATENCY; j++) { - sh->states[i].latency_count[j] = 0; - sh->states[i].latency_min[j] = ktime_set(0, - 10000000); - sh->states[i].latency_max[j] = ktime_set(0, 0); - sh->states[i].latency_sum[j] = ktime_set(0, 0); - } - } - - sh->start = ktime_get(); - sh->measure_begin = sh->start; - /* Don't touch sh->state, since that is where we are now */ - - sh->exit_counter = 0; - sh->ape_blocked = 0; - sh->time_blocked = 0; - sh->both_blocked = 0; - sh->gov_blocked = 0; - } - spin_unlock_irqrestore(&dbg_lock, flags); -} - -static int get_val(const char __user *user_buf, - size_t count, int min, int max) -{ - long unsigned val; - int err; - - err = kstrtoul_from_user(user_buf, count, 0, &val); - - if (err) - return err; - - if (val > max) - val = max; - if (val < min) - val = min; - - return val; -} - -static ssize_t set_deepest_state(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - int val; - - val = get_val(user_buf, count, CI_WFI, cstates_len - 1); - - if (val < 0) - return val; - - deepest_allowed_state = val; - - pr_debug("cpuidle: changed deepest allowed sleep state to %d.\n", - deepest_allowed_state); - - return count; -} - -static int deepest_state_print(struct seq_file *s, void *p) -{ - seq_printf(s, "Deepest allowed sleep state is %d\n", - deepest_allowed_state); - - return 0; -} - -static ssize_t stats_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - state_history_reset(); - return count; -} - -static int wake_latency_read(struct seq_file *s, void *p) -{ - seq_printf(s, "wake latency measurements is %s\n", - wake_latency ? "on" : "off"); - return 0; -} - -static ssize_t wake_latency_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - int val = get_val(user_buf, count, 0, 1); - if (val < 0) - return val; - - wake_latency = val; - ux500_rtcrtt_measure_latency(wake_latency); - return count; -} - -static int verbose_read(struct seq_file *s, void *p) -{ - seq_printf(s, "verbose debug is %s\n", verbose ? "on" : "off"); - return 0; -} - -static ssize_t verbose_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - int val = get_val(user_buf, count, 0, 1); - if (val < 0) - return val; - - verbose = val; - state_history_reset(); - - return count; -} - -static void stats_disp_one(struct seq_file *s, struct state_history *sh, - s64 total_us, int i) -{ - int j; - s64 avg[NUM_LATENCY]; - s64 t_us; - s64 perc; - ktime_t init_time, zero_time; - - init_time = ktime_set(0, 10000000); - zero_time = ktime_set(0, 0); - - memset(&avg, 0, sizeof(s64) * NUM_LATENCY); - - for (j = 0; j < NUM_LATENCY; j++) - avg[j] = ktime_to_us(sh->states[i].latency_sum[j]); - - t_us = ktime_to_us(sh->states[i].time); - perc = ktime_to_us(sh->states[i].time); - do_div(t_us, 1000); /* to ms */ - do_div(total_us, 100); - if (total_us) - do_div(perc, total_us); - - for (j = 0; j < NUM_LATENCY; j++) { - if (sh->states[i].latency_count[j]) - do_div(avg[j], sh->states[i].latency_count[j]); - } - - seq_printf(s, "\n%d - %s: %u", - i, cstates[i].desc, - sh->states[i].counter); - - if (sh->states[i].counter == 0) - return; - - if (i > CI_WFI && verbose) - seq_printf(s, " (%u prcmu_int:%u int:%u err:%u)", - sh->states[i].state_ok, - sh->states[i].prcmu_int, - sh->states[i].pending_int, - sh->states[i].state_error); - - seq_printf(s, " in %d ms %d%%", - (u32) t_us, (u32)perc); - - if (cstates[i].state == CI_IDLE && verbose) - seq_printf(s, ", reg:%d time:%d both:%d gov:%d", - sh->ape_blocked, sh->time_blocked, - sh->both_blocked, sh->gov_blocked); - - if (sh->states[i].counter && verbose) - seq_printf(s, ", hit rate: %u%% ", - 100 * sh->states[i].hit_rate / - sh->states[i].counter); - - if (i == CI_RUNNING || !(measure_latency || wake_latency)) - return; - - for (j = 0; j < NUM_LATENCY; j++) { - bool show = false; - if (!ktime_equal(sh->states[i].latency_min[j], init_time)) { - seq_printf(s, "\n\t\t\t\t"); - switch (j) { - case LATENCY_ENTER: - if (measure_latency) { - seq_printf(s, "enter: "); - show = true; - } - break; - case LATENCY_EXIT: - if (measure_latency) { - seq_printf(s, "exit: "); - show = true; - } - break; - case LATENCY_WAKE: - if (wake_latency) { - seq_printf(s, "wake: "); - show = true; - } - break; - default: - seq_printf(s, "unknown!: "); - break; - } - - if (!show) - continue; - - if (ktime_equal(sh->states[i].latency_min[j], - zero_time)) - seq_printf(s, "min < 30"); - else - seq_printf(s, "min %lld", - ktime_to_us(sh->states[i].latency_min[j])); - - seq_printf(s, " avg %lld max %lld us, count: %d", - avg[j], - ktime_to_us(sh->states[i].latency_max[j]), - sh->states[i].latency_count[j]); - } - } -} - -static int stats_print(struct seq_file *s, void *p) -{ - int cpu; - int i; - unsigned long flags; - struct state_history *sh; - ktime_t total, wall; - s64 total_us, total_s; - - for_each_online_cpu(cpu) { - sh = per_cpu(state_history, cpu); - spin_lock_irqsave(&dbg_lock, flags); - seq_printf(s, "\nCPU%d\n", cpu); - - total = ktime_set(0, 0); - - for (i = 0; i < cstates_len; i++) - total = ktime_add(total, sh->states[i].time); - - wall = ktime_sub(ktime_get(), sh->measure_begin); - - total_us = ktime_to_us(wall); - total_s = ktime_to_ms(wall); - - do_div(total_s, 1000); - - if (verbose) { - if (total_s) - seq_printf(s, - "wake ups per s: %u.%u \n", - sh->exit_counter / (int) total_s, - (10 * sh->exit_counter / (int) total_s) - - 10 * (sh->exit_counter / (int) total_s)); - - seq_printf(s, - "\ndelta accounted vs wall clock: %lld us\n", - ktime_to_us(ktime_sub(wall, total))); - } - - for (i = 0; i < cstates_len; i++) - stats_disp_one(s, sh, total_us, i); - - seq_printf(s, "\n"); - spin_unlock_irqrestore(&dbg_lock, flags); - } - seq_printf(s, "\n"); - return 0; -} - - -static int ap_family_show(struct seq_file *s, void *iter) -{ - int i; - u32 count = 0; - unsigned long flags; - struct state_history *sh; - - sh = per_cpu(state_history, 0); - spin_lock_irqsave(&dbg_lock, flags); - - for (i = 0 ; i < cstates_len; i++) { - if (cstates[i].state == (enum ci_pwrst)s->private) - count += sh->states[i].counter; - } - - seq_printf(s, "%u\n", count); - spin_unlock_irqrestore(&dbg_lock, flags); - - return 0; -} - -static int deepest_state_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, deepest_state_print, inode->i_private); -} - -static int verbose_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, verbose_read, inode->i_private); -} - -static int stats_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, stats_print, inode->i_private); -} - -static int ap_family_open(struct inode *inode, - struct file *file) -{ - return single_open(file, ap_family_show, inode->i_private); -} - -static int wake_latency_open(struct inode *inode, - struct file *file) -{ - return single_open(file, wake_latency_read, inode->i_private); -} - -static const struct file_operations deepest_state_fops = { - .open = deepest_state_open_file, - .write = set_deepest_state, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations verbose_state_fops = { - .open = verbose_open_file, - .write = verbose_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations stats_fops = { - .open = stats_open_file, - .write = stats_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations ap_family_fops = { - .open = ap_family_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations wake_latency_fops = { - .open = wake_latency_open, - .write = wake_latency_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static struct dentry *cpuidle_dir; - -static void __init setup_debugfs(void) -{ - cpuidle_dir = debugfs_create_dir("cpuidle", NULL); - if (IS_ERR_OR_NULL(cpuidle_dir)) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("deepest_state", - S_IWUGO | S_IRUGO, cpuidle_dir, - NULL, &deepest_state_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("verbose", - S_IWUGO | S_IRUGO, cpuidle_dir, - NULL, &verbose_state_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("stats", - S_IRUGO, cpuidle_dir, NULL, - &stats_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_bool("dbg_console_enable", - S_IWUGO | S_IRUGO, cpuidle_dir, - &dbg_console_enable))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_bool("measure_latency", - S_IWUGO | S_IRUGO, cpuidle_dir, - &measure_latency))) - goto fail; - - - if (IS_ERR_OR_NULL(debugfs_create_file("wake_latency", - S_IWUGO | S_IRUGO, cpuidle_dir, - NULL, - &wake_latency_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("ap_idle", S_IRUGO, - cpuidle_dir, - (void *)CI_IDLE, - &ap_family_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("ap_sleep", S_IRUGO, - cpuidle_dir, - (void *)CI_SLEEP, - &ap_family_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("ap_deepidle", S_IRUGO, - cpuidle_dir, - (void *)CI_DEEP_IDLE, - &ap_family_fops))) - goto fail; - - if (IS_ERR_OR_NULL(debugfs_create_file("ap_deepsleep", S_IRUGO, - cpuidle_dir, - (void *)CI_DEEP_SLEEP, - &ap_family_fops))) - goto fail; - - return; -fail: - debugfs_remove_recursive(cpuidle_dir); -} - -#define __UART_BASE(soc, x) soc##_UART##x##_BASE -#define UART_BASE(soc, x) __UART_BASE(soc, x) - -void __init ux500_ci_dbg_init(void) -{ - static const char clkname[] __initconst - = "uart" __stringify(CONFIG_UX500_DEBUG_UART); - unsigned long baseaddr; - int cpu; - - struct state_history *sh; - - cstates = ux500_ci_get_cstates(&cstates_len); - - if (deepest_allowed_state > cstates_len) - deepest_allowed_state = cstates_len; - - for_each_possible_cpu(cpu) { - per_cpu(state_history, cpu) = kzalloc(sizeof(struct state_history), - GFP_KERNEL); - sh = per_cpu(state_history, cpu); - sh->states = kzalloc(sizeof(struct state_history_state) - * cstates_len, - GFP_KERNEL); - } - - state_history_reset(); - - for_each_possible_cpu(cpu) { - sh = per_cpu(state_history, cpu); - /* Only first CPU used during boot */ - if (cpu == 0) - sh->state = CI_RUNNING; - else - sh->state = CI_WFI; - } - - setup_debugfs(); - - /* Uart debug init */ - - if (cpu_is_u8500()) - baseaddr = UART_BASE(U8500, CONFIG_UX500_DEBUG_UART); - else if (cpu_is_u5500()) - baseaddr = UART_BASE(U5500, CONFIG_UX500_DEBUG_UART); - else - ux500_unknown_soc(); - - uart_base = ioremap(baseaddr, SZ_4K); - BUG_ON(!uart_base); - - uart_clk = clk_get_sys(clkname, NULL); - BUG_ON(IS_ERR(uart_clk)); - - INIT_DELAYED_WORK_DEFERRABLE(&cpuidle_work, dbg_cpuidle_work_function); - -} - -void ux500_ci_dbg_remove(void) -{ - int cpu; - struct state_history *sh; - - debugfs_remove_recursive(cpuidle_dir); - - for_each_possible_cpu(cpu) { - sh = per_cpu(state_history, cpu); - kfree(sh->states); - kfree(sh); - } - - iounmap(uart_base); -} diff --git a/arch/arm/mach-ux500/pm/cpuidle_dbg.h b/arch/arm/mach-ux500/pm/cpuidle_dbg.h deleted file mode 100644 index b660b039900..00000000000 --- a/arch/arm/mach-ux500/pm/cpuidle_dbg.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010-2011 - * - * License Terms: GNU General Public License v2 - * Author: Rickard Andersson <rickard.andersson@stericsson.com> for ST-Ericsson - * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson - */ - -#ifndef CPUIDLE_DBG_H -#define CPUIDLE_DBG_H - -#include "cpuidle.h" - -#ifdef CONFIG_U8500_CPUIDLE_DEBUG -void ux500_ci_dbg_init(void); -void ux500_ci_dbg_remove(void); - -void ux500_ci_dbg_log(int ctarget, ktime_t enter_time); -void ux500_ci_dbg_wake_latency(int ctarget, int sleep_time); -void ux500_ci_dbg_exit_latency(int ctarget, ktime_t now, ktime_t exit, - ktime_t enter); - -void ux500_ci_dbg_register_reason(int idx, bool power_state_req, - u32 sleep_time, u32 max_depth); - -bool ux500_ci_dbg_force_ape_on(void); -int ux500_ci_dbg_deepest_state(void); - -void ux500_ci_dbg_console(void); -void ux500_ci_dbg_console_check_uart(void); -void ux500_ci_dbg_console_handle_ape_resume(void); -void ux500_ci_dbg_console_handle_ape_suspend(void); - -#else - -static inline void ux500_ci_dbg_init(void) { } -static inline void ux500_ci_dbg_remove(void) { } - -static inline void ux500_ci_dbg_log(int ctarget, - ktime_t enter_time) { } - -static inline void ux500_ci_dbg_exit_latency(int ctarget, - ktime_t now, ktime_t exit, - ktime_t enter) { } -static inline void ux500_ci_dbg_wake_latency(int ctarget, int sleep_time) { } - - -static inline void ux500_ci_dbg_register_reason(int idx, bool power_state_req, - u32 sleep_time, u32 max_depth) { } - -static inline bool ux500_ci_dbg_force_ape_on(void) -{ - return false; -} - -static inline int ux500_ci_dbg_deepest_state(void) -{ - /* This means no lower sleep state than ApIdle */ - return CONFIG_U8500_CPUIDLE_DEEPEST_STATE; -} - -static inline void ux500_ci_dbg_console(void) { } -static inline void ux500_ci_dbg_console_check_uart(void) { } -static inline void ux500_ci_dbg_console_handle_ape_resume(void) { } -static inline void ux500_ci_dbg_console_handle_ape_suspend(void) { } - -#endif -#endif diff --git a/arch/arm/mach-ux500/pm/performance.c b/arch/arm/mach-ux500/pm/performance.c deleted file mode 100644 index 81d918107b9..00000000000 --- a/arch/arm/mach-ux500/pm/performance.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - * Author: Johan Rudholm <johan.rudholm@stericsson.com> - */ - -#include <linux/kernel.h> -#include <mach/prcmu-qos.h> -#include <linux/genhd.h> -#include <linux/major.h> -#include <linux/cdev.h> - -/* - * TODO: - * o Develop a more power-aware algorithm - * o Make the parameters visible through debugfs - * o Get the value of CONFIG_MMC_BLOCK_MINORS in runtime instead, since - * it may be altered by drivers/mmc/card/block.c - */ - -/* Sample reads and writes every n ms */ -#define PERF_MMC_PROBE_DELAY 1000 -/* Read threshold, sectors/second */ -#define PERF_MMC_LIMIT_READ 10240 -/* Write threshold, sectors/second */ -#define PERF_MMC_LIMIT_WRITE 8192 -/* Nr of MMC devices */ -#define PERF_MMC_HOSTS 8 - -/* - * Rescan for new MMC devices every - * PERF_MMC_PROBE_DELAY * PERF_MMC_RESCAN_CYCLES ms - */ -#define PERF_MMC_RESCAN_CYCLES 10 - -static struct delayed_work work_mmc; - -/* - * Loop through every CONFIG_MMC_BLOCK_MINORS'th minor device for - * MMC_BLOCK_MAJOR, get the struct gendisk for each device. Returns - * nr of found disks. Populate mmc_disks. - */ -static int scan_mmc_devices(struct gendisk *mmc_disks[]) -{ - dev_t devnr; - int i, j = 0, part; - struct gendisk *mmc_devices[256 / CONFIG_MMC_BLOCK_MINORS]; - - memset(&mmc_devices, 0, sizeof(mmc_devices)); - - for (i = 0; i * CONFIG_MMC_BLOCK_MINORS < 256; i++) { - devnr = MKDEV(MMC_BLOCK_MAJOR, i * CONFIG_MMC_BLOCK_MINORS); - mmc_devices[i] = get_gendisk(devnr, &part); - - /* Invalid capacity of device, do not add to list */ - if (!mmc_devices[i] || !get_capacity(mmc_devices[i])) - continue; - - mmc_disks[j] = mmc_devices[i]; - j++; - - if (j == PERF_MMC_HOSTS) - break; - } - - return j; -} - -/* - * Sample sectors read and written to any MMC devices, update PRCMU - * qos requirement - */ -static void mmc_load(struct work_struct *work) -{ - static unsigned long long old_sectors_read[PERF_MMC_HOSTS]; - static unsigned long long old_sectors_written[PERF_MMC_HOSTS]; - static struct gendisk *mmc_disks[PERF_MMC_HOSTS]; - static int cycle, nrdisk; - static bool old_mode; - unsigned long long sectors; - bool new_mode = false; - int i; - - if (!cycle) { - memset(&mmc_disks, 0, sizeof(mmc_disks)); - nrdisk = scan_mmc_devices(mmc_disks); - cycle = PERF_MMC_RESCAN_CYCLES; - } - cycle--; - - for (i = 0; i < nrdisk; i++) { - sectors = part_stat_read(&(mmc_disks[i]->part0), - sectors[READ]); - - if (old_sectors_read[i] && - sectors > old_sectors_read[i] && - (sectors - old_sectors_read[i]) > - PERF_MMC_LIMIT_READ) - new_mode = true; - - old_sectors_read[i] = sectors; - sectors = part_stat_read(&(mmc_disks[i]->part0), - sectors[WRITE]); - - if (old_sectors_written[i] && - sectors > old_sectors_written[i] && - (sectors - old_sectors_written[i]) > - PERF_MMC_LIMIT_WRITE) - new_mode = true; - - old_sectors_written[i] = sectors; - } - - if (!old_mode && new_mode) - prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, - "mmc", 125); - - if (old_mode && !new_mode) - prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, - "mmc", 25); - - old_mode = new_mode; - - schedule_delayed_work(&work_mmc, - msecs_to_jiffies(PERF_MMC_PROBE_DELAY)); - -} - - -static int __init performance_register(void) -{ - int ret; - - prcmu_qos_add_requirement(PRCMU_QOS_ARM_OPP, "mmc", 25); - - INIT_DELAYED_WORK_DEFERRABLE(&work_mmc, mmc_load); - ret = schedule_delayed_work(&work_mmc, - msecs_to_jiffies(PERF_MMC_PROBE_DELAY)); - - return ret; -} -late_initcall(performance_register); diff --git a/arch/arm/mach-ux500/pm/pm.c b/arch/arm/mach-ux500/pm/pm.c deleted file mode 100644 index ae6951ede45..00000000000 --- a/arch/arm/mach-ux500/pm/pm.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Rickard Andersson <rickard.andersson@stericsson.com> for - * ST-Ericsson. - * License terms: GNU General Public License (GPL) version 2 - * - */ - -#include <linux/io.h> -#include <linux/percpu.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/gpio.h> -#include <linux/gpio/nomadik.h> - -#include <asm/hardware/gic.h> -#include <asm/processor.h> - -#include <mach/hardware.h> -#include <mach/prcmu-regs.h> - -#include "pm.h" - -#define STABILIZATION_TIME 30 /* us */ -#define GIC_FREEZE_DELAY 1 /* us */ - -#define PRCM_ARM_WFI_STANDBY_CPU0_WFI 0x8 -#define PRCM_ARM_WFI_STANDBY_CPU1_WFI 0x10 - -static u32 u8500_gpio_banks[] = {U8500_GPIOBANK0_BASE, - U8500_GPIOBANK1_BASE, - U8500_GPIOBANK2_BASE, - U8500_GPIOBANK3_BASE, - U8500_GPIOBANK4_BASE, - U8500_GPIOBANK5_BASE, - U8500_GPIOBANK6_BASE, - U8500_GPIOBANK7_BASE, - U8500_GPIOBANK8_BASE}; - -static u32 u5500_gpio_banks[] = {U5500_GPIOBANK0_BASE, - U5500_GPIOBANK1_BASE, - U5500_GPIOBANK2_BASE, - U5500_GPIOBANK3_BASE, - U5500_GPIOBANK4_BASE, - U5500_GPIOBANK5_BASE, - U5500_GPIOBANK6_BASE, - U5500_GPIOBANK7_BASE}; - -static u32 ux500_gpio_wks[ARRAY_SIZE(u8500_gpio_banks)]; - -inline int ux500_pm_arm_on_ext_clk(bool leave_arm_pll_on) -{ - return 0; -} - -/* Decouple GIC from the interrupt bus */ -void ux500_pm_gic_decouple(void) -{ - writel(readl(PRCM_A9_MASK_REQ) | PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ, - PRCM_A9_MASK_REQ); - - while (!readl(PRCM_A9_MASK_REQ)) - cpu_relax(); - - /* TODO: Use the ack bit when possible */ - udelay(GIC_FREEZE_DELAY); /* Wait for the GIC to freeze */ -} - -/* Recouple GIC with the interrupt bus */ -void ux500_pm_gic_recouple(void) -{ - writel((readl(PRCM_A9_MASK_REQ) & ~PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ), - PRCM_A9_MASK_REQ); - - /* TODO: Use the ack bit when possible */ -} - -#define GIC_NUMBER_REGS 5 -bool ux500_pm_gic_pending_interrupt(void) -{ - u32 pr; /* Pending register */ - u32 er; /* Enable register */ - int i; - - /* 5 registers. STI & PPI not skipped */ - for (i = 0; i < GIC_NUMBER_REGS; i++) { - - pr = readl_relaxed(__io_address(U8500_GIC_DIST_BASE) + - GIC_DIST_PENDING_SET + i * 4); - er = readl_relaxed(__io_address(U8500_GIC_DIST_BASE) + - GIC_DIST_ENABLE_SET + i * 4); - - if (pr & er) - return true; /* There is a pending interrupt */ - } - return false; -} - -#define GIC_NUMBER_SPI_REGS 4 -bool ux500_pm_prcmu_pending_interrupt(void) -{ - u32 it; - u32 im; - int i; - - for (i = 0; i < GIC_NUMBER_SPI_REGS; i++) { /* There are 4 registers */ - - it = readl(PRCM_ARMITVAL31TO0 + i * 4); - im = readl(PRCM_ARMITMSK31TO0 + i * 4); - - if (it & im) - return true; /* There is a pending interrupt */ - } - - return false; -} - -void ux500_pm_prcmu_set_ioforce(bool enable) -{ - if (enable) - writel(readl(PRCM_IOCR) | PRCM_IOCR_IOFORCE, PRCM_IOCR); - else - writel(readl(PRCM_IOCR) & ~PRCM_IOCR_IOFORCE, PRCM_IOCR); -} - -void ux500_pm_prcmu_copy_gic_settings(void) -{ - u32 er; /* Enable register */ - int i; - - for (i = 0; i < GIC_NUMBER_SPI_REGS; i++) { /* 4*32 SPI interrupts */ - /* +1 due to skip STI and PPI */ - er = readl_relaxed(__io_address(U8500_GIC_DIST_BASE) + - GIC_DIST_ENABLE_SET + (i + 1) * 4); - writel(er, PRCM_ARMITMSK31TO0 + i * 4); - } -} - -void ux500_pm_gpio_save_wake_up_status(void) -{ - int num_banks; - u32 *banks; - int i; - - if (cpu_is_u5500()) { - num_banks = ARRAY_SIZE(u5500_gpio_banks); - banks = u5500_gpio_banks; - } else { - num_banks = ARRAY_SIZE(u8500_gpio_banks); - banks = u8500_gpio_banks; - } - - nmk_gpio_clocks_enable(); - - for (i = 0; i < num_banks; i++) - ux500_gpio_wks[i] = readl(__io_address(banks[i]) + NMK_GPIO_WKS); - - nmk_gpio_clocks_disable(); -} - -u32 ux500_pm_gpio_read_wake_up_status(unsigned int bank_num) -{ - if (WARN_ON(cpu_is_u5500() && bank_num >= - ARRAY_SIZE(u5500_gpio_banks))) - return 0; - - if (WARN_ON(cpu_is_u8500() && bank_num >= - ARRAY_SIZE(u8500_gpio_banks))) - return 0; - - return ux500_gpio_wks[bank_num]; -} - -/* Check if the other CPU is in WFI */ -bool ux500_pm_other_cpu_wfi(void) -{ - if (smp_processor_id()) { - /* We are CPU 1 => check if CPU0 is in WFI */ - if (readl(PRCM_ARM_WFI_STANDBY) & - PRCM_ARM_WFI_STANDBY_CPU0_WFI) - return true; - } else { - /* We are CPU 0 => check if CPU1 is in WFI */ - if (readl(PRCM_ARM_WFI_STANDBY) & - PRCM_ARM_WFI_STANDBY_CPU1_WFI) - return true; - } - - return false; -} - -/* PRCM_ACK_MB0_AP_PWRSTTR_STATUS */ -#define DB8500_PRCMU_STATUS_REGISTER 0x801b8e08 -#define DB5500_PRCMU_STATUS_REGISTER 0x80168f38 - -enum prcmu_idle_stat ux500_pm_prcmu_idle_stat(void) -{ - u32 val; - void __iomem *prcmu_status_reg; - - if (cpu_is_u8500()) - prcmu_status_reg = __io_address(DB8500_PRCMU_STATUS_REGISTER); - else if (cpu_is_u5500()) - prcmu_status_reg = __io_address(DB5500_PRCMU_STATUS_REGISTER); - else - ux500_unknown_soc(); - - val = readl(prcmu_status_reg) & 0xff; - - return (enum prcmu_idle_stat)val; -} diff --git a/arch/arm/mach-ux500/pm/pm.h b/arch/arm/mach-ux500/pm/pm.h index 8b58bd52e18..af95d7b2325 100644 --- a/arch/arm/mach-ux500/pm/pm.h +++ b/arch/arm/mach-ux500/pm/pm.h @@ -10,113 +10,9 @@ #define PM_COMMON_H #ifdef CONFIG_PM - -enum prcmu_idle_stat { - SLEEP_OK = 0xf3, - DEEP_SLEEP_OK = 0xf6, - IDLE_OK = 0xf0, - DEEPIDLE_OK = 0xe3, - PRCMU2ARMPENDINGIT_ER = 0x91, - ARMPENDINGIT_ER = 0x93, -}; - -/** - * ux500_pm_gic_decouple() - * - * Decouple GIC from the interrupt bus. - */ -void ux500_pm_gic_decouple(void); - -/** - * ux500_pm_gic_recouple() - * - * Recouple GIC with the interrupt bus. - */ -void ux500_pm_gic_recouple(void); - -/** - * ux500_pm_gic_pending_interrupt() - * - * returns true, if there are pending interrupts. - */ -bool ux500_pm_gic_pending_interrupt(void); - -/** - * ux500_pm_prcmu_pending_interrupt() - * - * returns true, if there are pending interrupts. - */ -bool ux500_pm_prcmu_pending_interrupt(void); - -/** - * ux500_pm_prcmu_set_ioforce() - * - * @enable: Enable/disable - * - * Enable/disable the gpio-ring - */ -void ux500_pm_prcmu_set_ioforce(bool enable); - -/** - * ux500_pm_prcmu_copy_gic_settings() - * - * This function copies all the gic interrupt settings to the prcmu. - * This is needed for the system to catch interrupts in ApIdle - */ -void ux500_pm_prcmu_copy_gic_settings(void); - -/** - * ux500_pm_gpio_save_wake_up_status() - * - * This function is called when the prcmu has woken the ARM - * but before ioforce is disabled. - */ -void ux500_pm_gpio_save_wake_up_status(void); - -/** - * ux500_pm_gpio_read_wake_up_status() - * - * @bank_number: The gpio bank. - * - * Returns the WKS register settings for given bank number. - * The WKS register is cleared when ioforce is released therefore - * this function is needed. - */ -u32 ux500_pm_gpio_read_wake_up_status(unsigned int bank_number); - -/** - * ux500_pm_other_cpu_wfi() - * - * Returns true if the other CPU is in WFI. - */ -bool ux500_pm_other_cpu_wfi(void); - -/** - * ux500_pm_prcmu_idle_stat() - * - * Returns the status of the last prcmu idle/sleep - */ -enum prcmu_idle_stat ux500_pm_prcmu_idle_stat(void); - struct dev_power_domain; extern struct dev_power_domain ux500_dev_power_domain; extern struct dev_power_domain ux500_amba_dev_power_domain; - -#else -u32 ux500_pm_gpio_read_wake_up_status(unsigned int bank_number) -{ - return 0; -} - -/** - * ux500_pm_prcmu_set_ioforce() - * - * @enable: Enable/disable - * - * Enable/disable the gpio-ring - */ -static inline void ux500_pm_prcmu_set_ioforce(bool enable) { } - #endif #endif diff --git a/arch/arm/mach-ux500/pm/suspend.c b/arch/arm/mach-ux500/pm/suspend.c deleted file mode 100644 index f0a9433b9fb..00000000000 --- a/arch/arm/mach-ux500/pm/suspend.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) STMicroelectronics 2009 - * Copyright (C) ST-Ericsson SA 2010-2011 - * - * License Terms: GNU General Public License v2 - * - * Authors: Rickard Andersson <rickard.andersson@stericsson.com>, - * Jonas Aaberg <jonas.aberg@stericsson.com>, - * Sundar Iyer for ST-Ericsson. - * - */ - -#include <linux/suspend.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/regulator/ab8500-debug.h> -#include <linux/gpio/nomadik.h> - -#include <mach/prcmu.h> -#include <mach/prcmu-regs.h> -#include <mach/prcmu-qos.h> -#include <mach/regulator.h> - -#include "context.h" -#include "pm.h" -#include "suspend_dbg.h" - -static void (*pins_suspend_force)(void); -static void (*pins_suspend_force_mux)(void); - -void suspend_set_pins_force_fn(void (*force)(void), void (*force_mux)(void)) -{ - pins_suspend_force = force; - pins_suspend_force_mux = force_mux; -} - -static atomic_t block_sleep = ATOMIC_INIT(0); - -void suspend_block_sleep(void) -{ - atomic_inc(&block_sleep); -} - -void suspend_unblock_sleep(void) -{ - atomic_dec(&block_sleep); -} - -static bool sleep_is_blocked(void) -{ - return (atomic_read(&block_sleep) != 0); -} - -static int suspend(bool do_deepsleep) -{ - bool pins_force = pins_suspend_force_mux && pins_suspend_force; - int ret = 0; - - if (sleep_is_blocked()) { - pr_info("suspend/resume: interrupted by modem.\n"); - return -EBUSY; - } - - nmk_gpio_clocks_enable(); - - ux500_suspend_dbg_add_wake_on_uart(); - nmk_gpio_wakeups_suspend(); - - /* configure the prcm for a sleep wakeup */ - prcmu_enable_wakeups(PRCMU_WAKEUP(ABB)); - - context_vape_save(); - - if (pins_force) { - /* - * Save GPIO settings before applying power save - * settings - */ - context_gpio_save(); - - /* Apply GPIO power save mux settings */ - context_gpio_mux_safe_switch(true); - pins_suspend_force_mux(); - context_gpio_mux_safe_switch(false); - - /* Apply GPIO power save settings */ - pins_suspend_force(); - } - - ux500_pm_gic_decouple(); - - if (ux500_pm_gic_pending_interrupt()) { - pr_info("suspend/resume: pending interrupt\n"); - - /* Recouple GIC with the interrupt bus */ - ux500_pm_gic_recouple(); - ret = -EBUSY; - - goto exit; - } - ux500_pm_prcmu_set_ioforce(true); - - if (do_deepsleep) { - context_varm_save_common(); - context_varm_save_core(); - context_gic_dist_disable_unneeded_irqs(); - context_save_cpu_registers(); - - /* - * Due to we have only 100us between requesting a powerstate - * and wfi, we clean the cache before as well to assure the - * final cache clean before wfi has as little as possible to - * do. - */ - context_clean_l1_cache_all(); - - (void) prcmu_set_power_state(PRCMU_AP_DEEP_SLEEP, - false, false); - context_save_to_sram_and_wfi(true); - - context_restore_cpu_registers(); - context_varm_restore_core(); - context_varm_restore_common(); - - } else { - - context_clean_l1_cache_all(); - (void) prcmu_set_power_state(APEXECUTE_TO_APSLEEP, - false, false); - dsb(); - __asm__ __volatile__("wfi\n\t" : : : "memory"); - } - - context_vape_restore(); - - /* If GPIO woke us up then save the pins that caused the wake up */ - ux500_pm_gpio_save_wake_up_status(); - - ux500_suspend_dbg_sleep_status(do_deepsleep); - - /* APE was turned off, restore IO ring */ - ux500_pm_prcmu_set_ioforce(false); - -exit: - if (pins_force) { - /* Restore gpio settings */ - context_gpio_mux_safe_switch(true); - context_gpio_restore_mux(); - context_gpio_mux_safe_switch(false); - context_gpio_restore(); - } - - /* This is what cpuidle wants */ - prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) | - PRCMU_WAKEUP(ABB)); - - nmk_gpio_wakeups_resume(); - ux500_suspend_dbg_remove_wake_on_uart(); - - nmk_gpio_clocks_disable(); - - return ret; -} - -static int ux500_suspend_enter(suspend_state_t state) -{ - - if (ux500_suspend_enabled()) { - if (ux500_suspend_deepsleep_enabled() && - state == PM_SUSPEND_MEM) - return suspend(true); - if (ux500_suspend_sleep_enabled()) - return suspend(false); - } - - ux500_suspend_dbg_add_wake_on_uart(); - /* - * Set IOFORCE in order to wake on GPIO the same way - * as in deeper sleep. - * (U5500 is not ready for IOFORCE) - */ - if (!cpu_is_u5500()) - ux500_pm_prcmu_set_ioforce(true); - - dsb(); - __asm__ __volatile__("wfi\n\t" : : : "memory"); - - if (!cpu_is_u5500()) - ux500_pm_prcmu_set_ioforce(false); - ux500_suspend_dbg_remove_wake_on_uart(); - - return 0; -} - -static int ux500_suspend_valid(suspend_state_t state) -{ - return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; -} - -static int ux500_suspend_prepare_late(void) -{ - /* ESRAM to retention instead of OFF until ROM is fixed */ - (void)prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); - ab8500_regulator_debug_force(); - ux500_regulator_suspend_debug(); - - return 0; -} - -static void ux500_suspend_wake(void) -{ - ux500_regulator_resume_debug(); - ab8500_regulator_debug_restore(); - (void)prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET); -} - -static int ux500_suspend_begin(suspend_state_t state) -{ - prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, - "suspend", 100); - return ux500_suspend_dbg_begin(state); -} - -static void ux500_suspend_end(void) -{ - prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, - "suspend", 25); -} - -static struct platform_suspend_ops ux500_suspend_ops = { - .enter = ux500_suspend_enter, - .valid = ux500_suspend_valid, - .prepare_late = ux500_suspend_prepare_late, - .wake = ux500_suspend_wake, - .begin = ux500_suspend_begin, - .end = ux500_suspend_end, -}; - -static __init int ux500_suspend_init(void) -{ - ux500_suspend_dbg_init(); - - prcmu_qos_add_requirement(PRCMU_QOS_ARM_OPP, "suspend", 25); - - suspend_set_ops(&ux500_suspend_ops); - return 0; -} - -device_initcall(ux500_suspend_init); diff --git a/arch/arm/mach-ux500/pm/suspend_dbg.c b/arch/arm/mach-ux500/pm/suspend_dbg.c deleted file mode 100644 index d89e280c9dd..00000000000 --- a/arch/arm/mach-ux500/pm/suspend_dbg.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * - * Author: Rickard Andersson <rickard.andersson@stericsson.com>, - * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson - * - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/suspend.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/uaccess.h> - -#include "pm.h" - -#ifdef CONFIG_UX500_SUSPEND_STANDBY -static u32 sleep_enabled = 1; -#else -static u32 sleep_enabled; -#endif - -#ifdef CONFIG_UX500_SUSPEND_MEM -static u32 deepsleep_enabled = 1; -#else -static u32 deepsleep_enabled; -#endif - -static u32 suspend_enabled = 1; - -static u32 deepsleeps_done; -static u32 deepsleeps_failed; -static u32 sleeps_done; -static u32 sleeps_failed; -static u32 suspend_count; - -#ifdef CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART -void ux500_suspend_dbg_add_wake_on_uart(void) -{ - irq_set_irq_wake(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), 1); - irq_set_irq_type(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), - IRQ_TYPE_EDGE_BOTH); -} - -void ux500_suspend_dbg_remove_wake_on_uart(void) -{ - irq_set_irq_wake(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), 0); -} -#endif - -bool ux500_suspend_enabled(void) -{ - return suspend_enabled != 0; -} - -bool ux500_suspend_sleep_enabled(void) -{ - return sleep_enabled != 0; -} - -bool ux500_suspend_deepsleep_enabled(void) -{ - return deepsleep_enabled != 0; -} - -void ux500_suspend_dbg_sleep_status(bool is_deepsleep) -{ - enum prcmu_idle_stat prcmu_status; - - prcmu_status = ux500_pm_prcmu_idle_stat(); - - if (is_deepsleep) { - pr_info("Returning from ApDeepSleep. PRCMU ret: 0x%x - %s\n", - prcmu_status, - prcmu_status == DEEP_SLEEP_OK ? "Success" : "Fail!"); - if (prcmu_status == DEEP_SLEEP_OK) - deepsleeps_done++; - else - deepsleeps_failed++; - } else { - pr_info("Returning from ApSleep. PRCMU ret: 0x%x - %s\n", - prcmu_status, - prcmu_status == SLEEP_OK ? "Success" : "Fail!"); - if (prcmu_status == SLEEP_OK) - sleeps_done++; - else - sleeps_failed++; - } -} - -int ux500_suspend_dbg_begin(suspend_state_t state) -{ - suspend_count++; - return 0; -} - -void ux500_suspend_dbg_init(void) -{ - struct dentry *suspend_dir = NULL; - struct dentry *sleep_file = NULL; - struct dentry *deepsleep_file = NULL; - struct dentry *enable_file = NULL; - struct dentry *suspend_count_file = NULL; - struct dentry *sleeps_done_file = NULL; - struct dentry *deepsleeps_done_file = NULL; - struct dentry *sleeps_failed_file = NULL; - struct dentry *deepsleeps_failed_file = NULL; - - suspend_dir = debugfs_create_dir("suspend", NULL); - if (IS_ERR_OR_NULL(suspend_dir)) - return; - - sleep_file = debugfs_create_bool("sleep", S_IWUGO | S_IRUGO, - suspend_dir, - &sleep_enabled); - if (IS_ERR_OR_NULL(sleep_file)) - goto error; - - deepsleep_file = debugfs_create_bool("deepsleep", S_IWUGO | S_IRUGO, - suspend_dir, - &deepsleep_enabled); - if (IS_ERR_OR_NULL(deepsleep_file)) - goto error; - - enable_file = debugfs_create_bool("enable", S_IWUGO | S_IRUGO, - suspend_dir, - &suspend_enabled); - if (IS_ERR_OR_NULL(enable_file)) - goto error; - - suspend_count_file = debugfs_create_u32("count", S_IRUGO, - suspend_dir, - &suspend_count); - if (IS_ERR_OR_NULL(suspend_count_file)) - goto error; - - sleeps_done_file = debugfs_create_u32("sleep_count", S_IRUGO, - suspend_dir, - &sleeps_done); - if (IS_ERR_OR_NULL(sleeps_done_file)) - goto error; - - deepsleeps_done_file = debugfs_create_u32("deepsleep_count", S_IRUGO, - suspend_dir, - &deepsleeps_done); - if (IS_ERR_OR_NULL(deepsleeps_done_file)) - goto error; - - - sleeps_failed_file = debugfs_create_u32("sleep_failed", S_IRUGO, - suspend_dir, - &sleeps_failed); - if (IS_ERR_OR_NULL(sleeps_failed_file)) - goto error; - - deepsleeps_failed_file = debugfs_create_u32("deepsleep_failed", S_IRUGO, - suspend_dir, - &deepsleeps_failed); - if (IS_ERR_OR_NULL(deepsleeps_failed_file)) - goto error; - - return; -error: - if (!IS_ERR_OR_NULL(deepsleeps_failed_file)) - debugfs_remove(deepsleeps_failed_file); - if (!IS_ERR_OR_NULL(sleeps_failed_file)) - debugfs_remove(sleeps_failed_file); - if (!IS_ERR_OR_NULL(deepsleeps_done_file)) - debugfs_remove(deepsleeps_done_file); - if (!IS_ERR_OR_NULL(sleeps_done_file)) - debugfs_remove(sleeps_done_file); - if (!IS_ERR_OR_NULL(suspend_count_file)) - debugfs_remove(suspend_count_file); - if (!IS_ERR_OR_NULL(enable_file)) - debugfs_remove(enable_file); - if (!IS_ERR_OR_NULL(deepsleep_file)) - debugfs_remove(deepsleep_file); - if (!IS_ERR_OR_NULL(sleep_file)) - debugfs_remove(sleep_file); - - debugfs_remove(suspend_dir); -} diff --git a/arch/arm/mach-ux500/pm/suspend_dbg.h b/arch/arm/mach-ux500/pm/suspend_dbg.h deleted file mode 100644 index bd2afb93472..00000000000 --- a/arch/arm/mach-ux500/pm/suspend_dbg.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson - * - */ - -#ifndef UX500_SUSPEND_DBG_H -#define UX500_SUSPEND_DBG_H - -#include <linux/kernel.h> -#include <linux/suspend.h> - -#ifdef CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART -void ux500_suspend_dbg_add_wake_on_uart(void); -void ux500_suspend_dbg_remove_wake_on_uart(void); -#else -static inline void ux500_suspend_dbg_add_wake_on_uart(void) { } -static inline void ux500_suspend_dbg_remove_wake_on_uart(void) { } -#endif - -#ifdef CONFIG_UX500_SUSPEND_DBG -bool ux500_suspend_enabled(void); -bool ux500_suspend_sleep_enabled(void); -bool ux500_suspend_deepsleep_enabled(void); -void ux500_suspend_dbg_sleep_status(bool is_deepsleep); -void ux500_suspend_dbg_init(void); -int ux500_suspend_dbg_begin(suspend_state_t state); - -#else -static inline bool ux500_suspend_enabled(void) -{ - return true; -} -static inline bool ux500_suspend_sleep_enabled(void) -{ -#ifdef CONFIG_UX500_SUSPEND_STANDBY - return true; -#else - return false; -#endif -} -static inline bool ux500_suspend_deepsleep_enabled(void) -{ -#ifdef CONFIG_UX500_SUSPEND_MEM - return true; -#else - return false; -#endif -} -static inline void ux500_suspend_dbg_sleep_status(bool is_deepsleep) { } -static inline void ux500_suspend_dbg_init(void) { } - -static inline int ux500_suspend_dbg_begin(suspend_state_t state) -{ - return 0; -} - -#endif - -#endif diff --git a/arch/arm/mach-ux500/pm/timer.c b/arch/arm/mach-ux500/pm/timer.c deleted file mode 100644 index 12553a3351b..00000000000 --- a/arch/arm/mach-ux500/pm/timer.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010-2011 - * - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson - * - * License Terms: GNU General Public License v2 - * - * The RTC timer block is a ST Microelectronics variant of ARM PL031. - * Clockwatch part is the same as PL031, while the timer part is only - * present on the ST Microelectronics variant. - * Here only the timer part is used. - * - * The timer part is quite troublesome to program correctly. Lots - * of long delays must be there in order to secure that you actually get what - * you wrote. - * - * In other words, this timer is and should only used from cpuidle during - * special conditions when the surroundings are know in order to be able - * to remove the number of delays. - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/ktime.h> -#include <linux/delay.h> - -#include <asm/errno.h> - -#include <mach/hardware.h> - -#include "cpuidle_dbg.h" - -#define RTC_IMSC 0x10 -#define RTC_MIS 0x18 -#define RTC_ICR 0x1C -#define RTC_TDR 0x20 -#define RTC_TLR1 0x24 -#define RTC_TCR 0x28 - -#define RTC_TLR2 0x2C -#define RTC_TPR1 0x3C - -#define RTC_TCR_RTTOS (1 << 0) -#define RTC_TCR_RTTEN (1 << 1) -#define RTC_TCR_RTTSS (1 << 2) - -#define RTC_IMSC_TIMSC (1 << 1) -#define RTC_ICR_TIC (1 << 1) -#define RTC_MIS_RTCTMIS (1 << 1) - -#define RTC_TCR_RTTPS_2 (1 << 4) -#define RTC_TCR_RTTPS_3 (2 << 4) -#define RTC_TCR_RTTPS_4 (3 << 4) -#define RTC_TCR_RTTPS_5 (4 << 4) -#define RTC_TCR_RTTPS_6 (5 << 4) -#define RTC_TCR_RTTPS_7 (6 << 4) -#define RTC_TCR_RTTPS_8 (7 << 4) - -#define WRITE_DELAY 130 /* 4 cycles plus margin */ - -/* - * Count down measure point. It just have to be high to differ - * from scheduled values. - */ -#define MEASURE_VAL 0xffffffff - -/* Just a value bigger than any reason able scheduled timeout. */ -#define MEASURE_VAL_LIMIT 0xf0000000 - - -#define TICKS_TO_NS(x) ((s64)x * 30512) -#define US_TO_TICKS(x) ((u32)((1000 * x) / 30512)) - -static void __iomem *rtc_base; -static bool measure_latency; - -#ifdef CONFIG_U8500_CPUIDLE_DEBUG - -/* - * The plan here is to be able to measure the ApSleep/ApDeepSleep exit latency - * by having a know timer pattern. - * The first entry in the pattern, LR1, is the value that the scheduler - * wants us to sleep. The second pattern in a high value, too large to be - * scheduled, so we can differ between a running scheduled value and a - * time measure value. - * When a RTT interrupt has occured, the block will automatically start - * to execute the measure value in LR2 and when the ARM is awake, it reads - * how far the RTT has decreased the value loaded from LR2 and from that - * calculate how long time it took to wake up. - */ -ktime_t u8500_rtc_exit_latency_get(void) -{ - u32 ticks; - - if (measure_latency) { - ticks = MEASURE_VAL - readl(rtc_base + RTC_TDR); - - /* - * Check if we are actually counting on a LR2 value. - * If not we have woken on another interrupt. - */ - if (ticks < MEASURE_VAL_LIMIT) { - /* convert 32 kHz ticks to ns */ - return ktime_set(0, TICKS_TO_NS(ticks)); - } - } - return ktime_set(0, 0); -} - -static void measure_latency_start(void) -{ - udelay(WRITE_DELAY); - /* - * Disable RTT and clean self-start due to we want to restart, - * not continue from current pattern. (See below) - */ - writel(0, rtc_base + RTC_TCR); - udelay(WRITE_DELAY); - - /* - * Program LR2 (load register two) to maximum value to ease - * identification of timer interrupt vs other. - */ - writel(MEASURE_VAL, rtc_base + RTC_TLR2); - /* - * Set Load Register execution pattern, bit clear - * means pick LR1, bit set means LR2 - * 0xfe, binary 11111110 means first do LR1 then do - * LR2 seven times - */ - writel(0xfe, rtc_base + RTC_TPR1); - - udelay(WRITE_DELAY); - - /* - * Enable self-start, plus a pattern of eight. - */ - writel(RTC_TCR_RTTSS | RTC_TCR_RTTPS_8, - rtc_base + RTC_TCR); - udelay(WRITE_DELAY); -} - -void ux500_rtcrtt_measure_latency(bool enable) -{ - if (enable) { - measure_latency_start(); - } else { - writel(RTC_TCR_RTTSS | RTC_TCR_RTTOS, rtc_base + RTC_TCR); - writel(RTC_ICR_TIC, rtc_base + RTC_ICR); - writel(RTC_IMSC_TIMSC, rtc_base + RTC_IMSC); - } - measure_latency = enable; -} -#else -static inline void measure_latency_start(void) { } -static inline void ux500_rtcrtt_measure_latency(bool enable) { } -#endif - -void ux500_rtcrtt_off(void) -{ - if (measure_latency) { - measure_latency_start(); - } else { - /* Clear eventual interrupts */ - if (readl(rtc_base + RTC_MIS) & RTC_MIS_RTCTMIS) - writel(RTC_ICR_TIC, rtc_base + RTC_ICR); - - /* Disable, self start and oneshot mode */ - writel(RTC_TCR_RTTSS | RTC_TCR_RTTOS, rtc_base + RTC_TCR); - } -} - -void ux500_rtcrtt_next(u32 time_us) -{ - writel(US_TO_TICKS(time_us), rtc_base + RTC_TLR1); -} - -static int __init ux500_rtcrtt_init(void) -{ - if (cpu_is_u8500()) { - rtc_base = __io_address(U8500_RTC_BASE); - } else if (cpu_is_u5500()) { - rtc_base = __io_address(U5500_RTC_BASE); - } else { - pr_err("timer-rtt: Unknown DB Asic!\n"); - return -EINVAL; - } - ux500_rtcrtt_measure_latency(false); - return 0; -} -subsys_initcall(ux500_rtcrtt_init); diff --git a/arch/arm/mach-ux500/pm/timer.h b/arch/arm/mach-ux500/pm/timer.h deleted file mode 100644 index ec9e919e70d..00000000000 --- a/arch/arm/mach-ux500/pm/timer.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> - * - * License Terms: GNU General Public License v2 - * - */ - -#ifndef PM_TIMER_H -#define PM_TIMER_H - -#include <linux/ktime.h> - -#ifdef CONFIG_U8500_CPUIDLE_DEBUG -ktime_t u8500_rtc_exit_latency_get(void); -void ux500_rtcrtt_measure_latency(bool enable); -#else -static inline ktime_t u8500_rtc_exit_latency_get(void) -{ - return ktime_set(0, 0); -} -static inline void ux500_rtcrtt_measure_latency(bool enable) { } - -#endif - -void ux500_rtcrtt_off(void); -void ux500_rtcrtt_next(u32 time_us); - -#endif diff --git a/arch/arm/mach-ux500/pm/usecase_gov.c b/arch/arm/mach-ux500/pm/usecase_gov.c deleted file mode 100644 index 2a6b36cfaef..00000000000 --- a/arch/arm/mach-ux500/pm/usecase_gov.c +++ /dev/null @@ -1,942 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * Author: Alexandre Torgue <alexandre.torgue@stericsson.com> for ST-Ericsson - * Author: Vincent Guittot <vincent.guittot@stericsson.com> for ST-Ericsson - * License terms: GNU General Public License (GPL) version 2 - */ - -#include <linux/io.h> -#include <linux/earlysuspend.h> -#include <linux/cpu.h> -#include <linux/sched.h> -#include <linux/tick.h> -#include <linux/workqueue.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/uaccess.h> -#include <linux/kernel_stat.h> -#include <linux/ktime.h> -#include <linux/cpufreq.h> -#include <mach/prcmu.h> - -#define CPULOAD_MEAS_DELAY 3000 /* 3 secondes of delta */ - -/* debug */ -static unsigned long debug; - -#define hp_printk \ - if (debug) \ - printk \ - -enum ux500_uc { - UX500_UC_NORMAL = 0, - UX500_UC_AUTO, /* Add use case below this. */ - UX500_UC_VC, - UX500_UC_LPA, - UX500_UC_USER, /* Add use case above this. */ - UX500_UC_MAX, -}; - -/* cpu load monitor struct */ -#define LOAD_MONITOR 4 -struct hotplug_cpu_info { - cputime64_t prev_cpu_wall; - cputime64_t prev_cpu_idle; - cputime64_t prev_cpu_io; - unsigned int load[LOAD_MONITOR]; - unsigned int io[LOAD_MONITOR]; - unsigned int idx; -}; - -static DEFINE_PER_CPU(struct hotplug_cpu_info, hotplug_info); - -/* Auto trigger criteria */ -/* loadavg threshold */ -static unsigned long lower_threshold = 175; -static unsigned long upper_threshold = 450; -/* load balancing */ -static unsigned long max_unbalance = 210; -/* trend load */ -static unsigned long trend_unbalance = 40; -static unsigned long min_trend = 5; -/* instant load */ -static unsigned long max_instant = 85; - -/* Number of interrupts per second before exiting auto mode */ -static u32 exit_irq_per_s = 1000; -static u64 old_num_irqs; - -static DEFINE_MUTEX(usecase_mutex); -static bool user_config_updated; -static enum ux500_uc current_uc = UX500_UC_MAX; -static bool is_work_scheduled; -static bool is_early_suspend; -static bool uc_master_enable = true; - -static unsigned int cpuidle_deepest_state; - -struct usecase_config { - char *name; - unsigned long max_freq; - unsigned long min_freq; /* if no requirement set 0 */ - unsigned long cpuidle_multiplier; - bool second_cpu_online; - bool l2_prefetch_en; - bool enable; - unsigned int forced_state; /* Forced cpu idle state. */ - bool vc_override; /* QOS override for voice-call. */ -}; - -static struct usecase_config usecase_conf[UX500_UC_MAX] = { - [UX500_UC_NORMAL] = { - .name = "normal", - .max_freq = 1000000, - .min_freq = 200000, - .cpuidle_multiplier = 1024, - .second_cpu_online = true, - .l2_prefetch_en = true, - .enable = true, - .forced_state = 0, - .vc_override = false, - }, - [UX500_UC_AUTO] = { - .name = "auto", - .max_freq = 400000, - .min_freq = 200000, - .cpuidle_multiplier = 0, - .second_cpu_online = false, - .l2_prefetch_en = true, - .enable = false, - .forced_state = 0, - .vc_override = false, - }, - [UX500_UC_VC] = { - .name = "voice-call", - .max_freq = 400000, - .min_freq = 400000, - .cpuidle_multiplier = 0, - .second_cpu_online = false, - .l2_prefetch_en = false, - .enable = false, - .forced_state = 0, - .vc_override = true, - }, - [UX500_UC_LPA] = { - .name = "low-power-audio", - .max_freq = 400000, - .min_freq = 400000, - .cpuidle_multiplier = 0, - .second_cpu_online = false, - .l2_prefetch_en = false, - .enable = false, - .forced_state = 0, /* Updated dynamically */ - .vc_override = false, - }, -}; - -/* daemon */ -static struct delayed_work work_usecase; -static struct early_suspend usecase_early_suspend; - -/* calculate loadavg */ -#define LOAD_INT(x) ((x) >> FSHIFT) -#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) - -extern int cpufreq_update_freq(int cpu, unsigned int min, unsigned int max); -extern int cpuidle_set_multiplier(unsigned int value); -extern int cpuidle_force_state(unsigned int state); - -static unsigned long determine_loadavg(void) -{ - unsigned long avg = 0; - unsigned long avnrun[3]; - - get_avenrun(avnrun, FIXED_1 / 200, 0); - avg += (LOAD_INT(avnrun[0]) * 100) + (LOAD_FRAC(avnrun[0]) % 100); - - return avg; -} - -static unsigned long determine_cpu_load(void) -{ - int i; - unsigned long total_load = 0; - - /* get cpu load of each cpu */ - for_each_online_cpu(i) { - unsigned int load, iowait; - unsigned int idle_time, iowait_time, wall_time; - cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; - struct hotplug_cpu_info *info; - - info = &per_cpu(hotplug_info, i); - - /* update both cur_idle_time and cur_wall_time */ - cur_idle_time = get_cpu_idle_time_us(i, &cur_wall_time); - cur_iowait_time = get_cpu_iowait_time_us(i, &cur_wall_time); - - /* how much wall time has passed since last iteration? */ - wall_time = (unsigned int) cputime64_sub(cur_wall_time, - info->prev_cpu_wall); - info->prev_cpu_wall = cur_wall_time; - - /* how much idle time has passed since last iteration? */ - idle_time = (unsigned int) cputime64_sub(cur_idle_time, - info->prev_cpu_idle); - info->prev_cpu_idle = cur_idle_time; - - /* how much io wait time has passed since last iteration? */ - iowait_time = (unsigned int) cputime64_sub(cur_iowait_time, - info->prev_cpu_io); - info->prev_cpu_io = cur_iowait_time; - - if (unlikely(!wall_time || wall_time < idle_time)) - continue; - - /* load is the percentage of time not spent in idle */ - load = 100 * (wall_time - idle_time) / wall_time; - info->load[info->idx] = load; - hp_printk("cpu %d load %u ", i, load); - - /* iowait is the percentage of time not spent in io wait */ - iowait = 100 * (iowait_time) / wall_time; - info->io[info->idx++] = load; - hp_printk("iowait %u\n", iowait); - - if (info->idx >= LOAD_MONITOR) - info->idx = 0; - - total_load += load; - } - - return total_load; -} - -static unsigned long determine_cpu_load_trend(void) -{ - int i, j, k; - unsigned long total_load = 0; - - /* Get cpu load of each cpu */ - for_each_online_cpu(i) { - unsigned int load = 0; - struct hotplug_cpu_info *info; - - info = &per_cpu(hotplug_info, i); - - for (k = 0, j = info->idx; k < LOAD_MONITOR; k++, j++) - load += info->load[j]; - - load /= LOAD_MONITOR; - - hp_printk("cpu %d load trend %u\n", i, load); - - total_load += load; - } - - return total_load; -} - -static unsigned long determine_cpu_balance_trend(void) -{ - int i, j, k; - unsigned long total_load = 0; - unsigned long min_load = (unsigned long) (-1); - - /* Get cpu load of each cpu */ - for_each_online_cpu(i) { - unsigned int load = 0; - struct hotplug_cpu_info *info; - - info = &per_cpu(hotplug_info, i); - - for (k = 0, j = info->idx; k < LOAD_MONITOR; k++, j++) - load += info->load[j]; - - load /= LOAD_MONITOR; - - if (min_load > load) - min_load = load; - total_load += load; - } - - if (min_load > min_trend) - total_load = (100 * total_load) / min_load; - else - total_load = 50 << num_online_cpus(); - - return total_load; -} - -static void init_cpu_load_trend(void) -{ - int i; - - for_each_possible_cpu(i) { - struct hotplug_cpu_info *info; - int j; - - info = &per_cpu(hotplug_info, i); - - info->prev_cpu_idle = get_cpu_idle_time_us(i, - &(info->prev_cpu_wall)); - info->prev_cpu_io = get_cpu_iowait_time_us(i, - &(info->prev_cpu_wall)); - - for (j = 0; j < LOAD_MONITOR; j++) { - info->load[j] = 100; - info->io[j] = 100; - } - info->idx = 0; - } -} - -static u32 get_num_interrupts_per_s(void) -{ - int cpu; - int i; - u64 num_irqs = 0; - ktime_t now; - static ktime_t last; - unsigned int delta; - u32 irqs = 0; - - now = ktime_get(); - - for_each_possible_cpu(cpu) { - for (i = 0; i < NR_IRQS; i++) - num_irqs += kstat_irqs_cpu(i, cpu); - } - pr_debug("%s: total num irqs: %lld, previous %lld\n", - __func__, num_irqs, old_num_irqs); - - if (old_num_irqs > 0) { - delta = (u32)ktime_to_ms(ktime_sub(now, last)) / 1000; - irqs = ((u32)(num_irqs - old_num_irqs)) / delta; - } - - old_num_irqs = num_irqs; - last = now; - - pr_debug("delta irqs per sec:%d\n", irqs); - - return irqs; -} - -static void set_cpu_config(enum ux500_uc new_uc) -{ - struct cpufreq_policy policy; - int err; - bool update = false; - u32 min_freq, max_freq; - - if (new_uc != current_uc) - update = true; - else if ((user_config_updated) && (new_uc == UX500_UC_USER)) - update = true; - - pr_debug("%s: new_usecase=%d, current_usecase=%d, update=%d\n", - __func__, new_uc, current_uc, update); - - if (!update) - goto exit; - - /* Cpu hotplug */ - if (!(usecase_conf[new_uc].second_cpu_online) && - (num_online_cpus() > 1)) - cpu_down(1); - else if ((usecase_conf[new_uc].second_cpu_online) && - (num_online_cpus() < 2)) - cpu_up(1); - - /* Cpu freq */ - err = cpufreq_get_policy(&policy, 0); - if (err) - pr_err("usecase-gov: get cpufreq policy failed\n"); - - /* If requirement is 0, use current policy value */ - min_freq = usecase_conf[new_uc].min_freq ? - usecase_conf[new_uc].min_freq : policy.min; - - max_freq = usecase_conf[new_uc].max_freq ? - usecase_conf[new_uc].max_freq : policy.max; - - /* - * cpufreq fw does not allow frequency change if - * "current min freq" > "new max freq" or - * "current max freq" < "new min freq". - * Thus the intermediate steps below. - */ - if (policy.min > max_freq) { - err = cpufreq_update_freq(0, min_freq, policy.max); - if (err) - pr_err("usecase-gov: update min cpufreq failed\n"); - } - if (policy.max < min_freq) { - err = cpufreq_update_freq(0, policy.min, max_freq); - if (err) - pr_err("usecase-gov: update max cpufreq failed\n"); - } - - err = cpufreq_update_freq(0, min_freq, max_freq); - if (err) - pr_err("usecase-gov: update min/max cpufreq failed\n"); - - /* Cpu idle */ - cpuidle_set_multiplier(usecase_conf[new_uc].cpuidle_multiplier); - - /* L2 prefetch */ - if (usecase_conf[new_uc].l2_prefetch_en) - outer_prefetch_enable(); - else - outer_prefetch_disable(); - - /* Force cpuidle state */ - cpuidle_force_state(usecase_conf[new_uc].forced_state); - - /* QOS override */ - prcmu_qos_voice_call_override(usecase_conf[new_uc].vc_override); - - current_uc = new_uc; - -exit: - /* Its ok to clear even if new_uc != UX500_UC_USER */ - user_config_updated = false; -} - -void usecase_update_governor_state(void) -{ - bool cancel_work = false; - - mutex_lock(&usecase_mutex); - - if (uc_master_enable && (usecase_conf[UX500_UC_AUTO].enable || - usecase_conf[UX500_UC_USER].enable)) { - /* - * Usecases are enabled. If we are in early suspend put - * governor to work. - */ - if (is_early_suspend && !is_work_scheduled) { - schedule_delayed_work_on(0, &work_usecase, - msecs_to_jiffies(CPULOAD_MEAS_DELAY)); - is_work_scheduled = true; - } else if (!is_early_suspend && is_work_scheduled) { - /* Exiting from early suspend. */ - cancel_work = true; - } - - } else if (is_work_scheduled) { - /* No usecase enabled or governor is not enabled. */ - cancel_work = true; - } - - if (cancel_work) { - cancel_delayed_work_sync(&work_usecase); - is_work_scheduled = false; - - /* Set the default settings before exiting. */ - set_cpu_config(UX500_UC_NORMAL); - } - - mutex_unlock(&usecase_mutex); - -} - -/* - * Start load measurment every 6 s in order detrmine if can unplug one CPU. - * In order to not corrupt measurment, the first load average is not done - * here call in early suspend. - */ -static void usecase_earlysuspend_callback(struct early_suspend *h) -{ - init_cpu_load_trend(); - - is_early_suspend = true; - - usecase_update_governor_state(); -} - -/* Stop measurement, call LCD early resume */ -static void usecase_lateresume_callback(struct early_suspend *h) -{ - is_early_suspend = false; - - usecase_update_governor_state(); -} - -static void delayed_usecase_work(struct work_struct *work) -{ - unsigned long avg, load, trend, balance; - bool inc_perf = false; - bool dec_perf = false; - u32 irqs_per_s; - - /* determine loadavg */ - avg = determine_loadavg(); - hp_printk("loadavg = %lu lower th %lu upper th %lu\n", - avg, lower_threshold, upper_threshold); - - /* determine instant load */ - load = determine_cpu_load(); - hp_printk("cpu instant load = %lu max %lu\n", load, max_instant); - - /* determine load trend */ - trend = determine_cpu_load_trend(); - hp_printk("cpu load trend = %lu min %lu unbal %lu\n", - trend, min_trend, trend_unbalance); - - /* determine load balancing */ - balance = determine_cpu_balance_trend(); - hp_printk("load balancing trend = %lu min %lu\n", - balance, max_unbalance); - - irqs_per_s = get_num_interrupts_per_s(); - - /* Dont let configuration change in the middle of our calculations. */ - mutex_lock(&usecase_mutex); - - /* detect "instant" load increase */ - if (load > max_instant || irqs_per_s > exit_irq_per_s) { - inc_perf = true; - } else if (!usecase_conf[UX500_UC_USER].enable && - usecase_conf[UX500_UC_AUTO].enable) { - /* detect high loadavg use case */ - if (avg > upper_threshold) - inc_perf = true; - /* detect idle use case */ - else if (trend < min_trend) - dec_perf = true; - /* detect unbalanced low cpu load use case */ - else if ((balance > max_unbalance) && (trend < trend_unbalance)) - dec_perf = true; - /* detect low loadavg use case */ - else if (avg < lower_threshold) - dec_perf = true; - /* All user use cases disabled, current load not triggering - * any change. - */ - else if (user_config_updated) - dec_perf = true; - } else { - dec_perf = true; - } - - /* - * set_cpu_config() will not update the config unless it has been - * changed. - */ - if (dec_perf) { - if (usecase_conf[UX500_UC_USER].enable) - set_cpu_config(UX500_UC_USER); - else if (usecase_conf[UX500_UC_AUTO].enable) - set_cpu_config(UX500_UC_AUTO); - } else if (inc_perf) { - set_cpu_config(UX500_UC_NORMAL); - } - - mutex_unlock(&usecase_mutex); - - /* reprogramm scheduled work */ - schedule_delayed_work_on(0, &work_usecase, - msecs_to_jiffies(CPULOAD_MEAS_DELAY)); - -} - -static struct dentry *usecase_dir; - -#ifdef CONFIG_DEBUG_FS -#define define_set(_name) \ -static ssize_t set_##_name(struct file *file, \ - const char __user *user_buf, \ - size_t count, loff_t *ppos) \ -{ \ - int err; \ - long unsigned i; \ - \ - err = kstrtoul_from_user(user_buf, count, 0, &i); \ - \ - if (err) \ - return err; \ - \ - _name = i; \ - hp_printk("New value : %lu\n", _name); \ - \ - return count; \ -} - -define_set(upper_threshold); -define_set(lower_threshold); -define_set(max_unbalance); -define_set(trend_unbalance); -define_set(min_trend); -define_set(max_instant); -define_set(debug); - -#define define_print(_name) \ -static ssize_t print_##_name(struct seq_file *s, void *p) \ -{ \ - return seq_printf(s, "%lu\n", _name); \ -} - -define_print(upper_threshold); -define_print(lower_threshold); -define_print(max_unbalance); -define_print(trend_unbalance); -define_print(min_trend); -define_print(max_instant); -define_print(debug); - -#define define_open(_name) \ -static ssize_t open_##_name(struct inode *inode, struct file *file) \ -{ \ - return single_open(file, print_##_name, inode->i_private); \ -} - -define_open(upper_threshold); -define_open(lower_threshold); -define_open(max_unbalance); -define_open(trend_unbalance); -define_open(min_trend); -define_open(max_instant); -define_open(debug); - -#define define_dbg_file(_name) \ -static const struct file_operations fops_##_name = { \ - .open = open_##_name, \ - .write = set_##_name, \ - .read = seq_read, \ - .llseek = seq_lseek, \ - .release = single_release, \ - .owner = THIS_MODULE, \ -}; \ -static struct dentry *file_##_name; - -define_dbg_file(upper_threshold); -define_dbg_file(lower_threshold); -define_dbg_file(max_unbalance); -define_dbg_file(trend_unbalance); -define_dbg_file(min_trend); -define_dbg_file(max_instant); -define_dbg_file(debug); - -struct dbg_file { - struct dentry **file; - const struct file_operations *fops; - const char *name; -}; - -#define define_dbg_entry(_name) \ -{ \ - .file = &file_##_name, \ - .fops = &fops_##_name, \ - .name = #_name \ -} - -static struct dbg_file debug_entry[] = { - define_dbg_entry(upper_threshold), - define_dbg_entry(lower_threshold), - define_dbg_entry(max_unbalance), - define_dbg_entry(trend_unbalance), - define_dbg_entry(min_trend), - define_dbg_entry(max_instant), - define_dbg_entry(debug), -}; - -static int setup_debugfs(void) -{ - int i; - usecase_dir = debugfs_create_dir("usecase", NULL); - - if (IS_ERR_OR_NULL(usecase_dir)) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(debug_entry); i++) { - if (IS_ERR_OR_NULL(debugfs_create_file(debug_entry[i].name, - S_IWUGO | S_IRUGO, - usecase_dir, - NULL, - debug_entry[i].fops))) - goto fail; - } - - if (IS_ERR_OR_NULL(debugfs_create_u32("exit_irq_per_s", - S_IWUGO | S_IRUGO, usecase_dir, - &exit_irq_per_s))) - goto fail; - return 0; -fail: - debugfs_remove_recursive(usecase_dir); - return -EINVAL; -} -#else -static int setup_debugfs(void) -{ - return 0; -} -#endif - -static void usecase_update_user_config(void) -{ - int i; - bool config_enable = false; - struct usecase_config *user_conf = &usecase_conf[UX500_UC_USER]; - - mutex_lock(&usecase_mutex); - - user_conf->max_freq = 0; - user_conf->min_freq = 0; - user_conf->cpuidle_multiplier = 0; - user_conf->second_cpu_online = false; - user_conf->l2_prefetch_en = false; - user_conf->forced_state = cpuidle_deepest_state; - user_conf->vc_override = true; /* A single false will clear it. */ - - /* Dont include Auto and Normal modes in this */ - for (i = (UX500_UC_AUTO + 1); i < UX500_UC_USER; i++) { - if (!usecase_conf[i].enable) - continue; - - config_enable = true; - - if (usecase_conf[i].max_freq > user_conf->max_freq) - user_conf->max_freq = usecase_conf[i].max_freq; - /* It's the highest min freq requirement that should be used */ - if (usecase_conf[i].min_freq > user_conf->min_freq) - user_conf->min_freq = usecase_conf[i].min_freq; - - if (usecase_conf[i].cpuidle_multiplier > - user_conf->cpuidle_multiplier) - user_conf->cpuidle_multiplier = - usecase_conf[i].cpuidle_multiplier; - - user_conf->second_cpu_online |= - usecase_conf[i].second_cpu_online; - - user_conf->l2_prefetch_en |= - usecase_conf[i].l2_prefetch_en; - - /* Take the shallowest state. */ - if (usecase_conf[i].forced_state < user_conf->forced_state) - user_conf->forced_state = usecase_conf[i].forced_state; - - /* Only override QOS if all enabled configurations are - * requesting it. - */ - if (!usecase_conf[i].vc_override) - user_conf->vc_override = false; - } - - user_conf->enable = config_enable; - user_config_updated = true; - - mutex_unlock(&usecase_mutex); -} - -struct usecase_devclass_attr { - struct sysdev_class_attribute class_attr; - u32 index; -}; - -/* One for each usecase except "user" + current + enable */ -#define UX500_NUM_SYSFS_NODES (UX500_UC_USER + 2) -#define UX500_CURRENT_NODE_INDEX (UX500_NUM_SYSFS_NODES - 1) -#define UX500_ENABLE_NODE_INDEX (UX500_NUM_SYSFS_NODES - 2) - -static struct usecase_devclass_attr usecase_dc_attr[UX500_NUM_SYSFS_NODES]; - -static struct attribute *dbs_attributes[UX500_NUM_SYSFS_NODES + 1] = {NULL}; - -static struct attribute_group dbs_attr_group = { - .attrs = dbs_attributes, - .name = "usecase", -}; - -static ssize_t show_current(struct sysdev_class *class, - struct sysdev_class_attribute *attr, char *buf) -{ - enum ux500_uc display_uc = (current_uc == UX500_UC_MAX) ? - UX500_UC_NORMAL : current_uc; - - return sprintf(buf, "max_freq: %ld\n" - "min_freq: %ld\n" - "cpuidle_multiplier: %ld\n" - "second_cpu_online: %s\n" - "l2_prefetch_en: %s\n" - "forced_state: %d\n" - "vc_override: %s\n", - usecase_conf[display_uc].max_freq, - usecase_conf[display_uc].min_freq, - usecase_conf[display_uc].cpuidle_multiplier, - usecase_conf[display_uc].second_cpu_online ? "true" : "false", - usecase_conf[display_uc].l2_prefetch_en ? "true" : "false", - usecase_conf[display_uc].forced_state, - usecase_conf[display_uc].vc_override ? "true" : "false"); -} - -static ssize_t show_enable(struct sysdev_class *class, - struct sysdev_class_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", uc_master_enable); -} - -static ssize_t store_enable(struct sysdev_class *class, - struct sysdev_class_attribute *attr, - const char *buf, size_t count) -{ - unsigned int input; - int ret; - - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; - - uc_master_enable = (bool) input; - - usecase_update_governor_state(); - - return count; -} - -static ssize_t show_dc_attr(struct sysdev_class *class, - struct sysdev_class_attribute *attr, char *buf) -{ - struct usecase_devclass_attr *uattr = - container_of(attr, struct usecase_devclass_attr, class_attr); - - return sprintf(buf, "%u\n", - usecase_conf[uattr->index].enable); -} - -static ssize_t store_dc_attr(struct sysdev_class *class, - struct sysdev_class_attribute *attr, - const char *buf, size_t count) -{ - unsigned int input; - int ret; - - struct usecase_devclass_attr *uattr = - container_of(attr, struct usecase_devclass_attr, class_attr); - - ret = sscanf(buf, "%u", &input); - - /* Normal mode cant be changed. */ - if ((ret != 1) || (uattr->index == 0)) - return -EINVAL; - - usecase_conf[uattr->index].enable = (bool)input; - - usecase_update_user_config(); - - usecase_update_governor_state(); - - return count; -} - -static int usecase_sysfs_init(void) -{ - int err; - int i; - - /* Last two nodes are not based on usecase configurations */ - for (i = 0; i < (UX500_NUM_SYSFS_NODES - 2); i++) { - usecase_dc_attr[i].class_attr.attr.name = usecase_conf[i].name; - usecase_dc_attr[i].class_attr.attr.mode = 0644; - usecase_dc_attr[i].class_attr.show = show_dc_attr; - usecase_dc_attr[i].class_attr.store = store_dc_attr; - usecase_dc_attr[i].index = i; - - dbs_attributes[i] = &(usecase_dc_attr[i].class_attr.attr); - } - - /* sysfs current */ - usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.attr.name = - "current"; - usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.attr.mode = - 0644; - usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.show = - show_current; - usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.store = - NULL; - usecase_dc_attr[UX500_CURRENT_NODE_INDEX].index = - 0; - dbs_attributes[UX500_CURRENT_NODE_INDEX] = - &(usecase_dc_attr[UX500_CURRENT_NODE_INDEX].class_attr.attr); - - /* sysfs enable */ - usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.attr.name = - "enable"; - usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.attr.mode = - 0644; - usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.show = - show_enable; - usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.store = - store_enable; - usecase_dc_attr[UX500_ENABLE_NODE_INDEX].index = - 0; - dbs_attributes[UX500_ENABLE_NODE_INDEX] = - &(usecase_dc_attr[UX500_ENABLE_NODE_INDEX].class_attr.attr); - - err = sysfs_create_group(&(cpu_sysdev_class.kset.kobj), - &dbs_attr_group); - if (err) - pr_err("usecase-gov: sysfs_create_group" - " failed with error = %d\n", err); - - return err; -} - -#include "cpuidle.h" - -static void usecase_cpuidle_init(void) -{ - int max_states; - int i; - struct cstate *state = ux500_ci_get_cstates(&max_states); - - for (i = 0; i < max_states; i++) - if ((state[i].APE == APE_OFF) && (state[i].ARM == ARM_RET)) - break; - - usecase_conf[UX500_UC_LPA].forced_state = i; - - cpuidle_deepest_state = max_states - 1; -} - -/* initialize devices */ -static int __init init_usecase_devices(void) -{ - int err; - - pr_info("Use-case governor initialized\n"); - - /* add early_suspend callback */ - usecase_early_suspend.level = 200; - usecase_early_suspend.suspend = usecase_earlysuspend_callback; - usecase_early_suspend.resume = usecase_lateresume_callback; - register_early_suspend(&usecase_early_suspend); - - /* register delayed queuework */ - INIT_DELAYED_WORK_DEFERRABLE(&work_usecase, - delayed_usecase_work); - - init_cpu_load_trend(); - - err = setup_debugfs(); - if (err) - goto error; - err = usecase_sysfs_init(); - if (err) - goto error2; - - usecase_cpuidle_init(); - - return 0; -error2: - debugfs_remove_recursive(usecase_dir); -error: - unregister_early_suspend(&usecase_early_suspend); - return err; -} - -device_initcall(init_usecase_devices); diff --git a/arch/arm/mach-ux500/prcmu-debug.c b/arch/arm/mach-ux500/prcmu-debug.c deleted file mode 100644 index 139498033fe..00000000000 --- a/arch/arm/mach-ux500/prcmu-debug.c +++ /dev/null @@ -1,550 +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 - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/uaccess.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> - -#include <mach/prcmu.h> - -#define MAX_STATES 5 -#define MAX_NAMELEN 16 - -struct state_history { - ktime_t start; - u32 state; - u32 counter[MAX_STATES]; - u8 opps[MAX_STATES]; - int max_states; - int req; - bool reqs[MAX_STATES]; - ktime_t time[MAX_STATES]; - int state_names[MAX_STATES]; - char prefix[MAX_NAMELEN]; - spinlock_t lock; -}; - -static struct state_history ape_sh = { - .prefix = "APE", - .req = PRCMU_QOS_APE_OPP, - .opps = {APE_50_OPP, APE_100_OPP}, - .state_names = {50, 100}, - .max_states = 2, -}; - -static struct state_history ddr_sh = { - .prefix = "DDR", - .req = PRCMU_QOS_DDR_OPP, - .opps = {DDR_25_OPP, DDR_50_OPP, DDR_100_OPP}, - .state_names = {25, 50, 100}, - .max_states = 3, -}; - -static struct state_history arm_sh = { - .prefix = "ARM", - .req = PRCMU_QOS_ARM_OPP, - .opps = {ARM_EXTCLK, ARM_50_OPP, ARM_100_OPP, ARM_MAX_OPP}, - .state_names = {25, 50, 100, 125}, - .max_states = 4, -}; - -static int ape_voltage_count; - -static void log_set(struct state_history *sh, u8 opp) -{ - ktime_t now; - ktime_t dtime; - unsigned long flags; - int state; - - now = ktime_get(); - spin_lock_irqsave(&sh->lock, flags); - - for (state = 0 ; sh->opps[state] != opp; state++) - ; - BUG_ON(state >= sh->max_states); - - dtime = ktime_sub(now, sh->start); - sh->time[sh->state] = ktime_add(sh->time[sh->state], dtime); - sh->start = now; - sh->counter[sh->state]++; - sh->state = state; - - spin_unlock_irqrestore(&sh->lock, flags); -} - -void prcmu_debug_ape_opp_log(u8 opp) -{ - log_set(&ape_sh, opp); -} - -void prcmu_debug_ddr_opp_log(u8 opp) -{ - log_set(&ddr_sh, opp); -} - -void prcmu_debug_arm_opp_log(u8 opp) -{ - log_set(&arm_sh, opp); -} - -static void log_reset(struct state_history *sh) -{ - unsigned long flags; - int i; - - pr_info("reset\n"); - - spin_lock_irqsave(&sh->lock, flags); - for (i = 0; i < sh->max_states; i++) { - sh->counter[i] = 0; - sh->time[i] = ktime_set(0, 0); - } - - sh->start = ktime_get(); - spin_unlock_irqrestore(&sh->lock, flags); - -} - -static ssize_t ape_stats_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - log_reset(&ape_sh); - return count; -} - -static ssize_t ddr_stats_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - log_reset(&ddr_sh); - return count; -} - -static ssize_t arm_stats_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - log_reset(&arm_sh); - return count; -} - -static int log_print(struct seq_file *s, struct state_history *sh) -{ - int i; - unsigned long flags; - ktime_t total; - ktime_t dtime; - s64 t_ms; - s64 perc; - s64 total_ms; - - spin_lock_irqsave(&sh->lock, flags); - - dtime = ktime_sub(ktime_get(), sh->start); - - total = dtime; - - for (i = 0; i < sh->max_states; i++) - total = ktime_add(total, sh->time[i]); - total_ms = ktime_to_ms(total); - - for (i = 0; i < sh->max_states; i++) { - ktime_t t = sh->time[i]; - if (sh->state == i) - t = ktime_add(t, dtime); - - t_ms = ktime_to_ms(t); - perc = 100 * t_ms; - do_div(perc, total_ms); - - seq_printf(s, "%s OPP %d: # %u in %lld ms %d%%\n", - sh->prefix, sh->state_names[i], - sh->counter[i] + (int)(sh->state == i), - t_ms, (u32)perc); - - } - spin_unlock_irqrestore(&sh->lock, flags); - return 0; -} - -static int ape_stats_print(struct seq_file *s, void *p) -{ - log_print(s, &ape_sh); - return 0; -} - -static int ddr_stats_print(struct seq_file *s, void *p) -{ - log_print(s, &ddr_sh); - return 0; -} - -static int arm_stats_print(struct seq_file *s, void *p) -{ - log_print(s, &arm_sh); - return 0; -} - -static int opp_read(struct seq_file *s, void *p) -{ - int opp; - - struct state_history *sh = (struct state_history *)s->private; - - switch (sh->req) { - case PRCMU_QOS_DDR_OPP: - opp = prcmu_get_ddr_opp(); - seq_printf(s, "%s (%d)\n", - (opp == DDR_100_OPP) ? "100%" : - (opp == DDR_50_OPP) ? "50%" : - (opp == DDR_25_OPP) ? "25%" : - "unknown", opp); - break; - case PRCMU_QOS_APE_OPP: - opp = prcmu_get_ape_opp(); - seq_printf(s, "%s (%d)\n", - (opp == APE_100_OPP) ? "100%" : - (opp == APE_50_OPP) ? "50%" : - "unknown", opp); - break; - case PRCMU_QOS_ARM_OPP: - opp = prcmu_get_arm_opp(); - seq_printf(s, "%s (%d)\n", - (opp == ARM_MAX_OPP) ? "max" : - (opp == ARM_MAX_FREQ100OPP) ? "max-freq100" : - (opp == ARM_100_OPP) ? "100%" : - (opp == ARM_50_OPP) ? "50%" : - (opp == ARM_EXTCLK) ? "25% (extclk)" : - "unknown", opp); - break; - default: - break; - } - return 0; - -} - -static ssize_t opp_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - long unsigned i; - int err; - struct state_history *sh = (struct state_history *) - ((struct seq_file *)file->private_data)->private; - - err = kstrtoul_from_user(user_buf, count, 0, &i); - - if (err) - return err; - - prcmu_qos_force_opp(sh->req, i); - - pr_info("prcmu debug: forced OPP for %s to %d\n", sh->prefix, (int)i); - - return count; -} - -static int cpufreq_delay_read(struct seq_file *s, void *p) -{ - return seq_printf(s, "%lu\n", prcmu_qos_get_cpufreq_opp_delay()); -} - -static int ape_voltage_read(struct seq_file *s, void *p) -{ - return seq_printf(s, "This reference count only includes " - "requests via debugfs.\nCount: %d\n", - ape_voltage_count); -} - -static ssize_t ape_voltage_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - long unsigned i; - int err; - - err = kstrtoul_from_user(user_buf, count, 0, &i); - - if (err) - return err; - - switch (i) { - case 0: - if (ape_voltage_count == 0) - pr_info("prcmu debug: reference count is already 0\n"); - else { - err = prcmu_request_ape_opp_100_voltage(false); - if (err) - pr_err("prcmu debug: drop request failed\n"); - else - ape_voltage_count--; - } - break; - case 1: - err = prcmu_request_ape_opp_100_voltage(true); - if (err) - pr_err("prcmu debug: request failed\n"); - else - ape_voltage_count++; - break; - default: - pr_info("prcmu debug: value not equal to 0 or 1\n"); - } - return count; -} - -static ssize_t cpufreq_delay_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - int err; - long unsigned i; - - err = kstrtoul_from_user(user_buf, count, 0, &i); - - if (err) - return err; - - prcmu_qos_set_cpufreq_opp_delay(i); - - pr_info("prcmu debug: changed delay between cpufreq change and QoS " - "requirement to %lu.\n", i); - - return count; -} - -/* These are just for u8500 */ -#define AVS_VBB_RET 0x0 -#define AVS_VBB_MAX_OPP 0x1 -#define AVS_VBB_100_OPP 0x2 -#define AVS_VBB_50_OPP 0x3 -#define AVS_VARM_MAX_OPP 0x4 -#define AVS_VARM_100_OPP 0x5 -#define AVS_VARM_50_OPP 0x6 -#define AVS_VARM_RET 0x7 -#define AVS_VAPE_100_OPP 0x8 -#define AVS_VAPE_50_OPP 0x9 -#define AVS_VMOD_100_OPP 0xA -#define AVS_VMOD_50_OPP 0xB -#define AVS_VSAFE 0xC -#define AVS_SIZE 14 - -/* TODO: declare this in proper include file when that exists */ -extern void prcmu_dump_avs(u8 *avs, int s); -static int avs_read(struct seq_file *s, void *p) -{ - - u8 avs[AVS_SIZE]; - - if (cpu_is_u8500()) { - prcmu_dump_avs(avs, AVS_SIZE); - - seq_printf(s, "VBB_RET : 0x%2x\n", avs[AVS_VBB_RET]); - seq_printf(s, "VBB_MAX_OPP : 0x%2x\n", avs[AVS_VBB_MAX_OPP]); - seq_printf(s, "VBB_100_OPP : 0x%2x\n", avs[AVS_VBB_100_OPP]); - seq_printf(s, "VBB_50_OPP : 0x%2x\n", avs[AVS_VBB_50_OPP]); - seq_printf(s, "VARM_MAX_OPP : 0x%2x\n", avs[AVS_VARM_MAX_OPP]); - seq_printf(s, "VARM_100_OPP : 0x%2x\n", avs[AVS_VARM_100_OPP]); - seq_printf(s, "VARM_50_OPP : 0x%2x\n", avs[AVS_VARM_50_OPP]); - seq_printf(s, "VARM_RET : 0x%2x\n", avs[AVS_VARM_RET]); - seq_printf(s, "VAPE_100_OPP : 0x%2x\n", avs[AVS_VAPE_100_OPP]); - seq_printf(s, "VAPE_50_OPP : 0x%2x\n", avs[AVS_VAPE_50_OPP]); - seq_printf(s, "VMOD_100_OPP : 0x%2x\n", avs[AVS_VMOD_100_OPP]); - seq_printf(s, "VMOD_50_OPP : 0x%2x\n", avs[AVS_VMOD_50_OPP]); - seq_printf(s, "VSAFE : 0x%2x\n", avs[AVS_VSAFE]); - } else { - seq_printf(s, "Only u8500 supported.\n"); - } - - return 0; -} - -static int opp_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, opp_read, inode->i_private); -} - -static int ape_stats_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, ape_stats_print, inode->i_private); -} - -static int ddr_stats_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, ddr_stats_print, inode->i_private); -} - -static int arm_stats_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, arm_stats_print, inode->i_private); -} - -static int cpufreq_delay_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, cpufreq_delay_read, inode->i_private); -} - -static int ape_voltage_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, ape_voltage_read, inode->i_private); -} - -static int avs_open_file(struct inode *inode, struct file *file) -{ - return single_open(file, avs_read, inode->i_private); -} - -static const struct file_operations opp_fops = { - .open = opp_open_file, - .write = opp_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations ape_stats_fops = { - .open = ape_stats_open_file, - .write = ape_stats_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations ddr_stats_fops = { - .open = ddr_stats_open_file, - .write = ddr_stats_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations arm_stats_fops = { - .open = arm_stats_open_file, - .write = arm_stats_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations cpufreq_delay_fops = { - .open = cpufreq_delay_open_file, - .write = cpufreq_delay_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations ape_voltage_fops = { - .open = ape_voltage_open_file, - .write = ape_voltage_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static const struct file_operations avs_fops = { - .open = avs_open_file, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, -}; - -static int setup_debugfs(void) -{ - struct dentry *dir; - struct dentry *file; - - dir = debugfs_create_dir("prcmu", NULL); - if (IS_ERR_OR_NULL(dir)) - goto fail; - - file = debugfs_create_file("ape_stats", (S_IRUGO | S_IWUGO), - dir, NULL, &ape_stats_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - file = debugfs_create_file("ddr_stats", (S_IRUGO | S_IWUGO), - dir, NULL, &ddr_stats_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - file = debugfs_create_file("arm_stats", (S_IRUGO | S_IWUGO), - dir, NULL, &arm_stats_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - file = debugfs_create_file("ape_opp", (S_IRUGO), - dir, (void *)&ape_sh, - &opp_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - file = debugfs_create_file("ddr_opp", (S_IRUGO), - dir, (void *)&ddr_sh, - &opp_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - file = debugfs_create_file("arm_opp", (S_IRUGO), - dir, (void *)&arm_sh, - &opp_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - file = debugfs_create_file("opp_cpufreq_delay", (S_IRUGO), - dir, NULL, &cpufreq_delay_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - file = debugfs_create_file("ape_voltage", (S_IRUGO), - dir, NULL, &ape_voltage_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - file = debugfs_create_file("avs", - (S_IRUGO), - dir, NULL, &avs_fops); - if (IS_ERR_OR_NULL(file)) - goto fail; - - return 0; -fail: - if (!IS_ERR_OR_NULL(dir)) - debugfs_remove_recursive(dir); - - pr_err("prcmu debug: debugfs entry failed\n"); - return -ENOMEM; -} - -int prcmu_debug_init(void) -{ - spin_lock_init(&ape_sh.lock); - spin_lock_init(&ddr_sh.lock); - spin_lock_init(&arm_sh.lock); - ape_sh.start = ktime_get(); - ddr_sh.start = ktime_get(); - arm_sh.start = ktime_get(); - setup_debugfs(); - return 0; -} diff --git a/arch/arm/mach-ux500/prcmu-qos-power.c b/arch/arm/mach-ux500/prcmu-qos-power.c deleted file mode 100644 index 1f49a60b92e..00000000000 --- a/arch/arm/mach-ux500/prcmu-qos-power.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - * Author: Martin Persson <martin.persson@stericsson.com> - * Per Fransson <per.xx.fransson@stericsson.com> - * - * Quality of Service for the U8500 PRCM Unit interface driver - * - * Strongly influenced by kernel/pm_qos_params.c. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/jiffies.h> -#include <linux/fs.h> -#include <linux/miscdevice.h> -#include <linux/uaccess.h> -#include <linux/cpufreq.h> - -#include <mach/prcmu.h> - -#include "pm/cpufreq.h" -#include "prcmu-debug.h" - -#define ARM_THRESHOLD_FREQ (400000) - -static int qos_delayed_cpufreq_notifier(struct notifier_block *, - unsigned long, void *); - -static s32 cpufreq_requirement_queued; -static s32 cpufreq_requirement_set; - -/* - * locking rule: all changes to requirements or prcmu_qos_object list - * and prcmu_qos_objects need to happen with prcmu_qos_lock - * held, taken with _irqsave. One lock to rule them all - */ -struct requirement_list { - struct list_head list; - union { - s32 value; - s32 usec; - s32 kbps; - }; - char *name; -}; - -static s32 max_compare(s32 v1, s32 v2); - -struct prcmu_qos_object { - struct requirement_list requirements; - struct blocking_notifier_head *notifiers; - struct miscdevice prcmu_qos_power_miscdev; - char *name; - s32 default_value; - s32 force_value; - atomic_t target_value; - s32 (*comparitor)(s32, s32); -}; - -static struct prcmu_qos_object null_qos; -static BLOCKING_NOTIFIER_HEAD(prcmu_ape_opp_notifier); -static BLOCKING_NOTIFIER_HEAD(prcmu_ddr_opp_notifier); - -static struct prcmu_qos_object ape_opp_qos = { - .requirements = { - LIST_HEAD_INIT(ape_opp_qos.requirements.list) - }, - .notifiers = &prcmu_ape_opp_notifier, - .name = "ape_opp", - /* Target value in % APE OPP */ - .default_value = 50, - .force_value = 0, - .target_value = ATOMIC_INIT(0), - .comparitor = max_compare -}; - -static struct prcmu_qos_object ddr_opp_qos = { - .requirements = { - LIST_HEAD_INIT(ddr_opp_qos.requirements.list) - }, - .notifiers = &prcmu_ddr_opp_notifier, - .name = "ddr_opp", - /* Target value in % DDR OPP */ - .default_value = 25, - .force_value = 0, - .target_value = ATOMIC_INIT(0), - .comparitor = max_compare -}; - -static struct prcmu_qos_object arm_opp_qos = { - .requirements = { - LIST_HEAD_INIT(arm_opp_qos.requirements.list) - }, - /* - * No notifier on ARM opp qos request, since this won't actually - * do anything, except changing limits for cpufreq - */ - .name = "arm_opp", - /* Target value in % ARM OPP, note can be 125% */ - .default_value = 25, - .force_value = 0, - .target_value = ATOMIC_INIT(0), - .comparitor = max_compare -}; - -static struct prcmu_qos_object *prcmu_qos_array[] = { - &null_qos, - &ape_opp_qos, - &ddr_opp_qos, - &arm_opp_qos, -}; - -static DEFINE_MUTEX(prcmu_qos_mutex); -static DEFINE_SPINLOCK(prcmu_qos_lock); - -static bool ape_opp_forced_to_50_partly_25; - -static unsigned long cpufreq_opp_delay = HZ / 5; - -unsigned long prcmu_qos_get_cpufreq_opp_delay(void) -{ - return cpufreq_opp_delay; -} - -static struct notifier_block qos_delayed_cpufreq_notifier_block = { - .notifier_call = qos_delayed_cpufreq_notifier, -}; - -void prcmu_qos_set_cpufreq_opp_delay(unsigned long n) -{ - if (n == 0) { - cpufreq_unregister_notifier(&qos_delayed_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - prcmu_qos_update_requirement(PRCMU_QOS_DDR_OPP, "cpufreq", - PRCMU_QOS_DEFAULT_VALUE); - prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "cpufreq", - PRCMU_QOS_DEFAULT_VALUE); - cpufreq_requirement_set = PRCMU_QOS_DEFAULT_VALUE; - cpufreq_requirement_queued = PRCMU_QOS_DEFAULT_VALUE; - } else if (cpufreq_opp_delay != 0) { - cpufreq_register_notifier(&qos_delayed_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - } - cpufreq_opp_delay = n; -} - -static void update_cpu_limits(s32 extreme_value) -{ - int cpu; - struct cpufreq_policy policy; - int ret; - int min_freq, max_freq; - - for_each_online_cpu(cpu) { - ret = cpufreq_get_policy(&policy, cpu); - if (ret) { - pr_err("prcmu qos: get cpufreq policy failed (cpu%d)\n", - cpu); - continue; - } - - ret = ux500_cpufreq_limits(cpu, extreme_value, - &min_freq, &max_freq); - if (ret) - continue; - /* - * cpufreq fw does not allow frequency change if - * "current min freq" > "new max freq" or - * "current max freq" < "new min freq". - * Thus the intermediate steps below. - */ - if (policy.min > max_freq) { - ret = cpufreq_update_freq(cpu, min_freq, policy.max); - if (ret) - pr_err("prcmu qos: update min cpufreq failed (1)\n"); - } - if (policy.max < min_freq) { - ret = cpufreq_update_freq(cpu, policy.min, max_freq); - if (ret) - pr_err("prcmu qos: update max cpufreq failed (2)\n"); - } - - ret = cpufreq_update_freq(cpu, min_freq, max_freq); - if (ret) - pr_err("prcmu qos: update max cpufreq failed (3)\n"); - } - -} - -/* static helper function */ -static s32 max_compare(s32 v1, s32 v2) -{ - return max(v1, v2); -} - -static void update_target(int target) -{ - s32 extreme_value; - struct requirement_list *node; - unsigned long flags; - bool update = false; - u8 op; - - mutex_lock(&prcmu_qos_mutex); - - spin_lock_irqsave(&prcmu_qos_lock, flags); - extreme_value = prcmu_qos_array[target]->default_value; - - if (prcmu_qos_array[target]->force_value != 0) { - extreme_value = prcmu_qos_array[target]->force_value; - update = true; - } else { - list_for_each_entry(node, - &prcmu_qos_array[target]->requirements.list, - list) { - extreme_value = prcmu_qos_array[target]->comparitor( - extreme_value, node->value); - } - if (atomic_read(&prcmu_qos_array[target]->target_value) - != extreme_value) { - update = true; - atomic_set(&prcmu_qos_array[target]->target_value, - extreme_value); - pr_debug("prcmu qos: new target for qos %d is %d\n", - target, atomic_read( - &prcmu_qos_array[target]->target_value - )); - } - } - spin_unlock_irqrestore(&prcmu_qos_lock, flags); - - if (!update) - goto unlock_and_return; - - if (prcmu_qos_array[target]->notifiers) - blocking_notifier_call_chain(prcmu_qos_array[target]->notifiers, - (unsigned long)extreme_value, - NULL); - - switch (target) { - case PRCMU_QOS_DDR_OPP: - switch (extreme_value) { - case 50: - op = DDR_50_OPP; - pr_debug("prcmu qos: set ddr opp to 50%%\n"); - break; - case 100: - op = DDR_100_OPP; - pr_debug("prcmu qos: set ddr opp to 100%%\n"); - break; - case 25: - /* 25% DDR OPP is not supported on 5500 */ - if (!cpu_is_u5500()) { - op = DDR_25_OPP; - pr_debug("prcmu qos: set ddr opp to 25%%\n"); - break; - } - default: - pr_err("prcmu qos: Incorrect ddr target value (%d)", - extreme_value); - goto unlock_and_return; - } - prcmu_debug_ddr_opp_log(op); - prcmu_set_ddr_opp(op); - break; - case PRCMU_QOS_APE_OPP: - switch (extreme_value) { - case 50: - op = APE_50_OPP; - pr_debug("prcmu qos: set ape opp to 50%%\n"); - break; - case 100: - op = APE_100_OPP; - pr_debug("prcmu qos: set ape opp to 100%%\n"); - break; - default: - pr_err("prcmu qos: Incorrect ape target value (%d)", - extreme_value); - goto unlock_and_return; - } - - if (!ape_opp_forced_to_50_partly_25) - (void)prcmu_set_ape_opp(op); - prcmu_debug_ape_opp_log(op); - break; - case PRCMU_QOS_ARM_OPP: - { - mutex_unlock(&prcmu_qos_mutex); - /* - * We can't hold the mutex since changing cpufreq - * will trigger an prcmu fw callback. - */ - update_cpu_limits(extreme_value); - /* Return since the lock is unlocked */ - return; - - break; - } - default: - pr_err("prcmu qos: Incorrect target\n"); - break; - } - -unlock_and_return: - mutex_unlock(&prcmu_qos_mutex); -} - -void prcmu_qos_force_opp(int prcmu_qos_class, s32 i) -{ - prcmu_qos_array[prcmu_qos_class]->force_value = i; - update_target(prcmu_qos_class); -} - -void prcmu_qos_voice_call_override(bool enable) -{ - u8 op; - - mutex_lock(&prcmu_qos_mutex); - - ape_opp_forced_to_50_partly_25 = enable; - - if (enable) { - (void)prcmu_set_ape_opp(APE_50_PARTLY_25_OPP); - goto unlock_and_return; - } - - /* Disable: set the OPP according to the current target value. */ - switch (atomic_read( - &prcmu_qos_array[PRCMU_QOS_APE_OPP]->target_value)) { - case 50: - op = APE_50_OPP; - break; - case 100: - op = APE_100_OPP; - break; - default: - goto unlock_and_return; - } - - (void)prcmu_set_ape_opp(op); - -unlock_and_return: - mutex_unlock(&prcmu_qos_mutex); -} - -/** - * prcmu_qos_requirement - returns current prcmu qos expectation - * @prcmu_qos_class: identification of which qos value is requested - * - * This function returns the current target value in an atomic manner. - */ -int prcmu_qos_requirement(int prcmu_qos_class) -{ - return atomic_read(&prcmu_qos_array[prcmu_qos_class]->target_value); -} -EXPORT_SYMBOL_GPL(prcmu_qos_requirement); - -/** - * prcmu_qos_add_requirement - inserts new qos request into the list - * @prcmu_qos_class: identifies which list of qos request to us - * @name: identifies the request - * @value: defines the qos request - * - * This function inserts a new entry in the prcmu_qos_class list of requested - * qos performance characteristics. It recomputes the aggregate QoS - * expectations for the prcmu_qos_class of parameters. - */ -int prcmu_qos_add_requirement(int prcmu_qos_class, char *name, s32 value) -{ - struct requirement_list *dep; - unsigned long flags; - - dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL); - if (dep == NULL) - return -ENOMEM; - - if (value == PRCMU_QOS_DEFAULT_VALUE) - dep->value = prcmu_qos_array[prcmu_qos_class]->default_value; - else - dep->value = value; - dep->name = kstrdup(name, GFP_KERNEL); - if (!dep->name) - goto cleanup; - - spin_lock_irqsave(&prcmu_qos_lock, flags); - list_add(&dep->list, - &prcmu_qos_array[prcmu_qos_class]->requirements.list); - spin_unlock_irqrestore(&prcmu_qos_lock, flags); - update_target(prcmu_qos_class); - - return 0; - -cleanup: - kfree(dep); - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(prcmu_qos_add_requirement); - -/** - * prcmu_qos_update_requirement - modifies an existing qos request - * @prcmu_qos_class: identifies which list of qos request to us - * @name: identifies the request - * @value: defines the qos request - * - * Updates an existing qos requirement for the prcmu_qos_class of parameters - * along with updating the target prcmu_qos_class value. - * - * If the named request isn't in the list then no change is made. - */ -int prcmu_qos_update_requirement(int prcmu_qos_class, char *name, s32 new_value) -{ - unsigned long flags; - struct requirement_list *node; - int pending_update = 0; - - spin_lock_irqsave(&prcmu_qos_lock, flags); - list_for_each_entry(node, - &prcmu_qos_array[prcmu_qos_class]->requirements.list, list) { - if (strcmp(node->name, name) == 0) { - if (new_value == PRCMU_QOS_DEFAULT_VALUE) - node->value = - prcmu_qos_array[prcmu_qos_class]->default_value; - else - node->value = new_value; - pending_update = 1; - break; - } - } - spin_unlock_irqrestore(&prcmu_qos_lock, flags); - if (pending_update) - update_target(prcmu_qos_class); - - return 0; -} -EXPORT_SYMBOL_GPL(prcmu_qos_update_requirement); - -/** - * prcmu_qos_remove_requirement - modifies an existing qos request - * @prcmu_qos_class: identifies which list of qos request to us - * @name: identifies the request - * - * Will remove named qos request from prcmu_qos_class list of parameters and - * recompute the current target value for the prcmu_qos_class. - */ -void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name) -{ - unsigned long flags; - struct requirement_list *node; - int pending_update = 0; - - spin_lock_irqsave(&prcmu_qos_lock, flags); - list_for_each_entry(node, - &prcmu_qos_array[prcmu_qos_class]->requirements.list, list) { - if (strcmp(node->name, name) == 0) { - kfree(node->name); - list_del(&node->list); - kfree(node); - pending_update = 1; - break; - } - } - spin_unlock_irqrestore(&prcmu_qos_lock, flags); - if (pending_update) - update_target(prcmu_qos_class); -} -EXPORT_SYMBOL_GPL(prcmu_qos_remove_requirement); - -/** - * prcmu_qos_add_notifier - sets notification entry for changes to target value - * @prcmu_qos_class: identifies which qos target changes should be notified. - * @notifier: notifier block managed by caller. - * - * will register the notifier into a notification chain that gets called - * upon changes to the prcmu_qos_class target value. - */ -int prcmu_qos_add_notifier(int prcmu_qos_class, struct notifier_block *notifier) -{ - int retval = -EINVAL; - - if (prcmu_qos_array[prcmu_qos_class]->notifiers) - retval = blocking_notifier_chain_register( - prcmu_qos_array[prcmu_qos_class]->notifiers, notifier); - - return retval; -} -EXPORT_SYMBOL_GPL(prcmu_qos_add_notifier); - -/** - * prcmu_qos_remove_notifier - deletes notification entry from chain. - * @prcmu_qos_class: identifies which qos target changes are notified. - * @notifier: notifier block to be removed. - * - * will remove the notifier from the notification chain that gets called - * upon changes to the prcmu_qos_class target value. - */ -int prcmu_qos_remove_notifier(int prcmu_qos_class, - struct notifier_block *notifier) -{ - int retval = -EINVAL; - if (prcmu_qos_array[prcmu_qos_class]->notifiers) - retval = blocking_notifier_chain_unregister( - prcmu_qos_array[prcmu_qos_class]->notifiers, notifier); - - return retval; -} -EXPORT_SYMBOL_GPL(prcmu_qos_remove_notifier); - -#define USER_QOS_NAME_LEN 32 - -static int prcmu_qos_power_open(struct inode *inode, struct file *filp, - long prcmu_qos_class) -{ - int ret; - char name[USER_QOS_NAME_LEN]; - - filp->private_data = (void *)prcmu_qos_class; - snprintf(name, USER_QOS_NAME_LEN, "file_%08x", (unsigned int)filp); - ret = prcmu_qos_add_requirement(prcmu_qos_class, name, - PRCMU_QOS_DEFAULT_VALUE); - if (ret >= 0) - return 0; - - return -EPERM; -} - - -static int prcmu_qos_ape_power_open(struct inode *inode, struct file *filp) -{ - return prcmu_qos_power_open(inode, filp, PRCMU_QOS_APE_OPP); -} - -static int prcmu_qos_ddr_power_open(struct inode *inode, struct file *filp) -{ - return prcmu_qos_power_open(inode, filp, PRCMU_QOS_DDR_OPP); -} - -static int prcmu_qos_power_release(struct inode *inode, struct file *filp) -{ - int prcmu_qos_class; - char name[USER_QOS_NAME_LEN]; - - prcmu_qos_class = (long)filp->private_data; - snprintf(name, USER_QOS_NAME_LEN, "file_%08x", (unsigned int)filp); - prcmu_qos_remove_requirement(prcmu_qos_class, name); - - return 0; -} - -static ssize_t prcmu_qos_power_write(struct file *filp, const char __user *buf, - size_t count, loff_t *f_pos) -{ - s32 value; - int prcmu_qos_class; - char name[USER_QOS_NAME_LEN]; - - prcmu_qos_class = (long)filp->private_data; - if (count != sizeof(s32)) - return -EINVAL; - if (copy_from_user(&value, buf, sizeof(s32))) - return -EFAULT; - snprintf(name, USER_QOS_NAME_LEN, "file_%08x", (unsigned int)filp); - prcmu_qos_update_requirement(prcmu_qos_class, name, value); - - return sizeof(s32); -} - -/* Functions to provide QoS to user space */ -static const struct file_operations prcmu_qos_ape_power_fops = { - .write = prcmu_qos_power_write, - .open = prcmu_qos_ape_power_open, - .release = prcmu_qos_power_release, -}; - -/* Functions to provide QoS to user space */ -static const struct file_operations prcmu_qos_ddr_power_fops = { - .write = prcmu_qos_power_write, - .open = prcmu_qos_ddr_power_open, - .release = prcmu_qos_power_release, -}; - -static int register_prcmu_qos_misc(struct prcmu_qos_object *qos, - const struct file_operations *fops) -{ - qos->prcmu_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR; - qos->prcmu_qos_power_miscdev.name = qos->name; - qos->prcmu_qos_power_miscdev.fops = fops; - - return misc_register(&qos->prcmu_qos_power_miscdev); -} - -static void qos_delayed_work_up_fn(struct work_struct *work) -{ - prcmu_qos_update_requirement(PRCMU_QOS_DDR_OPP, "cpufreq", 100); - prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "cpufreq", 100); - cpufreq_requirement_set = 100; -} - -static void qos_delayed_work_down_fn(struct work_struct *work) -{ - prcmu_qos_update_requirement(PRCMU_QOS_DDR_OPP, "cpufreq", - PRCMU_QOS_DEFAULT_VALUE); - prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, "cpufreq", - PRCMU_QOS_DEFAULT_VALUE); - cpufreq_requirement_set = PRCMU_QOS_DEFAULT_VALUE; -} - -static DECLARE_DELAYED_WORK(qos_delayed_work_up, qos_delayed_work_up_fn); -static DECLARE_DELAYED_WORK(qos_delayed_work_down, qos_delayed_work_down_fn); - -static int qos_delayed_cpufreq_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct cpufreq_freqs *freq = data; - s32 new_ddr_target; - - /* Only react once per transition and only for one core, e.g. core 0 */ - if (event != CPUFREQ_POSTCHANGE || freq->cpu != 0) - return 0; - - /* - * APE and DDR OPP are always handled together in this solution. - * Hence no need to check both DDR and APE opp in the code below. - */ - - /* Which DDR OPP are we aiming for? */ - if (freq->new > ARM_THRESHOLD_FREQ) - new_ddr_target = 100; - else - new_ddr_target = PRCMU_QOS_DEFAULT_VALUE; - - if (new_ddr_target == cpufreq_requirement_queued) { - /* - * We're already at, or going to, the target requirement. - * This is only a fluctuation within the interval - * corresponding to the same DDR requirement. - */ - return 0; - } - cpufreq_requirement_queued = new_ddr_target; - - if (freq->new > ARM_THRESHOLD_FREQ) { - cancel_delayed_work_sync(&qos_delayed_work_down); - /* - * Only schedule this requirement if it is not the current - * one. - */ - if (new_ddr_target != cpufreq_requirement_set) - schedule_delayed_work(&qos_delayed_work_up, - cpufreq_opp_delay); - } else { - cancel_delayed_work_sync(&qos_delayed_work_up); - /* - * Only schedule this requirement if it is not the current - * one. - */ - if (new_ddr_target != cpufreq_requirement_set) - schedule_delayed_work(&qos_delayed_work_down, - cpufreq_opp_delay); - } - - return 0; -} - -static int __init prcmu_qos_power_init(void) -{ - int ret = 0; - - /* 25% DDR OPP is not supported on 5500 */ - if (cpu_is_u5500()) - ddr_opp_qos.default_value = 50; - - ret = register_prcmu_qos_misc(&ape_opp_qos, &prcmu_qos_ape_power_fops); - if (ret < 0) { - pr_err("prcmu ape qos: setup failed\n"); - return ret; - } - - ret = register_prcmu_qos_misc(&ddr_opp_qos, &prcmu_qos_ddr_power_fops); - if (ret < 0) { - pr_err("prcmu ddr qos: setup failed\n"); - return ret; - } - - prcmu_qos_add_requirement(PRCMU_QOS_DDR_OPP, "cpufreq", - PRCMU_QOS_DEFAULT_VALUE); - prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, "cpufreq", - PRCMU_QOS_DEFAULT_VALUE); - cpufreq_requirement_set = PRCMU_QOS_DEFAULT_VALUE; - cpufreq_requirement_queued = PRCMU_QOS_DEFAULT_VALUE; - - cpufreq_register_notifier(&qos_delayed_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); - - return ret; -} - -late_initcall(prcmu_qos_power_init); diff --git a/arch/arm/mach-ux500/timer-mtu.c b/arch/arm/mach-ux500/timer-mtu.c deleted file mode 100644 index b06559787c6..00000000000 --- a/arch/arm/mach-ux500/timer-mtu.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * linux/arch/arm/mach-u8500/timer.c - * - * Copyright (C) 2008 STMicroelectronics - * Copyright (C) 2009 Alessandro Rubini, somewhat based on at91sam926x - * Copyright (C) 2009 ST-Ericsson SA - * added support to u8500 platform, heavily based on 8815 - * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> - * - * 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. - */ -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <linux/clockchips.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/jiffies.h> -//#include <linux/boottime.h> -#include <linux/cnt32_to_63.h> -#include <asm/mach/time.h> -#include <plat/mtu.h> -#include <mach/setup.h> - -#define TIMER_CTRL 0x80 /* No divisor */ -#define TIMER_PERIODIC 0x40 -#define TIMER_SZ32BIT 0x02 - -#define MTU_CRn_DIS (0x00 << 7) -#define MTU_CRn_FREERUNNING (0x00 << 6) - -static u32 u8500_cycle; /* write-once */ -static __iomem void *mtu0_base; -static bool mtu_periodic; - -/* - * U8500 sched_clock implementation. It has a resolution of - * at least 7.5ns (133MHz MTU rate) and a maximum value of 834 days. - * - * Because the hardware timer period is quite short (32.3 secs - * and because cnt32_to_63() needs to be called at - * least once per half period to work properly, a kernel timer is - * set up to ensure this requirement is always met. - * - * Based on plat-orion time.c implementation. - */ -#define TCLK2NS_SCALE_FACTOR 8 - -#ifdef CONFIG_UX500_MTU_TIMER -static unsigned long tclk2ns_scale; -static struct timer_list cnt32_to_63_keepwarm_timer; - -unsigned long long sched_clock(void) -{ - unsigned long long v; - - if (unlikely(!mtu0_base)) - return 0; - - v = cnt32_to_63(0xffffffff - readl(mtu0_base + MTU_VAL(1))); - return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR; -} - -static void cnt32_to_63_keepwarm(unsigned long data) -{ - mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data)); - (void) sched_clock(); -} - -static void __init setup_sched_clock(unsigned long tclk) -{ - unsigned long long v; - unsigned long data; - - v = NSEC_PER_SEC; - v <<= TCLK2NS_SCALE_FACTOR; - v += tclk / 2; - do_div(v, tclk); - /* - * We want an even value to automatically clear the top bit - * returned by cnt32_to_63() without an additional run time - * instruction. So if the LSB is 1 then round it up. - */ - if (v & 1) - v++; - tclk2ns_scale = v; - - data = (0xffffffffUL / tclk / 2 - 2) * HZ; - setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, data); - mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data)); -} -#else -static void __init setup_sched_clock(unsigned long tclk) -{ -} -#endif -/* - * clocksource: the MTU device is a decrementing counters, so we negate - * the value being read. - */ -static cycle_t u8500_read_timer(struct clocksource *cs) -{ - u32 count = readl(mtu0_base + MTU_VAL(1)); - return ~count; -} -/* - * Kernel assumes that sched_clock can be called early - * but the MTU may not yet be initialized. - */ -static cycle_t u8500_read_timer_dummy(struct clocksource *cs) -{ - return 0; -} - -void mtu_clocksource_reset(void) -{ - writel(MTU_CRn_DIS, mtu0_base + MTU_CR(1)); - - /* ClockSource: configure load and background-load, and fire it up */ - writel(u8500_cycle, mtu0_base + MTU_LR(1)); - writel(u8500_cycle, mtu0_base + MTU_BGLR(1)); - - writel(MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS | MTU_CRn_ENA | - MTU_CRn_FREERUNNING, mtu0_base + MTU_CR(1)); -} - -static struct clocksource u8500_clksrc = { - .name = "mtu_1", - .rating = 120, - .read = u8500_read_timer_dummy, - .shift = 20, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -#ifdef ARCH_HAS_READ_CURRENT_TIMER -void mtu_timer_delay_loop(unsigned long loops) -{ - unsigned long bclock, now; - - bclock = u8500_read_timer(&u8500_clksrc); - do { - now = u8500_read_timer(&u8500_clksrc); - /* If timer have been cleared (suspend) or wrapped we exit */ - if (unlikely(now < bclock)) - return; - } while ((now - bclock) < loops); -} - -/* Used to calibrate the delay */ -int read_current_timer(unsigned long *timer_val) -{ - *timer_val = u8500_read_timer(&u8500_clksrc); - return 0; -} -#endif - -/* - * Clockevent - */ -static int u8500_mtu_clkevt_next(unsigned long evt, struct clock_event_device *ev) -{ - writel(1 << 0, mtu0_base + MTU_IMSC); - writel(evt, mtu0_base + MTU_LR(0)); - /* Load highest value, enable device, enable interrupts */ - writel(MTU_CRn_ONESHOT | MTU_CRn_PRESCALE_1 | - MTU_CRn_32BITS | MTU_CRn_ENA, - mtu0_base + MTU_CR(0)); - return 0; -} - -void mtu_clockevent_reset(void) -{ - if (mtu_periodic) { - - /* Timer: configure load and background-load, and fire it up */ - writel(u8500_cycle, mtu0_base + MTU_LR(0)); - writel(u8500_cycle, mtu0_base + MTU_BGLR(0)); - - writel(MTU_CRn_PERIODIC | MTU_CRn_PRESCALE_1 | - MTU_CRn_32BITS | MTU_CRn_ENA, - mtu0_base + MTU_CR(0)); - writel(1 << 0, mtu0_base + MTU_IMSC); - } else { - /* Generate an interrupt to start the clockevent again */ - u8500_mtu_clkevt_next(u8500_cycle, NULL); - } -} - -static void u8500_mtu_clkevt_mode(enum clock_event_mode mode, - struct clock_event_device *dev) -{ - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - mtu_periodic = true; - mtu_clockevent_reset(); - break; - case CLOCK_EVT_MODE_ONESHOT: - mtu_periodic = false; - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - writel(MTU_CRn_DIS, mtu0_base + MTU_CR(0)); - writel(0, mtu0_base + MTU_IMSC); - break; - case CLOCK_EVT_MODE_RESUME: - break; - } -} - -/* - * IRQ Handler for the timer 0 of the MTU block. The irq is not shared - * as we are the only users of mtu0 by now. - */ -static irqreturn_t u8500_timer_interrupt(int irq, void *dev) -{ - struct clock_event_device *clkevt = dev; - /* ack: "interrupt clear register" */ - writel(1 << 0, mtu0_base + MTU_ICR); - - clkevt->event_handler(clkevt); - - return IRQ_HANDLED; -} - -/* - * Added here as asm/smp.h is removed in v2.6.34 and - * this funcitons is needed for current PM setup. - */ -#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST -void smp_timer_broadcast(const struct cpumask *mask); -#endif - -struct clock_event_device u8500_mtu_clkevt = { - .name = "mtu_0", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - /* Must be of higher rating the timer-rtt but lower than localtimers */ - .rating = 310, - .set_mode = u8500_mtu_clkevt_mode, - .set_next_event = u8500_mtu_clkevt_next, - .irq = IRQ_MTU0, -#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST - .broadcast = smp_timer_broadcast, -#endif - .cpumask = cpu_all_mask, -}; - -/* - * Set up timer interrupt, and return the current time in seconds. - */ -static struct irqaction u8500_timer_irq = { - .name = "MTU Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER, - .handler = u8500_timer_interrupt, - .dev_id = &u8500_mtu_clkevt, -}; - -void __init mtu_timer_init(void) -{ - unsigned long rate; - struct clk *clk0; - - clk0 = clk_get_sys("mtu0", NULL); - BUG_ON(IS_ERR(clk0)); - - rate = clk_get_rate(clk0); - - clk_enable(clk0); - - /* - * Set scale and timer for sched_clock - */ - setup_sched_clock(rate); - u8500_cycle = (rate + HZ/2) / HZ; - - /* Save global pointer to mtu, used by functions above */ - if (cpu_is_u5500()) { - mtu0_base = ioremap(U5500_MTU0_BASE, SZ_4K); - } else if (cpu_is_u8500()) { - mtu0_base = ioremap(U8500_MTU0_BASE, SZ_4K); - } else { - ux500_unknown_soc(); - } - - /* Restart clock source */ - mtu_clocksource_reset(); - - /* Now the scheduling clock is ready */ - u8500_clksrc.read = u8500_read_timer; - u8500_clksrc.mult = clocksource_hz2mult(rate, u8500_clksrc.shift); - - clocksource_register(&u8500_clksrc); - - /* Register irq and clockevents */ - - /* We can sleep for max 10s (actually max is longer) */ - clockevents_calc_mult_shift(&u8500_mtu_clkevt, rate, 10); - - u8500_mtu_clkevt.max_delta_ns = clockevent_delta2ns(0xffffffff, - &u8500_mtu_clkevt); - u8500_mtu_clkevt.min_delta_ns = clockevent_delta2ns(0xff, - &u8500_mtu_clkevt); - - setup_irq(IRQ_MTU0, &u8500_timer_irq); - clockevents_register_device(&u8500_mtu_clkevt); -#ifdef ARCH_HAS_READ_CURRENT_TIMER - set_delay_fn(mtu_timer_delay_loop); -#endif -} diff --git a/arch/arm/mach-ux500/timer-prcmu.c b/arch/arm/mach-ux500/timer-prcmu.c deleted file mode 100644 index 24f6b48e970..00000000000 --- a/arch/arm/mach-ux500/timer-prcmu.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * License Terms: GNU General Public License v2 - * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson - * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson - * sched_clock implementation is based on: - * plat-nomadik/timer.c Linus Walleij <linus.walleij@stericsson.com> - * - * DBx500-PRCMU Timer - * The PRCMU has 5 timers which are available in a always-on - * power domain. We use the Timer 4 for our always-on clock - * source on DB8500 and Timer 3 on DB5500. - */ -#include <linux/clockchips.h> -#include <linux/clk.h> -#include <linux/jiffies.h> -#include <linux/boottime.h> -#include <linux/cnt32_to_63.h> -#include <linux/sched.h> -#include <mach/setup.h> -#include <mach/db8500-regs.h> -#include <mach/hardware.h> - -#define RATE_32K (32768) - -#define TIMER_MODE_CONTINOUS (0x1) -#define TIMER_DOWNCOUNT_VAL (0xffffffff) - -#define PRCMU_TIMER_3_BASE 0x338 -#define PRCMU_TIMER_4_BASE 0x450 - -#define PRCMU_TIMER_REF 0x0 -#define PRCMU_TIMER_DOWNCOUNT 0x4 -#define PRCMU_TIMER_MODE 0x8 - -static __iomem void *timer_base; - -#define SCHED_CLOCK_MIN_WRAP (131072) /* 2^32 / 32768 */ - -static cycle_t prcmu_read_timer_nop(struct clocksource *cs) -{ - return 0; -} - -static struct clocksource prcmu_clksrc = { - .name = "prcmu-timer", - .rating = 300, - .read = prcmu_read_timer_nop, - .shift = 10, - .mask = CLOCKSOURCE_MASK(32), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static cycle_t prcmu_read_timer(struct clocksource *cs) -{ - u32 count, count2; - - do { - count = readl(timer_base + PRCMU_TIMER_DOWNCOUNT); - count2 = readl(timer_base + PRCMU_TIMER_DOWNCOUNT); - } while (count2 != count); - - /* - * clocksource: the prcmu timer is a decrementing counters, so we negate - * the value being read. - */ - return ~count; -} - -#ifdef CONFIG_UX500_PRCMU_TIMER -unsigned long long notrace sched_clock(void) -{ - return clocksource_cyc2ns(prcmu_clksrc.read( - &prcmu_clksrc), - prcmu_clksrc.mult, - prcmu_clksrc.shift); -} -#endif - -#ifdef CONFIG_BOOTTIME - -static unsigned long __init boottime_get_time(void) -{ - return div_s64(clocksource_cyc2ns(prcmu_clksrc.read( - &prcmu_clksrc), - prcmu_clksrc.mult, - prcmu_clksrc.shift), 1000); -} - -static struct boottime_timer __initdata boottime_timer = { - .init = NULL, - .get_time = boottime_get_time, - .finalize = NULL, -}; -#endif - -void __init prcmu_timer_init(void) -{ - void __iomem *prcmu_base; - - if (ux500_is_svp()) - return; - - if (cpu_is_u8500()) { - prcmu_base = __io_address(U8500_PRCMU_BASE); - timer_base = prcmu_base + PRCMU_TIMER_4_BASE; - } else if (cpu_is_u5500()) { - prcmu_base = __io_address(U5500_PRCMU_BASE); - timer_base = prcmu_base + PRCMU_TIMER_3_BASE; - } else - ux500_unknown_soc(); - - clocksource_calc_mult_shift(&prcmu_clksrc, - RATE_32K, SCHED_CLOCK_MIN_WRAP); - - /* - * The A9 sub system expects the timer to be configured as - * a continous looping timer. - * The PRCMU should configure it but if it for some reason - * don't we do it here. - */ - if (readl(timer_base + PRCMU_TIMER_MODE) != TIMER_MODE_CONTINOUS) { - writel(TIMER_MODE_CONTINOUS, timer_base + PRCMU_TIMER_MODE); - writel(TIMER_DOWNCOUNT_VAL, timer_base + PRCMU_TIMER_REF); - } - prcmu_clksrc.read = prcmu_read_timer; - - clocksource_register(&prcmu_clksrc); - - if (!ux500_is_svp()) - boottime_activate(&boottime_timer); -} - diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c deleted file mode 100644 index 7eb6241a924..00000000000 --- a/arch/arm/mach-ux500/timer.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * License Terms: GNU General Public License v2 - * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson - */ -#include <linux/io.h> -#include <mach/setup.h> -#include <mach/hardware.h> - -#include "pm/context.h" - -void rtc_rtt_timer_init(unsigned int cpu); -void prcmu_timer_init(void); -void mtu_timer_init(void); -void mtu_clocksource_reset(void); -void mtu_clockevent_reset(void); - -#ifdef CONFIG_LOCAL_TIMERS -#include <asm/smp_twd.h> -#endif - -#ifdef CONFIG_UX500_CONTEXT -static int mtu_context_notifier_call(struct notifier_block *this, - unsigned long event, void *data) -{ - if (event == CONTEXT_APE_RESTORE) - mtu_clocksource_reset(); - return NOTIFY_OK; -} - -static struct notifier_block mtu_context_notifier = { - .notifier_call = mtu_context_notifier_call, -}; -#endif - -static void ux500_timer_reset(void) -{ - mtu_clockevent_reset(); -} - -static void __init ux500_timer_init(void) -{ - -#ifdef CONFIG_LOCAL_TIMERS - if (cpu_is_u5500()) - twd_base = __io_address(U5500_TWD_BASE); - else if (cpu_is_u8500()) - twd_base = __io_address(U8500_TWD_BASE); - else - ux500_unknown_soc(); -#endif -/* - * Here we register the timerblocks active in the system. - * Localtimers (twd) is started when both cpu is up and running. - * MTU register a clocksource, clockevent and sched_clock. - * Since the MTU is located in the VAPE power domain - * it will be cleared in sleep which makes it unsuitable. - * We however need it as a timer tick (clockevent) - * during boot to calibrate delay until twd is started. - * RTC-RTT have problems as timer tick during boot since it is depending - * on delay which is not yet calibrated. RTC-RTT is in the always-on - * powerdomain and is used as clockevent instead of twd when sleeping. - * The PRCMU timer 4 register a clocksource and sched_clock with higher - * rating then MTU since is always-on. - * - */ - mtu_timer_init(); -#ifdef CONFIG_UX500_PRCMU_TIMER - prcmu_timer_init(); -#endif - -#ifdef CONFIG_UX500_CONTEXT - WARN_ON(context_ape_notifier_register(&mtu_context_notifier)); -#endif -} - -struct sys_timer ux500_timer = { - .init = ux500_timer_init, - .resume = ux500_timer_reset, -}; diff --git a/arch/arm/mach-ux500/uart-db8500.c b/arch/arm/mach-ux500/uart-db8500.c deleted file mode 100644 index aae1246ab09..00000000000 --- a/arch/arm/mach-ux500/uart-db8500.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2011 - * - * Author: Arun R Murthy <arun.murthy@stericsson.com>, - * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson - * - * License terms: GNU General Public License (GPL) version 2 - */ - -#include <linux/kernel.h> -#include <linux/io.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/amba/serial.h> -#include <mach/setup.h> -#include <mach/hardware.h> - -#include "pm/context.h" - -#ifdef CONFIG_UX500_CONTEXT - -static struct { - struct clk *uart_clk; - void __iomem *base; - /* dr */ - /* rsr_err */ - u32 dma_wm; - u32 timeout; - /* fr */ - u32 lcrh_rx; - u32 ilpr; - u32 ibrd; - u32 fbrd; - u32 lcrh_tx; - u32 cr; - u32 ifls; - u32 imsc; - /* ris */ - /* mis */ - /* icr */ - u32 dmacr; - u32 xfcr; - u32 xon1; - u32 xon2; - u32 xoff1; - u32 xoff2; - /* itcr */ - /* itip */ - /* itop */ - /* tdr */ - u32 abcr; - /* absr */ - /* abfmt */ - /* abdr */ - /* abdfr */ - /* abmr */ - u32 abimsc; - /* abris */ - /* abmis */ - /* abicr */ - /* id_product_h_xy */ - /* id_provider */ - /* periphid0 */ - /* periphid1 */ - /* periphid2 */ - /* periphid3 */ - /* pcellid0 */ - /* pcellid1 */ - /* pcellid2 */ - /* pcellid3 */ -} context_uart; - -static void save_uart(void) -{ - void __iomem *membase; - - membase = context_uart.base; - - clk_enable(context_uart.uart_clk); - - context_uart.dma_wm = readl_relaxed(membase + ST_UART011_DMAWM); - context_uart.timeout = readl_relaxed(membase + ST_UART011_TIMEOUT); - context_uart.lcrh_rx = readl_relaxed(membase + ST_UART011_LCRH_RX); - context_uart.ilpr = readl_relaxed(membase + UART01x_ILPR); - context_uart.ibrd = readl_relaxed(membase + UART011_IBRD); - context_uart.fbrd = readl_relaxed(membase + UART011_FBRD); - context_uart.lcrh_tx = readl_relaxed(membase + ST_UART011_LCRH_TX); - context_uart.cr = readl_relaxed(membase + UART011_CR); - context_uart.ifls = readl_relaxed(membase + UART011_IFLS); - context_uart.imsc = readl_relaxed(membase + UART011_IMSC); - context_uart.dmacr = readl_relaxed(membase + UART011_DMACR); - context_uart.xfcr = readl_relaxed(membase + ST_UART011_XFCR); - context_uart.xon1 = readl_relaxed(membase + ST_UART011_XON1); - context_uart.xon2 = readl_relaxed(membase + ST_UART011_XON2); - context_uart.xoff1 = readl_relaxed(membase + ST_UART011_XOFF1); - context_uart.xoff2 = readl_relaxed(membase + ST_UART011_XOFF2); - context_uart.abcr = readl_relaxed(membase + ST_UART011_ABCR); - context_uart.abimsc = readl_relaxed(membase + ST_UART011_ABIMSC); - - clk_disable(context_uart.uart_clk); -} - -static void restore_uart(void) -{ - int cnt; - int retries = 100; - unsigned int cr; - void __iomem *membase; - u16 dummy; - bool show_warn = false; - - membase = context_uart.base; - clk_enable(context_uart.uart_clk); - - writew_relaxed(context_uart.ifls, membase + UART011_IFLS); - cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE; - - writew_relaxed(cr, membase + UART011_CR); - writew_relaxed(0, membase + UART011_FBRD); - writew_relaxed(1, membase + UART011_IBRD); - writew_relaxed(0, membase + ST_UART011_LCRH_RX); - if (context_uart.lcrh_tx != ST_UART011_LCRH_RX) { - int i; - /* - * Wait 10 PCLKs before writing LCRH_TX register, - * to get this delay write read only register 10 times - */ - for (i = 0; i < 10; ++i) - dummy = readw(membase + ST_UART011_LCRH_RX); - writew_relaxed(0, membase + ST_UART011_LCRH_TX); - } - writew(0, membase + UART01x_DR); - do { - if (!(readw(membase + UART01x_FR) & UART01x_FR_BUSY)) - break; - cpu_relax(); - } while (retries-- > 0); - if (retries < 0) - /* - * We can't print out a warning here since the uart is - * not fully restored. Do it later. - */ - show_warn = true; - - writel_relaxed(context_uart.dma_wm, membase + ST_UART011_DMAWM); - writel_relaxed(context_uart.timeout, membase + ST_UART011_TIMEOUT); - writel_relaxed(context_uart.lcrh_rx, membase + ST_UART011_LCRH_RX); - writel_relaxed(context_uart.ilpr, membase + UART01x_ILPR); - writel_relaxed(context_uart.ibrd, membase + UART011_IBRD); - writel_relaxed(context_uart.fbrd, membase + UART011_FBRD); - /* - * Wait 10 PCLKs before writing LCRH_TX register, - * to get this delay write read only register 10-3 - * times, as already there are 3 writes after - * ST_UART011_LCRH_RX - */ - for (cnt = 0; cnt < 7; cnt++) - dummy = readw(membase + ST_UART011_LCRH_RX); - - writel_relaxed(context_uart.lcrh_tx, membase + ST_UART011_LCRH_TX); - writel_relaxed(context_uart.ifls, membase + UART011_IFLS); - writel_relaxed(context_uart.dmacr, membase + UART011_DMACR); - writel_relaxed(context_uart.xfcr, membase + ST_UART011_XFCR); - writel_relaxed(context_uart.xon1, membase + ST_UART011_XON1); - writel_relaxed(context_uart.xon2, membase + ST_UART011_XON2); - writel_relaxed(context_uart.xoff1, membase + ST_UART011_XOFF1); - writel_relaxed(context_uart.xoff2, membase + ST_UART011_XOFF2); - writel_relaxed(context_uart.abcr, membase + ST_UART011_ABCR); - writel_relaxed(context_uart.abimsc, membase + ST_UART011_ABIMSC); - writel_relaxed(context_uart.cr, membase + UART011_CR); - writel(context_uart.imsc, membase + UART011_IMSC); - - clk_disable(context_uart.uart_clk); - - if (show_warn) - pr_warning("%s:uart tx busy\n", __func__); -} - -static int uart_context_notifier_call(struct notifier_block *this, - unsigned long event, void *data) -{ - switch (event) { - case CONTEXT_APE_SAVE: - save_uart(); - break; - - case CONTEXT_APE_RESTORE: - restore_uart(); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block uart_context_notifier = { - .notifier_call = uart_context_notifier_call, -}; - -#define __UART_BASE(soc, x) soc##_UART##x##_BASE -#define UART_BASE(soc, x) __UART_BASE(soc, x) - -static int __init uart_context_notifier_init(void) -{ - unsigned long base; - static const char clkname[] __initconst - = "uart" __stringify(CONFIG_UX500_DEBUG_UART); - - if (cpu_is_u8500()) - base = UART_BASE(U8500, CONFIG_UX500_DEBUG_UART); - else if (cpu_is_u5500()) - base = UART_BASE(U5500, CONFIG_UX500_DEBUG_UART); - else - ux500_unknown_soc(); - - context_uart.base = ioremap(base, SZ_4K); - context_uart.uart_clk = clk_get_sys(clkname, NULL); - - if (IS_ERR(context_uart.uart_clk)) { - pr_err("%s:unable to get clk-uart%d\n", __func__, - CONFIG_UX500_DEBUG_UART); - return -EINVAL; - } - - return WARN_ON(context_ape_notifier_register(&uart_context_notifier)); -} -arch_initcall(uart_context_notifier_init); -#endif diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b1bcd16d421..0a5bea9e358 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -368,27 +368,6 @@ show_one(scaling_cur_freq, cur); static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy); -int cpufreq_update_freq(int cpu, unsigned int min, unsigned int max) -{ - int ret; - struct cpufreq_policy new_policy; - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - - ret = cpufreq_get_policy(&new_policy, cpu); - if (ret) - return -EINVAL; - - new_policy.min = min; - new_policy.max = max; - - ret = __cpufreq_set_policy(policy, &new_policy); - policy->user_policy.min = policy->min; - policy->user_policy.max = policy->max; - - return ret; -} -EXPORT_SYMBOL(cpufreq_update_freq); - /** * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access */ diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index a5bbbf60ae8..891360edecd 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -30,7 +30,7 @@ #define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) #define DEF_FREQUENCY_UP_THRESHOLD (80) -#define DEF_SAMPLING_DOWN_FACTOR (10) +#define DEF_SAMPLING_DOWN_FACTOR (1) #define MAX_SAMPLING_DOWN_FACTOR (100000) #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) #define MICRO_FREQUENCY_UP_THRESHOLD (95) diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index ed28f774ca4..c47f3d09c1e 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -19,8 +19,6 @@ #include <linux/tick.h> #include <linux/sched.h> #include <linux/math64.h> -#include <linux/cpu.h> -#include <linux/sysfs.h> #define BUCKETS 12 #define INTERVALS 8 @@ -123,8 +121,6 @@ struct menu_device { int interval_ptr; }; -static int tune_multiplier = 1024; -static int forced_state; #define LOAD_INT(x) ((x) >> FSHIFT) #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100) @@ -174,9 +170,6 @@ static inline int performance_multiplier(void) { int mult = 1; - if (tune_multiplier <= 1) - return tune_multiplier; - /* for higher loadavg, we are more reluctant */ mult += 2 * get_loadavg(); @@ -184,9 +177,6 @@ static inline int performance_multiplier(void) /* for IO wait tasks (per cpu!) we add 5x each */ mult += 10 * nr_iowait_cpu(smp_processor_id()); - if (tune_multiplier != 1024) - mult = (tune_multiplier * mult) / 1024; - return mult; } @@ -291,34 +281,26 @@ static int menu_select(struct cpuidle_device *dev) if (data->expected_us > 5) data->last_state_idx = CPUIDLE_DRIVER_STATE_START; - WARN((forced_state >= dev->state_count), \ - "Forced state value out of range.\n"); - - if ((forced_state != 0) && (forced_state < dev->state_count)) { - data->exit_us = dev->states[forced_state].exit_latency; - data->last_state_idx = forced_state; - } else { - /* - * Find the idle state with the lowest power while satisfying - * our constraints. - */ - for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) { - struct cpuidle_state *s = &dev->states[i]; - - if (s->flags & CPUIDLE_FLAG_IGNORE) - continue; - if (s->target_residency > data->predicted_us) - continue; - if (s->exit_latency > latency_req) - continue; - if (s->exit_latency * multiplier > data->predicted_us) - continue; - - if (s->power_usage < power_usage) { - power_usage = s->power_usage; - data->last_state_idx = i; - data->exit_us = s->exit_latency; - } + /* + * Find the idle state with the lowest power while satisfying + * our constraints. + */ + for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++) { + struct cpuidle_state *s = &dev->states[i]; + + if (s->flags & CPUIDLE_FLAG_IGNORE) + continue; + if (s->target_residency > data->predicted_us) + continue; + if (s->exit_latency > latency_req) + continue; + if (s->exit_latency * multiplier > data->predicted_us) + continue; + + if (s->power_usage < power_usage) { + power_usage = s->power_usage; + data->last_state_idx = i; + data->exit_us = s->exit_latency; } } @@ -399,63 +381,6 @@ static void menu_update(struct cpuidle_device *dev) data->interval_ptr = 0; } -int cpuidle_set_multiplier(unsigned int value) -{ - - if (value > 1024) - tune_multiplier = 1024; - else - tune_multiplier = value; - - return 0; -} -EXPORT_SYMBOL(cpuidle_set_multiplier); - -/* Writing 0 will remove the forced state. */ -int cpuidle_force_state(unsigned int state) -{ - forced_state = state; - - return 0; -} -EXPORT_SYMBOL(cpuidle_force_state); - -static ssize_t show_multiplier(struct sysdev_class *class, - struct sysdev_class_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", tune_multiplier); -} - -static ssize_t store_multiplier(struct sysdev_class *class, - struct sysdev_class_attribute *attr, - const char *buf, size_t count) -{ - unsigned int input; - int ret; - ret = sscanf(buf, "%u", &input); - - if (ret != 1) - return -EINVAL; - - cpuidle_set_multiplier(input); - - return count; -} - - -static SYSDEV_CLASS_ATTR(multiplier, 0644, show_multiplier, store_multiplier); - -static struct attribute *dbs_attributes[] = { - &attr_multiplier.attr, - NULL -}; - -static struct attribute_group dbs_attr_group = { - .attrs = dbs_attributes, - .name = "cpuidle", -}; - /** * menu_enable_device - scans a CPU's states and does setup * @dev: the CPU @@ -483,15 +408,7 @@ static struct cpuidle_governor menu_governor = { */ static int __init init_menu(void) { - int ret; - - ret = cpuidle_register_governor(&menu_governor); - - sysfs_merge_group(&(cpu_sysdev_class.kset.kobj), - &dbs_attr_group); - - return ret; - + return cpuidle_register_governor(&menu_governor); } /** @@ -499,9 +416,6 @@ static int __init init_menu(void) */ static void __exit exit_menu(void) { - sysfs_unmerge_group(&(cpu_sysdev_class.kset.kobj), - &dbs_attr_group); - cpuidle_unregister_governor(&menu_governor); } diff --git a/drivers/modem/shrm/shrm_protocol.c b/drivers/modem/shrm/shrm_protocol.c index 883c46b4f8f..3b7abf7da61 100644 --- a/drivers/modem/shrm/shrm_protocol.c +++ b/drivers/modem/shrm/shrm_protocol.c @@ -18,7 +18,6 @@ #include <linux/modem/modem_client.h> #include <mach/prcmu.h> #include <mach/prcmu-regs.h> -#include <mach/suspend.h> #include <mach/reboot_reasons.h> #define L2_HEADER_ISI 0x0 @@ -449,9 +448,6 @@ void shm_ca_sleep_req_work(struct work_struct *work) hrtimer_start(&timer, ktime_set(0, 10*NSEC_PER_MSEC), HRTIMER_MODE_REL); -#ifdef CONFIG_UX500_SUSPEND - suspend_unblock_sleep(); -#endif atomic_dec(&ac_sleep_disable_count); } @@ -559,9 +555,6 @@ static irqreturn_t shrm_prcmu_irq_handler(int irq, void *data) switch (irq) { case IRQ_PRCMU_CA_WAKE: -#ifdef CONFIG_UX500_SUSPEND - suspend_block_sleep(); -#endif if (shrm->msr_flag) atomic_set(&ac_sleep_disable_count, 0); atomic_inc(&ac_sleep_disable_count); |