|  | /* | 
|  | * Texas Instruments TNETV107X EVM Board Support | 
|  | * | 
|  | * Copyright (C) 2010 Texas Instruments | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU General Public License as | 
|  | * published by the Free Software Foundation version 2. | 
|  | * | 
|  | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | 
|  | * kind, whether express or implied; without even the implied warranty | 
|  | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | * GNU General Public License for more details. | 
|  | */ | 
|  | #include <linux/kernel.h> | 
|  | #include <linux/init.h> | 
|  | #include <linux/console.h> | 
|  | #include <linux/dma-mapping.h> | 
|  | #include <linux/interrupt.h> | 
|  | #include <linux/gpio.h> | 
|  | #include <linux/delay.h> | 
|  | #include <linux/platform_device.h> | 
|  | #include <linux/ratelimit.h> | 
|  | #include <linux/mtd/mtd.h> | 
|  | #include <linux/mtd/partitions.h> | 
|  | #include <linux/input.h> | 
|  | #include <linux/input/matrix_keypad.h> | 
|  | #include <linux/spi/spi.h> | 
|  | #include <linux/platform_data/edma.h> | 
|  |  | 
|  | #include <asm/mach/arch.h> | 
|  | #include <asm/mach-types.h> | 
|  |  | 
|  | #include <mach/irqs.h> | 
|  | #include <mach/mux.h> | 
|  | #include <mach/cp_intc.h> | 
|  | #include <mach/tnetv107x.h> | 
|  |  | 
|  | #define EVM_MMC_WP_GPIO		21 | 
|  | #define EVM_MMC_CD_GPIO		24 | 
|  | #define EVM_SPI_CS_GPIO		54 | 
|  |  | 
|  | static int initialize_gpio(int gpio, char *desc) | 
|  | { | 
|  | int ret; | 
|  |  | 
|  | ret = gpio_request(gpio, desc); | 
|  | if (ret < 0) { | 
|  | pr_err_ratelimited("cannot open %s gpio\n", desc); | 
|  | return -ENOSYS; | 
|  | } | 
|  | gpio_direction_input(gpio); | 
|  | return gpio; | 
|  | } | 
|  |  | 
|  | static int mmc_get_cd(int index) | 
|  | { | 
|  | static int gpio; | 
|  |  | 
|  | if (!gpio) | 
|  | gpio = initialize_gpio(EVM_MMC_CD_GPIO, "mmc card detect"); | 
|  |  | 
|  | if (gpio < 0) | 
|  | return gpio; | 
|  |  | 
|  | return gpio_get_value(gpio) ? 0 : 1; | 
|  | } | 
|  |  | 
|  | static int mmc_get_ro(int index) | 
|  | { | 
|  | static int gpio; | 
|  |  | 
|  | if (!gpio) | 
|  | gpio = initialize_gpio(EVM_MMC_WP_GPIO, "mmc write protect"); | 
|  |  | 
|  | if (gpio < 0) | 
|  | return gpio; | 
|  |  | 
|  | return gpio_get_value(gpio) ? 1 : 0; | 
|  | } | 
|  |  | 
|  | static struct davinci_mmc_config mmc_config = { | 
|  | .get_cd		= mmc_get_cd, | 
|  | .get_ro		= mmc_get_ro, | 
|  | .wires		= 4, | 
|  | .max_freq	= 50000000, | 
|  | .caps		= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED, | 
|  | }; | 
|  |  | 
|  | static const short sdio1_pins[] __initconst = { | 
|  | TNETV107X_SDIO1_CLK_1,		TNETV107X_SDIO1_CMD_1, | 
|  | TNETV107X_SDIO1_DATA0_1,	TNETV107X_SDIO1_DATA1_1, | 
|  | TNETV107X_SDIO1_DATA2_1,	TNETV107X_SDIO1_DATA3_1, | 
|  | TNETV107X_GPIO21,		TNETV107X_GPIO24, | 
|  | -1 | 
|  | }; | 
|  |  | 
|  | static const short uart1_pins[] __initconst = { | 
|  | TNETV107X_UART1_RD,		TNETV107X_UART1_TD, | 
|  | -1 | 
|  | }; | 
|  |  | 
|  | static const short ssp_pins[] __initconst = { | 
|  | TNETV107X_SSP0_0, TNETV107X_SSP0_1, TNETV107X_SSP0_2, | 
|  | TNETV107X_SSP1_0, TNETV107X_SSP1_1, TNETV107X_SSP1_2, | 
|  | TNETV107X_SSP1_3, -1 | 
|  | }; | 
|  |  | 
|  | static struct mtd_partition nand_partitions[] = { | 
|  | /* bootloader (U-Boot, etc) in first 12 sectors */ | 
|  | { | 
|  | .name		= "bootloader", | 
|  | .offset		= 0, | 
|  | .size		= (12*SZ_128K), | 
|  | .mask_flags	= MTD_WRITEABLE,	/* force read-only */ | 
|  | }, | 
|  | /* bootloader params in the next sector */ | 
|  | { | 
|  | .name		= "params", | 
|  | .offset		= MTDPART_OFS_NXTBLK, | 
|  | .size		= SZ_128K, | 
|  | .mask_flags	= MTD_WRITEABLE,	/* force read-only */ | 
|  | }, | 
|  | /* kernel */ | 
|  | { | 
|  | .name		= "kernel", | 
|  | .offset		= MTDPART_OFS_NXTBLK, | 
|  | .size		= SZ_4M, | 
|  | .mask_flags	= 0, | 
|  | }, | 
|  | /* file system */ | 
|  | { | 
|  | .name		= "filesystem", | 
|  | .offset		= MTDPART_OFS_NXTBLK, | 
|  | .size		= MTDPART_SIZ_FULL, | 
|  | .mask_flags	= 0, | 
|  | } | 
|  | }; | 
|  |  | 
|  | static struct davinci_nand_pdata nand_config = { | 
|  | .mask_cle	= 0x4000, | 
|  | .mask_ale	= 0x2000, | 
|  | .parts		= nand_partitions, | 
|  | .nr_parts	= ARRAY_SIZE(nand_partitions), | 
|  | .ecc_mode	= NAND_ECC_HW, | 
|  | .bbt_options	= NAND_BBT_USE_FLASH, | 
|  | .ecc_bits	= 1, | 
|  | }; | 
|  |  | 
|  | static struct davinci_uart_config serial_config __initconst = { | 
|  | .enabled_uarts	= BIT(1), | 
|  | }; | 
|  |  | 
|  | static const uint32_t keymap[] = { | 
|  | KEY(0, 0, KEY_NUMERIC_1), | 
|  | KEY(0, 1, KEY_NUMERIC_2), | 
|  | KEY(0, 2, KEY_NUMERIC_3), | 
|  | KEY(0, 3, KEY_FN_F1), | 
|  | KEY(0, 4, KEY_MENU), | 
|  |  | 
|  | KEY(1, 0, KEY_NUMERIC_4), | 
|  | KEY(1, 1, KEY_NUMERIC_5), | 
|  | KEY(1, 2, KEY_NUMERIC_6), | 
|  | KEY(1, 3, KEY_UP), | 
|  | KEY(1, 4, KEY_FN_F2), | 
|  |  | 
|  | KEY(2, 0, KEY_NUMERIC_7), | 
|  | KEY(2, 1, KEY_NUMERIC_8), | 
|  | KEY(2, 2, KEY_NUMERIC_9), | 
|  | KEY(2, 3, KEY_LEFT), | 
|  | KEY(2, 4, KEY_ENTER), | 
|  |  | 
|  | KEY(3, 0, KEY_NUMERIC_STAR), | 
|  | KEY(3, 1, KEY_NUMERIC_0), | 
|  | KEY(3, 2, KEY_NUMERIC_POUND), | 
|  | KEY(3, 3, KEY_DOWN), | 
|  | KEY(3, 4, KEY_RIGHT), | 
|  |  | 
|  | KEY(4, 0, KEY_FN_F3), | 
|  | KEY(4, 1, KEY_FN_F4), | 
|  | KEY(4, 2, KEY_MUTE), | 
|  | KEY(4, 3, KEY_HOME), | 
|  | KEY(4, 4, KEY_BACK), | 
|  |  | 
|  | KEY(5, 0, KEY_VOLUMEDOWN), | 
|  | KEY(5, 1, KEY_VOLUMEUP), | 
|  | KEY(5, 2, KEY_F1), | 
|  | KEY(5, 3, KEY_F2), | 
|  | KEY(5, 4, KEY_F3), | 
|  | }; | 
|  |  | 
|  | static const struct matrix_keymap_data keymap_data = { | 
|  | .keymap		= keymap, | 
|  | .keymap_size	= ARRAY_SIZE(keymap), | 
|  | }; | 
|  |  | 
|  | static struct matrix_keypad_platform_data keypad_config = { | 
|  | .keymap_data	= &keymap_data, | 
|  | .num_row_gpios	= 6, | 
|  | .num_col_gpios	= 5, | 
|  | .debounce_ms	= 0, /* minimum */ | 
|  | .active_low	= 0, /* pull up realization */ | 
|  | .no_autorepeat	= 0, | 
|  | }; | 
|  |  | 
|  | static void spi_select_device(int cs) | 
|  | { | 
|  | static int gpio; | 
|  |  | 
|  | if (!gpio) { | 
|  | int ret; | 
|  | ret = gpio_request(EVM_SPI_CS_GPIO, "spi chipsel"); | 
|  | if (ret < 0) { | 
|  | pr_err("cannot open spi chipsel gpio\n"); | 
|  | gpio = -ENOSYS; | 
|  | return; | 
|  | } else { | 
|  | gpio = EVM_SPI_CS_GPIO; | 
|  | gpio_direction_output(gpio, 0); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (gpio < 0) | 
|  | return; | 
|  |  | 
|  | return gpio_set_value(gpio, cs ? 1 : 0); | 
|  | } | 
|  |  | 
|  | static struct ti_ssp_spi_data spi_master_data = { | 
|  | .num_cs	= 2, | 
|  | .select	= spi_select_device, | 
|  | .iosel	= SSP_PIN_SEL(0, SSP_CLOCK)	| SSP_PIN_SEL(1, SSP_DATA) | | 
|  | SSP_PIN_SEL(2, SSP_CHIPSEL)	| SSP_PIN_SEL(3, SSP_IN)   | | 
|  | SSP_INPUT_SEL(3), | 
|  | }; | 
|  |  | 
|  | static struct ti_ssp_data ssp_config = { | 
|  | .out_clock	= 250 * 1000, | 
|  | .dev_data	= { | 
|  | [1] = { | 
|  | .dev_name = "ti-ssp-spi", | 
|  | .pdata = &spi_master_data, | 
|  | .pdata_size = sizeof(spi_master_data), | 
|  | }, | 
|  | }, | 
|  | }; | 
|  |  | 
|  | static struct tnetv107x_device_info evm_device_info __initconst = { | 
|  | .serial_config		= &serial_config, | 
|  | .mmc_config[1]		= &mmc_config,	/* controller 1 */ | 
|  | .nand_config[0]		= &nand_config,	/* chip select 0 */ | 
|  | .keypad_config		= &keypad_config, | 
|  | .ssp_config		= &ssp_config, | 
|  | }; | 
|  |  | 
|  | static struct spi_board_info spi_info[] __initconst = { | 
|  | }; | 
|  |  | 
|  | static __init void tnetv107x_evm_board_init(void) | 
|  | { | 
|  | davinci_cfg_reg_list(sdio1_pins); | 
|  | davinci_cfg_reg_list(uart1_pins); | 
|  | davinci_cfg_reg_list(ssp_pins); | 
|  |  | 
|  | tnetv107x_devices_init(&evm_device_info); | 
|  |  | 
|  | spi_register_board_info(spi_info, ARRAY_SIZE(spi_info)); | 
|  | } | 
|  |  | 
|  | #ifdef CONFIG_SERIAL_8250_CONSOLE | 
|  | static int __init tnetv107x_evm_console_init(void) | 
|  | { | 
|  | return add_preferred_console("ttyS", 0, "115200"); | 
|  | } | 
|  | console_initcall(tnetv107x_evm_console_init); | 
|  | #endif | 
|  |  | 
|  | MACHINE_START(TNETV107X, "TNETV107X EVM") | 
|  | .atag_offset	= 0x100, | 
|  | .map_io		= tnetv107x_init, | 
|  | .init_irq	= cp_intc_init, | 
|  | .init_time	= davinci_timer_init, | 
|  | .init_machine	= tnetv107x_evm_board_init, | 
|  | .init_late	= davinci_init_late, | 
|  | .dma_zone_size	= SZ_128M, | 
|  | .restart	= tnetv107x_restart, | 
|  | MACHINE_END |