blob: e962102e51d60ae914530ddac5b627bca33c4a7a [file] [log] [blame]
/*
* Copyright (C) 2009 ST-Ericsson SA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/sysdev.h>
#include <linux/amba/bus.h>
#include <linux/amba/serial.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/i2s/i2s.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/usb/musb.h>
#include <linux/dma-mapping.h>
#include <linux/input.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
#include <mach/devices.h>
#include <asm/dma.h>
#include <mach/dma.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-stm.h>
#include <linux/mmc/host.h>
#include <asm/setup.h>
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
#include <mach/msp.h>
#include <mach/i2c.h>
#include <mach/shrm.h>
#include <mach/mmc.h>
#include <mach/ab8500.h>
#include <mach/stmpe2401.h>
#include <mach/tc35892.h>
#include <mach/uart.h>
#include <mach/setup.h>
#include <mach/kpd.h>
void __init u8500_register_device(struct platform_device *dev, void *data)
{
int ret;
dev->dev.platform_data = data;
ret = platform_device_register(dev);
if (ret)
dev_err(&dev->dev, "unable to register device: %d\n", ret);
}
void __init u8500_register_amba_device(struct amba_device *dev, void *data)
{
int ret;
dev->dev.platform_data = data;
ret = amba_device_register(dev, &iomem_resource);
if (ret)
dev_err(&dev->dev, "unable to register device: %d\n", ret);
}
#ifdef CONFIG_UX500_SOC_DB8500
/* MSP is being used as a platform device because the perif id of all MSPs
* is same & hence probe would be called for
* 2 drivers namely: msp-spi & msp-i2s.
* Inorder to avoid this & bind a set of MSPs to each driver a platform
* bus is being used- binding based on name.
*/
static int msp_i2s_init(gpio_alt_function gpio)
{
return stm_gpio_altfuncenable(gpio);
}
static int msp_i2s_exit(gpio_alt_function gpio)
{
return stm_gpio_altfuncdisable(gpio);
}
static struct msp_i2s_platform_data msp0_platform_data = {
.id = MSP_0_I2S_CONTROLLER,
.gpio_alt_func = GPIO_ALT_MSP_0,
.msp_tx_dma_addr = DMA_DEV_MSP0_TX,
.msp_rx_dma_addr = DMA_DEV_MSP0_RX,
.msp_base_addr = U8500_MSP0_BASE,
.msp_i2s_init = msp_i2s_init,
.msp_i2s_exit = msp_i2s_exit,
};
static struct resource u8500_msp_0_resources[] = {
[0] = {
.start = U8500_MSP0_BASE,
.end = U8500_MSP0_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_MSP0,
.end = IRQ_MSP0,
.flags = IORESOURCE_IRQ}
};
struct platform_device u8500_msp0_device = {
.name = "MSP_I2S",
.id = 0,
.num_resources = 2,
.resource = u8500_msp_0_resources,
.dev = {
.init_name = "msp0",
.platform_data = &msp0_platform_data,
},
};
static struct msp_i2s_platform_data msp1_platform_data = {
.id = MSP_1_I2S_CONTROLLER,
.gpio_alt_func = GPIO_ALT_MSP_1,
.msp_tx_dma_addr = DMA_DEV_MSP1_TX,
.msp_rx_dma_addr = DMA_DEV_MSP1_RX,
.msp_base_addr = U8500_MSP1_BASE,
.msp_i2s_init = msp_i2s_init,
.msp_i2s_exit = msp_i2s_exit,
};
static struct resource u8500_msp_1_resources[] = {
[0] = {
.start = U8500_MSP1_BASE,
.end = U8500_MSP1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_MSP1,
.end = IRQ_MSP1,
.flags = IORESOURCE_IRQ}
};
struct platform_device u8500_msp1_device = {
.name = "MSP_I2S",
.id = 1,
.num_resources = 2,
.resource = u8500_msp_1_resources,
.dev = {
.init_name = "msp1",
.platform_data = &msp1_platform_data,
},
};
static struct msp_i2s_platform_data msp2_platform_data = {
.id = MSP_2_I2S_CONTROLLER,
.gpio_alt_func = GPIO_ALT_MSP_2,
.msp_tx_dma_addr = DMA_DEV_MSP2_TX,
.msp_rx_dma_addr = DMA_DEV_MSP2_RX,
.msp_base_addr = U8500_MSP2_BASE,
.msp_i2s_init = msp_i2s_init,
.msp_i2s_exit = msp_i2s_exit,
};
static struct resource u8500_msp_2_resources[] = {
[0] = {
.start = U8500_MSP2_BASE,
.end = U8500_MSP2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_MSP2,
.end = IRQ_MSP2,
.flags = IORESOURCE_IRQ
}
};
struct platform_device u8500_msp2_device = {
.name = "MSP_I2S",
.id = 2,
.num_resources = 2,
.resource = u8500_msp_2_resources,
.dev = {
.init_name = "msp2",
.platform_data = &msp2_platform_data,
},
};
#endif
#define NUM_MSP_CLIENTS 10
static struct nmdk_spi_master_cntlr msp2_spi_platform_data = {
.enable_dma = 1,
.id = MSP_2_CONTROLLER,
.num_chipselect = NUM_MSP_CLIENTS,
.base_addr = U8500_MSP2_BASE,
.rx_fifo_addr = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
.rx_fifo_dev_type = DMA_DEV_MSP2_RX,
.tx_fifo_addr = U8500_MSP2_BASE + MSP_TX_RX_REG_OFFSET,
.tx_fifo_dev_type = DMA_DEV_MSP2_TX,
.gpio_alt_func = GPIO_ALT_MSP_2,
.device_name = "msp2",
};
struct amba_device u8500_msp2_spi_device = {
.dev = {
.init_name = "msp2",
.platform_data = &msp2_spi_platform_data,
},
.res = {
.start = U8500_MSP2_BASE,
.end = U8500_MSP2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.dma_mask = ~0,
.irq = {IRQ_MSP2, NO_IRQ},
.periphid = MSP_PER_ID,
};
#define UX500_I2C_RESOURCES(id, size) \
static struct resource ux500_i2c_resources_##id[] = { \
[0] = { \
.start = UX500_I2C##id##_BASE, \
.end = UX500_I2C##id##_BASE + size - 1, \
.flags = IORESOURCE_MEM, \
}, \
[1] = { \
.start = IRQ_I2C##id, \
.end = IRQ_I2C##id, \
.flags = IORESOURCE_IRQ \
} \
}
UX500_I2C_RESOURCES(1, SZ_4K);
UX500_I2C_RESOURCES(2, SZ_4K);
UX500_I2C_RESOURCES(3, SZ_4K);
#define UX500_I2C_PDEVICE(cid) \
struct platform_device ux500_i2c_controller##cid = { \
.name = "nmk-i2c", \
.id = cid, \
.num_resources = 2, \
.resource = ux500_i2c_resources_##cid \
}
UX500_I2C_PDEVICE(1);
UX500_I2C_PDEVICE(2);
UX500_I2C_PDEVICE(3);
static struct shrm_plat_data shrm_platform_data = {
.pshm_dev_data = 0
};
static struct resource u8500_shrm_resources[] = {
[0] = {
.start = U8500_SHRM_GOP_INTERRUPT_BASE,
.end = U8500_SHRM_GOP_INTERRUPT_BASE + ((4*4)-1),
.name = "shrm_gop_register_base",
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_CA_WAKE_REQ_V1,
.end = IRQ_CA_WAKE_REQ_V1,
.name = "ca_irq_wake_req",
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = IRQ_AC_READ_NOTIFICATION_0_V1,
.end = IRQ_AC_READ_NOTIFICATION_0_V1,
.name = "ac_read_notification_0_irq",
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = IRQ_AC_READ_NOTIFICATION_1_V1,
.end = IRQ_AC_READ_NOTIFICATION_1_V1,
.name = "ac_read_notification_1_irq",
.flags = IORESOURCE_IRQ,
},
[4] = {
.start = IRQ_CA_MSG_PEND_NOTIFICATION_0_V1,
.end = IRQ_CA_MSG_PEND_NOTIFICATION_0_V1,
.name = "ca_msg_pending_notification_0_irq",
.flags = IORESOURCE_IRQ,
},
[5] = {
.start = IRQ_CA_MSG_PEND_NOTIFICATION_1_V1,
.end = IRQ_CA_MSG_PEND_NOTIFICATION_1_V1,
.name = "ca_msg_pending_notification_1_irq",
.flags = IORESOURCE_IRQ,
}
};
struct platform_device u8500_shrm_device = {
.name = "u8500_shrm",
.id = 0,
.dev = {
.init_name = "shrm_bus",
.coherent_dma_mask = ~0,
.platform_data = &shrm_platform_data,
},
.num_resources = ARRAY_SIZE(u8500_shrm_resources),
.resource = u8500_shrm_resources
};
static struct resource b2r2_resources[] = {
[0] = {
.start = UX500_B2R2_BASE,
.end = UX500_B2R2_BASE + ((4*1024)-1),
.name = "b2r2_base",
.flags = IORESOURCE_MEM,
},
[1] = {
.start = PRCM_B2R2CLK_MGT_REG,
.end = PRCM_B2R2CLK_MGT_REG + (sizeof(u32) - 1),
.name = "prcm_b2r2_clk",
.flags = IORESOURCE_MEM,
},
};
struct platform_device ux500_b2r2_device = {
.name = "U8500-B2R2",
.id = 0,
.dev = {
.init_name = "b2r2_bus",
.coherent_dma_mask = ~0,
},
.num_resources = ARRAY_SIZE(b2r2_resources),
.resource = b2r2_resources,
};
#ifdef CONFIG_ANDROID_PMEM
static int __init early_pmem_generic_parse(char *p, struct android_pmem_platform_data * data)
{
data->size = memparse(p, &p);
if (*p == '@')
data->start = memparse(p + 1, &p);
return 0;
}
/********************************************************************************
* Pmem device used by surface flinger
********************************************************************************/
static struct android_pmem_platform_data pmem_pdata = {
.name = "pmem",
.no_allocator = 1, /* MemoryHeapBase is having an allocator */
.cached = 1,
.start = 0,
.size = 0,
};
static int __init early_pmem(char *p)
{
return early_pmem_generic_parse(p, &pmem_pdata);
}
early_param("pmem", early_pmem);
struct platform_device u8500_pmem_device = {
.name = "android_pmem",
.id = 0,
.dev = {
.platform_data = &pmem_pdata,
},
};
/********************************************************************************
* Pmem device used by PV video output node
********************************************************************************/
static struct android_pmem_platform_data pmem_mio_pdata = {
.name = "pmem_mio",
.no_allocator = 1, /* We'll manage allocation */
.cached = 1,
.start = 0,
.size = 0,
};
static int __init early_pmem_mio(char *p)
{
return early_pmem_generic_parse(p, &pmem_mio_pdata);
}
early_param("pmem_mio", early_pmem_mio);
struct platform_device u8500_pmem_mio_device = {
.name = "android_pmem",
.id = 1,
.dev = {
.platform_data = &pmem_mio_pdata,
},
};
/********************************************************************************
* Pmem device used by OMX components allocating buffers
********************************************************************************/
static struct android_pmem_platform_data pmem_hwb_pdata = {
.name = "pmem_hwb",
.no_allocator = 1, /* We'll manage allocation */
.cached = 1,
.start = 0,
.size = 0,
};
static int __init early_pmem_hwb(char *p)
{
return early_pmem_generic_parse(p, &pmem_hwb_pdata);
}
early_param("pmem_hwb", early_pmem_hwb);
struct platform_device u8500_pmem_hwb_device = {
.name = "android_pmem",
.id = 2,
.dev = {
.platform_data = &pmem_hwb_pdata,
},
};
#endif
struct amba_device ux500_rtc_device = {
.dev = {
.init_name = "mb:15",
},
.res = {
.start = UX500_RTC_BASE,
.end = UX500_RTC_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_RTC_RTT, NO_IRQ},
.periphid = RTC_PER_ID,
};
static struct resource ux500_dma_resources[] = {
[0] = {
.start = UX500_DMA_BASE,
.end = UX500_DMA_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_DMA,
.end = IRQ_DMA,
.flags = IORESOURCE_IRQ
},
};
struct platform_device ux500_dma_device = {
.name = "STM-DMA",
.id = 0,
.num_resources = ARRAY_SIZE(ux500_dma_resources),
.resource = ux500_dma_resources
};
#ifdef CONFIG_CRYPTO_DEV_UX500_HASH
static struct resource ux500_hash1_resources[] = {
[0] = {
.start = UX500_HASH1_BASE,
.end = UX500_HASH1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
}
};
struct platform_device ux500_hash1_device = {
.name = "hash1",
.id = -1,
.num_resources = 1,
.resource = ux500_hash1_resources
};
#endif
#define NUM_SPI023_CLIENTS 10
static struct nmdk_spi_master_cntlr spi0_platform_data = {
.enable_dma = 1,
.id = SPI023_0_CONTROLLER,
.num_chipselect = NUM_SPI023_CLIENTS,
.base_addr = UX500_SPI0_BASE,
.rx_fifo_addr = UX500_SPI0_BASE + SPI_TX_RX_REG_OFFSET,
.rx_fifo_dev_type = DMA_DEV_SPI0_RX,
.tx_fifo_addr = UX500_SPI0_BASE + SPI_TX_RX_REG_OFFSET,
.tx_fifo_dev_type = DMA_DEV_SPI0_TX,
.gpio_alt_func = GPIO_ALT_SSP_0,
.device_name = "spi0",
};
struct amba_device ux500_spi0_device = {
.dev = {
.init_name = "spi0",
.platform_data = &spi0_platform_data,
},
.res = {
.start = UX500_SPI0_BASE,
.end = UX500_SPI0_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.dma_mask = DMA_BIT_MASK(32),
.irq = {IRQ_SPI0, NO_IRQ},
.periphid = SPI_PER_ID,
};
struct amba_device ux500_sdi0_device = {
.dev = {
.init_name = "sdi0",
},
.res = {
.start = UX500_SDI0_BASE,
.end = UX500_SDI0_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_SDMMC0, NO_IRQ},
.periphid = SDI_PER_ID,
};
struct amba_device ux500_sdi1_device = {
.dev = {
.init_name = "sdi1",
},
.res = {
.start = UX500_SDI1_BASE,
.end = UX500_SDI1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_SDMMC1, NO_IRQ},
.periphid = SDI_PER_ID,
};
struct amba_device ux500_sdi2_device = {
.dev = {
.init_name = "sdi2",
},
.res = {
.start = UX500_SDI2_BASE,
.end = UX500_SDI2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_SDMMC2, NO_IRQ},
.periphid = SDI_PER_ID,
};
struct amba_device ux500_sdi4_device = {
.dev = {
.init_name = "sdi4",
},
.res = {
.start = UX500_SDI4_BASE,
.end = UX500_SDI4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
.irq = {IRQ_SDMMC4, NO_IRQ},
.periphid = SDI_PER_ID,
};
static struct resource ab8500_resources[] = {
[0] = {
.start = STW4500_IRQ,
.end = STW4500_IRQ,
.flags = IORESOURCE_IRQ
}
};
/**
* ab8500_spi_cs_enable - disables the chip select for STw4500
*/
void ab8500_spi_cs_enable(void)
{
}
/**
* ab8500_spi_cs_disable - enables the chip select for STw4500
*/
void ab8500_spi_cs_disable(void)
{
}
static struct ab8500_device ab8500_board = {
.cs_en = ab8500_spi_cs_enable,
.cs_dis = ab8500_spi_cs_disable,
.ssp_controller = SSP_0_CONTROLLER,
};
struct platform_device u8500_ab8500_device = {
.name = "ab8500",
.id = 0,
.dev = {
.platform_data = &ab8500_board,
},
.num_resources = 1,
.resource = ab8500_resources,
};
#if defined(CONFIG_USB_MUSB_HOST)
#define MUSB_MODE MUSB_HOST
#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
#define MUSB_MODE MUSB_PERIPHERAL
#elif defined(CONFIG_USB_MUSB_OTG)
#define MUSB_MODE MUSB_OTG
#else
#define MUSB_MODE MUSB_UNDEFINED
#endif
static struct musb_hdrc_config musb_hdrc_hs_otg_config = {
.multipoint = true, /* multipoint device */
.dyn_fifo = true, /* supports dynamic fifo sizing */
.num_eps = 16, /* number of endpoints _with_ ep0 */
.ram_bits = 16, /* ram address size */
};
static struct musb_hdrc_platform_data musb_hdrc_hs_otg_platform_data = {
.mode = MUSB_MODE,
.clock = "usb", /* for clk_get() */
.config = &musb_hdrc_hs_otg_config,
};
static struct resource usb_resources[] = {
[0] = {
.name = "usb-mem",
.start = UX500_USBOTG_BASE,
.end = (UX500_USBOTG_BASE + SZ_64K - 1),
.flags = IORESOURCE_MEM,
},
[1] = {
.name = "usb-irq",
.start = IRQ_USBOTG,
.end = IRQ_USBOTG,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device ux500_musb_device = {
.name = "musb_hdrc",
.id = 0,
.dev = {
.init_name = "musb_hdrc.0", /* for clk_get() */
.platform_data = &musb_hdrc_hs_otg_platform_data,
.dma_mask = (u64 *)0xFFFFFFFF,
.coherent_dma_mask = (u64)0xFFFFFFFF
},
.num_resources = ARRAY_SIZE(usb_resources),
.resource = usb_resources,
};
static void uart0_init(void)
{
stm_gpio_altfuncenable(GPIO_ALT_UART_0_NO_MODEM);
}
static void uart0_exit(void)
{
stm_gpio_altfuncdisable(GPIO_ALT_UART_0_NO_MODEM);
}
struct uart_amba_plat_data uart0_plat = {
.init = uart0_init,
.exit = uart0_exit,
};
static void uart1_init(void)
{
stm_gpio_altfuncenable(GPIO_ALT_UART_1);
}
static void uart1_exit(void)
{
stm_gpio_altfuncdisable(GPIO_ALT_UART_1);
}
struct uart_amba_plat_data uart1_plat = {
.init = uart1_init,
.exit = uart1_exit,
};
static void uart2_init(void)
{
stm_gpio_altfuncenable(GPIO_ALT_UART_2);
}
static void uart2_exit(void)
{
stm_gpio_altfuncdisable(GPIO_ALT_UART_2);
}
struct uart_amba_plat_data uart2_plat = {
.init = uart2_init,
.exit = uart2_exit,
};
#define __MEM_4K_RESOURCE(x) \
.res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
/* These are active devices on this board, FIXME
* move this to board file
*/
#if defined(CONFIG_MACH_U5500_SIMULATOR)
/* Remap of uart0 and uart2 when using SVP5500
* remove this when uart2 problem solved in SVP5500
*/
struct amba_device ux500_uart2_device = {
.dev = {.init_name = "uart2", .platform_data = &uart0_plat, },
__MEM_4K_RESOURCE(UX500_UART0_BASE),
.irq = {IRQ_UART0, NO_IRQ},
};
struct amba_device ux500_uart1_device = {
.dev = {.init_name = "uart1", .platform_data = &uart1_plat, },
__MEM_4K_RESOURCE(UX500_UART1_BASE),
.irq = {IRQ_UART1, NO_IRQ},
};
struct amba_device ux500_uart0_device = {
.dev = {.init_name = "uart0", .platform_data = &uart2_plat, },
__MEM_4K_RESOURCE(UX500_UART2_BASE),
.irq = {IRQ_UART2, NO_IRQ},
};
#else
struct amba_device ux500_uart0_device = {
.dev = {.init_name = "uart0", .platform_data = &uart0_plat, },
__MEM_4K_RESOURCE(UX500_UART0_BASE),
.irq = {IRQ_UART0, NO_IRQ},
};
struct amba_device ux500_uart1_device = {
.dev = {.init_name = "uart1", .platform_data = &uart1_plat, },
__MEM_4K_RESOURCE(UX500_UART1_BASE),
.irq = {IRQ_UART1, NO_IRQ},
};
struct amba_device ux500_uart2_device = {
.dev = {.init_name = "uart2", .platform_data = &uart2_plat, },
__MEM_4K_RESOURCE(UX500_UART2_BASE),
.irq = {IRQ_UART2, NO_IRQ},
};
#endif
#ifdef CONFIG_KEYPAD_SKE
#define KEYPAD_DEBOUNCE_PERIOD_SKE 64
#define ROW_PIN_I0 164
#define ROW_PIN_I3 161
#define ROW_PIN_I4 156
#define ROW_PIN_I7 153
#define COL_PIN_O0 168
#define COL_PIN_O3 165
#define COL_PIN_O4 160
#define COL_PIN_O7 157
/* ske_set_gpio_column - Disables Pull up
* @start: start column pin
* @end: end column pin
* This function disables the pull up for output pins
*/
int ske_set_gpio_column(int start, int end)
{
int i;
int status = 0;
for (i = start; i <= end; i++) {
status = gpio_request(i, "ske");
if (status < 0) {
printk(KERN_ERR "%s: gpio request failed \n", __func__);
return status;
}
status = nmk_gpio_set_pull(i, NMK_GPIO_PULL_UP);
if (status < 0) {
printk(KERN_ERR "%s: gpio set pull failed \n", __func__);
return status;
}
gpio_free(i);
}
return status;
}
/* ske_set_gpio_row - enable the input pins
* @start: start row pin
* @end: end row pin
* This function enable the input pins
*/
int ske_set_gpio_row(int start, int end)
{
int i = 0;
int status = 0;
for (i = start; i <= end; i++) {
status = gpio_request(i, "ske");
if (status < 0) {
printk(KERN_ERR "%s: gpio request failed \n", __func__);
return status;
}
status = gpio_direction_output(i, 1);
if (status < 0) {
printk(KERN_ERR "%s: gpio direction failed \n", __func__);
gpio_free(i);
return status;
}
gpio_set_value(i, 1);
gpio_free(i);
}
return status;
}
/**
* ske_kp_init - enable the gpio configuration
* @kp: keypad device data pointer
*
* This function is used to enable the gpio configuration for keypad
*
*/
static int ske_kp_init(struct keypad_t *kp)
{
int ret;
ret = ske_set_gpio_row(ROW_PIN_I3, ROW_PIN_I0);
if (ret < 0)
goto err;
ret = ske_set_gpio_row(ROW_PIN_I7, ROW_PIN_I4);
if (ret < 0)
goto err;
ret = ske_set_gpio_column(COL_PIN_O3, COL_PIN_O0);
if (ret < 0)
goto err;
ret = ske_set_gpio_column(COL_PIN_O7, COL_PIN_O4);
if (ret < 0)
goto err;
ret = stm_gpio_altfuncenable(GPIO_ALT_KEYPAD);
if (ret)
goto err;
return 0;
err:
printk(KERN_ERR "%s: failed \n", __func__);
return ret;
}
/**
* ske_kp_exit - disable the gpio configuration
* @kp: keypad device data pointer
*
* This function is used to disable the gpio configuration for keypad
*
*/
static int ske_kp_exit(struct keypad_t *kp)
{
stm_gpio_altfuncdisable(GPIO_ALT_KEYPAD);
return 0;
}
/*
* Initializes the key scan table (lookup table) as per pre-defined the scan
* codes to be passed to upper layer with respective key codes
*/
u8 const kpd_lookup_tbl[MAX_KPROW][MAX_KPROW] = {
{
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_MENU,
KEY_RESERVED,
KEY_RESERVED
},
{
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_3,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED
},
{
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_END,
KEY_RESERVED,
KEY_RESERVED
},
{
KEY_RESERVED,
KEY_RESERVED,
KEY_7,
KEY_DOWN,
KEY_UP,
KEY_VOLUMEDOWN,
KEY_RESERVED,
KEY_RESERVED
},
{
KEY_RESERVED,
KEY_4,
KEY_VOLUMEUP,
KEY_LEFT,
KEY_RESERVED,
KEY_0,
KEY_RESERVED,
KEY_RESERVED
},
{
KEY_9,
KEY_RESERVED,
KEY_RIGHT,
KEY_RESERVED,
KEY_RESERVED,
KEY_1,
KEY_RESERVED,
KEY_RESERVED
},
{
KEY_RESERVED,
KEY_RESERVED,
KEY_BACK,
KEY_RESERVED,
KEY_SEND,
KEY_RESERVED,
KEY_RESERVED,
KEY_2
},
{
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_RESERVED,
KEY_ENTER,
KEY_RESERVED
}
};
static struct keypad_device keypad_board = {
.init = ske_kp_init,
.exit = ske_kp_exit,
.kcode_tbl = (u8 *) kpd_lookup_tbl,
.krow = MAX_KPROW,
.kcol = MAX_KPCOL,
.debounce_period = KEYPAD_DEBOUNCE_PERIOD_SKE,
.irqtype = 0,
.int_status = KP_INT_DISABLED,
.int_line_behaviour = INT_LINE_NOTSET,
};
struct resource keypad_resources[] = {
[0] = {
.start = U8500_SKE_BASE,
.end = U8500_SKE_BASE + SZ_4K - 1,
.name = "ux500_ske_base",
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_SKE_KP,
.end = IRQ_SKE_KP,
.name = "ux500_ske_irq",
.flags = IORESOURCE_IRQ,
},
};
struct platform_device ske_keypad_device = {
.name = "ske-kp",
.id = -1,
.dev = {
.platform_data = &keypad_board,
},
.num_resources = ARRAY_SIZE(keypad_resources),
.resource = keypad_resources,
};
#endif
#if defined(CONFIG_U5500_MLOADER_HELPER)
struct platform_device mloader_helper_device = {
.name = "mloader_helper",
.id = -1,
};
#endif
void __init amba_add_devices(struct amba_device *devs[], int num)
{
int i;
for (i = 0; i < num; i++) {
struct amba_device *d = devs[i];
amba_device_register(d, &iomem_resource);
}
}