diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2012-03-19 09:23:28 +0100 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@linaro.org> | 2012-03-19 09:23:28 +0100 |
commit | 95672cd1656bc5a45bb944f319547b3dbd32ee25 (patch) | |
tree | c72751682c4da7df67998506df4454208befe5ec /arch | |
parent | 350ab868ed4959536700fa201abd7dab562b171c (diff) | |
parent | d209c783f1ce1cf966800c6fae73e93c6ab3cddc (diff) |
Merge topic branch 'mach-plat' into integration-linux-ux500-3.3
Diffstat (limited to 'arch')
54 files changed, 6238 insertions, 1222 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 58ad0515e3a..46ad3ebd89b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1583,7 +1583,7 @@ config LOCAL_TIMERS config ARCH_NR_GPIO int default 1024 if ARCH_SHMOBILE || ARCH_TEGRA - default 350 if ARCH_U8500 + default 355 if ARCH_U8500 default 0 help Maximum number of GPIOs in the system. diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index c59e8b892d6..359fbd35644 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -4,21 +4,26 @@ config UX500_SOC_COMMON bool default y select ARM_GIC - select HAS_MTU + select NOMADIK_GPIO select PL310_ERRATA_753970 select ARM_ERRATA_754322 select ARM_ERRATA_764369 + select SYS_SOC + select HAS_MTU + +config UX500_SOC_DBX500 + depends on UX500_SOC_DB5500 || UX500_SOC_DB8500 + bool menu "Ux500 SoC" config UX500_SOC_DB5500 bool "DB5500" - select MFD_DB5500_PRCMU + select UX500_SOC_DBX500 config UX500_SOC_DB8500 bool "DB8500" - select MFD_DB8500_PRCMU - select REGULATOR_DB8500_PRCMU + select UX500_SOC_DBX500 endmenu @@ -27,13 +32,13 @@ menu "Ux500 target platform (boards)" config MACH_U8500 bool "U8500 Development platform" depends on UX500_SOC_DB8500 - select TPS6105X help Include support for the mop500 development platform. config MACH_HREFV60 bool "U85000 Development platform, HREFv60 version" depends on UX500_SOC_DB8500 + select MACH_U8500 help Include support for the HREFv60 new development platform. @@ -51,6 +56,50 @@ config MACH_U5500 Include support for the U5500 development platform. endmenu +choice + prompt "Ux500 UIB Keylayout" + default KEYLAYOUT_LAYOUT1 + +config KEYLAYOUT_LAYOUT1 + bool "UIB Keylayout 1; for generic users" + help + Supported keylayout for some numerics, power/call buttons, + volume control etc + +config KEYLAYOUT_LAYOUT2 + bool "UIB Keylayout 2; for connectivity users" + help + Supports keylayout numerics 0-9, left/right/up/down/back/ + enter keys and special character "."(dot) + +endchoice + +choice + prompt "DBx500 sched_clock" + +config DBX500_SCHED_CLOCK_PRCMU + bool "PRCMU Timer sched_clock" + depends on CLKSRC_DBX500_PRCMU + select CLKSRC_DBX500_PRCMU_SCHED_CLOCK + help + Use the always on PRCMU Timer as sched_clock + +config DB5500_MTIMER_SCHED_CLOCK + bool "MTIMER sched_clock" + depends on CLKSRC_DB5500_MTIMER + select CLKSRC_DB5500_MTIMER_SCHED_CLOCK + help + Use the always on MTIMER as sched_clock + +config DBX500_MTU_SCHED_CLOCK + bool "MTU sched_clock" + depends on HAS_MTU + select NOMADIK_MTU_SCHED_CLOCK + help + Use the Multi Timer Unit as the sched_clock. + +endchoice + config UX500_DEBUG_UART int "Ux500 UART to use for low-level debug" default 2 @@ -58,6 +107,12 @@ config UX500_DEBUG_UART Choose the UART on which kernel low-level debug messages should be output. +config UX500_GPIO_KEYS + bool "Use gpio-keys for proximity and hal sensors" + depends on KEYBOARD_GPIO + help + Add proximity and hal sensors as a gpio keyboard. + config U5500_MODEM_IRQ bool "Modem IRQ support" depends on UX500_SOC_DB5500 @@ -65,11 +120,56 @@ config U5500_MODEM_IRQ help Add support for handling IRQ:s from modem side -config U5500_MBOX - bool "Mailbox support" - depends on U5500_MODEM_IRQ +config DBX500_PRCMU_DEBUG + bool "DBX500 PRCMU debug" + depends on ((MFD_DB5500_PRCMU || MFD_DB8500_PRCMU) && DEBUG_FS) + help + Add support for PRCMU debug + +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 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. + +config UX500_L2X0_PREFETCH_CTRL + bool "PL310 prefetch control" + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) && \ + (TEE_UX500 && CACHE_L2X0) default y help - Add support for U5500 mailbox communication with modem side + Adds interface to control instruction and data prefetch. + Communication with Trustzone is done through TEE driver. + +config UX500_DB_DUMP + bool "DBx500 register dump on crash" + depends on (UX500_SOC_DB8500 || UX500_SOC_DB5500) + default y + help + Reads specific DBx500 register in case of kernel crash + and saves it. + +source "arch/arm/mach-ux500/pm/Kconfig" endif diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 6bd2f451c18..c3a5e7621b2 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -1,21 +1,69 @@ # -# Makefile for the linux kernel, U8500 machine. +# Makefile for the linux kernel, UX500 machine. # -obj-y := clock.o cpu.o devices.o devices-common.o \ - id.o usb.o timer.o +obj-y := clock.o cpu.o devices.o \ + devices-common.o id.o pins.o \ + usb.o reboot_reasons.o timer.o \ + uart-db8500.o clock-debug.o +obj-y += pm/ obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o -obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o -obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o + + +ifeq ($(CONFIG_UX500_SOC_DB5500), y) +obj-$(CONFIG_UX500_SOC_DBX500) += cpu-db5500.o dma-db5500.o \ + devices-db5500.o clock-db5500.o +board-mcde-objs += board-u5500-mcde.o +endif +ifeq ($(CONFIG_UX500_SOC_DB8500), y) +obj-$(CONFIG_UX500_SOC_DBX500) += cpu-db8500.o devices-db8500.o \ + clock-db8500.o dma-db8500.o cpu-db9500.o +board-mcde-objs += board-mop500-mcde.o +endif obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ board-mop500-regulators.o \ board-mop500-uib.o board-mop500-stuib.o \ - board-mop500-u8500uib.o \ - board-mop500-pins.o -obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o + board-mop500-u8500uib.o board-mop500-pins.o \ + board-mop500-bm.o \ + board-pins-sleep-force.o +obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o \ + board-u5500-regulators.o \ + board-u5500-pins.o +obj-$(CONFIG_U5500_MMIO) += board-u5500-mmio.o +obj-$(CONFIG_U8500_MMIO) += board-mop500-mmio.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o -obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o +obj-$(CONFIG_TEE_UX500) += tee_ux500.o product.o +obj-$(CONFIG_TEE_SVP) += tee_service_svp.o +obj-$(CONFIG_TEE_SVP) += tee_ta_start_modem_svp.o +obj-$(CONFIG_DB8500_MLOADER) += mloader-db8500.o +obj-$(CONFIG_U5500_MLOADER) += mloader-db5500.o +obj-$(CONFIG_UX500_DEBUG_HWREG) += hwreg.o +obj-$(CONFIG_HWMEM) += hwmem-int.o +obj-$(CONFIG_UX500_L2X0_PREFETCH_CTRL) += l2x0-prefetch.o +obj-$(CONFIG_AB5500_BM) += board-u5500-bm.o +obj-$(CONFIG_DBX500_PRCMU_DEBUG) += prcmu-debug.o +obj-$(CONFIG_UX500_DB_DUMP) += dbx500_dump.o + +obj-$(CONFIG_HWMEM) += dcache.o +ifdef CONFIG_STM_TRACE +obj-$(CONFIG_MACH_U8500) += board-mop500-stm.o +endif +ifdef CONFIG_SENSORS_LSM303DLH +obj-$(CONFIG_MACH_U8500) += board-mop500-sensors.o +endif +obj-$(CONFIG_FB_MCDE) += board-mcde.o +ifdef CONFIG_STM_MSP_SPI +obj-$(CONFIG_MACH_U8500) += board-mop500-msp.o +endif +ifdef CONFIG_CW1200 +obj-$(CONFIG_MACH_U8500) += board-mop500-wlan.o +obj-$(CONFIG_MACH_U5500) += board-u5500-wlan.o +endif +ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI +obj-$(CONFIG_MACH_U8500) += board-mop500-cyttsp.o +obj-$(CONFIG_MACH_U5500) += board-u5500-cyttsp.o +endif diff --git a/arch/arm/mach-ux500/board-mop500-cyttsp.c b/arch/arm/mach-ux500/board-mop500-cyttsp.c new file mode 100755 index 00000000000..2bfa9fb17fa --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-cyttsp.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA + * Author: Avinash A <avinash.a@stericsson.com> for ST-Ericsson + * License terms:GNU General Public License (GPL) version 2 + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/gpio.h> +#include <linux/cyttsp.h> +#include <linux/delay.h> +#include <linux/gpio/nomadik.h> +#include <linux/i2c.h> +#include <linux/input/matrix_keypad.h> +#include <linux/mfd/tc3589x.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <linux/amba/pl022.h> +#include <plat/pincfg.h> +#include <mach/hardware.h> +#include <mach/irqs.h> +#include <mach/irqs-db8500.h> +#include <asm/mach-types.h> +#include "pins-db8500.h" +#include "board-mop500.h" +#include "devices-db8500.h" + +#define NUM_SSP_CLIENTS 10 + +/* cyttsp_gpio_board_init : configures the touch panel. */ +static int cyttsp_plat_init(int on) +{ + int ret; + + ret = gpio_direction_output(CYPRESS_SLAVE_SELECT_GPIO, 1); + if (ret < 0) { + pr_err("slave select gpio direction failed\n"); + gpio_free(CYPRESS_SLAVE_SELECT_GPIO); + return ret; + } + return 0; +} + +static struct pl022_ssp_controller mop500_spi2_data = { + .bus_id = SPI023_2_CONTROLLER, + .num_chipselect = NUM_SSP_CLIENTS, +}; + +static int cyttsp_wakeup(void) +{ + int ret; + + ret = gpio_request(CYPRESS_TOUCH_INT_PIN, "Wakeup_pin"); + if (ret < 0) { + pr_err("touch gpio failed\n"); + return ret; + } + ret = gpio_direction_output(CYPRESS_TOUCH_INT_PIN, 1); + if (ret < 0) { + pr_err("touch gpio direction failed\n"); + goto out; + } + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 0); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 1); + /* + * To wake up the controller from sleep + * state the interrupt pin needs to be + * pulsed twice with a delay greater + * than 2 micro seconds. + */ + udelay(3); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 0); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 1); + ret = gpio_direction_input(CYPRESS_TOUCH_INT_PIN); + if (ret < 0) { + pr_err("touch gpio direction IN config failed\n"); + goto out; + } +out: + gpio_free(CYPRESS_TOUCH_INT_PIN); + return 0; +} +struct cyttsp_platform_data cyttsp_platdata = { + .maxx = 480, + .maxy = 854, + .flags = 0, + .gen = CY_GEN3, + .use_st = 0, + .use_mt = 1, + .use_trk_id = 0, + .use_hndshk = 0, + .use_sleep = 1, + .use_gestures = 0, + .use_load_file = 0, + .use_force_fw_update = 0, + .use_virtual_keys = 0, + /* activate up to 4 groups and set active distance */ + .gest_set = CY_GEST_GRP_NONE | CY_ACT_DIST, + /* change scn_type to enable finger and/or stylus detection */ + .scn_typ = 0xA5, /* autodetect finger+stylus; balanced mutual scan */ + .act_intrvl = CY_ACT_INTRVL_DFLT, /* Active refresh interval; ms */ + .tch_tmout = CY_TCH_TMOUT_DFLT, /* Active touch timeout; ms */ + .lp_intrvl = CY_LP_INTRVL_DFLT, /* Low power refresh interval; ms */ + .init = cyttsp_plat_init, + .mt_sync = input_mt_sync, + .wakeup = cyttsp_wakeup, + .name = CY_SPI_NAME, + .irq_gpio = CYPRESS_TOUCH_INT_PIN, + .rst_gpio = CYPRESS_TOUCH_RST_GPIO, +}; + +static void cyttsp_spi_cs_control(u32 command) +{ + if (command == SSP_CHIP_SELECT) + gpio_set_value(CYPRESS_SLAVE_SELECT_GPIO, 0); + else if (command == SSP_CHIP_DESELECT) + gpio_set_value(CYPRESS_SLAVE_SELECT_GPIO, 1); +} + +static struct pl022_config_chip cyttsp_ssp_config_chip = { + .com_mode = INTERRUPT_TRANSFER, + .iface = SSP_INTERFACE_MOTOROLA_SPI, + /* we can act as master only */ + .hierarchy = SSP_MASTER, + .slave_tx_disable = 0, + .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, + .tx_lev_trig = SSP_TX_16_OR_MORE_EMPTY_LOC, + .ctrl_len = SSP_BITS_16, + .wait_state = SSP_MWIRE_WAIT_ZERO, + .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, + .cs_control = cyttsp_spi_cs_control, +}; + +static struct spi_board_info cypress_spi_devices[] = { + { + .modalias = CY_SPI_NAME, + .controller_data = &cyttsp_ssp_config_chip, + .platform_data = &cyttsp_platdata, + .max_speed_hz = 1000000, + .bus_num = SPI023_2_CONTROLLER, + .chip_select = 0, + .mode = SPI_MODE_0, + } +}; + +/* + * TC35893 + */ +static const unsigned int sony_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 sony_keymap_data = { + .keymap = sony_keymap, + .keymap_size = ARRAY_SIZE(sony_keymap), +}; + +static struct tc3589x_keypad_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, + .enable_wakeup = true, + .keymap_data = &sony_keymap_data, + .no_autorepeat = true, +}; + +static struct tc3589x_platform_data tc3589x_keypad_data = { + .block = TC3589x_BLOCK_KEYPAD, + .keypad = &tc35893_data, + .irq_base = MOP500_EGPIO_IRQ_BASE, +}; + +static struct i2c_board_info __initdata mop500_i2c0_devices_u8500[] = { + { + I2C_BOARD_INFO("tc3589x", 0x44), + .platform_data = &tc3589x_keypad_data, + .irq = NOMADIK_GPIO_TO_IRQ(64), + .flags = I2C_CLIENT_WAKE, + }, +}; + +void mop500_cyttsp_init(void) +{ + int ret = 0; + + /* + * Enable the alternative C function + * in the PRCMU register + */ + prcmu_enable_spi2(); + ret = gpio_request(CYPRESS_SLAVE_SELECT_GPIO, "slave_select_gpio"); + if (ret < 0) + pr_err("slave select gpio failed\n"); + spi_register_board_info(cypress_spi_devices, + ARRAY_SIZE(cypress_spi_devices)); +} + +void __init mop500_u8500uib_r3_init(void) +{ + mop500_cyttsp_init(); + db8500_add_spi2(&mop500_spi2_data); + nmk_config_pin((GPIO64_GPIO | PIN_INPUT_PULLUP), false); + mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, + ARRAY_SIZE(mop500_i2c0_devices_u8500)); + mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, + ARRAY_SIZE(mop500_i2c0_devices_u8500)); +} diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index 74bfcff2bdf..8f9b02e252f 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -6,109 +6,50 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/string.h> #include <asm/mach-types.h> #include <plat/pincfg.h> -#include <plat/gpio-nomadik.h> +#include <linux/gpio/nomadik.h> +#include <linux/mfd/abx500/ab8500-gpio.h> + #include <mach/hardware.h> +#include <mach/suspend.h> #include "pins-db8500.h" +#include "pins.h" +#include "board-mop500.h" +#include "board-pins-sleep-force.h" + +enum custom_pin_cfg_t { + PINS_FOR_DEFAULT, + PINS_FOR_U9500, +}; + +static enum custom_pin_cfg_t pinsfor; static pin_cfg_t mop500_pins_common[] = { - /* 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, - - /* MSP0 */ + /* uMSP0 */ GPIO12_MSP0_TXD, GPIO13_MSP0_TFS, GPIO14_MSP0_TCK, GPIO15_MSP0_RXD, /* MSP2: HDMI */ - GPIO193_MSP2_TXD, - GPIO194_MSP2_TCK, - GPIO195_MSP2_TFS, + GPIO193_MSP2_TXD | PIN_INPUT_PULLDOWN, + GPIO194_MSP2_TCK | PIN_INPUT_PULLDOWN, + GPIO195_MSP2_TFS | PIN_INPUT_PULLDOWN, GPIO196_MSP2_RXD | PIN_OUTPUT_LOW, + /* LCD TE0 */ + GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP, + /* Touch screen INTERFACE */ GPIO84_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT1 */ /* STMPE1601/tc35893 keypad IRQ */ GPIO218_GPIO | PIN_INPUT_PULLUP, - /* MMC0 (MicroSD card) */ - 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 (SDIO) */ - 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 (On-board DATA INTERFACE eMMC) */ - 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, - - /* MMC4 (On-board STORAGE INTERFACE 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, - - /* SKE keypad */ - GPIO153_KP_I7, - GPIO154_KP_I6, - GPIO155_KP_I5, - GPIO156_KP_I4, - GPIO157_KP_O7, - GPIO158_KP_O6, - GPIO159_KP_O5, - GPIO160_KP_O4, - GPIO161_KP_I3, - GPIO162_KP_I2, - GPIO163_KP_I1, - GPIO164_KP_I0, - GPIO165_KP_O3, - GPIO166_KP_O2, - GPIO167_KP_O1, - GPIO168_KP_O0, - /* UART */ /* uart-0 pins gpio configuration should be * kept intact to prevent glitch in tx line @@ -127,10 +68,6 @@ static pin_cfg_t mop500_pins_common[] = { GPIO30_U2_TXD | PIN_OUTPUT_HIGH, GPIO31_U2_CTSn | PIN_INPUT_PULLUP, GPIO32_U2_RTSn | PIN_OUTPUT_HIGH, - - /* Display & HDMI HW sync */ - GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP, - GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP, }; static pin_cfg_t mop500_pins_default[] = { @@ -140,10 +77,13 @@ static pin_cfg_t mop500_pins_default[] = { GPIO145_SSP0_RXD | PIN_PULL_DOWN, GPIO146_SSP0_TXD, + /* XENON Flashgun INTERFACE */ + GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */ + GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */ GPIO217_GPIO | PIN_INPUT_PULLUP, /* TC35892 IRQ */ - /* SDI0 (MicroSD card) */ + /* sdi0 (removable MMC/SD/SDIO cards) not handled by pm_runtime */ GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH, /* UART */ @@ -155,13 +95,11 @@ static pin_cfg_t mop500_pins_default[] = { static pin_cfg_t hrefv60_pins[] = { /* WLAN */ - GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ GPIO85_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */ /* XENON Flashgun INTERFACE */ GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */ GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */ - GPIO170_GPIO | PIN_OUTPUT_LOW, /* XENON_CHARGE */ /* Assistant LED INTERFACE */ GPIO21_GPIO | PIN_OUTPUT_LOW, /* XENON_EN1 */ @@ -172,7 +110,7 @@ static pin_cfg_t hrefv60_pins[] = { GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */ /* Display Interface */ - GPIO65_GPIO | PIN_OUTPUT_LOW, /* DISP1 RST */ + GPIO65_GPIO | PIN_OUTPUT_HIGH, /* DISP1 NO RST */ GPIO66_GPIO | PIN_OUTPUT_LOW, /* DISP2 RST */ /* Touch screen INTERFACE */ @@ -214,11 +152,8 @@ static pin_cfg_t hrefv60_pins[] = { /* DiPro Sensor Interface */ GPIO139_GPIO | PIN_INPUT_PULLUP, /* DIPRO_INT */ - /* HAL SWITCH INTERFACE */ - GPIO145_GPIO | PIN_INPUT_PULLDOWN,/* HAL_SW */ - /* Audio Amplifier Interface */ - GPIO149_GPIO | PIN_OUTPUT_LOW, /* VAUDIO_HF_EN */ + GPIO149_GPIO | PIN_OUTPUT_HIGH, /* VAUDIO_HF_EN, enable MAX8968 */ /* GBF INTERFACE */ GPIO171_GPIO | PIN_OUTPUT_LOW, /* GBF_ENA_RESET */ @@ -230,10 +165,29 @@ static pin_cfg_t hrefv60_pins[] = { GPIO82_GPIO | PIN_INPUT_PULLUP, /* ACC_INT1 */ GPIO83_GPIO | PIN_INPUT_PULLUP, /* ACC_INT2 */ - /* Proximity Sensor */ - GPIO217_GPIO | PIN_INPUT_PULLUP, + /* SD card detect */ + GPIO95_GPIO | PIN_INPUT_PULLUP, +}; +static pin_cfg_t u9500_pins[] = { + GPIO4_U1_RXD | PIN_INPUT_PULLUP, + GPIO5_U1_TXD | PIN_OUTPUT_HIGH, + GPIO144_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ + /* HSI */ + GPIO219_HSIR_FLA0 | PIN_INPUT_PULLDOWN, + GPIO220_HSIR_DAT0 | PIN_INPUT_PULLDOWN, + GPIO221_HSIR_RDY0 | PIN_OUTPUT_LOW, + GPIO222_HSIT_FLA0 | PIN_OUTPUT_LOW, + GPIO223_HSIT_DAT0 | PIN_OUTPUT_LOW, + GPIO224_HSIT_RDY0 | PIN_INPUT_PULLDOWN, + GPIO225_HSIT_CAWAKE0 | PIN_INPUT_PULLDOWN, /* CA_WAKE0 */ + GPIO226_GPIO | PIN_OUTPUT_HIGH, /* AC_WAKE0 */ +}; + +static pin_cfg_t u8500_pins[] = { + GPIO226_GPIO | PIN_OUTPUT_LOW, /* WLAN_PMU_EN */ + GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ }; static pin_cfg_t snowball_pins[] = { @@ -274,15 +228,852 @@ static pin_cfg_t snowball_pins[] = { /* RSTn_LAN */ GPIO141_GPIO | PIN_OUTPUT_HIGH, + + /* Accelerometer/Magnetometer */ + GPIO163_GPIO | PIN_INPUT_PULLUP, /* ACCEL_IRQ1 */ + GPIO164_GPIO | PIN_INPUT_PULLUP, /* ACCEL_IRQ2 */ + GPIO165_GPIO | PIN_INPUT_PULLUP, /* MAG_DRDY */ + + /* WLAN/GBF */ + GPIO171_GPIO | PIN_OUTPUT_HIGH,/* GBF_ENA */ + GPIO215_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */ + GPIO216_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ +}; + +/* + * I2C + */ + +static UX500_PINS(mop500_pins_i2c0, + GPIO147_I2C0_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO148_I2C0_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c1, + GPIO16_I2C1_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO17_I2C1_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c2, + GPIO10_I2C2_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO11_I2C2_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_i2c3, + GPIO229_I2C3_SDA | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO230_I2C3_SCL | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_mcde_tvout, + GPIO78_LCD_D8, + GPIO79_LCD_D9, + GPIO80_LCD_D10, + GPIO81_LCD_D11, + GPIO150_LCDA_CLK, +); + +static UX500_PINS(mop500_pins_mcde_hdmi, + GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP, +); + +static UX500_PINS(mop500_pins_ske, + 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, +); + +/* 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, + 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, +); + +/* USB */ +static UX500_PINS(mop500_pins_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, +); + +/* SPI2 */ +static UX500_PINS(mop500_pins_spi2, + GPIO216_GPIO | PIN_OUTPUT_HIGH, + GPIO218_SPI2_RXD | PIN_INPUT_PULLDOWN, + GPIO215_SPI2_TXD | PIN_OUTPUT_LOW, + GPIO217_SPI2_CLK | PIN_OUTPUT_LOW, +); + +static UX500_PINS(mop500_pins_sensors1p_v60, + GPIO217_GPIO| PIN_INPUT_PULLUP | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO145_GPIO | PIN_INPUT_PULLDOWN | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, + GPIO139_GPIO | PIN_INPUT_PULLUP | + PIN_SLPM_GPIO | PIN_SLPM_INPUT_NOPULL, +); + +static UX500_PINS(mop500_pins_sensors1p, + PIN_CFG_INPUT(GPIO_PROX_SENSOR, GPIO, NOPULL), + PIN_CFG_INPUT(GPIO_HAL_SENSOR, GPIO, NOPULL), +); + +static struct ux500_pin_lookup mop500_runtime_pins[] = { + PIN_LOOKUP("mcde-tvout", &mop500_pins_mcde_tvout), + PIN_LOOKUP("av8100-hdmi", &mop500_pins_mcde_hdmi), + 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("sdi0", &mop500_pins_sdi0), + PIN_LOOKUP("sdi1", &mop500_pins_sdi1), + PIN_LOOKUP("sdi2", &mop500_pins_sdi2), + PIN_LOOKUP("sdi4", &mop500_pins_sdi4), + PIN_LOOKUP("ab8500-usb.0", &mop500_pins_usb), + PIN_LOOKUP("spi2", &mop500_pins_spi2), +}; + +static struct ux500_pin_lookup mop500_runtime_pins_v60[] = { + PIN_LOOKUP("ske", &mop500_pins_ske), + PIN_LOOKUP("gpio-keys.0", &mop500_pins_sensors1p_v60), }; +static struct ux500_pin_lookup mop500_runtime_pins_pre_v60[] = { + PIN_LOOKUP("ske", &mop500_pins_ske), + PIN_LOOKUP("gpio-keys.0", &mop500_pins_sensors1p), +}; + +/* + * Sleep pin configuration for u8500 platform. + * If another HW is used the GPIO's must be configured + * correctly when entering sleep for optimal power + * consumption. + */ +static pin_cfg_t mop500_pins_common_power_save_bank0[] = { + GPIO0_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO1_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO2_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO3_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO4_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO5_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO6_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO7_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO8_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO9_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 10-11 - I2C2 */ + GPIO10_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO11_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO12_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO13_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO14_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO15_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 16-17 - I2C1 */ + GPIO16_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO17_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO18_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO19_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO20_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO21_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO22_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO23_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO24_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO25_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO26_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO27_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO28_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO29_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO30_U2_TXD | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO31_U2_CTSn | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank0_href60[] = { + GPIO0_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO1_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO2_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO3_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO4_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO5_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO6_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO7_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO8_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO9_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 10-11 - I2C2 */ + GPIO10_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO11_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO12_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO13_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO14_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO15_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 16-17 - I2C1 */ + GPIO16_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO17_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO18_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO19_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO20_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO21_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO22_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO23_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO24_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO25_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO26_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO27_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO28_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO29_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO30_U2_TXD | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO31_U2_CTSn | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank1[] = { + GPIO32_U2_RTSn | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO33_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO34_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO35_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO36_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank2[] = { + GPIO64_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO65_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO66_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO67_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO68_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO69_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO70_STMAPE_CLK | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO71_STMAPE_DAT3 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO72_STMAPE_DAT2 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO73_STMAPE_DAT1 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO74_STMAPE_DAT0 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO75_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO76_U2_TXD | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO77_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO78_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO79_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO80_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO81_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO82_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO83_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO84_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO85_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO86_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO87_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO88_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO89_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO90_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO91_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO92_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO93_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO94_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO95_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank2_href60[] = { + GPIO64_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO65_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO66_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO67_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO68_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO69_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO70_STMAPE_CLK | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO71_STMAPE_DAT3 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO72_STMAPE_DAT2 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO73_STMAPE_DAT1 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO74_STMAPE_DAT0 | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_DISABLE | PIN_SLPM_PDIS_DISABLED, + GPIO75_U2_RXD | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO76_U2_TXD | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO77_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO78_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO79_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO80_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO81_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO82_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO83_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO84_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO85_GPIO, + GPIO86_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO87_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO88_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO89_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO90_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO91_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO92_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO93_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO94_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO95_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank3[] = { + GPIO96_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO97_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank4[] = { + GPIO128_MC2_CLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO129_MC2_CMD | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO130_MC2_FBCLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO131_MC2_DAT0 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO132_MC2_DAT1 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO133_MC2_DAT2 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO134_MC2_DAT3 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO135_MC2_DAT4 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO136_MC2_DAT5 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO137_MC2_DAT6 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO138_MC2_DAT7 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO139_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO140_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO141_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO142_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO143_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO144_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 145 - HAL sensor (on v60 and later) */ + GPIO145_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO146_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 147-148 - I2C0 */ + GPIO147_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO148_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO149_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO150_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO151_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO152_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO153_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO154_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO155_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO156_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO157_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO158_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO159_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank4_u9500_uibr3[] = { + GPIO128_MC2_CLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO129_MC2_CMD | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO130_MC2_FBCLK | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO131_MC2_DAT0 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO132_MC2_DAT1 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO133_MC2_DAT2 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO134_MC2_DAT3 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO135_MC2_DAT4 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO136_MC2_DAT5 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO137_MC2_DAT6 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO138_MC2_DAT7 | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO139_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO140_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO141_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO142_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO143_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO144_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 145 - HAL sensor (on v60 and later) */ + GPIO145_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + /* 147-148 - I2C0 */ + GPIO147_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO148_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO149_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO150_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO151_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO152_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO153_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO154_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO155_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO156_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO157_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO158_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO159_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank5[] = { + GPIO160_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO161_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO162_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO163_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO164_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO165_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO166_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO167_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO168_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO169_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO170_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO171_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank5_href60[] = { + GPIO160_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO161_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO162_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO163_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO164_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO165_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO166_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO167_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO168_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO169_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO170_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO171_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank6[] = { + GPIO192_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO193_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO194_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO195_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO196_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO197_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO198_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO199_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO200_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO201_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO202_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO203_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO204_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO205_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO206_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO207_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO208_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO209_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO210_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO211_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO212_GPIO, + GPIO213_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO214_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO215_GPIO, + + GPIO216_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO219_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO220_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO221_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO222_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO223_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank6_href60[] = { + GPIO192_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO193_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO194_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO195_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO196_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO197_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO198_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO199_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO200_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO201_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO202_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO203_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO204_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO205_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO206_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO207_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO208_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO209_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO210_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO211_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO212_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO213_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO214_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO215_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO216_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 217 - Proximity */ + GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO219_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO220_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO221_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO222_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO223_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank6_u9500[] = { + GPIO192_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO193_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO194_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO195_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO196_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO197_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO198_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO199_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO200_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO201_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO202_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO203_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO204_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO205_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO206_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO207_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO208_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO209_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO210_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO211_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO212_GPIO, + GPIO213_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO214_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO215_GPIO, + + GPIO216_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO217_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO218_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO219_GPIO | PIN_SLPM_INPUT_PULLDOWN, + + GPIO220_GPIO | PIN_SLPM_INPUT_PULLDOWN, + GPIO221_GPIO | PIN_SLPM_OUTPUT_LOW, + GPIO222_GPIO | PIN_SLPM_OUTPUT_LOW, + GPIO223_GPIO | PIN_SLPM_OUTPUT_LOW, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank7[] = { + GPIO224_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO225_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO226_GPIO | PIN_SLPM_DIR_OUTPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO227_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO228_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 229-230 - I2C3 */ + GPIO229_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO230_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank7_href60[] = { + GPIO224_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO225_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO226_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO227_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO228_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + /* 229-230 - I2C3 */ + GPIO229_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO230_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank7_u9500[] = { + GPIO224_GPIO | PIN_SLPM_INPUT_PULLDOWN, + GPIO225_GPIO | PIN_SLPM_INPUT_PULLDOWN | PIN_SLPM_WAKEUP_ENABLE, + GPIO226_GPIO | PIN_SLPM_OUTPUT_LOW, + GPIO227_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + + GPIO228_GPIO | PIN_SLPM_OUTPUT_LOW | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO229_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO230_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, +}; + +static pin_cfg_t mop500_pins_common_power_save_bank8[] = { + GPIO256_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO257_GPIO | PIN_SLPM_OUTPUT_HIGH | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_DISABLED, + GPIO258_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO259_GPIO | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + + GPIO260_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO261_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO262_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO263_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + + GPIO264_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO265_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO266_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, + GPIO267_GPIO | PIN_SLPM_DIR_INPUT | PIN_SLPM_WAKEUP_ENABLE | PIN_SLPM_PDIS_ENABLED, +}; + +static void mop500_pins_suspend_force(void) +{ + if (machine_is_hrefv60()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank0_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank0_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank0, + ARRAY_SIZE(mop500_pins_common_power_save_bank0)); + + sleep_pins_config_pm(mop500_pins_common_power_save_bank1, + ARRAY_SIZE(mop500_pins_common_power_save_bank1)); + + if (machine_is_hrefv60()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank2_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank2_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank2, + ARRAY_SIZE(mop500_pins_common_power_save_bank2)); + + sleep_pins_config_pm(mop500_pins_common_power_save_bank3, + ARRAY_SIZE(mop500_pins_common_power_save_bank3)); + + + if (pins_for_u9500() && uib_is_u8500uibr3()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank4_u9500_uibr3, + ARRAY_SIZE(mop500_pins_common_power_save_bank4_u9500_uibr3)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank4, + ARRAY_SIZE(mop500_pins_common_power_save_bank4)); + + if (machine_is_hrefv60()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank5_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank5_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank5, + ARRAY_SIZE(mop500_pins_common_power_save_bank5)); + + if (pins_for_u9500()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank6_u9500, + ARRAY_SIZE(mop500_pins_common_power_save_bank6_u9500)); + else if (machine_is_hrefv60()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank6_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank6_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank6, + ARRAY_SIZE(mop500_pins_common_power_save_bank6)); + + if (pins_for_u9500()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank7_u9500, + ARRAY_SIZE(mop500_pins_common_power_save_bank7_u9500)); + else if (machine_is_hrefv60()) + sleep_pins_config_pm(mop500_pins_common_power_save_bank7_href60, + ARRAY_SIZE(mop500_pins_common_power_save_bank7_href60)); + else + sleep_pins_config_pm(mop500_pins_common_power_save_bank7, + ARRAY_SIZE(mop500_pins_common_power_save_bank7)); + + sleep_pins_config_pm(mop500_pins_common_power_save_bank8, + ARRAY_SIZE(mop500_pins_common_power_save_bank8)); +} + +/* + * This function is called to force gpio power save + * mux settings during suspend. + * This is a temporary solution until all drivers are + * controlling their pin settings when in inactive mode. + */ +static void mop500_pins_suspend_force_mux(void) +{ + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank0, + ARRAY_SIZE(mop500_pins_common_power_save_bank0)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank1, + ARRAY_SIZE(mop500_pins_common_power_save_bank1)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank2, + ARRAY_SIZE(mop500_pins_common_power_save_bank2)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank3, + ARRAY_SIZE(mop500_pins_common_power_save_bank3)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank4, + ARRAY_SIZE(mop500_pins_common_power_save_bank4)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank5, + ARRAY_SIZE(mop500_pins_common_power_save_bank5)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank6, + ARRAY_SIZE(mop500_pins_common_power_save_bank6)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank7, + ARRAY_SIZE(mop500_pins_common_power_save_bank7)); + + sleep_pins_config_pm_mux(mop500_pins_common_power_save_bank8, + ARRAY_SIZE(mop500_pins_common_power_save_bank8)); +} + +/* + * passing "pinsfor=" in kernel cmdline allows for custom + * configuration of GPIOs on u8500 derived boards. + */ +static int __init early_pinsfor(char *p) +{ + pinsfor = PINS_FOR_DEFAULT; + + if (strcmp(p, "u9500-21") == 0) + pinsfor = PINS_FOR_U9500; + + return 0; +} +early_param("pinsfor", early_pinsfor); + +int pins_for_u9500(void) +{ + if (pinsfor == PINS_FOR_U9500) + return 1; + + return 0; +} + +static UX500_PINS(mop500_offchip_gpio_cfg, + /* + * Workaround for auto shutdown of 3.2MHz oscillator during + * deep sleep. APESPICSn/GPIO37 must be floating on the board + * to use this fix. + */ + AB8500_PIN_GPIO37 | PIN_OUTPUT_HIGH, +); + void __init mop500_pins_init(void) { nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + ux500_pins_add(mop500_runtime_pins_pre_v60, + ARRAY_SIZE(mop500_runtime_pins_pre_v60)); + + switch (pinsfor) { + case PINS_FOR_U9500: + nmk_config_pins(u9500_pins, ARRAY_SIZE(u9500_pins)); + break; + + case PINS_FOR_DEFAULT: + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + default: + break; + } + nmk_config_pins(mop500_pins_default, ARRAY_SIZE(mop500_pins_default)); + + suspend_set_pins_force_fn(mop500_pins_suspend_force, + mop500_pins_suspend_force_mux); } void __init snowball_pins_init(void) @@ -290,8 +1081,14 @@ void __init snowball_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); - nmk_config_pins(snowball_pins, - ARRAY_SIZE(snowball_pins)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + + nmk_config_pins(snowball_pins, ARRAY_SIZE(snowball_pins)); + + suspend_set_pins_force_fn(mop500_pins_suspend_force, + mop500_pins_suspend_force_mux); } void __init hrefv60_pins_init(void) @@ -299,6 +1096,35 @@ void __init hrefv60_pins_init(void) nmk_config_pins(mop500_pins_common, ARRAY_SIZE(mop500_pins_common)); + ux500_pins_add(mop500_runtime_pins, ARRAY_SIZE(mop500_runtime_pins)); + + ux500_pins_add(mop500_runtime_pins_v60, + ARRAY_SIZE(mop500_runtime_pins_v60)); + nmk_config_pins(hrefv60_pins, ARRAY_SIZE(hrefv60_pins)); + + switch (pinsfor) { + case PINS_FOR_U9500: + nmk_config_pins(u9500_pins, ARRAY_SIZE(u9500_pins)); + break; + + case PINS_FOR_DEFAULT: + nmk_config_pins(u8500_pins, ARRAY_SIZE(u8500_pins)); + default: + break; + } + + suspend_set_pins_force_fn(mop500_pins_suspend_force, + mop500_pins_suspend_force_mux); +} + +static int __init mop500_offchip_gpio_init(void) +{ + if (machine_is_hrefv60()) + ux500_offchip_gpio_init(&mop500_offchip_gpio_cfg); + + return 0; } +/* Let gpio chip drivers initialize. */ +late_initcall(mop500_offchip_gpio_init); diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 5dde4d4ebe8..ae484d6b74e 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -16,10 +16,10 @@ #include <plat/ste_dma40.h> #include <mach/devices.h> #include <mach/hardware.h> +#include <mach/ste-dma40-db8500.h> #include "devices-db8500.h" #include "board-mop500.h" -#include "ste-dma40-db8500.h" /* * v2 has a new version of this block that need to be forced, the number found diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c index 8c979770d87..273869bf3ca 100644 --- a/arch/arm/mach-ux500/board-mop500-stuib.c +++ b/arch/arm/mach-ux500/board-mop500-stuib.c @@ -11,33 +11,70 @@ #include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/i2c.h> +#ifdef CONFIG_U8500_FLASH +#include <../drivers/staging/camera_flash/adp1653_plat.h> +#endif #include <linux/input/matrix_keypad.h> #include <asm/mach-types.h> #include "board-mop500.h" -/* STMPE/SKE keypad use this key layout */ +/* + * 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 mop500_keymap[] = { +#if defined(CONFIG_KEYLAYOUT_LAYOUT1) KEY(2, 5, KEY_END), - KEY(4, 1, KEY_POWER), + KEY(4, 1, KEY_HOME), KEY(3, 5, KEY_VOLUMEDOWN), - KEY(1, 3, KEY_3), + KEY(1, 3, KEY_EMAIL), KEY(5, 2, KEY_RIGHT), - KEY(5, 0, KEY_9), + KEY(5, 0, KEY_BACKSPACE), KEY(0, 5, KEY_MENU), KEY(7, 6, KEY_ENTER), KEY(4, 5, KEY_0), - KEY(6, 7, KEY_2), + 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_1), + KEY(5, 5, KEY_SPACE), KEY(4, 3, KEY_LEFT), + KEY(3, 2, KEY_SEARCH), +#elif defined(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 }; static const struct matrix_keymap_data mop500_keymap_data = { @@ -73,6 +110,24 @@ static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = { }, }; +#ifdef CONFIG_U8500_FLASH +/* + * Config data for the flash + */ +static struct adp1653_platform_data __initdata adp1653_pdata_u8500_uib = { + .irq_no = CAMERA_FLASH_INT_PIN +}; +#endif + +static struct i2c_board_info __initdata mop500_i2c2_devices_stuib[] = { +#ifdef CONFIG_U8500_FLASH + { + I2C_BOARD_INFO("adp1653", 0x30), + .platform_data = &adp1653_pdata_u8500_uib + } +#endif +}; + /* * BU21013 ROHM touchscreen interface on the STUIBs */ @@ -111,6 +166,7 @@ static int bu21013_gpio_board_init(int reset_pin) __func__); return retval; } + gpio_set_value_cansleep(reset_pin, 1); } return retval; @@ -133,7 +189,8 @@ static int bu21013_gpio_board_exit(int reset_pin) __func__); return retval; } - gpio_set_value(reset_pin, 0); + gpio_set_value_cansleep(reset_pin, 0); + gpio_free(reset_pin); } bu21013_devices--; @@ -176,11 +233,11 @@ static struct bu21013_platform_device tsc_plat2_device = { static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = { { - I2C_BOARD_INFO("bu21013_tp", 0x5C), + I2C_BOARD_INFO("bu21013_ts", 0x5C), .platform_data = &tsc_plat_device, }, { - I2C_BOARD_INFO("bu21013_tp", 0x5D), + I2C_BOARD_INFO("bu21013_ts", 0x5D), .platform_data = &tsc_plat2_device, }, @@ -191,15 +248,25 @@ void __init mop500_stuib_init(void) if (machine_is_hrefv60()) { tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO; tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO; +#ifdef CONFIG_U8500_FLASH + adp1653_pdata_u8500_uib.enable_gpio = + HREFV60_CAMERA_FLASH_ENABLE; +#endif } else { tsc_plat_device.cs_pin = GPIO_BU21013_CS; tsc_plat2_device.cs_pin = GPIO_BU21013_CS; - +#ifdef CONFIG_U8500_FLASH + adp1653_pdata_u8500_uib.enable_gpio = + GPIO_CAMERA_FLASH_ENABLE; +#endif } mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib, ARRAY_SIZE(mop500_i2c0_devices_stuib)); + mop500_uib_i2c_add(2, mop500_i2c2_devices_stuib, + ARRAY_SIZE(mop500_i2c2_devices_stuib)); + mop500_uib_i2c_add(3, u8500_i2c3_devices_stuib, ARRAY_SIZE(u8500_i2c3_devices_stuib)); } diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c index feb5744d98b..d0631303a0b 100644 --- a/arch/arm/mach-ux500/board-mop500-u8500uib.c +++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c @@ -8,11 +8,22 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/i2c.h> +#ifdef CONFIG_U8500_FLASH +#include <../drivers/staging/camera_flash/adp1653_plat.h> +#endif #include <linux/gpio.h> #include <linux/interrupt.h> +#ifdef CONFIG_SENSORS_LSM303DLH +#include <linux/lsm303dlh.h> +#endif +#ifdef CONFIG_SENSORS_L3G4200D +#include <linux/l3g4200d.h> +#endif #include <linux/mfd/tc3589x.h> #include <linux/input/matrix_keypad.h> +#include <asm/mach-types.h> +#include <linux/gpio.h> #include <mach/irqs.h> #include "board-mop500.h" @@ -21,12 +32,28 @@ struct i2c_board_info __initdata __weak mop500_i2c3_devices_u8500[] = { }; +#ifdef CONFIG_U8500_FLASH +static struct adp1653_platform_data __initdata adp1653_pdata_u8500_uib = { + .irq_no = CAMERA_FLASH_INT_PIN +}; +#endif + +static struct i2c_board_info __initdata mop500_i2c2_devices_u8500[] = { +#ifdef CONFIG_U8500_FLASH + { + I2C_BOARD_INFO("adp1653", 0x30), + .platform_data = &adp1653_pdata_u8500_uib + } +#endif +}; + + /* * TC35893 */ static const unsigned int u8500_keymap[] = { KEY(3, 1, KEY_END), - KEY(4, 1, KEY_POWER), + KEY(4, 1, KEY_HOME), KEY(6, 4, KEY_VOLUMEDOWN), KEY(4, 2, KEY_EMAIL), KEY(3, 3, KEY_RIGHT), @@ -87,4 +114,15 @@ void __init mop500_u8500uib_init(void) mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, ARRAY_SIZE(mop500_i2c0_devices_u8500)); +#ifdef CONFIG_U8500_FLASH + if (machine_is_hrefv60()) + adp1653_pdata_u8500_uib.enable_gpio = + HREFV60_CAMERA_FLASH_ENABLE; + else + adp1653_pdata_u8500_uib.enable_gpio = + GPIO_CAMERA_FLASH_ENABLE; +#endif + + mop500_uib_i2c_add(2, mop500_i2c2_devices_u8500, + ARRAY_SIZE(mop500_i2c2_devices_u8500)); } diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c index 5af36aa56c0..908c5d973da 100644 --- a/arch/arm/mach-ux500/board-mop500-uib.c +++ b/arch/arm/mach-ux500/board-mop500-uib.c @@ -1,4 +1,5 @@ /* + * Copyright (C) ST-Ericsson SA 2010 * * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson @@ -10,13 +11,22 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/i2c.h> +#include <linux/platform_device.h> +#include <linux/input.h> +#include <linux/gpio_keys.h> +#include <linux/regulator/consumer.h> #include <mach/hardware.h> +#include <asm/mach-types.h> + +#include "pins.h" #include "board-mop500.h" enum mop500_uib { STUIB, U8500UIB, + U8500UIB_R3, + NO_UIB, }; struct uib { @@ -25,6 +35,8 @@ struct uib { void (*init)(void); }; +static u8 type_of_uib = NO_UIB; + static struct uib __initdata mop500_uibs[] = { [STUIB] = { .name = "ST-UIB", @@ -36,9 +48,16 @@ static struct uib __initdata mop500_uibs[] = { .option = "u8500uib", .init = mop500_u8500uib_init, }, +#ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI + [U8500UIB_R3] = { + .name = "U8500-UIBR3", + .option = "u8500uibr3", + .init = mop500_u8500uib_r3_init, + }, +#endif }; -static struct uib *mop500_uib; +static struct uib __initdata *mop500_uib; static int __init mop500_uib_setup(char *str) { @@ -64,7 +83,7 @@ __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 *info, +void mop500_uib_i2c_add(int busnum, struct i2c_board_info const *info, unsigned n) { struct i2c_adapter *adap; @@ -90,26 +109,137 @@ void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, static void __init __mop500_uib_init(struct uib *uib, const char *why) { pr_info("%s (%s)\n", uib->name, why); + + if (strcmp("stuib", uib->option) == 0) + type_of_uib = STUIB; + else if (strcmp("u8500uib", uib->option) == 0) + type_of_uib = U8500UIB; + else if (strcmp("u8500uibr3", uib->option) == 0) + type_of_uib = U8500UIB_R3; + uib->init(); } +int uib_is_stuib(void) +{ + return (type_of_uib == STUIB); +} + +int uib_is_u8500uib(void) +{ + return (type_of_uib == U8500UIB); +} + +int uib_is_u8500uibr3(void) +{ + return (type_of_uib == U8500UIB_R3); +} + + +#ifdef CONFIG_UX500_GPIO_KEYS +static struct gpio_keys_button mop500_gpio_keys[] = { + { + .desc = "SFH7741 Proximity Sensor", + .type = EV_SW, + .code = SW_FRONT_PROXIMITY, + .active_low = 0, + .can_disable = 1, + }, + { + .desc = "HED54XXU11 Hall Effect Sensor", + .type = EV_SW, + .code = SW_LID, /* FIXME arbitrary usage */ + .active_low = 0, + .can_disable = 1, + } +}; + +static struct regulator *gpio_keys_regulator; +static int mop500_gpio_keys_activate(struct device *dev); +static void mop500_gpio_keys_deactivate(struct device *dev); + +static struct gpio_keys_platform_data mop500_gpio_keys_data = { + .buttons = mop500_gpio_keys, + .nbuttons = ARRAY_SIZE(mop500_gpio_keys), + .enable = mop500_gpio_keys_activate, + .disable = mop500_gpio_keys_deactivate, +}; + +static struct platform_device mop500_gpio_keys_device = { + .name = "gpio-keys", + .id = 0, + .dev = { + .platform_data = &mop500_gpio_keys_data, + }, +}; + +static int mop500_gpio_keys_activate(struct device *dev) +{ + gpio_keys_regulator = regulator_get(&mop500_gpio_keys_device.dev, + "vcc"); + if (IS_ERR(gpio_keys_regulator)) { + dev_err(&mop500_gpio_keys_device.dev, "no regulator\n"); + return PTR_ERR(gpio_keys_regulator); + } + regulator_enable(gpio_keys_regulator); + + /* + * Please be aware that the start-up time of the SFH7741 is + * 120 ms and during that time the output is undefined. + */ + + return 0; +} + +static void mop500_gpio_keys_deactivate(struct device *dev) +{ + if (!IS_ERR(gpio_keys_regulator)) { + regulator_disable(gpio_keys_regulator); + regulator_put(gpio_keys_regulator); + } +} + +static __init void mop500_gpio_keys_init(void) +{ + struct ux500_pins *gpio_keys_pins = ux500_pins_get("gpio-keys.0"); + + if (gpio_keys_pins == NULL) { + pr_err("gpio_keys: Fail to get pins\n"); + return; + } + + ux500_pins_enable(gpio_keys_pins); + if (type_of_uib == U8500UIB_R3) + mop500_gpio_keys[0].gpio = PIN_NUM(gpio_keys_pins->cfg[2]); + else + mop500_gpio_keys[0].gpio = PIN_NUM(gpio_keys_pins->cfg[0]); + mop500_gpio_keys[1].gpio = PIN_NUM(gpio_keys_pins->cfg[1]); +} +#else +static inline void mop500_gpio_keys_init(void) { } +#endif + +/* add any platform devices here - TODO */ +static struct platform_device *mop500_uib_platform_devs[] __initdata = { +#ifdef CONFIG_UX500_GPIO_KEYS + &mop500_gpio_keys_device, +#endif +}; + /* * 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; + struct uib *uib = mop500_uibs; struct i2c_adapter *i2c0; + struct i2c_adapter *i2c3; int ret; - if (!cpu_is_u8500()) + /* snowball and non u8500 cpus dont have uib */ + if (!cpu_is_u8500() || machine_is_snowball()) return -ENODEV; - if (uib) { - __mop500_uib_init(uib, "from uib= boot argument"); - return 0; - } - i2c0 = i2c_get_adapter(0); if (!i2c0) { __mop500_uib_init(&mop500_uibs[STUIB], @@ -121,14 +251,32 @@ static int __init mop500_uib_init(void) ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_QUICK, NULL); i2c_put_adapter(i2c0); + i2c3 = i2c_get_adapter(3); + if (!i2c3) { + __mop500_uib_init(&mop500_uibs[STUIB], + "fallback, could not get i2c3"); + return -ENODEV; + } - if (ret == 0) - uib = &mop500_uibs[U8500UIB]; - else - uib = &mop500_uibs[STUIB]; - + if (ret == 0) { + ret = i2c_smbus_xfer(i2c3, 0x4B, 0, I2C_SMBUS_WRITE, 0, + I2C_SMBUS_QUICK, NULL); + i2c_put_adapter(i2c3); + if (ret == 0) + uib = &mop500_uibs[U8500UIB]; + else + uib = &mop500_uibs[U8500UIB_R3]; + } else { + ret = i2c_smbus_xfer(i2c3, 0x5C, 0, I2C_SMBUS_WRITE, 0, + I2C_SMBUS_QUICK, NULL); + i2c_put_adapter(i2c3); + if (ret == 0) + uib = &mop500_uibs[STUIB]; + } __mop500_uib_init(uib, "detected"); - + mop500_gpio_keys_init(); + platform_add_devices(mop500_uib_platform_devs, + ARRAY_SIZE(mop500_uib_platform_devs)); return 0; } diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 5c00712907d..1ffcf23fff6 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -15,22 +15,34 @@ #include <linux/io.h> #include <linux/i2c.h> #include <linux/gpio.h> +#include <linux/gpio/nomadik.h> #include <linux/amba/bus.h> #include <linux/amba/pl022.h> #include <linux/amba/serial.h> #include <linux/spi/spi.h> +#ifdef CONFIG_HSI +#include <linux/hsi/hsi.h> +#endif #include <linux/mfd/abx500/ab8500.h> #include <linux/regulator/ab8500.h> #include <linux/mfd/tc3589x.h> -#include <linux/mfd/tps6105x.h> #include <linux/mfd/abx500/ab8500-gpio.h> +#include <linux/regulator/fixed.h> #include <linux/leds-lp5521.h> #include <linux/input.h> #include <linux/smsc911x.h> #include <linux/gpio_keys.h> #include <linux/delay.h> - +#include <linux/mfd/ab8500/denc.h> +#ifdef CONFIG_STM_MSP_SPI +#include <linux/spi/stm_msp.h> +#endif +#include <linux/leds_pwm.h> +#include <linux/pwm_backlight.h> +#include <linux/gpio/nomadik.h> #include <linux/leds.h> +#include <linux/mfd/abx500/ab8500-sysctrl.h> + #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <asm/hardware/gic.h> @@ -38,18 +50,46 @@ #include <plat/i2c.h> #include <plat/ste_dma40.h> #include <plat/pincfg.h> -#include <plat/gpio-nomadik.h> #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> +#ifdef CONFIG_INPUT_AB8500_ACCDET +#include <mach/abx500-accdet.h> +#endif #include <mach/irqs.h> +#include <mach/ste-dma40-db8500.h> +#ifdef CONFIG_U8500_SIM_DETECT +#include <mach/sim_detect.h> +#endif +#ifdef CONFIG_CRYPTO_DEV_UX500 +#include <mach/crypto-ux500.h> +#endif +#include <mach/pm.h> +#ifdef CONFIG_AV8100 +#include <video/av8100.h> +#endif + +#ifdef CONFIG_KEYBOARD_NOMADIK_SKE +#include <plat/ske.h> +#include "pins.h" +#endif #include "pins-db8500.h" -#include "ste-dma40-db8500.h" #include "devices-db8500.h" #include "board-mop500.h" #include "board-mop500-regulators.h" +#include "board-mop500-bm.h" +#if defined(CONFIG_CW1200) || defined(CONFIG_CW1200_MODULE) +#include "board-mop500-wlan.h" +#endif + +#ifdef CONFIG_AB8500_DENC +static struct ab8500_denc_platform_data ab8500_denc_pdata = { + .ddr_enable = true, + .ddr_little_endian = false, +}; +#endif static struct gpio_led snowball_led_array[] = { { @@ -72,85 +112,123 @@ static struct platform_device snowball_led_dev = { }; static struct ab8500_gpio_platform_data ab8500_gpio_pdata = { - .gpio_base = MOP500_AB8500_GPIO(0), + .gpio_base = AB8500_PIN_GPIO1, .irq_base = MOP500_AB8500_VIR_GPIO_IRQ_BASE, - /* config_reg is the initial configuration of ab8500 pins. + /* + * 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 * explanation 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 + * GpioSel1 = 0x0F => Pin GPIO1 (SysClkReq2) + * Pin GPIO2 (SysClkReq3) + * Pin GPIO3 (SysClkReq4) + * Pin GPIO4 (SysClkReq6) are configured as GPIO + * GpioSel2 = 0x9E => 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 = 0x78 => 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 = {0x00, 0x1E, 0x80, 0x01, - 0x7A, 0x00, 0x00}, + .config_reg = {0x0F, 0x9E, 0x80, 0x01, 0x78, 0x02, 0x00}, + + /* + * config_direction allows for the initial GPIO direction to + * be set. For Snowball we set GPIO26 to output. + */ + .config_direction = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, + + /* + * config_pullups allows for the intial configuration of the + * GPIO pullup/pulldown configuration. + */ + .config_pullups = {0xE0, 0x01, 0x00, 0x00, 0x00, 0x00}, +}; + +static struct ab8500_sysctrl_platform_data ab8500_sysctrl_pdata = { + /* + * SysClkReq1RfClkBuf - SysClkReq8RfClkBuf + * The initial values should not be changed because of the way + * the system works today + */ + .initial_req_buf_config + = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, }; +#ifdef CONFIG_INPUT_AB8500_ACCDET +static struct abx500_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 + static struct gpio_keys_button snowball_key_array[] = { { - .gpio = 32, - .type = EV_KEY, - .code = KEY_1, - .desc = "userpb", + .gpio = 32, + .type = EV_KEY, + .code = KEY_1, + .desc = "userpb", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, { - .gpio = 151, - .type = EV_KEY, - .code = KEY_2, - .desc = "extkb1", + .gpio = 151, + .type = EV_KEY, + .code = KEY_2, + .desc = "extkb1", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, { - .gpio = 152, - .type = EV_KEY, - .code = KEY_3, - .desc = "extkb2", + .gpio = 152, + .type = EV_KEY, + .code = KEY_3, + .desc = "extkb2", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, { - .gpio = 161, - .type = EV_KEY, - .code = KEY_4, - .desc = "extkb3", + .gpio = 161, + .type = EV_KEY, + .code = KEY_4, + .desc = "extkb3", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, { - .gpio = 162, - .type = EV_KEY, - .code = KEY_5, - .desc = "extkb4", + .gpio = 162, + .type = EV_KEY, + .code = KEY_5, + .desc = "extkb4", .active_low = 1, .debounce_interval = 50, - .wakeup = 1, + .wakeup = 1, }, }; static struct gpio_keys_platform_data snowball_key_data = { - .buttons = snowball_key_array, + .buttons = snowball_key_array, .nbuttons = ARRAY_SIZE(snowball_key_array), }; static struct platform_device snowball_key_dev = { - .name = "gpio-keys", - .id = -1, - .dev = { + .name = "gpio-keys", + .id = -1, + .dev = { .platform_data = &snowball_key_data, + .pm_domain = &ux500_dev_power_domain, } }; @@ -176,21 +254,44 @@ static struct resource sbnet_res[] = { }; static struct platform_device snowball_sbnet_dev = { - .name = "smsc911x", + .name = "smsc911x", .num_resources = ARRAY_SIZE(sbnet_res), .resource = sbnet_res, - .dev = { + .dev = { .platform_data = &snowball_sbnet_cfg, }, }; +#ifdef CONFIG_MODEM_U8500 +static struct platform_device u8500_modem_dev = { + .name = "u8500-modem", + .id = 0, + .dev = { + .platform_data = NULL, + }, +}; +#endif + static struct ab8500_platform_data ab8500_platdata = { .irq_base = MOP500_AB8500_IRQ_BASE, - .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), + .regulator = &ab8500_regulator_plat_data, +#ifdef CONFIG_AB8500_DENC + .denc = &ab8500_denc_pdata, +#endif + .battery = &ab8500_bm_data, + .charger = &ab8500_charger_plat_data, + .btemp = &ab8500_btemp_plat_data, + .fg = &ab8500_fg_plat_data, + .chargalg = &ab8500_chargalg_plat_data, .gpio = &ab8500_gpio_pdata, + .sysctrl = &ab8500_sysctrl_pdata, +#ifdef CONFIG_INPUT_AB8500_ACCDET + .accdet = &ab8500_accdet_pdata, +#endif +#ifdef CONFIG_PM + .pm_power_off = true, +#endif + .thermal_time_out = 20, /* seconds */ }; static struct resource ab8500_resources[] = { @@ -211,15 +312,196 @@ struct platform_device ab8500_device = { .resource = ab8500_resources, }; +#ifdef CONFIG_KEYBOARD_NOMADIK_SKE + /* - * TPS61052 + * 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 struct tps6105x_platform_data mop500_tps61052_data = { - .mode = TPS6105X_MODE_VOLTAGE, - .regulator_data = &tps61052_regulator, +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 const unsigned int mop500_ske_keymap[] = { +#if defined(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), +#elif defined(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 }; +static struct matrix_keymap_data mop500_ske_keymap_data = { + .keymap = mop500_ske_keymap, + .keymap_size = ARRAY_SIZE(mop500_ske_keymap), +}; + + + +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 = &mop500_ske_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 */ +}; + +#endif + + +#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE +/* + * GPIO-regulator wlan vbat data + */ +static struct fixed_voltage_config snowball_gpio_wlan_vbat_data = { + .supply_name = "WLAN-VBAT", + .gpio = SNOWBALL_EN_3V6_GPIO, + .microvolts = 3600000, + .enable_high = 1, + .init_data = &gpio_wlan_vbat_regulator, + .startup_delay = 3500, /* Startup time */ +}; + +/* + * GPIO-regulator en 3v3 vbat data + */ + +static struct fixed_voltage_config snowball_gpio_en_3v3_data = { + .supply_name = "EN-3V3", + .gpio = SNOWBALL_EN_3V3_ETH_GPIO, + .microvolts = 3300000, + .enable_high = 1, + .init_data = &gpio_en_3v3_regulator, + .startup_delay = 5000, /* 1200us according to data sheet */ +}; +#endif + /* * TC35892 */ @@ -241,53 +523,64 @@ static struct tc3589x_platform_data mop500_tc35892_data = { }; static struct lp5521_led_config lp5521_pri_led[] = { - [0] = { - .chan_nr = 0, - .led_current = 0x2f, - .max_current = 0x5f, - }, - [1] = { - .chan_nr = 1, - .led_current = 0x2f, - .max_current = 0x5f, - }, - [2] = { - .chan_nr = 2, - .led_current = 0x2f, - .max_current = 0x5f, - }, + [0] = { + .chan_nr = 0, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [1] = { + .chan_nr = 1, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [2] = { + .chan_nr = 2, + .led_current = 0x2f, + .max_current = 0x5f, + }, +}; + +#ifdef CONFIG_AV8100 +static struct av8100_platform_data av8100_plat_data = { + .irq = NOMADIK_GPIO_TO_IRQ(192), + .reset = MOP500_HDMI_RST_GPIO, + .inputclk_id = "sysclk2", + .regulator_pwr_id = "hdmi_1v8", + .alt_powerupseq = true, + .mclk_freq = 3, /* MCLK_RNG_31_38 */ }; +#endif static struct lp5521_platform_data __initdata lp5521_pri_data = { - .label = "lp5521_pri", - .led_config = &lp5521_pri_led[0], - .num_channels = 3, - .clock_mode = LP5521_CLOCK_EXT, + .label = "lp5521_pri", + .led_config = &lp5521_pri_led[0], + .num_channels = 3, + .clock_mode = LP5521_CLOCK_EXT, }; static struct lp5521_led_config lp5521_sec_led[] = { - [0] = { - .chan_nr = 0, - .led_current = 0x2f, - .max_current = 0x5f, - }, - [1] = { - .chan_nr = 1, - .led_current = 0x2f, - .max_current = 0x5f, - }, - [2] = { - .chan_nr = 2, - .led_current = 0x2f, - .max_current = 0x5f, - }, + [0] = { + .chan_nr = 0, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [1] = { + .chan_nr = 1, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [2] = { + .chan_nr = 2, + .led_current = 0x2f, + .max_current = 0x5f, + }, }; static struct lp5521_platform_data __initdata lp5521_sec_data = { - .label = "lp5521_sec", - .led_config = &lp5521_sec_led[0], - .num_channels = 3, - .clock_mode = LP5521_CLOCK_EXT, + .label = "lp5521_sec", + .led_config = &lp5521_sec_led[0], + .num_channels = 3, + .clock_mode = LP5521_CLOCK_EXT, }; static struct i2c_board_info __initdata mop500_i2c0_devices[] = { @@ -296,15 +589,26 @@ static struct i2c_board_info __initdata mop500_i2c0_devices[] = { .irq = NOMADIK_GPIO_TO_IRQ(217), .platform_data = &mop500_tc35892_data, }, - /* I2C0 devices only available prior to HREFv60 */ +#ifdef CONFIG_AV8100 { - I2C_BOARD_INFO("tps61052", 0x33), - .platform_data = &mop500_tps61052_data, + I2C_BOARD_INFO("av8100", 0x70), + .platform_data = &av8100_plat_data, }, +#endif + /* I2C0 devices only available prior to HREFv60 */ }; #define NUM_PRE_V60_I2C0_DEVICES 1 +static struct i2c_board_info __initdata snowball_i2c0_devices[] = { +#ifdef CONFIG_AV8100 + { + I2C_BOARD_INFO("av8100", 0x70), + .platform_data = &av8100_plat_data, + }, +#endif +}; + static struct i2c_board_info __initdata mop500_i2c2_devices[] = { { /* lp5521 LED driver, 1st device */ @@ -345,13 +649,13 @@ static struct nmk_i2c_controller u8500_i2c##id##_data = { \ /* * The board uses 4 i2c controllers, initialize all of * them with slave data setup time of 250 ns, - * Tx & Rx FIFO threshold values as 8 and standard + * Tx & Rx FIFO threshold values as 1 and standard * mode of operation */ -U8500_I2C_CONTROLLER(0, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); -U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); -U8500_I2C_CONTROLLER(2, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); -U8500_I2C_CONTROLLER(3, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); +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); static void __init mop500_i2c_init(void) { @@ -361,60 +665,269 @@ static void __init mop500_i2c_init(void) db8500_add_i2c3(&u8500_i2c3_data); } -static struct gpio_keys_button mop500_gpio_keys[] = { - { - .desc = "SFH7741 Proximity Sensor", - .type = EV_SW, - .code = SW_FRONT_PROXIMITY, - .active_low = 0, - .can_disable = 1, - } +#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE +static struct platform_device snowball_gpio_wlan_vbat_regulator_device = { + .name = "reg-fixed-voltage", + .id = 0, + .dev = { + .platform_data = &snowball_gpio_wlan_vbat_data, + }, +}; + +static struct platform_device snowball_gpio_en_3v3_regulator_device = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &snowball_gpio_en_3v3_data, + }, +}; +#endif + +#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, + }, + [1] = { + .name = "sec-lcd-backlight", + .pwm_id = 2, + .max_brightness = 255, + .lth_brightness = 90, + .pwm_period_ns = 1023, + }, }; -static struct regulator *prox_regulator; -static int mop500_prox_activate(struct device *dev); -static void mop500_prox_deactivate(struct device *dev); +static struct led_pwm_platform_data u8500_leds_data = { + .num_leds = 1, + .leds = pwm_leds_data, +}; -static struct gpio_keys_platform_data mop500_gpio_keys_data = { - .buttons = mop500_gpio_keys, - .nbuttons = ARRAY_SIZE(mop500_gpio_keys), - .enable = mop500_prox_activate, - .disable = mop500_prox_deactivate, +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" +}; + +#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_FRAME, + .channels = 1, + .speed = 200000, + .ch_prio = {}, + {.arb_mode = HSI_ARB_RR}, + }, + .rx_cfg = { + .mode = HSI_MODE_FRAME, + .channels = 1, + .speed = 200000, + .ch_prio = {}, + {.flow = HSI_FLOW_SYNC}, + }, + }, + { + .name = "hsi_test", + .hsi_id = 0, + .port = 0, + .tx_cfg = { + .mode = HSI_MODE_FRAME, + .channels = 2, + .speed = 100000, + .ch_prio = {}, + {.arb_mode = HSI_ARB_RR}, + }, + .rx_cfg = { + .mode = HSI_MODE_FRAME, + .channels = 2, + .speed = 200000, + .ch_prio = {}, + {.flow = HSI_FLOW_SYNC}, + }, + }, + { + .name = "cfhsi_v3_driver", + .hsi_id = 0, + .port = 0, + .tx_cfg = { + .mode = HSI_MODE_STREAM, + .channels = 2, + .speed = 20000, + .ch_prio = {}, + {.arb_mode = HSI_ARB_RR}, + }, + .rx_cfg = { + .mode = HSI_MODE_STREAM, + .channels = 2, + .speed = 200000, + .ch_prio = {}, + {.flow = HSI_FLOW_SYNC}, + }, + }, +}; +#endif -static struct platform_device mop500_gpio_keys_device = { - .name = "gpio-keys", +#ifdef CONFIG_U8500_SIM_DETECT +static struct sim_detect_platform_data sim_detect_pdata = { + .irq_num = MOP500_AB8500_VIR_GPIO_IRQ(6), +}; +struct platform_device u8500_sim_detect_device = { + .name = "sim-detect", .id = 0, .dev = { - .platform_data = &mop500_gpio_keys_data, + .platform_data = &sim_detect_pdata, }, }; +#endif -static int mop500_prox_activate(struct device *dev) -{ - prox_regulator = regulator_get(&mop500_gpio_keys_device.dev, - "vcc"); - if (IS_ERR(prox_regulator)) { - dev_err(&mop500_gpio_keys_device.dev, - "no regulator\n"); - return PTR_ERR(prox_regulator); +#ifdef CONFIG_CRYPTO_DEV_UX500 +static struct cryp_platform_data u8500_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, } - regulator_enable(prox_regulator); - return 0; -} +}; -static void mop500_prox_deactivate(struct device *dev) -{ - regulator_disable(prox_regulator); - regulator_put(prox_regulator); -} +static struct stedma40_chan_cfg u8500_hash_dma_cfg_tx = { + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV50_HAC1_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_16, + .dst_info.psize = STEDMA40_PSIZE_LOG_16, +}; + +static struct hash_platform_data u8500_hash1_platform_data = { + .mem_to_engine = &u8500_hash_dma_cfg_tx, + .dma_filter = stedma40_filter, +}; +#endif /* add any platform devices here - TODO */ static struct platform_device *mop500_platform_devs[] __initdata = { - &mop500_gpio_keys_device, - &ab8500_device, +#ifdef CONFIG_U8500_SIM_DETECT + &u8500_sim_detect_device, +#endif + &u8500_shrm_device, + &ste_ff_vibra_device, +#ifdef CONFIG_U8500_MMIO + &ux500_mmio_device, +#endif + &ux500_hwmem_device, +#ifdef CONFIG_FB_MCDE + &u8500_mcde_device, +#endif + &u8500_b2r2_device, + &u8500_thsens_device, +#ifdef CONFIG_STE_TRACE_MODEM + &u8500_trace_modem, +#endif +#ifdef CONFIG_LEDS_PWM + &ux500_leds_device, +#endif +#ifdef CONFIG_BACKLIGHT_PWM + &ux500_backlight_device[0], + &ux500_backlight_device[1], +#endif +#ifdef CONFIG_DB8500_MLOADER + &mloader_fw_device, +#endif +#ifdef CONFIG_HSI + &u8500_hsi_device, +#endif +#ifdef CONFIG_MODEM_U8500 + &u8500_modem_dev, +#endif }; +#ifdef CONFIG_STM_MSP_SPI +/* + * MSP-SPI + */ + +#define NUM_MSP_CLIENTS 10 + +static struct stm_msp_controller mop500_msp2_spi_data = { + .id = 2, + .num_chipselect = NUM_MSP_CLIENTS, + .base_addr = U8500_MSP2_BASE, + .device_name = "msp2", +}; + +/* + * SSP + */ + +#define NUM_SSP_CLIENTS 10 + #ifdef CONFIG_STE_DMA40 static struct stedma40_chan_cfg ssp0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, @@ -436,27 +949,33 @@ static struct stedma40_chan_cfg ssp0_dma_cfg_tx = { #endif static struct pl022_ssp_controller ssp0_platform_data = { - .bus_id = 0, + .bus_id = 4, #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, -#else - .enable_dma = 0, #endif /* on this platform, gpio 31,142,144,214 & * 224 are connected as chip selects */ - .num_chipselect = 5, + .num_chipselect = NUM_SSP_CLIENTS, }; + static void __init mop500_spi_init(void) { db8500_add_ssp0(&ssp0_platform_data); + if (!machine_is_snowball()) + db8500_add_msp2_spi(&mop500_msp2_spi_data); } +#else +static void __init mop500_spi_init(void) +{ +} +#endif /* CONFIG_STM_MSP_SPI */ -#ifdef CONFIG_STE_DMA40 +#ifdef CONFIG_STE_DMA40_REMOVE static struct stedma40_chan_cfg uart0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_PERIPH_TO_MEM, @@ -522,6 +1041,7 @@ static pin_cfg_t mop500_pins_uart0[] = { #define PRCC_K_SOFTRST_SET 0x18 #define PRCC_K_SOFTRST_CLEAR 0x1C +/* pl011 reset */ static void ux500_uart0_reset(void) { void __iomem *prcc_rst_set, *prcc_rst_clr; @@ -560,8 +1080,10 @@ static void ux500_uart0_exit(void) pr_err("pl011: uart pins_disable failed\n"); } + + static struct amba_pl011_data uart0_plat = { -#ifdef CONFIG_STE_DMA40 +#ifdef CONFIG_STE_DMA40_REMOVE .dma_filter = stedma40_filter, .dma_rx_param = &uart0_dma_cfg_rx, .dma_tx_param = &uart0_dma_cfg_tx, @@ -572,7 +1094,7 @@ static struct amba_pl011_data uart0_plat = { }; static struct amba_pl011_data uart1_plat = { -#ifdef CONFIG_STE_DMA40 +#ifdef CONFIG_STE_DMA40_REMOVE .dma_filter = stedma40_filter, .dma_rx_param = &uart1_dma_cfg_rx, .dma_tx_param = &uart1_dma_cfg_tx, @@ -580,7 +1102,7 @@ static struct amba_pl011_data uart1_plat = { }; static struct amba_pl011_data uart2_plat = { -#ifdef CONFIG_STE_DMA40 +#ifdef CONFIG_STE_DMA40_REMOVE .dma_filter = stedma40_filter, .dma_rx_param = &uart2_dma_cfg_rx, .dma_tx_param = &uart2_dma_cfg_tx, @@ -594,23 +1116,44 @@ static void __init mop500_uart_init(void) db8500_add_uart2(&uart2_plat); } +static void __init u8500_cryp1_hash1_init(void) +{ +#ifdef CONFIG_CRYPTO_DEV_UX500 + db8500_add_cryp1(&u8500_cryp1_platform_data); + db8500_add_hash1(&u8500_hash1_platform_data); +#endif +} + static struct platform_device *snowball_platform_devs[] __initdata = { + &ux500_hwmem_device, &snowball_led_dev, &snowball_key_dev, +#ifdef CONFIG_REGULATOR_FIXED_VOLTAGE + &snowball_gpio_en_3v3_regulator_device, + &snowball_gpio_wlan_vbat_regulator_device, +#endif &snowball_sbnet_dev, - &ab8500_device, +#ifdef CONFIG_FB_MCDE + &u8500_mcde_device, +#endif + &u8500_b2r2_device, }; static void __init mop500_init_machine(void) { - int i2c0_devs; - - mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; - u8500_init_devices(); mop500_pins_init(); + mop500_regulator_init(); + + u8500_cryp1_hash1_init(); + +#ifdef CONFIG_HSI + hsi_register_board_info(u8500_hsi_devices, + ARRAY_SIZE(u8500_hsi_devices)); +#endif + platform_add_devices(mop500_platform_devs, ARRAY_SIZE(mop500_platform_devs)); @@ -618,12 +1161,23 @@ static void __init mop500_init_machine(void) mop500_sdi_init(); mop500_spi_init(); mop500_uart_init(); +#ifdef CONFIG_STM_MSP_SPI + mop500_msp_init(); +#endif +#if defined(CONFIG_CW1200) || defined(CONFIG_CW1200_MODULE) + mop500_wlan_init(); +#endif - i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); +#ifdef CONFIG_KEYBOARD_NOMADIK_SKE + db8500_add_ske_keypad(&mop500_ske_keypad_data); +#endif + + platform_device_register(&ab8500_device); - i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); + i2c_register_board_info(0, mop500_i2c0_devices, + ARRAY_SIZE(mop500_i2c0_devices)); i2c_register_board_info(2, mop500_i2c2_devices, - ARRAY_SIZE(mop500_i2c2_devices)); + ARRAY_SIZE(mop500_i2c2_devices)); /* This board has full regulator constraints */ regulator_has_full_constraints(); @@ -631,12 +1185,19 @@ static void __init mop500_init_machine(void) static void __init snowball_init_machine(void) { - int i2c0_devs; - u8500_init_devices(); snowball_pins_init(); + mop500_regulator_init(); + + u8500_cryp1_hash1_init(); + +#ifdef CONFIG_HSI + hsi_register_board_info(u8500_hsi_devices, + ARRAY_SIZE(u8500_hsi_devices)); +#endif + platform_add_devices(snowball_platform_devs, ARRAY_SIZE(snowball_platform_devs)); @@ -644,11 +1205,17 @@ static void __init snowball_init_machine(void) snowball_sdi_init(); mop500_spi_init(); mop500_uart_init(); +#ifdef CONFIG_STM_MSP_SPI + mop500_msp_init(); +#endif +#if defined(CONFIG_CW1200) || defined(CONFIG_CW1200_MODULE) + mop500_wlan_init(); +#endif - i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); - i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); - i2c_register_board_info(2, mop500_i2c2_devices, - ARRAY_SIZE(mop500_i2c2_devices)); + platform_device_register(&ab8500_device); + + i2c_register_board_info(0, snowball_i2c0_devices, + ARRAY_SIZE(snowball_i2c0_devices)); /* This board has full regulator constraints */ regulator_has_full_constraints(); @@ -656,19 +1223,37 @@ static void __init snowball_init_machine(void) static void __init hrefv60_init_machine(void) { - int i2c0_devs; - /* * The HREFv60 board removed a GPIO expander and routed * all these GPIO pins to the internal GPIO controller * instead. */ - mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; + +#ifdef CONFIG_INPUT_AB8500_ACCDET + /* + * On boards hrefpv60 and later, the accessory insertion/removal, + * button press/release are inverted. + */ + ab8500_accdet_pdata.is_detection_inverted = true; +#endif u8500_init_devices(); hrefv60_pins_init(); + mop500_regulator_init(); + + u8500_cryp1_hash1_init(); + +#ifdef CONFIG_HSI + hsi_register_board_info(u8500_hsi_devices, + ARRAY_SIZE(u8500_hsi_devices)); +#endif +#ifdef CONFIG_LEDS_PWM + if (uib_is_stuib()) + u8500_leds_data.num_leds = 2; +#endif + platform_add_devices(mop500_platform_devs, ARRAY_SIZE(mop500_platform_devs)); @@ -676,14 +1261,23 @@ static void __init hrefv60_init_machine(void) hrefv60_sdi_init(); mop500_spi_init(); mop500_uart_init(); +#ifdef CONFIG_STM_MSP_SPI + mop500_msp_init(); +#endif +#if defined(CONFIG_CW1200) || defined(CONFIG_CW1200_MODULE) + mop500_wlan_init(); +#endif - i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); +#ifdef CONFIG_KEYBOARD_NOMADIK_SKE + db8500_add_ske_keypad(&mop500_ske_keypad_data); +#endif - i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; + platform_device_register(&ab8500_device); - i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); + i2c_register_board_info(0, mop500_i2c0_devices, + ARRAY_SIZE(mop500_i2c0_devices)); i2c_register_board_info(2, mop500_i2c2_devices, - ARRAY_SIZE(mop500_i2c2_devices)); + ARRAY_SIZE(mop500_i2c2_devices)); /* This board has full regulator constraints */ regulator_has_full_constraints(); @@ -698,6 +1292,7 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform") .timer = &ux500_timer, .handle_irq = gic_handle_irq, .init_machine = mop500_init_machine, + .restart = ux500_restart, MACHINE_END MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") @@ -707,9 +1302,10 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") .timer = &ux500_timer, .handle_irq = gic_handle_irq, .init_machine = hrefv60_init_machine, + .restart = ux500_restart, MACHINE_END -MACHINE_START(SNOWBALL, "Calao Systems Snowball platform") +MACHINE_START(SNOWBALL, "ST-Ericsson Snowball platform") .atag_offset = 0x100, .map_io = u8500_map_io, .init_irq = ux500_init_irq, @@ -717,4 +1313,5 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform") .timer = &ux500_timer, .handle_irq = gic_handle_irq, .init_machine = snowball_init_machine, + .restart = ux500_restart, MACHINE_END diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index f926d3db620..5786f49fbf8 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -7,6 +7,10 @@ #ifndef __BOARD_MOP500_H #define __BOARD_MOP500_H +/* This defines the NOMADIK_NR_GPIO */ +#include <linux/mfd/abx500/ab8500-gpio.h> +#include <mach/gpio.h> + /* Snowball specific GPIO assignments, this board has no GPIO expander */ #define SNOWBALL_ACCEL_INT1_GPIO 163 #define SNOWBALL_ACCEL_INT2_GPIO 164 @@ -41,7 +45,6 @@ #define CYPRESS_SLAVE_SELECT_GPIO 216 /* GPIOs on the TC35892 expander */ -#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x)) #define GPIO_MAGNET_DRDY MOP500_EGPIO(1) #define GPIO_SDMMC_CD MOP500_EGPIO(3) #define GPIO_CAMERA_FLASH_ENABLE MOP500_EGPIO(4) @@ -55,7 +58,6 @@ #define MOP500_DISP1_RST_GPIO MOP500_EGPIO(15) #define GPIO_SDMMC_EN MOP500_EGPIO(17) #define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18) -#define MOP500_EGPIO_END MOP500_EGPIO(24) /* * GPIOs on the AB8500 mixed-signals circuit @@ -63,7 +65,7 @@ * because the AB8500 GPIO pins are enumbered starting from 1, so the value in * parens matches the GPIO pin number in the data sheet. */ -#define MOP500_AB8500_GPIO(x) (MOP500_EGPIO_END + (x) - 1) +#define MOP500_AB8500_PIN_GPIO(x) (MOP500_EGPIO_END + (x) - 1) /*Snowball AB8500 GPIO */ #define SNOWBALL_VSMPS2_1V8_GPIO MOP500_AB8500_PIN_GPIO(1) /* SYSCLKREQ2/GPIO1 */ #define SNOWBALL_PM_GPIO1_GPIO MOP500_AB8500_PIN_GPIO(2) /* SYSCLKREQ3/GPIO2 */ @@ -81,11 +83,21 @@ extern void hrefv60_sdi_init(void); extern void mop500_sdi_tc35892_init(void); void __init mop500_u8500uib_init(void); void __init mop500_stuib_init(void); +void __init mop500_msp_init(void); void __init mop500_pins_init(void); void __init hrefv60_pins_init(void); void __init snowball_pins_init(void); +void mop500_cyttsp_init(void); +void __init mop500_u8500uib_r3_init(void); -void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, +void mop500_uib_i2c_add(int busnum, struct i2c_board_info const *info, unsigned n); +int msp13_i2s_init(void); +int msp13_i2s_exit(void); + +int uib_is_stuib(void); +int uib_is_u8500uib(void); +int uib_is_u8500uibr3(void); + #endif diff --git a/arch/arm/mach-ux500/board-pins-sleep-force.c b/arch/arm/mach-ux500/board-pins-sleep-force.c new file mode 100644 index 00000000000..91eb1cefc22 --- /dev/null +++ b/arch/arm/mach-ux500/board-pins-sleep-force.c @@ -0,0 +1,269 @@ +/* + * 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 <linux/io.h> +#include <linux/string.h> + +#include <linux/gpio/nomadik.h> +#include <mach/hardware.h> + +#include "board-pins-sleep-force.h" +#include "pins-db8500.h" +#include "pins.h" + +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}; + +/* + * This function is called to force gpio power save + * settings during suspend. + */ +void sleep_pins_config_pm(pin_cfg_t *cfgs, int num) +{ + int i = 0; + int gpio = 0; + u32 w_imsc = 0; + u32 imsc = 0; + u32 offset; + u32 bitmask = 1; + u32 dirs_register = 0; + u32 dirc_register = 0; + u32 dats_register = 0; + u32 datc_register = 0; + u32 pdis_register_disable = 0; + u32 pdis_register_enabled = 0; + u32 slpm_register_disabled = 0; + u32 slpm_register_enabled = 0; + u32 bankaddr = 0; + + gpio = PIN_NUM(cfgs[i]); + + /* Get the bank number the pin is mapped to */ + bankaddr = IO_ADDRESS(u8500_gpio_banks[(gpio >> GPIO_BLOCK_SHIFT)]); + + w_imsc = readl(bankaddr + NMK_GPIO_RWIMSC) | + readl(bankaddr + NMK_GPIO_FWIMSC); + + imsc = readl(bankaddr + NMK_GPIO_RIMSC) | + readl(bankaddr + NMK_GPIO_FIMSC); + + for (i = 0; i < num; i++) { + /* Get the pin number */ + gpio = PIN_NUM(cfgs[i]); + + /* get the offest into the register */ + offset = gpio % NMK_GPIO_PER_CHIP; + /* Set the bit to toggle */ + bitmask = 1 << offset ; + + /* Next we check for direction (INPUT/OUTPUT) */ + switch (PIN_SLPM_DIR(cfgs[i])) { + case GPIO_IS_INPUT: + /* GPIO is set to input */ + dirc_register |= bitmask; + + /* + * Next check for pull (PULLUP/PULLDOWN) + * and configure accordingly. + */ + switch (PIN_SLPM_PULL(cfgs[i])) { + case GPIO_PULL_UPDOWN_DISABLED: + pdis_register_disable |= bitmask; + break; + + case GPIO_IS_PULLUP: + dats_register |= bitmask; + pdis_register_enabled |= bitmask; + break; + + case GPIO_IS_PULLDOWN: + datc_register |= bitmask; + pdis_register_enabled |= bitmask; + break; + + case GPIO_PULL_NO_CHANGE: + break; + + default: + BUG(); + break; + + } + break; + + case GPIO_IS_OUTPUT: + /* GPIO is set to output */ + dirs_register |= bitmask; + + /* + * Since its output there should not + * be a need to disable PULL UP/DOWN + * but better safe than sorry. + */ + pdis_register_disable |= bitmask; + /* Next we check for setting GPIO HIGH/LOW */ + switch (PIN_SLPM_VAL(cfgs[i])) { + case GPIO_IS_OUTPUT_LOW: + /* GPIO is set to LOW */ + datc_register |= bitmask; + break; + + case GPIO_IS_OUTPUT_HIGH: + /* GPIO is set to high */ + dats_register |= bitmask; + break; + + case GPIO_IS_NO_CHANGE: + break; + + default: + BUG(); + break; + } + + break; + case GPIO_IS_NOT_CHANGED: + break; + + default: + BUG(); + break; + } + + /* Next check for Sleep Power Managment (SLPM) */ + switch (PIN_SLPM(cfgs[i])) { + case GPIO_WAKEUP_IS_ENABLED: + slpm_register_enabled |= bitmask; + break; + + case GPIO_WAKEUP_IS_DISBLED: + slpm_register_disabled |= bitmask; + break; + + default: + BUG(); + break; + } + + /* Next check for Sleep Power Managment (SLPM) */ + switch (PIN_SLPM_PDIS(cfgs[i])) { + case GPIO_PDIS_NO_CHANGE: + break; + + case GPIO_PDIS_DISABLED: + pdis_register_disable |= bitmask; + break; + + case GPIO_PDIS_ENABLED: + pdis_register_enabled |= bitmask; + break; + + default: + BUG(); + break; + } + + } + + /* Write the register settings GPIO direction */ + writel(dirs_register & ~w_imsc, bankaddr + NMK_GPIO_DIRS); + writel(dirc_register, bankaddr + NMK_GPIO_DIRC); + + writel(datc_register & ~w_imsc, bankaddr + NMK_GPIO_DATC); + writel(dats_register & ~w_imsc, bankaddr + NMK_GPIO_DATS); + + /* Write the PDIS enable/disable */ + writel(readl(bankaddr + NMK_GPIO_PDIS) + | (pdis_register_disable & ~w_imsc & ~imsc), + bankaddr + NMK_GPIO_PDIS); + writel(readl(bankaddr + NMK_GPIO_PDIS) + & (~pdis_register_enabled & ~w_imsc & ~imsc), + bankaddr + NMK_GPIO_PDIS); + + /* Write the SLPM enable/disable */ + writel(readl(bankaddr + NMK_GPIO_SLPC) | slpm_register_disabled, + bankaddr + NMK_GPIO_SLPC); + writel(readl(bankaddr + NMK_GPIO_SLPC) & ~slpm_register_enabled, + bankaddr + NMK_GPIO_SLPC); +} + +void sleep_pins_config_pm_mux(pin_cfg_t *cfgs, int num) +{ + int i = 0; + int gpio = 0; + u32 offset; + u32 bitmask = 1; + u32 gpio_afsla_register_set = 0; + u32 gpio_afslb_register_set = 0; + u32 gpio_afsla_register_clear = 0; + u32 gpio_afslb_register_clear = 0; + u32 bankaddr = 0; + + gpio = PIN_NUM(cfgs[i]); + + /* Get the bank number the pin is mapped to */ + bankaddr = IO_ADDRESS(u8500_gpio_banks[(gpio >> GPIO_BLOCK_SHIFT)]); + + for (i = 0; i < num; i++) { + /* Get the pin number */ + gpio = PIN_NUM(cfgs[i]); + + /* get the offset into the register */ + offset = gpio % NMK_GPIO_PER_CHIP; + /* Set the bit to toggle */ + bitmask = 1 << offset ; + + /* First check for ALT pin configuration */ + switch (PIN_ALT(cfgs[i])) { + case NMK_GPIO_ALT_GPIO: + /* Set bit to configured as GPIO */ + gpio_afsla_register_clear |= bitmask; + gpio_afslb_register_clear |= bitmask; + break; + + case NMK_GPIO_ALT_A: + /* ALT A setting so set corresponding bit */ + gpio_afsla_register_set |= bitmask; + break; + + case NMK_GPIO_ALT_B: + /* ALT B setting so set corresponding bit */ + gpio_afslb_register_set |= bitmask; + break; + + case NMK_GPIO_ALT_C: + /* ALT C setting so set corresponding bits */ + gpio_afsla_register_set |= bitmask; + gpio_afslb_register_set |= bitmask; + break; + + default: + BUG(); + break; + } + } + /* Set bits that configures GPIO */ + writel(readl(bankaddr + NMK_GPIO_AFSLA) + & ~gpio_afsla_register_clear, bankaddr + NMK_GPIO_AFSLA); + writel(readl(bankaddr + NMK_GPIO_AFSLB) + & ~gpio_afslb_register_clear, bankaddr + NMK_GPIO_AFSLB); + + /* Set bits that configures ALT_X */ + writel(readl(bankaddr + NMK_GPIO_AFSLA) + | gpio_afsla_register_set, bankaddr + NMK_GPIO_AFSLA); + writel(readl(bankaddr + NMK_GPIO_AFSLB) + | gpio_afslb_register_set, bankaddr + NMK_GPIO_AFSLB); +} diff --git a/arch/arm/mach-ux500/board-pins-sleep-force.h b/arch/arm/mach-ux500/board-pins-sleep-force.h new file mode 100644 index 00000000000..0949c9bfcda --- /dev/null +++ b/arch/arm/mach-ux500/board-pins-sleep-force.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __BOARD_PINS_SLEEP_FORCE_H +#define __BOARD_PINS_SLEEP_FORCE_H + +#include <plat/pincfg.h> + +#define NMK_GPIO_PER_CHIP 32 +#define GPIO_BLOCK_SHIFT 5 + +#define GPIO_IS_NOT_CHANGED 0 +#define GPIO_IS_INPUT 1 +#define GPIO_IS_OUTPUT 2 + +#define GPIO_WAKEUP_IS_ENABLED 0 +#define GPIO_WAKEUP_IS_DISBLED 1 + +#define GPIO_IS_NO_CHANGE 0 +#define GPIO_IS_OUTPUT_LOW 1 +#define GPIO_IS_OUTPUT_HIGH 2 + +#define GPIO_PULL_NO_CHANGE 0 +#define GPIO_PULL_UPDOWN_DISABLED 1 +#define GPIO_IS_PULLUP 2 +#define GPIO_IS_PULLDOWN 3 + +#define GPIO_PDIS_NO_CHANGE 0 +#define GPIO_PDIS_DISABLED 1 +#define GPIO_PDIS_ENABLED 2 + +void sleep_pins_config_pm_mux(pin_cfg_t *cfgs, int num); +void sleep_pins_config_pm(pin_cfg_t *cfgs, int num); + +#endif diff --git a/arch/arm/mach-ux500/board-u5500-cyttsp.c b/arch/arm/mach-ux500/board-u5500-cyttsp.c new file mode 100755 index 00000000000..47eaa36c030 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-cyttsp.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA + * Author: Avinash A <avinash.a@stericsson.com> for ST-Ericsson + * License terms:GNU General Public License (GPL) version 2 + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/spi/spi.h> +#include <linux/gpio.h> +#include <linux/cyttsp.h> +#include <linux/delay.h> +#include <linux/amba/pl022.h> +#include <plat/pincfg.h> +#include <mach/hardware.h> + +#include "pins-db5500.h" +#include "board-u5500.h" + +/* cyttsp_gpio_board_init : configures the touch panel. */ +static int cyttsp_plat_init(int on) +{ + int ret; + + ret = gpio_direction_output(CYPRESS_SLAVE_SELECT_GPIO, 1); + if (ret < 0) { + pr_err("slave select gpio direction failed\n"); + gpio_free(CYPRESS_SLAVE_SELECT_GPIO); + return ret; + } + + return 0; +} + +static int cyttsp_wakeup(void) +{ + int ret; + + ret = gpio_request(CYPRESS_TOUCH_INT_PIN, "Wakeup_pin"); + if (ret < 0) { + pr_err("touch gpio failed\n"); + return ret; + } + ret = gpio_direction_output(CYPRESS_TOUCH_INT_PIN, 1); + if (ret < 0) { + pr_err("touch gpio direction failed\n"); + goto out; + } + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 0); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 1); + /* + * To wake up the controller from sleep + * state the interrupt pin needs to be + * pulsed twice with a delay greater + * than 2 micro seconds. + */ + udelay(3); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 0); + gpio_set_value(CYPRESS_TOUCH_INT_PIN, 1); + ret = gpio_direction_input(CYPRESS_TOUCH_INT_PIN); + if (ret < 0) { + pr_err("touch gpio direction IN config failed\n"); + goto out; + } +out: + gpio_free(CYPRESS_TOUCH_INT_PIN); + return 0; +} +static struct cyttsp_platform_data cyttsp_spi_platdata = { + .maxx = 480, + .maxy = 854, + .flags = 0, + .gen = CY_GEN3, + .use_st = 0, + .use_mt = 1, + .use_trk_id = 0, + .use_hndshk = 0, + .use_sleep = 1, + .use_gestures = 0, + .use_load_file = 0, + .use_force_fw_update = 0, + .use_virtual_keys = 0, + /* activate up to 4 groups and set active distance */ + .gest_set = CY_GEST_GRP_NONE | CY_ACT_DIST, + /* change scn_type to enable finger and/or stylus detection */ + .scn_typ = 0xA5, /* autodetect finger+stylus; balanced mutual scan */ + .act_intrvl = CY_ACT_INTRVL_DFLT, /* Active refresh interval; ms */ + .tch_tmout = CY_TCH_TMOUT_DFLT, /* Active touch timeout; ms */ + .lp_intrvl = CY_LP_INTRVL_DFLT, /* Low power refresh interval; ms */ + .init = cyttsp_plat_init, + .mt_sync = input_mt_sync, + .wakeup = cyttsp_wakeup, + .name = CY_SPI_NAME, + .irq_gpio = CYPRESS_TOUCH_INT_PIN, + .rst_gpio = CYPRESS_TOUCH_RST_GPIO, +}; + +static void cyttsp_spi_cs_control(u32 command) +{ + if (command == SSP_CHIP_SELECT) + gpio_set_value(CYPRESS_SLAVE_SELECT_GPIO, 0); + else if (command == SSP_CHIP_DESELECT) + gpio_set_value(CYPRESS_SLAVE_SELECT_GPIO, 1); +} + +static struct pl022_config_chip cyttsp_ssp_config_chip = { + .com_mode = INTERRUPT_TRANSFER, + .iface = SSP_INTERFACE_MOTOROLA_SPI, + /* we can act as master only */ + .hierarchy = SSP_MASTER, + .slave_tx_disable = 0, + .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, + .tx_lev_trig = SSP_TX_16_OR_MORE_EMPTY_LOC, + .ctrl_len = SSP_BITS_16, + .wait_state = SSP_MWIRE_WAIT_ZERO, + .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, + .cs_control = cyttsp_spi_cs_control, +}; + +static struct spi_board_info cypress_spi_devices[] = { + { + .modalias = CY_SPI_NAME, + .controller_data = &cyttsp_ssp_config_chip, + .platform_data = &cyttsp_spi_platdata, + .max_speed_hz = 1000000, + .bus_num = 1, + .chip_select = 0, + .mode = SPI_MODE_0, + } +}; + +void u5500_cyttsp_init(void) +{ + int ret = 0; + + ret = gpio_request(CYPRESS_SLAVE_SELECT_GPIO, "slave_select_gpio"); + if (ret < 0) { + pr_err("slave select gpio failed\n"); + return; + } + if (cpu_is_u5500v2()) + cyttsp_spi_platdata.invert = true; + spi_register_board_info(cypress_spi_devices, + ARRAY_SIZE(cypress_spi_devices)); +} 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..a6b63ca3ead --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-pins.c @@ -0,0 +1,225 @@ +/* + * 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 <linux/gpio/nomadik.h> +#include <plat/pincfg.h> + +#include "pins-db5500.h" +#include "pins.h" + +static pin_cfg_t u5500_pins_default[] = { + GPIO77_ACCTX_ON | PIN_SLPM_ALTFUNC, + GPIO79_ACCSIM_Clk | PIN_SLPM_ALTFUNC, + GPIO80_ACCSIM_Da | PIN_SLPM_ALTFUNC, + GPIO81_ACCSIM_Reset | PIN_SLPM_ALTFUNC, + GPIO82_ACCSIM_DDir | PIN_SLPM_ALTFUNC, + + /* 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_HIGH, + + /* Backlight Enable */ + GPIO224_GPIO | PIN_OUTPUT_HIGH, + + /* UART0 */ + GPIO28_U0_TXD | PIN_OUTPUT_HIGH, + GPIO29_U0_RXD | PIN_INPUT_PULLUP, + + /* UART3 */ + GPIO165_U3_RXD | PIN_INPUT_PULLUP, + GPIO166_U3_TXD | PIN_OUTPUT_HIGH | PIN_LOWEMI_ENABLED, + GPIO167_U3_RTSn | PIN_OUTPUT_HIGH | PIN_LOWEMI_ENABLED, + GPIO168_U3_CTSn | PIN_INPUT_PULLUP, + + /* AB5500 */ + GPIO78_IRQn | PIN_SLPM_NOCHANGE, + GPIO100_I2C0_SCL | PIN_INPUT_PULLUP | PIN_SLPM_NOCHANGE, + GPIO101_I2C0_SDA | PIN_SLPM_NOCHANGE, + + /* TOUCH_IRQ */ + GPIO179_GPIO | PIN_INPUT_PULLUP, + + /* SD-CARD detect/levelshifter pins */ + GPIO180_GPIO | PIN_INPUT_NOPULL, /* SD_CARD_DETn */ + GPIO227_GPIO | PIN_OUTPUT_LOW, /* SD_CARD_CTRL */ + GPIO185_GPIO | PIN_OUTPUT_LOW, /* SD_CARD_VSEL */ + + /* Display & HDMI HW sync */ + GPIO204_LCD_VSI1 | PIN_INPUT_PULLUP, + + /* TVOUT (connected, but unused) */ + GPIO205_GPIO | PIN_OUTPUT_LOW, + GPIO206_GPIO | PIN_OUTPUT_LOW, + GPIO207_GPIO | PIN_OUTPUT_LOW, + GPIO208_GPIO | PIN_OUTPUT_LOW, + GPIO209_GPIO | PIN_INPUT_PULLDOWN, + + /* Display (connected to NT35560 / TE, but unused) */ + GPIO211_GPIO | PIN_INPUT_PULLDOWN, + + /* Camera & MMIO XshutDown*/ + GPIO1_GPIO | PIN_OUTPUT_LOW, + GPIO2_GPIO | PIN_OUTPUT_LOW, + + /* USB chip select */ + GPIO76_GPIO | PIN_OUTPUT_LOW, + + GPIO202_ACCU0_RXD | PIN_INPUT_PULLUP | PIN_SLPM_NOCHANGE, + GPIO203_ACCU0_TXD | PIN_OUTPUT_HIGH | PIN_SLPM_NOCHANGE, + + /* Board Id Identification B5500 or S5500 */ + GPIO0_GPIO | PIN_INPUT_PULLUP, + GPIO214_GPIO | PIN_OUTPUT_LOW, /* SW_CRASH_INDICATOR */ + + /* Touchscreen chip select */ + GPIO186_GPIO | PIN_OUTPUT_HIGH | PIN_LOWEMI_ENABLED, + + GPIO133_GPIO | PIN_OUTPUT_LOW, /* DUALSIMRESETn */ + GPIO187_GPIO | PIN_OUTPUT_HIGH, /* Dual SIM CS */ + + GPIO163_GPIO | PIN_INPUT_PULLUP, /* SERVICEn */ + + GPIO223_GPIO | PIN_INPUT_PULLDOWN, /* HDMI_INT */ + GPIO225_GPIO | PIN_OUTPUT_LOW, /* HDMI_ENABLE */ +}; + +static UX500_PINS(db5500_kp_pins, + /* Keypad */ + GPIO128_KP_I0 | PIN_INPUT_PULLUP | PIN_SLPM_INPUT_PULLUP, + GPIO130_KP_I1 | PIN_INPUT_PULLUP | PIN_SLPM_INPUT_PULLUP, + GPIO132_KP_I2 | PIN_INPUT_PULLUP | PIN_SLPM_INPUT_PULLUP, + GPIO134_KP_I3 | PIN_INPUT_PULLUP | PIN_SLPM_INPUT_PULLUP, + GPIO137_KP_O4 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, + GPIO139_KP_O5 | PIN_INPUT_PULLUP | PIN_SLPM_OUTPUT_LOW, +); + +static UX500_PINS(db5500_pins_sdi0, + /* SDI0 (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, +); + +static UX500_PINS(db5500_pins_sdi1, + /* 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_PULLDOWN, + GPIO199_MC1_DAT0DIR | PIN_OUTPUT_HIGH, +); + +static UX500_PINS(db5500_pins_sdi2, + /* SDI2 (eMMC) */ + GPIO16_MC2_CMD | PIN_INPUT_PULLUP, + GPIO17_MC2_CLK | PIN_OUTPUT_LOW, + GPIO23_MC2_DAT0 | PIN_INPUT_PULLUP, + GPIO19_MC2_DAT1 | PIN_INPUT_PULLUP, + GPIO24_MC2_DAT2 | PIN_INPUT_PULLUP, + GPIO20_MC2_DAT3 | PIN_INPUT_PULLUP, + GPIO25_MC2_DAT4 | PIN_INPUT_PULLUP, + GPIO21_MC2_DAT5 | PIN_INPUT_PULLUP, + GPIO26_MC2_DAT6 | PIN_INPUT_PULLUP, + GPIO22_MC2_DAT7 | PIN_INPUT_PULLUP +); + +static UX500_PINS(db5500_pins_sdi3, + /* SDI3 (SDIO) */ + GPIO171_MC3_DAT0 | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO172_MC3_DAT1 | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO173_MC3_DAT2 | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO174_MC3_DAT3 | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO175_MC3_CMD | PIN_INPUT_PULLUP | PIN_LOWEMI_ENABLED, + GPIO176_MC3_CLK | PIN_OUTPUT_LOW, +); + +static UX500_PINS(u5500_pins_i2c1, + GPIO3_I2C1_SCL | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, + GPIO4_I2C1_SDA | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, +); + +static UX500_PINS(u5500_pins_i2c2, + GPIO218_I2C2_SCL | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, + GPIO219_I2C2_SDA | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, +); + +static UX500_PINS(u5500_pins_i2c3, + GPIO177_I2C3_SCL | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, + GPIO178_I2C3_SDA | PIN_INPUT_NOPULL | PIN_LOWEMI_ENABLED, +); + +static UX500_PINS(u5500_pins_spi3, + GPIO188_SPI3_RXD | PIN_INPUT_PULLUP, + GPIO189_SPI3_TXD | PIN_OUTPUT_LOW | PIN_LOWEMI_ENABLED, + GPIO190_SPI3_CLK | PIN_OUTPUT_LOW | PIN_LOWEMI_ENABLED, +); + +/* USB */ +static UX500_PINS(u5500_pins_usb, + GPIO74_USB_NXT | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO72_USB_STP | PIN_OUTPUT_HIGH | PIN_SLPM_OUTPUT_HIGH, + GPIO75_USB_XCLK | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO73_USB_DIR | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO71_USB_DAT7 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO70_USB_DAT6 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO69_USB_DAT5 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO68_USB_DAT4 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO67_USB_DAT3 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO66_USB_DAT2 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO65_USB_DAT1 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, + GPIO64_USB_DAT0 | PIN_INPUT_NOPULL | PIN_SLPM_INPUT_PULLDOWN, +); + +static struct ux500_pin_lookup u5500_pins[] = { + PIN_LOOKUP("nmk-i2c.1", &u5500_pins_i2c1), + PIN_LOOKUP("nmk-i2c.2", &u5500_pins_i2c2), + PIN_LOOKUP("nmk-i2c.3", &u5500_pins_i2c3), + PIN_LOOKUP("spi3", &u5500_pins_spi3), + PIN_LOOKUP("db5500_kp", &db5500_kp_pins), + PIN_LOOKUP("ab5500-usb.0", &u5500_pins_usb), + PIN_LOOKUP("sdi0", &db5500_pins_sdi0), + PIN_LOOKUP("sdi1", &db5500_pins_sdi1), + PIN_LOOKUP("sdi2", &db5500_pins_sdi2), + PIN_LOOKUP("sdi3", &db5500_pins_sdi3), +}; + +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)); +} + +/* Stub function to make board-ux500-cg2900.c compile within a U5500 configuration */ +int pins_for_u9500(void) +{ + return 0; +} diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 9de9e9c4dbb..92811f67bf5 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -1,7 +1,6 @@ /* * 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 */ @@ -9,8 +8,25 @@ #include <linux/platform_device.h> #include <linux/amba/bus.h> #include <linux/irq.h> +#include <linux/gpio/nomadik.h> #include <linux/i2c.h> #include <linux/mfd/abx500/ab5500.h> +#include <linux/amba/pl022.h> +#include <linux/delay.h> +#include <linux/led-lm3530.h> +#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h> +#include <linux/input/matrix_keypad.h> +#ifdef CONFIG_SENSORS_LSM303DLH +#include <linux/lsm303dlh.h> +#endif +#include <linux/leds-ab5500.h> +#ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI +#include <linux/cyttsp.h> +#endif + +#ifdef CONFIG_AV8100 +#include <video/av8100.h> +#endif #include <asm/hardware/gic.h> #include <asm/mach/arch.h> @@ -18,36 +34,132 @@ #include <plat/pincfg.h> #include <plat/i2c.h> -#include <plat/gpio-nomadik.h> #include <mach/hardware.h> +#include <mach/ste-dma40-db5500.h> +#ifdef CONFIG_UX500_SOC_DBX500 +#include <mach/msp.h> +#endif #include <mach/devices.h> #include <mach/setup.h> +#include <mach/db5500-keypad.h> +#include <mach/crypto-ux500.h> +#include <mach/abx500-accdet.h> #include "pins-db5500.h" +#include "pins.h" #include "devices-db5500.h" -#include <linux/led-lm3530.h> +#include "board-u5500.h" +#include "board-u5500-bm.h" +#include "board-u5500-wlan.h" + +#ifdef CONFIG_SENSORS_LSM303DLH +/* + * 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, +/* display is mounted reverse in the hardware */ + .negative_x = 1, + .negative_y = 1, + .negative_z = 1, +}; +#endif + +/* + * Touchscreen + */ +static struct synaptics_rmi4_platform_data rmi4_i2c_platformdata = { + .irq_number = NOMADIK_GPIO_TO_IRQ(179), + .irq_type = (IRQF_TRIGGER_FALLING | IRQF_SHARED), +#if defined(CONFIG_DISPLAY_GENERIC_DSI_PRIMARY_ROTATION_ANGLE) && \ + 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 = NOMADIK_GPIO_TO_IRQ(223), + .reset = 225, + .alt_powerupseq = true, + .mclk_freq = 1, /* MCLK_RNG_22_27 */ +}; /* - * GPIO + * leds LM3530 */ +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_4096ms, + .brt_ramp_law = 1, /* Linear */ + .brt_ramp_fall = LM3530_RAMP_TIME_260ms, + .brt_ramp_rise = LM3530_RAMP_TIME_260ms, + .als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm, + .als2_resistor_sel = LM3530_ALS_IMPD_Z, + .als_vmin = 730, /* mV */ + .als_vmax = 1020, /* mV */ + .brt_val = 0x7F, /* Max brightness */ + .hw_en_gpio = LM3530_BL_ENABLE_GPIO, +}; -static pin_cfg_t u5500_pins[] = { - /* I2C */ - GPIO218_I2C2_SCL | PIN_INPUT_PULLUP, - GPIO219_I2C2_SDA | PIN_INPUT_PULLUP, - /* DISPLAY_ENABLE */ - GPIO226_GPIO | PIN_OUTPUT_LOW, +/* leds-ab5500 */ +static struct ab5500_hvleds_platform_data ab5500_hvleds_data = { + .hw_fade = false, + .leds = { + [0] = { + .name = "red", + .led_on = true, + .led_id = 0, + .fade_hi = 255, + .fade_lo = 0, + .max_current = 10, /* wrong value may damage h/w */ + }, + [1] = { + .name = "green", + .led_on = true, + .led_id = 1, + .fade_hi = 255, + .fade_lo = 0, + .max_current = 10, /* wrong value may damage h/w */ + }, + [2] { + .name = "blue", + .led_on = true, + .led_id = 2, + .fade_hi = 255, + .fade_lo = 0, + .max_current = 10, /* wrong value may damage h/w */ + }, + }, +}; - /* Backlight Enbale */ - GPIO224_GPIO | PIN_OUTPUT_HIGH, +static struct ab5500_ponkey_platform_data ab5500_ponkey_data = { + /* + * Shutdown time in secs. Can be set + * to 10sec, 5sec and 0sec(disabled) + */ + .shutdown_secs = 10, }; + /* * I2C */ -#define U5500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ +#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 \ @@ -62,31 +174,35 @@ static struct nmk_i2c_controller u5500_i2c##id##_data = { \ .rft = _rft, \ /* std. mode operation */ \ .clk_freq = clk, \ + /* Slave response timeout(ms) */\ + .timeout = t_out, \ .sm = _sm, \ } + /* - * The board uses TODO <3> i2c controllers, initialize all of + * 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(2, 0xe, 1, 1, 400000, I2C_FREQ_MODE_FAST); +U5500_I2C_CONTROLLER(1, 0xe, 1, 10, 400000, 200, I2C_FREQ_MODE_FAST); +U5500_I2C_CONTROLLER(2, 0xe, 1, 10, 400000, 200, I2C_FREQ_MODE_FAST); +U5500_I2C_CONTROLLER(3, 0xe, 1, 10, 400000, 200, I2C_FREQ_MODE_FAST); -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_8s, - .brt_ramp_rise = LM3530_RAMP_TIME_8s, - .als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm, - .als2_resistor_sel = LM3530_ALS_IMPD_Z, - .als_vmin = 730, /* mV */ - .als_vmax = 1020, /* mV */ - .brt_val = 0x7F, /* Max brightness */ +static struct i2c_board_info __initdata u5500_i2c2_sensor_devices[] = { +#ifdef CONFIG_SENSORS_LSM303DLH + { + /* LSM303DLHC Accelerometer */ + I2C_BOARD_INFO("lsm303dlhc_a", 0x19), + .platform_data = &lsm303dlh_pdata, + }, + { + /* LSM303DLH Magnetometer */ + I2C_BOARD_INFO("lsm303dlh_m", 0x1E), + .platform_data = &lsm303dlh_pdata, + }, +#endif }; static struct i2c_board_info __initdata u5500_i2c2_devices[] = { @@ -95,54 +211,530 @@ static struct i2c_board_info __initdata u5500_i2c2_devices[] = { I2C_BOARD_INFO("lm3530-led", 0x36), .platform_data = &u5500_als_platform_data, }, + { + I2C_BOARD_INFO("av8100", 0x70), + .platform_data = &av8100_plat_data, + }, }; -static void __init u5500_i2c_init(void) +/* + * Keypad + */ + +#define ROW_PIN_I0 128 +#define ROW_PIN_I1 130 +#define ROW_PIN_I2 132 +#define ROW_PIN_I3 134 +#define COL_PIN_O4 137 +#define COL_PIN_O5 139 + +static int db5500_kp_rows[] = { + ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3, +}; + +static int db5500_kp_cols[] = { + COL_PIN_O4, COL_PIN_O5, +}; + +static bool db5500_config; +static int db5500_set_gpio_row(int gpio) +{ + int ret = -1; + + + if (!db5500_config) { + ret = gpio_request(gpio, "db5500_kpd"); + if (ret < 0) { + pr_err("db5500_set_gpio_row: gpio request failed\n"); + return ret; + } + } + + ret = gpio_direction_output(gpio, 1); + if (ret < 0) { + pr_err("db5500_set_gpio_row: gpio direction failed\n"); + gpio_free(gpio); + } + + return ret; +} + +static int db5500_kp_init(void) +{ + struct ux500_pins *pins; + int ret, i; + + pins = ux500_pins_get("db5500_kp"); + if (pins) + ux500_pins_enable(pins); + + for (i = 0; i < ARRAY_SIZE(db5500_kp_rows); i++) { + ret = db5500_set_gpio_row(db5500_kp_rows[i]); + if (ret < 0) { + pr_err("db5500_kp_init: failed init\n"); + return ret; + } + } + + if (!db5500_config) + db5500_config = true; + + return 0; +} + +static int db5500_kp_exit(void) +{ + struct ux500_pins *pins; + + pins = ux500_pins_get("db5500_kp"); + if (pins) + ux500_pins_disable(pins); + + return 0; +} + +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 = { + .init = db5500_kp_init, + .exit = db5500_kp_exit, + .gpio_input_pins = db5500_kp_rows, + .gpio_output_pins = db5500_kp_cols, + .keymap_data = &u5500_keymap_data, + .no_autorepeat = true, + .krow = ARRAY_SIZE(db5500_kp_rows), + .kcol = ARRAY_SIZE(db5500_kp_cols), + .debounce_ms = 40, /* milliseconds */ + .switch_delay = 200, /* in jiffies */ +}; + +#ifdef CONFIG_UX500_SOC_DBX500 +/* + * 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_I2S_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 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); +} +#else +static void __init u5500_msp_init(void) { - db5500_add_i2c2(&u5500_i2c2_data); - i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices)); } +#endif + +/* + * SPI + */ + +static struct pl022_ssp_controller u5500_spi3_data = { + .bus_id = 1, + .num_chipselect = 4, /* 3 possible CS lines + 1 for tests */ +}; + +static void __init u5500_spi_init(void) +{ + db5500_add_spi3(&u5500_spi3_data); +} + +static struct resource ab5500_resources[] = { + [0] = { + .start = IRQ_DB5500_PRCMU_ABB, + .end = IRQ_DB5500_PRCMU_ABB, + .flags = IORESOURCE_IRQ + } +}; + + +#ifdef CONFIG_INPUT_AB5500_ACCDET +static struct abx500_accdet_platform_data ab5500_accdet_pdata = { + .btn_keycode = KEY_MEDIA, + .accdet1_dbth = ACCDET1_TH_300mV | ACCDET1_DB_10ms, + .accdet2122_th = ACCDET21_TH_300mV | ACCDET22_TH_300mV, + .is_detection_inverted = false, + }; +#endif static struct ab5500_platform_data ab5500_plf_data = { .irq = { - .base = 0, - .count = 0, + .base = IRQ_AB5500_BASE, + .count = AB5500_NR_IRQS, }, - .init_settings = NULL, - .init_settings_sz = 0, - .pm_power_off = false, + .pm_power_off = true, + .regulator = &u5500_ab5500_regulator_data, +#ifdef CONFIG_INPUT_AB5500_ACCDET + .dev_data[AB5500_DEVID_ACCDET] = &ab5500_accdet_pdata, + .dev_data_sz[AB5500_DEVID_ACCDET] = sizeof(ab5500_accdet_pdata), +#endif + .dev_data[AB5500_DEVID_LEDS] = &ab5500_hvleds_data, + .dev_data_sz[AB5500_DEVID_LEDS] = sizeof(ab5500_hvleds_data), + .init_settings = (struct abx500_init_settings[]){ + { + .bank = 0x3, + .reg = 0x17, + .setting = 0x0F, + }, + { + .bank = 0x3, + .reg = 0x18, + .setting = 0x10, + }, + }, + .init_settings_sz = 2, +#if defined(CONFIG_AB5500_BM) + .dev_data[AB5500_DEVID_CHARGALG] = &abx500_bm_pt_data, + .dev_data_sz[AB5500_DEVID_CHARGALG] = sizeof(abx500_bm_pt_data), + .dev_data[AB5500_DEVID_CHARGER] = &abx500_bm_pt_data, + .dev_data_sz[AB5500_DEVID_CHARGER] = sizeof(abx500_bm_pt_data), + .dev_data[AB5500_DEVID_FG] = &abx500_bm_pt_data, + .dev_data_sz[AB5500_DEVID_FG] = sizeof(abx500_bm_pt_data), + .dev_data[AB5500_DEVID_BTEMP] = &abx500_bm_pt_data, + .dev_data_sz[AB5500_DEVID_BTEMP] = sizeof(abx500_bm_pt_data), +#endif + .dev_data[AB5500_DEVID_ONSWA] = &ab5500_ponkey_data, + .dev_data_sz[AB5500_DEVID_ONSWA] = sizeof(ab5500_ponkey_data), }; -static struct platform_device ab5500_device = { +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 platform_device u5500_mloader_device = { + .name = "db5500_mloader", + .id = -1, .num_resources = 0, }; +static struct cryp_platform_data u5500_cryp1_platform_data = { + .mem_to_engine = { + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB5500_DMA_DEV48_CRYPTO1_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 = DB5500_DMA_DEV48_CRYPTO1_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, + } +}; + +static struct stedma40_chan_cfg u5500_hash_dma_cfg_tx = { + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB5500_DMA_DEV50_HASH1_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_16, + .dst_info.psize = STEDMA40_PSIZE_LOG_16, +}; + +static struct hash_platform_data u5500_hash1_platform_data = { + .mem_to_engine = &u5500_hash_dma_cfg_tx, + .dma_filter = stedma40_filter, +}; + +/* modem crash dump detection driver data */ +static struct resource mcdd_resources[] = { + { + .name = "mcdd_intreset_addr", + .start = U5500_INTCON_MBOX1_INT_RESET_ADDR, + .end = U5500_INTCON_MBOX1_INT_RESET_ADDR, + .flags = IORESOURCE_MEM, + }, + { + .name = "mcdd_mbox_irq", + .start = MBOX_PAIR1_VIRT_IRQ, + .end = MBOX_PAIR1_VIRT_IRQ, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device u5500_mcdd_device = { + .name = "u5500-mcdd-modem", + .id = 0, + .resource = mcdd_resources, + .num_resources = ARRAY_SIZE(mcdd_resources), +}; + static struct platform_device *u5500_platform_devices[] __initdata = { - &ab5500_device, + &u5500_ab5500_device, +#ifdef CONFIG_FB_MCDE + &u5500_mcde_device, +#endif + &ux500_hwmem_device, + &u5500_b2r2_device, + &u5500_mloader_device, +#ifdef CONFIG_U5500_MMIO + &u5500_mmio_device, +#endif + &u5500_thsens_device, + &u5500_mcdd_device, }; +#define BACKUPRAM_ROM_DEBUG_ADDR 0xFFC +#define MMC_BLOCK_ID 0x20 + +int u5500_get_boot_mmc(void) +{ + unsigned int mmcblk; + + mmcblk = readl(__io_address(U5500_BACKUPRAM1_BASE) + + BACKUPRAM_ROM_DEBUG_ADDR); + + if (mmcblk & MMC_BLOCK_ID) + return 2; + + return 0; +} + +/* + * R3A (and presumably, future) S5500 boards have different regulator + * assignments from the earlier boards. Since there's no clean way to identify + * the board revision from hardware, we use the fact that R2A boots from MMC0 + * (via peripheral boot) and R3A boots from MMC2 to distinguish them. + */ +bool u5500_board_is_pre_r3a(void) +{ + if (!cpu_is_u5500v20()) + return false; + + if (!u5500_board_is_s5500()) + return true; + + if (u5500_get_boot_mmc() == 2) + return false; + + return true; +} + + +/* + * This function check whether it is Small S5500 board + * GPIO0 is HIGH for S5500 + */ +bool u5500_board_is_s5500(void) +{ + static bool s5500; + static bool once; + int err, val; + + if (once) + return s5500; + + err = gpio_request(GPIO_BOARD_VERSION, "Board Version"); + if (err) { + pr_err("Error %d while requesting GPIO for Board Version\n", + err); + return err; + } + + err = gpio_direction_input(GPIO_BOARD_VERSION); + if (err) { + pr_err("Error %d while setting GPIO for Board Version" + "output mode\n", err); + return err; + } + + val = gpio_get_value(GPIO_BOARD_VERSION); + + gpio_free(GPIO_BOARD_VERSION); + + s5500 = val; + once = true; + + return val; +} + +static long u5500_panic_blink(int state) +{ + gpio_direction_output(GPIO_SW_CRASH_INDICATOR, state); + return 0; +} + +#define PRCC_K_SOFTRST_SET 0x18 +#define PRCC_K_SOFTRST_CLEAR 0x1C +/* pl011 reset */ +static void ux500_uart3_reset(void) +{ + void __iomem *prcc_rst_set, *prcc_rst_clr; + + prcc_rst_set = __io_address(U5500_CLKRST5_BASE + + PRCC_K_SOFTRST_SET); + prcc_rst_clr = __io_address(U5500_CLKRST5_BASE + + PRCC_K_SOFTRST_CLEAR); + + /* + * Activate soft reset PRCC_K_SOFTRST_CLEAR + * + * As we are dealing with IP register lockup + * so to make double sure that IP gets reset + * and reset pulse remains for more than one + * clock cycle a delay is added. + */ + writel((readl(prcc_rst_clr) | 0x08), prcc_rst_clr); + udelay(1); + + /* Release soft reset PRCC_K_SOFTRST_SET */ + writel((readl(prcc_rst_set) | 0x08), prcc_rst_set); + udelay(1); +} + +static struct amba_pl011_data uart3_plat = { + .reset = ux500_uart3_reset, +}; + +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(2, ARRAY_AND_SIZE(u5500_i2c2_devices)); + i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_sensor_devices)); +} + static void __init u5500_uart_init(void) { db5500_add_uart0(NULL); db5500_add_uart1(NULL); db5500_add_uart2(NULL); + db5500_add_uart3(&uart3_plat); +} + +static void __init u5500_cryp1_hash1_init(void) +{ + db5500_add_cryp1(&u5500_cryp1_platform_data); + db5500_add_hash1(&u5500_hash1_platform_data); +} + +static int __init u5500_accel_sensor_init(void) +{ + int status; + union i2c_smbus_data data; + struct i2c_adapter *i2c2; + + i2c2 = i2c_get_adapter(2); + if (!i2c2) { + pr_err("failed to get i2c adapter\n"); + return; + } + status = i2c_smbus_xfer(i2c2, 0x19 , 0, + I2C_SMBUS_READ, 0x0F , + I2C_SMBUS_BYTE_DATA, &data); + if (status < 0) + lsm303dlh_pdata.chip_id = 0; + else + lsm303dlh_pdata.chip_id = data.byte; + i2c_put_adapter(i2c2); } +module_init(u5500_accel_sensor_init); static void __init u5500_init_machine(void) { u5500_init_devices(); - nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins)); + u5500_regulators_init(); + u5500_pins_init(); + u5500_i2c_init(); + u5500_msp_init(); + u5500_spi_init(); + u5500_sdi_init(); u5500_uart_init(); + u5500_wlan_init(); + + db5500_add_keypad(&u5500_keypad_board); + u5500_cryp1_hash1_init(); + +#ifdef CONFIG_TOUCHSCREEN_CYTTSP_SPI + u5500_cyttsp_init(); +#endif + platform_add_devices(u5500_platform_devices, ARRAY_SIZE(u5500_platform_devices)); + + if (!gpio_request_one(GPIO_SW_CRASH_INDICATOR, GPIOF_OUT_INIT_LOW, + "SW_CRASH_INDICATOR")) + panic_blink = u5500_panic_blink; } MACHINE_START(U5500, "ST-Ericsson U5500 Platform") @@ -152,4 +744,14 @@ MACHINE_START(U5500, "ST-Ericsson U5500 Platform") .timer = &ux500_timer, .handle_irq = gic_handle_irq, .init_machine = u5500_init_machine, + .restart = ux500_restart, +MACHINE_END + +MACHINE_START(B5500, "ST-Ericsson U5500 Big Board") + .atag_offset = 0x00000100, + .map_io = u5500_map_io, + .init_irq = ux500_init_irq, + .timer = &ux500_timer, + .init_machine = u5500_init_machine, + .restart = ux500_restart, 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..a7e4bbbc714 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500.h @@ -0,0 +1,35 @@ +/* + * 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 +#define GPIO_BOARD_VERSION 0 +#define GPIO_PRIMARY_CAM_XSHUTDOWN 1 +#define GPIO_SECONDARY_CAM_XSHUTDOWN 2 +#define GPIO_CAMERA_PMIC_EN 212 +#define GPIO_SW_CRASH_INDICATOR 214 + +#define CYPRESS_TOUCH_INT_PIN 179 +#define CYPRESS_TOUCH_RST_GPIO 135 +#define CYPRESS_SLAVE_SELECT_GPIO 186 + +#define LM3530_BL_ENABLE_GPIO 224 + +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); +void u5500_cyttsp_init(void); +bool u5500_board_is_s5500(void); +int u5500_get_boot_mmc(void); +bool u5500_board_is_pre_r3a(void); + +#endif diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 18aa5c05c69..e21a77475a3 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -9,20 +9,23 @@ #include <linux/amba/bus.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/gpio/nomadik.h> -#include <asm/mach/map.h> #include <asm/pmu.h> +#include <asm/mach/map.h> +#include <asm/cacheflush.h> +#include <asm/tlbflush.h> -#include <plat/gpio-nomadik.h> +#include <linux/gpio.h> #include <mach/hardware.h> #include <mach/devices.h> #include <mach/setup.h> #include <mach/irqs.h> #include <mach/usb.h> +#include <mach/ste-dma40-db5500.h> #include "devices-db5500.h" -#include "ste-dma40-db5500.h" static struct map_desc u5500_uart_io_desc[] __initdata = { __IO_DEV_DESC(U5500_UART0_BASE, SZ_4K), @@ -35,8 +38,16 @@ static struct map_desc u5500_io_desc[] __initdata = { __IO_DEV_DESC(U5500_GIC_DIST_BASE, SZ_4K), __IO_DEV_DESC(U5500_L2CC_BASE, SZ_4K), __IO_DEV_DESC(U5500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(U5500_MTU1_BASE, SZ_4K), + __IO_DEV_DESC(U5500_RTC_BASE, SZ_4K), + __IO_DEV_DESC(U5500_MTIMER_BASE, SZ_4K), __IO_DEV_DESC(U5500_BACKUPRAM0_BASE, SZ_8K), + /* Map U5500_PUBLIC_BOOT_ROM_BASE (base+18000) only + * for TEE security driver + * and avoid overlap with asic ID at base+1D000 */ + __MEM_DEV_DESC(U5500_BOOT_ROM_BASE+0x18000, 6*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), @@ -44,6 +55,11 @@ static struct map_desc u5500_io_desc[] __initdata = { __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), + __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[] = { @@ -130,31 +146,58 @@ static struct platform_device mbox2_device = { .num_resources = ARRAY_SIZE(mbox2_resources), }; +static struct platform_device db5500_prcmu_device = { + .name = "db5500-prcmu", +}; + static struct platform_device *db5500_platform_devs[] __initdata = { + &u5500_gpio_devs[0], + &u5500_gpio_devs[1], + &u5500_gpio_devs[2], + &u5500_gpio_devs[3], + &u5500_gpio_devs[4], + &u5500_gpio_devs[5], + &u5500_gpio_devs[6], + &u5500_gpio_devs[7], &mbox0_device, &mbox1_device, &mbox2_device, + &db5500_prcmu_device, + &u5500_wdt_device, }; -static resource_size_t __initdata db5500_gpio_base[] = { - 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 u8 db5500_revision; -static void __init db5500_add_gpios(void) +bool cpu_is_u5500v1() { - struct nmk_gpio_platform_data pdata = { - /* No custom data yet */ - }; + return db5500_revision == 0xA0; +} - dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base), - IRQ_DB5500_GPIO0, &pdata); +bool cpu_is_u5500v2() +{ + return (db5500_revision & 0xf0) == 0xB0; +} + +bool cpu_is_u5500v20() +{ + return db5500_revision == 0xB0; +} + +bool cpu_is_u5500v21() +{ + return db5500_revision == 0xB1; +} + +static void db5500_rev_init(void) +{ + unsigned int asicid; + + /* As in devicemaps_init() */ + local_flush_tlb_all(); + flush_cache_all(); + + asicid = readl_relaxed(__io_address(U5500_ASIC_ID_ADDRESS)); + db5500_revision = asicid & 0xff; } void __init u5500_map_io(void) @@ -169,6 +212,8 @@ void __init u5500_map_io(void) iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc)); _PRCMU_BASE = __io_address(U5500_PRCMU_BASE); + + db5500_rev_init(); } static void __init db5500_pmu_init(void) @@ -214,7 +259,10 @@ static int usb_db5500_tx_dma_cfg[] = { void __init u5500_init_devices(void) { - db5500_add_gpios(); +#ifdef CONFIG_STM_TRACE + /* Early init for STM tracing */ + /* platform_device_register(&u5500_stm_device); */ +#endif db5500_pmu_init(); db5500_dma_init(); db5500_add_rtc(); diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 7176ee7491a..a163e1fbf37 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -14,19 +14,23 @@ #include <linux/amba/bus.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/gpio/nomadik.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/dma-mapping.h> +#include <linux/sys_soc.h> -#include <asm/mach/map.h> #include <asm/pmu.h> -#include <plat/gpio-nomadik.h> +#include <asm/mach/map.h> #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> +#include <linux/mfd/dbx500-prcmu.h> +#include <mach/reboot_reasons.h> #include <mach/usb.h> +#include <mach/ste-dma40-db8500.h> #include "devices-db8500.h" -#include "ste-dma40-db8500.h" /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_uart_io_desc[] __initdata = { @@ -40,8 +44,15 @@ static struct map_desc u8500_io_desc[] __initdata = { __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(U8500_MTU1_BASE, SZ_4K), + __IO_DEV_DESC(U8500_RTC_BASE, SZ_4K), __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), + /* Map U8500_PUBLIC_BOOT_ROM_BASE (base+17000) only + * for TEE security driver + * and avoid overlap with asic ID at base+1D000 */ + __MEM_DEV_DESC(U8500_BOOT_ROM_BASE+0x17000, 6*SZ_4K), + __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), @@ -63,6 +74,14 @@ void __init u8500_map_io(void) */ iotable_init(u8500_uart_io_desc, ARRAY_SIZE(u8500_uart_io_desc)); + /* + * 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 + * Can't be higher than 14M with VMALLOC_END at 0xFF000000 + */ + init_consistent_dma_size(14*SZ_1M); + ux500_map_io(); iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); @@ -115,33 +134,20 @@ static struct platform_device db8500_prcmu_device = { }; static struct platform_device *platform_devs[] __initdata = { - &u8500_dma40_device, + &u8500_gpio_devs[0], + &u8500_gpio_devs[1], + &u8500_gpio_devs[2], + &u8500_gpio_devs[3], + &u8500_gpio_devs[4], + &u8500_gpio_devs[5], + &u8500_gpio_devs[6], + &u8500_gpio_devs[7], + &u8500_gpio_devs[8], &db8500_pmu_device, &db8500_prcmu_device, + &u8500_wdt_device, }; -static resource_size_t __initdata db8500_gpio_base[] = { - 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 void __init db8500_add_gpios(void) -{ - struct nmk_gpio_platform_data pdata = { - .supports_sleepmode = true, - }; - - dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), - IRQ_DB8500_GPIO0, &pdata); -} - static int usb_db8500_rx_dma_cfg[] = { DB8500_DMA_DEV38_USB_OTG_IEP_1_9, DB8500_DMA_DEV37_USB_OTG_IEP_2_10, @@ -169,8 +175,13 @@ static int usb_db8500_tx_dma_cfg[] = { */ void __init u8500_init_devices(void) { +#ifdef CONFIG_STM_TRACE + /* Early init for STM tracing */ + platform_device_register(&u8500_stm_device); +#endif + + db8500_dma_init(); db8500_add_rtc(); - db8500_add_gpios(); db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); diff --git a/arch/arm/mach-ux500/cpu-db9500.c b/arch/arm/mach-ux500/cpu-db9500.c new file mode 100644 index 00000000000..1bbc9b40c1b --- /dev/null +++ b/arch/arm/mach-ux500/cpu-db9500.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA + * + * Author: Pawel SZYSZUK <pawel.szyszuk@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/init.h> + +#include <mach/id.h> + +#include "pins.h" + +/* + * U9500 is currently using U8500v2 HW. Therefore, the platform detection + * is based on the kernel cmd line setting (early_param "pinsfor"). + */ +inline bool cpu_is_u9500() +{ + if (pins_for_u9500()) + return true; + else + return false; +} diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index f4185749437..8d7f1bc7936 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -8,9 +8,13 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/mfd/dbx500-prcmu.h> #include <linux/mfd/db8500-prcmu.h> #include <linux/mfd/db5500-prcmu.h> #include <linux/clksrc-dbx500-prcmu.h> +#include <linux/delay.h> +#include <linux/stat.h> +#include <linux/sys_soc.h> #include <asm/hardware/gic.h> #include <asm/mach/map.h> @@ -19,11 +23,34 @@ #include <mach/hardware.h> #include <mach/setup.h> #include <mach/devices.h> +#include <mach/reboot_reasons.h> +#include <mach/pm.h> #include "clock.h" void __iomem *_PRCMU_BASE; +void ux500_restart(char mode, const char *cmd) +{ + unsigned short reset_code; + + reset_code = reboot_reason_code(cmd); + prcmu_system_reset(reset_code); + + mdelay(1000); + + /* + * On 5500, the PRCMU firmware waits for up to 2 seconds for the modem + * to respond. + */ + if (cpu_is_u5500()) + mdelay(2000); + + printk(KERN_ERR "Reboot via PRCMU failed -- System halted\n"); + while (1) + ; +} + void __init ux500_init_irq(void) { void __iomem *dist_base; @@ -41,6 +68,12 @@ void __init ux500_init_irq(void) gic_init(0, 29, dist_base, cpu_base); /* + * On WD reboot gic is in some cases decoupled. + * This will make sure that the GIC is correctly configured. + */ + ux500_pm_gic_recouple(); + + /* * Init clocks here so that they are available for system timer * initialization. */ @@ -48,5 +81,86 @@ void __init ux500_init_irq(void) db5500_prcmu_early_init(); if (cpu_is_u8500()) db8500_prcmu_early_init(); + + arm_pm_restart = ux500_restart; clk_init(); } + +#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", dbx500_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 (dbx500_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 = dbx500_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 (dbx500_id.process == 0x00) + return sprintf(buf, "Standard\n"); + + return sprintf(buf, "%02xnm\n", dbx500_id.process); +} + +static ssize_t ux500_get_reset_code(char *buf, struct sysfs_soc_info *si) +{ + return sprintf(buf, "0x%04x\n", prcmu_get_reset_code()); +} + +static ssize_t ux500_get_reset_reason(char *buf, struct sysfs_soc_info *si) +{ + return sprintf(buf, "%s\n", + reboot_reason_string(prcmu_get_reset_code())); +} + +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), + SYSFS_SOC_ATTR_CALLBACK("reset_code", ux500_get_reset_code), + SYSFS_SOC_ATTR_CALLBACK("reset_reason", ux500_get_reset_reason), +}; + +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/dbx500_dump.c b/arch/arm/mach-ux500/dbx500_dump.c new file mode 100644 index 00000000000..49d1711f6ff --- /dev/null +++ b/arch/arm/mach-ux500/dbx500_dump.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * License Terms: GNU General Public License v2 + * Author: Johan Bjornstedt <johan.bjornstedt@stericsson.com> + * + * Save DBx500 registers in case of kernel crash + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/kdebug.h> + +#include <mach/hardware.h> +#include <mach/db8500-regs.h> +#include <mach/db5500-regs.h> + +struct dbx500_dump_info { + char *name; + int *data; + int *io_addr; + int phy_addr; + int size; +}; + +static struct dbx500_dump_info db8500_dump[] = { + { + .name = "prcmu_tcdm", + .phy_addr = U8500_PRCMU_TCDM_BASE, + .size = 0x1000, + }, + { + .name = "prcmu_non_sec_1", + .phy_addr = U8500_PRCMU_BASE, + .size = 0x340, + }, + { + .name = "prcmu_pmb", + .phy_addr = (U8500_PRCMU_BASE + 0x344), + .size = 0xC, + }, + { + .name = "prcmu_thermal", + .phy_addr = (U8500_PRCMU_BASE + 0x3C0), + .size = 0x40, + }, + { + .name = "prcmu_non_sec_2", + .phy_addr = (U8500_PRCMU_BASE + 0x404), + .size = 0x1FC, + }, + { + .name = "prcmu_icn_pmu", + .phy_addr = (U8500_PRCMU_BASE + 0xE00), + .size = 0x118, + }, +}; + +static struct dbx500_dump_info db5500_dump[] = { + { + .name = "prcmu_tcdm", + .phy_addr = U5500_PRCMU_TCDM_BASE, + .size = 0x5000, + }, + { + .name = "prcmu_gpio", + .phy_addr = U5500_GPIO2_BASE, + .size = 0x1000, + }, + { + .name = "prcmu_msp1", + .phy_addr = U5500_MSP1_BASE, + .size = 0x1000, + }, + { + .name = "prcmu_sec", + .phy_addr = (U5500_PRCMU_BASE + 0x1000), + .size = 0x1000, + }, + { + .name = "prcmu_unsec", + .phy_addr = U5500_PRCMU_BASE, + .size = 0x1000, + }, +}; + +static struct dbx500_dump_info *dbx500_dump; +static int dbx500_dump_size; + +static int crash_notifier(struct notifier_block *nb, unsigned long val, + void *data) +{ + int i; + + pr_info("dbx500_dump notified of crash\n"); + + for (i = 0; i < dbx500_dump_size; i++) { + memcpy_fromio(dbx500_dump[i].data, dbx500_dump[i].io_addr, + dbx500_dump[i].size); + } + + return 0; +} + +static void __init init_io_addresses(void) +{ + int i; + + for (i = 0; i < dbx500_dump_size; i++) + dbx500_dump[i].io_addr = ioremap(dbx500_dump[i].phy_addr, + dbx500_dump[i].size); +} + +static struct notifier_block die_notifier = { + .notifier_call = crash_notifier, + .priority = 0, +}; + +int __init dbx500_dump_init(void) +{ + int err, i; + + if (cpu_is_u5500()) { + dbx500_dump = db5500_dump; + dbx500_dump_size = ARRAY_SIZE(db5500_dump); + } else if (cpu_is_u8500()) { + dbx500_dump = db8500_dump; + dbx500_dump_size = ARRAY_SIZE(db8500_dump); + } else { + ux500_unknown_soc(); + } + + for (i = 0; i < dbx500_dump_size; i++) { + dbx500_dump[i].data = kmalloc(dbx500_dump[i].size, GFP_KERNEL); + if (!dbx500_dump[i].data) { + pr_err("dbx500_dump: Could not allocate memory for " + "%s\n", dbx500_dump[i].name); + err = -ENOMEM; + goto free_mem; + } + } + + init_io_addresses(); + + err = register_die_notifier(&die_notifier); + if (err != 0) { + pr_err("dbx500_dump: Unable to register a die notifier %d\n", + err); + goto free_mem; + } + pr_info("dbx500_dump: driver initialized\n"); + return err; + +free_mem: + for (i = i - 1; i >= 0; i--) + kfree(dbx500_dump[i].data); + + return err; +} +arch_initcall(dbx500_dump_init); diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index c563e5418d8..435b2523664 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -6,16 +6,19 @@ */ #include <linux/kernel.h> +#include <linux/export.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 <plat/gpio-nomadik.h> +#include <linux/pm.h> +#include <linux/gpio.h> +#include <linux/gpio/nomadik.h> #include <mach/hardware.h> +#include <mach/pm.h> #include "devices-common.h" @@ -38,6 +41,7 @@ dbx500_add_amba_device(const char *name, resource_size_t base, dev->dma_mask = DMA_BIT_MASK(32); dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + dev->dev.pm_domain = &ux500_amba_dev_power_domain; dev->irq[0] = irq; dev->irq[1] = NO_IRQ; @@ -68,6 +72,7 @@ dbx500_add_platform_device(const char *name, int id, void *pdata, dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); dev->dev.dma_mask = &dev->dev.coherent_dma_mask; + dev->dev.pm_domain = &ux500_dev_power_domain; ret = platform_device_add_resources(dev, res, resnum); if (ret) @@ -108,6 +113,22 @@ dbx500_add_platform_device_4k1irq(const char *name, int id, ARRAY_SIZE(resources)); } +struct platform_device * +dbx500_add_platform_device_noirq(const char *name, int id, + resource_size_t base, void *pdata) +{ + struct resource resources[] = { + [0] = { + .start = base, + .end = base + SZ_4K - 1, + .flags = IORESOURCE_MEM, + } + }; + + return dbx500_add_platform_device(name, id, pdata, resources, + ARRAY_SIZE(resources)); +} + static struct platform_device * dbx500_add_gpio(int id, resource_size_t addr, int irq, struct nmk_gpio_platform_data *pdata) @@ -140,7 +161,6 @@ void dbx500_add_gpios(resource_size_t *base, int num, int irq, pdata->first_gpio = first; pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first); pdata->num_gpio = 32; - dbx500_add_gpio(i, base[i], irq, pdata); } } diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 7825705033b..89b7a562f6c 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -8,6 +8,8 @@ #ifndef __DEVICES_COMMON_H #define __DEVICES_COMMON_H +#include <linux/amba/serial.h> + extern struct amba_device * dbx500_add_amba_device(const char *name, resource_size_t base, int irq, void *pdata, unsigned int periphid); @@ -17,18 +19,24 @@ dbx500_add_platform_device_4k1irq(const char *name, int id, resource_size_t base, int irq, void *pdata); -struct spi_master_cntlr; +extern struct platform_device * +dbx500_add_platform_device_noirq(const char *name, int id, + resource_size_t base, 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 spi_master_cntlr *pdata) + struct stm_msp_controller *pdata) { return dbx500_add_amba_device(name, base, irq, pdata, 0); } +struct pl022_ssp_controller; + static inline struct amba_device * dbx500_add_spi(const char *name, resource_size_t base, int irq, - struct spi_master_cntlr *pdata, + struct pl022_ssp_controller *pdata, u32 periphid) { return dbx500_add_amba_device(name, base, irq, pdata, periphid); @@ -69,7 +77,7 @@ 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, + return dbx500_add_platform_device_4k1irq("ux500-msp-i2s", id, base, irq, pdata); } @@ -79,6 +87,25 @@ dbx500_add_rtc(resource_size_t base, int irq) return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0); } +struct cryp_platform_data; + +static inline struct platform_device * +dbx500_add_cryp1(int id, resource_size_t base, int irq, + struct cryp_platform_data *pdata) +{ + return dbx500_add_platform_device_4k1irq("cryp1", id, base, irq, + pdata); +} + +struct hash_platform_data; + +static inline struct platform_device * +dbx500_add_hash1(int id, resource_size_t base, + struct hash_platform_data *pdata) +{ + return dbx500_add_platform_device_noirq("hash1", id, base, pdata); +} + struct nmk_gpio_platform_data; void dbx500_add_gpios(resource_size_t *base, int num, int irq, diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c new file mode 100644 index 00000000000..6d7764f3d9e --- /dev/null +++ b/arch/arm/mach-ux500/devices-db5500.c @@ -0,0 +1,282 @@ +/* + * 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/nomadik.h> + +#include <mach/hardware.h> +#include <mach/devices.h> + +#ifdef CONFIG_FB_MCDE +#include <video/mcde.h> +#endif +#include <mach/db5500-regs.h> + +#include <linux/mfd/dbx500-prcmu.h> +#include <mach/pm.h> + +#define GPIO_DATA(_name, first, num) \ + { \ + .name = _name, \ + .first_gpio = first, \ + .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ + .num_gpio = num, \ + .get_secondary_status = ux500_pm_gpio_read_wake_up_status, \ + .set_ioforce = ux500_pm_prcmu_set_ioforce, \ + } + +#define GPIO_RESOURCE(block) \ + { \ + .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, \ + }, \ + { \ + .start = IRQ_DB5500_PRCMU_GPIO##block, \ + .end = IRQ_DB5500_PRCMU_GPIO##block, \ + .flags = IORESOURCE_IRQ, \ + } + +#define GPIO_DEVICE(block) \ + { \ + .name = "gpio", \ + .id = block, \ + .num_resources = 3, \ + .resource = &u5500_gpio_resources[block * 3], \ + .dev = { \ + .platform_data = &u5500_gpio_data[block], \ + }, \ + } + +static struct nmk_gpio_platform_data u5500_gpio_data[] = { + 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[] = { + GPIO_RESOURCE(0), + GPIO_RESOURCE(1), + GPIO_RESOURCE(2), + GPIO_RESOURCE(3), + GPIO_RESOURCE(4), + GPIO_RESOURCE(5), + GPIO_RESOURCE(6), + GPIO_RESOURCE(7), +}; + +struct platform_device u5500_gpio_devs[] = { + GPIO_DEVICE(0), + GPIO_DEVICE(1), + GPIO_DEVICE(2), + GPIO_DEVICE(3), + GPIO_DEVICE(4), + GPIO_DEVICE(5), + 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), +}; + +#ifdef CONFIG_FB_MCDE +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 = { + .syncmux = 0x01, + .regulator_mcde_epod_id = "vsupply", + .regulator_esram_epod_id = "v-esram12", +#ifdef CONFIG_MCDE_DISPLAY_DSI + .clock_dsi_id = "hdmi", + .clock_dsi_lp_id = "tv", +#endif + .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 u5500_mcde_device = { + .name = "mcde", + .id = -1, + .dev = { + .platform_data = &mcde_pdata, + }, + .num_resources = ARRAY_SIZE(mcde_resources), + .resource = mcde_resources, +}; +#endif + +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 u5500_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 u5500_thsens_resources[] = { + [0] = { + .name = "IRQ_HOTMON_LOW", + .start = IRQ_DB5500_PRCMU_TEMP_SENSOR_LOW, + .end = IRQ_DB5500_PRCMU_TEMP_SENSOR_LOW, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .name = "IRQ_HOTMON_HIGH", + .start = IRQ_DB5500_PRCMU_TEMP_SENSOR_HIGH, + .end = IRQ_DB5500_PRCMU_TEMP_SENSOR_HIGH, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device u5500_thsens_device = { + .name = "db5500_temp", + .resource = u5500_thsens_resources, + .num_resources = ARRAY_SIZE(u5500_thsens_resources), +}; + +struct platform_device u5500_wdt_device = { + .name = "ux500_wdt", + .id = -1, +}; diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h index 0c4bccd02b9..a6536edd2d1 100644 --- a/arch/arm/mach-ux500/devices-db5500.h +++ b/arch/arm/mach-ux500/devices-db5500.h @@ -17,6 +17,16 @@ #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) \ @@ -37,21 +47,21 @@ #define db5500_add_usb(rx_cfg, tx_cfg) \ ux500_add_usb(U5500_USBOTG_BASE, IRQ_DB5500_USBOTG, rx_cfg, tx_cfg) -#define db5500_add_sdi0(pdata) \ +#define db5500_add_sdi0(pdata, pid) \ dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata, \ - 0x10480180) -#define db5500_add_sdi1(pdata) \ + pid) +#define db5500_add_sdi1(pdata, pid) \ dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata, \ - 0x10480180) -#define db5500_add_sdi2(pdata) \ - dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata \ - 0x10480180) -#define db5500_add_sdi3(pdata) \ - dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata \ - 0x10480180) -#define db5500_add_sdi4(pdata) \ - dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata \ - 0x10480180) + pid) +#define db5500_add_sdi2(pdata, pid) \ + dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata, \ + pid) +#define db5500_add_sdi3(pdata, pid) \ + dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata, \ + pid) +#define db5500_add_sdi4(pdata, pid) \ + dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata, \ + pid) /* This one has a bad peripheral ID in the U5500 silicon */ #define db5500_add_spi0(pdata) \ @@ -61,10 +71,10 @@ dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata, \ 0x10080023) #define db5500_add_spi2(pdata) \ - dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata \ + dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata, \ 0x10080023) #define db5500_add_spi3(pdata) \ - dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata \ + dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata, \ 0x10080023) #define db5500_add_uart0(plat) \ @@ -76,4 +86,9 @@ #define db5500_add_uart3(plat) \ dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, plat) +#define db5500_add_cryp1(pdata) \ + dbx500_add_cryp1(-1, U5500_CRYP1_BASE, IRQ_DB5500_CRYP1, pdata) +#define db5500_add_hash1(pdata) \ + dbx500_add_hash1(-1, U5500_HASH1_BASE, pdata) + #endif diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index a7c6cdc9b11..b4da60f2f76 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -10,160 +10,435 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/gpio/nomadik.h> #include <linux/amba/bus.h> #include <linux/amba/pl022.h> +#include <plat/pincfg.h> #include <plat/ste_dma40.h> +#include <mach/devices.h> #include <mach/hardware.h> #include <mach/setup.h> +#include <mach/pm.h> +#ifdef CONFIG_FB_MCDE +#include <video/mcde.h> +#endif +#include <linux/mfd/dbx500-prcmu.h> +#ifdef CONFIG_HSI +#include <mach/hsi.h> +#endif +#include <mach/ste-dma40-db8500.h> -#include "ste-dma40-db8500.h" +#include "pins-db8500.h" -static struct resource dma40_resources[] = { +#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, \ + .supports_sleepmode = true, \ + } + +#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, 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[] = { + GPIO_RESOURCE(0), + GPIO_RESOURCE(1), + GPIO_RESOURCE(2), + GPIO_RESOURCE(3), + GPIO_RESOURCE(4), + GPIO_RESOURCE(5), + GPIO_RESOURCE(6), + GPIO_RESOURCE(7), + GPIO_RESOURCE(8), +}; + +struct platform_device u8500_gpio_devs[] = { + GPIO_DEVICE(0), + GPIO_DEVICE(1), + GPIO_DEVICE(2), + GPIO_DEVICE(3), + GPIO_DEVICE(4), + GPIO_DEVICE(5), + GPIO_DEVICE(6), + GPIO_DEVICE(7), + GPIO_DEVICE(8), +}; + +static struct resource u8500_shrm_resources[] = { [0] = { - .start = U8500_DMA_BASE, - .end = U8500_DMA_BASE + SZ_4K - 1, + .start = U8500_SHRM_GOP_INTERRUPT_BASE, + .end = U8500_SHRM_GOP_INTERRUPT_BASE + ((4*4)-1), + .name = "shrm_gop_register_base", .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", + .start = IRQ_CA_WAKE_REQ_V1, + .end = IRQ_CA_WAKE_REQ_V1, + .name = "ca_irq_wake_req", + .flags = IORESOURCE_IRQ, }, [2] = { - .start = IRQ_DB8500_DMA, - .end = IRQ_DB8500_DMA, + .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, } }; -/* Default configuration for physcial memcpy */ -struct stedma40_chan_cfg dma40_memcpy_conf_phy = { - .mode = STEDMA40_MODE_PHYSICAL, - .dir = STEDMA40_MEM_TO_MEM, +struct platform_device u8500_shrm_device = { + .name = "u8500_shrm", + .id = 0, + .dev = { + .init_name = "shrm_bus", + .coherent_dma_mask = ~0, + }, - .src_info.data_width = STEDMA40_BYTE_WIDTH, - .src_info.psize = STEDMA40_PSIZE_PHY_1, - .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + .num_resources = ARRAY_SIZE(u8500_shrm_resources), + .resource = u8500_shrm_resources +}; - .dst_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.psize = STEDMA40_PSIZE_PHY_1, - .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +#ifdef CONFIG_FB_MCDE +static struct resource mcde_resources[] = { + [0] = { + .name = MCDE_IO_AREA, + .start = U8500_MCDE_BASE, + .end = U8500_MCDE_BASE + U8500_MCDE_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .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, + }, }; -/* Default configuration for logical memcpy */ -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, +static int mcde_platform_enable_dsipll(void) +{ + return prcmu_enable_dsipll(); +} - .dst_info.data_width = STEDMA40_BYTE_WIDTH, - .dst_info.psize = STEDMA40_PSIZE_LOG_1, - .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +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_u8500_pdata = { + /* + * [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 */ +#ifdef CONFIG_MCDE_DISPLAY_DSI + .regulator_vana_id = "vdddsi1v2", +#endif + .regulator_mcde_epod_id = "vsupply", + .regulator_esram_epod_id = "v-esram34", +#ifdef CONFIG_MCDE_DISPLAY_DSI + .clock_dsi_id = "hdmi", + .clock_dsi_lp_id = "tv", +#endif + .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, }; +struct platform_device u8500_mcde_device = { + .name = "mcde", + .id = -1, + .dev = { + .platform_data = &mcde_u8500_pdata, + }, + .num_resources = ARRAY_SIZE(mcde_resources), + .resource = mcde_resources, +}; +#endif /* CONFIG_FB_MCDE */ + +static struct resource b2r2_resources[] = { + [0] = { + .start = U8500_B2R2_BASE, + .end = U8500_B2R2_BASE + ((4*1024)-1), + .name = "b2r2_base", + .flags = IORESOURCE_MEM, + }, + [1] = { + .name = "B2R2_IRQ", + .start = IRQ_DB8500_B2R2, + .end = IRQ_DB8500_B2R2, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device u8500_b2r2_device = { + .name = "b2r2", + .id = 0, + .dev = { + .init_name = "b2r2_bus", + .coherent_dma_mask = ~0, + }, + .num_resources = ARRAY_SIZE(b2r2_resources), + .resource = b2r2_resources, +}; + +/* + * WATCHDOG + */ + +struct platform_device u8500_wdt_device = { + .name = "ux500_wdt", + .id = -1, +}; + +#ifdef CONFIG_HSI /* - * Mapping between destination event lines and physical device address. - * The event line is tied to a device and therefore the address is constant. - * When the address comes from a primecell it will be configured in runtime - * and we set the address to -1 as a placeholder. + * HSI */ -static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = { - /* MUSB - these will be runtime-reconfigured */ - [DB8500_DMA_DEV39_USB_OTG_OEP_8] = -1, - [DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = -1, - [DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = -1, - [DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = -1, - [DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = -1, - [DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1, - [DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1, - [DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1, - /* PrimeCells - run-time configured */ - [DB8500_DMA_DEV0_SPI0_TX] = -1, - [DB8500_DMA_DEV1_SD_MMC0_TX] = -1, - [DB8500_DMA_DEV2_SD_MMC1_TX] = -1, - [DB8500_DMA_DEV3_SD_MMC2_TX] = -1, - [DB8500_DMA_DEV8_SSP0_TX] = -1, - [DB8500_DMA_DEV9_SSP1_TX] = -1, - [DB8500_DMA_DEV11_UART2_TX] = -1, - [DB8500_DMA_DEV12_UART1_TX] = -1, - [DB8500_DMA_DEV13_UART0_TX] = -1, - [DB8500_DMA_DEV28_SD_MM2_TX] = -1, - [DB8500_DMA_DEV29_SD_MM0_TX] = -1, - [DB8500_DMA_DEV32_SD_MM1_TX] = -1, - [DB8500_DMA_DEV33_SPI2_TX] = -1, - [DB8500_DMA_DEV35_SPI1_TX] = -1, - [DB8500_DMA_DEV40_SPI3_TX] = -1, - [DB8500_DMA_DEV41_SD_MM3_TX] = -1, - [DB8500_DMA_DEV42_SD_MM4_TX] = -1, - [DB8500_DMA_DEV43_SD_MM5_TX] = -1, -}; - -/* Mapping between source event lines and physical device address */ -static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = { - /* MUSB - these will be runtime-reconfigured */ - [DB8500_DMA_DEV39_USB_OTG_IEP_8] = -1, - [DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = -1, - [DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = -1, - [DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = -1, - [DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = -1, - [DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1, - [DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1, - [DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1, - /* PrimeCells */ - [DB8500_DMA_DEV0_SPI0_RX] = -1, - [DB8500_DMA_DEV1_SD_MMC0_RX] = -1, - [DB8500_DMA_DEV2_SD_MMC1_RX] = -1, - [DB8500_DMA_DEV3_SD_MMC2_RX] = -1, - [DB8500_DMA_DEV8_SSP0_RX] = -1, - [DB8500_DMA_DEV9_SSP1_RX] = -1, - [DB8500_DMA_DEV11_UART2_RX] = -1, - [DB8500_DMA_DEV12_UART1_RX] = -1, - [DB8500_DMA_DEV13_UART0_RX] = -1, - [DB8500_DMA_DEV28_SD_MM2_RX] = -1, - [DB8500_DMA_DEV29_SD_MM0_RX] = -1, - [DB8500_DMA_DEV32_SD_MM1_RX] = -1, - [DB8500_DMA_DEV33_SPI2_RX] = -1, - [DB8500_DMA_DEV35_SPI1_RX] = -1, - [DB8500_DMA_DEV40_SPI3_RX] = -1, - [DB8500_DMA_DEV41_SD_MM3_RX] = -1, - [DB8500_DMA_DEV42_SD_MM4_RX] = -1, - [DB8500_DMA_DEV43_SD_MM5_RX] = -1, -}; - -/* 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 = DB8500_DMA_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, - .disabled_channels = {-1}, -}; - -struct platform_device u8500_dma40_device = { +#define HSI0_CAWAKE { \ + .start = IRQ_PRCMU_HSI0, \ + .end = IRQ_PRCMU_HSI0, \ + .flags = IORESOURCE_IRQ, \ + .name = "hsi0_cawake" \ +} + +#define HSI0_ACWAKE { \ + .start = 226, \ + .end = 226, \ + .flags = IORESOURCE_IO, \ + .name = "hsi0_acwake" \ +} + +#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 \ +} + +#define STE_HSI_PORT0_TX_CHANNEL_CFG(n) { \ + .dir = STEDMA40_MEM_TO_PERIPH, \ + .high_priority = true, \ + .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,\ +}, + +#define STE_HSI_PORT0_RX_CHANNEL_CFG(n) { \ + .dir = STEDMA40_PERIPH_TO_MEM, \ + .high_priority = true, \ + .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), + HSI0_CAWAKE, + HSI0_ACWAKE, +}; + +#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) +}; + +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 = &dma40_plat_data, + .platform_data = &u8500_hsi_platform_data, }, - .name = "dma40", + .name = "ste_hsi", .id = 0, - .num_resources = ARRAY_SIZE(dma40_resources), - .resource = dma40_resources + .resource = u8500_hsi_resources, + .num_resources = ARRAY_SIZE(u8500_hsi_resources) +}; +#endif /* CONFIG_HSI */ + +/* + * Thermal Sensor + */ + +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, + }, +}; + +struct platform_device u8500_thsens_device = { + .name = "dbx500_temp", + .resource = u8500_thsens_resources, + .num_resources = ARRAY_SIZE(u8500_thsens_resources), }; struct resource keypad_resources[] = { diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index cbd4a9ae810..4a54a6f5aa6 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -98,4 +98,9 @@ db8500_add_ssp(const char *name, resource_size_t base, int irq, #define db8500_add_uart2(pdata) \ dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, pdata) +#define db8500_add_cryp1(pdata) \ + dbx500_add_cryp1(-1, U8500_CRYP1_BASE, IRQ_DB8500_CRYP1, pdata) +#define db8500_add_hash1(pdata) \ + dbx500_add_hash1(-1, U8500_HASH1_BASE, pdata) + #endif diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c index ea0a2f92ca7..77d8d088460 100644 --- a/arch/arm/mach-ux500/devices.c +++ b/arch/arm/mach-ux500/devices.c @@ -14,6 +14,51 @@ #include <mach/hardware.h> #include <mach/setup.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 platform_device u8500_trace_modem = { + .name = "db8500-modem-trace", + .id = 0, + .dev = { + .init_name = "db8500-modem-trace", + .platform_data = &trace_pdata, + }, + .num_resources = 1, + .resource = &trace_resource, +}; + +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 - 1; + return 0; +} + +early_param("mem_mtrace", early_trace_modem); +#endif + +struct platform_device ux500_hwmem_device = { + .name = "hwmem", +}; + void __init amba_add_devices(struct amba_device *devs[], int num) { int i; diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c index 1cfab68ae41..8f31f2f06a5 100644 --- a/arch/arm/mach-ux500/dma-db5500.c +++ b/arch/arm/mach-ux500/dma-db5500.c @@ -14,8 +14,8 @@ #include <plat/ste_dma40.h> #include <mach/setup.h> #include <mach/hardware.h> - -#include "ste-dma40-db5500.h" +#include <mach/pm.h> +#include <mach/ste-dma40-db5500.h> static struct resource dma40_resources[] = { [0] = { @@ -72,28 +72,128 @@ static struct stedma40_chan_cfg dma40_memcpy_conf_log = { * now. */ static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = { - [DB5500_DMA_DEV24_SDMMC0_RX] = -1, - [DB5500_DMA_DEV38_USB_OTG_IEP_8] = -1, - [DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = -1, - [DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = -1, - [DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = -1, - [DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = -1, - [DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = -1, - [DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = -1, - [DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = -1, + [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, 30 not used */ + [DB5500_DMA_DEV31_CRYPTO1_RX] = 0, /* v2 */ + /* 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, + [DB5500_DMA_DEV46_CRYPTO1_RX] = 0, /* v2 */ + [DB5500_DMA_DEV47_MCDE_RX] = 0, + [DB5500_DMA_DEV48_CRYPTO1_RX] = U5500_CRYP1_BASE + CRYP1_RX_REG_OFFSET, + /* 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_DEV24_SDMMC0_TX] = -1, - [DB5500_DMA_DEV38_USB_OTG_OEP_8] = -1, - [DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = -1, - [DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = -1, - [DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = -1, - [DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = -1, - [DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = -1, - [DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = -1, - [DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = -1, + [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 not used */ + [DB5500_DMA_DEV30_HASH1_TX] = 0, /* v2 */ + [DB5500_DMA_DEV31_CRYPTO1_TX] = 0, /* v2 */ + [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, + [DB5500_DMA_DEV46_CRYPTO1_TX] = 0, /* v2 */ + [DB5500_DMA_DEV47_STM_TX] = 0, + [DB5500_DMA_DEV48_CRYPTO1_TX] = U5500_CRYP1_BASE + CRYP1_TX_REG_OFFSET, + [DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX] = 0, + [DB5500_DMA_DEV50_HASH1_TX] = U5500_HASH1_BASE + HASH1_TX_REG_OFFSET, + [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[] = { @@ -118,6 +218,9 @@ static struct stedma40_platform_data dma40_plat_data = { static struct platform_device dma40_device = { .dev = { .platform_data = &dma40_plat_data, +#ifdef CONFIG_PM + .pm_domain = &ux500_dev_power_domain, +#endif }, .name = "dma40", .id = 0, @@ -131,6 +234,6 @@ void __init db5500_dma_init(void) ret = platform_device_register(&dma40_device); if (ret) - dev_err(&dma40_device.dev, "unable to register device: %d\n", 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..17c4c80de33 --- /dev/null +++ b/arch/arm/mach-ux500/dma-db8500.c @@ -0,0 +1,314 @@ +/* + * 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> + +#ifdef CONFIG_HSI +#include <mach/hsi.h> +#endif +#include <mach/setup.h> +#include <mach/ste-dma40-db8500.h> +#include <mach/pm.h> +#include <mach/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 + }, + [3] = { + .start = U8500_DMA_LCLA_BASE, + .end = U8500_DMA_LCLA_BASE + SZ_8K - 1, + .flags = IORESOURCE_MEM, + .name = "lcla_esram", + } +}; + +/* 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] = U8500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [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, +#ifdef CONFIG_HSI + [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, +#endif + [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_MSP3_RX] = U8500_MSP3_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] = U8500_SDI0_BASE + SD_MMC_TX_RX_REG_OFFSET, + [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, +#ifdef CONFIG_HSI + [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, +#endif + [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] = U8500_HASH1_BASE + HASH1_TX_REG_OFFSET, + [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}, + .use_esram_lcla = true, +}; + +#ifdef CONFIG_UX500_CONTEXT +#define D40_DREG_GCC 0x000 +#define D40_DREG_LCPA 0x020 +#define D40_DREG_LCLA 0x024 + +static void __iomem *base; + +static int dma_context_notifier_call(struct notifier_block *this, + unsigned long event, void *data) +{ + static unsigned long lcpa; + static unsigned long lcla; + static unsigned long gcc; + + switch (event) { + case CONTEXT_APE_SAVE: + lcla = readl(base + D40_DREG_LCLA); + lcpa = readl(base + D40_DREG_LCPA); + gcc = readl(base + D40_DREG_GCC); + break; + + case CONTEXT_APE_RESTORE: + writel(gcc, base + D40_DREG_GCC); + writel(lcpa, base + D40_DREG_LCPA); + writel(lcla, base + D40_DREG_LCLA); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block dma_context_notifier = { + .notifier_call = dma_context_notifier_call, +}; + +static void dma_context_notifier_init(void) +{ + base = ioremap(dma40_resources[0].start, + resource_size(&dma40_resources[0])); + if (WARN_ON(!base)) + return; + + WARN_ON(context_ape_notifier_register(&dma_context_notifier)); +} +#else +static void dma_context_notifier_init(void) +{ +} +#endif + +static struct platform_device dma40_device = { + .dev = { + .platform_data = &dma40_plat_data, +#ifdef CONFIG_PM + .pm_domain = &ux500_dev_power_domain, +#endif + }, + .name = "dma40", + .id = 0, + .num_resources = ARRAY_SIZE(dma40_resources), + .resource = dma40_resources +}; + +void __init db8500_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); + + dma_context_notifier_init(); +} diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h index 8e714bcb099..187163bd63d 100644 --- a/arch/arm/mach-ux500/include/mach/db5500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h @@ -34,6 +34,7 @@ #define U5500_ICN_BASE 0xA0040000 #define U5500_B2R2_BASE 0xa0200000 #define U5500_BOOT_ROM_BASE 0x90000000 +#define U5500_ASIC_ID_ADDRESS (U5500_BOOT_ROM_BASE + 0x1FFF4) #define U5500_FSMC_BASE (U5500_PER1_BASE + 0x0000) #define U5500_SDI0_BASE (U5500_PER1_BASE + 0x1000) diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index 5f6cb71fc62..2392b06f91f 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -13,9 +13,25 @@ struct amba_device; extern struct platform_device u5500_gpio_devs[]; extern struct platform_device u8500_gpio_devs[]; +extern struct platform_device u8500_mcde_device; +extern struct platform_device u5500_mcde_device; +extern struct platform_device u8500_shrm_device; +extern struct platform_device u8500_b2r2_device; +extern struct platform_device u5500_b2r2_device; +extern struct platform_device u8500_trace_modem; +extern struct platform_device ux500_hwmem_device; +extern struct platform_device u8500_stm_device; extern struct amba_device ux500_pl031_device; - -extern struct platform_device u8500_dma40_device; +extern struct platform_device ux500_hash1_device; +extern struct platform_device ux500_cryp1_device; +extern struct platform_device mloader_fw_device; +extern struct platform_device u5500_thsens_device; +extern struct platform_device u8500_thsens_device; extern struct platform_device ux500_ske_keypad_device; +extern struct platform_device u8500_wdt_device; +extern struct platform_device u5500_wdt_device; +extern struct platform_device u8500_hsi_device; +extern struct platform_device ux500_mmio_device; +extern struct platform_device u5500_mmio_device; #endif diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index b6ba26a1367..552f32c103a 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -24,12 +24,29 @@ /* typesafe io address */ #define __io_address(n) __io(IO_ADDRESS(n)) -/* Used by some plat-nomadik code */ -#define io_p2v(n) __io_address(n) #include <mach/db8500-regs.h> #include <mach/db5500-regs.h> +/* + * FIFO offsets for IPs + */ +#define MSP_TX_RX_REG_OFFSET (0) +#define HASH1_TX_REG_OFFSET (0x4) +#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 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 + #ifndef __ASSEMBLY__ #include <mach/id.h> diff --git a/arch/arm/mach-ux500/include/mach/id.h b/arch/arm/mach-ux500/include/mach/id.h index 833d6a6edc9..e888929d43d 100644 --- a/arch/arm/mach-ux500/include/mach/id.h +++ b/arch/arm/mach-ux500/include/mach/id.h @@ -38,14 +38,41 @@ static inline unsigned int __attribute_const__ dbx500_revision(void) static inline bool __attribute_const__ cpu_is_u8500(void) { - return dbx500_partnumber() == 0x8500; +#ifdef CONFIG_UX500_SOC_DB8500 + /* partnumber 8520 also comes under 8500 */ + return ((dbx500_partnumber() >> 8) & 0xff) == 0x85; +#else + return false; +#endif +} + +static inline bool __attribute_const__ cpu_is_u8520(void) +{ +#ifdef CONFIG_UX500_SOC_DB8500 + return dbx500_partnumber() == 0x8520; +#else + return false; +#endif } static inline bool __attribute_const__ cpu_is_u5500(void) { +#ifdef CONFIG_UX500_SOC_DB5500 return dbx500_partnumber() == 0x5500; +#else + return false; +#endif } +#ifdef CONFIG_UX500_SOC_DB8500 +inline bool cpu_is_u9500(void); +#else +static inline bool cpu_is_u9500(void) +{ + return false; +} +#endif + /* * 5500 revisions */ @@ -74,26 +101,6 @@ static inline bool __attribute_const__ cpu_is_u5500v21(void) * 8500 revisions */ -static inline bool __attribute_const__ cpu_is_u8500ed(void) -{ - return cpu_is_u8500() && dbx500_revision() == 0x00; -} - -static inline bool __attribute_const__ cpu_is_u8500v1(void) -{ - return cpu_is_u8500() && (dbx500_revision() & 0xf0) == 0xA0; -} - -static inline bool __attribute_const__ cpu_is_u8500v10(void) -{ - return cpu_is_u8500() && dbx500_revision() == 0xA0; -} - -static inline bool __attribute_const__ cpu_is_u8500v11(void) -{ - return cpu_is_u8500() && dbx500_revision() == 0xA1; -} - static inline bool __attribute_const__ cpu_is_u8500v2(void) { return cpu_is_u8500() && ((dbx500_revision() & 0xf0) == 0xB0); @@ -109,9 +116,14 @@ static inline bool cpu_is_u8500v21(void) return cpu_is_u8500() && (dbx500_revision() == 0xB1); } +static inline bool cpu_is_u8500v22(void) +{ + return cpu_is_u8500() && (dbx500_revision() == 0xB2); +} + static inline bool cpu_is_u8500v20_or_later(void) { - return cpu_is_u8500() && !cpu_is_u8500v10() && !cpu_is_u8500v11(); + return cpu_is_u8500() && ((dbx500_revision() & 0xf0) >= 0xB0); } static inline bool ux500_is_svp(void) diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h index d2d4131435a..7c96540878b 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h @@ -43,6 +43,8 @@ #define MOP500_AB8500_VIR_GPIO_IRQ_BASE \ MOP500_STMPE1601_IRQ_END +#define MOP500_AB8500_VIR_GPIO_IRQ(x) \ + (MOP500_AB8500_VIR_GPIO_IRQ_BASE + (x)) #define MOP500_AB8500_VIR_GPIO_IRQ_END \ (MOP500_AB8500_VIR_GPIO_IRQ_BASE + AB8500_VIR_GPIO_NR_IRQS) @@ -57,7 +59,7 @@ */ #if MOP500_IRQ_END > IRQ_BOARD_END #undef IRQ_BOARD_END -#define IRQ_BOARD_END MOP500_IRQ_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 index 29d972c7717..2294a47b3a2 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-u5500.h @@ -7,13 +7,20 @@ #ifndef __MACH_IRQS_BOARD_U5500_H #define __MACH_IRQS_BOARD_U5500_H -#define AB5500_NR_IRQS 5 +#include <linux/mfd/abx500/ab5500.h> + +#define AB5500_NR_IRQS (AB5500_NUM_IRQ_REGS * 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 +/* + * We may have several boards, but only one will run at a + * time, so the one with most IRQs will bump this ahead, + * but the IRQ_BOARD_START remains the same for either board. + */ +#if U5500_IRQ_END > IRQ_BOARD_END #undef IRQ_BOARD_END #define IRQ_BOARD_END U5500_IRQ_END #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs-db5500.h b/arch/arm/mach-ux500/include/mach/irqs-db5500.h index 77239776a6f..234cf4ac4e1 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-db5500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-db5500.h @@ -85,6 +85,37 @@ #ifdef CONFIG_UX500_SOC_DB5500 +/* Virtual interrupts corresponding to the PRCMU wakeups. */ +#define IRQ_DB5500_PRCMU_BASE IRQ_SOC_START + +#define IRQ_DB5500_PRCMU_RTC (IRQ_DB5500_PRCMU_BASE) +#define IRQ_DB5500_PRCMU_RTT0 (IRQ_DB5500_PRCMU_BASE + 1) +#define IRQ_DB5500_PRCMU_RTT1 (IRQ_DB5500_PRCMU_BASE + 2) +#define IRQ_DB5500_PRCMU_CD_IRQ (IRQ_DB5500_PRCMU_BASE + 3) +#define IRQ_DB5500_PRCMU_SRP_TIM (IRQ_DB5500_PRCMU_BASE + 4) +#define IRQ_DB5500_PRCMU_APE_REQ (IRQ_DB5500_PRCMU_BASE + 5) +#define IRQ_DB5500_PRCMU_USB (IRQ_DB5500_PRCMU_BASE + 6) +#define IRQ_DB5500_PRCMU_ABB (IRQ_DB5500_PRCMU_BASE + 7) +#define IRQ_DB5500_PRCMU_ARM (IRQ_DB5500_PRCMU_BASE + 8) +#define IRQ_DB5500_PRCMU_MODEM_SW_RESET_REQ (IRQ_DB5500_PRCMU_BASE + 9) +#define IRQ_DB5500_PRCMU_AC_WAKE_ACK (IRQ_DB5500_PRCMU_BASE + 10) +#define IRQ_DB5500_PRCMU_GPIO0 (IRQ_DB5500_PRCMU_BASE + 11) +#define IRQ_DB5500_PRCMU_GPIO1 (IRQ_DB5500_PRCMU_BASE + 12) +#define IRQ_DB5500_PRCMU_GPIO2 (IRQ_DB5500_PRCMU_BASE + 13) +#define IRQ_DB5500_PRCMU_GPIO3 (IRQ_DB5500_PRCMU_BASE + 14) +#define IRQ_DB5500_PRCMU_GPIO4 (IRQ_DB5500_PRCMU_BASE + 15) +#define IRQ_DB5500_PRCMU_GPIO5 (IRQ_DB5500_PRCMU_BASE + 16) +#define IRQ_DB5500_PRCMU_GPIO6 (IRQ_DB5500_PRCMU_BASE + 17) +#define IRQ_DB5500_PRCMU_GPIO7 (IRQ_DB5500_PRCMU_BASE + 18) +#define IRQ_DB5500_PRCMU_AC_REL_ACK (IRQ_DB5500_PRCMU_BASE + 19) +#define IRQ_DB5500_PRCMU_LOW_POWER_AUDIO (IRQ_DB5500_PRCMU_BASE + 20) +#define IRQ_DB5500_PRCMU_TEMP_SENSOR_LOW (IRQ_DB5500_PRCMU_BASE + 21) +#define IRQ_DB5500_PRCMU_TEMP_SENSOR_HIGH (IRQ_DB5500_PRCMU_BASE + 22) +#define IRQ_DB5500_PRCMU_END (IRQ_DB5500_PRCMU_BASE + 23) +#define IRQ_DB5500_PRCMU_APE_REL 0x200 + +#define NUM_DB5500_PRCMU_WAKEUPS (IRQ_DB5500_PRCMU_END - IRQ_DB5500_PRCMU_BASE) + /* * After the GPIO ones we reserve a range of IRQ:s in which virtual * IRQ:s representing modem IRQ:s can be allocated diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 9db68d264c5..a2876464d43 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -11,9 +11,7 @@ #define ASM_ARCH_IRQS_H #include <mach/hardware.h> - -#define IRQ_LOCALTIMER 29 -#define IRQ_LOCALWDOG 30 +#include <linux/gpio.h> /* Shared Peripheral Interrupt (SHPI) */ #define IRQ_SHPI_START 32 @@ -22,27 +20,34 @@ * 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 IRQ_MTU0 (IRQ_SHPI_START + 4) +#define IRQ_MTU0 (IRQ_SHPI_START + 4) + +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 + +/*********************************************************************/ #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) + DBX500_NR_INTERNAL_IRQS) #define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - DBX500_NR_INTERNAL_IRQS) + +#define GPIO_TO_IRQ NOMADIK_GPIO_TO_IRQ +#define IRQ_TO_GPIO NOMADIK_IRQ_TO_GPIO #define IRQ_GPIO_END NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) -#define IRQ_SOC_START IRQ_GPIO_END +#define IRQ_SOC_START IRQ_GPIO_END /* This will be overridden by SoC-specific irq headers */ -#define IRQ_SOC_END IRQ_SOC_START +#define IRQ_SOC_END IRQ_SOC_START + +#define IRQ_BOARD_START IRQ_SOC_END +/* This will be overridden by board-specific irq headers */ +#define IRQ_BOARD_END IRQ_BOARD_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 - #ifdef CONFIG_MACH_U8500 #include <mach/irqs-board-mop500.h> #endif @@ -51,6 +56,8 @@ #include <mach/irqs-board-u5500.h> #endif +#ifndef NR_IRQS #define NR_IRQS IRQ_BOARD_END +#endif #endif /* ASM_ARCH_IRQS_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..4471c3c1f33 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/reboot_reasons.h @@ -0,0 +1,48 @@ +/* + * 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, or at a later stage userspace + * since the code is exposed through sysfs. + */ + +#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 exposed through a sysfs + * entry under /sys/socinfo, see mach-ux500/cpu-db8500.c + */ +#define SW_RESET_NO_ARGUMENT 0xBEEF +#define SW_RESET_FACTORY_RESET 0x4242 +#define SW_RESET_CRASH 0xDEAD +#define SW_RESET_NORMAL 0xc001 +#define SW_RESET_CHARGING 0xCAFE +#define SW_RESET_COLDSTART 0x0 +#define SW_RESET_RECOVERY 0x5502 +#define SW_RESET_CHGONLY_EXIT 0xCAFF + +/* + * The array reboot_reasons[] is used when you want to map a string to a reboot + * reason code + */ +struct reboot_reason { + const char *reason; + u16 code; +}; + +extern struct reboot_reason reboot_reasons[]; + +extern unsigned int reboot_reasons_size; + +u16 reboot_reason_code(const char *cmd); +const char *reboot_reason_string(u16 code); + +#endif diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index a7d363fdb4c..51a7287072f 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -14,6 +14,8 @@ #include <asm/mach/time.h> #include <linux/init.h> +extern void ux500_restart(char, const char *); + void __init ux500_map_io(void); extern void __init u5500_map_io(void); extern void __init u8500_map_io(void); @@ -26,6 +28,7 @@ extern void __init ux500_init_irq(void); extern void __init u5500_sdi_init(void); extern void __init db5500_dma_init(void); +extern void __init db8500_dma_init(void); /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); diff --git a/arch/arm/mach-ux500/ste-dma40-db5500.h b/arch/arm/mach-ux500/include/mach/ste-dma40-db5500.h index cb2110c3285..0ddd4ab9020 100644 --- a/arch/arm/mach-ux500/ste-dma40-db5500.h +++ b/arch/arm/mach-ux500/include/mach/ste-dma40-db5500.h @@ -42,7 +42,9 @@ enum dma_src_dev_type { DB5500_DMA_DEV26_SDMMC2_RX = 26, DB5500_DMA_DEV27_SDMMC3_RX = 27, DB5500_DMA_DEV28_SDMMC4_RX = 28, - /* 29 - 32 not used */ + /* 29, 30 not used */ + DB5500_DMA_DEV31_CRYPTO1_RX = 31, /* v2 */ + /* 32 not used */ DB5500_DMA_DEV33_SDMMC0_RX = 33, DB5500_DMA_DEV34_SDMMC1_RX = 34, DB5500_DMA_DEV35_SDMMC2_RX = 35, @@ -56,7 +58,7 @@ enum dma_src_dev_type { 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_DEV46_CRYPTO1_RX = 46, /* v2 */ DB5500_DMA_DEV47_MCDE_RX = 47, DB5500_DMA_DEV48_CRYPTO1_RX = 48, /* 49, 50 not used */ @@ -98,7 +100,9 @@ enum dma_dest_dev_type { DB5500_DMA_DEV26_SDMMC2_TX = 26, DB5500_DMA_DEV27_SDMMC3_TX = 27, DB5500_DMA_DEV28_SDMMC4_TX = 28, - /* 29 - 31 not used */ + /* 29 not used */ + DB5500_DMA_DEV30_HASH1_TX = 30, /* v2 */ + DB5500_DMA_DEV31_CRYPTO1_TX = 31, /* v2 */ DB5500_DMA_DEV32_FSMC_TX = 32, DB5500_DMA_DEV33_SDMMC0_TX = 33, DB5500_DMA_DEV34_SDMMC1_TX = 34, @@ -113,7 +117,7 @@ enum dma_dest_dev_type { 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_DEV46_CRYPTO1_TX = 46, /* v2 */ DB5500_DMA_DEV47_STM_TX = 47, DB5500_DMA_DEV48_CRYPTO1_TX = 48, DB5500_DMA_DEV49_CRYPTO1_TX_HASH1_TX = 49, diff --git a/arch/arm/mach-ux500/ste-dma40-db8500.h b/arch/arm/mach-ux500/include/mach/ste-dma40-db8500.h index a616419bea7..65799a75199 100644 --- a/arch/arm/mach-ux500/ste-dma40-db8500.h +++ b/arch/arm/mach-ux500/include/mach/ste-dma40-db8500.h @@ -1,16 +1,19 @@ /* - * arch/arm/mach-ux500/ste_dma40_db8500.h - * DB8500-SoC-specific configuration for DMA40 - * - * Copyright (C) ST-Ericsson 2007-2010 + * 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 - * Author: Per Friden <per.friden@stericsson.com> - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> + * + * 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, @@ -20,7 +23,7 @@ enum dma_src_dev_type { 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_DEV7_I2C4_RX = 7, DB8500_DMA_DEV8_SSP0_RX = 8, DB8500_DMA_DEV9_SSP1_RX = 9, DB8500_DMA_DEV10_MCDE_RX = 10, @@ -43,8 +46,6 @@ enum dma_src_dev_type { 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, @@ -82,7 +83,7 @@ enum dma_dest_dev_type { 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_DEV7_I2C4_TX = 7, DB8500_DMA_DEV8_SSP0_TX = 8, DB8500_DMA_DEV9_SSP1_TX = 9, /* 10 is not used*/ diff --git a/arch/arm/mach-ux500/include/mach/timex.h b/arch/arm/mach-ux500/include/mach/timex.h index d0942c17401..0ba497bd9d7 100644 --- a/arch/arm/mach-ux500/include/mach/timex.h +++ b/arch/arm/mach-ux500/include/mach/timex.h @@ -2,5 +2,6 @@ #define __ASM_ARCH_TIMEX_H #define CLOCK_TICK_RATE 110000000 +#define ARCH_HAS_READ_CURRENT_TIMER #endif diff --git a/arch/arm/mach-ux500/l2x0-prefetch.c b/arch/arm/mach-ux500/l2x0-prefetch.c new file mode 100644 index 00000000000..48a4495533f --- /dev/null +++ b/arch/arm/mach-ux500/l2x0-prefetch.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> + * License terms: GNU General Public License (GPL) version 2 + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/tee.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/hardware/cache-l2x0.h> + +static struct tee_session session; +static struct tee_context context; +static void __iomem *l2x0_base; + +#define L2X0_PREFETCH_CTRL_REG (0x00000F60) +#define L2X0_PREFETCH_CTRL_BIT_DATA_EN (1 << 28) +#define L2X0_PREFETCH_CTRL_BIT_INST_EN (1 << 29) + +#define L2X0_UUID_TEE_TA_START_LOW 0xBC765EDE +#define L2X0_UUID_TEE_TA_START_MID 0x6724 +#define L2X0_UUID_TEE_TA_START_HIGH 0x11DF +#define L2X0_UUID_TEE_TA_START_CLOCKSEQ \ + {0x8E, 0x12, 0xEC, 0xDB, 0xDF, 0xD7, 0x20, 0x85} + +static void prefetch_enable(void) +{ + struct tee_operation operation; + u32 data; + int err; + int origin_err; + + data = readl(l2x0_base + L2X0_PREFETCH_CTRL_REG); + + pr_debug("l2x0-prefetch: %s start, preftect_ctrl=0x%08x\n", __func__, + data); + if (!(data & L2X0_PREFETCH_CTRL_BIT_INST_EN) || + !(data & L2X0_PREFETCH_CTRL_BIT_DATA_EN)) { + + data |= (L2X0_PREFETCH_CTRL_BIT_INST_EN | + L2X0_PREFETCH_CTRL_BIT_DATA_EN); + + operation.shm[0].buffer = &data; + operation.shm[0].size = sizeof(data); + operation.shm[0].flags = TEEC_MEM_INPUT; + operation.flags = TEEC_MEMREF_0_USED; + + err = teec_invoke_command(&session, + TEE_STA_SET_L2CC_PREFETCH_CTRL_REGISTER, + &operation, &origin_err); + if (err) + pr_err("l2x0-prefetch: prefetch enable failed, err=%d", + err); + } + pr_debug("l2x0-prefetch: %s end, prefetch_ctrl=0x%08x\n", __func__, + readl(l2x0_base + L2X0_PREFETCH_CTRL_REG)); +} + +static void prefetch_disable(void) +{ + struct tee_operation operation; + u32 data; + int err; + int origin_err; + + data = readl(l2x0_base + L2X0_PREFETCH_CTRL_REG); + + pr_debug("l2x0-prefetch: %s start, preftect_ctrl=0x%08x\n", __func__, + data); + if (data & (L2X0_PREFETCH_CTRL_BIT_INST_EN | + L2X0_PREFETCH_CTRL_BIT_DATA_EN)) { + + data &= ~(L2X0_PREFETCH_CTRL_BIT_INST_EN | + L2X0_PREFETCH_CTRL_BIT_DATA_EN); + + operation.shm[0].buffer = &data; + operation.shm[0].size = sizeof(data); + operation.shm[0].flags = TEEC_MEM_INPUT; + operation.flags = TEEC_MEMREF_0_USED; + + err = teec_invoke_command(&session, + TEE_STA_SET_L2CC_PREFETCH_CTRL_REGISTER, + &operation, &origin_err); + if (err) + pr_err("l2x0-prefetch: prefetch disable failed, err=%d", + err); + } + pr_debug("l2x0-prefetch: %s end, prefetch_ctrl=0x%08x\n", __func__, + readl(l2x0_base + L2X0_PREFETCH_CTRL_REG)); +} + +static int __init prefetch_ctrl_init(void) +{ + int err; + int origin_err; + /* Selects trustzone application needed for the job. */ + struct tee_uuid static_uuid = { + L2X0_UUID_TEE_TA_START_LOW, + L2X0_UUID_TEE_TA_START_MID, + L2X0_UUID_TEE_TA_START_HIGH, + L2X0_UUID_TEE_TA_START_CLOCKSEQ, + }; + + /* Get PL310 base address. It will be used as readonly. */ + if (cpu_is_u5500()) + l2x0_base = __io_address(U5500_L2CC_BASE); + else if (cpu_is_u8500()) + l2x0_base = __io_address(U8500_L2CC_BASE); + else + ux500_unknown_soc(); + + err = teec_initialize_context(NULL, &context); + if (err) { + pr_err("l2x0-prefetch: unable to initialize tee context," + " err = %d\n", err); + err = -EINVAL; + goto error0; + } + + err = teec_open_session(&context, &session, &static_uuid, + TEEC_LOGIN_PUBLIC, NULL, NULL, &origin_err); + if (err) { + pr_err("l2x0-prefetch: unable to open tee session," + " tee error = %d, origin error = %d\n", + err, origin_err); + err = -EINVAL; + goto error1; + } + + outer_cache.prefetch_enable = prefetch_enable; + outer_cache.prefetch_disable = prefetch_disable; + + pr_info("l2x0-prefetch: initialized.\n"); + + return 0; + +error1: + (void)teec_finalize_context(&context); +error0: + return err; +} + +static void __exit prefetch_ctrl_exit(void) +{ + outer_cache.prefetch_enable = NULL; + outer_cache.prefetch_disable = NULL; + + (void)teec_close_session(&session); + (void)teec_finalize_context(&context); +} + +/* Wait for TEE driver to be initialized. */ +late_initcall(prefetch_ctrl_init); +module_exit(prefetch_ctrl_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("PL310 prefetch control"); diff --git a/arch/arm/mach-ux500/mbox-db5500.c b/arch/arm/mach-ux500/mbox-db5500.c deleted file mode 100644 index 2b2d51caf9d..00000000000 --- a/arch/arm/mach-ux500/mbox-db5500.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * 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. - */ - -/* - * Mailbox nomenclature: - * - * APE MODEM - * mbox pairX - * .......................... - * . . - * . peer . - * . send ---- . - * . --> | | . - * . | | . - * . ---- . - * . . - * . local . - * . rec ---- . - * . | | <-- . - * . | | . - * . ---- . - * ......................... - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/errno.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/platform_device.h> -#include <linux/debugfs.h> -#include <linux/seq_file.h> -#include <linux/completion.h> -#include <mach/mbox-db5500.h> - -#define MBOX_NAME "mbox" - -#define MBOX_FIFO_DATA 0x000 -#define MBOX_FIFO_ADD 0x004 -#define MBOX_FIFO_REMOVE 0x008 -#define MBOX_FIFO_THRES_FREE 0x00C -#define MBOX_FIFO_THRES_OCCUP 0x010 -#define MBOX_FIFO_STATUS 0x014 - -#define MBOX_DISABLE_IRQ 0x4 -#define MBOX_ENABLE_IRQ 0x0 -#define MBOX_LATCH 1 - -/* Global list of all mailboxes */ -static struct list_head mboxs = LIST_HEAD_INIT(mboxs); - -static struct mbox *get_mbox_with_id(u8 id) -{ - u8 i; - struct list_head *pos = &mboxs; - for (i = 0; i <= id; i++) - pos = pos->next; - - return (struct mbox *) list_entry(pos, struct mbox, list); -} - -int mbox_send(struct mbox *mbox, u32 mbox_msg, bool block) -{ - int res = 0; - - spin_lock(&mbox->lock); - - dev_dbg(&(mbox->pdev->dev), - "About to buffer 0x%X to mailbox 0x%X." - " ri = %d, wi = %d\n", - mbox_msg, (u32)mbox, mbox->read_index, - mbox->write_index); - - /* Check if write buffer is full */ - while (((mbox->write_index + 1) % MBOX_BUF_SIZE) == mbox->read_index) { - if (!block) { - dev_dbg(&(mbox->pdev->dev), - "Buffer full in non-blocking call! " - "Returning -ENOMEM!\n"); - res = -ENOMEM; - goto exit; - } - spin_unlock(&mbox->lock); - dev_dbg(&(mbox->pdev->dev), - "Buffer full in blocking call! Sleeping...\n"); - mbox->client_blocked = 1; - wait_for_completion(&mbox->buffer_available); - dev_dbg(&(mbox->pdev->dev), - "Blocking send was woken up! Trying again...\n"); - spin_lock(&mbox->lock); - } - - mbox->buffer[mbox->write_index] = mbox_msg; - mbox->write_index = (mbox->write_index + 1) % MBOX_BUF_SIZE; - - /* - * Indicate that we want an IRQ as soon as there is a slot - * in the FIFO - */ - writel(MBOX_ENABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); - -exit: - spin_unlock(&mbox->lock); - return res; -} -EXPORT_SYMBOL(mbox_send); - -#if defined(CONFIG_DEBUG_FS) -/* - * Expected input: <value> <nbr sends> - * Example: "echo 0xdeadbeef 4 > mbox-node" sends 0xdeadbeef 4 times - */ -static ssize_t mbox_write_fifo(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - unsigned long mbox_mess; - unsigned long nbr_sends; - unsigned long i; - char int_buf[16]; - char *token; - char *val; - - struct mbox *mbox = (struct mbox *) dev->platform_data; - - strncpy((char *) &int_buf, buf, sizeof(int_buf)); - token = (char *) &int_buf; - - /* Parse message */ - val = strsep(&token, " "); - if ((val == NULL) || (strict_strtoul(val, 16, &mbox_mess) != 0)) - mbox_mess = 0xDEADBEEF; - - val = strsep(&token, " "); - if ((val == NULL) || (strict_strtoul(val, 10, &nbr_sends) != 0)) - nbr_sends = 1; - - dev_dbg(dev, "Will write 0x%lX %ld times using data struct at 0x%X\n", - mbox_mess, nbr_sends, (u32) mbox); - - for (i = 0; i < nbr_sends; i++) - mbox_send(mbox, mbox_mess, true); - - return count; -} - -static ssize_t mbox_read_fifo(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int mbox_value; - struct mbox *mbox = (struct mbox *) dev->platform_data; - - if ((readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7) <= 0) - return sprintf(buf, "Mailbox is empty\n"); - - mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA); - writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE)); - - return sprintf(buf, "0x%X\n", mbox_value); -} - -static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo); - -static int mbox_show(struct seq_file *s, void *data) -{ - struct list_head *pos; - u8 mbox_index = 0; - - list_for_each(pos, &mboxs) { - struct mbox *m = - (struct mbox *) list_entry(pos, struct mbox, list); - if (m == NULL) { - seq_printf(s, - "Unable to retrieve mailbox %d\n", - mbox_index); - continue; - } - - spin_lock(&m->lock); - if ((m->virtbase_peer == NULL) || (m->virtbase_local == NULL)) { - seq_printf(s, "MAILBOX %d not setup or corrupt\n", - mbox_index); - spin_unlock(&m->lock); - continue; - } - - seq_printf(s, - "===========================\n" - " MAILBOX %d\n" - " PEER MAILBOX DUMP\n" - "---------------------------\n" - "FIFO: 0x%X (%d)\n" - "Free Threshold: 0x%.2X (%d)\n" - "Occupied Threshold: 0x%.2X (%d)\n" - "Status: 0x%.2X (%d)\n" - " Free spaces (ot): %d (%d)\n" - " Occup spaces (ot): %d (%d)\n" - "===========================\n" - " LOCAL MAILBOX DUMP\n" - "---------------------------\n" - "FIFO: 0x%.X (%d)\n" - "Free Threshold: 0x%.2X (%d)\n" - "Occupied Threshold: 0x%.2X (%d)\n" - "Status: 0x%.2X (%d)\n" - " Free spaces (ot): %d (%d)\n" - " Occup spaces (ot): %d (%d)\n" - "===========================\n" - "write_index: %d\n" - "read_index : %d\n" - "===========================\n" - "\n", - mbox_index, - readl(m->virtbase_peer + MBOX_FIFO_DATA), - readl(m->virtbase_peer + MBOX_FIFO_DATA), - readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE), - readl(m->virtbase_peer + MBOX_FIFO_THRES_FREE), - readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP), - readl(m->virtbase_peer + MBOX_FIFO_THRES_OCCUP), - readl(m->virtbase_peer + MBOX_FIFO_STATUS), - readl(m->virtbase_peer + MBOX_FIFO_STATUS), - (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 4) & 0x7, - (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 7) & 0x1, - (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 0) & 0x7, - (readl(m->virtbase_peer + MBOX_FIFO_STATUS) >> 3) & 0x1, - readl(m->virtbase_local + MBOX_FIFO_DATA), - readl(m->virtbase_local + MBOX_FIFO_DATA), - readl(m->virtbase_local + MBOX_FIFO_THRES_FREE), - readl(m->virtbase_local + MBOX_FIFO_THRES_FREE), - readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP), - readl(m->virtbase_local + MBOX_FIFO_THRES_OCCUP), - readl(m->virtbase_local + MBOX_FIFO_STATUS), - readl(m->virtbase_local + MBOX_FIFO_STATUS), - (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 4) & 0x7, - (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 7) & 0x1, - (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 0) & 0x7, - (readl(m->virtbase_local + MBOX_FIFO_STATUS) >> 3) & 0x1, - m->write_index, m->read_index); - mbox_index++; - spin_unlock(&m->lock); - } - - return 0; -} - -static int mbox_open(struct inode *inode, struct file *file) -{ - return single_open(file, mbox_show, NULL); -} - -static const struct file_operations mbox_operations = { - .owner = THIS_MODULE, - .open = mbox_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -static irqreturn_t mbox_irq(int irq, void *arg) -{ - u32 mbox_value; - int nbr_occup; - int nbr_free; - struct mbox *mbox = (struct mbox *) arg; - - spin_lock(&mbox->lock); - - dev_dbg(&(mbox->pdev->dev), - "mbox IRQ [%d] received. ri = %d, wi = %d\n", - irq, mbox->read_index, mbox->write_index); - - /* - * Check if we have any outgoing messages, and if there is space for - * them in the FIFO. - */ - if (mbox->read_index != mbox->write_index) { - /* - * Check by reading FREE for LOCAL since that indicates - * OCCUP for PEER - */ - nbr_free = (readl(mbox->virtbase_local + MBOX_FIFO_STATUS) - >> 4) & 0x7; - dev_dbg(&(mbox->pdev->dev), - "Status indicates %d empty spaces in the FIFO!\n", - nbr_free); - - while ((nbr_free > 0) && - (mbox->read_index != mbox->write_index)) { - /* Write the message and latch it into the FIFO */ - writel(mbox->buffer[mbox->read_index], - (mbox->virtbase_peer + MBOX_FIFO_DATA)); - writel(MBOX_LATCH, - (mbox->virtbase_peer + MBOX_FIFO_ADD)); - dev_dbg(&(mbox->pdev->dev), - "Wrote message 0x%X to addr 0x%X\n", - mbox->buffer[mbox->read_index], - (u32) (mbox->virtbase_peer + MBOX_FIFO_DATA)); - - nbr_free--; - mbox->read_index = - (mbox->read_index + 1) % MBOX_BUF_SIZE; - } - - /* - * Check if we still want IRQ:s when there is free - * space to send - */ - if (mbox->read_index != mbox->write_index) { - dev_dbg(&(mbox->pdev->dev), - "Still have messages to send, but FIFO full. " - "Request IRQ again!\n"); - writel(MBOX_ENABLE_IRQ, - mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); - } else { - dev_dbg(&(mbox->pdev->dev), - "No more messages to send. " - "Do not request IRQ again!\n"); - writel(MBOX_DISABLE_IRQ, - mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); - } - - /* - * Check if we can signal any blocked clients that it is OK to - * start buffering again - */ - if (mbox->client_blocked && - (((mbox->write_index + 1) % MBOX_BUF_SIZE) - != mbox->read_index)) { - dev_dbg(&(mbox->pdev->dev), - "Waking up blocked client\n"); - complete(&mbox->buffer_available); - mbox->client_blocked = 0; - } - } - - /* Check if we have any incoming messages */ - nbr_occup = readl(mbox->virtbase_local + MBOX_FIFO_STATUS) & 0x7; - if (nbr_occup == 0) - goto exit; - - if (mbox->cb == NULL) { - dev_dbg(&(mbox->pdev->dev), "No receive callback registered, " - "leaving %d incoming messages in fifo!\n", nbr_occup); - goto exit; - } - - /* Read and acknowledge the message */ - mbox_value = readl(mbox->virtbase_local + MBOX_FIFO_DATA); - writel(MBOX_LATCH, (mbox->virtbase_local + MBOX_FIFO_REMOVE)); - - /* Notify consumer of new mailbox message */ - dev_dbg(&(mbox->pdev->dev), "Calling callback for message 0x%X!\n", - mbox_value); - mbox->cb(mbox_value, mbox->client_data); - -exit: - dev_dbg(&(mbox->pdev->dev), "Exit mbox IRQ. ri = %d, wi = %d\n", - mbox->read_index, mbox->write_index); - spin_unlock(&mbox->lock); - - return IRQ_HANDLED; -} - -/* Setup is executed once for each mbox pair */ -struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv) -{ - struct resource *resource; - int irq; - int res; - struct mbox *mbox; - - mbox = get_mbox_with_id(mbox_id); - if (mbox == NULL) { - dev_err(&(mbox->pdev->dev), "Incorrect mailbox id: %d!\n", - mbox_id); - goto exit; - } - - /* - * Check if mailbox has been allocated to someone else, - * otherwise allocate it - */ - if (mbox->allocated) { - dev_err(&(mbox->pdev->dev), "Mailbox number %d is busy!\n", - mbox_id); - mbox = NULL; - goto exit; - } - mbox->allocated = true; - - dev_dbg(&(mbox->pdev->dev), "Initiating mailbox number %d: 0x%X...\n", - mbox_id, (u32)mbox); - - mbox->client_data = priv; - mbox->cb = mbox_cb; - - /* Get addr for peer mailbox and ioremap it */ - resource = platform_get_resource_byname(mbox->pdev, - IORESOURCE_MEM, - "mbox_peer"); - if (resource == NULL) { - dev_err(&(mbox->pdev->dev), - "Unable to retrieve mbox peer resource\n"); - mbox = NULL; - goto exit; - } - dev_dbg(&(mbox->pdev->dev), - "Resource name: %s start: 0x%X, end: 0x%X\n", - resource->name, resource->start, resource->end); - mbox->virtbase_peer = ioremap(resource->start, resource_size(resource)); - if (!mbox->virtbase_peer) { - dev_err(&(mbox->pdev->dev), "Unable to ioremap peer mbox\n"); - mbox = NULL; - goto exit; - } - dev_dbg(&(mbox->pdev->dev), - "ioremapped peer physical: (0x%X-0x%X) to virtual: 0x%X\n", - resource->start, resource->end, (u32) mbox->virtbase_peer); - - /* Get addr for local mailbox and ioremap it */ - resource = platform_get_resource_byname(mbox->pdev, - IORESOURCE_MEM, - "mbox_local"); - if (resource == NULL) { - dev_err(&(mbox->pdev->dev), - "Unable to retrieve mbox local resource\n"); - mbox = NULL; - goto exit; - } - dev_dbg(&(mbox->pdev->dev), - "Resource name: %s start: 0x%X, end: 0x%X\n", - resource->name, resource->start, resource->end); - mbox->virtbase_local = ioremap(resource->start, resource_size(resource)); - if (!mbox->virtbase_local) { - dev_err(&(mbox->pdev->dev), "Unable to ioremap local mbox\n"); - mbox = NULL; - goto exit; - } - dev_dbg(&(mbox->pdev->dev), - "ioremapped local physical: (0x%X-0x%X) to virtual: 0x%X\n", - resource->start, resource->end, (u32) mbox->virtbase_peer); - - init_completion(&mbox->buffer_available); - mbox->client_blocked = 0; - - /* Get IRQ for mailbox and allocate it */ - irq = platform_get_irq_byname(mbox->pdev, "mbox_irq"); - if (irq < 0) { - dev_err(&(mbox->pdev->dev), - "Unable to retrieve mbox irq resource\n"); - mbox = NULL; - goto exit; - } - - dev_dbg(&(mbox->pdev->dev), "Allocating irq %d...\n", irq); - res = request_irq(irq, mbox_irq, 0, mbox->name, (void *) mbox); - if (res < 0) { - dev_err(&(mbox->pdev->dev), - "Unable to allocate mbox irq %d\n", irq); - mbox = NULL; - goto exit; - } - - /* Set up mailbox to not launch IRQ on free space in mailbox */ - writel(MBOX_DISABLE_IRQ, mbox->virtbase_peer + MBOX_FIFO_THRES_FREE); - - /* - * Set up mailbox to launch IRQ on new message if we have - * a callback set. If not, do not raise IRQ, but keep message - * in FIFO for manual retrieval - */ - if (mbox_cb != NULL) - writel(MBOX_ENABLE_IRQ, - mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP); - else - writel(MBOX_DISABLE_IRQ, - mbox->virtbase_local + MBOX_FIFO_THRES_OCCUP); - -#if defined(CONFIG_DEBUG_FS) - res = device_create_file(&(mbox->pdev->dev), &dev_attr_fifo); - if (res != 0) - dev_warn(&(mbox->pdev->dev), - "Unable to create mbox sysfs entry"); - - (void) debugfs_create_file("mbox", S_IFREG | S_IRUGO, NULL, - NULL, &mbox_operations); -#endif - - dev_info(&(mbox->pdev->dev), - "Mailbox driver with index %d initiated!\n", mbox_id); - -exit: - return mbox; -} -EXPORT_SYMBOL(mbox_setup); - - -int __init mbox_probe(struct platform_device *pdev) -{ - struct mbox local_mbox; - struct mbox *mbox; - int res = 0; - dev_dbg(&(pdev->dev), "Probing mailbox (pdev = 0x%X)...\n", (u32) pdev); - - memset(&local_mbox, 0x0, sizeof(struct mbox)); - - /* Associate our mbox data with the platform device */ - res = platform_device_add_data(pdev, - (void *) &local_mbox, - sizeof(struct mbox)); - if (res != 0) { - dev_err(&(pdev->dev), - "Unable to allocate driver platform data!\n"); - goto exit; - } - - mbox = (struct mbox *) pdev->dev.platform_data; - mbox->pdev = pdev; - mbox->write_index = 0; - mbox->read_index = 0; - - INIT_LIST_HEAD(&(mbox->list)); - list_add_tail(&(mbox->list), &mboxs); - - sprintf(mbox->name, "%s", MBOX_NAME); - spin_lock_init(&mbox->lock); - - dev_info(&(pdev->dev), "Mailbox driver loaded\n"); - -exit: - return res; -} - -static struct platform_driver mbox_driver = { - .driver = { - .name = MBOX_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init mbox_init(void) -{ - return platform_driver_probe(&mbox_driver, mbox_probe); -} - -module_init(mbox_init); - -void __exit mbox_exit(void) -{ - platform_driver_unregister(&mbox_driver); -} - -module_exit(mbox_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MBOX driver"); diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h index 8b1d1a7a679..062c7acf457 100644 --- a/arch/arm/mach-ux500/pins-db8500.h +++ b/arch/arm/mach-ux500/pins-db8500.h @@ -35,40 +35,40 @@ #define GPIO4_GPIO PIN_CFG(4, GPIO) #define GPIO4_U1_RXD PIN_CFG(4, ALT_A) -#define GPIO4_I2C4_SCL PIN_CFG_INPUT(4, ALT_B, PULLUP) +#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_INPUT(5, ALT_B, PULLUP) +#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_INPUT(6, ALT_B, PULLUP) +#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_INPUT(7, ALT_B, PULLUP) +#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_INPUT(8, ALT_A, PULLUP) -#define GPIO8_I2C2_SDA PIN_CFG_INPUT(8, ALT_B, PULLUP) +#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_INPUT(9, ALT_A, PULLUP) -#define GPIO9_I2C2_SCL PIN_CFG_INPUT(9, ALT_B, PULLUP) +#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_INPUT(10, ALT_A, PULLUP) -#define GPIO10_I2C2_SDA PIN_CFG_INPUT(10, ALT_B, PULLUP) +#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_INPUT(11, ALT_A, PULLUP) -#define GPIO11_I2C2_SCL PIN_CFG_INPUT(11, ALT_B, PULLUP) +#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) @@ -87,12 +87,12 @@ #define GPIO16_GPIO PIN_CFG(16, GPIO) #define GPIO16_MSP0_RFS PIN_CFG(16, ALT_A) -#define GPIO16_I2C1_SCL PIN_CFG_INPUT(16, ALT_B, PULLUP) +#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_INPUT(17, ALT_B, PULLUP) +#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) @@ -434,10 +434,10 @@ #define GPIO146_SSP0_TXD PIN_CFG(146, ALT_A) #define GPIO147_GPIO PIN_CFG(147, GPIO) -#define GPIO147_I2C0_SCL PIN_CFG_INPUT(147, ALT_A, PULLUP) +#define GPIO147_I2C0_SCL PIN_CFG(147, ALT_A) #define GPIO148_GPIO PIN_CFG(148, GPIO) -#define GPIO148_I2C0_SDA PIN_CFG_INPUT(148, ALT_A, PULLUP) +#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) @@ -459,82 +459,82 @@ #define GPIO152_KP_O9 PIN_CFG(152, ALT_C) #define GPIO153_GPIO PIN_CFG(153, GPIO) -#define GPIO153_KP_I7 PIN_CFG_INPUT(153, ALT_A, PULLDOWN) +#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_INPUT(154, ALT_A, PULLDOWN) +#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_INPUT(155, ALT_A, PULLDOWN) +#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_INPUT(156, ALT_A, PULLDOWN) +#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_INPUT(157, ALT_A, PULLUP) +#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_INPUT(158, ALT_A, PULLUP) +#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_INPUT(159, ALT_A, PULLUP) +#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_INPUT(160, ALT_A, PULLUP) +#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_INPUT(161, ALT_A, PULLDOWN) +#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_INPUT(162, ALT_A, PULLDOWN) +#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_INPUT(163, ALT_A, PULLDOWN) +#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_INPUT(164, ALT_A, PULLUP) +#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_INPUT(165, ALT_A, PULLUP) +#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_INPUT(166, ALT_A, PULLUP) +#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_INPUT(167, ALT_A, PULLUP) +#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_INPUT(168, ALT_A, PULLUP) +#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) @@ -637,7 +637,7 @@ #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_INPUT(216, ALT_C, PULLUP) +#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) @@ -649,7 +649,7 @@ #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_INPUT(218, ALT_C, PULLUP) +#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) @@ -698,12 +698,12 @@ #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_INPUT(229, ALT_C, PULLUP) +#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_INPUT(230, ALT_C, PULLUP) +#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) diff --git a/arch/arm/mach-ux500/pins.c b/arch/arm/mach-ux500/pins.c new file mode 100644 index 00000000000..ed2ed7333ff --- /dev/null +++ b/arch/arm/mach-ux500/pins.c @@ -0,0 +1,252 @@ +/* + * 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/module.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> +#include <linux/err.h> +#include <plat/pincfg.h> +#include <linux/gpio.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); +} + +void __init ux500_offchip_gpio_init(struct ux500_pins *pins) +{ + int err; + int i; + int gpio; + int output; + int value; + pin_cfg_t cfg; + + for (i = 0; i < pins->num; i++) { + cfg = pins->cfg[i]; + gpio = PIN_NUM(cfg); + output = PIN_DIR(cfg); + value = PIN_VAL(cfg); + + err = gpio_request(gpio, "offchip_gpio_init"); + if (err < 0) { + pr_err("pins: gpio_request for gpio=%d failed with" + "err: %d\n", gpio, err); + /* Pin already requested. Try to configure rest. */ + continue; + } + + if (!output) { + err = gpio_direction_input(gpio); + if (err < 0) + pr_err("pins: gpio_direction_input for gpio=%d" + "failed with err: %d\n", gpio, err); + } else { + err = gpio_direction_output(gpio, value); + if (err < 0) + pr_err("pins: gpio_direction_output for gpio=" + "%d failed with err: %d\n", gpio, err); + } + gpio_free(gpio); + } +} + +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/slab.h> +#include <linux/gpio/nomadik.h> + +#include <mach/gpio.h> + +static void show_pin(struct seq_file *s, pin_cfg_t pin) +{ + static char *afnames[] = { + [NMK_GPIO_ALT_GPIO] = "GPIO", + [NMK_GPIO_ALT_A] = "A", + [NMK_GPIO_ALT_B] = "B", + [NMK_GPIO_ALT_C] = "C" + }; + static char *pullnames[] = { + [NMK_GPIO_PULL_NONE] = "none", + [NMK_GPIO_PULL_UP] = "up", + [NMK_GPIO_PULL_DOWN] = "down", + [3] /* illegal */ = "??" + }; + + int pin_num = PIN_NUM(pin); + int pull = PIN_PULL(pin); + int af = PIN_ALT(pin); + int slpm = PIN_SLPM(pin); + int output = PIN_DIR(pin); + int val = PIN_VAL(pin); + int slpm_pull = PIN_SLPM_PULL(pin); + int slpm_dir = PIN_SLPM_DIR(pin); + int slpm_val = PIN_SLPM_VAL(pin); + + seq_printf(s, + " pin %d [%#lx]: af %s, pull %s (%s%s) - slpm: %s%s%s%s\n", + pin_num, pin, afnames[af], + pullnames[pull], + output ? "output " : "input", + output ? (val ? "high" : "low") : "", + slpm ? "no-change/no-wakeup " : "input/wakeup ", + slpm_dir ? (slpm_dir == 1 ? "input " : "output ") : "", + slpm_dir == 1 ? (slpm_pull == 0 ? "pull: none " : + (slpm_pull == NMK_GPIO_PULL_UP ? + "pull: up " : "pull: down ") ): "", + slpm_dir == 2 ? (slpm_val == 1 ? "low " : "high ") : ""); +} + +static int pins_dbg_show(struct seq_file *s, void *iter) +{ + struct ux500_pin_lookup *pl; + int i; + bool *pins; + int prev = -2; + int first = 0; + + pins = kzalloc(sizeof(bool) * NOMADIK_NR_GPIO, GFP_KERNEL); + + mutex_lock(&pin_lookups_mutex); + + list_for_each_entry(pl, &pin_lookups, node) { + seq_printf(s, "\n%s (%d) usage: %d\n", + pl->name, pl->pins->num, pl->pins->usage); + for (i = 0; i < pl->pins->num; i++) { + show_pin(s, pl->pins->cfg[i]); + pins[PIN_NUM(pl->pins->cfg[i])] = true; + } + } + mutex_unlock(&pin_lookups_mutex); + + seq_printf(s, "\nSummary allocated pins:\n"); + for (i = 0; i < NOMADIK_NR_GPIO; i++) { + if (prev == i - 1) { + if (pins[i]) + prev = i; + else + if (prev > 0) { + if (first != prev) + seq_printf(s, "-%d, ", prev); + else + seq_printf(s, ", "); + } + continue; + } + if (pins[i]) { + seq_printf(s, "%d", i); + prev = i; + first = i; + } + } + if (prev == i - 1 && first != prev) + seq_printf(s, "-%d", prev); + + seq_printf(s, "\n"); + + kfree(pins); + + return 0; +} + +static int pins_dbg_open(struct inode *inode, + struct file *file) +{ + return single_open(file, pins_dbg_show, inode->i_private); +} + +static const struct file_operations pins_fops = { + .open = pins_dbg_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int __init pins_dbg_init(void) +{ + (void) debugfs_create_file("pins", S_IRUGO, + NULL, + NULL, + &pins_fops); + return 0; +} +late_initcall(pins_dbg_init); +#endif diff --git a/arch/arm/mach-ux500/pins.h b/arch/arm/mach-ux500/pins.h new file mode 100644 index 00000000000..0d36af2e7d9 --- /dev/null +++ b/arch/arm/mach-ux500/pins.h @@ -0,0 +1,46 @@ +/* + * 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> +#include <plat/pincfg.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); +void __init ux500_offchip_gpio_init(struct ux500_pins *pins); +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); +int pins_for_u9500(void); + +#endif diff --git a/arch/arm/mach-ux500/reboot_reasons.c b/arch/arm/mach-ux500/reboot_reasons.c new file mode 100644 index 00000000000..167a527e33e --- /dev/null +++ b/arch/arm/mach-ux500/reboot_reasons.c @@ -0,0 +1,78 @@ +/* + * 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 <linux/string.h> +#include <mach/reboot_reasons.h> + +struct reboot_reason reboot_reasons[] = { + {"crash", SW_RESET_CRASH}, + {"factory-reset", SW_RESET_FACTORY_RESET}, + {"recovery", SW_RESET_RECOVERY}, + {"charging", SW_RESET_CHARGING}, + {"coldstart", SW_RESET_COLDSTART}, + {"none", SW_RESET_NO_ARGUMENT}, /* Normal Boot */ + {"chgonly-exit", SW_RESET_CHGONLY_EXIT}, /* Exit Charge Only Mode */ +}; + +unsigned int reboot_reasons_size = ARRAY_SIZE(reboot_reasons); + +/* + * 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. + */ +u16 reboot_reason_code(const char *cmd) +{ + int i; + + if (cmd == NULL) { + if (oops_in_progress) { + /* if we're in an oops assume it's a crash */ + return SW_RESET_CRASH; + } else { + /* normal reboot w/o argument */ + return SW_RESET_NO_ARGUMENT; + } + } + + /* 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; + } + + /* No valid reboot reason found */ + return SW_RESET_NO_ARGUMENT; +} + +/* + * The saved sw reset reason is a 2 byte code that is translated into + * a reboot reason string which is up to 255 characters long by this + * function. + * + * See file reboot_reasons.h for conversion. + */ +const char *reboot_reason_string(u16 code) +{ + int i; + + /* Search through reboot reason list */ + for (i = 0; i < reboot_reasons_size; i++) { + if (reboot_reasons[i].code == code) + return reboot_reasons[i].reason; + } + + /* No valid reboot reason code found */ + return "unknown"; +} diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c index 64b3301892b..a287dbca892 100644 --- a/arch/arm/mach-ux500/timer.c +++ b/arch/arm/mach-ux500/timer.c @@ -15,6 +15,21 @@ #include <mach/setup.h> #include <mach/hardware.h> +#include <mach/context.h> + +#ifdef CONFIG_UX500_CONTEXT +static int mtu_context_notifier_call(struct notifier_block *this, + unsigned long event, void *data) +{ + if (event == CONTEXT_APE_RESTORE) + nmdk_clksrc_reset(); + return NOTIFY_OK; +} + +static struct notifier_block mtu_context_notifier = { + .notifier_call = mtu_context_notifier_call, +}; +#endif static void __init ux500_timer_init(void) { @@ -61,6 +76,10 @@ static void __init ux500_timer_init(void) if (cpu_is_u5500()) db5500_mtimer_init(__io_address(U5500_MTIMER_BASE)); clksrc_dbx500_prcmu_init(prcmu_timer_base); + +#ifdef CONFIG_UX500_CONTEXT + WARN_ON(context_ape_notifier_register(&mtu_context_notifier)); +#endif } static void ux500_timer_reset(void) diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 22cb97d2d8a..c015133a7ad 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -24,6 +24,7 @@ * bit 16..18 - SLPM pull up/down state * bit 19..20 - SLPM direction * bit 21..22 - SLPM Value (if output) + * bit 23..25 - PDIS value (if input) * * to facilitate the definition, the following macros are provided * @@ -67,6 +68,10 @@ typedef unsigned long pin_cfg_t; /* These two replace the above in DB8500v2+ */ #define PIN_SLPM_WAKEUP_ENABLE (NMK_GPIO_SLPM_WAKEUP_ENABLE << PIN_SLPM_SHIFT) #define PIN_SLPM_WAKEUP_DISABLE (NMK_GPIO_SLPM_WAKEUP_DISABLE << PIN_SLPM_SHIFT) +#define PIN_SLPM_USE_MUX_SETTINGS_IN_SLEEP PIN_SLPM_WAKEUP_DISABLE + +#define PIN_SLPM_GPIO PIN_SLPM_WAKEUP_ENABLE /* In SLPM, pin is a gpio */ +#define PIN_SLPM_ALTFUNC PIN_SLPM_WAKEUP_DISABLE /* In SLPM, pin is altfunc */ #define PIN_DIR_SHIFT 14 #define PIN_DIR_MASK (0x1 << PIN_DIR_SHIFT) @@ -105,6 +110,20 @@ typedef unsigned long pin_cfg_t; #define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) #define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_PDIS_SHIFT 23 +#define PIN_SLPM_PDIS_MASK (0x3 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS(x) \ + (((x) & PIN_SLPM_PDIS_MASK) >> PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_NO_CHANGE (0 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_DISABLED (1 << PIN_SLPM_PDIS_SHIFT) +#define PIN_SLPM_PDIS_ENABLED (2 << PIN_SLPM_PDIS_SHIFT) + +#define PIN_LOWEMI_SHIFT 25 +#define PIN_LOWEMI_MASK (0x1 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI(x) (((x) & PIN_LOWEMI_MASK) >> PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_DISABLED (0 << PIN_LOWEMI_SHIFT) +#define PIN_LOWEMI_ENABLED (1 << PIN_LOWEMI_SHIFT) + /* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ #define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) #define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h index fd0ee84c45d..d61faffd13d 100644 --- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h +++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h @@ -146,6 +146,7 @@ struct stedma40_chan_cfg { * @memcpy_conf_phy: default configuration of physical channel memcpy * @memcpy_conf_log: default configuration of logical channel memcpy * @disabled_channels: A vector, ending with -1, that marks physical channels + * @use_esram_lcla: flag for mapping the lcla into esram region * that are for different reasons not available for the driver. */ struct stedma40_platform_data { diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index ad1b45b605a..f9c714a2c6f 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -17,6 +17,7 @@ #include <linux/clk.h> #include <linux/jiffies.h> #include <linux/err.h> +#include <linux/delay.h> #include <asm/mach/time.h> #include <asm/sched_clock.h> @@ -151,6 +152,28 @@ static struct clock_event_device nmdk_clkevt = { .set_next_event = nmdk_clkevt_next, }; +#ifdef ARCH_HAS_READ_CURRENT_TIMER +static void nmdk_timer_delay_loop(unsigned long loops) +{ + unsigned long bclock, now; + + bclock = ~readl(mtu_base + MTU_VAL(0)); + do { + now = ~readl(mtu_base + MTU_VAL(0)); + /* 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 = ~readl(mtu_base + MTU_VAL(0)); + return 0; +} +#endif + /* * IRQ Handler for timer 1 of the MTU block. */ @@ -183,6 +206,11 @@ void nmdk_clksrc_reset(void) mtu_base + MTU_CR(0)); } +struct clock_event_device *nmdk_clkevt_get(void) +{ + return &nmdk_clkevt; +} + void __init nmdk_timer_init(void) { unsigned long rate; @@ -237,4 +265,8 @@ void __init nmdk_timer_init(void) /* Register irq and clockevents */ setup_irq(IRQ_MTU0, &nmdk_timer_irq); clockevents_register_device(&nmdk_clkevt); +#ifdef ARCH_HAS_READ_CURRENT_TIMER + set_delay_fn(nmdk_timer_delay_loop); +#endif + } |