/* * Copyright (C) 2008-2009 ST-Ericsson * * Author: Srinidhi KASAGAR * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ste-dma40-db8500.h" #include "devices-db8500.h" #include "board-mop500.h" #include "board-mop500-regulators.h" static struct ab8500_platform_data ab8500_platdata = { .irq_base = MOP500_AB8500_IRQ_BASE, .regulator = ab8500_regulators, .num_regulator = ARRAY_SIZE(ab8500_regulators), }; static struct resource ab8500_resources[] = { [0] = { .start = IRQ_DB8500_AB8500, .end = IRQ_DB8500_AB8500, .flags = IORESOURCE_IRQ } }; struct platform_device ab8500_device = { .name = "ab8500-i2c", .id = 0, .dev = { .platform_data = &ab8500_platdata, }, .num_resources = 1, .resource = ab8500_resources, }; /* * TC35892 */ static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base) { mop500_sdi_tc35892_init(); } static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = { .gpio_base = MOP500_EGPIO(0), .setup = mop500_tc35892_init, }; static struct tc3589x_platform_data mop500_tc35892_data = { .block = TC3589x_BLOCK_GPIO, .gpio = &mop500_tc35892_gpio_data, .irq_base = MOP500_EGPIO_IRQ_BASE, }; 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, }, }; 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, }; 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, }, }; 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, }; static struct i2c_board_info mop500_i2c0_devices[] = { { I2C_BOARD_INFO("tc3589x", 0x42), .irq = NOMADIK_GPIO_TO_IRQ(217), .platform_data = &mop500_tc35892_data, }, }; static struct i2c_board_info __initdata mop500_i2c2_devices[] = { { /* lp5521 LED driver, 1st device */ I2C_BOARD_INFO("lp5521", 0x33), .platform_data = &lp5521_pri_data, }, { /* lp5521 LED driver, 2st device */ I2C_BOARD_INFO("lp5521", 0x34), .platform_data = &lp5521_sec_data, }, { /* Light sensor Rohm BH1780GLI */ I2C_BOARD_INFO("bh1780", 0x29), }, }; #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ static struct nmk_i2c_controller u8500_i2c##id##_data = { \ /* \ * slave data setup time, which is \ * 250 ns,100ns,10ns which is 14,6,2 \ * respectively for a 48 Mhz \ * i2c clock \ */ \ .slsu = _slsu, \ /* Tx FIFO threshold */ \ .tft = _tft, \ /* Rx FIFO threshold */ \ .rft = _rft, \ /* std. mode operation */ \ .clk_freq = clk, \ .sm = _sm, \ } /* * The board uses 4 i2c controllers, initialize all of * them with slave data setup time of 250 ns, * Tx & Rx FIFO threshold values as 1 and standard * mode of operation */ U8500_I2C_CONTROLLER(0, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); static void __init mop500_i2c_init(void) { db8500_add_i2c0(&u8500_i2c0_data); db8500_add_i2c1(&u8500_i2c1_data); db8500_add_i2c2(&u8500_i2c2_data); 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, } }; static struct regulator *prox_regulator; static int mop500_prox_activate(struct device *dev); static void mop500_prox_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_prox_activate, .disable = mop500_prox_deactivate, }; static struct platform_device mop500_gpio_keys_device = { .name = "gpio-keys", .id = 0, .dev = { .platform_data = &mop500_gpio_keys_data, }, }; 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); } regulator_enable(prox_regulator); return 0; } static void mop500_prox_deactivate(struct device *dev) { regulator_disable(prox_regulator); regulator_put(prox_regulator); } /* add any platform devices here - TODO */ static struct platform_device *platform_devs[] __initdata = { &mop500_gpio_keys_device, }; #ifdef CONFIG_STE_DMA40 static struct stedma40_chan_cfg ssp0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_PERIPH_TO_MEM, .src_dev_type = DB8500_DMA_DEV8_SSP0_RX, .dst_dev_type = STEDMA40_DEV_DST_MEMORY, .src_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH, }; static struct stedma40_chan_cfg ssp0_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_MEM_TO_PERIPH, .src_dev_type = STEDMA40_DEV_SRC_MEMORY, .dst_dev_type = DB8500_DMA_DEV8_SSP0_TX, .src_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH, }; #endif static struct pl022_ssp_controller ssp0_platform_data = { .bus_id = 0, #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, }; static void __init mop500_spi_init(void) { db8500_add_ssp0(&ssp0_platform_data); } #ifdef CONFIG_STE_DMA40 static struct stedma40_chan_cfg uart0_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_PERIPH_TO_MEM, .src_dev_type = DB8500_DMA_DEV13_UART0_RX, .dst_dev_type = STEDMA40_DEV_DST_MEMORY, .src_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH, }; static struct stedma40_chan_cfg uart0_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_MEM_TO_PERIPH, .src_dev_type = STEDMA40_DEV_SRC_MEMORY, .dst_dev_type = DB8500_DMA_DEV13_UART0_TX, .src_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH, }; static struct stedma40_chan_cfg uart1_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_PERIPH_TO_MEM, .src_dev_type = DB8500_DMA_DEV12_UART1_RX, .dst_dev_type = STEDMA40_DEV_DST_MEMORY, .src_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH, }; static struct stedma40_chan_cfg uart1_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_MEM_TO_PERIPH, .src_dev_type = STEDMA40_DEV_SRC_MEMORY, .dst_dev_type = DB8500_DMA_DEV12_UART1_TX, .src_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH, }; static struct stedma40_chan_cfg uart2_dma_cfg_rx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_PERIPH_TO_MEM, .src_dev_type = DB8500_DMA_DEV11_UART2_RX, .dst_dev_type = STEDMA40_DEV_DST_MEMORY, .src_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH, }; static struct stedma40_chan_cfg uart2_dma_cfg_tx = { .mode = STEDMA40_MODE_LOGICAL, .dir = STEDMA40_MEM_TO_PERIPH, .src_dev_type = STEDMA40_DEV_SRC_MEMORY, .dst_dev_type = DB8500_DMA_DEV11_UART2_TX, .src_info.data_width = STEDMA40_BYTE_WIDTH, .dst_info.data_width = STEDMA40_BYTE_WIDTH, }; #endif static struct amba_pl011_data uart0_plat = { #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, .dma_rx_param = &uart0_dma_cfg_rx, .dma_tx_param = &uart0_dma_cfg_tx, #endif }; static struct amba_pl011_data uart1_plat = { #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, .dma_rx_param = &uart1_dma_cfg_rx, .dma_tx_param = &uart1_dma_cfg_tx, #endif }; static struct amba_pl011_data uart2_plat = { #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, .dma_rx_param = &uart2_dma_cfg_rx, .dma_tx_param = &uart2_dma_cfg_tx, #endif }; static void __init mop500_uart_init(void) { db8500_add_uart0(&uart0_plat); db8500_add_uart1(&uart1_plat); db8500_add_uart2(&uart2_plat); } static void __init mop500_init_machine(void) { /* * The HREFv60 board removed a GPIO expander and routed * all these GPIO pins to the internal GPIO controller * instead. */ if (machine_is_hrefv60()) mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; else mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; u8500_init_devices(); mop500_pins_init(); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); mop500_i2c_init(); mop500_sdi_init(); mop500_spi_init(); mop500_uart_init(); platform_device_register(&ab8500_device); 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)); } MACHINE_START(U8500, "ST-Ericsson MOP500 platform") /* Maintainer: Srinidhi Kasagar */ .boot_params = 0x100, .map_io = u8500_map_io, .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ .timer = &ux500_timer, .init_machine = mop500_init_machine, MACHINE_END MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") .boot_params = 0x100, .map_io = u8500_map_io, .init_irq = ux500_init_irq, .timer = &ux500_timer, .init_machine = mop500_init_machine, MACHINE_END