summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ux500')
-rw-r--r--arch/arm/mach-ux500/Kconfig269
-rw-r--r--arch/arm/mach-ux500/Kconfig-arch160
-rw-r--r--arch/arm/mach-ux500/Makefile90
-rw-r--r--arch/arm/mach-ux500/board-mop500-bm.c418
-rw-r--r--arch/arm/mach-ux500/board-mop500-bm.h24
-rw-r--r--arch/arm/mach-ux500/board-mop500-mcde.c790
-rw-r--r--arch/arm/mach-ux500/board-mop500-mcde.h24
-rw-r--r--arch/arm/mach-ux500/board-mop500-mmio.c505
-rw-r--r--arch/arm/mach-ux500/board-mop500-msp.c232
-rw-r--r--arch/arm/mach-ux500/board-mop500-nuib.c41
-rw-r--r--arch/arm/mach-ux500/board-mop500-pins.c731
-rw-r--r--arch/arm/mach-ux500/board-mop500-regulators.c1218
-rw-r--r--arch/arm/mach-ux500/board-mop500-regulators.h46
-rw-r--r--arch/arm/mach-ux500/board-mop500-sdi.c392
-rw-r--r--arch/arm/mach-ux500/board-mop500-stuib.c83
-rw-r--r--arch/arm/mach-ux500/board-mop500-u8500uib.c71
-rw-r--r--arch/arm/mach-ux500/board-mop500-uib.c140
-rw-r--r--arch/arm/mach-ux500/board-mop500.c1581
-rw-r--r--arch/arm/mach-ux500/board-mop500.h41
-rw-r--r--arch/arm/mach-ux500/board-pdp-mcde.c621
-rw-r--r--arch/arm/mach-ux500/board-snowball-digio.c118
-rw-r--r--arch/arm/mach-ux500/board-snowball-netdev.c74
-rw-r--r--arch/arm/mach-ux500/board-snowball-pins.c157
-rw-r--r--arch/arm/mach-ux500/board-snowball.c500
-rw-r--r--arch/arm/mach-ux500/board-snowball.h22
-rw-r--r--arch/arm/mach-ux500/board-svp5500.c45
-rw-r--r--arch/arm/mach-ux500/board-svp8500.c73
-rw-r--r--arch/arm/mach-ux500/board-u5500-cg2900.c144
-rw-r--r--arch/arm/mach-ux500/board-u5500-mcde.c493
-rw-r--r--arch/arm/mach-ux500/board-u5500-pins.c114
-rw-r--r--arch/arm/mach-ux500/board-u5500-regulators.c182
-rw-r--r--arch/arm/mach-ux500/board-u5500-sdi.c314
-rw-r--r--arch/arm/mach-ux500/board-u5500.c379
-rw-r--r--arch/arm/mach-ux500/board-u5500.h29
-rw-r--r--arch/arm/mach-ux500/clock-db5500.c793
-rw-r--r--arch/arm/mach-ux500/clock-db8500.c1289
-rw-r--r--arch/arm/mach-ux500/clock-debug.c228
-rw-r--r--arch/arm/mach-ux500/clock.c795
-rw-r--r--arch/arm/mach-ux500/clock.h230
-rw-r--r--arch/arm/mach-ux500/cpu-db5500.c126
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c271
-rw-r--r--arch/arm/mach-ux500/cpu.c169
-rw-r--r--arch/arm/mach-ux500/cw1200-wlan.c40
-rw-r--r--arch/arm/mach-ux500/dcache.c254
-rw-r--r--arch/arm/mach-ux500/devices-cg2900-u5500.c65
-rw-r--r--arch/arm/mach-ux500/devices-cg2900-u8500.c181
-rw-r--r--arch/arm/mach-ux500/devices-cg2900.c241
-rw-r--r--arch/arm/mach-ux500/devices-cg2900.h42
-rw-r--r--arch/arm/mach-ux500/devices-common.c114
-rw-r--r--arch/arm/mach-ux500/devices-common.h92
-rw-r--r--arch/arm/mach-ux500/devices-db5500.c282
-rw-r--r--arch/arm/mach-ux500/devices-db5500.h76
-rw-r--r--arch/arm/mach-ux500/devices-db8500.c617
-rw-r--r--arch/arm/mach-ux500/devices-db8500.h98
-rw-r--r--arch/arm/mach-ux500/devices.c277
-rw-r--r--arch/arm/mach-ux500/dma-db5500.c229
-rw-r--r--arch/arm/mach-ux500/dma-db8500.c304
-rw-r--r--arch/arm/mach-ux500/hotplug.c85
-rw-r--r--arch/arm/mach-ux500/hwmem-int.c165
-rw-r--r--arch/arm/mach-ux500/hwreg.c660
-rw-r--r--arch/arm/mach-ux500/include/mach/ab8500-accdet.h96
-rw-r--r--arch/arm/mach-ux500/include/mach/ab8500_codec.h327
-rw-r--r--arch/arm/mach-ux500/include/mach/ab8500_codec_p.h3082
-rw-r--r--arch/arm/mach-ux500/include/mach/ab8500_codec_p_v1_0.h3037
-rw-r--r--arch/arm/mach-ux500/include/mach/ab8500_codec_v1_0.h329
-rw-r--r--arch/arm/mach-ux500/include/mach/ab8500_gpadc.h36
-rw-r--r--arch/arm/mach-ux500/include/mach/crypto-ux500.h16
-rw-r--r--arch/arm/mach-ux500/include/mach/db5500-keypad.h25
-rw-r--r--arch/arm/mach-ux500/include/mach/db5500-regs.h36
-rw-r--r--arch/arm/mach-ux500/include/mach/db8500-regs.h42
-rw-r--r--arch/arm/mach-ux500/include/mach/dcache.h26
-rw-r--r--arch/arm/mach-ux500/include/mach/debug-macro.S14
-rw-r--r--arch/arm/mach-ux500/include/mach/devices.h46
-rw-r--r--arch/arm/mach-ux500/include/mach/entry-macro.S3
-rw-r--r--arch/arm/mach-ux500/include/mach/gpio.h203
-rw-r--r--arch/arm/mach-ux500/include/mach/hardware.h175
-rw-r--r--arch/arm/mach-ux500/include/mach/hcl_defs.h252
-rw-r--r--arch/arm/mach-ux500/include/mach/hsi.h122
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs-board-mop500.h58
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs-board-u5500.h21
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs-db5500.h108
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs-db8500.h145
-rw-r--r--arch/arm/mach-ux500/include/mach/irqs.h94
-rw-r--r--arch/arm/mach-ux500/include/mach/isa_ioctl.h51
-rw-r--r--arch/arm/mach-ux500/include/mach/kpd.h123
-rw-r--r--arch/arm/mach-ux500/include/mach/mbox.h88
-rw-r--r--arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h71
-rw-r--r--arch/arm/mach-ux500/include/mach/memory.h8
-rw-r--r--arch/arm/mach-ux500/include/mach/mloader-dbx500.h48
-rw-r--r--arch/arm/mach-ux500/include/mach/msp.h970
-rw-r--r--arch/arm/mach-ux500/include/mach/musb_db8500.h70
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu-db5500.h45
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu-fw-api.h532
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu-fw-defs_v1.h467
-rw-r--r--arch/arm/mach-ux500/include/mach/prcmu-regs.h110
-rw-r--r--arch/arm/mach-ux500/include/mach/reboot_reasons.h39
-rw-r--r--arch/arm/mach-ux500/include/mach/regulator.h88
-rw-r--r--arch/arm/mach-ux500/include/mach/scu.h25
-rw-r--r--arch/arm/mach-ux500/include/mach/sensors1p.h24
-rw-r--r--arch/arm/mach-ux500/include/mach/setup.h21
-rw-r--r--arch/arm/mach-ux500/include/mach/shrm.h23
-rw-r--r--arch/arm/mach-ux500/include/mach/shrm_config.h111
-rw-r--r--arch/arm/mach-ux500/include/mach/shrm_driver.h201
-rw-r--r--arch/arm/mach-ux500/include/mach/shrm_net.h44
-rw-r--r--arch/arm/mach-ux500/include/mach/shrm_private.h180
-rw-r--r--arch/arm/mach-ux500/include/mach/ste-dma40-db5500.h135
-rw-r--r--arch/arm/mach-ux500/include/mach/ste-dma40-db8500.h147
-rw-r--r--arch/arm/mach-ux500/include/mach/ste_audio_io.h18
-rw-r--r--arch/arm/mach-ux500/include/mach/ste_audio_io_ioctl.h234
-rw-r--r--arch/arm/mach-ux500/include/mach/ste_audio_io_vibrator.h37
-rw-r--r--arch/arm/mach-ux500/include/mach/stm_musb.h160
-rw-r--r--arch/arm/mach-ux500/include/mach/suspend.h13
-rw-r--r--arch/arm/mach-ux500/include/mach/system.h8
-rw-r--r--arch/arm/mach-ux500/include/mach/tc35893-keypad.h44
-rw-r--r--arch/arm/mach-ux500/include/mach/tee_ta_start_modem.h48
-rw-r--r--arch/arm/mach-ux500/include/mach/timex.h3
-rw-r--r--arch/arm/mach-ux500/include/mach/u8500_acodec_ab8500.h284
-rw-r--r--arch/arm/mach-ux500/include/mach/uart.h18
-rw-r--r--arch/arm/mach-ux500/include/mach/uncompress.h26
-rw-r--r--arch/arm/mach-ux500/localtimer.c11
-rw-r--r--arch/arm/mach-ux500/mloader-db8500.c82
-rw-r--r--arch/arm/mach-ux500/modem_irq.c139
-rw-r--r--arch/arm/mach-ux500/musb_db8500.c955
-rw-r--r--arch/arm/mach-ux500/pins-db5500.h620
-rw-r--r--arch/arm/mach-ux500/pins-db8500.h746
-rw-r--r--arch/arm/mach-ux500/pins.c88
-rw-r--r--arch/arm/mach-ux500/pins.h43
-rw-r--r--arch/arm/mach-ux500/platsmp.c54
-rw-r--r--arch/arm/mach-ux500/pm/Kconfig82
-rw-r--r--arch/arm/mach-ux500/pm/Makefile16
-rw-r--r--arch/arm/mach-ux500/pm/context-db5500.c395
-rw-r--r--arch/arm/mach-ux500/pm/context-db8500.c467
-rw-r--r--arch/arm/mach-ux500/pm/context.c911
-rw-r--r--arch/arm/mach-ux500/pm/context.h88
-rw-r--r--arch/arm/mach-ux500/pm/context_arm.S427
-rw-r--r--arch/arm/mach-ux500/pm/cpufreq-db8500.c53
-rw-r--r--arch/arm/mach-ux500/pm/cpufreq.c141
-rw-r--r--arch/arm/mach-ux500/pm/cpufreq.h12
-rw-r--r--arch/arm/mach-ux500/pm/cpuidle.c732
-rw-r--r--arch/arm/mach-ux500/pm/cpuidle.h87
-rw-r--r--arch/arm/mach-ux500/pm/cpuidle_dbg.c699
-rw-r--r--arch/arm/mach-ux500/pm/cpuidle_dbg.h60
-rw-r--r--arch/arm/mach-ux500/pm/pm.c349
-rw-r--r--arch/arm/mach-ux500/pm/pm.h110
-rw-r--r--arch/arm/mach-ux500/pm/runtime.c297
-rw-r--r--arch/arm/mach-ux500/pm/suspend.c225
-rw-r--r--arch/arm/mach-ux500/pm/suspend_dbg.c199
-rw-r--r--arch/arm/mach-ux500/pm/suspend_dbg.h60
-rw-r--r--arch/arm/mach-ux500/pm/usecase_gov.c590
-rw-r--r--arch/arm/mach-ux500/prcmu-db5500.c546
-rw-r--r--arch/arm/mach-ux500/prcmu-db5500.h43
-rw-r--r--arch/arm/mach-ux500/prcmu-db8500.c2058
-rw-r--r--arch/arm/mach-ux500/prcmu-debug.c503
-rw-r--r--arch/arm/mach-ux500/prcmu-debug.h23
-rw-r--r--arch/arm/mach-ux500/prcmu-qos-power.c568
-rw-r--r--arch/arm/mach-ux500/prcmu-regs-db5500.h48
-rw-r--r--arch/arm/mach-ux500/prcmu-regs-db8500.h162
-rw-r--r--arch/arm/mach-ux500/pwm.c461
-rw-r--r--arch/arm/mach-ux500/reboot_reasons.c20
-rw-r--r--arch/arm/mach-ux500/regulator-u5500.c67
-rw-r--r--arch/arm/mach-ux500/regulator-u5500.h15
-rw-r--r--arch/arm/mach-ux500/regulator-u8500.c266
-rw-r--r--arch/arm/mach-ux500/regulator-u8500.h46
-rw-r--r--arch/arm/mach-ux500/regulator-ux500.c392
-rw-r--r--arch/arm/mach-ux500/regulator-ux500.h39
-rw-r--r--arch/arm/mach-ux500/sensors1p.c298
-rw-r--r--arch/arm/mach-ux500/ste-dma40-db8500.h154
-rw-r--r--arch/arm/mach-ux500/tee_service_svp.c66
-rw-r--r--arch/arm/mach-ux500/tee_ta_start_modem_svp.c56
-rw-r--r--arch/arm/mach-ux500/tee_ux500.c112
-rw-r--r--arch/arm/mach-ux500/timer-db8500-prcmu.c122
-rw-r--r--arch/arm/mach-ux500/timer-db8500.c82
-rw-r--r--arch/arm/mach-ux500/timer-mtu.c343
-rw-r--r--arch/arm/mach-ux500/timer-rtt.c145
-rw-r--r--arch/arm/mach-ux500/uart-db8500.c236
-rw-r--r--arch/arm/mach-ux500/virt-regulator-u8500.c333
176 files changed, 45255 insertions, 1338 deletions
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 6625e5bbf4d..d753fff92b1 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -1,42 +1,277 @@
if ARCH_U8500
-config UX500_SOC_COMMON
+# Old bootloaders pass the Nomadik machine type, and the MACH_ option named
+# after the machine type must be present and selected for machine_is_*() to
+# work
+config MACH_NOMADIK
bool
- default y
- select ARM_GIC
- select HAS_MTU
- select NOMADIK_GPIO
-config UX500_SOC_DB8500
+config MACH_HREFV60
bool
+config MACH_SNOWBALL
+ bool
+
+choice
+ prompt "Ux500 platform"
+ default UX500_SOC_DB8500
+
+config UX500_SOC_DB8500
+ select CPU_V7
+ select ARM_GIC
+ select SMP
+ select ARM_ERRATA_753970
+ select SYS_SOC
+ bool "U8500"
+
config UX500_SOC_DB5500
+ select CPU_V7
+ select ARM_GIC
+ bool "U5500"
+
+endchoice
+
+config UX500_SVP
bool
+if UX500_SOC_DB8500
+
+menu "U8500 Machines"
+
+config MACH_SVP8500V1
+ bool "U8500 Simulator v1 (SVP8500v1)"
+ select UX500_SVP
+ help
+ Support Simulation for u8500 platform (v1)
+
+config MACH_SVP8500V2
+ bool "U8500 Simulator v2 (SVP8500v2)"
+ select UX500_SVP
+ help
+ Supports Simulation for u8500 platform (v2)
+
+config MACH_U8500
+ bool "U8500 MOP500/HREF/custom HW"
+ select MACH_NOMADIK
+ select MACH_HREFV60
+ help
+ Supports the generic U8500 board type used for MOP500/HREF and some
+ custom boards. Boards using the generic type cannot be built
+ together; select the specific board in the "U8500 HW" option.
+
+config MACH_SNOWBALL
+ bool "U8500 Snowball"
+ select MACH_U8500
+ select MACH_NOMADIK
+ help
+ Supports the Snowball board
+
+# If you are porting onto a new board, you really should be using a new machine
+# type and adding an entry into this list, not the "U8500 HW" list below.
+
+endmenu
+
+if MACH_U8500
+
choice
- prompt "Ux500 target platform"
+ prompt "U8500 HW"
default MACH_U8500_MOP
config MACH_U8500_MOP
- bool "U8500 Development platform"
- select UX500_SOC_DB8500
+ bool "MOP500/HREF"
+ help
+ Supports MOP500/HREF development boards.
+
+config MACH_U8500_SNOWBALL
+ bool "u8500 snowball"
+ help
+ Support for the u8500 snowball board.
+
+config MACH_U8500_PDP
+ bool "PDP"
+ help
+ Supports PDP target board
+
+endchoice
+
+endif
+
+endif
+
+if UX500_SOC_DB5500
+
+menu "U5500 Machines"
+
+config MACH_SVP5500
+ bool "U5500 Simulator (SVP5500)"
+ select UX500_SVP
+ help
+ Support for the U5500 Simulator
+
+config MACH_B5500
+ bool "U5500 Big Board (B5500)"
+ help
+ Support for the U5500 Big Board
+endmenu
+
+endif
+
+choice
+ prompt "Ux500 UIB Keylayout"
+ default KEYLAYOUT_LAYOUT1
+
+config KEYLAYOUT_LAYOUT1
+ bool "UIB Keylayout 1; for generic users"
help
- Include support for mop500 development platform
- based on U8500 architecture. The platform is based
- on early drop silicon version of 8500.
+ Supported keylayout for some numerics, power/call buttons,
+ volume control etc
-config MACH_U5500
- bool "U5500 Development platform"
- select UX500_SOC_DB5500
+config KEYLAYOUT_LAYOUT2
+ bool "UIB Keylayout 2; for connectivity users"
help
- Include support for the U5500 development platform.
+ Supports keylayout numerics 0-9, left/right/up/down/back/
+ enter keys and special character "."(dot)
+
endchoice
+choice
+ prompt "Ux500 sched_clock timer"
+ default UX500_MTU_TIMER
+
+config U8500_PRCMU_TIMER
+ bool "PRCMU Timer sched_clock"
+ depends on (UX500_SOC_DB8500 && !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
+ default n
+ help
+ Add support for PRCMU for U8500
+
+config U5500_PRCMU
+ bool "U5500 PRCMU support"
+ depends on UX500_SOC_DB5500
+ default y
+ help
+ Add support for PRCMU for U5500
+
+config UX500_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 U8500_REGULATOR_DEBUG
+ bool "Regulator debug support"
+ depends on REGULATOR_VIRTUAL_CONSUMER
+ default n
+ help
+ Add support for U8500 regulator debug
+
+config U5500_PWM
+ bool "PWM support"
+ default y
+ depends on UX500_SOC_DB5500
+ help
+ Add support for PWM for U5500
+
+config MOP500_SDI
+ bool
+ default y
+ depends on ((MACH_U8500_MOP || \
+ MACH_U8500_PDP || \
+ MACH_U8500_SNOWBALL) && MMC_ARMMMCI)
+
+config ARCH_HAS_CPU_IDLE_WAIT
+ def_bool y
+
config UX500_DEBUG_UART
int "Ux500 UART to use for low-level debug"
- default 2
+ default 2 if UX500_SOC_DB8500
+ default 0 if UX500_SOC_DB5500
help
Choose the UART on which kernel low-level debug messages should be
output.
+
+config SENSORS1P_MOP
+ tristate "HAL and Proximity sensors support"
+ depends on REGULATOR && (GPIO_STMPE2401 || GPIO_TC35892)
+ default y
+ help
+ Add support for Osram's SFH7741 Proximity Sensor and Samsumg
+ HED54XXU11 HAL Switch
+
+config U5500_MODEM_IRQ
+ bool "Modem IRQ support"
+ depends on UX500_SOC_DB5500
+ default y
+ help
+ Add support for handling IRQ:s from modem side
+
+config MOP500_NUIB
+ bool "MOP500 NUIB"
+ depends on MACH_U8500_MOP
+ default y
+ help
+ Add support for the platform data of synaptics rmi4 driver
+
+config TEE_UX500
+ bool "Trusted Execution Environment (TEE) ux500 hardware support"
+ depends on TEE_SUPPORT
+ default y
+ help
+ Adds TEE hardware support for ux500 platforms.
+
+config TEE_SVP
+ bool "Trusted Execution Environment (TEE) ux500 SVP support"
+ depends on TEE_SUPPORT && UX500_SVP
+ default y
+ help
+ Adds TEE support for SVP in ux500 platforms.
+
+config DB8500_MLOADER
+ bool "Modem firmware upload/download support"
+ depends on UX500_SOC_DB8500
+ select DBX500_MLOADER
+ default n
+ help
+ Adds Modem firmware upload/download support to DB8500.
+
+config UX500_DEBUG_HWREG
+ bool "Debug hardware registers from userspace"
+ depends on (DEBUG_FS && UX500_SOC_DB8500)
+ help
+ Adds various debug files to access registers.
+ This should never ever be used for anything else than debugging.
+
+config UX500_DEBUG_NO_LAUTERBACH
+ bool "Disable clocks needed for Lauterbach debugging"
+ help
+ Disable clocks needed for Lauterbach debugging at boot.
+ If yes, you will reduce the power consumption.
+
+source "arch/arm/mach-ux500/Kconfig-arch"
+source "arch/arm/mach-ux500/pm/Kconfig"
endif
diff --git a/arch/arm/mach-ux500/Kconfig-arch b/arch/arm/mach-ux500/Kconfig-arch
new file mode 100644
index 00000000000..3f590aaadc5
--- /dev/null
+++ b/arch/arm/mach-ux500/Kconfig-arch
@@ -0,0 +1,160 @@
+config GPIO_STM
+ bool "STM GPIO driver support"
+ default y
+ help
+ Say yes here to support the STM GPIO device
+
+config U8500_SECURE
+ bool "Support for running in Secure mode"
+ default n
+ help
+ Build the kernel to run in Secure mode.
+
+#Configuration for MCDE setup
+
+if FB_MCDE
+
+menu "Display selection"
+
+config DISPLAY_GENERIC_PRIMARY
+ bool "Generic primary display support"
+ depends on (MACH_U8500_MOP || MACH_B5500)
+ default y
+
+choice
+ prompt "Display port type"
+ depends on DISPLAY_GENERIC_PRIMARY
+ default DISPLAY_GENERIC_DSI_PRIMARY
+ help
+ Select the kind of display port used for the primary display
+
+config DISPLAY_GENERIC_DSI_PRIMARY
+ bool "DSI display"
+ select MCDE_DISPLAY_GENERIC_DSI
+ help
+ Say yes here when using a DSI display
+
+config MCDE_DISPLAY_DPI_PRIMARY
+ bool "DPI display"
+ select MCDE_DISPLAY_DPI
+ depends on MACH_8500_MOP
+ help
+ Say yes here when using a DPI display
+
+endchoice
+
+choice
+ prompt "Color depth"
+ depends on DISPLAY_GENERIC_PRIMARY
+ default MCDE_DISPLAY_PRIMARY_16BPP
+ help
+ Select color depth for primary display
+
+config MCDE_DISPLAY_PRIMARY_16BPP
+ bool "16 bpp"
+ help
+ 16 bpp color depth
+
+config MCDE_DISPLAY_PRIMARY_32BPP
+ bool "32 bpp"
+ help
+ 32 bpp color depth
+
+endchoice
+
+choice DISPLAY_GENERIC_DSI_PRIMARY_ROTATION
+ prompt "Enable main display rotation"
+ depends on DISPLAY_GENERIC_DSI_PRIMARY
+ default DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_90
+ help
+ Set rotation of main display
+
+config DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_0
+ bool "0 degrees"
+config DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_90
+ bool "90 degrees"
+config DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_180
+ bool "180 degrees"
+config DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_270
+ bool "270 degrees"
+endchoice
+
+config DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE
+ int
+ depends on DISPLAY_GENERIC_DSI_PRIMARY
+ default "0" if DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_0
+ default "90" if DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_90
+ default "180" if DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_180
+ default "270" if DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_270
+
+config DISPLAY_SONY_SY35560_DSI_PRIMARY
+ bool "Sony SY35560 primary display support"
+ depends on MACH_U8500_PDP
+ select MCDE_DISPLAY_SONY_SY35560_DSI
+ default y
+ help
+ Say yes here if main display exists
+
+config DISPLAY_GENERIC_DSI_PRIMARY_VSYNC
+ bool "Enable v-sync for primary display"
+ depends on DISPLAY_GENERIC_DSI_PRIMARY || DISPLAY_SONY_SY35560_DSI_PRIMARY
+ default n
+ help
+ Say yes to enable v-sync for primary display
+
+config DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+ bool "Enable auto sync for primary display"
+ depends on DISPLAY_GENERIC_DSI_PRIMARY
+ default n
+ help
+ Say yes to enable auto sync for primary display
+
+config SONY_SY35560_ENABLE_ESD_CHECK
+ bool "Enable esd status check for primary display"
+ depends on DISPLAY_SONY_SY35560_DSI_PRIMARY
+ default n
+ help
+ Say yes to enable esd status check for primary display
+
+config DISPLAY_GENERIC_DSI_SECONDARY
+ bool "Sub display support"
+ depends on MACH_U8500
+ select MCDE_DISPLAY_GENERIC_DSI
+ help
+ Say yes here if sub display exists
+
+config DISPLAY_GENERIC_DSI_SECONDARY_VSYNC
+ bool "Enable v-sync for secondary display"
+ depends on DISPLAY_GENERIC_DSI_SECONDARY
+ help
+ Say yes to enable v-sync for secondary display
+
+config DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC
+ bool "Enable auto sync for secondary display"
+ depends on DISPLAY_GENERIC_DSI_SECONDARY
+ help
+ Say yes to enable auto sync for secondary display
+
+config DISPLAY_AB8500_TERTIARY
+ bool "AB8500 TVout display support"
+ depends on MACH_U8500 && !AV8100_SDTV
+ select MCDE_DISPLAY_AB8500_DENC
+ help
+ Say yes here if tv out support
+
+config DISPLAY_AV8100_TERTIARY
+ bool "AV8100 HDMI/CVBS display support"
+ depends on (MACH_U8500_MOP || MACH_B5500 || MACH_U8500_SNOWBALL)
+ select MCDE_DISPLAY_AV8100
+ help
+ Say yes here if HDMI output support
+
+config DISPLAY_AV8100_TRIPPLE_BUFFER
+ bool "Enable tripple buffer for HDMI display"
+ depends on DISPLAY_AV8100_TERTIARY
+ help
+ Say yes to enable tripple buffer. You'll get double buffer otherwise
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 4556aea9c3c..91bc0036594 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -2,10 +2,86 @@
# Makefile for the linux kernel, U8500 machine.
#
-obj-y := clock.o cpu.o devices.o
-obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o
-obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o
-obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o
-obj-$(CONFIG_MACH_U5500) += board-u5500.o
-obj-$(CONFIG_SMP) += platsmp.o headsmp.o
-obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+ifeq ($(CONFIG_CRYPTO_DEV_UX500_HASH), m)
+ CFLAGS_devices.o += -DCONFIG_CRYPTO_DEV_UX500_HASH
+ CFLAGS_board-mop500.o += -DCONFIG_CRYPTO_DEV_UX500_HASH
+endif
+
+obj-y := clock.o timer-mtu.o \
+ devices-common.o pins.o dcache.o reboot_reasons.o
+obj-$(CONFIG_PM) += pm/
+obj-$(CONFIG_REGULATOR) += regulator-ux500.o
+
+ifeq ($(CONFIG_UX500_SOC_DB8500), y)
+obj-$(CONFIG_REGULATOR) += regulator-u8500.o
+obj-$(CONFIG_MFD_CG2900) += devices-cg2900-u8500.o
+endif
+
+ifeq ($(CONFIG_UX500_SOC_DB5500), y)
+obj-$(CONFIG_REGULATOR) += regulator-u5500.o
+obj-$(CONFIG_MFD_CG2900) += devices-cg2900-u5500.o
+endif
+
+obj-$(CONFIG_U8500_REGULATOR_DEBUG) += virt-regulator-u8500.o
+obj-$(CONFIG_ARCH_U8500) += devices.o cpu.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_MACH_B5500) += board-u5500.o board-u5500-mcde.o \
+ board-u5500-sdi.o \
+ board-u5500-regulators.o \
+ board-u5500-pins.o \
+ board-u5500-cg2900.o
+obj-$(CONFIG_MACH_SVP5500) += board-svp5500.o
+obj-$(CONFIG_U8500_MMIO) += board-mop500-mmio.o
+obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-msp.o board-mop500-uib.o \
+ board-mop500-stuib.o board-mop500-u8500uib.o \
+ board-mop500-pins.o board-mop500-bm.o \
+ board-mop500-regulators.o \
+ cw1200-wlan.o
+obj-$(CONFIG_MACH_U8500_PDP) += board-mop500.o board-mop500-msp.o board-mop500-bm.o \
+ board-mop500-pins.o board-mop500-regulators.o
+ # until pdp-specific files are there
+obj-$(CONFIG_MACH_U8500_SNOWBALL) += board-mop500.o board-mop500-msp.o \
+ board-mop500-pins.o board-mop500-bm.o \
+ board-snowball-netdev.o board-snowball-digio.o \
+ board-mop500-uib.o board-mop500-stuib.o board-mop500-u8500uib.o \
+ board-mop500-regulators.o cw1200-wlan.o
+#obj-$(CONFIG_MACH_U8500_SNOWBALL) += board-snowball.o board-mop500-msp.o \
+# board-snowball-pins.o \
+# board-snowball-netdev.o board-snowball-digio.o # add board-mop500-bm.o ???
+obj-$(CONFIG_MOP500_SDI) += board-mop500-sdi.o
+obj-$(CONFIG_UX500_SOC_DB5500) += devices-db5500.o cpu-db5500.o \
+ dma-db5500.o timer-db8500.o \
+ clock-db5500.o clock-debug.o
+obj-$(CONFIG_UX500_SOC_DB8500) += devices-db8500.o \
+ cpu-db8500.o dma-db8500.o\
+ uart-db8500.o clock-db8500.o
+obj-$(CONFIG_UX500_SOC_DB8500) += timer-rtt.o timer-db8500.o timer-db8500-prcmu.o
+obj-$(CONFIG_MACH_U8500_PDP) += board-pdp-mcde.o
+obj-$(CONFIG_MACH_U8500_MOP) += board-mop500-mcde.o
+obj-$(CONFIG_MACH_U8500_SNOWBALL) += board-mop500-mcde.o
+obj-$(CONFIG_MACH_SVP8500V1) += board-svp8500.o
+obj-$(CONFIG_MACH_SVP8500V2) += board-svp8500.o
+obj-$(CONFIG_MACH_U5500_SIMULATOR) += board-u5500.o
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+obj-$(CONFIG_U8500_PRCMU) += prcmu-db8500.o
+obj-$(CONFIG_U5500_PRCMU) += prcmu-db5500.o
+obj-$(CONFIG_UX500_PRCMU_QOS_POWER) += prcmu-qos-power.o
+obj-$(CONFIG_UX500_PRCMU_DEBUG) += prcmu-debug.o
+obj-$(CONFIG_SENSORS1P_MOP) += sensors1p.o
+obj-$(CONFIG_MACH_U5500_BB) += board-u5500.o
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
+obj-$(CONFIG_USB) += musb_db8500.o
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_U5500_MODEM_IRQ) += modem_irq.o
+obj-$(CONFIG_U5500_PWM) += pwm.o
+obj-$(CONFIG_MOP500_NUIB) += board-mop500-nuib.o
+obj-$(CONFIG_DB8500_MLOADER) += mloader-db8500.o
+
+obj-$(CONFIG_TEE_UX500) += tee_ux500.o
+obj-$(CONFIG_TEE_SVP) += tee_service_svp.o
+obj-$(CONFIG_TEE_SVP) += tee_ta_start_modem_svp.o
+obj-$(CONFIG_MFD_CG2900) += devices-cg2900.o
+obj-$(CONFIG_UX500_DEBUG_HWREG) += hwreg.o
+obj-$(CONFIG_HWMEM) += hwmem-int.o
+
diff --git a/arch/arm/mach-ux500/board-mop500-bm.c b/arch/arm/mach-ux500/board-mop500-bm.c
new file mode 100644
index 00000000000..923392cf1be
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-bm.c
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * U8500 board specific charger and battery initialization parameters.
+ *
+ * Author: Johan Palsson <johan.palsson@stericsson.com> for ST-Ericsson.
+ * Author: Johan Gardsmark <johan.gardsmark@stericsson.com> for ST-Ericsson.
+ *
+ */
+
+#include <linux/power_supply.h>
+#include <linux/mfd/ab8500/ab8500-bm.h>
+#include "board-mop500-bm.h"
+
+#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL
+/*
+ * These are the defined batteries that uses a NTC and ID resistor placed
+ * inside of the battery pack.
+ * Note that the res_to_temp table must be strictly sorted by falling resistance
+ * values to work.
+ */
+static struct res_to_temp temp_tbl_A[] = {
+ {-5, 53407},
+ { 0, 48594},
+ { 5, 43804},
+ {10, 39188},
+ {15, 34870},
+ {20, 30933},
+ {25, 27422},
+ {30, 24347},
+ {35, 21694},
+ {40, 19431},
+ {45, 17517},
+ {50, 15908},
+ {55, 14561},
+ {60, 13437},
+ {65, 12500},
+};
+static struct res_to_temp temp_tbl_B[] = {
+ {-5, 165418},
+ { 0, 159024},
+ { 5, 151921},
+ {10, 144300},
+ {15, 136424},
+ {20, 128565},
+ {25, 120978},
+ {30, 113875},
+ {35, 107397},
+ {40, 101629},
+ {45, 96592},
+ {50, 92253},
+ {55, 88569},
+ {60, 85461},
+ {65, 82869},
+};
+static struct v_to_cap cap_tbl_A[] = {
+ {4171, 100},
+ {4114, 95},
+ {4009, 83},
+ {3947, 74},
+ {3907, 67},
+ {3863, 59},
+ {3830, 56},
+ {3813, 53},
+ {3791, 46},
+ {3771, 33},
+ {3754, 25},
+ {3735, 20},
+ {3717, 17},
+ {3681, 13},
+ {3664, 8},
+ {3651, 6},
+ {3635, 5},
+ {3560, 3},
+ {3408, 1},
+ {3247, 0},
+};
+static struct v_to_cap cap_tbl_B[] = {
+ {4161, 100},
+ {4124, 98},
+ {4044, 90},
+ {4003, 85},
+ {3966, 80},
+ {3933, 75},
+ {3888, 67},
+ {3849, 60},
+ {3813, 55},
+ {3787, 47},
+ {3772, 30},
+ {3751, 25},
+ {3718, 20},
+ {3681, 16},
+ {3660, 14},
+ {3589, 10},
+ {3546, 7},
+ {3495, 4},
+ {3404, 2},
+ {3250, 0},
+};
+#endif
+static struct v_to_cap cap_tbl[] = {
+ {4186, 100},
+ {4163, 99},
+ {4114, 95},
+ {4068, 90},
+ {3990, 80},
+ {3926, 70},
+ {3898, 65},
+ {3866, 60},
+ {3833, 55},
+ {3812, 50},
+ {3787, 40},
+ {3768, 30},
+ {3747, 25},
+ {3730, 20},
+ {3705, 15},
+ {3699, 14},
+ {3684, 12},
+ {3672, 9},
+ {3657, 7},
+ {3638, 6},
+ {3556, 4},
+ {3424, 2},
+ {3317, 1},
+ {3094, 0},
+};
+
+/*
+ * Note that the res_to_temp table must be strictly sorted by falling
+ * resistance values to work.
+ */
+static struct res_to_temp temp_tbl[] = {
+ {-5, 214834},
+ { 0, 162943},
+ { 5, 124820},
+ {10, 96520},
+ {15, 75306},
+ {20, 59254},
+ {25, 47000},
+ {30, 37566},
+ {35, 30245},
+ {40, 24520},
+ {45, 20010},
+ {50, 16432},
+ {55, 13576},
+ {60, 11280},
+ {65, 9425},
+};
+
+static const struct battery_type bat_type[] = {
+ [BATTERY_UNKNOWN] = {
+ /* First element always represent the UNKNOWN battery */
+ .name = POWER_SUPPLY_TECHNOLOGY_UNKNOWN,
+ .resis_high = 0,
+ .resis_low = 0,
+ .battery_resistance = 300,
+ .charge_full_design = 612,
+ .nominal_voltage = 3700,
+ .termination_vol = 4050,
+ .termination_curr = 200,
+ .recharge_vol = 3990,
+ .normal_cur_lvl = 400,
+ .normal_vol_lvl = 4100,
+ .maint_a_cur_lvl = 400,
+ .maint_a_vol_lvl = 4050,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 400,
+ .maint_b_vol_lvl = 4000,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ },
+
+#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL
+ {
+ .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+ .resis_high = 53407,
+ .resis_low = 12500,
+ .battery_resistance = 300,
+ .charge_full_design = 900,
+ .nominal_voltage = 3600,
+ .termination_vol = 4150,
+ .termination_curr = 80,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_A),
+ .r_to_t_tbl = temp_tbl_A,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_A),
+ .v_to_cap_tbl = cap_tbl_A,
+
+ },
+ {
+ .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+ .resis_high = 165418,
+ .resis_low = 82869,
+ .battery_resistance = 300,
+ .charge_full_design = 900,
+ .nominal_voltage = 3600,
+ .termination_vol = 4150,
+ .termination_curr = 80,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl_B),
+ .r_to_t_tbl = temp_tbl_B,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl_B),
+ .v_to_cap_tbl = cap_tbl_B,
+ },
+#else
+/*
+ * These are the batteries that doesn't have an internal NTC resistor to measure
+ * its temperature. The temperature in this case is measure with a NTC placed
+ * near the battery but on the PCB.
+ */
+ {
+ .name = POWER_SUPPLY_TECHNOLOGY_LIPO,
+ .resis_high = 76000,
+ .resis_low = 53000,
+ .battery_resistance = 300,
+ .charge_full_design = 900,
+ .nominal_voltage = 3700,
+ .termination_vol = 4150,
+ .termination_curr = 100,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ },
+ {
+ .name = POWER_SUPPLY_TECHNOLOGY_LION,
+ .resis_high = 30000,
+ .resis_low = 10000,
+ .battery_resistance = 300,
+ .charge_full_design = 950,
+ .nominal_voltage = 3700,
+ .termination_vol = 4150,
+ .termination_curr = 100,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ },
+ {
+ .name = POWER_SUPPLY_TECHNOLOGY_LION,
+ .resis_high = 95000,
+ .resis_low = 76001,
+ .battery_resistance = 300,
+ .charge_full_design = 950,
+ .nominal_voltage = 3700,
+ .termination_vol = 4150,
+ .termination_curr = 100,
+ .recharge_vol = 4130,
+ .normal_cur_lvl = 700,
+ .normal_vol_lvl = 4200,
+ .maint_a_cur_lvl = 600,
+ .maint_a_vol_lvl = 4150,
+ .maint_a_chg_timer_h = 60,
+ .maint_b_cur_lvl = 600,
+ .maint_b_vol_lvl = 4100,
+ .maint_b_chg_timer_h = 200,
+ .low_high_cur_lvl = 300,
+ .low_high_vol_lvl = 4000,
+ .n_temp_tbl_elements = ARRAY_SIZE(temp_tbl),
+ .r_to_t_tbl = temp_tbl,
+ .n_v_cap_tbl_elements = ARRAY_SIZE(cap_tbl),
+ .v_to_cap_tbl = cap_tbl,
+ },
+#endif
+};
+
+static char *ab8500_charger_supplied_to[] = {
+ "ab8500_chargalg",
+ "ab8500_fg",
+ "ab8500_btemp",
+};
+
+static char *ab8500_btemp_supplied_to[] = {
+ "ab8500_chargalg",
+ "ab8500_fg",
+};
+
+static char *ab8500_fg_supplied_to[] = {
+ "ab8500_chargalg",
+};
+
+static char *ab8500_chargalg_supplied_to[] = {
+ "ab8500_fg",
+};
+
+struct ab8500_charger_platform_data ab8500_charger_plat_data = {
+ .supplied_to = ab8500_charger_supplied_to,
+ .num_supplicants = ARRAY_SIZE(ab8500_charger_supplied_to),
+};
+
+struct ab8500_btemp_platform_data ab8500_btemp_plat_data = {
+ .supplied_to = ab8500_btemp_supplied_to,
+ .num_supplicants = ARRAY_SIZE(ab8500_btemp_supplied_to),
+};
+
+struct ab8500_fg_platform_data ab8500_fg_plat_data = {
+ .supplied_to = ab8500_fg_supplied_to,
+ .num_supplicants = ARRAY_SIZE(ab8500_fg_supplied_to),
+};
+
+struct ab8500_chargalg_platform_data ab8500_chargalg_plat_data = {
+ .supplied_to = ab8500_chargalg_supplied_to,
+ .num_supplicants = ARRAY_SIZE(ab8500_chargalg_supplied_to),
+};
+
+static const struct ab8500_bm_capacity_levels cap_levels = {
+ .critical = 2,
+ .low = 10,
+ .normal = 70,
+ .high = 95,
+ .full = 100,
+};
+
+static const struct ab8500_fg_parameters fg = {
+ .recovery_sleep_timer = 10,
+ .recovery_total_time = 100,
+ .init_timer = 1,
+ .init_discard_time = 5,
+ .init_total_time = 40,
+ .high_curr_time = 60,
+ .accu_charging = 30,
+ .accu_high_curr = 30,
+ .high_curr_threshold = 50,
+ .lowbat_threshold = 3100,
+};
+
+static const struct ab8500_maxim_parameters maxi_params = {
+ .ena_maxi = true,
+ .chg_curr = 910,
+ .wait_cycles = 10,
+ .charger_curr_step = 100,
+};
+
+static const struct ab8500_bm_charger_parameters chg = {
+ .usb_volt_max = 5500,
+ .usb_curr_max = 1500,
+ .ac_volt_max = 7500,
+ .ac_curr_max = 1500,
+};
+
+struct ab8500_bm_data ab8500_bm_data = {
+ .temp_under = 3,
+ .temp_low = 8,
+ .temp_high = 55,
+ .temp_over = 60,
+ .main_safety_tmr_h = 4,
+ .usb_safety_tmr_h = 4,
+ .bkup_bat_v = BUP_VCH_SEL_2P6V,
+ .bkup_bat_i = BUP_ICH_SEL_150UA,
+ .no_maintenance = false,
+#ifdef CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL
+ .adc_therm = ADC_THERM_BATCTRL,
+#else
+ .adc_therm = ADC_THERM_BATTEMP,
+#endif
+ .chg_unknown_bat = false,
+ .enable_overshoot = false,
+ .fg_res = 10,
+ .cap_levels = &cap_levels,
+ .bat_type = bat_type,
+ .n_btypes = ARRAY_SIZE(bat_type),
+ .batt_id = 0,
+ .interval_charging = 5,
+ .interval_not_charging = 120,
+ .temp_hysteresis = 3,
+ .maxi = &maxi_params,
+ .chg_params = &chg,
+ .fg_params = &fg,
+};
diff --git a/arch/arm/mach-ux500/board-mop500-bm.h b/arch/arm/mach-ux500/board-mop500-bm.h
new file mode 100644
index 00000000000..ec69a85468f
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-bm.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * U8500 board specific charger and battery initialization parameters.
+ *
+ * Author: Johan Palsson <johan.palsson@stericsson.com> for ST-Ericsson.
+ * Author: Johan Gardsmark <johan.gardsmark@stericsson.com> for ST-Ericsson.
+ *
+ */
+
+#ifndef __BOARD_MOP500_BM_H
+#define __BOARD_MOP500_BM_H
+
+#include <linux/mfd/ab8500/ab8500-bm.h>
+
+extern struct ab8500_charger_platform_data ab8500_charger_plat_data;
+extern struct ab8500_btemp_platform_data ab8500_btemp_plat_data;
+extern struct ab8500_fg_platform_data ab8500_fg_plat_data;
+extern struct ab8500_chargalg_platform_data ab8500_chargalg_plat_data;
+extern struct ab8500_bm_data ab8500_bm_data;
+
+#endif
diff --git a/arch/arm/mach-ux500/board-mop500-mcde.c b/arch/arm/mach-ux500/board-mop500-mcde.c
new file mode 100644
index 00000000000..07b01ddb1fc
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-mcde.c
@@ -0,0 +1,790 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/mfd/ab8500/denc.h>
+#include <linux/workqueue.h>
+#include <linux/dispdev.h>
+#include <video/av8100.h>
+#include <video/mcde_display.h>
+#include <video/mcde_display-generic_dsi.h>
+#include <video/mcde_display-vuib500-dpi.h>
+#include <video/mcde_display-av8100.h>
+#include <video/mcde_display-ab8500.h>
+#include <video/mcde_fb.h>
+#include <video/mcde_dss.h>
+#include <plat/pincfg.h>
+#include "pins-db8500.h"
+#include "pins.h"
+#include "board-mop500.h"
+
+#define DSI_UNIT_INTERVAL_0 0x9
+#define DSI_UNIT_INTERVAL_1 0x9
+#define DSI_UNIT_INTERVAL_2 0x5
+
+#define PRIMARY_DISPLAY_ID 0
+#define SECONDARY_DISPLAY_ID 1
+#define TERTIARY_DISPLAY_ID 2
+
+#ifdef CONFIG_FB_MCDE
+
+/* The initialization of hdmi disp driver must be delayed in order to
+ * ensure that inputclk will be available (needed by hdmi hw) */
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+static struct delayed_work work_dispreg_hdmi;
+#define DISPREG_HDMI_DELAY 5000
+#endif
+
+#define MCDE_NR_OF_DISPLAYS 3
+static struct mcde_display_device *displays[MCDE_NR_OF_DISPLAYS] = { NULL };
+static int display_initialized_during_boot;
+
+static int __init startup_graphics_setup(char *str)
+{
+
+ if (get_option(&str, &display_initialized_during_boot) != 1)
+ display_initialized_during_boot = 0;
+
+ switch (display_initialized_during_boot) {
+ case 1:
+ pr_info("Startup graphics support\n");
+ break;
+ case 0:
+ default:
+ pr_info("No startup graphics supported\n");
+ break;
+ };
+
+ return 1;
+}
+__setup("startup_graphics=", startup_graphics_setup);
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY
+static struct mcde_port port0 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = 1,
+ .link = 0,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+ .sync_src = MCDE_SYNCSRC_OFF,
+ .update_auto_trig = true,
+#else
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .update_auto_trig = false,
+#endif
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_0,
+ .clk_cont = false,
+ .data_lanes_swap = false,
+ },
+ },
+};
+
+struct mcde_display_generic_platform_data generic_display0_pdata = {
+ .reset_delay = 1,
+#ifdef CONFIG_REGULATOR
+ .regulator_id = "v-display",
+ .min_supply_voltage = 2500000, /* 2.5V */
+ .max_supply_voltage = 2700000 /* 2.7V */
+#endif
+};
+
+struct mcde_display_device generic_display0 = {
+ .name = "mcde_disp_generic",
+ .id = PRIMARY_DISPLAY_ID,
+ .port = &port0,
+ .chnl_id = MCDE_CHNL_A,
+ /*
+ * A large fifo is needed when ddr is clocked down to 25% to not get
+ * latency problems.
+ */
+ .fifo = MCDE_FIFO_A,
+#ifdef CONFIG_MCDE_DISPLAY_PRIMARY_16BPP
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+#else
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888,
+#endif
+ .native_x_res = 864,
+ .native_y_res = 480,
+ .synchronized_update = false,
+ /* TODO: Remove rotation buffers once ESRAM driver is completed */
+ .rotbuf1 = U8500_ESRAM_BASE + 0x20000 * 4,
+ .rotbuf2 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x10000,
+ .dev = {
+ .platform_data = &generic_display0_pdata,
+ },
+};
+#endif /* CONFIG_DISPLAY_GENERIC_DSI_PRIMARY */
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY
+static struct mcde_port subdisplay_port = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = 1,
+ .link = 1,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC
+ .sync_src = MCDE_SYNCSRC_OFF,
+ .update_auto_trig = true,
+#else
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .update_auto_trig = false,
+#endif
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_1,
+ .clk_cont = false,
+ .data_lanes_swap = false,
+ },
+ },
+
+};
+
+static struct mcde_display_generic_platform_data generic_subdisplay_pdata = {
+ .reset_delay = 1,
+#ifdef CONFIG_REGULATOR
+ .regulator_id = "v-display",
+ .min_supply_voltage = 2500000, /* 2.5V */
+ .max_supply_voltage = 2700000 /* 2.7V */
+#endif
+};
+
+static struct mcde_display_device generic_subdisplay = {
+ .name = "mcde_disp_generic_subdisplay",
+ .id = SECONDARY_DISPLAY_ID,
+ .port = &subdisplay_port,
+ .chnl_id = MCDE_CHNL_C1,
+ .fifo = MCDE_FIFO_C1,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 864,
+ .native_y_res = 480,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_VSYNC
+ .synchronized_update = true,
+#else
+ .synchronized_update = false,
+#endif
+ .dev = {
+ .platform_data = &generic_subdisplay_pdata,
+ },
+};
+#endif /* CONFIG_DISPLAY_GENERIC_DSI_SECONDARY */
+
+#ifdef CONFIG_MCDE_DISPLAY_DPI_PRIMARY
+static struct mcde_port port0 = {
+ .type = MCDE_PORTTYPE_DPI,
+ .pixel_format = MCDE_PORTPIXFMT_DPI_24BPP,
+ .ifc = 0,
+ .link = 1, /* DPI channel B can only be on link 1 */
+ .sync_src = MCDE_SYNCSRC_OFF, /* sync from output formatter */
+ .update_auto_trig = true,
+ .phy = {
+ .dpi = {
+ .tv_mode = false,
+ .clock_div = 2,
+ .polarity = DPI_ACT_LOW_VSYNC | DPI_ACT_LOW_HSYNC,
+ },
+ },
+};
+
+struct mcde_display_dpi_platform_data generic_display0_pdata = {0};
+static struct ux500_pins *dpi_pins;
+
+static int dpi_display_platform_enable(struct mcde_display_device *ddev)
+{
+ int res;
+
+ if (!dpi_pins) {
+ dpi_pins = ux500_pins_get("mcde-dpi");
+ if (!dpi_pins)
+ return -EINVAL;
+ }
+
+ dev_info(&ddev->dev, "%s\n", __func__);
+ res = ux500_pins_enable(dpi_pins);
+ if (res)
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+
+ return res;
+}
+
+static int dpi_display_platform_disable(struct mcde_display_device *ddev)
+{
+ int res;
+
+ dev_info(&ddev->dev, "%s\n", __func__);
+
+ res = ux500_pins_disable(dpi_pins);
+ if (res)
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+
+ return res;
+
+}
+
+struct mcde_display_device generic_display0 = {
+ .name = "mcde_display_dpi",
+ .id = 0,
+ .port = &port0,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+#ifdef CONFIG_MCDE_DISPLAY_PRIMARY_16BPP
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+#else
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888,
+#endif
+ .native_x_res = 640,
+ .native_y_res = 480,
+ /* .synchronized_update: Don't care: port is set to update_auto_trig */
+ .dev = {
+ .platform_data = &generic_display0_pdata,
+ },
+ .platform_enable = dpi_display_platform_enable,
+ .platform_disable = dpi_display_platform_disable,
+};
+#endif /* CONFIG_MCDE_DISPLAY_DPI_PRIMARY */
+
+#ifdef CONFIG_DISPLAY_AB8500_TERTIARY
+static struct mcde_port port_tvout1 = {
+ .type = MCDE_PORTTYPE_DPI,
+ .pixel_format = MCDE_PORTPIXFMT_DPI_24BPP,
+ .ifc = 0,
+ .link = 1, /* channel B */
+ .sync_src = MCDE_SYNCSRC_OFF,
+ .update_auto_trig = true,
+ .phy = {
+ .dpi = {
+ .bus_width = 4, /* DDR mode */
+ .tv_mode = true,
+ .clock_div = MCDE_PORT_DPI_NO_CLOCK_DIV,
+ },
+ },
+};
+
+static struct ab8500_display_platform_data ab8500_display_pdata = {
+ .nr_regulators = 2,
+ .regulator_id = {"v-tvout", "v-ab8500-AV-switch"},
+ .rgb_2_yCbCr_transform = {
+ .matrix = {
+ {0x42, 0x81, 0x19},
+ {0xffda, 0xffb6, 0x70},
+ {0x70, 0xffa2, 0xffee},
+ },
+ .offset = {0x10, 0x80, 0x80},
+ }
+};
+
+static struct ux500_pins *tvout_pins;
+
+static int ab8500_platform_enable(struct mcde_display_device *ddev)
+{
+ int res = 0;
+
+ if (!tvout_pins) {
+ tvout_pins = ux500_pins_get("mcde-tvout");
+ if (!tvout_pins)
+ return -EINVAL;
+ }
+
+ dev_info(&ddev->dev, "%s\n", __func__);
+ res = ux500_pins_enable(tvout_pins);
+ if (res != 0)
+ goto failed;
+
+ return res;
+
+failed:
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+ return res;
+}
+
+static int ab8500_platform_disable(struct mcde_display_device *ddev)
+{
+ int res;
+
+ dev_info(&ddev->dev, "%s\n", __func__);
+
+ res = ux500_pins_disable(tvout_pins);
+ if (res != 0)
+ goto failed;
+ return res;
+
+failed:
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+ return res;
+}
+
+struct mcde_display_device tvout_ab8500_display = {
+ .name = "mcde_tv_ab8500",
+ .id = TERTIARY_DISPLAY_ID,
+ .port = &port_tvout1,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 720,
+ .native_y_res = 576,
+ /* .synchronized_update: Don't care: port is set to update_auto_trig */
+ .dev = {
+ .platform_data = &ab8500_display_pdata,
+ },
+
+ /*
+ * We might need to describe the std here:
+ * - there are different PAL / NTSC formats (do they require MCDE
+ * settings?)
+ */
+ .platform_enable = ab8500_platform_enable,
+ .platform_disable = ab8500_platform_disable,
+};
+#endif /* CONFIG_DISPLAY_AB8500_TERTIARY */
+
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+static struct mcde_port port2 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = 1,
+ .link = 2,
+#ifdef CONFIG_AV8100_HWTRIG_INT
+ .sync_src = MCDE_SYNCSRC_TE0,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_I2SDAT3
+ .sync_src = MCDE_SYNCSRC_TE1,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_DSI_TE
+ .sync_src = MCDE_SYNCSRC_TE_POLLING,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_NONE
+ .sync_src = MCDE_SYNCSRC_OFF,
+#endif
+ .update_auto_trig = true,
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_2,
+ .clk_cont = false,
+ .data_lanes_swap = false,
+ },
+ },
+ .hdmi_sdtv_switch = HDMI_SWITCH,
+};
+
+struct mcde_display_hdmi_platform_data av8100_hdmi_pdata = {
+ .reset_gpio = 0,
+ .reset_delay = 1,
+ .regulator_id = NULL, /* TODO: "display_main" */
+ .cvbs_regulator_id = "v-av8100-AV-switch",
+ .ddb_id = 1,
+ .rgb_2_yCbCr_transform = {
+ .matrix = {
+ {0x42, 0x81, 0x19},
+ {0xffda, 0xffb6, 0x70},
+ {0x70, 0xffa2, 0xffee},
+ },
+ .offset = {0x10, 0x80, 0x80},
+ }
+};
+
+struct mcde_display_device av8100_hdmi = {
+ .name = "av8100_hdmi",
+ .id = TERTIARY_DISPLAY_ID,
+ .port = &port2,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888,
+ .native_x_res = 1280,
+ .native_y_res = 720,
+ .synchronized_update = false,
+ .dev = {
+ .platform_data = &av8100_hdmi_pdata,
+ },
+ .platform_enable = NULL,
+ .platform_disable = NULL,
+};
+
+static void delayed_work_dispreg_hdmi(struct work_struct *ptr)
+{
+ if (mcde_display_device_register(&av8100_hdmi))
+ pr_warning("Failed to register av8100_hdmi\n");
+ displays[TERTIARY_DISPLAY_ID] = &av8100_hdmi;
+}
+#endif /* CONFIG_DISPLAY_AV8100_TERTIARY */
+
+/*
+* This function will create the framebuffer for the display that is registered.
+*/
+static int display_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *dev)
+{
+ struct mcde_display_device *ddev = dev;
+ u16 width, height;
+ u16 virtual_width, virtual_height;
+ u32 rotate = FB_ROTATE_UR;
+ struct fb_info *fbi;
+
+ if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED)
+ return 0;
+
+ if (ddev->id < PRIMARY_DISPLAY_ID || ddev->id >= MCDE_NR_OF_DISPLAYS)
+ return 0;
+
+ mcde_dss_get_native_resolution(ddev, &width, &height);
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY
+ if (ddev->id == PRIMARY_DISPLAY_ID) {
+ switch (CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE) {
+ case 0:
+ rotate = FB_ROTATE_UR;
+ break;
+ case 90:
+ rotate = FB_ROTATE_CW;
+ swap(width, height);
+ break;
+ case 180:
+ rotate = FB_ROTATE_UD;
+ break;
+ case 270:
+ rotate = FB_ROTATE_CCW;
+ swap(width, height);
+ break;
+ }
+ }
+#endif
+
+ virtual_width = width;
+ virtual_height = height * 2;
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+ if (ddev->id == PRIMARY_DISPLAY_ID)
+ virtual_height = height;
+#endif
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC
+ if (ddev->id == SECONDARY_DISPLAY_ID)
+ virtual_height = height;
+#endif
+
+#ifdef CONFIG_DISPLAY_AV8100_TRIPPLE_BUFFER
+ if (ddev->id == TERTIARY_DISPLAY_ID)
+ virtual_height = height * 3;
+#endif
+
+ if (ddev->id == TERTIARY_DISPLAY_ID) {
+#ifdef CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE
+ hdmi_fb_onoff(ddev, 1, 0, 0);
+#endif /* CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE */
+ } else {
+ /* Create frame buffer */
+ fbi = mcde_fb_create(ddev,
+ width, height,
+ virtual_width, virtual_height,
+ ddev->default_pixel_format,
+ rotate);
+
+ if (IS_ERR(fbi))
+ dev_warn(&ddev->dev,
+ "Failed to create fb for display %s\n",
+ ddev->name);
+ else
+ dev_info(&ddev->dev, "Framebuffer created (%s)\n",
+ ddev->name);
+
+#ifdef CONFIG_DISPDEV
+ /* Create a dispdev overlay for this display */
+ if (dispdev_create(ddev, true) < 0)
+ dev_warn(&ddev->dev,
+ "Failed to create disp for display %s\n",
+ ddev->name);
+ else
+ dev_info(&ddev->dev, "Disp dev created for (%s)\n",
+ ddev->name);
+#endif
+ }
+
+ return 0;
+}
+
+static struct notifier_block display_nb = {
+ .notifier_call = display_postregistered_callback,
+};
+
+/*
+* This function is used to refresh the display (lcd, hdmi, tvout) with black
+* when the framebuffer is registered.
+* The main display will not be updated if startup graphics is displayed
+* from u-boot.
+*/
+#if defined(CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC) || \
+ defined(CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_AUTO_SYNC)
+static int framebuffer_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int ret = 0;
+ struct fb_event *event_data = data;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+ int i;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
+
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ var = info->var;
+ fix = info->fix;
+
+ /* Apply overlay info */
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ struct mcde_overlay *ovly = mfb->ovlys[i];
+ struct mcde_overlay_info ovly_info;
+ struct mcde_fb *mfb = to_mcde_fb(info);
+ memset(&ovly_info, 0, sizeof(ovly_info));
+ ovly_info.paddr = fix.smem_start +
+ fix.line_length * var.yoffset;
+ if (ovly_info.paddr + fix.line_length * var.yres
+ > fix.smem_start + fix.smem_len)
+ ovly_info.paddr = fix.smem_start;
+ ovly_info.fmt = mfb->pix_fmt;
+ ovly_info.stride = fix.line_length;
+ ovly_info.w = var.xres;
+ ovly_info.h = var.yres;
+ ovly_info.dirty.w = var.xres;
+ ovly_info.dirty.h = var.yres;
+ (void) mcde_dss_apply_overlay(ovly, &ovly_info);
+ ret = mcde_dss_update_overlay(ovly);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+#else
+static int framebuffer_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int ret = 0;
+ struct fb_event *event_data = data;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
+
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ if (mfb->id == 0 && display_initialized_during_boot)
+ goto out;
+
+ var = info->var;
+ fix = info->fix;
+ var.yoffset = var.yoffset ? 0 : var.yres;
+ if (info->fbops->fb_pan_display)
+ ret = info->fbops->fb_pan_display(&var, info);
+out:
+ return ret;
+}
+#endif
+
+
+static struct notifier_block framebuffer_nb = {
+ .notifier_call = framebuffer_postregistered_callback,
+};
+
+int __init init_display_devices(void)
+{
+ int ret;
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC
+ struct i2c_adapter *i2c0;
+#endif
+
+ ret = fb_register_client(&framebuffer_nb);
+ if (ret)
+ pr_warning("Failed to register framebuffer notifier\n");
+
+ ret = mcde_dss_register_notifier(&display_nb);
+ if (ret)
+ pr_warning("Failed to register dss notifier\n");
+
+#ifdef CONFIG_DISPLAY_GENERIC_PRIMARY
+ if (machine_is_hrefv60())
+ generic_display0_pdata.reset_gpio = HREFV60_DISP1_RST_GPIO;
+ else
+ generic_display0_pdata.reset_gpio = EGPIO_PIN_15;
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ i2c0 = i2c_get_adapter(0);
+ if (i2c0) {
+ /*
+ * U8500-UIB has the TC35893 at 0x44 on I2C0, the
+ * ST-UIB has not.
+ */
+ ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
+ I2C_SMBUS_QUICK, NULL);
+ i2c_put_adapter(i2c0);
+
+ /* ret == 0 => U8500 UIB connected */
+ generic_display0.synchronized_update = (ret == 0);
+ }
+#else
+ generic_display0.synchronized_update = 0;
+#endif
+#endif
+
+ if (display_initialized_during_boot)
+ generic_display0.power_mode = MCDE_DISPLAY_PM_STANDBY;
+ ret = mcde_display_device_register(&generic_display0);
+ if (ret)
+ pr_warning("Failed to register generic display device 0\n");
+ displays[0] = &generic_display0;
+#endif
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY
+ if (machine_is_hrefv60())
+ generic_subdisplay_pdata.reset_gpio = HREFV60_DISP2_RST_GPIO;
+ else
+ generic_subdisplay_pdata.reset_gpio = EGPIO_PIN_14;
+ ret = mcde_display_device_register(&generic_subdisplay);
+ if (ret)
+ pr_warning("Failed to register generic sub display device\n");
+ displays[1] = &generic_subdisplay;
+#endif
+
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+ INIT_DELAYED_WORK_DEFERRABLE(&work_dispreg_hdmi,
+ delayed_work_dispreg_hdmi);
+
+ schedule_delayed_work(&work_dispreg_hdmi,
+ msecs_to_jiffies(DISPREG_HDMI_DELAY));
+#endif
+#ifdef CONFIG_DISPLAY_AB8500_TERTIARY
+ ret = mcde_display_device_register(&tvout_ab8500_display);
+ if (ret)
+ pr_warning("Failed to register ab8500 tvout device\n");
+ displays[2] = &tvout_ab8500_display;
+#endif
+
+ return ret;
+}
+
+struct mcde_display_device *mcde_get_main_display(void)
+{
+#if defined(CONFIG_DISPLAY_GENERIC_DSI_PRIMARY)
+ return &generic_display0;
+#elif defined(CONFIG_DISPLAY_GENERIC_DSI_SECONDARY)
+ return &generic_subdisplay;
+#elif defined(CONFIG_DISPLAY_AV8100_TERTIARY)
+ return &av8100_hdmi;
+#elif defined(CONFIG_DISPLAY_AB8500_TERTIARY)
+ return &tvout_ab8500_display;
+#else
+ return NULL;
+#endif
+}
+EXPORT_SYMBOL(mcde_get_main_display);
+
+void hdmi_fb_onoff(struct mcde_display_device *ddev,
+ bool enable, u8 cea, u8 vesa_cea_nr)
+{
+ struct fb_info *fbi;
+ u16 w, h;
+ u16 vw, vh;
+ u32 rotate = FB_ROTATE_UR;
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+ dev_dbg(&ddev->dev, "en:%d cea:%d nr:%d\n", enable, cea, vesa_cea_nr);
+
+ if (enable) {
+ if (ddev->enabled) {
+ dev_dbg(&ddev->dev, "Display is already enabled.\n");
+ return;
+ }
+
+ /* Create fb */
+ if (ddev->fbi == NULL) {
+ /* Note: change when dynamic buffering is available */
+ int buffering = 2;
+
+ /* Get default values */
+ mcde_dss_get_native_resolution(ddev, &w, &h);
+ vw = w;
+ vh = h * buffering;
+
+ if (vesa_cea_nr != 0)
+ ddev->ceanr_convert(ddev, cea, vesa_cea_nr,
+ buffering, &w, &h, &vw, &vh);
+
+ fbi = mcde_fb_create(ddev, w, h, vw, vh,
+ ddev->default_pixel_format, rotate);
+
+ if (IS_ERR(fbi)) {
+ dev_warn(&ddev->dev,
+ "Failed to create fb for display %s\n",
+ ddev->name);
+ goto hdmi_fb_onoff_end;
+ } else {
+ dev_info(&ddev->dev,
+ "Framebuffer created (%s)\n",
+ ddev->name);
+ }
+ driver_data->fbdevname = (char *)dev_name(fbi->dev);
+
+#ifdef CONFIG_DISPDEV
+ /* Create a dispdev overlay for this display */
+ if (dispdev_create(ddev, true) < 0)
+ dev_warn(&ddev->dev,
+ "Failed to create disp for %s\n",
+ ddev->name);
+ else
+ dev_info(&ddev->dev,
+ "Disp dev created for (%s)\n",
+ ddev->name);
+#endif /* CONFIG_DISPDEV */
+ }
+ } else {
+ if (!ddev->enabled) {
+ dev_dbg(&ddev->dev, "Display %s is already disabled.\n",
+ ddev->name);
+ return;
+ }
+
+#ifdef CONFIG_DISPDEV
+ dispdev_destroy(ddev);
+#endif /* CONFIG_DISPDEV */
+ mcde_fb_destroy(ddev);
+ }
+
+hdmi_fb_onoff_end:
+ return;
+}
+EXPORT_SYMBOL(hdmi_fb_onoff);
+
+
+module_init(init_display_devices);
+
+#endif
diff --git a/arch/arm/mach-ux500/board-mop500-mcde.h b/arch/arm/mach-ux500/board-mop500-mcde.h
new file mode 100644
index 00000000000..38094b81b34
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-mcde.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Marcel Tunnissen <marcel.tuennissen@stericsson.com> for ST-Ericsson
+ *
+ * MOP500 board specific initialization for regulators
+ */
+
+#ifndef __BOARD_MOP500_MCDE_H
+#define __BOARD_MOP500_MCDE_H
+
+#include <video/mcde_display.h>
+
+#ifdef CONFIG_DISPLAY_AB8500_TERTIARY
+extern struct mcde_display_device tvout_ab8500_display;
+#endif
+
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+extern struct mcde_display_device av8100_hdmi;
+#endif
+
+#endif /* __BOARD_MOP500_MCDE_H */
diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c
new file mode 100644
index 00000000000..3f3d27d3cee
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-mmio.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson
+ * Author: Joakim Axelsson <joakim.axelsson@stericsson.com> for ST-Ericsson
+ * Author: Rajat Verma <rajat.verma@stericsson.com> for ST-Ericsson.
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/mmio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/vmalloc.h>
+#include <plat/pincfg.h>
+#include <mach/gpio.h>
+#include <mach/devices.h>
+#include "pins-db8500.h"
+#include "pins.h"
+#include "board-mop500.h"
+
+static pin_cfg_t i2c2_pins[] = {
+ GPIO8_I2C2_SDA,
+ GPIO9_I2C2_SCL
+};
+static pin_cfg_t ipi2c_pins[] = {
+ GPIO8_IPI2C_SDA,
+ GPIO9_IPI2C_SCL
+};
+static pin_cfg_t i2c_disable_pins[] = {
+ GPIO8_GPIO,
+ GPIO9_GPIO
+};
+static pin_cfg_t xshutdown_host[] = {
+ GPIO141_GPIO,
+ GPIO142_GPIO
+};
+static pin_cfg_t xshutdown_fw[] = {
+ GPIO141_IP_GPIO2,
+ GPIO142_IP_GPIO3
+};
+static pin_cfg_t xshutdown_disable[] = {
+ GPIO141_GPIO,
+ GPIO142_GPIO
+};
+
+struct mmio_board_data{
+ int number_of_regulators;
+ struct regulator **mmio_regulators;
+ /* Pin configs */
+ int xenon_charge;
+ struct mmio_gpio xshutdown_pins[CAMERA_SLOT_END];
+ /* Internal clocks */
+ struct clk *clk_ptr_bml;
+ struct clk *clk_ptr_ipi2c;
+ /* External clocks */
+ struct clk *clk_ptr_ext[CAMERA_SLOT_END];
+};
+
+/* Fill names of regulators required for powering up the
+ * camera sensor in below array */
+static char *regulator_names[] = {"v-mmio-camera" , "v-ana"};
+
+/* This function is used to translate the physical GPIO used for reset GPIO
+ * to logical IPGPIO that needs to be communicated to Firmware. so that
+ * firmware can control reset GPIO of a RAW Bayer sensor */
+static int mmio_get_ipgpio(struct mmio_platform_data *pdata, int gpio,
+ int *ip_gpio)
+{
+ int err = 0;
+ dev_dbg(pdata->dev, "%s() : IPGPIO requested for %d", __func__, gpio);
+ switch (gpio) {
+ case 67:
+ case 140:
+ *ip_gpio = 7;
+ break;
+ case 5:
+ case 66:
+ *ip_gpio = 6;
+ break;
+ case 81:
+ case 65:
+ *ip_gpio = 5;
+ break;
+ case 80:
+ case 64:
+ *ip_gpio = 4;
+ break;
+ case 10:
+ case 79:
+ case 142:
+ *ip_gpio = 3;
+ break;
+ case 11:
+ case 78:
+ case 141:
+ *ip_gpio = 2;
+ break;
+ case 7:
+ case 150:
+ *ip_gpio = 1;
+ break;
+ case 6:
+ case 149:
+ *ip_gpio = 0;
+ break;
+ default:
+ *ip_gpio = -1;
+ err = -1;
+ break;
+ }
+ return err;
+}
+
+static int mmio_clock_init(struct mmio_platform_data *pdata)
+{
+ int err;
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+
+ extra->clk_ptr_bml = clk_get_sys("bml", NULL);
+ if (IS_ERR(extra->clk_ptr_bml)) {
+ err = PTR_ERR(extra->clk_ptr_bml);
+ dev_err(pdata->dev, "Error %d getting clock 'bml'\n", err);
+ goto err_bml_clk;
+ }
+ extra->clk_ptr_ipi2c = clk_get_sys("ipi2", NULL);
+ if (IS_ERR(extra->clk_ptr_ipi2c)) {
+ err = PTR_ERR(extra->clk_ptr_ipi2c);
+ dev_err(pdata->dev, "Error %d getting clock 'ipi2'\n", err);
+ goto err_ipi2c_clk;
+ }
+ extra->clk_ptr_ext[PRIMARY_CAMERA] = clk_get_sys("pri-cam", NULL);
+ if (IS_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA])) {
+ err = PTR_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA]);
+ dev_err(pdata->dev, "Error %d getting clock 'pri-cam'\n", err);
+ goto err_pri_ext_clk;
+ }
+ extra->clk_ptr_ext[SECONDARY_CAMERA] = clk_get_sys("sec-cam", NULL);
+ if (IS_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA])) {
+ err = PTR_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA]);
+ dev_err(pdata->dev, "Error %d getting clock 'sec-cam'\n", err);
+ goto err_sec_ext_clk;
+ }
+ dev_dbg(pdata->dev , "Board %s() Exit\n", __func__);
+ return 0;
+err_sec_ext_clk:
+ clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]);
+err_pri_ext_clk:
+ clk_put(extra->clk_ptr_ipi2c);
+err_ipi2c_clk:
+ clk_put(extra->clk_ptr_bml);
+err_bml_clk:
+ return err;
+}
+static void mmio_clock_exit(struct mmio_platform_data *pdata)
+{
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ clk_put(extra->clk_ptr_bml);
+ clk_put(extra->clk_ptr_ipi2c);
+ clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]);
+ clk_put(extra->clk_ptr_ext[SECONDARY_CAMERA]);
+}
+
+
+static int mmio_pin_cfg_init(struct mmio_platform_data *pdata)
+{
+ int err;
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+
+ extra->xshutdown_pins[PRIMARY_CAMERA].gpio = XSHUTDOWN_PRIMARY_SENSOR;
+ extra->xshutdown_pins[PRIMARY_CAMERA].active_high = 0;
+ extra->xshutdown_pins[PRIMARY_CAMERA].udelay = 500;
+
+ extra->xshutdown_pins[SECONDARY_CAMERA].active_high = 0;
+ extra->xshutdown_pins[SECONDARY_CAMERA].udelay = 500;
+
+ /* Update GPIO mappings according to board */
+ if (machine_is_hrefv60()) {
+ extra->xenon_charge = HREFV60_MMIO_XENON_CHARGE;
+ xshutdown_host[SECONDARY_CAMERA] = GPIO140_GPIO;
+ xshutdown_fw[SECONDARY_CAMERA] = GPIO140_IP_GPIO7;
+ xshutdown_disable[SECONDARY_CAMERA] = GPIO140_GPIO;
+ extra->xshutdown_pins[SECONDARY_CAMERA].gpio = 140;
+ } else {
+ extra->xenon_charge = EGPIO_PIN_5;
+ xshutdown_host[SECONDARY_CAMERA] = GPIO142_GPIO;
+ xshutdown_fw[SECONDARY_CAMERA] = GPIO142_IP_GPIO3;
+ xshutdown_disable[SECONDARY_CAMERA] = GPIO142_GPIO;
+ extra->xshutdown_pins[SECONDARY_CAMERA].gpio = 142;
+ }
+ /* Setup Xenon Charge */
+ err = gpio_request(extra->xenon_charge, "xenon charge");
+ if (err) {
+ dev_err(pdata->dev, "Error %d while requesting xenon charge\n",
+ err);
+ goto err_xenon_gpio_req;
+ }
+ err = gpio_direction_output(extra->xenon_charge, 0);
+ if (err) {
+ dev_err(pdata->dev, "Error %d while setting xenon charge in"
+ "output mode\n", err);
+ goto err_xenon_gpio_set_dir;
+ }
+ dev_dbg(pdata->dev , "Board %s() Exit\n", __func__);
+ return 0;
+err_xenon_gpio_set_dir:
+ gpio_free(extra->xenon_charge);
+err_xenon_gpio_req:
+ return err;
+}
+
+static void mmio_pin_cfg_exit(struct mmio_platform_data *pdata)
+{
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ gpio_free(extra->xenon_charge);
+}
+
+/* For now, both sensors on HREF have some power up sequence. If different
+ * sequences are needed for primary and secondary sensors, it can be
+ * implemented easily. Just use camera_slot field of mmio_platform_data
+ * to determine which camera needs to be powered up */
+static int mmio_power_init(struct mmio_platform_data *pdata)
+{
+ int err = 0, i = 0;
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ extra->number_of_regulators = sizeof(regulator_names)/
+ sizeof(regulator_names[0]);
+ extra->mmio_regulators =
+ kzalloc(sizeof(struct regulator *) * extra->number_of_regulators,
+ GFP_KERNEL);
+ if (!extra->mmio_regulators) {
+ dev_err(pdata->dev , "Error while allocating memory for mmio"
+ "regulators\n");
+ err = -ENOMEM;
+ goto err_no_mem_reg;
+ }
+ for (i = 0; i <
+ extra->number_of_regulators; i++) {
+ extra->mmio_regulators[i] =
+ regulator_get(pdata->dev, regulator_names[i]);
+ if (IS_ERR(extra->mmio_regulators[i])) {
+ err = PTR_ERR(extra->mmio_regulators[i]);
+ dev_err(pdata->dev , "Error %d getting regulator '%s'"
+ "\n", err, regulator_names[i]);
+ goto err_regulator;
+ }
+ }
+ dev_dbg(pdata->dev , "Board %s() Exit\n", __func__);
+ return 0;
+err_regulator:
+ /* Return regulators we have already requested */
+ while (i--)
+ regulator_put(extra->mmio_regulators[i]);
+ kfree(extra->mmio_regulators);
+err_no_mem_reg:
+ return err;
+}
+static void mmio_power_exit(struct mmio_platform_data *pdata)
+{
+ int i = 0;
+ struct mmio_board_data *extra = pdata->extra;;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ for (i = 0; i < extra->number_of_regulators; i++)
+ regulator_put(extra->mmio_regulators[i]);
+ kfree(extra->mmio_regulators);
+}
+
+static int mmio_platform_init(struct mmio_platform_data *pdata)
+{
+ int err = 0;
+ struct mmio_board_data *extra = NULL;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ /* Alloc memory for our own extra data */
+ extra = kzalloc(sizeof(struct mmio_board_data), GFP_KERNEL);
+ if (!extra) {
+ dev_err(pdata->dev, "%s: memory alloc failed for "
+ "mmio_board_data\n", __func__);
+ err = -ENOMEM;
+ goto err_no_mem_extra;
+ }
+ /* Hook the data for other callbacks to use */
+ pdata->extra = extra;
+
+ pdata->camera_slot = -1;
+
+ err = mmio_power_init(pdata);
+ if (err)
+ goto err_regulator;
+ err = mmio_clock_init(pdata);
+ if (err)
+ goto err_clock;
+ err = mmio_pin_cfg_init(pdata);
+ if (err)
+ goto err_pin_cfg;
+ /* Store logical IPGPIO for physical reset GPIOs used */
+ err = mmio_get_ipgpio(pdata,
+ extra->xshutdown_pins[PRIMARY_CAMERA].gpio,
+ &(pdata->reset_ipgpio[PRIMARY_CAMERA]));
+ if (err) {
+ dev_err(pdata->dev, "Error getting ipgpio for pri cam\n");
+ goto err_ipgpio;
+ }
+ err = mmio_get_ipgpio(pdata,
+ extra->xshutdown_pins[SECONDARY_CAMERA].gpio,
+ &(pdata->reset_ipgpio[SECONDARY_CAMERA]));
+ if (err) {
+ dev_err(pdata->dev, "Error getting ipgpio for sec cam\n");
+ goto err_ipgpio;
+ }
+ dev_dbg(pdata->dev , "Board %s() Exit\n", __func__);
+ return 0;
+err_ipgpio:
+ mmio_pin_cfg_exit(pdata);
+err_pin_cfg:
+ mmio_clock_exit(pdata);
+err_clock:
+ mmio_power_exit(pdata);
+err_regulator:
+ kfree(extra);
+err_no_mem_extra:
+ return err;
+}
+static void mmio_platform_exit(struct mmio_platform_data *pdata)
+{
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ mmio_power_exit(pdata);
+ mmio_clock_exit(pdata);
+ mmio_pin_cfg_exit(pdata);
+ kfree(extra);
+ pdata->extra = NULL;
+}
+
+static int mmio_power_enable(struct mmio_platform_data *pdata)
+{
+ int err = 0, i = 0;
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ /* Enable the regulators */
+ for (i = 0; i < extra->number_of_regulators; i++) {
+ err = regulator_enable(extra->mmio_regulators[i]);
+ if (IS_ERR(extra->mmio_regulators[i])) {
+ err = PTR_ERR(extra->mmio_regulators[i]);
+ dev_err(pdata->dev , "Error %d enabling regulator '%s'"
+ "\n", err, regulator_names[i]);
+ goto err_regulator;
+ }
+ }
+ /* Set Xenon Charge */
+ gpio_set_value(extra->xenon_charge, 1);
+ dev_dbg(pdata->dev , "Board %s() Exit\n", __func__);
+ return 0;
+err_regulator:
+ /* Disable regulators we already enabled */
+ while (i--)
+ regulator_disable(extra->mmio_regulators[i]);
+ return err;
+}
+
+static void mmio_power_disable(struct mmio_platform_data *pdata)
+{
+ int i;
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ /* Disable the regulators */
+ for (i = 0; i < extra->number_of_regulators; i++)
+ regulator_disable(extra->mmio_regulators[i]);
+ /* Disable Xenon Charge */
+ gpio_set_value(extra->xenon_charge, 0);
+}
+static int mmio_clock_enable(struct mmio_platform_data *pdata)
+{
+ int err = 0;
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ /* Enable internal clocks */
+ err = clk_enable(extra->clk_ptr_bml);
+ if (err) {
+ dev_err(pdata->dev, "Error activating bml clock %d\n", err);
+ goto err_bml_clk;
+ }
+ err = clk_enable(extra->clk_ptr_ipi2c);
+ if (err) {
+ dev_err(pdata->dev, "Error activating i2c2 clock %d\n", err);
+ goto err_ipi2c_clk;
+ }
+ /* Enable appropriate external clock */
+ err = clk_enable(extra->clk_ptr_ext[pdata->camera_slot]);
+ if (err) {
+ dev_err(pdata->dev, "Error activating clock for sensor %d, err"
+ "%d\n", pdata->camera_slot, err);
+ goto err_ext_clk;
+ }
+ dev_dbg(pdata->dev , "Board %s() Exit\n", __func__);
+ return 0;
+err_ext_clk:
+ clk_disable(extra->clk_ptr_ipi2c);
+err_ipi2c_clk:
+ clk_disable(extra->clk_ptr_bml);
+err_bml_clk:
+ return err;
+}
+
+static void mmio_clock_disable(struct mmio_platform_data *pdata)
+{
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ clk_disable(extra->clk_ptr_bml);
+ clk_disable(extra->clk_ptr_ipi2c);
+ clk_disable(extra->clk_ptr_ext[pdata->camera_slot]);
+}
+
+
+static int mmio_config_xshutdown_pins(struct mmio_platform_data *pdata,
+ enum mmio_select_xshutdown_t select,
+ int is_active_high)
+{
+ int err = 0;
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ switch (select) {
+ case MMIO_ENABLE_XSHUTDOWN_HOST:
+ extra->xshutdown_pins[pdata->camera_slot].active_high =
+ is_active_high;
+ err = nmk_config_pin(xshutdown_host[pdata->camera_slot] |
+ (is_active_high ? PIN_OUTPUT_LOW : PIN_OUTPUT_HIGH),
+ 0);
+ break;
+ case MMIO_ENABLE_XSHUTDOWN_FW:
+ err = nmk_config_pin(xshutdown_fw[pdata->camera_slot], 0);
+ break;
+ case MMIO_DISABLE_XSHUTDOWN:
+ err = nmk_config_pin(xshutdown_disable[pdata->camera_slot],
+ 0);
+ break;
+ default:
+ break;
+ }
+ if (err)
+ dev_dbg(pdata->dev , "Error configuring xshutdown, err = %d\n",
+ err);
+ return err;
+}
+static void mmio_set_xshutdown(struct mmio_platform_data *pdata)
+{
+ struct mmio_board_data *extra = pdata->extra;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ gpio_set_value(extra->xshutdown_pins[pdata->camera_slot].gpio ,
+ (extra->xshutdown_pins[pdata->camera_slot].active_high ? 1 :
+ 0));
+ udelay(extra->xshutdown_pins[pdata->camera_slot].udelay);
+}
+static int mmio_config_i2c_pins(struct mmio_platform_data *pdata,
+ enum mmio_select_i2c_t select)
+{
+ int err = 0;
+ dev_dbg(pdata->dev , "Board %s() Enter\n", __func__);
+ switch (select) {
+ case MMIO_ACTIVATE_I2C_HOST:
+ err = nmk_config_pins(i2c2_pins, ARRAY_SIZE(i2c2_pins));
+ break;
+ case MMIO_ACTIVATE_IPI2C2:
+ err = nmk_config_pins(ipi2c_pins, ARRAY_SIZE(ipi2c_pins));
+ break;
+ case MMIO_DEACTIVATE_I2C:
+ err = nmk_config_pins(i2c_disable_pins,
+ ARRAY_SIZE(i2c_disable_pins));
+ break;
+ default:
+ break;
+ }
+
+ return err;
+}
+static struct mmio_platform_data mmio_config = {
+ .platform_init = mmio_platform_init,
+ .platform_exit = mmio_platform_exit,
+ .power_enable = mmio_power_enable,
+ .power_disable = mmio_power_disable,
+ .clock_enable = mmio_clock_enable,
+ .clock_disable = mmio_clock_disable,
+ .config_i2c_pins = mmio_config_i2c_pins,
+ .config_xshutdown_pins = mmio_config_xshutdown_pins,
+ .set_xshutdown = mmio_set_xshutdown
+};
+
+struct platform_device ux500_mmio_device = {
+ .name = MMIO_NAME,
+ .id = -1,
+ .dev = {
+ .platform_data = &mmio_config,
+ }
+};
diff --git a/arch/arm/mach-ux500/board-mop500-msp.c b/arch/arm/mach-ux500/board-mop500-msp.c
new file mode 100644
index 00000000000..e90dead020b
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-msp.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/platform_device.h>
+#include <linux/i2s/i2s.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <plat/ste_dma40.h>
+#include <plat/pincfg.h>
+
+#include <mach/devices.h>
+#include <mach/ste-dma40-db8500.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/msp.h>
+
+#include "board-mop500.h"
+#include "devices-db8500.h"
+#include "pins-db8500.h"
+
+/* MSP1/3 Tx/Rx usage protection */
+static DEFINE_SPINLOCK(msp_rxtx_lock);
+
+/* Reference Count */
+static int msp_rxtx_ref;
+
+static pin_cfg_t mop500_msp1_pins_init[] = {
+ GPIO33_MSP1_TXD | PIN_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE,
+ GPIO34_MSP1_TFS | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE,
+ GPIO35_MSP1_TCK | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE,
+ GPIO36_MSP1_RXD | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_DISABLE,
+};
+
+static pin_cfg_t mop500_msp1_pins_exit[] = {
+ GPIO33_MSP1_TXD | PIN_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE,
+ GPIO34_MSP1_TFS | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE,
+ GPIO35_MSP1_TCK | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE,
+ GPIO36_MSP1_RXD | PIN_INPUT_NOPULL | PIN_SLPM_WAKEUP_ENABLE,
+};
+
+int msp13_i2s_init(void)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msp_rxtx_lock, flags);
+ if (msp_rxtx_ref == 0)
+ retval = nmk_config_pins(
+ ARRAY_AND_SIZE(mop500_msp1_pins_init));
+ if (!retval)
+ msp_rxtx_ref++;
+ spin_unlock_irqrestore(&msp_rxtx_lock, flags);
+
+ return retval;
+}
+
+int msp13_i2s_exit(void)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&msp_rxtx_lock, flags);
+ WARN_ON(!msp_rxtx_ref);
+ msp_rxtx_ref--;
+ if (msp_rxtx_ref == 0)
+ retval = nmk_config_pins_sleep(
+ ARRAY_AND_SIZE(mop500_msp1_pins_exit));
+ spin_unlock_irqrestore(&msp_rxtx_lock, flags);
+
+ return retval;
+}
+
+static struct stedma40_chan_cfg msp0_dma_rx = {
+ .high_priority = true,
+ .dir = STEDMA40_PERIPH_TO_MEM,
+
+ .src_dev_type = DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp0_dma_tx = {
+ .high_priority = true,
+ .dir = STEDMA40_MEM_TO_PERIPH,
+
+ .src_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct msp_i2s_platform_data msp0_platform_data = {
+ .id = MSP_0_I2S_CONTROLLER,
+ .msp_i2s_dma_rx = &msp0_dma_rx,
+ .msp_i2s_dma_tx = &msp0_dma_tx,
+};
+
+static struct stedma40_chan_cfg msp1_dma_rx = {
+ .high_priority = true,
+ .dir = STEDMA40_PERIPH_TO_MEM,
+
+ .src_dev_type = DB8500_DMA_DEV30_MSP1_RX, /* v2: MSP3 RX */
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp1_dma_tx = {
+ .high_priority = true,
+ .dir = STEDMA40_MEM_TO_PERIPH,
+
+ .src_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV30_MSP1_TX,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct msp_i2s_platform_data msp1_platform_data = {
+ .id = MSP_1_I2S_CONTROLLER,
+ .msp_i2s_dma_rx = &msp1_dma_rx,
+ .msp_i2s_dma_tx = &msp1_dma_tx,
+ .msp_i2s_init = msp13_i2s_init,
+ .msp_i2s_exit = msp13_i2s_exit,
+};
+
+static struct stedma40_chan_cfg msp2_dma_rx = {
+ .high_priority = true,
+ .dir = STEDMA40_PERIPH_TO_MEM,
+
+ .src_dev_type = DB8500_DMA_DEV14_MSP2_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct stedma40_chan_cfg msp2_dma_tx = {
+ .high_priority = true,
+ .dir = STEDMA40_MEM_TO_PERIPH,
+
+ .src_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV14_MSP2_TX,
+
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+
+ /* data_width is set during configuration */
+};
+
+static struct msp_i2s_platform_data msp2_platform_data = {
+ .id = MSP_2_I2S_CONTROLLER,
+ .msp_i2s_dma_rx = &msp2_dma_rx,
+ .msp_i2s_dma_tx = &msp2_dma_tx,
+};
+
+static struct msp_i2s_platform_data msp3_platform_data = {
+ .id = MSP_3_I2S_CONTROLLER,
+ .msp_i2s_dma_rx = &msp1_dma_rx,
+ .msp_i2s_dma_tx = NULL,
+ .msp_i2s_init = msp13_i2s_init,
+ .msp_i2s_exit = msp13_i2s_exit,
+};
+
+static struct i2s_board_info stm_i2s_board_info[] __initdata = {
+ {
+ .modalias = "i2s_device.0",
+ .id = MSP_0_CONTROLLER - 1,
+ .chip_select = 0,
+ },
+ {
+ .modalias = "i2s_device.1",
+ .id = MSP_1_CONTROLLER - 1,
+ .chip_select = 1,
+ },
+ {
+ .modalias = "i2s_device.2",
+ .id = MSP_2_CONTROLLER - 1,
+ .chip_select = 2,
+ },
+ {
+ .modalias = "i2s_device.3",
+ .id = MSP_3_CONTROLLER - 1,
+ .chip_select = 3,
+ },
+};
+
+static void __init mop500_msp_fixup(void)
+{
+ if (cpu_is_u8500ed() || cpu_is_u8500v1())
+ return;
+
+ /* DMA Rx is moved to MSP3 on DB8500v2 */
+ msp1_platform_data.msp_i2s_dma_rx = NULL;
+
+ /* MSP2 DMA doesn't work with PSIZE == 4 on DB8500v2 */
+ msp2_dma_rx.src_info.psize = STEDMA40_PSIZE_LOG_1;
+ msp2_dma_rx.dst_info.psize = STEDMA40_PSIZE_LOG_1;
+}
+
+void __init mop500_msp_init(void)
+{
+ mop500_msp_fixup();
+
+ db8500_add_msp0_i2s(&msp0_platform_data);
+ db8500_add_msp1_i2s(&msp1_platform_data);
+ db8500_add_msp2_i2s(&msp2_platform_data);
+
+ if (cpu_is_u8500v2())
+ db8500_add_msp3_i2s(&msp3_platform_data);
+
+ i2s_register_board_info(stm_i2s_board_info,
+ ARRAY_SIZE(stm_i2s_board_info));
+}
diff --git a/arch/arm/mach-ux500/board-mop500-nuib.c b/arch/arm/mach-ux500/board-mop500-nuib.c
new file mode 100644
index 00000000000..2f1e733afe3
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-nuib.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 ST-Ericsson SA
+ *
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input/synaptics_i2c_rmi4.h>
+
+#include "board-mop500.h"
+
+/* Descriptor structure.
+ * Describes the number of i2c devices on the bus that speak RMI.
+ */
+static struct synaptics_rmi4_platform_data rmi4_i2c_dev_platformdata = {
+ .irq_number = GPIO_TO_IRQ(84),
+ .irq_type = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
+#if CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE == 270
+ .x_flip = true,
+ .y_flip = false,
+#else
+ .x_flip = false,
+ .y_flip = true,
+#endif
+ .regulator_en = true,
+};
+
+static struct i2c_board_info __initdata u8500_i2c3_devices_nuib[] = {
+ {
+ /* Touschscreen */
+ I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
+ .platform_data = &rmi4_i2c_dev_platformdata,
+ },
+};
+
+void __init mop500_nuib_init(void)
+{
+ i2c_register_board_info(3, u8500_i2c3_devices_nuib,
+ ARRAY_SIZE(u8500_i2c3_devices_nuib));
+}
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
new file mode 100644
index 00000000000..bfe6e1f1fc6
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -0,0 +1,731 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/string.h>
+
+#include <plat/pincfg.h>
+#include <plat/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/suspend.h>
+
+#include "pins-db8500.h"
+#include "pins.h"
+
+enum custom_pin_cfg_t {
+ PINS_FOR_DEFAULT,
+ PINS_FOR_U9500_21,
+};
+
+static enum custom_pin_cfg_t pinsfor = PINS_FOR_DEFAULT;
+
+static pin_cfg_t mop500_pins_common[] = {
+ /* MSP0 */
+ GPIO12_MSP0_TXD,
+ GPIO13_MSP0_TFS,
+ GPIO14_MSP0_TCK,
+ GPIO15_MSP0_RXD,
+
+ /* MSP2: HDMI */
+ GPIO193_MSP2_TXD,
+ GPIO194_MSP2_TCK,
+ GPIO195_MSP2_TFS,
+ GPIO196_MSP2_RXD | PIN_OUTPUT_LOW,
+
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ /* Touch screen INTERFACE */
+ GPIO84_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT1 */
+#endif
+
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ /* STMPE1601/tc35893 keypad IRQ */
+ GPIO218_GPIO | PIN_INPUT_PULLUP,
+#endif
+
+ /* UART */
+ /* uart-0 pins gpio configuration should be
+ * kept intact to prevent glitch in tx line
+ * when tty dev is opened. Later these pins
+ * are configured to uart mop500_pins_uart0
+ *
+ * It will be replaced with uart configuration
+ * once the issue is solved.
+ */
+ GPIO0_GPIO | PIN_INPUT_PULLUP,
+ GPIO1_GPIO | PIN_OUTPUT_HIGH,
+ GPIO2_GPIO | PIN_INPUT_PULLUP,
+ GPIO3_GPIO | PIN_OUTPUT_LOW,
+
+ GPIO29_U2_RXD | PIN_INPUT_PULLUP,
+ GPIO30_U2_TXD | PIN_OUTPUT_HIGH,
+ GPIO31_U2_CTSn | PIN_INPUT_PULLUP,
+ GPIO32_U2_RTSn | PIN_OUTPUT_HIGH,
+
+ /* USB */
+ GPIO256_USB_NXT,
+ GPIO257_USB_STP | PIN_OUTPUT_HIGH,
+ GPIO258_USB_XCLK,
+ GPIO259_USB_DIR,
+ GPIO260_USB_DAT7,
+ GPIO261_USB_DAT6,
+ GPIO262_USB_DAT5,
+ GPIO263_USB_DAT4,
+ GPIO264_USB_DAT3,
+ GPIO265_USB_DAT2,
+ GPIO266_USB_DAT1,
+ GPIO267_USB_DAT0,
+
+/* May not be in snowball #ifndef CONFIG_MACH_U8500_SNOWBALL */
+ /* Display & HDMI HW sync */
+ GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP,
+ GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP,
+
+ /* HSI */
+ GPIO219_HSIR_FLA0,
+ GPIO220_HSIR_DAT0,
+ GPIO221_HSIR_RDY0,
+ GPIO222_HSIT_FLA0,
+ GPIO223_HSIT_DAT0,
+ GPIO224_HSIT_RDY0,
+ GPIO225_GPIO | PIN_INPUT_PULLDOWN, /* CA_WAKE0 */
+ GPIO226_GPIO | PIN_OUTPUT_LOW, /* WLAN_PMU_EN / AC_WAKE0 */
+/* May not be in snowball #endif */
+
+#ifdef CONFIG_MACH_U8500_SNOWBALL
+ /* SSP0, to AB8500 */
+ GPIO143_SSP0_CLK,
+ GPIO144_SSP0_FRM,
+ GPIO145_SSP0_RXD | PIN_PULL_DOWN,
+ GPIO146_SSP0_TXD,
+#endif
+
+#ifdef CONFIG_MACH_U8500_SNOWBALL
+ /* MMC2: LAN */
+ GPIO86_SM_ADQ0,
+ GPIO87_SM_ADQ1,
+ GPIO88_SM_ADQ2,
+ GPIO89_SM_ADQ3,
+ GPIO90_SM_ADQ4,
+ GPIO91_SM_ADQ5,
+ GPIO92_SM_ADQ6,
+ GPIO93_SM_ADQ7,
+
+ GPIO94_SM_ADVn,
+ GPIO95_SM_CS0n,
+ GPIO96_SM_OEn,
+ GPIO97_SM_WEn,
+
+ GPIO128_SM_CKO,
+ GPIO130_SM_FBCLK,
+ GPIO131_SM_ADQ8,
+ GPIO132_SM_ADQ9,
+ GPIO133_SM_ADQ10,
+ GPIO134_SM_ADQ11,
+ GPIO135_SM_ADQ12,
+ GPIO136_SM_ADQ13,
+ GPIO137_SM_ADQ14,
+ GPIO138_SM_ADQ15,
+
+ /* RSTn_LAN */
+ GPIO141_GPIO | PIN_OUTPUT_HIGH,
+ GPIO161_GPIO | PIN_OUTPUT_LOW, /* WLAN_PMU_EN */
+#endif
+
+
+};
+
+static pin_cfg_t mop500_pins_default[] = {
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ /* XENON Flashgun INTERFACE */
+ GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */
+ GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */
+
+#endif
+ GPIO217_GPIO | PIN_INPUT_PULLUP, /* TC35892 IRQ */
+
+ /* sdi0 (removable MMC/SD/SDIO cards) not handled by pm_runtime */
+ GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH,
+};
+
+static pin_cfg_t mop500_pins_hrefv60[] = {
+ /* WLAN */
+ GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */
+ GPIO85_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */
+
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ /* XENON Flashgun INTERFACE */
+ GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */
+ GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */
+#endif
+
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ /* Assistant LED INTERFACE */
+ GPIO21_GPIO | PIN_OUTPUT_LOW, /* XENON_EN1 */
+ GPIO64_IP_GPIO4 | PIN_OUTPUT_LOW, /* XENON_EN2 */
+#endif
+
+ /* Magnetometer */
+ GPIO31_GPIO | PIN_INPUT_PULLUP, /* magnetometer_INT */
+ GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */
+
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ /* Display Interface */
+ GPIO65_GPIO | PIN_OUTPUT_LOW, /* DISP1 RST */
+ GPIO66_GPIO | PIN_OUTPUT_LOW, /* DISP2 RST */
+#endif
+
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ /* Touch screen INTERFACE */
+ GPIO143_GPIO | PIN_OUTPUT_LOW,/*TOUCH_RST1 */
+
+ /* Touch screen INTERFACE 2 */
+ GPIO67_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT2 */
+ GPIO146_GPIO | PIN_OUTPUT_LOW,/*TOUCH_RST2 */
+
+ /* ETM_PTM_TRACE INTERFACE */
+ GPIO70_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA23 */
+ GPIO71_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA22 */
+ GPIO72_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA21 */
+ GPIO73_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA20 */
+ GPIO74_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA19 */
+
+ /* NAHJ INTERFACE */
+ GPIO76_GPIO | PIN_OUTPUT_LOW,/* NAHJ_CTRL */
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ GPIO216_GPIO | PIN_OUTPUT_HIGH,/* NAHJ_CTRL_INV */
+#endif
+
+ /* NFC INTERFACE */
+ GPIO77_GPIO | PIN_OUTPUT_LOW, /* NFC_ENA */
+ GPIO144_GPIO | PIN_INPUT_PULLDOWN, /* NFC_IRQ */
+ GPIO142_GPIO | PIN_OUTPUT_LOW, /* NFC_RESET */
+
+ /* Keyboard MATRIX INTERFACE */
+ GPIO90_MC5_CMD | PIN_OUTPUT_LOW, /* KP_O_1 */
+ GPIO87_MC5_DAT1 | PIN_OUTPUT_LOW, /* KP_O_2 */
+ GPIO86_MC5_DAT0 | PIN_OUTPUT_LOW, /* KP_O_3 */
+ GPIO96_KP_O6 | PIN_OUTPUT_LOW, /* KP_O_6 */
+ GPIO94_KP_O7 | PIN_OUTPUT_LOW, /* KP_O_7 */
+ GPIO93_MC5_DAT4 | PIN_INPUT_PULLUP, /* KP_I_0 */
+ GPIO89_MC5_DAT3 | PIN_INPUT_PULLUP, /* KP_I_2 */
+ GPIO88_MC5_DAT2 | PIN_INPUT_PULLUP, /* KP_I_3 */
+ GPIO91_GPIO | PIN_INPUT_PULLUP, /* FORCE_SENSING_INT */
+ GPIO92_GPIO | PIN_OUTPUT_LOW, /* FORCE_SENSING_RST */
+ GPIO97_GPIO | PIN_OUTPUT_LOW, /* FORCE_SENSING_WU */
+
+ /* DiPro Sensor Interface */
+ GPIO139_GPIO | PIN_INPUT_PULLUP, /* DIPRO_INT */
+
+ /* HAL SWITCH INTERFACE */
+ GPIO145_GPIO | PIN_INPUT_PULLDOWN,/* HAL_SW */
+#endif
+
+ /* Audio Amplifier Interface */
+ GPIO149_GPIO | PIN_OUTPUT_HIGH, /* VAUDIO_HF_EN, enable MAX8968 */
+
+ /* GBF INTERFACE */
+ GPIO171_GPIO | PIN_OUTPUT_LOW, /* GBF_ENA_RESET */
+
+#ifdef CONFIG_MACH_U8500_SNOWBALL
+ /* WLAN/GBF */
+ GPIO215_GPIO | PIN_OUTPUT_LOW, /* WLAN_ENABLE */
+ GPIO216_GPIO | PIN_INPUT_PULLUP, /* WLAN_IRQ */
+ GPIO171_GPIO | PIN_OUTPUT_HIGH, /* GBF_ENA_RESET */
+#endif
+
+
+ /* MSP : HDTV INTERFACE */
+ GPIO192_GPIO | PIN_INPUT_PULLDOWN,
+
+ /* ACCELEROMETER_INTERFACE */
+ GPIO82_GPIO | PIN_INPUT_PULLUP, /* ACC_INT1 */
+ GPIO83_GPIO | PIN_INPUT_PULLUP, /* ACC_INT2 */
+
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ /* Proximity Sensor */
+ GPIO217_GPIO | PIN_INPUT_PULLUP,
+#endif
+ /* SD card detect */
+ GPIO95_GPIO | PIN_INPUT_PULLUP,
+};
+
+static pin_cfg_t u9500_21_pins[] = {
+ GPIO4_U1_RXD | PIN_INPUT_PULLUP,
+ GPIO5_U1_TXD | PIN_OUTPUT_HIGH,
+};
+
+static UX500_PINS(mop500_pins_uart0,
+ GPIO0_U0_CTSn | PIN_INPUT_PULLUP,
+ GPIO1_U0_RTSn | PIN_OUTPUT_HIGH,
+ GPIO2_U0_RXD | PIN_INPUT_PULLUP,
+ GPIO3_U0_TXD | PIN_OUTPUT_HIGH,
+);
+
+/*
+ * I2C
+ */
+
+static UX500_PINS(mop500_pins_i2c0,
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ GPIO147_I2C0_SCL,
+ GPIO148_I2C0_SDA,
+#endif
+);
+
+static UX500_PINS(mop500_pins_i2c1,
+ GPIO16_I2C1_SCL,
+ GPIO17_I2C1_SDA,
+);
+
+static UX500_PINS(mop500_pins_i2c2,
+ GPIO10_I2C2_SDA,
+ GPIO11_I2C2_SCL,
+);
+
+static UX500_PINS(mop500_pins_i2c3,
+ GPIO229_I2C3_SDA,
+ GPIO230_I2C3_SCL,
+);
+
+static UX500_PINS(mop500_pins_mcde_dpi,
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ GPIO64_LCDB_DE,
+ GPIO65_LCDB_HSO,
+ GPIO66_LCDB_VSO,
+ GPIO67_LCDB_CLK,
+ GPIO70_LCD_D0,
+ GPIO71_LCD_D1,
+ GPIO72_LCD_D2,
+ GPIO73_LCD_D3,
+ GPIO74_LCD_D4,
+ GPIO75_LCD_D5,
+ GPIO76_LCD_D6,
+ GPIO77_LCD_D7,
+ GPIO153_LCD_D24,
+ GPIO154_LCD_D25,
+ GPIO155_LCD_D26,
+ GPIO156_LCD_D27,
+ GPIO157_LCD_D28,
+ GPIO158_LCD_D29,
+ GPIO159_LCD_D30,
+ GPIO160_LCD_D31,
+ GPIO161_LCD_D32,
+ GPIO162_LCD_D33,
+ GPIO163_LCD_D34,
+ GPIO164_LCD_D35,
+ GPIO165_LCD_D36,
+ GPIO166_LCD_D37,
+ GPIO167_LCD_D38,
+ GPIO168_LCD_D39,
+#endif
+);
+
+static UX500_PINS(mop500_pins_mcde_tvout,
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ GPIO78_LCD_D8,
+ GPIO79_LCD_D9,
+ GPIO80_LCD_D10,
+ GPIO81_LCD_D11,
+ GPIO150_LCDA_CLK,
+#endif
+);
+
+static UX500_PINS(mop500_pins_ske,
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ GPIO153_KP_I7 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
+ GPIO154_KP_I6 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
+ GPIO155_KP_I5 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
+ GPIO156_KP_I4 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
+ GPIO161_KP_I3 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
+ GPIO162_KP_I2 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
+ GPIO163_KP_I1 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
+ GPIO164_KP_I0 | PIN_INPUT_PULLDOWN | PIN_SLPM_INPUT_PULLUP,
+ GPIO157_KP_O7 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
+ GPIO158_KP_O6 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
+ GPIO159_KP_O5 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
+ GPIO160_KP_O4 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
+ GPIO165_KP_O3 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
+ GPIO166_KP_O2 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
+ GPIO167_KP_O1 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
+ GPIO168_KP_O0 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW,
+#endif
+);
+
+/* sdi0 (removable MMC/SD/SDIO cards) */
+static UX500_PINS(mop500_pins_sdi0,
+ GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH,
+ GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH,
+ GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH,
+
+ GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL,
+ GPIO23_MC0_CLK | PIN_OUTPUT_LOW,
+ GPIO24_MC0_CMD | PIN_INPUT_PULLUP,
+ GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP,
+ GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP,
+ GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP,
+ GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP,
+);
+
+/* sdi1 (WLAN CW1200) */
+static UX500_PINS(mop500_pins_sdi1,
+ GPIO208_MC1_CLK | PIN_OUTPUT_LOW,
+ GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL,
+ GPIO210_MC1_CMD | PIN_INPUT_PULLUP,
+ GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP,
+ GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP,
+ GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP,
+ GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP,
+);
+
+/* sdi2 (POP eMMC) */
+static UX500_PINS(mop500_pins_sdi2,
+ GPIO128_MC2_CLK | PIN_OUTPUT_LOW,
+ GPIO129_MC2_CMD | PIN_INPUT_PULLUP,
+ GPIO130_MC2_FBCLK | PIN_INPUT_NOPULL,
+ GPIO131_MC2_DAT0 | PIN_INPUT_PULLUP,
+ GPIO132_MC2_DAT1 | PIN_INPUT_PULLUP,
+ GPIO133_MC2_DAT2 | PIN_INPUT_PULLUP,
+ GPIO134_MC2_DAT3 | PIN_INPUT_PULLUP,
+ GPIO135_MC2_DAT4 | PIN_INPUT_PULLUP,
+ GPIO136_MC2_DAT5 | PIN_INPUT_PULLUP,
+ GPIO137_MC2_DAT6 | PIN_INPUT_PULLUP,
+ GPIO138_MC2_DAT7 | PIN_INPUT_PULLUP,
+);
+
+/* sdi4 (PCB eMMC) */
+static UX500_PINS(mop500_pins_sdi4,
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP,
+ GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP,
+ GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP,
+ GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP,
+ GPIO201_MC4_CMD | PIN_INPUT_PULLUP,
+ GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL,
+ GPIO203_MC4_CLK | PIN_OUTPUT_LOW,
+ GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP,
+ GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP,
+ GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP,
+ GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP,
+#endif
+);
+
+static struct ux500_pin_lookup mop500_pins[] = {
+ PIN_LOOKUP("mcde-dpi", &mop500_pins_mcde_dpi),
+ PIN_LOOKUP("mcde-tvout", &mop500_pins_mcde_tvout),
+ PIN_LOOKUP("uart0", &mop500_pins_uart0),
+ PIN_LOOKUP("nmk-i2c.0", &mop500_pins_i2c0),
+ PIN_LOOKUP("nmk-i2c.1", &mop500_pins_i2c1),
+ PIN_LOOKUP("nmk-i2c.2", &mop500_pins_i2c2),
+ PIN_LOOKUP("nmk-i2c.3", &mop500_pins_i2c3),
+ PIN_LOOKUP("ske", &mop500_pins_ske),
+ PIN_LOOKUP("sdi0", &mop500_pins_sdi0),
+ PIN_LOOKUP("sdi1", &mop500_pins_sdi1),
+ PIN_LOOKUP("sdi2", &mop500_pins_sdi2),
+ PIN_LOOKUP("sdi4", &mop500_pins_sdi4),
+};
+
+/*
+ * This function is called to force gpio power save
+ * 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(void)
+{
+ u32 bankaddr;
+ u32 w_imsc;
+ u32 imsc;
+ u32 mask;
+
+ /*
+ * Apply HSI GPIO Config for DeepSleep
+ *
+ * Bank0
+ */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK0_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+ mask = 0;
+ if (machine_is_hrefv60())
+ /* Mask away pin 4 (0x10) which is WLAN_IRQ */
+ mask |= 0x10;
+
+ writel(0x409C702A & ~w_imsc & ~mask, bankaddr + NMK_GPIO_DIR);
+ writel(0x001C0022 & ~w_imsc & ~mask, bankaddr + NMK_GPIO_DATS);
+ writel(0x807000 & ~w_imsc & ~mask, bankaddr + NMK_GPIO_DATC);
+ writel(0x5FFFFFFF & ~w_imsc & ~imsc & ~mask, bankaddr + NMK_GPIO_PDIS);
+ writel(readl(bankaddr + NMK_GPIO_SLPC) & mask,
+ bankaddr + NMK_GPIO_SLPC);
+
+ /* Bank1 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK1_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+ writel(0x3 & ~w_imsc, bankaddr + NMK_GPIO_DIRS);
+ writel(0x1C , bankaddr + NMK_GPIO_DIRC);
+ writel(0x2 & ~w_imsc, bankaddr + NMK_GPIO_DATC);
+ writel(0xFFFFFFFF & ~w_imsc & ~imsc, bankaddr + NMK_GPIO_PDIS);
+ writel(0 , bankaddr + NMK_GPIO_SLPC);
+
+ /* Bank2 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK2_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+ mask = 0;
+ if (machine_is_hrefv60())
+ /* Mask away pin 85 (0x200000) which is WLAN_ENABLE */
+ mask |= 0x200000;
+
+ writel(0x3D7C0 & ~w_imsc & ~mask, bankaddr + NMK_GPIO_DIRS);
+ writel(0x803C2830 & ~mask, bankaddr + NMK_GPIO_DIRC);
+ writel(0x3D7C0 & ~w_imsc & ~mask, bankaddr + NMK_GPIO_DATC);
+ writel(0xFFFFFFFF & ~w_imsc & ~imsc & ~mask, bankaddr + NMK_GPIO_PDIS);
+ /*
+ * No need to set SLPC (SLPM) register. This can break modem STM
+ * settings on pins (70-76) because modem is special and needs to
+ * have its mux connected even in suspend because modem could still
+ * be on and might send interesting STM debugging data.
+ */
+
+ /* Bank3 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK3_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+ writel(0x3 & ~w_imsc, bankaddr + NMK_GPIO_DIRS);
+ writel(0x3 & ~w_imsc, bankaddr + NMK_GPIO_DATC);
+ writel(0xFFFFFFFF & ~w_imsc & ~imsc, bankaddr + NMK_GPIO_PDIS);
+ writel(0 , bankaddr + NMK_GPIO_SLPC);
+
+ /* Bank4 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK4_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+ writel(0x5E000 & ~w_imsc, bankaddr + NMK_GPIO_DIRS);
+ writel(0xFFDA1800 , bankaddr + NMK_GPIO_DIRC);
+ writel(0x4E000 & ~w_imsc, bankaddr + NMK_GPIO_DATC);
+ writel(0x10000 & ~w_imsc, bankaddr + NMK_GPIO_DATS);
+ writel(0xFFFFFFF9 & ~w_imsc & ~imsc, bankaddr + NMK_GPIO_PDIS);
+ writel(0 , bankaddr + NMK_GPIO_SLPC);
+
+ /* Bank5 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK5_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+
+ if (machine_is_hrefv60()) {
+ /* Make sure that camera pin 170 "XENON_CHARGE" is low */
+ writel(0x400 & ~w_imsc, bankaddr + NMK_GPIO_DIRS);
+ writel(0x400 & ~w_imsc, bankaddr + NMK_GPIO_DATC);
+ }
+
+ writel(0x3FF , bankaddr + NMK_GPIO_DIRC);
+ writel(0xFFFFFFFF & ~w_imsc & ~imsc, bankaddr + NMK_GPIO_PDIS);
+ writel(0 , bankaddr + NMK_GPIO_SLPC);
+
+ /* Bank6 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK6_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+ mask = 0;
+ if (!machine_is_hrefv60()) {
+ /* Mask away pin 215 (0x800000) which is WLAN_ENABLE */
+ mask |= 0x800000;
+
+ /* Mask away pin 216 (0x1000000) which is WLAN_IRQ */
+ mask |= 0x1000000;
+ }
+ /* Mask away pin 212 (0x100000) which is SDIO DAT1 */
+ mask |= 0x100000;
+
+ writel(0x8810810 & ~w_imsc & ~mask, bankaddr + NMK_GPIO_DIRS);
+ writel(0xF57EF7EF & ~mask, bankaddr + NMK_GPIO_DIRC);
+ writel(0x8810810 & ~w_imsc & ~mask, bankaddr + NMK_GPIO_DATC);
+ writel(0xFFFFFFFF & ~w_imsc & ~imsc & ~mask, bankaddr + NMK_GPIO_PDIS);
+ writel(readl(bankaddr + NMK_GPIO_SLPC) & mask,
+ bankaddr + NMK_GPIO_SLPC);
+
+
+ /* Bank7 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK7_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+ writel(0x1C & ~w_imsc, bankaddr + NMK_GPIO_DIRS);
+ writel(0x63 , bankaddr + NMK_GPIO_DIRC);
+ writel(0x18 & ~w_imsc, bankaddr + NMK_GPIO_DATC);
+ writel(0xFFFFFFFF & ~w_imsc & ~imsc, bankaddr + NMK_GPIO_PDIS);
+ writel(0 , bankaddr + NMK_GPIO_SLPC);
+
+ /* Bank8 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK8_BASE);
+
+ w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) |
+ readl(bankaddr + NMK_GPIO_FWIMSC);
+
+ imsc = readl(bankaddr + NMK_GPIO_RIMSC) |
+ readl(bankaddr + NMK_GPIO_FIMSC);
+
+ writel(0x2 & ~w_imsc, bankaddr + NMK_GPIO_DIRS);
+ writel(0xFF0 , bankaddr + NMK_GPIO_DIRC);
+ writel(0x2 & ~w_imsc, bankaddr + NMK_GPIO_DATS);
+ writel(0x2 & ~w_imsc & ~imsc, bankaddr + NMK_GPIO_PDIS);
+ writel(0 , bankaddr + NMK_GPIO_SLPC);
+}
+
+/*
+ * 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)
+{
+ u32 bankaddr;
+
+
+ /*
+ * Apply HSI GPIO Config for DeepSleep
+ *
+ * Bank0
+ */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK0_BASE);
+
+ writel(0xE0000000, bankaddr + NMK_GPIO_AFSLA);
+ writel(0xE0000000, bankaddr + NMK_GPIO_AFSLB);
+
+ /* Bank1 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK1_BASE);
+
+ writel(0x1 , bankaddr + NMK_GPIO_AFSLA);
+ writel(0x1 , bankaddr + NMK_GPIO_AFSLB);
+
+ /* Bank2 (Nothing needs to be done) */
+
+ /* Bank3 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK3_BASE);
+
+ writel(0 , bankaddr + NMK_GPIO_AFSLA);
+ writel(0 , bankaddr + NMK_GPIO_AFSLB);
+
+ /* Bank4 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK4_BASE);
+
+ writel(0x7FF , bankaddr + NMK_GPIO_AFSLA);
+ writel(0 , bankaddr + NMK_GPIO_AFSLB);
+
+ /* Bank5 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK5_BASE);
+
+ writel(0 , bankaddr + NMK_GPIO_AFSLA);
+ writel(0 , bankaddr + NMK_GPIO_AFSLB);
+
+ /* Bank6 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK6_BASE);
+
+ writel(0 , bankaddr + NMK_GPIO_AFSLA);
+ writel(0 , bankaddr + NMK_GPIO_AFSLB);
+
+ /* Bank7 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK7_BASE);
+
+ writel(0 , bankaddr + NMK_GPIO_AFSLA);
+ writel(0 , bankaddr + NMK_GPIO_AFSLB);
+
+ /* Bank8 */
+ bankaddr = IO_ADDRESS(U8500_GPIOBANK8_BASE);
+
+ writel(0 , bankaddr + NMK_GPIO_AFSLA);
+ writel(0 , bankaddr + NMK_GPIO_AFSLB);
+
+
+}
+
+/*
+ * passing "pinsfor=" in kernel cmdline allows for custom
+ * configuration of GPIOs on u8500 derived boards.
+ */
+static int __init early_pinsfor(char *p)
+{
+ pinsfor = PINS_FOR_DEFAULT;
+
+ if (strcmp(p, "u9500-21") == 0)
+ pinsfor = PINS_FOR_U9500_21;
+
+ return 0;
+}
+early_param("pinsfor", early_pinsfor);
+
+void __init mop500_pins_init(void)
+{
+ nmk_config_pins(mop500_pins_common,
+ ARRAY_SIZE(mop500_pins_common));
+
+
+ if (machine_is_hrefv60())
+ nmk_config_pins(mop500_pins_hrefv60,
+ ARRAY_SIZE(mop500_pins_hrefv60));
+ else
+ nmk_config_pins(mop500_pins_default,
+ ARRAY_SIZE(mop500_pins_default));
+
+ ux500_pins_add(mop500_pins, ARRAY_SIZE(mop500_pins));
+
+ switch (pinsfor) {
+ case PINS_FOR_U9500_21:
+ nmk_config_pins(u9500_21_pins, ARRAY_SIZE(u9500_21_pins));
+ break;
+
+ case PINS_FOR_DEFAULT:
+ default:
+ break;
+ }
+
+ suspend_set_pins_force_fn(mop500_pins_suspend_force,
+ mop500_pins_suspend_force_mux);
+}
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
new file mode 100644
index 00000000000..ce0c0b5accf
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -0,0 +1,1218 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ *
+ * MOP500 board specific initialization for regulators
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/regulator/machine.h>
+
+#include "board-mop500-regulators.h"
+#include "board-mop500-mcde.h"
+
+/*
+ * AB8500 Regulator Configuration
+ */
+
+/* ab8500 regulator register initialization */
+struct ab8500_regulator_reg_init
+ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
+ /*
+ * VanaRequestCtrl = HP/LP depending on VxRequest
+ * VpllRequestCtrl = HP/LP depending on VxRequest
+ * VextSupply1RequestCtrl = HP/LP depending on VxRequest
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0x00),
+ /*
+ * VextSupply2RequestCtrl = HP/LP depending on VxRequest
+ * VextSupply3RequestCtrl = HP/LP depending on VxRequest
+ * Vaux1RequestCtrl = HP/LP depending on VxRequest
+ * Vaux2RequestCtrl = HP/LP depending on VxRequest
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0x00),
+ /*
+ * Vaux3RequestCtrl = HP/LP depending on VxRequest
+ * SwHPReq = Control through SWValid disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x00),
+ /*
+ * Vsmps1SysClkReq1HPValid = enabled
+ * Vsmps2SysClkReq1HPValid = enabled
+ * Vsmps3SysClkReq1HPValid = enabled
+ * VanaSysClkReq1HPValid = disabled
+ * VpllSysClkReq1HPValid = enabled
+ * Vaux1SysClkReq1HPValid = disabled
+ * Vaux2SysClkReq1HPValid = disabled
+ * Vaux3SysClkReq1HPValid = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0x17),
+ /*
+ * VextSupply1SysClkReq1HPValid = disabled
+ * VextSupply2SysClkReq1HPValid = disabled
+ * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x40),
+ /*
+ * VanaHwHPReq1Valid = disabled
+ * Vaux1HwHPreq1Valid = disabled
+ * Vaux2HwHPReq1Valid = disabled
+ * Vaux3HwHPReqValid = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0x00),
+ /*
+ * VextSupply1HwHPReq1Valid = disabled
+ * VextSupply2HwHPReq1Valid = disabled
+ * VextSupply3HwHPReq1Valid = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x00),
+ /*
+ * VanaHwHPReq2Valid = disabled
+ * Vaux1HwHPReq2Valid = disabled
+ * Vaux2HwHPReq2Valid = disabled
+ * Vaux3HwHPReq2Valid = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0x00),
+ /*
+ * VextSupply1HwHPReq2Valid = disabled
+ * VextSupply2HwHPReq2Valid = disabled
+ * VextSupply3HwHPReq2Valid = HWReq2 controlled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x04),
+ /*
+ * VanaSwHPReqValid = disabled
+ * Vaux1SwHPReqValid = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0x00),
+ /*
+ * Vaux2SwHPReqValid = disabled
+ * Vaux3SwHPReqValid = disabled
+ * VextSupply1SwHPReqValid = disabled
+ * VextSupply2SwHPReqValid = disabled
+ * VextSupply3SwHPReqValid = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x00),
+ /*
+ * SysClkReq2Valid1 = SysClkReq2 controlled
+ * SysClkReq3Valid1 = disabled
+ * SysClkReq4Valid1 = SysClkReq4 controlled
+ * SysClkReq5Valid1 = disabled
+ * SysClkReq6Valid1 = SysClkReq6 controlled
+ * SysClkReq7Valid1 = disabled
+ * SysClkReq8Valid1 = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0x2a),
+ /*
+ * SysClkReq2Valid2 = disabled
+ * SysClkReq3Valid2 = disabled
+ * SysClkReq4Valid2 = disabled
+ * SysClkReq5Valid2 = disabled
+ * SysClkReq6Valid2 = SysClkReq6 controlled
+ * SysClkReq7Valid2 = disabled
+ * SysClkReq8Valid2 = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0x20),
+ /*
+ * VTVoutEna = disabled
+ * Vintcore12Ena = disabled
+ * Vintcore12Sel = 1.25 V
+ * Vintcore12LP = inactive (HP)
+ * VTVoutLP = inactive (HP)
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0x10),
+ /*
+ * VaudioEna = disabled
+ * VdmicEna = disabled
+ * Vamic1Ena = disabled
+ * Vamic2Ena = disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x00),
+ /*
+ * Vamic1_dzout = high-Z when Vamic1 is disabled
+ * Vamic2_dzout = high-Z when Vamic2 is disabled
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x00),
+ /*
+ * VBBN = force OFF
+ * VBBP = force OFF
+ * NOTE! PRCMU register
+ */
+ INIT_REGULATOR_REGISTER(AB8500_ARMREGU2, 0x00),
+ /*
+ * VBBNSel1 = VBBP = VBBPFB
+ * VBBPSel1 = 0 V
+ * NOTE! PRCMU register
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VBBSEL1, 0x00),
+ /*
+ * VBBNSel2 = VBBP = VBBPFB
+ * VBBPSel2 = 0 V
+ * NOTE! PRCMU register
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VBBSEL2, 0x00),
+ /*
+ * Vsmps1Regu = HW control
+ * Vsmps1SelCtrl = Vsmps1 voltage defined by Vsmsp1Sel2
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VSMPS1REGU, 0x06),
+ /*
+ * Vsmps2Regu = force HP
+ * Vsmps2SelCtrl = Vsmps2 voltage defined by Vsmsp2Sel2
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VSMPS2REGU, 0x05),
+ /*
+ * Vsmps3Sel2 = 1.2125 V
+ * NOTE! PRCMU register
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VSMPS3SEL2, 0x29),
+ /*
+ * Vsmps3Regu = HW control
+ * Vsmps3SelCtrl = Vsmps3 voltage defined by Vsmps3Sel2
+ * NOTE! PRCMU register
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VSMPS3REGU, 0x06),
+ /*
+ * Vsmps3Sel1 = 1.0 V
+ * NOTE! PRCMU register
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VSMPS3SEL1, 0x18),
+ /*
+ * VPll = Hw controlled
+ * VanaRegu = force off
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x02),
+ /*
+ * VrefDDREna = disabled
+ * VrefDDRSleepMode = inactive (no pulldown)
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x00),
+ /*
+ * VextSupply1Regu = HW control
+ * VextSupply2Regu = HW control
+ * VextSupply3Regu = Low Power mode
+ * ExtSupply2Bypass = ExtSupply12LPn ball is 0 when Ena is 0
+ * ExtSupply3Bypass = ExtSupply3LPn ball is 0 when Ena is 0
+ */
+ INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0x1a),
+ /*
+ * Vaux1Regu = force HP
+ * Vaux2Regu = force off
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x01),
+ /*
+ * Vrf1Regu = HW control
+ * Vaux3Regu = force off
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x08),
+ /*
+ * Vsmps1 = 1.15V
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VSMPS1SEL1, 0x24),
+ /*
+ * Vaux1Sel = 2.5 V
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x08),
+ /*
+ * Vaux2Sel = 2.9 V
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0d),
+ /*
+ * Vaux3Sel = 2.91 V
+ */
+ INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07),
+ /*
+ * VextSupply12LP = disabled (no LP)
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x00),
+ /*
+ * Vaux1Disch = short discharge time
+ * Vaux2Disch = short discharge time
+ * Vaux3Disch = short discharge time
+ * Vintcore12Disch = short discharge time
+ * VTVoutDisch = short discharge time
+ * VaudioDisch = short discharge time
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0x00),
+ /*
+ * VanaDisch = short discharge time
+ * VdmicPullDownEna = pulldown disabled when Vdmic is disabled
+ * VdmicDisch = short discharge time
+ */
+ INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x00),
+};
+
+/* vana regulator configuration, for analogue part of displays */
+static struct regulator_consumer_supply ab8500_vana_consumers[] = {
+ {
+ .dev_name = "mcde",
+ .supply = "v-ana",
+ },
+ {
+ .dev_name = "mmio_camera",
+ .supply = "v-ana",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.9",
+ .supply = "ana",
+ },
+#endif
+};
+
+#if defined(CONFIG_MACH_U8500_MOP) && (CONFIG_SENSORS1P_MOP)
+extern struct platform_device sensors1p_device;
+#endif
+
+/* vaux1 regulator configuration */
+static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
+ {
+ .dev = NULL,
+ .supply = "v-display",
+ },
+#if defined(CONFIG_MACH_U8500_MOP) && (CONFIG_SENSORS1P_MOP)
+ {
+ .dev = &sensors1p_device.dev,
+ .supply = "v-proximity",
+ },
+ {
+ .dev = &sensors1p_device.dev,
+ .supply = "v-hal",
+ },
+#endif
+#ifdef CONFIG_SENSORS_BH1780
+ {
+ .dev_name = "bh1780",
+ .supply = "v-als",
+ },
+#endif
+#ifdef CONFIG_SENSORS_LSM303DLH
+ {
+ .dev_name = "lsm303dlh.0",
+ .supply = "v-accel",
+ },
+ {
+ .dev_name = "lsm303dlh.1",
+ .supply = "v-mag",
+ },
+#endif
+#ifdef CONFIG_SENSORS_L3G4200D
+ {
+ .dev_name = "l3g4200d",
+ .supply = "v-gyro",
+ },
+#endif
+ {
+ .dev_name = "mmio_camera",
+ .supply = "v-mmio-camera",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.0",
+ .supply = "aux1",
+ },
+#endif
+ {
+ .dev_name = "3-005c",
+ .supply = "avdd",
+ },
+
+ {
+ .dev_name = "3-005d",
+ .supply = "avdd",
+ },
+ {
+ .dev_name = "3-004b",
+ .supply = "vdd",
+ },
+};
+
+/* vaux2 regulator configuration */
+static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
+ {
+ .dev_name = "sdi4",
+ .supply = "v-eMMC",
+ },
+ {
+ .dev_name = "ab8500-codec.0",
+ .supply = "vcc-avswitch",
+ },
+ {
+ .dev_name = "ab8500-acc-det.0",
+ .supply = "vcc-avswitch"
+ },
+#ifdef CONFIG_DISPLAY_AB8500_TERTIARY
+ {
+ .dev = &tvout_ab8500_display.dev,
+ .supply = "v-ab8500-AV-switch",
+ },
+#endif
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+ {
+ .dev = &av8100_hdmi.dev,
+ .supply = "v-av8100-AV-switch",
+ },
+#endif
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.1",
+ .supply = "aux2",
+ },
+#endif
+};
+
+/* vaux3 regulator configuration */
+static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
+ {
+ .dev_name = "sdi0",
+ .supply = "v-MMC-SD"
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.2",
+ .supply = "aux3",
+ },
+#endif
+};
+
+/* vtvout regulator configuration, supply for tvout, gpadc, TVOUT LDO */
+static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
+#ifdef CONFIG_DISPLAY_AB8500_TERTIARY
+ {
+ .dev = &tvout_ab8500_display.dev,
+ .supply = "v-tvout",
+ },
+#endif
+ {
+ .supply = "ab8500-gpadc",
+ },
+ {
+ .dev_name = "ab8500-charger.0",
+ .supply = "vddadc"
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.4",
+ .supply = "tvout",
+ },
+#endif
+};
+
+/* vaudio regulator configuration, supply for ab8500-vaudio, VAUDIO LDO */
+static struct regulator_consumer_supply ab8500_vaudio_consumers[] = {
+ {
+ .supply = "v-audio",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.5",
+ .supply = "audio",
+ },
+#endif
+};
+
+/* vamic1 regulator configuration */
+static struct regulator_consumer_supply ab8500_vamic1_consumers[] = {
+ {
+ .supply = "v-amic1",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.6",
+ .supply = "anamic1",
+ },
+#endif
+};
+
+/* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
+static struct regulator_consumer_supply ab8500_vamic2_consumers[] = {
+ {
+ .supply = "v-amic2",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.7",
+ .supply = "anamic2",
+ },
+#endif
+};
+
+/* supply for v-dmic, VDMIC LDO */
+static struct regulator_consumer_supply ab8500_vdmic_consumers[] = {
+ {
+ .supply = "v-dmic",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.8",
+ .supply = "dmic",
+ },
+#endif
+};
+
+/* supply for v-intcore12, VINTCORE12 LDO */
+static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
+ {
+ .supply = "v-intcore",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.3",
+ .supply = "intcore",
+ },
+#endif
+ {
+ .dev_name = "ab8500-usb.0",
+ .supply = "v-intcore",
+ },
+
+};
+
+/* supply for CG2900 */
+static struct regulator_consumer_supply ab8500_sysclkreq_2_consumers[] = {
+ {
+ .dev_name = "cg2900-uart.0",
+ .supply = "gbf_1v8",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.10",
+ .supply = "sysclkreq-2",
+ },
+#endif
+};
+
+/* supply for CW1200 */
+static struct regulator_consumer_supply ab8500_sysclkreq_4_consumers[] = {
+ {
+ .dev_name = "cw1200",
+ .supply = "wlan_1v8",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.11",
+ .supply = "sysclkreq-4",
+ },
+#endif
+};
+
+/*
+ * AB8500 regulators
+ */
+struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
+ /* supplies to the display/camera */
+ [AB8500_LDO_AUX1] = {
+ .constraints = {
+ .name = "ab8500-vaux1",
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ .boot_on = 1, /* must be on for display */
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
+ .consumer_supplies = ab8500_vaux1_consumers,
+ },
+ /* supplies to the on-board eMMC */
+ [AB8500_LDO_AUX2] = {
+ .constraints = {
+ .name = "ab8500-vaux2",
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
+ .consumer_supplies = ab8500_vaux2_consumers,
+ },
+ /* supply for VAUX3, supplies to SDcard slots */
+ [AB8500_LDO_AUX3] = {
+ .constraints = {
+ .name = "ab8500-vaux3",
+ .min_uV = 1100000,
+ .max_uV = 3300000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
+ .consumer_supplies = ab8500_vaux3_consumers,
+ },
+ /* supply for tvout, gpadc, TVOUT LDO */
+ [AB8500_LDO_TVOUT] = {
+ .constraints = {
+ .name = "ab8500-vtvout",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers),
+ .consumer_supplies = ab8500_vtvout_consumers,
+ },
+ /* supply for ab8500-vaudio, VAUDIO LDO */
+ [AB8500_LDO_AUDIO] = {
+ .constraints = {
+ .name = "ab8500-vaudio",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vaudio_consumers),
+ .consumer_supplies = ab8500_vaudio_consumers,
+ },
+ /* supply for v-anamic1 VAMic1-LDO */
+ [AB8500_LDO_ANAMIC1] = {
+ .constraints = {
+ .name = "ab8500-vamic1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers),
+ .consumer_supplies = ab8500_vamic1_consumers,
+ },
+ /* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
+ [AB8500_LDO_ANAMIC2] = {
+ .constraints = {
+ .name = "ab8500-vamic2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers),
+ .consumer_supplies = ab8500_vamic2_consumers,
+ },
+ /* supply for v-dmic, VDMIC LDO */
+ [AB8500_LDO_DMIC] = {
+ .constraints = {
+ .name = "ab8500-vdmic",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vdmic_consumers),
+ .consumer_supplies = ab8500_vdmic_consumers,
+ },
+ /* supply for v-intcore12, VINTCORE12 LDO */
+ [AB8500_LDO_INTCORE] = {
+ .constraints = {
+ .name = "ab8500-vintcore",
+ .min_uV = 1200000,
+ .max_uV = 1350000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
+ .consumer_supplies = ab8500_vintcore_consumers,
+ },
+ /* supply for U8500 CSI/DSI, VANA LDO */
+ [AB8500_LDO_ANA] = {
+ .constraints = {
+ .name = "ab8500-vana",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
+ .consumer_supplies = ab8500_vana_consumers,
+ },
+ /* sysclkreq 2 pin */
+ [AB8500_SYSCLKREQ_2] = {
+ .constraints = {
+ .name = "ab8500-sysclkreq-2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies =
+ ARRAY_SIZE(ab8500_sysclkreq_2_consumers),
+ .consumer_supplies = ab8500_sysclkreq_2_consumers,
+ },
+ /* sysclkreq 4 pin */
+ [AB8500_SYSCLKREQ_4] = {
+ .constraints = {
+ .name = "ab8500-sysclkreq-4",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies =
+ ARRAY_SIZE(ab8500_sysclkreq_4_consumers),
+ .consumer_supplies = ab8500_sysclkreq_4_consumers,
+ },
+};
+
+/*
+ * Power State Regulator Configuration
+ */
+#define U8500_VAPE_REGULATOR_MIN_VOLTAGE 1800000
+#define U8500_VAPE_REGULATOR_MAX_VOLTAGE 2000000
+
+/* vape regulator configuration */
+static struct regulator_consumer_supply u8500_vape_consumers[] = {
+ {
+ .supply = "v-ape",
+ },
+ {
+ .dev_name = "nmk-i2c.0",
+ .supply = "v-i2c",
+ },
+ {
+ .dev_name = "nmk-i2c.1",
+ .supply = "v-i2c",
+ },
+ {
+ .dev_name = "nmk-i2c.2",
+ .supply = "v-i2c",
+ },
+ {
+ .dev_name = "nmk-i2c.3",
+ .supply = "v-i2c",
+ },
+ {
+ .dev_name = "sdi0",
+ .supply = "v-mmc",
+ },
+ {
+ .dev_name = "sdi1",
+ .supply = "v-mmc",
+ },
+ {
+ .dev_name = "sdi2",
+ .supply = "v-mmc",
+ },
+ {
+ .dev_name = "sdi4",
+ .supply = "v-mmc",
+ },
+ {
+ .dev_name = "dma40.0",
+ .supply = "v-dma",
+ },
+ {
+ .dev_name = "ab8500-usb.0",
+ .supply = "v-ape",
+ },
+ {
+ .dev_name = "uart0",
+ .supply = "v-uart",
+ },
+ {
+ .dev_name = "uart1",
+ .supply = "v-uart",
+ },
+ {
+ .dev_name = "uart2",
+ .supply = "v-uart",
+ },
+ {
+ .dev_name = "nmk-ske-keypad",
+ .supply = "v-ape",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.12",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_vape_regulator = {
+ .constraints = {
+ .name = "u8500-vape",
+ .min_uV = U8500_VAPE_REGULATOR_MIN_VOLTAGE,
+ .max_uV = U8500_VAPE_REGULATOR_MAX_VOLTAGE,
+ .input_uV = 1, /* notional, for set_mode* */
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_DRMS |
+ REGULATOR_CHANGE_STATUS,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL |
+ REGULATOR_MODE_IDLE,
+ },
+ .consumer_supplies = u8500_vape_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_vape_consumers),
+};
+
+/* varm regulator_configuration */
+static struct regulator_consumer_supply u8500_varm_consumers[] = {
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.13",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_varm_regulator = {
+ .constraints = {
+ .name = "u8500-varm",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_varm_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_varm_consumers),
+};
+
+/* vmodem regulator configuration */
+static struct regulator_consumer_supply u8500_vmodem_consumers[] = {
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.14",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_vmodem_regulator = {
+ .constraints = {
+ .name = "u8500-vmodem",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_vmodem_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_vmodem_consumers),
+};
+
+/* vpll regulator configuration */
+static struct regulator_consumer_supply u8500_vpll_consumers[] = {
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.15",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_vpll_regulator = {
+ .constraints = {
+ .name = "u8500-vpll",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_vpll_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_vpll_consumers),
+};
+
+/* vsmps1 regulator configuration */
+static struct regulator_consumer_supply u8500_vsmps1_consumers[] = {
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.16",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_vsmps1_regulator = {
+ .constraints = {
+ .name = "u8500-vsmps1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_vsmps1_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_vsmps1_consumers),
+};
+
+/* vsmsp2 regulator configuration */
+static struct regulator_consumer_supply u8500_vsmps2_consumers[] = {
+ {
+ .dev_name = "ab8500-usb.0",
+ .supply = "musb_1v8",
+ },
+ {
+ .dev_name = "0-0070",
+ .supply = "hdmi_1v8",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.17",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_vsmps2_regulator = {
+ .constraints = {
+ .name = "u8500-vsmps2",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_vsmps2_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_vsmps2_consumers),
+};
+
+/* vsmps3 regulator configuration */
+static struct regulator_consumer_supply u8500_vsmps3_consumers[] = {
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.18",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_vsmps3_regulator = {
+ .constraints = {
+ .name = "u8500-vsmps3",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_vsmps3_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_vsmps3_consumers),
+};
+
+/* vrf1 regulator configuration */
+static struct regulator_consumer_supply u8500_vrf1_consumers[] = {
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.19",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_vrf1_regulator = {
+ .constraints = {
+ .name = "u8500-vrf1",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_vrf1_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_vrf1_consumers),
+};
+
+/*
+ * Power Domain Switch Configuration
+ */
+
+/* SVA MMDSP regulator switch */
+static struct regulator_consumer_supply u8500_svammdsp_consumers[] = {
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-sva-mmdsp",
+ },
+ {
+ .dev_name = "cm_control",
+ .supply = "sva-mmdsp",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.20",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_svammdsp_regulator = {
+ /* dependency to u8500-vape is handled outside regulator framework */
+ .constraints = {
+ .name = "u8500-sva-mmdsp",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_svammdsp_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_svammdsp_consumers),
+};
+
+/* SVA MMDSP retention regulator switch */
+static struct regulator_consumer_supply u8500_svammdspret_consumers[] = {
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-sva-mmdsp-ret",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.21",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_svammdspret_regulator = {
+ .constraints = {
+ .name = "u8500-sva-mmdsp-ret",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_svammdspret_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_svammdspret_consumers),
+};
+
+/* SVA pipe regulator switch */
+static struct regulator_consumer_supply u8500_svapipe_consumers[] = {
+ /* Add SVA pipe device supply here */
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-sva-pipe",
+ },
+ {
+ .dev_name = "cm_control",
+ .supply = "sva-pipe",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.22",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_svapipe_regulator = {
+ /* dependency to u8500-vape is handled outside regulator framework */
+ .constraints = {
+ .name = "u8500-sva-pipe",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_svapipe_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_svapipe_consumers),
+};
+
+/* SIA MMDSP regulator switch */
+static struct regulator_consumer_supply u8500_siammdsp_consumers[] = {
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-sia-mmdsp",
+ },
+ {
+ .dev_name = "cm_control",
+ .supply = "sia-mmdsp",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.23",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_siammdsp_regulator = {
+ /* dependency to u8500-vape is handled outside regulator framework */
+ .constraints = {
+ .name = "u8500-sia-mmdsp",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_siammdsp_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_siammdsp_consumers),
+};
+
+/* SIA MMDSP retention regulator switch */
+static struct regulator_consumer_supply u8500_siammdspret_consumers[] = {
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-sia-mmdsp-ret",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.24",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_siammdspret_regulator = {
+ .constraints = {
+ .name = "u8500-sia-mmdsp-ret",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_siammdspret_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_siammdspret_consumers),
+};
+
+/* SIA pipe regulator switch */
+static struct regulator_consumer_supply u8500_siapipe_consumers[] = {
+ /* Add SIA pipe device supply here */
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-sia-pipe",
+ },
+ {
+ .dev_name = "cm_control",
+ .supply = "sia-pipe",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.25",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_siapipe_regulator = {
+ /* dependency to u8500-vape is handled outside regulator framework */
+ .constraints = {
+ .name = "u8500-sia-pipe",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_siapipe_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_siapipe_consumers),
+};
+
+/* SGA regulator switch */
+static struct regulator_consumer_supply u8500_sga_consumers[] = {
+ /* Add SGA device supply here */
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-sga",
+ },
+ {
+ /*
+ * The Mali driver doesn't have access to the device when
+ * requesting the SGA regulator. Therefore only supply name.
+ */
+ .supply = "v-mali",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.26",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_sga_regulator = {
+ .supply_regulator = "u8500-vape",
+ .constraints = {
+ .name = "u8500-sga",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_sga_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_sga_consumers),
+};
+
+/* B2R2-MCDE regulator switch */
+static struct regulator_consumer_supply u8500_b2r2_mcde_consumers[] = {
+ {
+ .dev_name = "b2r2_bus",
+ .supply = "vsupply",
+ },
+ {
+ .dev_name = "mcde",
+ .supply = "vsupply",
+ },
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-b2r2",
+ },
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-mcde",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.27",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_b2r2_mcde_regulator = {
+ .supply_regulator = "u8500-vape",
+ .constraints = {
+ .name = "u8500-b2r2-mcde",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_b2r2_mcde_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_b2r2_mcde_consumers),
+};
+
+/* ESRAM1 and 2 regulator switch */
+static struct regulator_consumer_supply u8500_esram12_consumers[] = {
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-esram1",
+ },
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-esram2",
+ },
+ {
+ .dev_name = "cm_control",
+ .supply = "esram12",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.28",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_esram12_regulator = {
+ .supply_regulator = "u8500-vape",
+ .constraints = {
+ .name = "u8500-esram12",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_esram12_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_esram12_consumers),
+};
+
+/* ESRAM1 and 2 retention regulator switch */
+static struct regulator_consumer_supply u8500_esram12ret_consumers[] = {
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-esram1-ret",
+ },
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-esram2-ret",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.29",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_esram12ret_regulator = {
+ .constraints = {
+ .name = "u8500-esram12-ret",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_esram12ret_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_esram12ret_consumers),
+};
+
+/* ESRAM3 and 4 regulator switch */
+static struct regulator_consumer_supply u8500_esram34_consumers[] = {
+ {
+ .dev_name = "mcde",
+ .supply = "v-esram34",
+ },
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-esram3",
+ },
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-esram4",
+ },
+ {
+ .dev_name = "cm_control",
+ .supply = "esram34",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.30",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_esram34_regulator = {
+ .supply_regulator = "u8500-vape",
+ .constraints = {
+ .name = "u8500-esram34",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_esram34_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_esram34_consumers),
+};
+
+/* ESRAM3 and 4 retention regulator switch */
+static struct regulator_consumer_supply u8500_esram34ret_consumers[] = {
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-esram3-ret",
+ },
+ {
+ /* NOTE! This is a temporary supply for prcmu_set_hwacc */
+ .supply = "hwacc-esram4-ret",
+ },
+#ifdef CONFIG_U8500_REGULATOR_DEBUG
+ {
+ .dev_name = "reg-virt-consumer.31",
+ .supply = "test",
+ },
+#endif
+};
+
+struct regulator_init_data u8500_esram34ret_regulator = {
+ .constraints = {
+ .name = "u8500-esram34-ret",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u8500_esram34ret_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u8500_esram34ret_consumers),
+};
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.h b/arch/arm/mach-ux500/board-mop500-regulators.h
new file mode 100644
index 00000000000..5a4f9560b1e
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-regulators.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ *
+ * MOP500 board specific initialization for regulators
+ */
+
+#ifndef __BOARD_MOP500_REGULATORS_H
+#define __BOARD_MOP500_REGULATORS_H
+
+#include <linux/regulator/machine.h>
+#include <linux/regulator/ab8500.h>
+
+/* AB8500 regulators */
+extern struct ab8500_regulator_reg_init
+ ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS];
+extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS];
+
+/* U8500 specific regulators */
+extern struct regulator_init_data u8500_vape_regulator;
+extern struct regulator_init_data u8500_varm_regulator;
+extern struct regulator_init_data u8500_vmodem_regulator;
+extern struct regulator_init_data u8500_vpll_regulator;
+extern struct regulator_init_data u8500_vsmps1_regulator;
+extern struct regulator_init_data u8500_vsmps2_regulator;
+extern struct regulator_init_data u8500_vsmps3_regulator;
+extern struct regulator_init_data u8500_vrf1_regulator;
+
+/* U8500 specific regulator switches */
+extern struct regulator_init_data u8500_svammdsp_regulator;
+extern struct regulator_init_data u8500_svammdspret_regulator;
+extern struct regulator_init_data u8500_svapipe_regulator;
+extern struct regulator_init_data u8500_siammdsp_regulator;
+extern struct regulator_init_data u8500_siammdspret_regulator;
+extern struct regulator_init_data u8500_siapipe_regulator;
+extern struct regulator_init_data u8500_sga_regulator;
+extern struct regulator_init_data u8500_b2r2_mcde_regulator;
+extern struct regulator_init_data u8500_esram12_regulator;
+extern struct regulator_init_data u8500_esram12ret_regulator;
+extern struct regulator_init_data u8500_esram34_regulator;
+extern struct regulator_init_data u8500_esram34ret_regulator;
+
+#endif
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
new file mode 100644
index 00000000000..b1acb64ae54
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2010 ST-Ericsson
+ *
+ * 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/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/core.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <plat/ste_dma40.h>
+#include <plat/pincfg.h>
+#include <mach/devices.h>
+#include <mach/gpio.h>
+#include <mach/ste-dma40-db8500.h>
+
+#include "devices-db8500.h"
+#include "pins-db8500.h"
+#include "board-mop500.h"
+
+
+/*
+ * SDI0 (SD/MMC card)
+ */
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg sdi0_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg sdi0_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
+static void sdi0_configure(void)
+{
+ int ret;
+ int gpio[2];
+ if (machine_is_snowball()) {
+ gpio[0] = SNOWBALL_SDMMC_EN_GPIO;
+ gpio[1] = SNOWBALL_SDMMC_1V8_3V_GPIO;
+ } else if (machine_is_hrefv60()) {
+ gpio[0] = HREFV60_SDMMC_EN_GPIO;
+ gpio[1] = HREFV60_SDMMC_1V8_3V_GPIO;
+ } else {
+ gpio[0] = EGPIO_PIN_17;
+ gpio[1] = EGPIO_PIN_18;
+ }
+ ret = gpio_request(gpio[0], "level shifter enable");
+ if (!ret)
+ ret = gpio_request(gpio[1], "level shifter select");
+
+ if (ret) {
+ printk(KERN_WARNING "unable to config gpios for level shifter.\n");
+ return;
+ }
+
+ /* Select the default 2.9V and eanble level shifter */
+ gpio_direction_output(gpio[1], 0);
+ gpio_direction_output(gpio[0], 1);
+}
+
+static void sdi0_vdd_handler(struct device *dev, unsigned int vdd,
+ unsigned char power_mode)
+{
+ int gpio[2];
+
+ if (machine_is_snowball()) {
+ gpio[0] = SNOWBALL_SDMMC_EN_GPIO;
+ gpio[1] = SNOWBALL_SDMMC_1V8_3V_GPIO;
+ } else if (machine_is_hrefv60()) {
+ gpio[0] = HREFV60_SDMMC_EN_GPIO;
+ gpio[1] = HREFV60_SDMMC_1V8_3V_GPIO;
+ } else {
+ gpio[0] = EGPIO_PIN_17;
+ gpio[1] = EGPIO_PIN_18;
+ }
+ switch (power_mode) {
+ case MMC_POWER_UP:
+ case MMC_POWER_ON:
+ /*
+ * Level shifter voltage should depend on vdd to when deciding
+ * on either 1.8V or 2.9V. Once the decision has been made the
+ * level shifter must be disabled and re-enabled with a changed
+ * select signal in order to switch the voltage. Since there is
+ * no framework support yet for indicating 1.8V in vdd, use the
+ * default 2.9V.
+ */
+ gpio_direction_output(gpio[1], 0);
+ /* Enable level shifter */
+ gpio_direction_output(gpio[0], 1);
+ udelay(100);
+ break;
+ case MMC_POWER_OFF:
+ gpio_direction_output(gpio[1], 0);
+ /* Disable level shifter */
+ gpio_direction_output(gpio[0], 0);
+ break;
+ }
+}
+
+static struct mmci_platform_data mop500_sdi0_data = {
+ .vcc = "v-mmc",
+ .vcard = "v-MMC-SD",
+ .vdd_handler = sdi0_vdd_handler,
+ .disable = 50,
+ .f_max = 50000000,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_SD_HIGHSPEED |
+ MMC_CAP_MMC_HIGHSPEED |
+ MMC_CAP_DISABLE,
+ .gpio_wp = -1,
+ .sigdir = MMCI_ST_DIRFBCLK |
+ MMCI_ST_DIRCMD |
+ MMCI_ST_DIRDAT0 |
+ MMCI_ST_DIRDAT2,
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &sdi0_dma_cfg_rx,
+ .dma_tx_param = &sdi0_dma_cfg_tx,
+#endif
+};
+
+/*
+ * SDI1 (SDIO WLAN)
+ */
+static irqreturn_t sdio_irq(int irq, void *dev_id)
+{
+ struct mmc_host *host = dev_id;
+
+ /*
+ * Signal an sdio irq for the sdio client.
+ * If we are in suspend state the host has been claimed
+ * by the pm framework, which prevents any sdio request
+ * to be served until the host gets resumed and released.
+ */
+ mmc_signal_sdio_irq(host);
+
+ return IRQ_HANDLED;
+}
+
+static void sdio_config_irq(struct mmc_host *host,
+ bool cfg_as_dat1,
+ int irq_pin,
+ pin_cfg_t irq_dat1,
+ pin_cfg_t irq_gpio)
+{
+ /*
+ * If the pin mux switch or interrupt registration fails we're in deep
+ * trouble and there is no decent recovery.
+ */
+ if (!gpio_is_valid(irq_pin)) {
+ dev_err(mmc_dev(host),
+ "invalid irq pin (%d) for sdio irq\n", irq_pin);
+ return;
+ }
+
+ if (!cfg_as_dat1) {
+
+ /*
+ * SDIO irq shall be handled as a gpio irq. We configure the
+ * dat[1] as gpio and register a gpio irq handler.
+ */
+
+ if (nmk_config_pin(irq_gpio, 0))
+ dev_err(mmc_dev(host),
+ "err config irq gpio (%lu) for sdio irq\n",
+ irq_gpio);
+
+ /* We use threaded irq */
+ if (request_threaded_irq(gpio_to_irq(irq_pin),
+ NULL,
+ sdio_irq,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+ dev_driver_string(mmc_dev(host)),
+ host))
+ dev_err(mmc_dev(host),
+ "err request_threaded_irq for sdio irq\n");
+
+ /*
+ * Set the irq as a wakeup irq to be able to be woken up
+ * from the suspend state and thus trigger a resume of
+ * the system.
+ */
+ if (enable_irq_wake(gpio_to_irq(irq_pin)))
+ dev_err(mmc_dev(host),
+ "err enabling wakeup irq for sdio irq\n");
+
+ /*
+ * Workaround to fix PL180 hw-problem of missing sdio irqs.
+ * If the DAT1 line has been asserted low we signal an sdio
+ * irq.
+ */
+ if (gpio_request(irq_pin, dev_driver_string(mmc_dev(host))))
+ dev_err(mmc_dev(host),
+ "err requesting irq for sdio irq\n");
+
+ if (!gpio_get_value(irq_pin))
+ mmc_signal_sdio_irq(host);
+
+ gpio_free(irq_pin);
+
+ } else {
+
+ /*
+ * SDIO irq shall be handled as dat[1] irq by the mmci
+ * driver. Configure the gpio back into dat[1] and remove
+ * the gpio irq handler.
+ */
+ if (disable_irq_wake(gpio_to_irq(irq_pin)))
+ dev_err(mmc_dev(host),
+ "err disabling wakeup irq for sdio irq\n");
+
+ free_irq(gpio_to_irq(irq_pin), host);
+
+ if (nmk_config_pin(irq_dat1, 0))
+ dev_err(mmc_dev(host),
+ "err config irq dat1 (%lu) for sdio irq\n",
+ irq_dat1);
+
+ }
+}
+
+static void wakeup_handler_sdi1(struct mmc_host *host, bool wakeup)
+{
+ if (host->card && mmc_card_sdio(host->card) && host->sdio_irqs)
+ sdio_config_irq(host,
+ wakeup,
+ 212,
+ GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP,
+ GPIO212_GPIO | PIN_INPUT_PULLUP);
+}
+
+#ifdef CONFIG_STE_DMA40
+static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV32_SD_MM1_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg sdi1_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV32_SD_MM1_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
+static struct mmci_platform_data mop500_sdi1_data = {
+ .vcc = "v-mmc",
+ .disable = 50,
+ .ocr_mask = MMC_VDD_29_30,
+ .f_max = 50000000,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_DISABLE |
+ MMC_CAP_SDIO_IRQ |
+ MMC_CAP_BROKEN_SDIO_CMD53,
+ .pm_flags = MMC_PM_KEEP_POWER,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+ .wakeup_handler = wakeup_handler_sdi1,
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &sdi1_dma_cfg_rx,
+ .dma_tx_param = &sdi1_dma_cfg_tx,
+#endif
+};
+
+/*
+ * SDI2 (POPed eMMC)
+ */
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg sdi2_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV28_SD_MM2_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+static struct stedma40_chan_cfg sdi2_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
+static struct mmci_platform_data mop500_sdi2_data = {
+ .vcc = "v-mmc",
+ .disable = 50,
+ .ocr_mask = MMC_VDD_165_195,
+ .f_max = 50000000,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA |
+ MMC_CAP_DISABLE,
+ .pm_flags = MMC_PM_KEEP_POWER,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &sdi2_dma_cfg_rx,
+ .dma_tx_param = &sdi2_dma_cfg_tx,
+#endif
+};
+
+/*
+ * SDI4 (On-board eMMC)
+ */
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg sdi4_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV42_SD_MM4_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg sdi4_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
+static struct mmci_platform_data mop500_sdi4_data = {
+ .vcc = "v-mmc",
+ .vcard = "v-eMMC",
+ .disable = 50,
+ .f_max = 50000000,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED |
+ MMC_CAP_DISABLE,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &sdi4_dma_cfg_rx,
+ .dma_tx_param = &sdi4_dma_cfg_tx,
+#endif
+};
+
+static int __init mop500_sdi_init(void)
+{
+ /* POP eMMC on v1.0 has problems with high speed */
+ if (!cpu_is_u8500v10())
+ mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+
+ /* sdi2 on snowball is in ATL_B mode for FSMC (LAN) */
+ if (!machine_is_snowball())
+ db8500_add_sdi2(&mop500_sdi2_data);
+
+ db8500_add_sdi4(&mop500_sdi4_data);
+
+ sdi0_configure();
+ if (machine_is_snowball()) {
+ mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO;
+ mop500_sdi0_data.cd_invert = true;
+ mop500_sdi0_data.sigdir = 0;
+ } else if (machine_is_hrefv60())
+ mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+ else
+ mop500_sdi0_data.gpio_cd = EGPIO_PIN_3;
+
+ db8500_add_sdi0(&mop500_sdi0_data);
+ db8500_add_sdi1(&mop500_sdi1_data);
+
+ return 0;
+}
+
+fs_initcall(mop500_sdi_init);
diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c
new file mode 100644
index 00000000000..595677a87c1
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-stuib.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/lsm303dlh.h>
+#include <linux/l3g4200d.h>
+#include <plat/pincfg.h>
+#include "pins-db8500.h"
+
+#include <linux/input/lps001wp.h>
+
+#include "board-mop500.h"
+
+static struct lsm303dlh_platform_data __initdata lsm303dlh_pdata_st_uib = {
+ .name_a = "lsm303dlh.0",
+ .name_m = "lsm303dlh.1",
+ .axis_map_x = 0,
+ .axis_map_y = 1,
+ .axis_map_z = 2,
+ .negative_x = 1,
+ .negative_y = 1,
+ .negative_z = 0,
+};
+
+static struct l3g4200d_gyr_platform_data __initdata l3g4200d_pdata_u8500 = {
+ .name_gyr = "l3g4200d",
+ .axis_map_x = 1,
+ .axis_map_y = 0,
+ .axis_map_z = 2,
+ .negative_x = 0,
+ .negative_y = 0,
+ .negative_z = 1,
+};
+
+static struct lps001wp_prs_platform_data __initdata lps001wp_pdata = {
+ .poll_interval = 500,
+ .min_interval = 10,
+};
+
+static struct i2c_board_info __initdata mop500_i2c2_devices_st_uib[] = {
+ {
+ /* LSM303DLH Accelerometer */
+ I2C_BOARD_INFO("lsm303dlh_a", 0x18),
+ .platform_data = &lsm303dlh_pdata_st_uib,
+ },
+ {
+ /* LSM303DLH Magnetometer */
+ I2C_BOARD_INFO("lsm303dlh_m", 0x1E),
+ .platform_data = &lsm303dlh_pdata_st_uib,
+ },
+ {
+ /* L3G4200D Gyroscope */
+ I2C_BOARD_INFO("l3g4200d", 0x68),
+ .platform_data = &l3g4200d_pdata_u8500,
+ },
+ {
+ /* LSP001WM Barometer */
+ I2C_BOARD_INFO("lps001wp_prs_sysfs", 0x5C),
+ .platform_data = &lps001wp_pdata,
+ },
+};
+
+void __init mop500_stuib_init(void)
+{
+ if (machine_is_hrefv60()) {
+ lsm303dlh_pdata_st_uib.irq_a1 = HREFV60_ACCEL_INT1_GPIO;
+ lsm303dlh_pdata_st_uib.irq_a2 = HREFV60_ACCEL_INT2_GPIO;
+ lsm303dlh_pdata_st_uib.irq_m = HREFV60_MAGNET_DRDY_GPIO;
+ } else {
+ lsm303dlh_pdata_st_uib.irq_a1 = EGPIO_PIN_10;
+ lsm303dlh_pdata_st_uib.irq_a2 = EGPIO_PIN_11;
+ lsm303dlh_pdata_st_uib.irq_m = EGPIO_PIN_1;
+ }
+ mop500_uib_i2c_add(2, mop500_i2c2_devices_st_uib,
+ ARRAY_SIZE(mop500_i2c2_devices_st_uib));
+}
diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c
new file mode 100644
index 00000000000..01e047db40a
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/lsm303dlh.h>
+#include <linux/l3g4200d.h>
+#include <plat/pincfg.h>
+#include "pins-db8500.h"
+
+#include "board-mop500.h"
+
+/* For U8500 UIB */
+static struct lsm303dlh_platform_data __initdata lsm303dlh_pdata_u8500_uib = {
+ .name_a = "lsm303dlh.0",
+ .name_m = "lsm303dlh.1",
+ .axis_map_x = 1,
+ .axis_map_y = 0,
+ .axis_map_z = 2,
+ .negative_x = 1,
+ .negative_y = 1,
+ .negative_z = 1,
+};
+
+static struct l3g4200d_gyr_platform_data __initdata l3g4200d_pdata_u8500_uib = {
+ .name_gyr = "l3g4200d",
+ .axis_map_x = 1,
+ .axis_map_y = 0,
+ .axis_map_z = 2,
+ .negative_x = 0,
+ .negative_y = 0,
+ .negative_z = 1,
+};
+static struct i2c_board_info __initdata mop500_i2c2_devices_u8500_uib[] = {
+ {
+ /* LSM303DLH Accelerometer */
+ I2C_BOARD_INFO("lsm303dlh_a", 0x18),
+ .platform_data = &lsm303dlh_pdata_u8500_uib,
+ },
+ {
+ /* LSM303DLH Magnetometer */
+ I2C_BOARD_INFO("lsm303dlh_m", 0x1E),
+ .platform_data = &lsm303dlh_pdata_u8500_uib,
+ },
+ {
+ /* L3G4200D Gyroscope */
+ I2C_BOARD_INFO("l3g4200d", 0x68),
+ .platform_data = &l3g4200d_pdata_u8500_uib,
+ },
+};
+
+void __init mop500_u8500uib_init(void)
+{
+ if (machine_is_hrefv60()) {
+ lsm303dlh_pdata_u8500_uib.irq_a1 = HREFV60_ACCEL_INT1_GPIO;
+ lsm303dlh_pdata_u8500_uib.irq_a2 = HREFV60_ACCEL_INT2_GPIO;
+ lsm303dlh_pdata_u8500_uib.irq_m = HREFV60_MAGNET_DRDY_GPIO;
+ } else {
+ lsm303dlh_pdata_u8500_uib.irq_a1 = EGPIO_PIN_10;
+ lsm303dlh_pdata_u8500_uib.irq_a2 = EGPIO_PIN_11;
+ lsm303dlh_pdata_u8500_uib.irq_m = EGPIO_PIN_1;
+ }
+ mop500_uib_i2c_add(2, mop500_i2c2_devices_u8500_uib,
+ ARRAY_SIZE(mop500_i2c2_devices_u8500_uib));
+}
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
new file mode 100644
index 00000000000..c95ca380bd8
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-uib.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#define pr_fmt(fmt) "mop500-uib: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#include <mach/hardware.h>
+#include "board-mop500.h"
+
+enum mop500_uib {
+ STUIB,
+ U8500UIB,
+};
+
+struct uib {
+ const char *name;
+ const char *option;
+ void (*init)(void);
+};
+
+static struct uib __initdata mop500_uibs[] = {
+ [STUIB] = {
+ .name = "ST-UIB",
+ .option = "stuib",
+ .init = mop500_stuib_init,
+ },
+ [U8500UIB] = {
+ .name = "U8500-UIB",
+ .option = "u8500uib",
+ .init = mop500_u8500uib_init,
+ },
+};
+
+static struct uib __initdata *mop500_uib;
+
+static int __init mop500_uib_setup(char *str)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
+ struct uib *uib = &mop500_uibs[i];
+
+ if (!strcmp(str, uib->option)) {
+ mop500_uib = uib;
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(mop500_uibs))
+ pr_err("invalid uib= option (%s)\n", str);
+
+ return 1;
+}
+__setup("uib=", mop500_uib_setup);
+
+/*
+ * The UIBs are detected after the I2C host controllers are registered, so
+ * i2c_register_board_info() can't be used.
+ */
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info const *info,
+ unsigned n)
+{
+ struct i2c_adapter *adap;
+ struct i2c_client *client;
+ int i;
+
+ adap = i2c_get_adapter(busnum);
+ if (!adap) {
+ pr_err("failed to get adapter i2c%d\n", busnum);
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ client = i2c_new_device(adap, &info[i]);
+ if (!client)
+ pr_err("failed to register %s to i2c%d\n",
+ info[i].type, busnum);
+ }
+
+ i2c_put_adapter(adap);
+}
+
+static void __init __mop500_uib_init(struct uib *uib, const char *why)
+{
+ pr_info("%s (%s)\n", uib->name, why);
+ uib->init();
+}
+
+/*
+ * Detect the UIB attached based on the presence or absence of i2c devices.
+ */
+static int __init mop500_uib_init(void)
+{
+ struct uib *uib = mop500_uib;
+
+ if (ux500_is_svp() || !cpu_is_u8500())
+ return -ENODEV;
+
+ if (uib) {
+ __mop500_uib_init(uib, "from uib= boot argument");
+ return 0;
+ }
+
+ {
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ struct i2c_adapter *i2c0;
+ int ret;
+
+ i2c0 = i2c_get_adapter(0);
+ if (!i2c0) {
+ __mop500_uib_init(&mop500_uibs[STUIB],
+ "fallback, could not get i2c0");
+ return -ENODEV;
+ }
+
+ /* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
+ ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
+ I2C_SMBUS_QUICK, NULL);
+ i2c_put_adapter(i2c0);
+
+ if (ret == 0)
+ uib = &mop500_uibs[U8500UIB];
+ else
+#endif
+ uib = &mop500_uibs[STUIB];
+ }
+
+ __mop500_uib_init(uib, "detected");
+
+ return 0;
+}
+
+module_init(mop500_uib_init);
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index bb8d7b77181..95fb0871240 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -8,70 +8,740 @@
* published by the Free Software Foundation.
*
*/
+#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/interrupt.h>
#include <linux/platform_device.h>
-#include <linux/io.h>
#include <linux/amba/bus.h>
#include <linux/amba/pl022.h>
+#include <linux/interrupt.h>
#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/hsi/hsi.h>
+#include <linux/i2s/i2s.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/mfd/tc35892.h>
+#include <linux/i2c/lp5521.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/input/bu21013.h>
+#include <linux/ste_timed_vibra.h>
+#include <linux/mmio.h>
+#include <linux/cw1200-wlan.h>
+#include <linux/spi/stm_msp.h>
+#include <linux/leds_pwm.h>
+#include <linux/pwm_backlight.h>
+#include <linux/mfd/ab8500/denc.h>
+#include <linux/mfd/ab8500/ab8500-gpio.h>
+#include <linux/mfd/cg2900.h>
+
+#ifdef CONFIG_USB_ANDROID
+#include <linux/usb/android_composite.h>
+#endif
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
-#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+#include <plat/pincfg.h>
+#include <plat/ske.h>
#include <plat/i2c.h>
+#include <plat/ste_dma40.h>
-#include <mach/hardware.h>
+#include <mach/devices.h>
+#include <mach/sensors1p.h>
+#include <mach/ab8500-accdet.h>
+#include <mach/ste_audio_io.h>
#include <mach/setup.h>
+#include <mach/tc35893-keypad.h>
+#include <video/av8100.h>
#include <mach/devices.h>
+#include <mach/irqs.h>
+#include <mach/ste-dma40-db8500.h>
+#ifdef CONFIG_DB8500_MLOADER
+#include <mach/mloader-dbx500.h>
+#endif
+
+#include <sound/ux500_ab8500_ext.h>
+
+#include "devices-cg2900.h"
+#include "devices-db8500.h"
+#include "board-mop500-regulators.h"
+#include "regulator-u8500.h"
+#include "pins-db8500.h"
+#include "board-mop500-bm.h"
+#include "board-mop500.h"
+#include "pins.h"
+
+#define IRQ_KP 1 /*To DO*/
+
+#ifdef CONFIG_USB_ANDROID
+#define PUBLIC_ID_BACKUPRAM1 (U8500_BACKUPRAM1_BASE + 0x0FC0)
+#define USB_SERIAL_NUMBER_LEN 31
+#endif
+
+/*
+ * This variable holds the number of touchscreen (bu21013) enabled.
+ */
+static int cs_en_check;
+
+/*
+ * ux500 keymaps
+ *
+ * Organized row-wise as on the UIB, starting at the top-left
+ *
+ * we support two key layouts, specific to requirements. The first
+ * keylayout includes controls for power/volume a few generic keys;
+ * the second key layout contains the full numeric layout, enter/back/left
+ * buttons along with a "."(dot), specifically for connectivity testing
+ */
+static const unsigned int ux500_keymap[] = {
+#ifdef CONFIG_KEYLAYOUT_LAYOUT1
+ KEY(2, 5, KEY_END),
+ KEY(4, 1, KEY_HOME),
+ KEY(3, 5, KEY_VOLUMEDOWN),
+ KEY(1, 3, KEY_EMAIL),
+ KEY(5, 2, KEY_RIGHT),
+ KEY(5, 0, KEY_BACKSPACE),
+
+ KEY(0, 5, KEY_MENU),
+ KEY(7, 6, KEY_ENTER),
+ KEY(4, 5, KEY_0),
+ KEY(6, 7, KEY_DOT),
+ KEY(3, 4, KEY_UP),
+ KEY(3, 3, KEY_DOWN),
+
+ KEY(6, 4, KEY_SEND),
+ KEY(6, 2, KEY_BACK),
+ KEY(4, 2, KEY_VOLUMEUP),
+ KEY(5, 5, KEY_SPACE),
+ KEY(4, 3, KEY_LEFT),
+ KEY(3, 2, KEY_SEARCH),
+#else
+#ifdef CONFIG_KEYLAYOUT_LAYOUT2
+ KEY(2, 5, KEY_RIGHT),
+ KEY(4, 1, KEY_ENTER),
+ KEY(3, 5, KEY_MENU),
+ KEY(1, 3, KEY_3),
+ KEY(5, 2, KEY_6),
+ KEY(5, 0, KEY_9),
+
+ KEY(0, 5, KEY_UP),
+ KEY(7, 6, KEY_DOWN),
+ KEY(4, 5, KEY_0),
+ KEY(6, 7, KEY_2),
+ KEY(3, 4, KEY_5),
+ KEY(3, 3, KEY_8),
+
+ KEY(6, 4, KEY_LEFT),
+ KEY(6, 2, KEY_BACK),
+ KEY(4, 2, KEY_KPDOT),
+ KEY(5, 5, KEY_1),
+ KEY(4, 3, KEY_4),
+ KEY(3, 2, KEY_7),
+#else
+#warning "No keypad layout defined."
+#endif
+#endif
+};
+
+static struct matrix_keymap_data ux500_keymap_data = {
+ .keymap = ux500_keymap,
+ .keymap_size = ARRAY_SIZE(ux500_keymap),
+};
+
+/*
+ * STMPE1601
+ */
+static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
+ .debounce_ms = 64,
+ .scan_count = 8,
+ .no_autorepeat = true,
+ .keymap_data = &ux500_keymap_data,
+};
+
+static struct stmpe_platform_data stmpe1601_data = {
+ .id = 1,
+ .blocks = STMPE_BLOCK_KEYPAD,
+ .irq_trigger = IRQF_TRIGGER_FALLING,
+ .irq_base = MOP500_STMPE1601_IRQ(0),
+ .keypad = &stmpe1601_keypad_data,
+ .autosleep = true,
+ .autosleep_timeout = 1024,
+};
+
+/*
+ * Nomadik SKE keypad
+ */
+#define ROW_PIN_I0 164
+#define ROW_PIN_I1 163
+#define ROW_PIN_I2 162
+#define ROW_PIN_I3 161
+#define ROW_PIN_I4 156
+#define ROW_PIN_I5 155
+#define ROW_PIN_I6 154
+#define ROW_PIN_I7 153
+#define COL_PIN_O0 168
+#define COL_PIN_O1 167
+#define COL_PIN_O2 166
+#define COL_PIN_O3 165
+#define COL_PIN_O4 160
+#define COL_PIN_O5 159
+#define COL_PIN_O6 158
+#define COL_PIN_O7 157
+
+static int ske_kp_rows[] = {
+ ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
+ ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
+};
+static int ske_kp_cols[] = {
+ COL_PIN_O0, COL_PIN_O1, COL_PIN_O2, COL_PIN_O3,
+ COL_PIN_O4, COL_PIN_O5, COL_PIN_O6, COL_PIN_O7,
+};
+
+static bool ske_config;
+/*
+ * ske_set_gpio_row: request and set gpio rows
+ */
+static int ske_set_gpio_row(int gpio)
+{
+ int ret;
+
+ if (!ske_config) {
+ ret = gpio_request(gpio, "ske-kp");
+ if (ret < 0) {
+ pr_err("ske_set_gpio_row: gpio request failed\n");
+ return ret;
+ }
+ }
+
+ ret = gpio_direction_output(gpio, 1);
+ if (ret < 0) {
+ pr_err("ske_set_gpio_row: gpio direction failed\n");
+ gpio_free(gpio);
+ }
+
+ return ret;
+}
+
+/*
+ * ske_kp_init - enable the gpio configuration
+ */
+static int ske_kp_init(void)
+{
+ struct ux500_pins *pins;
+ int ret, i;
+
+ pins = ux500_pins_get("ske");
+ if (pins)
+ ux500_pins_enable(pins);
+
+ for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
+ ret = ske_set_gpio_row(ske_kp_rows[i]);
+ if (ret < 0) {
+ pr_err("ske_kp_init: failed init\n");
+ return ret;
+ }
+ }
+ if (!ske_config)
+ ske_config = true;
+
+ return 0;
+}
+
+static int ske_kp_exit(void)
+{
+ struct ux500_pins *pins;
+
+ pins = ux500_pins_get("ske");
+ if (pins)
+ ux500_pins_disable(pins);
+
+ return 0;
+}
+
+static struct ske_keypad_platform_data mop500_ske_keypad_data = {
+ .init = ske_kp_init,
+ .exit = ske_kp_exit,
+ .gpio_input_pins = ske_kp_rows,
+ .gpio_output_pins = ske_kp_cols,
+ .keymap_data = &ux500_keymap_data,
+ .no_autorepeat = true,
+ .krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */
+ .kcol = SKE_KPD_MAX_COLS,
+ .debounce_ms = 20, /* in timeout period */
+ .switch_delay = 200, /* in jiffies */
+};
+
+static struct av8100_platform_data av8100_plat_data = {
+ .irq = GPIO_TO_IRQ(192),
+ .reset = 196,
+#ifdef CONFIG_MACH_U8500_SNOWBALL
+ .inputclk_id = "sysclk",
+#else
+ .inputclk_id = "sysclk2",
+#endif
+ .regulator_pwr_id = "hdmi_1v8",
+ .alt_powerupseq = true,
+ .mclk_freq = 3, /* MCLK_RNG_31_38 */
+};
+
+/*
+ * TC35892 Expander
+ */
+
+#if defined(CONFIG_MFD_TC35892)
+static struct tc35892_gpio_platform_data tc35892_gpio_platform_data = {
+ .gpio_base = U8500_NR_GPIO,
+};
+
+static struct tc35892_platform_data tc35892_data = {
+ .gpio = &tc35892_gpio_platform_data,
+ .irq_base = MOP500_EGPIO_IRQ_BASE,
+};
+#endif
+
+static const unsigned int nuib_keymap[] = {
+ KEY(3, 1, KEY_END),
+ KEY(4, 1, KEY_HOME),
+ KEY(6, 4, KEY_VOLUMEDOWN),
+ KEY(4, 2, KEY_EMAIL),
+ KEY(3, 3, KEY_RIGHT),
+ KEY(2, 5, KEY_BACKSPACE),
+
+ KEY(6, 7, KEY_MENU),
+ KEY(5, 0, KEY_ENTER),
+ KEY(4, 3, KEY_0),
+ KEY(3, 4, KEY_DOT),
+ KEY(5, 2, KEY_UP),
+ KEY(3, 5, KEY_DOWN),
+
+ KEY(4, 5, KEY_SEND),
+ KEY(0, 5, KEY_BACK),
+ KEY(6, 2, KEY_VOLUMEUP),
+ KEY(1, 3, KEY_SPACE),
+ KEY(7, 6, KEY_LEFT),
+ KEY(5, 5, KEY_SEARCH),
+};
+
+static struct matrix_keymap_data nuib_keymap_data = {
+ .keymap = nuib_keymap,
+ .keymap_size = ARRAY_SIZE(nuib_keymap),
+};
+
+#if defined(CONFIG_KEYBOARD_TC35893)
+static struct tc35893_platform_data tc35893_data = {
+ .krow = TC_KPD_ROWS,
+ .kcol = TC_KPD_COLUMNS,
+ .debounce_period = TC_KPD_DEBOUNCE_PERIOD,
+ .settle_time = TC_KPD_SETTLE_TIME,
+ .irqtype = (IRQF_TRIGGER_FALLING),
+ .irq = GPIO_TO_IRQ(218),
+ .enable_wakeup = true,
+ .keymap_data = &nuib_keymap_data,
+ .no_autorepeat = true,
+};
+#endif
+
+static struct lp5521_platform_data lp5521_data = {
+ .mode = LP5521_MODE_DIRECT_CONTROL,
+ .label = "uib-led",
+ .red_present = true,
+ .green_present = true,
+ .blue_present = true,
+};
+
+/**
+ * Touch panel related platform specific initialization
+ */
+
+/**
+ * bu21013_gpio_board_init : configures the touch panel.
+ * @reset_pin: reset pin number
+ * This function can be used to configures
+ * the voltage and reset the touch panel controller.
+ */
+static int bu21013_gpio_board_init(int reset_pin)
+{
+ int retval = 0;
+
+ cs_en_check++;
+ if (cs_en_check == 1) {
+ retval = gpio_request(reset_pin, "touchp_reset");
+ if (retval) {
+ printk(KERN_ERR "Unable to request gpio reset_pin");
+ return retval;
+ }
+ retval = gpio_direction_output(reset_pin, 1);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: gpio direction failed\n",
+ __func__);
+ return retval;
+ }
+ gpio_set_value(reset_pin, 1);
+ }
+ return retval;
+}
+
+/**
+ * bu21013_gpio_board_exit : deconfigures the touch panel controller
+ * @reset_pin: reset pin number
+ * This function can be used to deconfigures the chip selection
+ * for touch panel controller.
+ */
+static int bu21013_gpio_board_exit(int reset_pin)
+{
+ int retval = 0;
+
+ if (cs_en_check == 1) {
+ retval = gpio_direction_output(reset_pin, 0);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: gpio direction failed\n",
+ __func__);
+ return retval;
+ }
+ gpio_set_value(reset_pin, 0);
+
+ gpio_free(reset_pin);
+ }
+ cs_en_check--;
+ return retval;
+}
-static void ab4500_spi_cs_control(u32 command)
+/**
+ * bu21013_read_pin_val : get the interrupt pin value
+ * This function can be used to get the interrupt pin value for touch panel
+ * controller.
+ */
+static int bu21013_read_pin_val(void)
{
- /* set the FRM signal, which is CS - TODO */
+ return gpio_get_value(TOUCH_GPIO_PIN);
}
-struct pl022_config_chip ab4500_chip_info = {
- .lbm = LOOPBACK_DISABLED,
- .com_mode = INTERRUPT_TRANSFER,
- .iface = SSP_INTERFACE_MOTOROLA_SPI,
- /* we can act as master only */
- .hierarchy = SSP_MASTER,
- .slave_tx_disable = 0,
- .endian_rx = SSP_RX_MSB,
- .endian_tx = SSP_TX_MSB,
- .data_size = SSP_DATA_BITS_24,
- .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM,
- .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC,
- .clk_phase = SSP_CLK_SECOND_EDGE,
- .clk_pol = SSP_CLK_POL_IDLE_HIGH,
- .cs_control = ab4500_spi_cs_control,
+static struct bu21013_platform_device tsc_plat_device = {
+ .cs_en = bu21013_gpio_board_init,
+ .cs_dis = bu21013_gpio_board_exit,
+ .irq_read_val = bu21013_read_pin_val,
+ .irq = GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+ .x_max_res = 480,
+ .y_max_res = 864,
+ .touch_x_max = TOUCH_XMAX,
+ .touch_y_max = TOUCH_YMAX,
+ .portrait = true,
+ .has_ext_clk = true,
+ .enable_ext_clk = false,
+#if CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE == 270
+ .x_flip = true,
+ .y_flip = false,
+#else
+ .x_flip = false,
+ .y_flip = true,
+#endif
+};
+
+static struct bu21013_platform_device tsc_cntl2_plat_device = {
+ .cs_en = bu21013_gpio_board_init,
+ .cs_dis = bu21013_gpio_board_exit,
+ .irq_read_val = bu21013_read_pin_val,
+ .irq = GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+ .x_max_res = 480,
+ .y_max_res = 864,
+ .touch_x_max = TOUCH_XMAX,
+ .touch_y_max = TOUCH_YMAX,
+ .portrait = true,
+ .has_ext_clk = true,
+ .enable_ext_clk = false,
+#if CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE == 270
+ .x_flip = true,
+ .y_flip = false,
+#else
+ .x_flip = false,
+ .y_flip = true,
+#endif
+};
+
+static struct ab3550_platform_data ab3550_plf_data = {
+ .irq = {
+ .base = 0,
+ .count = 0,
+ },
+ .dev_data = {
+ },
+ .dev_data_sz = {
+ },
+ .init_settings = NULL,
+ .init_settings_sz = 0,
};
-static struct spi_board_info u8500_spi_devices[] = {
+static struct i2c_board_info __initdata mop500_i2c0_devices[] = {
+#if defined(CONFIG_MFD_TC35892)
{
- .modalias = "ab8500",
- .controller_data = &ab4500_chip_info,
- .max_speed_hz = 12000000,
- .bus_num = 0,
- .chip_select = 0,
- .mode = SPI_MODE_0,
- .irq = IRQ_AB4500,
+
+ I2C_BOARD_INFO("tc35892", 0x42),
+ .platform_data = &tc35892_data,
+ .irq = GPIO_TO_IRQ(217),
+ },
+#endif
+ {
+ /* STMPE1601 on UIB */
+ I2C_BOARD_INFO("stmpe1601", 0x40),
+ .irq = NOMADIK_GPIO_TO_IRQ(218),
+ .platform_data = &stmpe1601_data,
+ .flags = I2C_CLIENT_WAKE, /* enable wakeup */
},
+#if defined(CONFIG_KEYBOARD_TC35893)
+ {
+ /* TC35893 keypad */
+ I2C_BOARD_INFO("tc35893-kp", 0x44),
+ .platform_data = &tc35893_data,
+ .flags = I2C_CLIENT_WAKE, /* enable wakeup */
+ },
+#endif
+ {
+ I2C_BOARD_INFO("av8100", 0x70),
+ .platform_data = &av8100_plat_data,
+ },
+ {
+ /* FIXME - address TBD, TODO */
+ I2C_BOARD_INFO("uib-kpd", 0x45),
+ },
+ {
+ /* Audio step-up */
+ I2C_BOARD_INFO("tps61052", 0x33),
+ }
+};
+static struct i2c_board_info __initdata mop500_i2c1_devices[] = {
+ {
+ /* GPS - Address TBD, FIXME */
+ I2C_BOARD_INFO("gps", 0x68),
+ },
+ {
+ /* AB3550 */
+ I2C_BOARD_INFO("ab3550", 0x4A),
+ .irq = -1,
+ .platform_data = &ab3550_plf_data,
+ }
+};
+static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
+ {
+ /* ST 3D accelerometer @ 0x3A(w),0x3B(r) */
+ I2C_BOARD_INFO("lis302dl", 0x1D),
+ },
+ {
+ /* ASAHI KASEI AK8974 magnetometer, addr TBD FIXME */
+ I2C_BOARD_INFO("ak8974", 0x1),
+ },
+#if defined(CONFIG_SENSORS_BH1780)
+ {
+ /* Rohm BH1780GLI ambient light sensor */
+ I2C_BOARD_INFO("bh1780", 0x29),
+ },
+#endif
+ {
+ /* RGB LED driver, there are 1st and 2nd, TODO */
+ I2C_BOARD_INFO("lp5521", 0x33),
+ .platform_data = &lp5521_data,
+ },
+};
+static struct i2c_board_info __initdata mop500_i2c3_devices[] = {
+ {
+ /* NFC - Address TBD, FIXME */
+ I2C_BOARD_INFO("nfc", 0x68),
+ },
+#if defined(CONFIG_TOUCHSCREEN_BU21013)
+ {
+ /* Touschscreen */
+ I2C_BOARD_INFO("bu21013_ts", 0x5C),
+ .platform_data = &tsc_plat_device,
+ },
+ {
+ /* Touschscreen */
+ I2C_BOARD_INFO("bu21013_ts", 0x5D),
+ .platform_data = &tsc_cntl2_plat_device,
+ },
+#endif
};
-static struct pl022_ssp_controller ssp0_platform_data = {
- .bus_id = 0,
- /* pl022 not yet supports dma */
- .enable_dma = 0,
- /* on this platform, gpio 31,142,144,214 &
- * 224 are connected as chip selects
- */
- .num_chipselect = 5,
+/*
+ * MSP-SPI
+ */
+
+#define NUM_MSP_CLIENTS 10
+
+static struct stm_msp_controller mop500_msp2_spi_data = {
+ .id = MSP_2_CONTROLLER,
+ .num_chipselect = NUM_MSP_CLIENTS,
+ .base_addr = U8500_MSP2_BASE,
+ .device_name = "msp2",
+};
+
+/*
+ * SSP
+ */
+
+#define NUM_SSP_CLIENTS 10
+
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg ssp0_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV8_SSP0_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV8_SSP0_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
+static struct pl022_ssp_controller mop500_ssp0_data = {
+ .bus_id = SSP_0_CONTROLLER,
+ .num_chipselect = NUM_SSP_CLIENTS,
+#ifdef CONFIG_STE_DMA40
+ .enable_dma = 1,
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &ssp0_dma_cfg_rx,
+ .dma_tx_param = &ssp0_dma_cfg_tx,
+#endif
+
+};
+
+#ifdef CONFIG_SENSORS1P_MOP
+static struct sensors1p_config sensors1p_config = {
+ /* SFH7741 */
+ .proximity = {
+ .startup_time = 120, /* ms */
+ .regulator = "v-proximity",
+ },
+ /* HED54XXU11 */
+ .hal = {
+ .startup_time = 100, /* Actually, I have no clue. */
+ .regulator = "v-hal",
+ },
+};
+
+struct platform_device sensors1p_device = {
+ .name = "sensors1p",
+ .dev = {
+ .platform_data = (void *)&sensors1p_config,
+ },
+};
+#endif
+#ifdef CONFIG_USB_ANDROID
+
+static char *usb_functions_adb[] = {
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+ "usb_mass_storage",
+#endif
+#ifdef CONFIG_USB_ANDROID_ECM
+ "cdc_ethernet",
+#endif
+#ifdef CONFIG_USB_ANDROID_RNDIS
+ "rndis",
+#endif
+#ifdef CONFIG_USB_ANDROID_ACM
+ "acm",
+#endif
+#ifdef CONFIG_USB_ANDROID_ADB
+ "adb",
+#endif
};
-#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
-static struct nmk_i2c_controller u8500_i2c##id##_data = { \
+static struct android_usb_product usb_products[] = {
+ {
+ .product_id = 0x2323,
+ .num_functions = ARRAY_SIZE(usb_functions_adb),
+ .functions = usb_functions_adb,
+ },
+};
+
+static struct android_usb_platform_data android_usb_pdata = {
+ .vendor_id = 0x04cc,
+ .product_id = 0x2323,
+ .version = 0x0100,
+ .product_name = "Android Phone",
+ .manufacturer_name = "ST-Ericsson",
+ .serial_number = "0123456789ABCDEF0123456789ABCDE",
+ .num_products = ARRAY_SIZE(usb_products),
+ .products = usb_products,
+ .num_functions = ARRAY_SIZE(usb_functions_adb),
+ .functions = usb_functions_adb,
+};
+
+static struct platform_device android_usb_device = {
+ .name = "android_usb",
+ .id = -1,
+ .dev = {
+ .platform_data = &android_usb_pdata,
+ },
+};
+
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+static struct usb_mass_storage_platform_data mass_storage_pdata = {
+ .nluns = 2,
+ .vendor = "ST-Ericsson",
+ .product = "Android Phone",
+ .release = 0x0100,
+};
+
+static struct platform_device usb_mass_storage_device = {
+ .name = "usb_mass_storage",
+ .id = -1,
+ .dev = {
+ .platform_data = &mass_storage_pdata,
+ },
+};
+#endif /* CONFIG_USB_ANDROID_MASS_STORAGE */
+
+#ifdef CONFIG_USB_ANDROID_ECM
+static struct usb_ether_platform_data usb_ecm_pdata = {
+ .ethaddr = {0x02, 0x11, 0x22, 0x33, 0x44, 0x55},
+ .vendorID = 0x04cc,
+ .vendorDescr = "ST Ericsson",
+};
+
+static struct platform_device usb_ecm_device = {
+ .name = "cdc_ethernet",
+ .id = -1,
+ .dev = {
+ .platform_data = &usb_ecm_pdata,
+ },
+};
+#endif /* CONFIG_USB_ANDROID_ECM */
+
+#ifdef CONFIG_USB_ANDROID_RNDIS
+static struct usb_ether_platform_data usb_rndis_pdata = {
+ .ethaddr = {0x01, 0x11, 0x22, 0x33, 0x44, 0x55},
+ .vendorID = 0x04cc,
+ .vendorDescr = "ST Ericsson",
+};
+
+static struct platform_device usb_rndis_device = {
+ .name = "rndis",
+ .id = -1,
+ .dev = {
+ .platform_data = &usb_rndis_pdata,
+ },
+};
+#endif /* CONFIG_USB_ANDROID_RNDIS */
+
+#endif /* CONFIG_USB_ANDROID */
+
+#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, t_out, _sm) \
+static struct nmk_i2c_controller mop500_i2c##id##_data = { \
/* \
* slave data setup time, which is \
* 250 ns,100ns,10ns which is 14,6,2 \
@@ -85,6 +755,8 @@ static struct nmk_i2c_controller u8500_i2c##id##_data = { \
.rft = _rft, \
/* std. mode operation */ \
.clk_freq = clk, \
+ /* Slave response timeout(ms) */\
+ .timeout = t_out, \
.sm = _sm, \
}
@@ -94,57 +766,822 @@ static struct nmk_i2c_controller u8500_i2c##id##_data = { \
* Tx & Rx FIFO threshold values as 1 and standard
* mode of operation
*/
-U8500_I2C_CONTROLLER(0, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
-U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
-U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
-U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD);
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+U8500_I2C_CONTROLLER(0, 0xe, 1, 8, 400000, 200, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 400000, 200, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(2, 0xe, 1, 8, 400000, 200, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(3, 0xe, 1, 8, 400000, 200, I2C_FREQ_MODE_FAST);
+#else
+U8500_I2C_CONTROLLER(0, 0xe, 1, 1, 400000, 500, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 400000, 500, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, 500, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 400000, 500, I2C_FREQ_MODE_FAST);
+#endif
+
+#ifdef CONFIG_HSI
+static struct hsi_board_info __initdata u8500_hsi_devices[] = {
+ {
+ .name = "hsi_char",
+ .hsi_id = 0,
+ .port = 0,
+ .tx_cfg = {
+ .mode = HSI_MODE_STREAM,
+ .channels = 2,
+ .speed = 100000,
+ {.arb_mode = HSI_ARB_RR},
+ },
+ .rx_cfg = {
+ .mode = HSI_MODE_STREAM,
+ .channels = 2,
+ .speed = 200000,
+ {.flow = HSI_FLOW_SYNC},
+ },
+ },
+ {
+ .name = "hsi_test",
+ .hsi_id = 0,
+ .port = 0,
+ .tx_cfg = {
+ .mode = HSI_MODE_FRAME,
+ .channels = 2,
+ .speed = 100000,
+ {.arb_mode = HSI_ARB_RR},
+ },
+ .rx_cfg = {
+ .mode = HSI_MODE_FRAME,
+ .channels = 2,
+ .speed = 200000,
+ {.flow = HSI_FLOW_SYNC},
+ },
+ },
+ {
+ .name = "cfhsi_v3_driver",
+ .hsi_id = 0,
+ .port = 0,
+ .tx_cfg = {
+ .mode = HSI_MODE_STREAM,
+ .channels = 2,
+ .speed = 20000,
+ {.arb_mode = HSI_ARB_RR},
+ },
+ .rx_cfg = {
+ .mode = HSI_MODE_STREAM,
+ .channels = 2,
+ .speed = 200000,
+ {.flow = HSI_FLOW_SYNC},
+ },
+ },
+};
+#endif
+
+#ifdef CONFIG_INPUT_AB8500_ACCDET
+static struct ab8500_accdet_platform_data ab8500_accdet_pdata = {
+ .btn_keycode = KEY_MEDIA,
+ .accdet1_dbth = ACCDET1_TH_1200mV | ACCDET1_DB_70ms,
+ .accdet2122_th = ACCDET21_TH_1000mV | ACCDET22_TH_1000mV,
+ .video_ctrl_gpio = AB8500_PIN_GPIO35,
+};
+#endif
+
+#ifdef CONFIG_AB8500_GPIO
+static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
+ .gpio_base = AB8500_PIN_GPIO1,
+/* #ifndef CONFIG_MACH_U8500_SNOWBALL */
+ .irq_base = MOP500_AB8500_VIR_GPIO_IRQ_BASE,
+/* #endif */
+ /* config_reg is the initial configuration of ab8500 pins.
+ * The pins can be configured as GPIO or alt functions based
+ * on value present in GpioSel1 to GpioSel6 and AlternatFunction
+ * register. This is the array of 7 configuration settings.
+ * One has to compile time decide these settings. Below is the
+ * explaination of these setting
+ * GpioSel1 = 0x07 => Pin GPIO1 (SysClkReq2)
+ * Pin GPIO2 (SysClkReq3)
+ * Pin GPIO3 (SysClkReq4)
+ * Pin GPIO4 (SysClkReq6) are configured as GPIO
+ * GpioSel2 = 0x1E => Pins GPIO10 to GPIO13 are configured as GPIO
+ * GpioSel3 = 0x80 => Pin GPIO24 (SysClkReq7) is configured as GPIO
+ * GpioSel4 = 0x01 => Pin GPIO25 (SysClkReq8) is configured as GPIO
+ * GpioSel5 = 0x7A => Pin GPIO36 (ApeSpiClk)
+ Pin GPIO37 (ApeSpiCSn)
+ Pin GPIO38 (ApeSpiDout)
+ Pin GPIO39 (ApeSpiDin) are configured as GPIO
+ * GpioSel6 = 0x02 => Pin GPIO42 (SysClkReq5) is configured as GPIO
+ * AlternaFunction = 0x00 => If Pins GPIO10 to 13 are not configured
+ * as GPIO then this register selectes the alternate fucntions
+ */
+ .config_reg = {0x0F, 0x1E, 0x80, 0x01,
+ 0x7A, 0x02, 0x00},
+};
+#endif
+
+#ifdef CONFIG_AB8500_DENC
+static struct ab8500_denc_platform_data ab8500_denc_pdata = {
+ .ddr_enable = true,
+ .ddr_little_endian = false,
+};
+#endif
+
+static struct regulator_init_data *u8500_regulators[U8500_NUM_REGULATORS] = {
+ [U8500_REGULATOR_VAPE] = &u8500_vape_regulator,
+ [U8500_REGULATOR_VARM] = &u8500_varm_regulator,
+/* #ifndef CONFIG_MACH_U8500_SNOWBALL */
+ [U8500_REGULATOR_VMODEM] = &u8500_vmodem_regulator,
+/* #endif */
+ [U8500_REGULATOR_VPLL] = &u8500_vpll_regulator,
+ [U8500_REGULATOR_VSMPS1] = &u8500_vsmps1_regulator,
+ [U8500_REGULATOR_VSMPS2] = &u8500_vsmps2_regulator,
+ [U8500_REGULATOR_VSMPS3] = &u8500_vsmps3_regulator,
+ [U8500_REGULATOR_VRF1] = &u8500_vrf1_regulator,
+ [U8500_REGULATOR_SWITCH_SVAMMDSP] = &u8500_svammdsp_regulator,
+ [U8500_REGULATOR_SWITCH_SVAMMDSPRET] = &u8500_svammdspret_regulator,
+ [U8500_REGULATOR_SWITCH_SVAPIPE] = &u8500_svapipe_regulator,
+ [U8500_REGULATOR_SWITCH_SIAMMDSP] = &u8500_siammdsp_regulator,
+ [U8500_REGULATOR_SWITCH_SIAMMDSPRET] = &u8500_siammdspret_regulator,
+ [U8500_REGULATOR_SWITCH_SIAPIPE] = &u8500_siapipe_regulator,
+ [U8500_REGULATOR_SWITCH_SGA] = &u8500_sga_regulator,
+ [U8500_REGULATOR_SWITCH_B2R2_MCDE] = &u8500_b2r2_mcde_regulator,
+ [U8500_REGULATOR_SWITCH_ESRAM12] = &u8500_esram12_regulator,
+ [U8500_REGULATOR_SWITCH_ESRAM12RET] = &u8500_esram12ret_regulator,
+ [U8500_REGULATOR_SWITCH_ESRAM34] = &u8500_esram34_regulator,
+ [U8500_REGULATOR_SWITCH_ESRAM34RET] = &u8500_esram34ret_regulator,
+};
+
+static struct platform_device u8500_regulator_dev = {
+ .name = "u8500-regulators",
+ .id = 0,
+ .dev = {
+ .platform_data = u8500_regulators,
+ },
+};
+
+static struct ab8500_audio_platform_data ab8500_audio_plat_data = {
+ .ste_gpio_altf_init = msp13_i2s_init,
+ .ste_gpio_altf_exit = msp13_i2s_exit,
+};
+
+/*
+ * NOTE! The regulator configuration below must be in exactly the same order as
+ * the regulator description in the driver, see drivers/regulator/ab8500.c
+ */
+static struct ab8500_platform_data ab8500_platdata = {
+ .irq_base = MOP500_AB8500_IRQ_BASE,
+ .pm_power_off = true,
+ .regulator_reg_init = ab8500_regulator_reg_init,
+ .num_regulator_reg_init = ARRAY_SIZE(ab8500_regulator_reg_init),
+ .regulator = ab8500_regulators,
+ .num_regulator = ARRAY_SIZE(ab8500_regulators),
+#ifdef CONFIG_AB8500_DENC
+ .denc = &ab8500_denc_pdata,
+#endif
+ .audio = &ab8500_audio_plat_data,
+ .battery = &ab8500_bm_data,
+ .charger = &ab8500_charger_plat_data,
+ .btemp = &ab8500_btemp_plat_data,
+ .fg = &ab8500_fg_plat_data,
+ .chargalg = &ab8500_chargalg_plat_data,
+#ifdef CONFIG_AB8500_GPIO
+ .gpio = &ab8500_gpio_pdata,
+#endif
+#ifdef CONFIG_INPUT_AB8500_ACCDET
+ .accdet = &ab8500_accdet_pdata,
+#endif
+};
+
+static struct resource ab8500_resources[] = {
+ [0] = {
+ .start = IRQ_DB8500_AB8500,
+ .end = IRQ_DB8500_AB8500,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device ux500_ab8500_device = {
+ .name = "ab8500-i2c",
+ .id = 0,
+ .dev = {
+ .platform_data = &ab8500_platdata,
+ },
+ .num_resources = 1,
+ .resource = ab8500_resources,
+};
+
+#ifdef CONFIG_MFD_CG2900
+#define CG2900_BT_ENABLE_GPIO 170
+#define CG2900_GBF_ENA_RESET_GPIO 171
+#define WLAN_PMU_EN_GPIO 226
+#define SNOWBALL_WLAN_PMU_EN_GPIO 161
+#define CG2900_BT_CTS_GPIO 0
+
+enum cg2900_gpio_pull_sleep cg2900_sleep_gpio[21] = {
+ CG2900_NO_PULL, /* GPIO 0: PTA_CONFX */
+ CG2900_PULL_DN, /* GPIO 1: PTA_STATUS */
+ CG2900_NO_PULL, /* GPIO 2: UART_CTSN */
+ CG2900_PULL_UP, /* GPIO 3: UART_RTSN */
+ CG2900_PULL_UP, /* GPIO 4: UART_TXD */
+ CG2900_NO_PULL, /* GPIO 5: UART_RXD */
+ CG2900_PULL_DN, /* GPIO 6: IOM_DOUT */
+ CG2900_NO_PULL, /* GPIO 7: IOM_FSC */
+ CG2900_NO_PULL, /* GPIO 8: IOM_CLK */
+ CG2900_NO_PULL, /* GPIO 9: IOM_DIN */
+ CG2900_PULL_DN, /* GPIO 10: PWR_REQ */
+ CG2900_PULL_DN, /* GPIO 11: HOST_WAKEUP */
+ CG2900_PULL_DN, /* GPIO 12: IIS_DOUT */
+ CG2900_NO_PULL, /* GPIO 13: IIS_WS */
+ CG2900_NO_PULL, /* GPIO 14: IIS_CLK */
+ CG2900_NO_PULL, /* GPIO 15: IIS_DIN */
+ CG2900_PULL_DN, /* GPIO 16: PTA_FREQ */
+ CG2900_PULL_DN, /* GPIO 17: PTA_RF_ACTIVE */
+ CG2900_NO_PULL, /* GPIO 18: NotConnected (J6428) */
+ CG2900_NO_PULL, /* GPIO 19: EXT_DUTY_CYCLE */
+ CG2900_NO_PULL, /* GPIO 20: EXT_FRM_SYNCH */
+};
+
+static struct platform_device ux500_cg2900_device = {
+ .name = "cg2900",
+};
+
+#ifdef CONFIG_MFD_CG2900_CHIP
+static struct platform_device ux500_cg2900_chip_device = {
+ .name = "cg2900-chip",
+ .dev = {
+ .parent = &ux500_cg2900_device.dev,
+ },
+};
+#endif /* CONFIG_MFD_CG2900_CHIP */
+
+#ifdef CONFIG_MFD_STLC2690_CHIP
+static struct platform_device ux500_stlc2690_chip_device = {
+ .name = "stlc2690-chip",
+ .dev = {
+ .parent = &ux500_cg2900_device.dev,
+ },
+};
+#endif /* CONFIG_MFD_STLC2690_CHIP */
-static struct amba_device *amba_devs[] __initdata = {
- &ux500_uart0_device,
- &ux500_uart1_device,
- &ux500_uart2_device,
- &u8500_ssp0_device,
+#ifdef CONFIG_MFD_CG2900_TEST
+static struct cg2900_platform_data cg2900_test_platform_data = {
+ .bus = HCI_VIRTUAL,
+ .gpio_sleep = cg2900_sleep_gpio,
};
-/* add any platform devices here - TODO */
+static struct platform_device ux500_cg2900_test_device = {
+ .name = "cg2900-test",
+ .dev = {
+ .parent = &ux500_cg2900_device.dev,
+ .platform_data = &cg2900_test_platform_data,
+ },
+};
+#endif /* CONFIG_MFD_CG2900_TEST */
+
+#ifdef CONFIG_MFD_CG2900_UART
+static struct resource cg2900_uart_resources_pre_v60[] = {
+ {
+ .start = CG2900_GBF_ENA_RESET_GPIO,
+ .end = CG2900_GBF_ENA_RESET_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "gbf_ena_reset",
+ },
+ {
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ .start = WLAN_PMU_EN_GPIO,
+ .end = WLAN_PMU_EN_GPIO,
+#else
+ .start = SNOWBALL_WLAN_PMU_EN_GPIO,
+ .end = SNOWBALL_WLAN_PMU_EN_GPIO,
+#endif
+ .flags = IORESOURCE_IO,
+ .name = "pmu_en",
+ },
+ {
+ .start = CG2900_BT_ENABLE_GPIO,
+ .end = CG2900_BT_ENABLE_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "bt_enable",
+ },
+ {
+ .start = CG2900_BT_CTS_GPIO,
+ .end = CG2900_BT_CTS_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "cts_gpio",
+ },
+ {
+ .start = GPIO_TO_IRQ(CG2900_BT_CTS_GPIO),
+ .end = GPIO_TO_IRQ(CG2900_BT_CTS_GPIO),
+ .flags = IORESOURCE_IRQ,
+ .name = "cts_irq",
+ },
+};
+
+static struct resource cg2900_uart_resources[] = {
+ {
+ .start = CG2900_GBF_ENA_RESET_GPIO,
+ .end = CG2900_GBF_ENA_RESET_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "gbf_ena_reset",
+ },
+ {
+ .start = WLAN_PMU_EN_GPIO,
+ .end = WLAN_PMU_EN_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "pmu_en",
+ },
+ {
+ .start = CG2900_BT_CTS_GPIO,
+ .end = CG2900_BT_CTS_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "cts_gpio",
+ },
+ {
+ .start = GPIO_TO_IRQ(CG2900_BT_CTS_GPIO),
+ .end = GPIO_TO_IRQ(CG2900_BT_CTS_GPIO),
+ .flags = IORESOURCE_IRQ,
+ .name = "cts_irq",
+ },
+};
+
+static pin_cfg_t cg2900_uart_enabled[] = {
+ GPIO0_U0_CTSn | PIN_INPUT_PULLUP,
+ GPIO1_U0_RTSn | PIN_OUTPUT_HIGH,
+ GPIO2_U0_RXD | PIN_INPUT_PULLUP,
+ GPIO3_U0_TXD | PIN_OUTPUT_HIGH
+};
+
+static pin_cfg_t cg2900_uart_disabled[] = {
+ GPIO0_GPIO | PIN_INPUT_PULLUP, /* CTS pull up. */
+ GPIO1_GPIO | PIN_OUTPUT_HIGH, /* RTS high-flow off. */
+ GPIO2_GPIO | PIN_INPUT_PULLUP, /* RX pull down. */
+ GPIO3_GPIO | PIN_OUTPUT_LOW /* TX low - break on. */
+};
+
+static struct cg2900_platform_data cg2900_uart_platform_data = {
+ .bus = HCI_UART,
+ .gpio_sleep = cg2900_sleep_gpio,
+ .uart = {
+ .n_uart_gpios = 4,
+ .uart_enabled = cg2900_uart_enabled,
+ .uart_disabled = cg2900_uart_disabled,
+ },
+};
+
+static struct platform_device ux500_cg2900_uart_device = {
+ .name = "cg2900-uart",
+ .dev = {
+ .platform_data = &cg2900_uart_platform_data,
+ .parent = &ux500_cg2900_device.dev,
+ },
+};
+#endif /* CONFIG_MFD_CG2900_UART */
+#endif /* CONFIG_MFD_CG2900 */
+
+#ifdef CONFIG_LEDS_PWM
+static struct led_pwm pwm_leds_data[] = {
+ [0] = {
+ .name = "lcd-backlight",
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .lth_brightness = 90,
+ .pwm_period_ns = 1023,
+ },
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY
+ [1] = {
+ .name = "sec-lcd-backlight",
+ .pwm_id = 2,
+ .max_brightness = 255,
+ .lth_brightness = 90,
+ .pwm_period_ns = 1023,
+ },
+#endif
+};
+
+
+
+static struct led_pwm_platform_data u8500_leds_data = {
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY
+ .num_leds = 2,
+#else
+ .num_leds = 1,
+#endif
+ .leds = pwm_leds_data,
+};
+
+static struct platform_device ux500_leds_device = {
+ .name = "leds_pwm",
+ .dev = {
+ .platform_data = &u8500_leds_data,
+ },
+};
+#endif
+
+#ifdef CONFIG_BACKLIGHT_PWM
+static struct platform_pwm_backlight_data u8500_backlight_data[] = {
+ [0] = {
+ .pwm_id = 1,
+ .max_brightness = 255,
+ .dft_brightness = 200,
+ .lth_brightness = 90,
+ .pwm_period_ns = 1023,
+ },
+ [1] = {
+ .pwm_id = 2,
+ .max_brightness = 255,
+ .dft_brightness = 200,
+ .lth_brightness = 90,
+ .pwm_period_ns = 1023,
+ },
+};
+
+static struct platform_device ux500_backlight_device[] = {
+ [0] = {
+ .name = "pwm-backlight",
+ .id = 0,
+ .dev = {
+ .platform_data = &u8500_backlight_data[0],
+ },
+ },
+ [1] = {
+ .name = "pwm-backlight",
+ .id = 1,
+ .dev = {
+ .platform_data = &u8500_backlight_data[1],
+ },
+ },
+};
+#endif
+
+/* Force feedback vibrator device */
+static struct platform_device ste_ff_vibra_device = {
+ .name = "ste_ff_vibra"
+};
+
+/* For details check ste_timed_vibra docbook */
+static struct ste_timed_vibra_platform_data ste_timed_vibra_plat_data = {
+ .boost_level = 100,
+ .boost_time = 40,
+ .on_level = 50,
+ .off_level = 50,
+ .off_time = 20,
+#ifdef CONFIG_SND_SOC_UX500_AB8500
+ .timed_vibra_control = ux500_ab8500_audio_pwm_vibra,
+#endif
+};
+
+/* Timed output vibrator device */
+static struct platform_device ste_timed_output_vibra_device = {
+ .name = "ste_timed_output_vibra",
+ .dev = {
+ .platform_data = &ste_timed_vibra_plat_data,
+ },
+};
+
+static struct wlan1200_platform_data hrefv60_plat_data = {
+ .gpio_irq = 4,
+ .gpio_enable = 85,
+};
+
+static struct wlan1200_platform_data hrefv50_plat_data = {
+ .gpio_irq = 216,
+ .gpio_enable = 215,
+};
+
+#define PRCC_K_SOFTRST_SET 0x18
+#define PRCC_K_SOFTRST_CLEAR 0x1C
+static struct ux500_pins *uart0_pins;
+static void ux500_pl011_reset(void)
+{
+ void __iomem *prcc_rst_set, *prcc_rst_clr;
+
+ prcc_rst_set = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE +
+ PRCC_K_SOFTRST_SET);
+ prcc_rst_clr = (void __iomem *)IO_ADDRESS(U8500_CLKRST1_BASE +
+ PRCC_K_SOFTRST_CLEAR);
+
+ /* Activate soft reset PRCC_K_SOFTRST_CLEAR */
+ writel((readl(prcc_rst_clr) | 0x1), prcc_rst_clr);
+ udelay(1);
+
+ /* Release soft reset PRCC_K_SOFTRST_SET */
+ writel((readl(prcc_rst_set) | 0x1), prcc_rst_set);
+ udelay(1);
+}
+
+static void ux500_pl011_init(void)
+{
+ int ret;
+
+ if (!uart0_pins) {
+ uart0_pins = ux500_pins_get("uart0");
+ if (!uart0_pins) {
+ pr_err("pl011: uart0 pins_get failed\n");
+ return;
+ }
+ }
+
+ ret = ux500_pins_enable(uart0_pins);
+ if (ret)
+ pr_err("pl011: uart0 pins_enable failed\n");
+}
+
+static void ux500_pl011_exit(void)
+{
+ int ret;
+
+ if (uart0_pins) {
+ ret = ux500_pins_disable(uart0_pins);
+ if (ret)
+ pr_err("pl011: uart0 pins_disable failed\n");
+ }
+}
+
+static struct uart_amba_plat_data ux500_pl011_pdata = {
+ .init = ux500_pl011_init,
+ .exit = ux500_pl011_exit,
+ .reset = ux500_pl011_reset,
+};
+
+static struct platform_device *u8500_platform_devices[] __initdata = {
+ /*TODO - add platform devices here */
+#ifdef CONFIG_SENSORS1P_MOP
+ &sensors1p_device,
+#endif
+#ifdef CONFIG_LEDS_PWM
+ &ux500_leds_device,
+#endif
+#ifdef CONFIG_BACKLIGHT_PWM
+ &ux500_backlight_device[0],
+ &ux500_backlight_device[1],
+#endif
+#ifdef CONFIG_STM_TRACE
+ &ux500_stm_device,
+#endif
+};
static struct platform_device *platform_devs[] __initdata = {
- &u8500_i2c0_device,
- &ux500_i2c1_device,
- &ux500_i2c2_device,
- &ux500_i2c3_device,
+ &u8500_shrm_device,
+ &ste_ff_vibra_device,
+ &ste_timed_output_vibra_device,
+#ifdef CONFIG_U8500_MMIO
+ &ux500_mmio_device,
+#endif
+ &ux500_musb_device,
+ &ux500_hwmem_device,
+ &ux500_mcde_device,
+ &ux500_b2r2_device,
+ &u8500_thsens_device,
+#ifdef CONFIG_STE_TRACE_MODEM
+ &u8500_trace_modem,
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+ &u8500_pmem_hwb_device,
+#endif
+#ifdef CONFIG_CRYPTO_DEV_UX500_HASH
+ &ux500_hash1_device,
+#endif
+ &ux500_cryp1_device,
+#ifdef CONFIG_USB_ANDROID
+ &android_usb_device,
+#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
+ &usb_mass_storage_device,
+#endif
+#ifdef CONFIG_USB_ANDROID_ECM
+ &usb_ecm_device,
+#endif
+#ifdef CONFIG_USB_ANDROID_RNDIS
+ &usb_rndis_device,
+#endif
+#endif
+#ifdef CONFIG_DB8500_MLOADER
+ &mloader_fw_device,
+#endif
+#ifdef CONFIG_HSI
+ &u8500_hsi_device,
+#endif
};
-static void __init u8500_init_machine(void)
+static void __init mop500_i2c_init(void)
+{
+ db8500_add_i2c0(&mop500_i2c0_data);
+ db8500_add_i2c1(&mop500_i2c1_data);
+ db8500_add_i2c2(&mop500_i2c2_data);
+ db8500_add_i2c3(&mop500_i2c3_data);
+
+ i2c_register_board_info(0, ARRAY_AND_SIZE(mop500_i2c0_devices));
+ i2c_register_board_info(1, ARRAY_AND_SIZE(mop500_i2c1_devices));
+ i2c_register_board_info(2, ARRAY_AND_SIZE(mop500_i2c2_devices));
+ i2c_register_board_info(3, ARRAY_AND_SIZE(mop500_i2c3_devices));
+}
+
+static void __init mop500_spi_init(void)
+{
+ db8500_add_ssp0(&mop500_ssp0_data);
+ db8500_add_msp2_spi(&mop500_msp2_spi_data);
+}
+
+static void __init mop500_uart_init(void)
{
- int i;
+ db8500_add_uart0(&ux500_pl011_pdata);
+ db8500_add_uart1();
+ db8500_add_uart2();
+}
+
+#ifdef CONFIG_USB_ANDROID
+/*
+ * Public Id is a Unique number for each board and is stored
+ * in Backup RAM at address 0x80151FC0, ..FC4, FC8, FCC and FD0.
+ *
+ * This function reads the Public Ids from this address and returns
+ * a single string, which can be used as serial number for USB.
+ * Input parameter - serial_number should be of 'len' bytes long
+*/
+static void fetch_usb_serial_no(int len)
+{
+ u32 buf[5];
+ void __iomem *backup_ram = NULL;
+
+ if (len > strlen(android_usb_pdata.serial_number)) {
+ printk(KERN_ERR "$$ serial number is too long! truncating\n");
+ len = strlen(android_usb_pdata.serial_number);
+ }
+
+ backup_ram = ioremap(PUBLIC_ID_BACKUPRAM1, 0x14);
+
+ if (backup_ram) {
+ buf[0] = readl(backup_ram);
+ buf[1] = readl(backup_ram + 4);
+ buf[2] = readl(backup_ram + 8);
+ buf[3] = readl(backup_ram + 0x0c);
+ buf[4] = readl(backup_ram + 0x10);
+
+ snprintf(android_usb_pdata.serial_number, len+1,
+ "%.8X%.8X%.8X%.8X%.8X",
+ buf[0], buf[1], buf[2], buf[3], buf[4]);
+ iounmap(backup_ram);
+ } else {
+ printk(KERN_ERR "$$ ioremap failed\n");
+ }
+}
+#endif
- u8500_i2c0_device.dev.platform_data = &u8500_i2c0_data;
- ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data;
- ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data;
- ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data;
+static void device_gpio_cfg(void)
+{
+ if (machine_is_hrefv60()) {
+ tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
+ tsc_cntl2_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
+#ifdef CONFIG_SENSORS1P_MOP
+ sensors1p_config.proximity.pin = HREFV60_PROX_SENSE_GPIO;
+ sensors1p_config.hal.pin = HREFV60_HAL_SW_GPIO;
+#endif
+ } else {
+ tsc_plat_device.cs_pin = EGPIO_PIN_13;
+ tsc_cntl2_plat_device.cs_pin = EGPIO_PIN_13;
+#ifdef CONFIG_SENSORS1P_MOP
+ sensors1p_config.proximity.pin = EGPIO_PIN_7;
+ sensors1p_config.hal.pin = EGPIO_PIN_8;
+#endif
+ }
+}
- u8500_ssp0_device.dev.platform_data = &ssp0_platform_data;
+static void cw1200_gpio_cfg(void)
+{
+ if (machine_is_hrefv60())
+ wlan1200_set_platdata(&hrefv60_plat_data);
+ else
+ wlan1200_set_platdata(&hrefv50_plat_data);
+}
- /* Register the active AMBA devices on this board */
- for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
- amba_device_register(amba_devs[i], &iomem_resource);
+/*
+ * On boards hrefpv60 and later, the accessory insertion/removal,
+ * button press/release are inverted.
+*/
+static void accessory_detect_config(void)
+{
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ if (machine_is_hrefv60())
+ ab8500_accdet_pdata.is_detection_inverted = true;
+ else
+ ab8500_accdet_pdata.is_detection_inverted = false;
+#endif
+}
- platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+static void __init mop500_init_machine(void)
+{
+ device_gpio_cfg();
+ cw1200_gpio_cfg();
+ accessory_detect_config();
- spi_register_board_info(u8500_spi_devices,
- ARRAY_SIZE(u8500_spi_devices));
+#ifdef CONFIG_REGULATOR
+ platform_device_register(&u8500_regulator_dev);
+#endif
u8500_init_devices();
+
+#ifdef CONFIG_USB_ANDROID
+ fetch_usb_serial_no(USB_SERIAL_NUMBER_LEN);
+#endif
+
+ platform_add_devices(platform_devs,
+ ARRAY_SIZE(platform_devs));
+
+ mop500_pins_init();
+
+ platform_device_register(&ux500_ab8500_device);
+
+#ifdef CONFIG_MFD_CG2900
+#ifdef CONFIG_MFD_CG2900_TEST
+ dcg2900_init_platdata(&cg2900_test_platform_data);
+#endif /* CONFIG_MFD_CG2900_TEST */
+#ifdef CONFIG_MFD_CG2900_UART
+ dcg2900_init_platdata(&cg2900_uart_platform_data);
+#endif /* CONFIG_MFD_CG2900_UART */
+
+ platform_device_register(&ux500_cg2900_device);
+#ifdef CONFIG_MFD_CG2900_UART
+ if (machine_is_hrefv60()) {
+ ux500_cg2900_uart_device.num_resources =
+ ARRAY_SIZE(cg2900_uart_resources);
+ ux500_cg2900_uart_device.resource =
+ cg2900_uart_resources;
+ } else {
+ ux500_cg2900_uart_device.num_resources =
+ ARRAY_SIZE(cg2900_uart_resources_pre_v60);
+ ux500_cg2900_uart_device.resource =
+ cg2900_uart_resources_pre_v60;
+ }
+
+ platform_device_register(&ux500_cg2900_uart_device);
+#endif /* CONFIG_MFD_CG2900_UART */
+#ifdef CONFIG_MFD_CG2900_TEST
+ platform_device_register(&ux500_cg2900_test_device);
+#endif /* CONFIG_MFD_CG2900_TEST */
+#ifdef CONFIG_MFD_CG2900_CHIP
+ platform_device_register(&ux500_cg2900_chip_device);
+#endif /* CONFIG_MFD_CG2900_CHIP */
+#ifdef CONFIG_MFD_STLC2690_CHIP
+ platform_device_register(&ux500_stlc2690_chip_device);
+#endif /* CONFIG_MFD_STLC2690_CHIP */
+#endif /* CONFIG_MFD_CG2900 */
+
+ mop500_i2c_init();
+ mop500_msp_init();
+ mop500_spi_init();
+ mop500_uart_init();
+
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+ db8500_add_ske_keypad(&mop500_ske_keypad_data);
+#endif
+
+#ifdef CONFIG_HSI
+ hsi_register_board_info(u8500_hsi_devices,
+ ARRAY_SIZE(u8500_hsi_devices));
+#endif
+
+#ifdef CONFIG_MOP500_NUIB
+ mop500_nuib_init();
+#endif
+ platform_add_devices(u8500_platform_devices,
+ ARRAY_SIZE(u8500_platform_devices));
}
-MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
- /* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
+#ifndef CONFIG_MACH_U8500_SNOWBALL
+MACHINE_START(U8500, "ST-Ericsson U8500 Platform")
+ /* Maintainer: ST-Ericsson */
+ .phys_io = U8500_UART2_BASE,
+ .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = u8500_map_io,
+ .init_irq = ux500_init_irq,
+ .timer = &u8500_timer,
+ .init_machine = mop500_init_machine,
+MACHINE_END
+#else
+MACHINE_START(SNOWBALL, "ST-Ericsson Snowball board")
+ .phys_io = U8500_UART2_BASE,
+ .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = u8500_map_io,
+ .init_irq = ux500_init_irq,
+ .timer = &u8500_timer,
+ .init_machine = mop500_init_machine,
+MACHINE_END
+#endif
+
+MACHINE_START(NOMADIK, "ST-Ericsson U8500 Platform")
+ /* Maintainer: ST-Ericsson */
+ .phys_io = U8500_UART2_BASE,
+ .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = u8500_map_io,
+ .init_irq = ux500_init_irq,
+ .timer = &u8500_timer,
+ .init_machine = mop500_init_machine,
+MACHINE_END
+
+MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
+ /* Maintainer: ST-Ericsson */
.phys_io = U8500_UART2_BASE,
.io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
- .boot_params = 0x100,
+ .boot_params = 0x00000100,
.map_io = u8500_map_io,
.init_irq = ux500_init_irq,
- /* we re-use nomadik timer here */
- .timer = &ux500_timer,
- .init_machine = u8500_init_machine,
+ .timer = &u8500_timer,
+ .init_machine = mop500_init_machine,
MACHINE_END
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
new file mode 100644
index 00000000000..1367eae9637
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __BOARD_MOP500_H
+#define __BOARD_MOP500_H
+
+#define SNOWBALL_SDMMC_EN_GPIO 217
+#define SNOWBALL_SDMMC_1V8_3V_GPIO 228
+#define SNOWBALL_SDMMC_CD_GPIO 218
+
+#define HREFV60_TOUCH_RST_GPIO 143
+#define HREFV60_PROX_SENSE_GPIO 217
+#define HREFV60_HAL_SW_GPIO 145
+#define HREFV60_SDMMC_EN_GPIO 169
+#define HREFV60_SDMMC_1V8_3V_GPIO 5
+#define HREFV60_SDMMC_CD_GPIO 95
+#define HREFV60_ACCEL_INT1_GPIO 82
+#define HREFV60_ACCEL_INT2_GPIO 83
+#define HREFV60_MAGNET_DRDY_GPIO 32
+#define HREFV60_DISP1_RST_GPIO 65
+#define HREFV60_DISP2_RST_GPIO 66
+#define HREFV60_MMIO_XENON_CHARGE 170
+#define HREFV60_XSHUTDOWN_SECONDARY_SENSOR 140
+#define XSHUTDOWN_PRIMARY_SENSOR 141
+#define XSHUTDOWN_SECONDARY_SENSOR 142
+struct i2c_board_info;
+void mop500_nuib_init(void);
+void __init mop500_u8500uib_init(void);
+void __init mop500_stuib_init(void);
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info const *info,
+ unsigned n);
+void mop500_msp_init(void);
+void __init mop500_pins_init(void);
+
+int msp13_i2s_init(void);
+int msp13_i2s_exit(void);
+
+#endif
diff --git a/arch/arm/mach-ux500/board-pdp-mcde.c b/arch/arm/mach-ux500/board-pdp-mcde.c
new file mode 100644
index 00000000000..8094be89fef
--- /dev/null
+++ b/arch/arm/mach-ux500/board-pdp-mcde.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright (C) ST-Ericsson AB 2010
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/mfd/ab8500/denc.h>
+#include <video/av8100.h>
+#include <video/mcde_display.h>
+#include <video/mcde_display-sony_sy35560_dsi.h>
+#include <video/mcde_display-av8100.h>
+#include <video/mcde_display-ab8500.h>
+#include <video/mcde_fb.h>
+#include <video/mcde_dss.h>
+#include "pins-db8500.h"
+#include "pins.h"
+
+#define DSI_UNIT_INTERVAL_0 0x9
+#define DSI_UNIT_INTERVAL_1 0x9
+#define DSI_UNIT_INTERVAL_2 0x6
+
+#define PRIMARY_DISPLAY_ID 0
+#define SECONDARY_DISPLAY_ID 1
+#define TERTIARY_DISPLAY_ID 2
+
+#define ROTATE_MAIN 0
+
+static int display_initialized_during_boot;
+
+static int __init startup_graphics_setup(char *str)
+{
+
+ if (get_option(&str, &display_initialized_during_boot) != 1)
+ display_initialized_during_boot = 0;
+
+ switch (display_initialized_during_boot) {
+ case 1:
+ pr_info("Startup graphics support\n");
+ break;
+ case 0:
+ default:
+ pr_info("No startup graphics supported\n");
+ break;
+ };
+
+ return 1;
+}
+__setup("startup_graphics=", startup_graphics_setup);
+
+#ifdef CONFIG_DISPLAY_SONY_SY35560_DSI_PRIMARY
+
+static int sony_sy35560_update(struct mcde_display_device *dev)
+{
+ int ret;
+
+ /* TODO: Dirty */
+ if (dev->prepare_for_update) {
+ /* TODO: Send dirty rectangle */
+ ret = dev->prepare_for_update(dev, 0, 0,
+ dev->native_x_res, dev->native_y_res);
+ if (ret < 0) {
+ dev_warn(&dev->dev,
+ "%s:Failed to prepare for update\n", __func__);
+ return ret;
+ }
+ }
+ /* TODO: Calculate & set update rect */
+ ret = mcde_chnl_update(dev->chnl_state, &dev->update_area);
+ if (ret < 0) {
+ dev_warn(&dev->dev, "%s:Failed to update channel\n", __func__);
+ return ret;
+ }
+ if (dev->first_update && dev->on_first_update)
+ dev->on_first_update(dev);
+
+ if (dev->power_mode != MCDE_DISPLAY_PM_ON && dev->set_power_mode) {
+ /* need to wait a while before turning on the display */
+ mdelay(5);
+ ret = dev->set_power_mode(dev, MCDE_DISPLAY_PM_ON);
+ if (ret < 0) {
+ dev_warn(&dev->dev,
+ "%s:Failed to set power mode to on\n",
+ __func__);
+ return ret;
+ }
+ }
+
+ dev_vdbg(&dev->dev, "Overlay updated, chnl=%d\n", dev->chnl_id);
+
+ return 0;
+}
+
+static int sony_sy35560_platform_enable(struct mcde_display_device *dev)
+{
+ int ret = 0;
+ struct sony_sy35560_platform_data *pdata =
+ dev->dev.platform_data;
+
+ dev_info(&dev->dev, "%s: Reset & power on sony display\n", __func__);
+
+ if (pdata->regulator_id) {
+ ((struct sony_sy35560_device *)dev)->regulator =
+ regulator_get(NULL, pdata->regulator_id);
+ if (IS_ERR(((struct sony_sy35560_device *)dev)->regulator)) {
+ ret = PTR_ERR(
+ ((struct sony_sy35560_device *)dev)->regulator);
+ dev_err(&dev->dev,
+ "%s:Failed to get regulator '%s'\n",
+ __func__, pdata->regulator_id);
+ ((struct sony_sy35560_device *)dev)->regulator = NULL;
+ goto out;
+ }
+ regulator_set_voltage(
+ ((struct sony_sy35560_device *)dev)->regulator,
+ pdata->min_supply_voltage,
+ pdata->max_supply_voltage);
+ ret = regulator_enable(
+ ((struct sony_sy35560_device *)dev)->regulator);
+ if (ret < 0) {
+ dev_err(&dev->dev,
+ "%s:Failed to enable regulator\n"
+ , __func__);
+ goto out;
+ }
+ }
+
+ if (!pdata->skip_init) {
+ dev_info(&dev->dev,
+ "%s: Startup graphics disabled, doing full init\n",
+ __func__);
+ if (pdata->reset_gpio) {
+ ret = gpio_request(pdata->reset_gpio, NULL);
+ if (ret) {
+ dev_warn(&dev->dev,
+ "%s:Failed to request gpio %d\n",
+ __func__, pdata->reset_gpio);
+ goto out;
+ }
+
+ gpio_direction_output(pdata->reset_gpio, 1);
+ gpio_set_value(pdata->reset_gpio, 0);
+ mdelay(1);
+ gpio_set_value(pdata->reset_gpio, 1);
+ }
+ } else {
+ dev_info(&dev->dev,
+ "%s: Display already initialized during boot\n",
+ __func__);
+ pdata->skip_init = false;
+ }
+
+ dev->update = sony_sy35560_update;
+
+ /* TODO: Remove when DSI send command uses interrupts */
+ dev->prepare_for_update = NULL;
+
+#ifdef CONFIG_SONY_SY35560_ENABLE_ESD_CHECK
+ /* add ESD status check to workqueue */
+ queue_delayed_work(((struct sony_sy35560_device *)dev)->esd_wq,
+ &(((struct sony_sy35560_device *)dev)->esd_work),
+ SONY_SY35560_ESD_CHECK_PERIOD);
+#endif
+
+out:
+ if (pdata->reset_gpio)
+ gpio_free(pdata->reset_gpio);
+ return ret;
+}
+
+static int sony_sy35560_platform_disable(struct mcde_display_device *dev)
+{
+ dev_info(&dev->dev, "%s: Reset & power off sony display\n", __func__);
+
+ if (((struct sony_sy35560_device *)dev)->regulator) {
+ if (regulator_disable(
+ ((struct sony_sy35560_device *)dev)->regulator) < 0)
+ dev_err(&dev->dev,
+ "%s:Failed to disable regulator\n",
+ __func__);
+ }
+ return 0;
+}
+
+static struct mcde_port port0 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = 1,
+ .link = 0,
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .update_auto_trig = false,
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_0,
+ .clk_cont = false,
+ },
+ },
+};
+
+struct sony_sy35560_platform_data sony_sy35560_display0_pdata = {
+ .reset_gpio = EGPIO_PIN_15,
+#ifdef CONFIG_REGULATOR
+ .regulator_id = "v-display",
+ .min_supply_voltage = 2800000, /* 2.8V */
+ .max_supply_voltage = 2800000 /* 2.8V */
+#endif
+};
+
+struct sony_sy35560_device sony_sy35560_display0 = {
+ .base = {
+ .name = "mcde_disp_sony",
+ .id = PRIMARY_DISPLAY_ID,
+ .port = &port0,
+ .chnl_id = MCDE_CHNL_A,
+ .fifo = MCDE_FIFO_C0,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 480,
+ .native_y_res = 854,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC
+ .synchronized_update = true,
+#else
+ .synchronized_update = false,
+#endif
+ .platform_enable = sony_sy35560_platform_enable,
+ .platform_disable = sony_sy35560_platform_disable,
+ /* TODO: Remove rotation buffers once ESRAM driver
+ * is completed */
+ .rotbuf1 = U8500_ESRAM_BASE + 0x20000 * 4,
+ .rotbuf2 = U8500_ESRAM_BASE + 0x20000 * 4 + 0x10000,
+ .dev = {
+ .platform_data = &sony_sy35560_display0_pdata,
+ },
+ }
+};
+#endif /* CONFIG_DISPLAY_SONY_SY35560_DSI_PRIMARY */
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY
+static struct mcde_port subdisplay_port = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = 1,
+ .link = 1,
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .update_auto_trig = false,
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_1,
+ .clk_cont = false,
+ },
+ },
+
+};
+
+static struct mcde_display_generic_platform_data generic_subdisplay_pdata = {
+ .reset_gpio = EGPIO_PIN_14,
+ .reset_delay = 1,
+#ifdef CONFIG_REGULATOR
+ .regulator_id = "v-display",
+ .min_supply_voltage = 2500000, /* 2.5V */
+ .max_supply_voltage = 2700000 /* 2.7V */
+#endif
+};
+
+static struct mcde_display_device generic_subdisplay = {
+ .name = "mcde_disp_generic_subdisplay",
+ .id = SECONDARY_DISPLAY_ID,
+ .port = &subdisplay_port,
+ .chnl_id = MCDE_CHNL_C1,
+ .fifo = MCDE_FIFO_C1,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 864,
+ .native_y_res = 480,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY_VSYNC
+ .synchronized_update = true,
+#else
+ .synchronized_update = false,
+#endif
+ .dev = {
+ .platform_data = &generic_subdisplay_pdata,
+ },
+};
+#endif /* CONFIG_DISPLAY_GENERIC_DSI_SECONDARY */
+
+
+#ifdef CONFIG_DISPLAY_AB8500_TERTIARY
+static struct mcde_port port_tvout1 = {
+ .type = MCDE_PORTTYPE_DPI,
+ .pixel_format = MCDE_PORTPIXFMT_DPI_24BPP,
+ .ifc = 0,
+ .link = 1, /* channel B */
+ .sync_src = MCDE_SYNCSRC_OFF,
+ .update_auto_trig = true,
+ .phy = {
+ .dpi = {
+ .bus_width = 4, /* DDR mode */
+ .tv_mode = true,
+ .clock_div = MCDE_PORT_DPI_NO_CLOCK_DIV,
+ },
+ },
+};
+
+static struct ab8500_display_platform_data ab8500_display_pdata = {
+ .denc_regulator_id = "v-tvout",
+ .rgb_2_yCbCr_transform = {
+ .matrix = {
+ {0x42, 0x81, 0x19},
+ {0xffda, 0xffb6, 0x70},
+ {0x70, 0xffa2, 0xffee},
+ },
+ .offset = {0x10, 0x80, 0x80},
+ }
+};
+
+static struct ux500_pins *tvout_pins;
+
+static int ab8500_platform_enable(struct mcde_display_device *ddev)
+{
+ int res = 0;
+
+ dev_info(&ddev->dev, "%s\n", __func__);
+
+ if (!tvout_pins) {
+ tvout_pins = ux500_pins_get("mcde-tvout");
+ if (!tvout_pins)
+ return -EINVAL;
+ }
+
+ res = ux500_pins_enable(tvout_pins);
+ if (res != 0)
+ goto failed;
+
+ return res;
+
+failed:
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+ return res;
+}
+
+static int ab8500_platform_disable(struct mcde_display_device *ddev)
+{
+ int res;
+
+ dev_info(&ddev->dev, "%s\n", __func__);
+
+ res = ux500_pins_disable(tvout_pins);
+ if (res != 0)
+ goto failed;
+ return res;
+
+failed:
+ dev_warn(&ddev->dev, "Failure during %s\n", __func__);
+ return res;
+}
+
+struct mcde_display_device tvout_ab8500_display = {
+ .name = "mcde_tv_ab8500",
+ .id = TERTIARY_DISPLAY_ID,
+ .port = &port_tvout1,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 720,
+ .native_y_res = 576,
+ .dev = {
+ .platform_data = &ab8500_display_pdata,
+ },
+
+ /*
+ * We might need to describe the std here:
+ * - there are different PAL / NTSC formats (do they require MCDE
+ * settings?)
+ */
+ .platform_enable = ab8500_platform_enable,
+ .platform_disable = ab8500_platform_disable,
+};
+#endif /* CONFIG_DISPLAY_AB8500_TERTIARY */
+
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+static struct mcde_port port2 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = 1,
+ .link = 2,
+#ifdef CONFIG_AV8100_HWTRIG_INT
+ .sync_src = MCDE_SYNCSRC_TE0,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_I2SDAT3
+ .sync_src = MCDE_SYNCSRC_TE1,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_DSI_TE
+ .sync_src = MCDE_SYNCSRC_TE_POLLING,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_NONE
+ .sync_src = MCDE_SYNCSRC_OFF,
+#endif
+ .update_auto_trig = true,
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_2,
+ .clk_cont = false,
+ },
+ },
+ .hdmi_sdtv_switch = HDMI_SWITCH,
+};
+
+struct mcde_display_hdmi_platform_data av8100_hdmi_pdata = {
+ .reset_gpio = 0,
+ .reset_delay = 1,
+ .regulator_id = NULL, /* TODO: "display_main" */
+ .ddb_id = 1,
+ .rgb_2_yCbCr_transform = {
+ .matrix = {
+ {0x42, 0x81, 0x19},
+ {0xffda, 0xffb6, 0x70},
+ {0x70, 0xffa2, 0xffee},
+ },
+ .offset = {0x10, 0x80, 0x80},
+ }
+};
+
+static int av8100_platform_enable(struct mcde_display_device *dev)
+{
+ int ret;
+ struct mcde_display_hdmi_platform_data *pdata =
+ dev->dev.platform_data;
+
+ if (pdata->reset_gpio)
+ gpio_set_value(pdata->reset_gpio, pdata->reset_high);
+ if (pdata->regulator)
+ ret = regulator_enable(pdata->regulator);
+alt_func_failed:
+ return ret;
+}
+
+static int av8100_platform_disable(struct mcde_display_device *dev)
+{
+ int ret;
+ struct mcde_display_hdmi_platform_data *pdata =
+ dev->dev.platform_data;
+
+ if (pdata->reset_gpio)
+ gpio_set_value(pdata->reset_gpio, !pdata->reset_high);
+ if (pdata->regulator)
+ ret = regulator_disable(pdata->regulator);
+alt_func_failed:
+ return ret;
+}
+
+struct mcde_display_device av8100_hdmi = {
+ .name = "av8100_hdmi",
+ .id = TERTIARY_DISPLAY_ID,
+ .port = &port2,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 1280,
+ .native_y_res = 720,
+ .synchronized_update = true,
+ .dev = {
+ .platform_data = &av8100_hdmi_pdata,
+ },
+ .platform_enable = av8100_platform_enable,
+ .platform_disable = av8100_platform_disable,
+};
+#endif /* CONFIG_DISPLAY_AV8100_TERTIARY */
+
+static struct fb_info *fbs[3] = { NULL, NULL, NULL };
+static struct mcde_display_device *displays[3] = { NULL, NULL, NULL };
+
+static int display_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *dev)
+{
+ struct mcde_display_device *ddev = dev;
+ u16 width, height;
+ u16 virtual_width, virtual_height;
+ bool rotate;
+
+ if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED)
+ return 0;
+
+ if (ddev->id < PRIMARY_DISPLAY_ID || ddev->id >= ARRAY_SIZE(fbs))
+ return 0;
+
+ mcde_dss_get_native_resolution(ddev, &width, &height);
+
+ rotate = (ddev->id == 0 && ROTATE_MAIN);
+ if (rotate) {
+ u16 tmp = height;
+ height = width;
+ width = tmp;
+ }
+
+ virtual_width = width;
+ virtual_height = height * 2;
+
+ /* Create frame buffer */
+ fbs[ddev->id] = mcde_fb_create(ddev,
+ width, height,
+ virtual_width, virtual_height,
+ ddev->default_pixel_format,
+ rotate ? FB_ROTATE_CW : FB_ROTATE_UR);
+ if (IS_ERR(fbs[ddev->id]))
+ pr_warning("Failed to create fb for display %s\n", ddev->name);
+ else
+ pr_info("Framebuffer created (%s)\n", ddev->name);
+
+ return 0;
+}
+
+static struct notifier_block display_nb = {
+ .notifier_call = display_postregistered_callback,
+};
+
+static int framebuffer_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int ret = 0;
+ struct fb_event *event_data = data;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+ u8 *addr;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
+
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ if (mfb->id == 0 && display_initialized_during_boot)
+ goto out;
+
+
+ var = info->var;
+ fix = info->fix;
+ addr = ioremap(fix.smem_start,
+ var.yres_virtual * fix.line_length);
+ memset(addr, 0x00,
+ var.yres_virtual * fix.line_length);
+ var.yoffset = var.yoffset ? 0 : var.yres;
+ if (info->fbops->fb_pan_display)
+ ret = info->fbops->fb_pan_display(&var, info);
+out:
+ return ret;
+}
+
+static struct notifier_block framebuffer_nb = {
+ .notifier_call = framebuffer_postregistered_callback,
+};
+
+int __init init_display_devices(void)
+{
+ int ret;
+
+ ret = fb_register_client(&framebuffer_nb);
+ if (ret)
+ pr_warning("Failed to register framebuffer notifier\n");
+
+ ret = mcde_dss_register_notifier(&display_nb);
+ if (ret)
+ pr_warning("Failed to register dss notifier\n");
+
+#ifdef CONFIG_DISPLAY_SONY_SY35560_DSI_PRIMARY
+ /* TODO: enable this code if uboot graphics should be used
+ if (display_initialized_during_boot)
+ ((struct sony_sy35560_platform_data *)sony_sy35560_display0.
+ base.dev.platform_data)->skip_init = true;
+ */
+ ret = mcde_display_device_register(
+ (struct mcde_display_device *)&sony_sy35560_display0);
+ if (ret)
+ pr_warning("Failed to register Sony sy35560 display device 0\n");
+ displays[0] = (struct mcde_display_device *)&sony_sy35560_display0;
+#endif
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_SECONDARY
+ ret = mcde_display_device_register(&generic_subdisplay);
+ if (ret)
+ pr_warning("Failed to register generic sub display device\n");
+ displays[1] = &generic_subdisplay;
+#endif
+
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+ ret = mcde_display_device_register(&av8100_hdmi);
+ if (ret)
+ pr_warning("Failed to register av8100_hdmi\n");
+ displays[2] = &av8100_hdmi;
+#endif
+#ifdef CONFIG_DISPLAY_AB8500_TERTIARY
+ ret = platform_device_register(&ab8500_denc);
+ if (ret)
+ pr_warning("Failed to register ab8500_denc device\n");
+ else {
+ ret = mcde_display_device_register(&tvout_ab8500_display);
+ if (ret)
+ pr_warning("Failed to register ab8500 tvout device\n");
+ displays[2] = &tvout_ab8500_display;
+ }
+#endif
+
+ return ret;
+}
+
+module_init(init_display_devices);
diff --git a/arch/arm/mach-ux500/board-snowball-digio.c b/arch/arm/mach-ux500/board-snowball-digio.c
new file mode 100644
index 00000000000..b8fc1c033b7
--- /dev/null
+++ b/arch/arm/mach-ux500/board-snowball-digio.c
@@ -0,0 +1,118 @@
+
+/*
+ * This defines the user led (output) and 4-keys gpio keyboard (input)
+ * Original code by Gregory Hermant
+ * Split to a standalone file by Alessandro Rubini
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+#include <plat/pincfg.h>
+#include <plat/gpio.h>
+#include "pins-db5500.h"
+
+static pin_cfg_t snowball_pins[] = {
+ PIN_CFG(32, GPIO) | PIN_INPUT_PULLUP, /* led */
+ PIN_CFG(151, GPIO) | PIN_INPUT_PULLUP, /* button */
+ PIN_CFG(152, GPIO) | PIN_INPUT_PULLUP, /* button */
+/* PIN_CFG(161, GPIO) | PIN_INPUT_PULLUP, button */
+ PIN_CFG(162, GPIO) | PIN_INPUT_PULLUP, /* button */
+};
+
+static struct gpio_led snowball_led_array[] = {
+ {
+ .name = "user_led",
+ .default_trigger = "none",
+ .gpio = 142,
+ },
+};
+
+static struct gpio_led_platform_data snowball_led_data = {
+ .leds = snowball_led_array,
+ .num_leds = ARRAY_SIZE(snowball_led_array),
+};
+
+static struct platform_device snowball_led_dev = {
+ .name = "leds-gpio",
+ .dev = {
+ .platform_data = &snowball_led_data,
+ },
+};
+
+static struct gpio_keys_button snowball_key_array[] = {
+ {
+ .gpio = 32,
+ .type = EV_KEY,
+ .code = KEY_1,
+ .desc = "userpb",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+ {
+ .gpio = 151,
+ .type = EV_KEY,
+ .code = KEY_2,
+ .desc = "extkb1",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+ {
+ .gpio = 152,
+ .type = EV_KEY,
+ .code = KEY_3,
+ .desc = "extkb2",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+ /*
+ {
+ .gpio = 161,
+ .type = EV_KEY,
+ .code = KEY_4,
+ .desc = "extkb3",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+ */
+ {
+ .gpio = 162,
+ .type = EV_KEY,
+ .code = KEY_5,
+ .desc = "extkb4",
+ .active_low = 1,
+ .debounce_interval = 50,
+ .wakeup = 1,
+ },
+};
+
+static struct gpio_keys_platform_data snowball_key_data = {
+ .buttons = snowball_key_array,
+ .nbuttons = ARRAY_SIZE(snowball_key_array),
+};
+
+static struct platform_device snowball_key_dev = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &snowball_key_data,
+ }
+};
+
+static int snowball_digio_init(void)
+{
+ nmk_config_pins(snowball_pins, ARRAY_SIZE(snowball_pins));
+ platform_device_register(&snowball_led_dev);
+ platform_device_register(&snowball_key_dev);
+ return 0;
+}
+
+module_init(snowball_digio_init);
+
+/* no release function: I'm lazy at this point */
diff --git a/arch/arm/mach-ux500/board-snowball-netdev.c b/arch/arm/mach-ux500/board-snowball-netdev.c
new file mode 100644
index 00000000000..48404e4f953
--- /dev/null
+++ b/arch/arm/mach-ux500/board-snowball-netdev.c
@@ -0,0 +1,74 @@
+#include <linux/module.h>
+#include <linux/resource.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <mach/irqs.h>
+#include <asm/io.h>
+
+struct smsc911x_platform_config sbnet_cfg = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .shift = 1,
+ .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+};
+
+struct resource sbnet_res[] = {
+ {
+ .name = "smsc911x-memory",
+ .start = (0x5000 << 16),
+ .end = (0x5000 << 16) + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ },{
+ .start = GPIO_TO_IRQ(140),
+ .end = GPIO_TO_IRQ(140),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
+ },
+};
+
+struct platform_device sbnet_dev = {
+ .name = "smsc911x",
+ .num_resources = ARRAY_SIZE(sbnet_res),
+ .resource = sbnet_res,
+ .dev = {
+ .platform_data = &sbnet_cfg,
+ },
+};
+
+int sbnet_init(void)
+{
+ volatile u32 *ptr = ioremap(0x80000000, 0x10000);
+
+ if (!machine_is_snowball()) {
+ printk("no netdev: no snowball\n");
+ return 0;
+ }
+ printk("init netdev: is snowball\n");
+
+ /*
+ * Horribly, fix all the configuration by hand
+ */
+ /* Turn on the FSMC device */
+ *(ptr + 0xf000 / 4) = 1;
+ *(ptr + 0xf008 / 4) = 1;
+
+ /* Configure the FSMC device */
+ *(ptr + 0x0000 / 4) = 0x0000305b;
+ *(ptr + 0x0004 / 4) = 0x01010110;
+
+ /* Fix some gpio bits */
+ *(ptr + 0xe120 / 4) &= ~0x7f8;
+ *(ptr + 0xe124 / 4) |= 0x7f8;
+ iounmap(ptr);
+
+ return platform_device_register(&sbnet_dev);
+}
+
+void sbnet_exit(void)
+{
+ platform_device_unregister(&sbnet_dev);
+}
+
+module_init(sbnet_init);
+module_exit(sbnet_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ux500/board-snowball-pins.c b/arch/arm/mach-ux500/board-snowball-pins.c
new file mode 100644
index 00000000000..45ff0803f71
--- /dev/null
+++ b/arch/arm/mach-ux500/board-snowball-pins.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011-2012 ST-Ericsson
+ *
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <plat/pincfg.h>
+
+#include <mach/hardware.h>
+
+#include "pins-db8500.h"
+
+static pin_cfg_t snowball_pins[] = {
+ /* I2C */
+ GPIO147_I2C0_SCL,
+ GPIO148_I2C0_SDA,
+ GPIO16_I2C1_SCL,
+ GPIO17_I2C1_SDA,
+ GPIO10_I2C2_SDA,
+ GPIO11_I2C2_SCL,
+ GPIO229_I2C3_SDA,
+ GPIO230_I2C3_SCL,
+
+ /* SSP0, to AB8500 */
+ GPIO143_SSP0_CLK,
+ GPIO144_SSP0_FRM,
+ GPIO145_SSP0_RXD | PIN_PULL_DOWN,
+ GPIO146_SSP0_TXD,
+
+ /* MSP0: BT */
+ GPIO12_MSP0_TXD,
+ GPIO13_MSP0_TFS,
+ GPIO14_MSP0_TCK,
+ GPIO15_MSP0_RXD,
+
+ /* MSP2: HDMI */
+ GPIO193_MSP2_TXD,
+ GPIO194_MSP2_TCK,
+ GPIO195_MSP2_TFS,
+ GPIO196_MSP2_RXD | PIN_OUTPUT_LOW,
+
+ /* MMC0: MicroSD card */
+ GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH,
+ GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH,
+ GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH,
+ GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH,
+ GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL,
+ GPIO23_MC0_CLK | PIN_OUTPUT_LOW,
+ GPIO24_MC0_CMD | PIN_INPUT_PULLUP,
+ GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP,
+ GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP,
+ GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP,
+ GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP,
+
+ /* SDI1: WLAN */
+ GPIO208_MC1_CLK | PIN_OUTPUT_LOW,
+ GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL,
+ GPIO210_MC1_CMD | PIN_INPUT_PULLUP,
+ GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP,
+ GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP,
+ GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP,
+ GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP,
+
+ /* MMC2: LAN */
+ GPIO86_SM_ADQ0,
+ GPIO87_SM_ADQ1,
+ GPIO88_SM_ADQ2,
+ GPIO89_SM_ADQ3,
+ GPIO90_SM_ADQ4,
+ GPIO91_SM_ADQ5,
+ GPIO92_SM_ADQ6,
+ GPIO93_SM_ADQ7,
+
+ GPIO94_SM_ADVn,
+ GPIO95_SM_CS0n,
+ GPIO96_SM_OEn,
+ GPIO97_SM_WEn,
+
+ GPIO128_SM_CKO,
+ GPIO130_SM_FBCLK,
+ GPIO131_SM_ADQ8,
+ GPIO132_SM_ADQ9,
+ GPIO133_SM_ADQ10,
+ GPIO134_SM_ADQ11,
+ GPIO135_SM_ADQ12,
+ GPIO136_SM_ADQ13,
+ GPIO137_SM_ADQ14,
+ GPIO138_SM_ADQ15,
+
+ /* RSTn_LAN */
+ GPIO141_GPIO | PIN_OUTPUT_HIGH,
+
+ /* MMC4: eMMC */
+ GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP,
+ GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP,
+ GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP,
+ GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP,
+ GPIO201_MC4_CMD | PIN_INPUT_PULLUP,
+ GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL,
+ GPIO203_MC4_CLK | PIN_OUTPUT_LOW,
+ GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP,
+ GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP,
+ GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP,
+ GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP,
+
+ GPIO141_GPIO | PIN_OUTPUT_HIGH, /* RSTn_LAN */
+
+ /* UART: WLAN */
+ GPIO0_U0_CTSn | PIN_INPUT_PULLUP,
+ GPIO1_U0_RTSn | PIN_OUTPUT_HIGH,
+ GPIO2_U0_RXD | PIN_INPUT_PULLUP,
+ GPIO3_U0_TXD | PIN_OUTPUT_HIGH,
+
+ /* UART: DBG port */
+ GPIO29_U2_RXD | PIN_INPUT_PULLUP,
+ GPIO30_U2_TXD | PIN_OUTPUT_HIGH,
+ GPIO31_U2_CTSn | PIN_INPUT_PULLUP,
+ GPIO32_U2_RTSn | PIN_OUTPUT_HIGH,
+};
+
+/*
+ * This function is called to force gpio power save
+ * settings during suspend.
+ * This is a temporary solution until all drivers are
+ * controlling their pin settings when in inactive mode.
+ *
+ * Made empty for Snowball
+ */
+void mop500_pins_suspend_force(void)
+{
+ return;
+}
+
+/*
+ * 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.
+ */
+void mop500_pins_suspend_force_mux(void)
+{
+ return;
+}
+
+void __init snowball_pins_init(void)
+{
+ nmk_config_pins(snowball_pins,
+ ARRAY_SIZE(snowball_pins));
+}
diff --git a/arch/arm/mach-ux500/board-snowball.c b/arch/arm/mach-ux500/board-snowball.c
new file mode 100644
index 00000000000..c7d785fb1d6
--- /dev/null
+++ b/arch/arm/mach-ux500/board-snowball.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2011-2012 ST-Ericsson
+ *
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>, based on the
+ * work of Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> in
+ * board-mop500.c
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/pl022.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <linux/hsi.h>
+#include <linux/i2s/i2s.h>
+#include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/mfd/tc35892.h>
+#include <linux/i2c/lp5521.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/input/bu21013.h>
+#include <linux/spi/stm_msp.h>
+#include <linux/leds_pwm.h>
+#include <linux/pwm_backlight.h>
+#include <linux/mfd/ab8500/ab8500-bm.h>
+#include <linux/mfd/ab8500/denc.h>
+#include <linux/ste_timed_vibra.h>
+#include <linux/mfd/ab8500/ab8500-gpio.h>
+#include <linux/mfd/cg2900.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach-types.h>
+
+#include <plat/pincfg.h>
+#include <plat/ske.h>
+#include <plat/i2c.h>
+
+#include <mach/devices.h>
+#include <mach/sensors1p.h>
+#include <mach/ste_audio_io.h>
+#include <mach/setup.h>
+#include <mach/tc35893-keypad.h>
+#include <mach/ste_audio_io_vibrator.h>
+#include <video/av8100.h>
+#include <mach/devices.h>
+#include <mach/irqs.h>
+#include <mach/ste-dma40-db8500.h>
+
+#include "devices-cg2900.h"
+#include "devices-db8500.h"
+#include "board-mop500-regulators.h"
+#include "regulator-u8500.h"
+#include "pins-db8500.h"
+#include "board-snowball.h"
+
+static struct av8100_platform_data av8100_plat_data = {
+ .irq = GPIO_TO_IRQ(192),
+ .reset = 196,
+ .regulator_pwr_id = "hdmi_1v8",
+};
+
+static struct i2c_board_info __initdata mop500_i2c0_devices[] = {
+ {
+ I2C_BOARD_INFO("av8100", 0x70),
+ .platform_data = &av8100_plat_data,
+ },
+};
+static struct i2c_board_info __initdata mop500_i2c1_devices[] = {};
+static struct i2c_board_info __initdata mop500_i2c2_devices[] = {};
+static struct i2c_board_info __initdata mop500_i2c3_devices[] = {};
+
+/*
+ * MSP-SPI
+ */
+
+#define NUM_MSP_CLIENTS 10
+
+static struct stm_msp_controller mop500_msp2_spi_data = {
+ .id = MSP_2_CONTROLLER,
+ .num_chipselect = NUM_MSP_CLIENTS,
+ .base_addr = U8500_MSP2_BASE,
+ .device_name = "msp2",
+};
+
+/*
+ * SSP
+ */
+
+#define NUM_SSP_CLIENTS 10
+
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg ssp0_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV8_SSP0_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV8_SSP0_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
+static struct pl022_ssp_controller mop500_ssp0_data = {
+ .bus_id = SSP_0_CONTROLLER,
+ .num_chipselect = NUM_SSP_CLIENTS,
+#ifdef CONFIG_STE_DMA40
+ .enable_dma = 1,
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &ssp0_dma_cfg_rx,
+ .dma_tx_param = &ssp0_dma_cfg_tx,
+#endif
+
+};
+
+#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, t_out, _sm) \
+static struct nmk_i2c_controller mop500_i2c##id##_data = { \
+ /* \
+ * slave data setup time, which is \
+ * 250 ns,100ns,10ns which is 14,6,2 \
+ * respectively for a 48 Mhz \
+ * i2c clock \
+ */ \
+ .slsu = _slsu, \
+ /* Tx FIFO threshold */ \
+ .tft = _tft, \
+ /* Rx FIFO threshold */ \
+ .rft = _rft, \
+ /* std. mode operation */ \
+ .clk_freq = clk, \
+ /* Slave response timeout(ms) */\
+ .timeout = t_out, \
+ .sm = _sm, \
+}
+
+/*
+ * The board uses 4 i2c controllers, initialize all of
+ * them with slave data setup time of 250 ns,
+ * Tx & Rx FIFO threshold values as 1 and standard
+ * mode of operation
+ */
+U8500_I2C_CONTROLLER(0, 0xe, 1, 1, 400000, 500, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 400000, 500, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, 500, I2C_FREQ_MODE_FAST);
+U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 400000, 500, I2C_FREQ_MODE_FAST);
+
+static struct hsi_board_info __initdata stm_hsi_devices[] = {
+ {.type = "HSI_LOOPBACK", .flags = 0, .controller_id = 0,
+ .chan_num = 0, .mode = 1},
+ {.type = "HSI_LOOPBACK", .flags = 0, .controller_id = 1,
+ .chan_num = 0, .mode = 1},
+ {.type = "HSI_LOOPBACK", .flags = 0, .controller_id = 0,
+ .chan_num = 1, .mode = 1},
+ {.type = "HSI_LOOPBACK", .flags = 0, .controller_id = 1,
+ .chan_num = 1, .mode = 1},
+ {.type = "HSI_LOOPBACK", .flags = 0, .controller_id = 0,
+ .chan_num = 2, .mode = 1},
+ {.type = "HSI_LOOPBACK", .flags = 0, .controller_id = 1,
+ .chan_num = 2, .mode = 1},
+ {.type = "HSI_LOOPBACK", .flags = 0, .controller_id = 0,
+ .chan_num = 3, .mode = 1},
+ {.type = "HSI_LOOPBACK", .flags = 0, .controller_id = 1,
+ .chan_num = 3, .mode = 1},
+};
+
+#ifdef CONFIG_AB8500_GPIO
+static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
+ .gpio_base = AB8500_PIN_GPIO1,
+ /* config_reg is the initial configuration of ab8500 pins.
+ * The pins can be configured as GPIO or alt functions based
+ * on value present in GpioSel1 to GpioSel6 and AlternatFunction
+ * register. This is the array of 7 configuration settings.
+ * One has to compile time decide these settings. Below is the
+ * explaination of these setting
+ * GpioSel1 = 0x00 => Pins GPIO1 to GPIO8 are not used as GPIO
+ * GpioSel2 = 0x1E => Pins GPIO10 to GPIO13 are configured as GPIO
+ * GpioSel3 = 0x80 => Pin GPIO24 is configured as GPIO
+ * GpioSel4 = 0x01 => Pin GPIo25 is configured as GPIO
+ * GpioSel5 = 0x7A => Pins GPIO34, GPIO36 to GPIO39 are conf as GPIO
+ * GpioSel6 = 0x00 => Pins GPIo41 & GPIo42 are not configured as GPIO
+ * AlternaFunction = 0x00 => If Pins GPIO10 to 13 are not configured
+ * as GPIO then this register selectes the alternate fucntions
+ */
+ .config_reg = {0x00, 0x1E, 0x80, 0x01,
+ 0x7A, 0x00, 0x00},
+};
+#endif
+
+static struct regulator_init_data *u8500_regulators[U8500_NUM_REGULATORS] = {
+ [U8500_REGULATOR_VAPE] = &u8500_vape_regulator,
+ [U8500_REGULATOR_VARM] = &u8500_varm_regulator,
+ [U8500_REGULATOR_VMODEM] = &u8500_vmodem_regulator,
+ [U8500_REGULATOR_VPLL] = &u8500_vpll_regulator,
+ [U8500_REGULATOR_VSMPS1] = &u8500_vsmps1_regulator,
+ [U8500_REGULATOR_VSMPS2] = &u8500_vsmps2_regulator,
+ [U8500_REGULATOR_VSMPS3] = &u8500_vsmps3_regulator,
+ [U8500_REGULATOR_VRF1] = &u8500_vrf1_regulator,
+ [U8500_REGULATOR_SWITCH_SVAMMDSP] = &u8500_svammdsp_regulator,
+ [U8500_REGULATOR_SWITCH_SVAMMDSPRET] = &u8500_svammdspret_regulator,
+ [U8500_REGULATOR_SWITCH_SVAPIPE] = &u8500_svapipe_regulator,
+ [U8500_REGULATOR_SWITCH_SIAMMDSP] = &u8500_siammdsp_regulator,
+ [U8500_REGULATOR_SWITCH_SIAMMDSPRET] = &u8500_siammdspret_regulator,
+ [U8500_REGULATOR_SWITCH_SIAPIPE] = &u8500_siapipe_regulator,
+ [U8500_REGULATOR_SWITCH_SGA] = &u8500_sga_regulator,
+ [U8500_REGULATOR_SWITCH_B2R2_MCDE] = &u8500_b2r2_mcde_regulator,
+ [U8500_REGULATOR_SWITCH_ESRAM12] = &u8500_esram12_regulator,
+ [U8500_REGULATOR_SWITCH_ESRAM12RET] = &u8500_esram12ret_regulator,
+ [U8500_REGULATOR_SWITCH_ESRAM34] = &u8500_esram34_regulator,
+ [U8500_REGULATOR_SWITCH_ESRAM34RET] = &u8500_esram34ret_regulator,
+};
+
+static struct platform_device u8500_regulator_dev = {
+ .name = "u8500-regulators",
+ .id = 0,
+ .dev = {
+ .platform_data = u8500_regulators,
+ },
+};
+
+static struct ab8500_audio_platform_data ab8500_audio_plat_data = {
+ .ste_gpio_altf_init = msp13_i2s_init,
+ .ste_gpio_altf_exit = msp13_i2s_exit,
+};
+
+/*
+ * NOTE! The regulator configuration below must be in exactly the same order as
+ * the regulator description in the driver, see drivers/regulator/ab8500.c
+ */
+static struct ab8500_platform_data ab8500_platdata = {
+ .irq_base = MOP500_AB8500_IRQ_BASE,
+ .regulator = ab8500_regulators,
+ .num_regulator = ARRAY_SIZE(ab8500_regulators),
+ .audio = &ab8500_audio_plat_data,
+#ifdef CONFIG_AB8500_GPIO
+ .gpio = &ab8500_gpio_pdata,
+#endif
+};
+
+static struct resource ab8500_resources[] = {
+ [0] = {
+ .start = IRQ_DB8500_AB8500,
+ .end = IRQ_DB8500_AB8500,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device ux500_ab8500_device = {
+ .name = "ab8500-i2c",
+ .id = 0,
+ .dev = {
+ .platform_data = &ab8500_platdata,
+ },
+ .num_resources = 1,
+ .resource = ab8500_resources,
+};
+
+#ifdef CONFIG_MFD_CG2900
+#define CG2900_BT_ENABLE_GPIO 170
+#define CG2900_GBF_ENA_RESET_GPIO 171
+#define CG2900_BT_CTS_GPIO 0
+
+enum cg2900_gpio_pull_sleep cg2900_sleep_gpio[21] = {
+ CG2900_NO_PULL, /* GPIO 0: PTA_CONFX */
+ CG2900_PULL_DN, /* GPIO 1: PTA_STATUS */
+ CG2900_NO_PULL, /* GPIO 2: UART_CTSN */
+ CG2900_PULL_UP, /* GPIO 3: UART_RTSN */
+ CG2900_PULL_UP, /* GPIO 4: UART_TXD */
+ CG2900_NO_PULL, /* GPIO 5: UART_RXD */
+ CG2900_PULL_DN, /* GPIO 6: IOM_DOUT */
+ CG2900_NO_PULL, /* GPIO 7: IOM_FSC */
+ CG2900_NO_PULL, /* GPIO 8: IOM_CLK */
+ CG2900_NO_PULL, /* GPIO 9: IOM_DIN */
+ CG2900_PULL_DN, /* GPIO 10: PWR_REQ */
+ CG2900_PULL_DN, /* GPIO 11: HOST_WAKEUP */
+ CG2900_PULL_DN, /* GPIO 12: IIS_DOUT */
+ CG2900_NO_PULL, /* GPIO 13: IIS_WS */
+ CG2900_NO_PULL, /* GPIO 14: IIS_CLK */
+ CG2900_NO_PULL, /* GPIO 15: IIS_DIN */
+ CG2900_PULL_DN, /* GPIO 16: PTA_FREQ */
+ CG2900_PULL_DN, /* GPIO 17: PTA_RF_ACTIVE */
+ CG2900_NO_PULL, /* GPIO 18: NotConnected (J6428) */
+ CG2900_NO_PULL, /* GPIO 19: EXT_DUTY_CYCLE */
+ CG2900_NO_PULL, /* GPIO 20: EXT_FRM_SYNCH */
+};
+
+static struct platform_device ux500_cg2900_device = {
+ .name = "cg2900",
+};
+
+#ifdef CONFIG_MFD_CG2900_CHIP
+static struct platform_device ux500_cg2900_chip_device = {
+ .name = "cg2900-chip",
+ .dev = {
+ .parent = &ux500_cg2900_device.dev,
+ },
+};
+#endif /* CONFIG_MFD_CG2900_CHIP */
+
+#ifdef CONFIG_MFD_STLC2690_CHIP
+static struct platform_device ux500_stlc2690_chip_device = {
+ .name = "stlc2690-chip",
+ .dev = {
+ .parent = &ux500_cg2900_device.dev,
+ },
+};
+#endif /* CONFIG_MFD_STLC2690_CHIP */
+
+#ifdef CONFIG_MFD_CG2900_TEST
+static struct cg2900_platform_data cg2900_test_platform_data = {
+ .bus = HCI_VIRTUAL,
+ .gpio_sleep = cg2900_sleep_gpio,
+};
+
+static struct platform_device ux500_cg2900_test_device = {
+ .name = "cg2900-test",
+ .dev = {
+ .parent = &ux500_cg2900_device.dev,
+ .platform_data = &cg2900_test_platform_data,
+ },
+};
+#endif /* CONFIG_MFD_CG2900_TEST */
+
+#ifdef CONFIG_MFD_CG2900_UART
+static struct resource cg2900_uart_resources[] = {
+ {
+ .start = CG2900_GBF_ENA_RESET_GPIO,
+ .end = CG2900_GBF_ENA_RESET_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "gbf_ena_reset",
+ },
+ {
+ .start = CG2900_BT_ENABLE_GPIO,
+ .end = CG2900_BT_ENABLE_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "bt_enable",
+ },
+ {
+ .start = GPIO_TO_IRQ(CG2900_BT_CTS_GPIO),
+ .end = GPIO_TO_IRQ(CG2900_BT_CTS_GPIO),
+ .flags = IORESOURCE_IRQ,
+ .name = "cts_irq",
+ },
+};
+
+static pin_cfg_t cg2900_uart_enabled[] = {
+ GPIO0_U0_CTSn | PIN_INPUT_PULLUP,
+ GPIO1_U0_RTSn | PIN_OUTPUT_HIGH,
+ GPIO2_U0_RXD | PIN_INPUT_PULLUP,
+ GPIO3_U0_TXD | PIN_OUTPUT_HIGH
+};
+
+static pin_cfg_t cg2900_uart_disabled[] = {
+ GPIO0_GPIO | PIN_INPUT_PULLUP, /* CTS pull up. */
+ GPIO1_GPIO | PIN_OUTPUT_HIGH, /* RTS high-flow off. */
+ GPIO2_GPIO | PIN_INPUT_PULLUP, /* RX pull down. */
+ GPIO3_GPIO | PIN_OUTPUT_LOW /* TX low - break on. */
+};
+
+static struct cg2900_platform_data cg2900_uart_platform_data = {
+ .bus = HCI_UART,
+ .gpio_sleep = cg2900_sleep_gpio,
+ .uart = {
+ .n_uart_gpios = 4,
+ .uart_enabled = cg2900_uart_enabled,
+ .uart_disabled = cg2900_uart_disabled,
+ },
+};
+
+static struct platform_device ux500_cg2900_uart_device = {
+ .name = "cg2900-uart",
+ .dev = {
+ .platform_data = &cg2900_uart_platform_data,
+ .parent = &ux500_cg2900_device.dev,
+ },
+ .num_resources = ARRAY_SIZE(cg2900_uart_resources),
+ .resource = cg2900_uart_resources,
+};
+#endif /* CONFIG_MFD_CG2900_UART */
+#endif /* CONFIG_MFD_CG2900 */
+
+static struct platform_device *u8500_platform_devices[] __initdata = {
+ /*TODO - add platform devices here */
+};
+
+static struct platform_device *platform_devs[] __initdata = {
+ &u8500_hsit_device,
+ &u8500_hsir_device,
+ &u8500_shrm_device,
+ &ux500_musb_device,
+ &ux500_hwmem_device,
+ &ux500_mcde_device,
+ &ux500_b2r2_device,
+};
+
+static void __init mop500_i2c_init(void)
+{
+ db8500_add_i2c0(&mop500_i2c0_data);
+ db8500_add_i2c1(&mop500_i2c1_data);
+ db8500_add_i2c2(&mop500_i2c2_data);
+ db8500_add_i2c3(&mop500_i2c3_data);
+
+ i2c_register_board_info(0, ARRAY_AND_SIZE(mop500_i2c0_devices));
+ i2c_register_board_info(1, ARRAY_AND_SIZE(mop500_i2c1_devices));
+ i2c_register_board_info(2, ARRAY_AND_SIZE(mop500_i2c2_devices));
+ i2c_register_board_info(3, ARRAY_AND_SIZE(mop500_i2c3_devices));
+}
+
+static void __init mop500_spi_init(void)
+{
+ db8500_add_ssp0(&mop500_ssp0_data);
+ db8500_add_msp2_spi(&mop500_msp2_spi_data);
+}
+
+static void __init mop500_uart_init(void)
+{
+ db8500_add_uart0();
+ db8500_add_uart1();
+ db8500_add_uart2();
+}
+
+static void __init mop500_init_machine(void)
+{
+#ifdef CONFIG_REGULATOR
+ platform_device_register(&u8500_regulator_dev);
+#endif
+
+ u8500_init_devices();
+
+ platform_add_devices(platform_devs,
+ ARRAY_SIZE(platform_devs));
+
+ snowball_pins_init();
+
+ platform_device_register(&ux500_ab8500_device);
+
+#ifdef CONFIG_MFD_CG2900
+#ifdef CONFIG_MFD_CG2900_TEST
+ dcg2900_init_platdata(&cg2900_test_platform_data);
+#endif /* CONFIG_MFD_CG2900_TEST */
+#ifdef CONFIG_MFD_CG2900_UART
+ dcg2900_init_platdata(&cg2900_uart_platform_data);
+#endif /* CONFIG_MFD_CG2900_UART */
+
+ platform_device_register(&ux500_cg2900_device);
+#ifdef CONFIG_MFD_CG2900_UART
+ platform_device_register(&ux500_cg2900_uart_device);
+#endif /* CONFIG_MFD_CG2900_UART */
+#ifdef CONFIG_MFD_CG2900_TEST
+ platform_device_register(&ux500_cg2900_test_device);
+#endif /* CONFIG_MFD_CG2900_TEST */
+#ifdef CONFIG_MFD_CG2900_CHIP
+ platform_device_register(&ux500_cg2900_chip_device);
+#endif /* CONFIG_MFD_CG2900_CHIP */
+#ifdef CONFIG_MFD_STLC2690_CHIP
+ platform_device_register(&ux500_stlc2690_chip_device);
+#endif /* CONFIG_MFD_STLC2690_CHIP */
+#endif /* CONFIG_MFD_CG2900 */
+
+ mop500_i2c_init();
+ mop500_msp_init();
+ mop500_spi_init();
+ mop500_uart_init();
+
+ hsi_register_board_info(stm_hsi_devices, ARRAY_SIZE(stm_hsi_devices));
+
+ platform_add_devices(u8500_platform_devices,
+ ARRAY_SIZE(u8500_platform_devices));
+}
+
+MACHINE_START(SNOWBALL, "ST-Ericsson Snowball board")
+ .phys_io = U8500_UART2_BASE,
+ .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = u8500_map_io,
+ .init_irq = ux500_init_irq,
+ .timer = &u8500_timer,
+ .init_machine = mop500_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-ux500/board-snowball.h b/arch/arm/mach-ux500/board-snowball.h
new file mode 100644
index 00000000000..d8bd2cd4ed2
--- /dev/null
+++ b/arch/arm/mach-ux500/board-snowball.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __SNOWBALL_H
+#define __SNOWBALL_H
+
+#define SNOWBALL_SDMMC_EN_GPIO 217
+#define SNOWBALL_SDMMC_1V8_3V_GPIO 228
+#define SNOWBALL_SDMMC_CD_GPIO 218
+
+void mop500_msp_init(void);
+void __init snowball_pins_init(void);
+
+int msp13_i2s_init(void);
+int msp13_i2s_exit(void);
+
+#endif
diff --git a/arch/arm/mach-ux500/board-svp5500.c b/arch/arm/mach-ux500/board-svp5500.c
new file mode 100644
index 00000000000..61477e93ef5
--- /dev/null
+++ b/arch/arm/mach-ux500/board-svp5500.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/pincfg.h>
+
+#include <mach/devices.h>
+#include <mach/setup.h>
+
+#include "pins-db5500.h"
+#include "devices-db5500.h"
+
+static pin_cfg_t svp5500_pins[] = {
+ GPIO28_U0_TXD,
+ GPIO29_U0_RXD,
+};
+
+static void __init svp5500_init_machine(void)
+{
+ u5500_init_devices();
+
+ nmk_config_pins(ARRAY_AND_SIZE(svp5500_pins));
+
+ db5500_add_uart0();
+}
+
+MACHINE_START(SVP5500, "ST-Ericsson U5500 Simulator")
+ .phys_io = U5500_UART0_BASE,
+ .io_pg_offst = (IO_ADDRESS(U5500_UART0_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = u5500_map_io,
+ .init_irq = ux500_init_irq,
+ .timer = &u8500_timer,
+ .init_machine = svp5500_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-ux500/board-svp8500.c b/arch/arm/mach-ux500/board-svp8500.c
new file mode 100644
index 00000000000..78a7842b77e
--- /dev/null
+++ b/arch/arm/mach-ux500/board-svp8500.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/pincfg.h>
+
+#include <mach/devices.h>
+#include <mach/hardware.h>
+#include <mach/setup.h>
+
+#include "devices-db8500.h"
+#include "pins-db8500.h"
+
+static pin_cfg_t svp8500_pins[] = {
+ /* UART */
+ GPIO0_U0_CTSn | PIN_INPUT_PULLUP,
+ GPIO1_U0_RTSn | PIN_OUTPUT_HIGH,
+ GPIO2_U0_RXD | PIN_INPUT_PULLUP,
+ GPIO3_U0_TXD | PIN_OUTPUT_HIGH,
+ GPIO4_U1_RXD | PIN_INPUT_PULLUP,
+ GPIO5_U1_TXD | PIN_OUTPUT_HIGH,
+ GPIO6_U1_CTSn | PIN_INPUT_PULLUP,
+ GPIO7_U1_RTSn | PIN_OUTPUT_HIGH,
+ GPIO29_U2_RXD | PIN_INPUT_PULLUP,
+ GPIO30_U2_TXD | PIN_OUTPUT_HIGH,
+ GPIO31_U2_CTSn | PIN_INPUT_PULLUP,
+ GPIO32_U2_RTSn | PIN_OUTPUT_HIGH,
+};
+
+static void __init svp8500_uart_init(void)
+{
+ db8500_add_uart0(NULL);
+ db8500_add_uart1();
+ db8500_add_uart2();
+}
+
+static void __init svp8500_init_machine(void)
+{
+ nmk_config_pins(ARRAY_AND_SIZE(svp8500_pins));
+
+ svp8500_uart_init();
+}
+
+MACHINE_START(SVP8500V1, "ST-Ericsson U8500 Simulator (V1)")
+ .phys_io = U8500_UART2_BASE,
+ .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = u8500_map_io,
+ .init_irq = ux500_init_irq,
+ .timer = &u8500_timer,
+ .init_machine = svp8500_init_machine,
+MACHINE_END
+
+MACHINE_START(SVP8500V2, "ST-Ericsson U8500 Simulator (V2)")
+ .phys_io = U8500_UART2_BASE,
+ .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = u8500_map_io,
+ .init_irq = ux500_init_irq,
+ .timer = &u8500_timer,
+ .init_machine = svp8500_init_machine,
+MACHINE_END
diff --git a/arch/arm/mach-ux500/board-u5500-cg2900.c b/arch/arm/mach-ux500/board-u5500-cg2900.c
new file mode 100644
index 00000000000..a96d7743343
--- /dev/null
+++ b/arch/arm/mach-ux500/board-u5500-cg2900.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/platform_device.h>
+#include <linux/mfd/cg2900.h>
+#include <linux/gpio.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+
+#include <plat/gpio.h>
+#include <plat/pincfg.h>
+
+#include "devices-cg2900.h"
+#include "pins-db5500.h"
+
+#define CG2900_BT_CTS_GPIO 168
+
+enum cg2900_gpio_pull_sleep cg2900_sleep_gpio[21] = {
+ CG2900_NO_PULL, /* GPIO 0: PTA_CONFX */
+ CG2900_PULL_DN, /* GPIO 1: PTA_STATUS */
+ CG2900_NO_PULL, /* GPIO 2: UART_CTSN */
+ CG2900_PULL_UP, /* GPIO 3: UART_RTSN */
+ CG2900_PULL_UP, /* GPIO 4: UART_TXD */
+ CG2900_NO_PULL, /* GPIO 5: UART_RXD */
+ CG2900_PULL_DN, /* GPIO 6: IOM_DOUT */
+ CG2900_NO_PULL, /* GPIO 7: IOM_FSC */
+ CG2900_NO_PULL, /* GPIO 8: IOM_CLK */
+ CG2900_NO_PULL, /* GPIO 9: IOM_DIN */
+ CG2900_PULL_DN, /* GPIO 10: PWR_REQ */
+ CG2900_PULL_DN, /* GPIO 11: HOST_WAKEUP */
+ CG2900_PULL_DN, /* GPIO 12: IIS_DOUT */
+ CG2900_NO_PULL, /* GPIO 13: IIS_WS */
+ CG2900_NO_PULL, /* GPIO 14: IIS_CLK */
+ CG2900_NO_PULL, /* GPIO 15: IIS_DIN */
+ CG2900_PULL_DN, /* GPIO 16: PTA_FREQ */
+ CG2900_PULL_DN, /* GPIO 17: PTA_RF_ACTIVE */
+ CG2900_NO_PULL, /* GPIO 18: NotConnected (J6428) */
+ CG2900_NO_PULL, /* GPIO 19: EXT_DUTY_CYCLE */
+ CG2900_NO_PULL, /* GPIO 20: EXT_FRM_SYNCH */
+};
+
+static struct platform_device ux500_cg2900_device = {
+ .name = "cg2900",
+};
+
+#ifdef CONFIG_MFD_CG2900_CHIP
+static struct platform_device ux500_cg2900_chip_device = {
+ .name = "cg2900-chip",
+ .dev = {
+ .parent = &ux500_cg2900_device.dev,
+ },
+};
+#endif /* CONFIG_MFD_CG2900_CHIP */
+
+#ifdef CONFIG_MFD_CG2900_TEST
+static struct cg2900_platform_data cg2900_test_platform_data = {
+ .bus = HCI_VIRTUAL,
+ .gpio_sleep = cg2900_sleep_gpio,
+};
+
+static struct platform_device ux500_cg2900_test_device = {
+ .name = "cg2900-test",
+ .dev = {
+ .parent = &ux500_cg2900_device.dev,
+ .platform_data = &cg2900_test_platform_data,
+ },
+};
+#endif /* CONFIG_MFD_CG2900_TEST */
+
+#ifdef CONFIG_MFD_CG2900_UART
+static struct resource cg2900_uart_resources[] = {
+ {
+ .start = CG2900_BT_CTS_GPIO,
+ .end = CG2900_BT_CTS_GPIO,
+ .flags = IORESOURCE_IO,
+ .name = "cts_gpio",
+ },
+ {
+ .start = GPIO_TO_IRQ(CG2900_BT_CTS_GPIO),
+ .end = GPIO_TO_IRQ(CG2900_BT_CTS_GPIO),
+ .flags = IORESOURCE_IRQ,
+ .name = "cts_irq",
+ },
+};
+
+static pin_cfg_t cg2900_uart_enabled[] = {
+ GPIO165_U3_RXD | PIN_INPUT_PULLUP,
+ GPIO166_U3_TXD | PIN_OUTPUT_HIGH,
+ GPIO167_U3_RTSn | PIN_OUTPUT_HIGH,
+ GPIO168_U3_CTSn | PIN_INPUT_PULLUP,
+};
+
+static pin_cfg_t cg2900_uart_disabled[] = {
+ GPIO165_GPIO | PIN_INPUT_PULLUP, /* RX pull down. */
+ GPIO166_GPIO | PIN_OUTPUT_LOW, /* TX low - break on. */
+ GPIO167_GPIO | PIN_OUTPUT_HIGH, /* RTS high-flow off. */
+ GPIO168_GPIO | PIN_INPUT_PULLUP, /* CTS pull up. */
+};
+
+static struct cg2900_platform_data cg2900_uart_platform_data = {
+ .bus = HCI_UART,
+ .gpio_sleep = cg2900_sleep_gpio,
+ .uart = {
+ .n_uart_gpios = 4,
+ .uart_enabled = cg2900_uart_enabled,
+ .uart_disabled = cg2900_uart_disabled,
+ },
+};
+
+static struct platform_device ux500_cg2900_uart_device = {
+ .name = "cg2900-uart",
+ .dev = {
+ .platform_data = &cg2900_uart_platform_data,
+ .parent = &ux500_cg2900_device.dev,
+ },
+ .num_resources = ARRAY_SIZE(cg2900_uart_resources),
+ .resource = cg2900_uart_resources,
+};
+#endif /* CONFIG_MFD_CG2900_UART */
+
+void __init u5500_cg2900_init(void)
+{
+#ifdef CONFIG_MFD_CG2900_TEST
+ dcg2900_init_platdata(&cg2900_test_platform_data);
+#endif /* CONFIG_MFD_CG2900_TEST */
+#ifdef CONFIG_MFD_CG2900_UART
+ dcg2900_init_platdata(&cg2900_uart_platform_data);
+#endif /* CONFIG_MFD_CG2900_UART */
+
+ platform_device_register(&ux500_cg2900_device);
+#ifdef CONFIG_MFD_CG2900_UART
+ platform_device_register(&ux500_cg2900_uart_device);
+#endif /* CONFIG_MFD_CG2900_UART */
+#ifdef CONFIG_MFD_CG2900_TEST
+ platform_device_register(&ux500_cg2900_test_device);
+#endif /* CONFIG_MFD_CG2900_TEST */
+#ifdef CONFIG_MFD_CG2900_CHIP
+ platform_device_register(&ux500_cg2900_chip_device);
+#endif /* CONFIG_MFD_CG2900_CHIP */
+}
diff --git a/arch/arm/mach-ux500/board-u5500-mcde.c b/arch/arm/mach-ux500/board-u5500-mcde.c
new file mode 100644
index 00000000000..cf7d98ed6ed
--- /dev/null
+++ b/arch/arm/mach-ux500/board-u5500-mcde.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Marcus Lorentzon <marcus.xm.lorentzon@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/dispdev.h>
+#include <video/av8100.h>
+#include <video/mcde_display.h>
+#include <video/mcde_display-generic_dsi.h>
+#include <video/mcde_display-av8100.h>
+#include <video/mcde_fb.h>
+#include <video/mcde_dss.h>
+
+#define DSI_UNIT_INTERVAL_0 0xA
+#define DSI_UNIT_INTERVAL_2 0x5
+
+#define PRIMARY_DISPLAY_ID 0
+#define TERTIARY_DISPLAY_ID 1
+
+#ifdef CONFIG_FB_MCDE
+
+/* The initialization of hdmi disp driver must be delayed in order to
+ * ensure that inputclk will be available (needed by hdmi hw) */
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+static struct delayed_work work_dispreg_hdmi;
+#define DISPREG_HDMI_DELAY 6000
+#endif
+
+#define MCDE_NR_OF_DISPLAYS 2
+static int display_initialized_during_boot;
+
+static int __init startup_graphics_setup(char *str)
+{
+
+ if (get_option(&str, &display_initialized_during_boot) != 1)
+ display_initialized_during_boot = 0;
+
+ switch (display_initialized_during_boot) {
+ case 1:
+ pr_info("Startup graphics support\n");
+ break;
+ case 0:
+ default:
+ pr_info("No startup graphics supported\n");
+ break;
+ };
+
+ return 1;
+}
+__setup("startup_graphics=", startup_graphics_setup);
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY
+static struct mcde_port port0 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = DSI_VIDEO_MODE,
+ .link = 0,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+ .sync_src = MCDE_SYNCSRC_OFF,
+ .update_auto_trig = true,
+#else
+ .sync_src = MCDE_SYNCSRC_BTA,
+ .update_auto_trig = false,
+#endif
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_0,
+ .clk_cont = false,
+ .data_lanes_swap = false,
+ },
+ },
+};
+
+struct mcde_display_generic_platform_data generic_display0_pdata = {
+ .reset_gpio = 226,
+ .reset_delay = 10,
+ .sleep_out_delay = 140,
+#ifdef CONFIG_REGULATOR
+ .regulator_id = "v-display",
+ .min_supply_voltage = 2500000, /* 2.5V */
+ .max_supply_voltage = 2700000 /* 2.7V */
+#endif
+};
+
+struct mcde_display_device generic_display0 = {
+ .name = "mcde_disp_generic",
+ .id = PRIMARY_DISPLAY_ID,
+ .port = &port0,
+ .chnl_id = MCDE_CHNL_A,
+ .fifo = MCDE_FIFO_A,
+#ifdef CONFIG_MCDE_DISPLAY_PRIMARY_16BPP
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+#else
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGBA8888,
+#endif
+ .native_x_res = 864,
+ .native_y_res = 480,
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_VSYNC
+ .synchronized_update = true,
+#else
+ .synchronized_update = false,
+#endif
+ /* TODO: Remove rotation buffers once ESRAM driver is completed */
+ .rotbuf1 = U5500_ESRAM_BASE + 0x20000 * 2,
+ .rotbuf2 = U5500_ESRAM_BASE + 0x20000 * 2 + 0x10000,
+ .dev = {
+ .platform_data = &generic_display0_pdata,
+ },
+};
+#endif /* CONFIG_DISPLAY_GENERIC_DSI_PRIMARY */
+
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+static struct mcde_port port2 = {
+ .type = MCDE_PORTTYPE_DSI,
+ .mode = MCDE_PORTMODE_CMD,
+ .pixel_format = MCDE_PORTPIXFMT_DSI_24BPP,
+ .ifc = DSI_VIDEO_MODE,
+ .link = 1,
+#ifdef CONFIG_AV8100_HWTRIG_INT
+ .sync_src = MCDE_SYNCSRC_TE0,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_I2SDAT3
+ .sync_src = MCDE_SYNCSRC_TE1,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_DSI_TE
+ .sync_src = MCDE_SYNCSRC_TE_POLLING,
+#endif
+#ifdef CONFIG_AV8100_HWTRIG_NONE
+ .sync_src = MCDE_SYNCSRC_OFF,
+#endif
+ .update_auto_trig = true,
+ .phy = {
+ .dsi = {
+ .virt_id = 0,
+ .num_data_lanes = 2,
+ .ui = DSI_UNIT_INTERVAL_2,
+ .clk_cont = false,
+ .data_lanes_swap = false,
+ },
+ },
+ .hdmi_sdtv_switch = HDMI_SWITCH,
+};
+
+struct mcde_display_hdmi_platform_data av8100_hdmi_pdata = {
+ .reset_gpio = 0,
+ .reset_delay = 1,
+ .regulator_id = NULL,
+ .cvbs_regulator_id = "v-av8100-AV-switch",
+ .ddb_id = 1,
+ .rgb_2_yCbCr_transform = {
+ .matrix = {
+ {0x42, 0x81, 0x19},
+ {0xffda, 0xffb6, 0x70},
+ {0x70, 0xffa2, 0xffee},
+ },
+ .offset = {0x80, 0x10, 0x80},
+ }
+};
+
+struct mcde_display_device av8100_hdmi = {
+ .name = "av8100_hdmi",
+ .id = TERTIARY_DISPLAY_ID,
+ .port = &port2,
+ .chnl_id = MCDE_CHNL_B,
+ .fifo = MCDE_FIFO_B,
+ .default_pixel_format = MCDE_OVLYPIXFMT_RGB565,
+ .native_x_res = 1280,
+ .native_y_res = 720,
+ .synchronized_update = false,
+ .dev = {
+ .platform_data = &av8100_hdmi_pdata,
+ },
+ .platform_enable = NULL,
+ .platform_disable = NULL,
+};
+
+static void delayed_work_dispreg_hdmi(struct work_struct *ptr)
+{
+ if (mcde_display_device_register(&av8100_hdmi))
+ pr_warning("Failed to register av8100_hdmi\n");
+}
+#endif /* CONFIG_DISPLAY_AV8100_TERTIARY */
+
+/*
+* This function will create the framebuffer for the display that is registered.
+*/
+static int display_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *dev)
+{
+ struct mcde_display_device *ddev = dev;
+ u16 width, height;
+ u16 virtual_width, virtual_height;
+ u32 rotate = FB_ROTATE_UR;
+ struct fb_info *fbi;
+
+ if (event != MCDE_DSS_EVENT_DISPLAY_REGISTERED)
+ return 0;
+
+ if (ddev->id < PRIMARY_DISPLAY_ID || ddev->id >= MCDE_NR_OF_DISPLAYS)
+ return 0;
+
+ mcde_dss_get_native_resolution(ddev, &width, &height);
+
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY
+ if (ddev->id == PRIMARY_DISPLAY_ID) {
+ switch (CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE) {
+ case 0:
+ rotate = FB_ROTATE_UR;
+ break;
+ case 90:
+ rotate = FB_ROTATE_CW;
+ swap(width, height);
+ break;
+ case 180:
+ rotate = FB_ROTATE_UD;
+ break;
+ case 270:
+ rotate = FB_ROTATE_CCW;
+ swap(width, height);
+ break;
+ }
+ }
+#endif
+
+ virtual_width = width;
+ virtual_height = height * 2;
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+ if (ddev->id == PRIMARY_DISPLAY_ID)
+ virtual_height = height;
+#endif
+
+ if (ddev->id == TERTIARY_DISPLAY_ID) {
+#ifdef CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE
+ hdmi_fb_onoff(ddev, 1, 0, 0);
+#endif /* CONFIG_MCDE_DISPLAY_HDMI_FB_AUTO_CREATE */
+ } else {
+ /* Create frame buffer */
+ fbi = mcde_fb_create(ddev,
+ width, height,
+ virtual_width, virtual_height,
+ ddev->default_pixel_format,
+ rotate);
+
+ if (IS_ERR(fbi))
+ dev_warn(&ddev->dev,
+ "Failed to create fb for display %s\n",
+ ddev->name);
+ else
+ dev_info(&ddev->dev, "Framebuffer created (%s)\n",
+ ddev->name);
+
+#ifdef CONFIG_DISPDEV
+ /* Create a dispdev overlay for this display */
+ if (dispdev_create(ddev, true) < 0)
+ dev_warn(&ddev->dev,
+ "Failed to create disp for display %s\n",
+ ddev->name);
+ else
+ dev_info(&ddev->dev, "Disp dev created for (%s)\n",
+ ddev->name);
+#endif
+ }
+
+ return 0;
+}
+
+static struct notifier_block display_nb = {
+ .notifier_call = display_postregistered_callback,
+};
+
+/*
+* This function is used to refresh the display (lcd, hdmi, tvout) with black
+* when the framebuffer is registered.
+* The main display will not be updated if startup graphics is displayed
+* from u-boot.
+*/
+#ifdef CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_AUTO_SYNC
+static int framebuffer_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int ret = 0;
+ struct fb_event *event_data = data;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+ int i;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
+
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ var = info->var;
+ fix = info->fix;
+
+ /* Apply overlay info */
+ for (i = 0; i < mfb->num_ovlys; i++) {
+ struct mcde_overlay *ovly = mfb->ovlys[i];
+ struct mcde_overlay_info ovly_info;
+ struct mcde_fb *mfb = to_mcde_fb(info);
+ memset(&ovly_info, 0, sizeof(ovly_info));
+ ovly_info.paddr = fix.smem_start +
+ fix.line_length * var.yoffset;
+ if (ovly_info.paddr + fix.line_length * var.yres
+ > fix.smem_start + fix.smem_len)
+ ovly_info.paddr = fix.smem_start;
+ ovly_info.fmt = mfb->pix_fmt;
+ ovly_info.stride = fix.line_length;
+ ovly_info.w = var.xres;
+ ovly_info.h = var.yres;
+ ovly_info.dirty.w = var.xres;
+ ovly_info.dirty.h = var.yres;
+ (void) mcde_dss_apply_overlay(ovly, &ovly_info);
+ ret = mcde_dss_update_overlay(ovly);
+ if (ret)
+ break;
+ }
+
+ return ret;
+}
+#else
+static int framebuffer_postregistered_callback(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ int ret = 0;
+ struct fb_event *event_data = data;
+ struct fb_info *info;
+ struct fb_var_screeninfo var;
+ struct fb_fix_screeninfo fix;
+ struct mcde_fb *mfb;
+
+ if (event != FB_EVENT_FB_REGISTERED)
+ return 0;
+
+ if (!event_data)
+ return 0;
+
+ info = event_data->info;
+ mfb = to_mcde_fb(info);
+ if (mfb->id == 0 && display_initialized_during_boot)
+ goto out;
+
+ var = info->var;
+ fix = info->fix;
+ var.yoffset = var.yoffset ? 0 : var.yres;
+ if (info->fbops->fb_pan_display)
+ ret = info->fbops->fb_pan_display(&var, info);
+out:
+ return ret;
+}
+#endif
+
+
+static struct notifier_block framebuffer_nb = {
+ .notifier_call = framebuffer_postregistered_callback,
+};
+
+int __init init_display_devices(void)
+{
+ int ret;
+
+ ret = fb_register_client(&framebuffer_nb);
+ if (ret)
+ pr_warning("Failed to register framebuffer notifier\n");
+
+ ret = mcde_dss_register_notifier(&display_nb);
+ if (ret)
+ pr_warning("Failed to register dss notifier\n");
+
+#ifdef CONFIG_DISPLAY_GENERIC_PRIMARY
+ if (display_initialized_during_boot)
+ generic_display0.power_mode = MCDE_DISPLAY_PM_STANDBY;
+ ret = mcde_display_device_register(&generic_display0);
+ if (ret)
+ pr_warning("Failed to register generic display device 0\n");
+#endif
+
+#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
+ INIT_DELAYED_WORK_DEFERRABLE(&work_dispreg_hdmi,
+ delayed_work_dispreg_hdmi);
+
+ schedule_delayed_work(&work_dispreg_hdmi,
+ msecs_to_jiffies(DISPREG_HDMI_DELAY));
+#endif
+
+ return ret;
+}
+
+struct mcde_display_device *mcde_get_main_display(void)
+{
+#if defined(CONFIG_DISPLAY_GENERIC_DSI_PRIMARY)
+ return &generic_display0;
+#elif defined(CONFIG_DISPLAY_AV8100_TERTIARY)
+ return &av8100_hdmi;
+#else
+ return NULL;
+#endif
+}
+EXPORT_SYMBOL(mcde_get_main_display);
+
+void hdmi_fb_onoff(struct mcde_display_device *ddev,
+ bool enable, u8 cea, u8 vesa_cea_nr)
+{
+ struct fb_info *fbi;
+ u16 w, h;
+ u16 vw, vh;
+ u32 rotate = FB_ROTATE_UR;
+ struct display_driver_data *driver_data = dev_get_drvdata(&ddev->dev);
+
+ dev_dbg(&ddev->dev, "%s\n", __func__);
+ dev_dbg(&ddev->dev, "en:%d cea:%d nr:%d\n", enable, cea, vesa_cea_nr);
+
+ if (enable) {
+ if (ddev->enabled) {
+ dev_dbg(&ddev->dev, "Display is already enabled.\n");
+ return;
+ }
+
+ /* Create fb */
+ if (ddev->fbi == NULL) {
+ /* Note: change when dynamic buffering is available */
+ int buffering = 2;
+
+ /* Get default values */
+ mcde_dss_get_native_resolution(ddev, &w, &h);
+ vw = w;
+ vh = h * buffering;
+
+ if (vesa_cea_nr != 0)
+ ddev->ceanr_convert(ddev, cea, vesa_cea_nr,
+ buffering, &w, &h, &vw, &vh);
+
+ fbi = mcde_fb_create(ddev, w, h, vw, vh,
+ ddev->default_pixel_format, rotate);
+
+ if (IS_ERR(fbi)) {
+ dev_warn(&ddev->dev,
+ "Failed to create fb for display %s\n",
+ ddev->name);
+ goto hdmi_fb_onoff_end;
+ } else {
+ dev_info(&ddev->dev,
+ "Framebuffer created (%s)\n",
+ ddev->name);
+ }
+ driver_data->fbdevname = (char *)dev_name(fbi->dev);
+
+#ifdef CONFIG_DISPDEV
+ /* Create a dispdev overlay for this display */
+ if (dispdev_create(ddev, true) < 0)
+ dev_warn(&ddev->dev,
+ "Failed to create disp for %s\n",
+ ddev->name);
+ else
+ dev_info(&ddev->dev,
+ "Disp dev created for (%s)\n",
+ ddev->name);
+#endif /* CONFIG_DISPDEV */
+ }
+ } else {
+ if (!ddev->enabled) {
+ dev_dbg(&ddev->dev, "Display %s is already disabled.\n",
+ ddev->name);
+ return;
+ }
+
+#ifdef CONFIG_DISPDEV
+ dispdev_destroy(ddev);
+#endif /* CONFIG_DISPDEV */
+ mcde_fb_destroy(ddev);
+ }
+
+hdmi_fb_onoff_end:
+ return;
+}
+EXPORT_SYMBOL(hdmi_fb_onoff);
+
+module_init(init_display_devices);
+#endif
diff --git a/arch/arm/mach-ux500/board-u5500-pins.c b/arch/arm/mach-ux500/board-u5500-pins.c
new file mode 100644
index 00000000000..ddbe827ca83
--- /dev/null
+++ b/arch/arm/mach-ux500/board-u5500-pins.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <plat/pincfg.h>
+#include <plat/gpio.h>
+
+#include "pins-db5500.h"
+#include "pins.h"
+
+static pin_cfg_t u5500_pins_default[] = {
+ /* Keypad */
+ GPIO128_KP_I0 | PIN_INPUT_PULLUP,
+ GPIO130_KP_I1 | PIN_INPUT_PULLUP,
+ GPIO132_KP_I2 | PIN_INPUT_PULLUP,
+ GPIO134_KP_I3 | PIN_INPUT_PULLUP,
+ GPIO137_KP_O4 | PIN_INPUT_PULLUP,
+ GPIO139_KP_O5 | PIN_INPUT_PULLUP,
+
+ /* MSP */
+ GPIO32_MSP0_TCK | PIN_INPUT_PULLDOWN,
+ GPIO33_MSP0_TFS | PIN_INPUT_PULLDOWN,
+ GPIO34_MSP0_TXD | PIN_INPUT_PULLDOWN,
+ GPIO35_MSP0_RXD | PIN_INPUT_PULLDOWN,
+ GPIO96_MSP1_TCK | PIN_INPUT_PULLDOWN,
+ GPIO97_MSP1_TFS | PIN_INPUT_PULLDOWN,
+ GPIO98_MSP1_TXD | PIN_INPUT_PULLDOWN,
+ GPIO99_MSP1_RXD | PIN_INPUT_PULLDOWN,
+ GPIO220_MSP2_TCK | PIN_OUTPUT_LOW,
+ GPIO221_MSP2_TFS | PIN_OUTPUT_LOW,
+ GPIO222_MSP2_TXD | PIN_OUTPUT_LOW,
+
+ /* DISPLAY_ENABLE */
+ GPIO226_GPIO | PIN_OUTPUT_LOW,
+
+ /* Backlight Enable */
+ GPIO224_GPIO | PIN_OUTPUT_HIGH,
+
+ /* MMC0 (POP eMMC) */
+ GPIO5_MC0_DAT0 | PIN_INPUT_PULLUP,
+ GPIO6_MC0_DAT1 | PIN_INPUT_PULLUP,
+ GPIO7_MC0_DAT2 | PIN_INPUT_PULLUP,
+ GPIO8_MC0_DAT3 | PIN_INPUT_PULLUP,
+ GPIO9_MC0_DAT4 | PIN_INPUT_PULLUP,
+ GPIO10_MC0_DAT5 | PIN_INPUT_PULLUP,
+ GPIO11_MC0_DAT6 | PIN_INPUT_PULLUP,
+ GPIO12_MC0_DAT7 | PIN_INPUT_PULLUP,
+ GPIO13_MC0_CMD | PIN_INPUT_PULLUP,
+ GPIO14_MC0_CLK | PIN_OUTPUT_LOW,
+
+ /* UART3 */
+ GPIO165_U3_RXD | PIN_INPUT_PULLUP,
+ GPIO166_U3_TXD | PIN_OUTPUT_HIGH,
+ GPIO167_U3_RTSn | PIN_OUTPUT_HIGH,
+ GPIO168_U3_CTSn | PIN_INPUT_PULLUP,
+
+ /* AB5500 */
+ GPIO78_IRQn,
+
+ /* TOUCH_IRQ */
+ GPIO179_GPIO | PIN_INPUT_PULLUP,
+
+ /* SDI1 (SD-CARD) */
+ GPIO191_MC1_DAT0 | PIN_INPUT_PULLUP,
+ GPIO192_MC1_DAT1 | PIN_INPUT_PULLUP,
+ GPIO193_MC1_DAT2 | PIN_INPUT_PULLUP,
+ GPIO194_MC1_DAT3 | PIN_INPUT_PULLUP,
+ GPIO195_MC1_CLK | PIN_OUTPUT_LOW,
+ GPIO196_MC1_CMD | PIN_INPUT_PULLUP,
+ GPIO197_MC1_CMDDIR | PIN_OUTPUT_HIGH,
+ GPIO198_MC1_FBCLK | PIN_INPUT_NOPULL,
+ GPIO199_MC1_DAT0DIR | PIN_OUTPUT_HIGH,
+ /* SD-CARD detect/levelshifter pins */
+ GPIO180_GPIO | PIN_INPUT_PULLUP,
+ GPIO227_GPIO,
+ GPIO185_GPIO,
+
+ /* SDI3 (SDIO) */
+ GPIO171_MC3_DAT0 | PIN_INPUT_PULLUP,
+ GPIO172_MC3_DAT1 | PIN_INPUT_PULLUP,
+ GPIO173_MC3_DAT2 | PIN_INPUT_PULLUP,
+ GPIO174_MC3_DAT3 | PIN_INPUT_PULLUP,
+ GPIO175_MC3_CMD | PIN_INPUT_PULLUP,
+ GPIO176_MC3_CLK | PIN_OUTPUT_LOW,
+
+ /* Display & HDMI HW sync */
+ GPIO204_LCD_VSI1 | PIN_INPUT_PULLUP,
+};
+
+static UX500_PINS(u5500_pins_i2c1,
+ GPIO3_I2C1_SCL,
+ GPIO4_I2C1_SDA,
+);
+
+static UX500_PINS(u5500_pins_i2c2,
+ GPIO218_I2C2_SCL,
+ GPIO219_I2C2_SDA,
+);
+
+static struct ux500_pin_lookup u5500_pins[] = {
+ PIN_LOOKUP("nmk-i2c.1", &u5500_pins_i2c1),
+ PIN_LOOKUP("nmk-i2c.2", &u5500_pins_i2c2),
+};
+
+void __init u5500_pins_init(void)
+{
+ nmk_config_pins(u5500_pins_default, ARRAY_SIZE(u5500_pins_default));
+ ux500_pins_add(u5500_pins, ARRAY_SIZE(u5500_pins));
+}
diff --git a/arch/arm/mach-ux500/board-u5500-regulators.c b/arch/arm/mach-ux500/board-u5500-regulators.c
new file mode 100644
index 00000000000..f2b17974227
--- /dev/null
+++ b/arch/arm/mach-ux500/board-u5500-regulators.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/ab5500.h>
+
+#include "regulator-u5500.h"
+#include "board-u5500.h"
+
+/*
+ * AB5500
+ */
+
+static struct regulator_consumer_supply ab5500_ldo_d_consumers[] = {
+};
+
+static struct regulator_consumer_supply ab5500_ldo_g_consumers[] = {
+ REGULATOR_SUPPLY("v-MMC-SD", "sdi1"),
+};
+
+static struct regulator_consumer_supply ab5500_ldo_h_consumers[] = {
+ REGULATOR_SUPPLY("v-display", NULL),
+ REGULATOR_SUPPLY("vdd", "1-004b"), /* Synaptics */
+ REGULATOR_SUPPLY("vin", "2-0036"), /* LM3530 */
+};
+
+static struct regulator_consumer_supply ab5500_ldo_k_consumers[] = {
+ REGULATOR_SUPPLY("v-accel", "lsm303dlh.0"),
+ REGULATOR_SUPPLY("v-mag", "lsm303dlh.1"),
+ REGULATOR_SUPPLY("v-mmio-camera", "mmio_camera"),
+};
+
+static struct regulator_consumer_supply ab5500_ldo_l_consumers[] = {
+};
+
+static struct regulator_consumer_supply ab5500_ldo_s_consumers[] = {
+ REGULATOR_SUPPLY("v-ana", "mcde"),
+ REGULATOR_SUPPLY("v-ana", "mmio_camera"),
+};
+
+static struct regulator_consumer_supply ab5500_ldo_vdigmic_consumers[] = {
+};
+
+static struct regulator_consumer_supply ab5500_ldo_sim_consumers[] = {
+};
+
+static struct regulator_init_data
+ab5500_regulator_init_data[AB5500_NUM_REGULATORS] = {
+ /* AB internal analog */
+ [AB5500_LDO_D] = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = ab5500_ldo_d_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_d_consumers),
+ },
+ /* SD Card */
+ [AB5500_LDO_G] = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 2910000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = ab5500_ldo_g_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_g_consumers),
+ },
+ /* Display */
+ [AB5500_LDO_H] = {
+ .constraints = {
+ .min_uV = 2790000,
+ .max_uV = 2790000,
+ .apply_uV = 1,
+ .boot_on = 1, /* display on during boot */
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = ab5500_ldo_h_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_h_consumers),
+ },
+ /* Camera */
+ [AB5500_LDO_K] = {
+ .constraints = {
+ .min_uV = 2790000,
+ .max_uV = 2790000,
+ .apply_uV = 1,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = ab5500_ldo_k_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_k_consumers),
+ },
+ /* External eMMC */
+ [AB5500_LDO_L] = {
+ .constraints = {
+ .min_uV = 1200000,
+ .max_uV = 2910000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = ab5500_ldo_l_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_l_consumers),
+ },
+ [AB5500_LDO_S] = {
+ .constraints = {
+ .name = "VANA",
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = ab5500_ldo_s_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_s_consumers),
+ },
+ [AB5500_LDO_VDIGMIC] = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = ab5500_ldo_vdigmic_consumers,
+ .num_consumer_supplies =
+ ARRAY_SIZE(ab5500_ldo_vdigmic_consumers),
+ },
+ [AB5500_LDO_SIM] = {
+ .constraints = {
+ .min_uV = 1875000,
+ .max_uV = 2900000,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = ab5500_ldo_sim_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(ab5500_ldo_sim_consumers),
+ },
+};
+
+struct ab5500_regulator_platform_data u5500_ab5500_regulator_data = {
+ .regulator = ab5500_regulator_init_data,
+ .num_regulator = ARRAY_SIZE(ab5500_regulator_init_data),
+};
+
+/*
+ * Power state, ePOD, etc.
+ */
+
+static struct regulator_consumer_supply u5500_vape_consumers[] = {
+ REGULATOR_SUPPLY("v-ape", NULL),
+ REGULATOR_SUPPLY("v-i2c", "nmk-i2c.0"),
+ REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"),
+ REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"),
+ REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"),
+ REGULATOR_SUPPLY("v-mmc", "sdi0"),
+ REGULATOR_SUPPLY("v-mmc", "sdi1"),
+ REGULATOR_SUPPLY("v-mmc", "sdi2"),
+ REGULATOR_SUPPLY("v-mmc", "sdi3"),
+ REGULATOR_SUPPLY("v-mmc", "sdi4"),
+ REGULATOR_SUPPLY("v-uart", "uart0"),
+ REGULATOR_SUPPLY("v-uart", "uart1"),
+ REGULATOR_SUPPLY("v-uart", "uart2"),
+ REGULATOR_SUPPLY("v-uart", "uart3"),
+};
+
+static struct regulator_init_data *
+u5500_regulator_init_data[U5500_NUM_REGULATORS] __initdata = {
+ [U5500_REGULATOR_VAPE] = (struct regulator_init_data []) {
+ {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .consumer_supplies = u5500_vape_consumers,
+ .num_consumer_supplies = ARRAY_SIZE(u5500_vape_consumers),
+ }
+ },
+};
+
+void __init u5500_regulators_init(void)
+{
+ platform_device_register_data(NULL, "u5500-regulators", -1,
+ u5500_regulator_init_data,
+ sizeof(u5500_regulator_init_data));
+}
diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c
new file mode 100644
index 00000000000..f42c5b4e4b3
--- /dev/null
+++ b/arch/arm/mach-ux500/board-u5500-sdi.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2010 ST-Ericsson
+ *
+ * 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/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
+#include <linux/mmc/host.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <plat/ste_dma40.h>
+#include <plat/pincfg.h>
+#include <mach/devices.h>
+#include <mach/gpio.h>
+#include <mach/ste-dma40-db5500.h>
+
+#include "pins-db5500.h"
+#include "devices-db5500.h"
+#include "board-u5500.h"
+
+/*
+ * SDI0 (EMMC)
+ */
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg sdi0_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB5500_DMA_DEV24_SDMMC0_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg sdi0_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB5500_DMA_DEV24_SDMMC0_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+/*
+ * SDI1 (SD/MMC)
+ */
+
+static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB5500_DMA_DEV25_SDMMC1_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg sdi1_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB5500_DMA_DEV25_SDMMC1_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+/*
+ * SDI3 (SDIO)
+ */
+static struct stedma40_chan_cfg sdi3_dma_cfg_rx = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB5500_DMA_DEV27_SDMMC3_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg sdi3_dma_cfg_tx = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB5500_DMA_DEV27_SDMMC3_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+#endif
+
+static struct mmci_platform_data u5500_sdi0_data = {
+ .vcc = "v-mmc",
+ .ocr_mask = MMC_VDD_165_195,
+ .f_max = 50000000,
+ .disable = 500,
+ .pm_flags = MMC_PM_KEEP_POWER,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED |
+ MMC_CAP_DISABLE,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &sdi0_dma_cfg_rx,
+ .dma_tx_param = &sdi0_dma_cfg_tx,
+#endif
+};
+
+static void u5500_sdi1_vdd_handler(struct device *dev, unsigned int vdd,
+ unsigned char power_mode)
+{
+ switch (power_mode) {
+ case MMC_POWER_UP:
+ case MMC_POWER_ON:
+ /*
+ * Level shifter voltage should depend on vdd to when deciding
+ * on either 1.8V or 2.9V. Once the decision has been made the
+ * level shifter must be disabled and re-enabled with a changed
+ * select signal in order to switch the voltage. Since there is
+ * no framework support yet for indicating 1.8V in vdd, use the
+ * default 2.9V.
+ */
+
+ /* Enable level shifter */
+ gpio_direction_output(GPIO_MMC_CARD_CTRL, 1);
+ udelay(100);
+ break;
+ case MMC_POWER_OFF:
+ /* Disable level shifter */
+ gpio_direction_output(GPIO_MMC_CARD_CTRL, 0);
+ break;
+ }
+}
+
+static struct mmci_platform_data u5500_sdi1_data = {
+ .vcc = "v-mmc",
+ .vcard = "v-MMC-SD",
+ .vdd_handler = u5500_sdi1_vdd_handler,
+ .ocr_mask = MMC_VDD_29_30,
+ .disable = 500,
+ .f_max = 50000000,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED |
+ MMC_CAP_DISABLE,
+ .gpio_cd = GPIO_SDMMC_CD,
+ .gpio_wp = -1,
+ .cd_invert = true,
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &sdi1_dma_cfg_rx,
+ .dma_tx_param = &sdi1_dma_cfg_tx,
+#endif
+};
+static void sdi1_configure(void)
+{
+ int pin[2];
+ int ret;
+
+ /* Level-shifter GPIOs */
+ pin[0] = GPIO_MMC_CARD_CTRL;
+ pin[1] = GPIO_MMC_CARD_VSEL;
+
+ ret = gpio_request(pin[0], "MMC_CARD_CTRL");
+ if (!ret)
+ ret = gpio_request(pin[1], "MMC_CARD_VSEL");
+
+ if (ret) {
+ pr_err("mach-u5500: error in configuring \
+ GPIO pins for MMC\n");
+ return;
+ }
+ /* Select the default 2.9V and eanble level shifter */
+ gpio_direction_output(pin[0], 1);
+ gpio_direction_output(pin[1], 1);
+
+}
+
+/*
+ * SDI3 (SDIO WLAN)
+ */
+static irqreturn_t sdio_irq(int irq, void *dev_id)
+{
+ struct mmc_host *host = dev_id;
+
+ /*
+ * Signal an sdio irq for the sdio client.
+ * If we are in suspend state the host has been claimed
+ * by the pm framework, which prevents any sdio request
+ * to be served until the host gets resumed and released.
+ */
+ mmc_signal_sdio_irq(host);
+
+ return IRQ_HANDLED;
+}
+
+static void sdio_config_irq(struct mmc_host *host,
+ bool cfg_as_dat1,
+ int irq_pin,
+ pin_cfg_t irq_dat1,
+ pin_cfg_t irq_gpio)
+{
+ /*
+ * If the pin mux switch or interrupt registration fails we're in deep
+ * trouble and there is no decent recovery.
+ */
+ if (!gpio_is_valid(irq_pin)) {
+ dev_err(mmc_dev(host),
+ "invalid irq pin (%d) for sdio irq\n", irq_pin);
+ return;
+ }
+
+ if (!cfg_as_dat1) {
+
+ /*
+ * SDIO irq shall be handled as a gpio irq. We configure the
+ * dat[1] as gpio and register a gpio irq handler.
+ */
+
+ if (nmk_config_pin(irq_gpio, 0))
+ dev_err(mmc_dev(host),
+ "err config irq gpio (%lu) for sdio irq\n",
+ irq_gpio);
+
+ /* We use threaded irq */
+ if (request_threaded_irq(gpio_to_irq(irq_pin),
+ NULL,
+ sdio_irq,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+ dev_driver_string(mmc_dev(host)),
+ host))
+ dev_err(mmc_dev(host),
+ "err request_threaded_irq for sdio irq\n");
+
+ /*
+ * Set the irq as a wakeup irq to be able to be woken up
+ * from the suspend state and thus trigger a resume of
+ * the system.
+ */
+ if (enable_irq_wake(gpio_to_irq(irq_pin)))
+ dev_err(mmc_dev(host),
+ "err enabling wakeup irq for sdio irq\n");
+
+ /*
+ * Workaround to fix PL180 hw-problem of missing sdio irqs.
+ * If the DAT1 line has been asserted low we signal an sdio
+ * irq.
+ */
+ if (gpio_request(irq_pin, dev_driver_string(mmc_dev(host))))
+ dev_err(mmc_dev(host),
+ "err requesting irq for sdio irq\n");
+
+ if (!gpio_get_value(irq_pin))
+ mmc_signal_sdio_irq(host);
+
+ gpio_free(irq_pin);
+
+ } else {
+
+ /*
+ * SDIO irq shall be handled as dat[1] irq by the mmci
+ * driver. Configure the gpio back into dat[1] and remove
+ * the gpio irq handler.
+ */
+ if (disable_irq_wake(gpio_to_irq(irq_pin)))
+ dev_err(mmc_dev(host),
+ "err disabling wakeup irq for sdio irq\n");
+
+ free_irq(gpio_to_irq(irq_pin), host);
+
+ if (nmk_config_pin(irq_dat1, 0))
+ dev_err(mmc_dev(host),
+ "err config irq dat1 (%lu) for sdio irq\n",
+ irq_dat1);
+
+ }
+}
+
+static void wakeup_handler_sdi3(struct mmc_host *host, bool wakeup)
+{
+ if (host->card && mmc_card_sdio(host->card) && host->sdio_irqs)
+ sdio_config_irq(host,
+ wakeup,
+ 172,
+ GPIO172_MC3_DAT1 | PIN_INPUT_PULLUP,
+ GPIO172_GPIO | PIN_INPUT_PULLUP);
+}
+
+static struct mmci_platform_data u5500_sdi3_data = {
+ .vcc = "v-mmc",
+ .disable = 50,
+ .ocr_mask = MMC_VDD_29_30,
+ .f_max = 50000000,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_DISABLE |
+ MMC_CAP_SDIO_IRQ |
+ MMC_CAP_BROKEN_SDIO_CMD53,
+ .pm_flags = MMC_PM_KEEP_POWER,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+ .wakeup_handler = wakeup_handler_sdi3,
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &sdi3_dma_cfg_rx,
+ .dma_tx_param = &sdi3_dma_cfg_tx,
+#endif
+};
+
+static int __init u5500_mmc_init(void)
+{
+ db5500_add_sdi0(&u5500_sdi0_data);
+ sdi1_configure();
+ db5500_add_sdi1(&u5500_sdi1_data);
+ db5500_add_sdi3(&u5500_sdi3_data);
+
+ return 0;
+}
+
+fs_initcall(u5500_mmc_init);
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 4430e69cf53..951339b0df9 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -1,41 +1,398 @@
/*
* Copyright (C) ST-Ericsson SA 2010
*
- * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
+#include <linux/amba/pl022.h>
#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/i2s/i2s.h>
+#include <linux/input/synaptics_i2c_rmi4.h>
+#include <linux/input/matrix_keypad.h>
+#include <linux/mfd/abx500/ab5500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/led-lm3530.h>
+#include <linux/lsm303dlh.h>
+#include <linux/leds-ab5500.h>
+
+#include <video/av8100.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
-#include <mach/hardware.h>
+#include <plat/pincfg.h>
+#include <plat/i2c.h>
+
+#include <mach/ste-dma40-db5500.h>
+#include <mach/msp.h>
#include <mach/devices.h>
#include <mach/setup.h>
+#include <mach/db5500-keypad.h>
+
+#include "pins-db5500.h"
+#include "devices-db5500.h"
+#include "board-u5500.h"
+
+/*
+ * LSM303DLH
+ */
+
+static struct lsm303dlh_platform_data __initdata lsm303dlh_pdata = {
+ .name_a = "lsm303dlh.0",
+ .name_m = "lsm303dlh.1",
+ .axis_map_x = 1,
+ .axis_map_y = 0,
+ .axis_map_z = 2,
+ .negative_x = 1,
+ .negative_y = 1,
+ .negative_z = 1,
+};
+
+/*
+ * Touchscreen
+ */
+
+static struct synaptics_rmi4_platform_data rmi4_i2c_platformdata = {
+ .irq_number = GPIO_TO_IRQ(179),
+ .irq_type = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
+#if CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE == 270
+ .x_flip = true,
+ .y_flip = false,
+#else
+ .x_flip = false,
+ .y_flip = true,
+#endif
+ .regulator_en = true,
+};
+
+static struct av8100_platform_data av8100_plat_data = {
+ .irq = GPIO_TO_IRQ(223),
+ .reset = 225,
+ .alt_powerupseq = true,
+ .mclk_freq = 1, /* MCLK_RNG_22_27 */
+};
+
+
+static struct lm3530_platform_data u5500_als_platform_data = {
+ .mode = LM3530_BL_MODE_MANUAL,
+ .als_input_mode = LM3530_INPUT_ALS1,
+ .max_current = LM3530_FS_CURR_26mA,
+ .pwm_pol_hi = true,
+ .als_avrg_time = LM3530_ALS_AVRG_TIME_512ms,
+ .brt_ramp_law = 1, /* Linear */
+ .brt_ramp_fall = LM3530_RAMP_TIME_1ms,
+ .brt_ramp_rise = LM3530_RAMP_TIME_1ms,
+ .als1_resistor_sel = LM3530_ALS_IMPD_2_27kOhm,
+ .als2_resistor_sel = LM3530_ALS_IMPD_2_27kOhm,
+ .brt_val = 0x7F, /* Max brightness */
+};
+
+
+/* leds-ab5500 */
+static struct ab5500_hvleds_platform_data ab5500_hvleds_data = {
+ .hw_blink = false,
+ .leds = {
+ [0] = {
+ .name = "ab5500-hvled:channel-0:",
+ .led_id = 0,
+ .status = AB5500_LED_ON,
+ .max_current = 10, /* wrong value may damage h/w */
+ },
+ [1] = {
+ .name = "ab5500-hvled:channel-1:",
+ .led_id = 1,
+ .status = AB5500_LED_ON,
+ .max_current = 10, /* wrong value may damage h/w */
+ },
+ [2] {
+ .name = "ab5500-hvled:channel-2:",
+ .led_id = 2,
+ .status = AB5500_LED_ON,
+ .max_current = 10, /* wrong value may damage h/w */
+ },
+ },
+};
+
+/*
+ * I2C
+ */
+
+#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, t_out, _sm) \
+static struct nmk_i2c_controller u5500_i2c##id##_data = { \
+ /* \
+ * slave data setup time, which is \
+ * 250 ns,100ns,10ns which is 14,6,2 \
+ * respectively for a 48 Mhz \
+ * i2c clock \
+ */ \
+ .slsu = _slsu, \
+ /* Tx FIFO threshold */ \
+ .tft = _tft, \
+ /* Rx FIFO threshold */ \
+ .rft = _rft, \
+ /* std. mode operation */ \
+ .clk_freq = clk, \
+ /* Slave response timeout(ms) */\
+ .timeout = t_out, \
+ .sm = _sm, \
+}
+
+/*
+ * The board uses 3 i2c controllers, initialize all of
+ * them with slave data setup time of 250 ns,
+ * Tx & Rx FIFO threshold values as 1 and standard
+ * mode of operation
+ */
+
+U5500_I2C_CONTROLLER(1, 0xe, 1, 1, 400000, 200, I2C_FREQ_MODE_FAST);
+U5500_I2C_CONTROLLER(2, 0xe, 1, 1, 400000, 200, I2C_FREQ_MODE_FAST);
+U5500_I2C_CONTROLLER(3, 0xe, 1, 1, 400000, 200, I2C_FREQ_MODE_FAST);
+
+static struct i2c_board_info __initdata u5500_i2c1_devices[] = {
+ {
+ I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
+ .platform_data = &rmi4_i2c_platformdata,
+ },
+};
+
+static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
+ {
+ /* LSM303DLH Accelerometer */
+ I2C_BOARD_INFO("lsm303dlh_a", 0x19),
+ .platform_data = &lsm303dlh_pdata,
+ },
+ {
+ /* LSM303DLH Magnetometer */
+ I2C_BOARD_INFO("lsm303dlh_m", 0x1E),
+ .platform_data = &lsm303dlh_pdata,
+ },
+ {
+ /* Backlight */
+ I2C_BOARD_INFO("lm3530-led", 0x36),
+ .platform_data = &u5500_als_platform_data,
+ },
+ {
+ I2C_BOARD_INFO("av8100", 0x70),
+ .platform_data = &av8100_plat_data,
+ },
+};
+
+/*
+ * Keypad
+ */
+
+static const unsigned int u5500_keymap[] = {
+ KEY(4, 0, KEY_CAMERA), /* Camera2 */
+ KEY(4, 1, KEY_CAMERA_FOCUS), /* Camera1 */
+ KEY(4, 2, KEY_MENU),
+ KEY(4, 3, KEY_BACK),
+ KEY(5, 2, KEY_SEND),
+ KEY(5, 3, KEY_HOME),
+#ifndef CONFIG_INPUT_AB8500_PONKEY
+ /* AB5500 ONSWa is also hooked up to this key */
+ KEY(8, 0, KEY_END),
+#endif
+ KEY(8, 1, KEY_VOLUMEUP),
+ KEY(8, 2, KEY_VOLUMEDOWN),
+};
+
+static struct matrix_keymap_data u5500_keymap_data = {
+ .keymap = u5500_keymap,
+ .keymap_size = ARRAY_SIZE(u5500_keymap),
+};
+
+static struct db5500_keypad_platform_data u5500_keypad_board = {
+ .keymap_data = &u5500_keymap_data,
+ .no_autorepeat = true,
+ .debounce_ms = 40, /* milliseconds */
+};
+
+
+/*
+ * MSP
+ */
+
+#define MSP_DMA(num, eventline) \
+static struct stedma40_chan_cfg msp##num##_dma_rx = { \
+ .high_priority = true, \
+ .dir = STEDMA40_PERIPH_TO_MEM, \
+ .src_dev_type = eventline##_RX, \
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY, \
+ .src_info.psize = STEDMA40_PSIZE_LOG_4, \
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4, \
+}; \
+ \
+static struct stedma40_chan_cfg msp##num##_dma_tx = { \
+ .high_priority = true, \
+ .dir = STEDMA40_MEM_TO_PERIPH, \
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY, \
+ .dst_dev_type = eventline##_TX, \
+ .src_info.psize = STEDMA40_PSIZE_LOG_4, \
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4, \
+}
+
+MSP_DMA(0, DB5500_DMA_DEV9_MSP0);
+MSP_DMA(1, DB5500_DMA_DEV10_MSP1);
+MSP_DMA(2, DB5500_DMA_DEV11_MSP2);
+
+static struct msp_i2s_platform_data u5500_msp0_data = {
+ .id = MSP_0_CONTROLLER,
+ .msp_i2s_dma_rx = &msp0_dma_rx,
+ .msp_i2s_dma_tx = &msp0_dma_tx,
+};
+
+static struct msp_i2s_platform_data u5500_msp1_data = {
+ .id = MSP_1_I2S_CONTROLLER,
+ .msp_i2s_dma_rx = &msp1_dma_rx,
+ .msp_i2s_dma_tx = &msp1_dma_tx,
+};
+
+static struct msp_i2s_platform_data u5500_msp2_data = {
+ .id = MSP_2_I2S_CONTROLLER,
+ .msp_i2s_dma_rx = &msp2_dma_rx,
+ .msp_i2s_dma_tx = &msp2_dma_tx,
+};
+
+static struct i2s_board_info stm_i2s_board_info[] __initdata = {
+ {
+ .modalias = "i2s_device.0",
+ .id = 0,
+ .chip_select = 0,
+ },
+ {
+ .modalias = "i2s_device.1",
+ .id = 1,
+ .chip_select = 1,
+ },
+ {
+ .modalias = "i2s_device.2",
+ .id = 2,
+ .chip_select = 2,
+ },
+};
+
+static void __init u5500_msp_init(void)
+{
+ db5500_add_msp0_i2s(&u5500_msp0_data);
+ db5500_add_msp1_i2s(&u5500_msp1_data);
+ db5500_add_msp2_i2s(&u5500_msp2_data);
+
+ i2s_register_board_info(ARRAY_AND_SIZE(stm_i2s_board_info));
+}
+
+/*
+ * SPI
+ */
+
+static struct pl022_ssp_controller u5500_spi1_data = {
+ .bus_id = 1,
+ .num_chipselect = 4, /* 3 possible CS lines + 1 for tests */
+};
+
+static void __init u5500_spi_init(void)
+{
+ db5500_add_spi1(&u5500_spi1_data);
+}
+
+static struct resource ab5500_resources[] = {
+ [0] = {
+ /*TODO Change this when prcmu driver arrives */
+ .start = IRQ_DB5500_AB5500,
+ .end = IRQ_DB5500_AB5500,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct ab5500_platform_data ab5500_plf_data = {
+ .irq = {
+ .base = IRQ_AB5500_BASE,
+ .count = AB5500_NR_IRQS,
+ },
+ .pm_power_off = true,
+ .regulator = &u5500_ab5500_regulator_data,
+ .dev_data[AB5500_DEVID_LEDS] = &ab5500_hvleds_data,
+ .dev_data_sz[AB5500_DEVID_LEDS] = sizeof(ab5500_hvleds_data),
+};
+
+static struct platform_device u5500_ab5500_device = {
+ .name = "ab5500-core",
+ .id = 0,
+ .dev = {
+ .platform_data = &ab5500_plf_data,
+ },
+ .num_resources = 1,
+ .resource = ab5500_resources,
+};
-static struct amba_device *amba_board_devs[] __initdata = {
- &ux500_uart0_device,
- &ux500_uart1_device,
- &ux500_uart2_device,
+static struct platform_device *u5500_platform_devices[] __initdata = {
+ &u5500_ab5500_device,
+ &ux500_mcde_device,
+ &ux500_hwmem_device,
+ &ux500_b2r2_device,
+#ifdef CONFIG_STM_TRACE
+ &ux500_stm_device,
+#endif
};
+static void __init u5500_i2c_init(void)
+{
+ db5500_add_i2c1(&u5500_i2c1_data);
+ db5500_add_i2c2(&u5500_i2c2_data);
+ db5500_add_i2c3(&u5500_i2c3_data);
+
+ i2c_register_board_info(1, ARRAY_AND_SIZE(u5500_i2c1_devices));
+ i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
+}
+
+static void __init u5500_uart_init(void)
+{
+ db5500_add_uart0();
+ db5500_add_uart1();
+ db5500_add_uart2();
+ db5500_add_uart3();
+}
+
static void __init u5500_init_machine(void)
{
+ u5500_regulators_init();
u5500_init_devices();
+ u5500_pins_init();
+
+ u5500_cg2900_init();
- amba_add_devices(amba_board_devs, ARRAY_SIZE(amba_board_devs));
+ u5500_i2c_init();
+ u5500_msp_init();
+ u5500_spi_init();
+ u5500_uart_init();
+
+ db5500_add_keypad(&u5500_keypad_board);
+
+ platform_add_devices(u5500_platform_devices,
+ ARRAY_SIZE(u5500_platform_devices));
}
-MACHINE_START(U8500, "ST-Ericsson U5500 Platform")
- .phys_io = UX500_UART0_BASE,
- .io_pg_offst = (IO_ADDRESS(UX500_UART0_BASE) >> 18) & 0xfffc,
+MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
+ .phys_io = U5500_UART0_BASE,
+ .io_pg_offst = (IO_ADDRESS(U5500_UART0_BASE) >> 18) & 0xfffc,
+ .boot_params = 0x00000100,
+ .map_io = u5500_map_io,
+ .init_irq = ux500_init_irq,
+ .timer = &u8500_timer,
+ .init_machine = u5500_init_machine,
+MACHINE_END
+
+MACHINE_START(B5500, "ST-Ericsson U5500 Big Board")
+ .phys_io = U5500_UART0_BASE,
+ .io_pg_offst = (IO_ADDRESS(U5500_UART0_BASE) >> 18) & 0xfffc,
.boot_params = 0x00000100,
.map_io = u5500_map_io,
.init_irq = ux500_init_irq,
- .timer = &ux500_timer,
+ .timer = &u8500_timer,
.init_machine = u5500_init_machine,
MACHINE_END
diff --git a/arch/arm/mach-ux500/board-u5500.h b/arch/arm/mach-ux500/board-u5500.h
new file mode 100644
index 00000000000..4a0dc94a1c3
--- /dev/null
+++ b/arch/arm/mach-ux500/board-u5500.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __BOARD_U5500_H
+#define __BOARD_U5500_H
+
+#define GPIO_SDMMC_CD 180
+#define GPIO_MMC_CARD_CTRL 227
+#define GPIO_MMC_CARD_VSEL 185
+
+struct ab5500_regulator_platform_data;
+extern struct ab5500_regulator_platform_data u5500_ab5500_regulator_data;
+
+extern void u5500_pins_init(void);
+extern void __init u5500_regulators_init(void);
+
+#ifdef CONFIG_MFD_CG2900
+extern void u5500_cg2900_init(void);
+#else
+static inline void u5500_cg2900_init(void)
+{
+ return;
+};
+#endif
+
+#endif
diff --git a/arch/arm/mach-ux500/clock-db5500.c b/arch/arm/mach-ux500/clock-db5500.c
new file mode 100644
index 00000000000..7a50007ddad
--- /dev/null
+++ b/arch/arm/mach-ux500/clock-db5500.c
@@ -0,0 +1,793 @@
+/*
+ * Copyright (C) 2009 ST-Ericsson SA
+ * Copyright (C) 2009 STMicroelectronics
+ *
+ * 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/list.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/ab8500/sysctrl.h>
+#include <linux/workqueue.h>
+#include <linux/regulator/consumer.h>
+
+#include <plat/pincfg.h>
+
+#include <mach/hardware.h>
+#include <mach/prcmu-fw-api.h>
+
+#include "clock.h"
+#include "pins-db8500.h"
+#include "prcmu-db5500.h"
+
+static DEFINE_MUTEX(sysclk_mutex);
+static DEFINE_MUTEX(ab_ulpclk_mutex);
+static DEFINE_MUTEX(audioclk_mutex);
+
+/* PLL operations. */
+
+static int clk_pllsrc_enable(struct clk *clk)
+{
+ /* To enable pll */
+ return 0;
+}
+
+static void clk_pllsrc_disable(struct clk *clk)
+{
+ /* To disable pll */
+}
+
+static struct clkops pll_clk_ops = {
+ .enable = clk_pllsrc_enable,
+ .disable = clk_pllsrc_disable,
+};
+
+/* SysClk operations. */
+
+static int request_sysclk(bool enable)
+{
+ static int requests;
+
+ if ((enable && (requests++ == 0)) || (!enable && (--requests == 0)))
+ return db5500_prcmu_request_clock(DB5500_PRCMU_SYSCLK, enable);
+ return 0;
+}
+
+static int sysclk_enable(struct clk *clk)
+{
+ static bool swat_enable;
+ int r;
+
+ if (!swat_enable) {
+ r = ab8500_sysctrl_set(AB8500_SWATCTRL,
+ AB8500_SWATCTRL_SWATENABLE);
+ if (r)
+ return r;
+
+ swat_enable = true;
+ }
+
+ r = request_sysclk(true);
+ if (r)
+ return r;
+
+ if (clk->cg_sel) {
+ r = ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1, (u8)clk->cg_sel);
+ if (r)
+ (void)request_sysclk(false);
+ }
+ return r;
+}
+
+static void sysclk_disable(struct clk *clk)
+{
+ int r;
+
+ if (clk->cg_sel) {
+ r = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
+ (u8)clk->cg_sel);
+ if (r)
+ goto disable_failed;
+ }
+ r = request_sysclk(false);
+ if (r)
+ goto disable_failed;
+ return;
+
+disable_failed:
+ pr_err("clock: failed to disable %s.\n", clk->name);
+}
+
+static struct clkops sysclk_ops = {
+ .enable = sysclk_enable,
+ .disable = sysclk_disable,
+};
+
+/* AB8500 UlpClk operations */
+
+static int ab_ulpclk_enable(struct clk *clk)
+{
+ int err;
+
+ if (clk->regulator == NULL) {
+ struct regulator *reg;
+
+ reg = regulator_get(NULL, "v-intcore");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ clk->regulator = reg;
+ }
+ err = regulator_enable(clk->regulator);
+ if (err)
+ return err;
+ err = ab8500_sysctrl_clear(AB8500_SYSULPCLKCONF,
+ AB8500_SYSULPCLKCONF_ULPCLKCONF_MASK);
+ if (err)
+ return err;
+ return ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_ULPCLKREQ);
+}
+
+static void ab_ulpclk_disable(struct clk *clk)
+{
+ if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_ULPCLKREQ))
+ goto out_err;
+ if (clk->regulator != NULL) {
+ if (regulator_disable(clk->regulator))
+ goto out_err;
+ }
+ return;
+
+out_err:
+ pr_err("clock: %s failed to disable %s.\n", __func__, clk->name);
+}
+
+static struct clkops ab_ulpclk_ops = {
+ .enable = ab_ulpclk_enable,
+ .disable = ab_ulpclk_disable,
+};
+
+/* AB8500 audio clock operations */
+
+static int audioclk_enable(struct clk *clk)
+{
+ return ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_AUDIOCLKENA);
+}
+
+static void audioclk_disable(struct clk *clk)
+{
+ if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_AUDIOCLKENA)) {
+ pr_err("clock: %s failed to disable %s.\n", __func__,
+ clk->name);
+ }
+}
+
+static int audioclk_set_parent(struct clk *clk, struct clk *parent)
+{
+ if (parent->ops == &sysclk_ops) {
+ return ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK);
+ } else if (parent->ops == &ab_ulpclk_ops) {
+ return ab8500_sysctrl_write(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK,
+ (1 << AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT));
+ } else {
+ return -EINVAL;
+ }
+}
+
+static struct clkops audioclk_ops = {
+ .enable = audioclk_enable,
+ .disable = audioclk_disable,
+ .set_parent = audioclk_set_parent,
+};
+
+/* Primary camera clock operations */
+static int clkout0_enable(struct clk *clk)
+{
+ int r;
+
+ r = prcmu_config_clkout(0, PRCMU_CLKSRC_SYSCLK, 4);
+ if (r)
+ return r;
+ return nmk_config_pin(GPIO227_CLKOUT1, false);
+}
+
+static void clkout0_disable(struct clk *clk)
+{
+ int r;
+
+ r = nmk_config_pin(GPIO227_GPIO, false);
+ if (r)
+ goto disable_failed;
+ r = prcmu_config_clkout(0, PRCMU_CLKSRC_SYSCLK, 0);
+ if (!r)
+ return;
+disable_failed:
+ pr_err("clock: failed to disable %s.\n", clk->name);
+}
+
+/* Touch screen/secondary camera clock operations. */
+static int clkout1_enable(struct clk *clk)
+{
+ int r;
+
+ r = prcmu_config_clkout(1, PRCMU_CLKSRC_SYSCLK, 4);
+ if (r)
+ return r;
+ return nmk_config_pin(GPIO228_CLKOUT2, false);
+}
+
+static void clkout1_disable(struct clk *clk)
+{
+ int r;
+
+ r = nmk_config_pin(GPIO228_GPIO, false);
+ if (r)
+ goto disable_failed;
+ r = prcmu_config_clkout(1, PRCMU_CLKSRC_SYSCLK, 0);
+ if (!r)
+ return;
+disable_failed:
+ pr_err("clock: failed to disable %s.\n", clk->name);
+}
+
+static struct clkops clkout0_ops = {
+ .enable = clkout0_enable,
+ .disable = clkout0_disable,
+};
+
+static struct clkops clkout1_ops = {
+ .enable = clkout1_enable,
+ .disable = clkout1_disable,
+};
+
+#define DEF_PER1_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U5500_CLKRST1_BASE, _cg_bit, &per1clk)
+#define DEF_PER2_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U5500_CLKRST2_BASE, _cg_bit, &per2clk)
+#define DEF_PER3_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U5500_CLKRST3_BASE, _cg_bit, &per3clk)
+#define DEF_PER5_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U5500_CLKRST5_BASE, _cg_bit, &per5clk)
+#define DEF_PER6_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U5500_CLKRST6_BASE, _cg_bit, &per6clk)
+
+#define DEF_PER1_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U5500_CLKRST1_BASE, _cg_bit, _parent)
+#define DEF_PER2_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U5500_CLKRST2_BASE, _cg_bit, _parent)
+#define DEF_PER3_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U5500_CLKRST3_BASE, _cg_bit, _parent)
+#define DEF_PER5_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U5500_CLKRST5_BASE, _cg_bit, _parent)
+#define DEF_PER6_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U5500_CLKRST6_BASE, _cg_bit, _parent)
+
+#define DEF_MTU_CLK(_cg_sel, _name, _bus_parent) \
+ struct clk _name = { \
+ .name = #_name, \
+ .ops = &mtu_clk_ops, \
+ .cg_sel = _cg_sel, \
+ .bus_parent = _bus_parent, \
+ }
+
+/* Clock sources. */
+
+static struct clk soc0_pll = {
+ .name = "soc0_pll",
+ .ops = &pll_clk_ops,
+};
+
+static struct clk soc1_pll = {
+ .name = "soc1_pll",
+ .ops = &pll_clk_ops,
+};
+
+static struct clk ddr_pll = {
+ .name = "ddr_pll",
+ .ops = &pll_clk_ops,
+};
+
+static struct clk ulp38m4 = {
+ .name = "ulp38m4",
+};
+
+static struct clk sysclk = {
+ .name = "sysclk",
+ .ops = &sysclk_ops,
+ .rate = 38400000,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk sysclk2 = {
+ .name = "sysclk2",
+ .ops = &sysclk_ops,
+ .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk sysclk3 = {
+ .name = "sysclk3",
+ .ops = &sysclk_ops,
+ .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk sysclk4 = {
+ .name = "sysclk4",
+ .ops = &sysclk_ops,
+ .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk rtc32k = {
+ .name = "rtc32k",
+ .rate = 32768,
+};
+
+static struct clk kbd32k = {
+ .name = "kbd32k",
+ .rate = 32768,
+};
+
+static struct clk clk_dummy = {
+ .name = "dummy",
+};
+
+static struct clk clk_msp1 = {
+ .name = "msp1",
+ .rate = 26000000,
+};
+
+static struct clk clkout0 = {
+ .name = "clkout0",
+ .ops = &clkout0_ops,
+ .parent = &sysclk,
+ .rate = 9600000,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk clkout1 = {
+ .name = "clkout1",
+ .ops = &clkout1_ops,
+ .parent = &sysclk,
+ .rate = 9600000,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk ab_ulpclk = {
+ .name = "ab_ulpclk",
+ .ops = &ab_ulpclk_ops,
+ .rate = 38400000,
+ .mutex = &ab_ulpclk_mutex,
+};
+
+static struct clk *audioclk_parents[] = { &sysclk, &ab_ulpclk, NULL };
+
+static struct clk audioclk = {
+ .name = "audioclk",
+ .ops = &audioclk_ops,
+ .mutex = &audioclk_mutex,
+ .parent = &sysclk,
+ .parents = audioclk_parents,
+};
+
+static DEF_PRCMU_CLK(dmaclk, DB5500_PRCMU_DMACLK, 200000000);
+static DEF_PRCMU_CLK(b2r2clk, DB5500_PRCMU_B2R2CLK, 200000000);
+static DEF_PRCMU_CLK(sgaclk, DB5500_PRCMU_SGACLK, 199900000);
+static DEF_PRCMU_CLK(uartclk, DB5500_PRCMU_UARTCLK, 36360000);
+static DEF_PRCMU_CLK(msp02clk, DB5500_PRCMU_MSP02CLK, 13000000);
+static DEF_PRCMU_CLK(i2cclk, DB5500_PRCMU_I2CCLK, 24000000);
+static DEF_PRCMU_CLK(irdaclk, DB5500_PRCMU_IRDACLK, 48000000);
+static DEF_PRCMU_CLK(irrcclk, DB5500_PRCMU_IRRCCLK, 48000000);
+static DEF_PRCMU_CLK(rngclk, DB5500_PRCMU_RNGCLK, 26000000);
+static DEF_PRCMU_CLK(pwmclk, DB5500_PRCMU_PWMCLK, 26000000);
+static DEF_PRCMU_CLK(sdmmcclk, DB5500_PRCMU_SDMMCCLK, 100000000);
+static DEF_PRCMU_CLK(per1clk, DB5500_PRCMU_PER1CLK, 133330000);
+static DEF_PRCMU_CLK(per2clk, DB5500_PRCMU_PER2CLK, 133330000);
+static DEF_PRCMU_CLK(per3clk, DB5500_PRCMU_PER3CLK, 133330000);
+static DEF_PRCMU_CLK(per5clk, DB5500_PRCMU_PER5CLK, 133330000);
+static DEF_PRCMU_CLK(per6clk, DB5500_PRCMU_PER6CLK, 133330000);
+static DEF_PRCMU_CLK(hdmiclk, DB5500_PRCMU_HDMICLK, 26000000);
+static DEF_PRCMU_CLK(apeatclk, DB5500_PRCMU_APEATCLK, 200000000);
+static DEF_PRCMU_CLK(apetraceclk, DB5500_PRCMU_APETRACECLK, 266000000);
+static DEF_PRCMU_CLK(mcdeclk, DB5500_PRCMU_MCDECLK, 160000000);
+static DEF_PRCMU_CLK(tvclk, DB5500_PRCMU_TVCLK, 40000000);
+static DEF_PRCMU_CLK(dsialtclk, DB5500_PRCMU_DSIALTCLK, 400000000);
+static DEF_PRCMU_CLK(timclk, DB5500_PRCMU_TIMCLK, 3250000);
+
+/* PRCC PClocks */
+
+static DEF_PER1_PCLK(0, p1_pclk0);
+static DEF_PER1_PCLK(1, p1_pclk1);
+static DEF_PER1_PCLK(2, p1_pclk2);
+static DEF_PER1_PCLK(3, p1_pclk3);
+static DEF_PER1_PCLK(4, p1_pclk4);
+static DEF_PER1_PCLK(5, p1_pclk5);
+static DEF_PER1_PCLK(6, p1_pclk6);
+
+static DEF_PER2_PCLK(0, p2_pclk0);
+static DEF_PER2_PCLK(1, p2_pclk1);
+
+static DEF_PER3_PCLK(0, p3_pclk0);
+static DEF_PER3_PCLK(1, p3_pclk1);
+static DEF_PER3_PCLK(2, p3_pclk2);
+
+static DEF_PER5_PCLK(0, p5_pclk0);
+static DEF_PER5_PCLK(1, p5_pclk1);
+static DEF_PER5_PCLK(2, p5_pclk2);
+static DEF_PER5_PCLK(3, p5_pclk3);
+static DEF_PER5_PCLK(4, p5_pclk4);
+static DEF_PER5_PCLK(5, p5_pclk5);
+static DEF_PER5_PCLK(6, p5_pclk6);
+static DEF_PER5_PCLK(7, p5_pclk7);
+static DEF_PER5_PCLK(8, p5_pclk8);
+static DEF_PER5_PCLK(9, p5_pclk9);
+static DEF_PER5_PCLK(10, p5_pclk10);
+static DEF_PER5_PCLK(11, p5_pclk11);
+static DEF_PER5_PCLK(12, p5_pclk12);
+static DEF_PER5_PCLK(13, p5_pclk13);
+static DEF_PER5_PCLK(14, p5_pclk14);
+static DEF_PER5_PCLK(15, p5_pclk15);
+
+static DEF_PER6_PCLK(0, p6_pclk0);
+static DEF_PER6_PCLK(1, p6_pclk1);
+static DEF_PER6_PCLK(2, p6_pclk2);
+static DEF_PER6_PCLK(3, p6_pclk3);
+static DEF_PER6_PCLK(4, p6_pclk4);
+static DEF_PER6_PCLK(5, p6_pclk5);
+static DEF_PER6_PCLK(6, p6_pclk6);
+static DEF_PER6_PCLK(7, p6_pclk7);
+
+/* MSP0 */
+static DEF_PER1_KCLK(0, p1_msp0_kclk, &msp02clk);
+static DEF_PER_CLK(p1_msp0_clk, &p1_pclk0, &p1_msp0_kclk);
+
+/* SDI0 */
+static DEF_PER1_KCLK(1, p1_sdi0_kclk, &sdmmcclk);
+static DEF_PER_CLK(p1_sdi0_clk, &p1_pclk1, &p1_sdi0_kclk);
+
+/* SDI2 */
+static DEF_PER1_KCLK(2, p1_sdi2_kclk, &sdmmcclk);
+static DEF_PER_CLK(p1_sdi2_clk, &p1_pclk2, &p1_sdi2_kclk);
+
+/* UART0 */
+static DEF_PER1_KCLK(3, p1_uart0_kclk, &uartclk);
+static DEF_PER_CLK(p1_uart0_clk, &p1_pclk3, &p1_uart0_kclk);
+
+/* I2C1 */
+static DEF_PER1_KCLK(4, p1_i2c1_kclk, &i2cclk);
+static DEF_PER_CLK(p1_i2c1_clk, &p1_pclk4, &p1_i2c1_kclk);
+
+/* PWM */
+static DEF_PER3_KCLK(0, p3_pwm_kclk, &pwmclk);
+static DEF_PER_CLK(p3_pwm_clk, &p3_pclk1, &p3_pwm_kclk);
+
+/* KEYPAD */
+static DEF_PER3_KCLK(0, p3_keypad_kclk, &kbd32k);
+static DEF_PER_CLK(p3_keypad_clk, &p3_pclk0, &p3_keypad_kclk);
+
+/* MSP2 */
+static DEF_PER5_KCLK(0, p5_msp2_kclk, &msp02clk);
+static DEF_PER_CLK(p5_msp2_clk, &p5_pclk0, &p5_msp2_kclk);
+
+/* UART1 */
+static DEF_PER5_KCLK(1, p5_uart1_kclk, &uartclk);
+static DEF_PER_CLK(p5_uart1_clk, &p5_pclk1, &p5_uart1_kclk);
+
+/* UART2 */
+static DEF_PER5_KCLK(2, p5_uart2_kclk, &uartclk);
+static DEF_PER_CLK(p5_uart2_clk, &p5_pclk2, &p5_uart2_kclk);
+
+/* UART3 */
+static DEF_PER5_KCLK(3, p5_uart3_kclk, &uartclk);
+static DEF_PER_CLK(p5_uart3_clk, &p5_pclk3, &p5_uart3_kclk);
+
+/* SDI1 */
+static DEF_PER5_KCLK(4, p5_sdi1_kclk, &sdmmcclk);
+static DEF_PER_CLK(p5_sdi1_clk, &p5_pclk4, &p5_sdi1_kclk);
+
+/* SDI3 */
+static DEF_PER5_KCLK(5, p5_sdi3_kclk, &sdmmcclk);
+static DEF_PER_CLK(p5_sdi3_clk, &p5_pclk5, &p5_sdi3_kclk);
+
+/* SDI4 */
+static DEF_PER5_KCLK(6, p5_sdi4_kclk, &sdmmcclk);
+static DEF_PER_CLK(p5_sdi4_clk, &p5_pclk6, &p5_sdi4_kclk);
+
+/* I2C2 */
+static DEF_PER5_KCLK(7, p5_i2c2_kclk, &i2cclk);
+static DEF_PER_CLK(p5_i2c2_clk, &p5_pclk7, &p5_i2c2_kclk);
+
+/* I2C3 */
+static DEF_PER5_KCLK(8, p5_i2c3_kclk, &i2cclk);
+static DEF_PER_CLK(p5_i2c3_clk, &p5_pclk8, &p5_i2c3_kclk);
+
+/* IRRC */
+static DEF_PER5_KCLK(9, p5_irrc_kclk, &irrcclk);
+static DEF_PER_CLK(p5_irrc_clk, &p5_pclk9, &p5_irrc_kclk);
+
+/* IRDA */
+static DEF_PER5_KCLK(10, p5_irda_kclk, &irdaclk);
+static DEF_PER_CLK(p5_irda_clk, &p5_pclk10, &p5_irda_kclk);
+
+/* RNG */
+static DEF_PER6_KCLK(0, p6_rng_kclk, &rngclk);
+static DEF_PER_CLK(p6_rng_clk, &p6_pclk0, &p6_rng_kclk);
+
+/* MTU:S */
+
+/* MTU0 */
+static DEF_PER_CLK(p6_mtu0_clk, &p6_pclk6, &timclk);
+
+/* MTU1 */
+static DEF_PER_CLK(p6_mtu1_clk, &p6_pclk7, &timclk);
+
+static struct clk *db5500_dbg_clks[] = {
+ /* Clock sources */
+ &soc0_pll,
+ &soc1_pll,
+ &ddr_pll,
+ &ulp38m4,
+ &sysclk,
+ &rtc32k,
+
+ /* PRCMU clocks */
+ &sgaclk,
+ &uartclk,
+ &msp02clk,
+ &i2cclk,
+ &irdaclk,
+ &irrcclk,
+ &sdmmcclk,
+ &per1clk,
+ &per2clk,
+ &per3clk,
+ &per5clk,
+ &per6clk,
+ &hdmiclk,
+ &apeatclk,
+ &apetraceclk,
+ &mcdeclk,
+ &dsialtclk,
+ &dmaclk,
+ &b2r2clk,
+ &tvclk,
+ &rngclk,
+ &pwmclk,
+
+ /* Clock sources */
+ &sysclk2,
+ &clkout0,
+ &clkout1,
+};
+
+#define CLK_LOOKUP(_clk, _dev_id, _con_id) \
+ { .dev_id = _dev_id, .con_id = _con_id, .clk = &_clk }
+
+static struct clk_lookup u8500_common_clock_sources[] = {
+ CLK_LOOKUP(soc0_pll, NULL, "soc0_pll"),
+ CLK_LOOKUP(soc1_pll, NULL, "soc1_pll"),
+ CLK_LOOKUP(ddr_pll, NULL, "ddr_pll"),
+ CLK_LOOKUP(ulp38m4, NULL, "ulp38m4"),
+ CLK_LOOKUP(sysclk, NULL, "sysclk"),
+ CLK_LOOKUP(rtc32k, NULL, "clk32k"),
+ CLK_LOOKUP(sysclk, "ab8500-usb.0", "sysclk"),
+ CLK_LOOKUP(sysclk, "ab8500-codec.0", "sysclk"),
+ CLK_LOOKUP(ab_ulpclk, "ab8500-codec.0", "ulpclk"),
+ CLK_LOOKUP(audioclk, "ab8500-codec.0", "audioclk"),
+};
+
+static struct clk_lookup u8500_v2_sysclks[] = {
+ CLK_LOOKUP(sysclk2, NULL, "sysclk2"),
+ CLK_LOOKUP(sysclk3, NULL, "sysclk3"),
+ CLK_LOOKUP(sysclk4, NULL, "sysclk4"),
+};
+
+static struct clk_lookup db5500_prcmu_clocks[] = {
+ CLK_LOOKUP(sgaclk, "mali", NULL),
+ CLK_LOOKUP(uartclk, "UART", NULL),
+ CLK_LOOKUP(msp02clk, "MSP02", NULL),
+ CLK_LOOKUP(i2cclk, "I2C", NULL),
+ CLK_LOOKUP(sdmmcclk, "sdmmc", NULL),
+ CLK_LOOKUP(per1clk, "PERIPH1", NULL),
+ CLK_LOOKUP(per2clk, "PERIPH2", NULL),
+ CLK_LOOKUP(per3clk, "PERIPH3", NULL),
+ CLK_LOOKUP(per5clk, "PERIPH5", NULL),
+ CLK_LOOKUP(per6clk, "PERIPH6", NULL),
+ CLK_LOOKUP(hdmiclk, "mcde", "hdmi"),
+ CLK_LOOKUP(apeatclk, "apeat", NULL),
+ CLK_LOOKUP(apetraceclk, "apetrace", NULL),
+ CLK_LOOKUP(mcdeclk, "mcde", NULL),
+ CLK_LOOKUP(mcdeclk, "mcde", "mcde"),
+ CLK_LOOKUP(dmaclk, "dma40.0", NULL),
+ CLK_LOOKUP(b2r2clk, "b2r2", NULL),
+ CLK_LOOKUP(b2r2clk, "b2r2_bus", NULL),
+ CLK_LOOKUP(b2r2clk, "U8500-B2R2.0", NULL),
+ CLK_LOOKUP(tvclk, "tv", NULL),
+ CLK_LOOKUP(tvclk, "mcde", "tv"),
+};
+
+static struct clk_lookup db5500_prcc_clocks[] = {
+ CLK_LOOKUP(p1_msp0_clk, "MSP_I2S.0", NULL),
+ CLK_LOOKUP(p1_sdi0_clk, "sdi0", NULL),
+ CLK_LOOKUP(p1_sdi2_clk, "sdi2", NULL),
+ CLK_LOOKUP(p1_uart0_clk, "uart0", NULL),
+ CLK_LOOKUP(p1_i2c1_clk, "nmk-i2c.1", NULL),
+ CLK_LOOKUP(p1_pclk5, "gpio.0", NULL),
+ CLK_LOOKUP(p1_pclk5, "gpio.1", NULL),
+ CLK_LOOKUP(p1_pclk6, "fsmc", NULL),
+
+ CLK_LOOKUP(p2_pclk0, "musb_hdrc.0", NULL),
+ CLK_LOOKUP(p2_pclk1, "gpio.2", NULL),
+
+ CLK_LOOKUP(p3_keypad_clk, "db5500-keypad", NULL),
+ CLK_LOOKUP(p3_pwm_clk, "pwm", NULL),
+ CLK_LOOKUP(p3_pclk2, "gpio.4", NULL),
+
+ CLK_LOOKUP(p5_msp2_clk, "MSP_I2S.2", NULL),
+ CLK_LOOKUP(p5_uart1_clk, "uart1", NULL),
+ CLK_LOOKUP(p5_uart2_clk, "uart2", NULL),
+ CLK_LOOKUP(p5_uart3_clk, "uart3", NULL),
+ CLK_LOOKUP(p5_sdi1_clk, "sdi1", NULL),
+ CLK_LOOKUP(p5_sdi3_clk, "sdi3", NULL),
+ CLK_LOOKUP(p5_sdi4_clk, "sdi4", NULL),
+ CLK_LOOKUP(p5_i2c2_clk, "nmk-i2c.2", NULL),
+ CLK_LOOKUP(p5_i2c3_clk, "nmk-i2c.3", NULL),
+ CLK_LOOKUP(p5_irrc_clk, "irrc", NULL),
+ CLK_LOOKUP(p5_irda_clk, "irda", NULL),
+ CLK_LOOKUP(p5_pclk11, "spi0", NULL),
+ CLK_LOOKUP(p5_pclk12, "spi1", NULL),
+ CLK_LOOKUP(p5_pclk13, "spi2", NULL),
+ CLK_LOOKUP(p5_pclk14, "spi3", NULL),
+ CLK_LOOKUP(p5_pclk15, "gpio.5", NULL),
+ CLK_LOOKUP(p5_pclk15, "gpio.6", NULL),
+ CLK_LOOKUP(p5_pclk15, "gpio.7", NULL),
+
+ CLK_LOOKUP(p6_rng_clk, "rng", NULL),
+ CLK_LOOKUP(p6_pclk1, "cryp", NULL),
+ CLK_LOOKUP(p6_pclk2, "hash0", NULL),
+ CLK_LOOKUP(p6_pclk3, "pka", NULL),
+ CLK_LOOKUP(p6_pclk4, "hash1", NULL),
+ CLK_LOOKUP(p6_pclk5, "cfgreg", NULL),
+ CLK_LOOKUP(p6_mtu0_clk, "mtu0", NULL),
+ CLK_LOOKUP(p6_mtu1_clk, "mtu1", NULL),
+
+ /*
+ * TODO: Clarify whether MSP1 need to be accessed from Linux, and who
+ * sets up the GPIOs.
+ */
+ CLK_LOOKUP(clk_dummy, "gpio.3", NULL),
+ CLK_LOOKUP(clk_msp1, "MSP_I2S.1", NULL),
+};
+
+static struct clk_lookup u8500_v2_prcmu_clocks[] = {
+ CLK_LOOKUP(clkout0, "pri-cam", NULL),
+ CLK_LOOKUP(clkout1, "3-005c", NULL),
+ CLK_LOOKUP(clkout1, "3-005d", NULL),
+ CLK_LOOKUP(clkout1, "sec-cam", NULL),
+};
+
+static const char *db5500_boot_clk[] __initdata = {
+ "spi0",
+ "spi1",
+ "spi2",
+ "spi3",
+ "uart0",
+ "uart1",
+ "uart2",
+ "uart3",
+ "sdi0",
+ "sdi1",
+ "sdi2",
+ "sdi3",
+ "sdi4",
+};
+
+static struct clk *boot_clks[ARRAY_SIZE(db5500_boot_clk)] __initdata;
+
+static int __init db5500_boot_clk_disable(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(db5500_boot_clk); i++) {
+ clk_disable(boot_clks[i]);
+ clk_put(boot_clks[i]);
+ }
+
+ return 0;
+}
+late_initcall_sync(db5500_boot_clk_disable);
+
+static void __init db5500_boot_clk_enable(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(db5500_boot_clk); i++) {
+ boot_clks[i] = clk_get_sys(db5500_boot_clk[i], NULL);
+ BUG_ON(IS_ERR(boot_clks[i]));
+ clk_enable(boot_clks[i]);
+ }
+}
+
+static int db5500_prcmu_clk_enable(struct clk *clk)
+{
+ return db5500_prcmu_request_clock(clk->cg_sel, true);
+}
+
+static void db5500_prcmu_clk_disable(struct clk *clk)
+{
+ if (db5500_prcmu_request_clock(clk->cg_sel, false)) {
+ pr_err("clock: %s failed to disable %s.\n", __func__,
+ clk->name);
+ }
+}
+
+int __init db5500_clk_init(void)
+{
+ sysclk_ops.enable = NULL;
+ sysclk_ops.disable = NULL;
+ clkout0_ops.enable = NULL;
+ clkout0_ops.disable = NULL;
+ clkout1_ops.enable = NULL;
+ clkout1_ops.disable = NULL;
+
+ prcmu_clk_ops.enable = db5500_prcmu_clk_enable;
+ prcmu_clk_ops.disable = db5500_prcmu_clk_disable;
+
+ if (ux500_is_svp()) {
+ prcmu_clk_ops.enable = NULL;
+ prcmu_clk_ops.disable = NULL;
+ prcc_pclk_ops.enable = NULL;
+ prcc_pclk_ops.disable = NULL;
+ prcc_kclk_ops.enable = NULL;
+ prcc_kclk_ops.disable = NULL;
+ }
+
+ clks_register(u8500_common_clock_sources,
+ ARRAY_SIZE(u8500_common_clock_sources));
+
+ clks_register(db5500_prcmu_clocks, ARRAY_SIZE(db5500_prcmu_clocks));
+ clks_register(db5500_prcc_clocks, ARRAY_SIZE(db5500_prcc_clocks));
+
+ if (cpu_is_u8500v2()) {
+ clks_register(u8500_v2_sysclks,
+ ARRAY_SIZE(u8500_v2_sysclks));
+ clks_register(u8500_v2_prcmu_clocks,
+ ARRAY_SIZE(u8500_v2_prcmu_clocks));
+ }
+
+ db5500_boot_clk_enable();
+
+ /*
+ * The following clks are shared with secure world.
+ * Currently this leads to a limitation where we need to
+ * enable them at all times.
+ */
+ clk_enable(&p6_pclk1);
+ clk_enable(&p6_pclk2);
+ clk_enable(&p6_pclk3);
+ clk_enable(&p6_rng_clk);
+
+ return 0;
+}
+
+static int __init db5500_clk_debug_init(void)
+{
+ return dbx500_clk_debug_init(db5500_dbg_clks,
+ ARRAY_SIZE(db5500_dbg_clks));
+}
+module_init(db5500_clk_debug_init);
diff --git a/arch/arm/mach-ux500/clock-db8500.c b/arch/arm/mach-ux500/clock-db8500.c
new file mode 100644
index 00000000000..611a2d24276
--- /dev/null
+++ b/arch/arm/mach-ux500/clock-db8500.c
@@ -0,0 +1,1289 @@
+/*
+ * Copyright (C) 2009 ST-Ericsson SA
+ * Copyright (C) 2009 STMicroelectronics
+ *
+ * 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/list.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/ab8500/sysctrl.h>
+#include <linux/workqueue.h>
+#include <linux/regulator/consumer.h>
+
+#include <plat/pincfg.h>
+
+#include <mach/hardware.h>
+#include <mach/prcmu-fw-api.h>
+
+#include "clock.h"
+#include "pins-db8500.h"
+
+#define PRCM_SDMMCCLK_MGT 0x024
+#define PRCM_TCR 0x1C8
+#define PRCM_TCR_STOPPED (1 << 16)
+#define PRCM_TCR_DOZE_MODE (1 << 17)
+#define SD_CLK_DIV_MASK 0x1F
+#define SD_CLK_DIV_VAL 8
+
+static DEFINE_MUTEX(soc1_pll_mutex);
+static DEFINE_MUTEX(sysclk_mutex);
+static DEFINE_MUTEX(ab_ulpclk_mutex);
+static DEFINE_MUTEX(audioclk_mutex);
+
+static struct delayed_work sysclk_disable_work;
+
+/* PLL operations. */
+
+static int clk_pllsrc_enable(struct clk *clk)
+{
+ /* To enable pll */
+ return 0;
+}
+
+static void clk_pllsrc_disable(struct clk *clk)
+{
+ /* To disable pll */
+}
+
+static struct clkops pll_clk_ops = {
+ .enable = clk_pllsrc_enable,
+ .disable = clk_pllsrc_disable,
+};
+
+/* SysClk operations. */
+
+static int request_sysclk(bool enable)
+{
+ static int requests;
+
+ if ((enable && (requests++ == 0)) || (!enable && (--requests == 0)))
+ return prcmu_request_clock(PRCMU_SYSCLK, enable);
+ return 0;
+}
+
+static int sysclk_enable(struct clk *clk)
+{
+ static bool swat_enable;
+ int r;
+
+ if (!swat_enable) {
+ r = ab8500_sysctrl_set(AB8500_SWATCTRL,
+ AB8500_SWATCTRL_SWATENABLE);
+ if (r)
+ return r;
+
+ swat_enable = true;
+ }
+
+ r = request_sysclk(true);
+ if (r)
+ return r;
+
+ if (clk->cg_sel) {
+ r = ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1, (u8)clk->cg_sel);
+ if (r)
+ (void)request_sysclk(false);
+ }
+ return r;
+}
+
+static void sysclk_disable(struct clk *clk)
+{
+ int r;
+
+ if (clk->cg_sel) {
+ r = ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
+ (u8)clk->cg_sel);
+ if (r)
+ goto disable_failed;
+ }
+ r = request_sysclk(false);
+ if (r)
+ goto disable_failed;
+ return;
+
+disable_failed:
+ pr_err("clock: failed to disable %s.\n", clk->name);
+}
+
+static struct clkops sysclk_ops = {
+ .enable = sysclk_enable,
+ .disable = sysclk_disable,
+};
+
+/* AB8500 UlpClk operations */
+
+static int ab_ulpclk_enable(struct clk *clk)
+{
+ int err;
+
+ if (clk->regulator == NULL) {
+ struct regulator *reg;
+
+ reg = regulator_get(NULL, "v-intcore");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+ clk->regulator = reg;
+ }
+ err = regulator_enable(clk->regulator);
+ if (err)
+ return err;
+ err = ab8500_sysctrl_clear(AB8500_SYSULPCLKCONF,
+ AB8500_SYSULPCLKCONF_ULPCLKCONF_MASK);
+ if (err)
+ return err;
+ return ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1,
+ (AB8500_SYSULPCLKCTRL1_ULPCLKREQ |
+ AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK));
+}
+
+static void ab_ulpclk_disable(struct clk *clk)
+{
+ if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_ULPCLKREQ))
+ goto out_err;
+ if (clk->regulator != NULL) {
+ if (regulator_disable(clk->regulator))
+ goto out_err;
+ }
+ return;
+
+out_err:
+ pr_err("clock: %s failed to disable %s.\n", __func__, clk->name);
+}
+
+static struct clkops ab_ulpclk_ops = {
+ .enable = ab_ulpclk_enable,
+ .disable = ab_ulpclk_disable,
+};
+
+/* AB8500 audio clock operations */
+
+static int audioclk_enable(struct clk *clk)
+{
+ return ab8500_sysctrl_set(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_AUDIOCLKENA);
+}
+
+static void audioclk_disable(struct clk *clk)
+{
+ if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
+ AB8500_SYSULPCLKCTRL1_AUDIOCLKENA)) {
+ pr_err("clock: %s failed to disable %s.\n", __func__,
+ clk->name);
+ }
+}
+
+static struct clkops audioclk_ops = {
+ .enable = audioclk_enable,
+ .disable = audioclk_disable,
+};
+
+/* Primary camera clock operations */
+static int clkout0_enable(struct clk *clk)
+{
+ int r;
+
+ r = prcmu_config_clkout(0, PRCMU_CLKSRC_SYSCLK, 4);
+ if (r)
+ return r;
+ return nmk_config_pin(GPIO227_CLKOUT1, false);
+}
+
+static void clkout0_disable(struct clk *clk)
+{
+ int r;
+
+ r = nmk_config_pin(GPIO227_GPIO, false);
+ if (r)
+ goto disable_failed;
+ r = prcmu_config_clkout(0, PRCMU_CLKSRC_SYSCLK, 0);
+ if (!r)
+ return;
+disable_failed:
+ pr_err("clock: failed to disable %s.\n", clk->name);
+}
+
+/* Touch screen/secondary camera clock operations. */
+static int clkout1_enable(struct clk *clk)
+{
+ int r;
+
+ r = prcmu_config_clkout(1, PRCMU_CLKSRC_SYSCLK, 4);
+ if (r)
+ return r;
+ return nmk_config_pin(GPIO228_CLKOUT2, false);
+}
+
+static void clkout1_disable(struct clk *clk)
+{
+ int r;
+
+ r = nmk_config_pin(GPIO228_GPIO, false);
+ if (r)
+ goto disable_failed;
+ r = prcmu_config_clkout(1, PRCMU_CLKSRC_SYSCLK, 0);
+ if (!r)
+ return;
+disable_failed:
+ pr_err("clock: failed to disable %s.\n", clk->name);
+}
+
+static struct clkops clkout0_ops = {
+ .enable = clkout0_enable,
+ .disable = clkout0_disable,
+};
+
+static struct clkops clkout1_ops = {
+ .enable = clkout1_enable,
+ .disable = clkout1_disable,
+};
+
+#define DEF_PER1_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U8500_CLKRST1_BASE, _cg_bit, &per1clk)
+#define DEF_PER2_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U8500_CLKRST2_BASE, _cg_bit, &per2clk)
+#define DEF_PER3_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U8500_CLKRST3_BASE, _cg_bit, &per3clk)
+#define DEF_PER5_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U8500_CLKRST5_BASE, _cg_bit, &per5clk)
+#define DEF_PER6_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U8500_CLKRST6_BASE, _cg_bit, &per6clk)
+#define DEF_PER7_PCLK(_cg_bit, _name) \
+ DEF_PRCC_PCLK(_name, U8500_CLKRST7_BASE_ED, _cg_bit, &per7clk)
+
+#define DEF_PER1_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U8500_CLKRST1_BASE, _cg_bit, _parent)
+#define DEF_PER2_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U8500_CLKRST2_BASE, _cg_bit, _parent)
+#define DEF_PER3_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U8500_CLKRST3_BASE, _cg_bit, _parent)
+#define DEF_PER5_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U8500_CLKRST5_BASE, _cg_bit, _parent)
+#define DEF_PER6_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U8500_CLKRST6_BASE, _cg_bit, _parent)
+#define DEF_PER7_KCLK(_cg_bit, _name, _parent) \
+ DEF_PRCC_KCLK(_name, U8500_CLKRST7_BASE_ED, _cg_bit, _parent)
+
+#define DEF_MTU_CLK(_cg_sel, _name, _bus_parent) \
+ struct clk _name = { \
+ .name = #_name, \
+ .ops = &mtu_clk_ops, \
+ .cg_sel = _cg_sel, \
+ .bus_parent = _bus_parent, \
+ }
+
+/* Clock sources. */
+
+static struct clk soc0_pll = {
+ .name = "soc0_pll",
+ .ops = &pll_clk_ops,
+};
+
+static struct clk soc1_pll = {
+ .name = "soc1_pll",
+ .ops = &prcmu_clk_ops,
+ .cg_sel = PRCMU_PLLSOC1,
+ .mutex = &soc1_pll_mutex,
+};
+
+static struct clk ddr_pll = {
+ .name = "ddr_pll",
+ .ops = &pll_clk_ops,
+};
+
+static struct clk ulp38m4 = {
+ .name = "ulp38m4",
+};
+
+static struct clk sysclk = {
+ .name = "sysclk",
+ .ops = &sysclk_ops,
+ .rate = 38400000,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk sysclk2 = {
+ .name = "sysclk2",
+ .ops = &sysclk_ops,
+ .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk sysclk3 = {
+ .name = "sysclk3",
+ .ops = &sysclk_ops,
+ .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk sysclk4 = {
+ .name = "sysclk4",
+ .ops = &sysclk_ops,
+ .cg_sel = AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk rtc32k = {
+ .name = "rtc32k",
+ .rate = 32768,
+};
+
+static struct clk clkout0 = {
+ .name = "clkout0",
+ .ops = &clkout0_ops,
+ .parent = &sysclk,
+ .rate = 9600000,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk clkout1 = {
+ .name = "clkout1",
+ .ops = &clkout1_ops,
+ .parent = &sysclk,
+ .rate = 9600000,
+ .mutex = &sysclk_mutex,
+};
+
+static struct clk ab_ulpclk = {
+ .name = "ab_ulpclk",
+ .ops = &ab_ulpclk_ops,
+ .rate = 38400000,
+ .mutex = &ab_ulpclk_mutex,
+};
+
+static struct clk *audioclk_parents[] = { &sysclk, &ab_ulpclk, NULL };
+
+static struct clk audioclk = {
+ .name = "audioclk",
+ .ops = &audioclk_ops,
+ .mutex = &audioclk_mutex,
+ .parent = &sysclk,
+ .parents = audioclk_parents,
+};
+
+static DEF_PRCMU_CLK(sgaclk, PRCMU_SGACLK, 320000000);
+static DEF_PRCMU_CLK(uartclk, PRCMU_UARTCLK, 38400000);
+static DEF_PRCMU_CLK(msp02clk, PRCMU_MSP02CLK, 19200000);
+static DEF_PRCMU_CLK(msp1clk, PRCMU_MSP1CLK, 19200000);
+static DEF_PRCMU_CLK(i2cclk, PRCMU_I2CCLK, 24000000);
+static DEF_PRCMU_CLK(slimclk, PRCMU_SLIMCLK, 19200000);
+static DEF_PRCMU_CLK(per1clk, PRCMU_PER1CLK, 133330000);
+static DEF_PRCMU_CLK(per2clk, PRCMU_PER2CLK, 133330000);
+static DEF_PRCMU_CLK(per3clk, PRCMU_PER3CLK, 133330000);
+static DEF_PRCMU_CLK(per5clk, PRCMU_PER5CLK, 133330000);
+static DEF_PRCMU_CLK(per6clk, PRCMU_PER6CLK, 133330000);
+static DEF_PRCMU_CLK(per7clk, PRCMU_PER7CLK, 100000000);
+static DEF_PRCMU_CLK(lcdclk, PRCMU_LCDCLK, 48000000);
+static DEF_PRCMU_OPP100_CLK(bmlclk, PRCMU_BMLCLK, 200000000);
+static DEF_PRCMU_CLK(hsitxclk, PRCMU_HSITXCLK, 100000000);
+static DEF_PRCMU_CLK(hsirxclk, PRCMU_HSIRXCLK, 200000000);
+static DEF_PRCMU_CLK(hdmiclk, PRCMU_HDMICLK, 76800000);
+static DEF_PRCMU_CLK(apeatclk, PRCMU_APEATCLK, 160000000);
+static DEF_PRCMU_CLK(apetraceclk, PRCMU_APETRACECLK, 160000000);
+static DEF_PRCMU_CLK(mcdeclk, PRCMU_MCDECLK, 160000000);
+static DEF_PRCMU_OPP100_CLK(ipi2cclk, PRCMU_IPI2CCLK, 24000000);
+static DEF_PRCMU_CLK(dsialtclk, PRCMU_DSIALTCLK, 384000000);
+static DEF_PRCMU_CLK(dmaclk, PRCMU_DMACLK, 200000000);
+static DEF_PRCMU_CLK(b2r2clk, PRCMU_B2R2CLK, 200000000);
+static DEF_PRCMU_CLK(tvclk, PRCMU_TVCLK, 76800000);
+/* TODO: For SSPCLK, the spec says 24MHz, while the old driver says 48MHz. */
+static DEF_PRCMU_CLK(sspclk, PRCMU_SSPCLK, 24000000);
+static DEF_PRCMU_CLK(rngclk, PRCMU_RNGCLK, 19200000);
+static DEF_PRCMU_CLK(uiccclk, PRCMU_UICCCLK, 48000000);
+static DEF_PRCMU_CLK(timclk, PRCMU_TIMCLK, 2400000);
+static DEF_PRCMU_CLK(sdmmcclk, PRCMU_SDMMCCLK, 50000000);
+
+/* PRCC PClocks */
+
+static DEF_PER1_PCLK(0, p1_pclk0);
+static DEF_PER1_PCLK(1, p1_pclk1);
+static DEF_PER1_PCLK(2, p1_pclk2);
+static DEF_PER1_PCLK(3, p1_pclk3);
+static DEF_PER1_PCLK(4, p1_pclk4);
+static DEF_PER1_PCLK(5, p1_pclk5);
+static DEF_PER1_PCLK(6, p1_pclk6);
+static DEF_PER1_PCLK(7, p1_pclk7);
+static DEF_PER1_PCLK(8, p1_pclk8);
+static DEF_PER1_PCLK(9, p1_pclk9);
+static DEF_PER1_PCLK(10, p1_pclk10);
+static DEF_PER1_PCLK(11, p1_pclk11);
+
+static DEF_PER2_PCLK(0, p2_pclk0);
+static DEF_PER2_PCLK(1, p2_pclk1);
+static DEF_PER2_PCLK(2, p2_pclk2);
+static DEF_PER2_PCLK(3, p2_pclk3);
+static DEF_PER2_PCLK(4, p2_pclk4);
+static DEF_PER2_PCLK(5, p2_pclk5);
+static DEF_PER2_PCLK(6, p2_pclk6);
+static DEF_PER2_PCLK(7, p2_pclk7);
+static DEF_PER2_PCLK(8, p2_pclk8);
+static DEF_PER2_PCLK(9, p2_pclk9);
+static DEF_PER2_PCLK(10, p2_pclk10);
+static DEF_PER2_PCLK(11, p2_pclk11);
+static DEF_PER2_PCLK(12, p2_pclk12);
+
+static DEF_PER3_PCLK(0, p3_pclk0);
+static DEF_PER3_PCLK(1, p3_pclk1);
+static DEF_PER3_PCLK(2, p3_pclk2);
+static DEF_PER3_PCLK(3, p3_pclk3);
+static DEF_PER3_PCLK(4, p3_pclk4);
+static DEF_PER3_PCLK(5, p3_pclk5);
+static DEF_PER3_PCLK(6, p3_pclk6);
+static DEF_PER3_PCLK(7, p3_pclk7);
+static DEF_PER3_PCLK(8, p3_pclk8);
+
+static DEF_PER5_PCLK(0, p5_pclk0);
+static DEF_PER5_PCLK(1, p5_pclk1);
+
+static DEF_PER6_PCLK(0, p6_pclk0);
+static DEF_PER6_PCLK(1, p6_pclk1);
+static DEF_PER6_PCLK(2, p6_pclk2);
+static DEF_PER6_PCLK(3, p6_pclk3);
+static DEF_PER6_PCLK(4, p6_pclk4);
+static DEF_PER6_PCLK(5, p6_pclk5);
+static DEF_PER6_PCLK(6, p6_pclk6);
+static DEF_PER6_PCLK(7, p6_pclk7);
+
+static DEF_PER7_PCLK(0, p7_pclk0);
+static DEF_PER7_PCLK(1, p7_pclk1);
+static DEF_PER7_PCLK(2, p7_pclk2);
+static DEF_PER7_PCLK(3, p7_pclk3);
+static DEF_PER7_PCLK(4, p7_pclk4);
+
+/* UART0 */
+static DEF_PER1_KCLK(0, p1_uart0_kclk, &uartclk);
+static DEF_PER_CLK(p1_uart0_clk, &p1_pclk0, &p1_uart0_kclk);
+
+/* UART1 */
+static DEF_PER1_KCLK(1, p1_uart1_kclk, &uartclk);
+static DEF_PER_CLK(p1_uart1_clk, &p1_pclk1, &p1_uart1_kclk);
+
+/* I2C1 */
+static DEF_PER1_KCLK(2, p1_i2c1_kclk, &i2cclk);
+static DEF_PER_CLK(p1_i2c1_clk, &p1_pclk2, &p1_i2c1_kclk);
+
+/* MSP0 */
+static DEF_PER1_KCLK(3, p1_msp0_kclk, &msp02clk);
+static DEF_PER_CLK(p1_msp0_clk, &p1_pclk3, &p1_msp0_kclk);
+
+/* MSP1 */
+static DEF_PER1_KCLK(4, p1_msp1_kclk, &msp1clk);
+static DEF_PER_CLK(p1_msp1_clk, &p1_pclk4, &p1_msp1_kclk);
+
+static DEF_PER1_KCLK(4, p1_msp1_ed_kclk, &msp02clk);
+static DEF_PER_CLK(p1_msp1_ed_clk, &p1_pclk4, &p1_msp1_ed_kclk);
+
+/* SDI0 */
+static DEF_PER1_KCLK(5, p1_sdi0_kclk, &sdmmcclk);
+static DEF_PER_CLK(p1_sdi0_clk, &p1_pclk5, &p1_sdi0_kclk);
+
+/* I2C2 */
+static DEF_PER1_KCLK(6, p1_i2c2_kclk, &i2cclk);
+static DEF_PER_CLK(p1_i2c2_clk, &p1_pclk6, &p1_i2c2_kclk);
+
+/* SLIMBUS0 */
+static DEF_PER1_KCLK(3, p1_slimbus0_kclk, &slimclk);
+static DEF_PER_CLK(p1_slimbus0_clk, &p1_pclk8, &p1_slimbus0_kclk);
+
+/* I2C4 */
+static DEF_PER1_KCLK(9, p1_i2c4_kclk, &i2cclk);
+static DEF_PER_CLK(p1_i2c4_clk, &p1_pclk10, &p1_i2c4_kclk);
+
+/* MSP3 */
+static DEF_PER1_KCLK(10, p1_msp3_kclk, &msp1clk);
+static DEF_PER_CLK(p1_msp3_clk, &p1_pclk11, &p1_msp3_kclk);
+
+/* I2C3 */
+static DEF_PER2_KCLK(0, p2_i2c3_kclk, &i2cclk);
+static DEF_PER_CLK(p2_i2c3_clk, &p2_pclk0, &p2_i2c3_kclk);
+
+/* SDI4 */
+static DEF_PER2_KCLK(2, p2_sdi4_kclk, &sdmmcclk);
+static DEF_PER_CLK(p2_sdi4_clk, &p2_pclk4, &p2_sdi4_kclk);
+
+/* MSP2 */
+static DEF_PER2_KCLK(3, p2_msp2_kclk, &msp02clk);
+static DEF_PER_CLK(p2_msp2_clk, &p2_pclk5, &p2_msp2_kclk);
+
+static DEF_PER2_KCLK(4, p2_msp2_ed_kclk, &msp02clk);
+static DEF_PER_CLK(p2_msp2_ed_clk, &p2_pclk6, &p2_msp2_ed_kclk);
+
+/* SDI1 */
+static DEF_PER2_KCLK(4, p2_sdi1_kclk, &sdmmcclk);
+static DEF_PER_CLK(p2_sdi1_clk, &p2_pclk6, &p2_sdi1_kclk);
+
+/* These are probably broken now. */
+static DEF_PER2_KCLK(5, p2_sdi1_ed_kclk, &sdmmcclk);
+static DEF_PER_CLK(p2_sdi1_ed_clk, &p2_pclk7, &p2_sdi1_ed_kclk);
+
+/* SDI3 */
+static DEF_PER2_KCLK(5, p2_sdi3_kclk, &sdmmcclk);
+static DEF_PER_CLK(p2_sdi3_clk, &p2_pclk7, &p2_sdi3_kclk);
+
+/* These are probably broken now. */
+static DEF_PER2_KCLK(6, p2_sdi3_ed_kclk, &sdmmcclk);
+static DEF_PER_CLK(p2_sdi3_ed_clk, &p2_pclk8, &p2_sdi3_ed_kclk);
+
+/* HSIR */
+static DEF_PER2_KCLK(6, p2_ssirx_kclk, &hsirxclk);
+
+/* HSIT */
+static DEF_PER2_KCLK(7, p2_ssitx_kclk, &hsitxclk);
+
+/* SSP0 */
+static DEF_PER3_KCLK(1, p3_ssp0_kclk, &sspclk);
+static DEF_PER_CLK(p3_ssp0_clk, &p3_pclk1, &p3_ssp0_kclk);
+
+static DEF_PER3_KCLK(1, p3_ssp0_ed_kclk, &i2cclk);
+static DEF_PER_CLK(p3_ssp0_ed_clk, &p3_pclk1, &p3_ssp0_ed_kclk);
+
+/* SSP1 */
+static DEF_PER3_KCLK(2, p3_ssp1_kclk, &sspclk);
+static DEF_PER_CLK(p3_ssp1_clk, &p3_pclk2, &p3_ssp1_kclk);
+
+static DEF_PER3_KCLK(2, p3_ssp1_ed_kclk, &i2cclk);
+static DEF_PER_CLK(p3_ssp1_ed_clk, &p3_pclk2, &p3_ssp1_ed_kclk);
+
+/* I2C0 */
+static DEF_PER3_KCLK(3, p3_i2c0_kclk, &i2cclk);
+static DEF_PER_CLK(p3_i2c0_clk, &p3_pclk3, &p3_i2c0_kclk);
+
+/* SDI2 */
+static DEF_PER3_KCLK(4, p3_sdi2_kclk, &sdmmcclk);
+static DEF_PER_CLK(p3_sdi2_clk, &p3_pclk4, &p3_sdi2_kclk);
+
+/* SKE */
+static DEF_PER3_KCLK(5, p3_ske_kclk, &rtc32k);
+static DEF_PER_CLK(p3_ske_clk, &p3_pclk5, &p3_ske_kclk);
+
+/* UART2 */
+static DEF_PER3_KCLK(6, p3_uart2_kclk, &uartclk);
+static DEF_PER_CLK(p3_uart2_clk, &p3_pclk6, &p3_uart2_kclk);
+
+/* SDI5 */
+static DEF_PER3_KCLK(7, p3_sdi5_kclk, &sdmmcclk);
+static DEF_PER_CLK(p3_sdi5_clk, &p3_pclk7, &p3_sdi5_kclk);
+
+/* USB */
+static DEF_PER5_KCLK(0, p5_usb_ed_kclk, &i2cclk);
+static DEF_PER_CLK(p5_usb_ed_clk, &p5_pclk0, &p5_usb_ed_kclk);
+
+/* RNG */
+static DEF_PER6_KCLK(0, p6_rng_kclk, &rngclk);
+static DEF_PER_CLK(p6_rng_clk, &p6_pclk0, &p6_rng_kclk);
+
+static DEF_PER6_KCLK(0, p6_rng_ed_kclk, &i2cclk);
+static DEF_PER_CLK(p6_rng_ed_clk, &p6_pclk0, &p6_rng_ed_kclk);
+
+
+/* MTU:S */
+
+/* MTU0 */
+static DEF_PER_CLK(p6_mtu0_clk, &p6_pclk6, &timclk);
+static DEF_PER_CLK(p7_mtu0_ed_clk, &p7_pclk2, &timclk);
+
+/* MTU1 */
+static DEF_PER_CLK(p6_mtu1_clk, &p6_pclk7, &timclk);
+static DEF_PER_CLK(p7_mtu1_ed_clk, &p7_pclk3, &timclk);
+
+#ifdef CONFIG_DEBUG_FS
+
+struct clk_debug_info {
+ struct clk *clk;
+ struct dentry *dir;
+ struct dentry *enable;
+ struct dentry *requests;
+ int enabled;
+};
+
+static struct dentry *clk_dir;
+static struct dentry *clk_show;
+static struct dentry *clk_show_enabled_only;
+
+static struct clk_debug_info dbg_clks[] = {
+ /* Clock sources */
+ { .clk = &soc0_pll, },
+ { .clk = &soc1_pll, },
+ { .clk = &ddr_pll, },
+ { .clk = &ulp38m4, },
+ { .clk = &sysclk, },
+ { .clk = &rtc32k, },
+ /* PRCMU clocks */
+ { .clk = &sgaclk, },
+ { .clk = &uartclk, },
+ { .clk = &msp02clk, },
+ { .clk = &msp1clk, },
+ { .clk = &i2cclk, },
+ { .clk = &sdmmcclk, },
+ { .clk = &slimclk, },
+ { .clk = &per1clk, },
+ { .clk = &per2clk, },
+ { .clk = &per3clk, },
+ { .clk = &per5clk, },
+ { .clk = &per6clk, },
+ { .clk = &per7clk, },
+ { .clk = &lcdclk, },
+ { .clk = &bmlclk, },
+ { .clk = &hsitxclk, },
+ { .clk = &hsirxclk, },
+ { .clk = &hdmiclk, },
+ { .clk = &apeatclk, },
+ { .clk = &apetraceclk, },
+ { .clk = &mcdeclk, },
+ { .clk = &ipi2cclk, },
+ { .clk = &dsialtclk, },
+ { .clk = &dmaclk, },
+ { .clk = &b2r2clk, },
+ { .clk = &tvclk, },
+ { .clk = &sspclk, },
+ { .clk = &rngclk, },
+ { .clk = &uiccclk, },
+};
+
+static struct clk_debug_info dbg_clks_v2[] = {
+ /* Clock sources */
+ { .clk = &sysclk2, },
+ { .clk = &clkout0, },
+ { .clk = &clkout1, },
+};
+
+static int clk_show_print(struct seq_file *s, void *p)
+{
+ int i;
+ int enabled_only = (int)s->private;
+
+ seq_printf(s, "\n%-20s %s\n", "name", "enabled (kernel + debug)");
+ for (i = 0; i < ARRAY_SIZE(dbg_clks); i++) {
+ if (enabled_only && !dbg_clks[i].clk->enabled)
+ continue;
+ seq_printf(s,
+ "%-20s %5d + %d\n",
+ dbg_clks[i].clk->name,
+ dbg_clks[i].clk->enabled - dbg_clks[i].enabled,
+ dbg_clks[i].enabled);
+ }
+ if (cpu_is_u8500v2()) {
+ for (i = 0; i < ARRAY_SIZE(dbg_clks_v2); i++) {
+ if (enabled_only && !dbg_clks_v2[i].clk->enabled)
+ continue;
+ seq_printf(s,
+ "%-20s %5d + %d\n",
+ dbg_clks_v2[i].clk->name,
+ (dbg_clks_v2[i].clk->enabled -
+ dbg_clks_v2[i].enabled),
+ dbg_clks_v2[i].enabled);
+ }
+ }
+
+ return 0;
+}
+
+static int clk_show_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_show_print, inode->i_private);
+}
+
+static int clk_enable_print(struct seq_file *s, void *p)
+{
+ struct clk_debug_info *cdi = s->private;
+
+ return seq_printf(s, "%d\n", cdi->enabled);
+}
+
+static int clk_enable_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_enable_print, inode->i_private);
+}
+
+static ssize_t clk_enable_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct clk_debug_info *cdi;
+ char buf[32];
+ ssize_t buf_size;
+ long user_val;
+ int err;
+
+ cdi = ((struct seq_file *)(file->private_data))->private;
+
+ buf_size = min(count, (sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = '\0';
+
+ err = strict_strtol(buf, 0, &user_val);
+ if (err)
+ return -EINVAL;
+ if ((user_val > 0) && (!cdi->enabled)) {
+ err = clk_enable(cdi->clk);
+ if (err) {
+ pr_err("clock: clk_enable(%s) failed.\n",
+ cdi->clk->name);
+ return -EFAULT;
+ }
+ cdi->enabled = 1;
+ } else if ((user_val <= 0) && (cdi->enabled)) {
+ clk_disable(cdi->clk);
+ cdi->enabled = 0;
+ }
+ return buf_size;
+}
+
+static int clk_requests_print(struct seq_file *s, void *p)
+{
+ struct clk_debug_info *cdi = s->private;
+
+ return seq_printf(s, "%d\n", cdi->clk->enabled);
+}
+
+static int clk_requests_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_requests_print, inode->i_private);
+}
+
+static const struct file_operations clk_enable_fops = {
+ .open = clk_enable_open,
+ .write = clk_enable_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations clk_requests_fops = {
+ .open = clk_requests_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations clk_show_fops = {
+ .open = clk_show_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static int create_clk_dirs(struct clk_debug_info *cdi, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ cdi[i].dir = debugfs_create_dir(cdi[i].clk->name, clk_dir);
+ if (!cdi[i].dir)
+ goto no_dir;
+ }
+
+ for (i = 0; i < size; i++) {
+ cdi[i].enable = debugfs_create_file("enable",
+ (S_IRUGO | S_IWUGO),
+ cdi[i].dir, &cdi[i],
+ &clk_enable_fops);
+ if (!cdi[i].enable)
+ goto no_enable;
+ }
+ for (i = 0; i < size; i++) {
+ cdi[i].requests = debugfs_create_file("requests", S_IRUGO,
+ cdi[i].dir, &cdi[i],
+ &clk_requests_fops);
+ if (!cdi[i].requests)
+ goto no_requests;
+ }
+ return 0;
+
+no_requests:
+ while (i--)
+ debugfs_remove(cdi[i].requests);
+ i = size;
+no_enable:
+ while (i--)
+ debugfs_remove(cdi[i].enable);
+ i = size;
+no_dir:
+ while (i--)
+ debugfs_remove(cdi[i].dir);
+
+ return -ENOMEM;
+}
+
+static void remove_clk_dirs(struct clk_debug_info *cdi, int size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ debugfs_remove(cdi[i].requests);
+ debugfs_remove(cdi[i].enable);
+ debugfs_remove(cdi[i].dir);
+ }
+}
+
+static int __init clk_debug_init(void)
+{
+ clk_dir = debugfs_create_dir("clk", NULL);
+ if (!clk_dir)
+ goto no_dir;
+
+ clk_show = debugfs_create_file("show", S_IRUGO, clk_dir, (void *)0,
+ &clk_show_fops);
+ if (!clk_show)
+ goto no_show;
+
+ clk_show_enabled_only = debugfs_create_file("show-enabled-only",
+ S_IRUGO, clk_dir, (void *)1,
+ &clk_show_fops);
+ if (!clk_show_enabled_only)
+ goto no_enabled_only;
+
+ if (create_clk_dirs(&dbg_clks[0], ARRAY_SIZE(dbg_clks)))
+ goto no_clks;
+
+ if (cpu_is_u8500v2()) {
+ if (create_clk_dirs(&dbg_clks_v2[0], ARRAY_SIZE(dbg_clks_v2)))
+ goto common_clks;
+ }
+ return 0;
+
+common_clks:
+ remove_clk_dirs(&dbg_clks[0], ARRAY_SIZE(dbg_clks));
+no_clks:
+ debugfs_remove(clk_show_enabled_only);
+no_enabled_only:
+ debugfs_remove(clk_show);
+no_show:
+ debugfs_remove(clk_dir);
+no_dir:
+ return -ENOMEM;
+}
+
+static void __exit clk_debug_exit(void)
+{
+ remove_clk_dirs(&dbg_clks[0], ARRAY_SIZE(dbg_clks));
+ if (cpu_is_u8500v2())
+ remove_clk_dirs(&dbg_clks_v2[0], ARRAY_SIZE(dbg_clks_v2));
+
+ debugfs_remove(clk_show);
+ debugfs_remove(clk_show_enabled_only);
+ debugfs_remove(clk_dir);
+}
+
+subsys_initcall(clk_debug_init);
+module_exit(clk_debug_exit);
+#endif /* CONFIG_DEBUG_FS */
+
+/*
+ * TODO: Ensure names match with devices and then remove unnecessary entries
+ * when all drivers use the clk API.
+ */
+
+#define CLK_LOOKUP(_clk, _dev_id, _con_id) \
+ { .dev_id = _dev_id, .con_id = _con_id, .clk = &_clk }
+
+static struct clk_lookup u8500_common_clock_sources[] = {
+ CLK_LOOKUP(soc0_pll, NULL, "soc0_pll"),
+ CLK_LOOKUP(soc1_pll, NULL, "soc1_pll"),
+ CLK_LOOKUP(ddr_pll, NULL, "ddr_pll"),
+ CLK_LOOKUP(ulp38m4, NULL, "ulp38m4"),
+ CLK_LOOKUP(sysclk, NULL, "sysclk"),
+ CLK_LOOKUP(rtc32k, NULL, "clk32k"),
+ CLK_LOOKUP(sysclk, "ab8500-usb.0", "sysclk"),
+ CLK_LOOKUP(sysclk, "ab8500-codec.0", "sysclk"),
+ CLK_LOOKUP(ab_ulpclk, "ab8500-codec.0", "ulpclk"),
+ CLK_LOOKUP(audioclk, "ab8500-codec.0", "audioclk"),
+ CLK_LOOKUP(ab_ulpclk, "ab8500-pwm.1", NULL),
+ CLK_LOOKUP(ab_ulpclk, "ab8500-pwm.2", NULL),
+ CLK_LOOKUP(ab_ulpclk, "ab8500-pwm.3", NULL),
+};
+
+static struct clk_lookup u8500_v2_sysclks[] = {
+ CLK_LOOKUP(sysclk2, NULL, "sysclk2"),
+ CLK_LOOKUP(sysclk3, NULL, "sysclk3"),
+ CLK_LOOKUP(sysclk4, NULL, "sysclk4"),
+};
+
+static struct clk_lookup u8500_common_prcmu_clocks[] = {
+ CLK_LOOKUP(sgaclk, "mali", NULL),
+ CLK_LOOKUP(uartclk, "UART", NULL),
+ CLK_LOOKUP(msp02clk, "MSP02", NULL),
+ CLK_LOOKUP(i2cclk, "I2C", NULL),
+ CLK_LOOKUP(sdmmcclk, "sdmmc", NULL),
+ CLK_LOOKUP(slimclk, "slim", NULL),
+ CLK_LOOKUP(per1clk, "PERIPH1", NULL),
+ CLK_LOOKUP(per2clk, "PERIPH2", NULL),
+ CLK_LOOKUP(per3clk, "PERIPH3", NULL),
+ CLK_LOOKUP(per5clk, "PERIPH5", NULL),
+ CLK_LOOKUP(per6clk, "PERIPH6", NULL),
+ CLK_LOOKUP(per7clk, "PERIPH7", NULL),
+ CLK_LOOKUP(lcdclk, "lcd", NULL),
+ CLK_LOOKUP(bmlclk, "bml", NULL),
+ CLK_LOOKUP(p2_ssitx_kclk, "ste_hsi.0", "hsit_hsitxclk"),
+ CLK_LOOKUP(p2_ssirx_kclk, "ste_hsi.0", "hsir_hsirxclk"),
+ CLK_LOOKUP(lcdclk, "mcde", "lcd"),
+ CLK_LOOKUP(hdmiclk, "hdmi", NULL),
+ CLK_LOOKUP(hdmiclk, "mcde", "hdmi"),
+ CLK_LOOKUP(apeatclk, "apeat", NULL),
+ CLK_LOOKUP(apetraceclk, "apetrace", NULL),
+ CLK_LOOKUP(mcdeclk, "mcde", NULL),
+ CLK_LOOKUP(mcdeclk, "mcde", "mcde"),
+ CLK_LOOKUP(ipi2cclk, "ipi2", NULL),
+ CLK_LOOKUP(dmaclk, "dma40.0", NULL),
+ CLK_LOOKUP(b2r2clk, "b2r2", NULL),
+ CLK_LOOKUP(b2r2clk, "b2r2_bus", NULL),
+ CLK_LOOKUP(b2r2clk, "U8500-B2R2.0", NULL),
+ CLK_LOOKUP(tvclk, "tv", NULL),
+ CLK_LOOKUP(tvclk, "mcde", "tv"),
+};
+
+static struct clk_lookup u8500_common_prcc_clocks[] = {
+ /* PERIPH 1 */
+ CLK_LOOKUP(p1_uart0_clk, "uart0", NULL),
+ CLK_LOOKUP(p1_uart1_clk, "uart1", NULL),
+ CLK_LOOKUP(p1_i2c1_clk, "nmk-i2c.1", NULL),
+ CLK_LOOKUP(p1_msp0_clk, "msp0", NULL),
+ CLK_LOOKUP(p1_msp0_clk, "MSP_I2S.0", NULL),
+ CLK_LOOKUP(p1_sdi0_clk, "sdi0", NULL),
+ CLK_LOOKUP(p1_i2c2_clk, "nmk-i2c.2", NULL),
+ CLK_LOOKUP(p1_slimbus0_clk, "slimbus0", NULL),
+ CLK_LOOKUP(p1_pclk9, "gpio.0", NULL),
+ CLK_LOOKUP(p1_pclk9, "gpio.1", NULL),
+ CLK_LOOKUP(p1_pclk9, "gpioblock0", NULL),
+
+ /* PERIPH 2 */
+ CLK_LOOKUP(p2_i2c3_clk, "nmk-i2c.3", NULL),
+ CLK_LOOKUP(p2_pclk1, "spi2", NULL),
+ CLK_LOOKUP(p2_pclk2, "spi1", NULL),
+ CLK_LOOKUP(p2_pclk3, "pwl", NULL),
+ CLK_LOOKUP(p2_sdi4_clk, "sdi4", NULL),
+
+ /* PERIPH 3 */
+ CLK_LOOKUP(p3_pclk0, "fsmc", NULL),
+ CLK_LOOKUP(p3_i2c0_clk, "nmk-i2c.0", NULL),
+ CLK_LOOKUP(p3_sdi2_clk, "sdi2", NULL),
+ CLK_LOOKUP(p3_ske_clk, "ske", NULL),
+ CLK_LOOKUP(p3_ske_clk, "nmk-ske-keypad", NULL),
+ CLK_LOOKUP(p3_uart2_clk, "uart2", NULL),
+ CLK_LOOKUP(p3_sdi5_clk, "sdi5", NULL),
+ CLK_LOOKUP(p3_pclk8, "gpio.2", NULL),
+ CLK_LOOKUP(p3_pclk8, "gpio.3", NULL),
+ CLK_LOOKUP(p3_pclk8, "gpio.4", NULL),
+ CLK_LOOKUP(p3_pclk8, "gpio.5", NULL),
+ CLK_LOOKUP(p3_pclk8, "gpioblock2", NULL),
+
+ /* PERIPH 5 */
+ CLK_LOOKUP(p5_pclk1, "gpio.8", NULL),
+ CLK_LOOKUP(p5_pclk1, "gpioblock3", NULL),
+
+ /* PERIPH 6 */
+ CLK_LOOKUP(p6_pclk1, "cryp0", NULL),
+ CLK_LOOKUP(p6_pclk2, "hash0", NULL),
+ CLK_LOOKUP(p6_pclk3, "pka", NULL),
+};
+
+static struct clk_lookup u8500_ed_prcc_clocks[] = {
+ /* PERIPH 1 */
+ CLK_LOOKUP(p1_msp1_ed_clk, "msp1", NULL),
+ CLK_LOOKUP(p1_msp1_ed_clk, "MSP_I2S.1", NULL),
+ CLK_LOOKUP(p1_pclk7, "spi3", NULL),
+
+ /* PERIPH 2 */
+ CLK_LOOKUP(p2_msp2_ed_clk, "msp2", NULL),
+ CLK_LOOKUP(p2_msp2_ed_clk, "MSP_I2S.2", NULL),
+ CLK_LOOKUP(p2_sdi1_ed_clk, "sdi1", NULL),
+ CLK_LOOKUP(p2_sdi3_ed_clk, "sdi3", NULL),
+ CLK_LOOKUP(p2_pclk9, "spi0", NULL),
+ CLK_LOOKUP(p2_pclk12, "gpio.6", NULL),
+ CLK_LOOKUP(p2_pclk12, "gpio.7", NULL),
+ CLK_LOOKUP(p2_pclk12, "gpioblock1", NULL),
+
+ /* PERIPH 3 */
+ CLK_LOOKUP(p3_ssp0_ed_clk, "ssp0", NULL),
+ CLK_LOOKUP(p3_ssp1_ed_clk, "ssp1", NULL),
+
+ /* PERIPH 5 */
+ CLK_LOOKUP(p5_usb_ed_clk, "musb_hdrc.0", "usb"),
+
+ /* PERIPH 6 */
+ CLK_LOOKUP(p6_rng_ed_clk, "rng", NULL),
+ CLK_LOOKUP(p6_pclk4, "cryp1", NULL),
+ CLK_LOOKUP(p6_pclk5, "hash1", NULL),
+ CLK_LOOKUP(p6_pclk6, "dmc", NULL),
+
+ /* PERIPH 7 */
+ CLK_LOOKUP(p7_pclk0, "cfgreg", NULL),
+ CLK_LOOKUP(p7_pclk1, "wdg", NULL),
+ CLK_LOOKUP(p7_mtu0_ed_clk, "mtu0", NULL),
+ CLK_LOOKUP(p7_mtu1_ed_clk, "mtu1", NULL),
+ CLK_LOOKUP(p7_pclk4, "tzpc0", NULL),
+};
+
+static struct clk_lookup u8500_v1_v2_prcmu_clocks[] = {
+ CLK_LOOKUP(msp1clk, "MSP1", NULL),
+ CLK_LOOKUP(dsialtclk, "dsialt", NULL),
+ CLK_LOOKUP(sspclk, "SSP", NULL),
+ CLK_LOOKUP(rngclk, "rngclk", NULL),
+ CLK_LOOKUP(uiccclk, "uicc", NULL),
+};
+
+static struct clk_lookup u8500_v1_v2_prcc_clocks[] = {
+ /* PERIPH 1 */
+ CLK_LOOKUP(p1_msp1_clk, "msp1", NULL),
+ CLK_LOOKUP(p1_msp1_clk, "MSP_I2S.1", NULL),
+ CLK_LOOKUP(p1_msp1_kclk, "ab8500-codec.0", "msp1-kernel"),
+ CLK_LOOKUP(p1_pclk4, "ab8500-codec.0", "msp1-bus"),
+ CLK_LOOKUP(p1_pclk7, "spi3", NULL),
+ CLK_LOOKUP(p1_i2c4_clk, "nmk-i2c.4", NULL),
+
+ /* PERIPH 2 */
+ CLK_LOOKUP(p2_msp2_clk, "msp2", NULL),
+ CLK_LOOKUP(p2_msp2_clk, "MSP_I2S.2", NULL),
+ CLK_LOOKUP(p2_sdi1_clk, "sdi1", NULL),
+ CLK_LOOKUP(p2_sdi3_clk, "sdi3", NULL),
+ CLK_LOOKUP(p2_pclk8, "spi0", NULL),
+ CLK_LOOKUP(p2_pclk9, "ste_hsi.0", "hsir_hclk"),
+ CLK_LOOKUP(p2_pclk10, "ste_hsi.0", "hsit_hclk"),
+ CLK_LOOKUP(p2_pclk11, "gpio.6", NULL),
+ CLK_LOOKUP(p2_pclk11, "gpio.7", NULL),
+ CLK_LOOKUP(p2_pclk11, "gpioblock1", NULL),
+
+ /* PERIPH 3 */
+ CLK_LOOKUP(p3_ssp0_clk, "ssp0", NULL),
+ CLK_LOOKUP(p3_ssp1_clk, "ssp1", NULL),
+
+ /* PERIPH 5 */
+ CLK_LOOKUP(p5_pclk0, "musb_hdrc.0", "usb"),
+
+ /* PERIPH 6 */
+ CLK_LOOKUP(p6_pclk5, "hash1", NULL),
+ CLK_LOOKUP(p6_pclk4, "cryp1", NULL),
+ CLK_LOOKUP(p6_rng_clk, "rng", NULL),
+};
+
+static struct clk_lookup u8500_v2_prcmu_clocks[] = {
+ CLK_LOOKUP(clkout0, "pri-cam", NULL),
+ CLK_LOOKUP(clkout1, "3-005c", NULL),
+ CLK_LOOKUP(clkout1, "3-005d", NULL),
+ CLK_LOOKUP(clkout1, "sec-cam", NULL),
+};
+
+static struct clk_lookup u8500_v2_prcc_clocks[] = {
+ /* PERIPH 1 */
+ CLK_LOOKUP(p1_msp3_clk, "msp3", NULL),
+ CLK_LOOKUP(p1_msp3_clk, "MSP_I2S.3", NULL),
+ CLK_LOOKUP(p1_msp3_kclk, "ab8500-codec.0", "msp3-kernel"),
+ CLK_LOOKUP(p1_pclk11, "ab8500-codec.0", "msp3-bus"),
+
+ /* PERIPH 6 */
+ CLK_LOOKUP(p6_pclk4, "hash1", NULL),
+ CLK_LOOKUP(p6_pclk4, "cryp1", NULL),
+ CLK_LOOKUP(p6_pclk5, "cfgreg", NULL),
+ CLK_LOOKUP(p6_mtu0_clk, "mtu0", NULL),
+ CLK_LOOKUP(p6_mtu1_clk, "mtu1", NULL),
+};
+
+/* these are the clocks which are default from the bootloader */
+static const char *u8500_boot_clk[] = {
+ "uart0",
+ "uart1",
+ "uart2",
+ "gpioblock0",
+ "gpioblock1",
+ "gpioblock2",
+ "gpioblock3",
+ "mtu0",
+ "mtu1",
+ "ssp0",
+ "ssp1",
+ "spi0",
+ "spi1",
+ "spi2",
+ "spi3",
+ "msp0",
+ "msp2",
+ "nmk-i2c.0",
+ "nmk-i2c.1",
+ "nmk-i2c.2",
+ "nmk-i2c.3",
+ "nmk-i2c.4",
+};
+
+static void sysclk_init_disable(struct work_struct *not_used)
+{
+ int i;
+
+ mutex_lock(&sysclk_mutex);
+
+ /* Enable SWAT */
+ if (ab8500_sysctrl_set(AB8500_SWATCTRL, AB8500_SWATCTRL_SWATENABLE))
+ goto err_swat;
+
+ for (i = 0; i < ARRAY_SIZE(u8500_v2_sysclks); i++) {
+ struct clk *clk = u8500_v2_sysclks[i].clk;
+
+ /* Disable sysclks */
+ if (!clk->enabled && clk->cg_sel) {
+ if (ab8500_sysctrl_clear(AB8500_SYSULPCLKCTRL1,
+ (u8)clk->cg_sel))
+ goto err_sysclk;
+ }
+ }
+ goto unlock_and_exit;
+
+err_sysclk:
+ pr_err("clock: Disable %s failed", u8500_v2_sysclks[i].clk->name);
+ ab8500_sysctrl_clear(AB8500_SWATCTRL, AB8500_SWATCTRL_SWATENABLE);
+ goto unlock_and_exit;
+
+err_swat:
+ pr_err("clock: Enable SWAT failed");
+
+unlock_and_exit:
+ mutex_unlock(&sysclk_mutex);
+}
+
+struct clk *boot_clks[ARRAY_SIZE(u8500_boot_clk)];
+
+/* we disable a majority of peripherals enabled by default
+ * but without drivers
+ */
+static int __init u8500_boot_clk_disable(void)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < ARRAY_SIZE(u8500_boot_clk); i++) {
+ if (!boot_clks[i])
+ continue;
+
+ clk_disable(boot_clks[i]);
+ clk_put(boot_clks[i]);
+ }
+
+ INIT_DELAYED_WORK(&sysclk_disable_work, sysclk_init_disable);
+ schedule_delayed_work(&sysclk_disable_work, 10 * HZ);
+
+ return 0;
+}
+late_initcall_sync(u8500_boot_clk_disable);
+
+static void u8500_amba_clk_enable(void)
+{
+ unsigned int i = 0;
+
+ writel(~0x0 & ~(1 << 9), __io_address(U8500_PER1_BASE + 0xF000
+ + 0x04));
+ writel(~0x0, __io_address(U8500_PER1_BASE + 0xF000 + 0x0C));
+
+ writel(~0x0 & ~(1 << 11), __io_address(U8500_PER2_BASE + 0xF000
+ + 0x04));
+ writel(~0x0, __io_address(U8500_PER2_BASE + 0xF000 + 0x0C));
+
+ /*GPIO,UART2 are enabled for booting*/
+ writel(0xBF, __io_address(U8500_PER3_BASE + 0xF000 + 0x04));
+ writel(~0x0 & ~(1 << 6), __io_address(U8500_PER3_BASE + 0xF000
+ + 0x0C));
+
+ for (i = 0; i < ARRAY_SIZE(u8500_boot_clk); i++) {
+ boot_clks[i] = clk_get_sys(u8500_boot_clk[i], NULL);
+ clk_enable(boot_clks[i]);
+ }
+}
+
+int __init db8500_clk_init(void)
+{
+ if (cpu_is_u8500ed()) {
+ pr_err("clock: U8500 ED is no longer supported.\n");
+ return -ENOSYS;
+ } else if (cpu_is_u8500v1()) {
+ pr_err("clock: U8500 V1 is no longer supported.\n");
+ return -ENOSYS;
+ } else if (cpu_is_u5500()) {
+ per6clk.rate = 26000000;
+ uartclk.rate = 36360000;
+ }
+
+ if (cpu_is_u5500() || ux500_is_svp()) {
+ sysclk_ops.enable = NULL;
+ sysclk_ops.disable = NULL;
+ prcmu_clk_ops.enable = NULL;
+ prcmu_clk_ops.disable = NULL;
+ prcmu_opp100_clk_ops.enable = NULL;
+ prcmu_opp100_clk_ops.disable = NULL;
+ prcc_pclk_ops.enable = NULL;
+ prcc_pclk_ops.disable = NULL;
+ prcc_kclk_ops.enable = NULL;
+ prcc_kclk_ops.disable = NULL;
+ clkout0_ops.enable = NULL;
+ clkout0_ops.disable = NULL;
+ clkout1_ops.enable = NULL;
+ clkout1_ops.disable = NULL;
+ }
+
+ clks_register(u8500_common_clock_sources,
+ ARRAY_SIZE(u8500_common_clock_sources));
+ clks_register(u8500_common_prcmu_clocks,
+ ARRAY_SIZE(u8500_common_prcmu_clocks));
+ clks_register(u8500_common_prcc_clocks,
+ ARRAY_SIZE(u8500_common_prcc_clocks));
+
+ if (cpu_is_u5500()) {
+ clks_register(u8500_ed_prcc_clocks,
+ ARRAY_SIZE(u8500_ed_prcc_clocks));
+ } else if (cpu_is_u8500v2()) {
+ clks_register(u8500_v2_sysclks,
+ ARRAY_SIZE(u8500_v2_sysclks));
+ clks_register(u8500_v1_v2_prcmu_clocks,
+ ARRAY_SIZE(u8500_v1_v2_prcmu_clocks));
+ clks_register(u8500_v2_prcmu_clocks,
+ ARRAY_SIZE(u8500_v2_prcmu_clocks));
+ clks_register(u8500_v1_v2_prcc_clocks,
+ ARRAY_SIZE(u8500_v1_v2_prcc_clocks));
+ clks_register(u8500_v2_prcc_clocks,
+ ARRAY_SIZE(u8500_v2_prcc_clocks));
+ }
+
+ if (cpu_is_u8500())
+ u8500_amba_clk_enable();
+
+ /*
+ * The following clks are shared with secure world.
+ * Currently this leads to a limitation where we need to
+ * enable them at all times.
+ */
+ clk_enable(&p6_pclk1);
+ clk_enable(&p6_pclk2);
+ clk_enable(&p6_pclk3);
+ if (cpu_is_u8500() && !ux500_is_svp())
+ clk_enable(&p6_rng_clk);
+
+ /*
+ * APEATCLK and APETRACECLK are enabled at boot and needed
+ * in order to debug with lauterbach
+ */
+ clk_enable(&apeatclk);
+ clk_enable(&apetraceclk);
+#ifdef CONFIG_UX500_DEBUG_NO_LAUTERBACH
+ clk_disable(&apeatclk);
+ clk_disable(&apetraceclk);
+#endif
+ /* periph 7's clock is enabled at boot, but should be off */
+ clk_enable(&per7clk);
+ clk_disable(&per7clk);
+
+ /* the hsirx clock is enabled at boot, but should be off */
+ clk_enable(&hsirxclk);
+ clk_disable(&hsirxclk);
+
+ return 0;
+}
diff --git a/arch/arm/mach-ux500/clock-debug.c b/arch/arm/mach-ux500/clock-debug.c
new file mode 100644
index 00000000000..939edfaa94a
--- /dev/null
+++ b/arch/arm/mach-ux500/clock-debug.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+
+#include "clock.h"
+
+struct clk_debug_info {
+ struct clk *clk;
+ struct dentry *dir;
+ struct dentry *enable;
+ struct dentry *requests;
+ int enabled;
+};
+
+#ifdef CONFIG_DEBUG_FS
+
+static struct dentry *clk_dir;
+static struct dentry *clk_show;
+static struct dentry *clk_show_enabled_only;
+
+static struct clk_debug_info *cdi;
+static int num_clks;
+
+static int clk_show_print(struct seq_file *s, void *p)
+{
+ int i;
+ int enabled_only = (int)s->private;
+
+ seq_printf(s, "\n%-20s %s\n", "name", "enabled (kernel + debug)");
+ for (i = 0; i < num_clks; i++) {
+ if (enabled_only && !cdi[i].clk->enabled)
+ continue;
+ seq_printf(s,
+ "%-20s %5d + %d\n",
+ cdi[i].clk->name,
+ cdi[i].clk->enabled - cdi[i].enabled,
+ cdi[i].enabled);
+ }
+
+ return 0;
+}
+
+static int clk_show_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_show_print, inode->i_private);
+}
+
+static int clk_enable_print(struct seq_file *s, void *p)
+{
+ struct clk_debug_info *cdi = s->private;
+
+ return seq_printf(s, "%d\n", cdi->enabled);
+}
+
+static int clk_enable_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_enable_print, inode->i_private);
+}
+
+static ssize_t clk_enable_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct clk_debug_info *cdi;
+ char buf[32];
+ ssize_t buf_size;
+ long user_val;
+ int err;
+
+ cdi = ((struct seq_file *)(file->private_data))->private;
+
+ buf_size = min(count, (sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = '\0';
+
+ err = strict_strtol(buf, 0, &user_val);
+ if (err)
+ return -EINVAL;
+ if ((user_val > 0) && (!cdi->enabled)) {
+ err = clk_enable(cdi->clk);
+ if (err) {
+ pr_err("clock: clk_enable(%s) failed.\n",
+ cdi->clk->name);
+ return -EFAULT;
+ }
+ cdi->enabled = 1;
+ } else if ((user_val <= 0) && (cdi->enabled)) {
+ clk_disable(cdi->clk);
+ cdi->enabled = 0;
+ }
+ return buf_size;
+}
+
+static int clk_requests_print(struct seq_file *s, void *p)
+{
+ struct clk_debug_info *cdi = s->private;
+
+ return seq_printf(s, "%d\n", cdi->clk->enabled);
+}
+
+static int clk_requests_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clk_requests_print, inode->i_private);
+}
+
+static const struct file_operations clk_enable_fops = {
+ .open = clk_enable_open,
+ .write = clk_enable_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations clk_requests_fops = {
+ .open = clk_requests_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations clk_show_fops = {
+ .open = clk_show_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static int create_clk_dirs(struct clk_debug_info *cdi, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ cdi[i].dir = debugfs_create_dir(cdi[i].clk->name, clk_dir);
+ if (!cdi[i].dir)
+ goto no_dir;
+ }
+
+ for (i = 0; i < size; i++) {
+ cdi[i].enable = debugfs_create_file("enable",
+ (S_IRUGO | S_IWUGO),
+ cdi[i].dir, &cdi[i],
+ &clk_enable_fops);
+ if (!cdi[i].enable)
+ goto no_enable;
+ }
+ for (i = 0; i < size; i++) {
+ cdi[i].requests = debugfs_create_file("requests", S_IRUGO,
+ cdi[i].dir, &cdi[i],
+ &clk_requests_fops);
+ if (!cdi[i].requests)
+ goto no_requests;
+ }
+ return 0;
+
+no_requests:
+ while (i--)
+ debugfs_remove(cdi[i].requests);
+ i = size;
+no_enable:
+ while (i--)
+ debugfs_remove(cdi[i].enable);
+ i = size;
+no_dir:
+ while (i--)
+ debugfs_remove(cdi[i].dir);
+
+ return -ENOMEM;
+}
+
+int __init dbx500_clk_debug_init(struct clk **clks, int num)
+{
+ int i;
+
+ cdi = kcalloc(sizeof(struct clk_debug_info), num, GFP_KERNEL);
+ if (!cdi)
+ return -ENOMEM;
+
+ for (i = 0; i < num; i++)
+ cdi[i].clk = clks[i];
+
+ num_clks = num;
+
+ clk_dir = debugfs_create_dir("clk", NULL);
+ if (!clk_dir)
+ goto no_dir;
+
+ clk_show = debugfs_create_file("show", S_IRUGO, clk_dir, (void *)0,
+ &clk_show_fops);
+ if (!clk_show)
+ goto no_show;
+
+ clk_show_enabled_only = debugfs_create_file("show-enabled-only",
+ S_IRUGO, clk_dir, (void *)1,
+ &clk_show_fops);
+ if (!clk_show_enabled_only)
+ goto no_enabled_only;
+
+ if (create_clk_dirs(cdi, num))
+ goto no_clks;
+
+ return 0;
+
+no_clks:
+ debugfs_remove(clk_show_enabled_only);
+no_enabled_only:
+ debugfs_remove(clk_show);
+no_show:
+ debugfs_remove(clk_dir);
+no_dir:
+ kfree(cdi);
+ return -ENOMEM;
+}
+
+#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index 0a1318fc8e2..85cbae721bb 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -7,611 +7,380 @@
* published by the Free Software Foundation.
*/
#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/mfd/ab8500/sysctrl.h>
+#include <mach/prcmu-fw-api.h>
-#include <asm/clkdev.h>
-
-#include <plat/mtu.h>
-#include <mach/hardware.h>
#include "clock.h"
-#define PRCC_PCKEN 0x00
-#define PRCC_PCKDIS 0x04
-#define PRCC_KCKEN 0x08
-#define PRCC_KCKDIS 0x0C
-
-#define PRCM_YYCLKEN0_MGT_SET 0x510
-#define PRCM_YYCLKEN1_MGT_SET 0x514
-#define PRCM_YYCLKEN0_MGT_CLR 0x518
-#define PRCM_YYCLKEN1_MGT_CLR 0x51C
-#define PRCM_YYCLKEN0_MGT_VAL 0x520
-#define PRCM_YYCLKEN1_MGT_VAL 0x524
-
-#define PRCM_SVAMMDSPCLK_MGT 0x008
-#define PRCM_SIAMMDSPCLK_MGT 0x00C
-#define PRCM_SGACLK_MGT 0x014
-#define PRCM_UARTCLK_MGT 0x018
-#define PRCM_MSP02CLK_MGT 0x01C
-#define PRCM_MSP1CLK_MGT 0x288
-#define PRCM_I2CCLK_MGT 0x020
-#define PRCM_SDMMCCLK_MGT 0x024
-#define PRCM_SLIMCLK_MGT 0x028
-#define PRCM_PER1CLK_MGT 0x02C
-#define PRCM_PER2CLK_MGT 0x030
-#define PRCM_PER3CLK_MGT 0x034
-#define PRCM_PER5CLK_MGT 0x038
-#define PRCM_PER6CLK_MGT 0x03C
-#define PRCM_PER7CLK_MGT 0x040
-#define PRCM_LCDCLK_MGT 0x044
-#define PRCM_BMLCLK_MGT 0x04C
-#define PRCM_HSITXCLK_MGT 0x050
-#define PRCM_HSIRXCLK_MGT 0x054
-#define PRCM_HDMICLK_MGT 0x058
-#define PRCM_APEATCLK_MGT 0x05C
-#define PRCM_APETRACECLK_MGT 0x060
-#define PRCM_MCDECLK_MGT 0x064
-#define PRCM_IPI2CCLK_MGT 0x068
-#define PRCM_DSIALTCLK_MGT 0x06C
-#define PRCM_DMACLK_MGT 0x074
-#define PRCM_B2R2CLK_MGT 0x078
-#define PRCM_TVCLK_MGT 0x07C
-#define PRCM_TCR 0x1C8
-#define PRCM_TCR_STOPPED (1 << 16)
-#define PRCM_TCR_DOZE_MODE (1 << 17)
-#define PRCM_UNIPROCLK_MGT 0x278
-#define PRCM_SSPCLK_MGT 0x280
-#define PRCM_RNGCLK_MGT 0x284
-#define PRCM_UICCCLK_MGT 0x27C
-
-#define PRCM_MGT_ENABLE (1 << 8)
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-static void __clk_enable(struct clk *clk)
-{
- if (clk->enabled++ == 0) {
- if (clk->parent_cluster)
- __clk_enable(clk->parent_cluster);
+#define PRCC_PCKEN 0x0
+#define PRCC_PCKDIS 0x4
+#define PRCC_KCKEN 0x8
+#define PRCC_KCKDIS 0xC
+#define PRCC_PCKSR 0x10
+#define PRCC_KCKSR 0x14
- if (clk->parent_periph)
- __clk_enable(clk->parent_periph);
+DEFINE_MUTEX(clk_opp100_mutex);
+static DEFINE_SPINLOCK(clk_spin_lock);
+#define NO_LOCK &clk_spin_lock
- if (clk->ops && clk->ops->enable)
- clk->ops->enable(clk);
+static void __iomem *prcmu_base;
+
+static void __clk_lock(struct clk *clk, void *last_lock, unsigned long *flags)
+{
+ if (clk->mutex != last_lock) {
+ if (clk->mutex == NULL)
+ spin_lock_irqsave(&clk_spin_lock, *flags);
+ else
+ mutex_lock(clk->mutex);
}
}
-int clk_enable(struct clk *clk)
+static void __clk_unlock(struct clk *clk, void *last_lock, unsigned long flags)
+{
+ if (clk->mutex != last_lock) {
+ if (clk->mutex == NULL)
+ spin_unlock_irqrestore(&clk_spin_lock, flags);
+ else
+ mutex_unlock(clk->mutex);
+ }
+}
+
+static void __clk_disable(struct clk *clk, void *current_lock)
{
unsigned long flags;
- spin_lock_irqsave(&clocks_lock, flags);
- __clk_enable(clk);
- spin_unlock_irqrestore(&clocks_lock, flags);
+ if (clk == NULL)
+ return;
- return 0;
-}
-EXPORT_SYMBOL(clk_enable);
+ __clk_lock(clk, current_lock, &flags);
-static void __clk_disable(struct clk *clk)
-{
- if (--clk->enabled == 0) {
- if (clk->ops && clk->ops->disable)
+ if (clk->enabled && (--clk->enabled == 0)) {
+ if ((clk->ops != NULL) && (clk->ops->disable != NULL))
clk->ops->disable(clk);
+ __clk_disable(clk->parent, clk->mutex);
+ __clk_disable(clk->bus_parent, clk->mutex);
+ }
- if (clk->parent_periph)
- __clk_disable(clk->parent_periph);
+ __clk_unlock(clk, current_lock, flags);
- if (clk->parent_cluster)
- __clk_disable(clk->parent_cluster);
- }
+ return;
}
-void clk_disable(struct clk *clk)
+static int __clk_enable(struct clk *clk, void *current_lock)
{
+ int err;
unsigned long flags;
- WARN_ON(!clk->enabled);
+ if (clk == NULL)
+ return 0;
- spin_lock_irqsave(&clocks_lock, flags);
- __clk_disable(clk);
- spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
+ __clk_lock(clk, current_lock, &flags);
-/*
- * The MTU has a separate, rather complex muxing setup
- * with alternative parents (peripheral cluster or
- * ULP or fixed 32768 Hz) depending on settings
- */
-static unsigned long clk_mtu_get_rate(struct clk *clk)
-{
- void __iomem *addr = __io_address(UX500_PRCMU_BASE)
- + PRCM_TCR;
- u32 tcr = readl(addr);
- int mtu = (int) clk->data;
- /*
- * One of these is selected eventually
- * TODO: Replace the constant with a reference
- * to the ULP source once this is modeled.
- */
- unsigned long clk32k = 32768;
- unsigned long mturate;
- unsigned long retclk;
-
- /* Get the rate from the parent as a default */
- if (clk->parent_periph)
- mturate = clk_get_rate(clk->parent_periph);
- else if (clk->parent_cluster)
- mturate = clk_get_rate(clk->parent_cluster);
- else
- /* We need to be connected SOMEWHERE */
- BUG();
-
- /*
- * Are we in doze mode?
- * In this mode the parent peripheral or the fixed 32768 Hz
- * clock is fed into the block.
- */
- if (!(tcr & PRCM_TCR_DOZE_MODE)) {
- /*
- * Here we're using the clock input from the APE ULP
- * clock domain. But first: are the timers stopped?
- */
- if (tcr & PRCM_TCR_STOPPED) {
- clk32k = 0;
- mturate = 0;
- } else {
- /* Else default mode: 0 and 2.4 MHz */
- clk32k = 0;
- if (cpu_is_u5500())
- /* DB5500 divides by 8 */
- mturate /= 8;
- else if (cpu_is_u8500ed()) {
- /*
- * This clocking setting must not be used
- * in the ED chip, it is simply not
- * connected anywhere!
- */
- mturate = 0;
- BUG();
- } else
- /*
- * In this mode the ulp38m4 clock is divided
- * by a factor 16, on the DB8500 typically
- * 38400000 / 16 ~ 2.4 MHz.
- * TODO: Replace the constant with a reference
- * to the ULP source once this is modeled.
- */
- mturate = 38400000 / 16;
+ if (!clk->enabled) {
+ err = __clk_enable(clk->bus_parent, clk->mutex);
+ if (unlikely(err))
+ goto bus_parent_error;
+
+ err = __clk_enable(clk->parent, clk->mutex);
+ if (unlikely(err))
+ goto parent_error;
+
+ if ((clk->ops != NULL) && (clk->ops->enable != NULL)) {
+ err = clk->ops->enable(clk);
+ if (unlikely(err))
+ goto enable_error;
}
}
+ clk->enabled++;
- /* Return the clock selected for this MTU */
- if (tcr & (1 << mtu))
- retclk = clk32k;
- else
- retclk = mturate;
+ __clk_unlock(clk, current_lock, flags);
+
+ return 0;
+
+enable_error:
+ __clk_disable(clk->parent, clk->mutex);
+parent_error:
+ __clk_disable(clk->bus_parent, clk->mutex);
+bus_parent_error:
- pr_info("MTU%d clock rate: %lu Hz\n", mtu, retclk);
- return retclk;
+ __clk_unlock(clk, current_lock, flags);
+
+ return err;
}
-unsigned long clk_get_rate(struct clk *clk)
+unsigned long __clk_get_rate(struct clk *clk, void *current_lock)
{
unsigned long rate;
+ unsigned long flags;
- /*
- * If there is a custom getrate callback for this clock,
- * it will take precedence.
- */
- if (clk->get_rate)
- return clk->get_rate(clk);
-
- if (clk->ops && clk->ops->get_rate)
- return clk->ops->get_rate(clk);
-
- rate = clk->rate;
- if (!rate) {
- if (clk->parent_periph)
- rate = clk_get_rate(clk->parent_periph);
- else if (clk->parent_cluster)
- rate = clk_get_rate(clk->parent_cluster);
- }
+ if (clk == NULL)
+ return 0;
+
+ __clk_lock(clk, current_lock, &flags);
+
+ if ((clk->ops != NULL) && (clk->ops->get_rate != NULL))
+ rate = clk->ops->get_rate(clk);
+ else if (clk->rate)
+ rate = clk->rate;
+ else
+ rate = __clk_get_rate(clk->parent, clk->mutex);
+
+ __clk_unlock(clk, current_lock, flags);
return rate;
}
+
+static unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ if ((clk->ops != NULL) && (clk->ops->round_rate != NULL))
+ return clk->ops->round_rate(clk, rate);
+
+ return -ENOSYS;
+}
+
+static int __clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ if ((clk->ops != NULL) && (clk->ops->set_rate != NULL))
+ return clk->ops->set_rate(clk, rate);
+
+ return -ENOSYS;
+}
+
+int clk_enable(struct clk *clk)
+{
+ if (clk == NULL)
+ return -EINVAL;
+
+ return __clk_enable(clk, NO_LOCK);
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+
+ if (clk == NULL)
+ return;
+
+ WARN_ON(!clk->enabled);
+ __clk_disable(clk, NO_LOCK);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (clk == NULL)
+ return 0;
+
+ return __clk_get_rate(clk, NO_LOCK);
+}
EXPORT_SYMBOL(clk_get_rate);
long clk_round_rate(struct clk *clk, unsigned long rate)
{
- /*TODO*/
+ unsigned long flags;
+
+ if (clk == NULL)
+ return -EINVAL;
+
+ __clk_lock(clk, NO_LOCK, &flags);
+
+ rate = __clk_round_rate(clk, rate);
+
+ __clk_unlock(clk, NO_LOCK, flags);
+
return rate;
}
EXPORT_SYMBOL(clk_round_rate);
int clk_set_rate(struct clk *clk, unsigned long rate)
{
- clk->rate = rate;
- return 0;
+ int err;
+ unsigned long flags;
+
+ if (clk == NULL)
+ return -EINVAL;
+
+ __clk_lock(clk, NO_LOCK, &flags);
+
+ err = __clk_set_rate(clk, rate);
+
+ __clk_unlock(clk, NO_LOCK, flags);
+
+ return err;
}
EXPORT_SYMBOL(clk_set_rate);
-static void clk_prcmu_enable(struct clk *clk)
+int clk_set_parent(struct clk *clk, struct clk *parent)
{
- void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE)
- + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off;
+ int err = 0;
+ unsigned long flags;
+ struct clk **p;
+
+ if ((clk == NULL) || (clk->parents == NULL))
+ return -EINVAL;
+ for (p = clk->parents; *p != parent; p++) {
+ if (*p == NULL) /* invalid parent */
+ return -EINVAL;
+ }
+
+ __clk_lock(clk, NO_LOCK, &flags);
+
+ if ((clk->ops != NULL) && (clk->ops->set_parent != NULL)) {
+ err = clk->ops->set_parent(clk, parent);
+ if (err)
+ goto unlock_and_return;
+ } else if (clk->enabled) {
+ err = __clk_enable(parent, clk->mutex);
+ if (err)
+ goto unlock_and_return;
+ __clk_disable(clk->parent, clk->mutex);
+ }
+
+ clk->parent = parent;
- writel(1 << clk->prcmu_cg_bit, cg_set_reg);
+unlock_and_return:
+ __clk_unlock(clk, NO_LOCK, flags);
+
+ return err;
}
-static void clk_prcmu_disable(struct clk *clk)
-{
- void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE)
- + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off;
+/* PRCMU clock operations. */
- writel(1 << clk->prcmu_cg_bit, cg_clr_reg);
+static int prcmu_clk_enable(struct clk *clk)
+{
+ return prcmu_request_clock(clk->cg_sel, true);
}
-/* ED doesn't have the combined set/clr registers */
-static void clk_prcmu_ed_enable(struct clk *clk)
+static void prcmu_clk_disable(struct clk *clk)
{
- void __iomem *addr = __io_address(U8500_PRCMU_BASE)
- + clk->prcmu_cg_mgt;
+ if (prcmu_request_clock(clk->cg_sel, false)) {
+ pr_err("clock: %s failed to disable %s.\n", __func__,
+ clk->name);
+ }
+}
- writel(readl(addr) | PRCM_MGT_ENABLE, addr);
+static int request_ape_opp100(bool enable)
+{
+ static unsigned int requests;
+
+ if (enable) {
+ if (0 == requests++) {
+ return prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
+ "clock", 100);
+ }
+ } else if (1 == requests--) {
+ prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "clock");
+ }
+ return 0;
}
-static void clk_prcmu_ed_disable(struct clk *clk)
+static int prcmu_opp100_clk_enable(struct clk *clk)
{
- void __iomem *addr = __io_address(U8500_PRCMU_BASE)
- + clk->prcmu_cg_mgt;
+ int r;
+
+ r = request_ape_opp100(true);
+ if (r) {
+ pr_err("clock: %s failed to request APE OPP 100%% for %s.\n",
+ __func__, clk->name);
+ return r;
+ }
+ return prcmu_request_clock(clk->cg_sel, true);
+}
- writel(readl(addr) & ~PRCM_MGT_ENABLE, addr);
+static void prcmu_opp100_clk_disable(struct clk *clk)
+{
+ if (prcmu_request_clock(clk->cg_sel, false))
+ goto out_error;
+ if (request_ape_opp100(false))
+ goto out_error;
+ return;
+
+out_error:
+ pr_err("clock: %s failed to disable %s.\n", __func__, clk->name);
}
-static struct clkops clk_prcmu_ops = {
- .enable = clk_prcmu_enable,
- .disable = clk_prcmu_disable,
+struct clkops prcmu_clk_ops = {
+ .enable = prcmu_clk_enable,
+ .disable = prcmu_clk_disable,
};
-static unsigned int clkrst_base[] = {
- [1] = U8500_CLKRST1_BASE,
- [2] = U8500_CLKRST2_BASE,
- [3] = U8500_CLKRST3_BASE,
- [5] = U8500_CLKRST5_BASE,
- [6] = U8500_CLKRST6_BASE,
- [7] = U8500_CLKRST7_BASE_ED,
+struct clkops prcmu_opp100_clk_ops = {
+ .enable = prcmu_opp100_clk_enable,
+ .disable = prcmu_opp100_clk_disable,
};
-static void clk_prcc_enable(struct clk *clk)
-{
- void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
+/* PRCC clock operations. */
- if (clk->prcc_kernel != -1)
- writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN);
+static int prcc_pclk_enable(struct clk *clk)
+{
+ void __iomem *io_base = __io_address(clk->io_base);
- if (clk->prcc_bus != -1)
- writel(1 << clk->prcc_bus, addr + PRCC_PCKEN);
+ writel(clk->cg_sel, (io_base + PRCC_PCKEN));
+ while (!(readl(io_base + PRCC_PCKSR) & clk->cg_sel))
+ cpu_relax();
+ return 0;
}
-static void clk_prcc_disable(struct clk *clk)
+static void prcc_pclk_disable(struct clk *clk)
{
- void __iomem *addr = __io_address(clkrst_base[clk->cluster]);
-
- if (clk->prcc_bus != -1)
- writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS);
+ void __iomem *io_base = __io_address(clk->io_base);
- if (clk->prcc_kernel != -1)
- writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS);
+ writel(clk->cg_sel, (io_base + PRCC_PCKDIS));
}
-static struct clkops clk_prcc_ops = {
- .enable = clk_prcc_enable,
- .disable = clk_prcc_disable,
+struct clkops prcc_pclk_ops = {
+ .enable = prcc_pclk_enable,
+ .disable = prcc_pclk_disable,
};
-static struct clk clk_32khz = {
- .rate = 32000,
-};
+static int prcc_kclk_enable(struct clk *clk)
+{
+ void __iomem *io_base = __io_address(clk->io_base);
-/*
- * PRCMU level clock gating
- */
+ writel(clk->cg_sel, (io_base + PRCC_KCKEN));
+ while (!(readl(io_base + PRCC_KCKSR) & clk->cg_sel))
+ cpu_relax();
+ return 0;
+}
-/* Bank 0 */
-static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK);
-static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK);
-static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK);
-static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000);
-static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK);
-static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */
-static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000);
-static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 50000000);
-static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK);
-static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK);
-static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK);
-static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK);
-static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK);
-static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000);
-static DEFINE_PRCMU_CLK_RATE(per7clk, 0x0, 16, PER7CLK, 100000000);
-static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK);
-static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK);
-static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK);
-static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK);
-static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK);
-static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK);
-static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK);
-static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK);
-static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK);
-static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */
-static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK);
-static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK);
-static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK);
-static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */
-static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */
-
-/* Bank 1 */
-static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */
-static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */
+static void prcc_kclk_disable(struct clk *clk)
+{
+ void __iomem *io_base = __io_address(clk->io_base);
-/*
- * PRCC level clock gating
- * Format: per#, clk, PCKEN bit, KCKEN bit, parent
- */
+ writel(clk->cg_sel, (io_base + PRCC_KCKDIS));
+}
-/* Peripheral Cluster #1 */
-static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk);
-static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL);
-static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk);
-static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL);
-static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL);
-static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk);
-static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk);
-static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk);
-static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk);
-static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk);
-static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk);
-static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk);
-
-/* Peripheral Cluster #2 */
-
-static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL);
-static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk);
-static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL);
-static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL);
-static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk);
-
-static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL);
-static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL);
-static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL);
-static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL);
-static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk);
-static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL);
-static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL);
-static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL);
-static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk);
-
-/* Peripheral Cluster #3 */
-static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL);
-static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk);
-static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz);
-static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk);
-static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk);
-static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk);
-static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk);
-static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL);
-
-/* Peripheral Cluster #4 is in the always on domain */
-
-/* Peripheral Cluster #5 */
-static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL);
-static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk);
-static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL);
-
-/* Peripheral Cluster #6 */
-
-/* MTU ID in data */
-static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1);
-static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0);
-static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL);
-static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL);
-static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL);
-static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk);
-static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL);
-static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL);
-static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL);
-static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL);
-static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk);
-static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk);
-
-/* Peripheral Cluster #7 */
-
-static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL);
-/* MTU ID in data */
-static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1);
-static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
-static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL);
-static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL);
-
-static struct clk_lookup u8500_common_clks[] = {
- /* Peripheral Cluster #1 */
- CLK(gpio0, "gpio.0", NULL),
- CLK(gpio0, "gpio.1", NULL),
- CLK(slimbus0, "slimbus0", NULL),
- CLK(i2c2, "nmk-i2c.2", NULL),
- CLK(sdi0, "sdi0", NULL),
- CLK(msp0, "msp0", NULL),
- CLK(i2c1, "nmk-i2c.1", NULL),
- CLK(uart1, "uart1", NULL),
- CLK(uart0, "uart0", NULL),
-
- /* Peripheral Cluster #3 */
- CLK(gpio2, "gpio.2", NULL),
- CLK(gpio2, "gpio.3", NULL),
- CLK(gpio2, "gpio.4", NULL),
- CLK(gpio2, "gpio.5", NULL),
- CLK(sdi5, "sdi5", NULL),
- CLK(uart2, "uart2", NULL),
- CLK(ske, "ske", NULL),
- CLK(sdi2, "sdi2", NULL),
- CLK(i2c0, "nmk-i2c.0", NULL),
- CLK(fsmc, "fsmc", NULL),
-
- /* Peripheral Cluster #5 */
- CLK(gpio3, "gpio.8", NULL),
-
- /* Peripheral Cluster #6 */
- CLK(hash1, "hash1", NULL),
- CLK(pka, "pka", NULL),
- CLK(hash0, "hash0", NULL),
- CLK(cryp0, "cryp0", NULL),
-
- /* PRCMU level clock gating */
-
- /* Bank 0 */
- CLK(svaclk, "sva", NULL),
- CLK(siaclk, "sia", NULL),
- CLK(sgaclk, "sga", NULL),
- CLK(slimclk, "slim", NULL),
- CLK(lcdclk, "lcd", NULL),
- CLK(bmlclk, "bml", NULL),
- CLK(hsitxclk, "stm-hsi.0", NULL),
- CLK(hsirxclk, "stm-hsi.1", NULL),
- CLK(hdmiclk, "hdmi", NULL),
- CLK(apeatclk, "apeat", NULL),
- CLK(apetraceclk, "apetrace", NULL),
- CLK(mcdeclk, "mcde", NULL),
- CLK(ipi2clk, "ipi2", NULL),
- CLK(dmaclk, "dma40.0", NULL),
- CLK(b2r2clk, "b2r2", NULL),
- CLK(tvclk, "tv", NULL),
+struct clkops prcc_kclk_ops = {
+ .enable = prcc_kclk_enable,
+ .disable = prcc_kclk_disable,
};
-static struct clk_lookup u8500_ed_clks[] = {
- /* Peripheral Cluster #1 */
- CLK(spi3_ed, "spi3", NULL),
- CLK(msp1_ed, "msp1", NULL),
-
- /* Peripheral Cluster #2 */
- CLK(gpio1_ed, "gpio.6", NULL),
- CLK(gpio1_ed, "gpio.7", NULL),
- CLK(ssitx_ed, "ssitx", NULL),
- CLK(ssirx_ed, "ssirx", NULL),
- CLK(spi0_ed, "spi0", NULL),
- CLK(sdi3_ed, "sdi3", NULL),
- CLK(sdi1_ed, "sdi1", NULL),
- CLK(msp2_ed, "msp2", NULL),
- CLK(sdi4_ed, "sdi4", NULL),
- CLK(pwl_ed, "pwl", NULL),
- CLK(spi1_ed, "spi1", NULL),
- CLK(spi2_ed, "spi2", NULL),
- CLK(i2c3_ed, "nmk-i2c.3", NULL),
-
- /* Peripheral Cluster #3 */
- CLK(ssp1_ed, "ssp1", NULL),
- CLK(ssp0_ed, "ssp0", NULL),
-
- /* Peripheral Cluster #5 */
- CLK(usb_ed, "musb_hdrc.0", "usb"),
-
- /* Peripheral Cluster #6 */
- CLK(dmc_ed, "dmc", NULL),
- CLK(cryp1_ed, "cryp1", NULL),
- CLK(rng_ed, "rng", NULL),
-
- /* Peripheral Cluster #7 */
- CLK(tzpc0_ed, "tzpc0", NULL),
- CLK(mtu1_ed, "mtu1", NULL),
- CLK(mtu0_ed, "mtu0", NULL),
- CLK(wdg_ed, "wdg", NULL),
- CLK(cfgreg_ed, "cfgreg", NULL),
-};
+void clks_register(struct clk_lookup *clks, size_t num)
+{
+ unsigned int i;
-static struct clk_lookup u8500_v1_clks[] = {
- /* Peripheral Cluster #1 */
- CLK(i2c4, "nmk-i2c.4", NULL),
- CLK(spi3_v1, "spi3", NULL),
- CLK(msp1_v1, "msp1", NULL),
-
- /* Peripheral Cluster #2 */
- CLK(gpio1_v1, "gpio.6", NULL),
- CLK(gpio1_v1, "gpio.7", NULL),
- CLK(ssitx_v1, "ssitx", NULL),
- CLK(ssirx_v1, "ssirx", NULL),
- CLK(spi0_v1, "spi0", NULL),
- CLK(sdi3_v1, "sdi3", NULL),
- CLK(sdi1_v1, "sdi1", NULL),
- CLK(msp2_v1, "msp2", NULL),
- CLK(sdi4_v1, "sdi4", NULL),
- CLK(pwl_v1, "pwl", NULL),
- CLK(spi1_v1, "spi1", NULL),
- CLK(spi2_v1, "spi2", NULL),
- CLK(i2c3_v1, "nmk-i2c.3", NULL),
-
- /* Peripheral Cluster #3 */
- CLK(ssp1_v1, "ssp1", NULL),
- CLK(ssp0_v1, "ssp0", NULL),
-
- /* Peripheral Cluster #5 */
- CLK(usb_v1, "musb_hdrc.0", "usb"),
-
- /* Peripheral Cluster #6 */
- CLK(mtu1_v1, "mtu1", NULL),
- CLK(mtu0_v1, "mtu0", NULL),
- CLK(cfgreg_v1, "cfgreg", NULL),
- CLK(hash1, "hash1", NULL),
- CLK(unipro_v1, "unipro", NULL),
- CLK(rng_v1, "rng", NULL),
-
- /* PRCMU level clock gating */
-
- /* Bank 0 */
- CLK(uniproclk, "uniproclk", NULL),
- CLK(dsialtclk, "dsialt", NULL),
-
- /* Bank 1 */
- CLK(rngclk, "rng", NULL),
- CLK(uiccclk, "uicc", NULL),
-};
+ for (i = 0; i < num; i++)
+ clkdev_add(&clks[i]);
+}
int __init clk_init(void)
{
- if (cpu_is_u8500ed()) {
- clk_prcmu_ops.enable = clk_prcmu_ed_enable;
- clk_prcmu_ops.disable = clk_prcmu_ed_disable;
- clk_per6clk.rate = 100000000;
+ if (cpu_is_u8500()) {
+ prcmu_base = __io_address(U8500_PRCMU_BASE);
} else if (cpu_is_u5500()) {
- /* Clock tree for U5500 not implemented yet */
- clk_prcc_ops.enable = clk_prcc_ops.disable = NULL;
- clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL;
- clk_per6clk.rate = 26000000;
+ prcmu_base = __io_address(U5500_PRCMU_BASE);
+ } else {
+ pr_err("clock: Unknown DB Asic.\n");
+ return -EIO;
}
- clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
- if (cpu_is_u8500ed())
- clkdev_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
- else
- clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
+ if (cpu_is_u8500())
+ db8500_clk_init();
+ else if (cpu_is_u5500())
+ db5500_clk_init();
return 0;
}
diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h
index a0580250152..c242840e784 100644
--- a/arch/arm/mach-ux500/clock.h
+++ b/arch/arm/mach-ux500/clock.h
@@ -1,11 +1,53 @@
/*
- * Copyright (C) 2010 ST-Ericsson
+ * Copyright (C) 2010 ST-Ericsson SA
* Copyright (C) 2009 STMicroelectronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#ifndef UX500_CLOCK_H
+#define UX500_CLOCK_H
+
+#include <asm/clkdev.h>
+
+/**
+ * struct clk
+ * @ops: The hardware specific operations defined for the clock.
+ * @name: The name of the clock.
+ * @mutex: The mutex to lock when operating on the clock. %NULL means that
+ * the common clock spinlock will be used.
+ * @enabled: A reference counter of the enable requests for the clock.
+ * @opp100: A flag saying whether the clock is requested to run at the
+ * OPP 100%% frequency.
+ * @rate: The frequency of the clock. For scalable and scaling clocks,
+ * this is the OPP 100%% frequency.
+ * @io_base: An IO memory base address, meaningful only when considered
+ * together with the defined @ops.
+ * @cg_sel: Clock gate selector, meaningful only when considered together
+ * with the specified @ops.
+ * @parent: The current (or only) parent clock of the clock.
+ * @bus_parent: The (optional) auxiliary bus clock "parent" of the clock.
+ * @parents: A list of the possible parents the clock can have. This should
+ * be a %NULL-terminated &struct_clk array. Present if and only
+ * if clk_set_parent() is implemented for the clock.
+ * @regulator: The regulator needed to have the clock functional, if any.
+ */
+struct clk {
+ const struct clkops *ops;
+ const char *name;
+ struct mutex *mutex;
+ unsigned int enabled;
+ bool opp100;
+ unsigned long rate;
+ unsigned int io_base;
+ u32 cg_sel;
+ struct clk *parent;
+ struct clk *bus_parent;
+ struct clk **parents;
+ struct regulator *regulator;
+ struct list_head list;
+};
/**
* struct clkops - ux500 clock operations
@@ -18,130 +60,90 @@
* NULL, the rate in the struct clk will be used.
*/
struct clkops {
- void (*enable) (struct clk *);
- void (*disable) (struct clk *);
- unsigned long (*get_rate) (struct clk *);
+ int (*enable)(struct clk *);
+ void (*disable)(struct clk *);
+ unsigned long (*get_rate)(struct clk *);
+ int (*set_rate)(struct clk *, unsigned long);
+ unsigned long (*round_rate)(struct clk *, unsigned long);
+ int (*set_parent)(struct clk *, struct clk *);
};
-/**
- * struct clk - ux500 clock structure
- * @ops: pointer to clkops struct used to control this clock
- * @name: name, for debugging
- * @enabled: refcount. positive if enabled, zero if disabled
- * @get_rate: custom callback for getting the clock rate
- * @data: custom per-clock data for example for the get_rate
- * callback
- * @rate: fixed rate for clocks which don't implement
- * ops->getrate
- * @prcmu_cg_off: address offset of the combined enable/disable register
- * (used on u8500v1)
- * @prcmu_cg_bit: bit in the combined enable/disable register (used on
- * u8500v1)
- * @prcmu_cg_mgt: address of the enable/disable register (used on
- * u8500ed)
- * @cluster: peripheral cluster number
- * @prcc_bus: bit for the bus clock in the peripheral's CLKRST
- * @prcc_kernel: bit for the kernel clock in the peripheral's CLKRST.
- * -1 if no kernel clock exists.
- * @parent_cluster: pointer to parent's cluster clk struct
- * @parent_periph: pointer to parent's peripheral clk struct
- *
- * Peripherals are organised into clusters, and each cluster has an associated
- * bus clock. Some peripherals also have a parent peripheral clock.
- *
- * In order to enable a clock for a peripheral, we need to enable:
- * (1) the parent cluster (bus) clock at the PRCMU level
- * (2) the parent peripheral clock (if any) at the PRCMU level
- * (3) the peripheral's bus & kernel clock at the PRCC level
- *
- * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each
- * of the cluster and peripheral clocks, and hooking these as the parents of
- * the individual peripheral clocks.
- *
- * (3) is handled by specifying the bits in the PRCC control registers required
- * to enable these clocks and modifying them in the ->enable and
- * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK).
- *
- * This structure describes both the PRCMU-level clocks and PRCC-level clocks.
- * The prcmu_* fields are only used for the PRCMU clocks, and the cluster,
- * prcc, and parent pointers are only used for the PRCC-level clocks.
- */
-struct clk {
- const struct clkops *ops;
- const char *name;
- unsigned int enabled;
- unsigned long (*get_rate)(struct clk *);
- void *data;
-
- unsigned long rate;
- struct list_head list;
-
- /* These three are only for PRCMU clks */
-
- unsigned int prcmu_cg_off;
- unsigned int prcmu_cg_bit;
- unsigned int prcmu_cg_mgt;
+extern struct clkops prcmu_clk_ops;
+extern struct clkops prcmu_opp100_clk_ops;
+extern struct mutex clk_opp100_mutex;
+extern struct clkops prcc_pclk_ops;
+extern struct clkops prcc_kclk_ops;
+extern struct clkops sga_clk_ops;
- /* The rest are only for PRCC clks */
-
- int cluster;
- unsigned int prcc_bus;
- unsigned int prcc_kernel;
-
- struct clk *parent_cluster;
- struct clk *parent_periph;
-};
-
-#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \
-struct clk clk_##_name = { \
- .name = #_name, \
- .ops = &clk_prcmu_ops, \
- .prcmu_cg_off = _cg_off, \
- .prcmu_cg_bit = _cg_bit, \
- .prcmu_cg_mgt = PRCM_##_reg##_MGT \
+/* Define PRCMU Clock */
+#define DEF_PRCMU_CLK(_name, _cg_sel, _rate) \
+ struct clk _name = { \
+ .name = #_name, \
+ .ops = &prcmu_clk_ops, \
+ .cg_sel = _cg_sel, \
+ .rate = _rate, \
}
-#define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate) \
-struct clk clk_##_name = { \
- .name = #_name, \
- .ops = &clk_prcmu_ops, \
- .prcmu_cg_off = _cg_off, \
- .prcmu_cg_bit = _cg_bit, \
- .rate = _rate, \
- .prcmu_cg_mgt = PRCM_##_reg##_MGT \
+/* Use this for clocks that are only defined at OPP 100%. */
+#define DEF_PRCMU_OPP100_CLK(_name, _cg_sel, _rate) \
+ struct clk _name = { \
+ .name = #_name, \
+ .ops = &prcmu_opp100_clk_ops, \
+ .cg_sel = _cg_sel, \
+ .rate = _rate, \
+ .mutex = &clk_opp100_mutex, \
}
-#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \
-struct clk clk_##_name = { \
- .name = #_name, \
- .ops = &clk_prcc_ops, \
- .cluster = _pclust, \
- .prcc_bus = _bus_en, \
- .prcc_kernel = _kernel_en, \
- .parent_cluster = &clk_per##_pclust##clk, \
- .parent_periph = _kernclk \
+/* Define PRCC clock */
+#define DEF_PRCC_PCLK(_name, _io_base, _cg_bit, _parent) \
+ struct clk _name = { \
+ .name = #_name, \
+ .ops = &prcc_pclk_ops, \
+ .io_base = _io_base, \
+ .cg_sel = BIT(_cg_bit), \
+ .parent = _parent, \
}
-#define DEFINE_PRCC_CLK_CUSTOM(_pclust, _name, _bus_en, _kernel_en, _kernclk, _callback, _data) \
-struct clk clk_##_name = { \
- .name = #_name, \
- .ops = &clk_prcc_ops, \
- .cluster = _pclust, \
- .prcc_bus = _bus_en, \
- .prcc_kernel = _kernel_en, \
- .parent_cluster = &clk_per##_pclust##clk, \
- .parent_periph = _kernclk, \
- .get_rate = _callback, \
- .data = (void *) _data \
+#define DEF_PRCC_KCLK(_name, _io_base, _cg_bit, _parent) \
+ struct clk _name = { \
+ .name = #_name, \
+ .ops = &prcc_kclk_ops, \
+ .io_base = _io_base, \
+ .cg_sel = BIT(_cg_bit), \
+ .parent = _parent, \
}
-
-#define CLK(_clk, _devname, _conname) \
- { \
- .clk = &clk_##_clk, \
- .dev_id = _devname, \
- .con_id = _conname, \
+#define DEF_PER_CLK(_name, _bus_parent, _parent) \
+ struct clk _name = { \
+ .name = #_name, \
+ .parent = _parent, \
+ .bus_parent = _bus_parent, \
}
-int __init clk_db8500_ed_fixup(void);
+/* Functions defined in clock.c */
int __init clk_init(void);
+void clks_register(struct clk_lookup *clks, size_t num);
+unsigned long __clk_get_rate(struct clk *clk, void *current_lock);
+
+#ifdef CONFIG_DEBUG_FS
+int dbx500_clk_debug_init(struct clk **clks, int num);
+#else
+static inline int dbx500_clk_debug_init(struct clk **clks, int num)
+{
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_UX500_SOC_DB8500
+int __init db8500_clk_init(void);
+#else
+static inline int db8500_clk_init(void) { return 0; }
+#endif
+
+#ifdef CONFIG_UX500_SOC_DB5500
+int __init db5500_clk_init(void);
+#else
+static inline int db5500_clk_init(void) { return 0; }
+#endif
+
+#endif
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index e9278f6d67a..e94282808ec 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -8,20 +8,127 @@
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
#include <linux/io.h>
+#include <linux/err.h>
#include <asm/mach/map.h>
#include <mach/hardware.h>
#include <mach/devices.h>
#include <mach/setup.h>
+#include <mach/irqs.h>
+
+#include "devices-db5500.h"
static struct map_desc u5500_io_desc[] __initdata = {
+ __IO_DEV_DESC(U5500_MTU0_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_MTU1_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_SCU_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_TWD_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_UART0_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_UART1_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_UART2_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_RTC_BASE, SZ_4K),
__IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K),
__IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K),
__IO_DEV_DESC(U5500_GPIO2_BASE, SZ_4K),
__IO_DEV_DESC(U5500_GPIO3_BASE, SZ_4K),
__IO_DEV_DESC(U5500_GPIO4_BASE, SZ_4K),
__IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_PRCMU_TCDM_BASE, SZ_4K),
+ __MEM_DEV_DESC(U5500_BOOT_ROM_BASE, SZ_1M),
+ __IO_DEV_DESC(U5500_BACKUPRAM0_BASE, SZ_8K),
+ __IO_DEV_DESC(U5500_GIC_CPU_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_CLKRST1_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_CLKRST2_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_CLKRST3_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_CLKRST5_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_CLKRST6_BASE, SZ_4K),
+};
+
+static struct resource mbox0_resources[] = {
+ {
+ .name = "mbox_peer",
+ .start = U5500_MBOX0_PEER_START,
+ .end = U5500_MBOX0_PEER_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_local",
+ .start = U5500_MBOX0_LOCAL_START,
+ .end = U5500_MBOX0_LOCAL_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_irq",
+ .start = MBOX_PAIR0_VIRT_IRQ,
+ .end = MBOX_PAIR0_VIRT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource mbox1_resources[] = {
+ {
+ .name = "mbox_peer",
+ .start = U5500_MBOX1_PEER_START,
+ .end = U5500_MBOX1_PEER_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_local",
+ .start = U5500_MBOX1_LOCAL_START,
+ .end = U5500_MBOX1_LOCAL_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_irq",
+ .start = MBOX_PAIR1_VIRT_IRQ,
+ .end = MBOX_PAIR1_VIRT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource mbox2_resources[] = {
+ {
+ .name = "mbox_peer",
+ .start = U5500_MBOX2_PEER_START,
+ .end = U5500_MBOX2_PEER_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_local",
+ .start = U5500_MBOX2_LOCAL_START,
+ .end = U5500_MBOX2_LOCAL_END,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "mbox_irq",
+ .start = MBOX_PAIR2_VIRT_IRQ,
+ .end = MBOX_PAIR2_VIRT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device mbox0_device = {
+ .id = 0,
+ .name = "mbox",
+ .resource = mbox0_resources,
+ .num_resources = ARRAY_SIZE(mbox0_resources),
+};
+
+static struct platform_device mbox1_device = {
+ .id = 1,
+ .name = "mbox",
+ .resource = mbox1_resources,
+ .num_resources = ARRAY_SIZE(mbox1_resources),
+};
+
+static struct platform_device mbox2_device = {
+ .id = 2,
+ .name = "mbox",
+ .resource = mbox2_resources,
+ .num_resources = ARRAY_SIZE(mbox2_resources),
};
static struct platform_device *u5500_platform_devs[] __initdata = {
@@ -33,19 +140,34 @@ static struct platform_device *u5500_platform_devs[] __initdata = {
&u5500_gpio_devs[5],
&u5500_gpio_devs[6],
&u5500_gpio_devs[7],
+ &mbox0_device,
+ &mbox1_device,
+ &mbox2_device,
+ &u5500_pwm0_device,
+ &u5500_pwm1_device,
+ &u5500_pwm2_device,
+ &u5500_pwm3_device,
};
void __init u5500_map_io(void)
{
- ux500_map_io();
-
iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc));
+
+ _PRCMU_BASE = __io_address(U5500_PRCMU_BASE);
}
void __init u5500_init_devices(void)
{
+ struct amba_device *dev;
+
ux500_init_devices();
+ db5500_dma_init();
+
+ dev = db5500_add_rtc();
+ if (!IS_ERR(dev))
+ device_init_wakeup(&dev->dev, true);
+
platform_add_devices(u5500_platform_devs,
ARRAY_SIZE(u5500_platform_devs));
}
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index f21c444edd9..79953b65888 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -16,12 +16,56 @@
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/sys_soc.h>
+#include <asm/pmu.h>
#include <asm/mach/map.h>
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
+static struct resource db8500_pmu_resources[] = {
+ [0] = {
+ .start = IRQ_DB8500_PMU,
+ .end = IRQ_DB8500_PMU,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/*
+ * The PMU IRQ lines of two cores are wired together into a single interrupt.
+ * Bounce the interrupt to the other core if it's not ours.
+ */
+static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler)
+{
+ irqreturn_t ret = handler(irq, dev);
+ int other = !smp_processor_id();
+
+ if (ret == IRQ_NONE && cpu_online(other))
+ irq_set_affinity(irq, cpumask_of(other));
+
+ /*
+ * We should be able to get away with the amount of IRQ_NONEs we give,
+ * while still having the spurious IRQ detection code kick in if the
+ * interrupt really starts hitting spuriously.
+ */
+ return ret;
+}
+
+static struct arm_pmu_platdata db8500_pmu_platdata = {
+ .handle_irq = db8500_pmu_handler,
+};
+
+static struct platform_device db8500_pmu_device = {
+ .name = "arm-pmu",
+ .id = ARM_PMU_DEVICE_CPU,
+ .num_resources = ARRAY_SIZE(db8500_pmu_resources),
+ .resource = db8500_pmu_resources,
+ .dev.platform_data = &db8500_pmu_platdata,
+};
+
static struct platform_device *platform_devs[] __initdata = {
&u8500_gpio_devs[0],
&u8500_gpio_devs[1],
@@ -32,51 +76,264 @@ static struct platform_device *platform_devs[] __initdata = {
&u8500_gpio_devs[6],
&u8500_gpio_devs[7],
&u8500_gpio_devs[8],
- &u8500_dma40_device,
+ &ux500_wdt_device,
+ &db8500_pmu_device,
};
-/* minimum static i/o mapping required to boot U8500 platforms */
+#include "devices-db8500.h"
+
static struct map_desc u8500_io_desc[] __initdata = {
+ __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_MTU1_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_UART0_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_UART1_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_RTC_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_MSP0_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_MSP1_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_MSP2_BASE, SZ_4K),
__IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K),
__IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_STM_REG_BASE, SZ_4K),
+ {IO_ADDRESS(U8500_BACKUPRAM0_BASE),
+ __phys_to_pfn(U8500_BACKUPRAM0_BASE), SZ_8K, MT_BACKUP_RAM},
+ __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M),
+ __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K),
};
static struct map_desc u8500ed_io_desc[] __initdata = {
__IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K),
+ __IO_DEV_DESC(U8500_MTU1_BASE_ED, SZ_4K),
__IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K),
};
static struct map_desc u8500v1_io_desc[] __initdata = {
- __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K),
+ __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE_V1, SZ_4K),
};
-void __init u8500_map_io(void)
+static struct map_desc u8500v2_io_desc[] __initdata = {
+ __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K),
+};
+/*
+ * Functions to differentiate between later ASICs
+ * We look into the end of the ROM to locate the hardcoded ASIC ID.
+ * This is only needed to differentiate between minor revisions and
+ * process variants of an ASIC, the major revisions are encoded in
+ * the cpuid.
+ */
+#define U8500_ASIC_ID_LOC_ED_V1 (U8500_BOOT_ROM_BASE + 0x1FFF4)
+#define U8500_ASIC_ID_LOC_V2 (U8500_BOOT_ROM_BASE + 0x1DBF4)
+#define U8500_ASIC_REV_ED 0x01
+#define U8500_ASIC_REV_V10 0xA0
+#define U8500_ASIC_REV_V11 0xA1
+#define U8500_ASIC_REV_V20 0xB0
+#define U8500_ASIC_REV_V21 0xB1
+
+/**
+ * struct db8500_asic_id - fields of the ASIC ID
+ * @process: the manufacturing process, 0x40 is 40 nm
+ * 0x00 is "standard"
+ * @partnumber: hithereto 0x8500 for DB8500
+ * @revision: version code in the series
+ * This field definion is not formally defined but makes
+ * sense.
+ */
+struct db8500_asic_id {
+ u8 process;
+ u16 partnumber;
+ u8 revision;
+};
+
+/* This isn't going to change at runtime */
+static struct db8500_asic_id db8500_id;
+
+static void __init get_db8500_asic_id(void)
+{
+ u32 asicid;
+
+ if (cpu_is_u8500v1() || cpu_is_u8500ed())
+ asicid = readl(__io_address(U8500_ASIC_ID_LOC_ED_V1));
+ else if (cpu_is_u8500v2())
+ asicid = readl(__io_address(U8500_ASIC_ID_LOC_V2));
+ else
+ BUG();
+
+ db8500_id.process = (asicid >> 24);
+ db8500_id.partnumber = (asicid >> 16) & 0xFFFFU;
+ db8500_id.revision = asicid & 0xFFU;
+}
+
+bool cpu_is_u8500v10(void)
{
- ux500_map_io();
+ return (db8500_id.revision == U8500_ASIC_REV_V10);
+}
+
+bool cpu_is_u8500v11(void)
+{
+ return (db8500_id.revision == U8500_ASIC_REV_V11);
+}
+
+bool cpu_is_u8500v20(void)
+{
+ return (db8500_id.revision == U8500_ASIC_REV_V20);
+}
+
+bool cpu_is_u8500v21(void)
+{
+ return (db8500_id.revision == U8500_ASIC_REV_V21);
+}
+bool cpu_is_u8500v20_or_later(void)
+{
+ return !cpu_is_u8500v10() && !cpu_is_u8500v11();
+}
+
+void __init u8500_map_io(void)
+{
iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc));
if (cpu_is_u8500ed())
iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc));
- else
+ else if (cpu_is_u8500v1())
iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc));
+ else if (cpu_is_u8500v2())
+ iotable_init(u8500v2_io_desc, ARRAY_SIZE(u8500v2_io_desc));
+
+ _PRCMU_BASE = __io_address(U8500_PRCMU_BASE);
+
+ /* Read out the ASIC ID as early as we can */
+ get_db8500_asic_id();
}
+static void __init u8500_earlydrop_fixup(void)
+{
+ u8500_shrm_device.resource[1].start = IRQ_CA_WAKE_REQ_ED;
+ u8500_shrm_device.resource[1].end = IRQ_CA_WAKE_REQ_ED;
+ u8500_shrm_device.resource[2].start = IRQ_AC_READ_NOTIFICATION_0_ED;
+ u8500_shrm_device.resource[2].end = IRQ_AC_READ_NOTIFICATION_0_ED;
+ u8500_shrm_device.resource[3].start = IRQ_AC_READ_NOTIFICATION_1_ED;
+ u8500_shrm_device.resource[3].end = IRQ_AC_READ_NOTIFICATION_1_ED;
+ u8500_shrm_device.resource[4].start = IRQ_CA_MSG_PEND_NOTIFICATION_0_ED;
+ u8500_shrm_device.resource[4].end = IRQ_CA_MSG_PEND_NOTIFICATION_0_ED;
+ u8500_shrm_device.resource[5].start = IRQ_CA_MSG_PEND_NOTIFICATION_1_ED;
+ u8500_shrm_device.resource[5].end = IRQ_CA_MSG_PEND_NOTIFICATION_1_ED;
+}
/*
* This function is called from the board init
*/
void __init u8500_init_devices(void)
{
+ struct amba_device *dev;
+
ux500_init_devices();
+ /* Display some ASIC boilerplate */
+ pr_info("DB8500: process: %02x, revision ID: 0x%02x\n",
+ db8500_id.process, db8500_id.revision);
if (cpu_is_u8500ed())
- dma40_u8500ed_fixup();
+ pr_info("DB8500: Early Drop (ED)\n");
+ else if (cpu_is_u8500v10())
+ pr_info("DB8500: version 1.0\n");
+ else if (cpu_is_u8500v11())
+ pr_info("DB8500: version 1.1\n");
+ else if (cpu_is_u8500v20())
+ pr_info("DB8500: version 2.0\n");
+ else if (cpu_is_u8500v21())
+ pr_info("DB8500: version 2.1\n");
+ else
+ pr_warning("ASIC: UNKNOWN SILICON VERSION!\n");
+
+ if (cpu_is_u8500ed())
+ u8500_earlydrop_fixup();
+
+ db8500_dma_init();
+ db8500_uart_init();
+
+ dev = db8500_add_rtc();
+ if (!IS_ERR(dev))
+ device_init_wakeup(&dev->dev, true);
/* Register the platform devices */
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
return ;
}
+
+#ifdef CONFIG_SYS_SOC
+#define U8500_BB_UID_BASE (U8500_BACKUPRAM1_BASE + 0xFC0)
+#define U8500_BB_UID_LENGTH 5
+
+static ssize_t ux500_get_machine(char *buf, struct sysfs_soc_info *si)
+{
+ return sprintf(buf, "DB%2x00\n", db8500_id.partnumber);
+}
+
+static ssize_t ux500_get_soc_id(char *buf, struct sysfs_soc_info *si)
+{
+ void __iomem *uid_base;
+ int i;
+ ssize_t sz = 0;
+
+ if (db8500_id.partnumber == 0x85) {
+ uid_base = __io_address(U8500_BB_UID_BASE);
+ for (i = 0; i < U8500_BB_UID_LENGTH; i++)
+ sz += sprintf(buf + sz, "%08x", readl(uid_base + i * sizeof(u32)));
+ sz += sprintf(buf + sz, "\n");
+ }
+ else {
+ /* Don't know where it is located for U5500 */
+ sz = sprintf(buf, "N/A\n");
+ }
+
+ return sz;
+}
+
+static ssize_t ux500_get_revision(char *buf, struct sysfs_soc_info *si)
+{
+ unsigned int rev = db8500_id.revision;
+
+ if (rev == 0x01)
+ return sprintf(buf, "%s\n", "ED");
+ else if (rev >= 0xA0)
+ return sprintf(buf, "%d.%d\n" , (rev >> 4) - 0xA + 1, rev & 0xf);
+
+ return sprintf(buf, "%s", "Unknown\n");
+}
+
+static ssize_t ux500_get_process(char *buf, struct sysfs_soc_info *si)
+{
+ if (db8500_id.process == 0x00)
+ return sprintf(buf, "Standard\n");
+
+ return sprintf(buf, "%02xnm\n", db8500_id.process);
+}
+
+static struct sysfs_soc_info soc_info[] = {
+ SYSFS_SOC_ATTR_CALLBACK("machine", ux500_get_machine),
+ SYSFS_SOC_ATTR_VALUE("family", "Ux500"),
+ SYSFS_SOC_ATTR_CALLBACK("soc_id", ux500_get_soc_id),
+ SYSFS_SOC_ATTR_CALLBACK("revision", ux500_get_revision),
+ SYSFS_SOC_ATTR_CALLBACK("process", ux500_get_process),
+};
+
+static int __init ux500_sys_soc_init(void)
+{
+ return register_sysfs_soc(soc_info, ARRAY_SIZE(soc_info));
+}
+
+module_init(ux500_sys_soc_init);
+#endif
+
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index e0fd747e447..908bb057d8d 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -9,97 +9,170 @@
#include <linux/amba/bus.h>
#include <linux/io.h>
#include <linux/clk.h>
+#include <linux/delay.h>
+#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/gic.h>
#include <asm/mach/map.h>
-#include <asm/localtimer.h>
#include <plat/mtu.h>
#include <mach/hardware.h>
#include <mach/setup.h>
#include <mach/devices.h>
+#include <mach/prcmu-fw-api.h>
+#include <mach/prcmu-db5500.h>
+#include <mach/reboot_reasons.h>
#include "clock.h"
-static struct map_desc ux500_io_desc[] __initdata = {
- __IO_DEV_DESC(UX500_UART0_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_UART2_BASE, SZ_4K),
+void __iomem *gic_cpu_base_addr;
+void __iomem *_PRCMU_BASE;
- __IO_DEV_DESC(UX500_GIC_CPU_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_GIC_DIST_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_L2CC_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_TWD_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_SCU_BASE, SZ_4K),
+#ifdef CONFIG_CACHE_L2X0
+static void __iomem *l2x0_base;
+#endif
- __IO_DEV_DESC(UX500_CLKRST1_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_CLKRST2_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_CLKRST3_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_CLKRST5_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_CLKRST6_BASE, SZ_4K),
+/*
+ * The reboot reason string can be 255 characters long and the memory
+ * in which we save the sw reset reason is 2 bytes. Therefore we need to
+ * convert the string into a 16 bit pattern.
+ *
+ * See file reboot_reasons.h for conversion.
+ */
+static unsigned short map_cmd_to_code(const char *cmd)
+{
+ int i;
- __IO_DEV_DESC(UX500_MTU0_BASE, SZ_4K),
- __IO_DEV_DESC(UX500_MTU1_BASE, SZ_4K),
+ if (cmd == NULL)
+ /* normal reboot w/o argument */
+ return SW_RESET_NO_ARGUMENT;
- __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K),
-};
+ /* Search through reboot reason list */
+ for (i = 0; i < reboot_reasons_size; i++) {
+ if (!strcmp(reboot_reasons[i].reason, cmd))
+ return reboot_reasons[i].code;
+ }
-static struct amba_device *ux500_amba_devs[] __initdata = {
- &ux500_pl031_device,
-};
+ /* No valid Reboot Reason found */
+ return SW_RESET_CRASH;
+}
-void __init ux500_map_io(void)
+void __init ux500_init_devices(void)
{
- iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc));
+#ifdef CONFIG_CACHE_L2X0
+ BUG_ON(!l2x0_base);
+
+ /*
+ * Unlock Data and Instruction Lock if locked. This is done here
+ * instead of in l2x0_init since doing it there appears to cause the
+ * second core boot to occasionaly fail.
+ */
+ if (readl_relaxed(l2x0_base + L2X0_LOCKDOWN_WAY_D) & 0xFF)
+ writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D);
+
+ if (readl_relaxed(l2x0_base + L2X0_LOCKDOWN_WAY_I) & 0xFF)
+ writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I);
+
+#endif
}
-void __init ux500_init_devices(void)
+static void ux500_restart(char mode, const char *cmd)
{
- amba_add_devices(ux500_amba_devs, ARRAY_SIZE(ux500_amba_devs));
+ unsigned short reset_code;
+
+ reset_code = map_cmd_to_code(cmd);
+ prcmu_system_reset(reset_code);
+
+ mdelay(1000);
+ printk("Reboot via PRCMU failed -- System halted\n");
+ while (1);
}
void __init ux500_init_irq(void)
{
- gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
- gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+ void __iomem *dist_base;
+
+ if (cpu_is_u5500()) {
+ gic_cpu_base_addr = __io_address(U5500_GIC_CPU_BASE);
+ dist_base = __io_address(U5500_GIC_DIST_BASE);
+ } else if (cpu_is_u8500()) {
+ gic_cpu_base_addr = __io_address(U8500_GIC_CPU_BASE);
+ dist_base = __io_address(U8500_GIC_DIST_BASE);
+ } else
+ ux500_unknown_soc();
+
+ gic_dist_init(0, dist_base, 29);
+ gic_cpu_init(0, gic_cpu_base_addr);
/*
* Init clocks here so that they are available for system timer
* initialization.
*/
+ if (cpu_is_u5500())
+ db5500_prcmu_early_init();
+ else {
+ prcmu_early_init();
+ arm_pm_restart = ux500_restart;
+ }
+
clk_init();
}
#ifdef CONFIG_CACHE_L2X0
-static int ux500_l2x0_init(void)
+static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
{
- void __iomem *l2x0_base;
+ /* wait for the operation to complete */
+ while (readl_relaxed(reg) & mask)
+ ;
+}
- l2x0_base = __io_address(UX500_L2CC_BASE);
+static inline void ux500_cache_sync(void)
+{
+ void __iomem *base = l2x0_base;
- /* 64KB way size, 8 way associativity, force WA */
- l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+ writel_relaxed(0, base + L2X0_CACHE_SYNC);
+ ux500_cache_wait(base + L2X0_CACHE_SYNC, 1);
+}
- return 0;
+/* The L2 cache cannot be turned off in the non-secure world.
+ Dummy until a secure service is in place */
+static void ux500_l2x0_disable(void) {}
+
+/* This is only called when doing a kexec, just after turning off the L2
+ and L1 cache, and it is surrounded by a spinlock in the generic version.
+ However, we're not really turning off the L2 cache right now and the
+ PL310 does not support exclusive accesses (used to implement the spinlock).
+ So, the invalidation needs to be done without the spinlock. */
+static void ux500_l2x0_inv_all(void)
+{
+ void __iomem *base = l2x0_base;
+ uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */
+
+ /* invalidate all ways */
+ writel_relaxed(l2x0_way_mask, base + L2X0_INV_WAY);
+ ux500_cache_wait(base + L2X0_INV_WAY, l2x0_way_mask);
+ ux500_cache_sync();
}
-early_initcall(ux500_l2x0_init);
-#endif
-static void __init ux500_timer_init(void)
+static int ux500_l2x0_init(void)
{
-#ifdef CONFIG_LOCAL_TIMERS
- /* Setup the local timer base */
- twd_base = __io_address(UX500_TWD_BASE);
-#endif
- /* Setup the MTU base */
- if (cpu_is_u8500ed())
- mtu_base = __io_address(U8500_MTU0_BASE_ED);
+ if (cpu_is_u5500())
+ l2x0_base = __io_address(U5500_L2CC_BASE);
+ else if (cpu_is_u8500())
+ l2x0_base = __io_address(U8500_L2CC_BASE);
else
- mtu_base = __io_address(UX500_MTU0_BASE);
+ ux500_unknown_soc();
+
+ /* 64KB way size, 8 way associativity, force WA */
+ l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
+
+ /* Override invalidate function */
+ outer_cache.disable = ux500_l2x0_disable;
+ outer_cache.inv_all = ux500_l2x0_inv_all;
- nmdk_timer_init();
+ return 0;
}
+early_initcall(ux500_l2x0_init);
+#endif
-struct sys_timer ux500_timer = {
- .init = ux500_timer_init,
-};
diff --git a/arch/arm/mach-ux500/cw1200-wlan.c b/arch/arm/mach-ux500/cw1200-wlan.c
new file mode 100644
index 00000000000..0dc148596fe
--- /dev/null
+++ b/arch/arm/mach-ux500/cw1200-wlan.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * 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/gfp.h>
+#include <linux/err.h>
+#include <linux/cw1200-wlan.h>
+#include <linux/module.h>
+
+static const struct wlan1200_platform_data *platform_data;
+
+void wlan1200_set_platdata(struct wlan1200_platform_data *pdata)
+{
+ /*
+ * note, if we get a failure in allocation, we simply drop out of the
+ * function. If there is so little memory available at initialisation
+ * time then there is little chance the system is going to run.
+ */
+
+ platform_data = kmemdup(pdata, sizeof(struct wlan1200_platform_data), GFP_KERNEL);
+ if (!platform_data) {
+ printk(KERN_ERR "%s: failed copying platform data\n", __func__);
+ return;
+ }
+}
+EXPORT_SYMBOL(wlan1200_set_platdata);
+
+const struct wlan1200_platform_data *wlan1200_get_platform_data(void)
+{
+ if (!platform_data)
+ return ERR_PTR(-ENODEV);
+
+ return platform_data;
+}
+EXPORT_SYMBOL(wlan1200_get_platform_data);
+
diff --git a/arch/arm/mach-ux500/dcache.c b/arch/arm/mach-ux500/dcache.c
new file mode 100644
index 00000000000..b117d4e8283
--- /dev/null
+++ b/arch/arm/mach-ux500/dcache.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Cache handler integration and data cache helpers.
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/dma-mapping.h>
+
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+#include <asm/outercache.h>
+#include <asm/system.h>
+
+/*
+ * Values are derived from measurements on HREFP_1.1_V32_OM_S10 running
+ * u8500-android-2.2_r1.1_v0.21.
+ *
+ * A lot of time can be spent trying to figure out the perfect breakpoints but
+ * for now I've chosen the following simple way.
+ *
+ * breakpoint = best_case + (worst_case - best_case) * 0.666
+ * The breakpoint is moved slightly towards the worst case because a full
+ * clean/flush affects the entire system so we should be a bit careful.
+ *
+ * BEST CASE:
+ * Best case is that the cache is empty and the system is idling. The case
+ * where the cache contains only targeted data could be better in some cases
+ * but it's hard to do measurements and calculate on that case so I choose the
+ * easier alternative.
+ *
+ * inner_clean_breakpoint = time_2_range_clean_on_empty_cache(
+ * complete_clean_on_empty_cache_time)
+ * inner_flush_breakpoint = time_2_range_flush_on_empty_cache(
+ * complete_flush_on_empty_cache_time)
+ *
+ * outer_clean_breakpoint = time_2_range_clean_on_empty_cache(
+ * complete_clean_on_empty_cache_time)
+ * outer_flush_breakpoint = time_2_range_flush_on_empty_cache(
+ * complete_flush_on_empty_cache_time)
+ *
+ * WORST CASE:
+ * Worst case is that the cache is filled with dirty non targeted data that
+ * will be used after the synchronization and the system is under heavy load.
+ *
+ * inner_clean_breakpoint = time_2_range_clean_on_empty_cache(
+ * complete_clean_on_full_cache_time * 1.5)
+ * Times 1.5 because it runs on both cores half the time.
+ * inner_flush_breakpoint = time_2_range_flush_on_empty_cache(
+ * complete_flush_on_full_cache_time * 1.5 +
+ * complete_flush_on_full_cache_time / 2)
+ * Plus "complete_flush_on_full_cache_time / 2" because all data has to be read
+ * back, here we assume that both cores can fill their cache simultaneously
+ * (seems to be the case as operations on full and empty inner cache takes
+ * roughly the same amount of time ie the bus to outer is not the bottle neck).
+ *
+ * outer_clean_breakpoint = time_2_range_clean_on_empty_cache(
+ * complete_clean_on_full_cache_time +
+ * (complete_clean_on_full_cache_time -
+ * complete_clean_on_empty_cache_time))
+ * Plus "(complete_flush_on_full_cache_time -
+ * complete_flush_on_empty_cache_time)" because no one else can work when we
+ * hog the bus with our unecessary transfer.
+ * outer_flush_breakpoint = time_2_range_flush_on_empty_cache(
+ * complete_flush_on_full_cache_time * 2 +
+ * (complete_flush_on_full_cache_time -
+ * complete_flush_on_empty_cache_time) * 2)
+ *
+ * These values might have to be updated if changes are made to the CPU, L2$,
+ * memory bus or memory.
+ */
+/* 28930 */
+static const u32 inner_clean_breakpoint = 21324 + (32744 - 21324) * 0.666;
+/* 36224 */
+static const u32 inner_flush_breakpoint = 21324 + (43697 - 21324) * 0.666;
+/* 254069 */
+static const u32 outer_clean_breakpoint = 68041 + (347363 - 68041) * 0.666;
+/* 485414 */
+static const u32 outer_flush_breakpoint = 68041 + (694727 - 68041) * 0.666;
+
+static void __clean_inner_dcache_all(void *param);
+static void clean_inner_dcache_all(void);
+
+static void __flush_inner_dcache_all(void *param);
+static void flush_inner_dcache_all(void);
+
+static bool is_cache_exclusive(void);
+
+void drain_cpu_write_buf(void)
+{
+ dsb();
+ outer_cache.sync();
+}
+
+void clean_cpu_dcache(void *vaddr, u32 paddr, u32 length, bool inner_only,
+ bool *cleaned_everything)
+{
+ /*
+ * There is no problem with exclusive caches here as the Cortex-A9
+ * documentation (8.1.4. Exclusive L2 cache) says that when a dirty
+ * line is moved from L2 to L1 it is first written to mem. Because
+ * of this there is no way a line can avoid the clean by jumping
+ * between the cache levels.
+ */
+ *cleaned_everything = true;
+
+ if (length < inner_clean_breakpoint) {
+ /* Inner clean range */
+ dmac_map_area(vaddr, length, DMA_TO_DEVICE);
+ *cleaned_everything = false;
+ } else {
+ clean_inner_dcache_all();
+ }
+
+ if (!inner_only) {
+ /*
+ * There is currently no outer_cache.clean_all() so we use
+ * flush instead, which is ok as clean is a subset of flush.
+ * Clean range and flush range take the same amount of time
+ * so we can use outer_flush_breakpoint here.
+ */
+ if (length < outer_flush_breakpoint) {
+ outer_cache.clean_range(paddr, paddr + length);
+ *cleaned_everything = false;
+ } else {
+ outer_cache.flush_all();
+ }
+ }
+}
+
+void flush_cpu_dcache(void *vaddr, u32 paddr, u32 length, bool inner_only,
+ bool *flushed_everything)
+{
+ /*
+ * There might still be stale data in the caches after this call if the
+ * cache levels are exclusive. The follwing can happen.
+ * 1. Clean L1 moves the data to L2.
+ * 2. Speculative prefetch, preemption or loads on the other core moves
+ * all the data back to L1, any dirty data will be written to mem as a
+ * result of this.
+ * 3. Flush L2 does nothing as there is no targeted data in L2.
+ * 4. Flush L1 moves the data to L2. Notice that this does not happen
+ * when the cache levels are non-exclusive as clean pages are not
+ * written to L2 in that case.
+ * 5. Stale data is still present in L2!
+ * I see two possible solutions, don't use exclusive caches or
+ * (temporarily) disable prefetching to L1, preeemption and the other
+ * core.
+ *
+ * A situation can occur where the operation does not seem atomic from
+ * the other core's point of view, even on a non-exclusive cache setup.
+ * Replace step 2 in the previous scenarion with a write from the other
+ * core. The other core will write on top of the old data but the
+ * result will not be written to memory. One would expect either that
+ * the write was performed on top of the old data and was written to
+ * memory (the write occured before the flush) or that the write was
+ * performed on top of the new data and was not written to memory (the
+ * write occured after the flush). The same problem can occur with one
+ * core if kernel preemption is enabled. The solution is to
+ * (temporarily) disable the other core and preemption. I can't think
+ * of any situation where this would be a problem and disabling the
+ * other core for the duration of this call is mighty expensive so for
+ * now I just ignore the problem.
+ */
+
+ *flushed_everything = true;
+
+ if (!inner_only) {
+ /*
+ * Beautiful solution for the exclusive problems :)
+ */
+ if (is_cache_exclusive())
+ panic("%s can't handle exclusive CPU caches\n",
+ __func__);
+
+ if (length < inner_clean_breakpoint) {
+ /* Inner clean range */
+ dmac_map_area(vaddr, length, DMA_TO_DEVICE);
+ *flushed_everything = false;
+ } else {
+ clean_inner_dcache_all();
+ }
+
+ if (length < outer_flush_breakpoint) {
+ outer_cache.flush_range(paddr, paddr + length);
+ *flushed_everything = false;
+ } else {
+ outer_cache.flush_all();
+ }
+ }
+
+ if (length < inner_flush_breakpoint) {
+ /* Inner flush range */
+ dmac_flush_range(vaddr, (void *)((u32)vaddr + length));
+ *flushed_everything = false;
+ } else {
+ flush_inner_dcache_all();
+ }
+}
+
+bool speculative_data_prefetch(void)
+{
+ return true;
+}
+
+u32 get_dcache_granularity(void)
+{
+ return 32;
+}
+
+/*
+ * Local functions
+ */
+
+static void __clean_inner_dcache_all(void *param)
+{
+ __cpuc_clean_dcache_all();
+}
+
+static void clean_inner_dcache_all(void)
+{
+ on_each_cpu(__clean_inner_dcache_all, NULL, 1);
+}
+
+static void __flush_inner_dcache_all(void *param)
+{
+ __cpuc_flush_dcache_all();
+}
+
+static void flush_inner_dcache_all(void)
+{
+ on_each_cpu(__flush_inner_dcache_all, NULL, 1);
+}
+
+static bool is_cache_exclusive(void)
+{
+ static const u32 CA9_ACTLR_EXCL = 0x80;
+
+ u32 armv7_actlr;
+
+ asm (
+ "mrc p15, 0, %0, c1, c0, 1"
+ : "=r" (armv7_actlr)
+ );
+
+ if (armv7_actlr & CA9_ACTLR_EXCL)
+ return true;
+ else
+ return false;
+}
diff --git a/arch/arm/mach-ux500/devices-cg2900-u5500.c b/arch/arm/mach-ux500/devices-cg2900-u5500.c
new file mode 100644
index 00000000000..fac30589696
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-cg2900-u5500.c
@@ -0,0 +1,65 @@
+/*
+ * arch/arm/mach-ux500/devices-cg2900-u5500.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Authors:
+ * Par-Gunnar Hjalmdahl (par-gunnar.p.hjalmdahl@stericsson.com) for ST-Ericsson.
+ * Henrik Possung (henrik.possung@stericsson.com) for ST-Ericsson.
+ * Josef Kindberg (josef.kindberg@stericsson.com) for ST-Ericsson.
+ * Dariusz Szymszak (dariusz.xd.szymczak@stericsson.com) for ST-Ericsson.
+ * Kjell Andersson (kjell.k.andersson@stericsson.com) for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Board specific device support for the Linux Bluetooth HCI H:4 Driver
+ * for ST-Ericsson connectivity controller.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/types.h>
+#include <linux/mfd/cg2900.h>
+#include <linux/mfd/abx500/ab5500.h>
+
+#include <mach/prcmu-db5500.h>
+
+#include "devices-cg2900.h"
+
+/* prcmu resout1 pin is used for CG2900 reset*/
+void dcg2900_enable_chip(struct cg2900_chip_dev *dev)
+{
+ struct dcg2900_info *info = dev->b_data;
+
+ clk_enable(info->lpoclk);
+ /*
+ * Due to a bug in CG2900 we cannot just set GPIO high to enable
+ * the chip. We must wait more than 100 msecs before enbling the
+ * chip.
+ * - Set PDB to low.
+ * - Wait for 100 msecs
+ * - Set PDB to high.
+ */
+ prcmu_resetout(1, 0);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(
+ CHIP_ENABLE_PDB_LOW_TIMEOUT));
+ prcmu_resetout(1, 1);
+}
+
+void dcg2900_disable_chip(struct cg2900_chip_dev *dev)
+{
+ struct dcg2900_info *info = dev->b_data;
+
+ prcmu_resetout(1, 0);
+ clk_disable(info->lpoclk);
+}
+
+int dcg2900_setup(struct cg2900_chip_dev *dev,
+ struct dcg2900_info *info)
+{
+ info->lpoclk = clk_get(dev->dev, "lpoclk");
+ if (IS_ERR(info->lpoclk))
+ return PTR_ERR(info->lpoclk);
+
+ return 0;
+}
diff --git a/arch/arm/mach-ux500/devices-cg2900-u8500.c b/arch/arm/mach-ux500/devices-cg2900-u8500.c
new file mode 100644
index 00000000000..08332206beb
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-cg2900-u8500.c
@@ -0,0 +1,181 @@
+/*
+ * arch/arm/mach-ux500/devices-cg2900-u8500.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Authors:
+ * Par-Gunnar Hjalmdahl (par-gunnar.p.hjalmdahl@stericsson.com) for ST-Ericsson.
+ * Henrik Possung (henrik.possung@stericsson.com) for ST-Ericsson.
+ * Josef Kindberg (josef.kindberg@stericsson.com) for ST-Ericsson.
+ * Dariusz Szymszak (dariusz.xd.szymczak@stericsson.com) for ST-Ericsson.
+ * Kjell Andersson (kjell.k.andersson@stericsson.com) for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Board specific device support for the Linux Bluetooth HCI H:4 Driver
+ * for ST-Ericsson connectivity controller.
+ */
+
+#include <asm/byteorder.h>
+#include <asm-generic/errno-base.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/mfd/cg2900.h>
+#include <linux/mfd/abx500/ab5500.h>
+#include <plat/pincfg.h>
+
+#include "devices-cg2900.h"
+
+void dcg2900_enable_chip(struct cg2900_chip_dev *dev)
+{
+ struct dcg2900_info *info = dev->b_data;
+
+ if (info->gbf_gpio == -1)
+ return;
+
+ /*
+ * Due to a bug in CG2900 we cannot just set GPIO high to enable
+ * the chip. We must wait more than 100 msecs before enabling the
+ * chip.
+ * - Set PDB to low.
+ * - Wait for 100 msecs
+ * - Set PDB to high.
+ */
+ gpio_set_value(info->gbf_gpio, 0);
+ schedule_timeout_uninterruptible(msecs_to_jiffies(
+ CHIP_ENABLE_PDB_LOW_TIMEOUT));
+
+ if (info->pmuen_gpio != -1) {
+ /*
+ * We must first set PMU_EN pin high and then wait 300 us before
+ * setting the GBF_EN high.
+ */
+ gpio_set_value(info->pmuen_gpio, 1);
+ udelay(CHIP_ENABLE_PMU_EN_TIMEOUT);
+ }
+
+ gpio_set_value(info->gbf_gpio, 1);
+}
+
+void dcg2900_disable_chip(struct cg2900_chip_dev *dev)
+{
+ struct dcg2900_info *info = dev->b_data;
+
+ if (info->gbf_gpio != -1)
+ gpio_set_value(info->gbf_gpio, 0);
+ if (info->pmuen_gpio != -1)
+ gpio_set_value(info->pmuen_gpio, 0);
+}
+
+int dcg2900_setup(struct cg2900_chip_dev *dev,
+ struct dcg2900_info *info)
+{
+ int err = 0;
+ struct resource *resource;
+ const char *gbf_name;
+ const char *bt_name = NULL;
+ const char *pmuen_name = NULL;
+
+ resource = platform_get_resource_byname(dev->pdev, IORESOURCE_IO,
+ "gbf_ena_reset");
+ if (!resource) {
+ dev_err(dev->dev, "GBF GPIO does not exist\n");
+ err = -EINVAL;
+ goto err_handling;
+ }
+
+ info->gbf_gpio = resource->start;
+ gbf_name = resource->name;
+
+ resource = platform_get_resource_byname(dev->pdev, IORESOURCE_IO,
+ "bt_enable");
+ /* BT Enable GPIO may not exist */
+ if (resource) {
+ info->bt_gpio = resource->start;
+ bt_name = resource->name;
+ }
+
+ resource = platform_get_resource_byname(dev->pdev, IORESOURCE_IO,
+ "pmu_en");
+ /* PMU_EN GPIO may not exist */
+ if (resource) {
+ info->pmuen_gpio = resource->start;
+ pmuen_name = resource->name;
+ }
+
+ /* Now setup the GPIOs */
+ err = gpio_request(info->gbf_gpio, gbf_name);
+ if (err < 0) {
+ dev_err(dev->dev, "gpio_request %s failed with err: %d\n",
+ gbf_name, err);
+ goto err_handling;
+ }
+
+ err = gpio_direction_output(info->gbf_gpio, 0);
+ if (err < 0) {
+ dev_err(dev->dev,
+ "gpio_direction_output %s failed with err: %d\n",
+ gbf_name, err);
+ goto err_handling_free_gpio_gbf;
+ }
+
+ if (!pmuen_name)
+ goto set_bt_gpio;
+
+ err = gpio_request(info->pmuen_gpio, pmuen_name);
+ if (err < 0) {
+ dev_err(dev->dev, "gpio_request %s failed with err: %d\n",
+ pmuen_name, err);
+ goto err_handling_free_gpio_gbf;
+ }
+
+ err = gpio_direction_output(info->pmuen_gpio, 0);
+ if (err < 0) {
+ dev_err(dev->dev,
+ "gpio_direction_output %s failed with err: %d\n",
+ pmuen_name, err);
+ goto err_handling_free_gpio_pmuen;
+ }
+
+set_bt_gpio:
+ if (!bt_name)
+ goto finished;
+
+ err = gpio_request(info->bt_gpio, bt_name);
+ if (err < 0) {
+ dev_err(dev->dev, "gpio_request %s failed with err: %d\n",
+ bt_name, err);
+ goto err_handling_free_gpio_pmuen;
+ }
+
+ err = gpio_direction_output(info->bt_gpio, 1);
+ if (err < 0) {
+ dev_err(dev->dev,
+ "gpio_direction_output %s failed with err: %d\n",
+ bt_name, err);
+ goto err_handling_free_gpio_bt;
+ }
+
+finished:
+
+ return 0;
+
+err_handling_free_gpio_bt:
+ gpio_free(info->bt_gpio);
+ info->bt_gpio = -1;
+err_handling_free_gpio_pmuen:
+ if (info->pmuen_gpio != -1) {
+ gpio_free(info->pmuen_gpio);
+ info->pmuen_gpio = -1;
+ }
+err_handling_free_gpio_gbf:
+ gpio_free(info->gbf_gpio);
+ info->gbf_gpio = -1;
+err_handling:
+
+ return err;
+}
diff --git a/arch/arm/mach-ux500/devices-cg2900.c b/arch/arm/mach-ux500/devices-cg2900.c
new file mode 100644
index 00000000000..a48f2ee34d2
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-cg2900.c
@@ -0,0 +1,241 @@
+/*
+ * arch/arm/mach-ux500/devices-cg2900.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Authors:
+ * Par-Gunnar Hjalmdahl (par-gunnar.p.hjalmdahl@stericsson.com) for ST-Ericsson.
+ * Henrik Possung (henrik.possung@stericsson.com) for ST-Ericsson.
+ * Josef Kindberg (josef.kindberg@stericsson.com) for ST-Ericsson.
+ * Dariusz Szymszak (dariusz.xd.szymczak@stericsson.com) for ST-Ericsson.
+ * Kjell Andersson (kjell.k.andersson@stericsson.com) for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Board specific device support for the Linux Bluetooth HCI H:4 Driver
+ * for ST-Ericsson connectivity controller.
+ */
+
+#define NAME "devices-cg2900"
+#define pr_fmt(fmt) NAME ": " fmt "\n"
+
+#include <asm/byteorder.h>
+#include <asm-generic/errno-base.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/mfd/cg2900.h>
+#include <plat/pincfg.h>
+
+#include "devices-cg2900.h"
+
+#define BT_VS_POWER_SWITCH_OFF 0xFD40
+
+#define H4_HEADER_LENGTH 0x01
+#define BT_HEADER_LENGTH 0x03
+
+#define STLC2690_HCI_REV 0x0600
+#define CG2900_PG1_HCI_REV 0x0101
+#define CG2900_PG2_HCI_REV 0x0200
+#define CG2900_PG1_SPECIAL_HCI_REV 0x0700
+
+struct vs_power_sw_off_cmd {
+ __le16 op_code;
+ u8 len;
+ u8 gpio_0_7_pull_up;
+ u8 gpio_8_15_pull_up;
+ u8 gpio_16_20_pull_up;
+ u8 gpio_0_7_pull_down;
+ u8 gpio_8_15_pull_down;
+ u8 gpio_16_20_pull_down;
+} __packed;
+
+static struct sk_buff *dcg2900_get_power_switch_off_cmd
+ (struct cg2900_chip_dev *dev, u16 *op_code)
+{
+ struct sk_buff *skb;
+ struct vs_power_sw_off_cmd *cmd;
+ struct dcg2900_info *info;
+ int i;
+
+ /* If connected chip does not support the command return NULL */
+ if (CG2900_PG1_SPECIAL_HCI_REV != dev->chip.hci_revision &&
+ CG2900_PG1_HCI_REV != dev->chip.hci_revision &&
+ CG2900_PG2_HCI_REV != dev->chip.hci_revision)
+ return NULL;
+
+ dev_dbg(dev->dev, "Generating PowerSwitchOff command\n");
+
+ info = dev->b_data;
+
+ skb = alloc_skb(sizeof(*cmd) + H4_HEADER_LENGTH, GFP_KERNEL);
+ if (!skb) {
+ dev_err(dev->dev, "Could not allocate skb\n");
+ return NULL;
+ }
+
+ skb_reserve(skb, H4_HEADER_LENGTH);
+ cmd = (struct vs_power_sw_off_cmd *)skb_put(skb, sizeof(*cmd));
+ cmd->op_code = cpu_to_le16(BT_VS_POWER_SWITCH_OFF);
+ cmd->len = sizeof(*cmd) - BT_HEADER_LENGTH;
+ /*
+ * Enter system specific GPIO settings here:
+ * Section data[3-5] is GPIO pull-up selection
+ * Section data[6-8] is GPIO pull-down selection
+ * Each section is a bitfield where
+ * - byte 0 bit 0 is GPIO 0
+ * - byte 0 bit 1 is GPIO 1
+ * - up to
+ * - byte 2 bit 4 which is GPIO 20
+ * where each bit means:
+ * - 0: No pull-up / no pull-down
+ * - 1: Pull-up / pull-down
+ * All GPIOs are set as input.
+ */
+ if (!info->sleep_gpio_set) {
+ struct cg2900_platform_data *pf_data;
+
+ pf_data = dev_get_platdata(dev->dev);
+ for (i = 0; i < 8; i++) {
+ if (pf_data->gpio_sleep[i] == CG2900_PULL_UP)
+ info->gpio_0_7_pull_up |= (1 << i);
+ else if (pf_data->gpio_sleep[i] == CG2900_PULL_DN)
+ info->gpio_0_7_pull_down |= (1 << i);
+ }
+ for (i = 8; i < 16; i++) {
+ if (pf_data->gpio_sleep[i] == CG2900_PULL_UP)
+ info->gpio_8_15_pull_up |= (1 << (i - 8));
+ else if (pf_data->gpio_sleep[i] == CG2900_PULL_DN)
+ info->gpio_8_15_pull_down |= (1 << (i - 8));
+ }
+ for (i = 16; i < 21; i++) {
+ if (pf_data->gpio_sleep[i] == CG2900_PULL_UP)
+ info->gpio_16_20_pull_up |= (1 << (i - 16));
+ else if (pf_data->gpio_sleep[i] == CG2900_PULL_DN)
+ info->gpio_16_20_pull_down |= (1 << (i - 16));
+ }
+ info->sleep_gpio_set = true;
+ }
+ cmd->gpio_0_7_pull_up = info->gpio_0_7_pull_up;
+ cmd->gpio_8_15_pull_up = info->gpio_8_15_pull_up;
+ cmd->gpio_16_20_pull_up = info->gpio_16_20_pull_up;
+ cmd->gpio_0_7_pull_down = info->gpio_0_7_pull_down;
+ cmd->gpio_8_15_pull_down = info->gpio_8_15_pull_down;
+ cmd->gpio_16_20_pull_down = info->gpio_16_20_pull_down;
+
+
+ if (op_code)
+ *op_code = BT_VS_POWER_SWITCH_OFF;
+
+ return skb;
+}
+
+static int dcg2900_init(struct cg2900_chip_dev *dev)
+{
+ int err = 0;
+ struct dcg2900_info *info;
+
+ /* First retrieve and save the resources */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ dev_err(dev->dev, "Could not allocate dcg2900_info\n");
+ return -ENOMEM;
+ }
+
+ info->gbf_gpio = -1;
+ info->pmuen_gpio = -1;
+ info->bt_gpio = -1;
+
+ if (!dev->pdev->num_resources) {
+ dev_dbg(dev->dev, "No resources available\n");
+ goto finished;
+ }
+
+ err = dcg2900_setup(dev, info);
+ if (err)
+ goto err_handling;
+
+finished:
+ dev->b_data = info;
+ return 0;
+
+err_handling:
+ kfree(info);
+
+ return err;
+}
+
+static void dcg2900_exit(struct cg2900_chip_dev *dev)
+{
+ struct dcg2900_info *info = dev->b_data;
+
+ dcg2900_disable_chip(dev);
+ if (info->bt_gpio != -1)
+ gpio_free(info->bt_gpio);
+ if (info->pmuen_gpio != -1)
+ gpio_free(info->pmuen_gpio);
+ if (info->gbf_gpio != -1)
+ gpio_free(info->gbf_gpio);
+ kfree(info);
+ dev->b_data = NULL;
+}
+
+#ifdef CONFIG_MFD_CG2900_UART
+static int dcg2900_disable_uart(struct cg2900_chip_dev *dev)
+{
+ int err;
+ struct cg2900_platform_data *pdata = dev_get_platdata(dev->dev);
+
+ /*
+ * Without this delay we get interrupt on CTS immediately
+ * due to some turbulences on this line.
+ */
+ mdelay(4);
+
+ /* Disable UART functions. */
+ err = nmk_config_pins(pdata->uart.uart_disabled,
+ pdata->uart.n_uart_gpios);
+ if (err)
+ goto error;
+
+ return 0;
+
+error:
+ (void)nmk_config_pins(pdata->uart.uart_enabled,
+ pdata->uart.n_uart_gpios);
+ dev_err(dev->dev, "Cannot set interrupt (%d)\n", err);
+ return err;
+}
+
+static int dcg2900_enable_uart(struct cg2900_chip_dev *dev)
+{
+ int err;
+ struct cg2900_platform_data *pdata = dev_get_platdata(dev->dev);
+
+ /* Restore UART settings. */
+ err = nmk_config_pins(pdata->uart.uart_enabled,
+ pdata->uart.n_uart_gpios);
+ if (err)
+ dev_err(dev->dev, "Unable to enable UART (%d)\n", err);
+
+ return err;
+}
+#endif /* CONFIG_MFD_CG2900_UART */
+
+void dcg2900_init_platdata(struct cg2900_platform_data *data)
+{
+ data->init = dcg2900_init;
+ data->exit = dcg2900_exit;
+ data->enable_chip = dcg2900_enable_chip;
+ data->disable_chip = dcg2900_disable_chip;
+ data->get_power_switch_off_cmd = dcg2900_get_power_switch_off_cmd;
+#ifdef CONFIG_MFD_CG2900_UART
+ data->uart.enable_uart = dcg2900_enable_uart;
+ data->uart.disable_uart = dcg2900_disable_uart;
+#endif /* CONFIG_MFD_CG2900_UART */
+}
diff --git a/arch/arm/mach-ux500/devices-cg2900.h b/arch/arm/mach-ux500/devices-cg2900.h
new file mode 100644
index 00000000000..5a445d965f1
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-cg2900.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Par-Gunnar Hjalmdahl <par-gunnar.p.hjalmdahl@stericsson.com>
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_CG2900_H
+#define __DEVICES_CG2900_H
+
+#include <linux/mfd/cg2900.h>
+#include <linux/clk.h>
+
+#define CHIP_ENABLE_PDB_LOW_TIMEOUT 100 /* ms */
+#define CHIP_ENABLE_PMU_EN_TIMEOUT 300 /* us */
+
+struct dcg2900_info {
+ int gbf_gpio;
+ int pmuen_gpio;
+ int bt_gpio;
+ bool sleep_gpio_set;
+ u8 gpio_0_7_pull_up;
+ u8 gpio_8_15_pull_up;
+ u8 gpio_16_20_pull_up;
+ u8 gpio_0_7_pull_down;
+ u8 gpio_8_15_pull_down;
+ u8 gpio_16_20_pull_down;
+ struct clk *lpoclk;
+};
+
+extern void dcg2900_enable_chip(struct cg2900_chip_dev *dev);
+extern void dcg2900_disable_chip(struct cg2900_chip_dev *dev);
+extern int dcg2900_setup(struct cg2900_chip_dev *dev,
+ struct dcg2900_info *info);
+
+/**
+ * dcg2900_init_platdata() - Initializes platform data with callback functions.
+ * @data: Platform data.
+ */
+extern void dcg2900_init_platdata(struct cg2900_platform_data *data);
+
+#endif /* __DEVICES_CG2900_H */
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
new file mode 100644
index 00000000000..9c70ace7dda
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/pm.h>
+
+extern struct dev_power_domain ux500_dev_power_domain;
+
+#include <mach/hardware.h>
+
+#include "devices-common.h"
+
+struct amba_device *
+dbx500_add_amba_device(const char *init_name, resource_size_t base,
+ int irq, void *pdata, unsigned int periphid,
+ const char *name)
+{
+ struct amba_device *dev;
+ int ret;
+
+ dev = kzalloc(sizeof *dev, GFP_KERNEL);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev->dev.init_name = init_name;
+
+ dev->res.start = base;
+ dev->res.end = base + SZ_4K - 1;
+ dev->res.flags = IORESOURCE_MEM;
+
+ dev->dma_mask = DMA_BIT_MASK(32);
+ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ dev->dev.pwr_domain = &ux500_dev_power_domain;
+
+ dev->irq[0] = irq;
+ dev->irq[1] = NO_IRQ;
+
+ dev->periphid = periphid;
+ dev->name = name;
+
+ dev->dev.platform_data = pdata;
+
+ ret = amba_device_register(dev, &iomem_resource);
+ if (ret) {
+ kfree(dev);
+ return ERR_PTR(ret);
+ }
+
+ return dev;
+}
+
+static struct platform_device *
+dbx500_add_platform_device(const char *name, int id, void *pdata,
+ struct resource *res, int resnum)
+{
+ struct platform_device *dev;
+ int ret;
+
+ dev = platform_device_alloc(name, id);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+ dev->dev.pwr_domain = &ux500_dev_power_domain;
+
+ ret = platform_device_add_resources(dev, res, resnum);
+ if (ret)
+ goto out_free;
+
+ dev->dev.platform_data = pdata;
+
+ ret = platform_device_add(dev);
+ if (ret)
+ goto out_free;
+
+ return dev;
+
+out_free:
+ platform_device_put(dev);
+ return ERR_PTR(ret);
+}
+
+struct platform_device *
+dbx500_add_platform_device_4k1irq(const char *name, int id,
+ resource_size_t base,
+ int irq, void *pdata)
+{
+ struct resource resources[] = {
+ [0] = {
+ .start = base,
+ .end = base + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = irq,
+ .end = irq,
+ .flags = IORESOURCE_IRQ,
+ }
+ };
+
+ return dbx500_add_platform_device(name, id, pdata, resources,
+ ARRAY_SIZE(resources));
+}
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
new file mode 100644
index 00000000000..c3c14717584
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-common.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_COMMON_H
+#define __DEVICES_COMMON_H
+
+#include <mach/uart.h>
+
+extern struct amba_device *
+dbx500_add_amba_device(const char *init_name, resource_size_t base,
+ int irq, void *pdata, unsigned int periphid,
+ const char *name);
+
+extern struct platform_device *
+dbx500_add_platform_device_4k1irq(const char *name, int id,
+ resource_size_t base,
+ int irq, void *pdata);
+
+struct stm_msp_controller;
+
+static inline struct amba_device *
+dbx500_add_msp_spi(const char *name, resource_size_t base, int irq,
+ struct stm_msp_controller *pdata)
+{
+ return dbx500_add_amba_device(name, base, irq, pdata, MSP_PER_ID,
+ NULL);
+}
+
+struct pl022_ssp_controller;
+
+static inline struct amba_device *
+dbx500_add_spi(const char *init_name, resource_size_t base, int irq,
+ struct pl022_ssp_controller *pdata)
+{
+ const char *name = NULL;
+
+ if (cpu_is_u5500())
+ name = "db5500-spi";
+
+ return dbx500_add_amba_device(init_name, base, irq, pdata, SPI_PER_ID,
+ name);
+}
+
+struct mmci_platform_data;
+
+static inline struct amba_device *
+dbx500_add_sdi(const char *name, resource_size_t base, int irq,
+ struct mmci_platform_data *pdata)
+{
+ return dbx500_add_amba_device(name, base, irq, pdata, SDI_PER_ID,
+ NULL);
+}
+
+static inline struct amba_device *
+dbx500_add_uart(const char *name, resource_size_t base, int irq,
+ struct uart_amba_plat_data *pdata)
+{
+ return dbx500_add_amba_device(name, base, irq, pdata, 0, NULL);
+}
+
+struct nmk_i2c_controller;
+
+static inline struct platform_device *
+dbx500_add_i2c(int id, resource_size_t base, int irq,
+ struct nmk_i2c_controller *pdata)
+{
+ return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq,
+ pdata);
+}
+
+struct msp_i2s_platform_data;
+
+static inline struct platform_device *
+dbx500_add_msp_i2s(int id, resource_size_t base, int irq,
+ struct msp_i2s_platform_data *pdata)
+{
+ return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq,
+ pdata);
+}
+
+static inline struct amba_device *
+dbx500_add_rtc(resource_size_t base, int irq)
+{
+ return dbx500_add_amba_device("rtc-pl031", base, irq, NULL,
+ RTC_PER_ID, NULL);
+}
+
+#endif
diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c
index 33e5b56bebb..d2a5bc731d4 100644
--- a/arch/arm/mach-ux500/devices-db5500.c
+++ b/arch/arm/mach-ux500/devices-db5500.c
@@ -2,25 +2,68 @@
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ *
+ * Author: Pierre Peiffer <pierre.peiffer@stericsson.com> for ST-Ericsson.
+ * for the System Trace Module part.
+ *
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/devices.h>
+#include <video/mcde.h>
+#include <mach/db5500-regs.h>
+
+#include <mach/prcmu-fw-api.h>
+
+#include <trace/stm.h>
+
+#define GPIO_DATA(_name, first, num) \
+ { \
+ .name = _name, \
+ .first_gpio = first, \
+ .first_irq = NOMADIK_GPIO_TO_IRQ(first), \
+ .num_gpio = num, \
+ }
+
+#define GPIO_RESOURCE(block) \
+ { \
+ .start = U5500_GPIOBANK##block##_BASE, \
+ .end = U5500_GPIOBANK##block##_BASE + 127, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+ { \
+ .start = IRQ_DB5500_GPIO##block, \
+ .end = IRQ_DB5500_GPIO##block, \
+ .flags = IORESOURCE_IRQ, \
+ }
+
+#define GPIO_DEVICE(block) \
+ { \
+ .name = "gpio", \
+ .id = block, \
+ .num_resources = 2, \
+ .resource = &u5500_gpio_resources[block * 2], \
+ .dev = { \
+ .platform_data = &u5500_gpio_data[block], \
+ }, \
+ }
+
static struct nmk_gpio_platform_data u5500_gpio_data[] = {
- GPIO_DATA("GPIO-0-31", 0),
- GPIO_DATA("GPIO-32-63", 32), /* 36..63 not routed to pin */
- GPIO_DATA("GPIO-64-95", 64), /* 83..95 not routed to pin */
- GPIO_DATA("GPIO-96-127", 96), /* 102..127 not routed to pin */
- GPIO_DATA("GPIO-128-159", 128), /* 149..159 not routed to pin */
- GPIO_DATA("GPIO-160-191", 160),
- GPIO_DATA("GPIO-192-223", 192),
- GPIO_DATA("GPIO-224-255", 224), /* 228..255 not routed to pin */
+ GPIO_DATA("GPIO-0-31", 0, 32),
+ GPIO_DATA("GPIO-32-63", 32, 4), /* 36..63 not routed to pin */
+ GPIO_DATA("GPIO-64-95", 64, 19), /* 83..95 not routed to pin */
+ GPIO_DATA("GPIO-96-127", 96, 6), /* 102..127 not routed to pin */
+ GPIO_DATA("GPIO-128-159", 128, 21), /* 149..159 not routed to pin */
+ GPIO_DATA("GPIO-160-191", 160, 32),
+ GPIO_DATA("GPIO-192-223", 192, 32),
+ GPIO_DATA("GPIO-224-255", 224, 4), /* 228..255 not routed to pin */
};
static struct resource u5500_gpio_resources[] = {
@@ -44,3 +87,226 @@ struct platform_device u5500_gpio_devs[] = {
GPIO_DEVICE(6),
GPIO_DEVICE(7),
};
+
+#define U5500_PWM_SIZE 0x20
+static struct resource u5500_pwm0_resource[] = {
+ {
+ .name = "PWM_BASE",
+ .start = U5500_PWM_BASE,
+ .end = U5500_PWM_BASE + U5500_PWM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource u5500_pwm1_resource[] = {
+ {
+ .name = "PWM_BASE",
+ .start = U5500_PWM_BASE + U5500_PWM_SIZE,
+ .end = U5500_PWM_BASE + U5500_PWM_SIZE * 2 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource u5500_pwm2_resource[] = {
+ {
+ .name = "PWM_BASE",
+ .start = U5500_PWM_BASE + U5500_PWM_SIZE * 2,
+ .end = U5500_PWM_BASE + U5500_PWM_SIZE * 3 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct resource u5500_pwm3_resource[] = {
+ {
+ .name = "PWM_BASE",
+ .start = U5500_PWM_BASE + U5500_PWM_SIZE * 3,
+ .end = U5500_PWM_BASE + U5500_PWM_SIZE * 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device u5500_pwm0_device = {
+ .id = 0,
+ .name = "pwm",
+ .resource = u5500_pwm0_resource,
+ .num_resources = ARRAY_SIZE(u5500_pwm0_resource),
+};
+
+struct platform_device u5500_pwm1_device = {
+ .id = 1,
+ .name = "pwm",
+ .resource = u5500_pwm1_resource,
+ .num_resources = ARRAY_SIZE(u5500_pwm1_resource),
+};
+
+struct platform_device u5500_pwm2_device = {
+ .id = 2,
+ .name = "pwm",
+ .resource = u5500_pwm2_resource,
+ .num_resources = ARRAY_SIZE(u5500_pwm2_resource),
+};
+
+struct platform_device u5500_pwm3_device = {
+ .id = 3,
+ .name = "pwm",
+ .resource = u5500_pwm3_resource,
+ .num_resources = ARRAY_SIZE(u5500_pwm3_resource),
+};
+
+static struct resource mcde_resources[] = {
+ [0] = {
+ .name = MCDE_IO_AREA,
+ .start = U5500_MCDE_BASE,
+ .end = U5500_MCDE_BASE + U5500_MCDE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = MCDE_IO_AREA,
+ .start = U5500_DSI_LINK1_BASE,
+ .end = U5500_DSI_LINK1_BASE + U5500_DSI_LINK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = MCDE_IO_AREA,
+ .start = U5500_DSI_LINK2_BASE,
+ .end = U5500_DSI_LINK2_BASE + U5500_DSI_LINK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ .name = MCDE_IRQ,
+ .start = IRQ_DB5500_DISP,
+ .end = IRQ_DB5500_DISP,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static int mcde_platform_enable_dsipll(void)
+{
+ return prcmu_enable_dsipll();
+}
+
+static int mcde_platform_disable_dsipll(void)
+{
+ return prcmu_disable_dsipll();
+}
+
+static int mcde_platform_set_display_clocks(void)
+{
+ return prcmu_set_display_clocks();
+}
+
+static struct mcde_platform_data mcde_pdata = {
+ .num_dsilinks = 2,
+ .syncmux = 0x01,
+ .num_channels = 2,
+ .num_overlays = 3,
+ .regulator_vana_id = "v-ana",
+ .regulator_mcde_epod_id = "vsupply",
+ .regulator_esram_epod_id = "v-esram34",
+ .clock_dsi_id = "hdmi",
+ .clock_dsi_lp_id = "tv",
+ .clock_mcde_id = "mcde",
+ .platform_set_clocks = mcde_platform_set_display_clocks,
+ .platform_enable_dsipll = mcde_platform_enable_dsipll,
+ .platform_disable_dsipll = mcde_platform_disable_dsipll,
+};
+
+struct platform_device ux500_mcde_device = {
+ .name = "mcde",
+ .id = -1,
+ .dev = {
+ .platform_data = &mcde_pdata,
+ },
+ .num_resources = ARRAY_SIZE(mcde_resources),
+ .resource = mcde_resources,
+};
+
+static struct resource b2r2_resources[] = {
+ [0] = {
+ .start = U5500_B2R2_BASE,
+ .end = U5500_B2R2_BASE + ((4*1024)-1),
+ .name = "b2r2_base",
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "B2R2_IRQ",
+ .start = IRQ_DB5500_B2R2,
+ .end = IRQ_DB5500_B2R2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device ux500_b2r2_device = {
+ .name = "b2r2",
+ .id = 0,
+ .dev = {
+ .init_name = "b2r2_bus",
+ .coherent_dma_mask = ~0,
+ },
+ .num_resources = ARRAY_SIZE(b2r2_resources),
+ .resource = b2r2_resources,
+};
+
+#ifdef CONFIG_STM_TRACE
+/* TODO */
+static void stm_disable_modem_on_mipi34(void)
+{
+}
+
+/* TODO */
+static void stm_enable_modem_on_mipi34(void)
+{
+}
+
+/* TODO */
+static int stm_enable_mipi34(void)
+{
+ return 0;
+}
+
+/* TODO */
+static int stm_disable_mipi34(void)
+{
+ return 0;
+}
+
+/* TODO */
+static int stm_enable_ape_modem_mipi60(void)
+{
+ return 0;
+}
+
+/* TODO */
+static int stm_disable_ape_modem_mipi60(void)
+{
+ return 0;
+}
+
+static struct stm_platform_data stm_pdata = {
+ .regs_phys_base = U5500_STM_REG_BASE,
+ .channels_phys_base = U5500_STM_BASE,
+ .periph_id = 0xEC0D3800,
+ .cell_id = 0x0DF005B1,
+ /*
+ * These are the channels used by NMF and some external softwares
+ * expect the NMF traces to be output on these channels
+ * For legacy reason, we need to reserve them.
+ * NMF channels reserved HOSTEE (151)
+ */
+ .channels_reserved = {151, -1},
+ .ste_enable_modem_on_mipi34 = stm_enable_modem_on_mipi34,
+ .ste_disable_modem_on_mipi34 = stm_disable_modem_on_mipi34,
+ .ste_gpio_enable_mipi34 = stm_enable_mipi34,
+ .ste_gpio_disable_mipi34 = stm_disable_mipi34,
+ .ste_gpio_enable_ape_modem_mipi60 = stm_enable_ape_modem_mipi60,
+ .ste_gpio_disable_ape_modem_mipi60 = stm_disable_ape_modem_mipi60,
+};
+
+struct platform_device ux500_stm_device = {
+ .name = "stm",
+ .id = -1,
+ .dev = {
+ .platform_data = &stm_pdata,
+ },
+};
+#endif /* CONFIG_STM_TRACE */
diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h
new file mode 100644
index 00000000000..82263e04e3a
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-db5500.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_DB5500_H
+#define __DEVICES_DB5500_H
+
+#include "devices-common.h"
+
+#define db5500_add_i2c1(pdata) \
+ dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata)
+#define db5500_add_i2c2(pdata) \
+ dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata)
+#define db5500_add_i2c3(pdata) \
+ dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata)
+
+struct db5500_keypad_platform_data;
+
+static inline struct platform_device *
+db5500_add_keypad(struct db5500_keypad_platform_data *pdata)
+{
+ return dbx500_add_platform_device_4k1irq("db5500-keypad", -1,
+ U5500_KEYPAD_BASE,
+ IRQ_DB5500_KBD, pdata);
+}
+
+#define db5500_add_msp0_i2s(pdata) \
+ dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
+#define db5500_add_msp1_i2s(pdata) \
+ dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
+#define db5500_add_msp2_i2s(pdata) \
+ dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
+
+#define db5500_add_msp0_spi(pdata) \
+ dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata)
+#define db5500_add_msp1_spi(pdata) \
+ dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata)
+#define db5500_add_msp2_spi(pdata) \
+ dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata)
+
+#define db5500_add_rtc() \
+ dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC);
+
+#define db5500_add_sdi0(pdata) \
+ dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata)
+#define db5500_add_sdi1(pdata) \
+ dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata)
+#define db5500_add_sdi2(pdata) \
+ dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata)
+#define db5500_add_sdi3(pdata) \
+ dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata)
+#define db5500_add_sdi4(pdata) \
+ dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata)
+
+#define db5500_add_spi0(pdata) \
+ dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata)
+#define db5500_add_spi1(pdata) \
+ dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata)
+#define db5500_add_spi2(pdata) \
+ dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata)
+#define db5500_add_spi3(pdata) \
+ dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata)
+
+#define db5500_add_uart0() \
+ dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0, NULL)
+#define db5500_add_uart1() \
+ dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1, NULL)
+#define db5500_add_uart2() \
+ dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2, NULL)
+#define db5500_add_uart3() \
+ dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, NULL)
+
+#endif
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 82290342194..900c77c1057 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -2,6 +2,10 @@
* Copyright (C) ST-Ericsson SA 2010
*
* Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ *
+ * Author: Pierre Peiffer <pierre.peiffer@stericsson.com> for ST-Ericsson.
+ * for the System Trace Module part.
+ *
* License terms: GNU General Public License (GPL) version 2
*/
@@ -9,26 +13,76 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/amba/bus.h>
+#include <plat/pincfg.h>
-#include <plat/ste_dma40.h>
-
+#include <mach/devices.h>
#include <mach/hardware.h>
#include <mach/setup.h>
-#include "ste-dma40-db8500.h"
+#include <video/mcde.h>
+#include <mach/prcmu-fw-api.h>
+#include <mach/prcmu-regs.h>
+#include <mach/hsi.h>
+#include <mach/ste-dma40-db8500.h>
+
+#include <trace/stm.h>
+
+#include "pins-db8500.h"
+#include "pm/pm.h"
+
+#include <plat/ste_dma40.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) \
+ { \
+ .start = U8500_GPIOBANK##block##_BASE, \
+ .end = U8500_GPIOBANK##block##_BASE + 127, \
+ .flags = IORESOURCE_MEM, \
+ }, \
+ { \
+ .start = IRQ_DB8500_GPIO##block, \
+ .end = IRQ_DB8500_GPIO##block, \
+ .flags = IORESOURCE_IRQ, \
+ }, \
+ { \
+ .start = IRQ_PRCMU_GPIO##block, \
+ .end = IRQ_PRCMU_GPIO##block, \
+ .flags = IORESOURCE_IRQ, \
+ }
+
+#define GPIO_DEVICE(block) \
+ { \
+ .name = "gpio", \
+ .id = block, \
+ .num_resources = 3, \
+ .resource = &u8500_gpio_resources[block * 3], \
+ .dev = { \
+ .platform_data = &u8500_gpio_data[block], \
+ }, \
+ }
static struct nmk_gpio_platform_data u8500_gpio_data[] = {
- GPIO_DATA("GPIO-0-31", 0),
- GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */
- GPIO_DATA("GPIO-64-95", 64),
- GPIO_DATA("GPIO-96-127", 96), /* 98..127 not routed to pin */
- GPIO_DATA("GPIO-128-159", 128),
- GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */
- GPIO_DATA("GPIO-192-223", 192),
- GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */
- GPIO_DATA("GPIO-256-288", 256), /* 268..288 not routed to pin */
+ GPIO_DATA("GPIO-0-31", 0, 32),
+ GPIO_DATA("GPIO-32-63", 32, 5), /* 37..63 not routed to pin */
+ GPIO_DATA("GPIO-64-95", 64, 32),
+ GPIO_DATA("GPIO-96-127", 96, 2), /* 98..127 not routed to pin */
+ GPIO_DATA("GPIO-128-159", 128, 32),
+ GPIO_DATA("GPIO-160-191", 160, 12), /* 172..191 not routed to pin */
+ GPIO_DATA("GPIO-192-223", 192, 32),
+ GPIO_DATA("GPIO-224-255", 224, 7), /* 231..255 not routed to pin */
+ GPIO_DATA("GPIO-256-288", 256, 12), /* 268..288 not routed to pin */
};
static struct resource u8500_gpio_resources[] = {
@@ -55,162 +109,475 @@ struct platform_device u8500_gpio_devs[] = {
GPIO_DEVICE(8),
};
-struct amba_device u8500_ssp0_device = {
+static struct resource u8500_shrm_resources[] = {
+ [0] = {
+ .start = U8500_SHRM_GOP_INTERRUPT_BASE,
+ .end = U8500_SHRM_GOP_INTERRUPT_BASE + ((4*4)-1),
+ .name = "shrm_gop_register_base",
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_CA_WAKE_REQ_V1,
+ .end = IRQ_CA_WAKE_REQ_V1,
+ .name = "ca_irq_wake_req",
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = IRQ_AC_READ_NOTIFICATION_0_V1,
+ .end = IRQ_AC_READ_NOTIFICATION_0_V1,
+ .name = "ac_read_notification_0_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = IRQ_AC_READ_NOTIFICATION_1_V1,
+ .end = IRQ_AC_READ_NOTIFICATION_1_V1,
+ .name = "ac_read_notification_1_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ [4] = {
+ .start = IRQ_CA_MSG_PEND_NOTIFICATION_0_V1,
+ .end = IRQ_CA_MSG_PEND_NOTIFICATION_0_V1,
+ .name = "ca_msg_pending_notification_0_irq",
+ .flags = IORESOURCE_IRQ,
+ },
+ [5] = {
+ .start = IRQ_CA_MSG_PEND_NOTIFICATION_1_V1,
+ .end = IRQ_CA_MSG_PEND_NOTIFICATION_1_V1,
+ .name = "ca_msg_pending_notification_1_irq",
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device u8500_shrm_device = {
+ .name = "u8500_shrm",
+ .id = 0,
.dev = {
+ .init_name = "shrm_bus",
.coherent_dma_mask = ~0,
- .init_name = "ssp0",
- },
- .res = {
- .start = U8500_SSP0_BASE,
- .end = U8500_SSP0_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
},
- .irq = {IRQ_SSP0, NO_IRQ },
- /* ST-Ericsson modified id */
- .periphid = SSP_PER_ID,
+
+ .num_resources = ARRAY_SIZE(u8500_shrm_resources),
+ .resource = u8500_shrm_resources
};
-static struct resource u8500_i2c0_resources[] = {
+static struct resource mcde_resources[] = {
[0] = {
- .start = U8500_I2C0_BASE,
- .end = U8500_I2C0_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
+ .name = MCDE_IO_AREA,
+ .start = U8500_MCDE_BASE,
+ .end = U8500_MCDE_BASE + U8500_MCDE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_I2C0,
- .end = IRQ_I2C0,
- .flags = IORESOURCE_IRQ,
- }
+ .name = MCDE_IO_AREA,
+ .start = U8500_DSI_LINK1_BASE,
+ .end = U8500_DSI_LINK1_BASE + U8500_DSI_LINK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = MCDE_IO_AREA,
+ .start = U8500_DSI_LINK2_BASE,
+ .end = U8500_DSI_LINK2_BASE + U8500_DSI_LINK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [3] = {
+ .name = MCDE_IO_AREA,
+ .start = U8500_DSI_LINK3_BASE,
+ .end = U8500_DSI_LINK3_BASE + U8500_DSI_LINK_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [4] = {
+ .name = MCDE_IRQ,
+ .start = IRQ_DB8500_DISP,
+ .end = IRQ_DB8500_DISP,
+ .flags = IORESOURCE_IRQ,
+ },
};
-struct platform_device u8500_i2c0_device = {
- .name = "nmk-i2c",
- .id = 0,
- .resource = u8500_i2c0_resources,
- .num_resources = ARRAY_SIZE(u8500_i2c0_resources),
+static int mcde_platform_enable_dsipll(void)
+{
+ return prcmu_enable_dsipll();
+}
+
+static int mcde_platform_disable_dsipll(void)
+{
+ return prcmu_disable_dsipll();
+}
+
+static int mcde_platform_set_display_clocks(void)
+{
+ return prcmu_set_display_clocks();
+}
+
+static struct mcde_platform_data mcde_pdata = {
+ .num_dsilinks = 3,
+ /*
+ * [0] = 3: 24 bits DPI: connect LSB Ch B to D[0:7]
+ * [3] = 4: 24 bits DPI: connect MID Ch B to D[24:31]
+ * [4] = 5: 24 bits DPI: connect MSB Ch B to D[32:39]
+ *
+ * [1] = 3: TV out : connect LSB Ch B to D[8:15]
+ */
+#define DONT_CARE 0
+ .outmux = { 3, 3, DONT_CARE, 4, 5 },
+#undef DONT_CARE
+ .syncmux = 0x00, /* DPI channel A and B on output pins A and B resp */
+ .num_channels = 4,
+ .num_overlays = 6,
+ .regulator_vana_id = "v-ana",
+ .regulator_mcde_epod_id = "vsupply",
+ .regulator_esram_epod_id = "v-esram34",
+ .clock_dsi_id = "hdmi",
+ .clock_dsi_lp_id = "tv",
+ .clock_dpi_id = "lcd",
+ .clock_mcde_id = "mcde",
+ .platform_set_clocks = mcde_platform_set_display_clocks,
+ .platform_enable_dsipll = mcde_platform_enable_dsipll,
+ .platform_disable_dsipll = mcde_platform_disable_dsipll,
};
-static struct resource u8500_i2c4_resources[] = {
+struct platform_device ux500_mcde_device = {
+ .name = "mcde",
+ .id = -1,
+ .dev = {
+ .platform_data = &mcde_pdata,
+ },
+ .num_resources = ARRAY_SIZE(mcde_resources),
+ .resource = mcde_resources,
+};
+
+static struct resource b2r2_resources[] = {
[0] = {
- .start = U8500_I2C4_BASE,
- .end = U8500_I2C4_BASE + SZ_4K - 1,
+ .start = U8500_B2R2_BASE,
+ .end = U8500_B2R2_BASE + ((4*1024)-1),
+ .name = "b2r2_base",
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = IRQ_I2C4,
- .end = IRQ_I2C4,
- .flags = IORESOURCE_IRQ,
- }
+ .name = "B2R2_IRQ",
+ .start = IRQ_DB8500_B2R2,
+ .end = IRQ_DB8500_B2R2,
+ .flags = IORESOURCE_IRQ,
+ },
};
-struct platform_device u8500_i2c4_device = {
- .name = "nmk-i2c",
- .id = 4,
- .resource = u8500_i2c4_resources,
- .num_resources = ARRAY_SIZE(u8500_i2c4_resources),
+struct platform_device ux500_b2r2_device = {
+ .name = "b2r2",
+ .id = 0,
+ .dev = {
+ .init_name = "b2r2_bus",
+ .coherent_dma_mask = ~0,
+ },
+ .num_resources = ARRAY_SIZE(b2r2_resources),
+ .resource = b2r2_resources,
};
-static struct resource dma40_resources[] = {
+/*
+ * WATCHDOG
+ */
+
+static struct resource ux500_wdt_resources[] = {
[0] = {
- .start = U8500_DMA_BASE,
- .end = U8500_DMA_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- .name = "base",
+ .start = U8500_TWD_BASE,
+ .end = U8500_TWD_BASE+0x37,
+ .flags = IORESOURCE_MEM,
},
[1] = {
- .start = U8500_DMA_LCPA_BASE,
- .end = U8500_DMA_LCPA_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- .name = "lcpa",
- },
- [2] = {
- .start = U8500_DMA_LCLA_BASE,
- .end = U8500_DMA_LCLA_BASE + 16 * 1024 - 1,
- .flags = IORESOURCE_MEM,
- .name = "lcla",
- },
- [3] = {
- .start = IRQ_DMA,
- .end = IRQ_DMA,
- .flags = IORESOURCE_IRQ}
+ .start = IRQ_LOCALWDOG,
+ .end = IRQ_LOCALWDOG,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+struct platform_device ux500_wdt_device = {
+ .name = "mpcore_wdt",
+ .id = -1,
+ .resource = ux500_wdt_resources,
+ .num_resources = ARRAY_SIZE(ux500_wdt_resources),
};
-/* Default configuration for physcial memcpy */
-struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
- .channel_type = (STEDMA40_CHANNEL_IN_PHY_MODE |
- STEDMA40_LOW_PRIORITY_CHANNEL |
- STEDMA40_PCHAN_BASIC_MODE),
- .dir = STEDMA40_MEM_TO_MEM,
+/*
+ * HSI
+ */
+#define HSIR_OVERRUN(num) { \
+ .start = IRQ_DB8500_HSIR_CH##num##_OVRRUN, \
+ .end = IRQ_DB8500_HSIR_CH##num##_OVRRUN, \
+ .flags = IORESOURCE_IRQ, \
+ .name = "hsi_rx_overrun_ch"#num \
+}
- .src_info.endianess = STEDMA40_LITTLE_ENDIAN,
- .src_info.data_width = STEDMA40_BYTE_WIDTH,
- .src_info.psize = STEDMA40_PSIZE_PHY_1,
+#define STE_HSI_PORT0_TX_CHANNEL_CFG(n) { \
+ .dir = STEDMA40_MEM_TO_PERIPH, \
+ .high_priority = false, \
+ .mode = STEDMA40_MODE_LOGICAL, \
+ .mode_opt = STEDMA40_LCHAN_SRC_LOG_DST_LOG, \
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY, \
+ .dst_dev_type = n,\
+ .src_info.big_endian = false,\
+ .src_info.data_width = STEDMA40_WORD_WIDTH,\
+ .dst_info.big_endian = false,\
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,\
+},
- .dst_info.endianess = STEDMA40_LITTLE_ENDIAN,
- .dst_info.data_width = STEDMA40_BYTE_WIDTH,
- .dst_info.psize = STEDMA40_PSIZE_PHY_1,
+#define STE_HSI_PORT0_RX_CHANNEL_CFG(n) { \
+ .dir = STEDMA40_PERIPH_TO_MEM, \
+ .high_priority = false, \
+ .mode = STEDMA40_MODE_LOGICAL, \
+ .mode_opt = STEDMA40_LCHAN_SRC_LOG_DST_LOG, \
+ .src_dev_type = n,\
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY, \
+ .src_info.big_endian = false,\
+ .src_info.data_width = STEDMA40_WORD_WIDTH,\
+ .dst_info.big_endian = false,\
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,\
+},
+static struct resource u8500_hsi_resources[] = {
+ {
+ .start = U8500_HSIR_BASE,
+ .end = U8500_HSIR_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "hsi_rx_base"
+ },
+ {
+ .start = U8500_HSIT_BASE,
+ .end = U8500_HSIT_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "hsi_tx_base"
+ },
+ {
+ .start = IRQ_DB8500_HSIRD0,
+ .end = IRQ_DB8500_HSIRD0,
+ .flags = IORESOURCE_IRQ,
+ .name = "hsi_rx_irq0"
+ },
+ {
+ .start = IRQ_DB8500_HSITD0,
+ .end = IRQ_DB8500_HSITD0,
+ .flags = IORESOURCE_IRQ,
+ .name = "hsi_tx_irq0"
+ },
+ {
+ .start = IRQ_DB8500_HSIR_EXCEP,
+ .end = IRQ_DB8500_HSIR_EXCEP,
+ .flags = IORESOURCE_IRQ,
+ .name = "hsi_rx_excep0"
+ },
+ HSIR_OVERRUN(0),
+ HSIR_OVERRUN(1),
+ HSIR_OVERRUN(2),
+ HSIR_OVERRUN(3),
+ HSIR_OVERRUN(4),
+ HSIR_OVERRUN(5),
+ HSIR_OVERRUN(6),
+ HSIR_OVERRUN(7),
};
-/* Default configuration for logical memcpy */
-struct stedma40_chan_cfg dma40_memcpy_conf_log = {
- .channel_type = (STEDMA40_CHANNEL_IN_LOG_MODE |
- STEDMA40_LOW_PRIORITY_CHANNEL |
- STEDMA40_LCHAN_SRC_LOG_DST_LOG |
- STEDMA40_NO_TIM_FOR_LINK),
- .dir = STEDMA40_MEM_TO_MEM,
- .src_info.endianess = STEDMA40_LITTLE_ENDIAN,
- .src_info.data_width = STEDMA40_BYTE_WIDTH,
- .src_info.psize = STEDMA40_PSIZE_LOG_1,
+#ifdef CONFIG_STE_DMA40
+static struct stedma40_chan_cfg ste_hsi_port0_dma_tx_cfg[] = {
+ STE_HSI_PORT0_TX_CHANNEL_CFG(DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0)
+ STE_HSI_PORT0_TX_CHANNEL_CFG(DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1)
+ STE_HSI_PORT0_TX_CHANNEL_CFG(DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2)
+ STE_HSI_PORT0_TX_CHANNEL_CFG(DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3)
+};
- .dst_info.endianess = STEDMA40_LITTLE_ENDIAN,
- .dst_info.data_width = STEDMA40_BYTE_WIDTH,
- .dst_info.psize = STEDMA40_PSIZE_LOG_1,
+static struct stedma40_chan_cfg ste_hsi_port0_dma_rx_cfg[] = {
+ STE_HSI_PORT0_RX_CHANNEL_CFG(DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0)
+ STE_HSI_PORT0_RX_CHANNEL_CFG(DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1)
+ STE_HSI_PORT0_RX_CHANNEL_CFG(DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2)
+ STE_HSI_PORT0_RX_CHANNEL_CFG(DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3)
+};
+#endif
+static struct ste_hsi_port_cfg ste_hsi_port0_cfg = {
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_tx_cfg = ste_hsi_port0_dma_tx_cfg,
+ .dma_rx_cfg = ste_hsi_port0_dma_rx_cfg
+#endif
+};
+
+struct ste_hsi_platform_data u8500_hsi_platform_data = {
+ .num_ports = 1,
+ .use_dma = 1,
+ .port_cfg = &ste_hsi_port0_cfg,
+};
+
+struct platform_device u8500_hsi_device = {
+ .dev = {
+ .platform_data = &u8500_hsi_platform_data,
+ },
+ .name = "ste_hsi",
+ .id = 0,
+ .resource = u8500_hsi_resources,
+ .num_resources = ARRAY_SIZE(u8500_hsi_resources)
};
/*
- * Mapping between destination event lines and physical device address.
- * The event line is tied to a device and therefor the address is constant.
+ * Thermal Sensor
*/
-static const dma_addr_t dma40_tx_map[STEDMA40_NR_DEV];
-/* Mapping between source event lines and physical device address */
-static const dma_addr_t dma40_rx_map[STEDMA40_NR_DEV];
+static struct resource u8500_thsens_resources[] = {
+ {
+ .name = "IRQ_HOTMON_LOW",
+ .start = IRQ_PRCMU_HOTMON_LOW,
+ .end = IRQ_PRCMU_HOTMON_LOW,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "IRQ_HOTMON_HIGH",
+ .start = IRQ_PRCMU_HOTMON_HIGH,
+ .end = IRQ_PRCMU_HOTMON_HIGH,
+ .flags = IORESOURCE_IRQ,
+ },
+};
-/* Reserved event lines for memcpy only */
-static int dma40_memcpy_event[] = {
- STEDMA40_MEMCPY_TX_1,
- STEDMA40_MEMCPY_TX_2,
- STEDMA40_MEMCPY_TX_3,
- STEDMA40_MEMCPY_TX_4,
+struct platform_device u8500_thsens_device = {
+ .name = "db8500_temp",
+ .resource = u8500_thsens_resources,
+ .num_resources = ARRAY_SIZE(u8500_thsens_resources),
};
-static struct stedma40_platform_data dma40_plat_data = {
- .dev_len = STEDMA40_NR_DEV,
- .dev_rx = dma40_rx_map,
- .dev_tx = dma40_tx_map,
- .memcpy = dma40_memcpy_event,
- .memcpy_len = ARRAY_SIZE(dma40_memcpy_event),
- .memcpy_conf_phy = &dma40_memcpy_conf_phy,
- .memcpy_conf_log = &dma40_memcpy_conf_log,
- .llis_per_log = 8,
+#ifdef CONFIG_STM_TRACE
+static pin_cfg_t mop500_stm_mipi34_pins[] = {
+ GPIO70_STMAPE_CLK | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO71_STMAPE_DAT3 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO72_STMAPE_DAT2 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO73_STMAPE_DAT1 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO74_STMAPE_DAT0 | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO75_U2_RXD | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
+ GPIO76_U2_TXD | PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP,
};
-struct platform_device u8500_dma40_device = {
- .dev = {
- .platform_data = &dma40_plat_data,
- },
- .name = "dma40",
- .id = 0,
- .num_resources = ARRAY_SIZE(dma40_resources),
- .resource = dma40_resources
+static pin_cfg_t mop500_stm_mipi60_pins[] = {
+ GPIO153_U2_RXD,
+ GPIO154_U2_TXD,
+ GPIO155_STMAPE_CLK,
+ GPIO156_STMAPE_DAT3,
+ GPIO157_STMAPE_DAT2,
+ GPIO158_STMAPE_DAT1,
+ GPIO159_STMAPE_DAT0,
+};
+
+static pin_cfg_t mop500_ske_pins[] = {
+ GPIO153_KP_I7,
+ GPIO154_KP_I6,
+ GPIO155_KP_I5,
+ GPIO156_KP_I4,
+ GPIO157_KP_O7,
+ GPIO158_KP_O6,
+ GPIO159_KP_O5,
};
-void dma40_u8500ed_fixup(void)
+/*
+ * Disable Trace of modem on MIPI34 and MIPI60 probe 2
+ * ie disable ALT-C3 on GPIO70-76
+ */
+static void stm_disable_modem_on_mipi34(void)
+{
+ u32 gpiocr;
+
+ gpiocr = readl(PRCM_GPIOCR);
+ /* Disable altC3 on GPIO70-74 (STMMOD) */
+ gpiocr &= ~PRCM_GPIOCR_DBG_STM_MOD_CMD1;
+ /* Disable altC3 on GPIO75-76 (UARTMOD) (?) */
+ gpiocr &= ~PRCM_GPIOCR_DBG_UARTMOD_CMD0;
+ writel(gpiocr, PRCM_GPIOCR);
+}
+
+/*
+ * Enable Trace of modem on MIPI34 and MIPI60 probe 2
+ * ie enable ALT-C3 on GPIO70-76
+ */
+static void stm_enable_modem_on_mipi34(void)
+{
+ u32 gpiocr;
+
+ gpiocr = readl(PRCM_GPIOCR);
+ /* Enable altC3 on GPIO70-74 (STMMOD) and GPIO75-76 (UARTMOD) */
+ gpiocr |= (PRCM_GPIOCR_DBG_STM_MOD_CMD1 | PRCM_GPIOCR_DBG_UARTMOD_CMD0);
+ writel(gpiocr, PRCM_GPIOCR);
+}
+
+static int stm_enable_mipi34(void)
+{
+ int retval;
+
+ retval = nmk_config_pins(ARRAY_AND_SIZE(mop500_stm_mipi34_pins));
+ if (retval)
+ pr_err("STM: Failed to enable MIPI34");
+ return retval;
+}
+
+static int stm_disable_mipi34(void)
{
- dma40_plat_data.memcpy = NULL;
- dma40_plat_data.memcpy_len = 0;
- dma40_resources[0].start = U8500_DMA_BASE_ED;
- dma40_resources[0].end = U8500_DMA_BASE_ED + SZ_4K - 1;
+ int retval;
+
+ retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_stm_mipi34_pins));
+ if (retval)
+ pr_err("STM: Failed to disable MIPI34");
+ return retval;
}
+
+static int stm_enable_ape_modem_mipi60(void)
+{
+ int retval;
+
+ retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_ske_pins));
+ if (retval)
+ pr_err("STM: Failed to disable SKE GPIO");
+ else {
+ retval =
+ nmk_config_pins(ARRAY_AND_SIZE(mop500_stm_mipi60_pins));
+ if (retval)
+ pr_err("STM: Failed to enable MIPI60");
+ }
+ return retval;
+}
+
+static int stm_disable_ape_modem_mipi60(void)
+{
+ int retval;
+
+ retval = nmk_config_pins_sleep(ARRAY_AND_SIZE(mop500_stm_mipi60_pins));
+ if (retval)
+ pr_err("STM: Failed to disable MIPI60");
+ else {
+ retval = nmk_config_pins(ARRAY_AND_SIZE(mop500_ske_pins));
+ if (retval)
+ pr_err("STM: Failed to enable SKE gpio");
+ }
+ return retval;
+}
+
+static struct stm_platform_data stm_pdata = {
+ .regs_phys_base = U8500_STM_REG_BASE,
+ .channels_phys_base = U8500_STM_BASE,
+ .periph_id = 0xEC0D3800, /* or 0xEC0D2800 for 8500V1 */
+ .cell_id = 0x0DF005B1,
+ /*
+ * These are the channels used by NMF and some external softwares
+ * expect the NMF traces to be output on these channels
+ * For legacy reason, we need to reserve them.
+ * NMF channels reserved resp MPCEE (100), CM (101) & HOSTEE (151)
+ */
+ .channels_reserved = {100, 101, 151, -1},
+ /* Enable all except MCSBAG */
+ .masters_enabled = STM_ENABLE_ARM | STM_ENABLE_SVA |
+ STM_ENABLE_PRCMU | STM_ENABLE_SIA | STM_ENABLE_SIA_XP70,
+ .ste_enable_modem_on_mipi34 = stm_enable_modem_on_mipi34,
+ .ste_disable_modem_on_mipi34 = stm_disable_modem_on_mipi34,
+ .ste_gpio_enable_mipi34 = stm_enable_mipi34,
+ .ste_gpio_disable_mipi34 = stm_disable_mipi34,
+ .ste_gpio_enable_ape_modem_mipi60 = stm_enable_ape_modem_mipi60,
+ .ste_gpio_disable_ape_modem_mipi60 = stm_disable_ape_modem_mipi60,
+};
+
+struct platform_device ux500_stm_device = {
+ .name = "stm",
+ .id = -1,
+ .dev = {
+ .platform_data = &stm_pdata,
+ },
+};
+#endif /* CONFIG_STM_TRACE */
+
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
new file mode 100644
index 00000000000..1f997703e70
--- /dev/null
+++ b/arch/arm/mach-ux500/devices-db8500.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __DEVICES_DB8500_H
+#define __DEVICES_DB8500_H
+
+#include "devices-common.h"
+
+struct ske_keypad_platform_data;
+struct pl022_ssp_controller;
+
+static inline struct platform_device *
+db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata)
+{
+ return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1,
+ U8500_SKE_BASE,
+ IRQ_DB8500_KB, pdata);
+}
+
+static inline struct amba_device *
+db8500_add_ssp(const char *name, resource_size_t base, int irq,
+ struct pl022_ssp_controller *pdata)
+{
+ return dbx500_add_amba_device(name, base, irq, pdata, 0, NULL);
+}
+
+
+#define db8500_add_i2c0(pdata) \
+ dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata)
+#define db8500_add_i2c1(pdata) \
+ dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata)
+#define db8500_add_i2c2(pdata) \
+ dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata)
+#define db8500_add_i2c3(pdata) \
+ dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata)
+#define db8500_add_i2c4(pdata) \
+ dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata)
+
+#define db8500_add_msp0_i2s(pdata) \
+ dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
+#define db8500_add_msp1_i2s(pdata) \
+ dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
+#define db8500_add_msp2_i2s(pdata) \
+ dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
+#define db8500_add_msp3_i2s(pdata) \
+ dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
+
+#define db8500_add_msp0_spi(pdata) \
+ dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata)
+#define db8500_add_msp1_spi(pdata) \
+ dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata)
+#define db8500_add_msp2_spi(pdata) \
+ dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata)
+#define db8500_add_msp3_spi(pdata) \
+ dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata)
+
+#define db8500_add_rtc() \
+ dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC);
+
+#define db8500_add_sdi0(pdata) \
+ dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata)
+#define db8500_add_sdi1(pdata) \
+ dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata)
+#define db8500_add_sdi2(pdata) \
+ dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata)
+#define db8500_add_sdi3(pdata) \
+ dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata)
+#define db8500_add_sdi4(pdata) \
+ dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata)
+#define db8500_add_sdi5(pdata) \
+ dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata)
+
+#define db8500_add_ssp0(pdata) \
+ db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata)
+#define db8500_add_ssp1(pdata) \
+ db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata)
+
+#define db8500_add_spi0(pdata) \
+ dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata)
+#define db8500_add_spi1(pdata) \
+ dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata)
+#define db8500_add_spi2(pdata) \
+ dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata)
+#define db8500_add_spi3(pdata) \
+ dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata)
+
+#define db8500_add_uart0(pdata) \
+ dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0, pdata)
+#define db8500_add_uart1() \
+ dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1, NULL)
+#define db8500_add_uart2() \
+ dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, NULL)
+
+#endif
diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c
index 8a268893cb7..54d791d95c1 100644
--- a/arch/arm/mach-ux500/devices.c
+++ b/arch/arm/mach-ux500/devices.c
@@ -7,75 +7,258 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/usb/musb.h>
#include <linux/amba/bus.h>
+#include <linux/dma-mapping.h>
+#ifdef CONFIG_ANDROID_PMEM
+#include <linux/android_pmem.h>
+#endif
+
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/setup.h>
+#include <mach/crypto-ux500.h>
+#include <mach/irqs.h>
#include <mach/hardware.h>
+#include <mach/devices.h>
#include <mach/setup.h>
-#define __MEM_4K_RESOURCE(x) \
- .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
+#include <plat/ste_dma40.h>
+
+#ifdef CONFIG_STE_TRACE_MODEM
+#include <linux/db8500-modem-trace.h>
+#endif
+
+#ifdef CONFIG_STE_TRACE_MODEM
+static struct resource trace_resource = {
+ .start = 0,
+ .end = 0,
+ .name = "db8500-trace-area",
+ .flags = IORESOURCE_MEM
+};
+
+static struct db8500_trace_platform_data trace_pdata = {
+ .ape_base = U8500_APE_BASE,
+ .modem_base = U8500_MODEM_BASE,
+};
-struct amba_device ux500_pl031_device = {
+struct platform_device u8500_trace_modem = {
+ .name = "db8500-modem-trace",
+ .id = 0,
.dev = {
- .init_name = "pl031",
- },
- .res = {
- .start = UX500_RTC_BASE,
- .end = UX500_RTC_BASE + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
+ .init_name = "db8500-modem-trace",
+ .platform_data = &trace_pdata,
},
- .irq = {IRQ_RTC_RTT, NO_IRQ},
+ .num_resources = 1,
+ .resource = &trace_resource,
};
-struct amba_device ux500_uart0_device = {
- .dev = { .init_name = "uart0" },
- __MEM_4K_RESOURCE(UX500_UART0_BASE),
- .irq = {IRQ_UART0, NO_IRQ},
-};
+static int __init early_trace_modem(char *p)
+{
+ struct resource *data = &trace_resource;
+ u32 size = memparse(p, &p);
+
+ if (*p == '@')
+ data->start = memparse(p + 1, &p);
+ data->end = data->start + size;
+
+ return 0;
+}
+
+early_param("mem_mtrace", early_trace_modem);
+#endif
-struct amba_device ux500_uart1_device = {
- .dev = { .init_name = "uart1" },
- __MEM_4K_RESOURCE(UX500_UART1_BASE),
- .irq = {IRQ_UART1, NO_IRQ},
+#ifdef CONFIG_HWMEM
+struct platform_device ux500_hwmem_device = {
+ .name = "hwmem",
};
+#endif
+
+#ifdef CONFIG_ANDROID_PMEM
+static int __init early_pmem_generic_parse(char *p,
+ struct android_pmem_platform_data * data)
+{
+ data->size = memparse(p, &p);
+ if (*p == '@')
+ data->start = memparse(p + 1, &p);
-struct amba_device ux500_uart2_device = {
- .dev = { .init_name = "uart2" },
- __MEM_4K_RESOURCE(UX500_UART2_BASE),
- .irq = {IRQ_UART2, NO_IRQ},
+ return 0;
+}
+
+/*
+ * Pmem device used by surface flinger
+ */
+static struct android_pmem_platform_data pmem_pdata = {
+ .name = "pmem",
+ .no_allocator = 1, /* MemoryHeapBase is having an allocator */
+ .cached = 1,
+ .start = 0,
+ .size = 0,
};
-#define UX500_I2C_RESOURCES(id, size) \
-static struct resource ux500_i2c##id##_resources[] = { \
- [0] = { \
- .start = UX500_I2C##id##_BASE, \
- .end = UX500_I2C##id##_BASE + size - 1, \
- .flags = IORESOURCE_MEM, \
- }, \
- [1] = { \
- .start = IRQ_I2C##id, \
- .end = IRQ_I2C##id, \
- .flags = IORESOURCE_IRQ \
- } \
+static int __init early_pmem(char *p)
+{
+ return early_pmem_generic_parse(p, &pmem_pdata);
}
+early_param("pmem", early_pmem);
+
+struct platform_device u8500_pmem_device = {
+ .name = "android_pmem",
+ .id = 0,
+ .dev = {
+ .platform_data = &pmem_pdata,
+ },
+};
-UX500_I2C_RESOURCES(1, SZ_4K);
-UX500_I2C_RESOURCES(2, SZ_4K);
-UX500_I2C_RESOURCES(3, SZ_4K);
+/*
+ * Pmem device used by OMX components allocating buffers
+ */
+static struct android_pmem_platform_data pmem_hwb_pdata = {
+ .name = "pmem_hwb",
+ .no_allocator = 1, /* We'll manage allocation */
+ .cached = 1,
+ .start = 0,
+ .size = 0,
+};
-#define UX500_I2C_PDEVICE(cid) \
-struct platform_device ux500_i2c##cid##_device = { \
- .name = "nmk-i2c", \
- .id = cid, \
- .num_resources = 2, \
- .resource = ux500_i2c##cid##_resources, \
+static int __init early_pmem_hwb(char *p)
+{
+ return early_pmem_generic_parse(p, &pmem_hwb_pdata);
}
+early_param("pmem_hwb", early_pmem_hwb);
-UX500_I2C_PDEVICE(1);
-UX500_I2C_PDEVICE(2);
-UX500_I2C_PDEVICE(3);
+struct platform_device u8500_pmem_hwb_device = {
+ .name = "android_pmem",
+ .id = 2,
+ .dev = {
+ .platform_data = &pmem_hwb_pdata,
+ },
+};
+#endif
+
+#ifdef CONFIG_CRYPTO_DEV_UX500_HASH
+static struct resource ux500_hash1_resources[] = {
+ [0] = {
+ .start = U8500_HASH1_BASE,
+ .end = U8500_HASH1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+struct platform_device ux500_hash1_device = {
+ .name = "hash1",
+ .id = -1,
+ .num_resources = 1,
+ .resource = ux500_hash1_resources
+};
+#endif
+
+static struct resource ux500_cryp1_resources[] = {
+ [0] = {
+ .start = U8500_CRYP1_BASE,
+ .end = U8500_CRYP1_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_DB8500_CRYP1,
+ .end = IRQ_DB8500_CRYP1,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct cryp_platform_data cryp1_platform_data = {
+ .mem_to_engine = {
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV48_CAC1_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+ .mode = STEDMA40_MODE_LOGICAL,
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+ },
+ .engine_to_mem = {
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV48_CAC1_RX,
+ .dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+ .mode = STEDMA40_MODE_LOGICAL,
+ .src_info.psize = STEDMA40_PSIZE_LOG_4,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_4,
+ }
+};
+
+struct platform_device ux500_cryp1_device = {
+ .name = "cryp1",
+ .id = -1,
+ .dev = {
+ .platform_data = &cryp1_platform_data
+ },
+ .num_resources = ARRAY_SIZE(ux500_cryp1_resources),
+ .resource = ux500_cryp1_resources
+};
+
+#if defined(CONFIG_USB_MUSB_HOST)
+#define MUSB_MODE MUSB_HOST
+#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
+#define MUSB_MODE MUSB_PERIPHERAL
+#elif defined(CONFIG_USB_MUSB_OTG)
+#define MUSB_MODE MUSB_OTG
+#else
+#define MUSB_MODE MUSB_UNDEFINED
+#endif
+static struct musb_hdrc_config musb_hdrc_hs_otg_config = {
+ .multipoint = true, /* multipoint device */
+ .dyn_fifo = true, /* supports dynamic fifo sizing */
+ .num_eps = 16, /* number of endpoints _with_ ep0 */
+ .ram_bits = 16, /* ram address size */
+};
+
+static struct musb_hdrc_platform_data musb_hdrc_hs_otg_platform_data = {
+ .mode = MUSB_MODE,
+ .clock = "usb", /* for clk_get() */
+ .config = &musb_hdrc_hs_otg_config,
+};
+
+static struct resource usb_resources[] = {
+ [0] = {
+ .name = "usb-mem",
+ .start = U8500_USBOTG_BASE,
+ .end = (U8500_USBOTG_BASE + SZ_64K - 1),
+ .flags = IORESOURCE_MEM,
+ },
+
+ [1] = {
+ .name = "usb-irq",
+ .start = IRQ_DB8500_USBOTG,
+ .end = IRQ_DB8500_USBOTG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 musb_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device ux500_musb_device = {
+ .name = "musb_hdrc",
+ .id = 0,
+ .dev = {
+ .init_name = "musb_hdrc.0", /* for clk_get() */
+ .platform_data = &musb_hdrc_hs_otg_platform_data,
+ .dma_mask = &musb_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32)
+ },
+ .num_resources = ARRAY_SIZE(usb_resources),
+ .resource = usb_resources,
+};
void __init amba_add_devices(struct amba_device *devs[], int num)
{
diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c
new file mode 100644
index 00000000000..d4ef1b5fa3b
--- /dev/null
+++ b/arch/arm/mach-ux500/dma-db5500.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
+ * Author: Rabin Vincent <rabinv.vincent@stericsson.com> for ST-Ericsson
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <plat/ste_dma40.h>
+#include <mach/setup.h>
+#include <mach/ste-dma40-db5500.h>
+
+static struct resource dma40_resources[] = {
+ [0] = {
+ .start = U5500_DMA_BASE,
+ .end = U5500_DMA_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "base",
+ },
+ [1] = {
+ .start = U5500_DMA_LCPA_BASE,
+ .end = U5500_DMA_LCPA_BASE + 2 * SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "lcpa",
+ },
+ [2] = {
+ .start = IRQ_DB5500_DMA,
+ .end = IRQ_DB5500_DMA,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+/* Default configuration for physical memcpy */
+static struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
+ .mode = STEDMA40_MODE_PHYSICAL,
+ .dir = STEDMA40_MEM_TO_MEM,
+
+ .src_info.data_width = STEDMA40_BYTE_WIDTH,
+ .src_info.psize = STEDMA40_PSIZE_PHY_1,
+ .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+ .dst_info.data_width = STEDMA40_BYTE_WIDTH,
+ .dst_info.psize = STEDMA40_PSIZE_PHY_1,
+ .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+};
+
+/* Default configuration for logical memcpy */
+static struct stedma40_chan_cfg dma40_memcpy_conf_log = {
+ .dir = STEDMA40_MEM_TO_MEM,
+
+ .src_info.data_width = STEDMA40_BYTE_WIDTH,
+ .src_info.psize = STEDMA40_PSIZE_LOG_1,
+ .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+ .dst_info.data_width = STEDMA40_BYTE_WIDTH,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_1,
+ .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+};
+
+/*
+ * Mapping between soruce event lines and physical device address This was
+ * created assuming that the event line is tied to a device and therefore the
+ * address is constant, however this is not true for at least USB, and the
+ * values are just placeholders for USB. This table is preserved and used for
+ * now.
+ */
+static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = {
+ [DB5500_DMA_DEV0_SPI0_RX] = 0,
+ [DB5500_DMA_DEV1_SPI1_RX] = 0,
+ [DB5500_DMA_DEV2_SPI2_RX] = 0,
+ [DB5500_DMA_DEV3_SPI3_RX] = 0,
+ [DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV7_IRDA_RFS] = 0,
+ [DB5500_DMA_DEV8_IRDA_FIFO_RX] = 0,
+ [DB5500_DMA_DEV9_MSP0_RX] = U5500_MSP0_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV10_MSP1_RX] = U5500_MSP1_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV11_MSP2_RX] = U5500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV12_UART0_RX] = 0,
+ [DB5500_DMA_DEV13_UART1_RX] = 0,
+ [DB5500_DMA_DEV14_UART2_RX] = 0,
+ [DB5500_DMA_DEV15_UART3_RX] = 0,
+ [DB5500_DMA_DEV16_USB_OTG_IEP_8] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV17_USB_OTG_IEP_1_9] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV18_USB_OTG_IEP_2_10] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV19_USB_OTG_IEP_3_11] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV24_SDMMC0_RX] = U5500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV25_SDMMC1_RX] = U5500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV26_SDMMC2_RX] = U5500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV27_SDMMC3_RX] = U5500_SDI3_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV28_SDMMC4_RX] = U5500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ /* 29 - 32 not used */
+ [DB5500_DMA_DEV33_SDMMC0_RX] = U5500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV34_SDMMC1_RX] = U5500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV35_SDMMC2_RX] = U5500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV36_SDMMC3_RX] = U5500_SDI3_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV37_SDMMC4_RX] = U5500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV38_USB_OTG_IEP_8] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV39_USB_OTG_IEP_1_9] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV40_USB_OTG_IEP_2_10] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV41_USB_OTG_IEP_3_11] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV42_USB_OTG_IEP_4_12] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV43_USB_OTG_IEP_5_13] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV44_USB_OTG_IEP_6_14] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV45_USB_OTG_IEP_7_15] = U5500_USBOTG_BASE,
+ /* 46 not used */
+ [DB5500_DMA_DEV47_MCDE_RX] = 0,
+ [DB5500_DMA_DEV48_CRYPTO1_RX] = 0,
+ /* 49, 50 not used */
+ [DB5500_DMA_DEV49_I2C1_RX] = 0,
+ [DB5500_DMA_DEV50_I2C3_RX] = 0,
+ [DB5500_DMA_DEV51_I2C2_RX] = 0,
+ /* 54 - 60 not used */
+ [DB5500_DMA_DEV61_CRYPTO0_RX] = 0,
+ /* 62, 63 not used */
+};
+
+/* Mapping between destination event lines and physical device address */
+static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = {
+ [DB5500_DMA_DEV0_SPI0_TX] = 0,
+ [DB5500_DMA_DEV1_SPI1_TX] = 0,
+ [DB5500_DMA_DEV2_SPI2_TX] = 0,
+ [DB5500_DMA_DEV3_SPI3_TX] = 0,
+ [DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV7_IRRC_TX] = 0,
+ [DB5500_DMA_DEV8_IRDA_FIFO_TX] = 0,
+ [DB5500_DMA_DEV9_MSP0_TX] = U5500_MSP0_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV10_MSP1_TX] = U5500_MSP1_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV11_MSP2_TX] = U5500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV12_UART0_TX] = 0,
+ [DB5500_DMA_DEV13_UART1_TX] = 0,
+ [DB5500_DMA_DEV14_UART2_TX] = 0,
+ [DB5500_DMA_DEV15_UART3_TX] = 0,
+ [DB5500_DMA_DEV16_USB_OTG_OEP_8] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV17_USB_OTG_OEP_1_9] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV18_USB_OTG_OEP_2_10] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV19_USB_OTG_OEP_3_11] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV24_SDMMC0_TX] = U5500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV25_SDMMC1_TX] = U5500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV26_SDMMC2_TX] = U5500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV27_SDMMC3_TX] = U5500_SDI3_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV28_SDMMC4_TX] = U5500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ /* 29 - 31 not used */
+ [DB5500_DMA_DEV32_FSMC_TX] = 0,
+ [DB5500_DMA_DEV33_SDMMC0_TX] = U5500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV34_SDMMC1_TX] = U5500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV35_SDMMC2_TX] = U5500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV36_SDMMC3_TX] = U5500_SDI3_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV37_SDMMC4_TX] = U5500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB5500_DMA_DEV38_USB_OTG_OEP_8] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV39_USB_OTG_OEP_1_9] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV40_USB_OTG_OEP_2_10] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV41_USB_OTG_OEP_3_11] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV42_USB_OTG_OEP_4_12] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV43_USB_OTG_OEP_5_13] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV44_USB_OTG_OEP_6_14] = U5500_USBOTG_BASE,
+ [DB5500_DMA_DEV45_USB_OTG_OEP_7_15] = U5500_USBOTG_BASE,
+ /* 46 not used */
+ [DB5500_DMA_DEV47_STM_TX] = 0,
+ [DB5500_DMA_DEV48_CRYPTO1_TX] = 0,
+ [DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX] = 0,
+ [DB5500_DMA_DEV50_HASH1_TX] = 0,
+ [DB5500_DMA_DEV51_I2C1_TX] = 0,
+ [DB5500_DMA_DEV52_I2C3_TX] = 0,
+ [DB5500_DMA_DEV53_I2C2_TX] = 0,
+ /* 54, 55 not used */
+ [DB5500_DMA_MEMCPY_TX_1] = 0,
+ [DB5500_DMA_MEMCPY_TX_2] = 0,
+ [DB5500_DMA_MEMCPY_TX_3] = 0,
+ [DB5500_DMA_MEMCPY_TX_4] = 0,
+ [DB5500_DMA_MEMCPY_TX_5] = 0,
+ [DB5500_DMA_DEV61_CRYPTO0_TX] = 0,
+ [DB5500_DMA_DEV62_CRYPTO0_TX_HASH0_TX] = 0,
+ [DB5500_DMA_DEV63_HASH0_TX] = 0,
+};
+
+static int dma40_memcpy_event[] = {
+ DB5500_DMA_MEMCPY_TX_1,
+ DB5500_DMA_MEMCPY_TX_2,
+ DB5500_DMA_MEMCPY_TX_3,
+ DB5500_DMA_MEMCPY_TX_4,
+ DB5500_DMA_MEMCPY_TX_5,
+};
+
+static struct stedma40_platform_data dma40_plat_data = {
+ .dev_len = ARRAY_SIZE(dma40_rx_map),
+ .dev_rx = dma40_rx_map,
+ .dev_tx = dma40_tx_map,
+ .memcpy = dma40_memcpy_event,
+ .memcpy_len = ARRAY_SIZE(dma40_memcpy_event),
+ .memcpy_conf_phy = &dma40_memcpy_conf_phy,
+ .memcpy_conf_log = &dma40_memcpy_conf_log,
+ .disabled_channels = {-1},
+};
+
+static struct platform_device dma40_device = {
+ .dev = {
+ .platform_data = &dma40_plat_data,
+ },
+ .name = "dma40",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(dma40_resources),
+ .resource = dma40_resources
+};
+
+void __init db5500_dma_init(void)
+{
+ int ret;
+
+ ret = platform_device_register(&dma40_device);
+ if (ret)
+ dev_err(&dma40_device.dev, "unable to register device: %d\n", ret);
+
+}
diff --git a/arch/arm/mach-ux500/dma-db8500.c b/arch/arm/mach-ux500/dma-db8500.c
new file mode 100644
index 00000000000..f15fb2e48a0
--- /dev/null
+++ b/arch/arm/mach-ux500/dma-db8500.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2007-2010
+ *
+ * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <plat/ste_dma40.h>
+
+#include <mach/hsi.h>
+#include <mach/setup.h>
+#include <mach/ste-dma40-db8500.h>
+
+#include "pm/context.h"
+
+static struct resource dma40_resources[] = {
+ [0] = {
+ .start = U8500_DMA_BASE,
+ .end = U8500_DMA_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "base",
+ },
+ [1] = {
+ .start = U8500_DMA_LCPA_BASE,
+ .end = U8500_DMA_LCPA_BASE + 2 * SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "lcpa",
+ },
+ [2] = {
+ .start = IRQ_DB8500_DMA,
+ .end = IRQ_DB8500_DMA,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+/* Default configuration for physcial memcpy */
+static struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
+ .mode = STEDMA40_MODE_PHYSICAL,
+ .dir = STEDMA40_MEM_TO_MEM,
+
+ .src_info.data_width = STEDMA40_BYTE_WIDTH,
+ .src_info.psize = STEDMA40_PSIZE_PHY_1,
+ .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+ .dst_info.data_width = STEDMA40_BYTE_WIDTH,
+ .dst_info.psize = STEDMA40_PSIZE_PHY_1,
+ .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+};
+
+/* Default configuration for logical memcpy */
+static struct stedma40_chan_cfg dma40_memcpy_conf_log = {
+ .dir = STEDMA40_MEM_TO_MEM,
+
+ .src_info.data_width = STEDMA40_BYTE_WIDTH,
+ .src_info.psize = STEDMA40_PSIZE_LOG_1,
+ .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+ .dst_info.data_width = STEDMA40_BYTE_WIDTH,
+ .dst_info.psize = STEDMA40_PSIZE_LOG_1,
+ .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
+
+};
+
+/*
+ * Mapping between soruce event lines and physical device address
+ * This was created assuming that the event line is tied to a device and
+ * therefore the address is constant, however this is not true for at least
+ * USB, and the values are just placeholders for USB. This table is preserved
+ * and used for now.
+ */
+static dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = {
+ [DB8500_DMA_DEV0_SPI0_RX] = 0,
+ [DB8500_DMA_DEV1_SD_MMC0_RX] = 0,
+ [DB8500_DMA_DEV2_SD_MMC1_RX] = 0,
+ [DB8500_DMA_DEV3_SD_MMC2_RX] = 0,
+ [DB8500_DMA_DEV4_I2C1_RX] = 0,
+ [DB8500_DMA_DEV5_I2C3_RX] = 0,
+ [DB8500_DMA_DEV6_I2C2_RX] = 0,
+ [DB8500_DMA_DEV7_I2C4_RX] = 0,
+ [DB8500_DMA_DEV8_SSP0_RX] = U8500_SSP0_BASE + SSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV9_SSP1_RX] = 0,
+ [DB8500_DMA_DEV10_MCDE_RX] = 0,
+ [DB8500_DMA_DEV11_UART2_RX] = 0,
+ [DB8500_DMA_DEV12_UART1_RX] = 0,
+ [DB8500_DMA_DEV13_UART0_RX] = 0,
+ [DB8500_DMA_DEV14_MSP2_RX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV15_I2C0_RX] = 0,
+ [DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0] = U8500_HSIR_BASE + 0x0 + STE_HSI_RX_BUFFERX,
+ [DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1] = U8500_HSIR_BASE + 0x4 + STE_HSI_RX_BUFFERX,
+ [DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2] = U8500_HSIR_BASE + 0x8 + STE_HSI_RX_BUFFERX,
+ [DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3] = U8500_HSIR_BASE + 0xC + STE_HSI_RX_BUFFERX,
+ [DB8500_DMA_DEV24_SRC_SXA0_RX_TX] = 0,
+ [DB8500_DMA_DEV25_SRC_SXA1_RX_TX] = 0,
+ [DB8500_DMA_DEV26_SRC_SXA2_RX_TX] = 0,
+ [DB8500_DMA_DEV27_SRC_SXA3_RX_TX] = 0,
+ [DB8500_DMA_DEV28_SD_MM2_RX] = U8500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV29_SD_MM0_RX] = U8500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV30_MSP1_RX] = U8500_MSP1_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV32_SD_MM1_RX] = U8500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV33_SPI2_RX] = 0,
+ [DB8500_DMA_DEV34_I2C3_RX2] = 0,
+ [DB8500_DMA_DEV35_SPI1_RX] = 0,
+ [DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV39_USB_OTG_IEP_8] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV40_SPI3_RX] = 0,
+ [DB8500_DMA_DEV41_SD_MM3_RX] = 0,
+ [DB8500_DMA_DEV42_SD_MM4_RX] = U8500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV43_SD_MM5_RX] = 0,
+ [DB8500_DMA_DEV44_SRC_SXA4_RX_TX] = 0,
+ [DB8500_DMA_DEV45_SRC_SXA5_RX_TX] = 0,
+ [DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX] = 0,
+ [DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX] = 0,
+ [DB8500_DMA_DEV48_CAC1_RX] = U8500_CRYP1_BASE + CRYP1_RX_REG_OFFSET,
+ /* 49, 50 and 51 are not used */
+ [DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4] = 0,
+ [DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5] = 0,
+ [DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6] = 0,
+ [DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7] = 0,
+ /* 56, 57, 58, 59 and 60 are not used */
+ [DB8500_DMA_DEV61_CAC0_RX] = 0,
+ /* 62 and 63 are not used */
+};
+
+/* Mapping between destination event lines and physical device address */
+static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = {
+ [DB8500_DMA_DEV0_SPI0_TX] = 0,
+ [DB8500_DMA_DEV1_SD_MMC0_TX] = 0,
+ [DB8500_DMA_DEV2_SD_MMC1_TX] = 0,
+ [DB8500_DMA_DEV3_SD_MMC2_TX] = 0,
+ [DB8500_DMA_DEV4_I2C1_TX] = 0,
+ [DB8500_DMA_DEV5_I2C3_TX] = 0,
+ [DB8500_DMA_DEV6_I2C2_TX] = 0,
+ [DB8500_DMA_DEV7_I2C4_TX] = 0,
+ [DB8500_DMA_DEV8_SSP0_TX] = U8500_SSP0_BASE + SSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV9_SSP1_TX] = 0,
+ /* 10 is not used*/
+ [DB8500_DMA_DEV11_UART2_TX] = 0,
+ [DB8500_DMA_DEV12_UART1_TX] = 0,
+ [DB8500_DMA_DEV13_UART0_TX] = 0,
+ [DB8500_DMA_DEV14_MSP2_TX] = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV15_I2C0_TX] = 0,
+ [DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0] = U8500_HSIT_BASE + 0x0 + STE_HSI_TX_BUFFERX,
+ [DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1] = U8500_HSIT_BASE + 0x4 + STE_HSI_TX_BUFFERX,
+ [DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2] = U8500_HSIT_BASE + 0x8 + STE_HSI_TX_BUFFERX,
+ [DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3] = U8500_HSIT_BASE + 0xC + STE_HSI_TX_BUFFERX,
+ [DB8500_DMA_DEV24_DST_SXA0_RX_TX] = 0,
+ [DB8500_DMA_DEV25_DST_SXA1_RX_TX] = 0,
+ [DB8500_DMA_DEV26_DST_SXA2_RX_TX] = 0,
+ [DB8500_DMA_DEV27_DST_SXA3_RX_TX] = 0,
+ [DB8500_DMA_DEV28_SD_MM2_TX] = U8500_SDI2_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV29_SD_MM0_TX] = U8500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV30_MSP1_TX] = U8500_MSP1_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX] = U8500_MSP0_BASE + MSP_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV32_SD_MM1_TX] = U8500_SDI1_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV33_SPI2_TX] = 0,
+ [DB8500_DMA_DEV34_I2C3_TX2] = 0,
+ [DB8500_DMA_DEV35_SPI1_TX] = 0,
+ [DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV39_USB_OTG_OEP_8] = U8500_USBOTG_BASE,
+ [DB8500_DMA_DEV40_SPI3_TX] = 0,
+ [DB8500_DMA_DEV41_SD_MM3_TX] = 0,
+ [DB8500_DMA_DEV42_SD_MM4_TX] = U8500_SDI4_BASE + SD_MMC_TX_RX_REG_OFFSET,
+ [DB8500_DMA_DEV43_SD_MM5_TX] = 0,
+ [DB8500_DMA_DEV44_DST_SXA4_RX_TX] = 0,
+ [DB8500_DMA_DEV45_DST_SXA5_RX_TX] = 0,
+ [DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX] = 0,
+ [DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX] = 0,
+ [DB8500_DMA_DEV48_CAC1_TX] = U8500_CRYP1_BASE + CRYP1_TX_REG_OFFSET,
+ [DB8500_DMA_DEV49_CAC1_TX_HAC1_TX] = 0,
+ [DB8500_DMA_DEV50_HAC1_TX] = 0,
+ [DB8500_DMA_MEMCPY_TX_0] = 0,
+ [DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4] = 0,
+ [DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5] = 0,
+ [DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6] = 0,
+ [DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7] = 0,
+ [DB8500_DMA_MEMCPY_TX_1] = 0,
+ [DB8500_DMA_MEMCPY_TX_2] = 0,
+ [DB8500_DMA_MEMCPY_TX_3] = 0,
+ [DB8500_DMA_MEMCPY_TX_4] = 0,
+ [DB8500_DMA_MEMCPY_TX_5] = 0,
+ [DB8500_DMA_DEV61_CAC0_TX] = 0,
+ [DB8500_DMA_DEV62_CAC0_TX_HAC0_TX] = 0,
+ [DB8500_DMA_DEV63_HAC0_TX] = 0,
+};
+
+/* Reserved event lines for memcpy only */
+static int dma40_memcpy_event[] = {
+ DB8500_DMA_MEMCPY_TX_0,
+ DB8500_DMA_MEMCPY_TX_1,
+ DB8500_DMA_MEMCPY_TX_2,
+ DB8500_DMA_MEMCPY_TX_3,
+ DB8500_DMA_MEMCPY_TX_4,
+ DB8500_DMA_MEMCPY_TX_5,
+};
+
+static struct stedma40_platform_data dma40_plat_data = {
+ .dev_len = ARRAY_SIZE(dma40_rx_map),
+ .dev_rx = dma40_rx_map,
+ .dev_tx = dma40_tx_map,
+ .memcpy = dma40_memcpy_event,
+ .memcpy_len = ARRAY_SIZE(dma40_memcpy_event),
+ .memcpy_conf_phy = &dma40_memcpy_conf_phy,
+ .memcpy_conf_log = &dma40_memcpy_conf_log,
+ /* Audio is using physical channel 2 from MMDSP */
+ .disabled_channels = {2, -1},
+};
+
+#ifdef CONFIG_UX500_CONTEXT
+#define D40_DREG_GCC 0x000
+#define D40_DREG_LCPA 0x020
+
+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 gcc;
+
+ switch (event) {
+ case CONTEXT_APE_SAVE:
+ 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);
+ 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,
+ },
+ .name = "dma40",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(dma40_resources),
+ .resource = dma40_resources
+};
+
+void __init db8500_dma_init(void)
+{
+ int ret;
+
+ if (cpu_is_u8500ed()) {
+ dma40_plat_data.memcpy = NULL;
+ dma40_plat_data.memcpy_len = 0;
+ dma40_resources[0].start = U8500_DMA_BASE_ED;
+ dma40_resources[0].end = U8500_DMA_BASE_ED + SZ_4K - 1;
+ dma40_resources[1].start = U8500_DMA_LCPA_BASE_ED;
+ dma40_resources[1].end = U8500_DMA_LCPA_BASE_ED + 2 * SZ_1K - 1;
+ }
+
+ /* On DB8500v2+, RX line 30 is connected to MSP3 instead of MSP1 */
+ if (!cpu_is_u8500ed() && !cpu_is_u8500v1())
+ dma40_rx_map[DB8500_DMA_DEV30_MSP3_RX] = U8500_MSP3_BASE
+ + MSP_TX_RX_REG_OFFSET;
+
+ ret = platform_device_register(&dma40_device);
+ 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
new file mode 100644
index 00000000000..25bd84eb3a6
--- /dev/null
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Based on ARM realview platform
+ *
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/completion.h>
+
+#include <asm/cacheflush.h>
+
+#include "pm/cpuidle.h"
+#include "pm/context.h"
+
+extern volatile int pen_release;
+
+static DECLARE_COMPLETION(cpu_killed);
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+ flush_cache_all();
+ ux500_cpuidle_unplug(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();
+
+ if (pen_release == cpu) {
+ /*
+ * OK, proper wakeup, we're done
+ */
+ break;
+ }
+ }
+ ux500_cpuidle_plug(cpu);
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+ return wait_for_completion_timeout(&cpu_killed, 5000);
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+#ifdef DEBUG
+ unsigned int this_cpu = hard_smp_processor_id();
+
+ if (cpu != this_cpu) {
+ printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
+ this_cpu, cpu);
+ BUG();
+ }
+#endif
+
+ printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+ complete(&cpu_killed);
+
+ /* directly enter low power state, skipping secure registers */
+ platform_do_lowpower(cpu);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+ /*
+ * we don't allow CPU 0 to be shutdown (it is still too special
+ * e.g. clock tick interrupts)
+ */
+ return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-ux500/hwmem-int.c b/arch/arm/mach-ux500/hwmem-int.c
new file mode 100644
index 00000000000..c23049df4a6
--- /dev/null
+++ b/arch/arm/mach-ux500/hwmem-int.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Hardware memory driver integration
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com> for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/hwmem.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+/* CONA API */
+void *cona_create(const char *name, phys_addr_t region_paddr,
+ size_t region_size);
+void *cona_alloc(void *instance, size_t size);
+void cona_free(void *instance, void *alloc);
+phys_addr_t cona_get_alloc_paddr(void *alloc);
+void *cona_get_alloc_kaddr(void *instance, void *alloc);
+size_t cona_get_alloc_size(void *alloc);
+
+struct hwmem_mem_type_struct *hwmem_mem_types;
+unsigned int hwmem_num_mem_types;
+
+static phys_addr_t hwmem_paddr;
+static size_t hwmem_size;
+
+static int __init parse_hwmem_param(char *p)
+{
+ hwmem_size = memparse(p, &p);
+
+ if (*p != '@')
+ goto no_at;
+
+ hwmem_paddr = memparse(p + 1, &p);
+
+ return 0;
+
+no_at:
+ hwmem_size = 0;
+
+ return -EINVAL;
+}
+early_param("hwmem", parse_hwmem_param);
+
+static int __init setup_hwmem(void)
+{
+ static const unsigned int NUM_MEM_TYPES = 2;
+
+ int ret;
+
+ if (hwmem_paddr != PAGE_ALIGN(hwmem_paddr) ||
+ hwmem_size != PAGE_ALIGN(hwmem_size) || hwmem_size == 0) {
+ printk(KERN_WARNING "HWMEM: hwmem_paddr !="
+ " PAGE_ALIGN(hwmem_paddr) || hwmem_size !="
+ " PAGE_ALIGN(hwmem_size) || hwmem_size == 0\n");
+ return -ENOMSG;
+ }
+
+ hwmem_mem_types = kzalloc(sizeof(struct hwmem_mem_type_struct) *
+ NUM_MEM_TYPES, GFP_KERNEL);
+ if (hwmem_mem_types == NULL)
+ return -ENOMEM;
+
+ hwmem_mem_types[0].id = HWMEM_MEM_SCATTERED_SYS;
+ hwmem_mem_types[0].allocator_api.alloc = cona_alloc;
+ hwmem_mem_types[0].allocator_api.free = cona_free;
+ hwmem_mem_types[0].allocator_api.get_alloc_paddr =
+ cona_get_alloc_paddr;
+ hwmem_mem_types[0].allocator_api.get_alloc_kaddr =
+ cona_get_alloc_kaddr;
+ hwmem_mem_types[0].allocator_api.get_alloc_size = cona_get_alloc_size;
+ hwmem_mem_types[0].allocator_instance = cona_create("hwmem",
+ hwmem_paddr, hwmem_size);
+ if (IS_ERR(hwmem_mem_types[0].allocator_instance)) {
+ ret = PTR_ERR(hwmem_mem_types[0].allocator_instance);
+ goto hwmem_ima_init_failed;
+ }
+
+ hwmem_mem_types[1] = hwmem_mem_types[0];
+ hwmem_mem_types[1].id = HWMEM_MEM_CONTIGUOUS_SYS;
+
+ hwmem_num_mem_types = NUM_MEM_TYPES;
+
+ return 0;
+
+hwmem_ima_init_failed:
+ kfree(hwmem_mem_types);
+
+ return ret;
+}
+arch_initcall_sync(setup_hwmem);
+
+enum hwmem_alloc_flags cachi_get_cache_settings(
+ enum hwmem_alloc_flags requested_cache_settings)
+{
+ static const u32 CACHE_ON_FLAGS_MASK = HWMEM_ALLOC_HINT_CACHED |
+ HWMEM_ALLOC_HINT_CACHE_WB | HWMEM_ALLOC_HINT_CACHE_WT |
+ HWMEM_ALLOC_HINT_CACHE_NAOW | HWMEM_ALLOC_HINT_CACHE_AOW |
+ HWMEM_ALLOC_HINT_INNER_AND_OUTER_CACHE |
+ HWMEM_ALLOC_HINT_INNER_CACHE_ONLY;
+
+ enum hwmem_alloc_flags cache_settings;
+
+ if (!(requested_cache_settings & CACHE_ON_FLAGS_MASK) &&
+ requested_cache_settings & (HWMEM_ALLOC_HINT_NO_WRITE_COMBINE |
+ HWMEM_ALLOC_HINT_UNCACHED | HWMEM_ALLOC_HINT_WRITE_COMBINE))
+ /*
+ * We never use uncached as it's extremely slow and there is
+ * no scenario where it would be better than buffered memory.
+ */
+ return HWMEM_ALLOC_HINT_WRITE_COMBINE;
+
+ /*
+ * The user has specified cached or nothing at all, both are treated as
+ * cached.
+ */
+ cache_settings = (requested_cache_settings &
+ ~(HWMEM_ALLOC_HINT_UNCACHED |
+ HWMEM_ALLOC_HINT_NO_WRITE_COMBINE |
+ HWMEM_ALLOC_HINT_INNER_CACHE_ONLY |
+ HWMEM_ALLOC_HINT_CACHE_NAOW)) |
+ HWMEM_ALLOC_HINT_WRITE_COMBINE | HWMEM_ALLOC_HINT_CACHED |
+ HWMEM_ALLOC_HINT_CACHE_AOW |
+ HWMEM_ALLOC_HINT_INNER_AND_OUTER_CACHE;
+ if (!(cache_settings & (HWMEM_ALLOC_HINT_CACHE_WB |
+ HWMEM_ALLOC_HINT_CACHE_WT)))
+ cache_settings |= HWMEM_ALLOC_HINT_CACHE_WB;
+ /*
+ * On ARMv7 "alloc on write" is just a hint so we need to assume the
+ * worst case ie "alloc on write". We would however like to remember
+ * the requested "alloc on write" setting so that we can pass it on to
+ * the hardware, we use the reserved bit in the alloc flags to do that.
+ */
+ if (requested_cache_settings & HWMEM_ALLOC_HINT_CACHE_AOW)
+ cache_settings |= HWMEM_ALLOC_RESERVED_CHI;
+ else
+ cache_settings &= ~HWMEM_ALLOC_RESERVED_CHI;
+
+ return cache_settings;
+}
+
+void cachi_set_pgprot_cache_options(enum hwmem_alloc_flags cache_settings,
+ pgprot_t *pgprot)
+{
+ if (cache_settings & HWMEM_ALLOC_HINT_CACHED) {
+ if (cache_settings & HWMEM_ALLOC_HINT_CACHE_WT)
+ *pgprot = __pgprot_modify(*pgprot, L_PTE_MT_MASK,
+ L_PTE_MT_WRITETHROUGH);
+ else {
+ if (cache_settings & HWMEM_ALLOC_RESERVED_CHI)
+ *pgprot = __pgprot_modify(*pgprot,
+ L_PTE_MT_MASK, L_PTE_MT_WRITEALLOC);
+ else
+ *pgprot = __pgprot_modify(*pgprot,
+ L_PTE_MT_MASK, L_PTE_MT_WRITEBACK);
+ }
+ } else {
+ *pgprot = pgprot_writecombine(*pgprot);
+ }
+}
diff --git a/arch/arm/mach-ux500/hwreg.c b/arch/arm/mach-ux500/hwreg.c
new file mode 100644
index 00000000000..7ba3e0f2911
--- /dev/null
+++ b/arch/arm/mach-ux500/hwreg.c
@@ -0,0 +1,660 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson SA
+ *
+ * Author: Etienne CARRIERE <etienne.carriere@stericsson.com> for ST-Ericsson
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * HWREG: debug purpose module to map declared IOs and read/write
+ * access from debugfs entries.
+ *
+ * HWREG 32bit DB8500 v2.0 register access
+ * =======================================
+ *
+ * 32bit read:
+ * # echo <addr> > <debugfs>/mem/reg-addr
+ * # cat <debugfs>/mem/reg-val
+ *
+ * 32bit write:
+ * # echo <addr> > <debugfs>/mem/reg-addr
+ * # echo <value> > <debugfs>/mem/reg-val
+ *
+ * <addr> 0x-prefixed hexadecimal
+ * <value> decimal or 0x-prefixed hexadecimal
+ *
+ * HWREG DB8500 formated read/write access
+ * =======================================
+ *
+ * Read: read data, data>>SHIFT, data&=MASK, output data
+ * [0xABCDEF98] shift=12 mask=0xFFF => 0x00000CDE
+ * Write: read data, data &= ~(MASK<<SHIFT), data |= (VALUE<<SHIFT), write data
+ * [0xABCDEF98] shift=12 mask=0xFFF value=0x123 => [0xAB123F98]
+ *
+ * Usage:
+ * # echo "CMD [OPTIONS] ADRESS [VALUE]" > $debugfs/mem/hwreg
+ *
+ * CMD read read access
+ * write write access
+ *
+ * ADDRESS target reg physical addr (0x-hexa)
+ *
+ * VALUE (write) value to be updated
+ *
+ * OPTIONS
+ * -d|-dec (read) output in decimal
+ * -h|-hexa (read) output in 0x-hexa (default)
+ * -l|-w|-b 32bit (default), 16bit or 8bit reg access
+ * -m|-mask MASK 0x-hexa mask (default 0xFFFFFFFF)
+ * -s|-shift SHIFT bit shift value (read:left, write:right)
+ * -o|-offset OFFSET address offset to add to ADDRESS value
+ *
+ * Warning: bit shift operation is applied to bit-mask.
+ * Warning: bit shift direction depends on read or right command.
+ *
+ * Examples:
+ *
+ * before: [*ADDRESS = 0xABCDEF98]
+ * # echo read -h -mask 0xFFF -shift 12 ADDRESS > hwreg
+ * # cat hwreg-shift
+ * 0x0000CDE
+ * # echo write -h -mask 0xFFF -shift 12 ADDRESS 0x123 > hwreg
+ * # cat hwreg-shift
+ * 0x0000123
+ * after [*ADDRESS = 0xAB123F98]
+ *
+ * before: [*ADDRESS = 0xABCDEF98]
+ * # echo read -h -mask 0x00F0F000 ADDRESS 0x12345678 > hwreg
+ * # cat hwreg-shift
+ * 0x00C0E000
+ * # echo write -h -mask 0x00F0F000 ADDRESS 0x12345678 > hwreg
+ * # cat hwreg-shift
+ * 0xAB3D5F98
+ * after [*ADDRESS = 0xAB123F98]
+ *
+ * Read DB8500 version (full ID, chip version ID, chip version ID):
+ *
+ * echo read 0x9001DBF4 > hwreg
+ * cat hwreg
+ * echo read -m 0xFFFF -s 8 0x9001DBF4 > hwreg
+ * cat hwreg
+ * echo read -m 0xFF -s 0 0x9001DBF4 > hwreg
+ * cat hwreg
+ *
+ * Read and Enable/Disable I2C PRCMU clock:
+ *
+ * printf "I2CCLK = " && echo read -m 1 -s 8 0x80157520 > hwreg
+ * cat /sys/kernel/debug/db8500/hwreg
+ * printf "I2CCLK off" && echo write -m 1 -s 8 0x80157518 1 > hwreg
+ * printf "I2CCLK on" && echo write -m 1 -s 8 0x80157510 1 > hwreg
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include <mach/hardware.h>
+
+/*
+ * temporary definitions
+ * The following declarations are to be removed
+ * when kernel/arch/arm/mach-ux8500/include/mach/db8500-regs.h is up-to-date
+ */
+
+/* DDR-SDRAM chip-select 0 (0x0000 0000 : 0x1FFF FFFF) */
+#ifndef U8500_SCU_CD_R4_BASE
+#define U8500_SCU_CD_R4_BASE 0x17c40000
+#endif
+
+#ifndef U8500_SCU_AD_R4_BASE
+#define U8500_SCU_AD_R4_BASE 0x17d40000
+#endif
+
+#ifndef U8500_HSI2CMODEMR4_BASE
+#define U8500_HSI2CMODEMR4_BASE 0x17e02000
+#endif
+/* End of temporary definitions */
+
+static struct dentry *hwreg_debugfs_dir;
+
+/* 32bit read/write ressources */
+static u32 debug_address; /* shared: single read/write access */
+
+/* hwreg entry ressources */
+struct hwreg_cfg {
+ uint addr; /* target physical addr to access */
+ uint fmt; /* format */
+ uint mask; /* read/write mask, applied before any bit shift */
+ int shift; /* bit shift (read:right shift, write:left shift */
+};
+#define REG_FMT_DEC(c) ((c)->fmt & 0x1) /* bit 0: 0=hexa, 1=dec */
+#define REG_FMT_HEX(c) (!REG_FMT_DEC(c)) /* bit 0: 0=hexa, 1=dec */
+#define REG_FMT_32B(c) (((c)->fmt & 0x6)==0x0) /* bit[2:1]=0 => 32b access */
+#define REG_FMT_16B(c) (((c)->fmt & 0x6)==0x2) /* bit[2:1]=1 => 16b access */
+#define REG_FMT_8B(c) (((c)->fmt & 0x6)==0x4) /* bit[2:1]=2 => 8b access */
+
+static struct hwreg_cfg hwreg_cfg = {
+ .addr = 0, /* default: invalid phys addr */
+ .fmt = 0, /* default: 32bit access, hex output */
+ .mask = 0xFFFFFFFF, /* default: no mask */
+ .shift = 0, /* default: no bit shift */
+};
+
+/* HWREG guts: mapping table */
+
+struct hwreg_io_range {
+ u32 base;
+ u32 size;
+ u8 *addr;
+};
+
+/*
+ * HWREG guts: mapping table
+ */
+static struct hwreg_io_range hwreg_io_map[] = {
+ /* Periph1 Peripherals */
+ {.base = U8500_PER1_BASE, .size = 0x10000},
+ /* Periph2 Peripherals */
+ {.base = U8500_PER2_BASE, .size = 0x10000},
+ /* Periph3 Peripherals */
+ {.base = U8500_PER3_BASE, .size = 0x10000},
+ /* Periph4 Peripherals */
+ {.base = U8500_PER4_BASE, .size = 0x70000},
+ /* Periph5 Periphals */
+ {.base = U8500_PER5_BASE, .size = 0x20000},
+ /* Periph6 Peripherals */
+ {.base = U8500_PER6_BASE, .size = 0x10000},
+ /*
+ * Snoop Control Unit, A9 Private interrupt IF,
+ * A9 private peripherals, Level-2 Cache Configuration registers,
+ * and some reserved area
+ */
+ {.base = U8500_SCU_BASE, .size = 0x4000},
+
+ /* DISPLAY Ctrl. configuration registers */
+ {.base = U8500_MCDE_BASE, .size = SZ_4K},
+
+ /* DSI1 link registers */
+ {.base = U8500_DSI_LINK1_BASE, .size = SZ_4K},
+
+ /* DSI2 link registers */
+ {.base = U8500_DSI_LINK2_BASE, .size = SZ_4K},
+
+ /* DSI3 link registers */
+ {.base = U8500_DSI_LINK3_BASE, .size = SZ_4K},
+
+ /* DMA Ctrl. configuration registers (base address changed in V1) */
+ {.base = U8500_DMA_BASE, .size = SZ_4K},
+
+ /* 0xB7A00000 -> 0xB7E04000: Modem I2C */
+ {.base = U8500_MODEM_I2C, .size = 0x404000},
+
+ /* 0xA0390000 -> 0xA039FFFF: SBAG configuration registers */
+ {.base = U8500_SBAG_BASE, .size = SZ_4K},
+
+ /* 0xA0300000 -> 0xA031FFFF: SGA configuration registers */
+ {.base = U8500_SGA_BASE, .size = 0x10000},
+
+ /* 0xA0200000 -> 0xA02FFFFF: Smart Imaging Acc. Data Memory space (SIA) */
+ {.base = U8500_SIA_BASE, .size = 0x60000},
+
+ /* 0xA0100000 -> 0xA01FFFFF: Smart Video Acc. Data Memory space (SVA) */
+ {.base = U8500_SVA_BASE, .size = 0x60000},
+
+ /* 0x81000000 -> 0x8103FFFF: Main ICN Crossbar configuration registers */
+ {.base = U8500_ICN_BASE, .size = 0x2000},
+
+ /* 0x80140000 -> 0x8014FFFF: HSEM (Semaphores) configuration */
+ {.base = U8500_HSEM_BASE, .size = SZ_4K},
+
+ /* 0x80130000 -> 0x8013FFFF: B2R2 configuration registers */
+ {.base = U8500_B2R2_BASE, .size = SZ_4K},
+
+ /* 0x80100000 -> 0x8010FFFF: STM */
+ {.base = U8500_STM_BASE, .size = 0x10000},
+
+ /* High part of embedded boot ROM */
+ {.base = U8500_ASIC_ID_BASE, .size = SZ_4K},
+
+ /* 0x17C4 0000 : 0x17C4 007C */
+ {.base = U8500_SCU_CD_R4_BASE, .size = SZ_4K},
+
+ /* 0x17D4 0000 : 0x17D4 041C */
+ {.base = U8500_SCU_AD_R4_BASE, .size = SZ_4K},
+
+ /* 0x17E0 2000 : 0x17E0 2FFC */
+ {.base = U8500_HSI2CMODEMR4_BASE, .size = SZ_4K},
+
+ {.base = 0, .size = 0, },
+
+};
+
+static void hwreg_io_init(void)
+{
+ int i;
+
+ for (i = 0; hwreg_io_map[i].base; ++i) {
+ hwreg_io_map[i].addr = ioremap(hwreg_io_map[i].base,
+ hwreg_io_map[i].size);
+ if (!hwreg_io_map[i].addr)
+ printk(KERN_WARNING
+ "%s: ioremap for %d (%08x) failed\n",
+ __func__, i, hwreg_io_map[i].base);
+ }
+}
+
+static void hwreg_io_exit(void)
+{
+ int i;
+
+ for (i = 0; hwreg_io_map[i].base; ++i)
+ if (hwreg_io_map[i].addr)
+ iounmap(hwreg_io_map[i].addr);
+}
+
+static void *hwreg_io_ptov(u32 phys)
+{
+ int i;
+
+ for (i = 0; hwreg_io_map[i].base; ++i) {
+ u32 base = hwreg_io_map[i].base;
+ u32 size = hwreg_io_map[i].size;
+ u8 *addr = hwreg_io_map[i].addr;
+
+ if (phys < base || phys >= base + size)
+ continue;
+
+ if (addr)
+ return addr + phys - base;
+
+ break;
+ }
+
+ return NULL;
+}
+
+
+/*
+ * HWREG 32bit DB8500 register read/write access debugfs part
+ */
+
+static int hwreg_address_print(struct seq_file *s, void *p)
+{
+ return seq_printf(s, "0x%08X\n", debug_address);
+}
+
+static int hwreg_address_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hwreg_address_print, inode->i_private);
+}
+
+static ssize_t hwreg_address_write(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buf[32];
+ int buf_size;
+ unsigned long user_address;
+
+ /* Get userspace string and assure termination */
+ buf_size = min(count, (sizeof(buf) - 1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if(strict_strtoul(buf, 0, &user_address))
+ return -EINVAL;
+ if (hwreg_io_ptov(user_address)==NULL)
+ return -EADDRNOTAVAIL;
+
+ debug_address = user_address;
+ return buf_size;
+}
+
+static int hwreg_value_print(struct seq_file *s, void *p)
+{
+ void *ptr;
+
+ ptr = hwreg_io_ptov(debug_address);
+ if (ptr == NULL)
+ return -EADDRNOTAVAIL;
+ seq_printf(s, "0x%X\n", readl(ptr));
+ return 0;
+}
+
+static int hwreg_value_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hwreg_value_print, inode->i_private);
+}
+
+static ssize_t hwreg_value_write(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buf[32];
+ int buf_size;
+ unsigned long user_val;
+ void *ptr;
+
+ /* Get userspace string and assure termination */
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if (strict_strtoul(buf, 0, &user_val))
+ return -EINVAL;
+
+ if ((ptr = hwreg_io_ptov(debug_address)) == NULL)
+ return -EFAULT;
+ writel(user_val, ptr);
+ return buf_size;
+}
+
+static const struct file_operations hwreg_address_fops = {
+ .open = hwreg_address_open,
+ .write = hwreg_address_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+static const struct file_operations hwreg_value_fops = {
+ .open = hwreg_value_open,
+ .write = hwreg_value_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+/* 'map' read entry: display current HWREG IO mapping table */
+static int hwreg_map_print(struct seq_file *s, void *p)
+{
+ int err, i;
+ for (i = 0; hwreg_io_map[i].base; ++i) {
+ err = seq_printf(s, "%d: 0x%08X => 0x%08X\n",
+ i, hwreg_io_map[i].base,
+ hwreg_io_map[i].base+hwreg_io_map[i].size);
+ if (err < 0)
+ return -ENOMEM;
+ }
+ return 0;
+}
+static int hwreg_map_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hwreg_map_print, inode->i_private);
+}
+
+static const struct file_operations hwreg_map_fops = {
+ .open = hwreg_map_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+/*
+ * HWREG DB8500 formated routines
+ */
+
+static int hwreg_print(struct seq_file *s, void *d)
+{
+ struct hwreg_cfg *c = (struct hwreg_cfg*) s->private;
+ void *p;
+ uint v;
+
+ if ((c==NULL) || ((p = hwreg_io_ptov(c->addr))==NULL))
+ return -EADDRNOTAVAIL;
+
+ v = (uint) (REG_FMT_32B(c) ? readl(p) : REG_FMT_16B(c) ? readw(p) : readb(p));
+ v = (c->shift>=0) ? v >> c->shift : v << (-c->shift);
+ v = v & c->mask;
+
+ if (REG_FMT_DEC(c))
+ seq_printf(s, "%d\n", v);
+ else if (REG_FMT_32B(c))
+ seq_printf(s, "0x%08X\n", v);
+ else if (REG_FMT_32B(c))
+ seq_printf(s, "0x%04X\n", v);
+ else
+ seq_printf(s, "0x%02X\n", v);
+ return 0;
+}
+
+static int hwreg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hwreg_print, inode->i_private);
+}
+
+/*
+ * return length of an ASCII numerical value, 0 is string is not a numerical
+ * value. string shall start at value 1st char.
+ * string can be tailed with \0 or space or newline chars only.
+ * value can be decimal or hexadecimal (prefixed 0x or 0X).
+ */
+static int strval_len(char *b)
+{
+ char *s = b;
+ if((*s=='0') && ((*(s+1)=='x') || (*(s+1)=='X'))) {
+ s += 2;
+ for (; *s && (*s!=' ') && (*s!='\n'); s++) {
+ if (!isxdigit(*s))
+ return 0;
+ }
+ } else {
+ if (*s=='-')
+ s++;
+ for (; *s && (*s!=' ') && (*s!='\n'); s++) {
+ if (!isdigit(*s))
+ return 0;
+ }
+ }
+ return (int) (s-b);
+}
+
+/*
+ * parse hwreg input data.
+ * update global hwreg_cfg only if input data syntax is ok.
+ */
+static ssize_t hwreg_common_write(char *b, struct hwreg_cfg *cfg)
+{
+ uint write, val=0, offset=0;
+ struct hwreg_cfg loc = {
+ .addr = 0, /* default: invalid phys addr */
+ .fmt = 0, /* default: 32bit access, hex output */
+ .mask = 0xFFFFFFFF, /* default: no mask */
+ .shift = 0, /* default: no bit shift */
+ };
+
+ /* read or write ? */
+ if(!strncmp(b, "read ", 5)) {
+ write = 0;
+ b += 5;
+ } else if (!strncmp(b, "write ", 6)) {
+ write = 1;
+ b += 6;
+ } else {
+ return -EINVAL;
+ }
+
+ /* OPTIONS -l|-w|-b -s -m -o */
+ while((*b==' ') || (*b=='-')) {
+ if (*(b-1)!=' ') {
+ b++;
+ continue;
+ }
+ if ((!strncmp(b, "-d ", 3)) || (!strncmp(b, "-dec ", 5))) {
+ b += (*(b+2)==' ') ? 3 : 5;
+ loc.fmt |= (1<<0);
+ } else if ((!strncmp(b, "-h ", 3)) || (!strncmp(b, "-hex ", 5))) {
+ b += (*(b+2)==' ') ? 3 : 5;
+ loc.fmt &= ~(1<<0);
+ } else if ((!strncmp(b, "-m ", 3)) || (!strncmp(b, "-mask ", 6))) {
+ b += (*(b+2)==' ') ? 3 : 6;
+ if (strval_len(b)==0)
+ return -EINVAL;
+ loc.mask = simple_strtoul(b, &b, 0);
+ } else if ((!strncmp(b, "-s ", 3)) || (!strncmp(b,"-shift ", 7))) {
+ b += (*(b+2)==' ') ? 3 : 7;
+ if (strval_len(b)==0)
+ return -EINVAL;
+ loc.shift = simple_strtol(b, &b, 0);
+
+ } else if ((!strncmp(b, "-o ", 3)) || (!strncmp(b,"-offset ", 8))) {
+ b += (*(b+2)==' ') ? 3 : 8;
+ if (strval_len(b)==0)
+ return -EINVAL;
+ offset = simple_strtol(b, &b, 0);
+ } else if (!strncmp(b, "-l ", 3)) {
+ b += 3;
+ loc.fmt = (loc.fmt & ~(3<<1)) | (0<<1);
+ } else if (!strncmp(b, "-w ", 3)) {
+ b += 3;
+ loc.fmt = (loc.fmt & ~(3<<1)) | (1<<1);
+ } else if (!strncmp(b, "-b ", 3)) {
+ b += 3;
+ loc.fmt = (loc.fmt & ~(3<<1)) | (2<<1);
+ } else {
+ return -EINVAL;
+ }
+ }
+ /* get arg ADDRESS */
+ if (strval_len(b)==0)
+ return -EINVAL;
+ loc.addr = simple_strtoul(b, &b, 0);
+ loc.addr += offset;
+ if (hwreg_io_ptov(loc.addr) == NULL)
+ return -EINVAL;
+
+ if (write) {
+ while(*b==' ') b++; /* skip spaces up to arg VALUE */
+ if (strval_len(b)==0)
+ return -EINVAL;
+ val = simple_strtoul(b, &b, 0);
+ }
+
+ /* args are ok, update target cfg (mainly for read) */
+ *cfg = loc;
+
+#ifdef DEBUG
+ printk(KERN_INFO "HWREG request: %s %d-bit reg, %s, addr=0x%08X, "
+ "mask=0x%X, shift=%d value=0x%X\n",
+ (write)?"write":"read",
+ REG_FMT_32B(cfg)?32:REG_FMT_16B(cfg)?16:8,
+ REG_FMT_DEC(cfg)?"decimal":"hexa",
+ cfg->addr, cfg->mask, cfg->shift, val);
+#endif
+
+ if (write) {
+ void *p = hwreg_io_ptov(cfg->addr);
+ uint d = (uint) (REG_FMT_32B(cfg)) ? readl(p) :
+ (REG_FMT_16B(cfg)) ? readw(p) : readb(p);
+
+ if (cfg->shift>=0) {
+ d &= ~(cfg->mask << (cfg->shift));
+ val = (val & cfg->mask) << (cfg->shift);
+ } else {
+ d &= ~(cfg->mask >> (-cfg->shift));
+ val = (val & cfg->mask) >> (-cfg->shift);
+ }
+ val = val | d;
+
+ /* read reg, reset mask field and update value bit-field */
+ if (REG_FMT_32B(cfg))
+ writel(val, p);
+ else if (REG_FMT_16B(cfg))
+ writew(val, p);
+ else
+ writeb(val, p);
+ }
+ return 0;
+}
+
+static ssize_t hwreg_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char buf[128];
+ int buf_size, ret;
+
+ /* Get userspace string and assure termination */
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ /* get args and process */
+ ret = hwreg_common_write(buf, &hwreg_cfg);
+ return (ret) ? ret : buf_size;
+}
+
+static const struct file_operations hwreg_fops = {
+ .open = hwreg_open,
+ .write = hwreg_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+/*
+ * hwreg module init/cleanup
+ */
+static int __init hwreg_initialize(void)
+{
+ static struct dentry *file;
+ hwreg_io_init();
+
+ hwreg_debugfs_dir = debugfs_create_dir("mem", NULL);
+ if (!hwreg_debugfs_dir)
+ goto debugfs_err;
+
+ file = debugfs_create_file("reg-addr",
+ (S_IRUGO | S_IWUGO), hwreg_debugfs_dir,
+ NULL, &hwreg_address_fops);
+ if (!file)
+ goto debugfs_err;
+ file = debugfs_create_file("reg-val",
+ (S_IRUGO | S_IWUGO), hwreg_debugfs_dir,
+ NULL, &hwreg_value_fops);
+ if (!file)
+ goto debugfs_err;
+ file = debugfs_create_file("reg-map",
+ (S_IRUGO),
+ hwreg_debugfs_dir, NULL, &hwreg_map_fops);
+ if (!file)
+ goto debugfs_err;
+ file = debugfs_create_file("hwreg",
+ (S_IRUGO),
+ hwreg_debugfs_dir, &hwreg_cfg, &hwreg_fops);
+ if (!file)
+ goto debugfs_err;
+ return 0;
+
+debugfs_err:
+ if (hwreg_debugfs_dir)
+ debugfs_remove_recursive(hwreg_debugfs_dir);
+ printk(KERN_ERR "hwreg: failed to register debugfs entries.\n");
+ return -1;
+}
+
+static void __exit hwreg_finalize(void)
+{
+ debugfs_remove_recursive(hwreg_debugfs_dir);
+ hwreg_io_exit();
+}
+
+module_init(hwreg_initialize);
+module_exit(hwreg_finalize);
+
+MODULE_AUTHOR("ST-Ericsson");
+MODULE_DESCRIPTION("DB8500 HW registers access through debugfs");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-ux500/include/mach/ab8500-accdet.h b/arch/arm/mach-ux500/include/mach/ab8500-accdet.h
new file mode 100644
index 00000000000..b1b157e317e
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ab8500-accdet.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright ST-Ericsson 2011.
+ *
+ * Author: Jarmo K. Kuronen <jarmo.kuronen@symbio.com> for ST Ericsson.
+ * Licensed under GPLv2.
+ */
+
+#ifndef _AB8500_ACCDET_H
+#define _AB8500_ACCDET_H
+
+/*
+* Debounce times for AccDet1 input
+* @0x880 [2:0]
+*/
+#define ACCDET1_DB_0ms 0x00
+#define ACCDET1_DB_10ms 0x01
+#define ACCDET1_DB_20ms 0x02
+#define ACCDET1_DB_30ms 0x03
+#define ACCDET1_DB_40ms 0x04
+#define ACCDET1_DB_50ms 0x05
+#define ACCDET1_DB_60ms 0x06
+#define ACCDET1_DB_70ms 0x07
+
+/*
+* Voltage threshold for AccDet1 input
+* @0x880 [6:3]
+*/
+#define ACCDET1_TH_1100mV 0x40
+#define ACCDET1_TH_1200mV 0x48
+#define ACCDET1_TH_1300mV 0x50
+#define ACCDET1_TH_1400mV 0x58
+#define ACCDET1_TH_1500mV 0x60
+#define ACCDET1_TH_1600mV 0x68
+#define ACCDET1_TH_1700mV 0x70
+#define ACCDET1_TH_1800mV 0x78
+
+/*
+* Voltage threshold for AccDet21 input
+* @0x881 [3:0]
+*/
+#define ACCDET21_TH_300mV 0x00
+#define ACCDET21_TH_400mV 0x01
+#define ACCDET21_TH_500mV 0x02
+#define ACCDET21_TH_600mV 0x03
+#define ACCDET21_TH_700mV 0x04
+#define ACCDET21_TH_800mV 0x05
+#define ACCDET21_TH_900mV 0x06
+#define ACCDET21_TH_1000mV 0x07
+#define ACCDET21_TH_1100mV 0x08
+#define ACCDET21_TH_1200mV 0x09
+#define ACCDET21_TH_1300mV 0x0a
+#define ACCDET21_TH_1400mV 0x0b
+#define ACCDET21_TH_1500mV 0x0c
+#define ACCDET21_TH_1600mV 0x0d
+#define ACCDET21_TH_1700mV 0x0e
+#define ACCDET21_TH_1800mV 0x0f
+
+/*
+* Voltage threshold for AccDet22 input
+* @0x881 [7:4]
+*/
+#define ACCDET22_TH_300mV 0x00
+#define ACCDET22_TH_400mV 0x10
+#define ACCDET22_TH_500mV 0x20
+#define ACCDET22_TH_600mV 0x30
+#define ACCDET22_TH_700mV 0x40
+#define ACCDET22_TH_800mV 0x50
+#define ACCDET22_TH_900mV 0x60
+#define ACCDET22_TH_1000mV 0x70
+#define ACCDET22_TH_1100mV 0x80
+#define ACCDET22_TH_1200mV 0x90
+#define ACCDET22_TH_1300mV 0xa0
+#define ACCDET22_TH_1400mV 0xb0
+#define ACCDET22_TH_1500mV 0xc0
+#define ACCDET22_TH_1600mV 0xd0
+#define ACCDET22_TH_1700mV 0xe0
+#define ACCDET22_TH_1800mV 0xf0
+
+/**
+ * struct ab8500_accdet_platform_data - AV Accessory detection specific
+ * platform data
+ * @btn_keycode Keycode to be sent when accessory button is pressed.
+ * @accdet1_dbth Debounce time + voltage threshold for accdet 1 input.
+ * @accdet2122_th Voltage thresholds for accdet21 and accdet22 inputs.
+ * @is_detection_inverted Whether the accessory insert/removal, button
+ * press/release irq's are inverted.
+ */
+struct ab8500_accdet_platform_data {
+ int btn_keycode;
+ u8 accdet1_dbth;
+ u8 accdet2122_th;
+ unsigned int video_ctrl_gpio;
+ bool is_detection_inverted;
+};
+
+#endif /* _AB8500_ACCDET_H */
diff --git a/arch/arm/mach-ux500/include/mach/ab8500_codec.h b/arch/arm/mach-ux500/include/mach/ab8500_codec.h
new file mode 100644
index 00000000000..d45dea66b5d
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ab8500_codec.h
@@ -0,0 +1,327 @@
+/*****************************************************************************/
+/**
+* © ST-Ericsson, 2009 - All rights reserved
+* Reproduction and Communication of this document is strictly prohibited
+* unless specifically authorized in writing by ST-Ericsson
+*
+* \brief Public header file for AB8500 Codec
+* \author ST-Ericsson
+*/
+/*****************************************************************************/
+
+#ifndef _AB8500_CODEC_H_
+#define _AB8500_CODEC_H_
+
+/*---------------------------------------------------------------------
+ * Includes
+ *--------------------------------------------------------------------*/
+#include "hcl_defs.h"
+#include "debug.h"
+#include <mach/ab8500_codec_p.h>
+
+/*---------------------------------------------------------------------
+ * Define
+ *--------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+ typedef enum {
+ AB8500_CODEC_OK,
+ AB8500_CODEC_ERROR,
+ AB8500_CODEC_UNSUPPORTED_FEATURE,
+ AB8500_CODEC_INVALID_PARAMETER,
+ AB8500_CODEC_CONFIG_NOT_COHERENT,
+ AB8500_CODEC_TRANSACTION_FAILED
+ } t_ab8500_codec_error;
+
+ typedef enum {
+ AB8500_CODEC_MASTER_MODE_DISABLE,
+ AB8500_CODEC_MASTER_MODE_ENABLE
+ } t_ab8500_codec_master_mode;
+
+ typedef enum {
+ AB8500_CODEC_SLOT0,
+ AB8500_CODEC_SLOT1,
+ AB8500_CODEC_SLOT2,
+ AB8500_CODEC_SLOT3,
+ AB8500_CODEC_SLOT4,
+ AB8500_CODEC_SLOT5,
+ AB8500_CODEC_SLOT6,
+ AB8500_CODEC_SLOT7,
+ AB8500_CODEC_SLOT8,
+ AB8500_CODEC_SLOT9,
+ AB8500_CODEC_SLOT10,
+ AB8500_CODEC_SLOT11,
+ AB8500_CODEC_SLOT12,
+ AB8500_CODEC_SLOT13,
+ AB8500_CODEC_SLOT14,
+ AB8500_CODEC_SLOT15,
+ AB8500_CODEC_SLOT16,
+ AB8500_CODEC_SLOT17,
+ AB8500_CODEC_SLOT18,
+ AB8500_CODEC_SLOT19,
+ AB8500_CODEC_SLOT20,
+ AB8500_CODEC_SLOT21,
+ AB8500_CODEC_SLOT22,
+ AB8500_CODEC_SLOT23,
+ AB8500_CODEC_SLOT24,
+ AB8500_CODEC_SLOT25,
+ AB8500_CODEC_SLOT26,
+ AB8500_CODEC_SLOT27,
+ AB8500_CODEC_SLOT28,
+ AB8500_CODEC_SLOT29,
+ AB8500_CODEC_SLOT30,
+ AB8500_CODEC_SLOT31,
+ AB8500_CODEC_SLOT_UNDEFINED
+ } t_ab8500_codec_slot;
+
+ typedef enum {
+ AB8500_CODEC_DA_CHANNEL_NUMBER_1,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_2,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_3,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_4,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_5,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_6,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED
+ } t_ab8500_codec_da_channel_number;
+
+ typedef enum {
+ AB8500_CODEC_SRC_STATE_DISABLE,
+ AB8500_CODEC_SRC_STATE_ENABLE
+ } t_ab8500_codec_src_state;
+
+ typedef enum {
+ AB8500_CODEC_DEST_STATE_DISABLE,
+ AB8500_CODEC_DEST_STATE_ENABLE
+ } t_ab8500_codec_dest_state;
+
+ typedef struct {
+ t_ab8500_codec_cr27_if1_bitclk_osr cr27_if1_bitclk_osr;
+ t_ab8500_codec_cr27_if0_bitclk_osr cr27_if0_bitclk_osr;
+ t_ab8500_codec_cr28_if0wl cr28_if0wl;
+ t_ab8500_codec_cr30_if1wl cr30_if1wl;
+ t_ab8500_codec_cr28_bitclk0p cr28_bitclk0p;
+ t_ab8500_codec_cr28_if0del cr28_if0del;
+ } t_ab8500_codec_tdm_config;
+
+ typedef struct {
+ t_ab8500_codec_cr104_bfifoint cr104_bfifoint;
+ t_ab8500_codec_cr105_bfifotx cr105_bfifotx;
+ t_ab8500_codec_cr106_bfifofsext cr106_bfifofsext;
+ t_ab8500_codec_cr106_bfifomsk cr106_bfifomsk;
+ t_ab8500_codec_cr106_bfifomstr cr106_bfifomstr;
+ t_ab8500_codec_cr106_bfifostrt cr106_bfifostrt;
+ t_ab8500_codec_cr107_bfifosampnr cr107_bfifosampnr;
+ t_ab8500_codec_cr108_bfifowakeup cr108_bfifowakeup;
+ } t_ab8500_codec_burst_fifo_config;
+
+/************************************************************/
+/*---------------------------------------------------------------------
+ * Exported APIs
+ *--------------------------------------------------------------------*/
+/* Initialization */
+ t_ab8500_codec_error AB8500_CODEC_Init(IN t_uint8
+ slave_address_of_codec);
+ t_ab8500_codec_error AB8500_CODEC_Reset(void);
+
+/* Audio Codec basic configuration */
+ t_ab8500_codec_error AB8500_CODEC_SetModeAndDirection(IN
+ t_ab8500_codec_direction
+ ab8500_codec_direction,
+ IN
+ t_ab8500_codec_mode
+ ab8500_codec_mode_in,
+ IN
+ t_ab8500_codec_mode
+ ab8500_codec_mode_out,
+ IN
+ t_ab8500_codec_tdm_config
+ const *const
+ p_tdm_config);
+ t_ab8500_codec_error AB8500_CODEC_SelectInput(IN t_ab8500_codec_src
+ ab8500_codec_src);
+ t_ab8500_codec_error AB8500_CODEC_SelectOutput(IN t_ab8500_codec_dest
+ ab8500_codec_dest);
+
+/* Burst FIFO configuration */
+ t_ab8500_codec_error AB8500_CODEC_ConfigureBurstFifo(IN
+ t_ab8500_codec_burst_fifo_config
+ const *const
+ p_burst_fifo_config);
+ t_ab8500_codec_error AB8500_CODEC_EnableBurstFifo(void);
+ t_ab8500_codec_error AB8500_CODEC_DisableBurstFifo(void);
+
+/* Audio Codec Master mode configuration */
+ t_ab8500_codec_error AB8500_CODEC_SetMasterMode(IN
+ t_ab8500_codec_master_mode
+ mode);
+
+/* APIs to be implemented by user */
+ t_ab8500_codec_error AB8500_CODEC_Write(IN t_uint8 register_offset,
+ IN t_uint8 count,
+ IN t_uint8 * p_data);
+ t_ab8500_codec_error AB8500_CODEC_Read(IN t_uint8 register_offset,
+ IN t_uint8 count,
+ IN t_uint8 * p_dummy_data,
+ IN t_uint8 * p_data);
+
+/* Volume Management */
+ t_ab8500_codec_error AB8500_CODEC_SetSrcVolume(IN t_ab8500_codec_src
+ src_device,
+ IN t_uint8
+ in_left_volume,
+ IN t_uint8
+ in_right_volume);
+ t_ab8500_codec_error AB8500_CODEC_SetDestVolume(IN t_ab8500_codec_dest
+ dest_device,
+ IN t_uint8
+ out_left_volume,
+ IN t_uint8
+ out_right_volume);
+
+/* Power management */
+ t_ab8500_codec_error AB8500_CODEC_PowerDown(void);
+ t_ab8500_codec_error AB8500_CODEC_PowerUp(void);
+
+/* Interface Management */
+ t_ab8500_codec_error AB8500_CODEC_SelectInterface(IN
+ t_ab8500_codec_audio_interface
+ audio_interface);
+ t_ab8500_codec_error AB8500_CODEC_GetInterface(OUT
+ t_ab8500_codec_audio_interface
+ * p_audio_interface);
+
+/* Slot Allocation */
+ t_ab8500_codec_error AB8500_CODEC_ADSlotAllocation(IN
+ t_ab8500_codec_slot
+ ad_slot,
+ IN
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation
+ value);
+ t_ab8500_codec_error AB8500_CODEC_DASlotAllocation(IN
+ t_ab8500_codec_da_channel_number
+ channel_number,
+ IN
+ t_ab8500_codec_cr51_to_cr56_sltoda
+ slot);
+
+/* Loopback Management */
+ t_ab8500_codec_error AB8500_CODEC_SetAnalogLoopback(IN t_uint8
+ out_left_volume,
+ IN t_uint8
+ out_right_volume);
+ t_ab8500_codec_error AB8500_CODEC_RemoveAnalogLoopback(void);
+
+/* Bypass Management */
+ t_ab8500_codec_error AB8500_CODEC_EnableBypassMode(void);
+ t_ab8500_codec_error AB8500_CODEC_DisableBypassMode(void);
+
+/* Power Control Management */
+ t_ab8500_codec_error AB8500_CODEC_SrcPowerControl(IN t_ab8500_codec_src
+ src_device,
+ t_ab8500_codec_src_state
+ state);
+ t_ab8500_codec_error AB8500_CODEC_DestPowerControl(IN
+ t_ab8500_codec_dest
+ dest_device,
+ t_ab8500_codec_dest_state
+ state);
+
+/* Version Management */
+ t_ab8500_codec_error AB8500_CODEC_GetVersion(OUT t_version * p_version);
+
+#if 0
+/* Debug management */
+ t_ab8500_codec_error AB8500_CODEC_SetDbgLevel(IN t_dbg_level dbg_level);
+ t_ab8500_codec_error AB8500_CODEC_GetDbgLevel(OUT t_dbg_level *
+ p_dbg_level);
+#endif
+
+/*
+** following is added by $kardad$
+*/
+
+/* duplicate copy of enum from msp.h */
+/* for MSPConfiguration.in_clock_freq parameter to select msp clock freq */
+ typedef enum {
+ CODEC_MSP_INPUT_FREQ_1MHZ = 1024,
+ CODEC_MSP_INPUT_FREQ_2MHZ = 2048,
+ CODEC_MSP_INPUT_FREQ_3MHZ = 3072,
+ CODEC_MSP_INPUT_FREQ_4MHZ = 4096,
+ CODEC_MSP_INPUT_FREQ_5MHZ = 5760,
+ CODEC_MSP_INPUT_FREQ_6MHZ = 6144,
+ CODEC_MSP_INPUT_FREQ_8MHZ = 8192,
+ CODEC_MSP_INPUT_FREQ_11MHZ = 11264,
+ CODEC_MSP_INPUT_FREQ_12MHZ = 12288,
+ CODEC_MSP_INPUT_FREQ_16MHZ = 16384,
+ CODEC_MSP_INPUT_FREQ_22MHZ = 22579,
+ CODEC_MSP_INPUT_FREQ_24MHZ = 24576,
+ CODEC_MSP_INPUT_FREQ_48MHZ = 49152
+ } codec_msp_in_clock_freq_type;
+
+/* msp clock source internal/external for srg_clock_sel */
+ typedef enum {
+ CODEC_MSP_APB_CLOCK = 0,
+ CODEC_MSP_SCK_CLOCK = 2,
+ CODEC_MSP_SCK_SYNC_CLOCK = 3
+ } codec_msp_srg_clock_sel_type;
+
+/* Sample rate supported by Codec */
+
+ typedef enum {
+ CODEC_FREQUENCY_DONT_CHANGE = -100,
+ CODEC_SAMPLING_FREQ_RESET = -1,
+ CODEC_SAMPLING_FREQ_MINLIMIT = 7,
+ CODEC_SAMPLING_FREQ_8KHZ = 8, /*default */
+ CODEC_SAMPLING_FREQ_11KHZ = 11,
+ CODEC_SAMPLING_FREQ_12KHZ = 12,
+ CODEC_SAMPLING_FREQ_16KHZ = 16,
+ CODEC_SAMPLING_FREQ_22KHZ = 22,
+ CODEC_SAMPLING_FREQ_24KHZ = 24,
+ CODEC_SAMPLING_FREQ_32KHZ = 32,
+ CODEC_SAMPLING_FREQ_44KHZ = 44,
+ CODEC_SAMPLING_FREQ_48KHZ = 48,
+ CODEC_SAMPLING_FREQ_64KHZ = 64, /*the frequencies below this line are not supported in stw5094A */
+ CODEC_SAMPLING_FREQ_88KHZ = 88,
+ CODEC_SAMPLING_FREQ_96KHZ = 96,
+ CODEC_SAMPLING_FREQ_128KHZ = 128,
+ CODEC_SAMPLING_FREQ_176KHZ = 176,
+ CODEC_SAMPLING_FREQ_192KHZ = 192,
+ CODEC_SAMPLING_FREQ_MAXLIMIT = 193
+ } t_codec_sample_frequency;
+
+#define RESET -1
+#define DEFAULT -100
+/***********************************************************/
+/*
+** following stuff is added to compile code without debug print support $kardad$
+*/
+
+#define DBGEXIT(cr)
+#define DBGEXIT0(cr)
+#define DBGEXIT1(cr,ch,p1)
+#define DBGEXIT2(cr,ch,p1,p2)
+#define DBGEXIT3(cr,ch,p1,p2,p3)
+#define DBGEXIT4(cr,ch,p1,p2,p3,p4)
+#define DBGEXIT5(cr,ch,p1,p2,p3,p4,p5)
+#define DBGEXIT6(cr,ch,p1,p2,p3,p4,p5,p6)
+
+#define DBGENTER()
+#define DBGENTER0()
+#define DBGENTER1(ch,p1)
+#define DBGENTER2(ch,p1,p2)
+#define DBGENTER3(ch,p1,p2,p3)
+#define DBGENTER4(ch,p1,p2,p3,p4)
+#define DBGENTER5(ch,p1,p2,p3,p4,p5)
+#define DBGENTER6(ch,p1,p2,p3,p4,p5,p6)
+
+#define DBGPRINT(dbg_level,dbg_string)
+#define DBGPRINTHEX(dbg_level,dbg_string,uint32)
+#define DBGPRINTDEC(dbg_level,dbg_string,uint32)
+/***********************************************************/
+
+#ifdef __cplusplus
+} /* allow C++ to use these headers */
+#endif /* __cplusplus */
+#endif /* _AB8500_CODEC_H_ */
+/* End of file ab8500_codec.h*/
diff --git a/arch/arm/mach-ux500/include/mach/ab8500_codec_p.h b/arch/arm/mach-ux500/include/mach/ab8500_codec_p.h
new file mode 100644
index 00000000000..847a1729e44
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ab8500_codec_p.h
@@ -0,0 +1,3082 @@
+/*****************************************************************************/
+/**
+* © ST-Ericsson, 2009 - All rights reserved
+* Reproduction and Communication of this document is strictly prohibited
+* unless specifically authorized in writing by ST-Ericsson
+ *
+* \brief Private Header file for AB8500 CODEC
+* \author ST-Ericsson
+ */
+/*****************************************************************************/
+
+#ifndef _AB8500_CODECP_H_
+#define _AB8500_CODECP_H_
+
+/*----------------------------------------------------------------------------
+ * Includes
+ *---------------------------------------------------------------------------*/
+#include "hcl_defs.h"
+
+#define AB8500_CODEC_HCL_VERSION_ID 2
+#define AB8500_CODEC_HCL_MAJOR_ID 0
+#define AB8500_CODEC_HCL_MINOR_ID 0
+
+#define AB8500_CODEC_MASK_ONE_BIT 0x1UL
+#define AB8500_CODEC_MASK_TWO_BITS 0x3UL
+#define AB8500_CODEC_MASK_THREE_BITS 0x7UL
+#define AB8500_CODEC_MASK_FOUR_BITS 0xFUL
+#define AB8500_CODEC_MASK_FIVE_BITS 0x1FUL
+#define AB8500_CODEC_MASK_SIX_BITS 0x3FUL
+#define AB8500_CODEC_MASK_SEVEN_BITS 0x7FUL
+#define AB8500_CODEC_MASK_EIGHT_BITS 0xFFUL
+
+#define AB8500_CODEC_WRITE_BITS(reg, val, bit_nb, pos) (reg) = ((t_uint8) ((((reg) & (~(bit_nb << pos))) | (((val) & bit_nb) << pos))))
+
+#define AB8500_CODEC_BLOCK 0x0D
+
+#define AB8500_CODEC_MASK_TWO_MS_BITS 0xC0UL
+#define AB8500_CODEC_MASK_SIX_LS_BITS 0x3FUL
+
+/* Genepi AudioCodec Control Registers */
+
+#define AB8500_CODEC_CR0 0x00
+#define AB8500_CODEC_CR1 0x01
+#define AB8500_CODEC_CR2 0x02
+#define AB8500_CODEC_CR3 0x03
+#define AB8500_CODEC_CR4 0x04
+#define AB8500_CODEC_CR5 0x05
+#define AB8500_CODEC_CR6 0x06
+#define AB8500_CODEC_CR7 0x07
+#define AB8500_CODEC_CR8 0x08
+#define AB8500_CODEC_CR9 0x09
+#define AB8500_CODEC_CR10 0x0A
+#define AB8500_CODEC_CR11 0x0B
+#define AB8500_CODEC_CR12 0x0C
+#define AB8500_CODEC_CR13 0x0D
+#define AB8500_CODEC_CR14 0x0E
+#define AB8500_CODEC_CR15 0x0F
+#define AB8500_CODEC_CR16 0x10
+#define AB8500_CODEC_CR17 0x11
+#define AB8500_CODEC_CR18 0x12
+#define AB8500_CODEC_CR19 0x13
+#define AB8500_CODEC_CR20 0x14
+#define AB8500_CODEC_CR21 0x15
+#define AB8500_CODEC_CR22 0x16
+#define AB8500_CODEC_CR23 0x17
+#define AB8500_CODEC_CR24 0x18
+#define AB8500_CODEC_CR25 0x19
+#define AB8500_CODEC_CR26 0x1A
+#define AB8500_CODEC_CR27 0x1B
+#define AB8500_CODEC_CR28 0x1C
+#define AB8500_CODEC_CR29 0x1D
+#define AB8500_CODEC_CR30 0x1E
+#define AB8500_CODEC_CR31 0x1F
+#define AB8500_CODEC_CR32 0x20
+#define AB8500_CODEC_CR33 0x21
+#define AB8500_CODEC_CR34 0x22
+#define AB8500_CODEC_CR35 0x23
+#define AB8500_CODEC_CR36 0x24
+#define AB8500_CODEC_CR37 0x25
+#define AB8500_CODEC_CR38 0x26
+#define AB8500_CODEC_CR39 0x27
+#define AB8500_CODEC_CR40 0x28
+#define AB8500_CODEC_CR41 0x29
+#define AB8500_CODEC_CR42 0x2A
+#define AB8500_CODEC_CR43 0x2B
+#define AB8500_CODEC_CR44 0x2C
+#define AB8500_CODEC_CR45 0x2D
+#define AB8500_CODEC_CR46 0x2E
+#define AB8500_CODEC_CR47 0x2F
+#define AB8500_CODEC_CR48 0x30
+#define AB8500_CODEC_CR49 0x31
+#define AB8500_CODEC_CR50 0x32
+#define AB8500_CODEC_CR51 0x33
+#define AB8500_CODEC_CR52 0x34
+#define AB8500_CODEC_CR53 0x35
+#define AB8500_CODEC_CR54 0x36
+#define AB8500_CODEC_CR55 0x37
+#define AB8500_CODEC_CR56 0x38
+#define AB8500_CODEC_CR57 0x39
+#define AB8500_CODEC_CR58 0x3A
+#define AB8500_CODEC_CR59 0x3B
+#define AB8500_CODEC_CR60 0x3C
+#define AB8500_CODEC_CR61 0x3D
+#define AB8500_CODEC_CR62 0x3E
+#define AB8500_CODEC_CR63 0x3F
+#define AB8500_CODEC_CR64 0x40
+#define AB8500_CODEC_CR65 0x41
+#define AB8500_CODEC_CR66 0x42
+#define AB8500_CODEC_CR67 0x43
+#define AB8500_CODEC_CR68 0x44
+#define AB8500_CODEC_CR69 0x45
+#define AB8500_CODEC_CR70 0x46
+#define AB8500_CODEC_CR71 0x47
+#define AB8500_CODEC_CR72 0x48
+#define AB8500_CODEC_CR73 0x49
+#define AB8500_CODEC_CR74 0x4A
+#define AB8500_CODEC_CR75 0x4B
+#define AB8500_CODEC_CR76 0x4C
+#define AB8500_CODEC_CR77 0x4D
+#define AB8500_CODEC_CR78 0x4E
+#define AB8500_CODEC_CR79 0x4F
+#define AB8500_CODEC_CR80 0x50
+#define AB8500_CODEC_CR81 0x51
+#define AB8500_CODEC_CR82 0x52
+#define AB8500_CODEC_CR83 0x53
+#define AB8500_CODEC_CR84 0x54
+#define AB8500_CODEC_CR85 0x55
+#define AB8500_CODEC_CR86 0x56
+#define AB8500_CODEC_CR87 0x57
+#define AB8500_CODEC_CR88 0x58
+#define AB8500_CODEC_CR89 0x59
+#define AB8500_CODEC_CR90 0x5A
+#define AB8500_CODEC_CR91 0x5B
+#define AB8500_CODEC_CR92 0x5C
+#define AB8500_CODEC_CR93 0x5D
+#define AB8500_CODEC_CR94 0x5E
+#define AB8500_CODEC_CR95 0x5F
+#define AB8500_CODEC_CR96 0x60
+#define AB8500_CODEC_CR97 0x61
+#define AB8500_CODEC_CR98 0x62
+#define AB8500_CODEC_CR99 0x63
+#define AB8500_CODEC_CR100 0x64
+#define AB8500_CODEC_CR101 0x65
+#define AB8500_CODEC_CR102 0x66
+#define AB8500_CODEC_CR103 0x67
+#define AB8500_CODEC_CR104 0x68
+#define AB8500_CODEC_CR105 0x69
+#define AB8500_CODEC_CR106 0x6A
+#define AB8500_CODEC_CR107 0x6B
+#define AB8500_CODEC_CR108 0x6C
+#define AB8500_CODEC_CR109 0x6D
+
+/* CR0-CR0x0000 */
+#define AB8500_CODEC_CR0_POWERUP 7
+#define AB8500_CODEC_CR0_ENAANA 3
+
+/* CR1-CR0x0001 */
+#define AB8500_CODEC_CR1_SWRESET 7
+
+/* CR2-CR0x0002 */
+#define AB8500_CODEC_CR2_ENAD1 7
+#define AB8500_CODEC_CR2_ENAD2 6
+#define AB8500_CODEC_CR2_ENAD3 5
+#define AB8500_CODEC_CR2_ENAD4 4
+#define AB8500_CODEC_CR2_ENAD5 3
+#define AB8500_CODEC_CR2_ENAD6 2
+
+/* CR3-CR0x0003 */
+#define AB8500_CODEC_CR3_ENDA1 7
+#define AB8500_CODEC_CR3_ENDA2 6
+#define AB8500_CODEC_CR3_ENDA3 5
+#define AB8500_CODEC_CR3_ENDA4 4
+#define AB8500_CODEC_CR3_ENDA5 3
+#define AB8500_CODEC_CR3_ENDA6 2
+
+/* CR4-CR0x0004 */
+#define AB8500_CODEC_CR4_LOWPOWHS 7
+#define AB8500_CODEC_CR4_LOWPOWDACHS 5
+#define AB8500_CODEC_CR4_LOWPOWEAR 4
+#define AB8500_CODEC_CR4_EAR_SEL_CM 2
+#define AB8500_CODEC_CR4_HS_HP_DIS 1
+#define AB8500_CODEC_CR4_EAR_HP_DIS 0
+
+/* CR5-CR0x0005 */
+#define AB8500_CODEC_CR5_ENMIC1 7
+#define AB8500_CODEC_CR5_ENMIC2 6
+#define AB8500_CODEC_CR5_ENLINL 5
+#define AB8500_CODEC_CR5_ENLINR 4
+#define AB8500_CODEC_CR5_MUTMIC1 3
+#define AB8500_CODEC_CR5_MUTMIC2 2
+#define AB8500_CODEC_CR5_MUTELINL 1
+#define AB8500_CODEC_CR5_MUTELINR 0
+
+/* CR6-CR0x0006 */
+#define AB8500_CODEC_CR6_ENDMIC1 7
+#define AB8500_CODEC_CR6_ENDMIC2 6
+#define AB8500_CODEC_CR6_ENDMIC3 5
+#define AB8500_CODEC_CR6_ENDMIC4 4
+#define AB8500_CODEC_CR6_ENDMIC5 3
+#define AB8500_CODEC_CR6_ENDMIC6 2
+
+/* CR7-CR0x0007 */
+#define AB8500_CODEC_CR7_MIC1SEL 7
+#define AB8500_CODEC_CR7_LINRSEL 6
+#define AB8500_CODEC_CR7_ENDRVHSL 5
+#define AB8500_CODEC_CR7_ENDRVHSR 4
+#define AB8500_CODEC_CR7_ENADCMIC 2
+#define AB8500_CODEC_CR7_ENADCLINL 1
+#define AB8500_CODEC_CR7_ENADCLINR 0
+
+/* CR8-CR0x0008 */
+#define AB8500_CODEC_CR8_CP_DIS_PLDWN 7
+#define AB8500_CODEC_CR8_ENEAR 6
+#define AB8500_CODEC_CR8_ENHSL 5
+#define AB8500_CODEC_CR8_ENHSR 4
+#define AB8500_CODEC_CR8_ENHFL 3
+#define AB8500_CODEC_CR8_ENHFR 2
+#define AB8500_CODEC_CR8_ENVIBL 1
+#define AB8500_CODEC_CR8_ENVIBR 0
+
+/* CR9-CR0x0009 */
+#define AB8500_CODEC_CR9_ENADACEAR 6
+#define AB8500_CODEC_CR9_ENADACHSL 5
+#define AB8500_CODEC_CR9_ENADACHSR 4
+#define AB8500_CODEC_CR9_ENADACHFL 3
+#define AB8500_CODEC_CR9_ENADACHFR 2
+#define AB8500_CODEC_CR9_ENADACVIBL 1
+#define AB8500_CODEC_CR9_ENADACVIBR 0
+
+/* CR10-CR0x000A */
+#define AB8500_CODEC_CR10_MUTEEAR 6
+#define AB8500_CODEC_CR10_MUTEHSL 5
+#define AB8500_CODEC_CR10_MUTEHSR 4
+#define AB8500_CODEC_CR10_MUTEHFL 3
+#define AB8500_CODEC_CR10_MUTEHFR 2
+#define AB8500_CODEC_CR10_MUTEVIBL 1
+#define AB8500_CODEC_CR10_MUTEVIBR 0
+
+/* CR11-CR0x000B */
+#define AB8500_CODEC_CR11_ENSHORTPWD 7
+#define AB8500_CODEC_CR11_EARSHORTDIS 6
+#define AB8500_CODEC_CR11_HSLSHORTDIS 5
+#define AB8500_CODEC_CR11_HSRSHORTDIS 4
+#define AB8500_CODEC_CR11_HFLSHORTDIS 3
+#define AB8500_CODEC_CR11_HFRSHORTDIS 2
+#define AB8500_CODEC_CR11_VIBLSHORTDIS 1
+#define AB8500_CODEC_CR11_VIBRSHORTDIS 0
+
+/* CR12-CR0x000C */
+#define AB8500_CODEC_CR12_ENCPHS 7
+#define AB8500_CODEC_CR12_HSAUTOTIME 4
+#define AB8500_CODEC_CR12_HSAUTOENSEL 1
+#define AB8500_CODEC_CR12_HSAUTOEN 0
+
+/* CR13-CR0x000D */
+#define AB8500_CODEC_CR13_ENVDET_HTHRESH 4
+#define AB8500_CODEC_CR13_ENVDET_LTHRESH 0
+
+/* CR14-CR0x000E */
+#define AB8500_CODEC_CR14_SMPSLVEN 7
+#define AB8500_CODEC_CR14_ENVDETSMPSEN 6
+#define AB8500_CODEC_CR14_CPLVEN 5
+#define AB8500_CODEC_CR14_ENVDETCPEN 4
+#define AB8500_CODEC_CR14_ENVDET_TIME 0
+
+/* CR15-CR0x000F */
+#define AB8500_CODEC_CR15_PWMTOVIBL 7
+#define AB8500_CODEC_CR15_PWMTOVIBR 6
+#define AB8500_CODEC_CR15_PWMLCTRL 5
+#define AB8500_CODEC_CR15_PWMRCTRL 4
+#define AB8500_CODEC_CR15_PWMNLCTRL 3
+#define AB8500_CODEC_CR15_PWMPLCTRL 2
+#define AB8500_CODEC_CR15_PWMNRCTRL 1
+#define AB8500_CODEC_CR15_PWMPRCTRL 0
+
+/* CR16-CR0x0010 */
+#define AB8500_CODEC_CR16_PWMNLPOL 7
+#define AB8500_CODEC_CR16_PWMNLDUTYCYCLE 0
+
+/* CR17-CR0x0011 */
+#define AB8500_CODEC_CR17_PWMPLPOL 7
+#define AB8500_CODEC_CR17_PWMLPDUTYCYCLE 0
+
+/* CR18-CR0x0012 */
+#define AB8500_CODEC_CR18_PWMNRPOL 7
+#define AB8500_CODEC_CR18_PWMNRDUTYCYCLE 0
+
+/* CR19-CR0x0013 */
+#define AB8500_CODEC_CR19_PWMPRPOL 7
+#define AB8500_CODEC_CR19_PWMRPDUTYCYCLE 0
+
+/* CR20-CR0x0014 */
+#define AB8500_CODEC_CR20_EN_SE_MIC1 7
+#define AB8500_CODEC_CR20_MIC1_GAIN 0
+
+/* CR21-CR0x0015 */
+#define AB8500_CODEC_CR21_EN_SE_MIC2 7
+#define AB8500_CODEC_CR21_MIC2_GAIN 0
+
+/* CR22-CR0x0016 */
+#define AB8500_CODEC_CR22_HSL_GAIN 5
+#define AB8500_CODEC_CR22_LINL_GAIN 0
+
+/* CR23-CR0x0017 */
+#define AB8500_CODEC_CR23_HSR_GAIN 5
+#define AB8500_CODEC_CR23_LINR_GAIN 0
+
+/* CR24-CR0x0018 */
+#define AB8500_CODEC_CR24_LINTOHSL_GAIN 0
+
+/* CR25-CR0x0019 */
+#define AB8500_CODEC_CR25_LINTOHSR_GAIN 0
+
+/* CR26-CR0x001A */
+#define AB8500_CODEC_CR26_AD1NH 7
+#define AB8500_CODEC_CR26_AD2NH 6
+#define AB8500_CODEC_CR26_AD3NH 5
+#define AB8500_CODEC_CR26_AD4NH 4
+#define AB8500_CODEC_CR26_AD1_VOICE 3
+#define AB8500_CODEC_CR26_AD2_VOICE 2
+#define AB8500_CODEC_CR26_AD3_VOICE 1
+#define AB8500_CODEC_CR26_AD4_VOICE 0
+
+/* CR27-CR0x001B */
+#define AB8500_CODEC_CR27_EN_MASTGEN 7
+#define AB8500_CODEC_CR27_IF1_BITCLK_OSR 5
+#define AB8500_CODEC_CR27_ENFS_BITCLK1 4
+#define AB8500_CODEC_CR27_IF0_BITCLK_OSR 1
+#define AB8500_CODEC_CR27_ENFS_BITCLK0 0
+
+/* CR28-CR0x001C */
+#define AB8500_CODEC_CR28_FSYNC0P 6
+#define AB8500_CODEC_CR28_BITCLK0P 5
+#define AB8500_CODEC_CR28_IF0DEL 4
+#define AB8500_CODEC_CR28_IF0FORMAT 2
+#define AB8500_CODEC_CR28_IF0WL 0
+
+/* CR29-CR0x001D */
+#define AB8500_CODEC_CR29_IF0DATOIF1AD 7
+#define AB8500_CODEC_CR29_IF0CKTOIF1CK 6
+#define AB8500_CODEC_CR29_IF1MASTER 5
+#define AB8500_CODEC_CR29_IF1DATOIF0AD 3
+#define AB8500_CODEC_CR29_IF1CKTOIF0CK 2
+#define AB8500_CODEC_CR29_IF0MASTER 1
+#define AB8500_CODEC_CR29_IF0BFIFOEN 0
+
+/* CR30-CR0x001E */
+#define AB8500_CODEC_CR30_FSYNC1P 6
+#define AB8500_CODEC_CR30_BITCLK1P 5
+#define AB8500_CODEC_CR30_IF1DEL 4
+#define AB8500_CODEC_CR30_IF1FORMAT 2
+#define AB8500_CODEC_CR30_IF1WL 0
+
+/* CR31-CR0x001F */
+#define AB8500_CODEC_CR31_ADOTOSLOT1 4
+#define AB8500_CODEC_CR31_ADOTOSLOT0 0
+
+/* CR32-CR0x0020 */
+#define AB8500_CODEC_CR32_ADOTOSLOT3 4
+#define AB8500_CODEC_CR32_ADOTOSLOT2 0
+
+/* CR33-CR0x0021 */
+#define AB8500_CODEC_CR33_ADOTOSLOT5 4
+#define AB8500_CODEC_CR33_ADOTOSLOT4 0
+
+/* CR34-CR0x0022 */
+#define AB8500_CODEC_CR34_ADOTOSLOT7 4
+#define AB8500_CODEC_CR34_ADOTOSLOT6 0
+
+/* CR35-CR0x0023 */
+#define AB8500_CODEC_CR35_ADOTOSLOT9 4
+#define AB8500_CODEC_CR35_ADOTOSLOT8 0
+
+/* CR36-CR0x0024 */
+#define AB8500_CODEC_CR36_ADOTOSLOT11 4
+#define AB8500_CODEC_CR36_ADOTOSLOT10 0
+
+/* CR37-CR0x0025 */
+#define AB8500_CODEC_CR37_ADOTOSLOT13 4
+#define AB8500_CODEC_CR37_ADOTOSLOT12 0
+
+/* CR38-CR0x0026 */
+#define AB8500_CODEC_CR38_ADOTOSLOT15 4
+#define AB8500_CODEC_CR38_ADOTOSLOT14 0
+
+/* CR39-CR0x0027 */
+#define AB8500_CODEC_CR39_ADOTOSLOT17 4
+#define AB8500_CODEC_CR39_ADOTOSLOT16 0
+
+/* CR40-CR0x0028 */
+#define AB8500_CODEC_CR40_ADOTOSLOT19 4
+#define AB8500_CODEC_CR40_ADOTOSLOT18 0
+
+/* CR41-CR0x0029 */
+#define AB8500_CODEC_CR41_ADOTOSLOT21 4
+#define AB8500_CODEC_CR41_ADOTOSLOT20 0
+
+/* CR42-CR0x002A */
+#define AB8500_CODEC_CR42_ADOTOSLOT23 4
+#define AB8500_CODEC_CR42_ADOTOSLOT22 0
+
+/* CR43-CR0x002B */
+#define AB8500_CODEC_CR43_ADOTOSLOT25 4
+#define AB8500_CODEC_CR43_ADOTOSLOT24 0
+
+/* CR44-CR0x002C */
+#define AB8500_CODEC_CR44_ADOTOSLOT27 4
+#define AB8500_CODEC_CR44_ADOTOSLOT26 0
+
+/* CR45-CR0x002D */
+#define AB8500_CODEC_CR45_ADOTOSLOT29 4
+#define AB8500_CODEC_CR45_ADOTOSLOT28 0
+
+/* CR46-CR0x002E */
+#define AB8500_CODEC_CR46_ADOTOSLOT31 4
+#define AB8500_CODEC_CR46_ADOTOSLOT30 0
+
+/* CR47-CR0x002F */
+#define AB8500_CODEC_CR47_HIZ_SL7 7
+#define AB8500_CODEC_CR47_HIZ_SL6 6
+#define AB8500_CODEC_CR47_HIZ_SL5 5
+#define AB8500_CODEC_CR47_HIZ_SL4 4
+#define AB8500_CODEC_CR47_HIZ_SL3 3
+#define AB8500_CODEC_CR47_HIZ_SL2 2
+#define AB8500_CODEC_CR47_HIZ_SL1 1
+#define AB8500_CODEC_CR47_HIZ_SL0 0
+
+/* CR48-CR0x0030 */
+#define AB8500_CODEC_CR48_HIZ_SL15 7
+#define AB8500_CODEC_CR48_HIZ_SL14 6
+#define AB8500_CODEC_CR48_HIZ_SL13 5
+#define AB8500_CODEC_CR48_HIZ_SL12 4
+#define AB8500_CODEC_CR48_HIZ_SL11 3
+#define AB8500_CODEC_CR48_HIZ_SL10 2
+#define AB8500_CODEC_CR48_HIZ_SL9 1
+#define AB8500_CODEC_CR48_HIZ_SL8 0
+
+/* CR49-CR0x0031 */
+#define AB8500_CODEC_CR49_HIZ_SL23 7
+#define AB8500_CODEC_CR49_HIZ_SL22 6
+#define AB8500_CODEC_CR49_HIZ_SL21 5
+#define AB8500_CODEC_CR49_HIZ_SL20 4
+#define AB8500_CODEC_CR49_HIZ_SL19 3
+#define AB8500_CODEC_CR49_HIZ_SL18 2
+#define AB8500_CODEC_CR49_HIZ_SL17 1
+#define AB8500_CODEC_CR49_HIZ_SL16 0
+
+/* CR50-CR0x0032 */
+#define AB8500_CODEC_CR50_HIZ_SL31 7
+#define AB8500_CODEC_CR50_HIZ_SL30 6
+#define AB8500_CODEC_CR50_HIZ_SL29 5
+#define AB8500_CODEC_CR50_HIZ_SL28 4
+#define AB8500_CODEC_CR50_HIZ_SL27 3
+#define AB8500_CODEC_CR50_HIZ_SL26 2
+#define AB8500_CODEC_CR50_HIZ_SL25 1
+#define AB8500_CODEC_CR50_HIZ_SL24 0
+
+/* CR51-CR0x0033 */
+#define AB8500_CODEC_CR51_DA12_VOICE 7
+#define AB8500_CODEC_CR51_SLDAI1TOSLADO1 5
+#define AB8500_CODEC_CR51_SLTODA1 0
+
+/* CR52-CR0x0034 */
+#define AB8500_CODEC_CR52_SLDAI1TOSLADO2 5
+#define AB8500_CODEC_CR52_SLTODA2 0
+
+/* CR53-CR0x0035 */
+#define AB8500_CODEC_CR53_DA34_VOICE 7
+#define AB8500_CODEC_CR53_SLDAI1TOSLADO3 5
+#define AB8500_CODEC_CR53_SLTODA3 0
+
+/* CR54-CR0x0036 */
+#define AB8500_CODEC_CR54_SLDAI1TOSLADO4 5
+#define AB8500_CODEC_CR54_SLTODA4 0
+
+/* CR55-CR0x0037 */
+#define AB8500_CODEC_CR55_DA56_VOICE 7
+#define AB8500_CODEC_CR55_SLDAI1TOSLADO5 5
+#define AB8500_CODEC_CR55_SLTODA5 0
+
+/* CR56-CR0x0038 */
+#define AB8500_CODEC_CR56_SLDAI1TOSLADO6 5
+#define AB8500_CODEC_CR56_SLTODA6 0
+
+/* CR57-CR0x0039 */
+#define AB8500_CODEC_CR57_BFIFULL_MSK 6
+#define AB8500_CODEC_CR57_BFIEMPT_MSK 5
+#define AB8500_CODEC_CR57_DACHAN_MSK 4
+#define AB8500_CODEC_CR57_GAIN_MSK 3
+#define AB8500_CODEC_CR57_DSPAD_MSK 2
+#define AB8500_CODEC_CR57_DSPDA_MSK 1
+#define AB8500_CODEC_CR57_STFIR_MSK 0
+
+/* CR58-CR0x003A */
+#define AB8500_CODEC_CR58_BFIFULL_EV 6
+#define AB8500_CODEC_CR58_BFIEMPT_EV 5
+#define AB8500_CODEC_CR58_DACHAN_EV 4
+#define AB8500_CODEC_CR58_GAIN_EV 3
+#define AB8500_CODEC_CR58_DSPAD_EV 2
+#define AB8500_CODEC_CR58_DSPDA_EV 1
+#define AB8500_CODEC_CR58_STFIR_EV 0
+
+/* CR59-CR0x003B */
+#define AB8500_CODEC_CR59_VSSREADY_MSK 7
+#define AB8500_CODEC_CR59_SHRTVIBL_MSK 6
+#define AB8500_CODEC_CR59_SHRTVIBR_MSK 5
+#define AB8500_CODEC_CR59_SHRTHFL_MSK 4
+#define AB8500_CODEC_CR59_SHRTHFR_MSK 3
+#define AB8500_CODEC_CR59_SHRTHSL_MSK 2
+#define AB8500_CODEC_CR59_SHRTHSR_MSK 1
+#define AB8500_CODEC_CR59_SHRTEAR_MSK 0
+
+/* CR60-CR0x003C */
+#define AB8500_CODEC_CR60_VSSREADY_EV 7
+#define AB8500_CODEC_CR60_SHRTVIBL_EV 6
+#define AB8500_CODEC_CR60_SHRTVIBR_EV 5
+#define AB8500_CODEC_CR60_SHRTHFL_EV 4
+#define AB8500_CODEC_CR60_SHRTHFR_EV 3
+#define AB8500_CODEC_CR60_SHRTHSL_EV 2
+#define AB8500_CODEC_CR60_SHRTHSR_EV 1
+#define AB8500_CODEC_CR60_SHRTEAR_EV 0
+
+/* CR61-CR0x003D */
+#define AB8500_CODEC_CR61_REVISION 2
+#define AB8500_CODEC_CR61_FADE_SPEED 0
+
+/* CR62-CR0x003E */
+#define AB8500_CODEC_CR62_DMIC1SINC3 5
+#define AB8500_CODEC_CR62_DMIC2SINC3 4
+#define AB8500_CODEC_CR62_DMIC3SINC3 3
+#define AB8500_CODEC_CR62_DMIC4SINC3 2
+#define AB8500_CODEC_CR62_DMIC5SINC3 1
+#define AB8500_CODEC_CR62_DMIC6SINC3 0
+
+/* CR63-CR0x003F */
+#define AB8500_CODEC_CR63_DATOHSLEN 7
+#define AB8500_CODEC_CR63_DATOHSREN 6
+#define AB8500_CODEC_CR63_AD1SEL 5
+#define AB8500_CODEC_CR63_AD2SEL 4
+#define AB8500_CODEC_CR63_AD3SEL 3
+#define AB8500_CODEC_CR63_AD5SEL 2
+#define AB8500_CODEC_CR63_AD6SEL 1
+#define AB8500_CODEC_CR63_ANCSEL 0
+
+/* CR64-CR0x0040 */
+#define AB8500_CODEC_CR64_DATOHFREN 7
+#define AB8500_CODEC_CR64_DATOHFLEN 6
+#define AB8500_CODEC_CR64_HFRSEL 5
+#define AB8500_CODEC_CR64_HFLSEL 4
+#define AB8500_CODEC_CR64_STFIR1SEL 2
+#define AB8500_CODEC_CR64_STFIR2SEL 0
+
+/* CR65-CR0x0041 */
+#define AB8500_CODEC_CR65_FADEDIS_AD1 6
+#define AB8500_CODEC_CR65_AD1GAIN 0
+
+/* CR66-CR0x0042 */
+#define AB8500_CODEC_CR66_FADEDIS_AD2 6
+#define AB8500_CODEC_CR66_AD2GAIN 0
+
+/* CR67-CR0x0043 */
+#define AB8500_CODEC_CR67_FADEDIS_AD3 6
+#define AB8500_CODEC_CR67_AD3GAIN 0
+
+/* CR68-CR0x0044 */
+#define AB8500_CODEC_CR68_FADEDIS_AD4 6
+#define AB8500_CODEC_CR68_AD4GAIN 0
+
+/* CR69-CR0x0045 */
+#define AB8500_CODEC_CR69_FADEDIS_AD5 6
+#define AB8500_CODEC_CR69_AD5GAIN 0
+
+/* CR70-CR0x0046 */
+#define AB8500_CODEC_CR70_FADEDIS_AD6 6
+#define AB8500_CODEC_CR70_AD6GAIN 0
+
+/* CR71-CR0x0047 */
+#define AB8500_CODEC_CR71_FADEDIS_DA1 6
+#define AB8500_CODEC_CR71_DA1GAIN 0
+
+/* CR72-CR0x0048 */
+#define AB8500_CODEC_CR72_FADEDIS_DA2 6
+#define AB8500_CODEC_CR72_DA2GAIN 0
+
+/* CR73-CR0x0049 */
+#define AB8500_CODEC_CR73_FADEDIS_DA3 6
+#define AB8500_CODEC_CR73_DA3GAIN 0
+
+/* CR74-CR0x004A */
+#define AB8500_CODEC_CR74_FADEDIS_DA4 6
+#define AB8500_CODEC_CR74_DA4GAIN 0
+
+/* CR75-CR0x004B */
+#define AB8500_CODEC_CR75_FADEDIS_DA5 6
+#define AB8500_CODEC_CR75_DA5GAIN 0
+
+/* CR76-CR0x004C */
+#define AB8500_CODEC_CR76_FADEDIS_DA6 6
+#define AB8500_CODEC_CR76_DA6GAIN 0
+
+/* CR77-CR0x004D */
+#define AB8500_CODEC_CR77_FADEDIS_AD1L 6
+#define AB8500_CODEC_CR77_AD1LBGAIN 0
+
+/* CR78-CR0x004E */
+#define AB8500_CODEC_CR78_FADEDIS_AD2L 6
+#define AB8500_CODEC_CR78_AD2LBGAIN 0
+
+/* CR79-CR0x004F */
+#define AB8500_CODEC_CR79_HSSINC1 7
+#define AB8500_CODEC_CR79_FADEDIS_HSL 4
+#define AB8500_CODEC_CR79_HSLDGAIN 0
+
+/* CR80-CR0x0050 */
+#define AB8500_CODEC_CR80_FADEDIS_HSR 4
+#define AB8500_CODEC_CR80_HSRDGAIN 0
+
+/* CR81-CR0x0051 */
+#define AB8500_CODEC_CR81_STFIR1GAIN 0
+
+/* CR82-CR0x0052 */
+#define AB8500_CODEC_CR82_STFIR2GAIN 0
+
+/* CR83-CR0x0053 */
+#define AB8500_CODEC_CR83_ENANC 2
+#define AB8500_CODEC_CR83_ANCIIRINIT 1
+#define AB8500_CODEC_CR83_ANCFIRUPDATE 0
+
+/* CR84-CR0x0054 */
+#define AB8500_CODEC_CR84_ANCINSHIFT 0
+
+/* CR85-CR0x0055 */
+#define AB8500_CODEC_CR85_ANCFIROUTSHIFT 0
+
+/* CR86-CR0x0056 */
+#define AB8500_CODEC_CR86_ANCSHIFTOUT 0
+
+/* CR87-CR0x0057 */
+#define AB8500_CODEC_CR87_ANCFIRCOEFF_MSB 0
+
+/* CR88-CR0x0058 */
+#define AB8500_CODEC_CR88_ANCFIRCOEFF_LSB 0
+
+/* CR89-CR0x0059 */
+#define AB8500_CODEC_CR89_ANCIIRCOEFF_MSB 0
+
+/* CR90-CR0x005A */
+#define AB8500_CODEC_CR90_ANCIIRCOEFF_LSB 0
+
+/* CR91-CR0x005B */
+#define AB8500_CODEC_CR91_ANCWARPDEL_MSB 0
+
+/* CR92-CR0x005C */
+#define AB8500_CODEC_CR92_ANCWARPDEL_LSB 0
+
+/* CR93-CR0x005D */
+#define AB8500_CODEC_CR93_ANCFIRPEAK_MSB 0
+
+/* CR94-CR0x005E */
+#define AB8500_CODEC_CR94_ANCFIRPEAK_LSB 0
+
+/* CR95-CR0x005F */
+#define AB8500_CODEC_CR95_ANCIIRPEAK_MSB 0
+
+/* CR96-CR0x0060 */
+#define AB8500_CODEC_CR96_ANCIIRPEAK_LSB 0
+
+/* CR97-CR0x0061 */
+#define AB8500_CODEC_CR97_STFIR_SET 7
+#define AB8500_CODEC_CR97_STFIR_ADDR 0
+
+/* CR98-CR0x0062 */
+#define AB8500_CODEC_CR98_STFIR_COEFF_MSB 0
+
+/* CR99-CR0x0063 */
+#define AB8500_CODEC_CR99_STFIR_COEFF_LSB 0
+
+/* CR100-CR0x0064 */
+#define AB8500_CODEC_CR100_ENSTFIRS 2
+#define AB8500_CODEC_CR100_STFIRSTOIF1 1
+#define AB8500_CODEC_CR100_STFIR_BUSY 0
+
+/* CR101-CR0x0065 */
+#define AB8500_CODEC_CR101_PARLHF 7
+#define AB8500_CODEC_CR101_PARLVIB 6
+#define AB8500_CODEC_CR101_CLASSDVIBLSWAPEN 3
+#define AB8500_CODEC_CR101_CLASSDVIBRSWAPEN 2
+#define AB8500_CODEC_CR101_CLASSDHFLSWAPEN 1
+#define AB8500_CODEC_CR101_CLASSDHFRSWAPEN 0
+
+/* CR102-CR0x0066 */
+#define AB8500_CODEC_CR102_CLASSD_FIRBYP 4
+#define AB8500_CODEC_CR102_CLASSD_HIGHVOLEN 0
+
+/* CR103-CR0x0067 */
+#define AB8500_CODEC_CR103_CLASSD_DITHERHPGAIN 4
+#define AB8500_CODEC_CR103_CLASSD_DITHERWGAIN 0
+
+/* CR104-CR0x0068 */
+#define AB8500_CODEC_CR104_BFIFOINT 0
+
+/* CR105-CR0x0069 */
+#define AB8500_CODEC_CR105_BFIFOTX 0
+
+/* CR106-CR0x006A */
+#define AB8500_CODEC_CR106_BFIFOFSEXT 4
+#define AB8500_CODEC_CR106_BFIFOMSK 2
+#define AB8500_CODEC_CR106_BFIFOMSTR 1
+#define AB8500_CODEC_CR106_BFIFOSTRT 0
+
+/* CR107-CR0x006B */
+#define AB8500_CODEC_CR107_BFIFOSAMPNR 0
+
+/* CR108-CR0x006C */
+#define AB8500_CODEC_CR108_BFIFOWAKEUP 0
+
+/* CR109-CR0x006D */
+#define AB8500_CODEC_CR109_BFIFOSAMPLES 0
+
+/* For SetVolume API*/
+#define AB8500_CODEC_MAX_VOLUME 100
+
+/* Analog MIC1 & MIC2 */
+#define AB8500_CODEC_MIC_VOLUME_MAX 31
+#define AB8500_CODEC_MIC_VOLUME_MEDIUM 15
+#define AB8500_CODEC_MIC_VOLUME_MIN 0
+
+/* Line-in */
+#define AB8500_CODEC_LINEIN_VOLUME_MAX 31
+#define AB8500_CODEC_LINEIN_VOLUME_MEDIUM 15
+#define AB8500_CODEC_LINEIN_VOLUME_MIN 0
+
+/* HeadSet */
+#define AB8500_CODEC_HEADSET_VOLUME_MAX 0
+#define AB8500_CODEC_HEADSET_VOLUME_MEDIUM 3
+#define AB8500_CODEC_HEADSET_VOLUME_MIN 7
+
+/* HeadSet Digital */
+#define AB8500_CODEC_HEADSET_D_VOLUME_MAX 0
+#define AB8500_CODEC_HEADSET_D_VOLUME_MEDIUM 7
+#define AB8500_CODEC_HEADSET_D_VOLUME_MIN 15
+#define AB8500_CODEC_HEADSET_D_VOLUME_0DB 8
+
+/* Digital AD Path */
+#define AB8500_CODEC_AD_D_VOLUME_MAX 0
+#define AB8500_CODEC_AD_D_VOLUME_MEDIUM 31
+#define AB8500_CODEC_AD_D_VOLUME_MIN 63
+
+/* Digital DA Path */
+#define AB8500_CODEC_DA_D_VOLUME_MAX 0
+#define AB8500_CODEC_DA_D_VOLUME_MEDIUM 31
+#define AB8500_CODEC_DA_D_VOLUME_MIN 63
+
+/* EarPiece Digital */
+#define AB8500_CODEC_EARPIECE_D_VOLUME_MAX 0
+#define AB8500_CODEC_EARPIECE_D_VOLUME_MEDIUM 7
+#define AB8500_CODEC_EARPIECE_D_VOLUME_MIN 15
+
+/* AD1 loopback to HFL & HFR Digital */
+#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MAX 0
+#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MEDIUM 31
+#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MIN 63
+
+/* Line-in to HSL & HSR */
+#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MAX 0
+#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MEDIUM 9
+#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN 18
+#define AB8500_CODEC_LINEIN_TO_HS_L_R_LOOP_OPEN 19
+
+/* Vibrator */
+#define AB8500_CODEC_VIBRATOR_VOLUME_MAX 100
+#define AB8500_CODEC_VIBRATOR_VOLUME_MEDIUM 50
+#define AB8500_CODEC_VIBRATOR_VOLUME_MIN 0
+
+/* CR0 - 7 */
+typedef enum {
+ AB8500_CODEC_CR0_POWERUP_OFF,
+ AB8500_CODEC_CR0_POWERUP_ON
+} t_ab8500_codec_cr0_powerup;
+
+/* CR0 - 3 */
+typedef enum {
+ AB8500_CODEC_CR0_ENAANA_OFF,
+ AB8500_CODEC_CR0_ENAANA_ON
+} t_ab8500_codec_cr0_enaana;
+
+/* CR1 - 7 */
+typedef enum {
+ AB8500_CODEC_CR1_SWRESET_DISABLED,
+ AB8500_CODEC_CR1_SWRESET_ENABLED
+} t_ab8500_codec_cr1_swreset;
+
+/* CR2 - 7 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD1_DISABLED,
+ AB8500_CODEC_CR2_ENAD1_ENABLED
+} t_ab8500_codec_cr2_enad1;
+
+/* CR2 - 6 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD2_DISABLED,
+ AB8500_CODEC_CR2_ENAD2_ENABLED
+} t_ab8500_codec_cr2_enad2;
+
+/* CR2 - 5 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD3_DISABLED,
+ AB8500_CODEC_CR2_ENAD3_ENABLED
+} t_ab8500_codec_cr2_enad3;
+
+/* CR2 - 4 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD4_DISABLED,
+ AB8500_CODEC_CR2_ENAD4_ENABLED
+} t_ab8500_codec_cr2_enad4;
+
+/* CR2 - 3 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD5_DISABLED,
+ AB8500_CODEC_CR2_ENAD5_ENABLED
+} t_ab8500_codec_cr2_enad5;
+
+/* CR2 - 2 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD6_DISABLED,
+ AB8500_CODEC_CR2_ENAD6_ENABLED
+} t_ab8500_codec_cr2_enad6;
+
+/* CR3 - 7 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA1_DISABLED,
+ AB8500_CODEC_CR3_ENDA1_ENABLED
+} t_ab8500_codec_cr3_enda1;
+
+/* CR3 - 6 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA2_DISABLED,
+ AB8500_CODEC_CR3_ENDA2_ENABLED
+} t_ab8500_codec_cr3_enda2;
+
+/* CR3 - 5 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA3_DISABLED,
+ AB8500_CODEC_CR3_ENDA3_ENABLED
+} t_ab8500_codec_cr3_enda3;
+
+/* CR3 - 4 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA4_DISABLED,
+ AB8500_CODEC_CR3_ENDA4_ENABLED
+} t_ab8500_codec_cr3_enda4;
+
+/* CR3 - 3 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA5_DISABLED,
+ AB8500_CODEC_CR3_ENDA5_ENABLED
+} t_ab8500_codec_cr3_enda5;
+
+/* CR3 - 2 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA6_DISABLED,
+ AB8500_CODEC_CR3_ENDA6_ENABLED
+} t_ab8500_codec_cr3_enda6;
+
+/* CR4 - 7 */
+typedef enum {
+ AB8500_CODEC_CR4_LOWPOWHS_NORMAL,
+ AB8500_CODEC_CR4_LOWPOWHS_LP
+} t_ab8500_codec_cr4_lowpowhs;
+
+/* CR4 - 6:5 */
+typedef enum {
+ AB8500_CODEC_CR4_LOWPOWDACHS_NORMAL,
+ AB8500_CODEC_CR4_LOWPOWDACHS_DRIVERS_LP,
+ AB8500_CODEC_CR4_LOWPOWDACHS_LP,
+ AB8500_CODEC_CR4_LOWPOWDACHS_BOTH_LP
+} t_ab8500_codec_cr4_lowpowdachs;
+
+/* CR4 - 4 */
+typedef enum {
+ AB8500_CODEC_CR4_LOWPOWEAR_NORMAL,
+ AB8500_CODEC_CR4_LOWPOWEAR_LP
+} t_ab8500_codec_cr4_lowpowear;
+
+/* CR4 - 3:2 */
+typedef enum {
+ AB8500_CODEC_CR4_EAR_SEL_CM_0_95V,
+ AB8500_CODEC_CR4_EAR_SEL_CM_1_1V,
+ AB8500_CODEC_CR4_EAR_SEL_CM_1_27V,
+ AB8500_CODEC_CR4_EAR_SEL_CM_1_58V
+} t_ab8500_codec_cr4_ear_sel_cm;
+
+/* CR4 - 1 */
+typedef enum {
+ AB8500_CODEC_CR4_HS_HP_DIS_FILTER_ENABLED,
+ AB8500_CODEC_CR4_HS_HP_DIS_FILTER_DISABLED
+} t_ab8500_codec_cr4_hs_hp_dis;
+
+/* CR4 - 0 */
+typedef enum {
+ AB8500_CODEC_CR4_EAR_HP_DIS_FILTER_ENABLED,
+ AB8500_CODEC_CR4_EAR_HP_DIS_FILTER_DISABLED
+} t_ab8500_codec_cr4_ear_hp_dis;
+
+/* CR5 - 7 */
+typedef enum {
+ AB8500_CODEC_CR5_ENMIC1_DISABLED,
+ AB8500_CODEC_CR5_ENMIC1_ENABLED
+} t_ab8500_codec_cr5_enmic1;
+
+/* CR5 - 6 */
+typedef enum {
+ AB8500_CODEC_CR5_ENMIC2_DISABLED,
+ AB8500_CODEC_CR5_ENMIC2_ENABLED
+} t_ab8500_codec_cr5_enmic2;
+
+/* CR5 - 5 */
+typedef enum {
+ AB8500_CODEC_CR5_ENLINL_DISABLED,
+ AB8500_CODEC_CR5_ENLINL_ENABLED
+} t_ab8500_codec_cr5_enlinl;
+
+/* CR5 - 4 */
+typedef enum {
+ AB8500_CODEC_CR5_ENLINR_DISABLED,
+ AB8500_CODEC_CR5_ENLINR_ENABLED
+} t_ab8500_codec_cr5_enlinr;
+
+/* CR5 - 3 */
+typedef enum {
+ AB8500_CODEC_CR5_MUTMIC1_DISABLED,
+ AB8500_CODEC_CR5_MUTMIC1_ENABLED
+} t_ab8500_codec_cr5_mutmic1;
+
+/* CR5 - 2 */
+typedef enum {
+ AB8500_CODEC_CR5_MUTMIC2_DISABLED,
+ AB8500_CODEC_CR5_MUTMIC2_ENABLED
+} t_ab8500_codec_cr5_mutmic2;
+
+/* CR5 - 1 */
+typedef enum {
+ AB8500_CODEC_CR5_MUTLINL_DISABLED,
+ AB8500_CODEC_CR5_MUTLINL_ENABLED
+} t_ab8500_codec_cr5_mutlinl;
+
+/* CR5 - 0 */
+typedef enum {
+ AB8500_CODEC_CR5_MUTLINR_DISABLED,
+ AB8500_CODEC_CR5_MUTLINR_ENABLED
+} t_ab8500_codec_cr5_mutlinr;
+
+/* CR6 - 7 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC1_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC1_ENABLED
+} t_ab8500_codec_cr6_endmic1;
+
+/* CR6 - 6 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC2_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC2_ENABLED
+} t_ab8500_codec_cr6_endmic2;
+
+/* CR6 - 5 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC3_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC3_ENABLED
+} t_ab8500_codec_cr6_endmic3;
+
+/* CR6 - 4 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC4_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC4_ENABLED
+} t_ab8500_codec_cr6_endmic4;
+
+/* CR6 - 3 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC5_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC5_ENABLED
+} t_ab8500_codec_cr6_endmic5;
+
+/* CR6 - 2 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC6_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC6_ENABLED
+} t_ab8500_codec_cr6_endmic6;
+
+/* CR7 - 7 */
+typedef enum {
+ AB8500_CODEC_CR7_MIC1SEL_MIC1A,
+ AB8500_CODEC_CR7_MIC1SEL_MIC1B
+} t_ab8500_codec_cr7_mic1sel;
+
+/* CR7 - 6 */
+typedef enum {
+ AB8500_CODEC_CR7_LINRSEL_MIC2,
+ AB8500_CODEC_CR7_LINRSEL_LINR
+} t_ab8500_codec_cr7_linrsel;
+
+/* CR7 - 5 */
+typedef enum {
+ AB8500_CODEC_CR7_ENDRVHSL_DISABLED,
+ AB8500_CODEC_CR7_ENDRVHSL_ENABLED
+} t_ab8500_codec_cr7_endrvhsl;
+
+/* CR7 - 4 */
+typedef enum {
+ AB8500_CODEC_CR7_ENDRVHSR_DISABLED,
+ AB8500_CODEC_CR7_ENDRVHSR_ENABLED
+} t_ab8500_codec_cr7_endrvhsr;
+
+/* CR7 - 2 */
+typedef enum {
+ AB8500_CODEC_CR7_ENADCMIC_DISABLED,
+ AB8500_CODEC_CR7_ENADCMIC_ENABLED
+} t_ab8500_codec_cr7_enadcmic;
+
+/* CR7 - 1 */
+typedef enum {
+ AB8500_CODEC_CR7_ENADCLINL_DISABLED,
+ AB8500_CODEC_CR7_ENADCLINL_ENABLED
+} t_ab8500_codec_cr7_enadclinl;
+
+/* CR7 - 0 */
+typedef enum {
+ AB8500_CODEC_CR7_ENADCLINR_DISABLED,
+ AB8500_CODEC_CR7_ENADCLINR_ENABLED
+} t_ab8500_codec_cr7_enadclinr;
+
+/* CR8 - 7 */
+typedef enum {
+ AB8500_CODEC_CR8_CP_DIS_PLDWN_ENABLED,
+ AB8500_CODEC_CR8_CP_DIS_PLDWN_DISABLED
+} t_ab8500_codec_cr8_cp_dis_pldwn;
+
+/* CR8 - 6 */
+typedef enum {
+ AB8500_CODEC_CR8_ENEAR_DISABLED,
+ AB8500_CODEC_CR8_ENEAR_ENABLED
+} t_ab8500_codec_cr8_enear;
+
+/* CR8 - 5 */
+typedef enum {
+ AB8500_CODEC_CR8_ENHSL_DISABLED,
+ AB8500_CODEC_CR8_ENHSL_ENABLED
+} t_ab8500_codec_cr8_enhsl;
+
+/* CR8 - 4 */
+typedef enum {
+ AB8500_CODEC_CR8_ENHSR_DISABLED,
+ AB8500_CODEC_CR8_ENHSR_ENABLED
+} t_ab8500_codec_cr8_enhsr;
+
+/* CR8 - 3 */
+typedef enum {
+ AB8500_CODEC_CR8_ENHFL_DISABLED,
+ AB8500_CODEC_CR8_ENHFL_ENABLED
+} t_ab8500_codec_cr8_enhfl;
+
+/* CR8 - 2 */
+typedef enum {
+ AB8500_CODEC_CR8_ENHFR_DISABLED,
+ AB8500_CODEC_CR8_ENHFR_ENABLED
+} t_ab8500_codec_cr8_enhfr;
+
+/* CR8 - 1 */
+typedef enum {
+ AB8500_CODEC_CR8_ENVIBL_DISABLED,
+ AB8500_CODEC_CR8_ENVIBL_ENABLED
+} t_ab8500_codec_cr8_envibl;
+
+/* CR8 - 0 */
+typedef enum {
+ AB8500_CODEC_CR8_ENVIBR_DISABLED,
+ AB8500_CODEC_CR8_ENVIBR_ENABLED
+} t_ab8500_codec_cr8_envibr;
+
+/* CR9 - 6 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACEAR_DISABLED,
+ AB8500_CODEC_CR9_ENDACEAR_ENABLED
+} t_ab8500_codec_cr9_endacear;
+
+/* CR9 - 5 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACHSL_DISABLED,
+ AB8500_CODEC_CR9_ENDACHSL_ENABLED
+} t_ab8500_codec_cr9_endachsl;
+
+/* CR9 - 4 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACHSR_DISABLED,
+ AB8500_CODEC_CR9_ENDACHSR_ENABLED
+} t_ab8500_codec_cr9_endachsr;
+
+/* CR9 - 3 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACHFL_DISABLED,
+ AB8500_CODEC_CR9_ENDACHFL_ENABLED
+} t_ab8500_codec_cr9_endachfl;
+
+/* CR9 - 2 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACHFR_DISABLED,
+ AB8500_CODEC_CR9_ENDACHFR_ENABLED
+} t_ab8500_codec_cr9_endachfr;
+
+/* CR9 - 1 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACVIBL_DISABLED,
+ AB8500_CODEC_CR9_ENDACVIBL_ENABLED
+} t_ab8500_codec_cr9_endacvibl;
+
+/* CR9 - 0 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACVIBR_DISABLED,
+ AB8500_CODEC_CR9_ENDACVIBR_ENABLED
+} t_ab8500_codec_cr9_endacvibr;
+
+/* CR10 - 6 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEEAR_DISABLED,
+ AB8500_CODEC_CR10_MUTEEAR_ENABLED
+} t_ab8500_codec_cr10_muteear;
+
+/* CR10 - 5 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEHSL_DISABLED,
+ AB8500_CODEC_CR10_MUTEHSL_ENABLED
+} t_ab8500_codec_cr10_mutehsl;
+
+/* CR10 - 4 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEHSR_DISABLED,
+ AB8500_CODEC_CR10_MUTEHSR_ENABLED
+} t_ab8500_codec_cr10_mutehsr;
+
+/* CR10 - 3 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEHFL_DISABLED,
+ AB8500_CODEC_CR10_MUTEHFL_ENABLED
+} t_ab8500_codec_cr10_mutehfl;
+
+/* CR10 - 2 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEHFR_DISABLED,
+ AB8500_CODEC_CR10_MUTEHFR_ENABLED
+} t_ab8500_codec_cr10_mutehfr;
+
+/* CR10 - 1 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEVIBL_DISABLED,
+ AB8500_CODEC_CR10_MUTEVIBL_ENABLED
+} t_ab8500_codec_cr10_mutevibl;
+
+/* CR10 - 0 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEVIBR_DISABLED,
+ AB8500_CODEC_CR10_MUTEVIBR_ENABLED
+} t_ab8500_codec_cr10_mutevibr;
+
+/* CR11 - 7 */
+typedef enum {
+ AB8500_CODEC_CR11_EARSHORTPWD_DISABLED,
+ AB8500_CODEC_CR11_EARSHORTPWD_ENABLED
+} t_ab8500_codec_cr11_earshortpwd;
+
+/* CR11 - 6 */
+typedef enum {
+ AB8500_CODEC_CR11_EARSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_EARSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_earshortdis;
+
+/* CR11 - 5 */
+typedef enum {
+ AB8500_CODEC_CR11_HSLSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_HSLSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_hslshortdis;
+
+/* CR11 - 4 */
+typedef enum {
+ AB8500_CODEC_CR11_HSRSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_HSRSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_hsrshortdis;
+
+/* CR11 - 3 */
+typedef enum {
+ AB8500_CODEC_CR11_HFLSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_HFLSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_hflshortdis;
+
+/* CR11 - 2 */
+typedef enum {
+ AB8500_CODEC_CR11_HFRSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_HFRSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_hfrshortdis;
+
+/* CR11 - 1 */
+typedef enum {
+ AB8500_CODEC_CR11_VIBLSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_VIBLSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_viblshortdis;
+
+/* CR11 - 0 */
+typedef enum {
+ AB8500_CODEC_CR11_VIBRSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_VIBRSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_vibrshortdis;
+
+/* CR12 - 7 */
+typedef enum {
+ AB8500_CODEC_CR12_ENCPHS_DISABLED,
+ AB8500_CODEC_CR12_ENCPHS_ENABLED
+} t_ab8500_codec_cr12_encphs;
+
+/* CR12 - 6:4 */
+typedef enum {
+ AB8500_CODEC_CR12_HSAUTOTIME_6_6USEC,
+ AB8500_CODEC_CR12_HSAUTOTIME_13_3USEC,
+ AB8500_CODEC_CR12_HSAUTOTIME_26_6USEC,
+ AB8500_CODEC_CR12_HSAUTOTIME_53_2USEC,
+ AB8500_CODEC_CR12_HSAUTOTIME_106_4USEC,
+ AB8500_CODEC_CR12_HSAUTOTIME_212_8USEC,
+ AB8500_CODEC_CR12_HSAUTOTIME_425_6USEC,
+ AB8500_CODEC_CR12_HSAUTOTIME_851_2USEC,
+} t_ab8500_codec_cr12_hsautotime;
+
+/* CR12 - 1 */
+typedef enum {
+ AB8500_CODEC_CR12_HSAUTOENSEL_DISABLED,
+ AB8500_CODEC_CR12_HSAUTOENSEL_ENABLED
+} t_ab8500_codec_cr12_hsautoensel;
+
+/* CR12 - 0 */
+typedef enum {
+ AB8500_CODEC_CR12_HSAUTOEN_DISABLED,
+ AB8500_CODEC_CR12_HSAUTOEN_ENABLED
+} t_ab8500_codec_cr12_hsautoen;
+
+/* CR13 - 7:4 */
+typedef enum {
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_25,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_50,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_100,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_150,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_200,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_250,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_300,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_350,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_400,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_450,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_500,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_550,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_600,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_650,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_700,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_750
+} t_ab8500_codec_cr13_envdet_hthresh;
+
+/* CR13 - 3:0 */
+typedef enum {
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_25,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_50,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_100,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_150,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_200,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_250,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_300,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_350,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_400,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_450,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_500,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_550,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_600,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_650,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_700,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_750
+} t_ab8500_codec_cr13_envdet_lthresh;
+
+/* CR14 - 7 */
+typedef enum {
+ AB8500_CODEC_CR14_SMPSLVEN_HIGHVOLTAGE,
+ AB8500_CODEC_CR14_SMPSLVEN_LOWVOLTAGE
+} t_ab8500_codec_cr14_smpslven;
+
+/* CR14 - 6 */
+typedef enum {
+ AB8500_CODEC_CR14_ENVDETSMPSEN_DISABLED,
+ AB8500_CODEC_CR14_ENVDETSMPSEN_ENABLED
+} t_ab8500_codec_cr14_envdetsmpsen;
+
+/* CR14 - 5 */
+typedef enum {
+ AB8500_CODEC_CR14_CPLVEN_HIGHVOLTAGE,
+ AB8500_CODEC_CR14_CPLVEN_LOWVOLTAGE
+} t_ab8500_codec_cr14_cplven;
+
+/* CR14 - 4 */
+typedef enum {
+ AB8500_CODEC_CR14_ENVDETCPEN_DISABLED,
+ AB8500_CODEC_CR14_ENVDETCPEN_ENABLED
+} t_ab8500_codec_cr14_envdetcpen;
+
+/* CR14 - 3:0 */
+typedef enum {
+ AB8500_CODEC_CR14_ENVET_TIME_27USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_53USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_106USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_212USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_424USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_848USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_1MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_3MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_6MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_13MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_27MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_54MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_109MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_218MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_436MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_872MSEC,
+} t_ab8500_codec_cr14_envet_time;
+
+/* CR15 - 7 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMTOVIBL_DA_PATH,
+ AB8500_CODEC_CR15_PWMTOVIBL_PWM
+} t_ab8500_codec_cr15_pwmtovibl;
+
+/* CR15 - 6 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMTOVIBR_DA_PATH,
+ AB8500_CODEC_CR15_PWMTOVIBR_PWM
+} t_ab8500_codec_cr15_pwmtovibr;
+
+/* CR15 - 5 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMLCTRL_PWMNPLGPOL,
+ AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE
+} t_ab8500_codec_cr15_pwmlctrl;
+
+/* CR15 - 4 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMRCTRL_PWMNPRGPOL,
+ AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE
+} t_ab8500_codec_cr15_pwmrctrl;
+
+/* CR15 - 3 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMNLCTRL_PWMNLGPOL,
+ AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE
+} t_ab8500_codec_cr15_pwmnlctrl;
+
+/* CR15 - 2 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMPLCTRL_PWMPLGPOL,
+ AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE
+} t_ab8500_codec_cr15_pwmplctrl;
+
+/* CR15 - 1 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMNRCTRL_PWMNRGPOL,
+ AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE
+} t_ab8500_codec_cr15_pwmnrctrl;
+
+/* CR15 - 0 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMPRCTRL_PWMPRGPOL,
+ AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE
+} t_ab8500_codec_cr15_pwmprctrl;
+
+/* CR16 - 7 */
+typedef enum {
+ AB8500_CODEC_CR16_PWMNLPOL_GNDVIB,
+ AB8500_CODEC_CR16_PWMNLPOL_VINVIB
+} t_ab8500_codec_cr16_pwmnlpol;
+
+/* CR16 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr16_pwmnldutycycle;
+
+/* CR17 - 7 */
+typedef enum {
+ AB8500_CODEC_CR17_PWMPLPOL_GNDVIB,
+ AB8500_CODEC_CR17_PWMPLPOL_VINVIB
+} t_ab8500_codec_cr17_pwmplpol;
+
+/* CR17 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr17_pwmpldutycycle;
+
+/* CR18 - 7 */
+typedef enum {
+ AB8500_CODEC_CR18_PWMNRPOL_GNDVIB,
+ AB8500_CODEC_CR18_PWMNRPOL_VINVIB
+} t_ab8500_codec_cr18_pwmnrpol;
+
+/* CR18 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr18_pwmnrdutycycle;
+
+/* CR19 - 7 */
+typedef enum {
+ AB8500_CODEC_CR19_PWMPRPOL_GNDVIB,
+ AB8500_CODEC_CR19_PWMPRPOL_VINVIB
+} t_ab8500_codec_cr19_pwmprpol;
+
+/* CR19 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr19_pwmprdutycycle;
+
+/* CR20 - 7 */
+typedef enum {
+ AB8500_CODEC_CR20_EN_SE_MIC1_DIFFERENTIAL,
+ AB8500_CODEC_CR20_EN_SE_MIC1_SINGLE
+} t_ab8500_codec_cr20_en_se_mic1;
+
+/* CR20 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr20_mic1_gain;
+
+/* CR21 - 7 */
+typedef enum {
+ AB8500_CODEC_CR21_EN_SE_MIC2_DIFFERENTIAL,
+ AB8500_CODEC_CR21_EN_SE_MIC2_SINGLE
+} t_ab8500_codec_cr21_en_se_mic2;
+
+/* CR21 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr21_mic2_gain;
+
+/* CR22 - 7:5 */
+typedef t_uint8 t_ab8500_codec_cr22_hsl_gain;
+
+/* CR22 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr22_linl_gain;
+
+/* CR23 - 7:5 */
+typedef t_uint8 t_ab8500_codec_cr23_hsr_gain;
+
+/* CR23 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr23_linr_gain;
+
+/* CR24 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr24_lintohsl_gain;
+
+/* CR25 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr25_lintohsr_gain;
+
+/* CR26 - 7 */
+typedef enum {
+ AB8500_CODEC_CR26_AD1NH_FILTER_ENABLED,
+ AB8500_CODEC_CR26_AD1NH_FILTER_DISABLED
+} t_ab8500_codec_cr26_ad1nh;
+
+/* CR26 - 6 */
+typedef enum {
+ AB8500_CODEC_CR26_AD2NH_FILTER_ENABLED,
+ AB8500_CODEC_CR26_AD2NH_FILTER_DISABLED
+} t_ab8500_codec_cr26_ad2nh;
+
+/* CR26 - 5 */
+typedef enum {
+ AB8500_CODEC_CR26_AD3NH_FILTER_ENABLED,
+ AB8500_CODEC_CR26_AD3NH_FILTER_DISABLED
+} t_ab8500_codec_cr26_ad3nh;
+
+/* CR26 - 4 */
+typedef enum {
+ AB8500_CODEC_CR26_AD4NH_FILTER_ENABLED,
+ AB8500_CODEC_CR26_AD4NH_FILTER_DISABLED
+} t_ab8500_codec_cr26_ad4nh;
+
+/* CR26 - 3 */
+typedef enum {
+ AB8500_CODEC_CR26_AD1_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR26_AD1_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr26_ad1_voice;
+
+/* CR26 - 2 */
+typedef enum {
+ AB8500_CODEC_CR26_AD2_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR26_AD2_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr26_ad2_voice;
+
+/* CR26 - 1 */
+typedef enum {
+ AB8500_CODEC_CR26_AD3_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR26_AD3_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr26_ad3_voice;
+
+/* CR26 - 0 */
+typedef enum {
+ AB8500_CODEC_CR26_AD4_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR26_AD4_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr26_ad4_voice;
+
+/* CR27 - 7 */
+typedef enum {
+ AB8500_CODEC_CR27_EN_MASTGEN_DISABLED,
+ AB8500_CODEC_CR27_EN_MASTGEN_ENABLED
+} t_ab8500_codec_cr27_en_mastgen;
+
+/* CR27 - 6:5 */
+typedef enum {
+ AB8500_CODEC_CR27_IF1_BITCLK_OSR_32,
+ AB8500_CODEC_CR27_IF1_BITCLK_OSR_64,
+ AB8500_CODEC_CR27_IF1_BITCLK_OSR_128,
+ AB8500_CODEC_CR27_IF1_BITCLK_OSR_256
+} t_ab8500_codec_cr27_if1_bitclk_osr;
+
+/* CR27 - 4 */
+typedef enum {
+ AB8500_CODEC_CR27_ENFS_BITCLK1_DISABLED,
+ AB8500_CODEC_CR27_ENFS_BITCLK1_ENABLED
+} t_ab8500_codec_cr27_enfs_bitclk1;
+
+/* CR27 - 2:1 */
+typedef enum {
+ AB8500_CODEC_CR27_IF0_BITCLK_OSR_32,
+ AB8500_CODEC_CR27_IF0_BITCLK_OSR_64,
+ AB8500_CODEC_CR27_IF0_BITCLK_OSR_128,
+ AB8500_CODEC_CR27_IF0_BITCLK_OSR_256
+} t_ab8500_codec_cr27_if0_bitclk_osr;
+
+/* CR27 - 0 */
+typedef enum {
+ AB8500_CODEC_CR27_ENFS_BITCLK0_DISABLED,
+ AB8500_CODEC_CR27_ENFS_BITCLK0_ENABLED
+} t_ab8500_codec_cr27_enfs_bitclk0;
+
+/* CR28 - 6 */
+typedef enum {
+ AB8500_CODEC_CR28_FSYNC0P_RISING_EDGE,
+ AB8500_CODEC_CR28_FSYNC0P_FALLING_EDGE
+} t_ab8500_codec_cr28_fsync0p;
+
+/* CR28 - 5 */
+typedef enum {
+ AB8500_CODEC_CR28_BITCLK0P_RISING_EDGE,
+ AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE
+} t_ab8500_codec_cr28_bitclk0p;
+
+/* CR28 - 4 */
+typedef enum {
+ AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED,
+ AB8500_CODEC_CR28_IF0DEL_DELAYED
+} t_ab8500_codec_cr28_if0del;
+
+/* CR28 - 3:2 */
+typedef enum {
+ AB8500_CODEC_CR28_IF0FORMAT_DISABLED,
+ AB8500_CODEC_CR28_IF0FORMAT_TDM,
+ AB8500_CODEC_CR28_IF0FORMAT_I2S_LEFTALIGNED
+} t_ab8500_codec_cr28_if0format;
+
+/* CR28 - 1:0 */
+typedef enum {
+ AB8500_CODEC_CR28_IF0WL_16BITS,
+ AB8500_CODEC_CR28_IF0WL_20BITS,
+ AB8500_CODEC_CR28_IF0WL_24BITS,
+ AB8500_CODEC_CR28_IF0WL_32BITS
+} t_ab8500_codec_cr28_if0wl;
+
+/* CR29 - 7 */
+typedef enum {
+ AB8500_CODEC_CR29_IF0DATOIF1AD_NOTSENT,
+ AB8500_CODEC_CR29_IF0DATOIF1AD_SENT
+} t_ab8500_codec_cr29_if0datoif1ad;
+
+/* CR29 - 6 */
+typedef enum {
+ AB8500_CODEC_CR29_IF0CKTOIF1CK_NOTSENT,
+ AB8500_CODEC_CR29_IF0CKTOIF1CK_SENT
+} t_ab8500_codec_cr29_if0cktoif1ck;
+
+/* CR29 - 5 */
+typedef enum {
+ AB8500_CODEC_CR29_IF1MASTER_FS1CK1_INPUT,
+ AB8500_CODEC_CR29_IF1MASTER_FS1CK1_OUTPUT
+} t_ab8500_codec_cr29_if1master;
+
+/* CR29 - 3 */
+typedef enum {
+ AB8500_CODEC_CR29_IF1DATOIF0AD_NOTSENT,
+ AB8500_CODEC_CR29_IF1DATOIF0AD_SENT
+} t_ab8500_codec_cr29_if1datoif0ad;
+
+/* CR29 - 2 */
+typedef enum {
+ AB8500_CODEC_CR29_IF1CKTOIF0CK_NOTSENT,
+ AB8500_CODEC_CR29_IF1CKTOIF0CK_SENT
+} t_ab8500_codec_cr29_if1cktoif0ck;
+
+/* CR29 - 1 */
+typedef enum {
+ AB8500_CODEC_CR29_IF0MASTER_FS0CK0_INPUT,
+ AB8500_CODEC_CR29_IF0MASTER_FS0CK0_OUTPUT
+} t_ab8500_codec_cr29_if0master;
+
+/* CR29 - 0 */
+typedef enum {
+ AB8500_CODEC_CR29_IF0BFIFOEN_NORMAL_MODE,
+ AB8500_CODEC_CR29_IF0BFIFOEN_BURST_MODE
+} t_ab8500_codec_cr29_if0bfifoen;
+
+/* CR30 - 6 */
+typedef enum {
+ AB8500_CODEC_CR30_FSYNC1P_RISING_EDGE,
+ AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE
+} t_ab8500_codec_cr30_fsync1p;
+
+/* CR30 - 5 */
+typedef enum {
+ AB8500_CODEC_CR30_BITCLK1P_RISING_EDGE,
+ AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE
+} t_ab8500_codec_cr30_bitclk1p;
+
+/* CR30 - 4 */
+typedef enum {
+ AB8500_CODEC_CR30_IF1DEL_NOT_DELAYED,
+ AB8500_CODEC_CR30_IF1DEL_DELAYED
+} t_ab8500_codec_cr30_if1del;
+
+/* CR30 - 3:2 */
+typedef enum {
+ AB8500_CODEC_CR30_IF1FORMAT_DISABLED,
+ AB8500_CODEC_CR30_IF1FORMAT_TDM,
+ AB8500_CODEC_CR30_IF1FORMAT_I2S_LEFTALIGNED
+} t_ab8500_codec_cr30_if1format;
+
+/* CR30 - 1:0 */
+typedef enum {
+ AB8500_CODEC_CR30_IF1WL_16BITS,
+ AB8500_CODEC_CR30_IF1WL_20BITS,
+ AB8500_CODEC_CR30_IF1WL_24BITS,
+ AB8500_CODEC_CR30_IF1WL_32BITS
+} t_ab8500_codec_cr30_if1wl;
+
+/* CR31:46 - 7:4 or 3:0 */
+/* In ab8500_codec.h */
+
+/* CR47:50 - 7/6/5/4/3/2/1/0 */
+typedef enum {
+ AB8500_CODEC_CR47_TO_CR50_HIZ_SL_LOW_IMPEDANCE,
+ AB8500_CODEC_CR47_TO_CR50_HIZ_SL_HIGH_IMPEDANCE,
+} t_ab8500_codec_cr47_to_cr50_hiz_sl;
+
+/* CR51 - 7 */
+typedef enum {
+ AB8500_CODEC_CR51_DA12_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR51_DA12_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr51_da12_voice;
+
+/* CR51 - 5 */
+typedef enum {
+ AB8500_CODEC_CR51_SLDAI1TOSLADO1_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR51_SLDAI1TOSLADO1_LOOPEDBACK
+} t_ab8500_codec_cr51_sldai1toslado1;
+
+/* CR51:56 - 4:0 */
+/* In ab8500_codec.h */
+
+/* CR52 - 5 */
+typedef enum {
+ AB8500_CODEC_CR52_SLDAI2TOSLADO2_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR52_SLDAI2TOSLADO2_LOOPEDBACK
+} t_ab8500_codec_cr52_sldai2toslado2;
+
+/* CR53 - 7 */
+typedef enum {
+ AB8500_CODEC_CR53_DA34_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR53_DA34_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr53_da34_voice;
+
+/* CR53 - 5 */
+typedef enum {
+ AB8500_CODEC_CR53_SLDAI3TOSLADO3_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR53_SLDAI3TOSLADO3_LOOPEDBACK
+} t_ab8500_codec_cr53_sldai3toslado3;
+
+/* CR54 - 5 */
+typedef enum {
+ AB8500_CODEC_CR54_SLDAI4TOSLADO4_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR54_SLDAI4TOSLADO4_LOOPEDBACK
+} t_ab8500_codec_cr54_sldai4toslado4;
+
+/* CR55 - 7 */
+typedef enum {
+ AB8500_CODEC_CR55_DA56_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR55_DA56_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr55_da56_voice;
+
+/* CR55 - 6:5 */
+typedef enum {
+ AB8500_CODEC_CR55_SLDAI5TOSLADO5_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR55_SLDAI5TOSLADO5_DA_IN1_LOOPEDBACK,
+ AB8500_CODEC_CR55_SLDAI5TOSLADO5_DA_IN3_LOOPEDBACK,
+ AB8500_CODEC_CR55_SLDAI5TOSLADO5_DA_IN5_LOOPEDBACK
+} t_ab8500_codec_cr55_sldai5toslado5;
+
+/* CR56 - 6:5 */
+typedef enum {
+ AB8500_CODEC_CR56_SLDAI6TOSLADO7_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR56_SLDAI6TOSLADO7_DA_IN2_LOOPEDBACK,
+ AB8500_CODEC_CR56_SLDAI6TOSLADO7_DA_IN4_LOOPEDBACK,
+ AB8500_CODEC_CR56_SLDAI6TOSLADO7_DA_IN6_LOOPEDBACK
+} t_ab8500_codec_cr56_sldai6toslado7;
+
+/* CR57 - 6 */
+typedef enum {
+ AB8500_CODEC_CR57_BFIFULL_MSK_MASKED,
+ AB8500_CODEC_CR57_BFIFULL_MSK_ENABLED
+} t_ab8500_codec_cr57_bfifull_msk;
+
+/* CR57 - 5 */
+typedef enum {
+ AB8500_CODEC_CR57_BFIEMPT_MSK_MASKED,
+ AB8500_CODEC_CR57_BFIEMPT_MSK_ENABLED
+} t_ab8500_codec_cr57_bfiempt_msk;
+
+/* CR57 - 4 */
+typedef enum {
+ AB8500_CODEC_CR57_DACHAN_MSK_MASKED,
+ AB8500_CODEC_CR57_DACHAN_MSK_ENABLED
+} t_ab8500_codec_cr57_dachan_msk;
+
+/* CR57 - 3 */
+typedef enum {
+ AB8500_CODEC_CR57_GAIN_MSK_MASKED,
+ AB8500_CODEC_CR57_GAIN_MSK_ENABLED
+} t_ab8500_codec_cr57_gain_msk;
+
+/* CR57 - 2 */
+typedef enum {
+ AB8500_CODEC_CR57_DSPAD_MSK_MASKED,
+ AB8500_CODEC_CR57_DSPAD_MSK_ENABLED
+} t_ab8500_codec_cr57_dspad_msk;
+
+/* CR57 - 1 */
+typedef enum {
+ AB8500_CODEC_CR57_DSPDA_MSK_MASKED,
+ AB8500_CODEC_CR57_DSPDA_MSK_ENABLED
+} t_ab8500_codec_cr57_dspda_msk;
+
+/* CR57 - 0 */
+typedef enum {
+ AB8500_CODEC_CR57_STFIR_MSK_MASKED,
+ AB8500_CODEC_CR57_STFIR_MSK_ENABLED
+} t_ab8500_codec_cr57_stfir_msk;
+
+/* CR58 - Read Only */
+/* CR58 - 6 */
+typedef enum {
+ AB8500_CODEC_CR58_BFIFULL_EV_NOT_FULL,
+ AB8500_CODEC_CR58_BFIFULL_EV_FULL
+} t_ab8500_codec_cr58_bfifull_ev;
+
+/* CR58 - 5 */
+typedef enum {
+ AB8500_CODEC_CR58_BFIEMPT_EV_NOT_EMPTY,
+ AB8500_CODEC_CR58_BFIEMPT_EV_EMPTY
+} t_ab8500_codec_cr58_bfiempt_ev;
+
+/* CR58 - 4 */
+typedef enum {
+ AB8500_CODEC_CR58_DACHAN_EV_NO_SATURATION,
+ AB8500_CODEC_CR58_DACHAN_EV_SATURATION
+} t_ab8500_codec_cr58_dachan_ev;
+
+/* CR58 - 3 */
+typedef enum {
+ AB8500_CODEC_CR58_GAIN_EV_NO_SATURATION,
+ AB8500_CODEC_CR58_GAIN_EV_SATURATION
+} t_ab8500_codec_cr58_gain_ev;
+
+/* CR58 - 2 */
+typedef enum {
+ AB8500_CODEC_CR58_DSPAD_EV_NO_SATURATION,
+ AB8500_CODEC_CR58_DSPAD_EV_SATURATION
+} t_ab8500_codec_cr58_dspad_ev;
+
+/* CR58 - 1 */
+typedef enum {
+ AB8500_CODEC_CR58_DSPDA_EV_NO_SATURATION,
+ AB8500_CODEC_CR58_DSPDA_EV_SATURATION
+} t_ab8500_codec_cr58_dspda_ev;
+
+/* CR58 - 0 */
+typedef enum {
+ AB8500_CODEC_CR58_STFIR_EV_NO_SATURATION,
+ AB8500_CODEC_CR58_STFIR_EV_SATURATION
+} t_ab8500_codec_cr58_stfir_ev;
+
+/* CR59 - 7 */
+typedef enum {
+ AB8500_CODEC_CR59_VSSREADY_MSK_MASKED,
+ AB8500_CODEC_CR59_VSSREADY_MSK_ENABLED
+} t_ab8500_codec_cr59_vssready_msk;
+
+/* CR59 - 6 */
+typedef enum {
+ AB8500_CODEC_CR59_SHRTVIBL_MSK_MASKED,
+ AB8500_CODEC_CR59_SHRTVIBL_MSK_ENABLED
+} t_ab8500_codec_cr59_shrtvibl_msk;
+
+/* CR59 - 5 */
+typedef enum {
+ AB8500_CODEC_CR59_SHRTVIBR_MSK_MASKED,
+ AB8500_CODEC_CR59_SHRTVIBR_MSK_ENABLED
+} t_ab8500_codec_cr59_shrtvibr_msk;
+
+/* CR59 - 4 */
+typedef enum {
+ AB8500_CODEC_CR59_SHRTHFL_MSK_MASKED,
+ AB8500_CODEC_CR59_SHRTHFL_MSK_ENABLED
+} t_ab8500_codec_cr59_shrthfl_msk;
+
+/* CR59 - 3 */
+typedef enum {
+ AB8500_CODEC_CR59_SHRTHFR_MSK_MASKED,
+ AB8500_CODEC_CR59_SHRTHFR_MSK_ENABLED
+} t_ab8500_codec_cr59_shrthfr_msk;
+
+/* CR59 - 2 */
+typedef enum {
+ AB8500_CODEC_CR59_SHRTHSL_MSK_MASKED,
+ AB8500_CODEC_CR59_SHRTHSL_MSK_ENABLED
+} t_ab8500_codec_cr59_shrthsl_msk;
+
+/* CR59 - 1 */
+typedef enum {
+ AB8500_CODEC_CR59_SHRTHSR_MSK_MASKED,
+ AB8500_CODEC_CR59_SHRTHSR_MSK_ENABLED
+} t_ab8500_codec_cr59_shrthsr_msk;
+
+/* CR59 - 0 */
+typedef enum {
+ AB8500_CODEC_CR59_SHRTEAR_MSK_MASKED,
+ AB8500_CODEC_CR59_SHRTEAR_MSK_ENABLED
+} t_ab8500_codec_cr59_shrtear_msk;
+
+/* CR60 - Read Only */
+/* CR60 - 7 */
+typedef enum {
+ AB8500_CODEC_CR60_VSSREADY_EV_NOT_READY,
+ AB8500_CODEC_CR60_VSSREADY_EV_READY
+} t_ab8500_codec_cr60_vssready_ev;
+
+/* CR60 - 6 */
+typedef enum {
+ AB8500_CODEC_CR60_SHRTVIBL_EV_NO_SHORTCIRCUIT,
+ AB8500_CODEC_CR60_SHRTVIBL_EV_SHORTCIRCUIT
+} t_ab8500_codec_cr60_shrtvibl_ev;
+
+/* CR60 - 5 */
+typedef enum {
+ AB8500_CODEC_CR60_SHRTVIBR_EV_NO_SHORTCIRCUIT,
+ AB8500_CODEC_CR60_SHRTVIBR_EV_SHORTCIRCUIT
+} t_ab8500_codec_cr60_shrtvibr_ev;
+
+/* CR60 - 4 */
+typedef enum {
+ AB8500_CODEC_CR60_SHRTHFL_EV_NO_SHORTCIRCUIT,
+ AB8500_CODEC_CR60_SHRTHFL_EV_SHORTCIRCUIT
+} t_ab8500_codec_cr60_shrthfl_ev;
+
+/* CR60 - 3 */
+typedef enum {
+ AB8500_CODEC_CR60_SHRTHFR_EV_NO_SHORTCIRCUIT,
+ AB8500_CODEC_CR60_SHRTHFR_EV_SHORTCIRCUIT
+} t_ab8500_codec_cr60_shrthfr_ev;
+
+/* CR60 - 2 */
+typedef enum {
+ AB8500_CODEC_CR60_SHRTHSL_EV_NO_SHORTCIRCUIT,
+ AB8500_CODEC_CR60_SHRTHSL_EV_SHORTCIRCUIT
+} t_ab8500_codec_cr60_shrthsl_ev;
+
+/* CR60 - 1 */
+typedef enum {
+ AB8500_CODEC_CR60_SHRTHSR_EV_NO_SHORTCIRCUIT,
+ AB8500_CODEC_CR60_SHRTHSR_EV_SHORTCIRCUIT
+} t_ab8500_codec_cr60_shrthsr_ev;
+
+/* CR60 - 0 */
+typedef enum {
+ AB8500_CODEC_CR60_SHRTEAR_EV_NO_SHORTCIRCUIT,
+ AB8500_CODEC_CR60_SHRTEAR_EV_SHORTCIRCUIT
+} t_ab8500_codec_cr60_shrtear_ev;
+
+/* CR61 - 6:2 - Read Only */
+typedef enum {
+ AB8500_CODEC_CR61_REVISION_1_0,
+ AB8500_CODEC_CR61_REVISION_TBD
+} t_ab8500_codec_cr61_revision;
+
+/* CR61 - 1:0 */
+typedef enum {
+ AB8500_CODEC_CR61_FADE_SPEED_1MS,
+ AB8500_CODEC_CR61_FADE_SPEED_4MS,
+ AB8500_CODEC_CR61_FADE_SPEED_8MS,
+ AB8500_CODEC_CR61_FADE_SPEED_16MS
+} t_ab8500_codec_cr61_fade_speed;
+
+/* CR62 - Read Only */
+/* CR62 - 5 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC1SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC1SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic1sinc3;
+
+/* CR62 - 4 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC2SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC2SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic2sinc3;
+
+/* CR62 - 3 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC3SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC3SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic3sinc3;
+
+/* CR62 - 2 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC4SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC4SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic4sinc3;
+
+/* CR62 - 1 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC5SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC5SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic5sinc3;
+
+/* CR62 - 0 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC6SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC6SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic6sinc3;
+
+/* CR63 - 7 */
+typedef enum {
+ AB8500_CODEC_CR63_DATOHSLEN_DISABLED,
+ AB8500_CODEC_CR63_DATOHSLEN_ENABLED
+} t_ab8500_codec_cr63_datohslen;
+
+/* CR63 - 6 */
+typedef enum {
+ AB8500_CODEC_CR63_DATOHSREN_DISABLED,
+ AB8500_CODEC_CR63_DATOHSREN_ENABLED
+} t_ab8500_codec_cr63_datohsren;
+
+/* CR63 - 5 */
+typedef enum {
+ AB8500_CODEC_CR63_AD1SEL_LINLADL_SELECTED,
+ AB8500_CODEC_CR63_AD1SEL_DMIC1_SELECTED
+} t_ab8500_codec_cr63_ad1sel;
+
+/* CR63 - 4 */
+typedef enum {
+ AB8500_CODEC_CR63_AD2SEL_LINRADR_SELECTED,
+ AB8500_CODEC_CR63_AD2SEL_DMIC2_SELECTED
+} t_ab8500_codec_cr63_ad2sel;
+
+/* CR63 - 3 */
+typedef enum {
+ AB8500_CODEC_CR63_AD3SEL_ADMO_SELECTED,
+ AB8500_CODEC_CR63_AD3SEL_DMIC3_SELECTED
+} t_ab8500_codec_cr63_ad3sel;
+
+/* CR63 - 2 */
+typedef enum {
+ AB8500_CODEC_CR63_AD5SEL_AMADR_SELECTED,
+ AB8500_CODEC_CR63_AD5SEL_DMIC5_SELECTED
+} t_ab8500_codec_cr63_ad5sel;
+
+/* CR63 - 1 */
+typedef enum {
+ AB8500_CODEC_CR63_AD6SEL_ADMO_SELECTED,
+ AB8500_CODEC_CR63_AD6SEL_DMIC6_SELECTED
+} t_ab8500_codec_cr63_ad6sel;
+
+/* CR63 - 0 */
+typedef enum {
+ AB8500_CODEC_CR63_ANCSEL_NOT_MIXED_IN_EAR,
+ AB8500_CODEC_CR63_ANCSEL_MIXED_IN_EAR
+} t_ab8500_codec_cr63_ancsel;
+
+/* CR64 - 7 */
+typedef enum {
+ AB8500_CODEC_CR64_DATOHFREN_NOT_MIXED_TO_HFR,
+ AB8500_CODEC_CR64_DATOHFREN_MIXED_TO_HFR
+} t_ab8500_codec_cr64_datohfren;
+
+/* CR64 - 6 */
+typedef enum {
+ AB8500_CODEC_CR64_DATOHFLEN_NOT_MIXED_TO_HFL,
+ AB8500_CODEC_CR64_DATOHFLEN_MIXED_TO_HFL
+} t_ab8500_codec_cr64_datohflen;
+
+/* CR64 - 5 */
+typedef enum {
+ AB8500_CODEC_CR64_HFRSEL_DA4_MIXED_TO_HFR,
+ AB8500_CODEC_CR64_HFRSEL_ANC_MIXED_TO_HFR
+} t_ab8500_codec_cr64_hfrsel;
+
+/* CR64 - 4 */
+typedef enum {
+ AB8500_CODEC_CR64_HFLSEL_DA3_MIXED_TO_HFL,
+ AB8500_CODEC_CR64_HFLSEL_ANC_MIXED_TO_HFL
+} t_ab8500_codec_cr64_hflsel;
+
+/* CR64 - 3:2 */
+typedef enum {
+ AB8500_CODEC_CR64_STFIR1SEL_AD_OUT1_SELECTED,
+ AB8500_CODEC_CR64_STFIR1SEL_AD_OUT3_SELECTED,
+ AB8500_CODEC_CR64_STFIR1SEL_DA_IN1_SELECTED
+} t_ab8500_codec_cr64_stfir1sel;
+
+/* CR64 - 1:0 */
+typedef enum {
+ AB8500_CODEC_CR64_STFIR2SEL_AD_OUT2_SELECTED,
+ AB8500_CODEC_CR64_STFIR2SEL_AD_OUT4_SELECTED,
+ AB8500_CODEC_CR64_STFIR2SEL_DA_IN2_SELECTED
+} t_ab8500_codec_cr64_stfir2sel;
+
+/* CR65 - 6 */
+typedef enum {
+ AB8500_CODEC_CR65_FADEDIS_AD1_ENABLED,
+ AB8500_CODEC_CR65_FADEDIS_AD1_DISABLED
+} t_ab8500_codec_cr65_fadedis_ad1;
+
+/* CR65 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr65_ad1gain;
+
+/* CR66 - 6 */
+typedef enum {
+ AB8500_CODEC_CR66_FADEDIS_AD2_ENABLED,
+ AB8500_CODEC_CR66_FADEDIS_AD2_DISABLED
+} t_ab8500_codec_cr66_fadedis_ad2;
+
+/* CR66 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr66_ad2gain;
+
+/* CR67 - 6 */
+typedef enum {
+ AB8500_CODEC_CR67_FADEDIS_AD3_ENABLED,
+ AB8500_CODEC_CR67_FADEDIS_AD3_DISABLED
+} t_ab8500_codec_cr67_fadedis_ad3;
+
+/* CR67 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr67_ad3gain;
+
+/* CR68 - 6 */
+typedef enum {
+ AB8500_CODEC_CR68_FADEDIS_AD4_ENABLED,
+ AB8500_CODEC_CR68_FADEDIS_AD4_DISABLED
+} t_ab8500_codec_cr68_fadedis_ad4;
+
+/* CR68 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr68_ad4gain;
+
+/* CR69 - 6 */
+typedef enum {
+ AB8500_CODEC_CR69_FADEDIS_AD5_ENABLED,
+ AB8500_CODEC_CR69_FADEDIS_AD5_DISABLED
+} t_ab8500_codec_cr69_fadedis_ad5;
+
+/* CR69 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr69_ad5gain;
+
+/* CR70 - 6 */
+typedef enum {
+ AB8500_CODEC_CR70_FADEDIS_AD6_ENABLED,
+ AB8500_CODEC_CR70_FADEDIS_AD6_DISABLED
+} t_ab8500_codec_cr70_fadedis_ad6;
+
+/* CR70 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr70_ad6gain;
+
+/* CR71 - 6 */
+typedef enum {
+ AB8500_CODEC_CR71_FADEDIS_DA1_ENABLED,
+ AB8500_CODEC_CR71_FADEDIS_DA1_DISABLED
+} t_ab8500_codec_cr71_fadedis_da1;
+
+/* CR71 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr71_da1gain;
+
+/* CR72 - 6 */
+typedef enum {
+ AB8500_CODEC_CR72_FADEDIS_DA2_ENABLED,
+ AB8500_CODEC_CR72_FADEDIS_DA2_DISABLED
+} t_ab8500_codec_cr72_fadedis_da2;
+
+/* CR72 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr72_da2gain;
+
+/* CR73 - 6 */
+typedef enum {
+ AB8500_CODEC_CR73_FADEDIS_DA3_ENABLED,
+ AB8500_CODEC_CR73_FADEDIS_DA3_DISABLED
+} t_ab8500_codec_cr73_fadedis_da3;
+
+/* CR73 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr73_da3gain;
+
+/* CR74 - 6 */
+typedef enum {
+ AB8500_CODEC_CR74_FADEDIS_DA4_ENABLED,
+ AB8500_CODEC_CR74_FADEDIS_DA4_DISABLED
+} t_ab8500_codec_cr74_fadedis_da4;
+
+/* CR74 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr74_da4gain;
+
+/* CR75 - 6 */
+typedef enum {
+ AB8500_CODEC_CR75_FADEDIS_DA5_ENABLED,
+ AB8500_CODEC_CR75_FADEDIS_DA5_DISABLED
+} t_ab8500_codec_cr75_fadedis_da5;
+
+/* CR75 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr75_da5gain;
+
+/* CR76 - 6 */
+typedef enum {
+ AB8500_CODEC_CR76_FADEDIS_DA6_ENABLED,
+ AB8500_CODEC_CR76_FADEDIS_DA6_DISABLED
+} t_ab8500_codec_cr76_fadedis_da6;
+
+/* CR76 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr76_da6gain;
+
+/* CR77 - 6 */
+typedef enum {
+ AB8500_CODEC_CR77_FADEDIS_AD1L_TO_HFL_ENABLED,
+ AB8500_CODEC_CR77_FADEDIS_AD1L_TO_HFL_DISABLED
+} t_ab8500_codec_cr77_fadedis_ad1l;
+
+/* CR77 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr77_ad1lbgain_to_hfl;
+
+/* CR78 - 6 */
+typedef enum {
+ AB8500_CODEC_CR78_FADEDIS_AD2L_TO_HFR_ENABLED,
+ AB8500_CODEC_CR78_FADEDIS_AD2L_TO_HFR_DISABLED
+} t_ab8500_codec_cr78_fadedis_ad2l;
+
+/* CR78 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr78_ad2lbgain_to_hfr;
+
+/* CR79 - 7 */
+typedef enum {
+ AB8500_CODEC_CR79_HSSINC1_SINC3_CHOOSEN,
+ AB8500_CODEC_CR79_HSSINC1_SINC1_CHOOSEN
+} t_ab8500_codec_cr79_hssinc1;
+
+/* CR79 - 4 */
+typedef enum {
+ AB8500_CODEC_CR79_FADEDIS_HSL_ENABLED,
+ AB8500_CODEC_CR79_FADEDIS_HSL_DISABLED
+} t_ab8500_codec_cr79_fadedis_hsl;
+
+/* CR79 - 3:0 */
+typedef t_uint8 t_ab8500_codec_cr79_hsldgain;
+
+/* CR80 - 4 */
+typedef enum {
+ AB8500_CODEC_CR80_FADEDIS_HSR_ENABLED,
+ AB8500_CODEC_CR80_FADEDIS_HSR_DISABLED
+} t_ab8500_codec_cr80_fadedis_hsr;
+
+/* CR80 - 3:0 */
+typedef t_uint8 t_ab8500_codec_cr80_hsrdgain;
+
+/* CR81 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr81_stfir1gain;
+
+/* CR82 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr82_stfir2gain;
+
+/* CR83 - 2 */
+typedef enum {
+ AB8500_CODEC_CR83_ENANC_DISABLED,
+ AB8500_CODEC_CR83_ENANC_ENABLED
+} t_ab8500_codec_cr83_enanc;
+
+/* CR83 - 1 */
+typedef enum {
+ AB8500_CODEC_CR83_ANCIIRINIT_NOT_STARTED,
+ AB8500_CODEC_CR83_ANCIIRINIT_STARTED
+} t_ab8500_codec_cr83_anciirinit;
+
+/* CR83 - 0 */
+typedef enum {
+ AB8500_CODEC_CR83_ANCFIRUPDATE_RESETTED,
+ AB8500_CODEC_CR83_ANCFIRUPDATE_NOT_RESETTED
+} t_ab8500_codec_cr83_ancfirupdate;
+
+/* CR84 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr84_ancinshift;
+
+/* CR85 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr85_ancfiroutshift;
+
+/* CR86 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr86_ancshiftout;
+
+/* CR87 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr87_ancfircoeff_msb;
+
+/* CR88 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr88_ancfircoeff_lsb;
+
+/* CR89 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr89_anciircoeff_msb;
+
+/* CR90 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr90_anciircoeff_lsb;
+
+/* CR91 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr91_ancwarpdel_msb;
+
+/* CR92 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr92_ancwarpdel_lsb;
+
+/* CR93 - Read Only */
+/* CR93 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr93_ancfirpeak_msb;
+
+/* CR94 - Read Only */
+/* CR94 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr94_ancfirpeak_lsb;
+
+/* CR95 - Read Only */
+/* CR95 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr95_anciirpeak_msb;
+
+/* CR96 - Read Only */
+/* CR96 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr96_anciirpeak_lsb;
+
+/* CR97 - 7 */
+typedef enum {
+ AB8500_CODEC_CR97_STFIR_SET_LAST_NOT_APPLIED,
+ AB8500_CODEC_CR97_STFIR_SET_LAST_APPLIED
+} t_ab8500_codec_cr97_stfir_set;
+
+/* CR97 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr97_stfir_addr;
+
+/* CR98 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr98_stfir_coeff_msb;
+
+/* CR99 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr99_stfir_coeff_lsb;
+
+/* CR100 - 2 */
+typedef enum {
+ AB8500_CODEC_CR100_ENSTFIRS_DISABLED,
+ AB8500_CODEC_CR100_ENSTFIRS_ENABLED
+} t_ab8500_codec_cr100_enstfirs;
+
+/* CR100 - 1 */
+typedef enum {
+ AB8500_CODEC_CR100_STFIRSTOIF1_AUD_IF0_DATA_RATE,
+ AB8500_CODEC_CR100_STFIRSTOIF1_AUD_IF1_DATA_RATE
+} t_ab8500_codec_cr100_stfirstoif1;
+
+/* CR100 - 0 */
+typedef enum {
+ AB8500_CODEC_CR100_STFIR_BUSY_READY,
+ AB8500_CODEC_CR100_STFIR_BUSY_NOT_READY
+} t_ab8500_codec_cr100_stfir_busy;
+
+/* CR101 - 7 */
+typedef enum {
+ AB8500_CODEC_CR101_PARLHF_INDEPENDENT,
+ AB8500_CODEC_CR101_PARLHF_BRIDGED
+} t_ab8500_codec_cr101_parlhf;
+
+/* CR101 - 6 */
+typedef enum {
+ AB8500_CODEC_CR101_PARLVIB_INDEPENDENT,
+ AB8500_CODEC_CR101_PARLVIB_BRIDGED
+} t_ab8500_codec_cr101_parlvib;
+
+/* CR101 - 3 */
+typedef enum {
+ AB8500_CODEC_CR101_CLASSD_VIBLSWAPEN_DISABLED,
+ AB8500_CODEC_CR101_CLASSD_VIBLSWAPEN_ENABLED
+} t_ab8500_codec_cr101_classd_viblswapen;
+
+/* CR101 - 2 */
+typedef enum {
+ AB8500_CODEC_CR101_CLASSD_VIBRSWAPEN_DISABLED,
+ AB8500_CODEC_CR101_CLASSD_VIBRSWAPEN_ENABLED
+} t_ab8500_codec_cr101_classd_vibrswapen;
+
+/* CR101 - 1 */
+typedef enum {
+ AB8500_CODEC_CR101_CLASSD_HFLSWAPEN_DISABLED,
+ AB8500_CODEC_CR101_CLASSD_HFLSWAPEN_ENABLED
+} t_ab8500_codec_cr101_classd_hflswapen;
+
+/* CR101 - 0 */
+typedef enum {
+ AB8500_CODEC_CR101_CLASSD_HFRSWAPEN_DISABLED,
+ AB8500_CODEC_CR101_CLASSD_HFRSWAPEN_ENABLED
+} t_ab8500_codec_cr101_classd_hfrswapen;
+
+/* CR102 - 7:4 */
+typedef enum {
+ AB8500_CODEC_CR102_CLASSD_FIRBYP_ALL_ENABLED = 0,
+ AB8500_CODEC_CR102_CLASSD_FIRBYP_HFL_BYPASSED = 1,
+ AB8500_CODEC_CR102_CLASSD_FIRBYP_HFR_BYPASSED = 2,
+ AB8500_CODEC_CR102_CLASSD_FIRBYP_VIBL_BYPASSED = 4,
+ AB8500_CODEC_CR102_CLASSD_FIRBYP_VIBR_BYPASSED = 8
+} t_ab8500_codec_cr102_classd_firbyp;
+
+/* CR102 - 3:0 */
+typedef enum {
+ AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_DISABLED = 0,
+ AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_HFL_HIGHVOL = 1,
+ AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_HFR_HIGHVOL = 2,
+ AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_VIBL_HIGHVOL = 4,
+ AB8500_CODEC_CR102_CLASSD_HIGHVOLEN_VIBR_HIGHVOL = 8
+} t_ab8500_codec_cr102_classd_highvolen;
+
+/* CR103 - 7:4 */
+typedef t_uint8 t_ab8500_codec_cr103_classd_ditherhpgain;
+
+/* CR103 - 3:0 */
+typedef t_uint8 t_ab8500_codec_cr103_classd_ditherwgain;
+
+/* CR104 - 5:0 */
+/* In ab8500_codec.h */
+
+/* CR105 - 7:0 */
+/* In ab8500_codec.h */
+
+/* CR106 - 6:4 */
+/* In ab8500_codec.h */
+
+/* CR106 - 2 */
+/* In ab8500_codec.h */
+
+/* CR106 - 1 */
+/* In ab8500_codec.h */
+
+/* CR106 - 0 */
+/* In ab8500_codec.h */
+
+/* CR107 - 7:0 */
+/* In ab8500_codec.h */
+
+/* CR108 - 7:0 */
+/* In ab8500_codec.h */
+
+/* CR109 - Read Only */
+/* CR109 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr109_bfifosamples;
+
+typedef enum {
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT3,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT4,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT5,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT6,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT7,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT8,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_ZEROS,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_IS_TRISTATE = 15,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_UNDEFINED
+} t_ab8500_codec_cr31_to_cr46_ad_data_allocation;
+
+typedef enum {
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT00,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT01,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT02,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT03,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT04,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT05,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT06,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT07,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT08,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT09,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT10,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT11,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT12,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT13,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT14,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT15,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT16,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT17,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT18,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT19,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT20,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT21,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT22,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT23,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT24,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT25,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT26,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT27,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT28,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT29,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT30,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT31,
+ AB8500_CODEC_CR51_TO_CR56_SLTODA_SLOT_UNDEFINED
+} t_ab8500_codec_cr51_to_cr56_sltoda;
+
+/* CR104 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr104_bfifoint;
+
+/* CR105 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr105_bfifotx;
+
+/* CR106 - 6:4 */
+typedef enum {
+ AB8500_CODEC_CR106_BFIFOFSEXT_NO_EXTRA_CLK,
+ AB8500_CODEC_CR106_BFIFOFSEXT_1SLOT_EXTRA_CLK,
+ AB8500_CODEC_CR106_BFIFOFSEXT_2SLOT_EXTRA_CLK,
+ AB8500_CODEC_CR106_BFIFOFSEXT_3SLOT_EXTRA_CLK,
+ AB8500_CODEC_CR106_BFIFOFSEXT_4SLOT_EXTRA_CLK,
+ AB8500_CODEC_CR106_BFIFOFSEXT_5SLOT_EXTRA_CLK,
+ AB8500_CODEC_CR106_BFIFOFSEXT_6SLOT_EXTRA_CLK
+} t_ab8500_codec_cr106_bfifofsext;
+
+/* CR106 - 2 */
+typedef enum {
+ AB8500_CODEC_CR106_BFIFOMSK_AD_DATA0_UNMASKED,
+ AB8500_CODEC_CR106_BFIFOMSK_AD_DATA0_MASKED
+} t_ab8500_codec_cr106_bfifomsk;
+
+/* CR106 - 1 */
+typedef enum {
+ AB8500_CODEC_CR106_BFIFOMSTR_SLAVE_MODE,
+ AB8500_CODEC_CR106_BFIFOMSTR_MASTER_MODE
+} t_ab8500_codec_cr106_bfifomstr;
+
+/* CR106 - 0 */
+typedef enum {
+ AB8500_CODEC_CR106_BFIFOSTRT_STOPPED,
+ AB8500_CODEC_CR106_BFIFOSTRT_RUNNING
+} t_ab8500_codec_cr106_bfifostrt;
+
+/* CR107 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr107_bfifosampnr;
+
+/* CR108 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr108_bfifowakeup;
+
+/*configuration structure for AB8500 Codec*/
+typedef struct {
+ /* CR0 */
+ t_ab8500_codec_cr0_powerup cr0_powerup;
+ t_ab8500_codec_cr0_enaana cr0_enaana;
+
+ /* CR1 */
+ t_ab8500_codec_cr1_swreset cr1_swreset;
+
+ /* CR2 */
+ t_ab8500_codec_cr2_enad1 cr2_enad1;
+ t_ab8500_codec_cr2_enad2 cr2_enad2;
+ t_ab8500_codec_cr2_enad3 cr2_enad3;
+ t_ab8500_codec_cr2_enad4 cr2_enad4;
+ t_ab8500_codec_cr2_enad5 cr2_enad5;
+ t_ab8500_codec_cr2_enad6 cr2_enad6;
+
+ /* CR3 */
+ t_ab8500_codec_cr3_enda1 cr3_enda1;
+ t_ab8500_codec_cr3_enda2 cr3_enda2;
+ t_ab8500_codec_cr3_enda3 cr3_enda3;
+ t_ab8500_codec_cr3_enda4 cr3_enda4;
+ t_ab8500_codec_cr3_enda5 cr3_enda5;
+ t_ab8500_codec_cr3_enda6 cr3_enda6;
+
+ /* CR4 */
+ t_ab8500_codec_cr4_lowpowhs cr4_lowpowhs;
+ t_ab8500_codec_cr4_lowpowdachs cr4_lowpowdachs;
+ t_ab8500_codec_cr4_lowpowear cr4_lowpowear;
+ t_ab8500_codec_cr4_ear_sel_cm cr4_ear_sel_cm;
+ t_ab8500_codec_cr4_hs_hp_dis cr4_hs_hp_dis;
+ t_ab8500_codec_cr4_ear_hp_dis cr4_ear_hp_dis;
+
+ /* CR5 */
+ t_ab8500_codec_cr5_enmic1 cr5_enmic1;
+ t_ab8500_codec_cr5_enmic2 cr5_enmic2;
+ t_ab8500_codec_cr5_enlinl cr5_enlinl;
+ t_ab8500_codec_cr5_enlinr cr5_enlinr;
+ t_ab8500_codec_cr5_mutmic1 cr5_mutmic1;
+ t_ab8500_codec_cr5_mutmic2 cr5_mutmic2;
+ t_ab8500_codec_cr5_mutlinl cr5_mutlinl;
+ t_ab8500_codec_cr5_mutlinr cr5_mutlinr;
+
+ /* CR6 */
+ t_ab8500_codec_cr6_endmic1 cr6_endmic1;
+ t_ab8500_codec_cr6_endmic2 cr6_endmic2;
+ t_ab8500_codec_cr6_endmic3 cr6_endmic3;
+ t_ab8500_codec_cr6_endmic4 cr6_endmic4;
+ t_ab8500_codec_cr6_endmic5 cr6_endmic5;
+ t_ab8500_codec_cr6_endmic6 cr6_endmic6;
+
+ /* CR7 */
+ t_ab8500_codec_cr7_mic1sel cr7_mic1sel;
+ t_ab8500_codec_cr7_linrsel cr7_linrsel;
+ t_ab8500_codec_cr7_endrvhsl cr7_endrvhsl;
+ t_ab8500_codec_cr7_endrvhsr cr7_endrvhsr;
+ t_ab8500_codec_cr7_enadcmic cr7_enadcmic;
+ t_ab8500_codec_cr7_enadclinl cr7_enadclinl;
+ t_ab8500_codec_cr7_enadclinr cr7_enadclinr;
+
+ /* CR8 */
+ t_ab8500_codec_cr8_cp_dis_pldwn cr8_cp_dis_pldwn;
+ t_ab8500_codec_cr8_enear cr8_enear;
+ t_ab8500_codec_cr8_enhsl cr8_enhsl;
+ t_ab8500_codec_cr8_enhsr cr8_enhsr;
+ t_ab8500_codec_cr8_enhfl cr8_enhfl;
+ t_ab8500_codec_cr8_enhfr cr8_enhfr;
+ t_ab8500_codec_cr8_envibl cr8_envibl;
+ t_ab8500_codec_cr8_envibr cr8_envibr;
+
+ /* CR9 */
+ t_ab8500_codec_cr9_endacear cr9_endacear;
+ t_ab8500_codec_cr9_endachsl cr9_endachsl;
+ t_ab8500_codec_cr9_endachsr cr9_endachsr;
+ t_ab8500_codec_cr9_endachfl cr9_endachfl;
+ t_ab8500_codec_cr9_endachfr cr9_endachfr;
+ t_ab8500_codec_cr9_endacvibl cr9_endacvibl;
+ t_ab8500_codec_cr9_endacvibr cr9_endacvibr;
+
+ /* CR10 */
+ t_ab8500_codec_cr10_muteear cr10_muteear;
+ t_ab8500_codec_cr10_mutehsl cr10_mutehsl;
+ t_ab8500_codec_cr10_mutehsr cr10_mutehsr;
+ t_ab8500_codec_cr10_mutehfl cr10_mutehfl;
+ t_ab8500_codec_cr10_mutehfr cr10_mutehfr;
+ t_ab8500_codec_cr10_mutevibl cr10_mutevibl;
+ t_ab8500_codec_cr10_mutevibr cr10_mutevibr;
+
+ /* CR11 */
+ t_ab8500_codec_cr11_earshortpwd cr11_earshortpwd;
+ t_ab8500_codec_cr11_earshortdis cr11_earshortdis;
+ t_ab8500_codec_cr11_hslshortdis cr11_hslshortdis;
+ t_ab8500_codec_cr11_hsrshortdis cr11_hsrshortdis;
+ t_ab8500_codec_cr11_hflshortdis cr11_hflshortdis;
+ t_ab8500_codec_cr11_hfrshortdis cr11_hfrshortdis;
+ t_ab8500_codec_cr11_viblshortdis cr11_viblshortdis;
+ t_ab8500_codec_cr11_vibrshortdis cr11_vibrshortdis;
+
+ /* CR12 */
+ t_ab8500_codec_cr12_encphs cr12_encphs;
+ t_ab8500_codec_cr12_hsautotime cr12_hsautotime;
+ t_ab8500_codec_cr12_hsautoensel cr12_hsautoensel;
+ t_ab8500_codec_cr12_hsautoen cr12_hsautoen;
+
+ /* CR13 */
+ t_ab8500_codec_cr13_envdet_hthresh cr13_envdet_hthresh;
+ t_ab8500_codec_cr13_envdet_lthresh cr13_envdet_lthresh;
+
+ /* CR14 */
+ t_ab8500_codec_cr14_smpslven cr14_smpslven;
+ t_ab8500_codec_cr14_envdetsmpsen cr14_envdetsmpsen;
+ t_ab8500_codec_cr14_cplven cr14_cplven;
+ t_ab8500_codec_cr14_envdetcpen cr14_envdetcpen;
+ t_ab8500_codec_cr14_envet_time cr14_envet_time;
+
+ /* CR15 */
+ t_ab8500_codec_cr15_pwmtovibl cr15_pwmtovibl;
+ t_ab8500_codec_cr15_pwmtovibr cr15_pwmtovibr;
+ t_ab8500_codec_cr15_pwmlctrl cr15_pwmlctrl;
+ t_ab8500_codec_cr15_pwmrctrl cr15_pwmrctrl;
+ t_ab8500_codec_cr15_pwmnlctrl cr15_pwmnlctrl;
+ t_ab8500_codec_cr15_pwmplctrl cr15_pwmplctrl;
+ t_ab8500_codec_cr15_pwmnrctrl cr15_pwmnrctrl;
+ t_ab8500_codec_cr15_pwmprctrl cr15_pwmprctrl;
+
+ /* CR16 */
+ t_ab8500_codec_cr16_pwmnlpol cr16_pwmnlpol;
+ t_ab8500_codec_cr16_pwmnldutycycle cr16_pwmnldutycycle;
+
+ /* CR17 */
+ t_ab8500_codec_cr17_pwmplpol cr17_pwmplpol;
+ t_ab8500_codec_cr17_pwmpldutycycle cr17_pwmpldutycycle;
+
+ /* CR18 */
+ t_ab8500_codec_cr18_pwmnrpol cr18_pwmnrpol;
+ t_ab8500_codec_cr18_pwmnrdutycycle cr18_pwmnrdutycycle;
+
+ /* CR19 */
+ t_ab8500_codec_cr19_pwmprpol cr19_pwmprpol;
+ t_ab8500_codec_cr19_pwmprdutycycle cr19_pwmprdutycycle;
+
+ /* CR20 */
+ t_ab8500_codec_cr20_en_se_mic1 cr20_en_se_mic1;
+ t_ab8500_codec_cr20_mic1_gain cr20_mic1_gain;
+
+ /* CR21 */
+ t_ab8500_codec_cr21_en_se_mic2 cr21_en_se_mic2;
+ t_ab8500_codec_cr21_mic2_gain cr21_mic2_gain;
+
+ /* CR22 */
+ t_ab8500_codec_cr22_hsl_gain cr22_hsl_gain;
+ t_ab8500_codec_cr22_linl_gain cr22_linl_gain;
+
+ /* CR23 */
+ t_ab8500_codec_cr23_hsr_gain cr23_hsr_gain;
+ t_ab8500_codec_cr23_linr_gain cr23_linr_gain;
+
+ /* CR24 */
+ t_ab8500_codec_cr24_lintohsl_gain cr24_lintohsl_gain;
+
+ /* CR25 */
+ t_ab8500_codec_cr25_lintohsr_gain cr25_lintohsr_gain;
+
+ /* CR26 */
+ t_ab8500_codec_cr26_ad1nh cr26_ad1nh;
+ t_ab8500_codec_cr26_ad2nh cr26_ad2nh;
+ t_ab8500_codec_cr26_ad3nh cr26_ad3nh;
+ t_ab8500_codec_cr26_ad4nh cr26_ad4nh;
+ t_ab8500_codec_cr26_ad1_voice cr26_ad1_voice;
+ t_ab8500_codec_cr26_ad2_voice cr26_ad2_voice;
+ t_ab8500_codec_cr26_ad3_voice cr26_ad3_voice;
+ t_ab8500_codec_cr26_ad4_voice cr26_ad4_voice;
+
+ /* CR27 */
+ t_ab8500_codec_cr27_en_mastgen cr27_en_mastgen;
+ t_ab8500_codec_cr27_if1_bitclk_osr cr27_if1_bitclk_osr;
+ t_ab8500_codec_cr27_enfs_bitclk1 cr27_enfs_bitclk1;
+ t_ab8500_codec_cr27_if0_bitclk_osr cr27_if0_bitclk_osr;
+ t_ab8500_codec_cr27_enfs_bitclk0 cr27_enfs_bitclk0;
+
+ /* CR28 */
+ t_ab8500_codec_cr28_fsync0p cr28_fsync0p;
+ t_ab8500_codec_cr28_bitclk0p cr28_bitclk0p;
+ t_ab8500_codec_cr28_if0del cr28_if0del;
+ t_ab8500_codec_cr28_if0format cr28_if0format;
+ t_ab8500_codec_cr28_if0wl cr28_if0wl;
+
+ /* CR29 */
+ t_ab8500_codec_cr29_if0datoif1ad cr29_if0datoif1ad;
+ t_ab8500_codec_cr29_if0cktoif1ck cr29_if0cktoif1ck;
+ t_ab8500_codec_cr29_if1master cr29_if1master;
+ t_ab8500_codec_cr29_if1datoif0ad cr29_if1datoif0ad;
+ t_ab8500_codec_cr29_if1cktoif0ck cr29_if1cktoif0ck;
+ t_ab8500_codec_cr29_if0master cr29_if0master;
+ t_ab8500_codec_cr29_if0bfifoen cr29_if0bfifoen;
+
+ /* CR30 */
+ t_ab8500_codec_cr30_fsync1p cr30_fsync1p;
+ t_ab8500_codec_cr30_bitclk1p cr30_bitclk1p;
+ t_ab8500_codec_cr30_if1del cr30_if1del;
+ t_ab8500_codec_cr30_if1format cr30_if1format;
+ t_ab8500_codec_cr30_if1wl cr30_if1wl;
+
+ /* CR31 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr31_adotoslot1;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr31_adotoslot0;
+
+ /* CR32 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr32_adotoslot3;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr32_adotoslot2;
+
+ /* CR33 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr33_adotoslot5;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr33_adotoslot4;
+
+ /* CR34 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr34_adotoslot7;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr34_adotoslot6;
+
+ /* CR35 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr35_adotoslot9;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr35_adotoslot8;
+
+ /* CR36 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr36_adotoslot11;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr36_adotoslot10;
+
+ /* CR37 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr37_adotoslot13;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr37_adotoslot12;
+
+ /* CR38 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr38_adotoslot15;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr38_adotoslot14;
+
+ /* CR39 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr39_adotoslot17;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr39_adotoslot16;
+
+ /* CR40 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr40_adotoslot19;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr40_adotoslot18;
+
+ /* CR41 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr41_adotoslot21;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr41_adotoslot20;
+
+ /* CR42 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr42_adotoslot23;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr42_adotoslot22;
+
+ /* CR43 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr43_adotoslot25;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr43_adotoslot24;
+
+ /* CR44 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr44_adotoslot27;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr44_adotoslot26;
+
+ /* CR45 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr45_adotoslot29;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr45_adotoslot28;
+
+ /* CR46 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr46_adotoslot31;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr46_adotoslot30;
+
+ /* CR47 */
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl7;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl6;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl5;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl4;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl3;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl2;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl1;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl0;
+
+ /* CR48 */
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl15;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl14;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl13;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl12;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl11;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl10;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl9;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl8;
+
+ /* CR49 */
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl23;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl22;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl21;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl20;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl19;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl18;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl17;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl16;
+
+ /* CR50 */
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl31;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl30;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl29;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl28;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl27;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl26;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl25;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl24;
+
+ /* CR51 */
+ t_ab8500_codec_cr51_da12_voice cr51_da12_voice;
+ t_ab8500_codec_cr51_sldai1toslado1 cr51_sldai1toslado1;
+ t_ab8500_codec_cr51_to_cr56_sltoda cr51_sltoda1;
+
+ /* CR52 */
+ t_ab8500_codec_cr52_sldai2toslado2 cr52_sldai2toslado2;
+ t_ab8500_codec_cr51_to_cr56_sltoda cr52_sltoda2;
+
+ /* CR53 */
+ t_ab8500_codec_cr53_da34_voice cr53_da34_voice;
+ t_ab8500_codec_cr53_sldai3toslado3 cr53_sldai3toslado3;
+ t_ab8500_codec_cr51_to_cr56_sltoda cr53_sltoda3;
+
+ /* CR54 */
+ t_ab8500_codec_cr54_sldai4toslado4 cr54_sldai4toslado4;
+ t_ab8500_codec_cr51_to_cr56_sltoda cr54_sltoda4;
+
+ /* CR55 */
+ t_ab8500_codec_cr55_da56_voice cr55_da56_voice;
+ t_ab8500_codec_cr55_sldai5toslado5 cr55_sldai5toslado5;
+ t_ab8500_codec_cr51_to_cr56_sltoda cr55_sltoda5;
+
+ /* CR56 */
+ t_ab8500_codec_cr56_sldai6toslado7 cr56_sldai6toslado7;
+ t_ab8500_codec_cr51_to_cr56_sltoda cr56_sltoda6;
+
+ /* CR57 */
+ t_ab8500_codec_cr57_bfifull_msk cr57_bfifull_msk;
+ t_ab8500_codec_cr57_bfiempt_msk cr57_bfiempt_msk;
+ t_ab8500_codec_cr57_dachan_msk cr57_dachan_msk;
+ t_ab8500_codec_cr57_gain_msk cr57_gain_msk;
+ t_ab8500_codec_cr57_dspad_msk cr57_dspad_msk;
+ t_ab8500_codec_cr57_dspda_msk cr57_dspda_msk;
+ t_ab8500_codec_cr57_stfir_msk cr57_stfir_msk;
+
+ /* CR58 */
+ t_ab8500_codec_cr58_bfifull_ev cr58_bfifull_ev;
+ t_ab8500_codec_cr58_bfiempt_ev cr58_bfiempt_ev;
+ t_ab8500_codec_cr58_dachan_ev cr58_dachan_ev;
+ t_ab8500_codec_cr58_gain_ev cr58_gain_ev;
+ t_ab8500_codec_cr58_dspad_ev cr58_dspad_ev;
+ t_ab8500_codec_cr58_dspda_ev cr58_dspda_ev;
+ t_ab8500_codec_cr58_stfir_ev cr58_stfir_ev;
+
+ /* CR59 */
+ t_ab8500_codec_cr59_vssready_msk cr59_vssready_msk;
+ t_ab8500_codec_cr59_shrtvibl_msk cr59_shrtvibl_msk;
+ t_ab8500_codec_cr59_shrtvibr_msk cr59_shrtvibr_msk;
+ t_ab8500_codec_cr59_shrthfl_msk cr59_shrthfl_msk;
+ t_ab8500_codec_cr59_shrthfr_msk cr59_shrthfr_msk;
+ t_ab8500_codec_cr59_shrthsl_msk cr59_shrthsl_msk;
+ t_ab8500_codec_cr59_shrthsr_msk cr59_shrthsr_msk;
+ t_ab8500_codec_cr59_shrtear_msk cr59_shrtear_msk;
+
+ /* CR60 */
+ t_ab8500_codec_cr60_vssready_ev cr60_vssready_ev;
+ t_ab8500_codec_cr60_shrtvibl_ev cr60_shrtvibl_ev;
+ t_ab8500_codec_cr60_shrtvibr_ev cr60_shrtvibr_ev;
+ t_ab8500_codec_cr60_shrthfl_ev cr60_shrthfl_ev;
+ t_ab8500_codec_cr60_shrthfr_ev cr60_shrthfr_ev;
+ t_ab8500_codec_cr60_shrthsl_ev cr60_shrthsl_ev;
+ t_ab8500_codec_cr60_shrthsr_ev cr60_shrthsr_ev;
+ t_ab8500_codec_cr60_shrtear_ev cr60_shrtear_ev;
+
+ /* CR61 */
+ t_ab8500_codec_cr61_revision cr61_revision;
+ t_ab8500_codec_cr61_fade_speed cr61_fade_speed;
+
+ /* CR62 */
+ t_ab8500_codec_cr62_dmic1sinc3 cr62_dmic1sinc3;
+ t_ab8500_codec_cr62_dmic2sinc3 cr62_dmic2sinc3;
+ t_ab8500_codec_cr62_dmic3sinc3 cr62_dmic3sinc3;
+ t_ab8500_codec_cr62_dmic4sinc3 cr62_dmic4sinc3;
+ t_ab8500_codec_cr62_dmic5sinc3 cr62_dmic5sinc3;
+ t_ab8500_codec_cr62_dmic6sinc3 cr62_dmic6sinc3;
+
+ /* CR63 */
+ t_ab8500_codec_cr63_datohslen cr63_datohslen;
+ t_ab8500_codec_cr63_datohsren cr63_datohsren;
+ t_ab8500_codec_cr63_ad1sel cr63_ad1sel;
+ t_ab8500_codec_cr63_ad2sel cr63_ad2sel;
+ t_ab8500_codec_cr63_ad3sel cr63_ad3sel;
+ t_ab8500_codec_cr63_ad5sel cr63_ad5sel;
+ t_ab8500_codec_cr63_ad6sel cr63_ad6sel;
+ t_ab8500_codec_cr63_ancsel cr63_ancsel;
+
+ /* CR64 */
+ t_ab8500_codec_cr64_datohfren cr64_datohfren;
+ t_ab8500_codec_cr64_datohflen cr64_datohflen;
+ t_ab8500_codec_cr64_hfrsel cr64_hfrsel;
+ t_ab8500_codec_cr64_hflsel cr64_hflsel;
+ t_ab8500_codec_cr64_stfir1sel cr64_stfir1sel;
+ t_ab8500_codec_cr64_stfir2sel cr64_stfir2sel;
+
+ /* CR65 */
+ t_ab8500_codec_cr65_fadedis_ad1 cr65_fadedis_ad1;
+ t_ab8500_codec_cr65_ad1gain cr65_ad1gain;
+
+ /* CR66 */
+ t_ab8500_codec_cr66_fadedis_ad2 cr66_fadedis_ad2;
+ t_ab8500_codec_cr66_ad2gain cr66_ad2gain;
+
+ /* CR67 */
+ t_ab8500_codec_cr67_fadedis_ad3 cr67_fadedis_ad3;
+ t_ab8500_codec_cr67_ad3gain cr67_ad3gain;
+
+ /* CR68 */
+ t_ab8500_codec_cr68_fadedis_ad4 cr68_fadedis_ad4;
+ t_ab8500_codec_cr68_ad4gain cr68_ad4gain;
+
+ /* CR69 */
+ t_ab8500_codec_cr69_fadedis_ad5 cr69_fadedis_ad5;
+ t_ab8500_codec_cr69_ad5gain cr69_ad5gain;
+
+ /* CR70 */
+ t_ab8500_codec_cr70_fadedis_ad6 cr70_fadedis_ad6;
+ t_ab8500_codec_cr70_ad6gain cr70_ad6gain;
+
+ /* CR71 */
+ t_ab8500_codec_cr71_fadedis_da1 cr71_fadedis_da1;
+ t_ab8500_codec_cr71_da1gain cr71_da1gain;
+
+ /* CR72 */
+ t_ab8500_codec_cr72_fadedis_da2 cr72_fadedis_da2;
+ t_ab8500_codec_cr72_da2gain cr72_da2gain;
+
+ /* CR73 */
+ t_ab8500_codec_cr73_fadedis_da3 cr73_fadedis_da3;
+ t_ab8500_codec_cr73_da3gain cr73_da3gain;
+
+ /* CR74 */
+ t_ab8500_codec_cr74_fadedis_da4 cr74_fadedis_da4;
+ t_ab8500_codec_cr74_da4gain cr74_da4gain;
+
+ /* CR75 */
+ t_ab8500_codec_cr75_fadedis_da5 cr75_fadedis_da5;
+ t_ab8500_codec_cr75_da5gain cr75_da5gain;
+
+ /* CR76 */
+ t_ab8500_codec_cr76_fadedis_da6 cr76_fadedis_da6;
+ t_ab8500_codec_cr76_da6gain cr76_da6gain;
+
+ /* CR77 */
+ t_ab8500_codec_cr77_fadedis_ad1l cr77_fadedis_ad1l;
+ t_ab8500_codec_cr77_ad1lbgain_to_hfl cr77_ad1lbgain_to_hfl;
+
+ /* CR78 */
+ t_ab8500_codec_cr78_fadedis_ad2l cr78_fadedis_ad2l;
+ t_ab8500_codec_cr78_ad2lbgain_to_hfr cr78_ad2lbgain_to_hfr;
+
+ /* CR79 */
+ t_ab8500_codec_cr79_hssinc1 cr79_hssinc1;
+ t_ab8500_codec_cr79_fadedis_hsl cr79_fadedis_hsl;
+ t_ab8500_codec_cr79_hsldgain cr79_hsldgain;
+
+ /* CR80 */
+ t_ab8500_codec_cr80_fadedis_hsr cr80_fadedis_hsr;
+ t_ab8500_codec_cr80_hsrdgain cr80_hsrdgain;
+
+ /* CR81 */
+ t_ab8500_codec_cr81_stfir1gain cr81_stfir1gain;
+
+ /* CR82 */
+ t_ab8500_codec_cr82_stfir2gain cr82_stfir2gain;
+
+ /* CR83 */
+ t_ab8500_codec_cr83_enanc cr83_enanc;
+ t_ab8500_codec_cr83_anciirinit cr83_anciirinit;
+ t_ab8500_codec_cr83_ancfirupdate cr83_ancfirupdate;
+
+ /* CR84 */
+ t_ab8500_codec_cr84_ancinshift cr84_ancinshift;
+
+ /* CR85 */
+ t_ab8500_codec_cr85_ancfiroutshift cr85_ancfiroutshift;
+
+ /* CR86 */
+ t_ab8500_codec_cr86_ancshiftout cr86_ancshiftout;
+
+ /* CR87 */
+ t_ab8500_codec_cr87_ancfircoeff_msb cr87_ancfircoeff_msb;
+
+ /* CR88 */
+ t_ab8500_codec_cr88_ancfircoeff_lsb cr88_ancfircoeff_lsb;
+
+ /* CR89 */
+ t_ab8500_codec_cr89_anciircoeff_msb cr89_anciircoeff_msb;
+
+ /* CR90 */
+ t_ab8500_codec_cr90_anciircoeff_lsb cr90_anciircoeff_lsb;
+
+ /* CR91 */
+ t_ab8500_codec_cr91_ancwarpdel_msb cr91_ancwarpdel_msb;
+
+ /* CR92 */
+ t_ab8500_codec_cr92_ancwarpdel_lsb cr92_ancwarpdel_lsb;
+
+ /* CR93 */
+ t_ab8500_codec_cr93_ancfirpeak_msb cr93_ancfirpeak_msb;
+
+ /* CR94 */
+ t_ab8500_codec_cr94_ancfirpeak_lsb cr94_ancfirpeak_lsb;
+
+ /* CR95 */
+ t_ab8500_codec_cr95_anciirpeak_msb cr95_anciirpeak_msb;
+
+ /* CR96 */
+ t_ab8500_codec_cr96_anciirpeak_lsb cr96_anciirpeak_lsb;
+
+ /* CR97 */
+ t_ab8500_codec_cr97_stfir_set cr97_stfir_set;
+ t_ab8500_codec_cr97_stfir_addr cr97_stfir_addr;
+
+ /* CR98 */
+ t_ab8500_codec_cr98_stfir_coeff_msb cr98_stfir_coeff_msb;
+
+ /* CR99 */
+ t_ab8500_codec_cr99_stfir_coeff_lsb cr99_stfir_coeff_lsb;
+
+ /* CR100 */
+ t_ab8500_codec_cr100_enstfirs cr100_enstfirs;
+ t_ab8500_codec_cr100_stfirstoif1 cr100_stfirstoif1;
+ t_ab8500_codec_cr100_stfir_busy cr100_stfir_busy;
+
+ /* CR101 */
+ t_ab8500_codec_cr101_parlhf cr101_parlhf;
+ t_ab8500_codec_cr101_parlvib cr101_parlvib;
+ t_ab8500_codec_cr101_classd_viblswapen cr101_classd_viblswapen;
+ t_ab8500_codec_cr101_classd_vibrswapen cr101_classd_vibrswapen;
+ t_ab8500_codec_cr101_classd_hflswapen cr101_classd_hflswapen;
+ t_ab8500_codec_cr101_classd_hfrswapen cr101_classd_hfrswapen;
+
+ /* CR102 */
+ t_ab8500_codec_cr102_classd_firbyp cr102_classd_firbyp;
+ t_ab8500_codec_cr102_classd_highvolen cr102_classd_highvolen;
+
+ /* CR103 */
+ t_ab8500_codec_cr103_classd_ditherhpgain cr103_classd_ditherhpgain;
+ t_ab8500_codec_cr103_classd_ditherwgain cr103_classd_ditherwgain;
+
+ /* CR104 */
+ t_ab8500_codec_cr104_bfifoint cr104_bfifoint;
+
+ /* CR105 */
+ t_ab8500_codec_cr105_bfifotx cr105_bfifotx;
+
+ /* CR106 */
+ t_ab8500_codec_cr106_bfifofsext cr106_bfifofsext;
+ t_ab8500_codec_cr106_bfifomsk cr106_bfifomsk;
+ t_ab8500_codec_cr106_bfifomstr cr106_bfifomstr;
+ t_ab8500_codec_cr106_bfifostrt cr106_bfifostrt;
+
+ /* CR107 */
+ t_ab8500_codec_cr107_bfifosampnr cr107_bfifosampnr;
+
+ /* CR108 */
+ t_ab8500_codec_cr108_bfifowakeup cr108_bfifowakeup;
+
+ /* CR109 */
+ t_ab8500_codec_cr109_bfifosamples cr109_bfifosamples;
+
+} t_ab8500_codec_configuration;
+
+typedef enum {
+ AB8500_CODEC_DIRECTION_IN,
+ AB8500_CODEC_DIRECTION_OUT,
+ AB8500_CODEC_DIRECTION_INOUT
+} t_ab8500_codec_direction;
+
+typedef enum {
+ AB8500_CODEC_MODE_HIFI,
+ AB8500_CODEC_MODE_VOICE,
+ AB8500_CODEC_MODE_MANUAL_SETTING
+} t_ab8500_codec_mode;
+
+typedef enum {
+ AB8500_CODEC_AUDIO_INTERFACE_0,
+ AB8500_CODEC_AUDIO_INTERFACE_1
+} t_ab8500_codec_audio_interface;
+
+typedef enum {
+ AB8500_CODEC_SRC_LINEIN,
+ AB8500_CODEC_SRC_MICROPHONE_1A,
+ AB8500_CODEC_SRC_MICROPHONE_1B,
+ AB8500_CODEC_SRC_MICROPHONE_2,
+ AB8500_CODEC_SRC_D_MICROPHONE_1,
+ AB8500_CODEC_SRC_D_MICROPHONE_2,
+ AB8500_CODEC_SRC_D_MICROPHONE_3,
+ AB8500_CODEC_SRC_D_MICROPHONE_4,
+ AB8500_CODEC_SRC_D_MICROPHONE_5,
+ AB8500_CODEC_SRC_D_MICROPHONE_6,
+ AB8500_CODEC_SRC_FM_RX,
+ AB8500_CODEC_SRC_ALL
+} t_ab8500_codec_src;
+
+typedef enum {
+ AB8500_CODEC_DEST_HEADSET,
+ AB8500_CODEC_DEST_EARPIECE,
+ AB8500_CODEC_DEST_HANDSFREE,
+ AB8500_CODEC_DEST_VIBRATOR_L,
+ AB8500_CODEC_DEST_VIBRATOR_R,
+ AB8500_CODEC_DEST_ALL
+} t_ab8500_codec_dest;
+
+typedef struct {
+ t_uint8 slave_address_of_ab8500_codec;
+ t_ab8500_codec_direction ab8500_codec_direction;
+ t_ab8500_codec_mode ab8500_codec_mode_in;
+ t_ab8500_codec_mode ab8500_codec_mode_out;
+ t_ab8500_codec_audio_interface audio_interface;
+ t_ab8500_codec_src ab8500_codec_src;
+ t_ab8500_codec_dest ab8500_codec_dest;
+ t_uint8 in_left_volume;
+ t_uint8 in_right_volume;
+ t_uint8 out_left_volume;
+ t_uint8 out_right_volume;
+
+ t_ab8500_codec_configuration ab8500_codec_configuration;
+} t_ab8500_codec_system_context;
+#endif /* _AB8500_CODECP_H_ */
+
+/* End of file AB8500_CODECP.h */
diff --git a/arch/arm/mach-ux500/include/mach/ab8500_codec_p_v1_0.h b/arch/arm/mach-ux500/include/mach/ab8500_codec_p_v1_0.h
new file mode 100644
index 00000000000..866cd0c80f1
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ab8500_codec_p_v1_0.h
@@ -0,0 +1,3037 @@
+/*****************************************************************************/
+/**
+* © ST-Ericsson, 2009 - All rights reserved
+* Reproduction and Communication of this document is strictly prohibited
+* unless specifically authorized in writing by ST-Ericsson
+*
+* \brief Private Header file for AB8500 CODEC
+* \author ST-Ericsson
+*/
+/*****************************************************************************/
+
+#ifndef _AB8500_CODECP_V1_0_H_
+#define _AB8500_CODECP_V1_0_H_
+
+/*----------------------------------------------------------------------------
+ * Includes
+ *---------------------------------------------------------------------------*/
+#include "hcl_defs.h"
+
+#define AB8500_CODEC_HCL_VERSION_ID 3
+#define AB8500_CODEC_HCL_MAJOR_ID 0
+#define AB8500_CODEC_HCL_MINOR_ID 0
+
+#define AB8500_CODEC_MASK_ONE_BIT 0x1UL
+#define AB8500_CODEC_MASK_TWO_BITS 0x3UL
+#define AB8500_CODEC_MASK_THREE_BITS 0x7UL
+#define AB8500_CODEC_MASK_FOUR_BITS 0xFUL
+#define AB8500_CODEC_MASK_FIVE_BITS 0x1FUL
+#define AB8500_CODEC_MASK_SIX_BITS 0x3FUL
+#define AB8500_CODEC_MASK_SEVEN_BITS 0x7FUL
+#define AB8500_CODEC_MASK_EIGHT_BITS 0xFFUL
+
+#define AB8500_CODEC_WRITE_BITS(reg, val, bit_nb, pos) (reg) = ((t_uint8) ((((reg) & (~(bit_nb << pos))) | (((val) & bit_nb) << pos))))
+
+#define AB8500_CODEC_BLOCK 0x0D
+
+#define AB8500_CODEC_MASK_TWO_MS_BITS 0xC0UL
+#define AB8500_CODEC_MASK_SIX_LS_BITS 0x3FUL
+
+/* Genepi AudioCodec Control Registers */
+
+#define AB8500_CODEC_CR0 0x00
+#define AB8500_CODEC_CR1 0x01
+#define AB8500_CODEC_CR2 0x02
+#define AB8500_CODEC_CR3 0x03
+#define AB8500_CODEC_CR4 0x04
+#define AB8500_CODEC_CR5 0x05
+#define AB8500_CODEC_CR6 0x06
+#define AB8500_CODEC_CR7 0x07
+#define AB8500_CODEC_CR8 0x08
+#define AB8500_CODEC_CR9 0x09
+#define AB8500_CODEC_CR10 0x0A
+#define AB8500_CODEC_CR11 0x0B
+#define AB8500_CODEC_CR12 0x0C
+#define AB8500_CODEC_CR13 0x0D
+#define AB8500_CODEC_CR14 0x0E
+#define AB8500_CODEC_CR15 0x0F
+#define AB8500_CODEC_CR16 0x10
+#define AB8500_CODEC_CR17 0x11
+#define AB8500_CODEC_CR18 0x12
+#define AB8500_CODEC_CR19 0x13
+#define AB8500_CODEC_CR20 0x14
+#define AB8500_CODEC_CR21 0x15
+#define AB8500_CODEC_CR22 0x16
+#define AB8500_CODEC_CR23 0x17
+#define AB8500_CODEC_CR24 0x18
+#define AB8500_CODEC_CR25 0x19
+#define AB8500_CODEC_CR26 0x1A
+#define AB8500_CODEC_CR27 0x1B
+#define AB8500_CODEC_CR28 0x1C
+#define AB8500_CODEC_CR29 0x1D
+#define AB8500_CODEC_CR30 0x1E
+#define AB8500_CODEC_CR31 0x1F
+#define AB8500_CODEC_CR32 0x20
+#define AB8500_CODEC_CR33 0x21
+#define AB8500_CODEC_CR34 0x22
+#define AB8500_CODEC_CR35 0x23
+#define AB8500_CODEC_CR36 0x24
+#define AB8500_CODEC_CR37 0x25
+#define AB8500_CODEC_CR38 0x26
+#define AB8500_CODEC_CR39 0x27
+#define AB8500_CODEC_CR40 0x28
+#define AB8500_CODEC_CR41 0x29
+#define AB8500_CODEC_CR42 0x2A
+#define AB8500_CODEC_CR43 0x2B
+#define AB8500_CODEC_CR44 0x2C
+#define AB8500_CODEC_CR45 0x2D
+#define AB8500_CODEC_CR46 0x2E
+#define AB8500_CODEC_CR47 0x2F
+#define AB8500_CODEC_CR48 0x30
+#define AB8500_CODEC_CR49 0x31
+#define AB8500_CODEC_CR50 0x32
+#define AB8500_CODEC_CR51 0x33
+#define AB8500_CODEC_CR52 0x34
+#define AB8500_CODEC_CR53 0x35
+#define AB8500_CODEC_CR54 0x36
+#define AB8500_CODEC_CR55 0x37
+#define AB8500_CODEC_CR56 0x38
+#define AB8500_CODEC_CR57 0x39
+#define AB8500_CODEC_CR58 0x3A
+#define AB8500_CODEC_CR59 0x3B
+#define AB8500_CODEC_CR60 0x3C
+#define AB8500_CODEC_CR61 0x3D
+#define AB8500_CODEC_CR62 0x3E
+#define AB8500_CODEC_CR63 0x3F
+#define AB8500_CODEC_CR64 0x40
+#define AB8500_CODEC_CR65 0x41
+#define AB8500_CODEC_CR66 0x42
+#define AB8500_CODEC_CR67 0x43
+#define AB8500_CODEC_CR68 0x44
+#define AB8500_CODEC_CR69 0x45
+#define AB8500_CODEC_CR70 0x46
+#define AB8500_CODEC_CR71 0x47
+#define AB8500_CODEC_CR72 0x48
+#define AB8500_CODEC_CR73 0x49
+#define AB8500_CODEC_CR74 0x4A
+#define AB8500_CODEC_CR75 0x4B
+#define AB8500_CODEC_CR76 0x4C
+#define AB8500_CODEC_CR77 0x4D
+#define AB8500_CODEC_CR78 0x4E
+#define AB8500_CODEC_CR79 0x4F
+#define AB8500_CODEC_CR80 0x50
+#define AB8500_CODEC_CR81 0x51
+#define AB8500_CODEC_CR82 0x52
+#define AB8500_CODEC_CR83 0x53
+#define AB8500_CODEC_CR84 0x54
+#define AB8500_CODEC_CR85 0x55
+#define AB8500_CODEC_CR86 0x56
+#define AB8500_CODEC_CR87 0x57
+#define AB8500_CODEC_CR88 0x58
+#define AB8500_CODEC_CR89 0x59
+#define AB8500_CODEC_CR90 0x5A
+#define AB8500_CODEC_CR91 0x5B
+#define AB8500_CODEC_CR92 0x5C
+#define AB8500_CODEC_CR93 0x5D
+#define AB8500_CODEC_CR94 0x5E
+#define AB8500_CODEC_CR95 0x5F
+#define AB8500_CODEC_CR96 0x60
+#define AB8500_CODEC_CR97 0x61
+#define AB8500_CODEC_CR98 0x62
+#define AB8500_CODEC_CR99 0x63
+#define AB8500_CODEC_CR100 0x64
+#define AB8500_CODEC_CR101 0x65
+#define AB8500_CODEC_CR102 0x66
+#define AB8500_CODEC_CR103 0x67
+#define AB8500_CODEC_CR104 0x68
+#define AB8500_CODEC_CR105 0x69
+#define AB8500_CODEC_CR106 0x6A
+#define AB8500_CODEC_CR107 0x6B
+#define AB8500_CODEC_CR108 0x6C
+#define AB8500_CODEC_CR109 0x6D
+#define AB8500_CODEC_CR110 0x6E
+#define AB8500_CODEC_CR111 0x6F
+
+/* CR0-CR0x0000 */
+#define AB8500_CODEC_CR0_POWERUP 7
+#define AB8500_CODEC_CR0_ENAANA 3
+
+/* CR1-CR0x0001 */
+#define AB8500_CODEC_CR1_SWRESET 7
+
+/* CR2-CR0x0002 */
+#define AB8500_CODEC_CR2_ENAD1 7
+#define AB8500_CODEC_CR2_ENAD2 6
+#define AB8500_CODEC_CR2_ENAD3 5
+#define AB8500_CODEC_CR2_ENAD4 4
+#define AB8500_CODEC_CR2_ENAD5 3
+#define AB8500_CODEC_CR2_ENAD6 2
+
+/* CR3-CR0x0003 */
+#define AB8500_CODEC_CR3_ENDA1 7
+#define AB8500_CODEC_CR3_ENDA2 6
+#define AB8500_CODEC_CR3_ENDA3 5
+#define AB8500_CODEC_CR3_ENDA4 4
+#define AB8500_CODEC_CR3_ENDA5 3
+#define AB8500_CODEC_CR3_ENDA6 2
+
+/* CR4-CR0x0004 */
+#define AB8500_CODEC_CR4_LOWPOWHS 7
+#define AB8500_CODEC_CR4_LOWPOWDACHS 5
+#define AB8500_CODEC_CR4_LOWPOWEAR 4
+#define AB8500_CODEC_CR4_EAR_SEL_CM 2
+#define AB8500_CODEC_CR4_HS_HP_EN 1
+
+/* CR5-CR0x0005 */
+#define AB8500_CODEC_CR5_ENMIC1 7
+#define AB8500_CODEC_CR5_ENMIC2 6
+#define AB8500_CODEC_CR5_ENLINL 5
+#define AB8500_CODEC_CR5_ENLINR 4
+#define AB8500_CODEC_CR5_MUTMIC1 3
+#define AB8500_CODEC_CR5_MUTMIC2 2
+#define AB8500_CODEC_CR5_MUTELINL 1
+#define AB8500_CODEC_CR5_MUTELINR 0
+
+/* CR6-CR0x0006 */
+#define AB8500_CODEC_CR6_ENDMIC1 7
+#define AB8500_CODEC_CR6_ENDMIC2 6
+#define AB8500_CODEC_CR6_ENDMIC3 5
+#define AB8500_CODEC_CR6_ENDMIC4 4
+#define AB8500_CODEC_CR6_ENDMIC5 3
+#define AB8500_CODEC_CR6_ENDMIC6 2
+
+/* CR7-CR0x0007 */
+#define AB8500_CODEC_CR7_MIC1SEL 7
+#define AB8500_CODEC_CR7_LINRSEL 6
+#define AB8500_CODEC_CR7_ENDRVHSL 5
+#define AB8500_CODEC_CR7_ENDRVHSR 4
+#define AB8500_CODEC_CR7_ENADCMIC 2
+#define AB8500_CODEC_CR7_ENADCLINL 1
+#define AB8500_CODEC_CR7_ENADCLINR 0
+
+/* CR8-CR0x0008 */
+#define AB8500_CODEC_CR8_CP_DIS_PLDWN 7
+#define AB8500_CODEC_CR8_ENEAR 6
+#define AB8500_CODEC_CR8_ENHSL 5
+#define AB8500_CODEC_CR8_ENHSR 4
+#define AB8500_CODEC_CR8_ENHFL 3
+#define AB8500_CODEC_CR8_ENHFR 2
+#define AB8500_CODEC_CR8_ENVIBL 1
+#define AB8500_CODEC_CR8_ENVIBR 0
+
+/* CR9-CR0x0009 */
+#define AB8500_CODEC_CR9_ENADACEAR 6
+#define AB8500_CODEC_CR9_ENADACHSL 5
+#define AB8500_CODEC_CR9_ENADACHSR 4
+#define AB8500_CODEC_CR9_ENADACHFL 3
+#define AB8500_CODEC_CR9_ENADACHFR 2
+#define AB8500_CODEC_CR9_ENADACVIBL 1
+#define AB8500_CODEC_CR9_ENADACVIBR 0
+
+/* CR10-CR0x000A */
+#define AB8500_CODEC_CR10_MUTEEAR 6
+#define AB8500_CODEC_CR10_MUTEHSL 5
+#define AB8500_CODEC_CR10_MUTEHSR 4
+
+/* CR11-CR0x000B */
+#define AB8500_CODEC_CR11_ENSHORTPWD 7
+#define AB8500_CODEC_CR11_EARSHORTDIS 6
+#define AB8500_CODEC_CR11_HSSHORTDIS 5
+#define AB8500_CODEC_CR11_HSPULLDEN 4
+#define AB8500_CODEC_CR11_HSOSCEN 2
+#define AB8500_CODEC_CR11_HSFADEN 1
+#define AB8500_CODEC_CR11_HSZCDDIS 0
+
+/* CR12-CR0x000C */
+#define AB8500_CODEC_CR12_ENCPHS 7
+#define AB8500_CODEC_CR12_HSAUTOEN 0
+
+/* CR13-CR0x000D */
+#define AB8500_CODEC_CR13_ENVDET_HTHRESH 4
+#define AB8500_CODEC_CR13_ENVDET_LTHRESH 0
+
+/* CR14-CR0x000E */
+#define AB8500_CODEC_CR14_SMPSLVEN 7
+#define AB8500_CODEC_CR14_ENVDETSMPSEN 6
+#define AB8500_CODEC_CR14_CPLVEN 5
+#define AB8500_CODEC_CR14_ENVDETCPEN 4
+#define AB8500_CODEC_CR14_ENVDET_TIME 0
+
+/* CR15-CR0x000F */
+#define AB8500_CODEC_CR15_PWMTOVIBL 7
+#define AB8500_CODEC_CR15_PWMTOVIBR 6
+#define AB8500_CODEC_CR15_PWMLCTRL 5
+#define AB8500_CODEC_CR15_PWMRCTRL 4
+#define AB8500_CODEC_CR15_PWMNLCTRL 3
+#define AB8500_CODEC_CR15_PWMPLCTRL 2
+#define AB8500_CODEC_CR15_PWMNRCTRL 1
+#define AB8500_CODEC_CR15_PWMPRCTRL 0
+
+/* CR16-CR0x0010 */
+#define AB8500_CODEC_CR16_PWMNLPOL 7
+#define AB8500_CODEC_CR16_PWMNLDUTYCYCLE 0
+
+/* CR17-CR0x0011 */
+#define AB8500_CODEC_CR17_PWMPLPOL 7
+#define AB8500_CODEC_CR17_PWMLPDUTYCYCLE 0
+
+/* CR18-CR0x0012 */
+#define AB8500_CODEC_CR18_PWMNRPOL 7
+#define AB8500_CODEC_CR18_PWMNRDUTYCYCLE 0
+
+/* CR19-CR0x0013 */
+#define AB8500_CODEC_CR19_PWMPRPOL 7
+#define AB8500_CODEC_CR19_PWMRPDUTYCYCLE 0
+
+/* CR20-CR0x0014 */
+#define AB8500_CODEC_CR20_EN_SE_MIC1 7
+#define AB8500_CODEC_CR20_LOW_POW_MIC1 6
+#define AB8500_CODEC_CR20_MIC1_GAIN 0
+
+/* CR21-CR0x0015 */
+#define AB8500_CODEC_CR21_EN_SE_MIC2 7
+#define AB8500_CODEC_CR21_LOW_POW_MIC2 6
+#define AB8500_CODEC_CR21_MIC2_GAIN 0
+
+/* CR22-CR0x0016 */
+#define AB8500_CODEC_CR22_HSL_GAIN 4
+#define AB8500_CODEC_CR22_HSR_GAIN 0
+
+/* CR23-CR0x0017 */
+#define AB8500_CODEC_CR23_LINL_GAIN 4
+#define AB8500_CODEC_CR23_LINR_GAIN 0
+
+/* CR24-CR0x0018 */
+#define AB8500_CODEC_CR24_LINTOHSL_GAIN 0
+
+/* CR25-CR0x0019 */
+#define AB8500_CODEC_CR25_LINTOHSR_GAIN 0
+
+/* CR26-CR0x001A */
+#define AB8500_CODEC_CR26_AD1NH 7
+#define AB8500_CODEC_CR26_AD2NH 6
+#define AB8500_CODEC_CR26_AD3NH 5
+#define AB8500_CODEC_CR26_AD4NH 4
+#define AB8500_CODEC_CR26_AD1_VOICE 3
+#define AB8500_CODEC_CR26_AD2_VOICE 2
+#define AB8500_CODEC_CR26_AD3_VOICE 1
+#define AB8500_CODEC_CR26_AD4_VOICE 0
+
+/* CR27-CR0x001B */
+#define AB8500_CODEC_CR27_EN_MASTGEN 7
+#define AB8500_CODEC_CR27_IF1_BITCLK_OSR 5
+#define AB8500_CODEC_CR27_ENFS_BITCLK1 4
+#define AB8500_CODEC_CR27_IF0_BITCLK_OSR 1
+#define AB8500_CODEC_CR27_ENFS_BITCLK0 0
+
+/* CR28-CR0x001C */
+#define AB8500_CODEC_CR28_FSYNC0P 6
+#define AB8500_CODEC_CR28_BITCLK0P 5
+#define AB8500_CODEC_CR28_IF0DEL 4
+#define AB8500_CODEC_CR28_IF0FORMAT 2
+#define AB8500_CODEC_CR28_IF0WL 0
+
+/* CR29-CR0x001D */
+#define AB8500_CODEC_CR29_IF0DATOIF1AD 7
+#define AB8500_CODEC_CR29_IF0CKTOIF1CK 6
+#define AB8500_CODEC_CR29_IF1MASTER 5
+#define AB8500_CODEC_CR29_IF1DATOIF0AD 3
+#define AB8500_CODEC_CR29_IF1CKTOIF0CK 2
+#define AB8500_CODEC_CR29_IF0MASTER 1
+#define AB8500_CODEC_CR29_IF0BFIFOEN 0
+
+/* CR30-CR0x001E */
+#define AB8500_CODEC_CR30_FSYNC1P 6
+#define AB8500_CODEC_CR30_BITCLK1P 5
+#define AB8500_CODEC_CR30_IF1DEL 4
+#define AB8500_CODEC_CR30_IF1FORMAT 2
+#define AB8500_CODEC_CR30_IF1WL 0
+
+/* CR31-CR0x001F */
+#define AB8500_CODEC_CR31_ADOTOSLOT1 4
+#define AB8500_CODEC_CR31_ADOTOSLOT0 0
+
+/* CR32-CR0x0020 */
+#define AB8500_CODEC_CR32_ADOTOSLOT3 4
+#define AB8500_CODEC_CR32_ADOTOSLOT2 0
+
+/* CR33-CR0x0021 */
+#define AB8500_CODEC_CR33_ADOTOSLOT5 4
+#define AB8500_CODEC_CR33_ADOTOSLOT4 0
+
+/* CR34-CR0x0022 */
+#define AB8500_CODEC_CR34_ADOTOSLOT7 4
+#define AB8500_CODEC_CR34_ADOTOSLOT6 0
+
+/* CR35-CR0x0023 */
+#define AB8500_CODEC_CR35_ADOTOSLOT9 4
+#define AB8500_CODEC_CR35_ADOTOSLOT8 0
+
+/* CR36-CR0x0024 */
+#define AB8500_CODEC_CR36_ADOTOSLOT11 4
+#define AB8500_CODEC_CR36_ADOTOSLOT10 0
+
+/* CR37-CR0x0025 */
+#define AB8500_CODEC_CR37_ADOTOSLOT13 4
+#define AB8500_CODEC_CR37_ADOTOSLOT12 0
+
+/* CR38-CR0x0026 */
+#define AB8500_CODEC_CR38_ADOTOSLOT15 4
+#define AB8500_CODEC_CR38_ADOTOSLOT14 0
+
+/* CR39-CR0x0027 */
+#define AB8500_CODEC_CR39_ADOTOSLOT17 4
+#define AB8500_CODEC_CR39_ADOTOSLOT16 0
+
+/* CR40-CR0x0028 */
+#define AB8500_CODEC_CR40_ADOTOSLOT19 4
+#define AB8500_CODEC_CR40_ADOTOSLOT18 0
+
+/* CR41-CR0x0029 */
+#define AB8500_CODEC_CR41_ADOTOSLOT21 4
+#define AB8500_CODEC_CR41_ADOTOSLOT20 0
+
+/* CR42-CR0x002A */
+#define AB8500_CODEC_CR42_ADOTOSLOT23 4
+#define AB8500_CODEC_CR42_ADOTOSLOT22 0
+
+/* CR43-CR0x002B */
+#define AB8500_CODEC_CR43_ADOTOSLOT25 4
+#define AB8500_CODEC_CR43_ADOTOSLOT24 0
+
+/* CR44-CR0x002C */
+#define AB8500_CODEC_CR44_ADOTOSLOT27 4
+#define AB8500_CODEC_CR44_ADOTOSLOT26 0
+
+/* CR45-CR0x002D */
+#define AB8500_CODEC_CR45_ADOTOSLOT29 4
+#define AB8500_CODEC_CR45_ADOTOSLOT28 0
+
+/* CR46-CR0x002E */
+#define AB8500_CODEC_CR46_ADOTOSLOT31 4
+#define AB8500_CODEC_CR46_ADOTOSLOT30 0
+
+/* CR47-CR0x002F */
+#define AB8500_CODEC_CR47_HIZ_SL7 7
+#define AB8500_CODEC_CR47_HIZ_SL6 6
+#define AB8500_CODEC_CR47_HIZ_SL5 5
+#define AB8500_CODEC_CR47_HIZ_SL4 4
+#define AB8500_CODEC_CR47_HIZ_SL3 3
+#define AB8500_CODEC_CR47_HIZ_SL2 2
+#define AB8500_CODEC_CR47_HIZ_SL1 1
+#define AB8500_CODEC_CR47_HIZ_SL0 0
+
+/* CR48-CR0x0030 */
+#define AB8500_CODEC_CR48_HIZ_SL15 7
+#define AB8500_CODEC_CR48_HIZ_SL14 6
+#define AB8500_CODEC_CR48_HIZ_SL13 5
+#define AB8500_CODEC_CR48_HIZ_SL12 4
+#define AB8500_CODEC_CR48_HIZ_SL11 3
+#define AB8500_CODEC_CR48_HIZ_SL10 2
+#define AB8500_CODEC_CR48_HIZ_SL9 1
+#define AB8500_CODEC_CR48_HIZ_SL8 0
+
+/* CR49-CR0x0031 */
+#define AB8500_CODEC_CR49_HIZ_SL23 7
+#define AB8500_CODEC_CR49_HIZ_SL22 6
+#define AB8500_CODEC_CR49_HIZ_SL21 5
+#define AB8500_CODEC_CR49_HIZ_SL20 4
+#define AB8500_CODEC_CR49_HIZ_SL19 3
+#define AB8500_CODEC_CR49_HIZ_SL18 2
+#define AB8500_CODEC_CR49_HIZ_SL17 1
+#define AB8500_CODEC_CR49_HIZ_SL16 0
+
+/* CR50-CR0x0032 */
+#define AB8500_CODEC_CR50_HIZ_SL31 7
+#define AB8500_CODEC_CR50_HIZ_SL30 6
+#define AB8500_CODEC_CR50_HIZ_SL29 5
+#define AB8500_CODEC_CR50_HIZ_SL28 4
+#define AB8500_CODEC_CR50_HIZ_SL27 3
+#define AB8500_CODEC_CR50_HIZ_SL26 2
+#define AB8500_CODEC_CR50_HIZ_SL25 1
+#define AB8500_CODEC_CR50_HIZ_SL24 0
+
+/* CR51-CR0x0033 */
+#define AB8500_CODEC_CR51_DA12_VOICE 7
+#define AB8500_CODEC_CR51_SWAP_DA12_34 6
+#define AB8500_CODEC_CR51_SLDAI7TOSLADO1 5
+#define AB8500_CODEC_CR51_SLTODA1 0
+
+/* CR52-CR0x0034 */
+#define AB8500_CODEC_CR52_SLDAI8TOSLADO2 5
+#define AB8500_CODEC_CR52_SLTODA2 0
+
+/* CR53-CR0x0035 */
+#define AB8500_CODEC_CR53_DA34_VOICE 7
+#define AB8500_CODEC_CR53_SLDAI7TOSLADO3 5
+#define AB8500_CODEC_CR53_SLTODA3 0
+
+/* CR54-CR0x0036 */
+#define AB8500_CODEC_CR54_SLDAI8TOSLADO4 5
+#define AB8500_CODEC_CR54_SLTODA4 0
+
+/* CR55-CR0x0037 */
+#define AB8500_CODEC_CR55_DA56_VOICE 7
+#define AB8500_CODEC_CR55_SLDAI7TOSLADO5 5
+#define AB8500_CODEC_CR55_SLTODA5 0
+
+/* CR56-CR0x0038 */
+#define AB8500_CODEC_CR56_SLDAI8TOSLADO6 5
+#define AB8500_CODEC_CR56_SLTODA6 0
+
+/* CR57-CR0x0039 */
+#define AB8500_CODEC_CR57_SLDAI8TOSLADO7 5
+#define AB8500_CODEC_CR57_SLTODA7 0
+
+/* CR58-CR0x003A */
+#define AB8500_CODEC_CR58_SLDAI7TOSLADO8 5
+#define AB8500_CODEC_CR58_SLTODA8 0
+
+/* CR59-CR0x003B */
+#define AB8500_CODEC_CR59_PARLHF 7
+#define AB8500_CODEC_CR59_PARLVIB 6
+#define AB8500_CODEC_CR59_CLASSDVIB1SWAPEN 3
+#define AB8500_CODEC_CR59_CLASSDVIB2SWAPEN 2
+#define AB8500_CODEC_CR59_CLASSDHFLSWAPEN 1
+#define AB8500_CODEC_CR59_CLASSDHFRSWAPEN 0
+
+/* CR60-CR0x003C */
+#define AB8500_CODEC_CR60_CLASSD_FIR_BYP 4
+#define AB8500_CODEC_CR60_CLASSD_HIGHVOL_EN 0
+
+/* CR61-CR0x003D */
+#define AB8500_CODEC_CR61_CLASSD_DITH_HPGAIN 4
+#define AB8500_CODEC_CR61_CLASSD_DITH_WGAIN 0
+
+/* CR62-CR0x003E */
+#define AB8500_CODEC_CR62_DMIC1SINC3 5
+#define AB8500_CODEC_CR62_DMIC2SINC3 4
+#define AB8500_CODEC_CR62_DMIC3SINC3 3
+#define AB8500_CODEC_CR62_DMIC4SINC3 2
+#define AB8500_CODEC_CR62_DMIC5SINC3 1
+#define AB8500_CODEC_CR62_DMIC6SINC3 0
+
+/* CR63-CR0x003F */
+#define AB8500_CODEC_CR63_DATOHSLEN 7
+#define AB8500_CODEC_CR63_DATOHSREN 6
+#define AB8500_CODEC_CR63_AD1SEL 5
+#define AB8500_CODEC_CR63_AD2SEL 4
+#define AB8500_CODEC_CR63_AD3SEL 3
+#define AB8500_CODEC_CR63_AD5SEL 2
+#define AB8500_CODEC_CR63_AD6SEL 1
+#define AB8500_CODEC_CR63_ANCSEL 0
+
+/* CR64-CR0x0040 */
+#define AB8500_CODEC_CR64_DATOHFREN 7
+#define AB8500_CODEC_CR64_DATOHFLEN 6
+#define AB8500_CODEC_CR64_HFRSEL 5
+#define AB8500_CODEC_CR64_HFLSEL 4
+#define AB8500_CODEC_CR64_STFIR1SEL 2
+#define AB8500_CODEC_CR64_STFIR2SEL 0
+
+/* CR65-CR0x0041 */
+#define AB8500_CODEC_CR65_FADEDIS_AD1 6
+#define AB8500_CODEC_CR65_AD1GAIN 0
+
+/* CR66-CR0x0042 */
+#define AB8500_CODEC_CR66_FADEDIS_AD2 6
+#define AB8500_CODEC_CR66_AD2GAIN 0
+
+/* CR67-CR0x0043 */
+#define AB8500_CODEC_CR67_FADEDIS_AD3 6
+#define AB8500_CODEC_CR67_AD3GAIN 0
+
+/* CR68-CR0x0044 */
+#define AB8500_CODEC_CR68_FADEDIS_AD4 6
+#define AB8500_CODEC_CR68_AD4GAIN 0
+
+/* CR69-CR0x0045 */
+#define AB8500_CODEC_CR69_FADEDIS_AD5 6
+#define AB8500_CODEC_CR69_AD5GAIN 0
+
+/* CR70-CR0x0046 */
+#define AB8500_CODEC_CR70_FADEDIS_AD6 6
+#define AB8500_CODEC_CR70_AD6GAIN 0
+
+/* CR71-CR0x0047 */
+#define AB8500_CODEC_CR71_FADEDIS_DA1 6
+#define AB8500_CODEC_CR71_DA1GAIN 0
+
+/* CR72-CR0x0048 */
+#define AB8500_CODEC_CR72_FADEDIS_DA2 6
+#define AB8500_CODEC_CR72_DA2GAIN 0
+
+/* CR73-CR0x0049 */
+#define AB8500_CODEC_CR73_FADEDIS_DA3 6
+#define AB8500_CODEC_CR73_DA3GAIN 0
+
+/* CR74-CR0x004A */
+#define AB8500_CODEC_CR74_FADEDIS_DA4 6
+#define AB8500_CODEC_CR74_DA4GAIN 0
+
+/* CR75-CR0x004B */
+#define AB8500_CODEC_CR75_FADEDIS_DA5 6
+#define AB8500_CODEC_CR75_DA5GAIN 0
+
+/* CR76-CR0x004C */
+#define AB8500_CODEC_CR76_FADEDIS_DA6 6
+#define AB8500_CODEC_CR76_DA6GAIN 0
+
+/* CR77-CR0x004D */
+#define AB8500_CODEC_CR77_FADEDIS_AD1L 6
+#define AB8500_CODEC_CR77_AD1LBGAIN 0
+
+/* CR78-CR0x004E */
+#define AB8500_CODEC_CR78_FADEDIS_AD2L 6
+#define AB8500_CODEC_CR78_AD2LBGAIN 0
+
+/* CR79-CR0x004F */
+#define AB8500_CODEC_CR79_HSSINC1 7
+#define AB8500_CODEC_CR79_FADEDIS_HSL 4
+#define AB8500_CODEC_CR79_HSLDGAIN 0
+
+/* CR80-CR0x0050 */
+#define AB8500_CODEC_CR80_FADE_SPEED 6
+#define AB8500_CODEC_CR80_FADEDIS_HSR 4
+#define AB8500_CODEC_CR80_HSRDGAIN 0
+
+/* CR81-CR0x0051 */
+#define AB8500_CODEC_CR81_STFIR1GAIN 0
+
+/* CR82-CR0x0052 */
+#define AB8500_CODEC_CR82_STFIR2GAIN 0
+
+/* CR83-CR0x0053 */
+#define AB8500_CODEC_CR83_ENANC 2
+#define AB8500_CODEC_CR83_ANCIIRINIT 1
+#define AB8500_CODEC_CR83_ANCFIRUPDATE 0
+
+/* CR84-CR0x0054 */
+#define AB8500_CODEC_CR84_ANCINSHIFT 0
+
+/* CR85-CR0x0055 */
+#define AB8500_CODEC_CR85_ANCFIROUTSHIFT 0
+
+/* CR86-CR0x0056 */
+#define AB8500_CODEC_CR86_ANCSHIFTOUT 0
+
+/* CR87-CR0x0057 */
+#define AB8500_CODEC_CR87_ANCFIRCOEFF_MSB 0
+
+/* CR88-CR0x0058 */
+#define AB8500_CODEC_CR88_ANCFIRCOEFF_LSB 0
+
+/* CR89-CR0x0059 */
+#define AB8500_CODEC_CR89_ANCIIRCOEFF_MSB 0
+
+/* CR90-CR0x005A */
+#define AB8500_CODEC_CR90_ANCIIRCOEFF_LSB 0
+
+/* CR91-CR0x005B */
+#define AB8500_CODEC_CR91_ANCWARPDEL_MSB 0
+
+/* CR92-CR0x005C */
+#define AB8500_CODEC_CR92_ANCWARPDEL_LSB 0
+
+/* CR93-CR0x005D */
+#define AB8500_CODEC_CR93_ANCFIRPEAK_MSB 0
+
+/* CR94-CR0x005E */
+#define AB8500_CODEC_CR94_ANCFIRPEAK_LSB 0
+
+/* CR95-CR0x005F */
+#define AB8500_CODEC_CR95_ANCIIRPEAK_MSB 0
+
+/* CR96-CR0x0060 */
+#define AB8500_CODEC_CR96_ANCIIRPEAK_LSB 0
+
+/* CR97-CR0x0061 */
+#define AB8500_CODEC_CR97_STFIR_SET 7
+#define AB8500_CODEC_CR97_STFIR_ADDR 0
+
+/* CR98-CR0x0062 */
+#define AB8500_CODEC_CR98_STFIR_COEFF_MSB 0
+
+/* CR99-CR0x0063 */
+#define AB8500_CODEC_CR99_STFIR_COEFF_LSB 0
+
+/* CR100-CR0x0064 */
+#define AB8500_CODEC_CR100_ENSTFIRS 2
+#define AB8500_CODEC_CR100_STFIRSTOIF1 1
+#define AB8500_CODEC_CR100_STFIR_BUSY 0
+
+/* CR101-CR0x0065 */
+#define AB8500_CODEC_CR101_HSOFFSTMASK 7
+#define AB8500_CODEC_CR101_FIFOFULLMASK 6
+#define AB8500_CODEC_CR101_FIFOEMPTYMASK 5
+#define AB8500_CODEC_CR101_DASATMASK 4
+#define AB8500_CODEC_CR101_ADSATMASK 3
+#define AB8500_CODEC_CR101_ADDSPMASK 2
+#define AB8500_CODEC_CR101_DADSPMASK 1
+#define AB8500_CODEC_CR101_FIRSIDMASK 0
+
+/* CR102-CR0x0066 */
+#define AB8500_CODEC_CR102_IT_HSOFFST 7
+#define AB8500_CODEC_CR102_IT_FIFOFULL 6
+#define AB8500_CODEC_CR102_IT_FIFOEMPTY 5
+#define AB8500_CODEC_CR102_IT_DASAT 4
+#define AB8500_CODEC_CR102_IT_ADSAT 3
+#define AB8500_CODEC_CR102_IT_ADDSP 2
+#define AB8500_CODEC_CR102_IT_DADSP 1
+#define AB8500_CODEC_CR102_IT_FIRSID 0
+
+/* CR103-CR0x0067 */
+#define AB8500_CODEC_CR103_VSSREADYMASK 7
+#define AB8500_CODEC_CR103_SHORTHSLMASK 2
+#define AB8500_CODEC_CR103_SHORTHSRMASK 1
+#define AB8500_CODEC_CR103_SHORTEARMASK 0
+
+/* CR104-CR0x0068 */
+#define AB8500_CODEC_CR104_IT_VSSREADY 7
+#define AB8500_CODEC_CR104_IT_SHORTHSL 2
+#define AB8500_CODEC_CR104_IT_SHORTHSR 1
+#define AB8500_CODEC_CR104_IT_SHORTEAR 0
+
+/* CR105-CR0x0069 */
+#define AB8500_CODEC_CR105_BFIFOMASK 7
+#define AB8500_CODEC_CR105_BFIFOINT 0
+
+/* CR106-CR0x006A */
+#define AB8500_CODEC_CR106_BFIFOTX 0
+
+/* CR107-CR0x006B */
+#define AB8500_CODEC_CR107_BFIFOEXSL 5
+#define AB8500_CODEC_CR107_PREBITCLK0 2
+#define AB8500_CODEC_CR107_BFIFOMAST 1
+#define AB8500_CODEC_CR107_BFIFORUN 0
+
+/* CR108-CR0x006C */
+#define AB8500_CODEC_CR108_BFIFOFRAMESW 0
+
+/* CR109-CR0x006D */
+#define AB8500_CODEC_CR109_BFIFOWAKEUP 0
+
+/* CR110-CR0x006E */
+#define AB8500_CODEC_CR110_BFIFOSAMPLE 0
+
+/* CR111-CR0x006F */
+#define AB8500_CODEC_CR111_AUD_IP_REV 0
+
+/* For SetVolume API*/
+#define AB8500_CODEC_MAX_VOLUME 100
+
+/* Analog MIC1 & MIC2 */
+#define AB8500_CODEC_MIC_VOLUME_MAX 31
+#define AB8500_CODEC_MIC_VOLUME_MEDIUM 15
+#define AB8500_CODEC_MIC_VOLUME_MIN 0
+
+/* Line-in */
+#define AB8500_CODEC_LINEIN_VOLUME_MAX 15
+#define AB8500_CODEC_LINEIN_VOLUME_MEDIUM 7
+#define AB8500_CODEC_LINEIN_VOLUME_MIN 0
+
+/* HeadSet */
+#define AB8500_CODEC_HEADSET_VOLUME_MAX 13
+#define AB8500_CODEC_HEADSET_VOLUME_MEDIUM 6
+#define AB8500_CODEC_HEADSET_VOLUME_MIN 0
+
+/* HeadSet Digital */
+#define AB8500_CODEC_HEADSET_D_VOLUME_MAX 0
+#define AB8500_CODEC_HEADSET_D_VOLUME_MEDIUM 7
+#define AB8500_CODEC_HEADSET_D_VOLUME_MIN 15
+#define AB8500_CODEC_HEADSET_D_VOLUME_0DB 8
+
+/* Digital AD Path */
+#define AB8500_CODEC_AD_D_VOLUME_MAX 0
+#define AB8500_CODEC_AD_D_VOLUME_MEDIUM 31
+#define AB8500_CODEC_AD_D_VOLUME_MIN 63
+
+/* Digital DA Path */
+#define AB8500_CODEC_DA_D_VOLUME_MAX 0
+#define AB8500_CODEC_DA_D_VOLUME_MEDIUM 31
+#define AB8500_CODEC_DA_D_VOLUME_MIN 63
+
+/* EarPiece Digital */
+#define AB8500_CODEC_EARPIECE_D_VOLUME_MAX 0
+#define AB8500_CODEC_EARPIECE_D_VOLUME_MEDIUM 7
+#define AB8500_CODEC_EARPIECE_D_VOLUME_MIN 15
+
+/* AD1 loopback to HFL & HFR Digital */
+#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MAX 0
+#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MEDIUM 31
+#define AB8500_CODEC_AD_LB_TO_HF_L_R_VOLUME_MIN 63
+
+/* Line-in to HSL & HSR */
+#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MAX 0
+#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MEDIUM 9
+#define AB8500_CODEC_LINEIN_TO_HS_L_R_VOLUME_MIN 18
+#define AB8500_CODEC_LINEIN_TO_HS_L_R_LOOP_OPEN 19
+
+/* Vibrator */
+#define AB8500_CODEC_VIBRATOR_VOLUME_MAX 100
+#define AB8500_CODEC_VIBRATOR_VOLUME_MEDIUM 50
+#define AB8500_CODEC_VIBRATOR_VOLUME_MIN 0
+
+/* CR0 - 7 */
+typedef enum {
+ AB8500_CODEC_CR0_POWERUP_OFF,
+ AB8500_CODEC_CR0_POWERUP_ON
+} t_ab8500_codec_cr0_powerup;
+
+/* CR0 - 3 */
+typedef enum {
+ AB8500_CODEC_CR0_ENAANA_OFF,
+ AB8500_CODEC_CR0_ENAANA_ON
+} t_ab8500_codec_cr0_enaana;
+
+/* CR1 - 7 */
+typedef enum {
+ AB8500_CODEC_CR1_SWRESET_DISABLED,
+ AB8500_CODEC_CR1_SWRESET_ENABLED
+} t_ab8500_codec_cr1_swreset;
+
+/* CR2 - 7 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD1_DISABLED,
+ AB8500_CODEC_CR2_ENAD1_ENABLED
+} t_ab8500_codec_cr2_enad1;
+
+/* CR2 - 6 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD2_DISABLED,
+ AB8500_CODEC_CR2_ENAD2_ENABLED
+} t_ab8500_codec_cr2_enad2;
+
+/* CR2 - 5 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD3_DISABLED,
+ AB8500_CODEC_CR2_ENAD3_ENABLED
+} t_ab8500_codec_cr2_enad3;
+
+/* CR2 - 4 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD4_DISABLED,
+ AB8500_CODEC_CR2_ENAD4_ENABLED
+} t_ab8500_codec_cr2_enad4;
+
+/* CR2 - 3 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD5_DISABLED,
+ AB8500_CODEC_CR2_ENAD5_ENABLED
+} t_ab8500_codec_cr2_enad5;
+
+/* CR2 - 2 */
+typedef enum {
+ AB8500_CODEC_CR2_ENAD6_DISABLED,
+ AB8500_CODEC_CR2_ENAD6_ENABLED
+} t_ab8500_codec_cr2_enad6;
+
+/* CR3 - 7 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA1_DISABLED,
+ AB8500_CODEC_CR3_ENDA1_ENABLED
+} t_ab8500_codec_cr3_enda1;
+
+/* CR3 - 6 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA2_DISABLED,
+ AB8500_CODEC_CR3_ENDA2_ENABLED
+} t_ab8500_codec_cr3_enda2;
+
+/* CR3 - 5 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA3_DISABLED,
+ AB8500_CODEC_CR3_ENDA3_ENABLED
+} t_ab8500_codec_cr3_enda3;
+
+/* CR3 - 4 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA4_DISABLED,
+ AB8500_CODEC_CR3_ENDA4_ENABLED
+} t_ab8500_codec_cr3_enda4;
+
+/* CR3 - 3 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA5_DISABLED,
+ AB8500_CODEC_CR3_ENDA5_ENABLED
+} t_ab8500_codec_cr3_enda5;
+
+/* CR3 - 2 */
+typedef enum {
+ AB8500_CODEC_CR3_ENDA6_DISABLED,
+ AB8500_CODEC_CR3_ENDA6_ENABLED
+} t_ab8500_codec_cr3_enda6;
+
+/* CR4 - 7 */
+typedef enum {
+ AB8500_CODEC_CR4_LOWPOWHS_NORMAL,
+ AB8500_CODEC_CR4_LOWPOWHS_LP
+} t_ab8500_codec_cr4_lowpowhs;
+
+/* CR4 - 6:5 */
+typedef enum {
+ AB8500_CODEC_CR4_LOWPOWDACHS_NORMAL,
+ AB8500_CODEC_CR4_LOWPOWDACHS_DRIVERS_LP,
+ AB8500_CODEC_CR4_LOWPOWDACHS_LP,
+ AB8500_CODEC_CR4_LOWPOWDACHS_BOTH_LP
+} t_ab8500_codec_cr4_lowpowdachs;
+
+/* CR4 - 4 */
+typedef enum {
+ AB8500_CODEC_CR4_LOWPOWEAR_NORMAL,
+ AB8500_CODEC_CR4_LOWPOWEAR_LP
+} t_ab8500_codec_cr4_lowpowear;
+
+/* CR4 - 3:2 */
+typedef enum {
+ AB8500_CODEC_CR4_EAR_SEL_CM_0_95V,
+ AB8500_CODEC_CR4_EAR_SEL_CM_1_1V,
+ AB8500_CODEC_CR4_EAR_SEL_CM_1_27V,
+ AB8500_CODEC_CR4_EAR_SEL_CM_1_58V
+} t_ab8500_codec_cr4_ear_sel_cm;
+
+/* CR4 - 1 */
+typedef enum {
+ AB8500_CODEC_CR4_HS_HP_EN_FILTER_DISABLED,
+ AB8500_CODEC_CR4_HS_HP_EN_FILTER_ENABLED
+} t_ab8500_codec_cr4_hs_hp_en;
+
+/* CR5 - 7 */
+typedef enum {
+ AB8500_CODEC_CR5_ENMIC1_DISABLED,
+ AB8500_CODEC_CR5_ENMIC1_ENABLED
+} t_ab8500_codec_cr5_enmic1;
+
+/* CR5 - 6 */
+typedef enum {
+ AB8500_CODEC_CR5_ENMIC2_DISABLED,
+ AB8500_CODEC_CR5_ENMIC2_ENABLED
+} t_ab8500_codec_cr5_enmic2;
+
+/* CR5 - 5 */
+typedef enum {
+ AB8500_CODEC_CR5_ENLINL_DISABLED,
+ AB8500_CODEC_CR5_ENLINL_ENABLED
+} t_ab8500_codec_cr5_enlinl;
+
+/* CR5 - 4 */
+typedef enum {
+ AB8500_CODEC_CR5_ENLINR_DISABLED,
+ AB8500_CODEC_CR5_ENLINR_ENABLED
+} t_ab8500_codec_cr5_enlinr;
+
+/* CR5 - 3 */
+typedef enum {
+ AB8500_CODEC_CR5_MUTMIC1_DISABLED,
+ AB8500_CODEC_CR5_MUTMIC1_ENABLED
+} t_ab8500_codec_cr5_mutmic1;
+
+/* CR5 - 2 */
+typedef enum {
+ AB8500_CODEC_CR5_MUTMIC2_DISABLED,
+ AB8500_CODEC_CR5_MUTMIC2_ENABLED
+} t_ab8500_codec_cr5_mutmic2;
+
+/* CR5 - 1 */
+typedef enum {
+ AB8500_CODEC_CR5_MUTLINL_DISABLED,
+ AB8500_CODEC_CR5_MUTLINL_ENABLED
+} t_ab8500_codec_cr5_mutlinl;
+
+/* CR5 - 0 */
+typedef enum {
+ AB8500_CODEC_CR5_MUTLINR_DISABLED,
+ AB8500_CODEC_CR5_MUTLINR_ENABLED
+} t_ab8500_codec_cr5_mutlinr;
+
+/* CR6 - 7 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC1_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC1_ENABLED
+} t_ab8500_codec_cr6_endmic1;
+
+/* CR6 - 6 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC2_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC2_ENABLED
+} t_ab8500_codec_cr6_endmic2;
+
+/* CR6 - 5 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC3_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC3_ENABLED
+} t_ab8500_codec_cr6_endmic3;
+
+/* CR6 - 4 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC4_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC4_ENABLED
+} t_ab8500_codec_cr6_endmic4;
+
+/* CR6 - 3 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC5_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC5_ENABLED
+} t_ab8500_codec_cr6_endmic5;
+
+/* CR6 - 2 */
+typedef enum {
+ AB8500_CODEC_CR6_ENDMIC6_DISABLED,
+ AB8500_CODEC_CR6_ENDMIC6_ENABLED
+} t_ab8500_codec_cr6_endmic6;
+
+/* CR7 - 7 */
+typedef enum {
+ AB8500_CODEC_CR7_MIC1SEL_MIC1A,
+ AB8500_CODEC_CR7_MIC1SEL_MIC1B
+} t_ab8500_codec_cr7_mic1sel;
+
+/* CR7 - 6 */
+typedef enum {
+ AB8500_CODEC_CR7_LINRSEL_MIC2,
+ AB8500_CODEC_CR7_LINRSEL_LINR
+} t_ab8500_codec_cr7_linrsel;
+
+/* CR7 - 5 */
+typedef enum {
+ AB8500_CODEC_CR7_ENDRVHSL_DISABLED,
+ AB8500_CODEC_CR7_ENDRVHSL_ENABLED
+} t_ab8500_codec_cr7_endrvhsl;
+
+/* CR7 - 4 */
+typedef enum {
+ AB8500_CODEC_CR7_ENDRVHSR_DISABLED,
+ AB8500_CODEC_CR7_ENDRVHSR_ENABLED
+} t_ab8500_codec_cr7_endrvhsr;
+
+/* CR7 - 2 */
+typedef enum {
+ AB8500_CODEC_CR7_ENADCMIC_DISABLED,
+ AB8500_CODEC_CR7_ENADCMIC_ENABLED
+} t_ab8500_codec_cr7_enadcmic;
+
+/* CR7 - 1 */
+typedef enum {
+ AB8500_CODEC_CR7_ENADCLINL_DISABLED,
+ AB8500_CODEC_CR7_ENADCLINL_ENABLED
+} t_ab8500_codec_cr7_enadclinl;
+
+/* CR7 - 0 */
+typedef enum {
+ AB8500_CODEC_CR7_ENADCLINR_DISABLED,
+ AB8500_CODEC_CR7_ENADCLINR_ENABLED
+} t_ab8500_codec_cr7_enadclinr;
+
+/* CR8 - 7 */
+typedef enum {
+ AB8500_CODEC_CR8_CP_DIS_PLDWN_ENABLED,
+ AB8500_CODEC_CR8_CP_DIS_PLDWN_DISABLED
+} t_ab8500_codec_cr8_cp_dis_pldwn;
+
+/* CR8 - 6 */
+typedef enum {
+ AB8500_CODEC_CR8_ENEAR_DISABLED,
+ AB8500_CODEC_CR8_ENEAR_ENABLED
+} t_ab8500_codec_cr8_enear;
+
+/* CR8 - 5 */
+typedef enum {
+ AB8500_CODEC_CR8_ENHSL_DISABLED,
+ AB8500_CODEC_CR8_ENHSL_ENABLED
+} t_ab8500_codec_cr8_enhsl;
+
+/* CR8 - 4 */
+typedef enum {
+ AB8500_CODEC_CR8_ENHSR_DISABLED,
+ AB8500_CODEC_CR8_ENHSR_ENABLED
+} t_ab8500_codec_cr8_enhsr;
+
+/* CR8 - 3 */
+typedef enum {
+ AB8500_CODEC_CR8_ENHFL_DISABLED,
+ AB8500_CODEC_CR8_ENHFL_ENABLED
+} t_ab8500_codec_cr8_enhfl;
+
+/* CR8 - 2 */
+typedef enum {
+ AB8500_CODEC_CR8_ENHFR_DISABLED,
+ AB8500_CODEC_CR8_ENHFR_ENABLED
+} t_ab8500_codec_cr8_enhfr;
+
+/* CR8 - 1 */
+typedef enum {
+ AB8500_CODEC_CR8_ENVIBL_DISABLED,
+ AB8500_CODEC_CR8_ENVIBL_ENABLED
+} t_ab8500_codec_cr8_envibl;
+
+/* CR8 - 0 */
+typedef enum {
+ AB8500_CODEC_CR8_ENVIBR_DISABLED,
+ AB8500_CODEC_CR8_ENVIBR_ENABLED
+} t_ab8500_codec_cr8_envibr;
+
+/* CR9 - 6 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACEAR_DISABLED,
+ AB8500_CODEC_CR9_ENDACEAR_ENABLED
+} t_ab8500_codec_cr9_endacear;
+
+/* CR9 - 5 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACHSL_DISABLED,
+ AB8500_CODEC_CR9_ENDACHSL_ENABLED
+} t_ab8500_codec_cr9_endachsl;
+
+/* CR9 - 4 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACHSR_DISABLED,
+ AB8500_CODEC_CR9_ENDACHSR_ENABLED
+} t_ab8500_codec_cr9_endachsr;
+
+/* CR9 - 3 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACHFL_DISABLED,
+ AB8500_CODEC_CR9_ENDACHFL_ENABLED
+} t_ab8500_codec_cr9_endachfl;
+
+/* CR9 - 2 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACHFR_DISABLED,
+ AB8500_CODEC_CR9_ENDACHFR_ENABLED
+} t_ab8500_codec_cr9_endachfr;
+
+/* CR9 - 1 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACVIBL_DISABLED,
+ AB8500_CODEC_CR9_ENDACVIBL_ENABLED
+} t_ab8500_codec_cr9_endacvibl;
+
+/* CR9 - 0 */
+typedef enum {
+ AB8500_CODEC_CR9_ENDACVIBR_DISABLED,
+ AB8500_CODEC_CR9_ENDACVIBR_ENABLED
+} t_ab8500_codec_cr9_endacvibr;
+
+/* CR10 - 6 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEEAR_DISABLED,
+ AB8500_CODEC_CR10_MUTEEAR_ENABLED
+} t_ab8500_codec_cr10_muteear;
+
+/* CR10 - 5 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEHSL_DISABLED,
+ AB8500_CODEC_CR10_MUTEHSL_ENABLED
+} t_ab8500_codec_cr10_mutehsl;
+
+/* CR10 - 4 */
+typedef enum {
+ AB8500_CODEC_CR10_MUTEHSR_DISABLED,
+ AB8500_CODEC_CR10_MUTEHSR_ENABLED
+} t_ab8500_codec_cr10_mutehsr;
+
+/* CR11 - 7 */
+typedef enum {
+ AB8500_CODEC_CR11_ENSHORTPWD_DISABLED,
+ AB8500_CODEC_CR11_ENSHORTPWD_ENABLED
+} t_ab8500_codec_cr11_enshortpwd;
+
+/* CR11 - 6 */
+typedef enum {
+ AB8500_CODEC_CR11_EARSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_EARSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_earshortdis;
+
+/* CR11 - 5 */
+typedef enum {
+ AB8500_CODEC_CR11_HSSHORTDIS_ENABLED,
+ AB8500_CODEC_CR11_HSSHORTDIS_DISABLED
+} t_ab8500_codec_cr11_hsshortdis;
+
+/* CR11 - 4 */
+typedef enum {
+ AB8500_CODEC_CR11_HSPULLDEN_HIGH,
+ AB8500_CODEC_CR11_HSPULLDEN_DOWN
+} t_ab8500_codec_cr11_hspullden;
+
+/* CR11 - 2 */
+typedef enum {
+ AB8500_CODEC_CR11_HSOSCEN_SYSTEMCLOCK,
+ AB8500_CODEC_CR11_HSOSCEN_LOCALOSC
+} t_ab8500_codec_cr11_hsoscen;
+
+/* CR11 - 1 */
+typedef enum {
+ AB8500_CODEC_CR11_HSFADEN_FADING,
+ AB8500_CODEC_CR11_HSFADEN_IMMEDIATELY
+} t_ab8500_codec_cr11_hsfaden;
+
+/* CR11 - 0 */
+typedef enum {
+ AB8500_CODEC_CR11_HSZCDDIS_ONZEROCROSS,
+ AB8500_CODEC_CR11_HSZCDDIS_WITHOUTZEROCROSS
+} t_ab8500_codec_cr11_hszcddis;
+
+/* CR12 - 7 */
+typedef enum {
+ AB8500_CODEC_CR12_ENCPHS_DISABLED,
+ AB8500_CODEC_CR12_ENCPHS_ENABLED
+} t_ab8500_codec_cr12_encphs;
+
+/* CR12 - 0 */
+typedef enum {
+ AB8500_CODEC_CR12_HSAUTOEN_DISABLED,
+ AB8500_CODEC_CR12_HSAUTOEN_ENABLED
+} t_ab8500_codec_cr12_hsautoen;
+
+/* CR13 - 7:4 */
+typedef enum {
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_25,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_50,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_100,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_150,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_200,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_250,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_300,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_350,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_400,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_450,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_500,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_550,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_600,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_650,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_700,
+ AB8500_CODEC_CR13_ENVDET_HTHRESH_750
+} t_ab8500_codec_cr13_envdet_hthresh;
+
+/* CR13 - 3:0 */
+typedef enum {
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_25,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_50,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_100,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_150,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_200,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_250,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_300,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_350,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_400,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_450,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_500,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_550,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_600,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_650,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_700,
+ AB8500_CODEC_CR13_ENVDET_LTHRESH_750
+} t_ab8500_codec_cr13_envdet_lthresh;
+
+/* CR14 - 7 */
+typedef enum {
+ AB8500_CODEC_CR14_SMPSLVEN_HIGHVOLTAGE,
+ AB8500_CODEC_CR14_SMPSLVEN_LOWVOLTAGE
+} t_ab8500_codec_cr14_smpslven;
+
+/* CR14 - 6 */
+typedef enum {
+ AB8500_CODEC_CR14_ENVDETSMPSEN_DISABLED,
+ AB8500_CODEC_CR14_ENVDETSMPSEN_ENABLED
+} t_ab8500_codec_cr14_envdetsmpsen;
+
+/* CR14 - 5 */
+typedef enum {
+ AB8500_CODEC_CR14_CPLVEN_HIGHVOLTAGE,
+ AB8500_CODEC_CR14_CPLVEN_LOWVOLTAGE
+} t_ab8500_codec_cr14_cplven;
+
+/* CR14 - 4 */
+typedef enum {
+ AB8500_CODEC_CR14_ENVDETCPEN_DISABLED,
+ AB8500_CODEC_CR14_ENVDETCPEN_ENABLED
+} t_ab8500_codec_cr14_envdetcpen;
+
+/* CR14 - 3:0 */
+typedef enum {
+ AB8500_CODEC_CR14_ENVET_TIME_27USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_53USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_106USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_212USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_424USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_848USEC,
+ AB8500_CODEC_CR14_ENVET_TIME_1MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_3MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_6MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_13MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_27MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_54MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_109MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_218MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_436MSEC,
+ AB8500_CODEC_CR14_ENVET_TIME_872MSEC,
+} t_ab8500_codec_cr14_envet_time;
+
+/* CR15 - 7 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMTOVIBL_DA_PATH,
+ AB8500_CODEC_CR15_PWMTOVIBL_PWM
+} t_ab8500_codec_cr15_pwmtovibl;
+
+/* CR15 - 6 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMTOVIBR_DA_PATH,
+ AB8500_CODEC_CR15_PWMTOVIBR_PWM
+} t_ab8500_codec_cr15_pwmtovibr;
+
+/* CR15 - 5 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMLCTRL_PWMNPLGPOL,
+ AB8500_CODEC_CR15_PWMLCTRL_PWMNPLDUTYCYCLE
+} t_ab8500_codec_cr15_pwmlctrl;
+
+/* CR15 - 4 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMRCTRL_PWMNPRGPOL,
+ AB8500_CODEC_CR15_PWMRCTRL_PWMNPRDUTYCYCLE
+} t_ab8500_codec_cr15_pwmrctrl;
+
+/* CR15 - 3 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMNLCTRL_PWMNLGPOL,
+ AB8500_CODEC_CR15_PWMNLCTRL_PWMNLDUTYCYCLE
+} t_ab8500_codec_cr15_pwmnlctrl;
+
+/* CR15 - 2 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMPLCTRL_PWMPLGPOL,
+ AB8500_CODEC_CR15_PWMPLCTRL_PWMPLDUTYCYCLE
+} t_ab8500_codec_cr15_pwmplctrl;
+
+/* CR15 - 1 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMNRCTRL_PWMNRGPOL,
+ AB8500_CODEC_CR15_PWMNRCTRL_PWMNRDUTYCYCLE
+} t_ab8500_codec_cr15_pwmnrctrl;
+
+/* CR15 - 0 */
+typedef enum {
+ AB8500_CODEC_CR15_PWMPRCTRL_PWMPRGPOL,
+ AB8500_CODEC_CR15_PWMPRCTRL_PWMPRDUTYCYCLE
+} t_ab8500_codec_cr15_pwmprctrl;
+
+/* CR16 - 7 */
+typedef enum {
+ AB8500_CODEC_CR16_PWMNLPOL_GNDVIB,
+ AB8500_CODEC_CR16_PWMNLPOL_VINVIB
+} t_ab8500_codec_cr16_pwmnlpol;
+
+/* CR16 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr16_pwmnldutycycle;
+
+/* CR17 - 7 */
+typedef enum {
+ AB8500_CODEC_CR17_PWMPLPOL_GNDVIB,
+ AB8500_CODEC_CR17_PWMPLPOL_VINVIB
+} t_ab8500_codec_cr17_pwmplpol;
+
+/* CR17 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr17_pwmpldutycycle;
+
+/* CR18 - 7 */
+typedef enum {
+ AB8500_CODEC_CR18_PWMNRPOL_GNDVIB,
+ AB8500_CODEC_CR18_PWMNRPOL_VINVIB
+} t_ab8500_codec_cr18_pwmnrpol;
+
+/* CR18 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr18_pwmnrdutycycle;
+
+/* CR19 - 7 */
+typedef enum {
+ AB8500_CODEC_CR19_PWMPRPOL_GNDVIB,
+ AB8500_CODEC_CR19_PWMPRPOL_VINVIB
+} t_ab8500_codec_cr19_pwmprpol;
+
+/* CR19 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr19_pwmprdutycycle;
+
+/* CR20 - 7 */
+typedef enum {
+ AB8500_CODEC_CR20_EN_SE_MIC1_DIFFERENTIAL,
+ AB8500_CODEC_CR20_EN_SE_MIC1_SINGLE
+} t_ab8500_codec_cr20_en_se_mic1;
+
+/* CR20 - 6 */
+typedef enum {
+ AB8500_CODEC_CR20_LOW_POW_MIC1_NORMAL,
+ AB8500_CODEC_CR20_LOW_POW_MIC1_LOW_POWER
+} t_ab8500_codec_cr20_low_pow_mic1;
+
+/* CR20 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr20_mic1_gain;
+
+/* CR21 - 7 */
+typedef enum {
+ AB8500_CODEC_CR21_EN_SE_MIC2_DIFFERENTIAL,
+ AB8500_CODEC_CR21_EN_SE_MIC2_SINGLE
+} t_ab8500_codec_cr21_en_se_mic2;
+
+/* CR21 - 6 */
+typedef enum {
+ AB8500_CODEC_CR21_LOW_POW_MIC2_NORMAL,
+ AB8500_CODEC_CR21_LOW_POW_MIC2_LOW_POWER
+} t_ab8500_codec_cr21_low_pow_mic2;
+
+/* CR21 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr21_mic2_gain;
+
+/* CR22 - 7:4 */
+typedef t_uint8 t_ab8500_codec_cr22_hsl_gain;
+
+/* CR22 - 3:0 */
+typedef t_uint8 t_ab8500_codec_cr22_hsr_gain;
+
+/* CR23 - 7:4 */
+typedef t_uint8 t_ab8500_codec_cr23_linl_gain;
+
+/* CR23 - 3:0 */
+typedef t_uint8 t_ab8500_codec_cr23_linr_gain;
+
+/* CR24 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr24_lintohsl_gain;
+
+/* CR25 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr25_lintohsr_gain;
+
+/* CR26 - 7 */
+typedef enum {
+ AB8500_CODEC_CR26_AD1NH_FILTER_ENABLED,
+ AB8500_CODEC_CR26_AD1NH_FILTER_DISABLED
+} t_ab8500_codec_cr26_ad1nh;
+
+/* CR26 - 6 */
+typedef enum {
+ AB8500_CODEC_CR26_AD2NH_FILTER_ENABLED,
+ AB8500_CODEC_CR26_AD2NH_FILTER_DISABLED
+} t_ab8500_codec_cr26_ad2nh;
+
+/* CR26 - 5 */
+typedef enum {
+ AB8500_CODEC_CR26_AD3NH_FILTER_ENABLED,
+ AB8500_CODEC_CR26_AD3NH_FILTER_DISABLED
+} t_ab8500_codec_cr26_ad3nh;
+
+/* CR26 - 4 */
+typedef enum {
+ AB8500_CODEC_CR26_AD4NH_FILTER_ENABLED,
+ AB8500_CODEC_CR26_AD4NH_FILTER_DISABLED
+} t_ab8500_codec_cr26_ad4nh;
+
+/* CR26 - 3 */
+typedef enum {
+ AB8500_CODEC_CR26_AD1_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR26_AD1_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr26_ad1_voice;
+
+/* CR26 - 2 */
+typedef enum {
+ AB8500_CODEC_CR26_AD2_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR26_AD2_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr26_ad2_voice;
+
+/* CR26 - 1 */
+typedef enum {
+ AB8500_CODEC_CR26_AD3_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR26_AD3_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr26_ad3_voice;
+
+/* CR26 - 0 */
+typedef enum {
+ AB8500_CODEC_CR26_AD4_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR26_AD4_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr26_ad4_voice;
+
+/* CR27 - 7 */
+typedef enum {
+ AB8500_CODEC_CR27_EN_MASTGEN_DISABLED,
+ AB8500_CODEC_CR27_EN_MASTGEN_ENABLED
+} t_ab8500_codec_cr27_en_mastgen;
+
+/* CR27 - 6:5 */
+/* In ab8500_codec.h */
+
+/* CR27 - 4 */
+typedef enum {
+ AB8500_CODEC_CR27_ENFS_BITCLK1_DISABLED,
+ AB8500_CODEC_CR27_ENFS_BITCLK1_ENABLED
+} t_ab8500_codec_cr27_enfs_bitclk1;
+
+/* CR27 - 2:1 */
+/* In ab8500_codec.h */
+
+/* CR27 - 0 */
+typedef enum {
+ AB8500_CODEC_CR27_ENFS_BITCLK0_DISABLED,
+ AB8500_CODEC_CR27_ENFS_BITCLK0_ENABLED
+} t_ab8500_codec_cr27_enfs_bitclk0;
+
+/* CR28 - 6 */
+typedef enum {
+ AB8500_CODEC_CR28_FSYNC0P_RISING_EDGE,
+ AB8500_CODEC_CR28_FSYNC0P_FALLING_EDGE
+} t_ab8500_codec_cr28_fsync0p;
+
+/* CR28 - 5 */
+typedef enum {
+ AB8500_CODEC_CR28_BITCLK0P_RISING_EDGE,
+ AB8500_CODEC_CR28_BITCLK0P_FALLING_EDGE
+} t_ab8500_codec_cr28_bitclk0p;
+
+/* CR28 - 4 */
+typedef enum {
+ AB8500_CODEC_CR28_IF0DEL_NOT_DELAYED,
+ AB8500_CODEC_CR28_IF0DEL_DELAYED
+} t_ab8500_codec_cr28_if0del;
+
+/* CR28 - 3:2 */
+typedef enum {
+ AB8500_CODEC_CR28_IF0FORMAT_DISABLED,
+ AB8500_CODEC_CR28_IF0FORMAT_TDM,
+ AB8500_CODEC_CR28_IF0FORMAT_I2S_LEFTALIGNED
+} t_ab8500_codec_cr28_if0format;
+
+/* CR28 - 1:0 */
+/* In ab8500_codec.h */
+
+/* CR29 - 7 */
+typedef enum {
+ AB8500_CODEC_CR29_IF0DATOIF1AD_NOTSENT,
+ AB8500_CODEC_CR29_IF0DATOIF1AD_SENT
+} t_ab8500_codec_cr29_if0datoif1ad;
+
+/* CR29 - 6 */
+typedef enum {
+ AB8500_CODEC_CR29_IF0CKTOIF1CK_NOTSENT,
+ AB8500_CODEC_CR29_IF0CKTOIF1CK_SENT
+} t_ab8500_codec_cr29_if0cktoif1ck;
+
+/* CR29 - 5 */
+typedef enum {
+ AB8500_CODEC_CR29_IF1MASTER_FS1CK1_INPUT,
+ AB8500_CODEC_CR29_IF1MASTER_FS1CK1_OUTPUT
+} t_ab8500_codec_cr29_if1master;
+
+/* CR29 - 3 */
+typedef enum {
+ AB8500_CODEC_CR29_IF1DATOIF0AD_NOTSENT,
+ AB8500_CODEC_CR29_IF1DATOIF0AD_SENT
+} t_ab8500_codec_cr29_if1datoif0ad;
+
+/* CR29 - 2 */
+typedef enum {
+ AB8500_CODEC_CR29_IF1CKTOIF0CK_NOTSENT,
+ AB8500_CODEC_CR29_IF1CKTOIF0CK_SENT
+} t_ab8500_codec_cr29_if1cktoif0ck;
+
+/* CR29 - 1 */
+typedef enum {
+ AB8500_CODEC_CR29_IF0MASTER_FS0CK0_INPUT,
+ AB8500_CODEC_CR29_IF0MASTER_FS0CK0_OUTPUT
+} t_ab8500_codec_cr29_if0master;
+
+/* CR29 - 0 */
+typedef enum {
+ AB8500_CODEC_CR29_IF0BFIFOEN_NORMAL_MODE,
+ AB8500_CODEC_CR29_IF0BFIFOEN_BURST_MODE
+} t_ab8500_codec_cr29_if0bfifoen;
+
+/* CR30 - 6 */
+typedef enum {
+ AB8500_CODEC_CR30_FSYNC1P_RISING_EDGE,
+ AB8500_CODEC_CR30_FSYNC1P_FALLING_EDGE
+} t_ab8500_codec_cr30_fsync1p;
+
+/* CR30 - 5 */
+typedef enum {
+ AB8500_CODEC_CR30_BITCLK1P_RISING_EDGE,
+ AB8500_CODEC_CR30_BITCLK1P_FALLING_EDGE
+} t_ab8500_codec_cr30_bitclk1p;
+
+/* CR30 - 4 */
+typedef enum {
+ AB8500_CODEC_CR30_IF1DEL_NOT_DELAYED,
+ AB8500_CODEC_CR30_IF1DEL_DELAYED
+} t_ab8500_codec_cr30_if1del;
+
+/* CR30 - 3:2 */
+typedef enum {
+ AB8500_CODEC_CR30_IF1FORMAT_DISABLED,
+ AB8500_CODEC_CR30_IF1FORMAT_TDM,
+ AB8500_CODEC_CR30_IF1FORMAT_I2S_LEFTALIGNED
+} t_ab8500_codec_cr30_if1format;
+
+/* CR30 - 1:0 */
+/* In ab8500_codec.h */
+
+/* CR31:46 - 7:4 or 3:0 */
+/* In ab8500_codec.h */
+
+/* CR47:50 - 7/6/5/4/3/2/1/0 */
+typedef enum {
+ AB8500_CODEC_CR47_TO_CR50_HIZ_SL_LOW_IMPEDANCE,
+ AB8500_CODEC_CR47_TO_CR50_HIZ_SL_HIGH_IMPEDANCE,
+} t_ab8500_codec_cr47_to_cr50_hiz_sl;
+
+/* CR51 - 7 */
+typedef enum {
+ AB8500_CODEC_CR51_DA12_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR51_DA12_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr51_da12_voice;
+
+/* CR51 - 6 */
+typedef enum {
+ AB8500_CODEC_CR51_SWAPDA12_34_NORMAL,
+ AB8500_CODEC_CR51_SWAPDA12_34_SWAPPED
+} t_ab8500_codec_cr51_swapda12_34;
+
+/* CR51 - 5 */
+typedef enum {
+ AB8500_CODEC_CR51_SLDAI7TOSLADO1_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR51_SLDAI7TOSLADO1_LOOPEDBACK
+} t_ab8500_codec_cr51_sldai7toslado1;
+
+/* CR51:58 - 4:0 */
+/* In ab8500_codec.h */
+
+/* CR52 - 5 */
+typedef enum {
+ AB8500_CODEC_CR52_SLDAI8TOSLADO2_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR52_SLDAI8TOSLADO2_LOOPEDBACK
+} t_ab8500_codec_cr52_sldai8toslado2;
+
+/* CR53 - 7 */
+typedef enum {
+ AB8500_CODEC_CR53_DA34_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR53_DA34_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr53_da34_voice;
+
+/* CR53 - 5 */
+typedef enum {
+ AB8500_CODEC_CR53_SLDAI7TOSLADO3_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR53_SLDAI7TOSLADO3_LOOPEDBACK
+} t_ab8500_codec_cr53_sldai7toslado3;
+
+/* CR54 - 5 */
+typedef enum {
+ AB8500_CODEC_CR54_SLDAI8TOSLADO4_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR54_SLDAI8TOSLADO4_LOOPEDBACK
+} t_ab8500_codec_cr54_sldai8toslado4;
+
+/* CR55 - 7 */
+typedef enum {
+ AB8500_CODEC_CR55_DA56_VOICE_AUDIOFILTER,
+ AB8500_CODEC_CR55_DA56_VOICE_LOWLATENCYFILTER
+} t_ab8500_codec_cr55_da56_voice;
+
+/* CR55 - 5 */
+typedef enum {
+ AB8500_CODEC_CR55_SLDAI7TOSLADO5_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR55_SLDAI7TOSLADO5_LOOPEDBACK
+} t_ab8500_codec_cr55_sldai7toslado5;
+
+/* CR56 - 5 */
+typedef enum {
+ AB8500_CODEC_CR56_SLDAI8TOSLADO6_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR56_SLDAI8TOSLADO6_LOOPEDBACK
+} t_ab8500_codec_cr56_sldai8toslado6;
+
+/* CR57 - 5 */
+typedef enum {
+ AB8500_CODEC_CR57_SLDAI8TOSLADO7_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR57_SLDAI8TOSLADO7_LOOPEDBACK
+} t_ab8500_codec_cr57_sldai8toslado7;
+
+/* CR58 - 5 */
+typedef enum {
+ AB8500_CODEC_CR58_SLDAI7TOSLADO8_NOT_LOOPEDBACK,
+ AB8500_CODEC_CR58_SLDAI7TOSLADO8_LOOPEDBACK
+} t_ab8500_codec_cr58_sldai7toslado8;
+
+/* CR59 - 7 */
+typedef enum {
+ AB8500_CODEC_CR59_PARLHF_INDEPENDENT,
+ AB8500_CODEC_CR59_PARLHF_BRIDGED
+} t_ab8500_codec_cr59_parlhf;
+
+/* CR59 - 6 */
+typedef enum {
+ AB8500_CODEC_CR59_PARLVIB_INDEPENDENT,
+ AB8500_CODEC_CR59_PARLVIB_BRIDGED
+} t_ab8500_codec_cr59_parlvib;
+
+/* CR59 - 3 */
+typedef enum {
+ AB8500_CODEC_CR59_CLASSDVIB1_SWAPEN_DISABLED,
+ AB8500_CODEC_CR59_CLASSDVIB1_SWAPEN_ENABLED
+} t_ab8500_codec_cr59_classdvib1_swapen;
+
+/* CR59 - 2 */
+typedef enum {
+ AB8500_CODEC_CR59_CLASSDVIB2_SWAPEN_DISABLED,
+ AB8500_CODEC_CR59_CLASSDVIB2_SWAPEN_ENABLED
+} t_ab8500_codec_cr59_classdvib2_swapen;
+
+/* CR59 - 1 */
+typedef enum {
+ AB8500_CODEC_CR59_CLASSDHFL_SWAPEN_DISABLED,
+ AB8500_CODEC_CR59_CLASSDHFL_SWAPEN_ENABLED
+} t_ab8500_codec_cr59_classdhfl_swapen;
+
+/* CR59 - 0 */
+typedef enum {
+ AB8500_CODEC_CR59_CLASSDHFR_SWAPEN_DISABLED,
+ AB8500_CODEC_CR59_CLASSDHFR_SWAPEN_ENABLED
+} t_ab8500_codec_cr59_classdhfr_swapen;
+
+/* CR60 - 7:4 */
+typedef enum {
+ AB8500_CODEC_CR60_CLASSD_FIRBYP_ALL_ENABLED = 0,
+ AB8500_CODEC_CR60_CLASSD_FIRBYP_LEFT_HF_BYPASSED = 1,
+ AB8500_CODEC_CR60_CLASSD_FIRBYP_RIGHT_HF_BYPASSED = 2,
+ AB8500_CODEC_CR60_CLASSD_FIRBYP_VIBRA1_BYPASSED = 4,
+ AB8500_CODEC_CR60_CLASSD_FIRBYP_VIBRA2_BYPASSED = 8
+} t_ab8500_codec_cr60_classd_firbyp;
+
+/* CR60 - 3:0 */
+typedef enum {
+ AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_DISABLED = 0,
+ AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_LEFT_HF = 1,
+ AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_RIGHT_HF = 2,
+ AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_VIBRA1 = 4,
+ AB8500_CODEC_CR60_CLASSD_HIGHVOLEN_VIBRA2 = 8
+} t_ab8500_codec_cr60_classd_highvolen;
+
+/* CR61 - 7:4 */
+typedef t_uint8 t_ab8500_codec_cr61_classddith_hpgain;
+
+/* CR61 - 3:0 */
+typedef t_uint8 t_ab8500_codec_cr61_classddith_wgain;
+
+/* CR62 - Read Only */
+/* CR62 - 5 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC1SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC1SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic1sinc3;
+
+/* CR62 - 4 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC2SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC2SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic2sinc3;
+
+/* CR62 - 3 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC3SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC3SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic3sinc3;
+
+/* CR62 - 2 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC4SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC4SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic4sinc3;
+
+/* CR62 - 1 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC5SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC5SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic5sinc3;
+
+/* CR62 - 0 */
+typedef enum {
+ AB8500_CODEC_CR62_DMIC6SINC3_SINC5_SELECTED,
+ AB8500_CODEC_CR62_DMIC6SINC3_SINC3_SELECTED
+} t_ab8500_codec_cr62_dmic6sinc3;
+
+/* CR63 - 7 */
+typedef enum {
+ AB8500_CODEC_CR63_DATOHSLEN_DISABLED,
+ AB8500_CODEC_CR63_DATOHSLEN_ENABLED
+} t_ab8500_codec_cr63_datohslen;
+
+/* CR63 - 6 */
+typedef enum {
+ AB8500_CODEC_CR63_DATOHSREN_DISABLED,
+ AB8500_CODEC_CR63_DATOHSREN_ENABLED
+} t_ab8500_codec_cr63_datohsren;
+
+/* CR63 - 5 */
+typedef enum {
+ AB8500_CODEC_CR63_AD1SEL_LINLADL_SELECTED,
+ AB8500_CODEC_CR63_AD1SEL_DMIC1_SELECTED
+} t_ab8500_codec_cr63_ad1sel;
+
+/* CR63 - 4 */
+typedef enum {
+ AB8500_CODEC_CR63_AD2SEL_LINRADR_SELECTED,
+ AB8500_CODEC_CR63_AD2SEL_DMIC2_SELECTED
+} t_ab8500_codec_cr63_ad2sel;
+
+/* CR63 - 3 */
+typedef enum {
+ AB8500_CODEC_CR63_AD3SEL_ADMO_SELECTED,
+ AB8500_CODEC_CR63_AD3SEL_DMIC3_SELECTED
+} t_ab8500_codec_cr63_ad3sel;
+
+/* CR63 - 2 */
+typedef enum {
+ AB8500_CODEC_CR63_AD5SEL_AMADR_SELECTED,
+ AB8500_CODEC_CR63_AD5SEL_DMIC5_SELECTED
+} t_ab8500_codec_cr63_ad5sel;
+
+/* CR63 - 1 */
+typedef enum {
+ AB8500_CODEC_CR63_AD6SEL_ADMO_SELECTED,
+ AB8500_CODEC_CR63_AD6SEL_DMIC6_SELECTED
+} t_ab8500_codec_cr63_ad6sel;
+
+/* CR63 - 0 */
+typedef enum {
+ AB8500_CODEC_CR63_ANCSEL_NOT_MIXED_IN_EAR,
+ AB8500_CODEC_CR63_ANCSEL_MIXED_IN_EAR
+} t_ab8500_codec_cr63_ancsel;
+
+/* CR64 - 7 */
+typedef enum {
+ AB8500_CODEC_CR64_DATOHFREN_NOT_MIXED_TO_HFR,
+ AB8500_CODEC_CR64_DATOHFREN_MIXED_TO_HFR
+} t_ab8500_codec_cr64_datohfren;
+
+/* CR64 - 6 */
+typedef enum {
+ AB8500_CODEC_CR64_DATOHFLEN_NOT_MIXED_TO_HFL,
+ AB8500_CODEC_CR64_DATOHFLEN_MIXED_TO_HFL
+} t_ab8500_codec_cr64_datohflen;
+
+/* CR64 - 5 */
+typedef enum {
+ AB8500_CODEC_CR64_HFRSEL_DA4_MIXED_TO_HFR,
+ AB8500_CODEC_CR64_HFRSEL_ANC_MIXED_TO_HFR
+} t_ab8500_codec_cr64_hfrsel;
+
+/* CR64 - 4 */
+typedef enum {
+ AB8500_CODEC_CR64_HFLSEL_DA3_MIXED_TO_HFL,
+ AB8500_CODEC_CR64_HFLSEL_ANC_MIXED_TO_HFL
+} t_ab8500_codec_cr64_hflsel;
+
+/* CR64 - 3:2 */
+typedef enum {
+ AB8500_CODEC_CR64_STFIR1SEL_AD_OUT1_SELECTED,
+ AB8500_CODEC_CR64_STFIR1SEL_AD_OUT3_SELECTED,
+ AB8500_CODEC_CR64_STFIR1SEL_DA_IN1_SELECTED
+} t_ab8500_codec_cr64_stfir1sel;
+
+/* CR64 - 1:0 */
+typedef enum {
+ AB8500_CODEC_CR64_STFIR2SEL_AD_OUT2_SELECTED,
+ AB8500_CODEC_CR64_STFIR2SEL_AD_OUT4_SELECTED,
+ AB8500_CODEC_CR64_STFIR2SEL_DA_IN2_SELECTED
+} t_ab8500_codec_cr64_stfir2sel;
+
+/* CR65 - 6 */
+typedef enum {
+ AB8500_CODEC_CR65_FADEDIS_AD1_ENABLED,
+ AB8500_CODEC_CR65_FADEDIS_AD1_DISABLED
+} t_ab8500_codec_cr65_fadedis_ad1;
+
+/* CR65 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr65_ad1gain;
+
+/* CR66 - 6 */
+typedef enum {
+ AB8500_CODEC_CR66_FADEDIS_AD2_ENABLED,
+ AB8500_CODEC_CR66_FADEDIS_AD2_DISABLED
+} t_ab8500_codec_cr66_fadedis_ad2;
+
+/* CR66 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr66_ad2gain;
+
+/* CR67 - 6 */
+typedef enum {
+ AB8500_CODEC_CR67_FADEDIS_AD3_ENABLED,
+ AB8500_CODEC_CR67_FADEDIS_AD3_DISABLED
+} t_ab8500_codec_cr67_fadedis_ad3;
+
+/* CR67 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr67_ad3gain;
+
+/* CR68 - 6 */
+typedef enum {
+ AB8500_CODEC_CR68_FADEDIS_AD4_ENABLED,
+ AB8500_CODEC_CR68_FADEDIS_AD4_DISABLED
+} t_ab8500_codec_cr68_fadedis_ad4;
+
+/* CR68 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr68_ad4gain;
+
+/* CR69 - 6 */
+typedef enum {
+ AB8500_CODEC_CR69_FADEDIS_AD5_ENABLED,
+ AB8500_CODEC_CR69_FADEDIS_AD5_DISABLED
+} t_ab8500_codec_cr69_fadedis_ad5;
+
+/* CR69 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr69_ad5gain;
+
+/* CR70 - 6 */
+typedef enum {
+ AB8500_CODEC_CR70_FADEDIS_AD6_ENABLED,
+ AB8500_CODEC_CR70_FADEDIS_AD6_DISABLED
+} t_ab8500_codec_cr70_fadedis_ad6;
+
+/* CR70 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr70_ad6gain;
+
+/* CR71 - 6 */
+typedef enum {
+ AB8500_CODEC_CR71_FADEDIS_DA1_ENABLED,
+ AB8500_CODEC_CR71_FADEDIS_DA1_DISABLED
+} t_ab8500_codec_cr71_fadedis_da1;
+
+/* CR71 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr71_da1gain;
+
+/* CR72 - 6 */
+typedef enum {
+ AB8500_CODEC_CR72_FADEDIS_DA2_ENABLED,
+ AB8500_CODEC_CR72_FADEDIS_DA2_DISABLED
+} t_ab8500_codec_cr72_fadedis_da2;
+
+/* CR72 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr72_da2gain;
+
+/* CR73 - 6 */
+typedef enum {
+ AB8500_CODEC_CR73_FADEDIS_DA3_ENABLED,
+ AB8500_CODEC_CR73_FADEDIS_DA3_DISABLED
+} t_ab8500_codec_cr73_fadedis_da3;
+
+/* CR73 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr73_da3gain;
+
+/* CR74 - 6 */
+typedef enum {
+ AB8500_CODEC_CR74_FADEDIS_DA4_ENABLED,
+ AB8500_CODEC_CR74_FADEDIS_DA4_DISABLED
+} t_ab8500_codec_cr74_fadedis_da4;
+
+/* CR74 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr74_da4gain;
+
+/* CR75 - 6 */
+typedef enum {
+ AB8500_CODEC_CR75_FADEDIS_DA5_ENABLED,
+ AB8500_CODEC_CR75_FADEDIS_DA5_DISABLED
+} t_ab8500_codec_cr75_fadedis_da5;
+
+/* CR75 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr75_da5gain;
+
+/* CR76 - 6 */
+typedef enum {
+ AB8500_CODEC_CR76_FADEDIS_DA6_ENABLED,
+ AB8500_CODEC_CR76_FADEDIS_DA6_DISABLED
+} t_ab8500_codec_cr76_fadedis_da6;
+
+/* CR76 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr76_da6gain;
+
+/* CR77 - 6 */
+typedef enum {
+ AB8500_CODEC_CR77_FADEDIS_AD1L_TO_HFL_ENABLED,
+ AB8500_CODEC_CR77_FADEDIS_AD1L_TO_HFL_DISABLED
+} t_ab8500_codec_cr77_fadedis_ad1l;
+
+/* CR77 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr77_ad1lbgain_to_hfl;
+
+/* CR78 - 6 */
+typedef enum {
+ AB8500_CODEC_CR78_FADEDIS_AD2L_TO_HFR_ENABLED,
+ AB8500_CODEC_CR78_FADEDIS_AD2L_TO_HFR_DISABLED
+} t_ab8500_codec_cr78_fadedis_ad2l;
+
+/* CR78 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr78_ad2lbgain_to_hfr;
+
+/* CR79 - 7 */
+typedef enum {
+ AB8500_CODEC_CR79_HSSINC1_SINC3_CHOOSEN,
+ AB8500_CODEC_CR79_HSSINC1_SINC1_CHOOSEN
+} t_ab8500_codec_cr79_hssinc1;
+
+/* CR79 - 4 */
+typedef enum {
+ AB8500_CODEC_CR79_FADEDIS_HSL_ENABLED,
+ AB8500_CODEC_CR79_FADEDIS_HSL_DISABLED
+} t_ab8500_codec_cr79_fadedis_hsl;
+
+/* CR79 - 3:0 */
+typedef t_uint8 t_ab8500_codec_cr79_hsldgain;
+
+/* CR80 - 7:6 */
+typedef enum {
+ AB8500_CODEC_CR80_FADE_SPEED_1MS,
+ AB8500_CODEC_CR80_FADE_SPEED_4MS,
+ AB8500_CODEC_CR80_FADE_SPEED_8MS,
+ AB8500_CODEC_CR80_FADE_SPEED_16MS,
+} t_ab8500_codec_cr80_fade_speed;
+
+/* CR80 - 4 */
+typedef enum {
+ AB8500_CODEC_CR80_FADEDIS_HSR_ENABLED,
+ AB8500_CODEC_CR80_FADEDIS_HSR_DISABLED
+} t_ab8500_codec_cr80_fadedis_hsr;
+
+/* CR80 - 3:0 */
+typedef t_uint8 t_ab8500_codec_cr80_hsrdgain;
+
+/* CR81 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr81_stfir1gain;
+
+/* CR82 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr82_stfir2gain;
+
+/* CR83 - 2 */
+typedef enum {
+ AB8500_CODEC_CR83_ENANC_DISABLED,
+ AB8500_CODEC_CR83_ENANC_ENABLED
+} t_ab8500_codec_cr83_enanc;
+
+/* CR83 - 1 */
+typedef enum {
+ AB8500_CODEC_CR83_ANCIIRINIT_NOT_STARTED,
+ AB8500_CODEC_CR83_ANCIIRINIT_STARTED
+} t_ab8500_codec_cr83_anciirinit;
+
+/* CR83 - 0 */
+typedef enum {
+ AB8500_CODEC_CR83_ANCFIRUPDATE_RESETTED,
+ AB8500_CODEC_CR83_ANCFIRUPDATE_NOT_RESETTED
+} t_ab8500_codec_cr83_ancfirupdate;
+
+/* CR84 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr84_ancinshift;
+
+/* CR85 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr85_ancfiroutshift;
+
+/* CR86 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr86_ancshiftout;
+
+/* CR87 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr87_ancfircoeff_msb;
+
+/* CR88 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr88_ancfircoeff_lsb;
+
+/* CR89 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr89_anciircoeff_msb;
+
+/* CR90 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr90_anciircoeff_lsb;
+
+/* CR91 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr91_ancwarpdel_msb;
+
+/* CR92 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr92_ancwarpdel_lsb;
+
+/* CR93 - Read Only */
+/* CR93 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr93_ancfirpeak_msb;
+
+/* CR94 - Read Only */
+/* CR94 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr94_ancfirpeak_lsb;
+
+/* CR95 - Read Only */
+/* CR95 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr95_anciirpeak_msb;
+
+/* CR96 - Read Only */
+/* CR96 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr96_anciirpeak_lsb;
+
+/* CR97 - 7 */
+typedef enum {
+ AB8500_CODEC_CR97_STFIR_SET_LAST_NOT_APPLIED,
+ AB8500_CODEC_CR97_STFIR_SET_LAST_APPLIED
+} t_ab8500_codec_cr97_stfir_set;
+
+/* CR97 - 6:0 */
+typedef t_uint8 t_ab8500_codec_cr97_stfir_addr;
+
+/* CR98 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr98_stfir_coeff_msb;
+
+/* CR99 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr99_stfir_coeff_lsb;
+
+/* CR100 - 2 */
+typedef enum {
+ AB8500_CODEC_CR100_ENSTFIRS_DISABLED,
+ AB8500_CODEC_CR100_ENSTFIRS_ENABLED
+} t_ab8500_codec_cr100_enstfirs;
+
+/* CR100 - 1 */
+typedef enum {
+ AB8500_CODEC_CR100_STFIRSTOIF1_AUD_IF0_DATA_RATE,
+ AB8500_CODEC_CR100_STFIRSTOIF1_AUD_IF1_DATA_RATE
+} t_ab8500_codec_cr100_stfirstoif1;
+
+/* CR100 - 0 */
+typedef enum {
+ AB8500_CODEC_CR100_STFIR_BUSY_READY,
+ AB8500_CODEC_CR100_STFIR_BUSY_NOT_READY
+} t_ab8500_codec_cr100_stfir_busy;
+
+/* CR101 - 7 */
+typedef enum {
+ AB8500_CODEC_CR101_HSOFFST_MASK_MASKED,
+ AB8500_CODEC_CR101_HSOFFST_MASK_ENABLED
+} t_ab8500_codec_cr101_hsoffst_mask;
+
+/* CR101 - 6 */
+typedef enum {
+ AB8500_CODEC_CR101_FIFOFULL_MASK_MASKED,
+ AB8500_CODEC_CR101_FIFOFULL_MASK_ENABLED
+} t_ab8500_codec_cr101_fifofull_mask;
+
+/* CR101 - 5 */
+typedef enum {
+ AB8500_CODEC_CR101_FIFOEMPTY_MASK_MASKED,
+ AB8500_CODEC_CR101_FIFOEMPTY_MASK_ENABLED
+} t_ab8500_codec_cr101_fifoempty_mask;
+
+/* CR101 - 4 */
+typedef enum {
+ AB8500_CODEC_CR101_DASAT_MASK_MASKED,
+ AB8500_CODEC_CR101_DASAT_MASK_ENABLED
+} t_ab8500_codec_cr101_dasat_mask;
+
+/* CR101 - 3 */
+typedef enum {
+ AB8500_CODEC_CR101_ADSAT_MASK_MASKED,
+ AB8500_CODEC_CR101_ADSAT_MASK_ENABLED
+} t_ab8500_codec_cr101_adsat_mask;
+
+/* CR101 - 2 */
+typedef enum {
+ AB8500_CODEC_CR101_ADDSP_MASK_MASKED,
+ AB8500_CODEC_CR101_ADDSP_MASK_ENABLED
+} t_ab8500_codec_cr101_addsp_mask;
+
+/* CR101 - 1 */
+typedef enum {
+ AB8500_CODEC_CR101_DADSP_MASK_MASKED,
+ AB8500_CODEC_CR101_DADSP_MASK_ENABLED
+} t_ab8500_codec_cr101_dadsp_mask;
+
+/* CR101 - 0 */
+typedef enum {
+ AB8500_CODEC_CR101_FIRSID_MASK_MASKED,
+ AB8500_CODEC_CR101_FIRSID_MASK_ENABLED
+} t_ab8500_codec_cr101_firsid_mask;
+
+/* CR102 - Read Only */
+/* CR102 - 7 */
+typedef enum {
+ AB8500_CODEC_CR102_IT_HSOFFST_ON,
+ AB8500_CODEC_CR102_IT_HSOFFST_OFF
+} t_ab8500_codec_cr102_it_hsoffst;
+
+/* CR102 - 6 */
+typedef enum {
+ AB8500_CODEC_CR102_IT_FIFOFULL_NOT_FULL,
+ AB8500_CODEC_CR102_IT_FIFOFULL_FULL
+} t_ab8500_codec_cr102_it_fifofull;
+
+/* CR102 - 5 */
+typedef enum {
+ AB8500_CODEC_CR102_IT_FIFOEMPTY_NOT_EMPTY,
+ AB8500_CODEC_CR102_IT_FIFOEMPTY_EMPTY
+} t_ab8500_codec_cr102_it_fifoempty;
+
+/* CR102 - 4 */
+typedef enum {
+ AB8500_CODEC_CR102_IT_DASAT_NO_SATURATION,
+ AB8500_CODEC_CR102_IT_DASAT_SATURATION
+} t_ab8500_codec_cr102_it_dasat;
+
+/* CR102 - 3 */
+typedef enum {
+ AB8500_CODEC_CR102_IT_ADSAT_NO_SATURATION,
+ AB8500_CODEC_CR102_IT_ADSAT_SATURATION
+} t_ab8500_codec_cr102_it_adsat;
+
+/* CR102 - 2 */
+typedef enum {
+ AB8500_CODEC_CR102_IT_ADDSP_NO_SATURATION,
+ AB8500_CODEC_CR102_IT_ADDSP_SATURATION
+} t_ab8500_codec_cr102_it_addsp;
+
+/* CR102 - 1 */
+typedef enum {
+ AB8500_CODEC_CR102_IT_DADSP_NO_SATURATION,
+ AB8500_CODEC_CR102_IT_DADSP_SATURATION
+} t_ab8500_codec_cr102_it_dadsp;
+
+/* CR102 - 0 */
+typedef enum {
+ AB8500_CODEC_CR102_IT_FIRSID_NO_SATURATION,
+ AB8500_CODEC_CR102_IT_FIRSID_SATURATION
+} t_ab8500_codec_cr102_it_firsid;
+
+/* CR103 - 7 */
+typedef enum {
+ AB8500_CODEC_CR103_VSSREADY_MASK_MASKED,
+ AB8500_CODEC_CR103_VSSREADY_MASK_ENABLED
+} t_ab8500_codec_cr103_vssready_mask;
+
+/* CR103 - 2 */
+typedef enum {
+ AB8500_CODEC_CR103_SHORTHSL_MASK_MASKED,
+ AB8500_CODEC_CR103_SHORTHSL_MASK_ENABLED
+} t_ab8500_codec_cr103_shorthsl_mask;
+
+/* CR103 - 1 */
+typedef enum {
+ AB8500_CODEC_CR103_SHORTHSR_MASK_MASKED,
+ AB8500_CODEC_CR103_SHORTHSR_MASK_ENABLED
+} t_ab8500_codec_cr103_shorthsr_mask;
+
+/* CR103 - 0 */
+typedef enum {
+ AB8500_CODEC_CR103_SHORTEAR_MASK_MASKED,
+ AB8500_CODEC_CR103_SHORTEAR_MASK_ENABLED
+} t_ab8500_codec_cr103_shortear_mask;
+
+/* CR104 - Read Only */
+/* CR104 - 7 */
+typedef enum {
+ AB8500_CODEC_CR104_IT_VSSREADY_NOT_READY,
+ AB8500_CODEC_CR104_IT_VSSREADY_READY
+} t_ab8500_codec_cr104_it_vssready;
+
+/* CR104 - 2 */
+typedef enum {
+ AB8500_CODEC_CR104_IT_SHORTHSL_NOT_DETECTED,
+ AB8500_CODEC_CR104_IT_SHORTHSL_DETECTED
+} t_ab8500_codec_cr104_it_shorthsl;
+
+/* CR104 - 1 */
+typedef enum {
+ AB8500_CODEC_CR104_IT_SHORTHSR_NOT_DETECTED,
+ AB8500_CODEC_CR104_IT_SHORTHSR_DETECTED
+} t_ab8500_codec_cr104_it_shorthsr;
+
+/* CR104 - 0 */
+typedef enum {
+ AB8500_CODEC_CR104_IT_SHORTEAR_NOT_DETECTED,
+ AB8500_CODEC_CR104_IT_SHORTEAR_DETECTED
+} t_ab8500_codec_cr104_it_shortear;
+
+/* CR105 - 7 */
+/* In ab8500_codec.h */
+
+/* CR105 - 5:0 */
+/* In ab8500_codec.h */
+
+/* CR106 - 7:0 */
+/* In ab8500_codec.h */
+
+/* CR107 - 7:0 */
+/* In ab8500_codec.h */
+
+/* CR108 - 7:0 */
+/* In ab8500_codec.h */
+
+/* CR109 - 7:0 */
+/* In ab8500_codec.h */
+
+/* CR110 - Read Only */
+/* CR110 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr110_bfifosamples;
+
+/* CR111 - Read Only */
+/* CR111 - 4:0 */
+typedef t_uint8 t_ab8500_codec_cr111_aud_ip_rev;
+
+/* CR27 - 6:5 */
+typedef enum {
+ AB8500_CODEC_CR27_IF1_BITCLK_OSR_32,
+ AB8500_CODEC_CR27_IF1_BITCLK_OSR_64,
+ AB8500_CODEC_CR27_IF1_BITCLK_OSR_128,
+ AB8500_CODEC_CR27_IF1_BITCLK_OSR_256
+} t_ab8500_codec_cr27_if1_bitclk_osr;
+
+/* CR27 - 2:1 */
+typedef enum {
+ AB8500_CODEC_CR27_IF0_BITCLK_OSR_32,
+ AB8500_CODEC_CR27_IF0_BITCLK_OSR_64,
+ AB8500_CODEC_CR27_IF0_BITCLK_OSR_128,
+ AB8500_CODEC_CR27_IF0_BITCLK_OSR_256
+} t_ab8500_codec_cr27_if0_bitclk_osr;
+
+/* CR28 - 1:0 */
+typedef enum {
+ AB8500_CODEC_CR28_IF0WL_16BITS,
+ AB8500_CODEC_CR28_IF0WL_20BITS,
+ AB8500_CODEC_CR28_IF0WL_24BITS,
+ AB8500_CODEC_CR28_IF0WL_32BITS
+} t_ab8500_codec_cr28_if0wl;
+
+/* CR30 - 1:0 */
+typedef enum {
+ AB8500_CODEC_CR30_IF1WL_16BITS,
+ AB8500_CODEC_CR30_IF1WL_20BITS,
+ AB8500_CODEC_CR30_IF1WL_24BITS,
+ AB8500_CODEC_CR30_IF1WL_32BITS
+} t_ab8500_codec_cr30_if1wl;
+
+/* CR105 - 7 */
+typedef enum {
+ AB8500_CODEC_CR105_BFIFOMSK_AD_DATA0_UNMASKED,
+ AB8500_CODEC_CR105_BFIFOMSK_AD_DATA0_MASKED
+} t_ab8500_codec_cr105_bfifomsk;
+
+/* CR105 - 5:0 */
+typedef t_uint8 t_ab8500_codec_cr105_bfifoint;
+
+/* CR106 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr106_bfifotx;
+
+/* CR107 - 7:5 */
+typedef enum {
+ AB8500_CODEC_CR107_BFIFOEXSL_0_EXTRA_SLOT,
+ AB8500_CODEC_CR107_BFIFOEXSL_1_EXTRA_SLOT,
+ AB8500_CODEC_CR107_BFIFOEXSL_2_EXTRA_SLOT,
+ AB8500_CODEC_CR107_BFIFOEXSL_3_EXTRA_SLOT,
+ AB8500_CODEC_CR107_BFIFOEXSL_4_EXTRA_SLOT,
+ AB8500_CODEC_CR107_BFIFOEXSL_5_EXTRA_SLOT,
+ AB8500_CODEC_CR107_BFIFOEXSL_6_EXTRA_SLOT,
+} t_ab8500_codec_cr107_bfifoexsl;
+
+/* CR107 - 4:2 */
+typedef enum {
+ AB8500_CODEC_CR107_PREBITCLK0_0_EXTRA_CLK,
+ AB8500_CODEC_CR107_PREBITCLK0_1_EXTRA_CLK,
+ AB8500_CODEC_CR107_PREBITCLK0_2_EXTRA_CLK,
+ AB8500_CODEC_CR107_PREBITCLK0_3_EXTRA_CLK,
+ AB8500_CODEC_CR107_PREBITCLK0_4_EXTRA_CLK,
+ AB8500_CODEC_CR107_PREBITCLK0_5_EXTRA_CLK,
+ AB8500_CODEC_CR107_PREBITCLK0_6_EXTRA_CLK,
+ AB8500_CODEC_CR107_PREBITCLK0_7_EXTRA_CLK
+} t_ab8500_codec_cr107_prebitclk0;
+
+/* CR107 - 1 */
+typedef enum {
+ AB8500_CODEC_CR107_BFIFOMAST_SLAVE_MODE,
+ AB8500_CODEC_CR107_BFIFOMAST_MASTER_MODE
+} t_ab8500_codec_cr107_bfifomast;
+
+/* CR107 - 0 */
+typedef enum {
+ AB8500_CODEC_CR107_BFIFORUN_STOPPED,
+ AB8500_CODEC_CR107_BFIFORUN_RUNNING
+} t_ab8500_codec_cr107_bfiforun;
+
+/* CR108 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr108_bfifoframsw;
+
+/* CR109 - 7:0 */
+typedef t_uint8 t_ab8500_codec_cr109_bfifowakeup;
+
+typedef enum {
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT1,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT2,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT3,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT4,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT5,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT6,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT7,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_OUT8,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_ZEROS,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_IS_TRISTATE = 15,
+ AB8500_CODEC_CR31_TO_CR46_SLOT_OUTPUTS_DATA_FROM_AD_UNDEFINED
+} t_ab8500_codec_cr31_to_cr46_ad_data_allocation;
+
+typedef enum {
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT00,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT01,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT02,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT03,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT04,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT05,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT06,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT07,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT08,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT09,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT10,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT11,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT12,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT13,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT14,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT15,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT16,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT17,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT18,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT19,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT20,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT21,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT22,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT23,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT24,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT25,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT26,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT27,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT28,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT29,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT30,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT31,
+ AB8500_CODEC_CR51_TO_CR58_SLTODA_SLOT_UNDEFINED
+} t_ab8500_codec_cr51_to_cr58_sltoda;
+
+/*configuration structure for AB8500 Codec*/
+typedef struct {
+ /* CR0 */
+ t_ab8500_codec_cr0_powerup cr0_powerup;
+ t_ab8500_codec_cr0_enaana cr0_enaana;
+
+ /* CR1 */
+ t_ab8500_codec_cr1_swreset cr1_swreset;
+
+ /* CR2 */
+ t_ab8500_codec_cr2_enad1 cr2_enad1;
+ t_ab8500_codec_cr2_enad2 cr2_enad2;
+ t_ab8500_codec_cr2_enad3 cr2_enad3;
+ t_ab8500_codec_cr2_enad4 cr2_enad4;
+ t_ab8500_codec_cr2_enad5 cr2_enad5;
+ t_ab8500_codec_cr2_enad6 cr2_enad6;
+
+ /* CR3 */
+ t_ab8500_codec_cr3_enda1 cr3_enda1;
+ t_ab8500_codec_cr3_enda2 cr3_enda2;
+ t_ab8500_codec_cr3_enda3 cr3_enda3;
+ t_ab8500_codec_cr3_enda4 cr3_enda4;
+ t_ab8500_codec_cr3_enda5 cr3_enda5;
+ t_ab8500_codec_cr3_enda6 cr3_enda6;
+
+ /* CR4 */
+ t_ab8500_codec_cr4_lowpowhs cr4_lowpowhs;
+ t_ab8500_codec_cr4_lowpowdachs cr4_lowpowdachs;
+ t_ab8500_codec_cr4_lowpowear cr4_lowpowear;
+ t_ab8500_codec_cr4_ear_sel_cm cr4_ear_sel_cm;
+ t_ab8500_codec_cr4_hs_hp_en cr4_hs_hp_en;
+
+ /* CR5 */
+ t_ab8500_codec_cr5_enmic1 cr5_enmic1;
+ t_ab8500_codec_cr5_enmic2 cr5_enmic2;
+ t_ab8500_codec_cr5_enlinl cr5_enlinl;
+ t_ab8500_codec_cr5_enlinr cr5_enlinr;
+ t_ab8500_codec_cr5_mutmic1 cr5_mutmic1;
+ t_ab8500_codec_cr5_mutmic2 cr5_mutmic2;
+ t_ab8500_codec_cr5_mutlinl cr5_mutlinl;
+ t_ab8500_codec_cr5_mutlinr cr5_mutlinr;
+
+ /* CR6 */
+ t_ab8500_codec_cr6_endmic1 cr6_endmic1;
+ t_ab8500_codec_cr6_endmic2 cr6_endmic2;
+ t_ab8500_codec_cr6_endmic3 cr6_endmic3;
+ t_ab8500_codec_cr6_endmic4 cr6_endmic4;
+ t_ab8500_codec_cr6_endmic5 cr6_endmic5;
+ t_ab8500_codec_cr6_endmic6 cr6_endmic6;
+
+ /* CR7 */
+ t_ab8500_codec_cr7_mic1sel cr7_mic1sel;
+ t_ab8500_codec_cr7_linrsel cr7_linrsel;
+ t_ab8500_codec_cr7_endrvhsl cr7_endrvhsl;
+ t_ab8500_codec_cr7_endrvhsr cr7_endrvhsr;
+ t_ab8500_codec_cr7_enadcmic cr7_enadcmic;
+ t_ab8500_codec_cr7_enadclinl cr7_enadclinl;
+ t_ab8500_codec_cr7_enadclinr cr7_enadclinr;
+
+ /* CR8 */
+ t_ab8500_codec_cr8_cp_dis_pldwn cr8_cp_dis_pldwn;
+ t_ab8500_codec_cr8_enear cr8_enear;
+ t_ab8500_codec_cr8_enhsl cr8_enhsl;
+ t_ab8500_codec_cr8_enhsr cr8_enhsr;
+ t_ab8500_codec_cr8_enhfl cr8_enhfl;
+ t_ab8500_codec_cr8_enhfr cr8_enhfr;
+ t_ab8500_codec_cr8_envibl cr8_envibl;
+ t_ab8500_codec_cr8_envibr cr8_envibr;
+
+ /* CR9 */
+ t_ab8500_codec_cr9_endacear cr9_endacear;
+ t_ab8500_codec_cr9_endachsl cr9_endachsl;
+ t_ab8500_codec_cr9_endachsr cr9_endachsr;
+ t_ab8500_codec_cr9_endachfl cr9_endachfl;
+ t_ab8500_codec_cr9_endachfr cr9_endachfr;
+ t_ab8500_codec_cr9_endacvibl cr9_endacvibl;
+ t_ab8500_codec_cr9_endacvibr cr9_endacvibr;
+
+ /* CR10 */
+ t_ab8500_codec_cr10_muteear cr10_muteear;
+ t_ab8500_codec_cr10_mutehsl cr10_mutehsl;
+ t_ab8500_codec_cr10_mutehsr cr10_mutehsr;
+
+ /* CR11 */
+ t_ab8500_codec_cr11_enshortpwd cr11_enshortpwd;
+ t_ab8500_codec_cr11_earshortdis cr11_earshortdis;
+ t_ab8500_codec_cr11_hsshortdis cr11_hsshortdis;
+ t_ab8500_codec_cr11_hspullden cr11_hspullden;
+ t_ab8500_codec_cr11_hsoscen cr11_hsoscen;
+ t_ab8500_codec_cr11_hsfaden cr11_hsfaden;
+ t_ab8500_codec_cr11_hszcddis cr11_hszcddis;
+
+ /* CR12 */
+ t_ab8500_codec_cr12_encphs cr12_encphs;
+ t_ab8500_codec_cr12_hsautoen cr12_hsautoen;
+
+ /* CR13 */
+ t_ab8500_codec_cr13_envdet_hthresh cr13_envdet_hthresh;
+ t_ab8500_codec_cr13_envdet_lthresh cr13_envdet_lthresh;
+
+ /* CR14 */
+ t_ab8500_codec_cr14_smpslven cr14_smpslven;
+ t_ab8500_codec_cr14_envdetsmpsen cr14_envdetsmpsen;
+ t_ab8500_codec_cr14_cplven cr14_cplven;
+ t_ab8500_codec_cr14_envdetcpen cr14_envdetcpen;
+ t_ab8500_codec_cr14_envet_time cr14_envet_time;
+
+ /* CR15 */
+ t_ab8500_codec_cr15_pwmtovibl cr15_pwmtovibl;
+ t_ab8500_codec_cr15_pwmtovibr cr15_pwmtovibr;
+ t_ab8500_codec_cr15_pwmlctrl cr15_pwmlctrl;
+ t_ab8500_codec_cr15_pwmrctrl cr15_pwmrctrl;
+ t_ab8500_codec_cr15_pwmnlctrl cr15_pwmnlctrl;
+ t_ab8500_codec_cr15_pwmplctrl cr15_pwmplctrl;
+ t_ab8500_codec_cr15_pwmnrctrl cr15_pwmnrctrl;
+ t_ab8500_codec_cr15_pwmprctrl cr15_pwmprctrl;
+
+ /* CR16 */
+ t_ab8500_codec_cr16_pwmnlpol cr16_pwmnlpol;
+ t_ab8500_codec_cr16_pwmnldutycycle cr16_pwmnldutycycle;
+
+ /* CR17 */
+ t_ab8500_codec_cr17_pwmplpol cr17_pwmplpol;
+ t_ab8500_codec_cr17_pwmpldutycycle cr17_pwmpldutycycle;
+
+ /* CR18 */
+ t_ab8500_codec_cr18_pwmnrpol cr18_pwmnrpol;
+ t_ab8500_codec_cr18_pwmnrdutycycle cr18_pwmnrdutycycle;
+
+ /* CR19 */
+ t_ab8500_codec_cr19_pwmprpol cr19_pwmprpol;
+ t_ab8500_codec_cr19_pwmprdutycycle cr19_pwmprdutycycle;
+
+ /* CR20 */
+ t_ab8500_codec_cr20_en_se_mic1 cr20_en_se_mic1;
+ t_ab8500_codec_cr20_low_pow_mic1 cr20_low_pow_mic1;
+ t_ab8500_codec_cr20_mic1_gain cr20_mic1_gain;
+
+ /* CR21 */
+ t_ab8500_codec_cr21_en_se_mic2 cr21_en_se_mic2;
+ t_ab8500_codec_cr21_low_pow_mic2 cr21_low_pow_mic2;
+ t_ab8500_codec_cr21_mic2_gain cr21_mic2_gain;
+
+ /* CR22 */
+ t_ab8500_codec_cr22_hsl_gain cr22_hsl_gain;
+ t_ab8500_codec_cr22_hsr_gain cr22_hsr_gain;
+
+ /* CR23 */
+ t_ab8500_codec_cr23_linl_gain cr23_linl_gain;
+ t_ab8500_codec_cr23_linr_gain cr23_linr_gain;
+
+ /* CR24 */
+ t_ab8500_codec_cr24_lintohsl_gain cr24_lintohsl_gain;
+
+ /* CR25 */
+ t_ab8500_codec_cr25_lintohsr_gain cr25_lintohsr_gain;
+
+ /* CR26 */
+ t_ab8500_codec_cr26_ad1nh cr26_ad1nh;
+ t_ab8500_codec_cr26_ad2nh cr26_ad2nh;
+ t_ab8500_codec_cr26_ad3nh cr26_ad3nh;
+ t_ab8500_codec_cr26_ad4nh cr26_ad4nh;
+ t_ab8500_codec_cr26_ad1_voice cr26_ad1_voice;
+ t_ab8500_codec_cr26_ad2_voice cr26_ad2_voice;
+ t_ab8500_codec_cr26_ad3_voice cr26_ad3_voice;
+ t_ab8500_codec_cr26_ad4_voice cr26_ad4_voice;
+
+ /* CR27 */
+ t_ab8500_codec_cr27_en_mastgen cr27_en_mastgen;
+ t_ab8500_codec_cr27_if1_bitclk_osr cr27_if1_bitclk_osr;
+ t_ab8500_codec_cr27_enfs_bitclk1 cr27_enfs_bitclk1;
+ t_ab8500_codec_cr27_if0_bitclk_osr cr27_if0_bitclk_osr;
+ t_ab8500_codec_cr27_enfs_bitclk0 cr27_enfs_bitclk0;
+
+ /* CR28 */
+ t_ab8500_codec_cr28_fsync0p cr28_fsync0p;
+ t_ab8500_codec_cr28_bitclk0p cr28_bitclk0p;
+ t_ab8500_codec_cr28_if0del cr28_if0del;
+ t_ab8500_codec_cr28_if0format cr28_if0format;
+ t_ab8500_codec_cr28_if0wl cr28_if0wl;
+
+ /* CR29 */
+ t_ab8500_codec_cr29_if0datoif1ad cr29_if0datoif1ad;
+ t_ab8500_codec_cr29_if0cktoif1ck cr29_if0cktoif1ck;
+ t_ab8500_codec_cr29_if1master cr29_if1master;
+ t_ab8500_codec_cr29_if1datoif0ad cr29_if1datoif0ad;
+ t_ab8500_codec_cr29_if1cktoif0ck cr29_if1cktoif0ck;
+ t_ab8500_codec_cr29_if0master cr29_if0master;
+ t_ab8500_codec_cr29_if0bfifoen cr29_if0bfifoen;
+
+ /* CR30 */
+ t_ab8500_codec_cr30_fsync1p cr30_fsync1p;
+ t_ab8500_codec_cr30_bitclk1p cr30_bitclk1p;
+ t_ab8500_codec_cr30_if1del cr30_if1del;
+ t_ab8500_codec_cr30_if1format cr30_if1format;
+ t_ab8500_codec_cr30_if1wl cr30_if1wl;
+
+ /* CR31 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr31_adotoslot1;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr31_adotoslot0;
+
+ /* CR32 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr32_adotoslot3;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr32_adotoslot2;
+
+ /* CR33 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr33_adotoslot5;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr33_adotoslot4;
+
+ /* CR34 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr34_adotoslot7;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr34_adotoslot6;
+
+ /* CR35 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr35_adotoslot9;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr35_adotoslot8;
+
+ /* CR36 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr36_adotoslot11;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr36_adotoslot10;
+
+ /* CR37 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr37_adotoslot13;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr37_adotoslot12;
+
+ /* CR38 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr38_adotoslot15;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr38_adotoslot14;
+
+ /* CR39 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr39_adotoslot17;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr39_adotoslot16;
+
+ /* CR40 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr40_adotoslot19;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr40_adotoslot18;
+
+ /* CR41 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr41_adotoslot21;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr41_adotoslot20;
+
+ /* CR42 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr42_adotoslot23;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr42_adotoslot22;
+
+ /* CR43 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr43_adotoslot25;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr43_adotoslot24;
+
+ /* CR44 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr44_adotoslot27;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr44_adotoslot26;
+
+ /* CR45 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr45_adotoslot29;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr45_adotoslot28;
+
+ /* CR46 */
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr46_adotoslot31;
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation cr46_adotoslot30;
+
+ /* CR47 */
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl7;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl6;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl5;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl4;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl3;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl2;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl1;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr47_hiz_sl0;
+
+ /* CR48 */
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl15;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl14;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl13;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl12;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl11;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl10;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl9;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr48_hiz_sl8;
+
+ /* CR49 */
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl23;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl22;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl21;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl20;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl19;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl18;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl17;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr49_hiz_sl16;
+
+ /* CR50 */
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl31;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl30;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl29;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl28;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl27;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl26;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl25;
+ t_ab8500_codec_cr47_to_cr50_hiz_sl cr50_hiz_sl24;
+
+ /* CR51 */
+ t_ab8500_codec_cr51_da12_voice cr51_da12_voice;
+ t_ab8500_codec_cr51_swapda12_34 cr51_swapda12_34;
+ t_ab8500_codec_cr51_sldai7toslado1 cr51_sldai7toslado1;
+ t_ab8500_codec_cr51_to_cr58_sltoda cr51_sltoda1;
+
+ /* CR52 */
+ t_ab8500_codec_cr52_sldai8toslado2 cr52_sldai8toslado2;
+ t_ab8500_codec_cr51_to_cr58_sltoda cr52_sltoda2;
+
+ /* CR53 */
+ t_ab8500_codec_cr53_da34_voice cr53_da34_voice;
+ t_ab8500_codec_cr53_sldai7toslado3 cr53_sldai7toslado3;
+ t_ab8500_codec_cr51_to_cr58_sltoda cr53_sltoda3;
+
+ /* CR54 */
+ t_ab8500_codec_cr54_sldai8toslado4 cr54_sldai8toslado4;
+ t_ab8500_codec_cr51_to_cr58_sltoda cr54_sltoda4;
+
+ /* CR55 */
+ t_ab8500_codec_cr55_da56_voice cr55_da56_voice;
+ t_ab8500_codec_cr55_sldai7toslado5 cr55_sldai7toslado5;
+ t_ab8500_codec_cr51_to_cr58_sltoda cr55_sltoda5;
+
+ /* CR56 */
+ t_ab8500_codec_cr56_sldai8toslado6 cr56_sldai8toslado6;
+ t_ab8500_codec_cr51_to_cr58_sltoda cr56_sltoda6;
+
+ /* CR57 */
+ t_ab8500_codec_cr57_sldai8toslado7 cr57_sldai8toslado7;
+ t_ab8500_codec_cr51_to_cr58_sltoda cr57_sltoda7;
+
+ /* CR58 */
+ t_ab8500_codec_cr58_sldai7toslado8 cr58_sldai7toslado8;
+ t_ab8500_codec_cr51_to_cr58_sltoda cr58_sltoda8;
+
+ /* CR59 */
+ t_ab8500_codec_cr59_parlhf cr59_parlhf;
+ t_ab8500_codec_cr59_parlvib cr59_parlvib;
+ t_ab8500_codec_cr59_classdvib1_swapen cr59_classdvib1_swapen;
+ t_ab8500_codec_cr59_classdvib2_swapen cr59_classdvib2_swapen;
+ t_ab8500_codec_cr59_classdhfl_swapen cr59_classdhfl_swapen;
+ t_ab8500_codec_cr59_classdhfr_swapen cr59_classdhfr_swapen;
+
+ /* CR60 */
+ t_ab8500_codec_cr60_classd_firbyp cr60_classd_firbyp;
+ t_ab8500_codec_cr60_classd_highvolen cr60_classd_highvolen;
+
+ /* CR61 */
+ t_ab8500_codec_cr61_classddith_hpgain cr61_classddith_hpgain;
+ t_ab8500_codec_cr61_classddith_wgain cr61_classddith_wgain;
+
+ /* CR62 */
+ t_ab8500_codec_cr62_dmic1sinc3 cr62_dmic1sinc3;
+ t_ab8500_codec_cr62_dmic2sinc3 cr62_dmic2sinc3;
+ t_ab8500_codec_cr62_dmic3sinc3 cr62_dmic3sinc3;
+ t_ab8500_codec_cr62_dmic4sinc3 cr62_dmic4sinc3;
+ t_ab8500_codec_cr62_dmic5sinc3 cr62_dmic5sinc3;
+ t_ab8500_codec_cr62_dmic6sinc3 cr62_dmic6sinc3;
+
+ /* CR63 */
+ t_ab8500_codec_cr63_datohslen cr63_datohslen;
+ t_ab8500_codec_cr63_datohsren cr63_datohsren;
+ t_ab8500_codec_cr63_ad1sel cr63_ad1sel;
+ t_ab8500_codec_cr63_ad2sel cr63_ad2sel;
+ t_ab8500_codec_cr63_ad3sel cr63_ad3sel;
+ t_ab8500_codec_cr63_ad5sel cr63_ad5sel;
+ t_ab8500_codec_cr63_ad6sel cr63_ad6sel;
+ t_ab8500_codec_cr63_ancsel cr63_ancsel;
+
+ /* CR64 */
+ t_ab8500_codec_cr64_datohfren cr64_datohfren;
+ t_ab8500_codec_cr64_datohflen cr64_datohflen;
+ t_ab8500_codec_cr64_hfrsel cr64_hfrsel;
+ t_ab8500_codec_cr64_hflsel cr64_hflsel;
+ t_ab8500_codec_cr64_stfir1sel cr64_stfir1sel;
+ t_ab8500_codec_cr64_stfir2sel cr64_stfir2sel;
+
+ /* CR65 */
+ t_ab8500_codec_cr65_fadedis_ad1 cr65_fadedis_ad1;
+ t_ab8500_codec_cr65_ad1gain cr65_ad1gain;
+
+ /* CR66 */
+ t_ab8500_codec_cr66_fadedis_ad2 cr66_fadedis_ad2;
+ t_ab8500_codec_cr66_ad2gain cr66_ad2gain;
+
+ /* CR67 */
+ t_ab8500_codec_cr67_fadedis_ad3 cr67_fadedis_ad3;
+ t_ab8500_codec_cr67_ad3gain cr67_ad3gain;
+
+ /* CR68 */
+ t_ab8500_codec_cr68_fadedis_ad4 cr68_fadedis_ad4;
+ t_ab8500_codec_cr68_ad4gain cr68_ad4gain;
+
+ /* CR69 */
+ t_ab8500_codec_cr69_fadedis_ad5 cr69_fadedis_ad5;
+ t_ab8500_codec_cr69_ad5gain cr69_ad5gain;
+
+ /* CR70 */
+ t_ab8500_codec_cr70_fadedis_ad6 cr70_fadedis_ad6;
+ t_ab8500_codec_cr70_ad6gain cr70_ad6gain;
+
+ /* CR71 */
+ t_ab8500_codec_cr71_fadedis_da1 cr71_fadedis_da1;
+ t_ab8500_codec_cr71_da1gain cr71_da1gain;
+
+ /* CR72 */
+ t_ab8500_codec_cr72_fadedis_da2 cr72_fadedis_da2;
+ t_ab8500_codec_cr72_da2gain cr72_da2gain;
+
+ /* CR73 */
+ t_ab8500_codec_cr73_fadedis_da3 cr73_fadedis_da3;
+ t_ab8500_codec_cr73_da3gain cr73_da3gain;
+
+ /* CR74 */
+ t_ab8500_codec_cr74_fadedis_da4 cr74_fadedis_da4;
+ t_ab8500_codec_cr74_da4gain cr74_da4gain;
+
+ /* CR75 */
+ t_ab8500_codec_cr75_fadedis_da5 cr75_fadedis_da5;
+ t_ab8500_codec_cr75_da5gain cr75_da5gain;
+
+ /* CR76 */
+ t_ab8500_codec_cr76_fadedis_da6 cr76_fadedis_da6;
+ t_ab8500_codec_cr76_da6gain cr76_da6gain;
+
+ /* CR77 */
+ t_ab8500_codec_cr77_fadedis_ad1l cr77_fadedis_ad1l;
+ t_ab8500_codec_cr77_ad1lbgain_to_hfl cr77_ad1lbgain_to_hfl;
+
+ /* CR78 */
+ t_ab8500_codec_cr78_fadedis_ad2l cr78_fadedis_ad2l;
+ t_ab8500_codec_cr78_ad2lbgain_to_hfr cr78_ad2lbgain_to_hfr;
+
+ /* CR79 */
+ t_ab8500_codec_cr79_hssinc1 cr79_hssinc1;
+ t_ab8500_codec_cr79_fadedis_hsl cr79_fadedis_hsl;
+ t_ab8500_codec_cr79_hsldgain cr79_hsldgain;
+
+ /* CR80 */
+ t_ab8500_codec_cr80_fade_speed cr80_fade_speed;
+ t_ab8500_codec_cr80_fadedis_hsr cr80_fadedis_hsr;
+ t_ab8500_codec_cr80_hsrdgain cr80_hsrdgain;
+
+ /* CR81 */
+ t_ab8500_codec_cr81_stfir1gain cr81_stfir1gain;
+
+ /* CR82 */
+ t_ab8500_codec_cr82_stfir2gain cr82_stfir2gain;
+
+ /* CR83 */
+ t_ab8500_codec_cr83_enanc cr83_enanc;
+ t_ab8500_codec_cr83_anciirinit cr83_anciirinit;
+ t_ab8500_codec_cr83_ancfirupdate cr83_ancfirupdate;
+
+ /* CR84 */
+ t_ab8500_codec_cr84_ancinshift cr84_ancinshift;
+
+ /* CR85 */
+ t_ab8500_codec_cr85_ancfiroutshift cr85_ancfiroutshift;
+
+ /* CR86 */
+ t_ab8500_codec_cr86_ancshiftout cr86_ancshiftout;
+
+ /* CR87 */
+ t_ab8500_codec_cr87_ancfircoeff_msb cr87_ancfircoeff_msb;
+
+ /* CR88 */
+ t_ab8500_codec_cr88_ancfircoeff_lsb cr88_ancfircoeff_lsb;
+
+ /* CR89 */
+ t_ab8500_codec_cr89_anciircoeff_msb cr89_anciircoeff_msb;
+
+ /* CR90 */
+ t_ab8500_codec_cr90_anciircoeff_lsb cr90_anciircoeff_lsb;
+
+ /* CR91 */
+ t_ab8500_codec_cr91_ancwarpdel_msb cr91_ancwarpdel_msb;
+
+ /* CR92 */
+ t_ab8500_codec_cr92_ancwarpdel_lsb cr92_ancwarpdel_lsb;
+
+ /* CR93 */
+ t_ab8500_codec_cr93_ancfirpeak_msb cr93_ancfirpeak_msb;
+
+ /* CR94 */
+ t_ab8500_codec_cr94_ancfirpeak_lsb cr94_ancfirpeak_lsb;
+
+ /* CR95 */
+ t_ab8500_codec_cr95_anciirpeak_msb cr95_anciirpeak_msb;
+
+ /* CR96 */
+ t_ab8500_codec_cr96_anciirpeak_lsb cr96_anciirpeak_lsb;
+
+ /* CR97 */
+ t_ab8500_codec_cr97_stfir_set cr97_stfir_set;
+ t_ab8500_codec_cr97_stfir_addr cr97_stfir_addr;
+
+ /* CR98 */
+ t_ab8500_codec_cr98_stfir_coeff_msb cr98_stfir_coeff_msb;
+
+ /* CR99 */
+ t_ab8500_codec_cr99_stfir_coeff_lsb cr99_stfir_coeff_lsb;
+
+ /* CR100 */
+ t_ab8500_codec_cr100_enstfirs cr100_enstfirs;
+ t_ab8500_codec_cr100_stfirstoif1 cr100_stfirstoif1;
+ t_ab8500_codec_cr100_stfir_busy cr100_stfir_busy;
+
+ /* CR101 */
+ t_ab8500_codec_cr101_hsoffst_mask cr101_hsoffst_mask;
+ t_ab8500_codec_cr101_fifofull_mask cr101_fifofull_mask;
+ t_ab8500_codec_cr101_fifoempty_mask cr101_fifoempty_mask;
+ t_ab8500_codec_cr101_dasat_mask cr101_dasat_mask;
+ t_ab8500_codec_cr101_adsat_mask cr101_adsat_mask;
+ t_ab8500_codec_cr101_addsp_mask cr101_addsp_mask;
+ t_ab8500_codec_cr101_dadsp_mask cr101_dadsp_mask;
+ t_ab8500_codec_cr101_firsid_mask cr101_firsid_mask;
+
+ /* CR102 */
+ t_ab8500_codec_cr102_it_hsoffst cr102_it_hsoffst;
+ t_ab8500_codec_cr102_it_fifofull cr102_it_fifofull;
+ t_ab8500_codec_cr102_it_fifoempty cr102_it_fifoempty;
+ t_ab8500_codec_cr102_it_dasat cr102_it_dasat;
+ t_ab8500_codec_cr102_it_adsat cr102_it_adsat;
+ t_ab8500_codec_cr102_it_addsp cr102_it_addsp;
+ t_ab8500_codec_cr102_it_dadsp cr102_it_dadsp;
+ t_ab8500_codec_cr102_it_firsid cr102_it_firsid;
+
+ /* CR103 */
+ t_ab8500_codec_cr103_vssready_mask cr103_vssready_mask;
+ t_ab8500_codec_cr103_shorthsl_mask cr103_shorthsl_mask;
+ t_ab8500_codec_cr103_shorthsr_mask cr103_shorthsr_mask;
+ t_ab8500_codec_cr103_shortear_mask cr103_shortear_mask;
+
+ /* CR104 */
+ t_ab8500_codec_cr104_it_vssready cr104_it_vssready;
+ t_ab8500_codec_cr104_it_shorthsl cr104_it_shorthsl;
+ t_ab8500_codec_cr104_it_shorthsr cr104_it_shorthsr;
+ t_ab8500_codec_cr104_it_shortear cr104_it_shortear;
+
+ /* CR105 */
+ t_ab8500_codec_cr105_bfifomsk cr105_bfifomsk;
+ t_ab8500_codec_cr105_bfifoint cr105_bfifoint;
+
+ /* CR106 */
+ t_ab8500_codec_cr106_bfifotx cr106_bfifotx;
+
+ /* CR107 */
+ t_ab8500_codec_cr107_bfifoexsl cr107_bfifoexsl;
+ t_ab8500_codec_cr107_prebitclk0 cr107_prebitclk0;
+ t_ab8500_codec_cr107_bfifomast cr107_bfifomast;
+ t_ab8500_codec_cr107_bfiforun cr107_bfiforun;
+
+ /* CR108 */
+ t_ab8500_codec_cr108_bfifoframsw cr108_bfifoframsw;
+
+ /* CR109 */
+ t_ab8500_codec_cr109_bfifowakeup cr109_bfifowakeup;
+
+ /* CR110 */
+ t_ab8500_codec_cr110_bfifosamples cr110_bfifosamples;
+
+ /* CR111 */
+ t_ab8500_codec_cr111_aud_ip_rev cr111_aud_ip_rev;
+
+} t_ab8500_codec_configuration;
+
+typedef enum {
+ AB8500_CODEC_DIRECTION_IN,
+ AB8500_CODEC_DIRECTION_OUT,
+ AB8500_CODEC_DIRECTION_INOUT
+} t_ab8500_codec_direction;
+
+typedef enum {
+ AB8500_CODEC_AUDIO_INTERFACE_0,
+ AB8500_CODEC_AUDIO_INTERFACE_1
+} t_ab8500_codec_audio_interface;
+
+typedef enum {
+ AB8500_CODEC_MODE_HIFI,
+ AB8500_CODEC_MODE_VOICE,
+ AB8500_CODEC_MODE_MANUAL_SETTING
+} t_ab8500_codec_mode;
+
+typedef enum {
+ AB8500_CODEC_DEST_HEADSET,
+ AB8500_CODEC_DEST_EARPIECE,
+ AB8500_CODEC_DEST_HANDSFREE,
+ AB8500_CODEC_DEST_VIBRATOR_L,
+ AB8500_CODEC_DEST_VIBRATOR_R,
+ AB8500_CODEC_DEST_FM_TX,
+ AB8500_CODEC_DEST_ALL
+} t_ab8500_codec_dest;
+
+typedef enum {
+ AB8500_CODEC_SRC_LINEIN,
+ AB8500_CODEC_SRC_MICROPHONE_1A,
+ AB8500_CODEC_SRC_MICROPHONE_1B,
+ AB8500_CODEC_SRC_MICROPHONE_2,
+ AB8500_CODEC_SRC_D_MICROPHONE_1,
+ AB8500_CODEC_SRC_D_MICROPHONE_2,
+ AB8500_CODEC_SRC_D_MICROPHONE_3,
+ AB8500_CODEC_SRC_D_MICROPHONE_4,
+ AB8500_CODEC_SRC_D_MICROPHONE_5,
+ AB8500_CODEC_SRC_D_MICROPHONE_6,
+ AB8500_CODEC_SRC_D_MICROPHONE_12,
+ AB8500_CODEC_SRC_D_MICROPHONE_34,
+ AB8500_CODEC_SRC_D_MICROPHONE_56,
+ AB8500_CODEC_SRC_FM_RX,
+ AB8500_CODEC_SRC_ALL
+} t_ab8500_codec_src;
+
+typedef struct {
+ t_uint8 slave_address_of_ab8500_codec;
+ t_ab8500_codec_direction ab8500_codec_direction;
+ t_ab8500_codec_mode ab8500_codec_mode_in;
+ t_ab8500_codec_mode ab8500_codec_mode_out;
+ t_ab8500_codec_audio_interface audio_interface;
+ t_ab8500_codec_src ab8500_codec_src;
+ t_ab8500_codec_dest ab8500_codec_dest;
+ t_uint8 in_left_volume;
+ t_uint8 in_right_volume;
+ t_uint8 out_left_volume;
+ t_uint8 out_right_volume;
+
+ t_ab8500_codec_configuration ab8500_codec_configuration;
+} t_ab8500_codec_system_context;
+
+#endif /* _AB8500_CODECP_H_ */
+
+/* End of file AB8500_CODECP.h */
diff --git a/arch/arm/mach-ux500/include/mach/ab8500_codec_v1_0.h b/arch/arm/mach-ux500/include/mach/ab8500_codec_v1_0.h
new file mode 100644
index 00000000000..a5b8a57f341
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ab8500_codec_v1_0.h
@@ -0,0 +1,329 @@
+/*****************************************************************************/
+/**
+* © ST-Ericsson, 2009 - All rights reserved
+* Reproduction and Communication of this document is strictly prohibited
+* unless specifically authorized in writing by ST-Ericsson
+*
+* \brief Public header file for AB8500 Codec
+* \author ST-Ericsson
+*/
+/*****************************************************************************/
+
+#ifndef _AB8500_CODEC_V1_0_H_
+#define _AB8500_CODEC_V1_0_H_
+
+/*---------------------------------------------------------------------
+ * Includes
+ *--------------------------------------------------------------------*/
+#include "hcl_defs.h"
+#include "debug.h"
+#include <mach/ab8500_codec_p_v1_0.h>
+/*---------------------------------------------------------------------
+ * Define
+ *--------------------------------------------------------------------*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+ typedef enum {
+ AB8500_CODEC_OK,
+ AB8500_CODEC_ERROR,
+ AB8500_CODEC_UNSUPPORTED_FEATURE,
+ AB8500_CODEC_INVALID_PARAMETER,
+ AB8500_CODEC_CONFIG_NOT_COHERENT,
+ AB8500_CODEC_TRANSACTION_FAILED
+ } t_ab8500_codec_error;
+
+ typedef enum {
+ AB8500_CODEC_SRC_STATE_DISABLE,
+ AB8500_CODEC_SRC_STATE_ENABLE
+ } t_ab8500_codec_src_state;
+
+ typedef enum {
+ AB8500_CODEC_DEST_STATE_DISABLE,
+ AB8500_CODEC_DEST_STATE_ENABLE
+ } t_ab8500_codec_dest_state;
+
+ typedef enum {
+ AB8500_CODEC_MASTER_MODE_DISABLE,
+ AB8500_CODEC_MASTER_MODE_ENABLE
+ } t_ab8500_codec_master_mode;
+
+ typedef enum {
+ AB8500_CODEC_SLOT0,
+ AB8500_CODEC_SLOT1,
+ AB8500_CODEC_SLOT2,
+ AB8500_CODEC_SLOT3,
+ AB8500_CODEC_SLOT4,
+ AB8500_CODEC_SLOT5,
+ AB8500_CODEC_SLOT6,
+ AB8500_CODEC_SLOT7,
+ AB8500_CODEC_SLOT8,
+ AB8500_CODEC_SLOT9,
+ AB8500_CODEC_SLOT10,
+ AB8500_CODEC_SLOT11,
+ AB8500_CODEC_SLOT12,
+ AB8500_CODEC_SLOT13,
+ AB8500_CODEC_SLOT14,
+ AB8500_CODEC_SLOT15,
+ AB8500_CODEC_SLOT16,
+ AB8500_CODEC_SLOT17,
+ AB8500_CODEC_SLOT18,
+ AB8500_CODEC_SLOT19,
+ AB8500_CODEC_SLOT20,
+ AB8500_CODEC_SLOT21,
+ AB8500_CODEC_SLOT22,
+ AB8500_CODEC_SLOT23,
+ AB8500_CODEC_SLOT24,
+ AB8500_CODEC_SLOT25,
+ AB8500_CODEC_SLOT26,
+ AB8500_CODEC_SLOT27,
+ AB8500_CODEC_SLOT28,
+ AB8500_CODEC_SLOT29,
+ AB8500_CODEC_SLOT30,
+ AB8500_CODEC_SLOT31,
+ AB8500_CODEC_SLOT_UNDEFINED
+ } t_ab8500_codec_slot;
+
+ typedef enum {
+ AB8500_CODEC_DA_CHANNEL_NUMBER_1,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_2,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_3,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_4,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_5,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_6,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_7,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_8,
+ AB8500_CODEC_DA_CHANNEL_NUMBER_UNDEFINED
+ } t_ab8500_codec_da_channel_number;
+
+ typedef struct {
+ t_ab8500_codec_cr105_bfifomsk cr105_bfifomsk;
+ t_ab8500_codec_cr105_bfifoint cr105_bfifoint;
+ t_ab8500_codec_cr106_bfifotx cr106_bfifotx;
+ t_ab8500_codec_cr107_bfifoexsl cr107_bfifoexsl;
+ t_ab8500_codec_cr107_prebitclk0 cr107_prebitclk0;
+ t_ab8500_codec_cr107_bfifomast cr107_bfifomast;
+ t_ab8500_codec_cr107_bfiforun cr107_bfiforun;
+ t_ab8500_codec_cr108_bfifoframsw cr108_bfifoframsw;
+ t_ab8500_codec_cr109_bfifowakeup cr109_bfifowakeup;
+ } t_ab8500_codec_burst_fifo_config;
+
+ typedef struct {
+ t_ab8500_codec_cr27_if1_bitclk_osr cr27_if1_bitclk_osr;
+ t_ab8500_codec_cr27_if0_bitclk_osr cr27_if0_bitclk_osr;
+ t_ab8500_codec_cr28_if0wl cr28_if0wl;
+ t_ab8500_codec_cr30_if1wl cr30_if1wl;
+ t_ab8500_codec_cr28_bitclk0p cr28_bitclk0p;
+ t_ab8500_codec_cr28_if0del cr28_if0del;
+ } t_ab8500_codec_tdm_config;
+
+/************************************************************/
+/*---------------------------------------------------------------------
+ * Exported APIs
+ *--------------------------------------------------------------------*/
+/* Initialization */
+ t_ab8500_codec_error AB8500_CODEC_Init(IN t_uint8
+ slave_address_of_codec);
+ t_ab8500_codec_error AB8500_CODEC_Reset(void);
+
+/* Audio Codec basic configuration */
+ t_ab8500_codec_error AB8500_CODEC_SetModeAndDirection(IN
+ t_ab8500_codec_direction
+ ab8500_codec_direction,
+ IN
+ t_ab8500_codec_mode
+ ab8500_codec_mode_in,
+ IN
+ t_ab8500_codec_mode
+ ab8500_codec_mode_out,
+ IN
+ t_ab8500_codec_tdm_config
+ const *const
+ p_tdm_config);
+ t_ab8500_codec_error AB8500_CODEC_SelectInput(IN t_ab8500_codec_src
+ ab8500_codec_src);
+ t_ab8500_codec_error AB8500_CODEC_SelectOutput(IN t_ab8500_codec_dest
+ ab8500_codec_dest);
+
+/* Burst FIFO configuration */
+ t_ab8500_codec_error AB8500_CODEC_ConfigureBurstFifo(IN
+ t_ab8500_codec_burst_fifo_config
+ const *const
+ p_burst_fifo_config);
+ t_ab8500_codec_error AB8500_CODEC_EnableBurstFifo(void);
+ t_ab8500_codec_error AB8500_CODEC_DisableBurstFifo(void);
+
+/* Audio Codec Master mode configuration */
+ t_ab8500_codec_error AB8500_CODEC_SetMasterMode(IN
+ t_ab8500_codec_master_mode
+ mode);
+
+/* APIs to be implemented by user */
+ t_ab8500_codec_error AB8500_CODEC_Write(IN t_uint8 register_offset,
+ IN t_uint8 count,
+ IN t_uint8 * p_data);
+ t_ab8500_codec_error AB8500_CODEC_Read(IN t_uint8 register_offset,
+ IN t_uint8 count,
+ IN t_uint8 * p_dummy_data,
+ IN t_uint8 * p_data);
+
+/* Volume Management */
+ t_ab8500_codec_error AB8500_CODEC_SetSrcVolume(IN t_ab8500_codec_src
+ src_device,
+ IN t_uint8
+ in_left_volume,
+ IN t_uint8
+ in_right_volume);
+ t_ab8500_codec_error AB8500_CODEC_SetDestVolume(IN t_ab8500_codec_dest
+ dest_device,
+ IN t_uint8
+ out_left_volume,
+ IN t_uint8
+ out_right_volume);
+
+/* Power management */
+ t_ab8500_codec_error AB8500_CODEC_PowerDown(void);
+ t_ab8500_codec_error AB8500_CODEC_PowerUp(void);
+
+/* Interface Management */
+ t_ab8500_codec_error AB8500_CODEC_SelectInterface(IN
+ t_ab8500_codec_audio_interface
+ audio_interface);
+ t_ab8500_codec_error AB8500_CODEC_GetInterface(OUT
+ t_ab8500_codec_audio_interface
+ * p_audio_interface);
+
+/* Slot Allocation */
+ t_ab8500_codec_error AB8500_CODEC_ADSlotAllocation(IN
+ t_ab8500_codec_slot
+ ad_slot,
+ IN
+ t_ab8500_codec_cr31_to_cr46_ad_data_allocation
+ value);
+ t_ab8500_codec_error AB8500_CODEC_DASlotAllocation(IN
+ t_ab8500_codec_da_channel_number
+ channel_number,
+ IN
+ t_ab8500_codec_cr51_to_cr58_sltoda
+ slot);
+
+/* Loopback Management */
+ t_ab8500_codec_error AB8500_CODEC_SetAnalogLoopback(IN t_uint8
+ out_left_volume,
+ IN t_uint8
+ out_right_volume);
+ t_ab8500_codec_error AB8500_CODEC_RemoveAnalogLoopback(void);
+
+/* Bypass Management */
+ t_ab8500_codec_error AB8500_CODEC_EnableBypassMode(void);
+ t_ab8500_codec_error AB8500_CODEC_DisableBypassMode(void);
+
+/* Power Control Management */
+ t_ab8500_codec_error AB8500_CODEC_SrcPowerControl(IN t_ab8500_codec_src
+ src_device,
+ t_ab8500_codec_src_state
+ state);
+ t_ab8500_codec_error AB8500_CODEC_DestPowerControl(IN
+ t_ab8500_codec_dest
+ dest_device,
+ t_ab8500_codec_dest_state
+ state);
+
+/* Version Management */
+ t_ab8500_codec_error AB8500_CODEC_GetVersion(OUT t_version * p_version);
+
+#if 0
+/* Debug management */
+ t_ab8500_codec_error AB8500_CODEC_SetDbgLevel(IN t_dbg_level dbg_level);
+ t_ab8500_codec_error AB8500_CODEC_GetDbgLevel(OUT t_dbg_level *
+ p_dbg_level);
+#endif
+
+/*
+** following is added by $kardad$
+*/
+
+/* duplicate copy of enum from msp.h */
+/* for MSPConfiguration.in_clock_freq parameter to select msp clock freq */
+ typedef enum {
+ CODEC_MSP_INPUT_FREQ_1MHZ = 1024,
+ CODEC_MSP_INPUT_FREQ_2MHZ = 2048,
+ CODEC_MSP_INPUT_FREQ_3MHZ = 3072,
+ CODEC_MSP_INPUT_FREQ_4MHZ = 4096,
+ CODEC_MSP_INPUT_FREQ_5MHZ = 5760,
+ CODEC_MSP_INPUT_FREQ_6MHZ = 6144,
+ CODEC_MSP_INPUT_FREQ_8MHZ = 8192,
+ CODEC_MSP_INPUT_FREQ_11MHZ = 11264,
+ CODEC_MSP_INPUT_FREQ_12MHZ = 12288,
+ CODEC_MSP_INPUT_FREQ_16MHZ = 16384,
+ CODEC_MSP_INPUT_FREQ_22MHZ = 22579,
+ CODEC_MSP_INPUT_FREQ_24MHZ = 24576,
+ CODEC_MSP_INPUT_FREQ_48MHZ = 49152
+ } codec_msp_in_clock_freq_type;
+
+/* msp clock source internal/external for srg_clock_sel */
+ typedef enum {
+ CODEC_MSP_APB_CLOCK = 0,
+ CODEC_MSP_SCK_CLOCK = 2,
+ CODEC_MSP_SCK_SYNC_CLOCK = 3
+ } codec_msp_srg_clock_sel_type;
+
+/* Sample rate supported by Codec */
+
+ typedef enum {
+ CODEC_FREQUENCY_DONT_CHANGE = -100,
+ CODEC_SAMPLING_FREQ_RESET = -1,
+ CODEC_SAMPLING_FREQ_MINLIMIT = 7,
+ CODEC_SAMPLING_FREQ_8KHZ = 8, /*default */
+ CODEC_SAMPLING_FREQ_11KHZ = 11,
+ CODEC_SAMPLING_FREQ_12KHZ = 12,
+ CODEC_SAMPLING_FREQ_16KHZ = 16,
+ CODEC_SAMPLING_FREQ_22KHZ = 22,
+ CODEC_SAMPLING_FREQ_24KHZ = 24,
+ CODEC_SAMPLING_FREQ_32KHZ = 32,
+ CODEC_SAMPLING_FREQ_44KHZ = 44,
+ CODEC_SAMPLING_FREQ_48KHZ = 48,
+ CODEC_SAMPLING_FREQ_64KHZ = 64, /*the frequencies below this line are not supported in stw5094A */
+ CODEC_SAMPLING_FREQ_88KHZ = 88,
+ CODEC_SAMPLING_FREQ_96KHZ = 96,
+ CODEC_SAMPLING_FREQ_128KHZ = 128,
+ CODEC_SAMPLING_FREQ_176KHZ = 176,
+ CODEC_SAMPLING_FREQ_192KHZ = 192,
+ CODEC_SAMPLING_FREQ_MAXLIMIT = 193
+ } t_codec_sample_frequency;
+
+#define RESET -1
+#define DEFAULT -100
+/***********************************************************/
+/*
+** following stuff is added to compile code without debug print support $kardad$
+*/
+
+#define DBGEXIT(cr)
+#define DBGEXIT0(cr)
+#define DBGEXIT1(cr,ch,p1)
+#define DBGEXIT2(cr,ch,p1,p2)
+#define DBGEXIT3(cr,ch,p1,p2,p3)
+#define DBGEXIT4(cr,ch,p1,p2,p3,p4)
+#define DBGEXIT5(cr,ch,p1,p2,p3,p4,p5)
+#define DBGEXIT6(cr,ch,p1,p2,p3,p4,p5,p6)
+
+#define DBGENTER()
+#define DBGENTER0()
+#define DBGENTER1(ch,p1)
+#define DBGENTER2(ch,p1,p2)
+#define DBGENTER3(ch,p1,p2,p3)
+#define DBGENTER4(ch,p1,p2,p3,p4)
+#define DBGENTER5(ch,p1,p2,p3,p4,p5)
+#define DBGENTER6(ch,p1,p2,p3,p4,p5,p6)
+
+#define DBGPRINT(dbg_level,dbg_string)
+#define DBGPRINTHEX(dbg_level,dbg_string,uint32)
+#define DBGPRINTDEC(dbg_level,dbg_string,uint32)
+/***********************************************************/
+
+#ifdef __cplusplus
+} /* allow C++ to use these headers */
+#endif /* __cplusplus */
+#endif /* _AB8500_CODEC_H_ */
+/* End of file ab8500_codec.h*/
diff --git a/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h b/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h
new file mode 100644
index 00000000000..4289dcfc0aa
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ab8500_gpadc.h
@@ -0,0 +1,36 @@
+/*
+ * ab8500_gpadc.c - AB8500 GPADC Driver
+ *
+ * Copyright (C) 2010 ST-Ericsson SA
+ * Licensed under GPLv2.
+ *
+ * Author: Arun R Murthy <arun.murthy@stericsson.com>
+ */
+
+#ifndef _AB8500_GPADC_H
+#define _Ab8500_GPADC_H
+
+/* GPADC source: From datasheer(ADCSwSel[4:0] in GPADCCtrl2) */
+#define BAT_CTRL 0x01
+#define ACC_DETECT1 0x04
+#define ACC_DETECT2 0x05
+#define MAIN_BAT_V 0x08
+#define BK_BAT_V 0x0C
+#define VBUS_V 0x09
+#define MAIN_CHARGER_V 0x03
+#define MAIN_CHARGER_C 0x0A
+#define USB_CHARGER_C 0x0B
+#define DIE_TEMP 0x0D
+#define BTEMP_BALL 0x02
+
+struct ab8500_gpadc_device_info {
+ struct completion ab8500_gpadc_complete;
+ struct mutex ab8500_gpadc_lock;
+#if defined(CONFIG_REGULATOR)
+ struct regulator *regu;
+#endif
+};
+
+int ab8500_gpadc_conversion(int input);
+
+#endif /* _AB8500_GPADC_H */
diff --git a/arch/arm/mach-ux500/include/mach/crypto-ux500.h b/arch/arm/mach-ux500/include/mach/crypto-ux500.h
new file mode 100644
index 00000000000..57da88398d5
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/crypto-ux500.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef _CRYPTO_UX500_H
+#include <plat/ste_dma40.h>
+#include <mach/ste-dma40-db8500.h>
+
+struct cryp_platform_data {
+ struct stedma40_chan_cfg mem_to_engine;
+ struct stedma40_chan_cfg engine_to_mem;
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/db5500-keypad.h b/arch/arm/mach-ux500/include/mach/db5500-keypad.h
new file mode 100644
index 00000000000..66b4c07f838
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/db5500-keypad.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License, version 2
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ */
+
+#ifndef __DB5500_KEYPAD_H
+#define __DB5500_KEYPAD_H
+
+#include <linux/input/matrix_keypad.h>
+
+/**
+ * struct db5500_keypad_platform_data - structure for platform specific data
+ * @keymap_data: matrix scan code table for keycodes
+ * @debounce_ms: platform specific debounce time
+ * @no_autorepeat: flag for auto repetition
+ */
+struct db5500_keypad_platform_data {
+ const struct matrix_keymap_data *keymap_data;
+ u8 debounce_ms;
+ bool no_autorepeat;
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
index 545c80fc802..6ad98329410 100644
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h
@@ -17,6 +17,8 @@
#define U5500_GIC_DIST_BASE 0xA0411000
#define U5500_GIC_CPU_BASE 0xA0410100
#define U5500_DMA_BASE 0x90030000
+#define U5500_STM_BASE 0x90020000
+#define U5500_STM_REG_BASE (U5500_STM_BASE + 0xF000)
#define U5500_MCDE_BASE 0xA0400000
#define U5500_MODEM_BASE 0xB0000000
#define U5500_L2CC_BASE 0xA0412000
@@ -29,7 +31,9 @@
#define U5500_NAND0_BASE 0x60000000
#define U5500_NAND1_BASE 0x70000000
#define U5500_TWD_BASE 0xa0410600
+#define U5500_ICN_BASE 0xA0040000
#define U5500_B2R2_BASE 0xa0200000
+#define U5500_BOOT_ROM_BASE 0x90000000
#define U5500_FSMC_BASE (U5500_PER1_BASE + 0x0000)
#define U5500_SDI0_BASE (U5500_PER1_BASE + 0x1000)
@@ -60,6 +64,7 @@
#define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000)
#define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000)
#define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000)
+#define U5500_PRCMU_TCDM_BASE (U5500_PER4_BASE + 0x18000)
#define U5500_SPI0_BASE (U5500_PER5_BASE + 0x0000)
#define U5500_SPI1_BASE (U5500_PER5_BASE + 0x1000)
@@ -83,7 +88,7 @@
#define U5500_HASH0_BASE (U5500_PER6_BASE + 0x1000)
#define U5500_HASH1_BASE (U5500_PER6_BASE + 0x2000)
#define U5500_PKA_BASE (U5500_PER6_BASE + 0x4000)
-#define U5500_PKAM_BASE (U5500_PER6_BASE + 0x5000)
+#define U5500_PKAM_BASE (U5500_PER6_BASE + 0x5100)
#define U5500_MTU0_BASE (U5500_PER6_BASE + 0x6000)
#define U5500_MTU1_BASE (U5500_PER6_BASE + 0x7000)
#define U5500_CR_BASE (U5500_PER6_BASE + 0x8000)
@@ -100,4 +105,33 @@
#define U5500_GPIOBANK6_BASE (U5500_GPIO4_BASE + 0x80)
#define U5500_GPIOBANK7_BASE (U5500_GPIO4_BASE + 0x100)
+#define U5500_MBOX_BASE (U5500_MODEM_BASE + 0xFFD1000)
+#define U5500_MBOX0_PEER_START (U5500_MBOX_BASE + 0x40)
+#define U5500_MBOX0_PEER_END (U5500_MBOX_BASE + 0x5F)
+#define U5500_MBOX0_LOCAL_START (U5500_MBOX_BASE + 0x60)
+#define U5500_MBOX0_LOCAL_END (U5500_MBOX_BASE + 0x7F)
+#define U5500_MBOX1_PEER_START (U5500_MBOX_BASE + 0x80)
+#define U5500_MBOX1_PEER_END (U5500_MBOX_BASE + 0x9F)
+#define U5500_MBOX1_LOCAL_START (U5500_MBOX_BASE + 0xA0)
+#define U5500_MBOX1_LOCAL_END (U5500_MBOX_BASE + 0xBF)
+#define U5500_MBOX2_PEER_START (U5500_MBOX_BASE + 0x00)
+#define U5500_MBOX2_PEER_END (U5500_MBOX_BASE + 0x1F)
+#define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20)
+#define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F)
+
+#define U5500_ACCCON_BASE_SEC (0xBFFF0000)
+#define U5500_ACCCON_BASE (0xBFFF1000)
+#define U5500_ACCCON_CPUVEC_RESET_ADDR_OFFSET (0x00000020)
+#define U5500_ACCCON_ACC_CPU_CTRL_OFFSET (0x000000BC)
+
+#define U5500_ESRAM_BASE 0x40000000
+#define U5500_ESRAM_DMA_LCPA_OFFSET 0x10000
+#define U5500_DMA_LCPA_BASE (U5500_ESRAM_BASE + U5500_ESRAM_DMA_LCPA_OFFSET)
+
+#define U5500_MCDE_SIZE 0x1000
+#define U5500_DSI_LINK_SIZE 0x1000
+#define U5500_DSI_LINK_COUNT 0x2
+#define U5500_DSI_LINK1_BASE (U5500_MCDE_BASE + U5500_MCDE_SIZE)
+#define U5500_DSI_LINK2_BASE (U5500_DSI_LINK1_BASE + U5500_DSI_LINK_SIZE)
+
#endif
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h
index 85fc6a80b38..dc70e408459 100644
--- a/arch/arm/mach-ux500/include/mach/db8500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h
@@ -15,9 +15,14 @@
#define U8500_ESRAM_BANK2 (U8500_ESRAM_BANK1 + U8500_ESRAM_BANK_SIZE)
#define U8500_ESRAM_BANK3 (U8500_ESRAM_BANK2 + U8500_ESRAM_BANK_SIZE)
#define U8500_ESRAM_BANK4 (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE)
-/* Use bank 4 for DMA LCLA and LCPA */
-#define U8500_DMA_LCLA_BASE U8500_ESRAM_BANK4
-#define U8500_DMA_LCPA_BASE (U8500_ESRAM_BANK4 + 0x4000)
+/*
+ * on V1 DMA uses 4KB for logical parameters position is right after the 64KB
+ * reserved for security
+ */
+#define U8500_ESRAM_DMA_LCPA_OFFSET 0x10000
+
+#define U8500_DMA_LCPA_BASE (U8500_ESRAM_BANK0 + U8500_ESRAM_DMA_LCPA_OFFSET)
+#define U8500_DMA_LCPA_BASE_ED (U8500_ESRAM_BANK4 + 0x4000)
#define U8500_PER3_BASE 0x80000000
#define U8500_STM_BASE 0x80100000
@@ -27,11 +32,12 @@
#define U8500_B2R2_BASE 0x80130000
#define U8500_HSEM_BASE 0x80140000
#define U8500_PER4_BASE 0x80150000
+#define U8500_TPIU_BASE 0x80190000
#define U8500_ICN_BASE 0x81000000
#define U8500_BOOT_ROM_BASE 0x90000000
-/* ASIC ID is at 0xff4 offset within this region */
-#define U8500_ASIC_ID_BASE 0x9001F000
+/* ASIC ID is at 0xbf4 offset within this region */
+#define U8500_ASIC_ID_BASE 0x9001D000
#define U8500_PER6_BASE 0xa03c0000
#define U8500_PER5_BASE 0xa03e0000
@@ -72,13 +78,15 @@
/* per6 base addressess */
#define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000)
-#define U8500_PKA_BASE (U8500_PER6_BASE + 0x1000)
-#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x2000)
+#define U8500_HASH0_BASE (U8500_PER6_BASE + 0x1000)
+#define U8500_HASH1_BASE (U8500_PER6_BASE + 0x2000)
+#define U8500_PKA_BASE (U8500_PER6_BASE + 0x4000)
+#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x5100)
#define U8500_MTU0_BASE (U8500_PER6_BASE + 0x6000) /* v1 */
#define U8500_MTU1_BASE (U8500_PER6_BASE + 0x7000) /* v1 */
#define U8500_CR_BASE (U8500_PER6_BASE + 0x8000) /* v1 */
-#define U8500_CRYPTO0_BASE (U8500_PER6_BASE + 0xa000)
-#define U8500_CRYPTO1_BASE (U8500_PER6_BASE + 0xb000)
+#define U8500_CRYP0_BASE (U8500_PER6_BASE + 0xa000)
+#define U8500_CRYP1_BASE (U8500_PER6_BASE + 0xb000)
#define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000)
/* per5 base addressess */
@@ -94,7 +102,9 @@
#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000)
#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000)
#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000)
-#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x0f000)
+#define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000)
+#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
+#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000)
/* per3 base addresses */
#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000)
@@ -125,6 +135,7 @@
#define U8500_I2C1_BASE (U8500_PER1_BASE + 0x2000)
#define U8500_MSP0_BASE (U8500_PER1_BASE + 0x3000)
#define U8500_MSP1_BASE (U8500_PER1_BASE + 0x4000)
+#define U8500_MSP3_BASE (U8500_PER1_BASE + 0x5000)
#define U8500_SDI0_BASE (U8500_PER1_BASE + 0x6000)
#define U8500_I2C2_BASE (U8500_PER1_BASE + 0x8000)
#define U8500_SPI3_BASE (U8500_PER1_BASE + 0x9000)
@@ -144,4 +155,15 @@
#define U8500_GPIOBANK7_BASE (U8500_GPIO2_BASE + 0x80)
#define U8500_GPIOBANK8_BASE U8500_GPIO3_BASE
+#define U8500_MCDE_SIZE 0x1000
+#define U8500_DSI_LINK_SIZE 0x1000
+#define U8500_DSI_LINK1_BASE (U8500_MCDE_BASE + U8500_MCDE_SIZE)
+#define U8500_DSI_LINK2_BASE (U8500_DSI_LINK1_BASE + U8500_DSI_LINK_SIZE)
+#define U8500_DSI_LINK3_BASE (U8500_DSI_LINK2_BASE + U8500_DSI_LINK_SIZE)
+#define U8500_DSI_LINK_COUNT 0x3
+
+/* Modem and APE physical addresses */
+#define U8500_MODEM_BASE 0xe000000
+#define U8500_APE_BASE 0x6000000
+
#endif
diff --git a/arch/arm/mach-ux500/include/mach/dcache.h b/arch/arm/mach-ux500/include/mach/dcache.h
new file mode 100644
index 00000000000..83fe618b04f
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/dcache.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Data cache helpers
+ *
+ * Author: Johan Mossberg <johan.xx.mossberg@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef _MACH_UX500_DCACHE_H_
+#define _MACH_UX500_DCACHE_H_
+
+#include <linux/types.h>
+
+void drain_cpu_write_buf(void);
+void clean_cpu_dcache(void *vaddr, u32 paddr, u32 length, bool inner_only,
+ bool *cleaned_everything);
+void flush_cpu_dcache(void *vaddr, u32 paddr, u32 length, bool inner_only,
+ bool *flushed_everything);
+bool speculative_data_prefetch(void);
+/* Returns 1 if no cache is present */
+u32 get_dcache_granularity(void);
+
+#endif /* _MACH_UX500_DCACHE_H_ */
diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S
index c5203b7ea55..058498a5ae7 100644
--- a/arch/arm/mach-ux500/include/mach/debug-macro.S
+++ b/arch/arm/mach-ux500/include/mach/debug-macro.S
@@ -10,19 +10,17 @@
*/
#include <mach/hardware.h>
-#if CONFIG_UX500_DEBUG_UART > 2
-#error Invalid Ux500 debug UART
+#ifdef CONFIG_UX500_SOC_DB5500
+#define UX500_DEBUG_UART U5500_UART0_BASE
+#else
+#define UX500_DEBUG_UART U8500_UART2_BASE
#endif
-#define __UX500_UART(n) UX500_UART##n##_BASE
-#define UX500_UART(n) __UX500_UART(n)
-#define UART_BASE UX500_UART(CONFIG_UX500_DEBUG_UART)
-
.macro addruart, rx, tmp
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
- ldreq \rx, =UART_BASE @ no, physical address
- ldrne \rx, =IO_ADDRESS(UART_BASE) @ yes, virtual address
+ ldreq \rx, =UX500_DEBUG_UART @ no, physical address
+ ldrne \rx, =IO_ADDRESS(UX500_DEBUG_UART) @ yes, virtual address
.endm
#include <asm/hardware/debug-pl01x.S>
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index c2b2f257494..bf088670bbc 100644
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -13,20 +13,38 @@ struct amba_device;
extern struct platform_device u5500_gpio_devs[];
extern struct platform_device u8500_gpio_devs[];
-extern struct amba_device ux500_pl031_device;
-extern struct amba_device u8500_ssp0_device;
-extern struct amba_device ux500_uart0_device;
-extern struct amba_device ux500_uart1_device;
-extern struct amba_device ux500_uart2_device;
-
-extern struct platform_device ux500_i2c1_device;
-extern struct platform_device ux500_i2c2_device;
-extern struct platform_device ux500_i2c3_device;
-
-extern struct platform_device u8500_i2c0_device;
-extern struct platform_device u8500_i2c4_device;
-extern struct platform_device u8500_dma40_device;
+extern struct platform_device ux500_mcde_device;
+extern struct platform_device u8500_shrm_device;
+extern struct platform_device ux500_b2r2_device;
+extern struct platform_device u8500_trace_modem;
+extern struct platform_device u8500_pmem_device;
+extern struct platform_device u8500_pmem_mio_device;
+extern struct platform_device u8500_pmem_hwb_device;
+extern struct platform_device ux500_hwmem_device;
+extern struct platform_device ux500_dma_device;
+extern struct platform_device ux500_hash1_device;
+extern struct platform_device ux500_cryp1_device;
+extern struct platform_device ux500_musb_device;
+extern struct platform_device u5500_pwm0_device;
+extern struct platform_device u5500_pwm1_device;
+extern struct platform_device u5500_pwm2_device;
+extern struct platform_device u5500_pwm3_device;
+extern struct platform_device ux500_wdt_device;
+extern struct platform_device mloader_fw_device;
+extern struct platform_device u8500_thsens_device;
+extern struct platform_device ux500_stm_device;
+extern struct platform_device ux500_mmio_device;
+extern struct platform_device u8500_hsi_device;
+#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
+
+/**
+ * Touchpanel related macros declaration
+ */
+#define TOUCH_GPIO_PIN 84
-void dma40_u8500ed_fixup(void);
+#define TOUCH_XMAX 384
+#define TOUCH_YMAX 704
+#define PRCMU_CLOCK_OCR 0x1CC
+#define TSC_EXT_CLOCK_9_6MHZ 0x840000
#endif
diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S
index 60ea88db828..15baa203889 100644
--- a/arch/arm/mach-ux500/include/mach/entry-macro.S
+++ b/arch/arm/mach-ux500/include/mach/entry-macro.S
@@ -17,7 +17,8 @@
.endm
.macro get_irqnr_preamble, base, tmp
- ldr \base, =IO_ADDRESS(UX500_GIC_CPU_BASE)
+ ldr \base, =gic_cpu_base_addr
+ ldr \base, [\base]
.endm
.macro arch_ret_to_user, tmp1, tmp2
diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h
index d548a622e7d..25bbd61ced6 100644
--- a/arch/arm/mach-ux500/include/mach/gpio.h
+++ b/arch/arm/mach-ux500/include/mach/gpio.h
@@ -9,42 +9,171 @@
#include <plat/gpio.h>
-#define __GPIO_RESOURCE(soc, block) \
- { \
- .start = soc##_GPIOBANK##block##_BASE, \
- .end = soc##_GPIOBANK##block##_BASE + 127, \
- .flags = IORESOURCE_MEM, \
- }, \
- { \
- .start = IRQ_GPIO##block, \
- .end = IRQ_GPIO##block, \
- .flags = IORESOURCE_IRQ, \
- }
-
-#define __GPIO_DEVICE(soc, block) \
- { \
- .name = "gpio", \
- .id = block, \
- .num_resources = 2, \
- .resource = &soc##_gpio_resources[block * 2], \
- .dev = { \
- .platform_data = &soc##_gpio_data[block], \
- }, \
- }
-
-#define GPIO_DATA(_name, first) \
- { \
- .name = _name, \
- .first_gpio = first, \
- .first_irq = NOMADIK_GPIO_TO_IRQ(first), \
- }
-
-#ifdef CONFIG_UX500_SOC_DB8500
-#define GPIO_RESOURCE(block) __GPIO_RESOURCE(U8500, block)
-#define GPIO_DEVICE(block) __GPIO_DEVICE(u8500, block)
-#elif defined(CONFIG_UX500_SOC_DB5500)
-#define GPIO_RESOURCE(block) __GPIO_RESOURCE(U5500, block)
-#define GPIO_DEVICE(block) __GPIO_DEVICE(u5500, block)
+/* Used by test applications */
+#define GPIO_TOTAL_PINS 267
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+#define gpio_to_irq __gpio_to_irq
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+ if (irq < NR_IRQS)
+ return IRQ_TO_GPIO(irq);
+ else
+ return -EINVAL;
+}
+
+enum {
+ EGPIO_PIN_0 = U8500_NR_GPIO,
+ EGPIO_PIN_1,
+ EGPIO_PIN_2,
+ EGPIO_PIN_3,
+ EGPIO_PIN_4,
+ EGPIO_PIN_5,
+ EGPIO_PIN_6,
+ EGPIO_PIN_7,
+ EGPIO_PIN_8,
+ EGPIO_PIN_9,
+ EGPIO_PIN_10,
+ EGPIO_PIN_11,
+ EGPIO_PIN_12,
+ EGPIO_PIN_13,
+ EGPIO_PIN_14,
+ EGPIO_PIN_15,
+ EGPIO_PIN_16,
+ EGPIO_PIN_17,
+ EGPIO_PIN_18,
+ EGPIO_PIN_19,
+ EGPIO_PIN_20,
+ EGPIO_PIN_21,
+ EGPIO_PIN_22,
+ EGPIO_PIN_23,
+#ifdef CONFIG_AB8500_GPIO
+ AB8500_PIN_GPIO1,
+ AB8500_PIN_GPIO2,
+ AB8500_PIN_GPIO3,
+ AB8500_PIN_GPIO4,
+ AB8500_PIN_GPIO5,
+ AB8500_PIN_GPIO6,
+ AB8500_PIN_GPIO7,
+ AB8500_PIN_GPIO8,
+ AB8500_PIN_GPIO9,
+ AB8500_PIN_GPIO10,
+ AB8500_PIN_GPIO11,
+ AB8500_PIN_GPIO12,
+ AB8500_PIN_GPIO13,
+ AB8500_PIN_GPIO14,
+ AB8500_PIN_GPIO15,
+ AB8500_PIN_GPIO16,
+ AB8500_PIN_GPIO17,
+ AB8500_PIN_GPIO18,
+ AB8500_PIN_GPIO19,
+ AB8500_PIN_GPIO20,
+ AB8500_PIN_GPIO21,
+ AB8500_PIN_GPIO22,
+ AB8500_PIN_GPIO23,
+ AB8500_PIN_GPIO24,
+ AB8500_PIN_GPIO25,
+ AB8500_PIN_GPIO26,
+ AB8500_PIN_GPIO27,
+ AB8500_PIN_GPIO28,
+ AB8500_PIN_GPIO29,
+ AB8500_PIN_GPIO30,
+ AB8500_PIN_GPIO31,
+ AB8500_PIN_GPIO32,
+ AB8500_PIN_GPIO33,
+ AB8500_PIN_GPIO34,
+ AB8500_PIN_GPIO35,
+ AB8500_PIN_GPIO36,
+ AB8500_PIN_GPIO37,
+ AB8500_PIN_GPIO38,
+ AB8500_PIN_GPIO39,
+ AB8500_PIN_GPIO40,
+ AB8500_PIN_GPIO41,
+ AB8500_PIN_GPIO42,
#endif
+};
+
+/* Don't use in new code -- use the plain numbers */
+#define GPIO_LOW 0
+#define GPIO_HIGH 1
+#define GPIO_DATA_LOW 0
+#define GPIO_DATA_HIGH 1
+#define GPIO(x) (x)
+
+/*
+ * Alternate Function:
+ * refered in altfun_table to pointout particular altfun to be enabled
+ * when using GPIO_ALT_FUNCTION A/B/C enable/disable operation
+ */
+typedef enum {
+ GPIO_ALT_I2C_0,
+ GPIO_ALT_I2C_1,
+ GPIO_ALT_I2C_2,
+ GPIO_ALT_I2C_3,
+ GPIO_ALT_I2C_4,
+ GPIO_ALT_MSP_0,
+ GPIO_ALT_MSP_1,
+ GPIO_ALT_MSP_2,
+ GPIO_ALT_MSP_3,
+ GPIO_ALT_MM_CARD,
+ GPIO_ALT_SD_CARD,
+ GPIO_ALT_DMA_0,
+ GPIO_ALT_DMA_1,
+ GPIO_ALT_HSIR,
+ GPIO_ALT_CCIR656_INPUT,
+ GPIO_ALT_CCIR656_OUTPUT,
+ GPIO_ALT_LCD_PANELA,
+ GPIO_ALT_LCD_PANELB_ED,
+ GPIO_ALT_LCD_PANELB,
+ GPIO_ALT_MDIF,
+ GPIO_ALT_SDRAM,
+ GPIO_ALT_HAMAC_AUDIO_DBG,
+ GPIO_ALT_HAMAC_VIDEO_DBG,
+ GPIO_ALT_CLOCK_RESET,
+ GPIO_ALT_TSP,
+ GPIO_ALT_IRDA,
+ GPIO_ALT_USB_MINIMUM,
+ GPIO_ALT_USB_I2C,
+ GPIO_ALT_OWM,
+ GPIO_ALT_PWL,
+ GPIO_ALT_FSMC,
+ GPIO_ALT_COMP_FLASH,
+ GPIO_ALT_SRAM_NOR_FLASH,
+ GPIO_ALT_FSMC_ADDLINE_0_TO_15,
+ GPIO_ALT_SCROLL_KEY,
+ GPIO_ALT_MSHC,
+ GPIO_ALT_HPI,
+ GPIO_ALT_USB_OTG,
+ GPIO_ALT_SDIO,
+ GPIO_ALT_HSMMC,
+ GPIO_ALT_FSMC_ADD_DATA_0_TO_25,
+ GPIO_ALT_HSIT,
+ GPIO_ALT_NOR,
+ GPIO_ALT_NAND,
+ GPIO_ALT_KEYPAD,
+ GPIO_ALT_VPIP,
+ GPIO_ALT_CAM,
+ GPIO_ALT_CCP1,
+ GPIO_ALT_EMMC,
+ GPIO_ALT_SDMMC,
+ GPIO_ALT_TRACE,
+ GPIO_ALT_MMIO_INIT_BOARD,
+ GPIO_ALT_MMIO_CAM_SET_I2C,
+ GPIO_ALT_MMIO_CAM_SET_EXT_CLK,
+ GPIO_ALT_TRACE_MIPI60,
+ GPIO_ALT_SDMMC2,
+ GPIO_ALT_TP_SET_EXT_CLK,
+ GPIO_ALT_LCD_D_8,
+ GPIO_ALT_LCD_D_16,
+ GPIO_ALT_LCD_D_18,
+ GPIO_ALT_LCD_D_24,
+ GPIO_ALT_LCDA,
+ GPIO_ALT_LCDA_CLK,
+ GPIO_ALT_LCDB,
+ GPIO_ALT_FUNMAX /* Add new alt func before this */
+} gpio_alt_function;
-#endif /* __ASM_ARCH_GPIO_H */
+#endif /* __MACH_GPIO_H */
diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h
index 8656379a830..7bb75c7838e 100644
--- a/arch/arm/mach-ux500/include/mach/hardware.h
+++ b/arch/arm/mach-ux500/include/mach/hardware.h
@@ -29,72 +29,90 @@
#include <mach/db8500-regs.h>
#include <mach/db5500-regs.h>
-#ifdef CONFIG_UX500_SOC_DB8500
-#define UX500(periph) U8500_##periph##_BASE
-#elif defined(CONFIG_UX500_SOC_DB5500)
-#define UX500(periph) U5500_##periph##_BASE
-#endif
-
-#define UX500_BACKUPRAM0_BASE UX500(BACKUPRAM0)
-#define UX500_BACKUPRAM1_BASE UX500(BACKUPRAM1)
-#define UX500_B2R2_BASE UX500(B2R2)
-
-#define UX500_CLKRST1_BASE UX500(CLKRST1)
-#define UX500_CLKRST2_BASE UX500(CLKRST2)
-#define UX500_CLKRST3_BASE UX500(CLKRST3)
-#define UX500_CLKRST5_BASE UX500(CLKRST5)
-#define UX500_CLKRST6_BASE UX500(CLKRST6)
-
-#define UX500_DMA_BASE UX500(DMA)
-#define UX500_FSMC_BASE UX500(FSMC)
-
-#define UX500_GIC_CPU_BASE UX500(GIC_CPU)
-#define UX500_GIC_DIST_BASE UX500(GIC_DIST)
-
-#define UX500_I2C1_BASE UX500(I2C1)
-#define UX500_I2C2_BASE UX500(I2C2)
-#define UX500_I2C3_BASE UX500(I2C3)
-
-#define UX500_L2CC_BASE UX500(L2CC)
-#define UX500_MCDE_BASE UX500(MCDE)
-#define UX500_MTU0_BASE UX500(MTU0)
-#define UX500_MTU1_BASE UX500(MTU1)
-#define UX500_PRCMU_BASE UX500(PRCMU)
-
-#define UX500_RNG_BASE UX500(RNG)
-#define UX500_RTC_BASE UX500(RTC)
-
-#define UX500_SCU_BASE UX500(SCU)
-
-#define UX500_SDI0_BASE UX500(SDI0)
-#define UX500_SDI1_BASE UX500(SDI1)
-#define UX500_SDI2_BASE UX500(SDI2)
-#define UX500_SDI3_BASE UX500(SDI3)
-#define UX500_SDI4_BASE UX500(SDI4)
+/* ST-Ericsson modified pl022 id */
+#define SSP_PER_ID 0x01080022
+#define SSP_PER_MASK 0x0fffffff
-#define UX500_SPI0_BASE UX500(SPI0)
-#define UX500_SPI1_BASE UX500(SPI1)
-#define UX500_SPI2_BASE UX500(SPI2)
-#define UX500_SPI3_BASE UX500(SPI3)
+/* SSP specific declaration */
+#define SPI_PER_ID 0x00080023
+#define SPI_PER_MASK 0x0fffffff
-#define UX500_SIA_BASE UX500(SIA)
-#define UX500_SVA_BASE UX500(SVA)
+/* MSP specific declaration */
+#define MSP_PER_ID 0x00280021
+#define MSP_PER_MASK 0x00ffffff
-#define UX500_TWD_BASE UX500(TWD)
+/* DMA specific declaration */
+#define DMA_PER_ID 0x8A280080
+#define DMA_PER_MASK 0xffffffff
-#define UX500_UART0_BASE UX500(UART0)
-#define UX500_UART1_BASE UX500(UART1)
-#define UX500_UART2_BASE UX500(UART2)
+#define GPIO_PER_ID 0x1f380060
+#define GPIO_PER_MASK 0xffffffff
-#define UX500_USBOTG_BASE UX500(USBOTG)
+/* RTC specific declaration */
+#define RTC_PER_ID 0x00280031
+#define RTC_PER_MASK 0x00ffffff
-/* ST-Ericsson modified pl022 id */
-#define SSP_PER_ID 0x01080022
+/*
+ * FIFO offsets for IPs
+ */
+#define I2C_TX_REG_OFFSET (0x10)
+#define I2C_RX_REG_OFFSET (0x18)
+#define UART_TX_RX_REG_OFFSET (0)
+#define MSP_TX_RX_REG_OFFSET (0)
+#define SSP_TX_RX_REG_OFFSET (0x8)
+#define SPI_TX_RX_REG_OFFSET (0x8)
+#define SD_MMC_TX_RX_REG_OFFSET (0x80)
+#define CRYP1_RX_REG_OFFSET (0x10)
+#define CRYP1_TX_REG_OFFSET (0x8)
+
+#define MSP_0_CONTROLLER 1
+#define MSP_1_CONTROLLER 2
+#define MSP_2_CONTROLLER 3
+#define MSP_3_CONTROLLER 4
+
+#define SSP_0_CONTROLLER 4
+#define SSP_1_CONTROLLER 5
+
+#define SPI023_0_CONTROLLER 6
+#define SPI023_1_CONTROLLER 7
+#define SPI023_2_CONTROLLER 8
+#define SPI023_3_CONTROLLER 9
+
+/* MSP related board specific declaration************************/
+
+#define MSP_DATA_DELAY MSP_DELAY_0
+#define MSP_TX_CLOCK_EDGE MSP_FALLING_EDGE
+#define MSP_RX_CLOCK_EDGE MSP_FALLING_EDGE
+#define NUM_MSP_CONTROLLER 3
+
+/* I2C configuration
+ * * *
+ * * */
+#define I2C0_LP_OWNADDR 0x31
+#define I2C1_LP_OWNADDR 0x60
+#define I2C2_LP_OWNADDR 0x70
+#define I2C3_LP_OWNADDR 0x80
+#define I2C4_LP_OWNADDR 0x90
+
+/* SDMMC specific declarations */
+#define SDI_PER_ID 0x00480180
+#define SDI_PER_MASK 0x00ffffff
+/* B2R2 clock management register */
+#define PRCM_B2R2CLK_MGT_REG 0x80157078 /** B2R2 clock selection */
#ifndef __ASSEMBLY__
+extern void __iomem *_PRCMU_BASE;
+
#include <asm/cputype.h>
+#include <asm/mach-types.h>
+static inline bool ux500_is_svp(void)
+{
+ return machine_is_svp8500v1() ||
+ machine_is_svp8500v2() ||
+ machine_is_svp5500();
+}
static inline bool cpu_is_u8500(void)
{
#ifdef CONFIG_UX500_SOC_DB8500
@@ -104,16 +122,56 @@ static inline bool cpu_is_u8500(void)
#endif
}
+#define CPUID_DB8500ED 0x410fc090
+#define CPUID_DB8500V1 0x411fc091
+#define CPUID_DB8500V2 0x412fc091
+
static inline bool cpu_is_u8500ed(void)
{
- return cpu_is_u8500() && (read_cpuid_id() & 15) == 0;
+ /*
+ * SVP8500 unfortunately does not update the MIDR register on silicon
+ * revisions, but instead maintains the old ED value.
+ */
+ if (ux500_is_svp())
+ return false;
+
+ return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500ED);
}
static inline bool cpu_is_u8500v1(void)
{
- return cpu_is_u8500() && (read_cpuid_id() & 15) == 1;
+ if (machine_is_svp8500v1())
+ return true;
+ else if (machine_is_svp8500v2())
+ return false;
+
+ return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V1);
+}
+
+static inline bool cpu_is_u8500v2(void)
+{
+ if (machine_is_svp8500v1())
+ return false;
+ else if (machine_is_svp8500v2())
+ return true;
+
+ return cpu_is_u8500() && (read_cpuid_id() == CPUID_DB8500V2);
}
+#ifdef CONFIG_UX500_SOC_DB8500
+bool cpu_is_u8500v10(void);
+bool cpu_is_u8500v11(void);
+bool cpu_is_u8500v20(void);
+bool cpu_is_u8500v21(void);
+bool cpu_is_u8500v20_or_later(void);
+#else
+static inline bool cpu_is_u8500v10(void) { return false; }
+static inline bool cpu_is_u8500v11(void) { return false; }
+static inline bool cpu_is_u8500v20(void) { return false; }
+static inline bool cpu_is_u8500v21(void) { return false; }
+static inline bool cpu_is_u8500v20_or_later(void) { return false; }
+#endif
+
static inline bool cpu_is_u5500(void)
{
#ifdef CONFIG_UX500_SOC_DB5500
@@ -125,4 +183,7 @@ static inline bool cpu_is_u5500(void)
#endif
+/* Keep this greppable for SoC porters */
+#define ux500_unknown_soc() BUG()
+
#endif /* __MACH_HARDWARE_H */
diff --git a/arch/arm/mach-ux500/include/mach/hcl_defs.h b/arch/arm/mach-ux500/include/mach/hcl_defs.h
new file mode 100644
index 00000000000..efd37608cb3
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/hcl_defs.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 ST-Ericsson SA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef _HCL_DEFS_H
+#define _HCL_DEFS_H
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+//#include "platform_os.h"
+
+/*-----------------------------------------------------------------------------
+ * Type definition
+ *---------------------------------------------------------------------------*/
+typedef unsigned char t_uint8;
+typedef signed char t_sint8;
+typedef unsigned short t_uint16;
+typedef signed short t_sint16;
+typedef unsigned long t_uint32;
+typedef signed long t_sint32;
+
+typedef unsigned int t_bitfield;
+
+
+
+#if !defined(FALSE) && !defined(TRUE)
+typedef int t_bool;
+#define FALSE 0
+#define TRUE 1
+#endif
+
+/*
+ * Definition of the different kind of addresses manipulated into a system with MMU
+ * (handle physical AND logical addresses)
+ */
+
+
+typedef t_uint32 t_physical_address;
+typedef t_uint32 t_logical_address;
+
+
+
+/*
+ * Global frequency enumuration
+ * Added to avoid frequency conversion function which is required to convert one HCL
+ * frequency enumuration values to another HCL frequency enumuration values.
+ */
+
+/*typedef enum {
+ HCL_FREQ_NOT_SUPPORTED=-1,
+ HCL_FREQ_8KHZ ,
+ HCL_FREQ_11_25KHZ,
+ HCL_FREQ_12KHZ,
+ HCL_FREQ_16KHZ,
+ HCL_FREQ_22_05KHZ,
+ HCL_FREQ_22_5KHZ,
+ HCL_FREQ_24KHZ,
+ HCL_FREQ_32KHZ,
+ HCL_FREQ_44KHZ,
+ HCL_FREQ_44_1KHZ,
+ HCL_FREQ_48KHZ,
+ HCL_FREQ_64KHZ,
+ HCL_FREQ_88KHZ,
+ HCL_FREQ_88_2KHZ,
+ HCL_FREQ_96KHZ,
+ HCL_FREQ_128KHZ,
+ HCL_FREQ_176_4KHZ,
+ HCL_FREQ_192KHZ,
+
+ HCL_FREQ_1MHZ,
+ HCL_FREQ_2MHZ,
+ HCL_FREQ_3MHZ,
+ HCL_FREQ_4MHZ,
+ HCL_FREQ_5MHZ,
+ HCL_FREQ_6MHZ,
+ HCL_FREQ_8MHZ,
+ HCL_FREQ_11MHZ,
+ HCL_FREQ_12MHZ,
+ HCL_FREQ_16MHZ,
+ HCL_FREQ_22MHZ,
+ HCL_FREQ_24MHZ,
+ HCL_FREQ_48MHZ
+} t_frequency;
+
+*/
+
+typedef struct {
+ t_physical_address physical;
+ t_logical_address logical;
+} t_system_address;
+
+
+/*
+ * Define a type used to manipulate size of various buffers
+ */
+typedef t_uint32 t_size;
+
+typedef struct {
+ t_bitfield minor:8;
+ t_bitfield major:8;
+ t_bitfield version:16;
+} t_version;
+
+
+
+
+/*-----------------------------------------------------------------------------
+ * Keyword definition
+ *---------------------------------------------------------------------------*/
+#define PUBLIC /* Extern by default */
+#define PRIVATE static
+
+#ifndef NULL
+#define NULL (0)
+#endif /* ndef NULL */
+
+
+/*-----------------------------------------------------------------------------
+ * Bit setting or clearing
+ *---------------------------------------------------------------------------*/
+#define HCL_SET_BITS(reg,mask) ((reg) |= (mask))
+#define HCL_CLEAR_BITS(reg,mask) ((reg) &= ~(mask))
+#define HCL_READ_BITS(reg,mask) ((reg) & (mask))
+#define HCL_WRITE_BITS(reg,val,mask) ((reg) = (((reg) & ~(mask)) | ((val) & (mask))))
+#define HCL_READ_REG(reg) (reg)
+#define HCL_WRITE_REG(reg,val) ((reg) = (val))
+
+/*-----------------------------------------------------------------------------
+ * field offset extraction from a structure
+ *---------------------------------------------------------------------------*/
+#define HCL_BITFIELD_OFFSET(typeName, fieldName) (t_uint32)(&(((typeName *)0)->fieldName))
+
+/*-----------------------------------------------------------------------------
+ * Bit mask definition
+ *---------------------------------------------------------------------------*/
+#define MASK_NULL8 0x00
+#define MASK_NULL16 0x0000
+#define MASK_NULL32 0x00000000
+#define MASK_ALL8 0xFF
+#define MASK_ALL16 0xFFFF
+#define MASK_ALL32 0xFFFFFFFF
+
+#define MASK_BIT0 (1UL<<0)
+#define MASK_BIT1 (1UL<<1)
+#define MASK_BIT2 (1UL<<2)
+#define MASK_BIT3 (1UL<<3)
+#define MASK_BIT4 (1UL<<4)
+#define MASK_BIT5 (1UL<<5)
+#define MASK_BIT6 (1UL<<6)
+#define MASK_BIT7 (1UL<<7)
+#define MASK_BIT8 (1UL<<8)
+#define MASK_BIT9 (1UL<<9)
+#define MASK_BIT10 (1UL<<10)
+#define MASK_BIT11 (1UL<<11)
+#define MASK_BIT12 (1UL<<12)
+#define MASK_BIT13 (1UL<<13)
+#define MASK_BIT14 (1UL<<14)
+#define MASK_BIT15 (1UL<<15)
+#define MASK_BIT16 (1UL<<16)
+#define MASK_BIT17 (1UL<<17)
+#define MASK_BIT18 (1UL<<18)
+#define MASK_BIT19 (1UL<<19)
+#define MASK_BIT20 (1UL<<20)
+#define MASK_BIT21 (1UL<<21)
+#define MASK_BIT22 (1UL<<22)
+#define MASK_BIT23 (1UL<<23)
+#define MASK_BIT24 (1UL<<24)
+#define MASK_BIT25 (1UL<<25)
+#define MASK_BIT26 (1UL<<26)
+#define MASK_BIT27 (1UL<<27)
+#define MASK_BIT28 (1UL<<28)
+#define MASK_BIT29 (1UL<<29)
+#define MASK_BIT30 (1UL<<30)
+#define MASK_BIT31 (1UL<<31)
+
+/*-----------------------------------------------------------------------------
+ * quartet shift definition
+ *---------------------------------------------------------------------------*/
+#define MASK_QUARTET (0xFUL)
+#define SHIFT_QUARTET0 0
+#define SHIFT_QUARTET1 4
+#define SHIFT_QUARTET2 8
+#define SHIFT_QUARTET3 12
+#define SHIFT_QUARTET4 16
+#define SHIFT_QUARTET5 20
+#define SHIFT_QUARTET6 24
+#define SHIFT_QUARTET7 28
+#define MASK_QUARTET0 (MASK_QUARTET << SHIFT_QUARTET0)
+#define MASK_QUARTET1 (MASK_QUARTET << SHIFT_QUARTET1)
+#define MASK_QUARTET2 (MASK_QUARTET << SHIFT_QUARTET2)
+#define MASK_QUARTET3 (MASK_QUARTET << SHIFT_QUARTET3)
+#define MASK_QUARTET4 (MASK_QUARTET << SHIFT_QUARTET4)
+#define MASK_QUARTET5 (MASK_QUARTET << SHIFT_QUARTET5)
+#define MASK_QUARTET6 (MASK_QUARTET << SHIFT_QUARTET6)
+#define MASK_QUARTET7 (MASK_QUARTET << SHIFT_QUARTET7)
+
+/*-----------------------------------------------------------------------------
+ * Byte shift definition
+ *---------------------------------------------------------------------------*/
+#define MASK_BYTE (0xFFUL)
+#define SHIFT_BYTE0 0
+#define SHIFT_BYTE1 8
+#define SHIFT_BYTE2 16
+#define SHIFT_BYTE3 24
+#define MASK_BYTE0 (MASK_BYTE << SHIFT_BYTE0)
+#define MASK_BYTE1 (MASK_BYTE << SHIFT_BYTE1)
+#define MASK_BYTE2 (MASK_BYTE << SHIFT_BYTE2)
+#define MASK_BYTE3 (MASK_BYTE << SHIFT_BYTE3)
+
+/*-----------------------------------------------------------------------------
+ * Halfword shift definition
+ *---------------------------------------------------------------------------*/
+#define MASK_HALFWORD (0xFFFFUL)
+#define SHIFT_HALFWORD0 0
+#define SHIFT_HALFWORD1 16
+#define MASK_HALFWORD0 (MASK_HALFWORD << SHIFT_HALFWORD0)
+#define MASK_HALFWORD1 (MASK_HALFWORD << SHIFT_HALFWORD1)
+
+/*-----------------------------------------------------------------------------
+ * Global constants definition
+ *---------------------------------------------------------------------------*/
+ #define ONE_KB (1024)
+ #define ONE_MB (ONE_KB * ONE_KB)
+
+
+/*-----------------------------------------------------------------------------
+ * Address translation macros declaration
+ *---------------------------------------------------------------------------*/
+
+#define ARM_TO_AHB_ADDR(addr) (addr)
+#define AHB_TO_ARM_ADDR(addr) (addr)
+
+/* For input parameters - would not be changed by the API */
+#define IN
+/* For output parameters - would be changes by the API */
+#define OUT
+/* For input-output parameters - provides input to the API but would be changed by the API */
+#define INOUT
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _HCL_DEFS_H */
+
+/* End of file hcl_defs.h */
+
+
diff --git a/arch/arm/mach-ux500/include/mach/hsi.h b/arch/arm/mach-ux500/include/mach/hsi.h
new file mode 100644
index 00000000000..030e35e729b
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/hsi.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ */
+
+#ifndef __MACH_HSI_H
+#define __MACH_HSI_H
+
+#include <plat/ste_dma40.h>
+
+/* HSIT register offsets */
+#define STE_HSI_TX_ID 0x000
+#define STE_HSI_TX_MODE 0x004
+#define STE_HSI_TX_STATE 0x008
+#define STE_HSI_TX_IOSTATE 0x00C
+#define STE_HSI_TX_BUFSTATE 0x010
+#define STE_HSI_TX_DIVISOR 0x014
+#define STE_HSI_TX_PARITY 0x018
+#define STE_HSI_TX_BREAK 0x01C
+#define STE_HSI_TX_CHANNELS 0x020
+#define STE_HSI_TX_FLUSHBITS 0x024
+#define STE_HSI_TX_PRIORITY 0x028
+#define STE_HSI_TX_BURSTLEN 0x02C
+#define STE_HSI_TX_PREAMBLE 0x030
+#define STE_HSI_TX_DATASWAP 0x034
+#define STE_HSI_TX_FRAMELENX 0x080
+#define STE_HSI_TX_BUFFERX 0x0C0
+#define STE_HSI_TX_BASEX 0x100
+#define STE_HSI_TX_SPANX 0x140
+#define STE_HSI_TX_GAUGEX 0x180
+#define STE_HSI_TX_WATERMARKX 0x1C0
+#define STE_HSI_TX_DMAEN 0x200
+#define STE_HSI_TX_WATERMARKIS 0x204
+#define STE_HSI_TX_WATERMARKIM 0x208
+#define STE_HSI_TX_WATERMARKIC 0x20C
+#define STE_HSI_TX_WATERMARKID 0x210
+#define STE_HSI_TX_PERIPHID0 0xFE0
+#define STE_HSI_TX_PERIPHID1 0xFE4
+#define STE_HSI_TX_PERIPHID2 0xFE8
+#define STE_HSI_TX_PERIPHID3 0xFEC
+
+/* HSIR register offsets */
+#define STE_HSI_RX_ID 0x000
+#define STE_HSI_RX_MODE 0x004
+#define STE_HSI_RX_STATE 0x008
+#define STE_HSI_RX_BUFSTATE 0x00C
+#define STE_HSI_RX_THRESHOLD 0x010
+#define STE_HSI_RX_PARITY 0x014
+#define STE_HSI_RX_DETECTOR 0x018
+#define STE_HSI_RX_EXCEP 0x01C
+#define STE_HSI_RX_ACK 0x020
+#define STE_HSI_RX_CHANNELS 0x024
+#define STE_HSI_RX_REALTIME 0x028
+#define STE_HSI_RX_OVERRUN 0x02C
+#define STE_HSI_RX_OVERRUNACK 0x030
+#define STE_HSI_RX_PREAMBLE 0x034
+#define STE_HSI_RX_PIPEGAUGE 0x038
+#define STE_HSI_RX_STATICCONFID 0x03C
+#define STE_HSI_RX_BUFFERX 0x080
+#define STE_HSI_RX_FRAMELENX 0x0C0
+#define STE_HSI_RX_BASEX 0x100
+#define STE_HSI_RX_SPANX 0x140
+#define STE_HSI_RX_GAUGEX 0x180
+#define STE_HSI_RX_WATERMARKX 0x1C0
+#define STE_HSI_RX_DMAEN 0x200
+#define STE_HSI_RX_WATERMARKIS 0x204
+#define STE_HSI_RX_WATERMARKIM 0x208
+#define STE_HSI_RX_WATERMARKIC 0x20C
+#define STE_HSI_RX_WATERMARKID 0x210
+#define STE_HSI_RX_OVERRUNMIS 0x214
+#define STE_HSI_RX_OVERRUNIM 0x218
+#define STE_HSI_RX_EXCEPMIS 0x21C
+#define STE_HSI_RX_EXCEPIM 0x220
+#define STE_HSI_RX_PERIPHID0 0xFE0
+#define STE_HSI_RX_PERIPHID1 0xFE4
+#define STE_HSI_RX_PERIPHID2 0xFE8
+#define STE_HSI_RX_PERIPHID3 0xFEC
+
+/* HSI states */
+#define STE_HSI_STATE_IDLE 0x00
+#define STE_HSI_STATE_START 0x01
+#define STE_HSI_STATE_TRANSMIT 0x02
+#define STE_HSI_STATE_BREAK 0x03
+#define STE_HSI_STATE_FLUSH 0x04
+#define STE_HSI_STATE_HALT 0x05
+
+/* HSI exceptions */
+#define STE_HSI_EXCEP_TIMEOUT 0x01
+#define STE_HSI_EXCEP_OVERRUN 0x02
+#define STE_HSI_EXCEP_BREAK 0x04
+#define STE_HSI_EXCEP_PARITY 0x08
+
+/* HSI modes */
+#define STE_HSI_MODE_SLEEP 0x00
+#define STE_HSI_MODE_STREAM 0x01
+#define STE_HSI_MODE_FRAME 0x02
+#define STE_HSI_MODE_PIPELINED 0x03
+#define STE_HSI_MODE_FAILSAFE 0x04
+
+#define STE_HSI_MAX_BUFFERS 32
+
+/* Max channels of STE HSI controller */
+#define STE_HSI_MAX_CHANNELS 4
+
+struct stedma40_chan_cfg;
+
+struct ste_hsi_port_cfg {
+#ifdef CONFIG_STE_DMA40
+ bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+ struct stedma40_chan_cfg *dma_tx_cfg;
+ struct stedma40_chan_cfg *dma_rx_cfg;
+#endif
+};
+
+struct ste_hsi_platform_data {
+ int num_ports;
+ int use_dma;
+ struct ste_hsi_port_cfg *port_cfg;
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
new file mode 100644
index 00000000000..4aa25c31a22
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __MACH_IRQS_BOARD_MOP500_H
+#define __MACH_IRQS_BOARD_MOP500_H
+
+#define AB8500_NR_IRQS 112
+
+#define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START
+#define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \
+ + AB8500_NR_IRQS)
+
+/* TC3589X irqs */
+#define TC35892_NR_INTERNAL_IRQS 8
+#define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x))
+#define TC35892_NR_GPIOS 24
+#define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS)
+
+#define MOP500_EGPIO_NR_IRQS TC35892_NR_IRQS
+
+#define MOP500_EGPIO_IRQ_BASE MOP500_AB8500_IRQ_END
+#define MOP500_EGPIO_IRQ(x) (MOP500_EGPIO_IRQ_BASE + (x))
+#define MOP500_EGPIO_IRQ_END (MOP500_EGPIO_IRQ_BASE \
+ + MOP500_EGPIO_NR_IRQS)
+
+/* STMPE1601 irqs */
+#define STMPE_NR_INTERNAL_IRQS 9
+#define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x))
+#define STMPE_NR_GPIOS 24
+#define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS)
+
+#define MOP500_STMPE1601_IRQBASE MOP500_EGPIO_IRQ_END
+#define MOP500_STMPE1601_IRQ(x) (MOP500_STMPE1601_IRQBASE + (x))
+#define MOP500_STMPE1601_IRQ_END \
+ MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
+
+/* AB8500 virtual gpio IRQ */
+#define AB8500_VIR_GPIO_NR_IRQS 16
+
+#define MOP500_AB8500_VIR_GPIO_IRQ_BASE \
+ MOP500_STMPE1601_IRQ_END
+#define MOP500_AB8500_VIR_GPIO_IRQ_END \
+ (MOP500_AB8500_VIR_GPIO_IRQ_BASE + AB8500_VIR_GPIO_NR_IRQS)
+
+#define MOP500_NR_IRQS MOP500_AB8500_VIR_GPIO_IRQ_END
+
+#define MOP500_IRQ_END MOP500_NR_IRQS
+
+#if MOP500_IRQ_END > IRQ_BOARD_END
+#undef IRQ_BOARD_END
+#define IRQ_BOARD_END MOP500_IRQ_END
+#endif
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h b/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h
new file mode 100644
index 00000000000..48f9f382b29
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __MACH_IRQS_BOARD_U5500_H
+#define __MACH_IRQS_BOARD_U5500_H
+
+#define AB5500_NR_IRQS (23 * 8)
+#define IRQ_AB5500_BASE IRQ_BOARD_START
+#define IRQ_AB5500_END (IRQ_AB5500_BASE + AB5500_NR_IRQS)
+
+#define U5500_IRQ_END IRQ_AB5500_END
+
+#if IRQ_BOARD_END < U5500_IRQ_END
+#undef IRQ_BOARD_END
+#define IRQ_BOARD_END U5500_IRQ_END
+#endif
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
new file mode 100644
index 00000000000..92b1fbf32bb
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/irqs-db5500.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __MACH_IRQS_DB5500_H
+#define __MACH_IRQS_DB5500_H
+
+#define IRQ_DB5500_MTU0 (IRQ_SHPI_START + 4)
+#define IRQ_DB5500_SPI2 (IRQ_SHPI_START + 6)
+#define IRQ_DB5500_PMU0 (IRQ_SHPI_START + 7)
+#define IRQ_DB5500_SPI0 (IRQ_SHPI_START + 8)
+#define IRQ_DB5500_RTT (IRQ_SHPI_START + 9)
+#define IRQ_DB5500_PKA (IRQ_SHPI_START + 10)
+#define IRQ_DB5500_UART0 (IRQ_SHPI_START + 11)
+#define IRQ_DB5500_I2C3 (IRQ_SHPI_START + 12)
+#define IRQ_DB5500_L2CC (IRQ_SHPI_START + 13)
+#define IRQ_DB5500_MSP0 (IRQ_SHPI_START + 14)
+#define IRQ_DB5500_CRYP1 (IRQ_SHPI_START + 15)
+#define IRQ_DB5500_PMU1 (IRQ_SHPI_START + 16)
+#define IRQ_DB5500_MTU1 (IRQ_SHPI_START + 17)
+#define IRQ_DB5500_RTC (IRQ_SHPI_START + 18)
+#define IRQ_DB5500_UART1 (IRQ_SHPI_START + 19)
+#define IRQ_DB5500_USB_WAKEUP (IRQ_SHPI_START + 20)
+#define IRQ_DB5500_I2C0 (IRQ_SHPI_START + 21)
+#define IRQ_DB5500_I2C1 (IRQ_SHPI_START + 22)
+#define IRQ_DB5500_USBOTG (IRQ_SHPI_START + 23)
+#define IRQ_DB5500_DMA_SECURE (IRQ_SHPI_START + 24)
+#define IRQ_DB5500_DMA (IRQ_SHPI_START + 25)
+#define IRQ_DB5500_UART2 (IRQ_SHPI_START + 26)
+#define IRQ_DB5500_ICN_PMU1 (IRQ_SHPI_START + 27)
+#define IRQ_DB5500_ICN_PMU2 (IRQ_SHPI_START + 28)
+#define IRQ_DB5500_UART3 (IRQ_SHPI_START + 29)
+#define IRQ_DB5500_SPI3 (IRQ_SHPI_START + 30)
+#define IRQ_DB5500_SDMMC4 (IRQ_SHPI_START + 31)
+#define IRQ_DB5500_IRRC (IRQ_SHPI_START + 33)
+#define IRQ_DB5500_IRDA_FT (IRQ_SHPI_START + 34)
+#define IRQ_DB5500_IRDA_SD (IRQ_SHPI_START + 35)
+#define IRQ_DB5500_IRDA_FI (IRQ_SHPI_START + 36)
+#define IRQ_DB5500_IRDA_FD (IRQ_SHPI_START + 37)
+#define IRQ_DB5500_FSMC_CODEREADY (IRQ_SHPI_START + 38)
+#define IRQ_DB5500_FSMC_NANDWAIT (IRQ_SHPI_START + 39)
+#define IRQ_DB5500_AB5500 (IRQ_SHPI_START + 40)
+#define IRQ_DB5500_SDMMC2 (IRQ_SHPI_START + 41)
+#define IRQ_DB5500_SIA (IRQ_SHPI_START + 42)
+#define IRQ_DB5500_SIA2 (IRQ_SHPI_START + 43)
+#define IRQ_DB5500_HVA (IRQ_SHPI_START + 44)
+#define IRQ_DB5500_HVA2 (IRQ_SHPI_START + 45)
+#define IRQ_DB5500_PRCMU0 (IRQ_SHPI_START + 46)
+#define IRQ_DB5500_PRCMU1 (IRQ_SHPI_START + 47)
+#define IRQ_DB5500_DISP (IRQ_SHPI_START + 48)
+#define IRQ_DB5500_SDMMC1 (IRQ_SHPI_START + 50)
+#define IRQ_DB5500_MSP1 (IRQ_SHPI_START + 52)
+#define IRQ_DB5500_KBD (IRQ_SHPI_START + 53)
+#define IRQ_DB5500_I2C2 (IRQ_SHPI_START + 55)
+#define IRQ_DB5500_B2R2 (IRQ_SHPI_START + 56)
+#define IRQ_DB5500_CRYP0 (IRQ_SHPI_START + 57)
+#define IRQ_DB5500_SDMMC3 (IRQ_SHPI_START + 59)
+#define IRQ_DB5500_SDMMC0 (IRQ_SHPI_START + 60)
+#define IRQ_DB5500_HSEM (IRQ_SHPI_START + 61)
+#define IRQ_DB5500_SBAG (IRQ_SHPI_START + 63)
+#define IRQ_DB5500_MODEM (IRQ_SHPI_START + 65)
+#define IRQ_DB5500_SPI1 (IRQ_SHPI_START + 96)
+#define IRQ_DB5500_MSP2 (IRQ_SHPI_START + 98)
+#define IRQ_DB5500_SRPTIMER (IRQ_SHPI_START + 101)
+#define IRQ_DB5500_CTI0 (IRQ_SHPI_START + 108)
+#define IRQ_DB5500_CTI1 (IRQ_SHPI_START + 109)
+#define IRQ_DB5500_ICN_ERR (IRQ_SHPI_START + 110)
+#define IRQ_DB5500_MALI_PPMMU (IRQ_SHPI_START + 112)
+#define IRQ_DB5500_MALI_PP (IRQ_SHPI_START + 113)
+#define IRQ_DB5500_MALI_GPMMU (IRQ_SHPI_START + 114)
+#define IRQ_DB5500_MALI_GP (IRQ_SHPI_START + 115)
+#define IRQ_DB5500_MALI (IRQ_SHPI_START + 116)
+#define IRQ_DB5500_PRCMU_SEM (IRQ_SHPI_START + 118)
+#define IRQ_DB5500_GPIO0 (IRQ_SHPI_START + 119)
+#define IRQ_DB5500_GPIO1 (IRQ_SHPI_START + 120)
+#define IRQ_DB5500_GPIO2 (IRQ_SHPI_START + 121)
+#define IRQ_DB5500_GPIO3 (IRQ_SHPI_START + 122)
+#define IRQ_DB5500_GPIO4 (IRQ_SHPI_START + 123)
+#define IRQ_DB5500_GPIO5 (IRQ_SHPI_START + 124)
+#define IRQ_DB5500_GPIO6 (IRQ_SHPI_START + 125)
+#define IRQ_DB5500_GPIO7 (IRQ_SHPI_START + 126)
+
+#ifdef CONFIG_UX500_SOC_DB5500
+
+/*
+ * After the GPIO ones we reserve a range of IRQ:s in which virtual
+ * IRQ:s representing modem IRQ:s can be allocated
+ */
+#define IRQ_MODEM_EVENTS_BASE IRQ_SOC_START
+#define IRQ_MODEM_EVENTS_NBR 72
+#define IRQ_MODEM_EVENTS_END (IRQ_MODEM_EVENTS_BASE + IRQ_MODEM_EVENTS_NBR)
+
+/* List of virtual IRQ:s that are allocated from the range above */
+#define MBOX_PAIR0_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 43)
+#define MBOX_PAIR1_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 45)
+#define MBOX_PAIR2_VIRT_IRQ (IRQ_MODEM_EVENTS_BASE + 41)
+
+#if IRQ_SOC_END < IRQ_MODEM_EVENTS_END
+#undef IRQ_SOC_END
+#define IRQ_SOC_END IRQ_MODEM_EVENTS_END
+#endif
+
+#endif /* CONFIG_UX500_SOC_DB5500 */
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/irqs-db8500.h b/arch/arm/mach-ux500/include/mach/irqs-db8500.h
new file mode 100644
index 00000000000..29f905fcc1e
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/irqs-db8500.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __MACH_IRQS_DB8500_H
+#define __MACH_IRQS_DB8500_H
+
+#define IRQ_DB8500_MTU0 (IRQ_SHPI_START + 4)
+#define IRQ_DB8500_SPI2 (IRQ_SHPI_START + 6)
+#define IRQ_DB8500_PMU (IRQ_SHPI_START + 7)
+#define IRQ_DB8500_SPI0 (IRQ_SHPI_START + 8)
+#define IRQ_DB8500_RTT (IRQ_SHPI_START + 9)
+#define IRQ_DB8500_PKA (IRQ_SHPI_START + 10)
+#define IRQ_DB8500_UART0 (IRQ_SHPI_START + 11)
+#define IRQ_DB8500_I2C3 (IRQ_SHPI_START + 12)
+#define IRQ_DB8500_L2CC (IRQ_SHPI_START + 13)
+#define IRQ_DB8500_SSP0 (IRQ_SHPI_START + 14)
+#define IRQ_DB8500_CRYP1 (IRQ_SHPI_START + 15)
+#define IRQ_DB8500_MSP1_RX (IRQ_SHPI_START + 16)
+#define IRQ_DB8500_MTU1 (IRQ_SHPI_START + 17)
+#define IRQ_DB8500_RTC (IRQ_SHPI_START + 18)
+#define IRQ_DB8500_UART1 (IRQ_SHPI_START + 19)
+#define IRQ_DB8500_USB_WAKEUP (IRQ_SHPI_START + 20)
+#define IRQ_DB8500_I2C0 (IRQ_SHPI_START + 21)
+#define IRQ_DB8500_I2C1 (IRQ_SHPI_START + 22)
+#define IRQ_DB8500_USBOTG (IRQ_SHPI_START + 23)
+#define IRQ_DB8500_DMA_SECURE (IRQ_SHPI_START + 24)
+#define IRQ_DB8500_DMA (IRQ_SHPI_START + 25)
+#define IRQ_DB8500_UART2 (IRQ_SHPI_START + 26)
+#define IRQ_DB8500_ICN_PMU1 (IRQ_SHPI_START + 27)
+#define IRQ_DB8500_ICN_PMU2 (IRQ_SHPI_START + 28)
+#define IRQ_DB8500_HSIR_EXCEP (IRQ_SHPI_START + 29)
+#define IRQ_DB8500_MSP0 (IRQ_SHPI_START + 31)
+#define IRQ_DB8500_HSIR_CH0_OVRRUN (IRQ_SHPI_START + 32)
+#define IRQ_DB8500_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33)
+#define IRQ_DB8500_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34)
+#define IRQ_DB8500_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35)
+#define IRQ_DB8500_HSIR_CH4_OVRRUN (IRQ_SHPI_START + 36)
+#define IRQ_DB8500_HSIR_CH5_OVRRUN (IRQ_SHPI_START + 37)
+#define IRQ_DB8500_HSIR_CH6_OVRRUN (IRQ_SHPI_START + 38)
+#define IRQ_DB8500_HSIR_CH7_OVRRUN (IRQ_SHPI_START + 39)
+#define IRQ_DB8500_AB8500 (IRQ_SHPI_START + 40)
+#define IRQ_DB8500_SDMMC2 (IRQ_SHPI_START + 41)
+#define IRQ_DB8500_SIA (IRQ_SHPI_START + 42)
+#define IRQ_DB8500_SIA2 (IRQ_SHPI_START + 43)
+#define IRQ_DB8500_SVA (IRQ_SHPI_START + 44)
+#define IRQ_DB8500_SVA2 (IRQ_SHPI_START + 45)
+#define IRQ_DB8500_PRCMU0 (IRQ_SHPI_START + 46)
+#define IRQ_DB8500_PRCMU1 (IRQ_SHPI_START + 47)
+#define IRQ_DB8500_DISP (IRQ_SHPI_START + 48)
+#define IRQ_DB8500_SPI3 (IRQ_SHPI_START + 49)
+#define IRQ_DB8500_SDMMC1 (IRQ_SHPI_START + 50)
+#define IRQ_DB8500_I2C4 (IRQ_SHPI_START + 51)
+#define IRQ_DB8500_SSP1 (IRQ_SHPI_START + 52)
+#define IRQ_DB8500_SKE (IRQ_SHPI_START + 53)
+#define IRQ_DB8500_KB (IRQ_SHPI_START + 54)
+#define IRQ_DB8500_I2C2 (IRQ_SHPI_START + 55)
+#define IRQ_DB8500_B2R2 (IRQ_SHPI_START + 56)
+#define IRQ_DB8500_CRYP0 (IRQ_SHPI_START + 57)
+#define IRQ_DB8500_SDMMC3 (IRQ_SHPI_START + 59)
+#define IRQ_DB8500_SDMMC0 (IRQ_SHPI_START + 60)
+#define IRQ_DB8500_HSEM (IRQ_SHPI_START + 61)
+#define IRQ_DB8500_MSP1 (IRQ_SHPI_START + 62)
+#define IRQ_DB8500_SBAG (IRQ_SHPI_START + 63)
+#define IRQ_DB8500_SPI1 (IRQ_SHPI_START + 96)
+#define IRQ_DB8500_SRPTIMER (IRQ_SHPI_START + 97)
+#define IRQ_DB8500_MSP2 (IRQ_SHPI_START + 98)
+#define IRQ_DB8500_SDMMC4 (IRQ_SHPI_START + 99)
+#define IRQ_DB8500_SDMMC5 (IRQ_SHPI_START + 100)
+#define IRQ_DB8500_HSIRD0 (IRQ_SHPI_START + 104)
+#define IRQ_DB8500_HSIRD1 (IRQ_SHPI_START + 105)
+#define IRQ_DB8500_HSITD0 (IRQ_SHPI_START + 106)
+#define IRQ_DB8500_HSITD1 (IRQ_SHPI_START + 107)
+#define IRQ_DB8500_CTI0 (IRQ_SHPI_START + 108)
+#define IRQ_DB8500_CTI1 (IRQ_SHPI_START + 109)
+#define IRQ_DB8500_ICN_ERR (IRQ_SHPI_START + 110)
+#define IRQ_DB8500_MALI_PPMMU (IRQ_SHPI_START + 112)
+#define IRQ_DB8500_MALI_PP (IRQ_SHPI_START + 113)
+#define IRQ_DB8500_MALI_GPMMU (IRQ_SHPI_START + 114)
+#define IRQ_DB8500_MALI_GP (IRQ_SHPI_START + 115)
+#define IRQ_DB8500_MALI (IRQ_SHPI_START + 116)
+#define IRQ_DB8500_PRCMU_SEM (IRQ_SHPI_START + 118)
+#define IRQ_DB8500_GPIO0 (IRQ_SHPI_START + 119)
+#define IRQ_DB8500_GPIO1 (IRQ_SHPI_START + 120)
+#define IRQ_DB8500_GPIO2 (IRQ_SHPI_START + 121)
+#define IRQ_DB8500_GPIO3 (IRQ_SHPI_START + 122)
+#define IRQ_DB8500_GPIO4 (IRQ_SHPI_START + 123)
+#define IRQ_DB8500_GPIO5 (IRQ_SHPI_START + 124)
+#define IRQ_DB8500_GPIO6 (IRQ_SHPI_START + 125)
+#define IRQ_DB8500_GPIO7 (IRQ_SHPI_START + 126)
+#define IRQ_DB8500_GPIO8 (IRQ_SHPI_START + 127)
+
+#define IRQ_CA_WAKE_REQ_ED (IRQ_SHPI_START + 71)
+#define IRQ_AC_READ_NOTIFICATION_0_ED (IRQ_SHPI_START + 66)
+#define IRQ_AC_READ_NOTIFICATION_1_ED (IRQ_SHPI_START + 64)
+#define IRQ_CA_MSG_PEND_NOTIFICATION_0_ED (IRQ_SHPI_START + 67)
+#define IRQ_CA_MSG_PEND_NOTIFICATION_1_ED (IRQ_SHPI_START + 65)
+
+#define IRQ_CA_WAKE_REQ_V1 (IRQ_SHPI_START + 83)
+#define IRQ_AC_READ_NOTIFICATION_0_V1 (IRQ_SHPI_START + 78)
+#define IRQ_AC_READ_NOTIFICATION_1_V1 (IRQ_SHPI_START + 76)
+#define IRQ_CA_MSG_PEND_NOTIFICATION_0_V1 (IRQ_SHPI_START + 79)
+#define IRQ_CA_MSG_PEND_NOTIFICATION_1_V1 (IRQ_SHPI_START + 77)
+
+#ifdef CONFIG_UX500_SOC_DB8500
+
+/* Virtual interrupts corresponding to the PRCMU wakeups. */
+#define IRQ_PRCMU_BASE IRQ_SOC_START
+#define NUM_PRCMU_WAKEUPS (IRQ_PRCMU_END - IRQ_PRCMU_BASE)
+
+#define IRQ_PRCMU_RTC (IRQ_PRCMU_BASE)
+#define IRQ_PRCMU_RTT0 (IRQ_PRCMU_BASE + 1)
+#define IRQ_PRCMU_RTT1 (IRQ_PRCMU_BASE + 2)
+#define IRQ_PRCMU_HSI0 (IRQ_PRCMU_BASE + 3)
+#define IRQ_PRCMU_HSI1 (IRQ_PRCMU_BASE + 4)
+#define IRQ_PRCMU_CA_WAKE (IRQ_PRCMU_BASE + 5)
+#define IRQ_PRCMU_USB (IRQ_PRCMU_BASE + 6)
+#define IRQ_PRCMU_ABB (IRQ_PRCMU_BASE + 7)
+#define IRQ_PRCMU_ABB_FIFO (IRQ_PRCMU_BASE + 8)
+#define IRQ_PRCMU_ARM (IRQ_PRCMU_BASE + 9)
+#define IRQ_PRCMU_MODEM_SW_RESET_REQ (IRQ_PRCMU_BASE + 10)
+#define IRQ_PRCMU_GPIO0 (IRQ_PRCMU_BASE + 11)
+#define IRQ_PRCMU_GPIO1 (IRQ_PRCMU_BASE + 12)
+#define IRQ_PRCMU_GPIO2 (IRQ_PRCMU_BASE + 13)
+#define IRQ_PRCMU_GPIO3 (IRQ_PRCMU_BASE + 14)
+#define IRQ_PRCMU_GPIO4 (IRQ_PRCMU_BASE + 15)
+#define IRQ_PRCMU_GPIO5 (IRQ_PRCMU_BASE + 16)
+#define IRQ_PRCMU_GPIO6 (IRQ_PRCMU_BASE + 17)
+#define IRQ_PRCMU_GPIO7 (IRQ_PRCMU_BASE + 18)
+#define IRQ_PRCMU_GPIO8 (IRQ_PRCMU_BASE + 19)
+#define IRQ_PRCMU_CA_SLEEP (IRQ_PRCMU_BASE + 20)
+#define IRQ_PRCMU_HOTMON_LOW (IRQ_PRCMU_BASE + 21)
+#define IRQ_PRCMU_HOTMON_HIGH (IRQ_PRCMU_BASE + 22)
+#define IRQ_PRCMU_END (IRQ_PRCMU_BASE + 23)
+
+#if IRQ_SOC_END < IRQ_PRCMU_END
+#undef IRQ_SOC_END
+#define IRQ_SOC_END IRQ_PRCMU_END
+#endif
+
+#endif /* CONFIG_UX500_SOC_DB8500 */
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index 7970684b1d0..6f8f95dbd04 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -16,63 +16,47 @@
#define IRQ_LOCALWDOG 30
/* Shared Peripheral Interrupt (SHPI) */
-#define IRQ_SHPI_START 32
+#define IRQ_SPI_START 32
+#define IRQ_SHPI_START IRQ_SPI_START
-/* Interrupt numbers generic for shared peripheral */
-#define IRQ_MTU0 (IRQ_SHPI_START + 4)
-#define IRQ_SPI2 (IRQ_SHPI_START + 6)
-#define IRQ_SPI0 (IRQ_SHPI_START + 8)
-#define IRQ_UART0 (IRQ_SHPI_START + 11)
-#define IRQ_I2C3 (IRQ_SHPI_START + 12)
-#define IRQ_SSP0 (IRQ_SHPI_START + 14)
-#define IRQ_MTU1 (IRQ_SHPI_START + 17)
-#define IRQ_RTC_RTT (IRQ_SHPI_START + 18)
-#define IRQ_UART1 (IRQ_SHPI_START + 19)
-#define IRQ_I2C0 (IRQ_SHPI_START + 21)
-#define IRQ_I2C1 (IRQ_SHPI_START + 22)
-#define IRQ_USBOTG (IRQ_SHPI_START + 23)
-#define IRQ_DMA (IRQ_SHPI_START + 25)
-#define IRQ_UART2 (IRQ_SHPI_START + 26)
-#define IRQ_HSIR_EXCEP (IRQ_SHPI_START + 29)
-#define IRQ_MSP0 (IRQ_SHPI_START + 31)
-#define IRQ_HSIR_CH0_OVRRUN (IRQ_SHPI_START + 32)
-#define IRQ_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33)
-#define IRQ_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34)
-#define IRQ_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35)
-#define IRQ_AB4500 (IRQ_SHPI_START + 40)
-#define IRQ_DISP (IRQ_SHPI_START + 48)
-#define IRQ_SiPI3 (IRQ_SHPI_START + 49)
-#define IRQ_I2C4 (IRQ_SHPI_START + 51)
-#define IRQ_SSP1 (IRQ_SHPI_START + 52)
-#define IRQ_I2C2 (IRQ_SHPI_START + 55)
-#define IRQ_SDMMC0 (IRQ_SHPI_START + 60)
-#define IRQ_MSP1 (IRQ_SHPI_START + 62)
-#define IRQ_SPI1 (IRQ_SHPI_START + 96)
-#define IRQ_MSP2 (IRQ_SHPI_START + 98)
-#define IRQ_SDMMC4 (IRQ_SHPI_START + 99)
-#define IRQ_HSIRD0 (IRQ_SHPI_START + 104)
-#define IRQ_HSIRD1 (IRQ_SHPI_START + 105)
-#define IRQ_HSITD0 (IRQ_SHPI_START + 106)
-#define IRQ_HSITD1 (IRQ_SHPI_START + 107)
-#define IRQ_GPIO0 (IRQ_SHPI_START + 119)
-#define IRQ_GPIO1 (IRQ_SHPI_START + 120)
-#define IRQ_GPIO2 (IRQ_SHPI_START + 121)
-#define IRQ_GPIO3 (IRQ_SHPI_START + 122)
-#define IRQ_GPIO4 (IRQ_SHPI_START + 123)
-#define IRQ_GPIO5 (IRQ_SHPI_START + 124)
-#define IRQ_GPIO6 (IRQ_SHPI_START + 125)
-#define IRQ_GPIO7 (IRQ_SHPI_START + 126)
-#define IRQ_GPIO8 (IRQ_SHPI_START + 127)
-
-/* There are 128 shared peripheral interrupts assigned to
- * INTID[160:32]. The first 32 interrupts are reserved.
+/*
+ * MTU0 preserved for now until plat-nomadik is taught not to use it. Don't
+ * add any other IRQs here, use the irqs-dbx500.h files.
*/
-#define U8500_SOC_NR_IRQS 161
+#define IRQ_MTU0 (IRQ_SPI_START + 4)
+
+#define DBX500_NR_INTERNAL_IRQS 160
/* After chip-specific IRQ numbers we have the GPIO ones */
-#define NOMADIK_NR_GPIO 288
-#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + U8500_SOC_NR_IRQS)
-#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - U8500_SOC_NR_IRQS)
-#define NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
+#define U8500_NR_GPIO 268
+#define GPIO_TO_IRQ(gpio) (gpio + DBX500_NR_INTERNAL_IRQS)
+#define IRQ_TO_GPIO(irq) (irq - DBX500_NR_INTERNAL_IRQS)
+
+#define NOMADIK_GPIO_TO_IRQ GPIO_TO_IRQ
+#define NOMADIK_IRQ_TO_GPIO IRQ_TO_GPIO
+#define IRQ_GPIO_END NOMADIK_GPIO_TO_IRQ(U8500_NR_GPIO)
+
+#define IRQ_SOC_START IRQ_GPIO_END
+/* This will be overridden by SoC-specific irq headers */
+#define IRQ_SOC_END IRQ_SOC_START
+
+#include <mach/irqs-db5500.h>
+#include <mach/irqs-db8500.h>
+
+#define IRQ_BOARD_START IRQ_SOC_END
+/* This will be overridden by board-specific irq headers */
+#define IRQ_BOARD_END IRQ_BOARD_START
+
+#if defined(CONFIG_MACH_U8500_MOP) \
+ || defined(CONFIG_MACH_U8500_PDP) \
+ || defined(CONFIG_MACH_U8500_SNOWBALL)
+#include <mach/irqs-board-mop500.h>
+#endif
+
+#if defined(CONFIG_MACH_B5500)
+#include <mach/irqs-board-u5500.h>
+#endif
+
+#define NR_IRQS IRQ_BOARD_END
-#endif /*ASM_ARCH_IRQS_H*/
+#endif /* ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-ux500/include/mach/isa_ioctl.h b/arch/arm/mach-ux500/include/mach/isa_ioctl.h
new file mode 100644
index 00000000000..b05726f8c3c
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/isa_ioctl.h
@@ -0,0 +1,51 @@
+/*---------------------------------------------------------------------------*/
+/* Copyright ST Ericsson, 2009. */
+/* 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.1 of the License, or */
+/* (at your option) any later version. */
+/* */
+/* This program is distributed in the hope that it will be useful, but */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */
+/* See the GNU General Public License for more details. */
+/* */
+/* You should have received a copy of the GNU General Public License */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+/*---------------------------------------------------------------------------*/
+#ifndef __MODEM_IPC_INCLUDED
+#define __MODEM_IPC_INCLUDED
+
+#define DLP_IOCTL_MAGIC_NUMBER 'M'
+#define COMMON_BUFFER_SIZE (1024*1024)
+
+/**
+DLP Message Structure for Userland
+*/
+struct t_dlp_message{
+ unsigned int offset;
+ unsigned int size;
+};
+
+/**
+mmap constants.
+*/
+enum t_dlp_mmap_params {
+ MMAP_DLQUEUE,
+ MMAP_ULQUEUE
+};
+
+/**
+DLP IOCTLs for Userland
+*/
+#define DLP_IOC_ALLOCATE_BUFFER \
+ _IOWR(DLP_IOCTL_MAGIC_NUMBER, 0, struct t_dlp_message *)
+#define DLP_IOC_DEALLOCATE_BUFFER \
+ _IOWR(DLP_IOCTL_MAGIC_NUMBER, 1, struct t_dlp_message *)
+#define DLP_IOC_GET_MESSAGE \
+ _IOWR(DLP_IOCTL_MAGIC_NUMBER, 2, struct t_dlp_message *)
+#define DLP_IOC_PUT_MESSAGE \
+ _IOWR(DLP_IOCTL_MAGIC_NUMBER, 3, struct t_dlp_message *)
+
+#endif /*__MODEM_IPC_INCLUDED*/
+
diff --git a/arch/arm/mach-ux500/include/mach/kpd.h b/arch/arm/mach-ux500/include/mach/kpd.h
new file mode 100644
index 00000000000..ffff8eea193
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/kpd.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright STMicroelectronics, 2009.
+ * 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
+ */
+
+#ifndef __U8500_KPD_H
+#define __U8500_KPD_H
+
+#ifndef CONFIG_AUTOSCAN_ENABLED
+#define CONFIG_AUTOSCAN_ENABLED 1
+#endif
+#include <mach/hardware.h>
+#include <linux/clk.h>
+
+#define MAX_KPROW 8
+#define MAX_KPCOL 8
+#define MAX_KEYS (MAX_KPROW * MAX_KPCOL)
+/*keypad related Constants*/
+#define KEYPAD_RELEASE_PERIOD 11 /*11 msec, repeate key scan time */
+#define KEYPAD_SCAN_PERIOD 4 /*4msec for new keypress */
+#define KEYPAD_STATE_DEFAULT 0
+#define KEYPAD_STATE_PRESSED 1
+#define KEYPAD_STATE_PRESSACK 2
+#define KEYPAD_STATE_RELEASED 3
+#define KEYPAD_STATE_RELEASEACK 2
+
+#define KPINTR_LKBIT 0 /*bit used for interrupt locking */
+
+struct keypad_t;
+/**
+ * struct keypad_device - Device data structure for platform specific data
+ * @init: pointer to keypad init function
+ * @exit: pointer to keypad deinitialisation function
+ * @autoscan_check: pointer to read autoscan status function
+ * currently
+ * @autoscan_disable: pointer to autoscan feature disable function,
+ * not used currently
+ * @autoscan_results: pointer to read autoscan results function
+ * @autoscan_en: pointer to enable autoscan feature function
+ * currently
+ * @irqen: pointer to enable irq function
+ * @irqdis: pointer to disable irq function
+ * @kcode_tbl: lookup table for keycodes
+ * @krow: mask for available rows, value is 0xFF
+ * @kcol: mask for available columns, value is 0xFF
+ * @irqdis_int: pointer to disable irq function, to be called from ISR
+ * @debounce_period: platform specific debounce time, can be fine tuned later
+ * @irqtype: type of interrupt
+ * @irq: irq no,
+ * @int_status: interrupt status
+ * @int_line_behaviour: dynamis interrupt line behaviour
+ * @enable_wakeup: specifies if keypad event can wake up system from sleep
+ */
+struct keypad_device {
+ int (*init)(struct keypad_t *kp);
+ int (*exit)(struct keypad_t *kp);
+ int (*autoscan_check)(void);
+ void (*autoscan_disable)(void);
+ int (*autoscan_results)(struct keypad_t *kp);
+ void (*autoscan_en)(void);
+ int (*irqen)(struct keypad_t *kp);
+ int (*irqdis)(struct keypad_t *kp);
+ u8 *kcode_tbl;
+ u8 krow;
+ u8 kcol;
+ int (*irqdis_int)(struct keypad_t *kp);
+ u8 debounce_period;
+ unsigned long irqtype;
+ u8 irq;
+ u8 int_status;
+ u8 int_line_behaviour;
+ bool enable_wakeup;
+};
+/**
+ * struct keypad_t - keypad data structure used internally by keypad driver
+ * @irq: irq no
+ * @mode: 0 for interrupt mode, 1 for polling mode
+ * @ske_regs: ske regsiters base address
+ * @cr_lock: spinlock variable
+ * @key_state: array for saving keystates
+ * @lockbits: used for synchronisation in ISR
+ * @inp_dev: pointer to input device object
+ * @kscan_work: work queue
+ * @board: keypad platform device
+ * @key_cnt: count the keys pressed
+ * @clk: clock structure pointer
+ */
+struct keypad_t {
+ int irq;
+ int mode;
+ void __iomem *ske_regs;
+ int key_state[MAX_KPROW][MAX_KPCOL];
+ unsigned long lockbits;
+ spinlock_t cr_lock;
+ struct input_dev *inp_dev;
+ struct delayed_work kscan_work;
+ struct keypad_device *board;
+ int key_cnt;
+ struct clk *clk;
+};
+/**
+ * enum kp_int_status - enum for INTR status
+ * @KP_INT_DISABLED: interrupt disabled
+ * @KP_INT_ENABLED: interrupt enabled
+ */
+enum kp_int_status {
+ KP_INT_DISABLED = 0,
+ KP_INT_ENABLED,
+};
+/**
+ *enum kp_int_line_behaviour - enum for kp_int_line dynamic status
+ * @INT_LINE_NOTSET: IRQ not asserted
+ * @INT_LINE_SET: IRQ asserted
+ */
+enum kp_int_line_behaviour {
+ INT_LINE_NOTSET = 0,
+ INT_LINE_SET,
+};
+#endif /*__U8500_KPD_H*/
diff --git a/arch/arm/mach-ux500/include/mach/mbox.h b/arch/arm/mach-ux500/include/mach/mbox.h
new file mode 100644
index 00000000000..7f9da4d2fbd
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/mbox.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __INC_STE_MBOX_H
+#define __INC_STE_MBOX_H
+
+#define MBOX_BUF_SIZE 16
+#define MBOX_NAME_SIZE 8
+
+/**
+ * mbox_recv_cb_t - Definition of the mailbox callback.
+ * @mbox_msg: The mailbox message.
+ * @priv: The clients private data as specified in the call to mbox_setup.
+ *
+ * This function will be called upon reception of new mailbox messages.
+ */
+typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv);
+
+/**
+ * struct mbox - Mailbox instance struct
+ * @list: Linked list head.
+ * @pdev: Pointer to device struct.
+ * @cb: Callback function. Will be called
+ * when new data is received.
+ * @client_data: Clients private data. Will be sent back
+ * in the callback function.
+ * @virtbase_peer: Virtual address for outgoing mailbox.
+ * @virtbase_local: Virtual address for incoming mailbox.
+ * @buffer: Then internal queue for outgoing messages.
+ * @name: Name of this mailbox.
+ * @buffer_available: Completion variable to achieve "blocking send".
+ * This variable will be signaled when there is
+ * internal buffer space available.
+ * @client_blocked: To keep track if any client is currently
+ * blocked.
+ * @lock: Spinlock to protect this mailbox instance.
+ * @write_index: Index in internal buffer to write to.
+ * @read_index: Index in internal buffer to read from.
+ * @allocated: Indicates whether this particular mailbox
+ * id has been allocated by someone.
+ */
+struct mbox {
+ struct list_head list;
+ struct platform_device *pdev;
+ mbox_recv_cb_t *cb;
+ void *client_data;
+ void __iomem *virtbase_peer;
+ void __iomem *virtbase_local;
+ u32 buffer[MBOX_BUF_SIZE];
+ char name[MBOX_NAME_SIZE];
+ struct completion buffer_available;
+ u8 client_blocked;
+ spinlock_t lock;
+ u8 write_index;
+ u8 read_index;
+ bool allocated;
+};
+
+/**
+ * mbox_setup - Set up a mailbox and return its instance.
+ * @mbox_id: The ID number of the mailbox. 0 or 1 for modem CPU,
+ * 2 for modem DSP.
+ * @mbox_cb: Pointer to the callback function to be called when a new message
+ * is received.
+ * @priv: Client user data which will be returned in the callback.
+ *
+ * Returns a mailbox instance to be specified in subsequent calls to mbox_send.
+ */
+struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv);
+
+/**
+ * mbox_send - Send a mailbox message.
+ * @mbox: Mailbox instance (returned by mbox_setup)
+ * @mbox_msg: The mailbox message to send.
+ * @block: Specifies whether this call will block until send is possible,
+ * or return an error if the mailbox buffer is full.
+ *
+ * Returns 0 on success or a negative error code on error. -ENOMEM indicates
+ * that the internal buffer is full and you have to try again later (or
+ * specify "block" in order to block until send is possible).
+ */
+int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block);
+
+#endif /*INC_STE_MBOX_H*/
diff --git a/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h b/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h
new file mode 100644
index 00000000000..829b1708bf1
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ * Author: Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com> for ST-Ericsson.
+ * Bibek Basu <bibek.basu@stericsson.com>
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#ifndef __INC_MBOX_CHANNELS_H
+#define __INC_MBOX_CHANNELS_H
+
+/* Maximum number of datawords which can be send in one PDU */
+#define MAILBOX_NR_OF_DATAWORDS 3
+
+/**
+ * mbox_channel_cb_t - Definition of the mailbox channel callback.
+ * @data: Pointer to the data.
+ * @length: Length of the data.
+ * @priv: The client's private data.
+ *
+ * This function will be called upon reception of complete mbox channel PDU
+ * or after completion of send operation.
+ */
+typedef void mbox_channel_cb_t (u32 *data, u32 length, void *priv);
+
+/**
+ * mbox_channel_msg - Definition of mbox channel message
+ * @channel: Channel number.
+ * @data: Pointer to data to be sent.
+ * @length: Length of data to be sent.
+ * @cb: Pointer to the callback function to be called when send
+ * operation will be finished.
+ * @priv: The client's private data.
+ *
+ * This structure describes mailbox channel message.
+ */
+struct mbox_channel_msg {
+ u16 channel;
+ u32 *data;
+ u8 length;
+ mbox_channel_cb_t *cb;
+ void *priv;
+};
+
+/** mbox_channel_register - Set up a given mailbox channel.
+ * @channel: Mailbox channel number.
+ * @cb: Pointer to the callback function to be called when a new message
+ * is received.
+ * @priv: Client user data which will be returned in the callback.
+ *
+ * Returns 0 on success or a negative error code on error.
+ */
+int mbox_channel_register(u16 channel, mbox_channel_cb_t *cb, void *priv);
+
+/**
+ * mbox_channel_send - Send data on given mailbox channel.
+ * @msg: Mailbox channel message to be sent.
+ *
+ * Returns 0 on success or a negative error code on error.
+ */
+int mbox_channel_send(struct mbox_channel_msg *msg);
+
+/**
+ * mbox_channel_revoke_messages - Revoke messages on given mailbox channel.
+ * @channel: Mailbox channel number.
+ *
+ * Returns 0 on success or a negative error code on error.
+ */
+int mbox_channel_revoke_messages(u16 channel);
+
+#endif /*INC_STE_MBOX_H*/
+
diff --git a/arch/arm/mach-ux500/include/mach/memory.h b/arch/arm/mach-ux500/include/mach/memory.h
index 510571a59e2..e3def580cb9 100644
--- a/arch/arm/mach-ux500/include/mach/memory.h
+++ b/arch/arm/mach-ux500/include/mach/memory.h
@@ -15,4 +15,12 @@
#define PHYS_OFFSET UL(0x00000000)
#define BUS_OFFSET UL(0x00000000)
+#ifdef CONFIG_UX500_SOC_DB8500
+/*
+ * STE NMF CM driver only used on the U8500 allocate using dma_alloc_coherent:
+ * 8M for SIA and SVA data + 2M for SIA code + 2M for SVA code
+ */
+#define CONSISTENT_DMA_SIZE SZ_16M
+#endif
+
#endif
diff --git a/arch/arm/mach-ux500/include/mach/mloader-dbx500.h b/arch/arm/mach-ux500/include/mach/mloader-dbx500.h
new file mode 100644
index 00000000000..68fa55a3f53
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/mloader-dbx500.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Ludovic Barre <ludovic.barre@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef _MLOADER_UX500_H_
+#define _MLOADER_UX500_H_
+
+/**
+ * struct dbx500_ml_area - data structure for modem memory areas description
+ * @name: name of the area
+ * @start: start address of the area
+ * @size: size of the area
+ */
+struct dbx500_ml_area {
+ const char *name;
+ u32 start;
+ u32 size;
+};
+
+/**
+ * struct dbx500_ml_fw - data stucture for modem firmwares description
+ * @name: firmware name
+ * @area: area where firmware is uploaded
+ * @offset: offset in the area where firmware is uploaded
+ */
+struct dbx500_ml_fw {
+ const char *name;
+ struct dbx500_ml_area *area;
+ u32 offset;
+};
+
+/**
+ * struct dbx500_mloader_pdata - data structure for platform specific data
+ * @fws: pointer on firmwares table
+ * @nr_fws: number of firmwares
+ * @areas: pointer on areas table
+ * @nr_areas: number of areas
+ */
+struct dbx500_mloader_pdata {
+ struct dbx500_ml_fw *fws;
+ int nr_fws;
+ struct dbx500_ml_area *areas;
+ int nr_areas;
+};
+
+#endif /* _MLOADER_UX500_H_ */
diff --git a/arch/arm/mach-ux500/include/mach/msp.h b/arch/arm/mach-ux500/include/mach/msp.h
new file mode 100644
index 00000000000..aecca3a59a3
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/msp.h
@@ -0,0 +1,970 @@
+/*
+ * Copyright (c) 2009 STMicroelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+
+#ifndef _STM_MSP_HEADER
+#define _STM_MSP_HEADER
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/semaphore.h>
+#include <linux/dmaengine.h>
+#include <linux/i2s/i2s.h>
+#include <linux/irqreturn.h>
+#include <linux/bitops.h>
+#include <plat/ste_dma40.h>
+#include <mach/gpio.h>
+#include <linux/spi/stm_msp.h>
+
+/* Generic config struct. Use the actual values defined below for global
+ * control register
+ */
+
+enum msp_state {
+ MSP_STATE_IDLE = 0,
+ MSP_STATE_CONFIGURED = 1,
+ MSP_STATE_RUN = 2,
+};
+
+enum msp_rx_comparison_enable_mode {
+ MSP_COMPARISON_DISABLED = 0,
+ MSP_COMPARISON_NONEQUAL_ENABLED = 2,
+ MSP_COMPARISON_EQUAL_ENABLED = 3
+};
+
+#define RMCEN_BIT 0
+#define RMCSF_BIT 1
+#define RCMPM_BIT 3
+#define TMCEN_BIT 5
+#define TNCSF_BIT 6
+
+struct msp_multichannel_config {
+ bool rx_multichannel_enable;
+ bool tx_multichannel_enable;
+ enum msp_rx_comparison_enable_mode rx_comparison_enable_mode;
+ u8 padding;
+ u32 comparison_value;
+ u32 comparison_mask;
+ u32 rx_channel_0_enable;
+ u32 rx_channel_1_enable;
+ u32 rx_channel_2_enable;
+ u32 rx_channel_3_enable;
+ u32 tx_channel_0_enable;
+ u32 tx_channel_1_enable;
+ u32 tx_channel_2_enable;
+ u32 tx_channel_3_enable;
+};
+
+/**
+ * struct msp_protocol_desc- MSP Protocol desc structure per MSP.
+ * @rx_phase_mode: rx_phase_mode whether single or dual.
+ * @tx_phase_mode: tx_phase_mode whether single or dual.
+ * @rx_phase2_start_mode: rx_phase2_start_mode whether imediate or after
+ * some delay.
+ * @tx_phase2_start_mode: tx_phase2_start_mode whether imediate or after
+ * some delay.
+ * @rx_bit_transfer_format: MSP or LSB.
+ * @tx_bit_transfer_format: MSP or LSB.
+ * @rx_frame_length_1: Frame1 length 1,2,3..
+ * @rx_frame_length_2: Frame2 length 1,2,3..
+ * @tx_frame_length_1: Frame1 length 1,2,3..
+ * @tx_frame_length_2: Frame2 length 1,2,3..
+ * @rx_element_length_1: Element1 length 1,2,...
+ * @rx_element_length_2: Element2 length 1,2,...
+ * @tx_element_length_1: Element1 length 1,2,...
+ * @tx_element_length_2: Element2 length 1,2,...
+ * @rx_data_delay: Delay in clk cycle after frame sync
+ * @tx_data_delay: Delay in clk cycle after frame sync
+ * @rx_clock_pol: Rxpol whether rising or falling.It indicates pol of bit clock.
+ * @tx_clock_pol: Txpol whether rising or falling.It indicates pol of bit clock.
+ * @rx_frame_sync_pol: Frame sync pol whether rising or Falling.
+ * @tx_frame_sync_pol: Frame sync pol whether rising or Falling.
+ * @rx_half_word_swap: Word swap half word, full word.
+ * @tx_half_word_swap: Word swap half word, full word.
+ * @compression_mode: Compression mode whether Alaw or Ulaw or disabled.
+ * @expansion_mode: Compression mode whether Alaw or Ulaw or disabled.
+ * @spi_clk_mode: Spi clock mode to be enabled or not.
+ * @spi_burst_mode: Spi burst mode to be enabled or not.
+ * @frame_sync_ignore: Frame sync to be ignored or not. Ignore in case of Audio
+ * codec acting as Master.
+ * @frame_period: Frame period (clk cycles) after which new frame sync occurs.
+ * @frame_width: Frame width (clk cycles) after which frame sycn changes state.
+ * @total_clocks_for_one_frame: No. of clk cycles per frame.
+ *
+ * Main Msp protocol descriptor data structure to be used to store various info
+ * in transmit or recevie configuration registers of an MSP.
+ */
+
+struct msp_protocol_desc {
+ u32 rx_phase_mode;
+ u32 tx_phase_mode;
+ u32 rx_phase2_start_mode;
+ u32 tx_phase2_start_mode;
+ u32 rx_bit_transfer_format;
+ u32 tx_bit_transfer_format;
+ u32 rx_frame_length_1;
+ u32 rx_frame_length_2;
+ u32 tx_frame_length_1;
+ u32 tx_frame_length_2;
+ u32 rx_element_length_1;
+ u32 rx_element_length_2;
+ u32 tx_element_length_1;
+ u32 tx_element_length_2;
+ u32 rx_data_delay;
+ u32 tx_data_delay;
+ u32 rx_clock_pol;
+ u32 tx_clock_pol;
+ u32 rx_frame_sync_pol;
+ u32 tx_frame_sync_pol;
+ u32 rx_half_word_swap;
+ u32 tx_half_word_swap;
+ u32 compression_mode;
+ u32 expansion_mode;
+ u32 spi_clk_mode;
+ u32 spi_burst_mode;
+ u32 frame_sync_ignore;
+ u32 frame_period;
+ u32 frame_width;
+ u32 total_clocks_for_one_frame;
+};
+
+/**
+ * struct trans_data - MSP transfer data structure used during xfer.
+ * @message: i2s message.
+ * @msp: msp structure.
+ * @tx_handler: callback handler for transmit path.
+ * @rx_handler: callback handler for receive path.
+ * @tx_callback_data: callback data for transmit.
+ * @rx_callback_data: callback data for receive.
+ *
+ */
+struct trans_data {
+ struct i2s_message message;
+ struct msp *msp;
+ void (*tx_handler) (void *data);
+ void (*rx_handler) (void *data);
+ void *tx_callback_data;
+ void *rx_callback_data;
+};
+
+/**
+ * struct msp_config- MSP configuration structure used by i2s client.
+ * @input_clock_freq: Input clock frequency default is 48MHz.
+ * @rx_clock_sel: Receive clock selection (Provided by Sample Gen or external
+ * source).
+ * @tx_clock_sel: Transmit clock selection (Provided by Sample Gen or external.
+ * source).
+ * @srg_clock_sel: APB clock or clock dervied from Slave (Audio codec).
+ * @rx_frame_sync_pol: Receive frame sync polarity.
+ * @tx_frame_sync_pol: Transmit frame sync polarity.
+ * @rx_frame_sync_sel: Rx frame sync signal is provided by which source.
+ * External source or by frame generator logic.
+ * @tx_frame_sync_sel: Tx frame sync signal is provided by which source.
+ * External source or by frame generator logic.
+ * @rx_fifo_config: Receive fifo enable or not.
+ * @tx_fifo_config: Transmit fifo enable or not.
+ * @spi_clk_mode: In case of SPI protocol spi modes: Normal, Zero delay or
+ * half cycle delay.
+ * @spi_burst_mode: Spi burst mode is enabled or not.
+ * @loopback_enable: Loopback mode.
+ * @tx_data_enable: Transmit extra delay enable.
+ * @default_protocol_desc: Flag to indicate client defined protocol desc or
+ * statically defined in msp.h.
+ * @protocol_desc: Protocol desc structure filled by i2s client driver.
+ * In case client defined default_prtocol_desc as 0.
+ * @multichannel_configured: multichannel configuration structure.
+ * @multichannel_config: multichannel is enabled or not.
+ * @direction: Transmit, Receive or Both.
+ * @work_mode: Dma, Polling or Interrupt.
+ * @protocol: I2S, PCM, etc.
+ * @frame_freq: Sampling freq at which data is sampled.
+ * @frame_size: size of element.
+ * @data_size: data size which defines the format in which data is written on
+ * transmit or receive fifo. Only three modes 8,16,32 are supported.
+ * @def_elem_len: Flag to indicate whether default element length is to be used
+ * or should be changed acc to data size defined by user at run time.
+ * @iodelay: value for the MSP_IODLY register
+ * @handler: callback handler in case of interrupt or dma.
+ * @tx_callback_data: Callback data for transmit.
+ * @rx_callback_data: Callback data for receive.
+ *
+ * Main Msp configuration data structure used by i2s client driver to fill
+ * various info like data size, frequency etc.
+ */
+struct msp_config {
+ unsigned int input_clock_freq;
+ unsigned int rx_clock_sel;
+ unsigned int tx_clock_sel;
+ unsigned int srg_clock_sel;
+ unsigned int rx_frame_sync_pol;
+ unsigned int tx_frame_sync_pol;
+ unsigned int rx_frame_sync_sel;
+ unsigned int tx_frame_sync_sel;
+ unsigned int rx_fifo_config;
+ unsigned int tx_fifo_config;
+ unsigned int spi_clk_mode;
+ unsigned int spi_burst_mode;
+ unsigned int loopback_enable;
+ unsigned int tx_data_enable;
+ unsigned int default_protocol_desc;
+ struct msp_protocol_desc protocol_desc;
+ int multichannel_configured;
+ struct msp_multichannel_config multichannel_config;
+ unsigned int direction;
+ unsigned int work_mode;
+ unsigned int protocol;
+ unsigned int frame_freq;
+ unsigned int frame_size;
+ enum msp_data_size data_size;
+ unsigned int def_elem_len;
+ unsigned int iodelay;
+ void (*handler) (void *data);
+ void *tx_callback_data;
+ void *rx_callback_data;
+
+};
+
+/*** Protocols ***/
+enum msp_protocol {
+ MSP_I2S_PROTOCOL,
+ MSP_PCM_PROTOCOL,
+ MSP_PCM_COMPAND_PROTOCOL,
+ MSP_AC97_PROTOCOL,
+ MSP_MASTER_SPI_PROTOCOL,
+ MSP_SLAVE_SPI_PROTOCOL,
+ MSP_INVALID_PROTOCOL
+};
+
+/*** Sample Frequencies ***/
+/* These are no longer required, frequencies in Hz can be used directly */
+enum msp_sample_freq {
+ MSP_SAMPLE_FREQ_NOT_SUPPORTED = -1,
+ MSP_SAMPLE_FREQ_8KHZ = 8000,
+ MSP_SAMPLE_FREQ_12KHZ = 12000,
+ MSP_SAMPLE_FREQ_16KHZ = 16000,
+ MSP_SAMPLE_FREQ_24KHZ = 24000,
+ MSP_SAMPLE_FREQ_32KHZ = 32000,
+ MSP_SAMPLE_FREQ_44KHZ = 44000,
+ MSP_SAMPLE_FREQ_48KHZ = 48000,
+ MSP_SAMPLE_FREQ_64KHZ = 64000,
+ MSP_SAMPLE_FREQ_88KHZ = 88000,
+ MSP_SAMPLE_FREQ_96KHZ = 96000,
+ MSP_SAMPLE_FREQ_22KHZ = 22000,
+ MSP_SAMPLE_FREQ_11KHZ = 11000
+};
+
+/*** Input Frequencies ***/
+/* These are no longer required, frequencies in Hz can be used directly */
+enum msp_in_clock_freq {
+ MSP_INPUT_FREQ_1MHZ = 1000,
+ MSP_INPUT_FREQ_2MHZ = 2000,
+ MSP_INPUT_FREQ_3MHZ = 3000,
+ MSP_INPUT_FREQ_4MHZ = 4000,
+ MSP_INPUT_FREQ_5MHZ = 5000,
+ MSP_INPUT_FREQ_6MHZ = 6000,
+ MSP_INPUT_FREQ_8MHZ = 8000,
+ MSP_INPUT_FREQ_11MHZ = 11000,
+ MSP_INPUT_FREQ_12MHZ = 12000,
+ MSP_INPUT_FREQ_16MHZ = 16000,
+ MSP_INPUT_FREQ_22MHZ = 22000,
+ MSP_INPUT_FREQ_24MHZ = 24000,
+ MSP_INPUT_FREQ_48MHZ = 48000
+};
+
+#define MSP_INPUT_FREQ_APB 48000000
+
+/*** Stereo mode. Used for APB data accesses as 16 bits accesses (mono),
+ * 32 bits accesses (stereo).
+ ***/
+enum msp_stereo_mode {
+ MSP_MONO,
+ MSP_STEREO
+};
+
+/* Direction (Transmit/Receive mode) */
+enum msp_direction {
+ MSP_TRANSMIT_MODE,
+ MSP_RECEIVE_MODE,
+ MSP_BOTH_T_R_MODE
+};
+
+/* Dma mode should be used for large transfers,
+ * polling mode should be used for transfers of a few bytes
+ */
+enum msp_xfer_mode {
+ MSP_DMA_MODE,
+ MSP_POLLING_MODE,
+ MSP_INTERRUPT_MODE
+};
+
+/* User client for the MSP */
+enum msp_user {
+ MSP_NO_USER = 0,
+ MSP_USER_SPI,
+ MSP_USER_ALSA,
+ MSP_USER_SAA,
+};
+
+/*Flag structure for MSPx*/
+struct msp_flag {
+ struct semaphore lock;
+ enum msp_user user;
+};
+
+/* User client for the MSP */
+enum msp_mode {
+ MSP_NO_MODE = 0,
+ MSP_MODE_SPI,
+ MSP_MODE_NON_SPI,
+};
+
+/* Transmit and receive configuration register */
+#define MSP_BIG_ENDIAN 0x00000000
+#define MSP_LITTLE_ENDIAN 0x00001000
+#define MSP_UNEXPECTED_FS_ABORT 0x00000000
+#define MSP_UNEXPECTED_FS_IGNORE 0x00008000
+#define MSP_NON_MODE_BIT_MASK 0x00009000
+
+/* Global configuration register */
+#define RX_ENABLE 0x00000001
+#define RX_FIFO_ENABLE 0x00000002
+#define RX_SYNC_SRG 0x00000010
+#define RX_CLK_POL_RISING 0x00000020
+#define RX_CLK_SEL_SRG 0x00000040
+#define TX_ENABLE 0x00000100
+#define TX_FIFO_ENABLE 0x00000200
+#define TX_SYNC_SRG_PROG 0x00001800
+#define TX_SYNC_SRG_AUTO 0x00001000
+#define TX_CLK_POL_RISING 0x00002000
+#define TX_CLK_SEL_SRG 0x00004000
+#define TX_EXTRA_DELAY_ENABLE 0x00008000
+#define SRG_ENABLE 0x00010000
+#define FRAME_GEN_ENABLE 0x00100000
+#define SRG_CLK_SEL_APB 0x00000000
+#define RX_FIFO_SYNC_HI 0x00000000
+#define TX_FIFO_SYNC_HI 0x00000000
+#define SPI_CLK_MODE_NORMAL 0x00000000
+
+/* SPI Clock Modes enumertion
+ * SPI clock modes of MSP provides compatibility with
+ * the SPI protocol.MSP supports 2 SPI transfer formats.
+ * MSP_ZERO_DELAY_SPI_MODE:MSP transmits data over Tx/Rx
+ * Lines immediately after MSPTCK/MSPRCK rising/falling edge.
+ * MSP_HALF_CYCLE_DELY_SPI_MODE:MSP transmits data one-half cycle
+ * ahead of the rising/falling edge of the MSPTCK
+ */
+
+#define MSP_FRAME_SIZE_AUTO -1
+
+
+#define MSP_DR 0x00
+#define MSP_GCR 0x04
+#define MSP_TCF 0x08
+#define MSP_RCF 0x0c
+#define MSP_SRG 0x10
+#define MSP_FLR 0x14
+#define MSP_DMACR 0x18
+
+#define MSP_IMSC 0x20
+#define MSP_RIS 0x24
+#define MSP_MIS 0x28
+#define MSP_ICR 0x2c
+#define MSP_MCR 0x30
+#define MSP_RCV 0x34
+#define MSP_RCM 0x38
+
+#define MSP_TCE0 0x40
+#define MSP_TCE1 0x44
+#define MSP_TCE2 0x48
+#define MSP_TCE3 0x4c
+
+#define MSP_RCE0 0x60
+#define MSP_RCE1 0x64
+#define MSP_RCE2 0x68
+#define MSP_RCE3 0x6c
+#define MSP_IODLY 0x70
+
+#define MSP_ITCR 0x80
+#define MSP_ITIP 0x84
+#define MSP_ITOP 0x88
+#define MSP_TSTDR 0x8c
+
+#define MSP_PID0 0xfe0
+#define MSP_PID1 0xfe4
+#define MSP_PID2 0xfe8
+#define MSP_PID3 0xfec
+
+#define MSP_CID0 0xff0
+#define MSP_CID1 0xff4
+#define MSP_CID2 0xff8
+#define MSP_CID3 0xffc
+
+/* Single or dual phase mode */
+enum msp_phase_mode {
+ MSP_SINGLE_PHASE,
+ MSP_DUAL_PHASE
+};
+
+/* Frame length */
+enum msp_frame_length {
+ MSP_FRAME_LENGTH_1 = 0,
+ MSP_FRAME_LENGTH_2 = 1,
+ MSP_FRAME_LENGTH_4 = 3,
+ MSP_FRAME_LENGTH_8 = 7,
+ MSP_FRAME_LENGTH_12 = 11,
+ MSP_FRAME_LENGTH_16 = 15,
+ MSP_FRAME_LENGTH_20 = 19,
+ MSP_FRAME_LENGTH_32 = 31,
+ MSP_FRAME_LENGTH_48 = 47,
+ MSP_FRAME_LENGTH_64 = 63
+};
+
+/* Element length */
+enum msp_elem_length {
+ MSP_ELEM_LENGTH_8 = 0,
+ MSP_ELEM_LENGTH_10 = 1,
+ MSP_ELEM_LENGTH_12 = 2,
+ MSP_ELEM_LENGTH_14 = 3,
+ MSP_ELEM_LENGTH_16 = 4,
+ MSP_ELEM_LENGTH_20 = 5,
+ MSP_ELEM_LENGTH_24 = 6,
+ MSP_ELEM_LENGTH_32 = 7
+};
+
+enum msp_data_xfer_width {
+ MSP_DATA_TRANSFER_WIDTH_BYTE,
+ MSP_DATA_TRANSFER_WIDTH_HALFWORD,
+ MSP_DATA_TRANSFER_WIDTH_WORD
+};
+
+enum msp_frame_sync {
+ MSP_FRAME_SYNC_UNIGNORE = 0,
+ MSP_FRAME_SYNC_IGNORE = 1,
+
+};
+
+enum msp_phase2_start_mode {
+ MSP_PHASE2_START_MODE_IMEDIATE,
+ MSP_PHASE2_START_MODE_FRAME_SYNC
+};
+
+enum msp_btf {
+ MSP_BTF_MS_BIT_FIRST = 0,
+ MSP_BTF_LS_BIT_FIRST = 1
+};
+
+enum msp_frame_sync_pol {
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH = 0,
+ MSP_FRAME_SYNC_POL_ACTIVE_LOW = 1
+};
+
+/* Data delay (in bit clock cycles) */
+enum msp_delay {
+ MSP_DELAY_0 = 0,
+ MSP_DELAY_1 = 1,
+ MSP_DELAY_2 = 2,
+ MSP_DELAY_3 = 3
+};
+
+/* Configurations of clocks (transmit, receive or sample rate generator) */
+enum msp_edge {
+ MSP_FALLING_EDGE = 0,
+ MSP_RISING_EDGE = 1,
+};
+
+enum msp_hws {
+ MSP_HWS_NO_SWAP = 0,
+ MSP_HWS_BYTE_SWAP_IN_WORD = 1,
+ MSP_HWS_BYTE_SWAP_IN_EACH_HALF_WORD = 2,
+ MSP_HWS_HALF_WORD_SWAP_IN_WORD = 3
+};
+
+enum msp_compress_mode {
+ MSP_COMPRESS_MODE_LINEAR = 0,
+ MSP_COMPRESS_MODE_MU_LAW = 2,
+ MSP_COMPRESS_MODE_A_LAW = 3
+};
+
+enum msp_spi_clock_mode {
+ MSP_SPI_CLOCK_MODE_NON_SPI = 0,
+ MSP_SPI_CLOCK_MODE_ZERO_DELAY = 2,
+ MSP_SPI_CLOCK_MODE_HALF_CYCLE_DELAY = 3
+};
+
+enum msp_spi_burst_mode {
+ MSP_SPI_BURST_MODE_DISABLE = 0,
+ MSP_SPI_BURST_MODE_ENABLE = 1
+};
+
+enum msp_expand_mode {
+ MSP_EXPAND_MODE_LINEAR = 0,
+ MSP_EXPAND_MODE_LINEAR_SIGNED = 1,
+ MSP_EXPAND_MODE_MU_LAW = 2,
+ MSP_EXPAND_MODE_A_LAW = 3
+};
+
+/* Protocol dependant parameters list */
+#define RX_ENABLE_MASK BIT(0)
+#define RX_FIFO_ENABLE_MASK BIT(1)
+#define RX_FRAME_SYNC_MASK BIT(2)
+#define DIRECT_COMPANDING_MASK BIT(3)
+#define RX_SYNC_SEL_MASK BIT(4)
+#define RX_CLK_POL_MASK BIT(5)
+#define RX_CLK_SEL_MASK BIT(6)
+#define LOOPBACK_MASK BIT(7)
+#define TX_ENABLE_MASK BIT(8)
+#define TX_FIFO_ENABLE_MASK BIT(9)
+#define TX_FRAME_SYNC_MASK BIT(10)
+#define TX_MSP_TDR_TSR BIT(11)
+#define TX_SYNC_SEL_MASK (BIT(12) | BIT(11))
+#define TX_CLK_POL_MASK BIT(13)
+#define TX_CLK_SEL_MASK BIT(14)
+#define TX_EXTRA_DELAY_MASK BIT(15)
+#define SRG_ENABLE_MASK BIT(16)
+#define SRG_CLK_POL_MASK BIT(17)
+#define SRG_CLK_SEL_MASK (BIT(19) | BIT(18))
+#define FRAME_GEN_EN_MASK BIT(20)
+#define SPI_CLK_MODE_MASK (BIT(22) | BIT(21))
+#define SPI_BURST_MODE_MASK BIT(23)
+
+#define RXEN_SHIFT 0
+#define RFFEN_SHIFT 1
+#define RFSPOL_SHIFT 2
+#define DCM_SHIFT 3
+#define RFSSEL_SHIFT 4
+#define RCKPOL_SHIFT 5
+#define RCKSEL_SHIFT 6
+#define LBM_SHIFT 7
+#define TXEN_SHIFT 8
+#define TFFEN_SHIFT 9
+#define TFSPOL_SHIFT 10
+#define TFSSEL_SHIFT 11
+#define TCKPOL_SHIFT 13
+#define TCKSEL_SHIFT 14
+#define TXDDL_SHIFT 15
+#define SGEN_SHIFT 16
+#define SCKPOL_SHIFT 17
+#define SCKSEL_SHIFT 18
+#define FGEN_SHIFT 20
+#define SPICKM_SHIFT 21
+#define TBSWAP_SHIFT 28
+
+#define RCKPOL_MASK BIT(0)
+#define TCKPOL_MASK BIT(0)
+#define SPICKM_MASK (BIT(1) | BIT(0))
+#define MSP_RX_CLKPOL_BIT(n) ((n & RCKPOL_MASK) << RCKPOL_SHIFT)
+#define MSP_TX_CLKPOL_BIT(n) ((n & TCKPOL_MASK) << TCKPOL_SHIFT)
+#define MSP_SPI_CLK_MODE_BITS(n) ((n & SPICKM_MASK) << SPICKM_SHIFT)
+
+
+
+/* Use this to clear the clock mode bits to non-spi */
+#define MSP_NON_SPI_CLK_MASK (BIT(22) | BIT(21))
+
+#define P1ELEN_SHIFT 0
+#define P1FLEN_SHIFT 3
+#define DTYP_SHIFT 10
+#define ENDN_SHIFT 12
+#define DDLY_SHIFT 13
+#define FSIG_SHIFT 15
+#define P2ELEN_SHIFT 16
+#define P2FLEN_SHIFT 19
+#define P2SM_SHIFT 26
+#define P2EN_SHIFT 27
+#define FRAME_SYNC_SHIFT 15
+
+
+#define P1ELEN_MASK 0x00000007
+#define P2ELEN_MASK 0x00070000
+#define P1FLEN_MASK 0x00000378
+#define P2FLEN_MASK 0x03780000
+#define DDLY_MASK 0x00003000
+#define DTYP_MASK 0x00000600
+#define P2SM_MASK 0x04000000
+#define P2EN_MASK 0x08000000
+#define ENDN_MASK 0x00001000
+#define TFSPOL_MASK 0x00000400
+#define TBSWAP_MASK 0x30000000
+#define COMPANDING_MODE_MASK 0x00000c00
+#define FRAME_SYNC_MASK 0x00008000
+
+#define MSP_P1_ELEM_LEN_BITS(n) (n & P1ELEN_MASK)
+#define MSP_P2_ELEM_LEN_BITS(n) (((n) << P2ELEN_SHIFT) & P2ELEN_MASK)
+#define MSP_P1_FRAME_LEN_BITS(n) (((n) << P1FLEN_SHIFT) & P1FLEN_MASK)
+#define MSP_P2_FRAME_LEN_BITS(n) (((n) << P2FLEN_SHIFT) & P2FLEN_MASK)
+#define MSP_DATA_DELAY_BITS(n) (((n) << DDLY_SHIFT) & DDLY_MASK)
+#define MSP_DATA_TYPE_BITS(n) (((n) << DTYP_SHIFT) & DTYP_MASK)
+#define MSP_P2_START_MODE_BIT(n) ((n << P2SM_SHIFT) & P2SM_MASK)
+#define MSP_P2_ENABLE_BIT(n) ((n << P2EN_SHIFT) & P2EN_MASK)
+#define MSP_SET_ENDIANNES_BIT(n) ((n << ENDN_SHIFT) & ENDN_MASK)
+#define MSP_FRAME_SYNC_POL(n) ((n << TFSPOL_SHIFT) & TFSPOL_MASK)
+#define MSP_DATA_WORD_SWAP(n) ((n << TBSWAP_SHIFT) & TBSWAP_MASK)
+#define MSP_SET_COMPANDING_MODE(n) ((n << DTYP_SHIFT) & COMPANDING_MODE_MASK)
+#define MSP_SET_FRAME_SYNC_IGNORE(n) ((n << FRAME_SYNC_SHIFT) & \
+ FRAME_SYNC_MASK)
+
+/* Flag register */
+#define RX_BUSY BIT(0)
+#define RX_FIFO_EMPTY BIT(1)
+#define RX_FIFO_FULL BIT(2)
+#define TX_BUSY BIT(3)
+#define TX_FIFO_EMPTY BIT(4)
+#define TX_FIFO_FULL BIT(5)
+
+#define RBUSY_SHIFT 0
+#define RFE_SHIFT 1
+#define RFU_SHIFT 2
+#define TBUSY_SHIFT 3
+#define TFE_SHIFT 4
+#define TFU_SHIFT 5
+
+/* Multichannel control register */
+#define RMCEN_SHIFT 0
+#define RMCSF_SHIFT 1
+#define RCMPM_SHIFT 3
+#define TMCEN_SHIFT 5
+#define TNCSF_SHIFT 6
+
+/* Sample rate generator register */
+#define SCKDIV_SHIFT 0
+#define FRWID_SHIFT 10
+#define FRPER_SHIFT 16
+
+#define SCK_DIV_MASK 0x0000003FF
+#define FRAME_WIDTH_BITS(n) (((n) << FRWID_SHIFT) & 0x0000FC00)
+#define FRAME_PERIOD_BITS(n) (((n) << FRPER_SHIFT) & 0x1FFF0000)
+
+/* DMA controller register */
+#define RX_DMA_ENABLE BIT(0)
+#define TX_DMA_ENABLE BIT(1)
+
+#define RDMAE_SHIFT 0
+#define TDMAE_SHIFT 1
+
+/* Interrupt Register */
+#define RECEIVE_SERVICE_INT BIT(0)
+#define RECEIVE_OVERRUN_ERROR_INT BIT(1)
+#define RECEIVE_FRAME_SYNC_ERR_INT BIT(2)
+#define RECEIVE_FRAME_SYNC_INT BIT(3)
+#define TRANSMIT_SERVICE_INT BIT(4)
+#define TRANSMIT_UNDERRUN_ERR_INT BIT(5)
+#define TRANSMIT_FRAME_SYNC_ERR_INT BIT(6)
+#define TRANSMIT_FRAME_SYNC_INT BIT(7)
+#define ALL_INT 0x000000ff
+
+/*
+ * Protocol configuration values I2S:
+ * Single phase, 16 bits, 2 words per frame
+ */
+#define I2S_PROTOCOL_DESC \
+{ \
+ MSP_SINGLE_PHASE, \
+ MSP_SINGLE_PHASE, \
+ MSP_PHASE2_START_MODE_IMEDIATE, \
+ MSP_PHASE2_START_MODE_IMEDIATE, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_ELEM_LENGTH_32, \
+ MSP_ELEM_LENGTH_32, \
+ MSP_ELEM_LENGTH_32, \
+ MSP_ELEM_LENGTH_32, \
+ MSP_DELAY_1, \
+ MSP_DELAY_1, \
+ MSP_RISING_EDGE, \
+ MSP_RISING_EDGE, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_HWS_NO_SWAP, \
+ MSP_HWS_NO_SWAP, \
+ MSP_COMPRESS_MODE_LINEAR, \
+ MSP_EXPAND_MODE_LINEAR, \
+ MSP_SPI_CLOCK_MODE_NON_SPI, \
+ MSP_SPI_BURST_MODE_DISABLE, \
+ MSP_FRAME_SYNC_IGNORE, \
+ 31, \
+ 15, \
+ 32, \
+}
+
+#define PCM_PROTOCOL_DESC \
+{ \
+ MSP_DUAL_PHASE, \
+ MSP_DUAL_PHASE, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_ELEM_LENGTH_16, \
+ MSP_ELEM_LENGTH_16, \
+ MSP_ELEM_LENGTH_16, \
+ MSP_ELEM_LENGTH_16, \
+ MSP_DELAY_0, \
+ MSP_DELAY_0, \
+ MSP_FALLING_EDGE, \
+ MSP_FALLING_EDGE, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_HWS_NO_SWAP, \
+ MSP_HWS_NO_SWAP, \
+ MSP_COMPRESS_MODE_LINEAR, \
+ MSP_EXPAND_MODE_LINEAR, \
+ MSP_SPI_CLOCK_MODE_NON_SPI, \
+ MSP_SPI_BURST_MODE_DISABLE, \
+ MSP_FRAME_SYNC_IGNORE, \
+ 255, \
+ 0, \
+ 256, \
+}
+
+/* Companded PCM: Single phase, 8 bits, 1 word per frame */
+#define PCM_COMPAND_PROTOCOL_DESC \
+{ \
+ MSP_SINGLE_PHASE, \
+ MSP_SINGLE_PHASE, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_DELAY_0, \
+ MSP_DELAY_0, \
+ MSP_FALLING_EDGE, \
+ MSP_RISING_EDGE, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_HWS_NO_SWAP, \
+ MSP_HWS_NO_SWAP, \
+ MSP_COMPRESS_MODE_LINEAR, \
+ MSP_EXPAND_MODE_LINEAR, \
+ MSP_SPI_CLOCK_MODE_NON_SPI, \
+ MSP_SPI_BURST_MODE_DISABLE, \
+ MSP_FRAME_SYNC_IGNORE, \
+ 255, \
+ 0, \
+ 256, \
+}
+
+/*
+ * AC97: Double phase, 1 element of 16 bits during first phase,
+ * 12 elements of 20 bits in second phase.
+ */
+#define AC97_PROTOCOL_DESC \
+{ \
+ MSP_DUAL_PHASE, \
+ MSP_DUAL_PHASE, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_12, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_12, \
+ MSP_ELEM_LENGTH_16, \
+ MSP_ELEM_LENGTH_20, \
+ MSP_ELEM_LENGTH_16, \
+ MSP_ELEM_LENGTH_20, \
+ MSP_DELAY_1, \
+ MSP_DELAY_1, \
+ MSP_FALLING_EDGE, \
+ MSP_RISING_EDGE, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_HWS_NO_SWAP, \
+ MSP_HWS_NO_SWAP, \
+ MSP_COMPRESS_MODE_LINEAR, \
+ MSP_EXPAND_MODE_LINEAR, \
+ MSP_SPI_CLOCK_MODE_NON_SPI, \
+ MSP_SPI_BURST_MODE_DISABLE, \
+ MSP_FRAME_SYNC_IGNORE, \
+ 255, \
+ 0, \
+ 256, \
+}
+
+#define SPI_MASTER_PROTOCOL_DESC \
+{ \
+ MSP_SINGLE_PHASE, \
+ MSP_SINGLE_PHASE, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_DELAY_1, \
+ MSP_DELAY_1, \
+ MSP_RISING_EDGE, \
+ MSP_FALLING_EDGE, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_HWS_NO_SWAP, \
+ MSP_HWS_NO_SWAP, \
+ MSP_COMPRESS_MODE_LINEAR, \
+ MSP_EXPAND_MODE_LINEAR, \
+ MSP_SPI_CLOCK_MODE_NON_SPI, \
+ MSP_SPI_BURST_MODE_DISABLE, \
+ MSP_FRAME_SYNC_IGNORE, \
+ 255, \
+ 0, \
+ 256, \
+}
+
+#define SPI_SLAVE_PROTOCOL_DESC \
+{ \
+ MSP_SINGLE_PHASE, \
+ MSP_SINGLE_PHASE, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_PHASE2_START_MODE_FRAME_SYNC, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_BTF_MS_BIT_FIRST, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_FRAME_LENGTH_1, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_ELEM_LENGTH_8, \
+ MSP_DELAY_1, \
+ MSP_DELAY_1, \
+ MSP_RISING_EDGE, \
+ MSP_FALLING_EDGE, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_FRAME_SYNC_POL_ACTIVE_HIGH, \
+ MSP_HWS_NO_SWAP, \
+ MSP_HWS_NO_SWAP, \
+ MSP_COMPRESS_MODE_LINEAR, \
+ MSP_EXPAND_MODE_LINEAR, \
+ MSP_SPI_CLOCK_MODE_NON_SPI, \
+ MSP_SPI_BURST_MODE_DISABLE, \
+ MSP_FRAME_SYNC_IGNORE, \
+ 255, \
+ 0, \
+ 256, \
+}
+
+#define MSP_FRAME_PERIOD_IN_MONO_MODE 256
+#define MSP_FRAME_PERIOD_IN_STEREO_MODE 32
+#define MSP_FRAME_WIDTH_IN_STEREO_MODE 16
+
+/*
+ * No of registers to backup during
+ * suspend resume
+ */
+#define MAX_MSP_BACKUP_REGS 36
+
+enum enum_i2s_controller {
+ MSP_0_I2S_CONTROLLER = 1,
+ MSP_1_I2S_CONTROLLER,
+ MSP_2_I2S_CONTROLLER,
+ MSP_3_I2S_CONTROLLER,
+};
+
+/**
+ * struct msp - Main msp controller data structure per MSP.
+ * @work_mode: Mode i.e dma, polling or interrupt.
+ * @id: Controller id like MSP1 or MSP2 etc.
+ * @msp_io_error: To indicate error while transferring.
+ * @registers: MSP's register base address.
+ * @actual_data_size: Data size in which data needs to send or receive.
+ * @irq: MSP's irq number.
+ * @i2s_cont: MSP's Controller's structure pointer created per MSP.
+ * @lock: semaphore lock acquired while configuring msp.
+ * @dma_cfg_tx: TX DMA configuration
+ * @dma_cfg_rx: RX DMA configuration
+ * @tx_pipeid: TX DMA channel
+ * @rx_pipeid: RX DMA channel
+ * @msp_state: Current state of msp.
+ * @read: Function pointer for read, u8_msp_read,u16_msp_read,u32_msp_read.
+ * @write: Function pointer for write, u8_msp_write,u16_msp_write,u32_msp_write.
+ * @transfer: Function pointer for type of transfer i.e dma,polling or interrupt
+ * @xfer_data: MSP's transfer data structure. Contains info about current xfer.
+ * @plat_init: MSP's initialization function.
+ * @plat_exit: MSP's Exit function.
+ * @notify_timer: Timer used in Polling mode to prevent hang.
+ * @polling_flag: Flag used in error handling while polling.
+ * @def_elem_len: Flag indicates whether default elem len to be used in
+ * protocol_desc or not.
+ * @vape_opp_constraint: 1 if constraint is applied to have vape at 100OPP; 0 otherwise
+ * @infinite: true if an infinite transfer has been configured
+ *
+ * Main Msp private data structure to be used to store various info of a
+ * particular MSP.Longer description
+ */
+struct msp {
+ int work_mode;
+ enum enum_i2s_controller id;
+ int msp_io_error;
+ void __iomem *registers;
+ enum msp_data_size actual_data_size;
+ int irq;
+ struct i2s_controller *i2s_cont;
+ struct semaphore lock;
+ struct stedma40_chan_cfg *dma_cfg_rx;
+ struct stedma40_chan_cfg *dma_cfg_tx;
+ struct dma_chan *tx_pipeid;
+ struct dma_chan *rx_pipeid;
+ enum msp_state msp_state;
+ void (*read) (struct trans_data *xfer_data);
+ void (*write) (struct trans_data *xfer_data);
+ int (*transfer) (struct msp *msp, struct i2s_message *message);
+ struct trans_data xfer_data;
+ int (*plat_init) (void);
+ int (*plat_exit) (void);
+ struct timer_list notify_timer;
+ int polling_flag;
+ int def_elem_len;
+ struct clk *clk;
+ unsigned int direction;
+ int users;
+ int loopback_enable;
+ u32 backup_regs[MAX_MSP_BACKUP_REGS];
+ int vape_opp_constraint;
+ bool infinite;
+};
+
+/**
+ * struct msp_i2s_platform_data - Main msp controller platform data structure.
+ * @id: Controller id like MSP1 or MSP2 etc.
+ * @msp_i2s_dma_rx: RX DMA channel config
+ * @msp_i2s_dma_tx: RX DMA channel config
+ * @msp_i2s_init: MSP's initialization function.
+ * @msp_i2s_exit: MSP's Exit function.
+ * @backup_regs: used for backup registers during suspend resume.
+ *
+ * Platform data structure passed by devices.c file.
+ */
+struct msp_i2s_platform_data {
+ enum enum_i2s_controller id;
+ struct stedma40_chan_cfg *msp_i2s_dma_rx;
+ struct stedma40_chan_cfg *msp_i2s_dma_tx;
+ int (*msp_i2s_init) (void);
+ int (*msp_i2s_exit) (void);
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/musb_db8500.h b/arch/arm/mach-ux500/include/mach/musb_db8500.h
new file mode 100644
index 00000000000..7e210ca3dc9
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/musb_db8500.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 ST Ericsson.
+ *
+ * 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.
+ */
+
+/* AB8500 USB macros
+ */
+#define AB8500_REV_10 0x10
+#define AB8500_REV_11 0x11
+#define AB8500_REV_20 0x20
+#define AB8500_REV_30 0x30
+#define AB8500_USB_HOST 0x68
+#define AB8500_USB_LINK_STATUS_UPDT_DONE 135
+#define AB8500_IT_MASK20_MASK 0xFB
+#define AB8500_IT_MASK21_MASK 0xBE
+#define AB8500_IT_MASK2_MASK 0x3F
+#define AB8500_IT_MASK12_MASK 0x7F
+#define AB8500_SRC_INT_USB_DEVICE 0x80
+#define AB8500_SRC_INT_USB_HOST 0x04
+#define AB8500_VBUS_ENABLE 0x1
+#define AB8500_VBUS_DISABLE 0x0
+#define AB8500_USB_HOST_DEVICE_DISABLE 0x0
+#define AB8500_USB_HOST_ENABLE 0x1
+#define AB8500_USB_HOST_DISABLE 0x0
+#define AB8500_USB_DEVICE_ENABLE 0x2
+#define AB8500_USB_DEVICE_DISABLE 0x0
+#define AB8500_MAIN_WATCHDOG_ENABLE 0x1
+#define AB8500_MAIN_WATCHDOG_KICK 0x2
+#define AB8500_MAIN_WATCHDOG_DISABLE 0x0
+#define AB8500_USB_ADP_ENABLE 0x1
+
+/* USB Macros
+ */
+#define WATCHDOG_DELAY 10
+#define WATCHDOG_DELAY_US 100
+#define USB_ENABLE 1
+#define USB_DISABLE 0
+
+/* UsbLineStatus register bit masks */
+#define AB8500_USB_LINK_STATUS 0x78
+
+/* UsbLineStatus register - usb types */
+enum musb_link_status {
+ USB_LINK_NOT_CONFIGURED,
+ USB_LINK_STD_HOST_NC,
+ USB_LINK_STD_HOST_C_NS,
+ USB_LINK_STD_HOST_C_S,
+ USB_LINK_HOST_CHG_NM,
+ USB_LINK_HOST_CHG_HS,
+ USB_LINK_HOST_CHG_HS_CHIRP,
+ USB_LINK_DEDICATED_CHG,
+ USB_LINK_ACA_RID_A,
+ USB_LINK_ACA_RID_B,
+ USB_LINK_ACA_RID_C_NM,
+ USB_LINK_ACA_RID_C_HS,
+ USB_LINK_ACA_RID_C_HS_CHIRP,
+ USB_LINK_HM_IDGND,
+ USB_LINK_OTG_HOST_NO_CURRENT,
+ USB_LINK_NOT_VALID_LINK,
+};
+
+/* Specific functions for USB Phy enable and disable
+ */
+int musb_phy_en(u8 mode);
+int musb_force_detect(u8 mode);
+int musb_get_abx500_rev(void);
+
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-db5500.h b/arch/arm/mach-ux500/include/mach/prcmu-db5500.h
new file mode 100644
index 00000000000..d55ee1a51f3
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu-db5500.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * U5500 PRCMU API.
+ */
+#ifndef __MACH_PRCMU_U5500_H
+#define __MACH_PRCMU_U5500_H
+
+#ifdef CONFIG_U5500_PRCMU
+
+void db5500_prcmu_early_init(void);
+
+int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
+#else /* !CONFIG_U5500_PRCMU */
+
+static inline void db5500_prcmu_early_init(void)
+{
+}
+
+static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ return -ENOSYS;
+}
+
+static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_U5500_PRCMU */
+
+static inline int db5500_prcmu_config_abb_event_readout(u32 abb_events)
+{
+#ifdef CONFIG_MACH_U5500_SIMULATOR
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+#endif /* __MACH_PRCMU_U5500_H */
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h b/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h
new file mode 100644
index 00000000000..56402a115ed
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu-fw-api.h
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ *
+ * PRCMU f/w APIs
+ */
+#ifndef __MACH_PRCMU_FW_API_H
+#define __MACH_PRCMU_FW_API_H
+
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include "prcmu-fw-defs_v1.h"
+
+/* PRCMU Wakeup defines */
+enum prcmu_wakeup_index {
+ PRCMU_WAKEUP_INDEX_RTC,
+ PRCMU_WAKEUP_INDEX_RTT0,
+ PRCMU_WAKEUP_INDEX_RTT1,
+ PRCMU_WAKEUP_INDEX_HSI0,
+ PRCMU_WAKEUP_INDEX_HSI1,
+ PRCMU_WAKEUP_INDEX_USB,
+ PRCMU_WAKEUP_INDEX_ABB,
+ PRCMU_WAKEUP_INDEX_ABB_FIFO,
+ PRCMU_WAKEUP_INDEX_ARM,
+ NUM_PRCMU_WAKEUP_INDICES
+};
+#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name))
+
+/* PRCMU QoS APE OPP class */
+#define PRCMU_QOS_APE_OPP 1
+#define PRCMU_QOS_DDR_OPP 2
+#define PRCMU_QOS_DEFAULT_VALUE -1
+
+/**
+ * enum hw_acc_dev - enum for hw accelerators
+ * @HW_ACC_SVAMMDSP: for SVAMMDSP
+ * @HW_ACC_SVAPIPE: for SVAPIPE
+ * @HW_ACC_SIAMMDSP: for SIAMMDSP
+ * @HW_ACC_SIAPIPE: for SIAPIPE
+ * @HW_ACC_SGA: for SGA
+ * @HW_ACC_B2R2: for B2R2
+ * @HW_ACC_MCDE: for MCDE
+ * @HW_ACC_ESRAM1: for ESRAM1
+ * @HW_ACC_ESRAM2: for ESRAM2
+ * @HW_ACC_ESRAM3: for ESRAM3
+ * @HW_ACC_ESRAM4: for ESRAM4
+ * @NUM_HW_ACC: number of hardware accelerators
+ *
+ * Different hw accelerators which can be turned ON/
+ * OFF or put into retention (MMDSPs and ESRAMs).
+ * Used with EPOD API.
+ *
+ * NOTE! Deprecated, to be removed when all users switched over to use the
+ * regulator API.
+ */
+enum hw_acc_dev{
+ HW_ACC_SVAMMDSP,
+ HW_ACC_SVAPIPE,
+ HW_ACC_SIAMMDSP,
+ HW_ACC_SIAPIPE,
+ HW_ACC_SGA,
+ HW_ACC_B2R2,
+ HW_ACC_MCDE,
+ HW_ACC_ESRAM1,
+ HW_ACC_ESRAM2,
+ HW_ACC_ESRAM3,
+ HW_ACC_ESRAM4,
+ NUM_HW_ACC
+};
+
+/*
+ * Ids for all EPODs (power domains)
+ * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP
+ * - EPOD_ID_SVAPIPE: power domain for SVA pipe
+ * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP
+ * - EPOD_ID_SIAPIPE: power domain for SIA pipe
+ * - EPOD_ID_SGA: power domain for SGA
+ * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE
+ * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2
+ * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4
+ * - NUM_EPOD_ID: number of power domains
+ */
+#define EPOD_ID_SVAMMDSP 0
+#define EPOD_ID_SVAPIPE 1
+#define EPOD_ID_SIAMMDSP 2
+#define EPOD_ID_SIAPIPE 3
+#define EPOD_ID_SGA 4
+#define EPOD_ID_B2R2_MCDE 5
+#define EPOD_ID_ESRAM12 6
+#define EPOD_ID_ESRAM34 7
+#define NUM_EPOD_ID 8
+
+/*
+ * state definition for EPOD (power domain)
+ * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged
+ * - EPOD_STATE_OFF: The EPOD is switched off
+ * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in
+ * retention
+ * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off
+ * - EPOD_STATE_ON: Same as above, but with clock enabled
+ */
+#define EPOD_STATE_NO_CHANGE 0x00
+#define EPOD_STATE_OFF 0x01
+#define EPOD_STATE_RAMRET 0x02
+#define EPOD_STATE_ON_CLK_OFF 0x03
+#define EPOD_STATE_ON 0x04
+
+/*
+ * CLKOUT sources
+ */
+#define PRCMU_CLKSRC_CLK38M 0x00
+#define PRCMU_CLKSRC_ACLK 0x01
+#define PRCMU_CLKSRC_SYSCLK 0x02
+#define PRCMU_CLKSRC_LCDCLK 0x03
+#define PRCMU_CLKSRC_SDMMCCLK 0x04
+#define PRCMU_CLKSRC_TVCLK 0x05
+#define PRCMU_CLKSRC_TIMCLK 0x06
+#define PRCMU_CLKSRC_CLK009 0x07
+/* These are only valid for CLKOUT1: */
+#define PRCMU_CLKSRC_SIAMMDSPCLK 0x40
+#define PRCMU_CLKSRC_I2CCLK 0x41
+#define PRCMU_CLKSRC_MSP02CLK 0x42
+#define PRCMU_CLKSRC_ARMPLL_OBSCLK 0x43
+#define PRCMU_CLKSRC_HSIRXCLK 0x44
+#define PRCMU_CLKSRC_HSITXCLK 0x45
+#define PRCMU_CLKSRC_ARMCLKFIX 0x46
+#define PRCMU_CLKSRC_HDMICLK 0x47
+
+/*
+ * Definitions for autonomous power management configuration.
+ */
+
+#define PRCMU_AUTO_PM_OFF 0
+#define PRCMU_AUTO_PM_ON 1
+
+#define PRCMU_AUTO_PM_POWER_ON_HSEM BIT(0)
+#define PRCMU_AUTO_PM_POWER_ON_ABB_FIFO_IT BIT(1)
+
+enum prcmu_auto_pm_policy {
+ PRCMU_AUTO_PM_POLICY_NO_CHANGE,
+ PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF,
+ PRCMU_AUTO_PM_POLICY_DSP_OFF_RAMRET_HWP_OFF,
+ PRCMU_AUTO_PM_POLICY_DSP_CLK_OFF_HWP_OFF,
+ PRCMU_AUTO_PM_POLICY_DSP_CLK_OFF_HWP_CLK_OFF,
+};
+
+/**
+ * struct prcmu_auto_pm_config - Autonomous power management configuration.
+ * @sia_auto_pm_enable: SIA autonomous pm enable. (PRCMU_AUTO_PM_{OFF,ON})
+ * @sia_power_on: SIA power ON enable. (PRCMU_AUTO_PM_POWER_ON_* bitmask)
+ * @sia_policy: SIA power policy. (enum prcmu_auto_pm_policy)
+ * @sva_auto_pm_enable: SVA autonomous pm enable. (PRCMU_AUTO_PM_{OFF,ON})
+ * @sva_power_on: SVA power ON enable. (PRCMU_AUTO_PM_POWER_ON_* bitmask)
+ * @sva_policy: SVA power policy. (enum prcmu_auto_pm_policy)
+ */
+struct prcmu_auto_pm_config {
+ u8 sia_auto_pm_enable;
+ u8 sia_power_on;
+ u8 sia_policy;
+ u8 sva_auto_pm_enable;
+ u8 sva_power_on;
+ u8 sva_policy;
+};
+
+/**
+ * enum ddr_opp - DDR OPP states definition
+ * @DDR_100_OPP: The new DDR operating point is ddr100opp
+ * @DDR_50_OPP: The new DDR operating point is ddr50opp
+ * @DDR_25_OPP: The new DDR operating point is ddr25opp
+ */
+enum ddr_opp {
+ DDR_100_OPP = 0x00,
+ DDR_50_OPP = 0x01,
+ DDR_25_OPP = 0x02,
+};
+
+/*
+ * Clock identifiers.
+ */
+enum prcmu_clock {
+ PRCMU_SGACLK,
+ PRCMU_UARTCLK,
+ PRCMU_MSP02CLK,
+ PRCMU_MSP1CLK,
+ PRCMU_I2CCLK,
+ PRCMU_SDMMCCLK,
+ PRCMU_SLIMCLK,
+ PRCMU_PER1CLK,
+ PRCMU_PER2CLK,
+ PRCMU_PER3CLK,
+ PRCMU_PER5CLK,
+ PRCMU_PER6CLK,
+ PRCMU_PER7CLK,
+ PRCMU_LCDCLK,
+ PRCMU_BMLCLK,
+ PRCMU_HSITXCLK,
+ PRCMU_HSIRXCLK,
+ PRCMU_HDMICLK,
+ PRCMU_APEATCLK,
+ PRCMU_APETRACECLK,
+ PRCMU_MCDECLK,
+ PRCMU_IPI2CCLK,
+ PRCMU_DSIALTCLK,
+ PRCMU_DMACLK,
+ PRCMU_B2R2CLK,
+ PRCMU_TVCLK,
+ PRCMU_SSPCLK,
+ PRCMU_RNGCLK,
+ PRCMU_UICCCLK,
+ PRCMU_NUM_REG_CLOCKS,
+ PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
+ PRCMU_PLLSOC1,
+ PRCMU_TIMCLK,
+};
+
+/*
+ * Definitions for controlling ESRAM0 in deep sleep.
+ */
+#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
+#define ESRAM0_DEEP_SLEEP_STATE_RET 2
+
+#if defined(CONFIG_U8500_PRCMU) || defined(CONFIG_U5500_PRCMU)
+void __init prcmu_early_init(void);
+int prcmu_set_display_clocks(void);
+int prcmu_disable_dsipll(void);
+int prcmu_enable_dsipll(void);
+#else
+static inline void __init prcmu_early_init(void) {}
+#endif
+
+#ifdef CONFIG_U8500_PRCMU
+
+int prcmu_set_rc_a2p(enum romcode_write);
+enum romcode_read prcmu_get_rc_p2a(void);
+enum ap_pwrst prcmu_get_xp70_current_state(void);
+int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
+
+void prcmu_enable_wakeups(u32 wakeups);
+static inline void prcmu_disable_wakeups(void)
+{
+ prcmu_enable_wakeups(0);
+}
+
+void prcmu_config_abb_event_readout(u32 abb_events);
+void prcmu_get_abb_event_buffer(void __iomem **buf);
+int prcmu_set_arm_opp(u8 opp);
+int prcmu_get_arm_opp(void);
+bool prcmu_has_arm_maxopp(void);
+bool prcmu_is_u8400(void);
+int prcmu_set_ape_opp(u8 opp);
+int prcmu_get_ape_opp(void);
+int prcmu_request_ape_opp_100_voltage(bool enable);
+int prcmu_release_usb_wakeup_state(void);
+int prcmu_set_ddr_opp(u8 opp);
+int prcmu_get_ddr_opp(void);
+unsigned long prcmu_qos_get_cpufreq_opp_delay(void);
+void prcmu_qos_set_cpufreq_opp_delay(unsigned long);
+void prcmu_qos_force_opp(int, s32);
+/* NOTE! Use regulator framework instead */
+int prcmu_set_hwacc(u16 hw_acc_dev, u8 state);
+int prcmu_set_epod(u16 epod_id, u8 epod_state);
+void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
+ struct prcmu_auto_pm_config *idle);
+bool prcmu_is_auto_pm_enabled(void);
+
+int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
+int prcmu_request_clock(u8 clock, bool enable);
+int prcmu_set_clock_divider(u8 clock, u8 divider);
+int prcmu_config_esram0_deep_sleep(u8 state);
+int prcmu_config_hotdog(u8 threshold);
+int prcmu_config_hotmon(u8 low, u8 high);
+int prcmu_start_temp_sense(u16 cycles32k);
+int prcmu_stop_temp_sense(void);
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
+void prcmu_ac_wake_req(void);
+void prcmu_ac_sleep_req(void);
+void prcmu_system_reset(u16 reset_code);
+void prcmu_modem_reset(void);
+bool prcmu_is_ac_wake_requested(void);
+void prcmu_enable_spi2(void);
+void prcmu_disable_spi2(void);
+
+#else /* !CONFIG_U8500_PRCMU */
+
+static inline int prcmu_set_rc_a2p(enum romcode_write code)
+{
+ return 0;
+}
+
+static inline enum romcode_read prcmu_get_rc_p2a(void)
+{
+ return INIT;
+}
+
+static inline enum ap_pwrst prcmu_get_xp70_current_state(void)
+{
+ return AP_EXECUTE;
+}
+
+static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+ bool keep_ap_pll)
+{
+ return 0;
+}
+
+static inline void prcmu_enable_wakeups(u32 wakeups) {}
+
+static inline void prcmu_disable_wakeups(void) {}
+
+static inline void prcmu_config_abb_event_readout(u32 abb_events) {}
+
+static inline int prcmu_set_arm_opp(u8 opp)
+{
+ return 0;
+}
+
+static inline int prcmu_get_arm_opp(void)
+{
+ return ARM_100_OPP;
+}
+
+static bool prcmu_has_arm_maxopp(void)
+{
+ return false;
+}
+
+static bool prcmu_is_u8400(void)
+{
+ return false;
+}
+
+static inline int prcmu_set_ape_opp(u8 opp)
+{
+ return 0;
+}
+
+static inline int prcmu_get_ape_opp(void)
+{
+ return APE_100_OPP;
+}
+
+static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+ return 0;
+}
+
+static inline int prcmu_release_usb_wakeup_state(void)
+{
+ return 0;
+}
+
+static inline int prcmu_set_ddr_opp(u8 opp)
+{
+ return 0;
+}
+
+static inline int prcmu_get_ddr_opp(void)
+{
+ return DDR_100_OPP;
+}
+
+static inline unsigned long prcmu_qos_get_cpufreq_opp_delay(void)
+{
+ return 0;
+}
+
+static inline void prcmu_qos_set_cpufreq_opp_delay(unsigned long n) {}
+
+static inline void prcmu_qos_force_opp(int prcmu_qos_class, s32 i) {}
+
+static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state)
+{
+ return 0;
+}
+
+static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
+ struct prcmu_auto_pm_config *idle)
+{
+}
+
+static inline bool prcmu_is_auto_pm_enabled(void)
+{
+ return false;
+}
+
+static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
+{
+ return 0;
+}
+
+static inline int prcmu_request_clock(u8 clock, bool enable)
+{
+ return 0;
+}
+
+static inline int prcmu_set_clock_divider(u8 clock, u8 divider)
+{
+ return 0;
+}
+
+static inline int prcmu_config_esram0_deep_sleep(u8 state)
+{
+ return 0;
+}
+
+static inline int prcmu_config_hotdog(u8 threshold)
+{
+ return 0;
+}
+
+static inline int prcmu_config_hotmon(u8 low, u8 high)
+{
+ return 0;
+}
+
+static inline int prcmu_start_temp_sense(u16 cycles32k)
+{
+ return 0;
+}
+
+static inline int prcmu_stop_temp_sense(void)
+{
+ return 0;
+}
+
+static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ return -ENOSYS;
+}
+
+static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ return -ENOSYS;
+}
+
+static inline void prcmu_ac_wake_req(void) {}
+
+static inline void prcmu_ac_sleep_req(void) {}
+
+static inline void prcmu_system_reset(u16 reset_code) {}
+
+static inline void prcmu_modem_reset(void) {}
+
+static inline bool prcmu_is_ac_wake_requested(void)
+{
+ return false;
+}
+
+static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
+{
+ return 0;
+}
+
+#ifndef CONFIG_U5500_PRCMU
+static inline int prcmu_set_display_clocks(void)
+{
+ return 0;
+}
+
+static inline int prcmu_disable_dsipll(void)
+{
+ return 0;
+}
+
+static inline int prcmu_enable_dsipll(void)
+{
+ return 0;
+}
+#endif
+
+static inline int prcmu_enable_spi2(void)
+{
+ return 0;
+}
+
+static inline int prcmu_disable_spi2(void)
+{
+ return 0;
+}
+
+#endif /* CONFIG_U8500_PRCMU */
+
+#ifdef CONFIG_UX500_PRCMU_QOS_POWER
+int prcmu_qos_requirement(int pm_qos_class);
+int prcmu_qos_add_requirement(int pm_qos_class, char *name, s32 value);
+int prcmu_qos_update_requirement(int pm_qos_class, char *name, s32 new_value);
+void prcmu_qos_remove_requirement(int pm_qos_class, char *name);
+int prcmu_qos_add_notifier(int prcmu_qos_class,
+ struct notifier_block *notifier);
+int prcmu_qos_remove_notifier(int prcmu_qos_class,
+ struct notifier_block *notifier);
+#else
+static inline int prcmu_qos_requirement(int prcmu_qos_class)
+{
+ return 0;
+}
+
+static inline int prcmu_qos_add_requirement(int prcmu_qos_class,
+ char *name, s32 value)
+{
+ return 0;
+}
+
+static inline int prcmu_qos_update_requirement(int prcmu_qos_class,
+ char *name, s32 new_value)
+{
+ return 0;
+}
+
+static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name)
+{
+}
+
+static inline int prcmu_qos_add_notifier(int prcmu_qos_class,
+ struct notifier_block *notifier)
+{
+ return 0;
+}
+static inline int prcmu_qos_remove_notifier(int prcmu_qos_class,
+ struct notifier_block *notifier)
+{
+ return 0;
+}
+
+#endif
+
+#endif /* __MACH_PRCMU_FW_API_V1_H */
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-fw-defs_v1.h b/arch/arm/mach-ux500/include/mach/prcmu-fw-defs_v1.h
new file mode 100644
index 00000000000..42a8cd2310f
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu-fw-defs_v1.h
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ *
+ * PRCMU definitions for U8500 v1.0 cut
+ */
+#ifndef __MACH_PRCMU_FW_DEFS_V1_H
+#define __MACH_PRCMU_FW_DEFS_V1_H
+
+#include <linux/interrupt.h>
+
+/**
+ * enum state - ON/OFF state definition
+ * @OFF: State is ON
+ * @ON: State is OFF
+ *
+ */
+enum state {
+ OFF = 0x0,
+ ON = 0x1,
+};
+
+/**
+ * enum ret_state - general purpose On/Off/Retention states
+ *
+ */
+enum ret_state {
+ OFFST = 0,
+ ONST = 1,
+ RETST = 2
+};
+
+/**
+ * enum clk_arm - ARM Cortex A9 clock schemes
+ * @A9_OFF:
+ * @A9_BOOT:
+ * @A9_OPPT1:
+ * @A9_OPPT2:
+ * @A9_EXTCLK:
+ */
+enum clk_arm {
+ A9_OFF,
+ A9_BOOT,
+ A9_OPPT1,
+ A9_OPPT2,
+ A9_EXTCLK
+};
+
+/**
+ * enum clk_gen - GEN#0/GEN#1 clock schemes
+ * @GEN_OFF:
+ * @GEN_BOOT:
+ * @GEN_OPPT1:
+ */
+enum clk_gen {
+ GEN_OFF,
+ GEN_BOOT,
+ GEN_OPPT1,
+};
+
+/* some information between arm and xp70 */
+
+/**
+ * enum romcode_write - Romcode message written by A9 AND read by XP70
+ * @RDY_2_DS: Value set when ApDeepSleep state can be executed by XP70
+ * @RDY_2_XP70_RST: Value set when 0x0F has been successfully polled by the
+ * romcode. The xp70 will go into self-reset
+ */
+enum romcode_write {
+ RDY_2_DS = 0x09,
+ RDY_2_XP70_RST = 0x10
+};
+
+/**
+ * enum romcode_read - Romcode message written by XP70 and read by A9
+ * @INIT: Init value when romcode field is not used
+ * @FS_2_DS: Value set when power state is going from ApExecute to
+ * ApDeepSleep
+ * @END_DS: Value set when ApDeepSleep power state is reached coming from
+ * ApExecute state
+ * @DS_TO_FS: Value set when power state is going from ApDeepSleep to
+ * ApExecute
+ * @END_FS: Value set when ApExecute power state is reached coming from
+ * ApDeepSleep state
+ * @SWR: Value set when power state is going to ApReset
+ * @END_SWR: Value set when the xp70 finished executing ApReset actions and
+ * waits for romcode acknowledgment to go to self-reset
+ */
+enum romcode_read {
+ INIT = 0x00,
+ FS_2_DS = 0x0A,
+ END_DS = 0x0B,
+ DS_TO_FS = 0x0C,
+ END_FS = 0x0D,
+ SWR = 0x0E,
+ END_SWR = 0x0F
+};
+
+/**
+ * enum ap_pwrst - current power states defined in PRCMU firmware
+ * @NO_PWRST: Current power state init
+ * @AP_BOOT: Current power state is apBoot
+ * @AP_EXECUTE: Current power state is apExecute
+ * @AP_DEEP_SLEEP: Current power state is apDeepSleep
+ * @AP_SLEEP: Current power state is apSleep
+ * @AP_IDLE: Current power state is apIdle
+ * @AP_RESET: Current power state is apReset
+ */
+enum ap_pwrst {
+ NO_PWRST = 0x00,
+ AP_BOOT = 0x01,
+ AP_EXECUTE = 0x02,
+ AP_DEEP_SLEEP = 0x03,
+ AP_SLEEP = 0x04,
+ AP_IDLE = 0x05,
+ AP_RESET = 0x06
+};
+
+/**
+ * enum ap_pwrst_trans - Transition states defined in PRCMU firmware
+ * @NO_TRANSITION: No power state transition
+ * @APEXECUTE_TO_APSLEEP: Power state transition from ApExecute to ApSleep
+ * @APIDLE_TO_APSLEEP: Power state transition from ApIdle to ApSleep
+ * @APBOOT_TO_APEXECUTE: Power state transition from ApBoot to ApExecute
+ * @APEXECUTE_TO_APDEEPSLEEP: Power state transition from ApExecute to
+ * ApDeepSleep
+ * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle
+ */
+enum ap_pwrst_trans {
+ NO_TRANSITION = 0x00,
+ APEXECUTE_TO_APSLEEP = 0x01,
+ APIDLE_TO_APSLEEP = 0x02, /* To be removed */
+ PRCMU_AP_SLEEP = 0x01,
+ APBOOT_TO_APEXECUTE = 0x03,
+ APEXECUTE_TO_APDEEPSLEEP = 0x04, /* To be removed */
+ PRCMU_AP_DEEP_SLEEP = 0x04,
+ APEXECUTE_TO_APIDLE = 0x05, /* To be removed */
+ PRCMU_AP_IDLE = 0x05,
+ PRCMU_AP_DEEP_IDLE = 0x07,
+};
+
+/**
+ * enum ddr_pwrst - DDR power states definition
+ * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
+ * @DDR_PWR_STATE_ON:
+ * @DDR_PWR_STATE_OFFLOWLAT:
+ * @DDR_PWR_STATE_OFFHIGHLAT:
+ */
+enum ddr_pwrst {
+ DDR_PWR_STATE_UNCHANGED = 0x00,
+ DDR_PWR_STATE_ON = 0x01,
+ DDR_PWR_STATE_OFFLOWLAT = 0x02,
+ DDR_PWR_STATE_OFFHIGHLAT = 0x03
+};
+
+/**
+ * enum arm_opp - ARM OPP states definition
+ * @ARM_OPP_INIT:
+ * @ARM_NO_CHANGE: The ARM operating point is unchanged
+ * @ARM_100_OPP: The new ARM operating point is arm100opp
+ * @ARM_50_OPP: The new ARM operating point is arm50opp
+ * @ARM_MAX_OPP: Operating point is "max" (more than 100)
+ * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100
+ * @ARM_EXTCLK: The new ARM operating point is armExtClk
+ */
+enum arm_opp {
+ ARM_OPP_INIT = 0x00,
+ ARM_NO_CHANGE = 0x01,
+ ARM_100_OPP = 0x02,
+ ARM_50_OPP = 0x03,
+ ARM_MAX_OPP = 0x04,
+ ARM_MAX_FREQ100OPP = 0x05,
+ ARM_EXTCLK = 0x07
+};
+
+/**
+ * enum ape_opp - APE OPP states definition
+ * @APE_OPP_INIT:
+ * @APE_NO_CHANGE: The APE operating point is unchanged
+ * @APE_100_OPP: The new APE operating point is ape100opp
+ * @APE_50_OPP: 50%
+ */
+enum ape_opp {
+ APE_OPP_INIT = 0x00,
+ APE_NO_CHANGE = 0x01,
+ APE_100_OPP = 0x02,
+ APE_50_OPP = 0x03
+};
+
+/**
+ * enum hw_acc_state - State definition for hardware accelerator
+ * @HW_NO_CHANGE: The hardware accelerator state must remain unchanged
+ * @HW_OFF: The hardware accelerator must be switched off
+ * @HW_OFF_RAMRET: The hardware accelerator must be switched off with its
+ * internal RAM in retention
+ * @HW_ON: The hwa hardware accelerator hwa must be switched on
+ *
+ * NOTE! Deprecated, to be removed when all users switched over to use the
+ * regulator API.
+ */
+enum hw_acc_state {
+ HW_NO_CHANGE = 0x00,
+ HW_OFF = 0x01,
+ HW_OFF_RAMRET = 0x02,
+ HW_ON = 0x04
+};
+
+/**
+ * enum mbox_2_arm_stat - Status messages definition for mbox_arm
+ * @BOOT_TO_EXECUTEOK: The apBoot to apExecute state transition has been
+ * completed
+ * @DEEPSLEEPOK: The apExecute to apDeepSleep state transition has been
+ * completed
+ * @SLEEPOK: The apExecute to apSleep state transition has been completed
+ * @IDLEOK: The apExecute to apIdle state transition has been completed
+ * @SOFTRESETOK: The A9 watchdog/ SoftReset state has been completed
+ * @SOFTRESETGO : The A9 watchdog/SoftReset state is on going
+ * @BOOT_TO_EXECUTE: The apBoot to apExecute state transition is on going
+ * @EXECUTE_TO_DEEPSLEEP: The apExecute to apDeepSleep state transition is on
+ * going
+ * @DEEPSLEEP_TO_EXECUTE: The apDeepSleep to apExecute state transition is on
+ * going
+ * @DEEPSLEEP_TO_EXECUTEOK: The apDeepSleep to apExecute state transition has
+ * been completed
+ * @EXECUTE_TO_SLEEP: The apExecute to apSleep state transition is on going
+ * @SLEEP_TO_EXECUTE: The apSleep to apExecute state transition is on going
+ * @SLEEP_TO_EXECUTEOK: The apSleep to apExecute state transition has been
+ * completed
+ * @EXECUTE_TO_IDLE: The apExecute to apIdle state transition is on going
+ * @IDLE_TO_EXECUTE: The apIdle to apExecute state transition is on going
+ * @IDLE_TO_EXECUTEOK: The apIdle to apExecute state transition has been
+ * completed
+ * @INIT_STATUS: Status init
+ */
+enum ap_pwrsttr_status {
+ BOOT_TO_EXECUTEOK = 0xFF,
+ DEEPSLEEPOK = 0xFE,
+ SLEEPOK = 0xFD,
+ IDLEOK = 0xFC,
+ SOFTRESETOK = 0xFB,
+ SOFTRESETGO = 0xFA,
+ BOOT_TO_EXECUTE = 0xF9,
+ EXECUTE_TO_DEEPSLEEP = 0xF8,
+ DEEPSLEEP_TO_EXECUTE = 0xF7,
+ DEEPSLEEP_TO_EXECUTEOK = 0xF6,
+ EXECUTE_TO_SLEEP = 0xF5,
+ SLEEP_TO_EXECUTE = 0xF4,
+ SLEEP_TO_EXECUTEOK = 0xF3,
+ EXECUTE_TO_IDLE = 0xF2,
+ IDLE_TO_EXECUTE = 0xF1,
+ IDLE_TO_EXECUTEOK = 0xF0,
+ RDYTODS_RETURNTOEXE = 0xEF,
+ NORDYTODS_RETURNTOEXE = 0xEE,
+ EXETOSLEEP_RETURNTOEXE = 0xED,
+ EXETOIDLE_RETURNTOEXE = 0xEC,
+ INIT_STATUS = 0xEB,
+
+ /*error messages */
+ INITERROR = 0x00,
+ PLLARMLOCKP_ER = 0x01,
+ PLLDDRLOCKP_ER = 0x02,
+ PLLSOCLOCKP_ER = 0x03,
+ PLLSOCK1LOCKP_ER = 0x04,
+ ARMWFI_ER = 0x05,
+ SYSCLKOK_ER = 0x06,
+ I2C_NACK_DATA_ER = 0x07,
+ BOOT_ER = 0x08,
+ I2C_STATUS_ALWAYS_1 = 0x0A,
+ I2C_NACK_REG_ADDR_ER = 0x0B,
+ I2C_NACK_DATA0123_ER = 0x1B,
+ I2C_NACK_ADDR_ER = 0x1F,
+ CURAPPWRSTISNOT_BOOT = 0x20,
+ CURAPPWRSTISNOT_EXECUTE = 0x21,
+ CURAPPWRSTISNOT_SLEEPMODE = 0x22,
+ CURAPPWRSTISNOT_CORRECTFORIT10 = 0x23,
+ FIFO4500WUISNOT_WUPEVENT = 0x24,
+ PLL32KLOCKP_ER = 0x29,
+ DDRDEEPSLEEPOK_ER = 0x2A,
+ ROMCODEREADY_ER = 0x50,
+ WUPBEFOREDS = 0x51,
+ DDRCONFIG_ER = 0x52,
+ WUPBEFORESLEEP = 0x53,
+ WUPBEFOREIDLE = 0x54
+}; /* earlier called as mbox_2_arm_stat */
+
+/**
+ * enum dvfs_stat - DVFS status messages definition
+ * @DVFS_GO: A state transition DVFS is on going
+ * @DVFS_ARM100OPPOK: The state transition DVFS has been completed for 100OPP
+ * @DVFS_ARM50OPPOK: The state transition DVFS has been completed for 50OPP
+ * @DVFS_ARMEXTCLKOK: The state transition DVFS has been completed for EXTCLK
+ * @DVFS_NOCHGTCLKOK: The state transition DVFS has been completed for
+ * NOCHGCLK
+ * @DVFS_INITSTATUS: Value init
+ */
+enum dvfs_stat {
+ DVFS_GO = 0xFF,
+ DVFS_ARM100OPPOK = 0xFE,
+ DVFS_ARM50OPPOK = 0xFD,
+ DVFS_ARMEXTCLKOK = 0xFC,
+ DVFS_NOCHGTCLKOK = 0xFB,
+ DVFS_INITSTATUS = 0x00
+};
+
+/**
+ * enum sva_mmdsp_stat - SVA MMDSP status messages
+ * @SVA_MMDSP_GO: SVAMMDSP interrupt has happened
+ * @SVA_MMDSP_INIT: Status init
+ */
+enum sva_mmdsp_stat {
+ SVA_MMDSP_GO = 0xFF,
+ SVA_MMDSP_INIT = 0x00
+};
+
+/**
+ * enum sia_mmdsp_stat - SIA MMDSP status messages
+ * @SIA_MMDSP_GO: SIAMMDSP interrupt has happened
+ * @SIA_MMDSP_INIT: Status init
+ */
+enum sia_mmdsp_stat {
+ SIA_MMDSP_GO = 0xFF,
+ SIA_MMDSP_INIT = 0x00
+};
+
+/**
+ * enum mbox_to_arm_err - Error messages definition
+ * @INIT_ERR: Init value
+ * @PLLARMLOCKP_ERR: PLLARM has not been correctly locked in given time
+ * @PLLDDRLOCKP_ERR: PLLDDR has not been correctly locked in the given time
+ * @PLLSOC0LOCKP_ERR: PLLSOC0 has not been correctly locked in the given time
+ * @PLLSOC1LOCKP_ERR: PLLSOC1 has not been correctly locked in the given time
+ * @ARMWFI_ERR: The ARM WFI has not been correctly executed in the given time
+ * @SYSCLKOK_ERR: The SYSCLK is not available in the given time
+ * @BOOT_ERR: Romcode has not validated the XP70 self reset in the given time
+ * @ROMCODESAVECONTEXT: The Romcode didn.t correctly save it secure context
+ * @VARMHIGHSPEEDVALTO_ERR: The ARM high speed supply value transfered
+ * through I2C has not been correctly executed in the given time
+ * @VARMHIGHSPEEDACCESS_ERR: The command value of VarmHighSpeedVal transfered
+ * through I2C has not been correctly executed in the given time
+ * @VARMLOWSPEEDVALTO_ERR:The ARM low speed supply value transfered through
+ * I2C has not been correctly executed in the given time
+ * @VARMLOWSPEEDACCESS_ERR: The command value of VarmLowSpeedVal transfered
+ * through I2C has not been correctly executed in the given time
+ * @VARMRETENTIONVALTO_ERR: The ARM retention supply value transfered through
+ * I2C has not been correctly executed in the given time
+ * @VARMRETENTIONACCESS_ERR: The command value of VarmRetentionVal transfered
+ * through I2C has not been correctly executed in the given time
+ * @VAPEHIGHSPEEDVALTO_ERR: The APE highspeed supply value transfered through
+ * I2C has not been correctly executed in the given time
+ * @VSAFEHPVALTO_ERR: The SAFE high power supply value transfered through I2C
+ * has not been correctly executed in the given time
+ * @VMODSEL1VALTO_ERR: The MODEM sel1 supply value transfered through I2C has
+ * not been correctly executed in the given time
+ * @VMODSEL2VALTO_ERR: The MODEM sel2 supply value transfered through I2C has
+ * not been correctly executed in the given time
+ * @VARMOFFACCESS_ERR: The command value of Varm ON/OFF transfered through
+ * I2C has not been correctly executed in the given time
+ * @VAPEOFFACCESS_ERR: The command value of Vape ON/OFF transfered through
+ * I2C has not been correctly executed in the given time
+ * @VARMRETACCES_ERR: The command value of Varm retention ON/OFF transfered
+ * through I2C has not been correctly executed in the given time
+ * @CURAPPWRSTISNOTBOOT:Generated when Arm want to do power state transition
+ * ApBoot to ApExecute but the power current state is not Apboot
+ * @CURAPPWRSTISNOTEXECUTE: Generated when Arm want to do power state
+ * transition from ApExecute to others power state but the
+ * power current state is not ApExecute
+ * @CURAPPWRSTISNOTSLEEPMODE: Generated when wake up events are transmitted
+ * but the power current state is not ApDeepSleep/ApSleep/ApIdle
+ * @CURAPPWRSTISNOTCORRECTDBG: Generated when wake up events are transmitted
+ * but the power current state is not correct
+ * @ARMREGU1VALTO_ERR:The ArmRegu1 value transferred through I2C has not
+ * been correctly executed in the given time
+ * @ARMREGU2VALTO_ERR: The ArmRegu2 value transferred through I2C has not
+ * been correctly executed in the given time
+ * @VAPEREGUVALTO_ERR: The VApeRegu value transfered through I2C has not
+ * been correctly executed in the given time
+ * @VSMPS3REGUVALTO_ERR: The VSmps3Regu value transfered through I2C has not
+ * been correctly executed in the given time
+ * @VMODREGUVALTO_ERR: The VModemRegu value transfered through I2C has not
+ * been correctly executed in the given time
+ */
+enum mbox_to_arm_err {
+ INIT_ERR = 0x00,
+ PLLARMLOCKP_ERR = 0x01,
+ PLLDDRLOCKP_ERR = 0x02,
+ PLLSOC0LOCKP_ERR = 0x03,
+ PLLSOC1LOCKP_ERR = 0x04,
+ ARMWFI_ERR = 0x05,
+ SYSCLKOK_ERR = 0x06,
+ BOOT_ERR = 0x07,
+ ROMCODESAVECONTEXT = 0x08,
+ VARMHIGHSPEEDVALTO_ERR = 0x10,
+ VARMHIGHSPEEDACCESS_ERR = 0x11,
+ VARMLOWSPEEDVALTO_ERR = 0x12,
+ VARMLOWSPEEDACCESS_ERR = 0x13,
+ VARMRETENTIONVALTO_ERR = 0x14,
+ VARMRETENTIONACCESS_ERR = 0x15,
+ VAPEHIGHSPEEDVALTO_ERR = 0x16,
+ VSAFEHPVALTO_ERR = 0x17,
+ VMODSEL1VALTO_ERR = 0x18,
+ VMODSEL2VALTO_ERR = 0x19,
+ VARMOFFACCESS_ERR = 0x1A,
+ VAPEOFFACCESS_ERR = 0x1B,
+ VARMRETACCES_ERR = 0x1C,
+ CURAPPWRSTISNOTBOOT = 0x20,
+ CURAPPWRSTISNOTEXECUTE = 0x21,
+ CURAPPWRSTISNOTSLEEPMODE = 0x22,
+ CURAPPWRSTISNOTCORRECTDBG = 0x23,
+ ARMREGU1VALTO_ERR = 0x24,
+ ARMREGU2VALTO_ERR = 0x25,
+ VAPEREGUVALTO_ERR = 0x26,
+ VSMPS3REGUVALTO_ERR = 0x27,
+ VMODREGUVALTO_ERR = 0x28
+};
+
+enum hw_acc {
+ SVAMMDSP = 0,
+ SVAPIPE = 1,
+ SIAMMDSP = 2,
+ SIAPIPE = 3,
+ SGA = 4,
+ B2R2MCDE = 5,
+ ESRAM12 = 6,
+ ESRAM34 = 7,
+};
+
+enum cs_pwrmgt {
+ PWRDNCS0 = 0,
+ WKUPCS0 = 1,
+ PWRDNCS1 = 2,
+ WKUPCS1 = 3
+};
+
+/* Defs related to autonomous power management */
+
+/**
+ * enum sia_sva_pwr_policy - Power policy
+ * @NO_CHGT: No change
+ * @DSPOFF_HWPOFF:
+ * @DSPOFFRAMRET_HWPOFF:
+ * @DSPCLKOFF_HWPOFF:
+ * @DSPCLKOFF_HWPCLKOFF:
+ *
+ */
+enum sia_sva_pwr_policy {
+ NO_CHGT = 0x0,
+ DSPOFF_HWPOFF = 0x1,
+ DSPOFFRAMRET_HWPOFF = 0x2,
+ DSPCLKOFF_HWPOFF = 0x3,
+ DSPCLKOFF_HWPCLKOFF = 0x4,
+};
+
+/**
+ * enum auto_enable - Auto Power enable
+ * @AUTO_OFF:
+ * @AUTO_ON:
+ *
+ */
+enum auto_enable {
+ AUTO_OFF = 0x0,
+ AUTO_ON = 0x1,
+};
+
+#endif /* __MACH_PRCMU_FW_DEFS_V1_H */
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
new file mode 100644
index 00000000000..5478a553d60
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2009 ST-Ericsson SA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+#ifndef __MACH_PRCMU_REGS_H
+#define __MACH_PRCMU_REGS_H
+
+#include <mach/hardware.h>
+
+#define PRCM_ARM_PLLDIVPS (_PRCMU_BASE + 0x118)
+#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE 0x3f
+#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xf
+
+#define PRCM_PLLARM_LOCKP (_PRCMU_BASE + 0x0a8)
+#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 0x2
+
+#define PRCM_ARM_CHGCLKREQ (_PRCMU_BASE + 0x114)
+#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ 0x1
+
+#define PRCM_PLLARM_ENABLE (_PRCMU_BASE + 0x98)
+#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE 0x1
+#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON 0x100
+
+#define PRCM_ARMCLKFIX_MGT (_PRCMU_BASE + 0x0)
+#define PRCM_A9_RESETN_CLR (_PRCMU_BASE + 0x1f4)
+#define PRCM_A9_RESETN_SET (_PRCMU_BASE + 0x1f0)
+#define PRCM_ARM_LS_CLAMP (_PRCMU_BASE + 0x30c)
+#define PRCM_SRAM_A9 (_PRCMU_BASE + 0x308)
+
+/* ARM WFI Standby signal register */
+#define PRCM_ARM_WFI_STANDBY (_PRCMU_BASE + 0x130)
+#define PRCM_IOCR (_PRCMU_BASE + 0x310)
+#define PRCM_IOCR_IOFORCE 0x1
+
+/* CPU mailbox registers */
+#define PRCM_MBOX_CPU_VAL (_PRCMU_BASE + 0x0fc)
+#define PRCM_MBOX_CPU_SET (_PRCMU_BASE + 0x100)
+#define PRCM_MBOX_CPU_CLR (_PRCMU_BASE + 0x104)
+
+/* Dual A9 core interrupt management unit registers */
+#define PRCM_A9_MASK_REQ (_PRCMU_BASE + 0x328)
+#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ 0x1
+
+#define PRCM_A9_MASK_ACK (_PRCMU_BASE + 0x32c)
+#define PRCM_ARMITMSK31TO0 (_PRCMU_BASE + 0x11c)
+#define PRCM_ARMITMSK63TO32 (_PRCMU_BASE + 0x120)
+#define PRCM_ARMITMSK95TO64 (_PRCMU_BASE + 0x124)
+#define PRCM_ARMITMSK127TO96 (_PRCMU_BASE + 0x128)
+#define PRCM_POWER_STATE_VAL (_PRCMU_BASE + 0x25C)
+#define PRCM_ARMITVAL31TO0 (_PRCMU_BASE + 0x260)
+#define PRCM_ARMITVAL63TO32 (_PRCMU_BASE + 0x264)
+#define PRCM_ARMITVAL95TO64 (_PRCMU_BASE + 0x268)
+#define PRCM_ARMITVAL127TO96 (_PRCMU_BASE + 0x26C)
+
+#define PRCM_HOSTACCESS_REQ (_PRCMU_BASE + 0x334)
+#define ARM_WAKEUP_MODEM 0x1
+
+#define PRCM_ARM_IT1_CLEAR (_PRCMU_BASE + 0x48C)
+#define PRCM_ARM_IT1_VAL (_PRCMU_BASE + 0x494)
+#define PRCM_HOLD_EVT (_PRCMU_BASE + 0x174)
+
+#define PRCM_ITSTATUS0 (_PRCMU_BASE + 0x148)
+#define PRCM_ITSTATUS1 (_PRCMU_BASE + 0x150)
+#define PRCM_ITSTATUS2 (_PRCMU_BASE + 0x158)
+#define PRCM_ITSTATUS3 (_PRCMU_BASE + 0x160)
+#define PRCM_ITSTATUS4 (_PRCMU_BASE + 0x168)
+#define PRCM_ITSTATUS5 (_PRCMU_BASE + 0x484)
+#define PRCM_ITCLEAR5 (_PRCMU_BASE + 0x488)
+#define PRCM_ARMIT_MASKXP70_IT (_PRCMU_BASE + 0x1018)
+
+/* System reset register */
+#define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228)
+
+/* Level shifter and clamp control registers */
+#define PRCM_MMIP_LS_CLAMP_SET (_PRCMU_BASE + 0x420)
+#define PRCM_MMIP_LS_CLAMP_CLR (_PRCMU_BASE + 0x424)
+
+/* PRCMU clock/PLL/reset registers */
+#define PRCM_PLLDSI_FREQ (_PRCMU_BASE + 0x500)
+#define PRCM_PLLDSI_ENABLE (_PRCMU_BASE + 0x504)
+#define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508)
+#define PRCM_LCDCLK_MGT (_PRCMU_BASE + 0x044)
+#define PRCM_MCDECLK_MGT (_PRCMU_BASE + 0x064)
+#define PRCM_HDMICLK_MGT (_PRCMU_BASE + 0x058)
+#define PRCM_TVCLK_MGT (_PRCMU_BASE + 0x07c)
+#define PRCM_DSI_PLLOUT_SEL (_PRCMU_BASE + 0x530)
+#define PRCM_DSITVCLK_DIV (_PRCMU_BASE + 0x52C)
+#define PRCM_PLLDSI_LOCKP (_PRCMU_BASE + 0x508)
+#define PRCM_APE_RESETN_SET (_PRCMU_BASE + 0x1E4)
+#define PRCM_APE_RESETN_CLR (_PRCMU_BASE + 0x1E8)
+#define PRCM_CLKOCR (_PRCMU_BASE + 0x1CC)
+
+/* ePOD and memory power signal control registers */
+#define PRCM_EPOD_C_SET (_PRCMU_BASE + 0x410)
+#define PRCM_SRAM_LS_SLEEP (_PRCMU_BASE + 0x304)
+
+/* Debug power control unit registers */
+#define PRCM_POWER_STATE_SET (_PRCMU_BASE + 0x254)
+
+/* Miscellaneous unit registers */
+#define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324)
+#define PRCM_GPIOCR (_PRCMU_BASE + 0x138)
+#define PRCM_GPIOCR_DBG_STM_MOD_CMD1 0x800
+#define PRCM_GPIOCR_DBG_UARTMOD_CMD0 0x1
+
+
+#endif /* __MACH_PRCMU__REGS_H */
diff --git a/arch/arm/mach-ux500/include/mach/reboot_reasons.h b/arch/arm/mach-ux500/include/mach/reboot_reasons.h
new file mode 100644
index 00000000000..06a73754b56
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/reboot_reasons.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ * Author: Rickard Evertsson <rickard.evertsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Use this file to customize your reboot / sw reset reasons. Add, remove or
+ * modify reasons in reboot_reasons[].
+ * The reboot reasons will be saved to a secure location in TCDM memory and
+ * can be read at bootup by e.g. the bootloader.
+ */
+
+#ifndef _REBOOT_REASONS_H
+#define _REBOOT_REASONS_H
+
+/*
+ * These defines contains the codes that will be written down to a secure
+ * location before resetting. These values are just dummy values and does not,
+ * at the moment, affect anything.
+ */
+#define SW_RESET_NO_ARGUMENT 0x0
+#define SW_RESET_CRASH 0xDEAD
+#define SW_RESET_NORMAL 0xc001
+
+/*
+ * The array reboot_reasons[] is used when you want to map a string to a reboot
+ * reason code
+ */
+struct reboot_reason {
+ const char *reason;
+ unsigned short code;
+};
+
+extern struct reboot_reason reboot_reasons[];
+
+extern unsigned int reboot_reasons_size;
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/regulator.h b/arch/arm/mach-ux500/include/mach/regulator.h
new file mode 100644
index 00000000000..75ff3340359
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/regulator.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Bengt Jonsson <bengt.jonsson@stericsson.com> for ST-Ericsson,
+ * Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
+ *
+ * License Terms: GNU General Public License v2
+ *
+ */
+
+#ifndef MACH_UX500_REGULATOR_H
+#define MACH_UX500_REGULATOR_H
+
+#include <linux/device.h>
+
+struct ux500_regulator;
+
+#ifdef CONFIG_REGULATOR
+/*
+ * NOTE! The device will be connected to the correct regulator by this
+ * new framework. A list with connections will match up dev_name(dev)
+ * to the specific regulator. This follows the same principle as the
+ * normal regulator framework.
+ *
+ * This framework shall only be used in special cases when a regulator
+ * has to be enabled/disabled in atomic context.
+ */
+
+/**
+ * ux500_regulator_get()
+ *
+ * @dev: Drivers device struct
+ *
+ * Returns a ux500_regulator struct. Shall be used as argument for
+ * ux500_regulator_atomic_enable/disable calls.
+ * Return ERR_PTR(-EINVAL) upon no matching regulator found.
+ */
+struct ux500_regulator *__must_check ux500_regulator_get(struct device *dev);
+
+/**
+ * ux500_regulator_atomic_enable()
+ *
+ * @regulator: Regulator handle, provided from ux500_regulator_get.
+ *
+ * The enable/disable functions keep an internal counter, so every
+ * enable must be paired with an disable in order to turn off regulator.
+ */
+int ux500_regulator_atomic_enable(struct ux500_regulator *regulator);
+
+/**
+ * ux500_regulator_atomic_disable()
+ *
+ * @regulator: Regulator handle, provided from ux500_regulator_get.
+ *
+ */
+int ux500_regulator_atomic_disable(struct ux500_regulator *regulator);
+
+/**
+ * ux500_regulator_put()
+ *
+ * @regulator: Regulator handle, provided from ux500_regulator_get.
+ */
+void ux500_regulator_put(struct ux500_regulator *regulator);
+#else
+static inline struct ux500_regulator *__must_check
+ux500_regulator_get(struct device *dev)
+{
+ return ERR_PTR(-EINVAL);
+}
+
+static inline int
+ux500_regulator_atomic_enable(struct ux500_regulator *regulator)
+{
+ return -EINVAL;
+}
+
+static inline int
+ux500_regulator_atomic_disable(struct ux500_regulator *regulator)
+{
+ return -EINVAL;
+}
+
+static inline void ux500_regulator_put(struct ux500_regulator *regulator)
+{
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/scu.h b/arch/arm/mach-ux500/include/mach/scu.h
new file mode 100644
index 00000000000..a09e86a9d3c
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/scu.h
@@ -0,0 +1,25 @@
+/*
+ * 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/sensors1p.h b/arch/arm/mach-ux500/include/mach/sensors1p.h
new file mode 100644
index 00000000000..544e1d8bab5
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/sensors1p.h
@@ -0,0 +1,24 @@
+
+/*
+ * Copyright (C) 2009-2010 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Header file for 1 pin gpio sensors;
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ */
+
+#ifndef __ASM_ARCH_SFH7741_H
+#define __ASM_ARCH_SFH7741_H
+
+struct sensor_config {
+ int pin;
+ int startup_time; /* in ms */
+ char regulator[32];
+};
+
+struct sensors1p_config {
+ struct sensor_config hal;
+ struct sensor_config proximity;
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index e978dbd9e21..4156b10546e 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -14,7 +14,9 @@
#include <asm/mach/time.h>
#include <linux/init.h>
-extern void __init ux500_map_io(void);
+struct sys_timer;
+struct amba_device;
+
extern void __init u5500_map_io(void);
extern void __init u8500_map_io(void);
@@ -23,13 +25,17 @@ extern void __init u5500_init_devices(void);
extern void __init u8500_init_devices(void);
extern void __init ux500_init_irq(void);
-/* We re-use nomadik_timer for this platform */
-extern void nmdk_timer_init(void);
extern void __init amba_add_devices(struct amba_device *devs[], int num);
struct sys_timer;
-extern struct sys_timer ux500_timer;
+extern struct sys_timer u8500_timer;
+extern void __init db5500_dma_init(void);
+extern void __init db8500_dma_init(void);
+extern void __init db8500_uart_init(void);
+
+extern void __init u8500v2_msp_fixup(void);
+extern void __iomem *gic_cpu_base_addr;
#define __IO_DEV_DESC(x, sz) { \
.virtual = IO_ADDRESS(x), \
@@ -38,4 +44,11 @@ extern struct sys_timer ux500_timer;
.type = MT_DEVICE, \
}
+#define __MEM_DEV_DESC(x, sz) { \
+ .virtual = IO_ADDRESS(x), \
+ .pfn = __phys_to_pfn(x), \
+ .length = sz, \
+ .type = MT_MEMORY, \
+}
+
#endif /* __ASM_ARCH_SETUP_H */
diff --git a/arch/arm/mach-ux500/include/mach/shrm.h b/arch/arm/mach-ux500/include/mach/shrm.h
new file mode 100644
index 00000000000..6deeeb16ba8
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/shrm.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Biju Das <biju.das@stericsson.com> for ST-Ericsson
+ * Author: Kumar Sanghavi <kumar.sanghvi@stericsson.com> for ST-Ericsson
+ * Author: Arun Murthy <arun.murthy@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __SHM_DRIVER_IF_H__
+#define __SHM_DRIVER_IF_H__
+
+#include <linux/device.h>
+
+/* forward declaration */
+struct shrm_dev;
+
+typedef void (*rx_cb)(void *data, unsigned int length);
+typedef void (*received_msg_handler)(unsigned char l2_header,
+ void *msg_ptr, unsigned int length,
+ struct shrm_dev *shrm);
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/shrm_config.h b/arch/arm/mach-ux500/include/mach/shrm_config.h
new file mode 100644
index 00000000000..a82b35ef77b
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/shrm_config.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Biju Das <biju.das@stericsson.com> for ST-Ericsson
+ * Author: Kumar Sanghavi <kumar.sanghvi@stericsson.com> for ST-Ericsson
+ * Author: Arun Murthy <arun.murthy@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __SHRM_CONFIG_H
+#define __SHRM_CONFIG_H
+
+
+/*
+Note: modem need to define IPC as a non-cacheable area.
+In Cortex R4 MPU requires that base address of NC area is aligned on a
+region-sized boundary.On modem side, only 1 NC area can be defined, hence
+the whole IPC area must be defined as NC (at least).
+
+*/
+
+/* cache line size = 32bytes*/
+#define SHM_CACHE_LINE 32
+#define SHM_PTR_SIZE 4
+
+/* FIFO 0 address configuration */
+/* ---------------------------- */
+/* 128KB */
+#define SHM_FIFO_0_SIZE (128*1024)
+
+
+/* == APE addresses == */
+#ifdef CONFIG_SHRM_V1_UPDATES_VERSION
+#define SHM_IPC_BASE_AMCU 0x06F80000
+#else
+#define SHM_IPC_BASE_AMCU 0x06000000
+#endif
+
+/* offset pointers */
+#define SHM_ACFIFO_0_WRITE_AMCU SHM_IPC_BASE_AMCU
+#define SHM_ACFIFO_0_READ_AMCU (SHM_ACFIFO_0_WRITE_AMCU + SHM_PTR_SIZE)
+#define SHM_CAFIFO_0_WRITE_AMCU (SHM_ACFIFO_0_WRITE_AMCU + SHM_CACHE_LINE)
+#define SHM_CAFIFO_0_READ_AMCU (SHM_CAFIFO_0_WRITE_AMCU + SHM_PTR_SIZE)
+/* FIFO start */
+#define SHM_ACFIFO_0_START_AMCU (SHM_CAFIFO_0_WRITE_AMCU + SHM_CACHE_LINE)
+#define SHM_CAFIFO_0_START_AMCU (SHM_ACFIFO_0_START_AMCU + SHM_FIFO_0_SIZE)
+
+
+/* == CMT addresses ==*/
+#define SHM_IPC_BASE_CMCU (SHM_IPC_BASE_AMCU+0x08000000)
+/* offset pointers */
+#define SHM_ACFIFO_0_WRITE_CMCU SHM_IPC_BASE_CMCU
+#define SHM_ACFIFO_0_READ_CMCU (SHM_ACFIFO_0_WRITE_CMCU + SHM_PTR_SIZE)
+#define SHM_CAFIFO_0_WRITE_CMCU (SHM_ACFIFO_0_WRITE_CMCU + SHM_CACHE_LINE)
+#define SHM_CAFIFO_0_READ_CMCU (SHM_CAFIFO_0_WRITE_CMCU + SHM_PTR_SIZE)
+/* FIFO*/
+#define SHM_ACFIFO_0_START_CMCU (SHM_CAFIFO_0_WRITE_CMCU + SHM_CACHE_LINE)
+#define SHM_CAFIFO_0_START_CMCU (SHM_ACFIFO_0_START_CMCU + SHM_FIFO_0_SIZE)
+
+
+/* ADSP addresses*/
+#define SHM_ACFIFO_0_START_ADSP 0x0
+#define SHM_CAFIFO_0_START_ADSP 0x0
+#define SHM_ACFIFO_0_WRITE_ADSP 0x0
+#define SHM_ACFIFO_0_READ_ADSP 0x0
+#define SHM_CAFIFO_0_WRITE_ADSP 0x0
+#define SHM_CAFIFO_0_READ_ADSP 0x0
+
+/* FIFO 1 address configuration */
+/* ---------------------------- */
+
+
+/* FIFO 1 - 4K */
+#define SHM_FIFO_1_SIZE (4*1024)
+
+
+/* == APE addresses == */
+#define SHM_ACFIFO_1_WRITE_AMCU (SHM_CAFIFO_0_START_AMCU + SHM_FIFO_0_SIZE)
+#define SHM_ACFIFO_1_READ_AMCU (SHM_ACFIFO_1_WRITE_AMCU + SHM_PTR_SIZE)
+#define SHM_CAFIFO_1_WRITE_AMCU (SHM_ACFIFO_1_WRITE_AMCU + SHM_CACHE_LINE)
+#define SHM_CAFIFO_1_READ_AMCU (SHM_CAFIFO_1_WRITE_AMCU + SHM_PTR_SIZE)
+/* FIFO*/
+#define SHM_ACFIFO_1_START_AMCU (SHM_CAFIFO_1_WRITE_AMCU + SHM_CACHE_LINE)
+#define SHM_CAFIFO_1_START_AMCU (SHM_ACFIFO_1_START_AMCU + SHM_FIFO_1_SIZE)
+
+
+/* == CMT addresses ==*/
+#define SHM_ACFIFO_1_WRITE_CMCU (SHM_CAFIFO_0_START_CMCU + SHM_FIFO_0_SIZE)
+#define SHM_ACFIFO_1_READ_CMCU (SHM_ACFIFO_1_WRITE_CMCU + SHM_PTR_SIZE)
+#define SHM_CAFIFO_1_WRITE_CMCU (SHM_ACFIFO_1_WRITE_CMCU + SHM_CACHE_LINE)
+#define SHM_CAFIFO_1_READ_CMCU (SHM_CAFIFO_1_WRITE_CMCU + SHM_PTR_SIZE)
+/* FIFO1 start */
+#define SHM_ACFIFO_1_START_CMCU (SHM_CAFIFO_1_WRITE_CMCU + SHM_CACHE_LINE)
+#define SHM_CAFIFO_1_START_CMCU (SHM_ACFIFO_1_START_CMCU + SHM_FIFO_1_SIZE)
+
+
+/* ADSP addresses*/
+#define SHM_ACFIFO_1_START_ADSP 0x0
+#define SHM_CAFIFO_1_START_ADSP 0x0
+#define SHM_ACFIFO_1_WRITE_ADSP 0x0
+#define SHM_ACFIFO_1_READ_ADSP 0x0
+#define SHM_CAFIFO_1_WRITE_ADSP 0x0
+#define SHM_CAFIFO_1_READ_ADSP 0x0
+
+
+#define U8500_SHM_FIFO_APE_COMMON_BASE (SHM_ACFIFO_0_START_AMCU)
+#define U8500_SHM_FIFO_CMT_COMMON_BASE (SHM_CAFIFO_0_START_AMCU)
+#define U8500_SHM_FIFO_APE_AUDIO_BASE (SHM_ACFIFO_1_START_AMCU)
+#define U8500_SHM_FIFO_CMT_AUDIO_BASE (SHM_CAFIFO_1_START_AMCU)
+
+#endif /* __SHRM_CONFIG_H */
diff --git a/arch/arm/mach-ux500/include/mach/shrm_driver.h b/arch/arm/mach-ux500/include/mach/shrm_driver.h
new file mode 100644
index 00000000000..41f518238b3
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/shrm_driver.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Biju Das <biju.das@stericsson.com> for ST-Ericsson
+ * Author: Kumar Sanghavi <kumar.sanghvi@stericsson.com> for ST-Ericsson
+ * Author: Arun Murthy <arun.murthy@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __SHRM_DRIVER_H__
+#define __SHRM_DRIVER_H__
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+
+#include <mach/shrm.h>
+
+#include <linux/cdev.h>
+
+#define ISA_DEVICES 6
+
+#define BOOT_INIT (0)
+#define BOOT_INFO_SYNC (1)
+#define BOOT_DONE (2)
+#define BOOT_UNKNOWN (3)
+
+/**
+ * struct shrm_dev - shrm device information
+ * @ca_wake_irq: CMT wake interrupt number
+ * @ac_read_notif_0_irq: ape-cmt common channel read notify interrupt
+ * @ac_read_notif_1_irq: ape-cmt audio channel read notify interrupt
+ * @ca_msg_pending_notif_0_irq: cmt-ape common channel msg pending interrupt
+ * @ca_msg_pending_notif_1_irq: cmt-ape audio channel msg pending interrupt
+ * @intr_base: interrupt base register address
+ * @ape_common_fifo_base: ape side common channel fifo base addr
+ * @ape_audio_fifo_base: ape side audio channel fifo base addr
+ * @cmt_common_fifo_base: cmt side common channel fifo base addr
+ * @cmt_audio_fifo_base: cmt side audio channel fifo base addr
+ * @ape_common_fifo_base_phy: physical addr of ape common fifo
+ * @ape_audio_fifo_base_phy: physical addr of ape audio fifo
+ * @cmt_common_fifo_base_phy: physical addr of cmt common fifo
+ * @cmt_audio_fifo_base_phy: physical addr of cmt audio fifo
+ * @ape_common_fifo_size: ape side common channel fifo size
+ * @ape_audio_fifo_size: ape side audio channel fifo size
+ * @cmt_common_fifo_size: cmt side common channel fifo size
+ * @cmt_audio_fifo_size: cmt side audio channel fifo size
+ * @netdev_flag_up: flag to indicate up/down of netwok device
+ * @msr_flag: flag to check on-going MSR sequence
+ * @ac_common_shared_wptr: ape-cmt common channel write pointer
+ * @ac_common_shared_rptr: ape-cmt common channel read pointer
+ * @ca_common_shared_wptr: cmt-ape common channel write pointer
+ * @ca_common_shared_rptr: cmt-ape common channel read pointer
+ * @ac_audio_shared_wptr: ape-cmt audio channel write pointer
+ * @ac_audio_shared_rptr: ape-cmt audio channel read pointer
+ * @ca_audio_shared_wptr: cmt-ape audio channel write pointer
+ * @ca_audio_shared_rptr: cmt-ape audio channel read pointer
+ * @dev: pointer to the driver device
+ * @ndev: pointer to the network device structure
+ * @isa_context: pointer to t_isa_driver_sontext dtructure
+ * @shm_common_ch_wr_wq: work queue for writing to common channel
+ * @shm_audio_ch_wr_wq: workqueue for writing to audio channel
+ * @shm_ac_wake_wq: workqueue for receiving ape-cmt wake requests
+ * @shm_ca_wake_wq: workqueue for receiving cmt-ape wake requests
+ * @shm_ac_sleep_wq: workqueue for recieving ape-cmt sleep requests
+ * @send_ac_msg_pend_notify_0: work for handling pending message on common
+ * channel
+ * @send_ac_msg_pend_notify_1: work for handling pending message on audio
+ * channel
+ * @shm_ac_wake_req: work to send ape-cmt wake request
+ * @shm_ca_wake_req: work to send cmt-ape wake request
+ * @shm_ca_sleep_req: work to send cmt-ape sleep request
+ * @shm_ac_sleep_req: work to send ape-cmt sleep request
+ */
+struct shrm_dev {
+ u8 ca_wake_irq;
+ u8 ac_read_notif_0_irq;
+ u8 ac_read_notif_1_irq;
+ u8 ca_msg_pending_notif_0_irq;
+ u8 ca_msg_pending_notif_1_irq;
+ void __iomem *intr_base;
+ void __iomem *ape_common_fifo_base;
+ void __iomem *ape_audio_fifo_base;
+ void __iomem *cmt_common_fifo_base;
+ void __iomem *cmt_audio_fifo_base;
+
+ u32 *ape_common_fifo_base_phy;
+ u32 *ape_audio_fifo_base_phy;
+ u32 *cmt_common_fifo_base_phy;
+ u32 *cmt_audio_fifo_base_phy;
+
+ int ape_common_fifo_size;
+ int ape_audio_fifo_size;
+ int cmt_common_fifo_size;
+ int cmt_audio_fifo_size;
+ int netdev_flag_up;
+ int msr_flag;
+
+ void __iomem *ac_common_shared_wptr;
+ void __iomem *ac_common_shared_rptr;
+ void __iomem *ca_common_shared_wptr;
+ void __iomem *ca_common_shared_rptr;
+
+ void __iomem *ac_audio_shared_wptr;
+ void __iomem *ac_audio_shared_rptr;
+ void __iomem *ca_audio_shared_wptr;
+ void __iomem *ca_audio_shared_rptr;
+
+ struct device *dev;
+ struct net_device *ndev;
+ struct isa_driver_context *isa_context;
+ struct workqueue_struct *shm_common_ch_wr_wq;
+ struct workqueue_struct *shm_audio_ch_wr_wq;
+ struct workqueue_struct *shm_ac_wake_wq;
+ struct workqueue_struct *shm_ca_wake_wq;
+ struct workqueue_struct *shm_ac_sleep_wq;
+ struct work_struct send_ac_msg_pend_notify_0;
+ struct work_struct send_ac_msg_pend_notify_1;
+ struct work_struct shm_ac_wake_req;
+ struct work_struct shm_ca_wake_req;
+ struct work_struct shm_ca_sleep_req;
+ struct work_struct shm_ac_sleep_req;
+};
+
+/**
+ * struct queue_element - information to add an element to queue
+ * @entry: list entry
+ * @offset: message offset
+ * @size: message size
+ * @no: total number of messages
+ */
+struct queue_element {
+ struct list_head entry;
+ u32 offset;
+ u32 size;
+ u32 no;
+};
+
+/**
+ * struct message_queue - ISI, RPC, AUDIO, SECURITY message queue information
+ * @fifo_base: pointer to the respective fifo base
+ * @size: size of the data to be read
+ * @readptr: fifo read pointer
+ * @writeptr: fifo write pointer
+ * @no: total number of messages
+ * @update_lock: spinlock for protecting the queue read operation
+ * @q_rp: queue write pointer
+ * @wq_readable: wait queue head
+ * @msg_list: message list
+ * @shrm: pointer to shrm device information structure
+ */
+struct message_queue {
+ u8 *fifo_base;
+ u32 size;
+ u32 readptr;
+ u32 writeptr;
+ u32 no;
+ spinlock_t update_lock;
+ atomic_t q_rp;
+ wait_queue_head_t wq_readable;
+ struct list_head msg_list;
+ struct shrm_dev *shrm;
+};
+
+/**
+ * struct isadev_context - shrm char interface context
+ * @dl_queue: structre to store the queue related info
+ * @device_id: message id(ISI, RPC, AUDIO, SECURITY)
+ */
+struct isadev_context {
+ struct message_queue dl_queue;
+ u8 device_id;
+ void *addr;
+};
+
+/**
+ * struct isa_driver_context - shrm char interface device information
+ * @is_open: flag to check the usage of queue
+ * @isadev: pointer to struct t_isadev_context
+ * @common_tx: spinlock for protecting common channel
+ * @tx_audio_mutex: mutex for protecting audio channel
+ * @cdev: character device structre
+ * @shm_class: pointer to the class structure
+ */
+struct isa_driver_context {
+ atomic_t is_open[ISA_DEVICES];
+ struct isadev_context *isadev;
+ spinlock_t common_tx;
+ struct mutex tx_audio_mutex;
+ struct cdev cdev;
+ struct class *shm_class;
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/shrm_net.h b/arch/arm/mach-ux500/include/mach/shrm_net.h
new file mode 100644
index 00000000000..a97b276ee15
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/shrm_net.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2009
+ *
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __SHRM_NET_H
+#define __SHRM_NET_H
+
+#define SHRM_HLEN 1
+#define PHONET_ALEN 1
+
+#define PN_PIPE 0xD9
+#define PN_DEV_HOST 0x00
+#define PN_LINK_ADDR 0x26
+#define PN_TX_QUEUE_LEN 3
+
+#define RESOURCE_ID_INDEX 3
+#define SRC_OBJ_INDEX 7
+#define MSG_ID_INDEX 9
+#define PIPE_HDL_INDEX 10
+#define NETLINK_SHRM 20
+
+/**
+ * struct shrm_net_iface_priv - shrm net interface device information
+ * @shrm_device: pointer to the shrm device information structure
+ * @iface_num: flag used to indicate the up/down of netdev
+ */
+struct shrm_net_iface_priv {
+ struct shrm_dev *shrm_device;
+ unsigned int iface_num;
+};
+
+int shrm_register_netdev(struct shrm_dev *shrm_dev_data);
+int shrm_net_receive(struct net_device *dev);
+int shrm_suspend_netdev(struct net_device *dev);
+int shrm_resume_netdev(struct net_device *dev);
+int shrm_stop_netdev(struct net_device *dev);
+int shrm_restart_netdev(struct net_device *dev);
+int shrm_start_netdev(struct net_device *dev);
+void shrm_unregister_netdev(struct shrm_dev *shrm_dev_data);
+
+#endif /* __SHRM_NET_H */
diff --git a/arch/arm/mach-ux500/include/mach/shrm_private.h b/arch/arm/mach-ux500/include/mach/shrm_private.h
new file mode 100644
index 00000000000..33a0e18234b
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/shrm_private.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Biju Das <biju.das@stericsson.com> for ST-Ericsson
+ * Author: Kumar Sanghavi <kumar.sanghvi@stericsson.com> for ST-Ericsson
+ * Author: Arun Murthy <arun.murthy@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef __SHRM_PRIVATE_INCLUDED
+#define __SHRM_PRIVATE_INCLUDED
+
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <mach/shrm.h>
+
+#define GOP_OUTPUT_REGISTER_BASE (0x0)
+#define GOP_SET_REGISTER_BASE (0x4)
+#define GOP_CLEAR_REGISTER_BASE (0x8)
+#define GOP_TOGGLE_REGISTER_BASE (0xc)
+
+
+#define GOP_AUDIO_AC_READ_NOTIFICATION_BIT (0)
+#define GOP_AUDIO_CA_MSG_PENDING_NOTIFICATION_BIT (1)
+#define GOP_COMMON_AC_READ_NOTIFICATION_BIT (2)
+#define GOP_COMMON_CA_MSG_PENDING_NOTIFICATION_BIT (3)
+#define GOP_CA_WAKE_REQ_BIT (7)
+#define GOP_AUDIO_CA_READ_NOTIFICATION_BIT (23)
+#define GOP_AUDIO_AC_MSG_PENDING_NOTIFICATION_BIT (24)
+#define GOP_COMMON_CA_READ_NOTIFICATION_BIT (25)
+#define GOP_COMMON_AC_MSG_PENDING_NOTIFICATION_BIT (26)
+#define GOP_CA_WAKE_ACK_BIT (27)
+
+#define L2_MSG_MAPID_OFFSET (24)
+#define L1_MSG_MAPID_OFFSET (28)
+
+#define SHRM_SLEEP_STATE (0)
+#define SHRM_PTR_FREE (1)
+#define SHRM_PTR_BUSY (2)
+#define SHRM_IDLE (3)
+
+#define ISI_MESSAGING (0)
+#define RPC_MESSAGING (1)
+#define AUDIO_MESSAGING (2)
+#define SECURITY_MESSAGING (3)
+#define COMMON_LOOPBACK_MESSAGING (0xC0)
+#define AUDIO_LOOPBACK_MESSAGING (0x80)
+
+#define COMMON_CHANNEL 0
+#define AUDIO_CHANNEL 1
+
+typedef void (*MSG_PENDING_NOTIF)(const u32 Wptr);
+
+/**
+ * struct fifo_write_params - parameters used for FIFO write operation.
+ * @writer_local_rptr: pointer to local read buffer
+ * @writer_local_wptr: pointer to local write buffer
+ * @shared_wptr: write pointer shared by cmt and ape
+ * @shared_rptr: read pointer shared by cmt and ape
+ * @availablesize: available memory in fifo
+ * @end_addr_fifo: fifo end addr
+ * @fifo_virtual_addr: fifo virtual addr
+ *
+ * On writting a message to FIFO the same has to be read by the modem before
+ * writing the next message to the FIFO. In oder to over come this a local
+ * write and read pointer is used for internal purpose.
+ */
+struct fifo_write_params {
+ u32 writer_local_rptr;
+ u32 writer_local_wptr;
+ u32 shared_wptr;
+ u32 shared_rptr;
+ u32 availablesize;
+ u32 end_addr_fifo;
+ u32 *fifo_virtual_addr;
+ spinlock_t fifo_update_lock;
+} ;
+
+/**
+ * struct fifo_read_params - parameters used for FIFO read operation
+ * @reader_local_rptr: pointer to local read buffer
+ * @reader_local_wptr: pointer to local write buffer
+ * @shared_wptr: write pointer shared by cmt and ape
+ * @shared_rptr: read pointer shared by cmt and ape
+ * @availablesize: available memory in fifo
+ * @end_addr_fifo: fifo end add
+ * @fifo_virtual_addr: fifo virtual addr
+ */
+struct fifo_read_params{
+ u32 reader_local_rptr;
+ u32 reader_local_wptr;
+ u32 shared_wptr;
+ u32 shared_rptr;
+ u32 availablesize;
+ u32 end_addr_fifo;
+ u32 *fifo_virtual_addr;
+
+} ;
+
+int shrm_protocol_init(struct shrm_dev *shrm,
+ received_msg_handler common_rx_handler,
+ received_msg_handler audio_rx_handler);
+void shrm_protocol_deinit(struct shrm_dev *shrm);
+void shm_fifo_init(struct shrm_dev *shrm);
+int shm_write_msg_to_fifo(struct shrm_dev *shrm, u8 channel,
+ u8 l2header, void *addr, u32 length);
+int shm_write_msg(struct shrm_dev *shrm,
+ u8 l2_header, void *addr, u32 length);
+
+u8 is_the_only_one_unread_message(struct shrm_dev *shrm,
+ u8 channel, u32 length);
+u8 read_remaining_messages_common(void);
+u8 read_remaining_messages_audio(void);
+u8 read_one_l2msg_audio(struct shrm_dev *shrm,
+ u8 *p_l2_msg, u32 *p_len);
+u8 read_one_l2msg_common(struct shrm_dev *shrm,
+ u8 *p_l2_msg, u32 *p_len);
+void receive_messages_common(struct shrm_dev *shrm);
+void receive_messages_audio(struct shrm_dev *shrm);
+
+void update_ac_common_local_rptr(struct shrm_dev *shrm);
+void update_ac_audio_local_rptr(struct shrm_dev *shrm);
+void update_ca_common_local_wptr(struct shrm_dev *shrm);
+void update_ca_audio_local_wptr(struct shrm_dev *shrm);
+void update_ac_common_shared_wptr(struct shrm_dev *shrm);
+void update_ac_audio_shared_wptr(struct shrm_dev *shrm);
+void update_ca_common_shared_rptr(struct shrm_dev *shrm);
+void update_ca_audio_shared_rptr(struct shrm_dev *shrm);
+
+
+void get_writer_pointers(u8 msg_type, u32 *WriterLocalRptr, \
+ u32 *WriterLocalWptr, u32 *SharedWptr);
+void get_reader_pointers(u8 msg_type, u32 *ReaderLocalRptr, \
+ u32 *ReaderLocalWptr, u32 *SharedRptr);
+u8 read_boot_info_req(struct shrm_dev *shrm,
+ u32 *pConfig,
+ u32 *pVersion);
+void write_boot_info_resp(struct shrm_dev *shrm, u32 Config,
+ u32 Version);
+
+void send_ac_msg_pending_notification_0(struct shrm_dev *shrm);
+void send_ac_msg_pending_notification_1(struct shrm_dev *shrm);
+void ca_msg_read_notification_0(struct shrm_dev *shrm);
+void ca_msg_read_notification_1(struct shrm_dev *shrm);
+
+void set_ca_msg_0_read_notif_send(u8 val);
+u8 get_ca_msg_0_read_notif_send(void);
+void set_ca_msg_1_read_notif_send(u8 val);
+u8 get_ca_msg_1_read_notif_send(void);
+
+irqreturn_t ca_wake_irq_handler(int irq, void *ctrlr);
+irqreturn_t ac_read_notif_0_irq_handler(int irq, void *ctrlr);
+irqreturn_t ac_read_notif_1_irq_handler(int irq, void *ctrlr);
+irqreturn_t ca_msg_pending_notif_0_irq_handler(int irq, void *ctrlr);
+irqreturn_t ca_msg_pending_notif_1_irq_handler(int irq, void *ctrlr);
+
+void shm_ca_msgpending_0_tasklet(unsigned long);
+void shm_ca_msgpending_1_tasklet(unsigned long);
+void shm_ac_read_notif_0_tasklet(unsigned long);
+void shm_ac_read_notif_1_tasklet(unsigned long);
+void shm_ca_wake_req_tasklet(unsigned long);
+
+u8 get_boot_state(void);
+
+int get_ca_wake_req_state(void);
+
+/* shrm character interface */
+int isa_init(struct shrm_dev *shrm);
+void isa_exit(struct shrm_dev *shrm);
+int add_msg_to_queue(struct message_queue *q, u32 size);
+ssize_t isa_read(struct file *filp, char __user *buf, size_t len,
+ loff_t *ppos);
+int get_size_of_new_msg(struct message_queue *q);
+int remove_msg_from_queue(struct message_queue *q);
+void shrm_char_reset_queues(struct shrm_dev *shrm);
+int shrm_get_cdev_index(u8 l2_header);
+int shrm_get_cdev_l2header(u8 idx);
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/ste-dma40-db5500.h b/arch/arm/mach-ux500/include/mach/ste-dma40-db5500.h
new file mode 100644
index 00000000000..cb2110c3285
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ste-dma40-db5500.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * DB5500-SoC-specific configuration for DMA40
+ */
+
+#ifndef STE_DMA40_DB5500_H
+#define STE_DMA40_DB5500_H
+
+#define DB5500_DMA_NR_DEV 64
+
+enum dma_src_dev_type {
+ DB5500_DMA_DEV0_SPI0_RX = 0,
+ DB5500_DMA_DEV1_SPI1_RX = 1,
+ DB5500_DMA_DEV2_SPI2_RX = 2,
+ DB5500_DMA_DEV3_SPI3_RX = 3,
+ DB5500_DMA_DEV4_USB_OTG_IEP_1_9 = 4,
+ DB5500_DMA_DEV5_USB_OTG_IEP_2_10 = 5,
+ DB5500_DMA_DEV6_USB_OTG_IEP_3_11 = 6,
+ DB5500_DMA_DEV7_IRDA_RFS = 7,
+ DB5500_DMA_DEV8_IRDA_FIFO_RX = 8,
+ DB5500_DMA_DEV9_MSP0_RX = 9,
+ DB5500_DMA_DEV10_MSP1_RX = 10,
+ DB5500_DMA_DEV11_MSP2_RX = 11,
+ DB5500_DMA_DEV12_UART0_RX = 12,
+ DB5500_DMA_DEV13_UART1_RX = 13,
+ DB5500_DMA_DEV14_UART2_RX = 14,
+ DB5500_DMA_DEV15_UART3_RX = 15,
+ DB5500_DMA_DEV16_USB_OTG_IEP_8 = 16,
+ DB5500_DMA_DEV17_USB_OTG_IEP_1_9 = 17,
+ DB5500_DMA_DEV18_USB_OTG_IEP_2_10 = 18,
+ DB5500_DMA_DEV19_USB_OTG_IEP_3_11 = 19,
+ DB5500_DMA_DEV20_USB_OTG_IEP_4_12 = 20,
+ DB5500_DMA_DEV21_USB_OTG_IEP_5_13 = 21,
+ DB5500_DMA_DEV22_USB_OTG_IEP_6_14 = 22,
+ DB5500_DMA_DEV23_USB_OTG_IEP_7_15 = 23,
+ DB5500_DMA_DEV24_SDMMC0_RX = 24,
+ DB5500_DMA_DEV25_SDMMC1_RX = 25,
+ DB5500_DMA_DEV26_SDMMC2_RX = 26,
+ DB5500_DMA_DEV27_SDMMC3_RX = 27,
+ DB5500_DMA_DEV28_SDMMC4_RX = 28,
+ /* 29 - 32 not used */
+ DB5500_DMA_DEV33_SDMMC0_RX = 33,
+ DB5500_DMA_DEV34_SDMMC1_RX = 34,
+ DB5500_DMA_DEV35_SDMMC2_RX = 35,
+ DB5500_DMA_DEV36_SDMMC3_RX = 36,
+ DB5500_DMA_DEV37_SDMMC4_RX = 37,
+ DB5500_DMA_DEV38_USB_OTG_IEP_8 = 38,
+ DB5500_DMA_DEV39_USB_OTG_IEP_1_9 = 39,
+ DB5500_DMA_DEV40_USB_OTG_IEP_2_10 = 40,
+ DB5500_DMA_DEV41_USB_OTG_IEP_3_11 = 41,
+ DB5500_DMA_DEV42_USB_OTG_IEP_4_12 = 42,
+ DB5500_DMA_DEV43_USB_OTG_IEP_5_13 = 43,
+ DB5500_DMA_DEV44_USB_OTG_IEP_6_14 = 44,
+ DB5500_DMA_DEV45_USB_OTG_IEP_7_15 = 45,
+ /* 46 not used */
+ DB5500_DMA_DEV47_MCDE_RX = 47,
+ DB5500_DMA_DEV48_CRYPTO1_RX = 48,
+ /* 49, 50 not used */
+ DB5500_DMA_DEV49_I2C1_RX = 51,
+ DB5500_DMA_DEV50_I2C3_RX = 52,
+ DB5500_DMA_DEV51_I2C2_RX = 53,
+ /* 54 - 60 not used */
+ DB5500_DMA_DEV61_CRYPTO0_RX = 61,
+ /* 62, 63 not used */
+};
+
+enum dma_dest_dev_type {
+ DB5500_DMA_DEV0_SPI0_TX = 0,
+ DB5500_DMA_DEV1_SPI1_TX = 1,
+ DB5500_DMA_DEV2_SPI2_TX = 2,
+ DB5500_DMA_DEV3_SPI3_TX = 3,
+ DB5500_DMA_DEV4_USB_OTG_OEP_1_9 = 4,
+ DB5500_DMA_DEV5_USB_OTG_OEP_2_10 = 5,
+ DB5500_DMA_DEV6_USB_OTG_OEP_3_11 = 6,
+ DB5500_DMA_DEV7_IRRC_TX = 7,
+ DB5500_DMA_DEV8_IRDA_FIFO_TX = 8,
+ DB5500_DMA_DEV9_MSP0_TX = 9,
+ DB5500_DMA_DEV10_MSP1_TX = 10,
+ DB5500_DMA_DEV11_MSP2_TX = 11,
+ DB5500_DMA_DEV12_UART0_TX = 12,
+ DB5500_DMA_DEV13_UART1_TX = 13,
+ DB5500_DMA_DEV14_UART2_TX = 14,
+ DB5500_DMA_DEV15_UART3_TX = 15,
+ DB5500_DMA_DEV16_USB_OTG_OEP_8 = 16,
+ DB5500_DMA_DEV17_USB_OTG_OEP_1_9 = 17,
+ DB5500_DMA_DEV18_USB_OTG_OEP_2_10 = 18,
+ DB5500_DMA_DEV19_USB_OTG_OEP_3_11 = 19,
+ DB5500_DMA_DEV20_USB_OTG_OEP_4_12 = 20,
+ DB5500_DMA_DEV21_USB_OTG_OEP_5_13 = 21,
+ DB5500_DMA_DEV22_USB_OTG_OEP_6_14 = 22,
+ DB5500_DMA_DEV23_USB_OTG_OEP_7_15 = 23,
+ DB5500_DMA_DEV24_SDMMC0_TX = 24,
+ DB5500_DMA_DEV25_SDMMC1_TX = 25,
+ DB5500_DMA_DEV26_SDMMC2_TX = 26,
+ DB5500_DMA_DEV27_SDMMC3_TX = 27,
+ DB5500_DMA_DEV28_SDMMC4_TX = 28,
+ /* 29 - 31 not used */
+ DB5500_DMA_DEV32_FSMC_TX = 32,
+ DB5500_DMA_DEV33_SDMMC0_TX = 33,
+ DB5500_DMA_DEV34_SDMMC1_TX = 34,
+ DB5500_DMA_DEV35_SDMMC2_TX = 35,
+ DB5500_DMA_DEV36_SDMMC3_TX = 36,
+ DB5500_DMA_DEV37_SDMMC4_TX = 37,
+ DB5500_DMA_DEV38_USB_OTG_OEP_8 = 38,
+ DB5500_DMA_DEV39_USB_OTG_OEP_1_9 = 39,
+ DB5500_DMA_DEV40_USB_OTG_OEP_2_10 = 40,
+ DB5500_DMA_DEV41_USB_OTG_OEP_3_11 = 41,
+ DB5500_DMA_DEV42_USB_OTG_OEP_4_12 = 42,
+ DB5500_DMA_DEV43_USB_OTG_OEP_5_13 = 43,
+ DB5500_DMA_DEV44_USB_OTG_OEP_6_14 = 44,
+ DB5500_DMA_DEV45_USB_OTG_OEP_7_15 = 45,
+ /* 46 not used */
+ DB5500_DMA_DEV47_STM_TX = 47,
+ DB5500_DMA_DEV48_CRYPTO1_TX = 48,
+ DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX = 49,
+ DB5500_DMA_DEV50_HASH1_TX = 50,
+ DB5500_DMA_DEV51_I2C1_TX = 51,
+ DB5500_DMA_DEV52_I2C3_TX = 52,
+ DB5500_DMA_DEV53_I2C2_TX = 53,
+ /* 54, 55 not used */
+ DB5500_DMA_MEMCPY_TX_1 = 56,
+ DB5500_DMA_MEMCPY_TX_2 = 57,
+ DB5500_DMA_MEMCPY_TX_3 = 58,
+ DB5500_DMA_MEMCPY_TX_4 = 59,
+ DB5500_DMA_MEMCPY_TX_5 = 60,
+ DB5500_DMA_DEV61_CRYPTO0_TX = 61,
+ DB5500_DMA_DEV62_CRYPTO0_TX_HASH0_TX = 62,
+ DB5500_DMA_DEV63_HASH0_TX = 63,
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/ste-dma40-db8500.h b/arch/arm/mach-ux500/include/mach/ste-dma40-db8500.h
new file mode 100644
index 00000000000..64c494f0836
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ste-dma40-db8500.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2007-2010
+ * Author: Per Friden <per.friden@stericsson.com> for ST-Ericsson
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * DB8500-SoC-specific configuration for DMA40
+ */
+#ifndef STE_DMA40_DB8500_H
+#define STE_DMA40_DB8500_H
+
+#define DB8500_DMA_NR_DEV 64
+/*
+ * All entries with double names are multiplexed
+ * and can never be used at the same time.
+ */
+
+enum dma_src_dev_type {
+ DB8500_DMA_DEV0_SPI0_RX = 0,
+ DB8500_DMA_DEV1_SD_MMC0_RX = 1,
+ DB8500_DMA_DEV2_SD_MMC1_RX = 2,
+ DB8500_DMA_DEV3_SD_MMC2_RX = 3,
+ DB8500_DMA_DEV4_I2C1_RX = 4,
+ DB8500_DMA_DEV5_I2C3_RX = 5,
+ DB8500_DMA_DEV6_I2C2_RX = 6,
+ DB8500_DMA_DEV7_I2C4_RX = 7, /* Only on V1 and later */
+ DB8500_DMA_DEV8_SSP0_RX = 8,
+ DB8500_DMA_DEV9_SSP1_RX = 9,
+ DB8500_DMA_DEV10_MCDE_RX = 10,
+ DB8500_DMA_DEV11_UART2_RX = 11,
+ DB8500_DMA_DEV12_UART1_RX = 12,
+ DB8500_DMA_DEV13_UART0_RX = 13,
+ DB8500_DMA_DEV14_MSP2_RX = 14,
+ DB8500_DMA_DEV15_I2C0_RX = 15,
+ DB8500_DMA_DEV16_USB_OTG_IEP_7_15 = 16,
+ DB8500_DMA_DEV17_USB_OTG_IEP_6_14 = 17,
+ DB8500_DMA_DEV18_USB_OTG_IEP_5_13 = 18,
+ DB8500_DMA_DEV19_USB_OTG_IEP_4_12 = 19,
+ DB8500_DMA_DEV20_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
+ DB8500_DMA_DEV21_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
+ DB8500_DMA_DEV22_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
+ DB8500_DMA_DEV23_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
+ DB8500_DMA_DEV24_SRC_SXA0_RX_TX = 24,
+ DB8500_DMA_DEV25_SRC_SXA1_RX_TX = 25,
+ DB8500_DMA_DEV26_SRC_SXA2_RX_TX = 26,
+ DB8500_DMA_DEV27_SRC_SXA3_RX_TX = 27,
+ DB8500_DMA_DEV28_SD_MM2_RX = 28,
+ DB8500_DMA_DEV29_SD_MM0_RX = 29,
+ DB8500_DMA_DEV30_MSP1_RX = 30,
+ /* On DB8500v2, MSP3 RX replaces MSP1 RX */
+ DB8500_DMA_DEV30_MSP3_RX = 30,
+ DB8500_DMA_DEV31_MSP0_RX_SLIM0_CH0_RX = 31,
+ DB8500_DMA_DEV32_SD_MM1_RX = 32,
+ DB8500_DMA_DEV33_SPI2_RX = 33,
+ DB8500_DMA_DEV34_I2C3_RX2 = 34,
+ DB8500_DMA_DEV35_SPI1_RX = 35,
+ DB8500_DMA_DEV36_USB_OTG_IEP_3_11 = 36,
+ DB8500_DMA_DEV37_USB_OTG_IEP_2_10 = 37,
+ DB8500_DMA_DEV38_USB_OTG_IEP_1_9 = 38,
+ DB8500_DMA_DEV39_USB_OTG_IEP_8 = 39,
+ DB8500_DMA_DEV40_SPI3_RX = 40,
+ DB8500_DMA_DEV41_SD_MM3_RX = 41,
+ DB8500_DMA_DEV42_SD_MM4_RX = 42,
+ DB8500_DMA_DEV43_SD_MM5_RX = 43,
+ DB8500_DMA_DEV44_SRC_SXA4_RX_TX = 44,
+ DB8500_DMA_DEV45_SRC_SXA5_RX_TX = 45,
+ DB8500_DMA_DEV46_SLIM0_CH8_RX_SRC_SXA6_RX_TX = 46,
+ DB8500_DMA_DEV47_SLIM0_CH9_RX_SRC_SXA7_RX_TX = 47,
+ DB8500_DMA_DEV48_CAC1_RX = 48,
+ /* 49, 50 and 51 are not used */
+ DB8500_DMA_DEV52_SLIM0_CH4_RX_HSI_RX_CH4 = 52,
+ DB8500_DMA_DEV53_SLIM0_CH5_RX_HSI_RX_CH5 = 53,
+ DB8500_DMA_DEV54_SLIM0_CH6_RX_HSI_RX_CH6 = 54,
+ DB8500_DMA_DEV55_SLIM0_CH7_RX_HSI_RX_CH7 = 55,
+ /* 56, 57, 58, 59 and 60 are not used */
+ DB8500_DMA_DEV61_CAC0_RX = 61,
+ /* 62 and 63 are not used */
+};
+
+enum dma_dest_dev_type {
+ DB8500_DMA_DEV0_SPI0_TX = 0,
+ DB8500_DMA_DEV1_SD_MMC0_TX = 1,
+ DB8500_DMA_DEV2_SD_MMC1_TX = 2,
+ DB8500_DMA_DEV3_SD_MMC2_TX = 3,
+ DB8500_DMA_DEV4_I2C1_TX = 4,
+ DB8500_DMA_DEV5_I2C3_TX = 5,
+ DB8500_DMA_DEV6_I2C2_TX = 6,
+ DB8500_DMA_DEV7_I2C4_TX = 7, /* Only on V1 and later */
+ DB8500_DMA_DEV8_SSP0_TX = 8,
+ DB8500_DMA_DEV9_SSP1_TX = 9,
+ /* 10 is not used*/
+ DB8500_DMA_DEV11_UART2_TX = 11,
+ DB8500_DMA_DEV12_UART1_TX = 12,
+ DB8500_DMA_DEV13_UART0_TX = 13,
+ DB8500_DMA_DEV14_MSP2_TX = 14,
+ DB8500_DMA_DEV15_I2C0_TX = 15,
+ DB8500_DMA_DEV16_USB_OTG_OEP_7_15 = 16,
+ DB8500_DMA_DEV17_USB_OTG_OEP_6_14 = 17,
+ DB8500_DMA_DEV18_USB_OTG_OEP_5_13 = 18,
+ DB8500_DMA_DEV19_USB_OTG_OEP_4_12 = 19,
+ DB8500_DMA_DEV20_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
+ DB8500_DMA_DEV21_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
+ DB8500_DMA_DEV22_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
+ DB8500_DMA_DEV23_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
+ DB8500_DMA_DEV24_DST_SXA0_RX_TX = 24,
+ DB8500_DMA_DEV25_DST_SXA1_RX_TX = 25,
+ DB8500_DMA_DEV26_DST_SXA2_RX_TX = 26,
+ DB8500_DMA_DEV27_DST_SXA3_RX_TX = 27,
+ DB8500_DMA_DEV28_SD_MM2_TX = 28,
+ DB8500_DMA_DEV29_SD_MM0_TX = 29,
+ DB8500_DMA_DEV30_MSP1_TX = 30,
+ DB8500_DMA_DEV31_MSP0_TX_SLIM0_CH0_TX = 31,
+ DB8500_DMA_DEV32_SD_MM1_TX = 32,
+ DB8500_DMA_DEV33_SPI2_TX = 33,
+ DB8500_DMA_DEV34_I2C3_TX2 = 34,
+ DB8500_DMA_DEV35_SPI1_TX = 35,
+ DB8500_DMA_DEV36_USB_OTG_OEP_3_11 = 36,
+ DB8500_DMA_DEV37_USB_OTG_OEP_2_10 = 37,
+ DB8500_DMA_DEV38_USB_OTG_OEP_1_9 = 38,
+ DB8500_DMA_DEV39_USB_OTG_OEP_8 = 39,
+ DB8500_DMA_DEV40_SPI3_TX = 40,
+ DB8500_DMA_DEV41_SD_MM3_TX = 41,
+ DB8500_DMA_DEV42_SD_MM4_TX = 42,
+ DB8500_DMA_DEV43_SD_MM5_TX = 43,
+ DB8500_DMA_DEV44_DST_SXA4_RX_TX = 44,
+ DB8500_DMA_DEV45_DST_SXA5_RX_TX = 45,
+ DB8500_DMA_DEV46_SLIM0_CH8_TX_DST_SXA6_RX_TX = 46,
+ DB8500_DMA_DEV47_SLIM0_CH9_TX_DST_SXA7_RX_TX = 47,
+ DB8500_DMA_DEV48_CAC1_TX = 48,
+ DB8500_DMA_DEV49_CAC1_TX_HAC1_TX = 49,
+ DB8500_DMA_DEV50_HAC1_TX = 50,
+ DB8500_DMA_MEMCPY_TX_0 = 51,
+ DB8500_DMA_DEV52_SLIM1_CH4_TX_HSI_TX_CH4 = 52,
+ DB8500_DMA_DEV53_SLIM1_CH5_TX_HSI_TX_CH5 = 53,
+ DB8500_DMA_DEV54_SLIM1_CH6_TX_HSI_TX_CH6 = 54,
+ DB8500_DMA_DEV55_SLIM1_CH7_TX_HSI_TX_CH7 = 55,
+ DB8500_DMA_MEMCPY_TX_1 = 56,
+ DB8500_DMA_MEMCPY_TX_2 = 57,
+ DB8500_DMA_MEMCPY_TX_3 = 58,
+ DB8500_DMA_MEMCPY_TX_4 = 59,
+ DB8500_DMA_MEMCPY_TX_5 = 60,
+ DB8500_DMA_DEV61_CAC0_TX = 61,
+ DB8500_DMA_DEV62_CAC0_TX_HAC0_TX = 62,
+ DB8500_DMA_DEV63_HAC0_TX = 63,
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/ste_audio_io.h b/arch/arm/mach-ux500/include/mach/ste_audio_io.h
new file mode 100644
index 00000000000..a8a617b8392
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ste_audio_io.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2009 ST-Ericsson SA
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _U8500_STE_AUDIO_IO_H_
+#define _U8500_STE_AUDIO_IO_H_
+
+
+struct ab8500_audio_platform_data {
+ int (*ste_gpio_altf_init) (void);
+ int (*ste_gpio_altf_exit) (void);
+};
+
+#endif /* _U8500_STE_AUDIO_IO_H_ */
diff --git a/arch/arm/mach-ux500/include/mach/ste_audio_io_ioctl.h b/arch/arm/mach-ux500/include/mach/ste_audio_io_ioctl.h
new file mode 100644
index 00000000000..e04734d65a5
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ste_audio_io_ioctl.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Deepak KARDA/ deepak.karda@stericsson.com for ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2.
+ */
+
+#ifndef _AUDIOIO_IOCTL_H_
+#define _AUDIOIO_IOCTL_H_
+
+
+#define AUDIOIO_IOC_MAGIC 'N'
+#define AUDIOIO_READ_REGISTER _IOWR(AUDIOIO_IOC_MAGIC, 1,\
+ struct audioio_data_t)
+#define AUDIOIO_WRITE_REGISTER _IOW(AUDIOIO_IOC_MAGIC, 2,\
+ struct audioio_data_t)
+#define AUDIOIO_PWR_CTRL_TRNSDR _IOW(AUDIOIO_IOC_MAGIC, 3,\
+ struct audioio_pwr_ctrl_t)
+#define AUDIOIO_PWR_STS_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 4,\
+ struct audioio_pwr_ctrl_t)
+#define AUDIOIO_LOOP_CTRL _IOW(AUDIOIO_IOC_MAGIC, 5,\
+ struct audioio_loop_ctrl_t)
+#define AUDIOIO_LOOP_STS _IOR(AUDIOIO_IOC_MAGIC, 6,\
+ struct audioio_loop_ctrl_t)
+#define AUDIOIO_GET_TRNSDR_GAIN_CAPABILITY _IOR(AUDIOIO_IOC_MAGIC, 7,\
+ struct audioio_get_gain_t)
+#define AUDIOIO_GAIN_CAP_LOOP _IOR(AUDIOIO_IOC_MAGIC, 8,\
+ struct audioio_gain_loop_t)
+#define AUDIOIO_SUPPORT_LOOP _IOR(AUDIOIO_IOC_MAGIC, 9,\
+ struct audioio_support_loop_t)
+#define AUDIOIO_GAIN_DESC_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 10,\
+ struct audioio_gain_desc_trnsdr_t)
+#define AUDIOIO_GAIN_CTRL_TRNSDR _IOW(AUDIOIO_IOC_MAGIC, 11,\
+ struct audioio_gain_ctrl_trnsdr_t)
+#define AUDIOIO_GAIN_QUERY_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 12,\
+ struct audioio_gain_ctrl_trnsdr_t)
+#define AUDIOIO_MUTE_CTRL_TRNSDR _IOW(AUDIOIO_IOC_MAGIC, 13,\
+ struct audioio_mute_trnsdr_t)
+#define AUDIOIO_MUTE_STS_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 14,\
+ struct audioio_mute_trnsdr_t)
+#define AUDIOIO_FADE_CTRL _IOW(AUDIOIO_IOC_MAGIC, 15,\
+ struct audioio_fade_ctrl_t)
+#define AUDIOIO_BURST_CTRL _IOW(AUDIOIO_IOC_MAGIC, 16,\
+ struct audioio_burst_ctrl_t)
+#define AUDIOIO_READ_ALL_ACODEC_REGS_CTRL _IOW(AUDIOIO_IOC_MAGIC, 17,\
+ struct audioio_read_all_acodec_reg_ctrl_t)
+#define AUDIOIO_FSBITCLK_CTRL _IOW(AUDIOIO_IOC_MAGIC, 18,\
+ struct audioio_fsbitclk_ctrl_t)
+#define AUDIOIO_PSEUDOBURST_CTRL _IOW(AUDIOIO_IOC_MAGIC, 19,\
+ struct audioio_pseudoburst_ctrl_t)
+#define AUDIOIO_AUDIOCODEC_PWR_CTRL _IOW(AUDIOIO_IOC_MAGIC, 20, \
+ struct audioio_acodec_pwr_ctrl_t)
+#define AUDIOIO_FIR_COEFFS_CTRL _IOW(AUDIOIO_IOC_MAGIC, 21, \
+ struct audioio_fir_coefficients_t)
+#define AUDIOIO_LOOP_GAIN_DESC_TRNSDR _IOR(AUDIOIO_IOC_MAGIC, 22,\
+ struct audioio_gain_desc_trnsdr_t)
+#define AUDIOIO_CLK_SELECT_CTRL _IOR(AUDIOIO_IOC_MAGIC, 23,\
+ struct audioio_clk_select_t)
+/* audio codec channel ids */
+#define EAR_CH 0
+#define HS_CH 1
+#define IHF_CH 2
+#define VIBL_CH 3
+#define VIBR_CH 4
+#define MIC1A_CH 5
+#define MIC1B_CH 6
+#define MIC2_CH 7
+#define LIN_CH 8
+#define DMIC12_CH 9
+#define DMIC34_CH 10
+#define DMIC56_CH 11
+#define MULTI_MIC_CH 12
+#define FMRX_CH 13
+#define FMTX_CH 14
+#define BLUETOOTH_CH 15
+
+#define FIRST_CH EAR_CH
+#define LAST_CH BLUETOOTH_CH
+
+#define MAX_NO_TRANSDUCERS 16
+#define STE_AUDIOIO_MAX_COEFFICIENTS 128
+#define MAX_NO_OF_LOOPS 19
+
+#define AUDIOIO_TRUE 1
+#define AUDIOIO_FALSE 0
+
+enum AUDIOIO_CLK_TYPE {
+ AUDIOIO_ULP_CLK,
+ AUDIOIO_SYS_CLK
+};
+
+enum AUDIOIO_COMMON_SWITCH {
+ AUDIOIO_COMMON_OFF = 0,
+ AUDIOIO_COMMON_ON,
+ AUDIOIO_COMMON_ALLCHANNEL_UNSUPPORTED = 0xFFFF
+};
+
+enum AUDIOIO_HAL_HW_LOOPS {
+ AUDIOIO_NO_LOOP = 0x0,
+ AUDIOIO_SIDETONE_LOOP = 0x01,
+ AUDIOIO_MIC1B_TO_HFL = 0x02,
+ AUDIOIO_MIC1B_TO_HFR = 0x04,
+ AUDIOIO_MIC1B_TO_EAR = 0x08,
+ AUDIOIO_MIC1A_TO_HSL = 0x10,
+ AUDIOIO_MIC1A_TO_HSR = 0x20,
+ AUDIOIO_MIC1A_TO_HSR_HSL = 0x40,
+ AUDIOIO_LINEIN_TO_HF = 0x80,
+ AUDIOIO_DMIC12_TO_HSR_HSL = 0x100,
+ AUDIOIO_DIC34_TO_HSR_HSL = 0x200,
+ AUDIOIO_DIC56_TO_HSR_HSL = 0x400,
+ AUDIOIO_DMIC12_TO_ST = 0x800,
+ AUDIOIO_DMIC34_TO_ST = 0x1000,
+ AUDIOIO_DMIC56_TO_ST = 0x2000,
+ AUDIOIO_ANC_LOOP = 0x4000,
+ AUDIOIO_LININ_HS = 0x8000,
+ AUDIOIO_LININL_HSL = 0x10000,
+ AUDIOIO_LININ_HSR = 0x20000
+};
+
+
+enum AUDIOIO_FADE_PERIOD {
+ e_FADE_00,
+ e_FADE_01,
+ e_FADE_10,
+ e_FADE_11
+};
+
+enum AUDIOIO_CH_INDEX {
+ e_CHANNEL_1 = 0x01,
+ e_CHANNEL_2 = 0x02,
+ e_CHANNEL_3 = 0x04,
+ e_CHANNEL_4 = 0x08,
+ e_CHANNEL_ALL = 0x0f
+};
+
+struct audioio_data_t {
+ unsigned char block;
+ unsigned char addr;
+ unsigned char data;
+};
+
+struct audioio_pwr_ctrl_t {
+ enum AUDIOIO_COMMON_SWITCH ctrl_switch;
+ int channel_type;
+ enum AUDIOIO_CH_INDEX channel_index;
+};
+
+struct audioio_acodec_pwr_ctrl_t {
+ enum AUDIOIO_COMMON_SWITCH ctrl_switch;
+};
+
+struct audioio_loop_ctrl_t {
+ enum AUDIOIO_HAL_HW_LOOPS hw_loop;
+ enum AUDIOIO_COMMON_SWITCH ctrl_switch;
+ int channel_type;
+ enum AUDIOIO_CH_INDEX channel_index;
+ int loop_gain;
+};
+
+struct audioio_get_gain_t {
+ unsigned int num_channels;
+ unsigned short max_num_gain;
+};
+
+struct audioio_gain_loop_t {
+ int channel_type;
+ unsigned short num_loop;
+ unsigned short max_gains;
+};
+
+struct audioio_support_loop_t {
+ int channel_type;
+ unsigned short spprtd_loop_index;
+};
+
+struct audioio_gain_desc_trnsdr_t {
+ enum AUDIOIO_CH_INDEX channel_index;
+ int channel_type;
+ unsigned short gain_index;
+ int min_gain;
+ int max_gain;
+ unsigned int gain_step;
+};
+
+struct audioio_gain_ctrl_trnsdr_t {
+ enum AUDIOIO_CH_INDEX channel_index;
+ int channel_type;
+ unsigned short gain_index;
+ int gain_value;
+ unsigned int linear;
+};
+
+struct audioio_mute_trnsdr_t {
+ int channel_type;
+ enum AUDIOIO_CH_INDEX channel_index;
+ enum AUDIOIO_COMMON_SWITCH ctrl_switch;
+};
+
+struct audioio_fade_ctrl_t {
+ enum AUDIOIO_COMMON_SWITCH ctrl_switch;
+ enum AUDIOIO_FADE_PERIOD fade_period;
+ int channel_type;
+ enum AUDIOIO_CH_INDEX channel_index;
+};
+
+struct audioio_burst_ctrl_t {
+ enum AUDIOIO_COMMON_SWITCH ctrl_switch;
+ int channel_type;
+ int burst_fifo_interrupt_sample_count;
+ int burst_fifo_length;/* BFIFOTx */
+ int burst_fifo_switch_frame;
+ int burst_fifo_sample_number;
+};
+
+struct audioio_read_all_acodec_reg_ctrl_t {
+ unsigned char data[200];
+};
+
+struct audioio_fsbitclk_ctrl_t {
+ enum AUDIOIO_COMMON_SWITCH ctrl_switch;
+};
+
+struct audioio_pseudoburst_ctrl_t {
+ enum AUDIOIO_COMMON_SWITCH ctrl_switch;
+};
+
+struct audioio_fir_coefficients_t {
+ unsigned char start_addr;
+ unsigned short coefficients[STE_AUDIOIO_MAX_COEFFICIENTS];
+};
+
+struct audioio_clk_select_t {
+ enum AUDIOIO_CLK_TYPE required_clk;
+};
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/ste_audio_io_vibrator.h b/arch/arm/mach-ux500/include/mach/ste_audio_io_vibrator.h
new file mode 100644
index 00000000000..6b6a558e90a
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/ste_audio_io_vibrator.h
@@ -0,0 +1,37 @@
+/*
+* Overview:
+* Header File defining vibrator kernel space interface
+*
+* Copyright (C) 2010 ST Ericsson
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#ifndef _STE_AUDIO_IO_VIBRATOR_H_
+#define _STE_AUDIO_IO_VIBRATOR_H_
+
+/* Client definitions which can use vibrator, defined as bitmask */
+#define STE_AUDIOIO_CLIENT_AUDIO_L 1
+#define STE_AUDIOIO_CLIENT_AUDIO_R 2
+#define STE_AUDIOIO_CLIENT_FF_VIBRA 4
+#define STE_AUDIOIO_CLIENT_TIMED_VIBRA 8
+
+/*
+ * Define vibrator's maximum speed allowed
+ * Duty cycle supported by vibrator's PWM is 0-100
+ */
+#define STE_AUDIOIO_VIBRATOR_MAX_SPEED 100
+
+/* Vibrator speed structure */
+struct ste_vibra_speed {
+ unsigned char positive;
+ unsigned char negative;
+};
+
+/* Vibrator control function - uses PWM source */
+int ste_audioio_vibrator_pwm_control(int client,
+ struct ste_vibra_speed left_speed, struct ste_vibra_speed right_speed);
+
+#endif
diff --git a/arch/arm/mach-ux500/include/mach/stm_musb.h b/arch/arm/mach-ux500/include/mach/stm_musb.h
new file mode 100644
index 00000000000..8fe93dd07b3
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/stm_musb.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 STMicroelectronics
+ * 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 __MUSB_U8500_H__
+#define __MUSB_U8500_H__
+
+#include <mach/hardware.h>
+
+/*
+ * TODO: We don't want dependencies from a generic driver (power/ab8500_bm)
+ * towards a enum in machine specific header files. This should be changed
+ */
+enum ab8500_usb_state {
+ AB8500_BM_USB_STATE_RESET_HS, /* HighSpeed Reset */
+ AB8500_BM_USB_STATE_RESET_FS, /* FullSpeed/LowSpeed Reset */
+ AB8500_BM_USB_STATE_CONFIGURED,
+ AB8500_BM_USB_STATE_SUSPEND,
+ AB8500_BM_USB_STATE_RESUME,
+ AB8500_BM_USB_STATE_MAX,
+};
+
+/*
+ * U8500-specific definitions
+ */
+
+/*
+ * Top-level Control and Status Registers
+ */
+#define OTG_DMASEL 0x200 /* OTG DMA Selector Register */
+#define OTG_TOPCTRL 0x204 /* OTG Top Control Register */
+
+/*
+ * ULPI-specific Registers
+ */
+#define OTG_UVBCTRL 0x70 /* OTG ULPI VBUS Control Register*/
+#define OTG_UCKIT 0x71 /* OTG ULPI CarKit Control Register*/
+#define OTG_UINTMASK 0x72 /* OTG ULPI INT Mask Register*/
+#define OTG_UINTSRC 0x73 /* OTG ULPI INT Source Register*/
+#define OTG_UREGDATA 0x74 /* OTG ULPI Reg Data Register*/
+#define OTG_UREGADDR 0x75 /* OTG ULPI Reg Address Register*/
+#define OTG_UREGCTRL 0x76 /* OTG ULPI Reg Control Register*/
+#define OTG_URAWDATA 0x77 /* OTG ULPI Raw Data Register*/
+
+/*
+ * OTG Top Control Register Bits
+ */
+#define OTG_TOPCTRL_MODE_ULPI (1 << 0) /* Activate ULPI interface*/
+#define OTG_TOPCTRL_UDDR (1 << 1) /* Activate ULPI double-data rate mode */
+#define OTG_TOPCTRL_SRST (1 << 2) /* OTG core soft reset*/
+#define OTG_TOPCTRL_XGATE (1 << 3) /* Activate transceiver clock*/
+#define OTG_TOPCTRL_I2C_OFF (1 << 4) /* Switch off I2C controller*/
+#define OTG_TOPCTRL_HDEV (1 << 5) /* Select host mode with FS interface*/
+#define OTG_TOPCTRL_VBUSLO (1 << 6) /* Enable VBUS for FS transceivers*/
+
+/*
+ * OTG ULPI VBUS Control Register Bits
+ */
+#define OTG_UVBCTRL_EXTVB (1 << 0) /* Use External VBUS*/
+#define OTG_UVBCTRL_EXTVI (1 << 1) /* Use External VBUS Indicator*/
+
+/*
+ * OTG ULPI Reg Control Register Bits
+ */
+#define OTG_UREGCTRL_REGREQ (1 << 0) /* Request ULPI register access */
+#define OTG_UREGCTRL_REGCMP (1 << 1) /* ULPI register access completion flag */
+#define OTG_UREGCTRL_URW (1 << 2) /* Request read from register access */
+
+/*
+ * STULPI01/STULPI05-specific definitions
+ */
+
+/*
+ * Registers accessors (different offsets for read/write/set/clear functions)
+ */
+#define ULPI_REG_READ(x) (x + 0)
+#define ULPI_REG_WRITE(x) (x + 0)
+#define ULPI_REG_SET(x) (x + 1)
+#define ULPI_REG_CLEAR(x) (x + 2)
+
+/*
+ * STULPI01/STULPI05 Registers
+ */
+#define ULPI_VIDLO 0x00 /* Vendor ID Low (Read Only) */
+#define ULPI_VIDHI 0x01 /* Vendor ID High (Read Only) */
+#define ULPI_PIDLO 0x02 /* Product ID Low (Read Only) */
+#define ULPI_PIDHI 0x03 /* Product ID High (Read Only) */
+#define ULPI_FCTRL 0x04 /* Function Control Register */
+#define ULPI_ICTRL 0x07 /* Interface Control Register */
+#define ULPI_OCTRL 0x0A /* OTG Control Register */
+#define ULPI_INTENRIS 0x0D /* Interrupt Enable Rising */
+#define ULPI_INTENFAL 0x10 /* Interrupt Enable Falling */
+#define ULPI_INTSTATU 0x13 /* Interrupt Status (Read Only) */
+#define ULPI_INTLATCH 0x14 /* Interrupt Latch (Read Only) */
+#define ULPI_DEBUG 0x15 /* Debug Register (Read Only) */
+#define ULPI_SCRATCH 0x16 /* Scratch Register */
+#define ULPI_CCTRL 0x19 /* Carkit Control Register */
+#define ULPI_PCTRL 0x3D /* Power Control Register */
+#define ULPI_ULINKSTAT 0x39 /* USB Link Status & Control Register */
+
+/*
+ * Vendor and Product IDs
+ */
+#define ULPI_VIDLO_VALUE 0x83 /*Vendor ID Low*/
+#define ULPI_VIDHI_VALUE 0x04 /*Vendor ID High*/
+#define ULPI_PIDLO_VALUE 0x4B /*Product ID Low*/
+#define ULPI_PIDHI_VALUE 0x4F /*Product ID High*/
+
+/**
+ * STULPI Function Control Register Bits
+ */
+#define ULPI_FCTRL_HSEN (0 << 0)
+#define ULPI_FCTRL_FSEN (1 << 0)
+#define ULPI_FCTRL_LSEN (2 << 0)
+#define ULPI_FCTRL_FSLSEN (3 << 0)
+#define ULPI_FCTRL_TSELECT (1 << 2)
+#define ULPI_FCTRL_OM_NORM (0 << 3)
+#define ULPI_FCTRL_OM_NONDRIV (1 << 3)
+#define ULPI_FCTRL_OM_NRZIDIS (2 << 3)
+#define ULPI_FCTRL_OM_NOSYNC (3 << 3)
+#define ULPI_FCTRL_RESET (1 << 5)
+#define ULPI_FCTRL_NOSUSPEND (1 << 6)
+
+/*
+ * STULPI Interface Control Register Bits
+ */
+#define ULPI_ICTRL_6PINSERIAL (1 << 0)
+#define ULPI_ICTRL_3PINSERIAL (1 << 1)
+#define ULPI_ICTRL_CARKITEN (1 << 2)
+#define ULPI_ICTRL_PSCLOCKEN (1 << 3)
+#define ULPI_ICTRL_VBUSINV (1 << 5)
+#define ULPI_ICTRL_IPASSTHRU (1 << 6)
+#define ULPI_ICTRL_IPROTDIS (1 << 7)
+
+/*
+ * STULPI OTG Control Register Bits
+ */
+#define ULPI_OCTRL_IDPULLUP (1 << 0)
+#define ULPI_OCTRL_DPPULLDOWN (1 << 1)
+#define ULPI_OCTRL_DMPULLDOWN (1 << 2)
+#define ULPI_OCTRL_DISCHRGVBUS (1 << 3)
+#define ULPI_OCTRL_CHRGVBUS (1 << 4)
+#define ULPI_OCTRL_DRVVBUS (1 << 5)
+#define ULPI_OCTRL_DRVVBUSEXT (1 << 6)
+#define ULPI_OCTRL_EXTVBUSIND (1 << 7)
+
+/*
+ * STULPI USB Link Status & Control Register
+ */
+
+/* function prototypes */
+void ab8500_bm_usb_state_changed_wrapper(u8 bm_usb_state);
+
+#endif/* __MUSB_U8500_H__ */
diff --git a/arch/arm/mach-ux500/include/mach/suspend.h b/arch/arm/mach-ux500/include/mach/suspend.h
new file mode 100644
index 00000000000..582fa324df3
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/suspend.h
@@ -0,0 +1,13 @@
+/*
+ * 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);
+void suspend_set_pins_force_fn(void (*force)(void), void (*force_mux)(void));
+
+#endif /* __MACH_SUSPEND_H */
diff --git a/arch/arm/mach-ux500/include/mach/system.h b/arch/arm/mach-ux500/include/mach/system.h
index c0cd8006f1a..ec056d9198c 100644
--- a/arch/arm/mach-ux500/include/mach/system.h
+++ b/arch/arm/mach-ux500/include/mach/system.h
@@ -8,6 +8,9 @@
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
+#include <mach/prcmu-fw-api.h>
+#include <mach/reboot_reasons.h>
+
static inline void arch_idle(void)
{
/*
@@ -19,7 +22,10 @@ static inline void arch_idle(void)
static inline void arch_reset(char mode, const char *cmd)
{
- /* yet to be implemented - TODO */
+#ifdef CONFIG_UX500_SOC_DB8500
+ /* Call the PRCMU reset API (w/o reset reason code) */
+ prcmu_system_reset(SW_RESET_NO_ARGUMENT);
+#endif
}
#endif
diff --git a/arch/arm/mach-ux500/include/mach/tc35893-keypad.h b/arch/arm/mach-ux500/include/mach/tc35893-keypad.h
new file mode 100644
index 00000000000..e585a2029f5
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/tc35893-keypad.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License, version 2
+ * Author: Jayeeta Banerjee <jayeeta.banerjee@stericsson.com> for ST-Ericsson
+ */
+
+#ifndef __TC35893_KEYPAD_H
+#define __TC35893_KEYPAD_H
+
+/*
+ * Keypad related platform specific constants
+ * These values may be modified for fine tuning
+ */
+#define TC_KPD_ROWS 0x8
+#define TC_KPD_COLUMNS 0x8
+#define TC_KPD_DEBOUNCE_PERIOD 0xA3
+#define TC_KPD_SETTLE_TIME 0xA3
+
+/**
+ * struct tc35893_platform_data - data structure for platform specific data
+ * @keymap_data: matrix scan code table for keycodes
+ * @krow: mask for available rows, value is 0xFF
+ * @kcol: mask for available columns, value is 0xFF
+ * @debounce_period: platform specific debounce time
+ * @settle_time: platform specific settle down time
+ * @irqtype: type of interrupt, falling or rising edge
+ * @irq: irq no,
+ * @enable_wakeup: specifies if keypad event can wake up system from sleep
+ * @no_autorepeat: flag for auto repetition
+ */
+struct tc35893_platform_data {
+ struct matrix_keymap_data *keymap_data;
+ u8 krow;
+ u8 kcol;
+ u8 debounce_period;
+ u8 settle_time;
+ unsigned long irqtype;
+ int irq;
+ bool enable_wakeup;
+ bool no_autorepeat;
+};
+
+#endif /*__TC35893_KEYPAD_H*/
diff --git a/arch/arm/mach-ux500/include/mach/tee_ta_start_modem.h b/arch/arm/mach-ux500/include/mach/tee_ta_start_modem.h
new file mode 100644
index 00000000000..6978b7314c5
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/tee_ta_start_modem.h
@@ -0,0 +1,48 @@
+/*
+ * Data types and interface for TEE application for starting the modem.
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#ifndef TEE_TA_START_MODEM_H
+#define TEE_TA_START_MODEM_H
+
+#define COMMAND_ID_START_MODEM 0x00000001
+
+#define UUID_TEE_TA_START_MODEM_LOW 0x8AD94107
+#define UUID_TEE_TA_START_MODEM_MID 0x6E50
+#define UUID_TEE_TA_START_MODEM_HIGH 0x418E
+#define UUID_TEE_TA_START_MODEM_CLOCKSEQ \
+ {0xB1, 0x14, 0x75, 0x7D, 0x60, 0x21, 0xBD, 0x36}
+
+struct mcore_segment_descr {
+ void *segment;
+ void *hash;
+ u32 size;
+};
+
+struct access_image_descr {
+ void *elf_hdr;
+ void *pgm_hdr_tbl;
+ void *signature;
+ unsigned long nbr_segment;
+ struct mcore_segment_descr *descr;
+};
+
+/* TODO: To be redefined with only info needed by Secure world. */
+struct tee_ta_start_modem {
+ void *access_mem_start;
+ u32 shared_mem_size;
+ u32 access_private_mem_size;
+ struct access_image_descr access_image_descr;
+};
+
+/**
+ * This is the function to handle the modem release.
+ */
+int tee_ta_start_modem(struct tee_ta_start_modem *data);
+
+#endif
+
diff --git a/arch/arm/mach-ux500/include/mach/timex.h b/arch/arm/mach-ux500/include/mach/timex.h
index d0942c17401..c100e3dc2ef 100644
--- a/arch/arm/mach-ux500/include/mach/timex.h
+++ b/arch/arm/mach-ux500/include/mach/timex.h
@@ -2,5 +2,8 @@
#define __ASM_ARCH_TIMEX_H
#define CLOCK_TICK_RATE 110000000
+#ifndef CONFIG_UX500_SOC_DB5500
+#define ARCH_HAS_READ_CURRENT_TIMER
+#endif
#endif
diff --git a/arch/arm/mach-ux500/include/mach/u8500_acodec_ab8500.h b/arch/arm/mach-ux500/include/mach/u8500_acodec_ab8500.h
new file mode 100644
index 00000000000..0575bbdb730
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/u8500_acodec_ab8500.h
@@ -0,0 +1,284 @@
+/* Header file for u8500 audiocodec specific data structures, enums
+ * and private & public functions.
+ * Author: Deepak Karda
+ * Copyright (C) 2009 ST-Ericsson Pvt. Ltd.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _U8500_ACODEC_AB8500_H_
+#define _U8500_ACODEC_AB8500_H_
+
+#include <mach/ab8500.h>
+#include <linux/i2s/i2s.h>
+
+#ifdef CONFIG_U8500_AB8500_CUT10
+#include <mach/ab8500_codec_v1_0.h>
+//#include <mach/ab8500_codec_p_v1_0.h>
+#else /*CONFIG_U8500_4500_ED */
+#include <mach/ab8500_codec.h>
+#include <mach/ab8500_codec_p.h>
+#endif
+
+#define NUMBER_OUTPUT_DEVICE 5
+#define NUMBER_INPUT_DEVICE 13
+#define NUMBER_LOOPBACK_STATE 2
+#define NUMBER_SWITCH_STATE 2
+#define NUMBER_POWER_STATE 2
+#define NUMBER_TDM_MODE_STATE 2
+#define NUMBER_DIRECT_RENDERING_STATE 2
+#define NUMBER_PCM_RENDERING_STATE 3
+
+#define CODEC_MUTE 0x20
+#define DEFAULT_VOLUME 0x64
+#define DEFAULT_GAIN 0x32
+#define VOL_MAX 0x64
+#define VOL_MIN 0x00
+#define DEFAULT_OUTPUT_DEVICE AB8500_CODEC_DEST_HEADSET
+#define DEFAULT_INPUT_DEVICE AB8500_CODEC_SRC_D_MICROPHONE_1
+#define DEFAULT_LOOPBACK_STATE DISABLE
+#define DEFAULT_SWITCH_STATE DISABLE
+#define DEFAULT_TDM8_CH_MODE_STATE DISABLE
+#define DEFAULT_DIRECT_RENDERING_STATE DISABLE
+#define DEFAULT_BURST_FIFO_STATE RENDERING_DISABLE
+#define DEFAULT_FM_PLAYBACK_STATE RENDERING_DISABLE
+#define DEFAULT_FM_TX_STATE RENDERING_DISABLE
+
+#define MIN_RATE_PLAYBACK 48000
+#define MAX_RATE_PLAYBACK 48000
+#define MIN_RATE_CAPTURE 48000
+#define MAX_RATE_CAPTURE 48000
+#define MAX_NO_OF_RATES 1
+
+#define ALSA_MSP_BT_NUM 0
+#define ALSA_MSP_PCM_NUM 1
+#define ALSA_MSP_HDMI_NUM 2
+
+#define I2S_CLIENT_MSP0 0
+#define I2S_CLIENT_MSP1 1
+#define I2S_CLIENT_MSP2 2
+
+typedef enum {
+ DISABLE,
+ ENABLE
+} t_u8500_bool_state;
+
+typedef enum {
+ RENDERING_DISABLE,
+ RENDERING_ENABLE,
+ RENDERING_PENDING
+} t_u8500_pmc_rendering_state;
+
+typedef enum {
+ ACODEC_CONFIG_REQUIRED,
+ ACODEC_CONFIG_NOT_REQUIRED
+} t_u8500_acodec_config_need;
+
+typedef enum {
+ CLASSICAL_MODE,
+ TDM_8_CH_MODE
+} t_u8500_mode;
+
+typedef struct {
+ unsigned int left_volume;
+ unsigned int right_volume;
+ unsigned int mute_state;
+ t_u8500_bool_state power_state;
+} u8500_io_dev_config_t;
+
+typedef enum {
+ NO_USER = 0,
+ USER_ALSA = 2, /*To make it equivalent to user id for MSP */
+ USER_SAA,
+} t_acodec_user;
+
+typedef struct {
+ u8500_io_dev_config_t output_config[NUMBER_OUTPUT_DEVICE];
+ u8500_io_dev_config_t input_config[NUMBER_INPUT_DEVICE];
+ //t_acodec_user user;
+ t_acodec_user cur_user;
+} t_u8500_codec_system_context;
+
+typedef enum {
+ T_CODEC_SAMPLING_FREQ_48KHZ = 48,
+} acodec_sample_frequency;
+
+struct acodec_configuration {
+ t_ab8500_codec_direction direction;
+ acodec_sample_frequency input_frequency;
+ acodec_sample_frequency output_frequency;
+ codec_msp_srg_clock_sel_type mspClockSel;
+ codec_msp_in_clock_freq_type mspInClockFreq;
+ u32 channels;
+ t_acodec_user user;
+ t_u8500_acodec_config_need acodec_config_need;
+ t_u8500_bool_state direct_rendering_mode;
+ t_u8500_bool_state tdm8_ch_mode;
+ t_u8500_bool_state digital_loopback;
+ void (*handler) (void *data);
+ void *tx_callback_data;
+ void *rx_callback_data;
+};
+
+typedef enum {
+ ACODEC_DISABLE_ALL,
+ ACODEC_DISABLE_TRANSMIT,
+ ACODEC_DISABLE_RECEIVE,
+} t_acodec_disable;
+
+struct i2sdrv_data {
+ struct i2s_device *i2s;
+ spinlock_t i2s_lock;
+ /* buffer is NULL unless this device is open (users > 0) */
+ int flag;
+ u32 tx_status;
+ u32 rx_status;
+};
+
+#define MAX_I2S_CLIENTS 3 //0=BT, 1=ACODEC, 2=HDMI
+
+/*extern t_ab8500_codec_error u8500_acodec_set_volume(int input_vol_left,
+ int input_vol_right,
+ int output_vol_left,
+ int output_vol_right, t_acodec_user user);*/
+
+extern t_ab8500_codec_error u8500_acodec_open(int client_id, int stream_id);
+//extern t_ab8500_codec_error u8500_acodec_pause_transfer(void);
+//extern t_ab8500_codec_error u8500_acodec_unpause_transfer(void);
+extern t_ab8500_codec_error u8500_acodec_send_data(int client_id, void *data,
+ size_t bytes, int dma_flag);
+extern t_ab8500_codec_error u8500_acodec_receive_data(int client_id, void *data,
+ size_t bytes,
+ int dma_flag);
+extern t_ab8500_codec_error u8500_acodec_close(int client_id,
+ t_acodec_disable flag);
+extern t_ab8500_codec_error u8500_acodec_tx_rx_data(int client_id,
+ void *tx_data,
+ size_t tx_bytes,
+ void *rx_data,
+ size_t rx_bytes,
+ int dma_flag);
+
+extern t_ab8500_codec_error u8500_acodec_set_output_volume(t_ab8500_codec_dest
+ dest_device,
+ int left_volume,
+ int right_volume,
+ t_acodec_user user);
+
+extern t_ab8500_codec_error u8500_acodec_get_output_volume(t_ab8500_codec_dest
+ dest_device,
+ int *p_left_volume,
+ int *p_right_volume,
+ t_acodec_user user);
+
+extern t_ab8500_codec_error u8500_acodec_set_input_volume(t_ab8500_codec_src
+ src_device,
+ int left_volume,
+ int right_volume,
+ t_acodec_user user);
+
+extern t_ab8500_codec_error u8500_acodec_get_input_volume(t_ab8500_codec_src
+ src_device,
+ int *p_left_volume,
+ int *p_right_volume,
+ t_acodec_user user);
+
+extern t_ab8500_codec_error u8500_acodec_toggle_analog_lpbk(t_u8500_bool_state
+ lpbk_state,
+ t_acodec_user user);
+
+extern t_ab8500_codec_error u8500_acodec_toggle_digital_lpbk(t_u8500_bool_state
+ lpbk_state,
+ t_ab8500_codec_dest
+ dest_device,
+ t_ab8500_codec_src
+ src_device,
+ t_acodec_user user,
+ t_u8500_bool_state
+ tdm8_ch_mode);
+
+extern t_ab8500_codec_error
+u8500_acodec_toggle_playback_mute_control(t_ab8500_codec_dest dest_device,
+ t_u8500_bool_state mute_state,
+ t_acodec_user user);
+extern t_ab8500_codec_error
+u8500_acodec_toggle_capture_mute_control(t_ab8500_codec_src src_device,
+ t_u8500_bool_state mute_state,
+ t_acodec_user user);
+
+extern t_ab8500_codec_error u8500_acodec_enable_audio_mode(struct
+ acodec_configuration
+ *acodec_config);
+/*extern t_ab8500_codec_error u8500_acodec_enable_voice_mode(struct acodec_configuration *acodec_config);*/
+
+extern t_ab8500_codec_error u8500_acodec_select_input(t_ab8500_codec_src
+ input_device,
+ t_acodec_user user,
+ t_u8500_mode mode);
+extern t_ab8500_codec_error u8500_acodec_select_output(t_ab8500_codec_dest
+ output_device,
+ t_acodec_user user,
+ t_u8500_mode mode);
+
+extern t_ab8500_codec_error u8500_acodec_allocate_ad_slot(t_ab8500_codec_src
+ input_device,
+ t_u8500_mode mode);
+extern t_ab8500_codec_error u8500_acodec_unallocate_ad_slot(t_ab8500_codec_src
+ input_device,
+ t_u8500_mode mode);
+extern t_ab8500_codec_error u8500_acodec_allocate_da_slot(t_ab8500_codec_dest
+ output_device,
+ t_u8500_mode mode);
+extern t_ab8500_codec_error u8500_acodec_unallocate_da_slot(t_ab8500_codec_dest
+ output_device,
+ t_u8500_mode mode);
+
+extern t_ab8500_codec_error u8500_acodec_set_src_power_cntrl(t_ab8500_codec_src
+ input_device,
+ t_u8500_bool_state
+ pwr_state);
+extern t_ab8500_codec_error
+u8500_acodec_set_dest_power_cntrl(t_ab8500_codec_dest output_device,
+ t_u8500_bool_state pwr_state);
+
+extern t_u8500_bool_state u8500_acodec_get_src_power_state(t_ab8500_codec_src
+ input_device);
+extern t_u8500_bool_state u8500_acodec_get_dest_power_state(t_ab8500_codec_dest
+ output_device);
+extern t_ab8500_codec_error
+u8500_acodec_set_burst_mode_fifo(t_u8500_pmc_rendering_state fifo_state);
+
+extern t_ab8500_codec_error u8500_acodec_unsetuser(t_acodec_user user);
+extern t_ab8500_codec_error u8500_acodec_setuser(t_acodec_user user);
+
+extern void codec_power_init(void);
+extern void u8500_acodec_powerdown(void);
+
+//t_ab8500_codec_error acodec_msp_enable(t_touareg_codec_sample_frequency freq,int channels, t_acodec_user user);
+
+#define TRG_CODEC_ADDRESS_ON_SPI_BUS (0x0D)
+
+extern int ab8500_write(u8 block, u32 adr, u8 data);
+extern int ab8500_read(u8 block, u32 adr);
+
+#if 0
+#define FUNC_ENTER() printk("\n -Enter : %s",__FUNCTION__)
+#define FUNC_EXIT() printk("\n -Exit : %s",__FUNCTION__)
+#else
+#define FUNC_ENTER()
+#define FUNC_EXIT()
+#endif
+#endif /*END OF HEADSER FILE */
diff --git a/arch/arm/mach-ux500/include/mach/uart.h b/arch/arm/mach-ux500/include/mach/uart.h
new file mode 100644
index 00000000000..1b10a0be5a6
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/uart.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2009 ST-Ericsson SA
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _U8500_UART_H_
+#define _U8500_UART_H_
+
+struct uart_amba_plat_data {
+ void (*init) (void);
+ void (*exit) (void);
+ void (*reset) (void);
+};
+
+#endif /* _U8500_UART_H_ */
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h
index 0271ca0a83d..9f19d5c8b21 100644
--- a/arch/arm/mach-ux500/include/mach/uncompress.h
+++ b/arch/arm/mach-ux500/include/mach/uncompress.h
@@ -19,38 +19,46 @@
#define __ASM_ARCH_UNCOMPRESS_H
#include <asm/setup.h>
+#include <asm/mach-types.h>
#include <linux/io.h>
+#include <linux/amba/serial.h>
#include <mach/hardware.h>
-#define U8500_UART_DR 0x80007000
-#define U8500_UART_LCRH 0x8000702c
-#define U8500_UART_CR 0x80007030
-#define U8500_UART_FR 0x80007018
+static u32 ux500_uart_base;
static void putc(const char c)
{
/* Do nothing if the UART is not enabled. */
- if (!(__raw_readb(U8500_UART_CR) & 0x1))
+ if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1))
return;
if (c == '\n')
putc('\r');
- while (__raw_readb(U8500_UART_FR) & (1 << 5))
+ while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 5))
barrier();
- __raw_writeb(c, U8500_UART_DR);
+ __raw_writeb(c, ux500_uart_base + UART01x_DR);
}
static void flush(void)
{
- if (!(__raw_readb(U8500_UART_CR) & 0x1))
+ if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1))
return;
- while (__raw_readb(U8500_UART_FR) & (1 << 3))
+ while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 3))
barrier();
}
static inline void arch_decomp_setup(void)
{
+ /* Check in run time if we run on an U8500 or U5500 */
+ if (machine_is_u8500() ||
+ machine_is_svp8500v1() ||
+ machine_is_svp8500v2() ||
+ machine_is_snowball() ||
+ machine_is_hrefv60()) {
+ ux500_uart_base = U8500_UART2_BASE;
+ } else if (machine_is_u5500())
+ ux500_uart_base = U5500_UART0_BASE;
}
#define arch_decomp_wdog() /* nothing to do here */
diff --git a/arch/arm/mach-ux500/localtimer.c b/arch/arm/mach-ux500/localtimer.c
index 2288f6a7c51..758e156251b 100644
--- a/arch/arm/mach-ux500/localtimer.c
+++ b/arch/arm/mach-ux500/localtimer.c
@@ -18,11 +18,20 @@
#include <asm/smp_twd.h>
#include <asm/localtimer.h>
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+void smp_timer_broadcast(const struct cpumask *mask);
+#endif
+
/*
* Setup the local clock events for a CPU.
*/
void __cpuinit local_timer_setup(struct clock_event_device *evt)
{
evt->irq = IRQ_LOCALTIMER;
- twd_timer_setup(evt);
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+ evt->broadcast = smp_timer_broadcast;
+#endif
+
+ twd_timer_setup_scalable(evt, 2500 * 1000, 2);
}
diff --git a/arch/arm/mach-ux500/mloader-db8500.c b/arch/arm/mach-ux500/mloader-db8500.c
new file mode 100644
index 00000000000..6171a9db82f
--- /dev/null
+++ b/arch/arm/mach-ux500/mloader-db8500.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson
+ *
+ * Author: Maxime Coquelin <maxime.coquelin-nonst@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/types.h>
+#include <linux/platform_device.h>
+
+#include <mach/mloader-dbx500.h>
+
+static struct dbx500_ml_area modem_areas[] = {
+ { .name = "modem_trace", .start = 0x6000000, .size = 0xf00000 },
+ { .name = "modem_shared", .start = 0x6f00000, .size = 0x100000 },
+ { .name = "modem_priv", .start = 0x7000000, .size = 0x1000000 },
+};
+
+static struct dbx500_ml_fw modem_fws[] = {
+ { .name = "MODEM", .area = &modem_areas[0], .offset = 0x0 },
+ { .name = "IPL", .area = &modem_areas[1], .offset = 0x00 },
+};
+
+static struct dbx500_mloader_pdata mloader_fw_data = {
+ .fws = modem_fws,
+ .nr_fws = ARRAY_SIZE(modem_fws),
+ .areas = modem_areas,
+ .nr_areas = ARRAY_SIZE(modem_areas),
+};
+
+struct platform_device mloader_fw_device = {
+ .name = "dbx500_mloader_fw",
+ .id = -1,
+ .dev = {
+ .platform_data = &mloader_fw_data,
+ },
+ .num_resources = 0,
+};
+
+/* Default areas can be overloaded in cmdline */
+static int __init early_modem_priv(char *p)
+{
+ struct dbx500_ml_area *area = &modem_areas[2];
+
+ area->size = memparse(p, &p);
+
+ if (*p == '@')
+ area->start = memparse(p + 1, &p);
+
+ return 0;
+}
+early_param("mem_modem", early_modem_priv);
+
+static int __init early_modem_shared(char *p)
+{
+ struct dbx500_ml_area *area = &modem_areas[1];
+
+ area->size = memparse(p, &p);
+
+ if (*p == '@')
+ area->start = memparse(p + 1, &p);
+
+ return 0;
+}
+early_param("mem_mshared", early_modem_shared);
+
+static int __init early_modem_trace(char *p)
+{
+ struct dbx500_ml_area *area = &modem_areas[0];
+
+ area->size = memparse(p, &p);
+
+ if (*p == '@')
+ area->start = memparse(p + 1, &p);
+
+ return 0;
+}
+early_param("mem_mtrace", early_modem_trace);
+
diff --git a/arch/arm/mach-ux500/modem_irq.c b/arch/arm/mach-ux500/modem_irq.c
new file mode 100644
index 00000000000..bfe36b2aa09
--- /dev/null
+++ b/arch/arm/mach-ux500/modem_irq.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for ST-Ericsson.
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#define MODEM_INTCON_BASE_ADDR 0xBFFD3000
+#define MODEM_INTCON_SIZE 0xFFF
+
+#define DEST_IRQ41_OFFSET 0x2A4
+#define DEST_IRQ43_OFFSET 0x2AC
+#define DEST_IRQ45_OFFSET 0x2B4
+
+#define PRIO_IRQ41_OFFSET 0x6A4
+#define PRIO_IRQ43_OFFSET 0x6AC
+#define PRIO_IRQ45_OFFSET 0x6B4
+
+#define ALLOW_IRQ_OFFSET 0x104
+
+#define MODEM_INTCON_CPU_NBR 0x1
+#define MODEM_INTCON_PRIO_HIGH 0x0
+
+#define MODEM_INTCON_ALLOW_IRQ41 0x0200
+#define MODEM_INTCON_ALLOW_IRQ43 0x0800
+#define MODEM_INTCON_ALLOW_IRQ45 0x2000
+
+#define MODEM_IRQ_REG_OFFSET 0x4
+
+struct modem_irq {
+ void __iomem *modem_intcon_base;
+};
+
+
+static void setup_modem_intcon(void __iomem *modem_intcon_base)
+{
+ /* IC_DESTINATION_BASE_ARRAY - Which CPU to receive the IRQ */
+ writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ41_OFFSET);
+ writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ43_OFFSET);
+ writel(MODEM_INTCON_CPU_NBR, modem_intcon_base + DEST_IRQ45_OFFSET);
+
+ /* IC_PRIORITY_BASE_ARRAY - IRQ priority in modem IRQ controller */
+ writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ41_OFFSET);
+ writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ43_OFFSET);
+ writel(MODEM_INTCON_PRIO_HIGH, modem_intcon_base + PRIO_IRQ45_OFFSET);
+
+ /* IC_ALLOW_ARRAY - IRQ enable */
+ writel(MODEM_INTCON_ALLOW_IRQ41 |
+ MODEM_INTCON_ALLOW_IRQ43 |
+ MODEM_INTCON_ALLOW_IRQ45,
+ modem_intcon_base + ALLOW_IRQ_OFFSET);
+}
+
+static irqreturn_t modem_cpu_irq_handler(int irq, void *data)
+{
+ int real_irq;
+ int virt_irq;
+ struct modem_irq *mi = (struct modem_irq *)data;
+
+ /* Read modem side IRQ number from modem IRQ controller */
+ real_irq = readl(mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET) & 0xFF;
+ virt_irq = IRQ_MODEM_EVENTS_BASE + real_irq;
+
+ pr_debug("modem_irq: Worker read addr 0x%X and got value 0x%X "
+ "which will be 0x%X (%d) which translates to "
+ "virtual IRQ 0x%X (%d)!\n",
+ (u32)mi->modem_intcon_base + MODEM_IRQ_REG_OFFSET,
+ real_irq,
+ real_irq & 0xFF,
+ real_irq & 0xFF,
+ virt_irq,
+ virt_irq);
+
+ if (virt_irq != 0)
+ generic_handle_irq(virt_irq);
+
+ pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq);
+
+ return IRQ_HANDLED;
+}
+
+static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip)
+{
+ set_irq_chip(irq, modem_irq_chip);
+ set_irq_handler(irq, handle_simple_irq);
+ set_irq_flags(irq, IRQF_VALID);
+
+ pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
+}
+
+static int modem_irq_init(void)
+{
+ int err;
+ static struct irq_chip modem_irq_chip;
+ struct modem_irq *mi;
+
+ pr_info("modem_irq: Set up IRQ handler for incoming modem IRQ %d\n",
+ IRQ_DB5500_MODEM);
+
+ mi = kmalloc(sizeof(struct modem_irq), GFP_KERNEL);
+ if (!mi) {
+ pr_err("modem_irq: Could not allocate device\n");
+ return -ENOMEM;
+ }
+
+ mi->modem_intcon_base =
+ ioremap(MODEM_INTCON_BASE_ADDR, MODEM_INTCON_SIZE);
+ pr_debug("modem_irq: ioremapped modem_intcon_base from "
+ "phy 0x%x to virt 0x%x\n", MODEM_INTCON_BASE_ADDR,
+ (u32)mi->modem_intcon_base);
+
+ setup_modem_intcon(mi->modem_intcon_base);
+
+ modem_irq_chip = dummy_irq_chip;
+ modem_irq_chip.name = "modem_irq";
+
+ /* Create the virtual IRQ:s needed */
+ create_virtual_irq(MBOX_PAIR0_VIRT_IRQ, &modem_irq_chip);
+ create_virtual_irq(MBOX_PAIR1_VIRT_IRQ, &modem_irq_chip);
+ create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip);
+
+ err = request_threaded_irq(IRQ_DB5500_MODEM, NULL,
+ modem_cpu_irq_handler,
+ IRQF_ONESHOT, "ModemIRQ", mi);
+ if (err)
+ pr_err("modem_irq: Could not register IRQ %d\n",
+ IRQ_DB5500_MODEM);
+
+ return 0;
+}
+
+arch_initcall(modem_irq_init);
diff --git a/arch/arm/mach-ux500/musb_db8500.c b/arch/arm/mach-ux500/musb_db8500.c
new file mode 100644
index 00000000000..c6bc6bf6c05
--- /dev/null
+++ b/arch/arm/mach-ux500/musb_db8500.c
@@ -0,0 +1,955 @@
+/*
+ * Copyright (C) 2009 ST Ericsson.
+ *
+ * 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/delay.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/usb/musb.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <mach/musb_db8500.h>
+#include <mach/prcmu-fw-api.h>
+
+/* Registers in Bank 0x02 */
+#define AB8500_MAIN_WDOG_CTRL_REG 0x01
+
+/* Registers in Bank 0x05 */
+#define AB8500_REGU_VUSB_CTRL_REG 0x82
+#define AB8500_USB_LINE_STAT_REG 0x80
+#define AB8500_USB_LINE_CTRL1_REG 0x81
+#define AB8500_USB_LINE_CTRL2_REG 0x82
+#define AB8500_USB_LINE_CTRL3_REG 0x83
+#define AB8500_USB_LINE_CTRL4_REG 0x84
+#define AB8500_USB_LINE_CTRL5_REG 0x85
+#define AB8500_USB_OTG_CTRL_REG 0x87
+#define AB8500_USB_OTG_STAT_REG 0x88
+#define AB8500_USB_OTG_STAT_REG 0x88
+#define AB8500_USB_CTRL_SPARE_REG 0x89
+#define AB8500_USB_PHY_CTRL_REG 0x8A
+#define AB8500_USB_ADP_CTRL_REG 0x93
+
+/* Registers in Bank 0x0E */
+#define AB8500_IT_MASK2_REG 0x41
+#define AB8500_IT_MASK12_REG 0x4B
+#define AB8500_IT_MASK20_REG 0x53
+#define AB8500_IT_MASK21_REG 0x54
+#define AB8500_IT_SOURCE2_REG 0x01
+#define AB8500_IT_SOURCE20_REG 0x13
+
+/* Registers in bank 0x11 */
+#define AB8500_BANK12_ACCESS 0x00
+
+/* Registers in bank 0x12 */
+#define AB8500_USB_PHY_TUNE1 0x05
+#define AB8500_USB_PHY_TUNE2 0x06
+#define AB8500_USB_PHY_TUNE3 0x07
+
+#define DEVICE_NAME "musb_qos"
+
+static struct completion usb_link_status_update;
+static struct device *device;
+static struct regulator *musb_vape_supply;
+static struct regulator *musb_vintcore_supply, *musb_smps2_supply;
+static struct clk *sysclock;
+
+static int boot_time_flag = USB_DISABLE;
+static int irq_host_remove;
+static int irq_device_remove;
+static int irq_link_status_update;
+static int ab8500_rev;
+/* Phy Status. Right now Used for Device only. */
+static int phy_enable_stat = USB_DISABLE;
+#ifdef CONFIG_USB_OTG_20
+static int irq_adp_plug;
+static int irq_adp_unplug;
+#endif
+/*
+ * work queue for USB cable insertion processing
+ */
+static struct work_struct usb_host_remove;
+static struct work_struct usb_device_remove;
+static struct work_struct usb_lnk_status_update;
+static struct work_struct usb_dedicated_charger_remove;
+static struct workqueue_struct *usb_cable_wq;
+
+static void usb_host_remove_work(struct work_struct *work);
+static void usb_device_remove_work(struct work_struct *work);
+static void usb_link_status_update_work(struct work_struct *work);
+static void usb_dedicated_charger_remove_work(struct work_struct *work);
+static void usb_device_phy_en(int enable);
+static void usb_kick_watchdog(void);
+static void usb_host_phy_en(int enable);
+
+#include <linux/wakelock.h>
+static struct wake_lock ab8500_musb_wakelock;
+/**
+ * stm_musb_states - Different states of musb_chip
+ *
+ * Used for USB cable plug-in state machine
+ */
+enum stm_musb_states {
+ USB_IDLE,
+ USB_DEVICE,
+ USB_HOST,
+ USB_DEDICATED_CHG,
+};
+enum stm_musb_states stm_musb_curr_state = USB_IDLE;
+
+/* ACA Modification */
+static enum musb_link_status stm_usb_link_curr_state = USB_LINK_NOT_CONFIGURED;
+static enum musb_link_status stm_usb_link_prev_state = USB_LINK_NOT_CONFIGURED;
+
+void musb_set_session(void);
+#ifdef CONFIG_PM
+void stm_musb_context(int);
+#endif
+
+#ifdef CONFIG_USB_OTG_20
+int musb_adp(void);
+static void enable_adp(void)
+{
+ if (ab8500_rev == AB8500_REV_20)
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_ADP_CTRL_REG,
+ AB8500_USB_ADP_ENABLE);
+}
+#endif
+
+void musb_platform_session_req(void)
+{
+ /* Discaharge the VBUS */
+ /* TODO */
+}
+
+/*
+ * musb_platform_device_en(): Enable/Disable the device.
+
+ */
+
+void musb_platform_device_en(int enable)
+{
+
+
+ if ((enable == 1) && (phy_enable_stat == USB_DISABLE)) {
+ stm_musb_curr_state = USB_DEVICE;
+ usb_device_phy_en(USB_ENABLE);
+ return;
+ }
+
+ if ((enable == 1) && (phy_enable_stat == USB_ENABLE)) {
+ /* Phy already enabled. no need to do anything. */
+ return;
+ }
+
+ if ((enable == 0) && (phy_enable_stat == USB_DISABLE)) {
+ /* Phy already disabled. no need to do anything. */
+ return;
+ }
+
+ if ((enable == 0) && (phy_enable_stat == USB_ENABLE)) {
+ /* Phy enabled. Disable it */
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_DEVICE_DISABLE);
+ prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
+ DEVICE_NAME, 50);
+ prcmu_release_usb_wakeup_state();
+ regulator_disable(musb_vape_supply);
+ regulator_disable(musb_vintcore_supply);
+ regulator_disable(musb_smps2_supply);
+ clk_disable(sysclock);
+ phy_enable_stat = USB_DISABLE;
+
+ return;
+ }
+}
+
+/**
+ * usb_kick_watchdog() - Kick the watch dog timer
+ *
+ * This function used to Kick the watch dog timer
+ */
+static void usb_kick_watchdog(void)
+{
+ if ((ab8500_rev == AB8500_REV_20)
+ || (ab8500_rev == AB8500_REV_30)) {
+ abx500_set_register_interruptible(device,
+ AB8500_SYS_CTRL2_BLOCK,
+ AB8500_MAIN_WDOG_CTRL_REG,
+ AB8500_MAIN_WATCHDOG_ENABLE);
+ udelay(WATCHDOG_DELAY_US);
+ abx500_set_register_interruptible(device,
+ AB8500_SYS_CTRL2_BLOCK,
+ AB8500_MAIN_WDOG_CTRL_REG,
+ (AB8500_MAIN_WATCHDOG_ENABLE
+ | AB8500_MAIN_WATCHDOG_KICK));
+ udelay(WATCHDOG_DELAY_US);
+ abx500_set_register_interruptible(device,
+ AB8500_SYS_CTRL2_BLOCK,
+ AB8500_MAIN_WDOG_CTRL_REG,
+ AB8500_MAIN_WATCHDOG_DISABLE);
+ udelay(WATCHDOG_DELAY_US);
+ }
+}
+/**
+ * usb_host_phy_en() - for enabling the 5V to usb host
+ * @enable: to enabling the Phy for host.
+ *
+ * This function used to set the voltage for USB host mode
+ */
+static void usb_host_phy_en(int enable)
+{
+ int volt = 0;
+ int ret = -1;
+
+ if ((ab8500_rev == AB8500_REV_20)
+ || (ab8500_rev == AB8500_REV_30)) {
+ if (enable == USB_ENABLE) {
+ wake_lock(&ab8500_musb_wakelock);
+
+ clk_enable(sysclock);
+ regulator_enable(musb_vape_supply);
+ regulator_enable(musb_smps2_supply);
+
+ /* Set Vintcore12 LDO to 1.3V */
+ ret = regulator_set_voltage(musb_vintcore_supply,
+ 1300000, 1350000);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to set the Vintcore"
+ " to 1.3V, ret=%d\n", ret);
+ regulator_enable(musb_vintcore_supply);
+ volt = regulator_get_voltage(musb_vintcore_supply);
+ if ((volt != 1300000) && (volt != 1350000))
+ printk(KERN_ERR "Vintcore is not"
+ " set to 1.3V"
+ " volt=%d\n", volt);
+#ifdef CONFIG_PM
+ stm_musb_context(USB_ENABLE);
+#endif
+ usb_kick_watchdog();
+
+ prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
+ DEVICE_NAME, 100);
+
+ /* Enable the PHY */
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_HOST_ENABLE);
+ } else { /* enable == USB_DISABLE */
+ if (boot_time_flag)
+ boot_time_flag = USB_DISABLE;
+
+ /*
+ * Workaround for bug31952 in ABB cut2.0. Write 0x1
+ * before disabling the PHY.
+ */
+ abx500_set_register_interruptible(device, AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_HOST_ENABLE);
+
+ udelay(100);
+
+ abx500_set_register_interruptible(device, AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_HOST_DISABLE);
+
+ prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
+ DEVICE_NAME, 50);
+ prcmu_release_usb_wakeup_state();
+ regulator_disable(musb_vape_supply);
+ regulator_disable(musb_smps2_supply);
+ regulator_disable(musb_vintcore_supply);
+ /* Set Vintcore12 LDO to 0V to 1.35V */
+ ret = regulator_set_voltage(musb_vintcore_supply,
+ 0000000, 1350000);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to set the Vintcore"
+ " to 0V to 1.35V,"
+ " ret=%d\n", ret);
+ clk_disable(sysclock);
+ wake_unlock(&ab8500_musb_wakelock);
+ }
+ }
+}
+
+/**
+ * usb_host_remove_handler() - Removed the USB host cable
+ *
+ * This function used to detect the USB host cable removed.
+ */
+static irqreturn_t usb_host_remove_handler(int irq, void *data)
+{
+ if (stm_musb_curr_state == USB_HOST) {
+ /* Change the current state */
+ stm_musb_curr_state = USB_IDLE;
+ queue_work(usb_cable_wq, &usb_host_remove);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+/**
+ * usb_device_phy_en() - for enabling the 5V to usb gadget
+ * @enable: to enabling the Phy for device.
+ *
+ * This function used to set the voltage for USB gadget mode.
+ */
+static void usb_device_phy_en(int enable)
+{
+ int volt = 0;
+ int ret = -1;
+
+ if (phy_enable_stat == enable)
+ return;
+
+ if ((ab8500_rev == AB8500_REV_20)
+ || (ab8500_rev == AB8500_REV_30)) {
+ if (enable == USB_ENABLE) {
+ wake_lock(&ab8500_musb_wakelock);
+ clk_enable(sysclock);
+ phy_enable_stat = USB_ENABLE;
+ regulator_enable(musb_vape_supply);
+ regulator_enable(musb_smps2_supply);
+
+ /* Set Vintcore12 LDO to 1.3V */
+ ret = regulator_set_voltage(musb_vintcore_supply,
+ 1300000, 1350000);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to set the Vintcore"
+ " to 1.3V, ret=%d\n", ret);
+ regulator_enable(musb_vintcore_supply);
+ volt = regulator_get_voltage(musb_vintcore_supply);
+ if ((volt != 1300000) && (volt != 1350000))
+ printk(KERN_ERR "Vintcore is not"
+ " set to 1.3V"
+ " volt=%d\n", volt);
+#ifdef CONFIG_PM
+ stm_musb_context(USB_ENABLE);
+#endif
+ usb_kick_watchdog();
+
+ prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
+ DEVICE_NAME, 100);
+
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_DEVICE_ENABLE);
+ } else { /* enable == USB_DISABLE */
+ if (boot_time_flag)
+ boot_time_flag = USB_DISABLE;
+
+ /*
+ * Workaround for bug31952 in ABB cut2.0. Write 0x1
+ * before disabling the PHY.
+ */
+ abx500_set_register_interruptible(device, AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_DEVICE_ENABLE);
+
+ udelay(100);
+
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_DEVICE_DISABLE);
+ prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
+ DEVICE_NAME, 50);
+ prcmu_release_usb_wakeup_state();
+ phy_enable_stat = USB_DISABLE;
+ regulator_disable(musb_vape_supply);
+ regulator_disable(musb_smps2_supply);
+ regulator_disable(musb_vintcore_supply);
+ /* Set Vintcore12 LDO to 0V to 1.35V */
+ ret = regulator_set_voltage(musb_vintcore_supply,
+ 0000000, 1350000);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to set the Vintcore"
+ " to 0V to 1.35V,"
+ " ret=%d\n", ret);
+ clk_disable(sysclock);
+ stm_musb_context(USB_DISABLE);
+ wake_unlock(&ab8500_musb_wakelock);
+ }
+ }
+}
+
+/**
+ * usb_device_remove_handler() - remove the 5V to usb device
+ *
+ * This function used to remove the voltage for USB device mode.
+ */
+static irqreturn_t usb_device_remove_handler(int irq, void *data)
+{
+ if (stm_musb_curr_state == USB_DEVICE) {
+ /* Change the current state */
+ stm_musb_curr_state = USB_IDLE;
+ queue_work(usb_cable_wq, &usb_device_remove);
+ return IRQ_HANDLED;
+ } else if (stm_musb_curr_state == USB_DEDICATED_CHG) {
+ stm_musb_curr_state = USB_IDLE;
+ if (ab8500_rev == AB8500_REV_20)
+ queue_work(usb_cable_wq, &usb_dedicated_charger_remove);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+/**
+ * usb_link_status_update_handler() - USB Link status update complete
+ *
+ * This function is used to signal the completion of
+ * USB Link status register update
+ */
+static irqreturn_t usb_link_status_update_handler(int irq, void *data)
+{
+ queue_work(usb_cable_wq, &usb_lnk_status_update);
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_USB_OTG_20
+static irqreturn_t irq_adp_plug_handler(int irq, void *data)
+{
+ int ret;
+
+ ret = musb_adp();
+ if (ret) {
+
+ if (stm_musb_curr_state == USB_HOST)
+ musb_set_session();
+ if (stm_musb_curr_state == USB_DEVICE) {
+ /*TODO*/
+ /* Generate SRP */
+ }
+ if (stm_musb_curr_state == USB_IDLE)
+ printk(KERN_INFO "No device is connected\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t irq_adp_unplug_handler(int irq, void *data)
+{
+ if (stm_musb_curr_state == USB_HOST) {
+ stm_musb_curr_state = USB_IDLE;
+ queue_work(usb_cable_wq, &usb_host_remove);
+ }
+ if (stm_musb_curr_state == USB_DEVICE) {
+ stm_musb_curr_state = USB_IDLE;
+ queue_work(usb_cable_wq, &usb_device_remove);
+ }
+
+ return IRQ_HANDLED;
+}
+#endif
+
+/**
+ * musb_phy_en : register USB callback handlers for ab8500
+ * @mode: value for mode.
+ *
+ * This function is used to register USB callback handlers for ab8500.
+ */
+int musb_phy_en(u8 mode)
+{
+ int ret = -1;
+
+ if (!device)
+ return -EINVAL;
+ ab8500_rev = abx500_get_chip_id(device);
+ if (ab8500_rev < 0) {
+ dev_err(device, "get chip id failed\n");
+ return ab8500_rev;
+ }
+ if (!((ab8500_rev == AB8500_REV_20)
+ || (ab8500_rev == AB8500_REV_30))) {
+ dev_err(device, "Unknown AB type!\n");
+ return -ENODEV;
+ }
+ musb_vape_supply = regulator_get(device, "v-ape");
+ if (IS_ERR(musb_vape_supply)) {
+ dev_err(device, "Could not get %s:v-ape supply\n",
+ dev_name(device));
+
+ ret = PTR_ERR(musb_vape_supply);
+ return ret;
+ }
+ musb_vintcore_supply = regulator_get(device, "v-intcore");
+ if (IS_ERR(musb_vintcore_supply)) {
+ dev_err(device, "Could not get %s:v-intcore12 supply\n",
+ dev_name(device));
+
+ ret = PTR_ERR(musb_vintcore_supply);
+ return ret;
+ }
+ musb_smps2_supply = regulator_get(device, "musb_1v8");
+ if (IS_ERR(musb_smps2_supply)) {
+ dev_err(device, "Could not get %s:v-intcore12 supply\n",
+ dev_name(device));
+
+ ret = PTR_ERR(musb_smps2_supply);
+ return ret;
+ }
+ sysclock = clk_get(device, "sysclk");
+ if (IS_ERR(sysclock)) {
+ ret = PTR_ERR(sysclock);
+ sysclock = NULL;
+ return ret;
+ }
+ /*
+ * When usb cable is not connected,set Qos for VAPE to 50.
+ * This is done to run APE at low OPP when usb is not used.
+ */
+ prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, DEVICE_NAME, 50);
+ if ((ab8500_rev == AB8500_REV_20)
+ || (ab8500_rev == AB8500_REV_30)) {
+ if (mode == MUSB_HOST || mode == MUSB_OTG) {
+ ret = request_threaded_irq(irq_host_remove, NULL,
+ usb_host_remove_handler,
+ IRQF_NO_SUSPEND | IRQF_SHARED,
+ "usb-host-remove", device);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to set the callback"
+ " handler for usb host"
+ " removal\n");
+ return ret;
+ }
+ }
+ if ((mode == MUSB_PERIPHERAL) || (mode == MUSB_OTG)) {
+ ret = request_threaded_irq(irq_device_remove, NULL,
+ usb_device_remove_handler,
+ IRQF_NO_SUSPEND | IRQF_SHARED,
+ "usb-device-remove", device);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to set the callback"
+ " handler for usb host"
+ " removal\n");
+ return ret;
+ }
+ }
+
+ /* create a thread for work */
+ usb_cable_wq = create_singlethread_workqueue(
+ "usb_cable_wq");
+ if (usb_cable_wq == NULL)
+ return -ENOMEM;
+
+ INIT_WORK(&usb_host_remove, usb_host_remove_work);
+ INIT_WORK(&usb_device_remove, usb_device_remove_work);
+ INIT_WORK(&usb_lnk_status_update,
+ usb_link_status_update_work);
+
+ if (ab8500_rev == AB8500_REV_20)
+ INIT_WORK(&usb_dedicated_charger_remove,
+ usb_dedicated_charger_remove_work);
+
+ /* Required for Host, Device and OTG mode */
+ init_completion(&usb_link_status_update);
+ ret = request_threaded_irq(irq_link_status_update,
+ NULL, usb_link_status_update_handler,
+ IRQF_NO_SUSPEND | IRQF_SHARED,
+ "usb-link-status-update", device);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to set the callback"
+ " handler for usb charge"
+ " detect done\n");
+ return ret;
+ }
+#ifdef CONFIG_USB_OTG_20
+ ret = request_threaded_irq(irq_adp_plug, NULL,
+ irq_adp_plug_handler,
+ IRQF_SHARED, "usb-adp-plug", device);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to set the callback"
+ " handler for usb adp"
+ " plug\n");
+ return ret;
+ }
+ ret = request_threaded_irq(irq_adp_unplug, NULL,
+ irq_adp_unplug_handler,
+ IRQF_SHARED, "usb-adp-unplug", device);
+ if (ret < 0) {
+ printk(KERN_ERR "failed to set the callback"
+ " handler for usb adp"
+ " unplug\n");
+ return ret;
+ }
+#endif
+ /* Write Phy tuning values */
+ if (ab8500_rev == AB8500_REV_30) {
+ /* Enable the PBT/Bank 0x12 access */
+ ret = abx500_set_register_interruptible(device,
+ AB8500_DEVELOPMENT,
+ AB8500_BANK12_ACCESS,
+ 0x01);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to enable bank12"
+ " access ret=%d\n", ret);
+
+ ret = abx500_set_register_interruptible(device,
+ AB8500_DEBUG,
+ AB8500_USB_PHY_TUNE1,
+ 0xC8);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to set PHY_TUNE1"
+ " register ret=%d\n", ret);
+
+ ret = abx500_set_register_interruptible(device,
+ AB8500_DEBUG,
+ AB8500_USB_PHY_TUNE2,
+ 0x00);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to set PHY_TUNE2"
+ " register ret=%d\n", ret);
+
+ ret = abx500_set_register_interruptible(device,
+ AB8500_DEBUG,
+ AB8500_USB_PHY_TUNE3,
+ 0x78);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to set PHY_TUNE3"
+ " regester ret=%d\n", ret);
+
+ /* Switch to normal mode/disable Bank 0x12 access */
+ ret = abx500_set_register_interruptible(device,
+ AB8500_DEVELOPMENT,
+ AB8500_BANK12_ACCESS,
+ 0x00);
+ if (ret < 0)
+ printk(KERN_ERR "Failed to switch bank12"
+ " access ret=%d\n", ret);
+ }
+ usb_kick_watchdog();
+ }
+ return 0;
+}
+/**
+ * musb_force_detect : detect the USB cable during boot time.
+ * @mode: value for mode.
+ *
+ * This function is used to detect the USB cable during boot time.
+ */
+int musb_force_detect(u8 mode)
+{
+ int ret;
+ u8 usb_status = 0;
+ u8 val = 0;
+
+ if (!device)
+ return -EINVAL;
+
+ if ((ab8500_rev == AB8500_REV_20)
+ || (ab8500_rev == AB8500_REV_30)) {
+ /* Disabling PHY before selective enable or disable */
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_DEVICE_ENABLE);
+
+ udelay(100);
+
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_DEVICE_DISABLE);
+
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_HOST_ENABLE);
+
+ udelay(100);
+
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_HOST_DISABLE);
+
+ if (mode == MUSB_HOST || mode == MUSB_OTG) {
+ ret = abx500_get_register_interruptible(device,
+ AB8500_INTERRUPT, AB8500_IT_SOURCE20_REG,
+ &usb_status);
+ if (ret < 0) {
+ dev_err(device, "Read IT 20 failed\n");
+ return ret;
+ }
+
+ if (usb_status & AB8500_SRC_INT_USB_HOST) {
+ boot_time_flag = USB_ENABLE;
+ /* Change the current state */
+ stm_musb_curr_state = USB_HOST;
+ usb_host_phy_en(USB_ENABLE);
+ }
+ }
+ if (mode == MUSB_PERIPHERAL || mode == MUSB_OTG) {
+ ret = abx500_get_register_interruptible(device,
+ AB8500_INTERRUPT, AB8500_IT_SOURCE2_REG,
+ &usb_status);
+ if (ret < 0) {
+ dev_err(device, "Read IT 2 failed\n");
+ return ret;
+ }
+
+ if (usb_status & AB8500_SRC_INT_USB_DEVICE) {
+ /* Check if it is a dedicated charger */
+ (void)abx500_get_register_interruptible(device,
+ AB8500_USB, AB8500_USB_LINE_STAT_REG, &val);
+
+ val = (val & AB8500_USB_LINK_STATUS) >> 3;
+
+ if (val == USB_LINK_DEDICATED_CHG) {
+ /* Change the current state */
+ stm_musb_curr_state = USB_DEDICATED_CHG;
+ } else {
+ boot_time_flag = USB_ENABLE;
+ /* Change the current state */
+ stm_musb_curr_state = USB_DEVICE;
+ usb_device_phy_en(USB_ENABLE);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * usb_host_remove_work : work handler for host cable insert.
+ * @work: work structure
+ *
+ * This function is used to handle the host cable insert work.
+ */
+static void usb_host_remove_work(struct work_struct *work)
+{
+ usb_host_phy_en(USB_DISABLE);
+}
+
+/**
+ * usb_device_remove_work : work handler for device cable insert.
+ * @work: work structure
+ *
+ * This function is used to handle the device cable insert work.
+ */
+static void usb_device_remove_work(struct work_struct *work)
+{
+ usb_device_phy_en(USB_DISABLE);
+}
+
+/* Work created for PHY handling in case of dedicated charger disconnect */
+static void usb_dedicated_charger_remove_work(struct work_struct *work)
+{
+ /*
+ * Workaround for bug31952 in ABB cut2.0. Write 0x1
+ * before disabling the PHY.
+ */
+ abx500_set_register_interruptible(device, AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_DEVICE_ENABLE);
+
+ udelay(100);
+
+ abx500_set_register_interruptible(device,
+ AB8500_USB,
+ AB8500_USB_PHY_CTRL_REG,
+ AB8500_USB_DEVICE_DISABLE);
+}
+
+/* Work created after an link status update handler*/
+static void usb_link_status_update_work(struct work_struct *work)
+{
+ u8 val = 0;
+
+ (void)abx500_get_register_interruptible(device,
+ AB8500_USB, AB8500_USB_LINE_STAT_REG, &val);
+
+ val = (val & AB8500_USB_LINK_STATUS) >> 3;
+ stm_usb_link_curr_state = (enum stm_musb_states) val;
+
+ switch (stm_usb_link_curr_state) {
+ case USB_LINK_DEDICATED_CHG:
+ stm_musb_curr_state = USB_DEDICATED_CHG;
+ break;
+ case USB_LINK_NOT_CONFIGURED:
+ case USB_LINK_NOT_VALID_LINK:
+ case USB_LINK_ACA_RID_B:
+ /* PHY is disabled */
+ switch (stm_musb_curr_state) {
+ case USB_DEVICE:
+ /* Change the current state */
+ stm_musb_curr_state = USB_IDLE;
+ usb_device_phy_en(USB_DISABLE);
+ break;
+ case USB_HOST:
+ /* Change the current state */
+ stm_musb_curr_state = USB_IDLE;
+ usb_host_phy_en(USB_DISABLE);
+ break;
+ case USB_IDLE:
+ case USB_DEDICATED_CHG:
+ break;
+ }
+ break;
+ case USB_LINK_STD_HOST_NC:
+ case USB_LINK_STD_HOST_C_NS:
+ case USB_LINK_STD_HOST_C_S:
+ case USB_LINK_HOST_CHG_NM:
+ case USB_LINK_HOST_CHG_HS:
+ case USB_LINK_HOST_CHG_HS_CHIRP:
+ case USB_LINK_ACA_RID_C_NM:
+ case USB_LINK_ACA_RID_C_HS:
+ case USB_LINK_ACA_RID_C_HS_CHIRP:
+ /* Device PHY is enabled */
+ switch (stm_musb_curr_state) {
+ case USB_HOST:
+ /* Change the current state */
+ stm_musb_curr_state = USB_DEVICE;
+ usb_host_phy_en(USB_DISABLE);
+ usb_device_phy_en(USB_ENABLE);
+ break;
+ case USB_IDLE:
+ /* Change the current state */
+ stm_musb_curr_state = USB_DEVICE;
+ usb_device_phy_en(USB_ENABLE);
+ break;
+ case USB_DEVICE:
+ case USB_DEDICATED_CHG:
+ break;
+ }
+ break;
+ case USB_LINK_HM_IDGND:
+ case USB_LINK_ACA_RID_A:
+ /* Host PHY is enabled */
+ switch (stm_musb_curr_state) {
+ case USB_DEVICE:
+ /* Change the current state */
+ stm_musb_curr_state = USB_HOST;
+ usb_device_phy_en(USB_DISABLE);
+ usb_host_phy_en(USB_ENABLE);
+ musb_set_session();
+ break;
+ case USB_IDLE:
+ /* Change the current state */
+ stm_musb_curr_state = USB_HOST;
+ usb_host_phy_en(USB_ENABLE);
+ musb_set_session();
+ break;
+ case USB_HOST:
+ case USB_DEDICATED_CHG:
+ break;
+ }
+ break;
+ case USB_LINK_OTG_HOST_NO_CURRENT:
+ default:
+ break;
+ }
+ stm_usb_link_prev_state = stm_usb_link_curr_state;
+}
+
+/*
+ * musb_get_abx500_rev : Get the ABx500 revision number
+ *
+ * This function returns the ABx500 revision number.
+ */
+int musb_get_abx500_rev()
+{
+ return ab8500_rev;
+}
+
+static int __devinit ab8500_musb_probe(struct platform_device *pdev)
+{
+#ifdef CONFIG_USB_OTG_20
+ u8 usb_status = 0;
+ int ret;
+#endif
+ device = &pdev->dev;
+ irq_host_remove = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
+ if (irq_host_remove < 0) {
+ dev_err(&pdev->dev, "Host remove irq not found, err %d\n",
+ irq_host_remove);
+ return irq_host_remove;
+ }
+
+ irq_device_remove = platform_get_irq_byname(pdev, "VBUS_DET_F");
+ if (irq_device_remove < 0) {
+ dev_err(&pdev->dev, "Device remove irq not found, err %d\n",
+ irq_device_remove);
+ return irq_device_remove;
+ }
+
+ irq_link_status_update = platform_get_irq_byname(pdev,
+ "USB_LINK_STATUS");
+ if (irq_link_status_update < 0) {
+ dev_err(&pdev->dev, "USB Link status irq not found, err %d\n",
+ irq_link_status_update);
+ return irq_link_status_update;
+ }
+
+#ifdef CONFIG_USB_OTG_20
+ enable_adp();
+ irq_adp_plug = platform_get_irq_byname(pdev, "USB_ADP_PROBE_PLUG");
+ if (irq_adp_plug < 0) {
+ dev_err(&pdev->dev, "ADP Probe plug irq not found, err %d\n",
+ irq_adp_plug);
+ return irq_adp_plug;
+ }
+ irq_adp_unplug = platform_get_irq_byname(pdev, "USB_ADP_PROBE_UNPLUG");
+ if (irq_adp_unplug < 0) {
+ dev_err(&pdev->dev, "ADP Probe unplug irq not found,"
+ " err %d\n",
+ irq_adp_unplug);
+ return irq_adp_unplug;
+ }
+ ret = abx500_get_register_interruptible(device,
+ AB8500_INTERRUPT, AB8500_IT_SOURCE20_REG,
+ &usb_status);
+ if (ret < 0) {
+ dev_err(device, "Read IT 2 failed\n");
+ return ret;
+ }
+
+ if (usb_status & AB8500_USB_DEVICE_ENABLE) {
+ boot_time_flag = USB_ENABLE;
+ stm_musb_curr_state = USB_DEVICE;
+ musb_phy_en(MUSB_HOST);
+ }
+#endif
+
+ wake_lock_init(&ab8500_musb_wakelock, WAKE_LOCK_SUSPEND, "ab8500-usb");
+ return 0;
+}
+
+static int __devexit ab8500_musb_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver ab8500_musb_driver = {
+ .driver = {
+ .name = "ab8500-usb",
+ .owner = THIS_MODULE,
+ },
+ .probe = ab8500_musb_probe,
+ .remove = __devexit_p(ab8500_musb_remove),
+};
+
+static int __init ab8500_musb_init(void)
+{
+ return platform_driver_register(&ab8500_musb_driver);
+}
+module_init(ab8500_musb_init);
+
+static void __exit ab8500_musb_exit(void)
+{
+ platform_driver_unregister(&ab8500_musb_driver);
+}
+module_exit(ab8500_musb_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-ux500/pins-db5500.h b/arch/arm/mach-ux500/pins-db5500.h
new file mode 100644
index 00000000000..bf50c21fe69
--- /dev/null
+++ b/arch/arm/mach-ux500/pins-db5500.h
@@ -0,0 +1,620 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ */
+
+#ifndef __MACH_DB5500_PINS_H
+#define __MACH_DB5500_PINS_H
+
+#define GPIO0_GPIO PIN_CFG(0, GPIO)
+#define GPIO0_SM_CS3n PIN_CFG(0, ALT_A)
+
+#define GPIO1_GPIO PIN_CFG(1, GPIO)
+#define GPIO1_SM_A3 PIN_CFG(1, ALT_A)
+
+#define GPIO2_GPIO PIN_CFG(2, GPIO)
+#define GPIO2_SM_A4 PIN_CFG(2, ALT_A)
+#define GPIO2_SM_AVD PIN_CFG(2, ALT_B)
+
+#define GPIO3_GPIO PIN_CFG(3, GPIO)
+#define GPIO3_I2C1_SCL PIN_CFG(3, ALT_A)
+
+#define GPIO4_GPIO PIN_CFG(4, GPIO)
+#define GPIO4_I2C1_SDA PIN_CFG(4, ALT_A)
+
+#define GPIO5_GPIO PIN_CFG(5, GPIO)
+#define GPIO5_MC0_DAT0 PIN_CFG(5, ALT_A)
+#define GPIO5_SM_ADQ8 PIN_CFG(5, ALT_B)
+
+#define GPIO6_GPIO PIN_CFG(6, GPIO)
+#define GPIO6_MC0_DAT1 PIN_CFG(6, ALT_A)
+#define GPIO6_SM_ADQ0 PIN_CFG(6, ALT_B)
+
+#define GPIO7_GPIO PIN_CFG(7, GPIO)
+#define GPIO7_MC0_DAT2 PIN_CFG(7, ALT_A)
+#define GPIO7_SM_ADQ9 PIN_CFG(7, ALT_B)
+
+#define GPIO8_GPIO PIN_CFG(8, GPIO)
+#define GPIO8_MC0_DAT3 PIN_CFG(8, ALT_A)
+#define GPIO8_SM_ADQ1 PIN_CFG(8, ALT_B)
+
+#define GPIO9_GPIO PIN_CFG(9, GPIO)
+#define GPIO9_MC0_DAT4 PIN_CFG(9, ALT_A)
+#define GPIO9_SM_ADQ10 PIN_CFG(9, ALT_B)
+
+#define GPIO10_GPIO PIN_CFG(10, GPIO)
+#define GPIO10_MC0_DAT5 PIN_CFG(10, ALT_A)
+#define GPIO10_SM_ADQ2 PIN_CFG(10, ALT_B)
+
+#define GPIO11_GPIO PIN_CFG(11, GPIO)
+#define GPIO11_MC0_DAT6 PIN_CFG(11, ALT_A)
+#define GPIO11_SM_ADQ11 PIN_CFG(11, ALT_B)
+
+#define GPIO12_GPIO PIN_CFG(12, GPIO)
+#define GPIO12_MC0_DAT7 PIN_CFG(12, ALT_A)
+#define GPIO12_SM_ADQ3 PIN_CFG(12, ALT_B)
+
+#define GPIO13_GPIO PIN_CFG(13, GPIO)
+#define GPIO13_MC0_CMD PIN_CFG(13, ALT_A)
+#define GPIO13_SM_BUSY0n PIN_CFG(13, ALT_B)
+#define GPIO13_SM_WAIT0n PIN_CFG(13, ALT_C)
+
+#define GPIO14_GPIO PIN_CFG(14, GPIO)
+#define GPIO14_MC0_CLK PIN_CFG(14, ALT_A)
+#define GPIO14_SM_CS1n PIN_CFG(14, ALT_B)
+#define GPIO14_SM_CKO PIN_CFG(14, ALT_C)
+
+#define GPIO15_GPIO PIN_CFG(15, GPIO)
+#define GPIO15_SM_A5 PIN_CFG(15, ALT_A)
+#define GPIO15_SM_CLE PIN_CFG(15, ALT_B)
+
+#define GPIO16_GPIO PIN_CFG(16, GPIO)
+#define GPIO16_MC2_CMD PIN_CFG(16, ALT_A)
+#define GPIO16_SM_OEn PIN_CFG(16, ALT_B)
+
+#define GPIO17_GPIO PIN_CFG(17, GPIO)
+#define GPIO17_MC2_CLK PIN_CFG(17, ALT_A)
+#define GPIO17_SM_WEn PIN_CFG(17, ALT_B)
+
+#define GPIO18_GPIO PIN_CFG(18, GPIO)
+#define GPIO18_SM_A6 PIN_CFG(18, ALT_A)
+#define GPIO18_SM_ALE PIN_CFG(18, ALT_B)
+#define GPIO18_SM_AVDn PIN_CFG(18, ALT_C)
+
+#define GPIO19_GPIO PIN_CFG(19, GPIO)
+#define GPIO19_MC2_DAT1 PIN_CFG(19, ALT_A)
+#define GPIO19_SM_ADQ4 PIN_CFG(19, ALT_B)
+
+#define GPIO20_GPIO PIN_CFG(20, GPIO)
+#define GPIO20_MC2_DAT3 PIN_CFG(20, ALT_A)
+#define GPIO20_SM_ADQ5 PIN_CFG(20, ALT_B)
+
+#define GPIO21_GPIO PIN_CFG(21, GPIO)
+#define GPIO21_MC2_DAT5 PIN_CFG(21, ALT_A)
+#define GPIO21_SM_ADQ6 PIN_CFG(21, ALT_B)
+
+#define GPIO22_GPIO PIN_CFG(22, GPIO)
+#define GPIO22_MC2_DAT7 PIN_CFG(22, ALT_A)
+#define GPIO22_SM_ADQ7 PIN_CFG(22, ALT_B)
+
+#define GPIO23_GPIO PIN_CFG(23, GPIO)
+#define GPIO23_MC2_DAT0 PIN_CFG(23, ALT_A)
+#define GPIO23_SM_ADQ12 PIN_CFG(23, ALT_B)
+#define GPIO23_MC0_DAT1 PIN_CFG(23, ALT_C)
+
+#define GPIO24_GPIO PIN_CFG(24, GPIO)
+#define GPIO24_MC2_DAT2 PIN_CFG(24, ALT_A)
+#define GPIO24_SM_ADQ13 PIN_CFG(24, ALT_B)
+#define GPIO24_MC0_DAT3 PIN_CFG(24, ALT_C)
+
+#define GPIO25_GPIO PIN_CFG(25, GPIO)
+#define GPIO25_MC2_DAT4 PIN_CFG(25, ALT_A)
+#define GPIO25_SM_ADQ14 PIN_CFG(25, ALT_B)
+#define GPIO25_MC0_CMD PIN_CFG(25, ALT_C)
+
+#define GPIO26_GPIO PIN_CFG(26, GPIO)
+#define GPIO26_MC2_DAT6 PIN_CFG(26, ALT_A)
+#define GPIO26_SM_ADQ15 PIN_CFG(26, ALT_B)
+
+#define GPIO27_GPIO PIN_CFG(27, GPIO)
+#define GPIO27_SM_CS0n PIN_CFG(27, ALT_A)
+#define GPIO27_SM_PS0n PIN_CFG(27, ALT_B)
+
+#define GPIO28_GPIO PIN_CFG(28, GPIO)
+#define GPIO28_U0_TXD PIN_CFG(28, ALT_A)
+#define GPIO28_SM_A0 PIN_CFG(28, ALT_B)
+
+#define GPIO29_GPIO PIN_CFG(29, GPIO)
+#define GPIO29_U0_RXD PIN_CFG(29, ALT_A)
+#define GPIO29_SM_A1 PIN_CFG(29, ALT_B)
+#define GPIO29_PWM_0 PIN_CFG(29, ALT_C)
+
+#define GPIO30_GPIO PIN_CFG(30, GPIO)
+#define GPIO30_MC0_DAT5 PIN_CFG(30, ALT_A)
+#define GPIO30_SM_A2 PIN_CFG(30, ALT_B)
+#define GPIO30_PWM_1 PIN_CFG(30, ALT_C)
+
+#define GPIO31_GPIO PIN_CFG(31, GPIO)
+#define GPIO31_MC0_DAT7 PIN_CFG(31, ALT_A)
+#define GPIO31_SM_CS2n PIN_CFG(31, ALT_B)
+#define GPIO31_PWM_2 PIN_CFG(31, ALT_C)
+
+#define GPIO32_GPIO PIN_CFG(32, GPIO)
+#define GPIO32_MSP0_TCK PIN_CFG(32, ALT_A)
+#define GPIO32_ACCI2S0_SCK PIN_CFG(32, ALT_B)
+
+#define GPIO33_GPIO PIN_CFG(33, GPIO)
+#define GPIO33_MSP0_TFS PIN_CFG(33, ALT_A)
+#define GPIO33_ACCI2S0_WS PIN_CFG(33, ALT_B)
+
+#define GPIO34_GPIO PIN_CFG(34, GPIO)
+#define GPIO34_MSP0_TXD PIN_CFG(34, ALT_A)
+#define GPIO34_ACCI2S0_DLD PIN_CFG(34, ALT_B)
+
+#define GPIO35_GPIO PIN_CFG(35, GPIO)
+#define GPIO35_MSP0_RXD PIN_CFG(35, ALT_A)
+#define GPIO35_ACCI2S0_ULD PIN_CFG(35, ALT_B)
+
+#define GPIO64_GPIO PIN_CFG(64, GPIO)
+#define GPIO64_USB_DAT0 PIN_CFG(64, ALT_A)
+#define GPIO64_U0_TXD PIN_CFG(64, ALT_B)
+
+#define GPIO65_GPIO PIN_CFG(65, GPIO)
+#define GPIO65_USB_DAT1 PIN_CFG(65, ALT_A)
+#define GPIO65_U0_RXD PIN_CFG(65, ALT_B)
+
+#define GPIO66_GPIO PIN_CFG(66, GPIO)
+#define GPIO66_USB_DAT2 PIN_CFG(66, ALT_A)
+
+#define GPIO67_GPIO PIN_CFG(67, GPIO)
+#define GPIO67_USB_DAT3 PIN_CFG(67, ALT_A)
+
+#define GPIO68_GPIO PIN_CFG(68, GPIO)
+#define GPIO68_USB_DAT4 PIN_CFG(68, ALT_A)
+
+#define GPIO69_GPIO PIN_CFG(69, GPIO)
+#define GPIO69_USB_DAT5 PIN_CFG(69, ALT_A)
+
+#define GPIO70_GPIO PIN_CFG(70, GPIO)
+#define GPIO70_USB_DAT6 PIN_CFG(70, ALT_A)
+
+#define GPIO71_GPIO PIN_CFG(71, GPIO)
+#define GPIO71_USB_DAT7 PIN_CFG(71, ALT_A)
+
+#define GPIO72_GPIO PIN_CFG(72, GPIO)
+#define GPIO72_USB_STP PIN_CFG(72, ALT_A)
+
+#define GPIO73_GPIO PIN_CFG(73, GPIO)
+#define GPIO73_USB_DIR PIN_CFG(73, ALT_A)
+
+#define GPIO74_GPIO PIN_CFG(74, GPIO)
+#define GPIO74_USB_NXT PIN_CFG(74, ALT_A)
+
+#define GPIO75_GPIO PIN_CFG(75, GPIO)
+#define GPIO75_USB_XCLK PIN_CFG(75, ALT_A)
+
+#define GPIO76_GPIO PIN_CFG(76, GPIO)
+
+#define GPIO77_GPIO PIN_CFG(77, GPIO)
+#define GPIO77_ACCTX_ON PIN_CFG(77, ALT_A)
+
+#define GPIO78_GPIO PIN_CFG(78, GPIO)
+#define GPIO78_IRQn PIN_CFG(78, ALT_A)
+
+#define GPIO79_GPIO PIN_CFG(79, GPIO)
+#define GPIO79_ACCSIM_Clk PIN_CFG(79, ALT_A)
+
+#define GPIO80_GPIO PIN_CFG(80, GPIO)
+#define GPIO80_ACCSIM_Da PIN_CFG(80, ALT_A)
+
+#define GPIO81_GPIO PIN_CFG(81, GPIO)
+#define GPIO81_ACCSIM_Reset PIN_CFG(81, ALT_A)
+
+#define GPIO82_GPIO PIN_CFG(82, GPIO)
+#define GPIO82_ACCSIM_DDir PIN_CFG(82, ALT_A)
+
+#define GPIO96_GPIO PIN_CFG(96, GPIO)
+#define GPIO96_MSP1_TCK PIN_CFG(96, ALT_A)
+#define GPIO96_PRCMU_DEBUG3 PIN_CFG(96, ALT_B)
+#define GPIO96_PRCMU_DEBUG7 PIN_CFG(96, ALT_C)
+
+#define GPIO97_GPIO PIN_CFG(97, GPIO)
+#define GPIO97_MSP1_TFS PIN_CFG(97, ALT_A)
+#define GPIO97_PRCMU_DEBUG2 PIN_CFG(97, ALT_B)
+#define GPIO97_PRCMU_DEBUG6 PIN_CFG(97, ALT_C)
+
+#define GPIO98_GPIO PIN_CFG(98, GPIO)
+#define GPIO98_MSP1_TXD PIN_CFG(98, ALT_A)
+#define GPIO98_PRCMU_DEBUG1 PIN_CFG(98, ALT_B)
+#define GPIO98_PRCMU_DEBUG5 PIN_CFG(98, ALT_C)
+
+#define GPIO99_GPIO PIN_CFG(99, GPIO)
+#define GPIO99_MSP1_RXD PIN_CFG(99, ALT_A)
+#define GPIO99_PRCMU_DEBUG0 PIN_CFG(99, ALT_B)
+#define GPIO99_PRCMU_DEBUG4 PIN_CFG(99, ALT_C)
+
+#define GPIO100_GPIO PIN_CFG(100, GPIO)
+#define GPIO100_I2C0_SCL PIN_CFG(100, ALT_A)
+
+#define GPIO101_GPIO PIN_CFG(101, GPIO)
+#define GPIO101_I2C0_SDA PIN_CFG(101, ALT_A)
+
+#define GPIO128_GPIO PIN_CFG(128, GPIO)
+#define GPIO128_KP_I0 PIN_CFG(128, ALT_A)
+#define GPIO128_BUSMON_D0 PIN_CFG(128, ALT_B)
+
+#define GPIO129_GPIO PIN_CFG(129, GPIO)
+#define GPIO129_KP_O0 PIN_CFG(129, ALT_A)
+#define GPIO129_BUSMON_D1 PIN_CFG(129, ALT_B)
+
+#define GPIO130_GPIO PIN_CFG(130, GPIO)
+#define GPIO130_KP_I1 PIN_CFG(130, ALT_A)
+#define GPIO130_BUSMON_D2 PIN_CFG(130, ALT_B)
+
+#define GPIO131_GPIO PIN_CFG(131, GPIO)
+#define GPIO131_KP_O1 PIN_CFG(131, ALT_A)
+#define GPIO131_BUSMON_D3 PIN_CFG(131, ALT_B)
+
+#define GPIO132_GPIO PIN_CFG(132, GPIO)
+#define GPIO132_KP_I2 PIN_CFG(132, ALT_A)
+#define GPIO132_ETM_D15 PIN_CFG(132, ALT_B)
+#define GPIO132_STMAPE_CLK PIN_CFG(132, ALT_C)
+
+#define GPIO133_GPIO PIN_CFG(133, GPIO)
+#define GPIO133_KP_O2 PIN_CFG(133, ALT_A)
+#define GPIO133_ETM_D14 PIN_CFG(133, ALT_B)
+#define GPIO133_U0_RXD PIN_CFG(133, ALT_C)
+
+#define GPIO134_GPIO PIN_CFG(134, GPIO)
+#define GPIO134_KP_I3 PIN_CFG(134, ALT_A)
+#define GPIO134_ETM_D13 PIN_CFG(134, ALT_B)
+#define GPIO134_STMAPE_DAT0 PIN_CFG(134, ALT_C)
+
+#define GPIO135_GPIO PIN_CFG(135, GPIO)
+#define GPIO135_KP_O3 PIN_CFG(135, ALT_A)
+#define GPIO135_ETM_D12 PIN_CFG(135, ALT_B)
+#define GPIO135_STMAPE_DAT1 PIN_CFG(135, ALT_C)
+
+#define GPIO136_GPIO PIN_CFG(136, GPIO)
+#define GPIO136_KP_I4 PIN_CFG(136, ALT_A)
+#define GPIO136_ETM_D11 PIN_CFG(136, ALT_B)
+#define GPIO136_STMAPE_DAT2 PIN_CFG(136, ALT_C)
+
+#define GPIO137_GPIO PIN_CFG(137, GPIO)
+#define GPIO137_KP_O4 PIN_CFG(137, ALT_A)
+#define GPIO137_ETM_D10 PIN_CFG(137, ALT_B)
+#define GPIO137_STMAPE_DAT3 PIN_CFG(137, ALT_C)
+
+#define GPIO138_GPIO PIN_CFG(138, GPIO)
+#define GPIO138_KP_I5 PIN_CFG(138, ALT_A)
+#define GPIO138_ETM_D9 PIN_CFG(138, ALT_B)
+#define GPIO138_U0_TXD PIN_CFG(138, ALT_C)
+
+#define GPIO139_GPIO PIN_CFG(139, GPIO)
+#define GPIO139_KP_O5 PIN_CFG(139, ALT_A)
+#define GPIO139_ETM_D8 PIN_CFG(139, ALT_B)
+#define GPIO139_BUSMON_D11 PIN_CFG(139, ALT_C)
+
+#define GPIO140_GPIO PIN_CFG(140, GPIO)
+#define GPIO140_KP_I6 PIN_CFG(140, ALT_A)
+#define GPIO140_ETM_D7 PIN_CFG(140, ALT_B)
+#define GPIO140_STMAPE_CLK PIN_CFG(140, ALT_C)
+
+#define GPIO141_GPIO PIN_CFG(141, GPIO)
+#define GPIO141_KP_O6 PIN_CFG(141, ALT_A)
+#define GPIO141_ETM_D6 PIN_CFG(141, ALT_B)
+#define GPIO141_U0_RXD PIN_CFG(141, ALT_C)
+
+#define GPIO142_GPIO PIN_CFG(142, GPIO)
+#define GPIO142_KP_I7 PIN_CFG(142, ALT_A)
+#define GPIO142_ETM_D5 PIN_CFG(142, ALT_B)
+#define GPIO142_STMAPE_DAT0 PIN_CFG(142, ALT_C)
+
+#define GPIO143_GPIO PIN_CFG(143, GPIO)
+#define GPIO143_KP_O7 PIN_CFG(143, ALT_A)
+#define GPIO143_ETM_D4 PIN_CFG(143, ALT_B)
+#define GPIO143_STMAPE_DAT1 PIN_CFG(143, ALT_C)
+
+#define GPIO144_GPIO PIN_CFG(144, GPIO)
+#define GPIO144_I2C3_SCL PIN_CFG(144, ALT_A)
+#define GPIO144_ETM_D3 PIN_CFG(144, ALT_B)
+#define GPIO144_STMAPE_DAT2 PIN_CFG(144, ALT_C)
+
+#define GPIO145_GPIO PIN_CFG(145, GPIO)
+#define GPIO145_I2C3_SDA PIN_CFG(145, ALT_A)
+#define GPIO145_ETM_D2 PIN_CFG(145, ALT_B)
+#define GPIO145_STMAPE_DAT3 PIN_CFG(145, ALT_C)
+
+#define GPIO146_GPIO PIN_CFG(146, GPIO)
+#define GPIO146_PWM_0 PIN_CFG(146, ALT_A)
+#define GPIO146_ETM_D1 PIN_CFG(146, ALT_B)
+
+#define GPIO147_GPIO PIN_CFG(147, GPIO)
+#define GPIO147_PWM_1 PIN_CFG(147, ALT_A)
+#define GPIO147_ETM_D0 PIN_CFG(147, ALT_B)
+
+#define GPIO148_GPIO PIN_CFG(148, GPIO)
+#define GPIO148_PWM_2 PIN_CFG(148, ALT_A)
+#define GPIO148_ETM_CLK PIN_CFG(148, ALT_B)
+
+#define GPIO160_GPIO PIN_CFG(160, GPIO)
+#define GPIO160_CLKOUT_REQn PIN_CFG(160, ALT_A)
+
+#define GPIO161_GPIO PIN_CFG(161, GPIO)
+#define GPIO161_CLKOUT_0 PIN_CFG(161, ALT_A)
+
+#define GPIO162_GPIO PIN_CFG(162, GPIO)
+#define GPIO162_CLKOUT_1 PIN_CFG(162, ALT_A)
+
+#define GPIO163_GPIO PIN_CFG(163, GPIO)
+
+#define GPIO164_GPIO PIN_CFG(164, GPIO)
+#define GPIO164_GPS_START PIN_CFG(164, ALT_A)
+
+#define GPIO165_GPIO PIN_CFG(165, GPIO)
+#define GPIO165_SPI1_CS2n PIN_CFG(165, ALT_A)
+#define GPIO165_U3_RXD PIN_CFG(165, ALT_B)
+#define GPIO165_BUSMON_D20 PIN_CFG(165, ALT_C)
+
+#define GPIO166_GPIO PIN_CFG(166, GPIO)
+#define GPIO166_SPI1_CS1n PIN_CFG(166, ALT_A)
+#define GPIO166_U3_TXD PIN_CFG(166, ALT_B)
+#define GPIO166_BUSMON_D21 PIN_CFG(166, ALT_C)
+
+#define GPIO167_GPIO PIN_CFG(167, GPIO)
+#define GPIO167_SPI1_CS0n PIN_CFG(167, ALT_A)
+#define GPIO167_U3_RTSn PIN_CFG(167, ALT_B)
+#define GPIO167_BUSMON_D22 PIN_CFG(167, ALT_C)
+
+#define GPIO168_GPIO PIN_CFG(168, GPIO)
+#define GPIO168_SPI1_RXD PIN_CFG(168, ALT_A)
+#define GPIO168_U3_CTSn PIN_CFG(168, ALT_B)
+#define GPIO168_BUSMON_D23 PIN_CFG(168, ALT_C)
+
+#define GPIO169_GPIO PIN_CFG(169, GPIO)
+#define GPIO169_SPI1_TXD PIN_CFG(169, ALT_A)
+#define GPIO169_DDR_RC PIN_CFG(169, ALT_B)
+#define GPIO169_BUSMON_D24 PIN_CFG(169, ALT_C)
+
+#define GPIO170_GPIO PIN_CFG(170, GPIO)
+#define GPIO170_SPI1_CLK PIN_CFG(170, ALT_A)
+
+#define GPIO171_GPIO PIN_CFG(171, GPIO)
+#define GPIO171_MC3_DAT0 PIN_CFG(171, ALT_A)
+#define GPIO171_SPI3_RXD PIN_CFG(171, ALT_B)
+#define GPIO171_BUSMON_D25 PIN_CFG(171, ALT_C)
+
+#define GPIO172_GPIO PIN_CFG(172, GPIO)
+#define GPIO172_MC3_DAT1 PIN_CFG(172, ALT_A)
+#define GPIO172_SPI3_CS1n PIN_CFG(172, ALT_B)
+#define GPIO172_BUSMON_D26 PIN_CFG(172, ALT_C)
+
+#define GPIO173_GPIO PIN_CFG(173, GPIO)
+#define GPIO173_MC3_DAT2 PIN_CFG(173, ALT_A)
+#define GPIO173_SPI3_CS2n PIN_CFG(173, ALT_B)
+#define GPIO173_BUSMON_D27 PIN_CFG(173, ALT_C)
+
+#define GPIO174_GPIO PIN_CFG(174, GPIO)
+#define GPIO174_MC3_DAT3 PIN_CFG(174, ALT_A)
+#define GPIO174_SPI3_CS0n PIN_CFG(174, ALT_B)
+#define GPIO174_BUSMON_D28 PIN_CFG(174, ALT_C)
+
+#define GPIO175_GPIO PIN_CFG(175, GPIO)
+#define GPIO175_MC3_CMD PIN_CFG(175, ALT_A)
+#define GPIO175_SPI3_TXD PIN_CFG(175, ALT_B)
+#define GPIO175_BUSMON_D29 PIN_CFG(175, ALT_C)
+
+#define GPIO176_GPIO PIN_CFG(176, GPIO)
+#define GPIO176_MC3_CLK PIN_CFG(176, ALT_A)
+#define GPIO176_SPI3_CLK PIN_CFG(176, ALT_B)
+
+#define GPIO177_GPIO PIN_CFG(177, GPIO)
+#define GPIO177_U2_RXD PIN_CFG(177, ALT_A)
+#define GPIO177_I2C3_SCL PIN_CFG(177, ALT_B)
+#define GPIO177_BUSMON_D30 PIN_CFG(177, ALT_C)
+
+#define GPIO178_GPIO PIN_CFG(178, GPIO)
+#define GPIO178_U2_TXD PIN_CFG(178, ALT_A)
+#define GPIO178_I2C3_SDA PIN_CFG(178, ALT_B)
+#define GPIO178_BUSMON_D31 PIN_CFG(178, ALT_C)
+
+#define GPIO179_GPIO PIN_CFG(179, GPIO)
+#define GPIO179_U2_CTSn PIN_CFG(179, ALT_A)
+#define GPIO179_U3_RXD PIN_CFG(179, ALT_B)
+#define GPIO179_BUSMON_D32 PIN_CFG(179, ALT_C)
+
+#define GPIO180_GPIO PIN_CFG(180, GPIO)
+#define GPIO180_U2_RTSn PIN_CFG(180, ALT_A)
+#define GPIO180_U3_TXD PIN_CFG(180, ALT_B)
+#define GPIO180_BUSMON_D33 PIN_CFG(180, ALT_C)
+
+#define GPIO185_GPIO PIN_CFG(185, GPIO)
+#define GPIO185_SPI3_CS2n PIN_CFG(185, ALT_A)
+#define GPIO185_MC4_DAT0 PIN_CFG(185, ALT_B)
+
+#define GPIO186_GPIO PIN_CFG(186, GPIO)
+#define GPIO186_SPI3_CS1n PIN_CFG(186, ALT_A)
+#define GPIO186_MC4_DAT1 PIN_CFG(186, ALT_B)
+
+#define GPIO187_GPIO PIN_CFG(187, GPIO)
+#define GPIO187_SPI3_CS0n PIN_CFG(187, ALT_A)
+#define GPIO187_MC4_DAT2 PIN_CFG(187, ALT_B)
+
+#define GPIO188_GPIO PIN_CFG(188, GPIO)
+#define GPIO188_SPI3_RXD PIN_CFG(188, ALT_A)
+#define GPIO188_MC4_DAT3 PIN_CFG(188, ALT_B)
+
+#define GPIO189_GPIO PIN_CFG(189, GPIO)
+#define GPIO189_SPI3_TXD PIN_CFG(189, ALT_A)
+#define GPIO189_MC4_CMD PIN_CFG(189, ALT_B)
+
+#define GPIO190_GPIO PIN_CFG(190, GPIO)
+#define GPIO190_SPI3_CLK PIN_CFG(190, ALT_A)
+#define GPIO190_MC4_CLK PIN_CFG(190, ALT_B)
+
+#define GPIO191_GPIO PIN_CFG(191, GPIO)
+#define GPIO191_MC1_DAT0 PIN_CFG(191, ALT_A)
+#define GPIO191_MC4_DAT4 PIN_CFG(191, ALT_B)
+#define GPIO191_STMAPE_DAT0 PIN_CFG(191, ALT_C)
+
+#define GPIO192_GPIO PIN_CFG(192, GPIO)
+#define GPIO192_MC1_DAT1 PIN_CFG(192, ALT_A)
+#define GPIO192_MC4_DAT5 PIN_CFG(192, ALT_B)
+#define GPIO192_STMAPE_DAT1 PIN_CFG(192, ALT_C)
+
+#define GPIO193_GPIO PIN_CFG(193, GPIO)
+#define GPIO193_MC1_DAT2 PIN_CFG(193, ALT_A)
+#define GPIO193_MC4_DAT6 PIN_CFG(193, ALT_B)
+#define GPIO193_STMAPE_DAT2 PIN_CFG(193, ALT_C)
+
+#define GPIO194_GPIO PIN_CFG(194, GPIO)
+#define GPIO194_MC1_DAT3 PIN_CFG(194, ALT_A)
+#define GPIO194_MC4_DAT7 PIN_CFG(194, ALT_B)
+#define GPIO194_STMAPE_DAT3 PIN_CFG(194, ALT_C)
+
+#define GPIO195_GPIO PIN_CFG(195, GPIO)
+#define GPIO195_MC1_CLK PIN_CFG(195, ALT_A)
+#define GPIO195_STMAPE_CLK PIN_CFG(195, ALT_B)
+#define GPIO195_BUSMON_CLK PIN_CFG(195, ALT_C)
+
+#define GPIO196_GPIO PIN_CFG(196, GPIO)
+#define GPIO196_MC1_CMD PIN_CFG(196, ALT_A)
+#define GPIO196_U0_RXD PIN_CFG(196, ALT_B)
+#define GPIO196_BUSMON_D38 PIN_CFG(196, ALT_C)
+
+#define GPIO197_GPIO PIN_CFG(197, GPIO)
+#define GPIO197_MC1_CMDDIR PIN_CFG(197, ALT_A)
+#define GPIO197_BUSMON_D39 PIN_CFG(197, ALT_B)
+
+#define GPIO198_GPIO PIN_CFG(198, GPIO)
+#define GPIO198_MC1_FBCLK PIN_CFG(198, ALT_A)
+
+#define GPIO199_GPIO PIN_CFG(199, GPIO)
+#define GPIO199_MC1_DAT0DIR PIN_CFG(199, ALT_A)
+#define GPIO199_BUSMON_D40 PIN_CFG(199, ALT_B)
+
+#define GPIO200_GPIO PIN_CFG(200, GPIO)
+#define GPIO200_U1_TXD PIN_CFG(200, ALT_A)
+#define GPIO200_ACCU0_RTSn PIN_CFG(200, ALT_B)
+
+#define GPIO201_GPIO PIN_CFG(201, GPIO)
+#define GPIO201_U1_RXD PIN_CFG(201, ALT_A)
+#define GPIO201_ACCU0_CTSn PIN_CFG(201, ALT_B)
+
+#define GPIO202_GPIO PIN_CFG(202, GPIO)
+#define GPIO202_U1_CTSn PIN_CFG(202, ALT_A)
+#define GPIO202_ACCU0_RXD PIN_CFG(202, ALT_B)
+
+#define GPIO203_GPIO PIN_CFG(203, GPIO)
+#define GPIO203_U1_RTSn PIN_CFG(203, ALT_A)
+#define GPIO203_ACCU0_TXD PIN_CFG(203, ALT_B)
+
+#define GPIO204_GPIO PIN_CFG(204, GPIO)
+#define GPIO204_SPI0_CS2n PIN_CFG(204, ALT_A)
+#define GPIO204_ACCGPIO_000 PIN_CFG(204, ALT_B)
+#define GPIO204_LCD_VSI1 PIN_CFG(204, ALT_C)
+
+#define GPIO205_GPIO PIN_CFG(205, GPIO)
+#define GPIO205_SPI0_CS1n PIN_CFG(205, ALT_A)
+#define GPIO205_ACCGPIO_001 PIN_CFG(205, ALT_B)
+#define GPIO205_LCD_D3 PIN_CFG(205, ALT_C)
+
+#define GPIO206_GPIO PIN_CFG(206, GPIO)
+#define GPIO206_SPI0_CS0n PIN_CFG(206, ALT_A)
+#define GPIO206_ACCGPIO_002 PIN_CFG(206, ALT_B)
+#define GPIO206_LCD_D2 PIN_CFG(206, ALT_C)
+
+#define GPIO207_GPIO PIN_CFG(207, GPIO)
+#define GPIO207_SPI0_RXD PIN_CFG(207, ALT_A)
+#define GPIO207_ACCGPIO_003 PIN_CFG(207, ALT_B)
+#define GPIO207_LCD_D1 PIN_CFG(207, ALT_C)
+
+#define GPIO208_GPIO PIN_CFG(208, GPIO)
+#define GPIO208_SPI0_TXD PIN_CFG(208, ALT_A)
+#define GPIO208_ACCGPIO_004 PIN_CFG(208, ALT_B)
+#define GPIO208_LCD_D0 PIN_CFG(208, ALT_C)
+
+#define GPIO209_GPIO PIN_CFG(209, GPIO)
+#define GPIO209_SPI0_CLK PIN_CFG(209, ALT_A)
+#define GPIO209_ACCGPIO_005 PIN_CFG(209, ALT_B)
+#define GPIO209_LCD_CLK PIN_CFG(209, ALT_C)
+
+#define GPIO210_GPIO PIN_CFG(210, GPIO)
+#define GPIO210_LCD_VSO PIN_CFG(210, ALT_A)
+#define GPIO210_PRCMU_PWRCTRL1 PIN_CFG(210, ALT_B)
+
+#define GPIO211_GPIO PIN_CFG(211, GPIO)
+#define GPIO211_LCD_VSI0 PIN_CFG(211, ALT_A)
+#define GPIO211_PRCMU_PWRCTRL2 PIN_CFG(211, ALT_B)
+
+#define GPIO212_GPIO PIN_CFG(212, GPIO)
+#define GPIO212_SPI2_CS2n PIN_CFG(212, ALT_A)
+#define GPIO212_LCD_HSO PIN_CFG(212, ALT_B)
+
+#define GPIO213_GPIO PIN_CFG(213, GPIO)
+#define GPIO213_SPI2_CS1n PIN_CFG(213, ALT_A)
+#define GPIO213_LCD_DE PIN_CFG(213, ALT_B)
+#define GPIO213_BUSMON_D16 PIN_CFG(213, ALT_C)
+
+#define GPIO214_GPIO PIN_CFG(214, GPIO)
+#define GPIO214_SPI2_CS0n PIN_CFG(214, ALT_A)
+#define GPIO214_LCD_D7 PIN_CFG(214, ALT_B)
+#define GPIO214_BUSMON_D17 PIN_CFG(214, ALT_C)
+
+#define GPIO215_GPIO PIN_CFG(215, GPIO)
+#define GPIO215_SPI2_RXD PIN_CFG(215, ALT_A)
+#define GPIO215_LCD_D6 PIN_CFG(215, ALT_B)
+#define GPIO215_BUSMON_D18 PIN_CFG(215, ALT_C)
+
+#define GPIO216_GPIO PIN_CFG(216, GPIO)
+#define GPIO216_SPI2_CLK PIN_CFG(216, ALT_A)
+#define GPIO216_LCD_D5 PIN_CFG(216, ALT_B)
+
+#define GPIO217_GPIO PIN_CFG(217, GPIO)
+#define GPIO217_SPI2_TXD PIN_CFG(217, ALT_A)
+#define GPIO217_LCD_D4 PIN_CFG(217, ALT_B)
+#define GPIO217_BUSMON_D19 PIN_CFG(217, ALT_C)
+
+#define GPIO218_GPIO PIN_CFG(218, GPIO)
+#define GPIO218_I2C2_SCL PIN_CFG(218, ALT_A)
+#define GPIO218_LCD_VSO PIN_CFG(218, ALT_B)
+
+#define GPIO219_GPIO PIN_CFG(219, GPIO)
+#define GPIO219_I2C2_SDA PIN_CFG(219, ALT_A)
+#define GPIO219_LCD_D3 PIN_CFG(219, ALT_B)
+
+#define GPIO220_GPIO PIN_CFG(220, GPIO)
+#define GPIO220_MSP2_TCK PIN_CFG(220, ALT_A)
+#define GPIO220_LCD_D2 PIN_CFG(220, ALT_B)
+
+#define GPIO221_GPIO PIN_CFG(221, GPIO)
+#define GPIO221_MSP2_TFS PIN_CFG(221, ALT_A)
+#define GPIO221_LCD_D1 PIN_CFG(221, ALT_B)
+
+#define GPIO222_GPIO PIN_CFG(222, GPIO)
+#define GPIO222_MSP2_TXD PIN_CFG(222, ALT_A)
+#define GPIO222_LCD_D0 PIN_CFG(222, ALT_B)
+
+#define GPIO223_GPIO PIN_CFG(223, GPIO)
+#define GPIO223_MSP2_RXD PIN_CFG(223, ALT_A)
+#define GPIO223_LCD_CLK PIN_CFG(223, ALT_B)
+
+#define GPIO224_GPIO PIN_CFG(224, GPIO)
+#define GPIO224_PRCMU_PWRCTRL0 PIN_CFG(224, ALT_A)
+#define GPIO224_LCD_VSI1 PIN_CFG(224, ALT_B)
+
+#define GPIO225_GPIO PIN_CFG(225, GPIO)
+#define GPIO225_PRCMU_PWRCTRL1 PIN_CFG(225, ALT_A)
+#define GPIO225_IRDA_RXD PIN_CFG(225, ALT_B)
+
+#define GPIO226_GPIO PIN_CFG(226, GPIO)
+#define GPIO226_PRCMU_PWRCTRL2 PIN_CFG(226, ALT_A)
+#define GPIO226_IRRC_DAT PIN_CFG(226, ALT_B)
+
+#define GPIO227_GPIO PIN_CFG(227, GPIO)
+#define GPIO227_IRRC_DAT PIN_CFG(227, ALT_A)
+#define GPIO227_IRDA_TXD PIN_CFG(227, ALT_B)
+
+#endif
diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h
new file mode 100644
index 00000000000..062c7acf457
--- /dev/null
+++ b/arch/arm/mach-ux500/pins-db8500.h
@@ -0,0 +1,746 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License, version 2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ */
+
+#ifndef __MACH_PINS_DB8500_H
+#define __MACH_PINS_DB8500_H
+
+/*
+ * TODO: Eventually encode all non-board specific pull up/down configuration
+ * here.
+ */
+
+#define GPIO0_GPIO PIN_CFG(0, GPIO)
+#define GPIO0_U0_CTSn PIN_CFG(0, ALT_A)
+#define GPIO0_TRIG_OUT PIN_CFG(0, ALT_B)
+#define GPIO0_IP_TDO PIN_CFG(0, ALT_C)
+
+#define GPIO1_GPIO PIN_CFG(1, GPIO)
+#define GPIO1_U0_RTSn PIN_CFG(1, ALT_A)
+#define GPIO1_TRIG_IN PIN_CFG(1, ALT_B)
+#define GPIO1_IP_TDI PIN_CFG(1, ALT_C)
+
+#define GPIO2_GPIO PIN_CFG(2, GPIO)
+#define GPIO2_U0_RXD PIN_CFG(2, ALT_A)
+#define GPIO2_NONE PIN_CFG(2, ALT_B)
+#define GPIO2_IP_TMS PIN_CFG(2, ALT_C)
+
+#define GPIO3_GPIO PIN_CFG(3, GPIO)
+#define GPIO3_U0_TXD PIN_CFG(3, ALT_A)
+#define GPIO3_NONE PIN_CFG(3, ALT_B)
+#define GPIO3_IP_TCK PIN_CFG(3, ALT_C)
+
+#define GPIO4_GPIO PIN_CFG(4, GPIO)
+#define GPIO4_U1_RXD PIN_CFG(4, ALT_A)
+#define GPIO4_I2C4_SCL PIN_CFG(4, ALT_B)
+#define GPIO4_IP_TRSTn PIN_CFG(4, ALT_C)
+
+#define GPIO5_GPIO PIN_CFG(5, GPIO)
+#define GPIO5_U1_TXD PIN_CFG(5, ALT_A)
+#define GPIO5_I2C4_SDA PIN_CFG(5, ALT_B)
+#define GPIO5_IP_GPIO6 PIN_CFG(5, ALT_C)
+
+#define GPIO6_GPIO PIN_CFG(6, GPIO)
+#define GPIO6_U1_CTSn PIN_CFG(6, ALT_A)
+#define GPIO6_I2C1_SCL PIN_CFG(6, ALT_B)
+#define GPIO6_IP_GPIO0 PIN_CFG(6, ALT_C)
+
+#define GPIO7_GPIO PIN_CFG(7, GPIO)
+#define GPIO7_U1_RTSn PIN_CFG(7, ALT_A)
+#define GPIO7_I2C1_SDA PIN_CFG(7, ALT_B)
+#define GPIO7_IP_GPIO1 PIN_CFG(7, ALT_C)
+
+#define GPIO8_GPIO PIN_CFG(8, GPIO)
+#define GPIO8_IPI2C_SDA PIN_CFG(8, ALT_A)
+#define GPIO8_I2C2_SDA PIN_CFG(8, ALT_B)
+
+#define GPIO9_GPIO PIN_CFG(9, GPIO)
+#define GPIO9_IPI2C_SCL PIN_CFG(9, ALT_A)
+#define GPIO9_I2C2_SCL PIN_CFG(9, ALT_B)
+
+#define GPIO10_GPIO PIN_CFG(10, GPIO)
+#define GPIO10_IPI2C_SDA PIN_CFG(10, ALT_A)
+#define GPIO10_I2C2_SDA PIN_CFG(10, ALT_B)
+#define GPIO10_IP_GPIO3 PIN_CFG(10, ALT_C)
+
+#define GPIO11_GPIO PIN_CFG(11, GPIO)
+#define GPIO11_IPI2C_SCL PIN_CFG(11, ALT_A)
+#define GPIO11_I2C2_SCL PIN_CFG(11, ALT_B)
+#define GPIO11_IP_GPIO2 PIN_CFG(11, ALT_C)
+
+#define GPIO12_GPIO PIN_CFG(12, GPIO)
+#define GPIO12_MSP0_TXD PIN_CFG(12, ALT_A)
+#define GPIO12_MSP0_RXD PIN_CFG(12, ALT_B)
+
+#define GPIO13_GPIO PIN_CFG(13, GPIO)
+#define GPIO13_MSP0_TFS PIN_CFG(13, ALT_A)
+
+#define GPIO14_GPIO PIN_CFG(14, GPIO)
+#define GPIO14_MSP0_TCK PIN_CFG(14, ALT_A)
+
+#define GPIO15_GPIO PIN_CFG(15, GPIO)
+#define GPIO15_MSP0_RXD PIN_CFG(15, ALT_A)
+#define GPIO15_MSP0_TXD PIN_CFG(15, ALT_B)
+
+#define GPIO16_GPIO PIN_CFG(16, GPIO)
+#define GPIO16_MSP0_RFS PIN_CFG(16, ALT_A)
+#define GPIO16_I2C1_SCL PIN_CFG(16, ALT_B)
+#define GPIO16_SLIM0_DAT PIN_CFG(16, ALT_C)
+
+#define GPIO17_GPIO PIN_CFG(17, GPIO)
+#define GPIO17_MSP0_RCK PIN_CFG(17, ALT_A)
+#define GPIO17_I2C1_SDA PIN_CFG(17, ALT_B)
+#define GPIO17_SLIM0_CLK PIN_CFG(17, ALT_C)
+
+#define GPIO18_GPIO PIN_CFG(18, GPIO)
+#define GPIO18_MC0_CMDDIR PIN_CFG_INPUT(18, ALT_A, PULLUP)
+#define GPIO18_U2_RXD PIN_CFG(18, ALT_B)
+#define GPIO18_MS_IEP PIN_CFG(18, ALT_C)
+
+#define GPIO19_GPIO PIN_CFG(19, GPIO)
+#define GPIO19_MC0_DAT0DIR PIN_CFG_INPUT(19, ALT_A, PULLUP)
+#define GPIO19_U2_TXD PIN_CFG(19, ALT_B)
+#define GPIO19_MS_DAT0DIR PIN_CFG(19, ALT_C)
+
+#define GPIO20_GPIO PIN_CFG(20, GPIO)
+#define GPIO20_MC0_DAT2DIR PIN_CFG_INPUT(20, ALT_A, PULLUP)
+#define GPIO20_UARTMOD_TXD PIN_CFG(20, ALT_B)
+#define GPIO20_IP_TRIGOUT PIN_CFG(20, ALT_C)
+
+#define GPIO21_GPIO PIN_CFG(21, GPIO)
+#define GPIO21_MC0_DAT31DIR PIN_CFG_INPUT(21, ALT_A, PULLUP)
+#define GPIO21_MSP0_SCK PIN_CFG(21, ALT_B)
+#define GPIO21_MS_DAT31DIR PIN_CFG(21, ALT_C)
+
+#define GPIO22_GPIO PIN_CFG(22, GPIO)
+#define GPIO22_MC0_FBCLK PIN_CFG_INPUT(22, ALT_A, PULLUP)
+#define GPIO22_UARTMOD_RXD PIN_CFG(22, ALT_B)
+#define GPIO22_MS_FBCLK PIN_CFG(22, ALT_C)
+
+#define GPIO23_GPIO PIN_CFG(23, GPIO)
+#define GPIO23_MC0_CLK PIN_CFG_INPUT(23, ALT_A, PULLUP)
+#define GPIO23_STMMOD_CLK PIN_CFG(23, ALT_B)
+#define GPIO23_MS_CLK PIN_CFG(23, ALT_C)
+
+#define GPIO24_GPIO PIN_CFG(24, GPIO)
+#define GPIO24_MC0_CMD PIN_CFG_INPUT(24, ALT_A, PULLUP)
+#define GPIO24_UARTMOD_RXD PIN_CFG(24, ALT_B)
+#define GPIO24_MS_BS PIN_CFG(24, ALT_C)
+
+#define GPIO25_GPIO PIN_CFG(25, GPIO)
+#define GPIO25_MC0_DAT0 PIN_CFG_INPUT(25, ALT_A, PULLUP)
+#define GPIO25_STMMOD_DAT0 PIN_CFG(25, ALT_B)
+#define GPIO25_MS_DAT0 PIN_CFG(25, ALT_C)
+
+#define GPIO26_GPIO PIN_CFG(26, GPIO)
+#define GPIO26_MC0_DAT1 PIN_CFG_INPUT(26, ALT_A, PULLUP)
+#define GPIO26_STMMOD_DAT1 PIN_CFG(26, ALT_B)
+#define GPIO26_MS_DAT1 PIN_CFG(26, ALT_C)
+
+#define GPIO27_GPIO PIN_CFG(27, GPIO)
+#define GPIO27_MC0_DAT2 PIN_CFG_INPUT(27, ALT_A, PULLUP)
+#define GPIO27_STMMOD_DAT2 PIN_CFG(27, ALT_B)
+#define GPIO27_MS_DAT2 PIN_CFG(27, ALT_C)
+
+#define GPIO28_GPIO PIN_CFG(28, GPIO)
+#define GPIO28_MC0_DAT3 PIN_CFG_INPUT(28, ALT_A, PULLUP)
+#define GPIO28_STMMOD_DAT3 PIN_CFG(28, ALT_B)
+#define GPIO28_MS_DAT3 PIN_CFG(28, ALT_C)
+
+#define GPIO29_GPIO PIN_CFG(29, GPIO)
+#define GPIO29_MC0_DAT4 PIN_CFG(29, ALT_A)
+#define GPIO29_SPI3_CLK PIN_CFG(29, ALT_B)
+#define GPIO29_U2_RXD PIN_CFG(29, ALT_C)
+
+#define GPIO30_GPIO PIN_CFG(30, GPIO)
+#define GPIO30_MC0_DAT5 PIN_CFG(30, ALT_A)
+#define GPIO30_SPI3_RXD PIN_CFG(30, ALT_B)
+#define GPIO30_U2_TXD PIN_CFG(30, ALT_C)
+
+#define GPIO31_GPIO PIN_CFG(31, GPIO)
+#define GPIO31_MC0_DAT6 PIN_CFG(31, ALT_A)
+#define GPIO31_SPI3_FRM PIN_CFG(31, ALT_B)
+#define GPIO31_U2_CTSn PIN_CFG(31, ALT_C)
+
+#define GPIO32_GPIO PIN_CFG(32, GPIO)
+#define GPIO32_MC0_DAT7 PIN_CFG(32, ALT_A)
+#define GPIO32_SPI3_TXD PIN_CFG(32, ALT_B)
+#define GPIO32_U2_RTSn PIN_CFG(32, ALT_C)
+
+#define GPIO33_GPIO PIN_CFG(33, GPIO)
+#define GPIO33_MSP1_TXD PIN_CFG(33, ALT_A)
+#define GPIO33_MSP1_RXD PIN_CFG(33, ALT_B)
+#define GPIO33_U0_DTRn PIN_CFG(33, ALT_C)
+
+#define GPIO34_GPIO PIN_CFG(34, GPIO)
+#define GPIO34_MSP1_TFS PIN_CFG(34, ALT_A)
+#define GPIO34_NONE PIN_CFG(34, ALT_B)
+#define GPIO34_U0_DCDn PIN_CFG(34, ALT_C)
+
+#define GPIO35_GPIO PIN_CFG(35, GPIO)
+#define GPIO35_MSP1_TCK PIN_CFG(35, ALT_A)
+#define GPIO35_NONE PIN_CFG(35, ALT_B)
+#define GPIO35_U0_DSRn PIN_CFG(35, ALT_C)
+
+#define GPIO36_GPIO PIN_CFG(36, GPIO)
+#define GPIO36_MSP1_RXD PIN_CFG(36, ALT_A)
+#define GPIO36_MSP1_TXD PIN_CFG(36, ALT_B)
+#define GPIO36_U0_RIn PIN_CFG(36, ALT_C)
+
+#define GPIO64_GPIO PIN_CFG(64, GPIO)
+#define GPIO64_LCDB_DE PIN_CFG(64, ALT_A)
+#define GPIO64_KP_O1 PIN_CFG(64, ALT_B)
+#define GPIO64_IP_GPIO4 PIN_CFG(64, ALT_C)
+
+#define GPIO65_GPIO PIN_CFG(65, GPIO)
+#define GPIO65_LCDB_HSO PIN_CFG(65, ALT_A)
+#define GPIO65_KP_O0 PIN_CFG(65, ALT_B)
+#define GPIO65_IP_GPIO5 PIN_CFG(65, ALT_C)
+
+#define GPIO66_GPIO PIN_CFG(66, GPIO)
+#define GPIO66_LCDB_VSO PIN_CFG(66, ALT_A)
+#define GPIO66_KP_I1 PIN_CFG(66, ALT_B)
+#define GPIO66_IP_GPIO6 PIN_CFG(66, ALT_C)
+
+#define GPIO67_GPIO PIN_CFG(67, GPIO)
+#define GPIO67_LCDB_CLK PIN_CFG(67, ALT_A)
+#define GPIO67_KP_I0 PIN_CFG(67, ALT_B)
+#define GPIO67_IP_GPIO7 PIN_CFG(67, ALT_C)
+
+#define GPIO68_GPIO PIN_CFG(68, GPIO)
+#define GPIO68_LCD_VSI0 PIN_CFG(68, ALT_A)
+#define GPIO68_KP_O7 PIN_CFG(68, ALT_B)
+#define GPIO68_SM_CLE PIN_CFG(68, ALT_C)
+
+#define GPIO69_GPIO PIN_CFG(69, GPIO)
+#define GPIO69_LCD_VSI1 PIN_CFG(69, ALT_A)
+#define GPIO69_KP_I7 PIN_CFG(69, ALT_B)
+#define GPIO69_SM_ALE PIN_CFG(69, ALT_C)
+
+#define GPIO70_GPIO PIN_CFG(70, GPIO)
+#define GPIO70_LCD_D0 PIN_CFG(70, ALT_A)
+#define GPIO70_KP_O5 PIN_CFG(70, ALT_B)
+#define GPIO70_STMAPE_CLK PIN_CFG(70, ALT_C)
+
+#define GPIO71_GPIO PIN_CFG(71, GPIO)
+#define GPIO71_LCD_D1 PIN_CFG(71, ALT_A)
+#define GPIO71_KP_O4 PIN_CFG(71, ALT_B)
+#define GPIO71_STMAPE_DAT3 PIN_CFG(71, ALT_C)
+
+#define GPIO72_GPIO PIN_CFG(72, GPIO)
+#define GPIO72_LCD_D2 PIN_CFG(72, ALT_A)
+#define GPIO72_KP_O3 PIN_CFG(72, ALT_B)
+#define GPIO72_STMAPE_DAT2 PIN_CFG(72, ALT_C)
+
+#define GPIO73_GPIO PIN_CFG(73, GPIO)
+#define GPIO73_LCD_D3 PIN_CFG(73, ALT_A)
+#define GPIO73_KP_O2 PIN_CFG(73, ALT_B)
+#define GPIO73_STMAPE_DAT1 PIN_CFG(73, ALT_C)
+
+#define GPIO74_GPIO PIN_CFG(74, GPIO)
+#define GPIO74_LCD_D4 PIN_CFG(74, ALT_A)
+#define GPIO74_KP_I5 PIN_CFG(74, ALT_B)
+#define GPIO74_STMAPE_DAT0 PIN_CFG(74, ALT_C)
+
+#define GPIO75_GPIO PIN_CFG(75, GPIO)
+#define GPIO75_LCD_D5 PIN_CFG(75, ALT_A)
+#define GPIO75_KP_I4 PIN_CFG(75, ALT_B)
+#define GPIO75_U2_RXD PIN_CFG(75, ALT_C)
+
+#define GPIO76_GPIO PIN_CFG(76, GPIO)
+#define GPIO76_LCD_D6 PIN_CFG(76, ALT_A)
+#define GPIO76_KP_I3 PIN_CFG(76, ALT_B)
+#define GPIO76_U2_TXD PIN_CFG(76, ALT_C)
+
+#define GPIO77_GPIO PIN_CFG(77, GPIO)
+#define GPIO77_LCD_D7 PIN_CFG(77, ALT_A)
+#define GPIO77_KP_I2 PIN_CFG(77, ALT_B)
+#define GPIO77_NONE PIN_CFG(77, ALT_C)
+
+#define GPIO78_GPIO PIN_CFG(78, GPIO)
+#define GPIO78_LCD_D8 PIN_CFG(78, ALT_A)
+#define GPIO78_KP_O6 PIN_CFG(78, ALT_B)
+#define GPIO78_IP_GPIO2 PIN_CFG(78, ALT_C)
+
+#define GPIO79_GPIO PIN_CFG(79, GPIO)
+#define GPIO79_LCD_D9 PIN_CFG(79, ALT_A)
+#define GPIO79_KP_I6 PIN_CFG(79, ALT_B)
+#define GPIO79_IP_GPIO3 PIN_CFG(79, ALT_C)
+
+#define GPIO80_GPIO PIN_CFG(80, GPIO)
+#define GPIO80_LCD_D10 PIN_CFG(80, ALT_A)
+#define GPIO80_KP_SKA0 PIN_CFG(80, ALT_B)
+#define GPIO80_IP_GPIO4 PIN_CFG(80, ALT_C)
+
+#define GPIO81_GPIO PIN_CFG(81, GPIO)
+#define GPIO81_LCD_D11 PIN_CFG(81, ALT_A)
+#define GPIO81_KP_SKB0 PIN_CFG(81, ALT_B)
+#define GPIO81_IP_GPIO5 PIN_CFG(81, ALT_C)
+
+#define GPIO82_GPIO PIN_CFG(82, GPIO)
+#define GPIO82_LCD_D12 PIN_CFG(82, ALT_A)
+#define GPIO82_KP_O5 PIN_CFG(82, ALT_B)
+
+#define GPIO83_GPIO PIN_CFG(83, GPIO)
+#define GPIO83_LCD_D13 PIN_CFG(83, ALT_A)
+#define GPIO83_KP_O4 PIN_CFG(83, ALT_B)
+
+#define GPIO84_GPIO PIN_CFG(84, GPIO)
+#define GPIO84_LCD_D14 PIN_CFG(84, ALT_A)
+#define GPIO84_KP_I5 PIN_CFG(84, ALT_B)
+
+#define GPIO85_GPIO PIN_CFG(85, GPIO)
+#define GPIO85_LCD_D15 PIN_CFG(85, ALT_A)
+#define GPIO85_KP_I4 PIN_CFG(85, ALT_B)
+
+#define GPIO86_GPIO PIN_CFG(86, GPIO)
+#define GPIO86_LCD_D16 PIN_CFG(86, ALT_A)
+#define GPIO86_SM_ADQ0 PIN_CFG(86, ALT_B)
+#define GPIO86_MC5_DAT0 PIN_CFG(86, ALT_C)
+
+#define GPIO87_GPIO PIN_CFG(87, GPIO)
+#define GPIO87_LCD_D17 PIN_CFG(87, ALT_A)
+#define GPIO87_SM_ADQ1 PIN_CFG(87, ALT_B)
+#define GPIO87_MC5_DAT1 PIN_CFG(87, ALT_C)
+
+#define GPIO88_GPIO PIN_CFG(88, GPIO)
+#define GPIO88_LCD_D18 PIN_CFG(88, ALT_A)
+#define GPIO88_SM_ADQ2 PIN_CFG(88, ALT_B)
+#define GPIO88_MC5_DAT2 PIN_CFG(88, ALT_C)
+
+#define GPIO89_GPIO PIN_CFG(89, GPIO)
+#define GPIO89_LCD_D19 PIN_CFG(89, ALT_A)
+#define GPIO89_SM_ADQ3 PIN_CFG(89, ALT_B)
+#define GPIO89_MC5_DAT3 PIN_CFG(89, ALT_C)
+
+#define GPIO90_GPIO PIN_CFG(90, GPIO)
+#define GPIO90_LCD_D20 PIN_CFG(90, ALT_A)
+#define GPIO90_SM_ADQ4 PIN_CFG(90, ALT_B)
+#define GPIO90_MC5_CMD PIN_CFG(90, ALT_C)
+
+#define GPIO91_GPIO PIN_CFG(91, GPIO)
+#define GPIO91_LCD_D21 PIN_CFG(91, ALT_A)
+#define GPIO91_SM_ADQ5 PIN_CFG(91, ALT_B)
+#define GPIO91_MC5_FBCLK PIN_CFG(91, ALT_C)
+
+#define GPIO92_GPIO PIN_CFG(92, GPIO)
+#define GPIO92_LCD_D22 PIN_CFG(92, ALT_A)
+#define GPIO92_SM_ADQ6 PIN_CFG(92, ALT_B)
+#define GPIO92_MC5_CLK PIN_CFG(92, ALT_C)
+
+#define GPIO93_GPIO PIN_CFG(93, GPIO)
+#define GPIO93_LCD_D23 PIN_CFG(93, ALT_A)
+#define GPIO93_SM_ADQ7 PIN_CFG(93, ALT_B)
+#define GPIO93_MC5_DAT4 PIN_CFG(93, ALT_C)
+
+#define GPIO94_GPIO PIN_CFG(94, GPIO)
+#define GPIO94_KP_O7 PIN_CFG(94, ALT_A)
+#define GPIO94_SM_ADVn PIN_CFG(94, ALT_B)
+#define GPIO94_MC5_DAT5 PIN_CFG(94, ALT_C)
+
+#define GPIO95_GPIO PIN_CFG(95, GPIO)
+#define GPIO95_KP_I7 PIN_CFG(95, ALT_A)
+#define GPIO95_SM_CS0n PIN_CFG(95, ALT_B)
+#define GPIO95_SM_PS0n PIN_CFG(95, ALT_C)
+
+#define GPIO96_GPIO PIN_CFG(96, GPIO)
+#define GPIO96_KP_O6 PIN_CFG(96, ALT_A)
+#define GPIO96_SM_OEn PIN_CFG(96, ALT_B)
+#define GPIO96_MC5_DAT6 PIN_CFG(96, ALT_C)
+
+#define GPIO97_GPIO PIN_CFG(97, GPIO)
+#define GPIO97_KP_I6 PIN_CFG(97, ALT_A)
+#define GPIO97_SM_WEn PIN_CFG(97, ALT_B)
+#define GPIO97_MC5_DAT7 PIN_CFG(97, ALT_C)
+
+#define GPIO128_GPIO PIN_CFG(128, GPIO)
+#define GPIO128_MC2_CLK PIN_CFG_INPUT(128, ALT_A, PULLUP)
+#define GPIO128_SM_CKO PIN_CFG(128, ALT_B)
+
+#define GPIO129_GPIO PIN_CFG(129, GPIO)
+#define GPIO129_MC2_CMD PIN_CFG_INPUT(129, ALT_A, PULLUP)
+#define GPIO129_SM_WAIT0n PIN_CFG(129, ALT_B)
+
+#define GPIO130_GPIO PIN_CFG(130, GPIO)
+#define GPIO130_MC2_FBCLK PIN_CFG_INPUT(130, ALT_A, PULLUP)
+#define GPIO130_SM_FBCLK PIN_CFG(130, ALT_B)
+#define GPIO130_MC2_RSTN PIN_CFG(130, ALT_C)
+
+#define GPIO131_GPIO PIN_CFG(131, GPIO)
+#define GPIO131_MC2_DAT0 PIN_CFG_INPUT(131, ALT_A, PULLUP)
+#define GPIO131_SM_ADQ8 PIN_CFG(131, ALT_B)
+
+#define GPIO132_GPIO PIN_CFG(132, GPIO)
+#define GPIO132_MC2_DAT1 PIN_CFG_INPUT(132, ALT_A, PULLUP)
+#define GPIO132_SM_ADQ9 PIN_CFG(132, ALT_B)
+
+#define GPIO133_GPIO PIN_CFG(133, GPIO)
+#define GPIO133_MC2_DAT2 PIN_CFG_INPUT(133, ALT_A, PULLUP)
+#define GPIO133_SM_ADQ10 PIN_CFG(133, ALT_B)
+
+#define GPIO134_GPIO PIN_CFG(134, GPIO)
+#define GPIO134_MC2_DAT3 PIN_CFG_INPUT(134, ALT_A, PULLUP)
+#define GPIO134_SM_ADQ11 PIN_CFG(134, ALT_B)
+
+#define GPIO135_GPIO PIN_CFG(135, GPIO)
+#define GPIO135_MC2_DAT4 PIN_CFG_INPUT(135, ALT_A, PULLUP)
+#define GPIO135_SM_ADQ12 PIN_CFG(135, ALT_B)
+
+#define GPIO136_GPIO PIN_CFG(136, GPIO)
+#define GPIO136_MC2_DAT5 PIN_CFG_INPUT(136, ALT_A, PULLUP)
+#define GPIO136_SM_ADQ13 PIN_CFG(136, ALT_B)
+
+#define GPIO137_GPIO PIN_CFG(137, GPIO)
+#define GPIO137_MC2_DAT6 PIN_CFG_INPUT(137, ALT_A, PULLUP)
+#define GPIO137_SM_ADQ14 PIN_CFG(137, ALT_B)
+
+#define GPIO138_GPIO PIN_CFG(138, GPIO)
+#define GPIO138_MC2_DAT7 PIN_CFG_INPUT(138, ALT_A, PULLUP)
+#define GPIO138_SM_ADQ15 PIN_CFG(138, ALT_B)
+
+#define GPIO139_GPIO PIN_CFG(139, GPIO)
+#define GPIO139_SSP1_RXD PIN_CFG(139, ALT_A)
+#define GPIO139_SM_WAIT1n PIN_CFG(139, ALT_B)
+#define GPIO139_KP_O8 PIN_CFG(139, ALT_C)
+
+#define GPIO140_GPIO PIN_CFG(140, GPIO)
+#define GPIO140_SSP1_TXD PIN_CFG(140, ALT_A)
+#define GPIO140_IP_GPIO7 PIN_CFG(140, ALT_B)
+#define GPIO140_KP_SKA1 PIN_CFG(140, ALT_C)
+
+#define GPIO141_GPIO PIN_CFG(141, GPIO)
+#define GPIO141_SSP1_CLK PIN_CFG(141, ALT_A)
+#define GPIO141_IP_GPIO2 PIN_CFG(141, ALT_B)
+#define GPIO141_KP_O9 PIN_CFG(141, ALT_C)
+
+#define GPIO142_GPIO PIN_CFG(142, GPIO)
+#define GPIO142_SSP1_FRM PIN_CFG(142, ALT_A)
+#define GPIO142_IP_GPIO3 PIN_CFG(142, ALT_B)
+#define GPIO142_KP_SKB1 PIN_CFG(142, ALT_C)
+
+#define GPIO143_GPIO PIN_CFG(143, GPIO)
+#define GPIO143_SSP0_CLK PIN_CFG(143, ALT_A)
+
+#define GPIO144_GPIO PIN_CFG(144, GPIO)
+#define GPIO144_SSP0_FRM PIN_CFG(144, ALT_A)
+
+#define GPIO145_GPIO PIN_CFG(145, GPIO)
+#define GPIO145_SSP0_RXD PIN_CFG(145, ALT_A)
+
+#define GPIO146_GPIO PIN_CFG(146, GPIO)
+#define GPIO146_SSP0_TXD PIN_CFG(146, ALT_A)
+
+#define GPIO147_GPIO PIN_CFG(147, GPIO)
+#define GPIO147_I2C0_SCL PIN_CFG(147, ALT_A)
+
+#define GPIO148_GPIO PIN_CFG(148, GPIO)
+#define GPIO148_I2C0_SDA PIN_CFG(148, ALT_A)
+
+#define GPIO149_GPIO PIN_CFG(149, GPIO)
+#define GPIO149_IP_GPIO0 PIN_CFG(149, ALT_A)
+#define GPIO149_SM_CS1n PIN_CFG(149, ALT_B)
+#define GPIO149_SM_PS1n PIN_CFG(149, ALT_C)
+
+#define GPIO150_GPIO PIN_CFG(150, GPIO)
+#define GPIO150_IP_GPIO1 PIN_CFG(150, ALT_A)
+#define GPIO150_LCDA_CLK PIN_CFG(150, ALT_B)
+
+#define GPIO151_GPIO PIN_CFG(151, GPIO)
+#define GPIO151_KP_SKA0 PIN_CFG(151, ALT_A)
+#define GPIO151_LCD_VSI0 PIN_CFG(151, ALT_B)
+#define GPIO151_KP_O8 PIN_CFG(151, ALT_C)
+
+#define GPIO152_GPIO PIN_CFG(152, GPIO)
+#define GPIO152_KP_SKB0 PIN_CFG(152, ALT_A)
+#define GPIO152_LCD_VSI1 PIN_CFG(152, ALT_B)
+#define GPIO152_KP_O9 PIN_CFG(152, ALT_C)
+
+#define GPIO153_GPIO PIN_CFG(153, GPIO)
+#define GPIO153_KP_I7 PIN_CFG(153, ALT_A)
+#define GPIO153_LCD_D24 PIN_CFG(153, ALT_B)
+#define GPIO153_U2_RXD PIN_CFG(153, ALT_C)
+
+#define GPIO154_GPIO PIN_CFG(154, GPIO)
+#define GPIO154_KP_I6 PIN_CFG(154, ALT_A)
+#define GPIO154_LCD_D25 PIN_CFG(154, ALT_B)
+#define GPIO154_U2_TXD PIN_CFG(154, ALT_C)
+
+#define GPIO155_GPIO PIN_CFG(155, GPIO)
+#define GPIO155_KP_I5 PIN_CFG(155, ALT_A)
+#define GPIO155_LCD_D26 PIN_CFG(155, ALT_B)
+#define GPIO155_STMAPE_CLK PIN_CFG(155, ALT_C)
+
+#define GPIO156_GPIO PIN_CFG(156, GPIO)
+#define GPIO156_KP_I4 PIN_CFG(156, ALT_A)
+#define GPIO156_LCD_D27 PIN_CFG(156, ALT_B)
+#define GPIO156_STMAPE_DAT3 PIN_CFG(156, ALT_C)
+
+#define GPIO157_GPIO PIN_CFG(157, GPIO)
+#define GPIO157_KP_O7 PIN_CFG(157, ALT_A)
+#define GPIO157_LCD_D28 PIN_CFG(157, ALT_B)
+#define GPIO157_STMAPE_DAT2 PIN_CFG(157, ALT_C)
+
+#define GPIO158_GPIO PIN_CFG(158, GPIO)
+#define GPIO158_KP_O6 PIN_CFG(158, ALT_A)
+#define GPIO158_LCD_D29 PIN_CFG(158, ALT_B)
+#define GPIO158_STMAPE_DAT1 PIN_CFG(158, ALT_C)
+
+#define GPIO159_GPIO PIN_CFG(159, GPIO)
+#define GPIO159_KP_O5 PIN_CFG(159, ALT_A)
+#define GPIO159_LCD_D30 PIN_CFG(159, ALT_B)
+#define GPIO159_STMAPE_DAT0 PIN_CFG(159, ALT_C)
+
+#define GPIO160_GPIO PIN_CFG(160, GPIO)
+#define GPIO160_KP_O4 PIN_CFG(160, ALT_A)
+#define GPIO160_LCD_D31 PIN_CFG(160, ALT_B)
+#define GPIO160_NONE PIN_CFG(160, ALT_C)
+
+#define GPIO161_GPIO PIN_CFG(161, GPIO)
+#define GPIO161_KP_I3 PIN_CFG(161, ALT_A)
+#define GPIO161_LCD_D32 PIN_CFG(161, ALT_B)
+#define GPIO161_UARTMOD_RXD PIN_CFG(161, ALT_C)
+
+#define GPIO162_GPIO PIN_CFG(162, GPIO)
+#define GPIO162_KP_I2 PIN_CFG(162, ALT_A)
+#define GPIO162_LCD_D33 PIN_CFG(162, ALT_B)
+#define GPIO162_UARTMOD_TXD PIN_CFG(162, ALT_C)
+
+#define GPIO163_GPIO PIN_CFG(163, GPIO)
+#define GPIO163_KP_I1 PIN_CFG(163, ALT_A)
+#define GPIO163_LCD_D34 PIN_CFG(163, ALT_B)
+#define GPIO163_STMMOD_CLK PIN_CFG(163, ALT_C)
+
+#define GPIO164_GPIO PIN_CFG(164, GPIO)
+#define GPIO164_KP_I0 PIN_CFG(164, ALT_A)
+#define GPIO164_LCD_D35 PIN_CFG(164, ALT_B)
+#define GPIO164_STMMOD_DAT3 PIN_CFG(164, ALT_C)
+
+#define GPIO165_GPIO PIN_CFG(165, GPIO)
+#define GPIO165_KP_O3 PIN_CFG(165, ALT_A)
+#define GPIO165_LCD_D36 PIN_CFG(165, ALT_B)
+#define GPIO165_STMMOD_DAT2 PIN_CFG(165, ALT_C)
+
+#define GPIO166_GPIO PIN_CFG(166, GPIO)
+#define GPIO166_KP_O2 PIN_CFG(166, ALT_A)
+#define GPIO166_LCD_D37 PIN_CFG(166, ALT_B)
+#define GPIO166_STMMOD_DAT1 PIN_CFG(166, ALT_C)
+
+#define GPIO167_GPIO PIN_CFG(167, GPIO)
+#define GPIO167_KP_O1 PIN_CFG(167, ALT_A)
+#define GPIO167_LCD_D38 PIN_CFG(167, ALT_B)
+#define GPIO167_STMMOD_DAT0 PIN_CFG(167, ALT_C)
+
+#define GPIO168_GPIO PIN_CFG(168, GPIO)
+#define GPIO168_KP_O0 PIN_CFG(168, ALT_A)
+#define GPIO168_LCD_D39 PIN_CFG(168, ALT_B)
+#define GPIO168_NONE PIN_CFG(168, ALT_C)
+
+#define GPIO169_GPIO PIN_CFG(169, GPIO)
+#define GPIO169_RF_PURn PIN_CFG(169, ALT_A)
+#define GPIO169_LCDA_DE PIN_CFG(169, ALT_B)
+#define GPIO169_USBSIM_PDC PIN_CFG(169, ALT_C)
+
+#define GPIO170_GPIO PIN_CFG(170, GPIO)
+#define GPIO170_MODEM_STATE PIN_CFG(170, ALT_A)
+#define GPIO170_LCDA_VSO PIN_CFG(170, ALT_B)
+#define GPIO170_KP_SKA1 PIN_CFG(170, ALT_C)
+
+#define GPIO171_GPIO PIN_CFG(171, GPIO)
+#define GPIO171_MODEM_PWREN PIN_CFG(171, ALT_A)
+#define GPIO171_LCDA_HSO PIN_CFG(171, ALT_B)
+#define GPIO171_KP_SKB1 PIN_CFG(171, ALT_C)
+
+#define GPIO192_GPIO PIN_CFG(192, GPIO)
+#define GPIO192_MSP2_SCK PIN_CFG(192, ALT_A)
+
+#define GPIO193_GPIO PIN_CFG(193, GPIO)
+#define GPIO193_MSP2_TXD PIN_CFG(193, ALT_A)
+
+#define GPIO194_GPIO PIN_CFG(194, GPIO)
+#define GPIO194_MSP2_TCK PIN_CFG(194, ALT_A)
+
+#define GPIO195_GPIO PIN_CFG(195, GPIO)
+#define GPIO195_MSP2_TFS PIN_CFG(195, ALT_A)
+
+#define GPIO196_GPIO PIN_CFG(196, GPIO)
+#define GPIO196_MSP2_RXD PIN_CFG(196, ALT_A)
+
+#define GPIO197_GPIO PIN_CFG(197, GPIO)
+#define GPIO197_MC4_DAT3 PIN_CFG_INPUT(197, ALT_A, PULLUP)
+
+#define GPIO198_GPIO PIN_CFG(198, GPIO)
+#define GPIO198_MC4_DAT2 PIN_CFG_INPUT(198, ALT_A, PULLUP)
+
+#define GPIO199_GPIO PIN_CFG(199, GPIO)
+#define GPIO199_MC4_DAT1 PIN_CFG_INPUT(199, ALT_A, PULLUP)
+
+#define GPIO200_GPIO PIN_CFG(200, GPIO)
+#define GPIO200_MC4_DAT0 PIN_CFG_INPUT(200, ALT_A, PULLUP)
+
+#define GPIO201_GPIO PIN_CFG(201, GPIO)
+#define GPIO201_MC4_CMD PIN_CFG_INPUT(201, ALT_A, PULLUP)
+
+#define GPIO202_GPIO PIN_CFG(202, GPIO)
+#define GPIO202_MC4_FBCLK PIN_CFG_INPUT(202, ALT_A, PULLUP)
+#define GPIO202_PWL PIN_CFG(202, ALT_B)
+#define GPIO202_MC4_RSTN PIN_CFG(202, ALT_C)
+
+#define GPIO203_GPIO PIN_CFG(203, GPIO)
+#define GPIO203_MC4_CLK PIN_CFG_INPUT(203, ALT_A, PULLUP)
+
+#define GPIO204_GPIO PIN_CFG(204, GPIO)
+#define GPIO204_MC4_DAT7 PIN_CFG_INPUT(204, ALT_A, PULLUP)
+
+#define GPIO205_GPIO PIN_CFG(205, GPIO)
+#define GPIO205_MC4_DAT6 PIN_CFG_INPUT(205, ALT_A, PULLUP)
+
+#define GPIO206_GPIO PIN_CFG(206, GPIO)
+#define GPIO206_MC4_DAT5 PIN_CFG_INPUT(206, ALT_A, PULLUP)
+
+#define GPIO207_GPIO PIN_CFG(207, GPIO)
+#define GPIO207_MC4_DAT4 PIN_CFG_INPUT(207, ALT_A, PULLUP)
+
+#define GPIO208_GPIO PIN_CFG(208, GPIO)
+#define GPIO208_MC1_CLK PIN_CFG(208, ALT_A)
+
+#define GPIO209_GPIO PIN_CFG(209, GPIO)
+#define GPIO209_MC1_FBCLK PIN_CFG(209, ALT_A)
+#define GPIO209_SPI1_CLK PIN_CFG(209, ALT_B)
+
+#define GPIO210_GPIO PIN_CFG(210, GPIO)
+#define GPIO210_MC1_CMD PIN_CFG(210, ALT_A)
+
+#define GPIO211_GPIO PIN_CFG(211, GPIO)
+#define GPIO211_MC1_DAT0 PIN_CFG(211, ALT_A)
+
+#define GPIO212_GPIO PIN_CFG(212, GPIO)
+#define GPIO212_MC1_DAT1 PIN_CFG(212, ALT_A)
+#define GPIO212_SPI1_FRM PIN_CFG(212, ALT_B)
+
+#define GPIO213_GPIO PIN_CFG(213, GPIO)
+#define GPIO213_MC1_DAT2 PIN_CFG(213, ALT_A)
+#define GPIO213_SPI1_TXD PIN_CFG(213, ALT_B)
+
+#define GPIO214_GPIO PIN_CFG(214, GPIO)
+#define GPIO214_MC1_DAT3 PIN_CFG(214, ALT_A)
+#define GPIO214_SPI1_RXD PIN_CFG(214, ALT_B)
+
+#define GPIO215_GPIO PIN_CFG(215, GPIO)
+#define GPIO215_MC1_CMDDIR PIN_CFG(215, ALT_A)
+#define GPIO215_MC3_DAT2DIR PIN_CFG(215, ALT_B)
+#define GPIO215_CLKOUT1 PIN_CFG(215, ALT_C)
+#define GPIO215_SPI2_TXD PIN_CFG(215, ALT_C)
+
+#define GPIO216_GPIO PIN_CFG(216, GPIO)
+#define GPIO216_MC1_DAT2DIR PIN_CFG(216, ALT_A)
+#define GPIO216_MC3_CMDDIR PIN_CFG(216, ALT_B)
+#define GPIO216_I2C3_SDA PIN_CFG(216, ALT_C)
+#define GPIO216_SPI2_FRM PIN_CFG(216, ALT_C)
+
+#define GPIO217_GPIO PIN_CFG(217, GPIO)
+#define GPIO217_MC1_DAT0DIR PIN_CFG(217, ALT_A)
+#define GPIO217_MC3_DAT31DIR PIN_CFG(217, ALT_B)
+#define GPIO217_CLKOUT2 PIN_CFG(217, ALT_C)
+#define GPIO217_SPI2_CLK PIN_CFG(217, ALT_C)
+
+#define GPIO218_GPIO PIN_CFG(218, GPIO)
+#define GPIO218_MC1_DAT31DIR PIN_CFG(218, ALT_A)
+#define GPIO218_MC3_DAT0DIR PIN_CFG(218, ALT_B)
+#define GPIO218_I2C3_SCL PIN_CFG(218, ALT_C)
+#define GPIO218_SPI2_RXD PIN_CFG(218, ALT_C)
+
+#define GPIO219_GPIO PIN_CFG(219, GPIO)
+#define GPIO219_HSIR_FLA0 PIN_CFG(219, ALT_A)
+#define GPIO219_MC3_CLK PIN_CFG(219, ALT_B)
+
+#define GPIO220_GPIO PIN_CFG(220, GPIO)
+#define GPIO220_HSIR_DAT0 PIN_CFG(220, ALT_A)
+#define GPIO220_MC3_FBCLK PIN_CFG(220, ALT_B)
+#define GPIO220_SPI0_CLK PIN_CFG(220, ALT_C)
+
+#define GPIO221_GPIO PIN_CFG(221, GPIO)
+#define GPIO221_HSIR_RDY0 PIN_CFG(221, ALT_A)
+#define GPIO221_MC3_CMD PIN_CFG(221, ALT_B)
+
+#define GPIO222_GPIO PIN_CFG(222, GPIO)
+#define GPIO222_HSIT_FLA0 PIN_CFG(222, ALT_A)
+#define GPIO222_MC3_DAT0 PIN_CFG(222, ALT_B)
+
+#define GPIO223_GPIO PIN_CFG(223, GPIO)
+#define GPIO223_HSIT_DAT0 PIN_CFG(223, ALT_A)
+#define GPIO223_MC3_DAT1 PIN_CFG(223, ALT_B)
+#define GPIO223_SPI0_FRM PIN_CFG(223, ALT_C)
+
+#define GPIO224_GPIO PIN_CFG(224, GPIO)
+#define GPIO224_HSIT_RDY0 PIN_CFG(224, ALT_A)
+#define GPIO224_MC3_DAT2 PIN_CFG(224, ALT_B)
+#define GPIO224_SPI0_TXD PIN_CFG(224, ALT_C)
+
+#define GPIO225_GPIO PIN_CFG(225, GPIO)
+#define GPIO225_HSIT_CAWAKE0 PIN_CFG(225, ALT_A)
+#define GPIO225_MC3_DAT3 PIN_CFG(225, ALT_B)
+#define GPIO225_SPI0_RXD PIN_CFG(225, ALT_C)
+
+#define GPIO226_GPIO PIN_CFG(226, GPIO)
+#define GPIO226_HSIT_ACWAKE0 PIN_CFG(226, ALT_A)
+#define GPIO226_PWL PIN_CFG(226, ALT_B)
+#define GPIO226_USBSIM_PDC PIN_CFG(226, ALT_C)
+
+#define GPIO227_GPIO PIN_CFG(227, GPIO)
+#define GPIO227_CLKOUT1 PIN_CFG(227, ALT_A)
+
+#define GPIO228_GPIO PIN_CFG(228, GPIO)
+#define GPIO228_CLKOUT2 PIN_CFG(228, ALT_A)
+
+#define GPIO229_GPIO PIN_CFG(229, GPIO)
+#define GPIO229_CLKOUT1 PIN_CFG(229, ALT_A)
+#define GPIO229_PWL PIN_CFG(229, ALT_B)
+#define GPIO229_I2C3_SDA PIN_CFG(229, ALT_C)
+
+#define GPIO230_GPIO PIN_CFG(230, GPIO)
+#define GPIO230_CLKOUT2 PIN_CFG(230, ALT_A)
+#define GPIO230_PWL PIN_CFG(230, ALT_B)
+#define GPIO230_I2C3_SCL PIN_CFG(230, ALT_C)
+
+#define GPIO256_GPIO PIN_CFG(256, GPIO)
+#define GPIO256_USB_NXT PIN_CFG(256, ALT_A)
+
+#define GPIO257_GPIO PIN_CFG(257, GPIO)
+#define GPIO257_USB_STP PIN_CFG(257, ALT_A)
+
+#define GPIO258_GPIO PIN_CFG(258, GPIO)
+#define GPIO258_USB_XCLK PIN_CFG(258, ALT_A)
+#define GPIO258_NONE PIN_CFG(258, ALT_B)
+#define GPIO258_DDR_TRIG PIN_CFG(258, ALT_C)
+
+#define GPIO259_GPIO PIN_CFG(259, GPIO)
+#define GPIO259_USB_DIR PIN_CFG(259, ALT_A)
+
+#define GPIO260_GPIO PIN_CFG(260, GPIO)
+#define GPIO260_USB_DAT7 PIN_CFG(260, ALT_A)
+
+#define GPIO261_GPIO PIN_CFG(261, GPIO)
+#define GPIO261_USB_DAT6 PIN_CFG(261, ALT_A)
+
+#define GPIO262_GPIO PIN_CFG(262, GPIO)
+#define GPIO262_USB_DAT5 PIN_CFG(262, ALT_A)
+
+#define GPIO263_GPIO PIN_CFG(263, GPIO)
+#define GPIO263_USB_DAT4 PIN_CFG(263, ALT_A)
+
+#define GPIO264_GPIO PIN_CFG(264, GPIO)
+#define GPIO264_USB_DAT3 PIN_CFG(264, ALT_A)
+
+#define GPIO265_GPIO PIN_CFG(265, GPIO)
+#define GPIO265_USB_DAT2 PIN_CFG(265, ALT_A)
+
+#define GPIO266_GPIO PIN_CFG(266, GPIO)
+#define GPIO266_USB_DAT1 PIN_CFG(266, ALT_A)
+
+#define GPIO267_GPIO PIN_CFG(267, GPIO)
+#define GPIO267_USB_DAT0 PIN_CFG(267, ALT_A)
+
+#endif
diff --git a/arch/arm/mach-ux500/pins.c b/arch/arm/mach-ux500/pins.c
new file mode 100644
index 00000000000..38c1d47b29a
--- /dev/null
+++ b/arch/arm/mach-ux500/pins.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <plat/pincfg.h>
+
+#include "pins.h"
+
+static LIST_HEAD(pin_lookups);
+static DEFINE_MUTEX(pin_lookups_mutex);
+static DEFINE_SPINLOCK(pins_lock);
+
+void __init ux500_pins_add(struct ux500_pin_lookup *pl, size_t num)
+{
+ mutex_lock(&pin_lookups_mutex);
+
+ while (num--) {
+ list_add_tail(&pl->node, &pin_lookups);
+ pl++;
+ }
+
+ mutex_unlock(&pin_lookups_mutex);
+}
+
+struct ux500_pins *ux500_pins_get(const char *name)
+{
+ struct ux500_pins *pins = NULL;
+ struct ux500_pin_lookup *pl;
+
+ mutex_lock(&pin_lookups_mutex);
+
+ list_for_each_entry(pl, &pin_lookups, node) {
+ if (!strcmp(pl->name, name)) {
+ pins = pl->pins;
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&pin_lookups_mutex);
+ return pins;
+}
+
+int ux500_pins_enable(struct ux500_pins *pins)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&pins_lock, flags);
+
+ if (pins->usage++ == 0)
+ ret = nmk_config_pins(pins->cfg, pins->num);
+
+ spin_unlock_irqrestore(&pins_lock, flags);
+ return ret;
+}
+
+int ux500_pins_disable(struct ux500_pins *pins)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&pins_lock, flags);
+
+ if (WARN_ON(pins->usage == 0))
+ goto out;
+
+ if (--pins->usage == 0)
+ ret = nmk_config_pins_sleep(pins->cfg, pins->num);
+
+out:
+ spin_unlock_irqrestore(&pins_lock, flags);
+ return ret;
+}
+
+void ux500_pins_put(struct ux500_pins *pins)
+{
+ WARN_ON(!pins);
+}
diff --git a/arch/arm/mach-ux500/pins.h b/arch/arm/mach-ux500/pins.h
new file mode 100644
index 00000000000..52e123963f1
--- /dev/null
+++ b/arch/arm/mach-ux500/pins.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __MACH_UX500_PINS_H
+#define __MACH_UX500_PINS_H
+
+#include <linux/list.h>
+
+#define PIN_LOOKUP(_name, _pins) \
+{ \
+ .name = _name, \
+ .pins = _pins, \
+}
+
+#define UX500_PINS(name, pins...) \
+struct ux500_pins name = { \
+ .cfg = (pin_cfg_t[]) {pins}, \
+ .num = ARRAY_SIZE(((pin_cfg_t[]) {pins})), \
+}
+
+struct ux500_pins {
+ int usage;
+ int num;
+ pin_cfg_t *cfg;
+};
+
+struct ux500_pin_lookup {
+ struct list_head node;
+ const char *name;
+ struct ux500_pins *pins;
+};
+
+void __init ux500_pins_add(struct ux500_pin_lookup *pl, size_t num);
+struct ux500_pins *ux500_pins_get(const char *name);
+int ux500_pins_enable(struct ux500_pins *pins);
+int ux500_pins_disable(struct ux500_pins *pins);
+void ux500_pins_put(struct ux500_pins *pins);
+
+#endif
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 438ef16aec9..47bafde8611 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -21,16 +21,34 @@
#include <asm/localtimer.h>
#include <asm/smp_scu.h>
#include <mach/hardware.h>
+#include <mach/setup.h>
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
-volatile int __cpuinitdata pen_release = -1;
+volatile int pen_release = -1;
+
+static void __iomem *scu_base_addr(void)
+{
+ if (cpu_is_u5500())
+ return __io_address(U5500_SCU_BASE);
+ else if (cpu_is_u8500())
+ return __io_address(U8500_SCU_BASE);
+ else
+ ux500_unknown_soc();
+
+ return NULL;
+}
static unsigned int __init get_core_count(void)
{
- return scu_get_core_count(__io_address(UX500_SCU_BASE));
+ void __iomem *scu_base = scu_base_addr();
+
+ if (scu_base)
+ return scu_get_core_count(scu_base);
+
+ return 1;
}
static DEFINE_SPINLOCK(boot_lock);
@@ -44,7 +62,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
- gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+ gic_cpu_init(0, gic_cpu_base_addr);
/*
* let the primary processor know we're out of the
@@ -78,6 +96,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
+ smp_cross_call(cpumask_of(cpu));
+
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
if (pen_release == -1)
@@ -95,6 +115,15 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
static void __init wakeup_secondary(void)
{
+ void __iomem *backupram;
+
+ if (cpu_is_u5500())
+ backupram = __io_address(U5500_BACKUPRAM0_BASE);
+ else if (cpu_is_u8500())
+ backupram = __io_address(U8500_BACKUPRAM0_BASE);
+ else
+ ux500_unknown_soc();
+
/* nobody is to be released from the pen yet */
pen_release = -1;
@@ -104,15 +133,13 @@ static void __init wakeup_secondary(void)
* backup ram register at offset 0x1FF0, which is what boot rom code
* is waiting for. This would wake up the secondary core from WFE
*/
-#define U8500_CPU1_JUMPADDR_OFFSET 0x1FF4
+#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
__raw_writel(virt_to_phys(u8500_secondary_startup),
- __io_address(UX500_BACKUPRAM0_BASE) +
- U8500_CPU1_JUMPADDR_OFFSET);
+ backupram + UX500_CPU1_JUMPADDR_OFFSET);
-#define U8500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
+#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
__raw_writel(0xA1FEED01,
- __io_address(UX500_BACKUPRAM0_BASE) +
- U8500_CPU1_WAKEMAGIC_OFFSET);
+ backupram + UX500_CPU1_WAKEMAGIC_OFFSET);
/* make sure write buffer is drained */
mb();
@@ -166,13 +193,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
+ percpu_timer_setup();
+
if (max_cpus > 1) {
- /*
- * Enable the local timer or broadcast device for the
- * boot CPU, but only if we have more than one CPU.
- */
- percpu_timer_setup();
- scu_enable(__io_address(UX500_SCU_BASE));
+ scu_enable(scu_base_addr());
wakeup_secondary();
}
}
diff --git a/arch/arm/mach-ux500/pm/Kconfig b/arch/arm/mach-ux500/pm/Kconfig
new file mode 100644
index 00000000000..5de1afe1bee
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/Kconfig
@@ -0,0 +1,82 @@
+config U8500_CPUFREQ
+ tristate "CPUFreq support"
+ depends on UX500_SOC_DB8500 && CPU_FREQ
+ default y
+ help
+ Add support for CPU Frequency scaling for U8500.
+
+config U8500_CPUIDLE
+ tristate "CPUIdle support"
+ depends on UX500_SOC_DB8500 && CPU_IDLE && U8500_PRCMU
+ 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
+ depends on U8500_CPUIDLE
+ help
+ Set deepest sleep state. See the cstate struct in cpuidle.c.
+ Default is ApSleep.
+
+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 && UX500_SOC_DB8500
+ 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 && UX500_SOC_DB8500
+ 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
+ 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)
+ default y
+ help
+ Adjusts CPU_IDLE, CPU_FREQ, HOTPLUG_CPU and L2 cache parameters
diff --git a/arch/arm/mach-ux500/pm/Makefile b/arch/arm/mach-ux500/pm/Makefile
new file mode 100644
index 00000000000..abd08ee341e
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/Makefile
@@ -0,0 +1,16 @@
+#
+# Power save related files
+#
+obj-y := pm.o runtime.o
+
+obj-$(CONFIG_U8500_CPUIDLE) += cpuidle.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_U8500_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_U8500_CPUFREQ) += cpufreq-db8500.o
+endif
diff --git a/arch/arm/mach-ux500/pm/context-db5500.c b/arch/arm/mach-ux500/pm/context-db5500.c
new file mode 100644
index 00000000000..f9a8376620f
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/context-db5500.c
@@ -0,0 +1,395 @@
+/*
+ * 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_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
+
+#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[3];
+ u32 hibw2_ddr_in_limit[3];
+ 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_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_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_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_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_4K);
+}
diff --git a/arch/arm/mach-ux500/pm/context-db8500.c b/arch/arm/mach-ux500/pm/context-db8500.c
new file mode 100644
index 00000000000..f43a2a81f8e
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/context-db8500.c
@@ -0,0 +1,467 @@
+/*
+ * 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/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
+/* only in v1 */
+#define NODE_HIBW2_DDR_IN_3_PRIORITY 0xC0C
+/* address update between v1 and v2 */
+#define NODE_HIBW2_DDR_IN_0_LIMIT_V1 0xC30
+#define NODE_HIBW2_DDR_IN_1_LIMIT_V1 0xC34
+#define NODE_HIBW2_DDR_IN_0_LIMIT 0xC24
+#define NODE_HIBW2_DDR_IN_1_LIMIT 0xC28
+/* only in v2 */
+#define NODE_HIBW2_DDR_IN_2_LIMIT 0xC2C
+#define NODE_HIBW2_DDR_OUT_0_PRIORITY 0xC30
+#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)
+{
+
+ context_icn.hibw1_esram_in_pri[0] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_0_PRIORITY);
+ context_icn.hibw1_esram_in_pri[1] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_1_PRIORITY);
+ context_icn.hibw1_esram_in_pri[2] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_2_PRIORITY);
+
+ context_icn.hibw1_esram_in0_arb[0] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_1_LIMIT);
+ context_icn.hibw1_esram_in0_arb[1] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_2_LIMIT);
+ context_icn.hibw1_esram_in0_arb[2] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_0_ARB_3_LIMIT);
+
+ context_icn.hibw1_esram_in1_arb[0] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_1_LIMIT);
+ context_icn.hibw1_esram_in1_arb[1] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_2_LIMIT);
+ context_icn.hibw1_esram_in1_arb[2] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_1_ARB_3_LIMIT);
+
+ context_icn.hibw1_esram_in2_arb[0] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT);
+ context_icn.hibw1_esram_in2_arb[1] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT);
+ context_icn.hibw1_esram_in2_arb[2] =
+ readb(context_icn.base + NODE_HIBW1_ESRAM_IN_2_ARB_3_LIMIT);
+
+ context_icn.hibw1_ddr_in_prio[0] =
+ readb(context_icn.base + NODE_HIBW1_DDR_IN_0_PRIORITY);
+ context_icn.hibw1_ddr_in_prio[1] =
+ readb(context_icn.base + NODE_HIBW1_DDR_IN_1_PRIORITY);
+ context_icn.hibw1_ddr_in_prio[2] =
+ readb(context_icn.base + NODE_HIBW1_DDR_IN_2_PRIORITY);
+
+ context_icn.hibw1_ddr_in_limit[0] =
+ readb(context_icn.base + NODE_HIBW1_DDR_IN_0_LIMIT);
+ context_icn.hibw1_ddr_in_limit[1] =
+ readb(context_icn.base + NODE_HIBW1_DDR_IN_1_LIMIT);
+ context_icn.hibw1_ddr_in_limit[2] =
+ readb(context_icn.base + NODE_HIBW1_DDR_IN_2_LIMIT);
+
+ context_icn.hibw1_ddr_out_prio =
+ readb(context_icn.base + NODE_HIBW1_DDR_OUT_0_PRIORITY);
+
+ context_icn.hibw2_esram_in_pri[0] =
+ readb(context_icn.base + NODE_HIBW2_ESRAM_IN_0_PRIORITY);
+ context_icn.hibw2_esram_in_pri[1] =
+ readb(context_icn.base + NODE_HIBW2_ESRAM_IN_1_PRIORITY);
+
+ context_icn.hibw2_esram_in0_arblimit[0] =
+ readb(context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_1_LIMIT);
+ context_icn.hibw2_esram_in0_arblimit[1] =
+ readb(context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_2_LIMIT);
+ context_icn.hibw2_esram_in0_arblimit[2] =
+ readb(context_icn.base + NODE_HIBW2_ESRAM_IN_0_ARB_3_LIMIT);
+
+ context_icn.hibw2_esram_in1_arblimit[0] =
+ readb(context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_1_LIMIT);
+ context_icn.hibw2_esram_in1_arblimit[1] =
+ readb(context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_2_LIMIT);
+ context_icn.hibw2_esram_in1_arblimit[2] =
+ readb(context_icn.base + NODE_HIBW2_ESRAM_IN_1_ARB_3_LIMIT);
+
+ context_icn.hibw2_ddr_in_prio[0] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_0_PRIORITY);
+ context_icn.hibw2_ddr_in_prio[1] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_1_PRIORITY);
+ context_icn.hibw2_ddr_in_prio[2] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_2_PRIORITY);
+
+ if (cpu_is_u8500v1()) {
+ context_icn.hibw2_ddr_in_prio[3] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_3_PRIORITY);
+
+ context_icn.hibw2_ddr_in_limit[0] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_0_LIMIT_V1);
+ context_icn.hibw2_ddr_in_limit[1] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_1_LIMIT_V1);
+ }
+
+ if (cpu_is_u8500v2()) {
+ context_icn.hibw2_ddr_in_limit[0] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_0_LIMIT);
+ context_icn.hibw2_ddr_in_limit[1] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_1_LIMIT);
+
+ context_icn.hibw2_ddr_in_limit[2] =
+ readb(context_icn.base + NODE_HIBW2_DDR_IN_2_LIMIT);
+
+ context_icn.hibw2_ddr_out_prio =
+ readb(context_icn.base +
+ NODE_HIBW2_DDR_OUT_0_PRIORITY);
+
+ context_icn.esram0_in_prio[0] =
+ readb(context_icn.base + NODE_ESRAM0_IN_0_PRIORITY);
+ context_icn.esram0_in_prio[1] =
+ readb(context_icn.base + NODE_ESRAM0_IN_1_PRIORITY);
+ context_icn.esram0_in_prio[2] =
+ readb(context_icn.base + NODE_ESRAM0_IN_2_PRIORITY);
+ context_icn.esram0_in_prio[3] =
+ readb(context_icn.base + NODE_ESRAM0_IN_3_PRIORITY);
+
+ context_icn.esram0_in_lim[0] =
+ readb(context_icn.base + NODE_ESRAM0_IN_0_LIMIT);
+ context_icn.esram0_in_lim[1] =
+ readb(context_icn.base + NODE_ESRAM0_IN_1_LIMIT);
+ context_icn.esram0_in_lim[2] =
+ readb(context_icn.base + NODE_ESRAM0_IN_2_LIMIT);
+ context_icn.esram0_in_lim[3] =
+ readb(context_icn.base + NODE_ESRAM0_IN_3_LIMIT);
+ }
+ context_icn.esram12_in_prio[0] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_0_PRIORITY);
+ context_icn.esram12_in_prio[1] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_1_PRIORITY);
+ context_icn.esram12_in_prio[2] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_2_PRIORITY);
+ context_icn.esram12_in_prio[3] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_3_PRIORITY);
+
+ context_icn.esram12_in_arb_lim[0] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_0_ARB_1_LIMIT);
+ context_icn.esram12_in_arb_lim[1] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_0_ARB_2_LIMIT);
+ context_icn.esram12_in_arb_lim[2] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT);
+ context_icn.esram12_in_arb_lim[3] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_1_ARB_2_LIMIT);
+ context_icn.esram12_in_arb_lim[4] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT);
+ context_icn.esram12_in_arb_lim[5] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_2_ARB_2_LIMIT);
+ context_icn.esram12_in_arb_lim[6] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_3_ARB_1_LIMIT);
+ context_icn.esram12_in_arb_lim[7] =
+ readb(context_icn.base + NODE_ESRAM1_2_IN_3_ARB_2_LIMIT);
+
+ context_icn.esram34_in_prio[0] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_0_PRIORITY);
+ context_icn.esram34_in_prio[1] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_1_PRIORITY);
+ context_icn.esram34_in_prio[2] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_2_PRIORITY);
+ context_icn.esram34_in_prio[3] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_3_PRIORITY);
+
+ context_icn.esram34_in_arb_lim[0] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_0_ARB_1_LIMIT);
+ context_icn.esram34_in_arb_lim[1] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_0_ARB_2_LIMIT);
+ context_icn.esram34_in_arb_lim[2] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT);
+ context_icn.esram34_in_arb_lim[3] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_1_ARB_2_LIMIT);
+ context_icn.esram34_in_arb_lim[4] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT);
+ context_icn.esram34_in_arb_lim[5] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_2_ARB_2_LIMIT);
+ context_icn.esram34_in_arb_lim[6] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_3_ARB_1_LIMIT);
+ context_icn.esram34_in_arb_lim[7] =
+ readb(context_icn.base + NODE_ESRAM3_4_IN_3_ARB_2_LIMIT);
+
+}
+
+/**
+ * u8500_context_restore_icn() - restore ICN context
+ *
+ */
+void u8500_context_restore_icn(void)
+{
+ 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_in_pri[2],
+ context_icn.base + NODE_HIBW1_ESRAM_IN_2_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_esram_in2_arb[0],
+ context_icn.base + NODE_HIBW1_ESRAM_IN_2_ARB_1_LIMIT);
+ writel(context_icn.hibw1_esram_in2_arb[1],
+ context_icn.base + NODE_HIBW1_ESRAM_IN_2_ARB_2_LIMIT);
+ writel(context_icn.hibw1_esram_in2_arb[2],
+ context_icn.base + NODE_HIBW1_ESRAM_IN_2_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,
+ context_icn.base + NODE_HIBW1_DDR_OUT_0_PRIORITY);
+
+ 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);
+ if (cpu_is_u8500v1()) {
+ 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_V1);
+ writel(context_icn.hibw2_ddr_in_limit[1],
+ context_icn.base + NODE_HIBW2_DDR_IN_1_LIMIT_V1);
+ }
+ if (cpu_is_u8500v2()) {
+ 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_out_prio,
+ context_icn.base + NODE_HIBW2_DDR_OUT_0_PRIORITY);
+
+ writel(context_icn.esram0_in_prio[0],
+ context_icn.base + NODE_ESRAM0_IN_0_PRIORITY);
+ writel(context_icn.esram0_in_prio[1],
+ context_icn.base + NODE_ESRAM0_IN_1_PRIORITY);
+ writel(context_icn.esram0_in_prio[2],
+ context_icn.base + NODE_ESRAM0_IN_2_PRIORITY);
+ writel(context_icn.esram0_in_prio[3],
+ context_icn.base + NODE_ESRAM0_IN_3_PRIORITY);
+
+ writel(context_icn.esram0_in_lim[0],
+ context_icn.base + NODE_ESRAM0_IN_0_LIMIT);
+ writel(context_icn.esram0_in_lim[1],
+ context_icn.base + NODE_ESRAM0_IN_1_LIMIT);
+ writel(context_icn.esram0_in_lim[2],
+ context_icn.base + NODE_ESRAM0_IN_2_LIMIT);
+ writel(context_icn.esram0_in_lim[3],
+ context_icn.base + NODE_ESRAM0_IN_3_LIMIT);
+ }
+
+ 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_prio[3],
+ context_icn.base + NODE_ESRAM1_2_IN_3_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_0_ARB_2_LIMIT);
+ writel(context_icn.esram12_in_arb_lim[2],
+ context_icn.base + NODE_ESRAM1_2_IN_1_ARB_1_LIMIT);
+ writel(context_icn.esram12_in_arb_lim[3],
+ context_icn.base + NODE_ESRAM1_2_IN_1_ARB_2_LIMIT);
+ writel(context_icn.esram12_in_arb_lim[4],
+ context_icn.base + NODE_ESRAM1_2_IN_2_ARB_1_LIMIT);
+ writel(context_icn.esram12_in_arb_lim[5],
+ context_icn.base + NODE_ESRAM1_2_IN_2_ARB_2_LIMIT);
+ writel(context_icn.esram12_in_arb_lim[6],
+ context_icn.base + NODE_ESRAM1_2_IN_3_ARB_1_LIMIT);
+ writel(context_icn.esram12_in_arb_lim[7],
+ context_icn.base + NODE_ESRAM1_2_IN_3_ARB_2_LIMIT);
+
+ 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_prio[3],
+ context_icn.base + NODE_ESRAM3_4_IN_3_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_0_ARB_2_LIMIT);
+ writel(context_icn.esram34_in_arb_lim[2],
+ context_icn.base + NODE_ESRAM3_4_IN_1_ARB_1_LIMIT);
+ writel(context_icn.esram34_in_arb_lim[3],
+ context_icn.base + NODE_ESRAM3_4_IN_1_ARB_2_LIMIT);
+ writel(context_icn.esram34_in_arb_lim[4],
+ context_icn.base + NODE_ESRAM3_4_IN_2_ARB_1_LIMIT);
+ writel(context_icn.esram34_in_arb_lim[5],
+ context_icn.base + NODE_ESRAM3_4_IN_2_ARB_2_LIMIT);
+ writel(context_icn.esram34_in_arb_lim[6],
+ context_icn.base + NODE_ESRAM3_4_IN_3_ARB_1_LIMIT);
+ writel(context_icn.esram34_in_arb_lim[7],
+ context_icn.base + 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
new file mode 100644
index 00000000000..3bfb3acf8c9
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/context.c
@@ -0,0 +1,911 @@
+/*
+ * 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 <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/scu.h>
+
+#include <plat/gpio.h>
+
+#include "context.h"
+#include "pm.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)
+
+/* Special dedicated addresses in backup RAM */
+#define U8500_EXT_RAM_LOC_BACKUPRAM_ADDR 0x80151FDC
+#define U8500_CPU0_CP15_CR_BACKUPRAM_ADDR 0x80151F80
+#define U8500_CPU1_CP15_CR_BACKUPRAM_ADDR 0x80151FA0
+
+/* For v1.x */
+#define U8500_CPU0_BACKUPRAM_ADDR_BACKUPRAM_LOG_ADDR 0x80151FD8
+#define U8500_CPU1_BACKUPRAM_ADDR_BACKUPRAM_LOG_ADDR 0x80151FE0
+
+/* For v2.0 and later */
+#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_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 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, varm_registers_backup_stack[1024]);
+static DEFINE_PER_CPU(u32 *, varm_registers_pointer);
+
+static DEFINE_PER_CPU(u32, varm_cp15_backup_stack[1024]);
+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);
+}
+
+/*
+ * 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)
+{
+ 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)
+{
+ 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(c_gic_cpu->base + GIC_CPU_CTRL);
+ c_gic_cpu->primask = readl(c_gic_cpu->base + GIC_CPU_PRIMASK);
+ c_gic_cpu->binpoint = readl(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(c_gic_cpu->ctrl, c_gic_cpu->base + GIC_CPU_CTRL);
+ writel(c_gic_cpu->primask, c_gic_cpu->base + GIC_CPU_PRIMASK);
+ writel(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(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(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(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(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.spi_target[i] =
+ readl(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(context_gic_dist_common.spi_target[i],
+ context_gic_dist_common.base +
+ GIC_DIST_CONFIG_SPI32 + i * 4);
+
+ for (i = 0; i < GIC_DIST_SPI_TARGET_COMMON_NUM; i++)
+ writel(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(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(context_gic_dist_common.enable_set[i],
+ context_gic_dist_common.base +
+ GIC_DIST_ENABLE_SET_SPI32 + i * 4);
+
+ writel(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(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(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(c_gic->base +
+ GIC_DIST_SPI_TARGET_SPI0 + i * 4);
+
+ for (i = 0; i < GIC_DIST_CONFIG_CPU_NUM; i++)
+ c_gic->spi_target[i] =
+ readl(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(c_gic->spi_target[i],
+ c_gic->base +
+ GIC_DIST_CONFIG_SPI0 + i * 4);
+
+ for (i = 0; i < GIC_DIST_SPI_TARGET_CPU_NUM; i++)
+ writel(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(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(c_gic->enable_set[i],
+ c_gic->base +
+ GIC_DIST_ENABLE_SET_SPI0 + i * 4);
+}
+static void save_scu(void)
+{
+ context_scu.ctrl =
+ readl(context_scu.base + SCU_CTRL);
+ context_scu.cpu_pwrstatus =
+ readl(context_scu.base + SCU_CPU_STATUS);
+ context_scu.inv_all_nonsecure =
+ readl(context_scu.base + SCU_INVALIDATE);
+ context_scu.filter_start_addr =
+ readl(context_scu.base + SCU_FILTER_STARTADDR);
+ context_scu.filter_end_addr =
+ readl(context_scu.base + SCU_FILTER_ENDADDR);
+ context_scu.access_ctrl_sac =
+ readl(context_scu.base + SCU_ACCESS_CTRL_SAC);
+}
+
+static void restore_scu(void)
+{
+ writel(context_scu.ctrl,
+ context_scu.base + SCU_CTRL);
+ writel(context_scu.cpu_pwrstatus,
+ context_scu.base + SCU_CPU_STATUS);
+ writel(context_scu.inv_all_nonsecure,
+ context_scu.base + SCU_INVALIDATE);
+ writel(context_scu.filter_start_addr,
+ context_scu.base + SCU_FILTER_STARTADDR);
+ writel(context_scu.filter_end_addr,
+ context_scu.base + SCU_FILTER_ENDADDR);
+ writel(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();
+
+ if (cpu_is_u8500())
+ context_save_to_sram_and_wfi_internal(backup_sram_storage[cpu],
+ cleanL2cache);
+ else if (cpu_is_u5500())
+ __asm__ __volatile__("wfi\n" : : : "memory");
+}
+
+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));
+
+ /* Give logical address to backup RAM. For both CPUs */
+ if (cpu_is_u8500v20_or_later()) {
+ 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));
+ } else {
+ writel(IO_ADDRESS(U8500_BACKUPRAM0_BASE),
+ IO_ADDRESS(U8500_CPU0_BACKUPRAM_ADDR_BACKUPRAM_LOG_ADDR));
+
+ writel(IO_ADDRESS(U8500_BACKUPRAM0_BASE),
+ IO_ADDRESS(U8500_CPU1_BACKUPRAM_ADDR_BACKUPRAM_LOG_ADDR));
+ }
+
+ /* FIXME: To UX500 */
+ 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);
+
+ for (i = 0; i < num_possible_cpus(); i++) {
+ per_cpu(context_gic_cpu, i).base = ioremap(U8500_GIC_CPU_BASE,
+ SZ_4K);
+ per_cpu(context_gic_dist_cpu, i).base =
+ ioremap(U8500_GIC_DIST_BASE,
+ SZ_4K);
+ }
+
+ context_gic_dist_common.base = ioremap(U8500_GIC_DIST_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);
+
+ 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
new file mode 100644
index 00000000000..20ffaafdb41
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/context.h
@@ -0,0 +1,88 @@
+/*
+ * 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_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);
+
+/*
+ * cleanL2cache - Indicate if L2 cache should be cleaned.
+ * Note that L1 cache is always cleaned.
+ */
+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
new file mode 100644
index 00000000000..7778b3d4503
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/context_arm.S
@@ -0,0 +1,427 @@
+/*
+ * 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, lr} @ Save on 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, 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, lr} @ Save on 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, 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)
+
+
+/*
+ * L2 cache clean function. Commit from PL310 L2 cache
+ * controller to DDR SDRAM.
+ *
+ * r0, r2 used locally
+ *
+ */
+ .align 4
+ .section ".text", "ax"
+ENTRY(ux500_clean_l2_cache_all)
+
+ ldr r0, =IO_ADDRESS(U8500_L2CC_BASE)
+
+ ldr r1, =0xff @ TODO: Ok to assume 8-way cache
+ @ on Ux500?
+ str r1, [r0, #L2X0_CLEAN_WAY]
+ L2busywaitLoopClean:
+ ldr r1, [r0, #L2X0_CLEAN_WAY]
+ cmp r1, #0 @ All bits in L2X0_CLEAN_WAY
+ @ will be zero once clean is
+ @ finished
+ bne L2busywaitLoopClean
+
+ ldr r1, =0x0
+ str r1, [r0, #L2X0_CACHE_SYNC]
+ @ l2x0 C code busy-wait here to
+ @ ensure no background op is
+ @ running.
+ @ In our case we have already
+ @ checked this after the cache
+ @ clean and CACHE_SYNC is atomic
+ @ according to refman
+ mov pc, lr
+
+
+/*
+ * Last saves and WFI
+ *
+ * r0 = address to backup_sram_storage base adress
+ * r1 = indicate whether L1 and 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, r2
+ @ will be destroyed by
+ @ v7_clean_l1_cache_all
+ dsb
+ cmp r4, #0
+
+ blne context_clean_l1_cache_all @ Commit all dirty data in L1
+ @ cache to L2 without
+ @ invalidating
+ dsb
+ cmp r4, #0
+
+ blne ux500_clean_l2_cache_all @ If r2 != FALSE then clean all
+ @ dirty data in L2 cache, no
+ @ invalidate
+
+ 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-db8500.c b/arch/arm/mach-ux500/pm/cpufreq-db8500.c
new file mode 100644
index 00000000000..c5f16a373ce
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/cpufreq-db8500.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ */
+
+#include <linux/kernel.h>
+#include <linux/cpufreq.h>
+
+#include <mach/prcmu-fw-api.h>
+
+#include "cpufreq.h"
+
+static struct cpufreq_frequency_table freq_table[] = {
+ [0] = {
+ .index = 0,
+ .frequency = 300000,
+ },
+ [1] = {
+ .index = 1,
+ .frequency = 600000,
+ },
+ [2] = {
+ /* Used for MAX_OPP, if available */
+ .index = 2,
+ .frequency = CPUFREQ_TABLE_END,
+ },
+ [3] = {
+ .index = 3,
+ .frequency = CPUFREQ_TABLE_END,
+ },
+};
+
+static enum arm_opp idx2opp[] = {
+ ARM_50_OPP,
+ ARM_100_OPP,
+ ARM_MAX_OPP
+};
+
+static int __init u8500_cpufreq_register(void)
+{
+ BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
+
+ if (cpu_is_u8500v2() && !prcmu_is_u8400()) {
+ freq_table[0].frequency = 400000;
+ freq_table[1].frequency = 800000;
+ if (prcmu_has_arm_maxopp())
+ freq_table[2].frequency = 1000000;
+ }
+
+ return ux500_cpufreq_register(freq_table, idx2opp);
+}
+device_initcall(u8500_cpufreq_register);
diff --git a/arch/arm/mach-ux500/pm/cpufreq.c b/arch/arm/mach-ux500/pm/cpufreq.c
new file mode 100644
index 00000000000..1f5999e8271
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/cpufreq.c
@@ -0,0 +1,141 @@
+/*
+ * 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-fw-api.h>
+#include <mach/prcmu-regs.h>
+
+static struct cpufreq_frequency_table *freq_table;
+static enum arm_opp *idx2opp;
+
+static struct freq_attr *u8500_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static int u8500_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("u8500-cpufreq: Failed to set OPP level\n");
+ return -EINVAL;
+ }
+
+ /* post change notification */
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return 0;
+}
+
+static unsigned int u8500_cpufreq_getspeed(unsigned int cpu)
+{
+ int i;
+ /* request the prcm to get the current ARM opp */
+ for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++)
+ ;
+ return freq_table[i].frequency;
+}
+
+static int __cpuinit u8500_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("u8500-cpufreq : Failed to read policy table\n");
+ return res;
+ }
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = u8500_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 u8500_cpufreq_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = u8500_cpufreq_verify_speed,
+ .target = u8500_cpufreq_target,
+ .get = u8500_cpufreq_getspeed,
+ .init = u8500_cpufreq_init,
+ .name = "U8500",
+ .attr = u8500_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 u8500 started\n");
+ return cpufreq_register_driver(&u8500_cpufreq_driver);
+}
diff --git a/arch/arm/mach-ux500/pm/cpufreq.h b/arch/arm/mach-ux500/pm/cpufreq.h
new file mode 100644
index 00000000000..dc8744078f5
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/cpufreq.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ */
+#ifndef __UX500_PM_CPUFREQ_H
+#define __UX500_PM_CPUFREQ_H
+
+extern int ux500_cpufreq_register(struct cpufreq_frequency_table *freq_table,
+ enum arm_opp *idx2opp);
+
+#endif
diff --git a/arch/arm/mach-ux500/pm/cpuidle.c b/arch/arm/mach-ux500/pm/cpuidle.c
new file mode 100644
index 00000000000..97ac7bd2fff
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/cpuidle.c
@@ -0,0 +1,732 @@
+/*
+ * 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 <plat/gpio.h>
+
+#include <mach/prcmu-fw-api.h>
+
+#include "cpuidle.h"
+#include "cpuidle_dbg.h"
+#include "context.h"
+#include "pm.h"
+#include "../regulator-u8500.h"
+
+#define DEEP_SLEEP_WAKE_UP_LATENCY 8500
+#define SLEEP_WAKE_UP_LATENCY 800
+#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,
+ .ARM_PLL = ARM_PLL_ON,
+ .UL_PLL = UL_PLL_ON,
+ .ESRAM = ESRAM_RET,
+ .pwrst = NO_TRANSITION,
+ .flags = CPUIDLE_FLAG_POLL,
+ .state = CI_RUNNING,
+ .desc = "Running ",
+ },
+ {
+ .enter_latency = 0,
+ .exit_latency = 0,
+ .threshold = 0,
+ .power_usage = 10,
+ .APE = APE_ON,
+ .ARM = ARM_ON,
+ .ARM_PLL = ARM_PLL_ON,
+ .UL_PLL = UL_PLL_ON,
+ .ESRAM = ESRAM_RET,
+ .pwrst = NO_TRANSITION,
+ .flags = CPUIDLE_FLAG_SHALLOW | CPUIDLE_FLAG_TIME_VALID,
+ .state = CI_WFI,
+ .desc = "Wait for interrupt ",
+ },
+ {
+ .enter_latency = 40,
+ .exit_latency = 50,
+ .threshold = 150,
+ .power_usage = 5,
+ .APE = APE_ON,
+ .ARM = ARM_RET,
+ .ARM_PLL = ARM_PLL_ON,
+ .UL_PLL = UL_PLL_ON,
+ .ESRAM = ESRAM_RET,
+ .pwrst = PRCMU_AP_IDLE,
+ .flags = CPUIDLE_FLAG_SHALLOW | CPUIDLE_FLAG_TIME_VALID,
+ .state = CI_IDLE,
+ .desc = "ApIdle ",
+ },
+ {
+ .enter_latency = 45,
+ .exit_latency = 50,
+ .threshold = 160,
+ .power_usage = 4,
+ .APE = APE_ON,
+ .ARM = ARM_RET,
+ .ARM_PLL = ARM_PLL_OFF,
+ .UL_PLL = UL_PLL_ON,
+ .ESRAM = ESRAM_RET,
+ .pwrst = PRCMU_AP_IDLE,
+ .flags = CPUIDLE_FLAG_SHALLOW | CPUIDLE_FLAG_TIME_VALID,
+ .state = CI_IDLE,
+ .desc = "ApIdle, ARM PLL off ",
+ },
+ {
+ .enter_latency = 120,
+ .exit_latency = SLEEP_WAKE_UP_LATENCY,
+ /*
+ * Note: Sleep time must be longer than 120 us or else
+ * there might be issues with the RTC-RTT block.
+ */
+ .threshold = SLEEP_WAKE_UP_LATENCY + 120 + 50,
+ .power_usage = 3,
+ .APE = APE_OFF,
+ .ARM = ARM_RET,
+ .ARM_PLL = ARM_PLL_OFF,
+ .UL_PLL = UL_PLL_ON,
+ .ESRAM = ESRAM_RET,
+ .pwrst = PRCMU_AP_SLEEP,
+ .flags = CPUIDLE_FLAG_BALANCED | CPUIDLE_FLAG_TIME_VALID,
+ .state = CI_SLEEP,
+ .desc = "ApSleep ",
+ },
+ {
+ .enter_latency = 150,
+ .exit_latency = (SLEEP_WAKE_UP_LATENCY +
+ UL_PLL_START_UP_LATENCY),
+ .threshold = (2 * (SLEEP_WAKE_UP_LATENCY +
+ UL_PLL_START_UP_LATENCY + 50)),
+ .power_usage = 2,
+ .APE = APE_OFF,
+ .ARM = ARM_RET,
+ .ARM_PLL = ARM_PLL_OFF,
+ .UL_PLL = UL_PLL_OFF,
+ .ESRAM = ESRAM_RET,
+ .pwrst = PRCMU_AP_SLEEP,
+ .flags = CPUIDLE_FLAG_BALANCED | CPUIDLE_FLAG_TIME_VALID,
+ .state = CI_SLEEP,
+ .desc = "ApSleep, UL PLL off ",
+ },
+#ifdef ENABLE_AP_DEEP_IDLE
+ {
+ .enter_latency = 160,
+ .exit_latency = DEEP_SLEEP_WAKE_UP_LATENCY,
+ .threshold = DEEP_SLEEP_WAKE_UP_LATENCY + 160 + 50,
+ .power_usage = 2,
+ .APE = APE_ON,
+ .ARM = ARM_OFF,
+ .ARM_PLL = ARM_PLL_OFF,
+ .UL_PLL = UL_PLL_ON,
+ .ESRAM = ESRAM_RET,
+ .pwrst = PRCMU_AP_DEEP_IDLE,
+ .flags = CPUIDLE_FLAG_DEEP | CPUIDLE_FLAG_TIME_VALID,
+ .state = CI_DEEP_IDLE,
+ .desc = "ApDeepIdle, UL PLL off ",
+ },
+#endif
+ {
+ .enter_latency = 200,
+ .exit_latency = DEEP_SLEEP_WAKE_UP_LATENCY,
+ .threshold = DEEP_SLEEP_WAKE_UP_LATENCY + 200 + 50,
+ .power_usage = 1,
+ .APE = APE_OFF,
+ .ARM = ARM_OFF,
+ .ARM_PLL = ARM_PLL_OFF,
+ .UL_PLL = UL_PLL_OFF,
+ .ESRAM = ESRAM_RET,
+ .pwrst = PRCMU_AP_DEEP_SLEEP,
+ .flags = CPUIDLE_FLAG_DEEP | 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;
+};
+
+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 */
+
+extern struct clock_event_device u8500_rtt_clkevt;
+extern struct clock_event_device u8500_mtu_clkevt;
+
+static atomic_t idle_cpus_counter = ATOMIC_INIT(0);
+static ktime_t time_zero;
+
+struct cstate *ux500_ci_get_cstates(int *len)
+{
+ if (len != NULL)
+ (*len) = ARRAY_SIZE(cstates);
+ return cstates;
+}
+
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpuidle & hotplug - plug or unplug a cpu in idle sequence
+ */
+void ux500_cpuidle_plug(int cpu)
+{
+ atomic_dec(&idle_cpus_counter);
+ wmb();
+}
+void ux500_cpuidle_unplug(int cpu)
+{
+ atomic_inc(&idle_cpus_counter);
+ wmb();
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
+ * pm_idle and update to new pm_idle value. Required while changing pm_idle
+ * handler on SMP systems.
+ *
+ * Caller must have changed pm_idle to the new value before the call. Old
+ * pm_idle value will not be used by any CPU after the return of this function.
+ */
+void cpu_idle_wait(void)
+{
+ smp_mb();
+ /* kick all the CPUs so that they exit out of pm_idle */
+ smp_call_function(do_nothing, NULL, 1);
+}
+
+static void restore_sequence(struct cpu_state *state,
+ bool always_on_timer_migrated)
+{
+ unsigned long iflags;
+ int this_cpu = smp_processor_id();
+
+ spin_lock_irqsave(&cpuidle_lock, iflags);
+
+ smp_rmb();
+ if (restore_arm) {
+
+ restore_arm = false;
+ smp_wmb();
+
+ context_varm_restore_core();
+ /* Restore gic settings */
+ context_varm_restore_common();
+ }
+
+ smp_rmb();
+ if (restore_ape) {
+ /* Wake in 1 us */
+ ktime_t time_next = ktime_set(0, 1000);
+
+ 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();
+
+ clockevents_set_mode(&u8500_rtt_clkevt,
+ CLOCK_EVT_MODE_SHUTDOWN);
+ /*
+ * TODO: We might have woken on other interrupt.
+ * Reprogram MTU to wake at correct time.
+ */
+
+ /* Make sure have an MTU interrupt waiting for us */
+ clockevents_program_event(&u8500_mtu_clkevt,
+ time_next,
+ time_zero);
+ }
+
+ /*
+ * TODO: Figure out why the second CPU does not get scheduled
+ * when it should be the first one out of ApSleep.
+ * (First cpu gets all shared interrupts.)
+ */
+
+ if (this_cpu == 0) {
+ int cpu;
+ for_each_online_cpu(cpu) {
+ /* TODO: Only kick the CPU that was supposed to wake */
+ if (cpu != this_cpu)
+ /* Send an unused IPI interrupt (2) */
+ gic_raise_softirq(cpumask_of(cpu), 2);
+ }
+ }
+
+ spin_unlock_irqrestore(&cpuidle_lock, iflags);
+
+ smp_rmb();
+ if (always_on_timer_migrated) {
+ /* Use the ARM local timer for this cpu */
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT,
+ &this_cpu);
+ }
+}
+
+/**
+ * get_remaining_sleep_time() - returns remaining sleep time in
+ * microseconds (us)
+ */
+static int get_remaining_sleep_time(void)
+{
+ ktime_t now;
+ int cpu;
+ unsigned long iflags;
+ int t;
+ int remaining_sleep_time = INT_MAX;
+
+ now = ktime_get();
+
+ /* Check next schedule to expire considering both cpus */
+
+ spin_lock_irqsave(&cpuidle_lock, iflags);
+ for_each_online_cpu(cpu) {
+ t = ktime_to_us(ktime_sub(per_cpu(cpu_state,
+ cpu)->sched_wake_up,
+ now));
+ if ((t < remaining_sleep_time) && (t > 0))
+ remaining_sleep_time = t;
+ }
+ spin_unlock_irqrestore(&cpuidle_lock, iflags);
+
+ return remaining_sleep_time;
+}
+
+static int determine_sleep_state(void)
+{
+ int i;
+ int sleep_time;
+ int cpu;
+ int max_depth;
+ bool power_state_req;
+
+ /* If first cpu to sleep, go to most shallow sleep state */
+ if (atomic_read(&idle_cpus_counter) < num_online_cpus())
+ 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 (atomic_read(&idle_cpus_counter) < num_online_cpus())
+ return CI_WFI;
+ }
+
+ power_state_req = power_state_active_is_enabled() ||
+ prcmu_is_ac_wake_requested();
+
+ sleep_time = get_remaining_sleep_time();
+
+ /*
+ * 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;
+ }
+
+ return max(CI_WFI, i);
+
+}
+
+static void enter_sleep_shallow(struct cpu_state *state, ktime_t t1)
+{
+ int this_cpu = smp_processor_id();
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &this_cpu);
+
+ switch (cstates[state->gov_cstate].ARM) {
+ case ARM_OFF:
+ context_varm_save_core();
+ context_save_cpu_registers();
+ /* fall through */
+ case ARM_RET:
+ ux500_ci_dbg_log(CI_WFI, t1);
+ context_save_to_sram_and_wfi(false);
+ if (cstates[state->gov_cstate].ARM == ARM_OFF)
+ context_restore_cpu_registers();
+ break;
+ case ARM_ON:
+ ux500_ci_dbg_log(CI_WFI, t1);
+ __asm__ __volatile__
+ ("dsb\n\t" "wfi\n\t" : : : "memory");
+ break;
+ default:
+ break;
+ }
+}
+
+static int enter_sleep(struct cpuidle_device *dev,
+ struct cpuidle_state *ci_state)
+{
+ ktime_t t1, t2, t3;
+ ktime_t sleep_time;
+ s64 diff;
+ int ret;
+ int target;
+ struct cpu_state *state;
+ unsigned long iflags;
+ u32 divps_rate;
+ bool slept_well = false;
+ bool always_on_timer_migrated = false;
+ int this_cpu = smp_processor_id();
+
+ local_irq_disable();
+
+ t1 = ktime_get(); /* Time now */
+
+ state = per_cpu(cpu_state, smp_processor_id());
+
+ /* Retrive the cstate that the governor recommends for this CPU */
+ state->gov_cstate = (int) cpuidle_get_statedata(ci_state);
+
+ /* Save scheduled wake up for this cpu */
+ spin_lock_irqsave(&cpuidle_lock, iflags);
+ state->sched_wake_up = ktime_add(t1, tick_nohz_get_sleep_length());
+ spin_unlock_irqrestore(&cpuidle_lock, iflags);
+
+ atomic_inc(&idle_cpus_counter);
+
+ /*
+ * Determine sleep state considering both CPUs and
+ * shared resources like e.g. VAPE
+ */
+ target = determine_sleep_state();
+ if (target < 0) {
+ /* "target" will be last_state in the cpuidle framework */
+ goto exit_fast;
+ }
+
+ if (cstates[target].ARM == ARM_ON) {
+ /* Handle first cpu to enter sleep state */
+ always_on_timer_migrated = true;
+ enter_sleep_shallow(state, t1);
+ t3 = ktime_get();
+ slept_well = true;
+ goto exit;
+ }
+
+ /* Decouple GIC from the interrupt bus */
+ ux500_pm_gic_decouple();
+
+ if (!ux500_pm_other_cpu_wfi())
+ /* Other CPU was not in WFI => abort */
+ goto exit;
+
+ clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &this_cpu);
+
+ always_on_timer_migrated = true;
+
+ /*
+ * Check if we have a pending interrupt or if sleep
+ * state has changed after GIC has been frozen
+ */
+ if (ux500_pm_gic_pending_interrupt())
+ goto exit;
+
+ if (target != determine_sleep_state())
+ /* Sleep state has changed => abort */
+ goto exit;
+
+ /* Copy GIC interrupt settings to PRCMU interrupt settings */
+ ux500_pm_prcmu_copy_gic_settings();
+
+ /* Clean the cache before slowing down cpu frequency */
+ if (cstates[target].ARM == ARM_OFF)
+ context_clean_l1_cache_all();
+
+ divps_rate = ux500_pm_arm_on_ext_clk(cstates[target].ARM_PLL);
+
+ if (ux500_pm_prcmu_pending_interrupt()) {
+ /* An interrupt found => abort */
+ ux500_pm_arm_on_arm_pll(divps_rate);
+ goto exit;
+ }
+
+ /* No PRCMU interrupt was pending => continue the sleeping stages */
+
+ if (cstates[target].APE == APE_OFF) {
+ /* We are going to sleep or deep sleep => prepare for it */
+
+ /* Program the only timer that is available when APE is off */
+ clockevents_set_mode(&u8500_rtt_clkevt,
+ CLOCK_EVT_MODE_ONESHOT);
+
+ sleep_time = ktime_set(0, get_remaining_sleep_time() * 1000);
+
+ if (cstates[target].UL_PLL == UL_PLL_OFF) {
+ ktime_t ulpll_sleep = ktime_set(0,
+ UL_PLL_START_UP_LATENCY * 1000);
+ /* Compensate for ULPLL start up time */
+ sleep_time = ktime_sub(sleep_time, ulpll_sleep);
+
+ /*
+ * Not checking for negative sleep time since
+ * determine_sleep_state has already checked that
+ * there is enough time.
+ */
+ }
+
+ clockevents_program_event(&u8500_rtt_clkevt,
+ sleep_time,
+ time_zero);
+
+ context_vape_save();
+
+ ux500_ci_dbg_console_handle_ape_suspend();
+ ux500_pm_prcmu_set_ioforce(true);
+
+ spin_lock_irqsave(&cpuidle_lock, iflags);
+ restore_ape = true;
+ spin_unlock_irqrestore(&cpuidle_lock, iflags);
+ }
+
+ if (cstates[target].ARM == ARM_OFF) {
+ /* Save gic settings */
+ context_varm_save_common();
+
+ context_varm_save_core();
+
+ spin_lock_irqsave(&cpuidle_lock, iflags);
+ restore_arm = true;
+ spin_unlock_irqrestore(&cpuidle_lock, iflags);
+ context_save_cpu_registers();
+ }
+
+ /* TODO: To use desc as debug print might be a bad idea */
+ ux500_ci_dbg_msg(cstates[target].desc);
+
+ /*
+ * 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.
+ */
+ if (cstates[target].ARM == ARM_OFF)
+ context_clean_l1_cache_all();
+
+ ux500_ci_dbg_log(target, t1);
+
+ prcmu_set_power_state(cstates[target].pwrst,
+ cstates[target].UL_PLL,
+ /* Is actually the AP PLL */
+ cstates[target].UL_PLL);
+ /*
+ * 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
+ */
+
+ context_save_to_sram_and_wfi(cstates[target].ARM == ARM_OFF);
+
+ t3 = ktime_get();
+
+ /* The PRCMU restores ARM PLL and recouples the GIC */
+ if (cstates[target].ARM == ARM_OFF)
+ context_restore_cpu_registers();
+
+ slept_well = true;
+exit:
+ if (!slept_well)
+ /* Recouple GIC with the interrupt bus */
+ ux500_pm_gic_recouple();
+
+ restore_sequence(state, always_on_timer_migrated);
+
+exit_fast:
+
+ if (target < 0)
+ target = CI_RUNNING;
+
+ spin_lock_irqsave(&cpuidle_lock, iflags);
+ /* Remove wake up time i.e. set wake up far ahead */
+ state->sched_wake_up = ktime_add_us(state->sched_wake_up,
+ 1000000000); /* 16 minutes ahead */
+ smp_wmb();
+ spin_unlock_irqrestore(&cpuidle_lock, iflags);
+
+ atomic_dec(&idle_cpus_counter);
+
+ /*
+ * 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]);
+
+ t2 = ktime_get();
+ diff = ktime_to_us(ktime_sub(t2, t1));
+ if (diff > INT_MAX)
+ diff = INT_MAX;
+
+ ret = (int)diff;
+
+ ux500_ci_dbg_console_check_uart();
+ if (slept_well)
+ ux500_ci_dbg_wake_leave(target, t3);
+
+ ux500_ci_dbg_log(CI_RUNNING, t2);
+
+ 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;
+
+ /* Zero time used on a few places */
+ time_zero = ktime_set(0, 0);
+
+ /* 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);
+}
+
+module_init(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
new file mode 100644
index 00000000000..7baaf99d855
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/cpuidle.h
@@ -0,0 +1,87 @@
+/*
+ * 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>
+
+#include <mach/prcmu-fw-defs_v1.h>
+
+enum ARM {
+ ARM_OFF,
+ ARM_RET,
+ ARM_ON
+};
+
+enum APE {
+ APE_OFF,
+ APE_ON
+};
+
+enum ARM_PLL {
+ ARM_PLL_OFF = 0,
+ ARM_PLL_ON = 1
+};
+
+enum UL_PLL {
+ UL_PLL_OFF,
+ UL_PLL_ON
+};
+
+enum ESRAM {
+ ESRAM_OFF,
+ ESRAM_RET
+};
+
+enum ci_pwrst {
+ CI_RUNNING = 0,
+ CI_WFI = 1,
+ CI_IDLE,
+ CI_SLEEP,
+ CI_DEEP_IDLE,
+ CI_DEEP_SLEEP,
+};
+
+struct cstate {
+ /* Required state of different hardwares */
+ enum ARM ARM;
+ enum APE APE;
+ enum ARM_PLL ARM_PLL;
+ 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;
+ enum ap_pwrst_trans pwrst;
+
+ /* Only used for debugging purpose */
+ enum ci_pwrst state;
+ char desc[CPUIDLE_DESC_LEN];
+};
+
+struct cstate *ux500_ci_get_cstates(int *len);
+
+#ifdef CONFIG_U8500_CPUIDLE
+void ux500_cpuidle_plug(int cpu);
+void ux500_cpuidle_unplug(int cpu);
+#else
+static inline void ux500_cpuidle_plug(int cpu)
+{
+}
+
+static inline void ux500_cpuidle_unplug(int cpu)
+{
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-ux500/pm/cpuidle_dbg.c b/arch/arm/mach-ux500/pm/cpuidle_dbg.c
new file mode 100644
index 00000000000..c451696fc6c
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/cpuidle_dbg.c
@@ -0,0 +1,699 @@
+/*
+ * 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/slab.h>
+#include <linux/sched.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/amba/serial.h>
+
+#include <plat/gpio.h>
+#include <asm/hardware/gic.h>
+
+#include "cpuidle.h"
+#include "pm.h"
+
+#define DBG_BUF_SIZE 5000
+#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 */
+
+struct state_history_state {
+ u32 counter;
+ ktime_t time;
+
+ u32 enter_latency_count;
+ ktime_t enter_latency_sum;
+ ktime_t enter_latency_min;
+ ktime_t enter_latency_max;
+
+ u32 exit_latency_count;
+ ktime_t exit_latency_sum;
+ ktime_t exit_latency_min;
+ ktime_t exit_latency_max;
+};
+
+struct state_history {
+ ktime_t start;
+ u32 state;
+ 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 struct cstate *cstates;
+static int cstates_len;
+static DEFINE_SPINLOCK(dbg_lock);
+
+#ifdef U8500_CPUIDLE_EXTRA_DBG
+void ux500_ci_dbg_msg(char *dbg_string)
+{
+ static char dbg_buf[DBG_BUF_SIZE];
+ static int index; /* protected by dbg_lock */
+ int str_len;
+ int smp_no_len;
+ int head_len;
+ unsigned long flags;
+ static const char * const smp_no_str = "\n %d:";
+ static const char * const head_str = ":HEAD->";
+
+ spin_lock_irqsave(&dbg_lock, flags);
+
+ str_len = strlen(dbg_string);
+ smp_no_len = strlen(smp_no_str);
+ head_len = strlen(head_str);
+
+ if (index > head_len)
+ /* Remove last head printing */
+ index -= head_len;
+
+ if ((index + str_len + smp_no_len + head_len) > DBG_BUF_SIZE)
+ index = 0; /* Non perfect wrapping... */
+
+ sprintf(&dbg_buf[index], smp_no_str, smp_processor_id());
+ index += smp_no_len;
+
+ strcpy(&dbg_buf[index], dbg_string);
+ index += str_len;
+
+ strcpy(&dbg_buf[index], head_str);
+ index += head_len;
+
+ spin_unlock_irqrestore(&dbg_lock, flags);
+}
+#endif
+
+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;
+
+ set_irq_wake(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), 1);
+ 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);
+ }
+ 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(u32 *count,
+ ktime_t d,
+ ktime_t *sum,
+ ktime_t *min,
+ ktime_t *max,
+ bool lock)
+{
+ unsigned long flags;
+
+ if (lock)
+ spin_lock_irqsave(&dbg_lock, flags);
+
+ (*count)++;
+ (*sum) = ktime_add((*sum), d);
+
+ if (ktime_to_us(d) > ktime_to_us(*max))
+ (*max) = d;
+
+ if (ktime_to_us(d) < ktime_to_us((*min)))
+ (*min) = d;
+
+ if (lock)
+ spin_unlock_irqrestore(&dbg_lock, flags);
+}
+
+void ux500_ci_dbg_wake_leave(enum ci_pwrst pstate, ktime_t t)
+{
+ struct state_history *sh;
+
+ if (pstate < CI_IDLE || !measure_latency)
+ return;
+
+ sh = per_cpu(state_history, smp_processor_id());
+
+ store_latency(&sh->states[pstate].exit_latency_count,
+ ktime_sub(ktime_get(), t),
+ &sh->states[pstate].exit_latency_sum,
+ &sh->states[pstate].exit_latency_min,
+ &sh->states[pstate].exit_latency_max,
+ true);
+}
+
+static void state_record_time(struct state_history *sh, enum ci_pwrst pstate,
+ 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 = pstate;
+
+ if (latency && pstate != CI_RUNNING && measure_latency)
+ store_latency(&sh->states[sh->state].enter_latency_count,
+ ktime_sub(now, start),
+ &sh->states[sh->state].enter_latency_sum,
+ &sh->states[sh->state].enter_latency_min,
+ &sh->states[sh->state].enter_latency_max,
+ false);
+
+ sh->states[sh->state].counter++;
+}
+
+void ux500_ci_dbg_log(enum ci_pwrst pstate, 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);
+
+ /*
+ * Check if current state is just a repeat of
+ * the state we're already in, then just quit.
+ */
+ if (pstate == sh->state)
+ goto done;
+
+ state_record_time(sh, pstate, 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 (pstate == CI_RUNNING && sh_other->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, pstate, 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;
+ 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].time = ktime_set(0, 0);
+
+ sh->states[i].enter_latency_count = 0;
+ sh->states[i].enter_latency_min = ktime_set(0,
+ 10000000);
+ sh->states[i].enter_latency_max = ktime_set(0, 0);
+ sh->states[i].enter_latency_sum = ktime_set(0, 0);
+
+ sh->states[i].exit_latency_count = 0;
+ sh->states[i].exit_latency_min = ktime_set(0,
+ 10000000);
+ sh->states[i].exit_latency_max = ktime_set(0, 0);
+ sh->states[i].exit_latency_sum = ktime_set(0, 0);
+ }
+
+ for (i = 0; i <= cstates_len; i++)
+ sh->start = ktime_get();
+ sh->state = cstates_len; /* CI_RUNNING */
+ }
+ spin_unlock_irqrestore(&dbg_lock, flags);
+}
+
+static ssize_t set_deepest_state(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char buf[32];
+ ssize_t buf_size;
+ long unsigned int i;
+
+ /* Get userspace string and assure termination */
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if (strict_strtoul(buf, 0, &i) != 0)
+ return buf_size;
+
+ if (i > cstates_len - 1)
+ i = cstates_len - 1;
+
+ if (i == 0)
+ i = 1;
+
+ deepest_allowed_state = i;
+
+ pr_debug("cpuidle: changed deepest allowed sleep state to %d.\n",
+ deepest_allowed_state);
+
+ return buf_size;
+}
+
+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)
+{
+
+ pr_info("\nreset\n");
+ state_history_reset();
+ return count;
+}
+
+static int stats_print(struct seq_file *s, void *p)
+{
+ int cpu;
+ int i;
+ unsigned long flags;
+ struct state_history *sh;
+ ktime_t total;
+ s64 t_us;
+ s64 perc;
+ s64 total_us;
+ ktime_t init_time, zero_time;
+
+ init_time = ktime_set(0, 10000000);
+ zero_time = ktime_set(0, 0);
+
+ for_each_possible_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);
+
+ total_us = ktime_to_us(total);
+ do_div(total_us, 100);
+
+ for (i = 0; i < cstates_len; i++) {
+ s64 avg_enter = 0;
+ s64 avg_exit = 0;
+ if (measure_latency) {
+ avg_enter = ktime_to_us(sh->states[i].enter_latency_sum);
+ avg_exit = ktime_to_us(sh->states[i].exit_latency_sum);
+ }
+
+ t_us = ktime_to_us(sh->states[i].time);
+ perc = ktime_to_us(sh->states[i].time);
+ do_div(t_us, 1000); /* to ms */
+ if (total_us)
+ do_div(perc, total_us);
+ if (sh->states[i].enter_latency_count && measure_latency)
+ do_div(avg_enter, sh->states[i].enter_latency_count);
+
+ if (sh->states[i].exit_latency_count && measure_latency)
+ do_div(avg_exit, sh->states[i].exit_latency_count);
+
+ seq_printf(s, "\n%d - %s: # %u in %d ms %d%%",
+ i, cstates[i].desc,
+ sh->states[i].counter,
+ (u32) t_us, (u32)perc);
+ if (i == CI_RUNNING)
+ continue;
+
+ if (!ktime_equal(sh->states[i].enter_latency_min,
+ init_time) && measure_latency) {
+ if (ktime_equal(sh->states[i].enter_latency_min,
+ zero_time))
+ seq_printf(s, " (enter: min < 30");
+ else
+ seq_printf(s, " (enter: min %lld",
+ ktime_to_us(sh->states[i].enter_latency_min));
+
+ seq_printf(s, " avg %lld max %lld us)",
+ avg_enter,
+ ktime_to_us(sh->states[i].enter_latency_max));
+ }
+
+ if (!ktime_equal(sh->states[i].exit_latency_min,
+ init_time) && measure_latency) {
+
+ if (ktime_equal(sh->states[i].exit_latency_min,
+ zero_time))
+ seq_printf(s, " (exit: min < 30");
+ else
+ seq_printf(s, " (exit: min %lld",
+ ktime_to_us(sh->states[i].exit_latency_min));
+
+ seq_printf(s, " avg %lld max %lld us)",
+ avg_exit,
+ ktime_to_us(sh->states[i].exit_latency_max));
+ }
+ }
+ 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 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 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 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 struct dentry *cpuidle_dir;
+
+static void 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("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("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);
+}
+
+void ux500_ci_dbg_init(void)
+{
+ char clkname[10];
+ int cpu;
+
+ struct state_history *sh;
+
+ cstates = ux500_ci_get_cstates(&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 */
+ switch (CONFIG_UX500_DEBUG_UART) {
+ case 0:
+ uart_base = ioremap(U8500_UART0_BASE, SZ_4K);
+ break;
+ case 1:
+ uart_base = ioremap(U8500_UART1_BASE, SZ_4K);
+ break;
+ case 2:
+ uart_base = ioremap(U8500_UART2_BASE, SZ_4K);
+ break;
+ default:
+ uart_base = ioremap(U8500_UART2_BASE, SZ_4K);
+ break;
+ }
+
+ snprintf(clkname, sizeof(clkname), "uart%d", CONFIG_UX500_DEBUG_UART);
+ uart_clk = clk_get_sys(clkname, NULL);
+ BUG_ON(IS_ERR(uart_clk));
+
+ INIT_DELAYED_WORK(&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
new file mode 100644
index 00000000000..93df7528e6c
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/cpuidle_dbg.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * 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
+
+#ifdef CONFIG_U8500_CPUIDLE_DEBUG
+void ux500_ci_dbg_init(void);
+void ux500_ci_dbg_remove(void);
+
+void ux500_ci_dbg_log(enum ci_pwrst pstate, ktime_t enter_time);
+void ux500_ci_dbg_wake_leave(enum ci_pwrst pstate, ktime_t t);
+
+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);
+
+#ifdef U8500_CPUIDLE_EXTRA_DBG
+void ux500_ci_dbg_msg(char *dbg_string);
+#else
+static inline void ux500_ci_dbg_msg(char *dbg_string) { }
+#endif
+
+#else
+
+static inline void ux500_ci_dbg_init(void) { }
+static inline void ux500_ci_dbg_remove(void) { }
+
+static inline void ux500_ci_dbg_log(enum ci_pwrst pstate,
+ ktime_t enter_time) { }
+static inline void ux500_ci_dbg_wake_leave(enum ci_pwrst pstate, ktime_t t) { }
+
+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) { }
+static inline void ux500_ci_dbg_msg(char *dbg_string) { }
+
+#endif
+#endif
diff --git a/arch/arm/mach-ux500/pm/pm.c b/arch/arm/mach-ux500/pm/pm.c
new file mode 100644
index 00000000000..1db45c8c0ae
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/pm.c
@@ -0,0 +1,349 @@
+/*
+ * 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 <asm/hardware/gic.h>
+
+#include <mach/hardware.h>
+#include <mach/prcmu-regs.h>
+
+#define STABILIZATION_TIME 30 /* 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)];
+#ifdef ENABLE_ARM_FREQ_RAMP
+/*
+ * Ramp down the ARM frequency in order to reduce voltage
+ * overshoot/undershoot
+ */
+int ux500_pm_arm_on_ext_clk(bool leave_arm_pll_on)
+{
+ u32 val;
+ int divps_rate;
+
+ /*
+ * TODO: we should check that there is no ongoing
+ * OPP change because then our writings could collide with the PRCMU.
+ */
+
+ val = readl(PRCM_ARM_CHGCLKREQ);
+
+ if (val & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ)
+ return -EINVAL;
+
+ val = readl(PRCM_ARM_PLLDIVPS);
+
+ /*
+ * TODO: Investigate if ramp down should start
+ * from current frequency.
+ */
+ if (cpu_is_u8500v20_or_later()) {
+
+ /*
+ * Store the current rate value. Is needed if
+ * we need to restore the frequency
+ */
+ divps_rate = val & PRCM_ARM_PLLDIVPS_ARM_BRM_RATE;
+ val &= ~PRCM_ARM_PLLDIVPS_ARM_BRM_RATE;
+
+ /* Slow down the cpu's */
+ if (divps_rate > 11) {
+ writel(val | 11, PRCM_ARM_PLLDIVPS);
+ /* Wait for voltage to stabilize */
+ udelay(STABILIZATION_TIME);
+ }
+ if (divps_rate > 5) {
+ writel(val | 5, PRCM_ARM_PLLDIVPS);
+ /* Wait for voltage to stabilize */
+ udelay(STABILIZATION_TIME);
+ }
+ if (divps_rate > 2)
+ writel(val | 2, PRCM_ARM_PLLDIVPS);
+ } else {
+
+ divps_rate = val & PRCM_ARM_PLLDIVPS_MAX_MASK;
+ val &= ~PRCM_ARM_PLLDIVPS_MAX_MASK;
+
+ /* Slow down the cpu's */
+ if (divps_rate < 3) {
+ writel(val | 3, PRCM_ARM_PLLDIVPS);
+ /* Wait for voltage to stabilize */
+ udelay(STABILIZATION_TIME);
+ }
+ if (divps_rate < 7) {
+ writel(val | 7, PRCM_ARM_PLLDIVPS);
+ /* Wait for voltage to stabilize */
+ udelay(STABILIZATION_TIME);
+ }
+ if (divps_rate < 15)
+ writel(val | 15, PRCM_ARM_PLLDIVPS);
+ }
+
+ /* switch to external clock */
+ writel(readl(PRCM_ARM_CHGCLKREQ) |
+ PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ,
+ PRCM_ARM_CHGCLKREQ);
+
+ val = readl(PRCM_PLLARM_ENABLE);
+
+ if (leave_arm_pll_on)
+ /* Leave ARM PLL on */
+ writel(val & (~PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON),
+ PRCM_PLLARM_ENABLE);
+ else
+ /* Stop ARM PLL */
+ writel(val & (~PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE),
+ PRCM_PLLARM_ENABLE);
+ return divps_rate;
+}
+#else
+inline int ux500_pm_arm_on_ext_clk(bool leave_arm_pll_on)
+{
+ return 0;
+}
+#endif
+
+#ifdef ENABLE_ARM_FREQ_RAMP
+void ux500_pm_arm_on_arm_pll(int divps_rate)
+{
+ u32 pll_arm;
+ u32 clk_req;
+ u32 val;
+
+ if (divps_rate < 0)
+ return;
+
+ clk_req = readl(PRCM_ARM_CHGCLKREQ);
+
+ /* Return, if not running on external pll */
+ if (!(clk_req & PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ))
+ return;
+
+ pll_arm = readl(PRCM_PLLARM_ENABLE);
+
+ if (pll_arm & PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE) {
+ /* ARM PLL is still on, set "counton" bit */
+ writel(pll_arm | PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON,
+ PRCM_PLLARM_ENABLE);
+ } else {
+ /* ARM PLL was stopped => turn on */
+ writel(pll_arm | PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE,
+ PRCM_PLLARM_ENABLE);
+
+ /* Wait for PLL to lock */
+ while (!(readl(PRCM_PLLARM_LOCKP) &
+ PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3))
+ cpu_relax();
+ }
+
+ writel(clk_req & ~PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ,
+ PRCM_ARM_CHGCLKREQ);
+
+ val = readl(PRCM_ARM_PLLDIVPS);
+
+ if (cpu_is_u8500v20_or_later()) {
+ val &= ~PRCM_ARM_PLLDIVPS_ARM_BRM_RATE;
+
+ /* Ramp up the ARM PLL */
+ if (divps_rate >= 2) {
+ writel(val | 2, PRCM_ARM_PLLDIVPS);
+ /* Wait for voltage to stabilize */
+ udelay(STABILIZATION_TIME);
+ }
+ if (divps_rate >= 5) {
+ writel(val | 5, PRCM_ARM_PLLDIVPS);
+ /* Wait for voltage to stabilize */
+ udelay(STABILIZATION_TIME);
+ }
+ if (divps_rate >= 11)
+ writel(val | 11, PRCM_ARM_PLLDIVPS);
+ } else {
+ val &= ~PRCM_ARM_PLLDIVPS_MAX_MASK;
+ /* Ramp up the ARM PLL */
+ if (divps_rate <= 15) {
+ writel(val | 15, PRCM_ARM_PLLDIVPS);
+ /* Wait for voltage to stabilize */
+ udelay(STABILIZATION_TIME);
+ }
+ if (divps_rate <= 7) {
+ writel(val | 7, PRCM_ARM_PLLDIVPS);
+ /* Wait for voltage to stabilize */
+ udelay(STABILIZATION_TIME);
+ }
+ if (divps_rate <= 3)
+ writel(val | 3, PRCM_ARM_PLLDIVPS);
+ }
+}
+#else
+inline void ux500_pm_arm_on_arm_pll(int divps_rate)
+{
+}
+#endif
+
+/* 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 */
+}
+
+/* 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(__io_address(U8500_GIC_DIST_BASE) +
+ GIC_DIST_PENDING_SET + i * 4);
+ er = readl(__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(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;
+}
diff --git a/arch/arm/mach-ux500/pm/pm.h b/arch/arm/mach-ux500/pm/pm.h
new file mode 100644
index 00000000000..e8f67183682
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/pm.h
@@ -0,0 +1,110 @@
+/*
+ * 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
+ *
+ */
+
+#ifndef PM_COMMON_H
+#define PM_COMMON_H
+
+#ifdef CONFIG_PM
+/**
+ * ux500_pm_arm_on_ext_clk()
+ *
+ * @leave_arm_pll_on: True, if leave the ARM PLL on.
+ *
+ * returns divps_rate, used as input for ux500_pm_arm_on_arm_pll
+ * or -EINVAL if already running on external clock.
+ */
+int ux500_pm_arm_on_ext_clk(bool leave_arm_pll_on);
+
+/**
+ * ux500_pm_arm_on_arm_pll()
+ *
+ * @divps_rate: Rate provided by ux500_pm_arm_on_ext_clk
+ *
+ * Restores the previous arm pll settings.
+ */
+void ux500_pm_arm_on_arm_pll(int divps_rate);
+
+/**
+ * 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);
+
+#else
+u32 ux500_pm_gpio_read_wake_up_status(unsigned int bank_number)
+{
+ return 0;
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-ux500/pm/runtime.c b/arch/arm/mach-ux500/pm/runtime.c
new file mode 100644
index 00000000000..cb6801b04b1
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/runtime.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson> for ST-Ericsson
+ *
+ * Based on:
+ * Runtime PM support code for SuperH Mobile ARM
+ * Copyright (C) 2009-2010 Magnus Damm
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/clk.h>
+#include <plat/pincfg.h>
+#include <mach/regulator.h>
+
+#include "../pins.h"
+
+#ifdef CONFIG_PM_RUNTIME
+#define BIT_ONCE 0
+#define BIT_ACTIVE 1
+#define BIT_ENABLED 2
+
+struct pm_runtime_data {
+ unsigned long flags;
+ struct ux500_regulator *regulator;
+ struct ux500_pins *pins;
+};
+
+static void __devres_release(struct device *dev, void *res)
+{
+ struct pm_runtime_data *prd = res;
+
+ dev_dbg(dev, "__devres_release()\n");
+
+ if (test_bit(BIT_ENABLED, &prd->flags)) {
+ if (prd->pins)
+ ux500_pins_disable(prd->pins);
+ if (prd->regulator)
+ ux500_regulator_atomic_disable(prd->regulator);
+ }
+
+ if (test_bit(BIT_ACTIVE, &prd->flags)) {
+ if (prd->pins)
+ ux500_pins_put(prd->pins);
+ if (prd->regulator)
+ ux500_regulator_put(prd->regulator);
+ }
+}
+
+static struct pm_runtime_data *__to_prd(struct device *dev)
+{
+ return devres_find(dev, __devres_release, NULL, NULL);
+}
+
+static void platform_pm_runtime_init(struct device *dev,
+ struct pm_runtime_data *prd)
+{
+ if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags)) {
+ prd->pins = ux500_pins_get(dev_name(dev));
+
+ prd->regulator = ux500_regulator_get(dev);
+ if (IS_ERR(prd->regulator))
+ prd->regulator = NULL;
+
+ if (prd->pins || prd->regulator) {
+ dev_info(dev, "managed by runtime pm: %s%s\n",
+ prd->pins ? "pins " : "",
+ prd->regulator ? "regulator " : "");
+
+ set_bit(BIT_ACTIVE, &prd->flags);
+ }
+ }
+}
+
+static void platform_pm_runtime_bug(struct device *dev,
+ struct pm_runtime_data *prd)
+{
+ if (prd && !test_and_set_bit(BIT_ONCE, &prd->flags))
+ dev_err(dev, "runtime pm suspend before resume\n");
+}
+
+static int ux500_pd_runtime_suspend(struct device *dev)
+{
+ struct pm_runtime_data *prd = __to_prd(dev);
+
+ dev_vdbg(dev, "%s()\n", __func__);
+
+ platform_pm_runtime_bug(dev, prd);
+
+ if (prd && test_bit(BIT_ACTIVE, &prd->flags)) {
+ if (prd->pins)
+ ux500_pins_disable(prd->pins);
+
+ if (prd->regulator)
+ ux500_regulator_atomic_disable(prd->regulator);
+
+ clear_bit(BIT_ENABLED, &prd->flags);
+ }
+
+ return 0;
+}
+
+static int ux500_pd_runtime_resume(struct device *dev)
+{
+ struct pm_runtime_data *prd = __to_prd(dev);
+
+ dev_vdbg(dev, "%s()\n", __func__);
+
+ platform_pm_runtime_init(dev, prd);
+
+ if (prd && test_bit(BIT_ACTIVE, &prd->flags)) {
+ if (prd->pins)
+ ux500_pins_enable(prd->pins);
+
+ if (prd->regulator)
+ ux500_regulator_atomic_enable(prd->regulator);
+
+ set_bit(BIT_ENABLED, &prd->flags);
+ }
+
+ return 0;
+}
+
+static int ux500_pd_suspend_noirq(struct device *dev)
+{
+ struct pm_runtime_data *prd = __to_prd(dev);
+
+ dev_vdbg(dev, "%s()\n", __func__);
+
+ /* Only handle devices that use runtime pm */
+ if (!prd || !test_bit(BIT_ONCE, &prd->flags))
+ return 0;
+
+ /* Already is runtime suspended? Nothing to do. */
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ /*
+ * We get here only if the device was not runtime suspended for some
+ * reason. We still need to do the power save stuff when going into
+ * suspend, so force it here.
+ */
+ return ux500_pd_runtime_suspend(dev);
+}
+
+static int ux500_pd_resume_noirq(struct device *dev)
+{
+ struct pm_runtime_data *prd = __to_prd(dev);
+
+ dev_vdbg(dev, "%s()\n", __func__);
+
+ /* Only handle devices that use runtime pm */
+ if (!prd || !test_bit(BIT_ONCE, &prd->flags))
+ return 0;
+
+ /*
+ * Already was runtime suspended? No need to resume here, runtime
+ * resume will take care of it.
+ */
+ if (pm_runtime_suspended(dev))
+ return 0;
+
+ /*
+ * We get here only if the device was not runtime suspended,
+ * but we forced it down in suspend_noirq above. Bring it
+ * up since pm-runtime thinks it is not suspended.
+ */
+ return ux500_pd_runtime_resume(dev);
+}
+
+static int ux500_pd_bus_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct device *dev = data;
+ struct pm_runtime_data *prd;
+
+ dev_dbg(dev, "%s() %ld !\n", __func__, action);
+
+ if (action == BUS_NOTIFY_BIND_DRIVER) {
+ prd = devres_alloc(__devres_release, sizeof(*prd), GFP_KERNEL);
+ if (prd)
+ devres_add(dev, prd);
+ else
+ dev_err(dev, "unable to alloc memory for runtime pm\n");
+ }
+
+ return 0;
+}
+
+#else /* CONFIG_PM_RUNTIME */
+
+#define ux500_pd_suspend_noirq NULL
+#define ux500_pd_resume_noirq NULL
+#define ux500_pd_runtime_suspend NULL
+#define ux500_pd_runtime_resume NULL
+
+static int ux500_pd_bus_notify(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct ux500_regulator *regulator = NULL;
+ struct ux500_pins *pins = NULL;
+ struct device *dev = data;
+ const char *onoff = NULL;
+
+ dev_dbg(dev, "%s() %ld !\n", __func__, action);
+
+ switch (action) {
+ case BUS_NOTIFY_BIND_DRIVER:
+ pins = ux500_pins_get(dev_name(dev));
+ if (pins) {
+ ux500_pins_enable(pins);
+ ux500_pins_put(pins);
+ }
+
+ regulator = ux500_regulator_get(dev);
+ if (IS_ERR(regulator))
+ regulator = NULL;
+ else {
+ ux500_regulator_atomic_enable(regulator);
+ ux500_regulator_put(regulator);
+ }
+
+ onoff = "on";
+ break;
+ case BUS_NOTIFY_UNBOUND_DRIVER:
+ pins = ux500_pins_get(dev_name(dev));
+ if (pins) {
+ ux500_pins_disable(pins);
+ ux500_pins_put(pins);
+ }
+
+ regulator = ux500_regulator_get(dev);
+ if (IS_ERR(regulator))
+ regulator = NULL;
+ else {
+ ux500_regulator_atomic_disable(regulator);
+ ux500_regulator_put(regulator);
+ }
+
+ onoff = "off";
+ break;
+ }
+
+ if (pins || regulator) {
+ dev_info(dev, "runtime pm disabled, forced %s: %s%s\n",
+ onoff,
+ pins ? "pins " : "",
+ regulator ? "regulator " : "");
+ }
+
+ return 0;
+}
+
+#endif /* CONFIG_PM_RUNTIME */
+
+struct dev_power_domain ux500_dev_power_domain = {
+ .ops = {
+ .suspend_noirq = ux500_pd_suspend_noirq,
+ .resume_noirq = ux500_pd_resume_noirq,
+ .runtime_suspend = ux500_pd_runtime_suspend,
+ .runtime_resume = ux500_pd_runtime_resume,
+ },
+};
+
+static struct notifier_block ux500_pd_platform_notifier = {
+ .notifier_call = ux500_pd_bus_notify,
+};
+
+static struct notifier_block ux500_pd_amba_notifier = {
+ .notifier_call = ux500_pd_bus_notify,
+};
+
+static int __init ux500_pm_runtime_platform_init(void)
+{
+ bus_register_notifier(&platform_bus_type, &ux500_pd_platform_notifier);
+ return 0;
+}
+core_initcall(ux500_pm_runtime_platform_init);
+
+/*
+ * The amba bus itself gets registered in a core_initcall, so we can't use
+ * that.
+ */
+static int __init ux500_pm_runtime_amba_init(void)
+{
+ bus_register_notifier(&amba_bustype, &ux500_pd_amba_notifier);
+ return 0;
+}
+arch_initcall(ux500_pm_runtime_amba_init);
diff --git a/arch/arm/mach-ux500/pm/suspend.c b/arch/arm/mach-ux500/pm/suspend.c
new file mode 100644
index 00000000000..4ca62da3842
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/suspend.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Authors: Rickard Andersson <rickard.andersson@stericsson.com>,
+ * Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ *
+ */
+
+#include <linux/suspend.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/regulator/ab8500-debug.h>
+
+#include <mach/prcmu-fw-api.h>
+#include <mach/prcmu-regs.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;
+ u32 divps_rate;
+
+ 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();
+
+ /* TODO: decouple gic should look at status bit.*/
+ udelay(100);
+
+ divps_rate = ux500_pm_arm_on_ext_clk(false);
+
+ if (ux500_pm_gic_pending_interrupt()) {
+ pr_info("suspend/resume: pending interrupt\n");
+
+ ux500_pm_arm_on_arm_pll(divps_rate);
+ /* 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_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);
+ /* For debugging, if Sleep and DeepSleep disabled, do Idle */
+ prcmu_set_power_state(PRCMU_AP_IDLE, true, true);
+ }
+
+ dsb();
+ __asm__ __volatile__("wfi\n\t" : : : "memory");
+ 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)
+{
+ /*
+ * Below should be set to state OFF. Current workaround set state to
+ * RET since there is a problem with security saving data in esram
+ * which does not work during deep sleep.
+ * Once security is fixed below should be state OFF again to save 40uA.
+ */
+ (void)prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
+ ab8500_regulator_debug_force();
+
+ return 0;
+}
+
+static void ux500_suspend_wake(void)
+{
+ ab8500_regulator_debug_restore();
+ (void)prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
+}
+
+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_dbg_begin,
+};
+
+static __init int ux500_suspend_init(void)
+{
+ ux500_suspend_dbg_init();
+ 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
new file mode 100644
index 00000000000..fce77b5cf73
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/suspend_dbg.c
@@ -0,0 +1,199 @@
+/*
+ * 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>
+
+#define DEEP_SLEEP_OK 0xf6
+#define SLEEP_OK 0xf3
+
+#define PRCMU_STATUS_REGISTER_V1 0x8015fe08
+#define PRCMU_STATUS_REGISTER_V2 0x801b8e08
+
+static void __iomem *prcmu_status_reg;
+
+#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)
+{
+ set_irq_wake(GPIO_TO_IRQ(CONFIG_UX500_CONSOLE_UART_GPIO_PIN), 1);
+ 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)
+{
+ 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)
+{
+ u32 prcmu_status;
+
+ prcmu_status = readl(prcmu_status_reg) & 0xff;
+
+ 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;
+
+
+ if (cpu_is_u8500v20_or_later())
+ prcmu_status_reg = (void *)IO_ADDRESS(PRCMU_STATUS_REGISTER_V2);
+ else
+ prcmu_status_reg = (void *)IO_ADDRESS(PRCMU_STATUS_REGISTER_V1);
+
+ 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
new file mode 100644
index 00000000000..46cbe6e7014
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/suspend_dbg.h
@@ -0,0 +1,60 @@
+/*
+ * 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) { }
+
+#define ux500_suspend_dbg_begin NULL
+
+#endif
+
+#endif
diff --git a/arch/arm/mach-ux500/pm/usecase_gov.c b/arch/arm/mach-ux500/pm/usecase_gov.c
new file mode 100644
index 00000000000..eca26539e97
--- /dev/null
+++ b/arch/arm/mach-ux500/pm/usecase_gov.c
@@ -0,0 +1,590 @@
+/*
+ * 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>
+
+#define CPULOAD_MEAS_DELAY 3000 /* 3 secondes of delta */
+
+/* debug */
+static unsigned long debug;
+
+#define hp_printk \
+ if (debug) \
+ printk \
+
+/* 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;
+
+/* Use case management */
+#define MAX_USECASE 4
+#define NORMAL_UC 0
+#define AUTO_UC 1
+
+static unsigned long current_usecase = AUTO_UC;
+static unsigned long updated_usecase = -1;
+
+char *name_usecase[MAX_USECASE] = {
+ "normal",
+ "auto",
+ "Speech Call",
+ "Low power MP3",
+};
+
+struct usecase_config {
+ unsigned long max_freq;
+ unsigned long multiplier;
+ unsigned long online;
+};
+
+static struct usecase_config usecase_conf[MAX_USECASE] = {
+ { /* normal */
+ 1000000,
+ 1024,
+ 1
+ },
+ { /* auto */
+ 400000,
+ 0,
+ 0
+ },
+ { /* speech call */
+ 400000,
+ 0,
+ 0
+ },
+ { /* low power mp3 */
+ 400000,
+ 0,
+ 1
+ },
+};
+
+/* daemon */
+static unsigned long enable = 1;
+static unsigned long trig = 2;
+
+static struct delayed_work work_cpu_hotplug;
+static struct early_suspend cpuhotplug_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);
+
+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 void set_cpu_config(int mode)
+{
+ static int previous_mode = -1;
+
+ if (mode != previous_mode) {
+ previous_mode = mode;
+
+ if (!(usecase_conf[mode].online) && (num_online_cpus() > 1))
+ cpu_down(1);
+ else if ((usecase_conf[mode].online) && (num_online_cpus() < 2))
+ cpu_up(1);
+
+ cpufreq_update_freq(0, 0, usecase_conf[mode].max_freq);
+ cpuidle_set_multiplier(usecase_conf[mode].multiplier);
+ }
+}
+
+/*
+ * 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 start_cpu_hotplug_check(struct early_suspend *h)
+{
+ trig = 2;
+ init_cpu_load_trend();
+ schedule_delayed_work_on(0, &work_cpu_hotplug,
+ msecs_to_jiffies(CPULOAD_MEAS_DELAY));
+}
+
+/* Stop measurement, call LCD early resume */
+static void stop_cpu_hotplug_check(struct early_suspend *h)
+{
+ cancel_delayed_work_sync(&work_cpu_hotplug);
+
+ set_cpu_config(NORMAL_UC);
+
+ trig = 2;
+}
+
+static void delayed_cpu_hotplug_work(struct work_struct *work)
+{
+ unsigned long avg, load, trend, balance, tmp_trig;
+
+ /* 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);
+
+ tmp_trig = trig;
+ hp_printk("current trig = %lu\n", tmp_trig);
+
+ /* detect "instant" load increase */
+ if (load > max_instant) {
+ tmp_trig++;
+ } else if (current_usecase == 1) { /* auto mode */
+ /* detect high loadavg use case */
+ if (avg > upper_threshold)
+ tmp_trig++;
+ /* detect idle use case */
+ else if (trend < min_trend)
+ tmp_trig--;
+ /* detect unbalanced low cpu load use case */
+ else if ((balance > max_unbalance) && (trend < trend_unbalance))
+ tmp_trig--;
+ /* detect low loadavg use case */
+ else if (avg < lower_threshold)
+ tmp_trig--;
+ } else {
+ tmp_trig--;
+ }
+
+ if (updated_usecase != -1) {
+ current_usecase = updated_usecase;
+ updated_usecase = -1;
+ if (!tmp_trig)
+ tmp_trig = 1;
+ }
+
+ if ((enable) && (tmp_trig == 1)) {
+ hp_printk("enter use case config\n");
+ set_cpu_config(current_usecase);
+ trig = 1;
+ } else if (enable && (tmp_trig == 2)) {
+ hp_printk("enter normal config\n");
+ set_cpu_config(NORMAL_UC);
+ trig = 2;
+ }
+
+ /* reprogramm scheduled work */
+ schedule_delayed_work_on(0, &work_cpu_hotplug,
+ msecs_to_jiffies(CPULOAD_MEAS_DELAY));
+
+}
+
+#define define_set(_name) \
+static ssize_t set_##_name(struct file *file, \
+ const char __user *user_buf, \
+ size_t count, loff_t *ppos) \
+{ \
+ char buf[32]; \
+ ssize_t buf_size; \
+ long unsigned int i; \
+ \
+ /* Get userspace string and assure termination */ \
+ buf_size = min(count, (sizeof(buf)-1)); \
+ if (copy_from_user(buf, user_buf, buf_size)) \
+ return -EFAULT; \
+ buf[buf_size] = 0; \
+ \
+ if (strict_strtoul(buf, 0, &i) != 0) \
+ return buf_size; \
+ \
+ _name = i; \
+ hp_printk("New value : %lu\n", _name); \
+ \
+ return buf_size; \
+}
+
+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(enable);
+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(enable);
+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(enable);
+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(enable);
+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(enable),
+ define_dbg_entry(debug),
+ {
+ .file = NULL,
+ },
+};
+
+static struct dentry *cpuhotplug_dir;
+
+static void remove_debugfs(void)
+{
+ struct dbg_file *entry;
+
+ entry = &debug_entry[0];
+ while (entry->file != NULL) {
+ if (!IS_ERR_OR_NULL(*(entry->file)))
+ debugfs_remove(*(entry->file));
+ entry++;
+ }
+}
+
+static void setup_debugfs(void)
+{
+ struct dbg_file *entry;
+
+ cpuhotplug_dir = debugfs_create_dir("cpu_hotplug", NULL);
+
+ if (IS_ERR_OR_NULL(cpuhotplug_dir))
+ goto fail;
+
+ entry = &debug_entry[0];
+ while (entry->file != NULL) {
+ *(entry->file) = debugfs_create_file(entry->name,
+ S_IWUGO | S_IRUGO, cpuhotplug_dir,
+ NULL, (entry->fops));
+
+ if (IS_ERR_OR_NULL(*(entry->file)))
+ break;
+
+ entry++;
+ }
+
+ return;
+fail:
+ remove_debugfs();
+}
+
+static ssize_t show_mode(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%lu : %s\n",
+ current_usecase, name_usecase[current_usecase]);
+}
+
+static ssize_t store_mode(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;
+
+ if (input < MAX_USECASE)
+ updated_usecase = input;
+
+ return count;
+}
+
+static SYSDEV_CLASS_ATTR(mode, 0644, show_mode, store_mode);
+
+static struct attribute *dbs_attributes[] = {
+ &attr_mode.attr,
+ NULL
+};
+
+static struct attribute_group dbs_attr_group = {
+ .attrs = dbs_attributes,
+ .name = "usecase-gov",
+};
+
+/* initialize devices */
+int __init init_cpuhotplug_devices(void)
+{
+ int err;
+
+ pr_info("Use-case governor initialized\n");
+
+ /* add early_suspend callback */
+ cpuhotplug_early_suspend.level = 200;
+ cpuhotplug_early_suspend.suspend = start_cpu_hotplug_check;
+ cpuhotplug_early_suspend.resume = stop_cpu_hotplug_check;
+ register_early_suspend(&cpuhotplug_early_suspend);
+
+ /* register delayed queuework */
+ INIT_DELAYED_WORK_DEFERRABLE(&work_cpu_hotplug,
+ delayed_cpu_hotplug_work);
+
+ init_cpu_load_trend();
+
+ setup_debugfs();
+
+ 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);
+ goto error;
+ }
+
+
+ return 0;
+
+error:
+ remove_debugfs();
+ unregister_early_suspend(&cpuhotplug_early_suspend);
+ return err;
+}
+
+module_init(init_cpuhotplug_devices);
diff --git a/arch/arm/mach-ux500/prcmu-db5500.c b/arch/arm/mach-ux500/prcmu-db5500.c
new file mode 100644
index 00000000000..e5d90ae367f
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu-db5500.c
@@ -0,0 +1,546 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ *
+ * U5500 PRCM Unit interface driver
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/prcmu-regs.h>
+#include <mach/prcmu-db5500.h>
+#include <mach/prcmu-fw-api.h>
+#include <mach/db5500-regs.h>
+
+#include "prcmu-regs-db5500.h"
+#include "prcmu-db5500.h"
+
+#define _PRCM_MB_HEADER (tcdm_base + 0xFE8)
+#define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0)
+#define PRCM_REQ_MB1_HEADER (_PRCM_MB_HEADER + 0x1)
+#define PRCM_REQ_MB2_HEADER (_PRCM_MB_HEADER + 0x2)
+#define PRCM_REQ_MB3_HEADER (_PRCM_MB_HEADER + 0x3)
+#define PRCM_REQ_MB4_HEADER (_PRCM_MB_HEADER + 0x4)
+#define PRCM_REQ_MB5_HEADER (_PRCM_MB_HEADER + 0x5)
+#define PRCM_REQ_MB6_HEADER (_PRCM_MB_HEADER + 0x6)
+#define PRCM_REQ_MB7_HEADER (_PRCM_MB_HEADER + 0x7)
+#define PRCM_ACK_MB0_HEADER (_PRCM_MB_HEADER + 0x8)
+#define PRCM_ACK_MB1_HEADER (_PRCM_MB_HEADER + 0x9)
+#define PRCM_ACK_MB2_HEADER (_PRCM_MB_HEADER + 0xa)
+#define PRCM_ACK_MB3_HEADER (_PRCM_MB_HEADER + 0xb)
+#define PRCM_ACK_MB4_HEADER (_PRCM_MB_HEADER + 0xc)
+#define PRCM_ACK_MB5_HEADER (_PRCM_MB_HEADER + 0xd)
+#define PRCM_ACK_MB6_HEADER (_PRCM_MB_HEADER + 0xe)
+#define PRCM_ACK_MB7_HEADER (_PRCM_MB_HEADER + 0xf)
+
+/* Req Mailboxes */
+#define PRCM_REQ_MB0 (tcdm_base + 0xFD8)
+#define PRCM_REQ_MB1 (tcdm_base + 0xFCC)
+#define PRCM_REQ_MB2 (tcdm_base + 0xFC4)
+#define PRCM_REQ_MB3 (tcdm_base + 0xFC0)
+#define PRCM_REQ_MB4 (tcdm_base + 0xF98)
+#define PRCM_REQ_MB5 (tcdm_base + 0xF90)
+#define PRCM_REQ_MB6 (tcdm_base + 0xF8C)
+#define PRCM_REQ_MB7 (tcdm_base + 0xF84)
+
+/* Ack Mailboxes */
+#define PRCM_ACK_MB0 (tcdm_base + 0xF38)
+#define PRCM_ACK_MB1 (tcdm_base + 0xF30)
+#define PRCM_ACK_MB2 (tcdm_base + 0xF24)
+#define PRCM_ACK_MB3 (tcdm_base + 0xF20)
+#define PRCM_ACK_MB4 (tcdm_base + 0xF1C)
+#define PRCM_ACK_MB5 (tcdm_base + 0xF14)
+#define PRCM_ACK_MB6 (tcdm_base + 0xF0C)
+#define PRCM_ACK_MB7 (tcdm_base + 0xF08)
+
+enum mb_return_code {
+ RC_SUCCESS,
+ RC_FAIL,
+};
+
+/* Mailbox 0 headers. */
+enum mb0_header {
+ /* request */
+ RMB0H_PWR_STATE_TRANS = 1,
+ RMB0H_WAKE_UP_CFG,
+ RMB0H_RD_WAKE_UP_ACK,
+ /* acknowledge */
+ AMB0H_WAKE_UP = 1,
+};
+
+/* Mailbox 5 headers. */
+enum mb5_header {
+ MB5H_I2C_WRITE = 1,
+ MB5H_I2C_READ,
+};
+
+/* Request mailbox 5 fields. */
+#define PRCM_REQ_MB5_I2C_SLAVE (PRCM_REQ_MB5 + 0)
+#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 1)
+#define PRCM_REQ_MB5_I2C_SIZE (PRCM_REQ_MB5 + 2)
+#define PRCM_REQ_MB5_I2C_DATA (PRCM_REQ_MB5 + 4)
+
+/* Acknowledge mailbox 5 fields. */
+#define PRCM_ACK_MB5_RETURN_CODE (PRCM_ACK_MB5 + 0)
+#define PRCM_ACK_MB5_I2C_DATA (PRCM_ACK_MB5 + 4)
+
+#define NUM_MB 8
+#define MBOX_BIT BIT
+#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
+
+/*
+* Used by MCDE to setup all necessary PRCMU registers
+*/
+#define PRCMU_RESET_DSIPLL 0x00004000
+#define PRCMU_UNCLAMP_DSIPLL 0x00400800
+
+/* HDMI CLK MGT PLLSW=001 (PLLSOC0), PLLDIV=0x8, = 50 Mhz*/
+#define PRCMU_DSI_CLOCK_SETTING 0x00000128
+/* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */
+#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000135
+#define PRCMU_PLLDSI_FREQ_SETTING 0x00020121
+#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000002
+#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x03000201
+#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00000101
+
+#define PRCMU_ENABLE_PLLDSI 0x00000001
+#define PRCMU_DISABLE_PLLDSI 0x00000000
+
+#define PRCMU_DSI_RESET_SW 0x00000003
+
+#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3
+
+/*
+ * mb0_transfer - state needed for mailbox 0 communication.
+ * @lock: The transaction lock.
+ */
+static struct {
+ spinlock_t lock;
+} mb0_transfer;
+
+/*
+ * mb5_transfer - state needed for mailbox 5 communication.
+ * @lock: The transaction lock.
+ * @work: The transaction completion structure.
+ * @ack: Reply ("acknowledge") data.
+ */
+static struct {
+ struct mutex lock;
+ struct completion work;
+ struct {
+ u8 header;
+ u8 status;
+ u8 value[4];
+ } ack;
+} mb5_transfer;
+
+/* PRCMU TCDM base IO address. */
+static __iomem void *tcdm_base;
+
+struct clk_mgt {
+ unsigned int offset;
+ u32 pllsw;
+};
+
+static DEFINE_SPINLOCK(clk_mgt_lock);
+
+#define CLK_MGT_ENTRY(_name)[DB5500_PRCMU_##_name] = { \
+ (DB5500_PRCM_##_name##_MGT), 0 \
+}
+static struct clk_mgt clk_mgt[DB5500_PRCMU_NUM_REG_CLOCKS] = {
+ CLK_MGT_ENTRY(SGACLK),
+ CLK_MGT_ENTRY(UARTCLK),
+ CLK_MGT_ENTRY(MSP02CLK),
+ CLK_MGT_ENTRY(I2CCLK),
+ CLK_MGT_ENTRY(SDMMCCLK),
+ CLK_MGT_ENTRY(PER1CLK),
+ CLK_MGT_ENTRY(PER2CLK),
+ CLK_MGT_ENTRY(PER3CLK),
+ CLK_MGT_ENTRY(PER5CLK),
+ CLK_MGT_ENTRY(PER6CLK),
+ CLK_MGT_ENTRY(PWMCLK),
+ CLK_MGT_ENTRY(IRDACLK),
+ CLK_MGT_ENTRY(IRRCCLK),
+ CLK_MGT_ENTRY(HDMICLK),
+ CLK_MGT_ENTRY(APEATCLK),
+ CLK_MGT_ENTRY(APETRACECLK),
+ CLK_MGT_ENTRY(MCDECLK),
+ CLK_MGT_ENTRY(DSIALTCLK),
+ CLK_MGT_ENTRY(DMACLK),
+ CLK_MGT_ENTRY(B2R2CLK),
+ CLK_MGT_ENTRY(TVCLK),
+ CLK_MGT_ENTRY(RNGCLK),
+};
+
+static int request_timclk(bool enable)
+{
+ u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK);
+
+ if (!enable)
+ val |= PRCM_TCR_STOP_TIMERS;
+ writel(val, (_PRCMU_BASE + PRCM_TCR));
+
+ return 0;
+}
+
+static int request_reg_clock(u8 clock, bool enable)
+{
+ u32 val;
+ unsigned long flags;
+
+ WARN_ON(!clk_mgt[clock].offset);
+
+ spin_lock_irqsave(&clk_mgt_lock, flags);
+
+ /* Grab the HW semaphore. */
+ while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+ cpu_relax();
+
+ val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
+ if (enable) {
+ val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw);
+ } else {
+ clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
+ val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK);
+ }
+ writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
+
+ /* Release the HW semaphore. */
+ writel(0, (_PRCMU_BASE + PRCM_SEM));
+
+ spin_unlock_irqrestore(&clk_mgt_lock, flags);
+
+ return 0;
+}
+
+/**
+ * db5500_prcmu_request_clock() - Request for a clock to be enabled or disabled.
+ * @clock: The clock for which the request is made.
+ * @enable: Whether the clock should be enabled (true) or disabled (false).
+ *
+ * This function should only be used by the clock implementation.
+ * Do not use it from any other place!
+ */
+int db5500_prcmu_request_clock(u8 clock, bool enable)
+{
+ if (clock < DB5500_PRCMU_NUM_REG_CLOCKS)
+ return request_reg_clock(clock, enable);
+ else if (clock == DB5500_PRCMU_TIMCLK)
+ return request_timclk(enable);
+ else if (clock == DB5500_PRCMU_SYSCLK)
+ return -EINVAL;
+ else
+ return -EINVAL;
+}
+
+/**
+ * db5500_prcmu_abb_read() - Read register value(s) from the ABB.
+ * @slave: The I2C slave address.
+ * @reg: The (start) register address.
+ * @value: The read out value(s).
+ * @size: The number of registers to read.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be <= 4.
+ */
+int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ int r;
+
+ if ((size < 1) || (4 < size))
+ return -EINVAL;
+
+ mutex_lock(&mb5_transfer.lock);
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+ cpu_relax();
+ writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
+ writeb(reg, PRCM_REQ_MB5_I2C_REG);
+ writeb(size, PRCM_REQ_MB5_I2C_SIZE);
+ writeb(MB5H_I2C_READ, PRCM_REQ_MB5_HEADER);
+
+ writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
+ wait_for_completion(&mb5_transfer.work);
+
+ r = 0;
+ if ((mb5_transfer.ack.header == MB5H_I2C_READ) &&
+ (mb5_transfer.ack.status == RC_SUCCESS))
+ memcpy(value, mb5_transfer.ack.value, (size_t)size);
+ else
+ r = -EIO;
+
+ mutex_unlock(&mb5_transfer.lock);
+
+ return r;
+}
+
+/**
+ * db5500_prcmu_abb_write() - Write register value(s) to the ABB.
+ * @slave: The I2C slave address.
+ * @reg: The (start) register address.
+ * @value: The value(s) to write.
+ * @size: The number of registers to write.
+ *
+ * Writes register value(s) to the ABB.
+ * @size has to be <= 4.
+ */
+int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ int r;
+
+ if ((size < 1) || (4 < size))
+ return -EINVAL;
+
+ mutex_lock(&mb5_transfer.lock);
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+ cpu_relax();
+ writeb(slave, PRCM_REQ_MB5_I2C_SLAVE);
+ writeb(reg, PRCM_REQ_MB5_I2C_REG);
+ writeb(size, PRCM_REQ_MB5_I2C_SIZE);
+ memcpy_toio(PRCM_REQ_MB5_I2C_DATA, value, size);
+ writeb(MB5H_I2C_WRITE, PRCM_REQ_MB5_HEADER);
+
+ writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
+ wait_for_completion(&mb5_transfer.work);
+
+ if ((mb5_transfer.ack.header == MB5H_I2C_WRITE) &&
+ (mb5_transfer.ack.status == RC_SUCCESS))
+ r = 0;
+ else
+ r = -EIO;
+
+ mutex_unlock(&mb5_transfer.lock);
+
+ return r;
+}
+
+int prcmu_enable_dsipll(void)
+{
+ int i;
+
+ /* Enable DSIPLL_RESETN resets */
+ writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR);
+ /* Unclamp DSIPLL in/out */
+ writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR);
+ /* Set DSI PLL FREQ */
+ writel(PRCMU_PLLDSI_FREQ_SETTING, PRCM_PLLDSI_FREQ);
+ writel(PRCMU_DSI_PLLOUT_SEL_SETTING,
+ PRCM_DSI_PLLOUT_SEL);
+ /* Enable Escape clocks */
+ writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
+
+ /* Start DSI PLL */
+ writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
+ /* Reset DSI PLL */
+ writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET);
+ for (i = 0; i < 10; i++) {
+ if ((readl(PRCM_PLLDSI_LOCKP) &
+ PRCMU_PLLDSI_LOCKP_LOCKED) == PRCMU_PLLDSI_LOCKP_LOCKED)
+ break;
+ udelay(100);
+ }
+ /* Release DSIPLL_RESETN */
+ writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET);
+ return 0;
+}
+
+int prcmu_disable_dsipll(void)
+{
+ /* Disable dsi pll */
+ writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
+ /* Disable escapeclock */
+ writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
+ return 0;
+}
+
+int prcmu_set_display_clocks(void)
+{
+ writel(PRCMU_DSI_CLOCK_SETTING, PRCM_HDMICLK_MGT);
+ writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT);
+ return 0;
+}
+
+static void ack_dbb_wakeup(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+ cpu_relax();
+
+ writeb(RMB0H_RD_WAKE_UP_ACK, PRCM_REQ_MB0_HEADER);
+ writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+}
+
+static inline void print_unknown_header_warning(u8 n, u8 header)
+{
+ pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n",
+ header, n);
+}
+
+static bool read_mailbox_0(void)
+{
+ bool r;
+ u8 header;
+
+ header = readb(PRCM_ACK_MB0_HEADER);
+ switch (header) {
+ case AMB0H_WAKE_UP:
+ r = true;
+ break;
+ default:
+ print_unknown_header_warning(0, header);
+ r = false;
+ break;
+ }
+ writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
+ return r;
+}
+
+static bool read_mailbox_1(void)
+{
+ writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
+ return false;
+}
+
+static bool read_mailbox_2(void)
+{
+ writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
+ return false;
+}
+
+static bool read_mailbox_3(void)
+{
+ writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
+ return false;
+}
+
+static bool read_mailbox_4(void)
+{
+ writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
+ return false;
+}
+
+static bool read_mailbox_5(void)
+{
+ u8 header;
+
+ header = readb(PRCM_ACK_MB5_HEADER);
+ switch (header) {
+ case MB5H_I2C_READ:
+ memcpy_fromio(mb5_transfer.ack.value, PRCM_ACK_MB5_I2C_DATA, 4);
+ case MB5H_I2C_WRITE:
+ mb5_transfer.ack.header = header;
+ mb5_transfer.ack.status = readb(PRCM_ACK_MB5_RETURN_CODE);
+ complete(&mb5_transfer.work);
+ break;
+ default:
+ print_unknown_header_warning(5, header);
+ break;
+ }
+ writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
+ return false;
+}
+
+static bool read_mailbox_6(void)
+{
+ writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
+ return false;
+}
+
+static bool read_mailbox_7(void)
+{
+ writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
+ return false;
+}
+
+static bool (* const read_mailbox[NUM_MB])(void) = {
+ read_mailbox_0,
+ read_mailbox_1,
+ read_mailbox_2,
+ read_mailbox_3,
+ read_mailbox_4,
+ read_mailbox_5,
+ read_mailbox_6,
+ read_mailbox_7
+};
+
+static irqreturn_t prcmu_irq_handler(int irq, void *data)
+{
+ u32 bits;
+ u8 n;
+ irqreturn_t r;
+
+ bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
+ if (unlikely(!bits))
+ return IRQ_NONE;
+
+ r = IRQ_HANDLED;
+ for (n = 0; bits; n++) {
+ if (bits & MBOX_BIT(n)) {
+ bits -= MBOX_BIT(n);
+ if (read_mailbox[n]())
+ r = IRQ_WAKE_THREAD;
+ }
+ }
+ return r;
+}
+
+static irqreturn_t prcmu_irq_thread_fn(int irq, void *data)
+{
+ ack_dbb_wakeup();
+ return IRQ_HANDLED;
+}
+
+void __init db5500_prcmu_early_init(void)
+{
+ tcdm_base = __io_address(U5500_PRCMU_TCDM_BASE);
+ spin_lock_init(&mb0_transfer.lock);
+ mutex_init(&mb5_transfer.lock);
+ init_completion(&mb5_transfer.work);
+}
+
+/**
+ * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
+ *
+ */
+int __init db5500_prcmu_init(void)
+{
+ int r = 0;
+
+ if (ux500_is_svp() || !cpu_is_u5500())
+ return -ENODEV;
+
+ /* Clean up the mailbox interrupts after pre-kernel code. */
+ writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLEAR);
+
+ r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
+ prcmu_irq_thread_fn, 0, "prcmu", NULL);
+ if (r < 0) {
+ pr_err("prcmu: Failed to allocate IRQ_DB5500_PRCMU1.\n");
+ return -EBUSY;
+ }
+ return 0;
+}
+
+arch_initcall(db5500_prcmu_init);
diff --git a/arch/arm/mach-ux500/prcmu-db5500.h b/arch/arm/mach-ux500/prcmu-db5500.h
new file mode 100644
index 00000000000..713bd0d858d
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu-db5500.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License terms: GNU General Public License, version 2
+ */
+
+#ifndef __MACH_PRCMU_DB4500_H
+#define __MACH_PRCMU_DB4500_H
+
+/*
+ * Clock identifiers.
+ */
+enum db5500_prcmu_clock {
+ DB5500_PRCMU_SGACLK,
+ DB5500_PRCMU_UARTCLK,
+ DB5500_PRCMU_MSP02CLK,
+ DB5500_PRCMU_I2CCLK,
+ DB5500_PRCMU_SDMMCCLK,
+ DB5500_PRCMU_PER1CLK,
+ DB5500_PRCMU_PER2CLK,
+ DB5500_PRCMU_PER3CLK,
+ DB5500_PRCMU_PER5CLK,
+ DB5500_PRCMU_PER6CLK,
+ DB5500_PRCMU_PWMCLK,
+ DB5500_PRCMU_IRDACLK,
+ DB5500_PRCMU_IRRCCLK,
+ DB5500_PRCMU_HDMICLK,
+ DB5500_PRCMU_APEATCLK,
+ DB5500_PRCMU_APETRACECLK,
+ DB5500_PRCMU_MCDECLK,
+ DB5500_PRCMU_DSIALTCLK,
+ DB5500_PRCMU_DMACLK,
+ DB5500_PRCMU_B2R2CLK,
+ DB5500_PRCMU_TVCLK,
+ DB5500_PRCMU_RNGCLK,
+ DB5500_PRCMU_NUM_REG_CLOCKS,
+ DB5500_PRCMU_SYSCLK = DB5500_PRCMU_NUM_REG_CLOCKS,
+ DB5500_PRCMU_TIMCLK,
+};
+
+extern int db5500_prcmu_request_clock(u8 clock, bool enable);
+
+#endif
diff --git a/arch/arm/mach-ux500/prcmu-db8500.c b/arch/arm/mach-ux500/prcmu-db8500.c
new file mode 100644
index 00000000000..edb7003aaa0
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu-db8500.c
@@ -0,0 +1,2058 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com>
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ *
+ * U8500 PRCM Unit interface driver
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+
+/*
+ * NOTE! Temporary until all users of set_hwacc() are using the regulator
+ * framework API
+ */
+#include <linux/regulator/consumer.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include "prcmu-regs-db8500.h"
+#include "prcmu-debug.h"
+#include <mach/prcmu-fw-api.h>
+#include <mach/prcmu-fw-defs_v1.h>
+#include <mach/db8500-regs.h>
+
+/* Offset for the firmware version within the TCPM */
+#define PRCMU_FW_VERSION_OFFSET 0xA4
+
+/* PRCMU project numbers, defined by PRCMU FW */
+#define PRCMU_PROJECT_ID_8500V1_0 1
+#define PRCMU_PROJECT_ID_8500V2_0 2
+#define PRCMU_PROJECT_ID_8400V2_0 3
+
+/* Index of different voltages to be used when accessing AVSData */
+#define PRCM_AVS_BASE 0x2FC
+#define PRCM_AVS_VBB_RET (PRCM_AVS_BASE + 0x0)
+#define PRCM_AVS_VBB_MAX_OPP (PRCM_AVS_BASE + 0x1)
+#define PRCM_AVS_VBB_100_OPP (PRCM_AVS_BASE + 0x2)
+#define PRCM_AVS_VBB_50_OPP (PRCM_AVS_BASE + 0x3)
+#define PRCM_AVS_VARM_MAX_OPP (PRCM_AVS_BASE + 0x4)
+#define PRCM_AVS_VARM_100_OPP (PRCM_AVS_BASE + 0x5)
+#define PRCM_AVS_VARM_50_OPP (PRCM_AVS_BASE + 0x6)
+#define PRCM_AVS_VARM_RET (PRCM_AVS_BASE + 0x7)
+#define PRCM_AVS_VAPE_100_OPP (PRCM_AVS_BASE + 0x8)
+#define PRCM_AVS_VAPE_50_OPP (PRCM_AVS_BASE + 0x9)
+#define PRCM_AVS_VMOD_100_OPP (PRCM_AVS_BASE + 0xA)
+#define PRCM_AVS_VMOD_50_OPP (PRCM_AVS_BASE + 0xB)
+#define PRCM_AVS_VSAFE (PRCM_AVS_BASE + 0xC)
+
+#define PRCM_AVS_VOLTAGE 0
+#define PRCM_AVS_VOLTAGE_MASK 0x3f
+#define PRCM_AVS_ISSLOWSTARTUP 6
+#define PRCM_AVS_ISSLOWSTARTUP_MASK (1 << PRCM_AVS_ISSLOWSTARTUP)
+#define PRCM_AVS_ISMODEENABLE 7
+#define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE)
+
+#define PRCM_BOOT_STATUS 0xFFF
+#define PRCM_ROMCODE_A2P 0xFFE
+#define PRCM_ROMCODE_P2A 0xFFD
+#define PRCM_XP70_CUR_PWR_STATE 0xFFC /* 4 BYTES */
+
+#define PRCM_SW_RST_REASON 0xFF8 /* 2 bytes */
+
+#define _PRCM_MBOX_HEADER 0xFE8 /* 16 bytes */
+#define PRCM_MBOX_HEADER_REQ_MB0 (_PRCM_MBOX_HEADER + 0x0)
+#define PRCM_MBOX_HEADER_REQ_MB1 (_PRCM_MBOX_HEADER + 0x1)
+#define PRCM_MBOX_HEADER_REQ_MB2 (_PRCM_MBOX_HEADER + 0x2)
+#define PRCM_MBOX_HEADER_REQ_MB3 (_PRCM_MBOX_HEADER + 0x3)
+#define PRCM_MBOX_HEADER_REQ_MB4 (_PRCM_MBOX_HEADER + 0x4)
+#define PRCM_MBOX_HEADER_REQ_MB5 (_PRCM_MBOX_HEADER + 0x5)
+#define PRCM_MBOX_HEADER_ACK_MB0 (_PRCM_MBOX_HEADER + 0x8)
+
+/* Req Mailboxes */
+#define PRCM_REQ_MB0 0xFDC /* 12 bytes */
+#define PRCM_REQ_MB1 0xFD0 /* 12 bytes */
+#define PRCM_REQ_MB2 0xFC0 /* 16 bytes */
+#define PRCM_REQ_MB3 0xE4C /* 372 bytes */
+#define PRCM_REQ_MB4 0xE48 /* 4 bytes */
+#define PRCM_REQ_MB5 0xE44 /* 4 bytes */
+
+/* Ack Mailboxes */
+#define PRCM_ACK_MB0 0xE08 /* 52 bytes */
+#define PRCM_ACK_MB1 0xE04 /* 4 bytes */
+#define PRCM_ACK_MB2 0xE00 /* 4 bytes */
+#define PRCM_ACK_MB3 0xDFC /* 4 bytes */
+#define PRCM_ACK_MB4 0xDF8 /* 4 bytes */
+#define PRCM_ACK_MB5 0xDF4 /* 4 bytes */
+
+/* Mailbox 0 headers */
+#define MB0H_POWER_STATE_TRANS 0
+#define MB0H_CONFIG_WAKEUPS_EXE 1
+#define MB0H_READ_WAKEUP_ACK 3
+#define MB0H_CONFIG_WAKEUPS_SLEEP 4
+
+#define MB0H_WAKEUP_EXE 2
+#define MB0H_WAKEUP_SLEEP 5
+
+/* Mailbox 0 REQs */
+#define PRCM_REQ_MB0_AP_POWER_STATE (PRCM_REQ_MB0 + 0x0)
+#define PRCM_REQ_MB0_AP_PLL_STATE (PRCM_REQ_MB0 + 0x1)
+#define PRCM_REQ_MB0_ULP_CLOCK_STATE (PRCM_REQ_MB0 + 0x2)
+#define PRCM_REQ_MB0_DO_NOT_WFI (PRCM_REQ_MB0 + 0x3)
+#define PRCM_REQ_MB0_WAKEUP_8500 (PRCM_REQ_MB0 + 0x4)
+#define PRCM_REQ_MB0_WAKEUP_4500 (PRCM_REQ_MB0 + 0x8)
+
+/* Mailbox 0 ACKs */
+#define PRCM_ACK_MB0_AP_PWRSTTR_STATUS (PRCM_ACK_MB0 + 0x0)
+#define PRCM_ACK_MB0_READ_POINTER (PRCM_ACK_MB0 + 0x1)
+#define PRCM_ACK_MB0_WAKEUP_0_8500 (PRCM_ACK_MB0 + 0x4)
+#define PRCM_ACK_MB0_WAKEUP_0_4500 (PRCM_ACK_MB0 + 0x8)
+#define PRCM_ACK_MB0_WAKEUP_1_8500 (PRCM_ACK_MB0 + 0x1C)
+#define PRCM_ACK_MB0_WAKEUP_1_4500 (PRCM_ACK_MB0 + 0x20)
+#define PRCM_ACK_MB0_EVENT_4500_NUMBERS 20
+
+/* Mailbox 1 headers */
+#define MB1H_ARM_APE_OPP 0x0
+#define MB1H_RESET_MODEM 0x2
+#define MB1H_REQUEST_APE_OPP_100_VOLT 0x3
+#define MB1H_RELEASE_APE_OPP_100_VOLT 0x4
+#define MB1H_RELEASE_USB_WAKEUP 0x5
+#define MB1H_PLL_ON_OFF 0x6
+
+/* Mailbox 1 Requests */
+#define PRCM_REQ_MB1_ARM_OPP (PRCM_REQ_MB1 + 0x0)
+#define PRCM_REQ_MB1_APE_OPP (PRCM_REQ_MB1 + 0x1)
+#define PRCM_REQ_MB1_APE_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x4)
+#define PRCM_REQ_MB1_ARM_OPP_100_RESTORE (PRCM_REQ_MB1 + 0x8)
+#define PRCM_REQ_MB1_PLL_ON_OFF (PRCM_REQ_MB1 + 0x4)
+#define PLL_SOC1_OFF 0x4
+#define PLL_SOC1_ON 0x8
+
+/* Mailbox 1 ACKs */
+#define PRCM_ACK_MB1_CURRENT_ARM_OPP (PRCM_ACK_MB1 + 0x0)
+#define PRCM_ACK_MB1_CURRENT_APE_OPP (PRCM_ACK_MB1 + 0x1)
+#define PRCM_ACK_MB1_APE_VOLTAGE_STATUS (PRCM_ACK_MB1 + 0x2)
+#define PRCM_ACK_MB1_DVFS_STATUS (PRCM_ACK_MB1 + 0x3)
+
+/* Mailbox 2 headers */
+#define MB2H_DPS 0x0
+#define MB2H_AUTO_PWR 0x1
+
+/* Mailbox 2 REQs */
+#define PRCM_REQ_MB2_SVA_MMDSP (PRCM_REQ_MB2 + 0x0)
+#define PRCM_REQ_MB2_SVA_PIPE (PRCM_REQ_MB2 + 0x1)
+#define PRCM_REQ_MB2_SIA_MMDSP (PRCM_REQ_MB2 + 0x2)
+#define PRCM_REQ_MB2_SIA_PIPE (PRCM_REQ_MB2 + 0x3)
+#define PRCM_REQ_MB2_SGA (PRCM_REQ_MB2 + 0x4)
+#define PRCM_REQ_MB2_B2R2_MCDE (PRCM_REQ_MB2 + 0x5)
+#define PRCM_REQ_MB2_ESRAM12 (PRCM_REQ_MB2 + 0x6)
+#define PRCM_REQ_MB2_ESRAM34 (PRCM_REQ_MB2 + 0x7)
+#define PRCM_REQ_MB2_AUTO_PM_SLEEP (PRCM_REQ_MB2 + 0x8)
+#define PRCM_REQ_MB2_AUTO_PM_IDLE (PRCM_REQ_MB2 + 0xC)
+
+/* Mailbox 2 ACKs */
+#define PRCM_ACK_MB2_DPS_STATUS (PRCM_ACK_MB2 + 0x0)
+#define HWACC_PWR_ST_OK 0xFE
+
+/* Mailbox 3 headers */
+#define MB3H_ANC 0x0
+#define MB3H_SIDETONE 0x1
+#define MB3H_SYSCLK 0xE
+
+/* Mailbox 3 Requests */
+#define PRCM_REQ_MB3_ANC_FIR_COEFF (PRCM_REQ_MB3 + 0x0)
+#define PRCM_REQ_MB3_ANC_IIR_COEFF (PRCM_REQ_MB3 + 0x20)
+#define PRCM_REQ_MB3_ANC_SHIFTER (PRCM_REQ_MB3 + 0x60)
+#define PRCM_REQ_MB3_ANC_WARP (PRCM_REQ_MB3 + 0x64)
+#define PRCM_REQ_MB3_SIDETONE_FIR_GAIN (PRCM_REQ_MB3 + 0x68)
+#define PRCM_REQ_MB3_SIDETONE_FIR_COEFF (PRCM_REQ_MB3 + 0x6C)
+#define PRCM_REQ_MB3_SYSCLK_MGT (PRCM_REQ_MB3 + 0x16C)
+
+/* Mailbox 4 headers */
+#define MB4H_DDR_INIT 0x0
+#define MB4H_MEM_ST 0x1
+#define MB4H_HOTDOG 0x12
+#define MB4H_HOTMON 0x13
+#define MB4H_HOT_PERIOD 0x14
+
+/* Mailbox 4 Requests */
+#define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE (PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE (PRCM_REQ_MB4 + 0x1)
+#define PRCM_REQ_MB4_ESRAM0_ST (PRCM_REQ_MB4 + 0x3)
+#define PRCM_REQ_MB4_HOTDOG_THRESHOLD (PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_HOTMON_LOW (PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_HOTMON_HIGH (PRCM_REQ_MB4 + 0x1)
+#define PRCM_REQ_MB4_HOTMON_CONFIG (PRCM_REQ_MB4 + 0x2)
+#define PRCM_REQ_MB4_HOT_PERIOD (PRCM_REQ_MB4 + 0x0)
+#define HOTMON_CONFIG_LOW BIT(0)
+#define HOTMON_CONFIG_HIGH BIT(1)
+
+/* Mailbox 5 Requests */
+#define PRCM_REQ_MB5_I2C_SLAVE_OP (PRCM_REQ_MB5 + 0x0)
+#define PRCM_REQ_MB5_I2C_HW_BITS (PRCM_REQ_MB5 + 0x1)
+#define PRCM_REQ_MB5_I2C_REG (PRCM_REQ_MB5 + 0x2)
+#define PRCM_REQ_MB5_I2C_VAL (PRCM_REQ_MB5 + 0x3)
+#define PRCMU_I2C_WRITE(slave) \
+ (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
+#define PRCMU_I2C_READ(slave) \
+ (((slave) << 1) | BIT(0) | (cpu_is_u8500v2() ? BIT(6) : 0))
+#define PRCMU_I2C_STOP_EN BIT(3)
+
+/* Mailbox 5 ACKs */
+#define PRCM_ACK_MB5_I2C_STATUS (PRCM_ACK_MB5 + 0x1)
+#define PRCM_ACK_MB5_I2C_VAL (PRCM_ACK_MB5 + 0x3)
+#define I2C_WR_OK 0x1
+#define I2C_RD_OK 0x2
+
+#define NUM_MB 8
+#define MBOX_BIT BIT
+#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
+
+/*
+ * Wakeups/IRQs
+ */
+
+#define WAKEUP_BIT_RTC BIT(0)
+#define WAKEUP_BIT_RTT0 BIT(1)
+#define WAKEUP_BIT_RTT1 BIT(2)
+#define WAKEUP_BIT_HSI0 BIT(3)
+#define WAKEUP_BIT_HSI1 BIT(4)
+#define WAKEUP_BIT_CA_WAKE BIT(5)
+#define WAKEUP_BIT_USB BIT(6)
+#define WAKEUP_BIT_ABB BIT(7)
+#define WAKEUP_BIT_ABB_FIFO BIT(8)
+#define WAKEUP_BIT_SYSCLK_OK BIT(9)
+#define WAKEUP_BIT_CA_SLEEP BIT(10)
+#define WAKEUP_BIT_AC_WAKE_ACK BIT(11)
+#define WAKEUP_BIT_SIDE_TONE_OK BIT(12)
+#define WAKEUP_BIT_ANC_OK BIT(13)
+#define WAKEUP_BIT_SW_ERROR BIT(14)
+#define WAKEUP_BIT_AC_SLEEP_ACK BIT(15)
+#define WAKEUP_BIT_ARM BIT(17)
+#define WAKEUP_BIT_HOTMON_LOW BIT(18)
+#define WAKEUP_BIT_HOTMON_HIGH BIT(19)
+#define WAKEUP_BIT_MODEM_SW_RESET_REQ BIT(20)
+#define WAKEUP_BIT_GPIO0 BIT(23)
+#define WAKEUP_BIT_GPIO1 BIT(24)
+#define WAKEUP_BIT_GPIO2 BIT(25)
+#define WAKEUP_BIT_GPIO3 BIT(26)
+#define WAKEUP_BIT_GPIO4 BIT(27)
+#define WAKEUP_BIT_GPIO5 BIT(28)
+#define WAKEUP_BIT_GPIO6 BIT(29)
+#define WAKEUP_BIT_GPIO7 BIT(30)
+#define WAKEUP_BIT_GPIO8 BIT(31)
+
+/*
+ * This vector maps irq numbers to the bits in the bit field used in
+ * communication with the PRCMU firmware.
+ *
+ * The reason for having this is to keep the irq numbers contiguous even though
+ * the bits in the bit field are not. (The bits also have a tendency to move
+ * around, to further complicate matters.)
+ */
+#define IRQ_INDEX(_name) ((IRQ_PRCMU_##_name) - IRQ_PRCMU_BASE)
+#define IRQ_ENTRY(_name)[IRQ_INDEX(_name)] = (WAKEUP_BIT_##_name)
+static u32 prcmu_irq_bit[NUM_PRCMU_WAKEUPS] = {
+ IRQ_ENTRY(RTC),
+ IRQ_ENTRY(RTT0),
+ IRQ_ENTRY(RTT1),
+ IRQ_ENTRY(HSI0),
+ IRQ_ENTRY(HSI1),
+ IRQ_ENTRY(CA_WAKE),
+ IRQ_ENTRY(USB),
+ IRQ_ENTRY(ABB),
+ IRQ_ENTRY(ABB_FIFO),
+ IRQ_ENTRY(CA_SLEEP),
+ IRQ_ENTRY(ARM),
+ IRQ_ENTRY(HOTMON_LOW),
+ IRQ_ENTRY(HOTMON_HIGH),
+ IRQ_ENTRY(MODEM_SW_RESET_REQ),
+ IRQ_ENTRY(GPIO0),
+ IRQ_ENTRY(GPIO1),
+ IRQ_ENTRY(GPIO2),
+ IRQ_ENTRY(GPIO3),
+ IRQ_ENTRY(GPIO4),
+ IRQ_ENTRY(GPIO5),
+ IRQ_ENTRY(GPIO6),
+ IRQ_ENTRY(GPIO7),
+ IRQ_ENTRY(GPIO8)
+};
+
+#define VALID_WAKEUPS (BIT(NUM_PRCMU_WAKEUP_INDICES) - 1)
+#define WAKEUP_ENTRY(_name)[PRCMU_WAKEUP_INDEX_##_name] = (WAKEUP_BIT_##_name)
+static u32 prcmu_wakeup_bit[NUM_PRCMU_WAKEUP_INDICES] = {
+ WAKEUP_ENTRY(RTC),
+ WAKEUP_ENTRY(RTT0),
+ WAKEUP_ENTRY(RTT1),
+ WAKEUP_ENTRY(HSI0),
+ WAKEUP_ENTRY(HSI1),
+ WAKEUP_ENTRY(USB),
+ WAKEUP_ENTRY(ABB),
+ WAKEUP_ENTRY(ABB_FIFO),
+ WAKEUP_ENTRY(ARM)
+};
+
+/*
+ * mb0_transfer - state needed for mailbox 0 communication.
+ * @lock: The transaction lock.
+ * @dbb_events_lock: A lock used to handle concurrent access to (parts of)
+ * the request data.
+ * @mask_work: Work structure used for (un)masking wakeup interrupts.
+ * @req: Request data that need to persist between requests.
+ */
+static struct {
+ spinlock_t lock;
+ spinlock_t dbb_irqs_lock;
+ struct work_struct mask_work;
+ struct mutex ac_wake_lock;
+ struct completion ac_wake_work;
+ struct {
+ u32 dbb_irqs;
+ u32 dbb_wakeups;
+ u32 abb_events;
+ } req;
+} mb0_transfer;
+
+/*
+ * mb1_transfer - state needed for mailbox 1 communication.
+ * @lock: The transaction lock.
+ * @work: The transaction completion structure.
+ * @ack: Reply ("acknowledge") data.
+ */
+static struct {
+ struct mutex lock;
+ struct completion work;
+ struct {
+ u8 header;
+ u8 arm_opp;
+ u8 ape_opp;
+ u8 ape_voltage_status;
+ } ack;
+} mb1_transfer;
+
+/*
+ * mb2_transfer - state needed for mailbox 2 communication.
+ * @lock: The transaction lock.
+ * @work: The transaction completion structure.
+ * @auto_pm_lock: The autonomous power management configuration lock.
+ * @auto_pm_enabled: A flag indicating whether autonomous PM is enabled.
+ * @req: Request data that need to persist between requests.
+ * @ack: Reply ("acknowledge") data.
+ */
+static struct {
+ struct mutex lock;
+ struct completion work;
+ spinlock_t auto_pm_lock;
+ bool auto_pm_enabled;
+ struct {
+ u8 status;
+ } ack;
+} mb2_transfer;
+
+/*
+ * mb3_transfer - state needed for mailbox 3 communication.
+ * @lock: The request lock.
+ * @sysclk_lock: A lock used to handle concurrent sysclk requests.
+ * @sysclk_work: Work structure used for sysclk requests.
+ */
+static struct {
+ spinlock_t lock;
+ struct mutex sysclk_lock;
+ struct completion sysclk_work;
+} mb3_transfer;
+
+/*
+ * mb4_transfer - state needed for mailbox 4 communication.
+ * @lock: The transaction lock.
+ * @work: The transaction completion structure.
+ */
+static struct {
+ struct mutex lock;
+ struct completion work;
+} mb4_transfer;
+
+/*
+ * mb5_transfer - state needed for mailbox 5 communication.
+ * @lock: The transaction lock.
+ * @work: The transaction completion structure.
+ * @ack: Reply ("acknowledge") data.
+ */
+static struct {
+ struct mutex lock;
+ struct completion work;
+ struct {
+ u8 status;
+ u8 value;
+ } ack;
+} mb5_transfer;
+
+static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
+
+/* Spinlocks */
+static DEFINE_SPINLOCK(clkout_lock);
+static DEFINE_SPINLOCK(gpiocr_lock);
+
+/* Global var to runtime determine TCDM base for v2 or v1 */
+static __iomem void *tcdm_base;
+
+struct clk_mgt {
+ unsigned int offset;
+ u32 pllsw;
+};
+
+static DEFINE_SPINLOCK(clk_mgt_lock);
+
+#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT), 0 }
+struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
+ CLK_MGT_ENTRY(SGACLK),
+ CLK_MGT_ENTRY(UARTCLK),
+ CLK_MGT_ENTRY(MSP02CLK),
+ CLK_MGT_ENTRY(MSP1CLK),
+ CLK_MGT_ENTRY(I2CCLK),
+ CLK_MGT_ENTRY(SDMMCCLK),
+ CLK_MGT_ENTRY(SLIMCLK),
+ CLK_MGT_ENTRY(PER1CLK),
+ CLK_MGT_ENTRY(PER2CLK),
+ CLK_MGT_ENTRY(PER3CLK),
+ CLK_MGT_ENTRY(PER5CLK),
+ CLK_MGT_ENTRY(PER6CLK),
+ CLK_MGT_ENTRY(PER7CLK),
+ CLK_MGT_ENTRY(LCDCLK),
+ CLK_MGT_ENTRY(BMLCLK),
+ CLK_MGT_ENTRY(HSITXCLK),
+ CLK_MGT_ENTRY(HSIRXCLK),
+ CLK_MGT_ENTRY(HDMICLK),
+ CLK_MGT_ENTRY(APEATCLK),
+ CLK_MGT_ENTRY(APETRACECLK),
+ CLK_MGT_ENTRY(MCDECLK),
+ CLK_MGT_ENTRY(IPI2CCLK),
+ CLK_MGT_ENTRY(DSIALTCLK),
+ CLK_MGT_ENTRY(DMACLK),
+ CLK_MGT_ENTRY(B2R2CLK),
+ CLK_MGT_ENTRY(TVCLK),
+ CLK_MGT_ENTRY(SSPCLK),
+ CLK_MGT_ENTRY(RNGCLK),
+ CLK_MGT_ENTRY(UICCCLK),
+};
+
+/*
+ * NOTE! Temporary until all users of set_hwacc() are using the regulator
+ * framework API
+ */
+static struct regulator *hwacc_regulator[NUM_HW_ACC];
+static struct regulator *hwacc_ret_regulator[NUM_HW_ACC];
+
+static bool hwacc_enabled[NUM_HW_ACC];
+static bool hwacc_ret_enabled[NUM_HW_ACC];
+
+static const char *hwacc_regulator_name[NUM_HW_ACC] = {
+ [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp",
+ [HW_ACC_SVAPIPE] = "hwacc-sva-pipe",
+ [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp",
+ [HW_ACC_SIAPIPE] = "hwacc-sia-pipe",
+ [HW_ACC_SGA] = "hwacc-sga",
+ [HW_ACC_B2R2] = "hwacc-b2r2",
+ [HW_ACC_MCDE] = "hwacc-mcde",
+ [HW_ACC_ESRAM1] = "hwacc-esram1",
+ [HW_ACC_ESRAM2] = "hwacc-esram2",
+ [HW_ACC_ESRAM3] = "hwacc-esram3",
+ [HW_ACC_ESRAM4] = "hwacc-esram4",
+};
+
+static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
+ [HW_ACC_SVAMMDSP] = "hwacc-sva-mmdsp-ret",
+ [HW_ACC_SIAMMDSP] = "hwacc-sia-mmdsp-ret",
+ [HW_ACC_ESRAM1] = "hwacc-esram1-ret",
+ [HW_ACC_ESRAM2] = "hwacc-esram2-ret",
+ [HW_ACC_ESRAM3] = "hwacc-esram3-ret",
+ [HW_ACC_ESRAM4] = "hwacc-esram4-ret",
+};
+
+/*
+* Used by MCDE to setup all necessary PRCMU registers
+*/
+#define PRCMU_RESET_DSIPLL 0x00004000
+#define PRCMU_UNCLAMP_DSIPLL 0x00400800
+
+#define PRCMU_CLK_PLL_DIV_SHIFT 0
+#define PRCMU_CLK_PLL_SW_SHIFT 5
+#define PRCMU_CLK_38 (1 << 9)
+#define PRCMU_CLK_38_SRC (1 << 10)
+#define PRCMU_CLK_38_DIV (1 << 11)
+
+/* PLLDIV=12, PLLSW=4 (PLLDDR) */
+#define PRCMU_DSI_CLOCK_SETTING 0x0000008C
+
+/* PLLDIV=8, PLLSW=4 (PLLDDR) */
+#define PRCMU_DSI_CLOCK_SETTING_U8400 0x00000088
+
+/* DPI 50000000 Hz */
+#define PRCMU_DPI_CLOCK_SETTING ((1 << PRCMU_CLK_PLL_SW_SHIFT) | \
+ (16 << PRCMU_CLK_PLL_DIV_SHIFT))
+#define PRCMU_DSI_LP_CLOCK_SETTING 0x00000E00
+
+/* D=101, N=1, R=4, SELDIV2=0 */
+#define PRCMU_PLLDSI_FREQ_SETTING 0x00040165
+
+/* D=70, N=1, R=3, SELDIV2=0 */
+#define PRCMU_PLLDSI_FREQ_SETTING_U8400 0x00030146
+
+#define PRCMU_ENABLE_PLLDSI 0x00000001
+#define PRCMU_DISABLE_PLLDSI 0x00000000
+#define PRCMU_RELEASE_RESET_DSS 0x0000400C
+#define PRCMU_DSI_PLLOUT_SEL_SETTING 0x00000202
+/* ESC clk, div0=1, div1=1, div2=3 */
+#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV 0x07030101
+#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV 0x00030101
+#define PRCMU_DSI_RESET_SW 0x00000007
+
+#define PRCMU_PLLDSI_LOCKP_LOCKED 0x3
+
+static struct {
+ u8 project_number;
+ u8 api_version;
+ u8 func_version;
+ u8 errata;
+} prcmu_version;
+
+
+int prcmu_enable_dsipll(void)
+{
+ int i;
+ unsigned int plldsifreq;
+
+ /* Clear DSIPLL_RESETN */
+ writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_CLR));
+ /* Unclamp DSIPLL in/out */
+ writel(PRCMU_UNCLAMP_DSIPLL, (_PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR));
+
+ if (prcmu_is_u8400())
+ plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400;
+ else
+ plldsifreq = PRCMU_PLLDSI_FREQ_SETTING;
+ /* Set DSI PLL FREQ */
+ writel(plldsifreq, (_PRCMU_BASE + PRCM_PLLDSI_FREQ));
+ writel(PRCMU_DSI_PLLOUT_SEL_SETTING,
+ (_PRCMU_BASE + PRCM_DSI_PLLOUT_SEL));
+ /* Enable Escape clocks */
+ writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV,
+ (_PRCMU_BASE + PRCM_DSITVCLK_DIV));
+
+ /* Start DSI PLL */
+ writel(PRCMU_ENABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE));
+ /* Reset DSI PLL */
+ writel(PRCMU_DSI_RESET_SW, (_PRCMU_BASE + PRCM_DSI_SW_RESET));
+ for (i = 0; i < 10; i++) {
+ if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) &
+ PRCMU_PLLDSI_LOCKP_LOCKED)
+ == PRCMU_PLLDSI_LOCKP_LOCKED)
+ break;
+ udelay(100);
+ }
+ /* Set DSIPLL_RESETN */
+ writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET));
+ return 0;
+}
+
+int prcmu_disable_dsipll(void)
+{
+ /* Disable dsi pll */
+ writel(PRCMU_DISABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE));
+ /* Disable escapeclock */
+ writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV,
+ (_PRCMU_BASE + PRCM_DSITVCLK_DIV));
+ return 0;
+}
+
+int prcmu_set_display_clocks(void)
+{
+ unsigned long flags;
+ unsigned int dsiclk;
+
+ if (prcmu_is_u8400())
+ dsiclk = PRCMU_DSI_CLOCK_SETTING_U8400;
+ else
+ dsiclk = PRCMU_DSI_CLOCK_SETTING;
+
+ spin_lock_irqsave(&clk_mgt_lock, flags);
+
+ /* Grab the HW semaphore. */
+ while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+ cpu_relax();
+
+ writel(dsiclk, (_PRCMU_BASE + PRCM_HDMICLK_MGT));
+ writel(PRCMU_DSI_LP_CLOCK_SETTING, (_PRCMU_BASE + PRCM_TVCLK_MGT));
+ writel(PRCMU_DPI_CLOCK_SETTING, (_PRCMU_BASE + PRCM_LCDCLK_MGT));
+
+ /* Release the HW semaphore. */
+ writel(0, (_PRCMU_BASE + PRCM_SEM));
+
+ spin_unlock_irqrestore(&clk_mgt_lock, flags);
+
+ return 0;
+}
+
+/**
+ * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1.
+ */
+void prcmu_enable_spi2(void)
+{
+ u32 reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpiocr_lock, flags);
+ reg = readl(_PRCMU_BASE + PRCM_GPIOCR);
+ writel(reg | PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR);
+ spin_unlock_irqrestore(&gpiocr_lock, flags);
+}
+
+/**
+ * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
+ */
+void prcmu_disable_spi2(void)
+{
+ u32 reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpiocr_lock, flags);
+ reg = readl(_PRCMU_BASE + PRCM_GPIOCR);
+ writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR);
+ spin_unlock_irqrestore(&gpiocr_lock, flags);
+}
+
+bool prcmu_has_arm_maxopp(void)
+{
+ return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) &
+ PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK;
+}
+
+bool prcmu_is_u8400(void)
+{
+ return prcmu_version.project_number == PRCMU_PROJECT_ID_8400V2_0;
+}
+
+/**
+ * prcmu_get_boot_status - PRCMU boot status checking
+ * Returns: the current PRCMU boot status
+ */
+int prcmu_get_boot_status(void)
+{
+ return readb(tcdm_base + PRCM_BOOT_STATUS);
+}
+
+/**
+ * prcmu_set_rc_a2p - This function is used to run few power state sequences
+ * @val: Value to be set, i.e. transition requested
+ * Returns: 0 on success, -EINVAL on invalid argument
+ *
+ * This function is used to run the following power state sequences -
+ * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep
+ */
+int prcmu_set_rc_a2p(enum romcode_write val)
+{
+ if (val < RDY_2_DS || val > RDY_2_XP70_RST)
+ return -EINVAL;
+ writeb(val, (tcdm_base + PRCM_ROMCODE_A2P));
+ return 0;
+}
+
+/**
+ * prcmu_get_rc_p2a - This function is used to get power state sequences
+ * Returns: the power transition that has last happened
+ *
+ * This function can return the following transitions-
+ * any state to ApReset, ApDeepSleep to ApExecute, ApExecute to ApDeepSleep
+ */
+enum romcode_read prcmu_get_rc_p2a(void)
+{
+ return readb(tcdm_base + PRCM_ROMCODE_P2A);
+}
+
+/**
+ * prcmu_get_current_mode - Return the current XP70 power mode
+ * Returns: Returns the current AP(ARM) power mode: init,
+ * apBoot, apExecute, apDeepSleep, apSleep, apIdle, apReset
+ */
+enum ap_pwrst prcmu_get_xp70_current_state(void)
+{
+ return readb(tcdm_base + PRCM_XP70_CUR_PWR_STATE);
+}
+
+/**
+ * prcmu_config_clkout - Configure one of the programmable clock outputs.
+ * @clkout: The CLKOUT number (0 or 1).
+ * @source: The clock to be used (one of the PRCMU_CLKSRC_*).
+ * @div: The divider to be applied.
+ *
+ * Configures one of the programmable clock outputs (CLKOUTs).
+ * @div should be in the range [1,63] to request a configuration, or 0 to
+ * inform that the configuration is no longer requested.
+ */
+int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
+{
+ static int requests[2];
+ int r = 0;
+ unsigned long flags;
+ u32 val;
+ u32 bits;
+ u32 mask;
+ u32 div_mask;
+
+ BUG_ON(clkout > 1);
+ BUG_ON(div > 63);
+ BUG_ON((clkout == 0) && (source > PRCMU_CLKSRC_CLK009));
+
+ if (!div && !requests[clkout])
+ return -EINVAL;
+
+ switch (clkout) {
+ case 0:
+ div_mask = PRCM_CLKOCR_CLKODIV0_MASK;
+ mask = (PRCM_CLKOCR_CLKODIV0_MASK | PRCM_CLKOCR_CLKOSEL0_MASK);
+ bits = ((source << PRCM_CLKOCR_CLKOSEL0_SHIFT) |
+ (div << PRCM_CLKOCR_CLKODIV0_SHIFT));
+ break;
+ case 1:
+ div_mask = PRCM_CLKOCR_CLKODIV1_MASK;
+ mask = (PRCM_CLKOCR_CLKODIV1_MASK | PRCM_CLKOCR_CLKOSEL1_MASK |
+ PRCM_CLKOCR_CLK1TYPE);
+ bits = ((source << PRCM_CLKOCR_CLKOSEL1_SHIFT) |
+ (div << PRCM_CLKOCR_CLKODIV1_SHIFT));
+ break;
+ }
+ bits &= mask;
+
+ spin_lock_irqsave(&clkout_lock, flags);
+
+ val = readl(_PRCMU_BASE + PRCM_CLKOCR);
+ if (val & div_mask) {
+ if (div) {
+ if ((val & mask) != bits) {
+ r = -EBUSY;
+ goto unlock_and_return;
+ }
+ } else {
+ if ((val & mask & ~div_mask) != bits) {
+ r = -EINVAL;
+ goto unlock_and_return;
+ }
+ }
+ }
+ writel((bits | (val & ~mask)), (_PRCMU_BASE + PRCM_CLKOCR));
+ requests[clkout] += (div ? 1 : -1);
+
+unlock_and_return:
+ spin_unlock_irqrestore(&clkout_lock, flags);
+
+ return r;
+}
+
+int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
+{
+ unsigned long flags;
+
+ BUG_ON((state < PRCMU_AP_SLEEP) || (PRCMU_AP_DEEP_IDLE < state));
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+ cpu_relax();
+
+ writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
+ writeb(state, (tcdm_base + PRCM_REQ_MB0_AP_POWER_STATE));
+ writeb((keep_ap_pll ? 1 : 0), (tcdm_base + PRCM_REQ_MB0_AP_PLL_STATE));
+ writeb((keep_ulp_clk ? 1 : 0),
+ (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE));
+ writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI));
+ writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+
+ return 0;
+}
+
+/* This function should only be called while mb0_transfer.lock is held. */
+static void config_wakeups(void)
+{
+ const u8 header[2] = {
+ MB0H_CONFIG_WAKEUPS_EXE,
+ MB0H_CONFIG_WAKEUPS_SLEEP
+ };
+ static u32 last_dbb_events;
+ static u32 last_abb_events;
+ u32 dbb_events;
+ u32 abb_events;
+ unsigned int i;
+
+ dbb_events = mb0_transfer.req.dbb_irqs | mb0_transfer.req.dbb_wakeups;
+ dbb_events |= (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK);
+
+ abb_events = mb0_transfer.req.abb_events;
+
+ if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events))
+ return;
+
+ for (i = 0; i < 2; i++) {
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+ cpu_relax();
+ writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500));
+ writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500));
+ writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
+ writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ }
+ last_dbb_events = dbb_events;
+ last_abb_events = abb_events;
+}
+
+void prcmu_enable_wakeups(u32 wakeups)
+{
+ unsigned long flags;
+ u32 bits;
+ int i;
+
+ BUG_ON(wakeups != (wakeups & VALID_WAKEUPS));
+
+ for (i = 0, bits = 0; i < NUM_PRCMU_WAKEUP_INDICES; i++) {
+ if (wakeups & BIT(i))
+ bits |= prcmu_wakeup_bit[i];
+ }
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ mb0_transfer.req.dbb_wakeups = bits;
+ config_wakeups();
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+}
+
+void prcmu_config_abb_event_readout(u32 abb_events)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ mb0_transfer.req.abb_events = abb_events;
+ config_wakeups();
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+}
+
+void prcmu_get_abb_event_buffer(void __iomem **buf)
+{
+ if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
+ *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500);
+ else
+ *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_0_4500);
+}
+
+/**
+ * prcmu_set_arm_opp - set the appropriate ARM OPP
+ * @opp: The new ARM operating point to which transition is to be made
+ * Returns: 0 on success, non-zero on failure
+ *
+ * This function sets the the operating point of the ARM.
+ */
+int prcmu_set_arm_opp(u8 opp)
+{
+ int r;
+
+ if (opp < ARM_NO_CHANGE || opp > ARM_EXTCLK)
+ return -EINVAL;
+
+ r = 0;
+
+ mutex_lock(&mb1_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+ cpu_relax();
+
+ writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+ writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
+ writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
+
+ writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb1_transfer.work);
+
+ if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
+ (mb1_transfer.ack.arm_opp != opp))
+ r = -EIO;
+
+ mutex_unlock(&mb1_transfer.lock);
+
+ return r;
+}
+
+/**
+ * prcmu_get_arm_opp - get the current ARM OPP
+ *
+ * Returns: the current ARM OPP
+ */
+int prcmu_get_arm_opp(void)
+{
+ return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
+}
+
+/**
+ * prcmu_get_ddr_opp - get the current DDR OPP
+ *
+ * Returns: the current DDR OPP
+ */
+int prcmu_get_ddr_opp(void)
+{
+ return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW);
+}
+
+/**
+ * set_ddr_opp - set the appropriate DDR OPP
+ * @opp: The new DDR operating point to which transition is to be made
+ * Returns: 0 on success, non-zero on failure
+ *
+ * This function sets the operating point of the DDR.
+ */
+int prcmu_set_ddr_opp(u8 opp)
+{
+ if (opp < DDR_100_OPP || opp > DDR_25_OPP)
+ return -EINVAL;
+ /* Changing the DDR OPP can hang the hardware pre-v21 */
+ if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20())
+ writeb(opp, (_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW));
+
+ return 0;
+}
+/**
+ * set_ape_opp - set the appropriate APE OPP
+ * @opp: The new APE operating point to which transition is to be made
+ * Returns: 0 on success, non-zero on failure
+ *
+ * This function sets the operating point of the APE.
+ */
+int prcmu_set_ape_opp(u8 opp)
+{
+ int r = 0;
+
+ mutex_lock(&mb1_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+ cpu_relax();
+
+ writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+ writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
+ writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
+
+ writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb1_transfer.work);
+
+ if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
+ (mb1_transfer.ack.ape_opp != opp))
+ r = -EIO;
+
+ mutex_unlock(&mb1_transfer.lock);
+
+ return r;
+}
+
+/**
+ * prcmu_get_ape_opp - get the current APE OPP
+ *
+ * Returns: the current APE OPP
+ */
+int prcmu_get_ape_opp(void)
+{
+ return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP);
+}
+
+/**
+ * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
+ * @enable: true to request the higher voltage, false to drop a request.
+ *
+ * Calls to this function to enable and disable requests must be balanced.
+ */
+int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+ int r = 0;
+ u8 header;
+ static unsigned int requests;
+
+ mutex_lock(&mb1_transfer.lock);
+
+ if (enable) {
+ if (0 != requests++)
+ goto unlock_and_return;
+ header = MB1H_REQUEST_APE_OPP_100_VOLT;
+ } else {
+ if (requests == 0) {
+ r = -EIO;
+ goto unlock_and_return;
+ } else if (1 != requests--) {
+ goto unlock_and_return;
+ }
+ header = MB1H_RELEASE_APE_OPP_100_VOLT;
+ }
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+ cpu_relax();
+
+ writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+
+ writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb1_transfer.work);
+
+ if ((mb1_transfer.ack.header != header) ||
+ ((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0))
+ r = -EIO;
+
+unlock_and_return:
+ mutex_unlock(&mb1_transfer.lock);
+
+ return r;
+}
+
+/**
+ * prcmu_release_usb_wakeup_state - release the state required by a USB wakeup
+ *
+ * This function releases the power state requirements of a USB wakeup.
+ */
+int prcmu_release_usb_wakeup_state(void)
+{
+ int r = 0;
+
+ mutex_lock(&mb1_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+ cpu_relax();
+
+ writeb(MB1H_RELEASE_USB_WAKEUP,
+ (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+
+ writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb1_transfer.work);
+
+ if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) ||
+ ((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0))
+ r = -EIO;
+
+ mutex_unlock(&mb1_transfer.lock);
+
+ return r;
+}
+
+static int request_pll(u8 clock, bool enable)
+{
+ int r = 0;
+
+ if (clock == PRCMU_PLLSOC1)
+ clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF);
+ else
+ return -EINVAL;
+
+ mutex_lock(&mb1_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+ cpu_relax();
+
+ writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+ writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF));
+
+ writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb1_transfer.work);
+
+ if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF)
+ r = -EIO;
+
+ mutex_unlock(&mb1_transfer.lock);
+
+ return r;
+}
+
+/**
+ * prcmu_set_hwacc - set the power state of a h/w accelerator
+ * @hwacc_dev: The hardware accelerator (enum hw_acc_dev).
+ * @state: The new power state (enum hw_acc_state).
+ *
+ * This function sets the power state of a hardware accelerator.
+ * This function should not be called from interrupt context.
+ *
+ * NOTE! Deprecated, to be removed when all users switched over to use the
+ * regulator framework API.
+ */
+int prcmu_set_hwacc(u16 hwacc_dev, u8 state)
+{
+ int r = 0;
+ bool ram_retention = false;
+ bool enable, enable_ret;
+
+ /* check argument */
+ BUG_ON(hwacc_dev >= NUM_HW_ACC);
+
+ /* get state of switches */
+ enable = hwacc_enabled[hwacc_dev];
+ enable_ret = hwacc_ret_enabled[hwacc_dev];
+
+ /* set flag if retention is possible */
+ switch (hwacc_dev) {
+ case HW_ACC_SVAMMDSP:
+ case HW_ACC_SIAMMDSP:
+ case HW_ACC_ESRAM1:
+ case HW_ACC_ESRAM2:
+ case HW_ACC_ESRAM3:
+ case HW_ACC_ESRAM4:
+ ram_retention = true;
+ break;
+ }
+
+ /* check argument */
+ BUG_ON(state > HW_ON);
+ BUG_ON(state == HW_OFF_RAMRET && !ram_retention);
+
+ /* modify enable flags */
+ switch (state) {
+ case HW_OFF:
+ enable_ret = false;
+ enable = false;
+ break;
+ case HW_ON:
+ enable = true;
+ break;
+ case HW_OFF_RAMRET:
+ enable_ret = true;
+ enable = false;
+ break;
+ }
+
+ /* get regulator (lazy) */
+ if (hwacc_regulator[hwacc_dev] == NULL) {
+ hwacc_regulator[hwacc_dev] = regulator_get(NULL,
+ hwacc_regulator_name[hwacc_dev]);
+ if (IS_ERR(hwacc_regulator[hwacc_dev])) {
+ pr_err("prcmu: failed to get supply %s\n",
+ hwacc_regulator_name[hwacc_dev]);
+ r = PTR_ERR(hwacc_regulator[hwacc_dev]);
+ goto out;
+ }
+ }
+
+ if (ram_retention) {
+ if (hwacc_ret_regulator[hwacc_dev] == NULL) {
+ hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL,
+ hwacc_ret_regulator_name[hwacc_dev]);
+ if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) {
+ pr_err("prcmu: failed to get supply %s\n",
+ hwacc_ret_regulator_name[hwacc_dev]);
+ r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]);
+ goto out;
+ }
+ }
+ }
+
+ /* set regulators */
+ if (ram_retention) {
+ if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) {
+ r = regulator_enable(hwacc_ret_regulator[hwacc_dev]);
+ if (r < 0) {
+ pr_err("prcmu_set_hwacc: ret enable failed\n");
+ goto out;
+ }
+ hwacc_ret_enabled[hwacc_dev] = true;
+ }
+ }
+
+ if (enable && !hwacc_enabled[hwacc_dev]) {
+ r = regulator_enable(hwacc_regulator[hwacc_dev]);
+ if (r < 0) {
+ pr_err("prcmu_set_hwacc: enable failed\n");
+ goto out;
+ }
+ hwacc_enabled[hwacc_dev] = true;
+ }
+
+ if (!enable && hwacc_enabled[hwacc_dev]) {
+ r = regulator_disable(hwacc_regulator[hwacc_dev]);
+ if (r < 0) {
+ pr_err("prcmu_set_hwacc: disable failed\n");
+ goto out;
+ }
+ hwacc_enabled[hwacc_dev] = false;
+ }
+
+ if (ram_retention) {
+ if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) {
+ r = regulator_disable(hwacc_ret_regulator[hwacc_dev]);
+ if (r < 0) {
+ pr_err("prcmu_set_hwacc: ret disable failed\n");
+ goto out;
+ }
+ hwacc_ret_enabled[hwacc_dev] = false;
+ }
+ }
+
+out:
+ return r;
+}
+EXPORT_SYMBOL(prcmu_set_hwacc);
+
+/**
+ * prcmu_set_epod - set the state of a EPOD (power domain)
+ * @epod_id: The EPOD to set
+ * @epod_state: The new EPOD state
+ *
+ * This function sets the state of a EPOD (power domain). It may not be called
+ * from interrupt context.
+ */
+int prcmu_set_epod(u16 epod_id, u8 epod_state)
+{
+ int r = 0;
+ bool ram_retention = false;
+ int i;
+
+ /* check argument */
+ BUG_ON(epod_id >= NUM_EPOD_ID);
+
+ /* set flag if retention is possible */
+ switch (epod_id) {
+ case EPOD_ID_SVAMMDSP:
+ case EPOD_ID_SIAMMDSP:
+ case EPOD_ID_ESRAM12:
+ case EPOD_ID_ESRAM34:
+ ram_retention = true;
+ break;
+ }
+
+ /* check argument */
+ BUG_ON(epod_state > EPOD_STATE_ON);
+ BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention);
+
+ /* get lock */
+ mutex_lock(&mb2_transfer.lock);
+
+ /* wait for mailbox */
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
+ cpu_relax();
+
+ /* fill in mailbox */
+ for (i = 0; i < NUM_EPOD_ID; i++)
+ writeb(EPOD_STATE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB2 + i));
+ writeb(epod_state, (tcdm_base + PRCM_REQ_MB2 + epod_id));
+
+ writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2));
+
+ writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+
+ /*
+ * The current firmware version does not handle errors correctly,
+ * and we cannot recover if there is an error.
+ * This is expected to change when the firmware is updated.
+ */
+ if (!wait_for_completion_timeout(&mb2_transfer.work,
+ msecs_to_jiffies(20000))) {
+ pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ __func__);
+ r = -EIO;
+ goto unlock_and_return;
+ }
+
+ if (mb2_transfer.ack.status != HWACC_PWR_ST_OK)
+ r = -EIO;
+
+unlock_and_return:
+ mutex_unlock(&mb2_transfer.lock);
+ return r;
+}
+
+/**
+ * prcmu_configure_auto_pm - Configure autonomous power management.
+ * @sleep: Configuration for ApSleep.
+ * @idle: Configuration for ApIdle.
+ */
+void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
+ struct prcmu_auto_pm_config *idle)
+{
+ u32 sleep_cfg;
+ u32 idle_cfg;
+ unsigned long flags;
+
+ BUG_ON((sleep == NULL) || (idle == NULL));
+
+ sleep_cfg = (sleep->sva_auto_pm_enable & 0xF);
+ sleep_cfg = ((sleep_cfg << 4) | (sleep->sia_auto_pm_enable & 0xF));
+ sleep_cfg = ((sleep_cfg << 8) | (sleep->sva_power_on & 0xFF));
+ sleep_cfg = ((sleep_cfg << 8) | (sleep->sia_power_on & 0xFF));
+ sleep_cfg = ((sleep_cfg << 4) | (sleep->sva_policy & 0xF));
+ sleep_cfg = ((sleep_cfg << 4) | (sleep->sia_policy & 0xF));
+
+ idle_cfg = (idle->sva_auto_pm_enable & 0xF);
+ idle_cfg = ((idle_cfg << 4) | (idle->sia_auto_pm_enable & 0xF));
+ idle_cfg = ((idle_cfg << 8) | (idle->sva_power_on & 0xFF));
+ idle_cfg = ((idle_cfg << 8) | (idle->sia_power_on & 0xFF));
+ idle_cfg = ((idle_cfg << 4) | (idle->sva_policy & 0xF));
+ idle_cfg = ((idle_cfg << 4) | (idle->sia_policy & 0xF));
+
+ spin_lock_irqsave(&mb2_transfer.auto_pm_lock, flags);
+
+ /*
+ * The autonomous power management configuration is done through
+ * fields in mailbox 2, but these fields are only used as shared
+ * variables - i.e. there is no need to send a message.
+ */
+ writel(sleep_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_SLEEP));
+ writel(idle_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_IDLE));
+
+ mb2_transfer.auto_pm_enabled =
+ ((sleep->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
+ (sleep->sia_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
+ (idle->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
+ (idle->sia_auto_pm_enable == PRCMU_AUTO_PM_ON));
+
+ spin_unlock_irqrestore(&mb2_transfer.auto_pm_lock, flags);
+}
+EXPORT_SYMBOL(prcmu_configure_auto_pm);
+
+bool prcmu_is_auto_pm_enabled(void)
+{
+ return mb2_transfer.auto_pm_enabled;
+}
+
+static int request_sysclk(bool enable)
+{
+ int r;
+ unsigned long flags;
+
+ r = 0;
+
+ mutex_lock(&mb3_transfer.sysclk_lock);
+
+ spin_lock_irqsave(&mb3_transfer.lock, flags);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
+ cpu_relax();
+
+ writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT));
+
+ writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3));
+ writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+
+ spin_unlock_irqrestore(&mb3_transfer.lock, flags);
+
+ /*
+ * The firmware only sends an ACK if we want to enable the
+ * SysClk, and it succeeds.
+ */
+ if (enable && !wait_for_completion_timeout(&mb3_transfer.sysclk_work,
+ msecs_to_jiffies(20000))) {
+ pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ __func__);
+ r = -EIO;
+ }
+
+ mutex_unlock(&mb3_transfer.sysclk_lock);
+
+ return r;
+}
+
+static int request_timclk(bool enable)
+{
+ u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK);
+
+ if (!enable)
+ val |= PRCM_TCR_STOP_TIMERS;
+ writel(val, (_PRCMU_BASE + PRCM_TCR));
+
+ return 0;
+}
+
+static int request_reg_clock(u8 clock, bool enable)
+{
+ u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_mgt_lock, flags);
+
+ /* Grab the HW semaphore. */
+ while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+ cpu_relax();
+
+ val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
+ if (enable) {
+ val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw);
+ } else {
+ clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
+ val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK);
+ }
+ writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
+
+ /* Release the HW semaphore. */
+ writel(0, (_PRCMU_BASE + PRCM_SEM));
+
+ spin_unlock_irqrestore(&clk_mgt_lock, flags);
+
+ return 0;
+}
+
+/**
+ * prcmu_request_clock() - Request for a clock to be enabled or disabled.
+ * @clock: The clock for which the request is made.
+ * @enable: Whether the clock should be enabled (true) or disabled (false).
+ *
+ * This function should only be used by the clock implementation.
+ * Do not use it from any other place!
+ */
+int prcmu_request_clock(u8 clock, bool enable)
+{
+ if (clock < PRCMU_NUM_REG_CLOCKS)
+ return request_reg_clock(clock, enable);
+ else if (clock == PRCMU_TIMCLK)
+ return request_timclk(enable);
+ else if (clock == PRCMU_SYSCLK)
+ return request_sysclk(enable);
+ else if (clock == PRCMU_PLLSOC1)
+ return request_pll(clock, enable);
+ else
+ return -EINVAL;
+}
+
+int prcmu_config_esram0_deep_sleep(u8 state)
+{
+ if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) ||
+ (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
+ return -EINVAL;
+
+ mutex_lock(&mb4_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+ cpu_relax();
+
+ writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+ writeb(((DDR_PWR_STATE_OFFHIGHLAT << 4) | DDR_PWR_STATE_ON),
+ (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE));
+ writeb(DDR_PWR_STATE_ON,
+ (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE));
+ writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST));
+
+ writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb4_transfer.work);
+
+ mutex_unlock(&mb4_transfer.lock);
+
+ return 0;
+}
+
+int prcmu_config_hotdog(u8 threshold)
+{
+ mutex_lock(&mb4_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+ cpu_relax();
+
+ writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD));
+ writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+
+ writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb4_transfer.work);
+
+ mutex_unlock(&mb4_transfer.lock);
+
+ return 0;
+}
+
+int prcmu_config_hotmon(u8 low, u8 high)
+{
+ mutex_lock(&mb4_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+ cpu_relax();
+
+ writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW));
+ writeb(high, (tcdm_base + PRCM_REQ_MB4_HOTMON_HIGH));
+ writeb((HOTMON_CONFIG_LOW | HOTMON_CONFIG_HIGH),
+ (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG));
+ writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+
+ writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb4_transfer.work);
+
+ mutex_unlock(&mb4_transfer.lock);
+
+ return 0;
+}
+
+static int config_hot_period(u16 val)
+{
+ mutex_lock(&mb4_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+ cpu_relax();
+
+ writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD));
+ writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+
+ writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb4_transfer.work);
+
+ mutex_unlock(&mb4_transfer.lock);
+
+ return 0;
+}
+
+int prcmu_start_temp_sense(u16 cycles32k)
+{
+ if (cycles32k == 0xFFFF)
+ return -EINVAL;
+
+ return config_hot_period(cycles32k);
+}
+
+int prcmu_stop_temp_sense(void)
+{
+ return config_hot_period(0xFFFF);
+}
+
+/**
+ * prcmu_set_clock_divider() - Configure the clock divider.
+ * @clock: The clock for which the request is made.
+ * @divider: The clock divider. (< 32)
+ *
+ * This function should only be used by the clock implementation.
+ * Do not use it from any other place!
+ */
+int prcmu_set_clock_divider(u8 clock, u8 divider)
+{
+ u32 val;
+ unsigned long flags;
+
+ if ((clock >= PRCMU_NUM_REG_CLOCKS) || (divider < 1) || (31 < divider))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clk_mgt_lock, flags);
+
+ /* Grab the HW semaphore. */
+ while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+ cpu_relax();
+
+ val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
+ val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK);
+ val |= (u32)divider;
+ writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
+
+ /* Release the HW semaphore. */
+ writel(0, (_PRCMU_BASE + PRCM_SEM));
+
+ spin_unlock_irqrestore(&clk_mgt_lock, flags);
+
+ return 0;
+}
+
+/**
+ * prcmu_abb_read() - Read register value(s) from the ABB.
+ * @slave: The I2C slave address.
+ * @reg: The (start) register address.
+ * @value: The read out value(s).
+ * @size: The number of registers to read.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ int r;
+
+ if (size != 1)
+ return -EINVAL;
+
+ mutex_lock(&mb5_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+ cpu_relax();
+
+ writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
+ writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
+ writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
+ writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
+
+ writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+
+ if (!wait_for_completion_timeout(&mb5_transfer.work,
+ msecs_to_jiffies(20000))) {
+ pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ __func__);
+ r = -EIO;
+ } else {
+ r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
+ }
+
+ if (!r)
+ *value = mb5_transfer.ack.value;
+
+ mutex_unlock(&mb5_transfer.lock);
+
+ return r;
+}
+
+/**
+ * prcmu_abb_write() - Write register value(s) to the ABB.
+ * @slave: The I2C slave address.
+ * @reg: The (start) register address.
+ * @value: The value(s) to write.
+ * @size: The number of registers to write.
+ *
+ * Reads register value(s) from the ABB.
+ * @size has to be 1 for the current firmware version.
+ */
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ int r;
+
+ if (size != 1)
+ return -EINVAL;
+
+ mutex_lock(&mb5_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+ cpu_relax();
+
+ writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
+ writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
+ writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
+ writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
+
+ writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+
+ if (!wait_for_completion_timeout(&mb5_transfer.work,
+ msecs_to_jiffies(20000))) {
+ pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ __func__);
+ r = -EIO;
+ } else {
+ r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
+ }
+
+ mutex_unlock(&mb5_transfer.lock);
+
+ return r;
+}
+
+/**
+ * prcmu_ac_wake_req - should be called whenever ARM wants to wakeup Modem
+ */
+void prcmu_ac_wake_req(void)
+{
+ u32 val;
+
+ mutex_lock(&mb0_transfer.ac_wake_lock);
+
+ val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ);
+ if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)
+ goto unlock_and_return;
+
+ atomic_set(&ac_wake_req_state, 1);
+
+ writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
+ (_PRCMU_BASE + PRCM_HOSTACCESS_REQ));
+
+ if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
+ msecs_to_jiffies(20000))) {
+ pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ __func__);
+ }
+
+unlock_and_return:
+ mutex_unlock(&mb0_transfer.ac_wake_lock);
+}
+
+/**
+ * prcmu_ac_sleep_req - called when ARM no longer needs to talk to modem
+ */
+void prcmu_ac_sleep_req()
+{
+ u32 val;
+
+ mutex_lock(&mb0_transfer.ac_wake_lock);
+
+ val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ);
+ if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ))
+ goto unlock_and_return;
+
+ writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
+ (_PRCMU_BASE + PRCM_HOSTACCESS_REQ));
+
+ if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
+ msecs_to_jiffies(20000))) {
+ pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+ __func__);
+ }
+
+ atomic_set(&ac_wake_req_state, 0);
+
+unlock_and_return:
+ mutex_unlock(&mb0_transfer.ac_wake_lock);
+}
+
+bool prcmu_is_ac_wake_requested(void)
+{
+ return (atomic_read(&ac_wake_req_state) != 0);
+}
+
+/**
+ * prcmu_system_reset - System reset
+ *
+ * Saves the reset reason code and then sets the APE_SOFRST register which
+ * fires interrupt to fw
+ */
+void prcmu_system_reset(u16 reset_code)
+{
+ writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON));
+ writel(1, (_PRCMU_BASE + PRCM_APE_SOFTRST));
+}
+
+/**
+ * prcmu_reset_modem - ask the PRCMU to reset modem
+ */
+void prcmu_modem_reset(void)
+{
+ mutex_lock(&mb1_transfer.lock);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+ cpu_relax();
+
+ writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+ writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+ wait_for_completion(&mb1_transfer.work);
+
+ /*
+ * No need to check return from PRCMU as modem should go in reset state
+ * This state is already managed by upper layer
+ */
+
+ mutex_unlock(&mb1_transfer.lock);
+}
+
+static void ack_dbb_wakeup(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+ cpu_relax();
+
+ writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
+ writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+}
+
+static inline void print_unknown_header_warning(u8 n, u8 header)
+{
+ pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n",
+ header, n);
+}
+
+static bool read_mailbox_0(void)
+{
+ bool r;
+ u32 ev;
+ unsigned int n;
+ u8 header;
+
+ header = readb(tcdm_base + PRCM_MBOX_HEADER_ACK_MB0);
+ switch (header) {
+ case MB0H_WAKEUP_EXE:
+ case MB0H_WAKEUP_SLEEP:
+ if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
+ ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_1_8500);
+ else
+ ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_0_8500);
+
+ if (ev & (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK))
+ complete(&mb0_transfer.ac_wake_work);
+ if (ev & WAKEUP_BIT_SYSCLK_OK)
+ complete(&mb3_transfer.sysclk_work);
+
+ ev &= mb0_transfer.req.dbb_irqs;
+
+ for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
+ if (ev & prcmu_irq_bit[n])
+ generic_handle_irq(IRQ_PRCMU_BASE + n);
+ }
+ r = true;
+ break;
+ default:
+ print_unknown_header_warning(0, header);
+ r = false;
+ break;
+ }
+ writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+ return r;
+}
+
+static bool read_mailbox_1(void)
+{
+ mb1_transfer.ack.header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB1);
+ mb1_transfer.ack.arm_opp = readb(tcdm_base +
+ PRCM_ACK_MB1_CURRENT_ARM_OPP);
+ mb1_transfer.ack.ape_opp = readb(tcdm_base +
+ PRCM_ACK_MB1_CURRENT_APE_OPP);
+ mb1_transfer.ack.ape_voltage_status = readb(tcdm_base +
+ PRCM_ACK_MB1_APE_VOLTAGE_STATUS);
+ writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+ complete(&mb1_transfer.work);
+ return false;
+}
+
+static bool read_mailbox_2(void)
+{
+ mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS);
+ writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+ complete(&mb2_transfer.work);
+ return false;
+}
+
+static bool read_mailbox_3(void)
+{
+ writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+ return false;
+}
+
+static bool read_mailbox_4(void)
+{
+ u8 header;
+ bool do_complete = true;
+
+ header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB4);
+ switch (header) {
+ case MB4H_MEM_ST:
+ case MB4H_HOTDOG:
+ case MB4H_HOTMON:
+ case MB4H_HOT_PERIOD:
+ break;
+ default:
+ print_unknown_header_warning(4, header);
+ do_complete = false;
+ break;
+ }
+
+ writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+
+ if (do_complete)
+ complete(&mb4_transfer.work);
+
+ return false;
+}
+
+static bool read_mailbox_5(void)
+{
+ mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS);
+ mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL);
+ writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+ complete(&mb5_transfer.work);
+ return false;
+}
+
+static bool read_mailbox_6(void)
+{
+ writel(MBOX_BIT(6), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+ return false;
+}
+
+static bool read_mailbox_7(void)
+{
+ writel(MBOX_BIT(7), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+ return false;
+}
+
+static bool (* const read_mailbox[NUM_MB])(void) = {
+ read_mailbox_0,
+ read_mailbox_1,
+ read_mailbox_2,
+ read_mailbox_3,
+ read_mailbox_4,
+ read_mailbox_5,
+ read_mailbox_6,
+ read_mailbox_7
+};
+
+static irqreturn_t prcmu_irq_handler(int irq, void *data)
+{
+ u32 bits;
+ u8 n;
+ irqreturn_t r;
+
+ bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
+ if (unlikely(!bits))
+ return IRQ_NONE;
+
+ r = IRQ_HANDLED;
+ for (n = 0; bits; n++) {
+ if (bits & MBOX_BIT(n)) {
+ bits -= MBOX_BIT(n);
+ if (read_mailbox[n]())
+ r = IRQ_WAKE_THREAD;
+ }
+ }
+ return r;
+}
+
+static irqreturn_t prcmu_irq_thread_fn(int irq, void *data)
+{
+ ack_dbb_wakeup();
+ return IRQ_HANDLED;
+}
+
+static void prcmu_mask_work(struct work_struct *work)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.lock, flags);
+
+ config_wakeups();
+
+ spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+}
+
+static void prcmu_irq_mask(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
+
+ mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[irq - IRQ_PRCMU_BASE];
+
+ spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
+
+ if (irq != IRQ_PRCMU_CA_SLEEP)
+ schedule_work(&mb0_transfer.mask_work);
+}
+
+static void prcmu_irq_unmask(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
+
+ mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[irq - IRQ_PRCMU_BASE];
+
+ spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
+
+ if (irq != IRQ_PRCMU_CA_SLEEP)
+ schedule_work(&mb0_transfer.mask_work);
+}
+
+static void noop(unsigned int irq)
+{
+}
+
+static struct irq_chip prcmu_irq_chip = {
+ .name = "prcmu",
+ .disable = prcmu_irq_mask,
+ .ack = noop,
+ .mask = prcmu_irq_mask,
+ .unmask = prcmu_irq_unmask,
+};
+
+void __init prcmu_early_init(void)
+{
+ unsigned int i;
+
+ if (cpu_is_u8500v1()) {
+ tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1);
+ } else if (cpu_is_u8500v2()) {
+ void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
+
+ if (tcpm_base != NULL) {
+ int version;
+ version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET);
+ prcmu_version.project_number = version & 0xFF;
+ prcmu_version.api_version = (version >> 8) & 0xFF;
+ prcmu_version.func_version = (version >> 16) & 0xFF;
+ prcmu_version.errata = (version >> 24) & 0xFF;
+ pr_info("PRCMU firmware version %d.%d.%d\n",
+ (version >> 8) & 0xFF, (version >> 16) & 0xFF,
+ (version >> 24) & 0xFF);
+ iounmap(tcpm_base);
+ }
+
+ tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
+ } else {
+ pr_err("prcmu: Unsupported chip version\n");
+ BUG();
+ }
+
+ spin_lock_init(&mb0_transfer.lock);
+ spin_lock_init(&mb0_transfer.dbb_irqs_lock);
+ mutex_init(&mb0_transfer.ac_wake_lock);
+ init_completion(&mb0_transfer.ac_wake_work);
+ mutex_init(&mb1_transfer.lock);
+ init_completion(&mb1_transfer.work);
+ mutex_init(&mb2_transfer.lock);
+ init_completion(&mb2_transfer.work);
+ spin_lock_init(&mb2_transfer.auto_pm_lock);
+ spin_lock_init(&mb3_transfer.lock);
+ mutex_init(&mb3_transfer.sysclk_lock);
+ init_completion(&mb3_transfer.sysclk_work);
+ mutex_init(&mb4_transfer.lock);
+ init_completion(&mb4_transfer.work);
+ mutex_init(&mb5_transfer.lock);
+ init_completion(&mb5_transfer.work);
+
+ INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
+
+ /* Initalize irqs. */
+ for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) {
+ unsigned int irq;
+
+ irq = IRQ_PRCMU_BASE + i;
+ set_irq_chip(irq, &prcmu_irq_chip);
+ set_irq_flags(irq, IRQF_VALID);
+ set_irq_handler(irq, handle_simple_irq);
+ }
+}
+
+/**
+ * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
+ *
+ */
+int __init prcmu_init(void)
+{
+ int err = 0;
+
+ if (ux500_is_svp())
+ return -ENODEV;
+
+ /* Clean up the mailbox interrupts after pre-kernel code. */
+ writel(ALL_MBOX_BITS, (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+
+ err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler,
+ prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
+ if (err < 0) {
+ pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n");
+ err = -EBUSY;
+ goto no_irq_return;
+ }
+
+ prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
+
+ if (prcmu_debug_init())
+ pr_err("prcmu: Failed to initialize debugfs\n");
+
+no_irq_return:
+ return err;
+}
+
+arch_initcall(prcmu_init);
diff --git a/arch/arm/mach-ux500/prcmu-debug.c b/arch/arm/mach-ux500/prcmu-debug.c
new file mode 100644
index 00000000000..0e45a2309d0
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu-debug.c
@@ -0,0 +1,503 @@
+/*
+ * 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-fw-api.h>
+
+enum ape_opp_debug {
+ APE_50_OPP_DEBUG,
+ APE_100_OPP_DEBUG,
+ NUM_APE_OPP_DEBUG,
+};
+
+enum ddr_opp_debug {
+ DDR_25_OPP_DEBUG,
+ DDR_50_OPP_DEBUG,
+ DDR_100_OPP_DEBUG,
+ NUM_DDR_OPP_DEBUG,
+};
+
+struct ape_state_history {
+ ktime_t start;
+ u32 state;
+ u32 counter[NUM_APE_OPP_DEBUG];
+ ktime_t time[NUM_APE_OPP_DEBUG];
+ spinlock_t lock;
+};
+
+struct ddr_state_history {
+ ktime_t start;
+ u32 state;
+ u32 counter[NUM_DDR_OPP_DEBUG];
+ ktime_t time[NUM_DDR_OPP_DEBUG];
+ spinlock_t lock;
+};
+
+static struct ape_state_history *ape_sh;
+static struct ddr_state_history *ddr_sh;
+
+void prcmu_debug_ape_opp_log(u8 opp)
+{
+ ktime_t now;
+ ktime_t dtime;
+ unsigned long flags;
+ int state;
+
+ if (opp == APE_50_OPP)
+ state = APE_50_OPP_DEBUG;
+ else
+ state = APE_100_OPP_DEBUG;
+
+ now = ktime_get();
+ spin_lock_irqsave(&ape_sh->lock, flags);
+
+ dtime = ktime_sub(now, ape_sh->start);
+ ape_sh->time[state] = ktime_add(ape_sh->time[state], dtime);
+ ape_sh->start = now;
+ ape_sh->counter[state]++;
+ ape_sh->state = state;
+
+ spin_unlock_irqrestore(&ape_sh->lock, flags);
+}
+
+void prcmu_debug_ddr_opp_log(u8 opp)
+{
+ ktime_t now;
+ ktime_t dtime;
+ unsigned long flags;
+ int state;
+
+ if (opp == DDR_25_OPP)
+ state = DDR_25_OPP_DEBUG;
+ else if (opp == DDR_50_OPP)
+ state = DDR_50_OPP_DEBUG;
+ else
+ state = DDR_100_OPP_DEBUG;
+
+ now = ktime_get();
+ spin_lock_irqsave(&ddr_sh->lock, flags);
+
+ dtime = ktime_sub(now, ddr_sh->start);
+ ddr_sh->time[state] = ktime_add(ddr_sh->time[state], dtime);
+ ddr_sh->start = now;
+ ddr_sh->counter[state]++;
+ ddr_sh->state = state;
+
+ spin_unlock_irqrestore(&ddr_sh->lock, flags);
+}
+
+static ssize_t ape_stats_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long flags;
+ int i;
+
+ pr_info("/nreset\n");
+
+ spin_lock_irqsave(&ape_sh->lock, flags);
+ for (i = 0; i < NUM_APE_OPP_DEBUG; i++) {
+ ape_sh->counter[i] = 0;
+ ape_sh->time[i] = ktime_set(0, 0);
+ }
+
+ ape_sh->start = ktime_get();
+ spin_unlock_irqrestore(&ape_sh->lock, flags);
+
+ return count;
+}
+
+static ssize_t ddr_stats_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long flags;
+ int i;
+
+ pr_info("/nreset\n");
+
+ spin_lock_irqsave(&ddr_sh->lock, flags);
+ for (i = 0; i < NUM_DDR_OPP_DEBUG; i++) {
+ ddr_sh->counter[i] = 0;
+ ddr_sh->time[i] = ktime_set(0, 0);
+ }
+
+ ddr_sh->start = ktime_get();
+ spin_unlock_irqrestore(&ddr_sh->lock, flags);
+
+ return count;
+}
+
+static int ape_stats_print(struct seq_file *s, void *p)
+{
+ int i;
+ unsigned long flags;
+ ktime_t total;
+ ktime_t now;
+ ktime_t dtime;
+ s64 t_us;
+ s64 perc;
+ s64 total_us;
+
+ spin_lock_irqsave(&ape_sh->lock, flags);
+ /* Update time in state */
+ now = ktime_get();
+ dtime = ktime_sub(now, ape_sh->start);
+ ape_sh->time[ape_sh->state] =
+ ktime_add(ape_sh->time[ape_sh->state], dtime);
+ ape_sh->start = now;
+
+ /* Now print the stats */
+ total = ktime_set(0, 0);
+
+ for (i = 0; i < NUM_APE_OPP_DEBUG; i++)
+ total = ktime_add(total, ape_sh->time[i]);
+ total_us = ktime_to_us(total);
+ do_div(total_us, 100);
+
+ for (i = 0; i < NUM_APE_OPP_DEBUG; i++) {
+ t_us = ktime_to_us(ape_sh->time[i]);
+ perc = ktime_to_us(ape_sh->time[i]);
+ do_div(t_us, 1000); /* to ms */
+ do_div(perc, total_us);
+ if (i == APE_50_OPP_DEBUG)
+ seq_printf(s, "%s: # %u in %d ms %d%%\n",
+ "APE OPP 50% ",
+ ape_sh->counter[i],
+ (u32) t_us, (u32)perc);
+ else
+ seq_printf(s, "%s: # %u in %d ms %d%%\n",
+ "APE OPP 100%",
+ ape_sh->counter[i],
+ (u32) t_us, (u32)perc);
+
+ }
+ spin_unlock_irqrestore(&ape_sh->lock, flags);
+ return 0;
+}
+
+static int ddr_stats_print(struct seq_file *s, void *p)
+{
+ int i;
+ unsigned long flags;
+ ktime_t total;
+ ktime_t now;
+ ktime_t dtime;
+ s64 t_us;
+ s64 perc;
+ s64 total_us;
+
+ spin_lock_irqsave(&ddr_sh->lock, flags);
+ /* Update time in state */
+ now = ktime_get();
+ dtime = ktime_sub(now, ddr_sh->start);
+ ddr_sh->time[ddr_sh->state] =
+ ktime_add(ddr_sh->time[ddr_sh->state], dtime);
+ ddr_sh->start = now;
+
+ /* Now print the stats */
+ total = ktime_set(0, 0);
+
+ for (i = 0; i < NUM_DDR_OPP_DEBUG; i++)
+ total = ktime_add(total, ddr_sh->time[i]);
+ total_us = ktime_to_us(total);
+ do_div(total_us, 100);
+
+ for (i = 0; i < NUM_DDR_OPP_DEBUG; i++) {
+ t_us = ktime_to_us(ddr_sh->time[i]);
+ perc = ktime_to_us(ddr_sh->time[i]);
+ do_div(t_us, 1000); /* to ms */
+ do_div(perc, total_us);
+ if (i == DDR_25_OPP_DEBUG)
+ seq_printf(s, "%s: # %u in %d ms %d%%\n",
+ "DDR OPP 25% ",
+ ddr_sh->counter[i],
+ (u32) t_us, (u32)perc);
+ else if (i == DDR_50_OPP_DEBUG)
+ seq_printf(s, "%s: # %u in %d ms %d%%\n",
+ "DDR OPP 50% ",
+ ddr_sh->counter[i],
+ (u32) t_us, (u32)perc);
+ else
+ seq_printf(s, "%s: # %u in %d ms %d%%\n",
+ "DDR OPP 100%",
+ ddr_sh->counter[i],
+ (u32) t_us, (u32)perc);
+
+ }
+ spin_unlock_irqrestore(&ddr_sh->lock, flags);
+ return 0;
+}
+
+static int arm_opp_read(struct seq_file *s, void *p)
+{
+ int opp;
+
+ opp = prcmu_get_arm_opp();
+ return 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);
+}
+
+static int ape_opp_read(struct seq_file *s, void *p)
+{
+ int opp;
+
+ opp = prcmu_get_ape_opp();
+ return seq_printf(s, "%s (%d)\n",
+ (opp == APE_100_OPP) ? "100%" :
+ (opp == APE_50_OPP) ? "50%" :
+ "unknown", opp);
+}
+
+static int ddr_opp_read(struct seq_file *s, void *p)
+{
+ int opp;
+
+ opp = prcmu_get_ddr_opp();
+ return seq_printf(s, "%s (%d)\n",
+ (opp == DDR_100_OPP) ? "100%" :
+ (opp == DDR_50_OPP) ? "50%" :
+ (opp == DDR_25_OPP) ? "25%" :
+ "unknown", opp);
+}
+
+static ssize_t opp_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos, int prcmu_qos_class)
+{
+ char buf[32];
+ ssize_t buf_size;
+ long unsigned int i;
+
+ /* Get userspace string and assure termination */
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if (strict_strtoul(buf, 0, &i) != 0)
+ return buf_size;
+
+ prcmu_qos_force_opp(prcmu_qos_class, i);
+
+ pr_info("prcmu debug: forced OPP for %d to %d\n", prcmu_qos_class, (int)i);
+
+ return buf_size;
+}
+
+static ssize_t ddr_opp_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return opp_write(file, user_buf, count, ppos, PRCMU_QOS_DDR_OPP);
+}
+
+static ssize_t ape_opp_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ return opp_write(file, user_buf, count, ppos, PRCMU_QOS_APE_OPP);
+}
+
+static int cpufreq_delay_read(struct seq_file *s, void *p)
+{
+ return seq_printf(s, "%lu\n", prcmu_qos_get_cpufreq_opp_delay());
+}
+
+static ssize_t cpufreq_delay_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+
+ char buf[32];
+ ssize_t buf_size;
+ long unsigned int i;
+
+ /* Get userspace string and assure termination */
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ if (strict_strtoul(buf, 0, &i) != 0)
+ return buf_size;
+
+ prcmu_qos_set_cpufreq_opp_delay(i);
+
+ pr_info("prcmu debug: changed delay between cpufreq change and QoS "
+ "requirement to %lu.\n", i);
+
+ return buf_size;
+}
+
+static int arm_opp_open_file(struct inode *inode, struct file *file)
+{
+ return single_open(file, arm_opp_read, inode->i_private);
+}
+
+static int ape_opp_open_file(struct inode *inode, struct file *file)
+{
+ return single_open(file, ape_opp_read, inode->i_private);
+}
+
+static int ddr_opp_open_file(struct inode *inode, struct file *file)
+{
+ return single_open(file, ddr_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 cpufreq_delay_open_file(struct inode *inode, struct file *file)
+{
+ return single_open(file, cpufreq_delay_read, inode->i_private);
+}
+
+static const struct file_operations arm_opp_fops = {
+ .open = arm_opp_open_file,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations ape_opp_fops = {
+ .open = ape_opp_open_file,
+ .write = ape_opp_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static const struct file_operations ddr_opp_fops = {
+ .open = ddr_opp_open_file,
+ .write = ddr_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 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 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("ape_opp", (S_IRUGO),
+ dir, NULL, &ape_opp_fops);
+ if (IS_ERR_OR_NULL(file))
+ goto fail;
+
+ file = debugfs_create_file("ddr_opp", (S_IRUGO),
+ dir, NULL, &ddr_opp_fops);
+ if (IS_ERR_OR_NULL(file))
+ goto fail;
+
+ file = debugfs_create_file("arm_opp", (S_IRUGO),
+ dir, NULL, &arm_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;
+
+ return 0;
+fail:
+ if ((file == NULL) && (dir != NULL))
+ debugfs_remove_recursive(dir);
+
+ pr_err("prcmu debug: debugfs entry failed\n");
+ return -ENOMEM;
+}
+
+int prcmu_debug_init(void)
+{
+ ape_sh = kzalloc(sizeof(struct ape_state_history), GFP_KERNEL);
+ if (ape_sh < 0) {
+ pr_err("prcmu debug: kzalloc failed\n");
+ return -ENOMEM;
+ }
+
+ ddr_sh = kzalloc(sizeof(struct ddr_state_history), GFP_KERNEL);
+ if (ddr_sh < 0) {
+ pr_err("prcmu debug: kzalloc failed\n");
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&ape_sh->lock);
+ spin_lock_init(&ddr_sh->lock);
+ ape_sh->start = ktime_get();
+ ddr_sh->start = ktime_get();
+ setup_debugfs();
+ return 0;
+}
diff --git a/arch/arm/mach-ux500/prcmu-debug.h b/arch/arm/mach-ux500/prcmu-debug.h
new file mode 100644
index 00000000000..c536aed1f6b
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu-debug.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Martin Persson <martin.persson@stericsson.com> for ST-Ericsson
+ * Etienne Carriere <etienne.carriere@stericsson.com> for ST-Ericsson
+ *
+ */
+
+#ifndef PRCMU_DEBUG_H
+#define PRCMU_DEBUG_H
+
+#ifdef CONFIG_UX500_PRCMU_DEBUG
+void prcmu_debug_ape_opp_log(u8 opp);
+void prcmu_debug_ddr_opp_log(u8 opp);
+int prcmu_debug_init(void);
+#else
+static inline void prcmu_debug_ape_opp_log(u8 opp) {}
+static inline void prcmu_debug_ddr_opp_log(u8 opp) {}
+static inline int prcmu_debug_init(void) {}
+#endif
+#endif
diff --git a/arch/arm/mach-ux500/prcmu-qos-power.c b/arch/arm/mach-ux500/prcmu-qos-power.c
new file mode 100644
index 00000000000..c7fa4160f62
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu-qos-power.c
@@ -0,0 +1,568 @@
+/*
+ * 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 "prcmu-debug.h"
+#include <mach/prcmu-fw-api.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 *prcmu_qos_array[] = {
+ &null_qos,
+ &ape_opp_qos,
+ &ddr_opp_qos
+};
+
+static DEFINE_SPINLOCK(prcmu_qos_lock);
+
+static unsigned long cpufreq_opp_delay = HZ / 5;
+
+unsigned long prcmu_qos_get_cpufreq_opp_delay()
+{
+ 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 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;
+ int update = 0;
+ u8 op;
+
+ 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 = 1;
+ } 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 = 1;
+ 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) {
+ blocking_notifier_call_chain(prcmu_qos_array[target]->notifiers,
+ (unsigned long)extreme_value, NULL);
+
+ if (target == PRCMU_QOS_DDR_OPP) {
+ switch (extreme_value) {
+ case 25:
+ op = DDR_25_OPP;
+ pr_debug("prcmu qos: set ddr opp to 25%%\n");
+ break;
+ 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;
+ default:
+ pr_err("prcmu qos: Incorrect ddr target value (%d)",
+ extreme_value);
+ return;
+ }
+ prcmu_debug_ddr_opp_log(op);
+ prcmu_set_ddr_opp(op);
+ } else {
+ 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);
+ return;
+ }
+ prcmu_set_ape_opp(op);
+ prcmu_debug_ape_opp_log(op);
+ }
+ }
+}
+
+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);
+}
+
+/**
+ * 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 < 0)
+ 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;
+
+ 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;
+
+ 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;
+
+ 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/prcmu-regs-db5500.h b/arch/arm/mach-ux500/prcmu-regs-db5500.h
new file mode 100644
index 00000000000..c18e482d136
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu-regs-db5500.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ */
+
+#ifndef __MACH_PRCMU_REGS_DB5500_H
+#define __MACH_PRCMU_REGS_DB5500_H
+
+#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
+
+#define PRCM_TCR 0x1C8
+#define PRCM_TCR_TENSEL_MASK BITS(0, 7)
+#define PRCM_TCR_STOP_TIMERS BIT(16)
+#define PRCM_TCR_DOZE_MODE BIT(17)
+
+/* PRCMU HW semaphore */
+#define PRCM_SEM 0x400
+#define PRCM_SEM_PRCM_SEM BIT(0)
+
+#define DB5500_PRCM_SGACLK_MGT 0x014
+#define DB5500_PRCM_UARTCLK_MGT 0x018
+#define DB5500_PRCM_MSP02CLK_MGT 0x01C
+#define DB5500_PRCM_I2CCLK_MGT 0x020
+#define DB5500_PRCM_SDMMCCLK_MGT 0x024
+#define DB5500_PRCM_PER1CLK_MGT 0x02C
+#define DB5500_PRCM_PER2CLK_MGT 0x030
+#define DB5500_PRCM_PER3CLK_MGT 0x034
+#define DB5500_PRCM_PER5CLK_MGT 0x038
+#define DB5500_PRCM_PER6CLK_MGT 0x03C
+#define DB5500_PRCM_PWMCLK_MGT 0x044
+#define DB5500_PRCM_IRDACLK_MGT 0x048
+#define DB5500_PRCM_IRRCCLK_MGT 0x04C
+#define DB5500_PRCM_HDMICLK_MGT 0x058
+#define DB5500_PRCM_APEATCLK_MGT 0x05C
+#define DB5500_PRCM_APETRACECLK_MGT 0x060
+#define DB5500_PRCM_MCDECLK_MGT 0x064
+#define DB5500_PRCM_DSIALTCLK_MGT 0x06C
+#define DB5500_PRCM_DMACLK_MGT 0x074
+#define DB5500_PRCM_B2R2CLK_MGT 0x078
+#define DB5500_PRCM_TVCLK_MGT 0x07C
+#define DB5500_PRCM_RNGCLK_MGT 0x284
+
+#define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4)
+#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7)
+#define PRCM_CLK_MGT_CLKEN BIT(8)
+
+#endif
diff --git a/arch/arm/mach-ux500/prcmu-regs-db8500.h b/arch/arm/mach-ux500/prcmu-regs-db8500.h
new file mode 100644
index 00000000000..7ae1218f6ba
--- /dev/null
+++ b/arch/arm/mach-ux500/prcmu-regs-db8500.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2009 ST-Ericsson SA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+#ifndef __MACH_PRCMU_REGS_H
+#define __MACH_PRCMU_REGS_H
+
+#include <linux/bitops.h>
+#include <mach/hardware.h>
+
+#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
+
+#define PRCM_ARM_PLLDIVPS 0x118
+#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE BITS(0, 5)
+#define PRCM_ARM_PLLDIVPS_MAX_MASK 0xF
+
+#define PRCM_PLLARM_LOCKP 0x0A8
+#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 BIT(1)
+
+#define PRCM_ARM_CHGCLKREQ 0x114
+#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0)
+
+#define PRCM_PLLARM_ENABLE 0x98
+#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE BIT(0)
+#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON BIT(8)
+
+#define PRCM_ARMCLKFIX_MGT 0x0
+#define PRCM_A9_RESETN_CLR 0x1f4
+#define PRCM_A9_RESETN_SET 0x1f0
+#define PRCM_ARM_LS_CLAMP 0x30C
+#define PRCM_SRAM_A9 0x308
+
+/* ARM WFI Standby signal register */
+#define PRCM_ARM_WFI_STANDBY 0x130
+#define PRCM_IOCR 0x310
+#define PRCM_IOCR_IOFORCE BIT(0)
+
+/* CPU mailbox registers */
+#define PRCM_MBOX_CPU_VAL 0x0FC
+#define PRCM_MBOX_CPU_SET 0x100
+
+/* Dual A9 core interrupt management unit registers */
+#define PRCM_A9_MASK_REQ 0x328
+#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ BIT(0)
+
+#define PRCM_A9_MASK_ACK 0x32C
+#define PRCM_ARMITMSK31TO0 0x11C
+#define PRCM_ARMITMSK63TO32 0x120
+#define PRCM_ARMITMSK95TO64 0x124
+#define PRCM_ARMITMSK127TO96 0x128
+#define PRCM_POWER_STATE_VAL 0x25C
+#define PRCM_ARMITVAL31TO0 0x260
+#define PRCM_ARMITVAL63TO32 0x264
+#define PRCM_ARMITVAL95TO64 0x268
+#define PRCM_ARMITVAL127TO96 0x26C
+
+#define PRCM_HOSTACCESS_REQ 0x334
+#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ BIT(0)
+
+#define PRCM_ARM_IT1_CLR 0x48C
+#define PRCM_ARM_IT1_VAL 0x494
+
+#define PRCM_ITSTATUS0 0x148
+#define PRCM_ITSTATUS1 0x150
+#define PRCM_ITSTATUS2 0x158
+#define PRCM_ITSTATUS3 0x160
+#define PRCM_ITSTATUS4 0x168
+#define PRCM_ITSTATUS5 0x484
+#define PRCM_ITCLEAR5 0x488
+#define PRCM_ARMIT_MASKXP70_IT 0x1018
+
+/* System reset register */
+#define PRCM_APE_SOFTRST 0x228
+
+/* Level shifter and clamp control registers */
+#define PRCM_MMIP_LS_CLAMP_SET 0x420
+#define PRCM_MMIP_LS_CLAMP_CLR 0x424
+
+/* PRCMU HW semaphore */
+#define PRCM_SEM 0x400
+#define PRCM_SEM_PRCM_SEM BIT(0)
+
+/* PRCMU clock/PLL/reset registers */
+#define PRCM_PLLDSI_FREQ 0x500
+#define PRCM_PLLDSI_ENABLE 0x504
+#define PRCM_PLLDSI_LOCKP 0x508
+#define PRCM_DSI_PLLOUT_SEL 0x530
+#define PRCM_DSITVCLK_DIV 0x52C
+#define PRCM_APE_RESETN_SET 0x1E4
+#define PRCM_APE_RESETN_CLR 0x1E8
+
+#define PRCM_TCR 0x1C8
+#define PRCM_TCR_TENSEL_MASK BITS(0, 7)
+#define PRCM_TCR_STOP_TIMERS BIT(16)
+#define PRCM_TCR_DOZE_MODE BIT(17)
+
+#define PRCM_CLKOCR 0x1CC
+#define PRCM_CLKOCR_CLKODIV0_SHIFT 0
+#define PRCM_CLKOCR_CLKODIV0_MASK BITS(0, 5)
+#define PRCM_CLKOCR_CLKOSEL0_SHIFT 6
+#define PRCM_CLKOCR_CLKOSEL0_MASK BITS(6, 8)
+#define PRCM_CLKOCR_CLKODIV1_SHIFT 16
+#define PRCM_CLKOCR_CLKODIV1_MASK BITS(16, 21)
+#define PRCM_CLKOCR_CLKOSEL1_SHIFT 22
+#define PRCM_CLKOCR_CLKOSEL1_MASK BITS(22, 24)
+#define PRCM_CLKOCR_CLK1TYPE BIT(28)
+
+#define PRCM_SGACLK_MGT 0x014
+#define PRCM_UARTCLK_MGT 0x018
+#define PRCM_MSP02CLK_MGT 0x01C
+#define PRCM_MSP1CLK_MGT 0x288
+#define PRCM_I2CCLK_MGT 0x020
+#define PRCM_SDMMCCLK_MGT 0x024
+#define PRCM_SLIMCLK_MGT 0x028
+#define PRCM_PER1CLK_MGT 0x02C
+#define PRCM_PER2CLK_MGT 0x030
+#define PRCM_PER3CLK_MGT 0x034
+#define PRCM_PER5CLK_MGT 0x038
+#define PRCM_PER6CLK_MGT 0x03C
+#define PRCM_PER7CLK_MGT 0x040
+#define PRCM_LCDCLK_MGT 0x044
+#define PRCM_BMLCLK_MGT 0x04C
+#define PRCM_HSITXCLK_MGT 0x050
+#define PRCM_HSIRXCLK_MGT 0x054
+#define PRCM_HDMICLK_MGT 0x058
+#define PRCM_APEATCLK_MGT 0x05C
+#define PRCM_APETRACECLK_MGT 0x060
+#define PRCM_MCDECLK_MGT 0x064
+#define PRCM_IPI2CCLK_MGT 0x068
+#define PRCM_DSIALTCLK_MGT 0x06C
+#define PRCM_DMACLK_MGT 0x074
+#define PRCM_B2R2CLK_MGT 0x078
+#define PRCM_TVCLK_MGT 0x07C
+#define PRCM_UNIPROCLK_MGT 0x278
+#define PRCM_SSPCLK_MGT 0x280
+#define PRCM_RNGCLK_MGT 0x284
+#define PRCM_UICCCLK_MGT 0x27C
+
+#define PRCM_CLK_MGT_CLKPLLDIV_MASK BITS(0, 4)
+#define PRCM_CLK_MGT_CLKPLLSW_MASK BITS(5, 7)
+#define PRCM_CLK_MGT_CLKEN BIT(8)
+
+/* ePOD and memory power signal control registers */
+#define PRCM_EPOD_C_SET 0x410
+#define PRCM_SRAM_LS_SLEEP 0x304
+
+/* Debug power control unit registers */
+#define PRCM_POWER_STATE_SET 0x254
+
+/* Miscellaneous unit registers */
+#define PRCM_DSI_SW_RESET 0x324
+#define PRCM_GPIOCR 0x138
+
+/* GPIOCR register */
+#define PRCM_GPIOCR_SPI2_SELECT BIT(23)
+
+#define PRCM_DDR_SUBSYS_APE_MINBW 0x438
+
+#endif /* __MACH_PRCMU__REGS_H */
diff --git a/arch/arm/mach-ux500/pwm.c b/arch/arm/mach-ux500/pwm.c
new file mode 100644
index 00000000000..37f6bd481c5
--- /dev/null
+++ b/arch/arm/mach-ux500/pwm.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Stefan Nilsson <stefan.xk.nilsson@stericsson.com> for
+ * ST-Ericsson.
+ * Author: Magnus Templing <magnus.templing@stericsson.com> for
+ * ST-Ericsson.
+ *
+ * PWM (Pulse Width Modulator) driver for the DB5500 digital baseband
+ * controller. Based on arch/arm/mach-pxa/pwm.c.
+ */
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+/* Register offsets */
+#define PWM_CONTROL_REG_OFFSET 0x00
+#define PWM_DUTY_REG_OFFSET 0x04
+#define PWM_PERIOD_REG_OFFSET 0x08
+#define PWM_BURST_REG_OFFSET 0x10
+#define PWM_SEQUENCE_REG_OFFSET 0x14
+#define PWM_DELAY_REG_OFFSET 0x18
+
+/* CONTROL_REG */
+#define PWM_CONTROL_REG_ENABLE_POS 0
+#define PWM_CONTROL_REG_CBM_POS 1
+#define PWM_CONTROL_REG_PRESCALER_POS 2
+#define PWM_CONTROL_REG_DISABLE 0
+#define PWM_CONTROL_REG_ENABLE 1
+#define PWM_CONTROL_REG_CBM_ENABLE 1
+
+#define PWM_BURST_REG_ONE_PULSE_PER_BURST 0
+#define PWM_SEQUENCE_REG_ONE_BURST_PER_SEQUENCE 0
+#define PWM_DELAY_REG_NO_DELAY 0
+#define PWM_PRESCALE 25
+
+struct pwm_device {
+ struct list_head node;
+ struct platform_device *pdev;
+
+ void __iomem *mmio_base;
+
+ unsigned int pwm_id;
+ unsigned int use_count;
+};
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+#if defined(CONFIG_DEBUG_FS)
+static void init_debugfs(void);
+#else
+#define init_debugfs(x)
+#endif
+
+/*
+ * PWM_CLK_RATE = 26000000 Hz
+ *
+ * period_ns = 10^9 * (PWM_PRESCALE + 1) * period / PWM_CLK_RATE
+ * duty_ns = 10^9 * (PWM_PRESCALE + 1) * dc / PWM_CLK_RATE
+ *
+ * period = period_ns * 26000000 / 10^9 / 26 => period = period_ns / 1000
+ * dc = duty_ns * 26000000 / 10^9 / 26 => dc = duty_ns / 1000
+ */
+#define MAGIC_DIVISOR (1000)
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+ u32 period;
+ u32 dc;
+
+ dev_dbg(&pwm->pdev->dev, "%s duty_ns: %d period_ns: %d\n",
+ __func__, duty_ns, period_ns);
+
+ if (pwm == NULL || period_ns == 0 || duty_ns >= period_ns) {
+ dev_err(&pwm->pdev->dev, "%s INVALID ARGUMENTS!\n", __func__);
+ return -EINVAL;
+ }
+
+ period = period_ns / MAGIC_DIVISOR;
+ dc = duty_ns / MAGIC_DIVISOR;
+
+ writel(period, pwm->mmio_base + PWM_PERIOD_REG_OFFSET);
+ writel(dc, pwm->mmio_base + PWM_DUTY_REG_OFFSET);
+ writel(PWM_BURST_REG_ONE_PULSE_PER_BURST,
+ pwm->mmio_base + PWM_BURST_REG_OFFSET);
+ writel(PWM_SEQUENCE_REG_ONE_BURST_PER_SEQUENCE,
+ pwm->mmio_base + PWM_SEQUENCE_REG_OFFSET);
+ writel(PWM_DELAY_REG_NO_DELAY, pwm->mmio_base + PWM_DELAY_REG_OFFSET);
+
+ return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+ u32 val;
+
+ val = (PWM_CONTROL_REG_ENABLE << PWM_CONTROL_REG_ENABLE_POS);
+ val |= (PWM_CONTROL_REG_CBM_ENABLE << PWM_CONTROL_REG_CBM_POS);
+ val |= (PWM_PRESCALE << PWM_CONTROL_REG_PRESCALER_POS);
+
+ writel(val, pwm->mmio_base + PWM_CONTROL_REG_OFFSET);
+
+ return 0;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+ writel(PWM_CONTROL_REG_DISABLE,
+ pwm->mmio_base + PWM_CONTROL_REG_OFFSET);
+}
+EXPORT_SYMBOL(pwm_disable);
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+ struct pwm_device *pwm;
+ bool found = false;
+
+ mutex_lock(&pwm_lock);
+
+ list_for_each_entry(pwm, &pwm_list, node) {
+ if (pwm->pwm_id == pwm_id) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ if (pwm->use_count == 0)
+ pwm->use_count++;
+ else
+ pwm = ERR_PTR(-EBUSY);
+ } else {
+ pwm = ERR_PTR(-ENOENT);
+ }
+
+ mutex_unlock(&pwm_lock);
+ return pwm;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+ mutex_lock(&pwm_lock);
+
+ if (pwm->use_count)
+ pwm->use_count--;
+ else
+ dev_warn(&pwm->pdev->dev, "PWM device already freed\n");
+
+ mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_free);
+
+int __init pwm_probe(struct platform_device *pdev)
+{
+ struct pwm_device *pwm;
+ struct resource *r;
+ int ret = 0;
+
+ dev_dbg(&pdev->dev, "%s\n", __func__);
+
+ pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
+ if (pwm == NULL) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ pwm->pwm_id = pdev->id;
+ pwm->pdev = pdev;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (r == NULL) {
+ dev_err(&pdev->dev, "no memory resource defined\n");
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ pwm->mmio_base = ioremap(r->start, resource_size(r));
+ if (pwm->mmio_base == NULL) {
+ dev_err(&pdev->dev, "failed to ioremap() registers\n");
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ mutex_lock(&pwm_lock);
+ list_add_tail(&pwm->node, &pwm_list);
+ mutex_unlock(&pwm_lock);
+
+ platform_set_drvdata(pdev, pwm);
+
+ init_debugfs();
+
+ return 0;
+
+err_free:
+ kfree(pwm);
+ return ret;
+}
+
+static int __devexit pwm_remove(struct platform_device *pdev)
+{
+ struct pwm_device *pwm;
+
+ pwm = platform_get_drvdata(pdev);
+ if (pwm == NULL)
+ return -ENODEV;
+
+ mutex_lock(&pwm_lock);
+ list_del(&pwm->node);
+ mutex_unlock(&pwm_lock);
+
+ iounmap(pwm->mmio_base);
+
+ kfree(pwm);
+ return 0;
+}
+
+static struct platform_driver pwm_driver = {
+ .driver = {
+ .name = "pwm",
+ .owner = THIS_MODULE,
+ },
+ .remove = __devexit_p(pwm_remove),
+};
+
+static int __init pwm_init(void)
+{
+ int ret = 0;
+
+ ret = platform_driver_probe(&pwm_driver, pwm_probe);
+ if (ret) {
+ pr_err("PWM: probe failed ret=%d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+static int pwm_dump(struct seq_file *s, void *data)
+{
+ struct list_head *pos;
+ struct pwm_device *pwm;
+ int pwm_index = 0;
+
+ mutex_lock(&pwm_lock);
+
+ list_for_each(pos, &pwm_list) {
+ pwm = (struct pwm_device *)
+ list_entry(pos, struct pwm_device, node);
+
+ seq_printf(s, "===========================\n"
+ " PWM DUMP %d\n"
+ " mmio_base: 0x%p\n"
+ " CONTROL : 0x%X\n"
+ " DUTY : 0x%X\n"
+ " PERIOD : 0x%X\n"
+ " BURST : 0x%X\n"
+ " SEQUENCE : 0x%X\n"
+ " DELAY : 0x%X\n",
+ pwm_index,
+ pwm->mmio_base,
+ readl(pwm->mmio_base + PWM_CONTROL_REG_OFFSET),
+ readl(pwm->mmio_base + PWM_DUTY_REG_OFFSET),
+ readl(pwm->mmio_base + PWM_PERIOD_REG_OFFSET),
+ readl(pwm->mmio_base + PWM_BURST_REG_OFFSET),
+ readl(pwm->mmio_base + PWM_SEQUENCE_REG_OFFSET),
+ readl(pwm->mmio_base + PWM_DELAY_REG_OFFSET));
+ pwm_index++;
+ }
+
+ mutex_unlock(&pwm_lock);
+
+ return 0;
+}
+
+static int pwm_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pwm_dump, NULL);
+}
+
+static int get_value(char **c, char *s, int *v)
+{
+ char *val;
+ long value;
+ int ret = -1;
+
+ if (c != NULL) {
+ val = strsep(c, s);
+
+ if (val) {
+ ret = strict_strtol(val, 10, &value);
+
+ if (!ret)
+ *v = value;
+ }
+ }
+
+ return ret;
+}
+
+#define MAX_BUFFER_SIZE 64
+
+static int pwm_write_raw(struct file *file, const char __user *buffer,
+ size_t size, loff_t *offset)
+{
+ char int_buf[MAX_BUFFER_SIZE];
+ char *token;
+ u32 period;
+ u32 dc;
+ u32 burst;
+ u32 seq;
+ u32 delay;
+ u32 ctrl;
+ int max_size = max(size, strlen(buffer));
+
+ struct pwm_device *pwm = (struct pwm_device *)
+ list_first_entry(&pwm_list, struct pwm_device, node);
+
+ /* Copy the buffer since strsep alters it */
+ strncpy((char *) &int_buf, (char*)buffer, max_size);
+
+ token = (char *) &int_buf;
+
+ if (get_value(&token, " ", &period)) {
+ dev_err(&pwm->pdev->dev, "%s 1\n", __func__);
+ return size;
+ }
+
+ if (get_value(&token, " ", &dc)) {
+ dev_err(&pwm->pdev->dev, "%s 2\n", __func__);
+ return size;
+ }
+
+ if (get_value(&token, " ", &burst)) {
+ dev_err(&pwm->pdev->dev, "%s 3\n", __func__);
+ return size;
+ }
+
+ if (get_value(&token, " ", &seq)) {
+ dev_err(&pwm->pdev->dev, "%s 4\n", __func__);
+ return size;
+ }
+
+ if (get_value(&token, " ", &delay)) {
+ dev_err(&pwm->pdev->dev, "%s 5\n", __func__);
+ return size;
+ }
+
+ if (get_value(&token, "\n", &ctrl)) {
+ dev_err(&pwm->pdev->dev, "%s 6\n", __func__);
+ return size;
+ }
+
+ dev_dbg(&pwm->pdev->dev,
+ "%s p: 0x%X d: 0x%X b: 0x%X s: 0x%X d: 0x%X c: 0x%X\n"
+ , __func__, period, dc, burst, seq, delay, ctrl);
+
+ writel(period, pwm->mmio_base + PWM_PERIOD_REG_OFFSET);
+ writel(dc , pwm->mmio_base + PWM_DUTY_REG_OFFSET);
+ writel(burst , pwm->mmio_base + PWM_BURST_REG_OFFSET);
+ writel(seq , pwm->mmio_base + PWM_SEQUENCE_REG_OFFSET);
+ writel(delay , pwm->mmio_base + PWM_DELAY_REG_OFFSET);
+ writel(ctrl , pwm->mmio_base + PWM_CONTROL_REG_OFFSET);
+
+ return size;
+}
+
+static int pwm_write(struct file *file,
+ const char __user *buffer,
+ size_t size, loff_t *offset)
+{
+ char int_buf[MAX_BUFFER_SIZE];
+ char *token;
+ u32 period = 0;
+ u32 dc = 0;
+ u32 ctrl = 0;
+ int max_size = max(size, strlen(buffer));
+
+ struct pwm_device *pwm = (struct pwm_device *)
+ list_first_entry(&pwm_list, struct pwm_device, node);
+
+ /* Copy the buffer since strsep alters it */
+ strncpy((char *) &int_buf, (char*)buffer, max((int) size, max_size));
+
+ token = (char *) &int_buf;
+
+ if (get_value(&token, " ", &period)) {
+ dev_err(&pwm->pdev->dev, "%s 1\n", __func__);
+ return size;
+ }
+
+ if (get_value(&token, " ", &dc)) {
+ dev_err(&pwm->pdev->dev, "%s 2\n", __func__);
+ return size;
+ }
+
+ if (get_value(&token, "\n", &ctrl)) {
+ dev_err(&pwm->pdev->dev, "%s 3\n", __func__);
+ return size;
+ }
+
+ dev_dbg(&pwm->pdev->dev, "%s p: 0x%X d: 0x%X c: 0x%X\n",
+ __func__, period, dc, ctrl);
+
+ if (ctrl == 0)
+ pwm_disable(pwm);
+ else {
+ pwm_config(pwm, dc, period);
+ pwm_enable(pwm);
+ }
+
+ return size;
+}
+
+static const struct file_operations pwm_operations = {
+ .owner = THIS_MODULE,
+ .open = pwm_open,
+ .read = seq_read,
+ .write = pwm_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations pwm_operations_raw = {
+ .owner = THIS_MODULE,
+ .open = pwm_open,
+ .read = seq_read,
+ .write = pwm_write_raw,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void init_debugfs(void)
+{
+ (void) debugfs_create_file("pwm_if", S_IFREG | S_IRUGO | S_IWUGO,
+ NULL, NULL, &pwm_operations);
+ (void) debugfs_create_file("pwm_raw", S_IFREG | S_IRUGO | S_IWUGO,
+ NULL, NULL, &pwm_operations_raw);
+}
+#endif
+
+module_init(pwm_init);
+
+static void __exit pwm_exit(void)
+{
+ platform_driver_unregister(&pwm_driver);
+}
+module_exit(pwm_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-ux500/reboot_reasons.c b/arch/arm/mach-ux500/reboot_reasons.c
new file mode 100644
index 00000000000..b625c6a615f
--- /dev/null
+++ b/arch/arm/mach-ux500/reboot_reasons.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ * Author: Rickard Evertsson <rickard.evertsson@stericsson.com>
+ * for ST-Ericsson.
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * Use this file to customize your reboot / sw reset reasons. Add, remove or
+ * modify reasons in reboot_reasons[].
+ */
+
+#include <linux/kernel.h>
+#include <mach/reboot_reasons.h>
+
+struct reboot_reason reboot_reasons[] = {
+ {"crash", SW_RESET_CRASH},
+ {"", SW_RESET_NORMAL}, /* Normal Boot */
+};
+
+unsigned int reboot_reasons_size = ARRAY_SIZE(reboot_reasons);
diff --git a/arch/arm/mach-ux500/regulator-u5500.c b/arch/arm/mach-ux500/regulator-u5500.c
new file mode 100644
index 00000000000..bd988c7c109
--- /dev/null
+++ b/arch/arm/mach-ux500/regulator-u5500.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <mach/prcmu-fw-api.h>
+
+#include "regulator-ux500.h"
+#include "regulator-u5500.h"
+
+static struct u8500_regulator_info
+u5500_regulator_info[U5500_NUM_REGULATORS] = {
+ [U5500_REGULATOR_VAPE] = {
+ .desc = {
+ .name = "u5500-vape",
+ .id = U5500_REGULATOR_VAPE,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ },
+};
+
+static int __devinit u5500_regulator_probe(struct platform_device *pdev)
+{
+ return ux500_regulator_probe(pdev, u5500_regulator_info,
+ ARRAY_SIZE(u5500_regulator_info));
+}
+
+static int __devexit u5500_regulator_remove(struct platform_device *pdev)
+{
+ return ux500_regulator_remove(pdev, u5500_regulator_info,
+ ARRAY_SIZE(u5500_regulator_info));
+}
+
+static struct platform_driver u5500_regulator_driver = {
+ .driver = {
+ .name = "u5500-regulators",
+ .owner = THIS_MODULE,
+ },
+ .probe = u5500_regulator_probe,
+ .remove = __devexit_p(u5500_regulator_remove),
+};
+
+static int __init u5500_regulator_init(void)
+{
+ return platform_driver_register(&u5500_regulator_driver);
+}
+
+static void __exit u5500_regulator_exit(void)
+{
+ platform_driver_unregister(&u5500_regulator_driver);
+}
+
+arch_initcall(u5500_regulator_init);
+module_exit(u5500_regulator_exit);
+
+MODULE_DESCRIPTION("U5500 regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-ux500/regulator-u5500.h b/arch/arm/mach-ux500/regulator-u5500.h
new file mode 100644
index 00000000000..2c363096d12
--- /dev/null
+++ b/arch/arm/mach-ux500/regulator-u5500.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ */
+
+#ifndef __REGULATOR_U5500_H
+#define __REGULATOR_U5500_H
+
+enum u5500_regulator_id {
+ U5500_REGULATOR_VAPE,
+ U5500_NUM_REGULATORS
+};
+
+#endif
diff --git a/arch/arm/mach-ux500/regulator-u8500.c b/arch/arm/mach-ux500/regulator-u8500.c
new file mode 100644
index 00000000000..fbbff443ba6
--- /dev/null
+++ b/arch/arm/mach-ux500/regulator-u8500.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <mach/prcmu-fw-api.h>
+
+#include "regulator-ux500.h"
+#include "regulator-u8500.h"
+
+static struct u8500_regulator_info
+ u8500_regulator_info[U8500_NUM_REGULATORS] = {
+ [U8500_REGULATOR_VAPE] = {
+ .desc = {
+ .name = "u8500-vape",
+ .id = U8500_REGULATOR_VAPE,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ },
+ [U8500_REGULATOR_VARM] = {
+ .desc = {
+ .name = "u8500-varm",
+ .id = U8500_REGULATOR_VARM,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ },
+ [U8500_REGULATOR_VMODEM] = {
+ .desc = {
+ .name = "u8500-vmodem",
+ .id = U8500_REGULATOR_VMODEM,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ },
+ [U8500_REGULATOR_VPLL] = {
+ .desc = {
+ .name = "u8500-vpll",
+ .id = U8500_REGULATOR_VPLL,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ },
+ [U8500_REGULATOR_VSMPS1] = {
+ .desc = {
+ .name = "u8500-vsmps1",
+ .id = U8500_REGULATOR_VSMPS1,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ },
+ [U8500_REGULATOR_VSMPS2] = {
+ .desc = {
+ .name = "u8500-vsmps2",
+ .id = U8500_REGULATOR_VSMPS2,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .exclude_from_power_state = true,
+ },
+ [U8500_REGULATOR_VSMPS3] = {
+ .desc = {
+ .name = "u8500-vsmps3",
+ .id = U8500_REGULATOR_VSMPS3,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ },
+ [U8500_REGULATOR_VRF1] = {
+ .desc = {
+ .name = "u8500-vrf1",
+ .id = U8500_REGULATOR_VRF1,
+ .ops = &ux500_regulator_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ },
+ [U8500_REGULATOR_SWITCH_SVAMMDSP] = {
+ .desc = {
+ .name = "u8500-sva-mmdsp",
+ .id = U8500_REGULATOR_SWITCH_SVAMMDSP,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_SVAMMDSP,
+ },
+ [U8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
+ .desc = {
+ .name = "u8500-sva-mmdsp-ret",
+ .id = U8500_REGULATOR_SWITCH_SVAMMDSPRET,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_SVAMMDSP,
+ .is_ramret = true,
+ },
+ [U8500_REGULATOR_SWITCH_SVAPIPE] = {
+ .desc = {
+ .name = "u8500-sva-pipe",
+ .id = U8500_REGULATOR_SWITCH_SVAPIPE,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_SVAPIPE,
+ },
+ [U8500_REGULATOR_SWITCH_SIAMMDSP] = {
+ .desc = {
+ .name = "u8500-sia-mmdsp",
+ .id = U8500_REGULATOR_SWITCH_SIAMMDSP,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_SIAMMDSP,
+ },
+ [U8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
+ .desc = {
+ .name = "u8500-sia-mmdsp-ret",
+ .id = U8500_REGULATOR_SWITCH_SIAMMDSPRET,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_SIAMMDSP,
+ .is_ramret = true,
+ },
+ [U8500_REGULATOR_SWITCH_SIAPIPE] = {
+ .desc = {
+ .name = "u8500-sia-pipe",
+ .id = U8500_REGULATOR_SWITCH_SIAPIPE,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_SIAPIPE,
+ },
+ [U8500_REGULATOR_SWITCH_SGA] = {
+ .desc = {
+ .name = "u8500-sga",
+ .id = U8500_REGULATOR_SWITCH_SGA,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_SGA,
+ },
+ [U8500_REGULATOR_SWITCH_B2R2_MCDE] = {
+ .desc = {
+ .name = "u8500-b2r2-mcde",
+ .id = U8500_REGULATOR_SWITCH_B2R2_MCDE,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_B2R2_MCDE,
+ },
+ [U8500_REGULATOR_SWITCH_ESRAM12] = {
+ .desc = {
+ .name = "u8500-esram12",
+ .id = U8500_REGULATOR_SWITCH_ESRAM12,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_ESRAM12,
+ .is_enabled = true,
+ },
+ [U8500_REGULATOR_SWITCH_ESRAM12RET] = {
+ .desc = {
+ .name = "u8500-esram12-ret",
+ .id = U8500_REGULATOR_SWITCH_ESRAM12RET,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_ESRAM12,
+ .is_ramret = true,
+ },
+ [U8500_REGULATOR_SWITCH_ESRAM34] = {
+ .desc = {
+ .name = "u8500-esram34",
+ .id = U8500_REGULATOR_SWITCH_ESRAM34,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_ESRAM34,
+ .is_enabled = true,
+ },
+ [U8500_REGULATOR_SWITCH_ESRAM34RET] = {
+ .desc = {
+ .name = "u8500-esram34-ret",
+ .id = U8500_REGULATOR_SWITCH_ESRAM34RET,
+ .ops = &ux500_regulator_switch_ops,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ },
+ .epod_id = EPOD_ID_ESRAM34,
+ .is_ramret = true,
+ },
+};
+
+static int __devinit u8500_regulator_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = ux500_regulator_probe(pdev, u8500_regulator_info,
+ ARRAY_SIZE(u8500_regulator_info));
+ if (!ret)
+ regulator_has_full_constraints();
+
+ return ret;
+}
+
+static int __devexit u8500_regulator_remove(struct platform_device *pdev)
+{
+ return ux500_regulator_remove(pdev, u8500_regulator_info,
+ ARRAY_SIZE(u8500_regulator_info));
+}
+
+static struct platform_driver u8500_regulator_driver = {
+ .driver = {
+ .name = "u8500-regulators",
+ .owner = THIS_MODULE,
+ },
+ .probe = u8500_regulator_probe,
+ .remove = __devexit_p(u8500_regulator_remove),
+};
+
+static int __init u8500_regulator_init(void)
+{
+ return platform_driver_register(&u8500_regulator_driver);
+}
+
+static void __exit u8500_regulator_exit(void)
+{
+ platform_driver_unregister(&u8500_regulator_driver);
+}
+
+/* replaced subsys_initcall as regulators must be turned on early */
+arch_initcall(u8500_regulator_init);
+module_exit(u8500_regulator_exit);
+
+MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");
+MODULE_DESCRIPTION("U8500 regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-ux500/regulator-u8500.h b/arch/arm/mach-ux500/regulator-u8500.h
new file mode 100644
index 00000000000..01dfeeb9da7
--- /dev/null
+++ b/arch/arm/mach-ux500/regulator-u8500.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ *
+ * Interface to platform specific regulators on U8500
+ */
+
+#ifndef __REGULATOR_H__
+#define __REGULATOR_H__
+
+/* Number of U8500 regulators and regulator enumeration */
+enum u8500_regulator_id {
+ U8500_REGULATOR_VAPE,
+ U8500_REGULATOR_VARM,
+ U8500_REGULATOR_VMODEM,
+ U8500_REGULATOR_VPLL,
+ U8500_REGULATOR_VSMPS1,
+ U8500_REGULATOR_VSMPS2,
+ U8500_REGULATOR_VSMPS3,
+ U8500_REGULATOR_VRF1,
+ U8500_REGULATOR_SWITCH_SVAMMDSP,
+ U8500_REGULATOR_SWITCH_SVAMMDSPRET,
+ U8500_REGULATOR_SWITCH_SVAPIPE,
+ U8500_REGULATOR_SWITCH_SIAMMDSP,
+ U8500_REGULATOR_SWITCH_SIAMMDSPRET,
+ U8500_REGULATOR_SWITCH_SIAPIPE,
+ U8500_REGULATOR_SWITCH_SGA,
+ U8500_REGULATOR_SWITCH_B2R2_MCDE,
+ U8500_REGULATOR_SWITCH_ESRAM12,
+ U8500_REGULATOR_SWITCH_ESRAM12RET,
+ U8500_REGULATOR_SWITCH_ESRAM34,
+ U8500_REGULATOR_SWITCH_ESRAM34RET,
+ U8500_NUM_REGULATORS
+};
+
+/*
+ * Exported interface for CPUIdle only. This function is called with all
+ * interrupts turned off.
+ */
+int power_state_active_is_enabled(void);
+
+#endif
+
diff --git a/arch/arm/mach-ux500/regulator-ux500.c b/arch/arm/mach-ux500/regulator-ux500.c
new file mode 100644
index 00000000000..fc6568a6e5a
--- /dev/null
+++ b/arch/arm/mach-ux500/regulator-ux500.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Authors: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ * Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ *
+ * Platform specific regulators on U8500
+ *
+ * NOTE! The power domains in here will be updated once B2R2 and MCDE are
+ * converted to use the regulator API.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include "regulator-ux500.h"
+
+#include <mach/prcmu-fw-api.h>
+
+/*
+ * power state reference count
+ */
+static int power_state_active_cnt; /* will initialize to zero */
+static DEFINE_SPINLOCK(power_state_active_lock);
+
+static void power_state_active_enable(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&power_state_active_lock, flags);
+ power_state_active_cnt++;
+ spin_unlock_irqrestore(&power_state_active_lock, flags);
+}
+
+static int power_state_active_disable(void)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&power_state_active_lock, flags);
+ if (power_state_active_cnt <= 0) {
+ pr_err("power state: unbalanced enable/disable calls\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ power_state_active_cnt--;
+out:
+ spin_unlock_irqrestore(&power_state_active_lock, flags);
+ return ret;
+}
+
+/*
+ * Exported interface for CPUIdle only. This function is called when interrupts
+ * are turned off. Hence, no locking.
+ */
+int power_state_active_is_enabled(void)
+{
+ return (power_state_active_cnt > 0);
+}
+
+struct ux500_regulator {
+ char *name;
+ void (*enable)(void);
+ int (*disable)(void);
+};
+
+/*
+ * Don't add any clients to this struct without checking with regulator
+ * responsible!
+ */
+static struct ux500_regulator ux500_atomic_regulators[] = {
+ {
+ .name = "dma40.0",
+ .enable = power_state_active_enable,
+ .disable = power_state_active_disable,
+ },
+ {
+ .name = "ssp0",
+ .enable = power_state_active_enable,
+ .disable = power_state_active_disable,
+ },
+ {
+ .name = "ssp1",
+ .enable = power_state_active_enable,
+ .disable = power_state_active_disable,
+ },
+ {
+ .name = "spi0",
+ .enable = power_state_active_enable,
+ .disable = power_state_active_disable,
+ },
+ {
+ .name = "spi1",
+ .enable = power_state_active_enable,
+ .disable = power_state_active_disable,
+ },
+ {
+ .name = "spi2",
+ .enable = power_state_active_enable,
+ .disable = power_state_active_disable,
+ },
+ {
+ .name = "spi3",
+ .enable = power_state_active_enable,
+ .disable = power_state_active_disable,
+ },
+};
+
+struct ux500_regulator *__must_check ux500_regulator_get(struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ux500_atomic_regulators); i++) {
+ if (!strcmp(dev_name(dev), ux500_atomic_regulators[i].name))
+ return &ux500_atomic_regulators[i];
+ }
+
+ return ERR_PTR(-EINVAL);
+}
+
+int ux500_regulator_atomic_enable(struct ux500_regulator *regulator)
+{
+ if (regulator) {
+ regulator->enable();
+ return 0;
+ }
+ return -EINVAL;
+}
+
+int ux500_regulator_atomic_disable(struct ux500_regulator *regulator)
+{
+ if (regulator)
+ return regulator->disable();
+ else
+ return -EINVAL;
+}
+
+void ux500_regulator_put(struct ux500_regulator *regulator)
+{
+ /* Here for symetric reasons and for possible future use */
+}
+
+static int u8500_regulator_enable(struct regulator_dev *rdev)
+{
+ struct u8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+ if (info == NULL)
+ return -EINVAL;
+
+ dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n",
+ info->desc.name);
+
+ info->is_enabled = 1;
+ if (!info->exclude_from_power_state)
+ power_state_active_enable();
+
+ return 0;
+}
+
+static int u8500_regulator_disable(struct regulator_dev *rdev)
+{
+ struct u8500_regulator_info *info = rdev_get_drvdata(rdev);
+ int ret = 0;
+
+ if (info == NULL)
+ return -EINVAL;
+
+ dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n",
+ info->desc.name);
+
+ info->is_enabled = 0;
+ if (!info->exclude_from_power_state)
+ ret = power_state_active_disable();
+
+ return ret;
+}
+
+static int u8500_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct u8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+ if (info == NULL)
+ return -EINVAL;
+
+ dev_vdbg(rdev_get_dev(rdev), "regulator-%s-is_enabled (is_enabled):"
+ " %i\n", info->desc.name, info->is_enabled);
+
+ return info->is_enabled;
+}
+
+/* u8500 regulator operations */
+struct regulator_ops ux500_regulator_ops = {
+ .enable = u8500_regulator_enable,
+ .disable = u8500_regulator_disable,
+ .is_enabled = u8500_regulator_is_enabled,
+};
+
+/*
+ * EPOD control
+ */
+static bool epod_on[NUM_EPOD_ID];
+static bool epod_ramret[NUM_EPOD_ID];
+
+static int enable_epod(u16 epod_id, bool ramret)
+{
+ int ret;
+
+ if (ramret) {
+ if (!epod_on[epod_id]) {
+ ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+ if (ret < 0)
+ return ret;
+ }
+ epod_ramret[epod_id] = true;
+ } else {
+ ret = prcmu_set_epod(epod_id, EPOD_STATE_ON);
+ if (ret < 0)
+ return ret;
+ epod_on[epod_id] = true;
+ }
+
+ return 0;
+}
+
+static int disable_epod(u16 epod_id, bool ramret)
+{
+ int ret;
+
+ if (ramret) {
+ if (!epod_on[epod_id]) {
+ ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
+ if (ret < 0)
+ return ret;
+ }
+ epod_ramret[epod_id] = false;
+ } else {
+ if (epod_ramret[epod_id]) {
+ ret = prcmu_set_epod(epod_id, EPOD_STATE_RAMRET);
+ if (ret < 0)
+ return ret;
+ } else {
+ ret = prcmu_set_epod(epod_id, EPOD_STATE_OFF);
+ if (ret < 0)
+ return ret;
+ }
+ epod_on[epod_id] = false;
+ }
+
+ return 0;
+}
+
+/*
+ * Regulator switch
+ */
+static int u8500_regulator_switch_enable(struct regulator_dev *rdev)
+{
+ struct u8500_regulator_info *info = rdev_get_drvdata(rdev);
+ int ret;
+
+ if (info == NULL)
+ return -EINVAL;
+
+ dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-enable\n",
+ info->desc.name);
+
+ ret = enable_epod(info->epod_id, info->is_ramret);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(rdev),
+ "regulator-switch-%s-enable: prcmu call failed\n",
+ info->desc.name);
+ goto out;
+ }
+
+ info->is_enabled = 1;
+out:
+ return ret;
+}
+
+static int u8500_regulator_switch_disable(struct regulator_dev *rdev)
+{
+ struct u8500_regulator_info *info = rdev_get_drvdata(rdev);
+ int ret;
+
+ if (info == NULL)
+ return -EINVAL;
+
+ dev_vdbg(rdev_get_dev(rdev), "regulator-switch-%s-disable\n",
+ info->desc.name);
+
+ ret = disable_epod(info->epod_id, info->is_ramret);
+ if (ret < 0) {
+ dev_err(rdev_get_dev(rdev),
+ "regulator_switch-%s-disable: prcmu call failed\n",
+ info->desc.name);
+ goto out;
+ }
+
+ info->is_enabled = 0;
+out:
+ return ret;
+}
+
+static int u8500_regulator_switch_is_enabled(struct regulator_dev *rdev)
+{
+ struct u8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+ if (info == NULL)
+ return -EINVAL;
+
+ dev_vdbg(rdev_get_dev(rdev),
+ "regulator-switch-%s-is_enabled (is_enabled): %i\n",
+ info->desc.name, info->is_enabled);
+
+ return info->is_enabled;
+}
+
+struct regulator_ops ux500_regulator_switch_ops = {
+ .enable = u8500_regulator_switch_enable,
+ .disable = u8500_regulator_switch_disable,
+ .is_enabled = u8500_regulator_switch_is_enabled,
+};
+
+int __devinit
+ux500_regulator_probe(struct platform_device *pdev,
+ struct u8500_regulator_info *regulator_info,
+ int num_regulators)
+{
+ struct regulator_init_data **u8500_init_data =
+ dev_get_platdata(&pdev->dev);
+ int i, err;
+
+ /* register all regulators */
+ for (i = 0; i < num_regulators; i++) {
+ struct u8500_regulator_info *info;
+ struct regulator_init_data *init_data = u8500_init_data[i];
+
+ /* assign per-regulator data */
+ info = &regulator_info[i];
+ info->dev = &pdev->dev;
+
+ /* register with the regulator framework */
+ info->rdev = regulator_register(&info->desc, &pdev->dev,
+ init_data, info);
+ if (IS_ERR(info->rdev)) {
+ err = PTR_ERR(info->rdev);
+ dev_err(&pdev->dev, "failed to register %s: err %i\n",
+ info->desc.name, err);
+
+ /* if failing, unregister all earlier regulators */
+ i--;
+ while (i >= 0) {
+ info = &regulator_info[i];
+ regulator_unregister(info->rdev);
+ i--;
+ }
+ return err;
+ }
+
+ dev_vdbg(rdev_get_dev(info->rdev),
+ "regulator-%s-probed\n", info->desc.name);
+ }
+
+ return 0;
+}
+
+int __devexit
+ux500_regulator_remove(struct platform_device *pdev,
+ struct u8500_regulator_info *regulator_info,
+ int num_regulators)
+{
+ int i;
+
+ for (i = 0; i < num_regulators; i++) {
+ struct u8500_regulator_info *info;
+
+ info = &regulator_info[i];
+
+ dev_vdbg(rdev_get_dev(info->rdev),
+ "regulator-%s-remove\n", info->desc.name);
+
+ regulator_unregister(info->rdev);
+ }
+
+ return 0;
+}
diff --git a/arch/arm/mach-ux500/regulator-ux500.h b/arch/arm/mach-ux500/regulator-ux500.h
new file mode 100644
index 00000000000..b62863881b1
--- /dev/null
+++ b/arch/arm/mach-ux500/regulator-ux500.h
@@ -0,0 +1,39 @@
+#ifndef __REGULATOR_UX500_H
+#define __REGULATOR_UX500_H
+
+struct platform_device;
+
+/**
+ * struct u8500_regulator_info - u8500 regulator information
+ * @dev: device pointer
+ * @desc: regulator description
+ * @rdev: regulator device pointer
+ * @is_enabled: status of the regulator
+ * @epod_id: id for EPOD (power domain)
+ * @is_ramret: RAM retention switch for EPOD (power domain)
+ * @operating_point: operating point (only for vape, to be removed)
+ * @exclude_from_power_state: don't let this regulator prevent ApSLeep
+ */
+struct u8500_regulator_info {
+ struct device *dev;
+ struct regulator_desc desc;
+ struct regulator_dev *rdev;
+ bool is_enabled;
+ u16 epod_id;
+ bool is_ramret;
+ bool exclude_from_power_state;
+ unsigned int operating_point;
+};
+
+extern struct regulator_ops ux500_regulator_ops;
+extern struct regulator_ops ux500_regulator_switch_ops;
+
+int ux500_regulator_probe(struct platform_device *pdev,
+ struct u8500_regulator_info *info,
+ int num_regulators);
+
+int ux500_regulator_remove(struct platform_device *pdev,
+ struct u8500_regulator_info *info,
+ int num_regulators);
+
+#endif
diff --git a/arch/arm/mach-ux500/sensors1p.c b/arch/arm/mach-ux500/sensors1p.c
new file mode 100644
index 00000000000..e7f4642b1d9
--- /dev/null
+++ b/arch/arm/mach-ux500/sensors1p.c
@@ -0,0 +1,298 @@
+
+/*
+ * Copyright (C) 2009-2010 ST-Ericsson AB
+ * License terms: GNU General Public License (GPL) version 2
+ * Simple userspace interface for
+ * Proximity Sensor Osram SFH 7741 and HAL switch Samsung HED54XXU11
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
+ *
+ * This driver is only there for making Android happy. It is not ment
+ * for mainline.
+ */
+
+
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+
+#include <mach/sensors1p.h>
+
+struct sensor {
+ struct regulator *regulator;
+ int pin;
+ int startup_time;
+ int active;
+ u64 when_enabled;
+};
+
+struct sensors1p {
+ struct sensor hal;
+ struct sensor proximity;
+};
+
+static int sensors1p_power_write(struct device *dev,
+ struct sensor *s, const char *buf)
+{
+ int val;
+
+ if (sscanf(buf, "%d", &val) != 1)
+ return -EINVAL;
+
+ if (val != 0 && val != 1)
+ return -EINVAL;
+
+ if (val != s->active) {
+ if (val) {
+ regulator_enable(s->regulator);
+ s->when_enabled = get_jiffies_64() +
+ msecs_to_jiffies(s->startup_time);
+ } else
+ regulator_disable(s->regulator);
+ }
+ s->active = val;
+
+ return strnlen(buf, PAGE_SIZE);
+
+}
+
+static ssize_t sensors1p_sysfs_hal_active_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+
+ struct sensors1p *s = platform_get_drvdata(container_of(dev,
+ struct platform_device,
+ dev));
+ return sensors1p_power_write(dev, &s->hal, buf);
+
+}
+
+static ssize_t sensors1p_sysfs_proximity_active_set(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+
+
+ struct sensors1p *s = platform_get_drvdata(container_of(dev,
+ struct platform_device,
+ dev));
+ return sensors1p_power_write(dev, &s->proximity, buf);
+
+}
+
+static ssize_t sensors1p_sysfs_hal_active_get(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sensors1p *s = platform_get_drvdata(container_of(dev,
+ struct platform_device,
+ dev));
+ return sprintf(buf, "%d", s->hal.active);
+}
+
+static ssize_t sensors1p_sysfs_proximity_active_get(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sensors1p *s = platform_get_drvdata(container_of(dev,
+ struct platform_device,
+ dev));
+ return sprintf(buf, "%d", s->proximity.active);
+}
+
+static int sensors1p_read(struct device *dev, struct sensor *s, char *buf)
+{
+ int ret;
+
+ if (!s->active)
+ return -EINVAL;
+
+ /* Only wait if read() is called before the sensor is up and running
+ * Since jiffies wraps, always sleep maximum time.
+ */
+ if (time_before64(get_jiffies_64(), s->when_enabled))
+ mdelay(s->startup_time);
+
+ /* For some odd reason, setting direction in the probe function fails */
+ ret = gpio_direction_input(s->pin);
+
+ if (ret)
+ dev_err(dev, "Failed to set GPIO pin %d to input.\n", s->pin);
+ else
+ ret = gpio_get_value(s->pin);
+
+ return sprintf(buf, "%d", ret);
+}
+
+static ssize_t sensors1p_sysfs_hal_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sensors1p *s = platform_get_drvdata(container_of(dev,
+ struct platform_device,
+ dev));
+ return sensors1p_read(dev, &s->hal, buf);
+}
+
+static ssize_t sensors1p_sysfs_proximity_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct sensors1p *s = platform_get_drvdata(container_of(dev,
+ struct platform_device,
+ dev));
+ return sensors1p_read(dev, &s->proximity, buf);
+}
+
+static DEVICE_ATTR(proximity_activate, 0666,
+ sensors1p_sysfs_proximity_active_get,
+ sensors1p_sysfs_proximity_active_set);
+static DEVICE_ATTR(hal_activate, 0666,
+ sensors1p_sysfs_hal_active_get,
+ sensors1p_sysfs_hal_active_set);
+static DEVICE_ATTR(proximity, 0444, sensors1p_sysfs_proximity_show, NULL);
+static DEVICE_ATTR(hal, 0444, sensors1p_sysfs_hal_show, NULL);
+
+static struct attribute *sensors1p_attrs[] = {
+ &dev_attr_proximity_activate.attr,
+ &dev_attr_hal_activate.attr,
+ &dev_attr_proximity.attr,
+ &dev_attr_hal.attr,
+ NULL,
+};
+
+static struct attribute_group sensors1p_attr_group = {
+ .name = NULL,
+ .attrs = sensors1p_attrs,
+};
+
+static int __init sensors1p_probe(struct platform_device *pdev)
+{
+ int err = -EINVAL;
+ struct sensors1p_config *c;
+ struct sensors1p *s = NULL;
+
+ if (!pdev)
+ goto out;
+
+ c = pdev->dev.platform_data;
+
+ if (c == NULL) {
+ dev_err(&pdev->dev, "Error: Missconfigured.\n");
+ goto out;
+ }
+
+ s = kzalloc(sizeof(struct sensors1p), GFP_KERNEL);
+
+ if (s == NULL) {
+ dev_err(&pdev->dev,
+ "Could not allocate struct memory!\n");
+ err = -ENOMEM;
+ goto out;
+ }
+
+ s->hal.pin = c->hal.pin;
+ err = gpio_request(c->hal.pin, "hal sensor");
+ if (err < 0) {
+ dev_err(&pdev->dev, "gpio_request failed with err: %d", err);
+ goto err_hal_gpio;
+ }
+
+ s->proximity.pin = c->proximity.pin;
+ err = gpio_request(c->proximity.pin, "proximity sensor");
+ if (err < 0) {
+ dev_err(&pdev->dev, "gpio_request failed with err: %d", err);
+ goto err_proximity_gpio;
+ }
+
+ s->hal.startup_time = c->hal.startup_time;
+ s->proximity.startup_time = c->proximity.startup_time;
+
+
+ s->hal.regulator = regulator_get(&pdev->dev, c->hal.regulator);
+
+ if (IS_ERR(s->hal.regulator)) {
+ dev_err(&pdev->dev, "regulator_get(\"%s\") failed.\n",
+ c->hal.regulator);
+ err = PTR_ERR(s->hal.regulator);
+ goto err_hal_reg;
+ }
+ s->proximity.regulator = regulator_get(&pdev->dev,
+ c->proximity.regulator);
+
+ if (IS_ERR(s->proximity.regulator)) {
+ dev_err(&pdev->dev, "regulator_get(\"%s\") failed.\n",
+ c->proximity.regulator);
+ err = PTR_ERR(s->proximity.regulator);
+ goto err_proximity_reg;
+ }
+
+ err = sysfs_create_group(&pdev->dev.kobj, &sensors1p_attr_group);
+
+ if (err) {
+ dev_err(&pdev->dev, "Failed to create sysfs entries.\n");
+ goto err_sysfs;
+ }
+
+ platform_set_drvdata(pdev, s);
+
+ return 0;
+
+err_sysfs:
+ regulator_put(s->proximity.regulator);
+err_proximity_reg:
+ regulator_put(s->hal.regulator);
+err_hal_reg:
+ gpio_free(s->proximity.pin);
+err_proximity_gpio:
+ gpio_free(s->hal.pin);
+err_hal_gpio:
+ kfree(s);
+out:
+ return err;
+}
+
+static int __exit sensors1p_remove(struct platform_device *pdev)
+{
+ struct sensors1p *s = platform_get_drvdata(pdev);
+
+ sysfs_remove_group(&pdev->dev.kobj, &sensors1p_attr_group);
+ gpio_free(s->hal.pin);
+ gpio_free(s->proximity.pin);
+ regulator_put(s->hal.regulator);
+ regulator_put(s->proximity.regulator);
+ kfree(s);
+ return 0;
+}
+
+static struct platform_driver sensors1p_driver = {
+ .remove = __exit_p(sensors1p_remove),
+ .driver = {
+ .name = "sensors1p",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init sensors1p_init(void)
+{
+ return platform_driver_probe(&sensors1p_driver, sensors1p_probe);
+}
+
+static void __exit sensors1p_exit(void)
+{
+ platform_driver_unregister(&sensors1p_driver);
+}
+
+late_initcall(sensors1p_init);
+module_exit(sensors1p_exit);
+
+MODULE_AUTHOR("Jonas Aaberg <jonas.aberg@stericsson.com>");
+MODULE_DESCRIPTION("One pin gpio sensors driver (Proximity+HAL)");
+MODULE_LICENSE("GPLv2");
diff --git a/arch/arm/mach-ux500/ste-dma40-db8500.h b/arch/arm/mach-ux500/ste-dma40-db8500.h
deleted file mode 100644
index e7016278dfa..00000000000
--- a/arch/arm/mach-ux500/ste-dma40-db8500.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * arch/arm/mach-ux500/ste_dma40_db8500.h
- * DB8500-SoC-specific configuration for DMA40
- *
- * Copyright (C) ST-Ericsson 2007-2010
- * License terms: GNU General Public License (GPL) version 2
- * Author: Per Friden <per.friden@stericsson.com>
- * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- */
-#ifndef STE_DMA40_DB8500_H
-#define STE_DMA40_DB8500_H
-
-#define STEDMA40_NR_DEV 64
-
-enum dma_src_dev_type {
- STEDMA40_DEV_SPI0_RX = 0,
- STEDMA40_DEV_SD_MMC0_RX = 1,
- STEDMA40_DEV_SD_MMC1_RX = 2,
- STEDMA40_DEV_SD_MMC2_RX = 3,
- STEDMA40_DEV_I2C1_RX = 4,
- STEDMA40_DEV_I2C3_RX = 5,
- STEDMA40_DEV_I2C2_RX = 6,
- STEDMA40_DEV_I2C4_RX = 7, /* Only on V1 */
- STEDMA40_DEV_SSP0_RX = 8,
- STEDMA40_DEV_SSP1_RX = 9,
- STEDMA40_DEV_MCDE_RX = 10,
- STEDMA40_DEV_UART2_RX = 11,
- STEDMA40_DEV_UART1_RX = 12,
- STEDMA40_DEV_UART0_RX = 13,
- STEDMA40_DEV_MSP2_RX = 14,
- STEDMA40_DEV_I2C0_RX = 15,
- STEDMA40_DEV_USB_OTG_IEP_8 = 16,
- STEDMA40_DEV_USB_OTG_IEP_1_9 = 17,
- STEDMA40_DEV_USB_OTG_IEP_2_10 = 18,
- STEDMA40_DEV_USB_OTG_IEP_3_11 = 19,
- STEDMA40_DEV_SLIM0_CH0_RX_HSI_RX_CH0 = 20,
- STEDMA40_DEV_SLIM0_CH1_RX_HSI_RX_CH1 = 21,
- STEDMA40_DEV_SLIM0_CH2_RX_HSI_RX_CH2 = 22,
- STEDMA40_DEV_SLIM0_CH3_RX_HSI_RX_CH3 = 23,
- STEDMA40_DEV_SRC_SXA0_RX_TX = 24,
- STEDMA40_DEV_SRC_SXA1_RX_TX = 25,
- STEDMA40_DEV_SRC_SXA2_RX_TX = 26,
- STEDMA40_DEV_SRC_SXA3_RX_TX = 27,
- STEDMA40_DEV_SD_MM2_RX = 28,
- STEDMA40_DEV_SD_MM0_RX = 29,
- STEDMA40_DEV_MSP1_RX = 30,
- /*
- * This channel is either SlimBus or MSP,
- * never both at the same time.
- */
- STEDMA40_SLIM0_CH0_RX = 31,
- STEDMA40_DEV_MSP0_RX = 31,
- STEDMA40_DEV_SD_MM1_RX = 32,
- STEDMA40_DEV_SPI2_RX = 33,
- STEDMA40_DEV_I2C3_RX2 = 34,
- STEDMA40_DEV_SPI1_RX = 35,
- STEDMA40_DEV_USB_OTG_IEP_4_12 = 36,
- STEDMA40_DEV_USB_OTG_IEP_5_13 = 37,
- STEDMA40_DEV_USB_OTG_IEP_6_14 = 38,
- STEDMA40_DEV_USB_OTG_IEP_7_15 = 39,
- STEDMA40_DEV_SPI3_RX = 40,
- STEDMA40_DEV_SD_MM3_RX = 41,
- STEDMA40_DEV_SD_MM4_RX = 42,
- STEDMA40_DEV_SD_MM5_RX = 43,
- STEDMA40_DEV_SRC_SXA4_RX_TX = 44,
- STEDMA40_DEV_SRC_SXA5_RX_TX = 45,
- STEDMA40_DEV_SRC_SXA6_RX_TX = 46,
- STEDMA40_DEV_SRC_SXA7_RX_TX = 47,
- STEDMA40_DEV_CAC1_RX = 48,
- /* RX channels 49 and 50 are unused */
- STEDMA40_DEV_MSHC_RX = 51,
- STEDMA40_DEV_SLIM1_CH0_RX_HSI_RX_CH4 = 52,
- STEDMA40_DEV_SLIM1_CH1_RX_HSI_RX_CH5 = 53,
- STEDMA40_DEV_SLIM1_CH2_RX_HSI_RX_CH6 = 54,
- STEDMA40_DEV_SLIM1_CH3_RX_HSI_RX_CH7 = 55,
- /* RX channels 56 thru 60 are unused */
- STEDMA40_DEV_CAC0_RX = 61,
- /* RX channels 62 and 63 are unused */
-};
-
-enum dma_dest_dev_type {
- STEDMA40_DEV_SPI0_TX = 0,
- STEDMA40_DEV_SD_MMC0_TX = 1,
- STEDMA40_DEV_SD_MMC1_TX = 2,
- STEDMA40_DEV_SD_MMC2_TX = 3,
- STEDMA40_DEV_I2C1_TX = 4,
- STEDMA40_DEV_I2C3_TX = 5,
- STEDMA40_DEV_I2C2_TX = 6,
- STEDMA50_DEV_I2C4_TX = 7, /* Only on V1 */
- STEDMA40_DEV_SSP0_TX = 8,
- STEDMA40_DEV_SSP1_TX = 9,
- /* TX channel 10 is unused */
- STEDMA40_DEV_UART2_TX = 11,
- STEDMA40_DEV_UART1_TX = 12,
- STEDMA40_DEV_UART0_TX= 13,
- STEDMA40_DEV_MSP2_TX = 14,
- STEDMA40_DEV_I2C0_TX = 15,
- STEDMA40_DEV_USB_OTG_OEP_8 = 16,
- STEDMA40_DEV_USB_OTG_OEP_1_9 = 17,
- STEDMA40_DEV_USB_OTG_OEP_2_10= 18,
- STEDMA40_DEV_USB_OTG_OEP_3_11 = 19,
- STEDMA40_DEV_SLIM0_CH0_TX_HSI_TX_CH0 = 20,
- STEDMA40_DEV_SLIM0_CH1_TX_HSI_TX_CH1 = 21,
- STEDMA40_DEV_SLIM0_CH2_TX_HSI_TX_CH2 = 22,
- STEDMA40_DEV_SLIM0_CH3_TX_HSI_TX_CH3 = 23,
- STEDMA40_DEV_DST_SXA0_RX_TX = 24,
- STEDMA40_DEV_DST_SXA1_RX_TX = 25,
- STEDMA40_DEV_DST_SXA2_RX_TX = 26,
- STEDMA40_DEV_DST_SXA3_RX_TX = 27,
- STEDMA40_DEV_SD_MM2_TX = 28,
- STEDMA40_DEV_SD_MM0_TX = 29,
- STEDMA40_DEV_MSP1_TX = 30,
- /*
- * This channel is either SlimBus or MSP,
- * never both at the same time.
- */
- STEDMA40_SLIM0_CH0_TX = 31,
- STEDMA40_DEV_MSP0_TX = 31,
- STEDMA40_DEV_SD_MM1_TX = 32,
- STEDMA40_DEV_SPI2_TX = 33,
- /* Secondary I2C3 channel */
- STEDMA40_DEV_I2C3_TX2 = 34,
- STEDMA40_DEV_SPI1_TX = 35,
- STEDMA40_DEV_USB_OTG_OEP_4_12 = 36,
- STEDMA40_DEV_USB_OTG_OEP_5_13 = 37,
- STEDMA40_DEV_USB_OTG_OEP_6_14 = 38,
- STEDMA40_DEV_USB_OTG_OEP_7_15 = 39,
- STEDMA40_DEV_SPI3_TX = 40,
- STEDMA40_DEV_SD_MM3_TX = 41,
- STEDMA40_DEV_SD_MM4_TX = 42,
- STEDMA40_DEV_SD_MM5_TX = 43,
- STEDMA40_DEV_DST_SXA4_RX_TX = 44,
- STEDMA40_DEV_DST_SXA5_RX_TX = 45,
- STEDMA40_DEV_DST_SXA6_RX_TX = 46,
- STEDMA40_DEV_DST_SXA7_RX_TX = 47,
- STEDMA40_DEV_CAC1_TX = 48,
- STEDMA40_DEV_CAC1_TX_HAC1_TX = 49,
- STEDMA40_DEV_HAC1_TX = 50,
- STEDMA40_MEMXCPY_TX_0 = 51,
- STEDMA40_DEV_SLIM1_CH0_TX_HSI_TX_CH4 = 52,
- STEDMA40_DEV_SLIM1_CH1_TX_HSI_TX_CH5 = 53,
- STEDMA40_DEV_SLIM1_CH2_TX_HSI_TX_CH6 = 54,
- STEDMA40_DEV_SLIM1_CH3_TX_HSI_TX_CH7 = 55,
- STEDMA40_MEMCPY_TX_1 = 56,
- STEDMA40_MEMCPY_TX_2 = 57,
- STEDMA40_MEMCPY_TX_3 = 58,
- STEDMA40_MEMCPY_TX_4 = 59,
- STEDMA40_MEMCPY_TX_5 = 60,
- STEDMA40_DEV_CAC0_TX = 61,
- STEDMA40_DEV_CAC0_TX_HAC0_TX = 62,
- STEDMA40_DEV_HAC0_TX = 63,
-};
-
-#endif
diff --git a/arch/arm/mach-ux500/tee_service_svp.c b/arch/arm/mach-ux500/tee_service_svp.c
new file mode 100644
index 00000000000..8c68e51ab74
--- /dev/null
+++ b/arch/arm/mach-ux500/tee_service_svp.c
@@ -0,0 +1,66 @@
+/*
+ * TEE service to handle the calls to trusted applications in SVP.
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/tee.h>
+#include <linux/err.h>
+#include "mach/tee_ta_start_modem.h"
+
+static int cmp_uuid_start_modem(struct tee_uuid *uuid)
+{
+ int ret = -EINVAL;
+
+ if (uuid == NULL)
+ return -EINVAL;
+
+ /* This handles the calls to TA for start the modem */
+ if ((uuid->timeLow == UUID_TEE_TA_START_MODEM_LOW) &&
+ (uuid->timeMid == UUID_TEE_TA_START_MODEM_MID) &&
+ (uuid->timeHiAndVersion == UUID_TEE_TA_START_MODEM_HIGH)) {
+
+ u8 clockSeqAndNode[TEE_UUID_CLOCK_SIZE] =
+ UUID_TEE_TA_START_MODEM_CLOCKSEQ;
+
+ ret = memcmp(uuid->clockSeqAndNode, clockSeqAndNode,
+ TEE_UUID_CLOCK_SIZE);
+ }
+
+ return ret;
+}
+
+int svp_call_sec_world(struct tee_session *ts, int sec_cmd)
+{
+ int ret = 0;
+
+ if (ts == NULL)
+ return -EINVAL;
+
+ if (cmp_uuid_start_modem(ts->uuid))
+ return -EINVAL;
+
+ switch (ts->cmd) {
+ case COMMAND_ID_START_MODEM:
+ ret = tee_ta_start_modem((struct tee_ta_start_modem *)
+ ts->op);
+ if (ret) {
+ ts->err = TEED_ERROR_GENERIC;
+ ts->origin = TEED_ORIGIN_TEE_APPLICATION;
+ pr_err("tee_ta_start_modem() failed!\n");
+ return ret;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ /* TODO: to handle more trusted applications. */
+
+ return ret;
+}
diff --git a/arch/arm/mach-ux500/tee_ta_start_modem_svp.c b/arch/arm/mach-ux500/tee_ta_start_modem_svp.c
new file mode 100644
index 00000000000..12337b93154
--- /dev/null
+++ b/arch/arm/mach-ux500/tee_ta_start_modem_svp.c
@@ -0,0 +1,56 @@
+/*
+ * Trusted application for starting the modem.
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Shujuan Chen <shujuan.chen@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/elf.h>
+#include <mach/hardware.h>
+
+#include "mach/tee_ta_start_modem.h"
+
+static int reset_modem(unsigned long modem_start_addr)
+{
+ void __iomem *base = ioremap(U5500_ACCCON_BASE_SEC, 0x2FF);
+ if (!base)
+ return -ENOMEM;
+
+ pr_info("[%s] Setting modem start address!\n", __func__);
+ writel(base + (U5500_ACCCON_CPUVEC_RESET_ADDR_OFFSET/sizeof(uint32_t)),
+ modem_start_addr);
+
+ pr_info("[%s] resetting the modem!\n", __func__);
+ writel(base + (U5500_ACCCON_ACC_CPU_CTRL_OFFSET/sizeof(uint32_t)), 1);
+
+ iounmap(base);
+
+ return 0;
+}
+
+int tee_ta_start_modem(struct tee_ta_start_modem *data)
+{
+ int ret = 0;
+ struct elfhdr *elfhdr;
+ void __iomem *vaddr;
+
+ vaddr = ioremap((unsigned long)data->access_image_descr.elf_hdr,
+ sizeof(struct elfhdr));
+ if (!vaddr)
+ return -ENOMEM;
+
+ elfhdr = (struct elfhdr *)readl(vaddr);
+ pr_info("Reading in kernel:elfhdr 0x%x:elfhdr->entry=0x%x\n",
+ (uint32_t)elfhdr, (uint32_t)elfhdr->e_entry);
+
+ pr_info("[%s] reset modem()...\n", __func__);
+ ret = reset_modem(elfhdr->e_entry);
+
+ iounmap(vaddr);
+
+ return ret;
+}
diff --git a/arch/arm/mach-ux500/tee_ux500.c b/arch/arm/mach-ux500/tee_ux500.c
new file mode 100644
index 00000000000..8b271913db1
--- /dev/null
+++ b/arch/arm/mach-ux500/tee_ux500.c
@@ -0,0 +1,112 @@
+/*
+ * TEE service to handle the calls to trusted applications.
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Joakim Bech <joakim.xx.bech@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#include <linux/kernel.h>
+#include <linux/tee.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+
+#include <mach/hardware.h>
+
+#ifdef CONFIG_UX500_SVP
+extern int svp_call_sec_world(struct tee_session *ts, int sec_cmd);
+#else
+static int svp_call_sec_world(struct tee_session *ts, int sec_cmd)
+{
+ return -EINVAL;
+}
+#endif
+
+#define ISSWAPI_EXECUTE_TA 0x11000001
+#define ISSWAPI_CLOSE_TA 0x11000002
+
+#define SEC_ROM_NO_FLAG_MASK 0x0000
+
+static u32 call_sec_rom_bridge(u32 service_id, u32 cfg, ...)
+{
+ typedef u32 (*bridge_func)(u32, u32, va_list);
+ bridge_func hw_sec_rom_pub_bridge;
+ va_list ap;
+ u32 ret;
+
+ if (cpu_is_u8500v2())
+ hw_sec_rom_pub_bridge = (bridge_func)
+ ((u32)IO_ADDRESS(U8500_BOOT_ROM_BASE + 0x17300));
+ else if (cpu_is_u8500v1())
+ hw_sec_rom_pub_bridge = (bridge_func)
+ ((u32)IO_ADDRESS(U8500_BOOT_ROM_BASE + 0x18300));
+ else if (cpu_is_u5500())
+ hw_sec_rom_pub_bridge = (bridge_func)
+ ((u32)IO_ADDRESS(U5500_BOOT_ROM_BASE + 0x18300));
+ else {
+ pr_err("tee-ux500: Unknown DB Asic!\n");
+ return -EIO;
+ }
+
+ va_start(ap, cfg);
+ ret = hw_sec_rom_pub_bridge(service_id, cfg, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+int call_sec_world(struct tee_session *ts, int sec_cmd)
+{
+ if (ux500_is_svp())
+ return svp_call_sec_world(ts, sec_cmd);
+
+ /*
+ * ts->ta and ts->uuid is set to NULL when opening the device,
+ * hence it should be safe to just do the call here.
+ */
+
+ switch (sec_cmd) {
+ case TEED_INVOKE:
+ if (!ts->uuid) {
+ call_sec_rom_bridge(ISSWAPI_EXECUTE_TA,
+ SEC_ROM_NO_FLAG_MASK,
+ virt_to_phys(&ts->id),
+ NULL,
+ virt_to_phys(ts->ta),
+ ts->cmd,
+ virt_to_phys((void *)(ts->op)),
+ virt_to_phys((void *)(&ts->err)),
+ virt_to_phys((void *)(&ts->origin)));
+ } else {
+ call_sec_rom_bridge(ISSWAPI_EXECUTE_TA,
+ SEC_ROM_NO_FLAG_MASK,
+ virt_to_phys(&ts->id),
+ virt_to_phys(ts->uuid),
+ virt_to_phys(ts->ta),
+ ts->cmd,
+ virt_to_phys((void *)(ts->op)),
+ virt_to_phys((void *)(&ts->err)),
+ virt_to_phys((void *)(&ts->origin)));
+ }
+ break;
+
+ case TEED_CLOSE_SESSION:
+ call_sec_rom_bridge(ISSWAPI_CLOSE_TA,
+ SEC_ROM_NO_FLAG_MASK,
+ ts->id,
+ NULL,
+ virt_to_phys(ts->ta),
+ virt_to_phys((void *)(&ts->err)));
+
+ /* Since the TEE Client API does NOT take care of
+ * the return value, we print a warning here if
+ * something went wrong in secure world.
+ */
+ if (ts->err != TEED_SUCCESS)
+ pr_warning("[%s] failed in secure world\n",
+ __func__);
+
+ break;
+ }
+
+ return 0;
+}
diff --git a/arch/arm/mach-ux500/timer-db8500-prcmu.c b/arch/arm/mach-ux500/timer-db8500-prcmu.c
new file mode 100644
index 00000000000..606efa3c0f8
--- /dev/null
+++ b/arch/arm/mach-ux500/timer-db8500-prcmu.c
@@ -0,0 +1,122 @@
+/*
+ * 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>
+ *
+ * DB8500-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.
+ */
+#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)
+
+/* PRCMU Timer 4 */
+#define PRCMU_TIMER_4_REF (prcmu_base + 0x450)
+#define PRCMU_TIMER_4_DOWNCOUNT (prcmu_base + 0x454)
+#define PRCMU_TIMER_4_MODE (prcmu_base + 0x458)
+
+static __iomem void *prcmu_base;
+
+#define SCHED_CLOCK_MIN_WRAP (131072) /* 2^32 / 32768 */
+
+static cycle_t db8500_prcmu_read_timer_nop(struct clocksource *cs)
+{
+ return 0;
+}
+
+static struct clocksource db8500_prcmu_clksrc = {
+ .name = "db8500-prcmu-timer4",
+ .rating = 300,
+ .read = db8500_prcmu_read_timer_nop,
+ .shift = 10,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static cycle_t db8500_prcmu_read_timer(struct clocksource *cs)
+{
+ u32 count, count2;
+
+ do {
+ count = readl(PRCMU_TIMER_4_DOWNCOUNT);
+ count2 = readl(PRCMU_TIMER_4_DOWNCOUNT);
+ } while (count2 != count);
+
+ /*
+ * clocksource: the prcmu timer is a decrementing counters, so we negate
+ * the value being read.
+ */
+ return ~count;
+}
+
+#ifdef CONFIG_U8500_PRCMU_TIMER
+unsigned long long notrace sched_clock(void)
+{
+ return clocksource_cyc2ns(db8500_prcmu_clksrc.read(
+ &db8500_prcmu_clksrc),
+ db8500_prcmu_clksrc.mult,
+ db8500_prcmu_clksrc.shift);
+}
+#endif
+
+#ifdef CONFIG_BOOTTIME
+
+static unsigned long __init boottime_get_time(void)
+{
+ return div_s64(clocksource_cyc2ns(db8500_prcmu_clksrc.read(
+ &db8500_prcmu_clksrc),
+ db8500_prcmu_clksrc.mult,
+ db8500_prcmu_clksrc.shift), 1000);
+}
+
+static struct boottime_timer __initdata boottime_timer = {
+ .init = NULL,
+ .get_time = boottime_get_time,
+ .finalize = NULL,
+};
+#endif
+
+void __init db8500_prcmu_timer_init(void)
+{
+ if (ux500_is_svp())
+ return;
+
+ prcmu_base = __io_address(U8500_PRCMU_BASE);
+
+ clocksource_calc_mult_shift(&db8500_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(PRCMU_TIMER_4_MODE) != TIMER_MODE_CONTINOUS) {
+ writel(TIMER_MODE_CONTINOUS, PRCMU_TIMER_4_MODE);
+ writel(TIMER_DOWNCOUNT_VAL, PRCMU_TIMER_4_REF);
+ }
+ db8500_prcmu_clksrc.read = db8500_prcmu_read_timer;
+
+ clocksource_register(&db8500_prcmu_clksrc);
+
+ if (!ux500_is_svp())
+ boottime_activate(&boottime_timer);
+}
+
diff --git a/arch/arm/mach-ux500/timer-db8500.c b/arch/arm/mach-ux500/timer-db8500.c
new file mode 100644
index 00000000000..70ec8f6275c
--- /dev/null
+++ b/arch/arm/mach-ux500/timer-db8500.c
@@ -0,0 +1,82 @@
+/*
+ * 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 u8500_rtc_init(unsigned int cpu);
+void db8500_prcmu_timer_init(void);
+void mtu_timer_init(void);
+void mtu_clocksource_reset(void);
+void mtu_clockevent_reset(void);
+
+#ifdef CONFIG_LOCAL_TIMERS
+extern void *twd_base;
+#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 u8500_timer_reset(void)
+{
+ mtu_clockevent_reset();
+}
+
+static void __init u8500_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_U8500_PRCMU
+ u8500_rtc_init(0);
+ db8500_prcmu_timer_init();
+#endif
+
+#ifdef CONFIG_UX500_CONTEXT
+ WARN_ON(context_ape_notifier_register(&mtu_context_notifier));
+#endif
+}
+
+struct sys_timer u8500_timer = {
+ .init = u8500_timer_init,
+ .resume = u8500_timer_reset,
+};
diff --git a/arch/arm/mach-ux500/timer-mtu.c b/arch/arm/mach-ux500/timer-mtu.c
new file mode 100644
index 00000000000..51778245515
--- /dev/null
+++ b/arch/arm/mach-ux500/timer-mtu.c
@@ -0,0 +1,343 @@
+/*
+ * 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 <mach/setup.h>
+
+#define MTU_IMSC 0x00 /* Interrupt mask set/clear */
+#define MTU_RIS 0x04 /* Raw interrupt status */
+#define MTU_MIS 0x08 /* Masked interrupt status */
+#define MTU_ICR 0x0C /* Interrupt clear register */
+
+/* per-timer registers take 0..3 as argument */
+#define MTU_LR(x) (0x10 + 0x10 * (x) + 0x00) /* Load value */
+#define MTU_VAL(x) (0x10 + 0x10 * (x) + 0x04) /* Current value */
+#define MTU_CR(x) (0x10 + 0x10 * (x) + 0x08) /* Control reg */
+#define MTU_BGLR(x) (0x10 + 0x10 * (x) + 0x0c) /* At next overflow */
+
+/* bits for the control register */
+#define MTU_CRn_ENA (0x01 << 7)
+#define MTU_CRn_DIS (0x00 << 7)
+#define MTU_CRn_PERIODIC (0x01 << 6) /* if 0 = free-running */
+#define MTU_CRn_FREERUNNING (0x00 << 6)
+#define MTU_CRn_PRESCALE_MASK (0x03 << 2)
+#define MTU_CRn_PRESCALE_1 (0x00 << 2)
+#define MTU_CRn_PRESCALE_16 (0x01 << 2)
+#define MTU_CRn_PRESCALE_256 (0x02 << 2)
+#define MTU_CRn_32BITS (0x01 << 1)
+
+/* if 0 = wraps reloading from BGLR*/
+#define MTU_CRn_ONESHOT (0x01 << 0)
+
+/* Other registers are usual amba/primecell registers, currently not used */
+#define MTU_ITCR 0xff0
+#define MTU_ITOP 0xff4
+
+#define MTU_PERIPH_ID0 0xfe0
+#define MTU_PERIPH_ID1 0xfe4
+#define MTU_PERIPH_ID2 0xfe8
+#define MTU_PERIPH_ID3 0xfeC
+
+#define MTU_PCELL0 0xff0
+#define MTU_PCELL1 0xff4
+#define MTU_PCELL2 0xff8
+#define MTU_PCELL3 0xffC
+
+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-rtt.c b/arch/arm/mach-ux500/timer-rtt.c
new file mode 100644
index 00000000000..e13ea25195f
--- /dev/null
+++ b/arch/arm/mach-ux500/timer-rtt.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com>
+ *
+ * NOTE: This timer is optimized to be used from cpuidle only, so
+ * if you enable this timer as broadcast timer, it won't work.
+ *
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/clockchips.h>
+
+#include <asm/smp.h>
+#include <asm/mach/time.h>
+
+#define RATE_32K 32768
+
+#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_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)
+
+static void __iomem *rtc_base;
+
+static void u8500_rtc_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ pr_err("timer-rtt: periodic timer not supported\n");
+ case CLOCK_EVT_MODE_ONESHOT:
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ /* Disable, self start and oneshot mode */
+ writel(RTC_TCR_RTTSS | RTC_TCR_RTTOS, rtc_base + RTC_TCR);
+ /*
+ * Here you should actually wait for 130 us before
+ * touching RTC_TCR again.
+ */
+ break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ break;
+
+ }
+}
+
+static int u8500_rtc_set_event(unsigned long delta,
+ struct clock_event_device *dev)
+{
+ /*
+ * Here you must be sure that the timer is off or else
+ * you'll probably fail programming it.
+ */
+ writel(delta, rtc_base + RTC_TLR1);
+
+ /* Here you must be sure not to touch TCR for 130 us */
+
+ return 0;
+}
+
+static irqreturn_t u8500_rtc_interrupt(int irq, void *dev)
+{
+
+ /* we make sure if this is our rtt isr */
+ if (readl(rtc_base + RTC_MIS) & RTC_MIS_RTCTMIS) {
+ writel(RTC_ICR_TIC, rtc_base + RTC_ICR);
+ /* Here you should normally call the event handler */
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+
+/*
+ * 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_rtt_clkevt = {
+ .name = "rtc-rtt",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ /* This timer is not working except from cpuidle */
+ .rating = 0,
+ .set_next_event = u8500_rtc_set_event,
+ .set_mode = u8500_rtc_set_mode,
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+ .broadcast = smp_timer_broadcast,
+#endif
+ .cpumask = cpu_all_mask,
+};
+
+extern struct clock_event_device u8500_mtu_clkevt;
+static struct irqaction u8500_rtc_irq = {
+ .name = "RTC-RTT Timer Tick",
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_SHARED,
+ .handler = u8500_rtc_interrupt,
+ .irq = IRQ_DB8500_RTC,
+};
+
+void u8500_rtc_init(unsigned int cpu)
+{
+
+ if (cpu_is_u8500()) {
+ rtc_base = __io_address(U8500_RTC_BASE);
+ } else if (cpu_is_u5500()) {
+ rtc_base = __io_address(U5500_RTC_BASE);
+ u8500_rtt_clkevt.irq = IRQ_DB5500_RTC;
+ } else {
+ pr_err("timer-rtt: Unknown DB Asic!\n");
+ return;
+ }
+
+ 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);
+
+ /* We can sleep for max 10s (actually max is longer) */
+ clockevents_calc_mult_shift(&u8500_rtt_clkevt, RATE_32K, 10);
+
+ u8500_rtt_clkevt.max_delta_ns = clockevent_delta2ns(0xffffffff,
+ &u8500_rtt_clkevt);
+ /* Don't program times less than eight cycles */
+ u8500_rtt_clkevt.min_delta_ns = clockevent_delta2ns(8,
+ &u8500_rtt_clkevt);
+ setup_irq(u8500_rtc_irq.irq, &u8500_rtc_irq);
+ clockevents_register_device(&u8500_rtt_clkevt);
+}
diff --git a/arch/arm/mach-ux500/uart-db8500.c b/arch/arm/mach-ux500/uart-db8500.c
new file mode 100644
index 00000000000..a2836da9cec
--- /dev/null
+++ b/arch/arm/mach-ux500/uart-db8500.c
@@ -0,0 +1,236 @@
+/*
+ * 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
+
+#define UX500_NR_UARTS 3
+
+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[UX500_NR_UARTS];
+
+
+static void save_uart(void)
+{
+ int i;
+ void __iomem *membase;
+
+ for (i = 0; i < UX500_NR_UARTS; i++) {
+ if (i != CONFIG_UX500_DEBUG_UART)
+ continue;
+
+ membase = context_uart[i].base;
+ clk_enable(context_uart[i].uart_clk);
+
+ context_uart[i].dma_wm = readl(membase + ST_UART011_DMAWM);
+ context_uart[i].timeout = readl(membase + ST_UART011_TIMEOUT);
+ context_uart[i].lcrh_rx = readl(membase + ST_UART011_LCRH_RX);
+ context_uart[i].ilpr = readl(membase + UART01x_ILPR);
+ context_uart[i].ibrd = readl(membase + UART011_IBRD);
+ context_uart[i].fbrd = readl(membase + UART011_FBRD);
+ context_uart[i].lcrh_tx = readl(membase + ST_UART011_LCRH_TX);
+ context_uart[i].cr = readl(membase + UART011_CR);
+ context_uart[i].ifls = readl(membase + UART011_IFLS);
+ context_uart[i].imsc = readl(membase + UART011_IMSC);
+ context_uart[i].dmacr = readl(membase + UART011_DMACR);
+ context_uart[i].xfcr = readl(membase + ST_UART011_XFCR);
+ context_uart[i].xon1 = readl(membase + ST_UART011_XON1);
+ context_uart[i].xon2 = readl(membase + ST_UART011_XON2);
+ context_uart[i].xoff1 = readl(membase + ST_UART011_XOFF1);
+ context_uart[i].xoff2 = readl(membase + ST_UART011_XOFF2);
+ context_uart[i].abcr = readl(membase + ST_UART011_ABCR);
+ context_uart[i].abimsc = readl(membase + ST_UART011_ABIMSC);
+
+ clk_disable(context_uart[i].uart_clk);
+ }
+}
+
+static void restore_uart(void)
+{
+ int i, cnt;
+ int retries = 100;
+ unsigned int cr;
+ void __iomem *membase;
+
+ for (i = 0; i < UX500_NR_UARTS; i++) {
+ if (i != CONFIG_UX500_DEBUG_UART)
+ continue;
+
+ membase = context_uart[i].base;
+ clk_enable(context_uart[i].uart_clk);
+
+ writew(context_uart[i].ifls, membase + UART011_IFLS);
+ cr = UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_LBE;
+
+ writew(cr, membase + UART011_CR);
+ writew(0, membase + UART011_FBRD);
+ writew(1, membase + UART011_IBRD);
+ writew(0, membase + ST_UART011_LCRH_RX);
+ if (context_uart[i].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)
+ writew(0xff, membase + UART011_MIS);
+ writew(0, membase + ST_UART011_LCRH_TX);
+ }
+ writew(0, membase + UART01x_DR);
+ do {
+ if (!(readw(membase + UART01x_FR) & UART01x_FR_BUSY))
+ break;
+ } while (retries-- > 0);
+ if (retries < 0)
+ pr_warning("%s:uart tx busy\n", __func__);
+ barrier();
+
+ writel(context_uart[i].dma_wm, membase + ST_UART011_DMAWM);
+ writel(context_uart[i].timeout, membase + ST_UART011_TIMEOUT);
+ writel(context_uart[i].lcrh_rx, membase + ST_UART011_LCRH_RX);
+ writel(context_uart[i].ilpr, membase + UART01x_ILPR);
+ writel(context_uart[i].ibrd, membase + UART011_IBRD);
+ writel(context_uart[i].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++)
+ writew(0xff, membase + UART011_MIS);
+
+ writel(context_uart[i].lcrh_tx, membase + ST_UART011_LCRH_TX);
+ writel(context_uart[i].ifls, membase + UART011_IFLS);
+ writel(context_uart[i].dmacr, membase + UART011_DMACR);
+ writel(context_uart[i].xfcr, membase + ST_UART011_XFCR);
+ writel(context_uart[i].xon1, membase + ST_UART011_XON1);
+ writel(context_uart[i].xon2, membase + ST_UART011_XON2);
+ writel(context_uart[i].xoff1, membase + ST_UART011_XOFF1);
+ writel(context_uart[i].xoff2, membase + ST_UART011_XOFF2);
+ writel(context_uart[i].abcr, membase + ST_UART011_ABCR);
+ writel(context_uart[i].abimsc, membase + ST_UART011_ABIMSC);
+ writel(context_uart[i].cr, membase + UART011_CR);
+ writel(context_uart[i].imsc, membase + UART011_IMSC);
+
+ clk_disable(context_uart[i].uart_clk);
+ }
+}
+
+
+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,
+};
+
+static void uart_context_notifier_init(void)
+{
+ context_uart[0].base = ioremap(U8500_UART0_BASE, SZ_4K);
+ context_uart[1].base = ioremap(U8500_UART1_BASE, SZ_4K);
+ context_uart[2].base = ioremap(U8500_UART2_BASE, SZ_4K);
+
+ context_uart[0].uart_clk = clk_get_sys("uart0", NULL);
+ if (IS_ERR(context_uart[0].uart_clk)) {
+ printk(KERN_ERR"%s:unable to get clk-uart0\n", __func__);
+ return;
+ }
+ context_uart[1].uart_clk = clk_get_sys("uart1", NULL);
+ if (IS_ERR(context_uart[1].uart_clk)) {
+ printk(KERN_ERR"%s:unable to get clk-uart1\n", __func__);
+ return;
+ }
+ context_uart[2].uart_clk = clk_get_sys("uart2", NULL);
+ if (IS_ERR(context_uart[2].uart_clk)) {
+ printk(KERN_ERR"%s:unable to get clk-uart2\n", __func__);
+ return;
+ }
+
+ WARN_ON(context_ape_notifier_register(&uart_context_notifier));
+}
+#else
+static void uart_context_notifier_init(void)
+{
+}
+#endif
+
+void __init db8500_uart_init(void)
+{
+ uart_context_notifier_init();
+}
diff --git a/arch/arm/mach-ux500/virt-regulator-u8500.c b/arch/arm/mach-ux500/virt-regulator-u8500.c
new file mode 100644
index 00000000000..4915a4cf636
--- /dev/null
+++ b/arch/arm/mach-ux500/virt-regulator-u8500.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> for ST-Ericsson
+ *
+ * Board specific file for configuration of virtual regulators. These virtual
+ * regulators are used for debug purposes. They connect to the regulator device
+ * just like any other consumer and expose controls in sysfs, so that
+ * regulators can be controlled from user space.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+/*
+ * Configuration for AB8500 virtual regulators
+ */
+static struct platform_device u8500_aux1_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 0,
+ .dev = {
+ .platform_data = "aux1",
+ },
+};
+
+static struct platform_device u8500_aux2_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 1,
+ .dev = {
+ .platform_data = "aux2",
+ },
+};
+
+static struct platform_device u8500_aux3_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 2,
+ .dev = {
+ .platform_data = "aux3",
+ },
+};
+
+static struct platform_device u8500_intcore_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 3,
+ .dev = {
+ .platform_data = "intcore",
+ },
+};
+
+static struct platform_device u8500_tvout_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 4,
+ .dev = {
+ .platform_data = "tvout",
+ },
+};
+
+static struct platform_device u8500_audio_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 5,
+ .dev = {
+ .platform_data = "audio",
+ },
+};
+
+static struct platform_device u8500_anamic1_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 6,
+ .dev = {
+ .platform_data = "anamic1",
+ },
+};
+
+static struct platform_device u8500_anamic2_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 7,
+ .dev = {
+ .platform_data = "anamic2",
+ },
+};
+
+static struct platform_device u8500_dmic_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 8,
+ .dev = {
+ .platform_data = "dmic",
+ },
+};
+
+static struct platform_device u8500_ana_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 9,
+ .dev = {
+ .platform_data = "ana",
+ },
+};
+
+static struct platform_device u8500_sysclkreq_2_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 10,
+ .dev = {
+ .platform_data = "sysclkreq-2",
+ },
+};
+
+static struct platform_device u8500_sysclkreq_4_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 11,
+ .dev = {
+ .platform_data = "sysclkreq-4",
+ },
+};
+
+/*
+ * Configuration for other U8500 virtual regulators
+ */
+static struct platform_device u8500_ape_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 12,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_arm_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 13,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_modem_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 14,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_pll_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 15,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_smps1_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 16,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_smps2_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 17,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_smps3_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 18,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_rf1_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 19,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+/*
+ * Configuration for U8500 power domain virtual regulators
+ */
+static struct platform_device u8500_sva_mmdsp_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 20,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_sva_mmdsp_ret_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 21,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_sva_pipe_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 22,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_sia_mmdsp_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 23,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_sia_mmdsp_ret_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 24,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_sia_pipe_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 25,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_sga_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 26,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_b2r2_mcde_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 27,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_esram12_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 28,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_esram12_ret_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 29,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_esram34_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 30,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device u8500_esram34_ret_virtual_regulator_device = {
+ .name = "reg-virt-consumer",
+ .id = 31,
+ .dev = {
+ .platform_data = "test",
+ },
+};
+
+static struct platform_device *u8500_virtual_regulator_devices[] = {
+ &u8500_aux1_virtual_regulator_device,
+ &u8500_aux2_virtual_regulator_device,
+ &u8500_aux3_virtual_regulator_device,
+ &u8500_intcore_virtual_regulator_device,
+ &u8500_tvout_virtual_regulator_device,
+ &u8500_audio_virtual_regulator_device,
+ &u8500_anamic1_virtual_regulator_device,
+ &u8500_anamic2_virtual_regulator_device,
+ &u8500_dmic_virtual_regulator_device,
+ &u8500_ana_virtual_regulator_device,
+ &u8500_sysclkreq_2_virtual_regulator_device,
+ &u8500_sysclkreq_4_virtual_regulator_device,
+ &u8500_ape_virtual_regulator_device,
+ &u8500_arm_virtual_regulator_device,
+ &u8500_modem_virtual_regulator_device,
+ &u8500_pll_virtual_regulator_device,
+ &u8500_smps1_virtual_regulator_device,
+ &u8500_smps2_virtual_regulator_device,
+ &u8500_smps3_virtual_regulator_device,
+ &u8500_rf1_virtual_regulator_device,
+ &u8500_sva_mmdsp_virtual_regulator_device,
+ &u8500_sva_mmdsp_ret_virtual_regulator_device,
+ &u8500_sva_pipe_virtual_regulator_device,
+ &u8500_sia_mmdsp_virtual_regulator_device,
+ &u8500_sia_mmdsp_ret_virtual_regulator_device,
+ &u8500_sia_pipe_virtual_regulator_device,
+ &u8500_sga_virtual_regulator_device,
+ &u8500_b2r2_mcde_virtual_regulator_device,
+ &u8500_esram12_virtual_regulator_device,
+ &u8500_esram12_ret_virtual_regulator_device,
+ &u8500_esram34_virtual_regulator_device,
+ &u8500_esram34_ret_virtual_regulator_device,
+};
+
+static int __init u8500_virtual_regulator_init(void)
+{
+ int ret;
+
+ ret = platform_add_devices(u8500_virtual_regulator_devices,
+ ARRAY_SIZE(u8500_virtual_regulator_devices));
+ if (ret != 0)
+ pr_err("Failed to register U8500 virtual regulator devices:"
+ " %d\n", ret);
+
+ return ret;
+}
+module_init(u8500_virtual_regulator_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com");
+MODULE_DESCRIPTION("Configuration of u8500 virtual regulators");
+MODULE_ALIAS("platform:u8500-virtual-regulator");