diff options
32 files changed, 997 insertions, 296 deletions
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index ae890caa17a7..019fb7c67dc3 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -58,6 +58,7 @@ CONFIG_ARM_ERRATA_411920=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_SMP=y +CONFIG_NR_CPUS=2 # CONFIG_LOCAL_TIMERS is not set CONFIG_AEABI=y CONFIG_LEDS=y diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 9b4e78fe3d1c..b9d8a7b2a862 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -310,6 +310,7 @@ config MACH_OMAP_4430SDP depends on ARCH_OMAP4 select OMAP_PACKAGE_CBL select OMAP_PACKAGE_CBS + select REGULATOR_FIXED_VOLTAGE config MACH_OMAP4_PANDA bool "OMAP4 Panda Board" @@ -317,6 +318,7 @@ config MACH_OMAP4_PANDA depends on ARCH_OMAP4 select OMAP_PACKAGE_CBL select OMAP_PACKAGE_CBS + select REGULATOR_FIXED_VOLTAGE config OMAP3_EMU bool "OMAP3 debugging peripherals" diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index ec74c0f2051c..cc42d474c443 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -22,6 +22,7 @@ #include <linux/mmc/host.h> #include <linux/delay.h> #include <linux/i2c/twl.h> +#include <linux/regulator/machine.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> @@ -147,6 +148,25 @@ static void __init omap_2430sdp_init_early(void) omap2_init_common_devices(NULL, NULL); } +static struct regulator_consumer_supply sdp2430_vmmc1_supplies[] = { + REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0"), +}; + +/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */ +static struct regulator_init_data sdp2430_vmmc1 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 3150000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = ARRAY_SIZE(sdp2430_vmmc1_supplies), + .consumer_supplies = &sdp2430_vmmc1_supplies[0], +}; + static struct twl4030_gpio_platform_data sdp2430_gpio_data = { .gpio_base = OMAP_MAX_GPIO_LINES, .irq_base = TWL4030_GPIO_IRQ_BASE, @@ -159,6 +179,7 @@ static struct twl4030_platform_data sdp2430_twldata = { /* platform_data for children goes here */ .gpio = &sdp2430_gpio_data, + .vmmc1 = &sdp2430_vmmc1, }; static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = { diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 31085883199e..76a260f7c00e 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -315,11 +315,6 @@ static struct platform_device sdp3430_dss_device = { }, }; -static struct regulator_consumer_supply sdp3430_vdda_dac_supply = { - .supply = "vdda_dac", - .dev = &sdp3430_dss_device.dev, -}; - static struct platform_device *sdp3430_devices[] __initdata = { &sdp3430_dss_device, }; @@ -369,18 +364,6 @@ static struct omap2_hsmmc_info mmc[] = { {} /* Terminator */ }; -static struct regulator_consumer_supply sdp3430_vmmc1_supply = { - .supply = "vmmc", -}; - -static struct regulator_consumer_supply sdp3430_vsim_supply = { - .supply = "vmmc_aux", -}; - -static struct regulator_consumer_supply sdp3430_vmmc2_supply = { - .supply = "vmmc", -}; - static int sdp3430_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { @@ -391,13 +374,6 @@ static int sdp3430_twl_gpio_setup(struct device *dev, mmc[1].gpio_cd = gpio + 1; omap2_hsmmc_init(mmc); - /* link regulators to MMC adapters ... we "know" the - * regulators will be set up only *after* we return. - */ - sdp3430_vmmc1_supply.dev = mmc[0].dev; - sdp3430_vsim_supply.dev = mmc[0].dev; - sdp3430_vmmc2_supply.dev = mmc[1].dev; - /* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */ gpio_request(gpio + 7, "sub_lcd_en_bkl"); gpio_direction_output(gpio + 7, 0); @@ -426,6 +402,34 @@ static struct twl4030_madc_platform_data sdp3430_madc_data = { .irq_line = 1, }; +/* regulator consumer mappings */ + +/* ads7846 on SPI */ +static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = { + REGULATOR_SUPPLY("vcc", "spi1.0"), +}; + +static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = { + REGULATOR_SUPPLY("vdda_dac", "omapdss"), +}; + +/* VPLL2 for digital video outputs */ +static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), +}; + +static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = { + REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0"), +}; + +static struct regulator_consumer_supply sdp3430_vsim_supplies[] = { + REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.0"), +}; + +static struct regulator_consumer_supply sdp3430_vmmc2_supplies[] = { + REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1"), +}; + /* * Apply all the fixed voltages since most versions of U-Boot * don't bother with that initialization. @@ -468,6 +472,8 @@ static struct regulator_init_data sdp3430_vaux3 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(sdp3430_vaux3_supplies), + .consumer_supplies = sdp3430_vaux3_supplies, }; /* VAUX4 for OMAP VDD_CSI2 (camera) */ @@ -494,8 +500,8 @@ static struct regulator_init_data sdp3430_vmmc1 = { | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &sdp3430_vmmc1_supply, + .num_consumer_supplies = ARRAY_SIZE(sdp3430_vmmc1_supplies), + .consumer_supplies = sdp3430_vmmc1_supplies, }; /* VMMC2 for MMC2 card */ @@ -509,8 +515,8 @@ static struct regulator_init_data sdp3430_vmmc2 = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &sdp3430_vmmc2_supply, + .num_consumer_supplies = ARRAY_SIZE(sdp3430_vmmc2_supplies), + .consumer_supplies = sdp3430_vmmc2_supplies, }; /* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */ @@ -524,8 +530,8 @@ static struct regulator_init_data sdp3430_vsim = { | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &sdp3430_vsim_supply, + .num_consumer_supplies = ARRAY_SIZE(sdp3430_vsim_supplies), + .consumer_supplies = sdp3430_vsim_supplies, }; /* VDAC for DSS driving S-Video */ @@ -539,16 +545,8 @@ static struct regulator_init_data sdp3430_vdac = { .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &sdp3430_vdda_dac_supply, -}; - -/* VPLL2 for digital video outputs */ -static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = { - { - .supply = "vdds_dsi", - .dev = &sdp3430_dss_device.dev, - } + .num_consumer_supplies = ARRAY_SIZE(sdp3430_vdda_dac_supplies), + .consumer_supplies = sdp3430_vdda_dac_supplies, }; static struct regulator_init_data sdp3430_vpll2 = { @@ -812,7 +810,7 @@ static void __init omap_3430sdp_init(void) omap_serial_init(); usb_musb_init(&musb_board_data); board_smc91x_init(); - board_flash_init(sdp_flash_partitions, chip_sel_3430); + board_flash_init(sdp_flash_partitions, chip_sel_3430, 0); sdp3430_display_init(); enable_board_wakeup_source(); usb_ehci_init(&ehci_pdata); diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c index 16538757291a..8d1c4358ecf9 100644 --- a/arch/arm/mach-omap2/board-3630sdp.c +++ b/arch/arm/mach-omap2/board-3630sdp.c @@ -11,6 +11,7 @@ #include <linux/platform_device.h> #include <linux/input.h> #include <linux/gpio.h> +#include <linux/mtd/nand.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -208,7 +209,7 @@ static void __init omap_sdp_init(void) zoom_peripherals_init(); zoom_display_init(); board_smc91x_init(); - board_flash_init(sdp_flash_partitions, chip_sel_sdp); + board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16); enable_board_wakeup_source(); usb_ehci_init(&ehci_pdata); } diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index bf8268438d00..1a943be822c3 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -35,6 +35,7 @@ #include <plat/common.h> #include <plat/usb.h> #include <plat/mmc.h> +#include <plat/omap4-keypad.h> #include "mux.h" #include "hsmmc.h" @@ -47,6 +48,90 @@ #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO 184 #define OMAP4_SFH7741_ENABLE_GPIO 188 +static const int sdp4430_keymap[] = { + KEY(0, 0, KEY_E), + KEY(0, 1, KEY_R), + KEY(0, 2, KEY_T), + KEY(0, 3, KEY_HOME), + KEY(0, 4, KEY_F5), + KEY(0, 5, KEY_UNKNOWN), + KEY(0, 6, KEY_I), + KEY(0, 7, KEY_LEFTSHIFT), + + KEY(1, 0, KEY_D), + KEY(1, 1, KEY_F), + KEY(1, 2, KEY_G), + KEY(1, 3, KEY_SEND), + KEY(1, 4, KEY_F6), + KEY(1, 5, KEY_UNKNOWN), + KEY(1, 6, KEY_K), + KEY(1, 7, KEY_ENTER), + + KEY(2, 0, KEY_X), + KEY(2, 1, KEY_C), + KEY(2, 2, KEY_V), + KEY(2, 3, KEY_END), + KEY(2, 4, KEY_F7), + KEY(2, 5, KEY_UNKNOWN), + KEY(2, 6, KEY_DOT), + KEY(2, 7, KEY_CAPSLOCK), + + KEY(3, 0, KEY_Z), + KEY(3, 1, KEY_KPPLUS), + KEY(3, 2, KEY_B), + KEY(3, 3, KEY_F1), + KEY(3, 4, KEY_F8), + KEY(3, 5, KEY_UNKNOWN), + KEY(3, 6, KEY_O), + KEY(3, 7, KEY_SPACE), + + KEY(4, 0, KEY_W), + KEY(4, 1, KEY_Y), + KEY(4, 2, KEY_U), + KEY(4, 3, KEY_F2), + KEY(4, 4, KEY_VOLUMEUP), + KEY(4, 5, KEY_UNKNOWN), + KEY(4, 6, KEY_L), + KEY(4, 7, KEY_LEFT), + + KEY(5, 0, KEY_S), + KEY(5, 1, KEY_H), + KEY(5, 2, KEY_J), + KEY(5, 3, KEY_F3), + KEY(5, 4, KEY_F9), + KEY(5, 5, KEY_VOLUMEDOWN), + KEY(5, 6, KEY_M), + KEY(5, 7, KEY_RIGHT), + + KEY(6, 0, KEY_Q), + KEY(6, 1, KEY_A), + KEY(6, 2, KEY_N), + KEY(6, 3, KEY_BACK), + KEY(6, 4, KEY_BACKSPACE), + KEY(6, 5, KEY_UNKNOWN), + KEY(6, 6, KEY_P), + KEY(6, 7, KEY_UP), + + KEY(7, 0, KEY_PROG1), + KEY(7, 1, KEY_PROG2), + KEY(7, 2, KEY_PROG3), + KEY(7, 3, KEY_PROG4), + KEY(7, 4, KEY_F4), + KEY(7, 5, KEY_UNKNOWN), + KEY(7, 6, KEY_OK), + KEY(7, 7, KEY_DOWN), +}; + +static struct matrix_keymap_data sdp4430_keymap_data = { + .keymap = sdp4430_keymap, + .keymap_size = ARRAY_SIZE(sdp4430_keymap), +}; + +static struct omap4_keypad_platform_data sdp4430_keypad_data = { + .keymap_data = &sdp4430_keymap_data, + .rows = 8, + .cols = 8, +}; static struct gpio_led sdp4430_gpio_leds[] = { { .name = "omap4:green:debug0", @@ -422,7 +507,6 @@ static struct regulator_init_data sdp4430_vana = { .constraints = { .min_uV = 2100000, .max_uV = 2100000, - .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE @@ -434,7 +518,6 @@ static struct regulator_init_data sdp4430_vcxio = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, - .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE @@ -446,7 +529,6 @@ static struct regulator_init_data sdp4430_vdac = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, - .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE @@ -574,6 +656,10 @@ static void __init omap_4430sdp_init(void) spi_register_board_info(sdp4430_spi_board_info, ARRAY_SIZE(sdp4430_spi_board_info)); } + + status = omap4_keyboard_init(&sdp4430_keypad_data); + if (status) + pr_err("Keypad initialization failed: %d\n", status); } static void __init omap_4430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index fd38c05bb47f..c32c06828f08 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -1,5 +1,5 @@ /* - * board-sdp-flash.c + * board-flash.c * Modified from mach-omap2/board-3430sdp-flash.c * * Copyright (C) 2009 Nokia Corporation @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <linux/mtd/physmap.h> #include <linux/io.h> +#include <plat/irqs.h> #include <plat/gpmc.h> #include <plat/nand.h> @@ -73,11 +74,11 @@ __init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs) + FLASH_SIZE_SDPV1 - 1; } if (err < 0) { - printk(KERN_ERR "NOR: Can't request GPMC CS\n"); + pr_err("NOR: Can't request GPMC CS\n"); return; } if (platform_device_register(&board_nor_device) < 0) - printk(KERN_ERR "Unable to register NOR device\n"); + pr_err("Unable to register NOR device\n"); } #if defined(CONFIG_MTD_ONENAND_OMAP2) || \ @@ -139,12 +140,16 @@ static struct omap_nand_platform_data board_nand_data = { }; void -__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs) +__init board_nand_init(struct mtd_partition *nand_parts, + u8 nr_parts, u8 cs, int nand_type) { board_nand_data.cs = cs; board_nand_data.parts = nand_parts; - board_nand_data.nr_parts = nr_parts; + board_nand_data.nr_parts = nr_parts; + board_nand_data.devsize = nand_type; + board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; + board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs; gpmc_nand_init(&board_nand_data); } #else @@ -189,12 +194,12 @@ unmap: } /** - * sdp3430_flash_init - Identify devices connected to GPMC and register. + * board_flash_init - Identify devices connected to GPMC and register. * * @return - void. */ void board_flash_init(struct flash_partitions partition_info[], - char chip_sel_board[][GPMC_CS_NUM]) + char chip_sel_board[][GPMC_CS_NUM], int nand_type) { u8 cs = 0; u8 norcs = GPMC_CS_NUM + 1; @@ -208,7 +213,7 @@ void board_flash_init(struct flash_partitions partition_info[], */ idx = get_gpmc0_type(); if (idx >= MAX_SUPPORTED_GPMC_CONFIG) { - printk(KERN_ERR "%s: Invalid chip select: %d\n", __func__, cs); + pr_err("%s: Invalid chip select: %d\n", __func__, cs); return; } config_sel = (unsigned char *)(chip_sel_board[idx]); @@ -232,23 +237,20 @@ void board_flash_init(struct flash_partitions partition_info[], } if (norcs > GPMC_CS_NUM) - printk(KERN_INFO "NOR: Unable to find configuration " - "in GPMC\n"); + pr_err("NOR: Unable to find configuration in GPMC\n"); else board_nor_init(partition_info[0].parts, partition_info[0].nr_parts, norcs); if (onenandcs > GPMC_CS_NUM) - printk(KERN_INFO "OneNAND: Unable to find configuration " - "in GPMC\n"); + pr_err("OneNAND: Unable to find configuration in GPMC\n"); else board_onenand_init(partition_info[1].parts, partition_info[1].nr_parts, onenandcs); if (nandcs > GPMC_CS_NUM) - printk(KERN_INFO "NAND: Unable to find configuration " - "in GPMC\n"); + pr_err("NAND: Unable to find configuration in GPMC\n"); else board_nand_init(partition_info[2].parts, - partition_info[2].nr_parts, nandcs); + partition_info[2].nr_parts, nandcs, nand_type); } diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h index 69befe00dd2f..c240a3f8d163 100644 --- a/arch/arm/mach-omap2/board-flash.h +++ b/arch/arm/mach-omap2/board-flash.h @@ -25,6 +25,6 @@ struct flash_partitions { }; extern void board_flash_init(struct flash_partitions [], - char chip_sel[][GPMC_CS_NUM]); + char chip_sel[][GPMC_CS_NUM], int nand_type); extern void board_nand_init(struct mtd_partition *nand_parts, - u8 nr_parts, u8 cs); + u8 nr_parts, u8 cs, int nand_type); diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index d8eb2cb7cbc7..a3fae5697a72 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -433,7 +433,7 @@ static void __init omap_ldp_init(void) omap_serial_init(); usb_musb_init(&musb_board_data); board_nand_init(ldp_nand_partitions, - ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS); + ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0); omap2_hsmmc_init(mmc); /* link regulators to MMC adapters */ diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index c2a0fca4aa53..d4a115712290 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -30,6 +30,8 @@ #include <linux/usb/otg.h> #include <linux/smsc911x.h> +#include <linux/wl12xx.h> +#include <linux/regulator/fixed.h> #include <linux/regulator/machine.h> #include <linux/mmc/host.h> @@ -58,6 +60,13 @@ #define OMAP3EVM_ETHR_ID_REV 0x50 #define OMAP3EVM_ETHR_GPIO_IRQ 176 #define OMAP3EVM_SMSC911X_CS 5 +/* + * Eth Reset signal + * 64 = Generation 1 (<=RevD) + * 7 = Generation 2 (>=RevE) + */ +#define OMAP3EVM_GEN1_ETHR_GPIO_RST 64 +#define OMAP3EVM_GEN2_ETHR_GPIO_RST 7 static u8 omap3_evm_version; @@ -124,10 +133,15 @@ static struct platform_device omap3evm_smsc911x_device = { static inline void __init omap3evm_init_smsc911x(void) { - int eth_cs; + int eth_cs, eth_rst; struct clk *l3ck; unsigned int rate; + if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1) + eth_rst = OMAP3EVM_GEN1_ETHR_GPIO_RST; + else + eth_rst = OMAP3EVM_GEN2_ETHR_GPIO_RST; + eth_cs = OMAP3EVM_SMSC911X_CS; l3ck = clk_get(NULL, "l3_ck"); @@ -136,6 +150,27 @@ static inline void __init omap3evm_init_smsc911x(void) else rate = clk_get_rate(l3ck); + /* Configure ethernet controller reset gpio */ + if (cpu_is_omap3430()) { + if (gpio_request(eth_rst, "SMSC911x gpio") < 0) { + pr_err(KERN_ERR "Failed to request %d for smsc911x\n", + eth_rst); + return; + } + + if (gpio_direction_output(eth_rst, 1) < 0) { + pr_err(KERN_ERR "Failed to set direction of %d for" \ + " smsc911x\n", eth_rst); + return; + } + /* reset pulse to ethernet controller*/ + usleep_range(150, 220); + gpio_set_value(eth_rst, 0); + usleep_range(150, 220); + gpio_set_value(eth_rst, 1); + usleep_range(1, 2); + } + if (gpio_request(OMAP3EVM_ETHR_GPIO_IRQ, "SMSC911x irq") < 0) { printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n", OMAP3EVM_ETHR_GPIO_IRQ); @@ -235,9 +270,9 @@ static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev) gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0); if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) - gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); + gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); else - gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); + gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); lcd_enabled = 1; return 0; @@ -248,9 +283,9 @@ static void omap3_evm_disable_lcd(struct omap_dss_device *dssdev) gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 1); if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) - gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); + gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1); else - gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); + gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0); lcd_enabled = 0; } @@ -289,7 +324,7 @@ static int omap3_evm_enable_dvi(struct omap_dss_device *dssdev) return -EINVAL; } - gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 1); + gpio_set_value_cansleep(OMAP3EVM_DVI_PANEL_EN_GPIO, 1); dvi_enabled = 1; return 0; @@ -297,7 +332,7 @@ static int omap3_evm_enable_dvi(struct omap_dss_device *dssdev) static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev) { - gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 0); + gpio_set_value_cansleep(OMAP3EVM_DVI_PANEL_EN_GPIO, 0); dvi_enabled = 0; } @@ -381,6 +416,16 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_cd = -EINVAL, .gpio_wp = 63, }, +#ifdef CONFIG_WL12XX_PLATFORM_DATA + { + .name = "wl1271", + .mmc = 2, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, + .gpio_wp = -EINVAL, + .gpio_cd = -EINVAL, + .nonremovable = true, + }, +#endif {} /* Terminator */ }; @@ -411,6 +456,8 @@ static struct platform_device leds_gpio = { static int omap3evm_twl_gpio_setup(struct device *dev, unsigned gpio, unsigned ngpio) { + int r; + /* gpio + 0 is "mmc0_cd" (input/IRQ) */ omap_mux_init_gpio(63, OMAP_PIN_INPUT); mmc[0].gpio_cd = gpio + 0; @@ -426,8 +473,12 @@ static int omap3evm_twl_gpio_setup(struct device *dev, */ /* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */ - gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL"); - gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); + r = gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL"); + if (!r) + r = gpio_direction_output(gpio + TWL4030_GPIO_MAX, + (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) ? 1 : 0); + if (r) + printk(KERN_ERR "failed to get/set lcd_bkl gpio\n"); /* gpio + 7 == DVI Enable */ gpio_request(gpio + 7, "EN_DVI"); @@ -538,6 +589,69 @@ static struct regulator_init_data omap3_evm_vpll2 = { .consumer_supplies = &omap3_evm_vpll2_supply, }; +/* ads7846 on SPI */ +static struct regulator_consumer_supply omap3evm_vio_supply = + REGULATOR_SUPPLY("vcc", "spi1.0"); + +/* VIO for ads7846 */ +static struct regulator_init_data omap3evm_vio = { + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .apply_uV = true, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &omap3evm_vio_supply, +}; + +#ifdef CONFIG_WL12XX_PLATFORM_DATA + +#define OMAP3EVM_WLAN_PMENA_GPIO (150) +#define OMAP3EVM_WLAN_IRQ_GPIO (149) + +static struct regulator_consumer_supply omap3evm_vmmc2_supply = { + .supply = "vmmc", + .dev_name = "mmci-omap-hs.1", +}; + +/* VMMC2 for driving the WL12xx module */ +static struct regulator_init_data omap3evm_vmmc2 = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &omap3evm_vmmc2_supply, +}; + +static struct fixed_voltage_config omap3evm_vwlan = { + .supply_name = "vwl1271", + .microvolts = 1800000, /* 1.80V */ + .gpio = OMAP3EVM_WLAN_PMENA_GPIO, + .startup_delay = 70000, /* 70ms */ + .enable_high = 1, + .enabled_at_boot = 0, + .init_data = &omap3evm_vmmc2, +}; + +static struct platform_device omap3evm_vwlan_device = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &omap3evm_vwlan, + }, +}; + +struct wl12xx_platform_data omap3evm_wlan_data __initdata = { + .irq = OMAP_GPIO_IRQ(OMAP3EVM_WLAN_IRQ_GPIO), + /* ref clock is 38.4 MHz */ + .board_ref_clock = 2, +}; +#endif + static struct twl4030_platform_data omap3evm_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, @@ -550,6 +664,7 @@ static struct twl4030_platform_data omap3evm_twldata = { .codec = &omap3evm_codec_data, .vdac = &omap3_evm_vdac, .vpll2 = &omap3_evm_vpll2, + .vio = &omap3evm_vio, }; static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = { @@ -651,14 +766,61 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = { }; #ifdef CONFIG_OMAP_MUX -static struct omap_board_mux board_mux[] __initdata = { +static struct omap_board_mux omap35x_board_mux[] __initdata = { + OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP | + OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW | + OMAP_PIN_OFF_WAKEUPENABLE), + OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP | + OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW | + OMAP_PIN_OFF_WAKEUPENABLE), + OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP | + OMAP_PIN_OFF_NONE), + OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP | + OMAP_PIN_OFF_NONE), +#ifdef CONFIG_WL12XX_PLATFORM_DATA + /* WLAN IRQ - GPIO 149 */ + OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP), + + /* WLAN POWER ENABLE - GPIO 150 */ + OMAP3_MUX(UART1_CTS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT), + + /* MMC2 SDIO pin muxes for WL12xx */ + OMAP3_MUX(SDMMC2_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP3_MUX(SDMMC2_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP3_MUX(SDMMC2_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP3_MUX(SDMMC2_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP3_MUX(SDMMC2_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP3_MUX(SDMMC2_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), +#endif + { .reg_offset = OMAP_MUX_TERMINATOR }, +}; + +static struct omap_board_mux omap36x_board_mux[] __initdata = { OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW | OMAP_PIN_OFF_WAKEUPENABLE), OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP | - OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW), + OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW | + OMAP_PIN_OFF_WAKEUPENABLE), + /* AM/DM37x EVM: DSS data bus muxed with sys_boot */ + OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(SYS_BOOT0, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(SYS_BOOT1, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(SYS_BOOT3, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), + { .reg_offset = OMAP_MUX_TERMINATOR }, }; +#else +#define omap35x_board_mux NULL +#define omap36x_board_mux NULL #endif static struct omap_musb_board_data musb_board_data = { @@ -670,7 +832,11 @@ static struct omap_musb_board_data musb_board_data = { static void __init omap3_evm_init(void) { omap3_evm_get_revision(); - omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); + + if (cpu_is_omap3630()) + omap3_mux_init(omap36x_board_mux, OMAP_PACKAGE_CBB); + else + omap3_mux_init(omap35x_board_mux, OMAP_PACKAGE_CBB); omap3_evm_i2c_init(); @@ -714,6 +880,13 @@ static void __init omap3_evm_init(void) ads7846_dev_init(); omap3evm_init_smsc911x(); omap3_evm_display_init(); + +#ifdef CONFIG_WL12XX_PLATFORM_DATA + /* WL12xx WLAN Init */ + if (wl12xx_set_platform_data(&omap3evm_wlan_data)) + pr_err("error setting wl12xx data\n"); + platform_device_register(&omap3evm_vwlan_device); +#endif } MACHINE_START(OMAP3EVM, "OMAP3 EVM") diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index fca5b9e80c18..3dd241b95159 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c @@ -26,6 +26,8 @@ #include <linux/usb/otg.h> #include <linux/i2c/twl.h> #include <linux/regulator/machine.h> +#include <linux/regulator/fixed.h> +#include <linux/wl12xx.h> #include <mach/hardware.h> #include <mach/omap4-common.h> @@ -45,6 +47,8 @@ #define GPIO_HUB_POWER 1 #define GPIO_HUB_NRESET 62 +#define GPIO_WIFI_PMENA 43 +#define GPIO_WIFI_IRQ 53 static struct gpio_led gpio_leds[] = { { @@ -161,6 +165,15 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_wp = -EINVAL, .gpio_cd = -EINVAL, }, + { + .name = "wl1271", + .mmc = 5, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, + .gpio_wp = -EINVAL, + .gpio_cd = -EINVAL, + .ocr_mask = MMC_VDD_165_195, + .nonremovable = true, + }, {} /* Terminator */ }; @@ -171,6 +184,43 @@ static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = { }, }; +static struct regulator_consumer_supply omap4_panda_vmmc5_supply = { + .supply = "vmmc", + .dev_name = "mmci-omap-hs.4", +}; + +static struct regulator_init_data panda_vmmc5 = { + .constraints = { + .valid_ops_mask = REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &omap4_panda_vmmc5_supply, +}; + +static struct fixed_voltage_config panda_vwlan = { + .supply_name = "vwl1271", + .microvolts = 1800000, /* 1.8V */ + .gpio = GPIO_WIFI_PMENA, + .startup_delay = 70000, /* 70msec */ + .enable_high = 1, + .enabled_at_boot = 0, + .init_data = &panda_vmmc5, +}; + +static struct platform_device omap_vwlan_device = { + .name = "reg-fixed-voltage", + .id = 1, + .dev = { + .platform_data = &panda_vwlan, + }, +}; + +struct wl12xx_platform_data omap_panda_wlan_data __initdata = { + .irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ), + /* PANDA ref clock is 38.4 MHz */ + .board_ref_clock = 2, +}; + static int omap4_twl6030_hsmmc_late_init(struct device *dev) { int ret = 0; @@ -304,7 +354,6 @@ static struct regulator_init_data omap4_panda_vana = { .constraints = { .min_uV = 2100000, .max_uV = 2100000, - .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE @@ -316,7 +365,6 @@ static struct regulator_init_data omap4_panda_vcxio = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, - .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE @@ -328,7 +376,6 @@ static struct regulator_init_data omap4_panda_vdac = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, - .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE @@ -390,6 +437,19 @@ static int __init omap4_panda_i2c_init(void) #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { + /* WLAN IRQ - GPIO 53 */ + OMAP4_MUX(GPMC_NCS3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), + /* WLAN POWER ENABLE - GPIO 43 */ + OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT), + /* WLAN SDIO: MMC5 CMD */ + OMAP4_MUX(SDMMC5_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + /* WLAN SDIO: MMC5 CLK */ + OMAP4_MUX(SDMMC5_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + /* WLAN SDIO: MMC5 DAT[0-3] */ + OMAP4_MUX(SDMMC5_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), + OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP), { .reg_offset = OMAP_MUX_TERMINATOR }, }; #else @@ -404,8 +464,12 @@ static void __init omap4_panda_init(void) package = OMAP_PACKAGE_CBL; omap4_mux_init(board_mux, package); + if (wl12xx_set_platform_data(&omap_panda_wlan_data)) + pr_err("error setting wl12xx data\n"); + omap4_panda_i2c_init(); platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices)); + platform_device_register(&omap_vwlan_device); omap_serial_init(); omap4_twl6030_hsmmc_init(mmc); omap4_ehci_init(); diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c index 85d4170f30ab..7e3f1595d77b 100644 --- a/arch/arm/mach-omap2/board-zoom.c +++ b/arch/arm/mach-omap2/board-zoom.c @@ -16,6 +16,7 @@ #include <linux/input.h> #include <linux/gpio.h> #include <linux/i2c/twl.h> +#include <linux/mtd/nand.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -124,8 +125,8 @@ static void __init omap_zoom_init(void) usb_ehci_init(&ehci_pdata); } - board_nand_init(zoom_nand_partitions, - ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS); + board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions), + ZOOM_NAND_CS, NAND_BUSWIDTH_16); zoom_debugboard_init(); zoom_peripherals_init(); zoom_display_init(); diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c index a781cd6795a4..e25364de028a 100644 --- a/arch/arm/mach-omap2/clkt_clksel.c +++ b/arch/arm/mach-omap2/clkt_clksel.c @@ -97,7 +97,7 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk, u32 *field_val) { const struct clksel *clks; - const struct clksel_rate *clkr, *max_clkr; + const struct clksel_rate *clkr, *max_clkr = NULL; u8 max_div = 0; clks = _get_clksel_by_parent(clk, src_clk); diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 71f099b85e7c..9ee876fd367a 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -31,6 +31,7 @@ #include <plat/dma.h> #include <plat/omap_hwmod.h> #include <plat/omap_device.h> +#include <plat/omap4-keypad.h> #include "mux.h" #include "control.h" @@ -142,6 +143,46 @@ static inline void omap_init_camera(void) } #endif +struct omap_device_pm_latency omap_keyboard_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +int __init omap4_keyboard_init(struct omap4_keypad_platform_data + *sdp4430_keypad_data) +{ + struct omap_device *od; + struct omap_hwmod *oh; + struct omap4_keypad_platform_data *keypad_data; + unsigned int id = -1; + char *oh_name = "kbd"; + char *name = "omap4-keypad"; + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("Could not look up %s\n", oh_name); + return -ENODEV; + } + + keypad_data = sdp4430_keypad_data; + + od = omap_device_build(name, id, oh, keypad_data, + sizeof(struct omap4_keypad_platform_data), + omap_keyboard_latency, + ARRAY_SIZE(omap_keyboard_latency), 0); + + if (IS_ERR(od)) { + WARN(1, "Cant build omap_device for %s:%s.\n", + name, oh->name); + return PTR_ERR(od); + } + + return 0; +} + #if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE) #define MBOX_REG_SIZE 0x120 diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index 2bb29c160702..c1791d08ae56 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -12,6 +12,7 @@ #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/mtd/nand.h> #include <asm/mach/flash.h> @@ -69,8 +70,10 @@ static int omap2_nand_gpmc_retime(void) t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle); /* Configure GPMC */ - gpmc_cs_configure(gpmc_nand_data->cs, - GPMC_CONFIG_DEV_SIZE, gpmc_nand_data->devsize); + if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) + gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1); + else + gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0); gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND); err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t); diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 3a7d25fb00ef..d776ded9830d 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -94,7 +94,7 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) } static void set_onenand_cfg(void __iomem *onenand_base, int latency, - int sync_read, int sync_write, int hf) + int sync_read, int sync_write, int hf, int vhf) { u32 reg; @@ -114,12 +114,57 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency, reg |= ONENAND_SYS_CFG1_HF; else reg &= ~ONENAND_SYS_CFG1_HF; + if (vhf) + reg |= ONENAND_SYS_CFG1_VHF; + else + reg &= ~ONENAND_SYS_CFG1_VHF; writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); } +static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg, + void __iomem *onenand_base, bool *clk_dep) +{ + u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID); + int freq = 0; + + if (cfg->get_freq) { + struct onenand_freq_info fi; + + fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID); + fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID); + fi.ver_id = ver; + freq = cfg->get_freq(&fi, clk_dep); + if (freq) + return freq; + } + + switch ((ver >> 4) & 0xf) { + case 0: + freq = 40; + break; + case 1: + freq = 54; + break; + case 2: + freq = 66; + break; + case 3: + freq = 83; + break; + case 4: + freq = 104; + break; + default: + freq = 54; + break; + } + + return freq; +} + static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, void __iomem *onenand_base, - int freq) + int *freq_ptr) { struct gpmc_timings t; const int t_cer = 15; @@ -130,10 +175,11 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, const int t_wph = 30; int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; - int first_time = 0, hf = 0, sync_read = 0, sync_write = 0; + int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0; int err, ticks_cez; - int cs = cfg->cs; + int cs = cfg->cs, freq = *freq_ptr; u32 reg; + bool clk_dep = false; if (cfg->flags & ONENAND_SYNC_READ) { sync_read = 1; @@ -148,27 +194,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, err = omap2_onenand_set_async_mode(cs, onenand_base); if (err) return err; - reg = readw(onenand_base + ONENAND_REG_VERSION_ID); - switch ((reg >> 4) & 0xf) { - case 0: - freq = 40; - break; - case 1: - freq = 54; - break; - case 2: - freq = 66; - break; - case 3: - freq = 83; - break; - case 4: - freq = 104; - break; - default: - freq = 54; - break; - } + freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep); first_time = 1; } @@ -180,7 +206,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, t_avdh = 2; t_ach = 3; t_aavdh = 6; - t_rdyo = 9; + t_rdyo = 6; break; case 83: min_gpmc_clk_period = 12000; /* 83 MHz */ @@ -217,16 +243,36 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, gpmc_clk_ns = gpmc_ticks_to_ns(div); if (gpmc_clk_ns < 15) /* >66Mhz */ hf = 1; - if (hf) + if (gpmc_clk_ns < 12) /* >83Mhz */ + vhf = 1; + if (vhf) + latency = 8; + else if (hf) latency = 6; else if (gpmc_clk_ns >= 25) /* 40 MHz*/ latency = 3; else latency = 4; + if (clk_dep) { + if (gpmc_clk_ns < 12) { /* >83Mhz */ + t_ces = 3; + t_avds = 4; + } else if (gpmc_clk_ns < 15) { /* >66Mhz */ + t_ces = 5; + t_avds = 4; + } else if (gpmc_clk_ns < 25) { /* >40Mhz */ + t_ces = 6; + t_avds = 5; + } else { + t_ces = 7; + t_avds = 7; + } + } + if (first_time) set_onenand_cfg(onenand_base, latency, - sync_read, sync_write, hf); + sync_read, sync_write, hf, vhf); if (div == 1) { reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); @@ -264,6 +310,9 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, /* Read */ t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh)); t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach)); + /* Force at least 1 clk between AVD High to OE Low */ + if (t.oe_on <= t.adv_rd_off) + t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1); t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div); t.oe_off = t.access + gpmc_round_ns_to_ticks(1); t.cs_rd_off = t.oe_off; @@ -317,18 +366,20 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, if (err) return err; - set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf); + set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf); + + *freq_ptr = freq; return 0; } -static int gpmc_onenand_setup(void __iomem *onenand_base, int freq) +static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr) { struct device *dev = &gpmc_onenand_device.dev; /* Set sync timings in GPMC */ if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base, - freq) < 0) { + freq_ptr) < 0) { dev_err(dev, "Unable to set synchronous mode\n"); return -EINVAL; } diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 1b7b3e7d02f7..674174365f78 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -14,6 +14,7 @@ */ #undef DEBUG +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/err.h> @@ -22,6 +23,7 @@ #include <linux/spinlock.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/interrupt.h> #include <asm/mach-types.h> #include <plat/gpmc.h> @@ -58,7 +60,6 @@ #define GPMC_CHUNK_SHIFT 24 /* 16 MB */ #define GPMC_SECTION_SHIFT 28 /* 128 MB */ -#define PREFETCH_FIFOTHRESHOLD (0x40 << 8) #define CS_NUM_SHIFT 24 #define ENABLE_PREFETCH (0x1 << 7) #define DMA_MPU_MODE 2 @@ -100,6 +101,8 @@ static void __iomem *gpmc_base; static struct clk *gpmc_l3_clk; +static irqreturn_t gpmc_handle_irq(int irq, void *dev); + static void gpmc_write_reg(int idx, u32 val) { __raw_writel(val, gpmc_base + idx); @@ -497,6 +500,10 @@ int gpmc_cs_configure(int cs, int cmd, int wval) u32 regval = 0; switch (cmd) { + case GPMC_ENABLE_IRQ: + gpmc_write_reg(GPMC_IRQENABLE, wval); + break; + case GPMC_SET_IRQ_STATUS: gpmc_write_reg(GPMC_IRQSTATUS, wval); break; @@ -598,15 +605,19 @@ EXPORT_SYMBOL(gpmc_nand_write); /** * gpmc_prefetch_enable - configures and starts prefetch transfer * @cs: cs (chip select) number + * @fifo_th: fifo threshold to be used for read/ write * @dma_mode: dma mode enable (1) or disable (0) * @u32_count: number of bytes to be transferred * @is_write: prefetch read(0) or write post(1) mode */ -int gpmc_prefetch_enable(int cs, int dma_mode, +int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode, unsigned int u32_count, int is_write) { - if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { + if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) { + pr_err("gpmc: fifo threshold is not supported\n"); + return -1; + } else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { /* Set the amount of bytes to be prefetched */ gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count); @@ -614,7 +625,7 @@ int gpmc_prefetch_enable(int cs, int dma_mode, * enable the engine. Set which cs is has requested for. */ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) | - PREFETCH_FIFOTHRESHOLD | + PREFETCH_FIFOTHRESHOLD(fifo_th) | ENABLE_PREFETCH | (dma_mode << DMA_MPU_MODE) | (0x1 & is_write))); @@ -678,9 +689,10 @@ static void __init gpmc_mem_init(void) } } -void __init gpmc_init(void) +static int __init gpmc_init(void) { - u32 l; + u32 l, irq; + int cs, ret = -EINVAL; char *ck = NULL; if (cpu_is_omap24xx()) { @@ -698,7 +710,7 @@ void __init gpmc_init(void) } if (WARN_ON(!ck)) - return; + return ret; gpmc_l3_clk = clk_get(NULL, ck); if (IS_ERR(gpmc_l3_clk)) { @@ -723,6 +735,36 @@ void __init gpmc_init(void) l |= (0x02 << 3) | (1 << 0); gpmc_write_reg(GPMC_SYSCONFIG, l); gpmc_mem_init(); + + /* initalize the irq_chained */ + irq = OMAP_GPMC_IRQ_BASE; + for (cs = 0; cs < GPMC_CS_NUM; cs++) { + set_irq_handler(irq, handle_simple_irq); + set_irq_flags(irq, IRQF_VALID); + irq++; + } + + ret = request_irq(INT_34XX_GPMC_IRQ, + gpmc_handle_irq, IRQF_SHARED, "gpmc", gpmc_base); + if (ret) + pr_err("gpmc: irq-%d could not claim: err %d\n", + INT_34XX_GPMC_IRQ, ret); + return ret; +} +postcore_initcall(gpmc_init); + +static irqreturn_t gpmc_handle_irq(int irq, void *dev) +{ + u8 cs; + + if (irq != INT_34XX_GPMC_IRQ) + return IRQ_HANDLED; + /* check cs to invoke the irq */ + cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7; + if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END) + generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs); + + return IRQ_HANDLED; } #ifdef CONFIG_ARCH_OMAP3 diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 34272e4863fd..5496bc7d40ad 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -350,6 +350,11 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) mmc->slots[0].after_set_reg = NULL; } break; + case 4: + case 5: + mmc->slots[0].before_set_reg = NULL; + mmc->slots[0].after_set_reg = NULL; + break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); kfree(mmc); diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 5c25f1b55235..3168b17bc264 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -6,7 +6,7 @@ * Copyright (C) 2005 Nokia Corporation * Written by Tony Lindgren <tony@atomide.com> * - * Copyright (C) 2009 Texas Instruments + * Copyright (C) 2009-11 Texas Instruments * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> * * This program is free software; you can redistribute it and/or modify @@ -328,7 +328,7 @@ static void __init omap4_check_revision(void) */ idcode = read_tap_reg(OMAP_TAP_IDCODE); hawkeye = (idcode >> 12) & 0xffff; - rev = (idcode >> 28) & 0xff; + rev = (idcode >> 28) & 0xf; /* * Few initial ES2.0 samples IDCODE is same as ES1.0 @@ -347,22 +347,31 @@ static void __init omap4_check_revision(void) omap_chip.oc |= CHIP_IS_OMAP4430ES1; break; case 1: + default: omap_revision = OMAP4430_REV_ES2_0; omap_chip.oc |= CHIP_IS_OMAP4430ES2; + } + break; + case 0xb95c: + switch (rev) { + case 3: + omap_revision = OMAP4430_REV_ES2_1; + omap_chip.oc |= CHIP_IS_OMAP4430ES2_1; break; + case 4: default: - omap_revision = OMAP4430_REV_ES2_0; - omap_chip.oc |= CHIP_IS_OMAP4430ES2; - } - break; + omap_revision = OMAP4430_REV_ES2_2; + omap_chip.oc |= CHIP_IS_OMAP4430ES2_2; + } + break; default: - /* Unknown default to latest silicon rev as default*/ - omap_revision = OMAP4430_REV_ES2_0; - omap_chip.oc |= CHIP_IS_OMAP4430ES2; + /* Unknown default to latest silicon rev as default */ + omap_revision = OMAP4430_REV_ES2_2; + omap_chip.oc |= CHIP_IS_OMAP4430ES2_2; } - pr_info("OMAP%04x ES%d.0\n", - omap_rev() >> 16, ((omap_rev() >> 12) & 0xf) + 1); + pr_info("OMAP%04x ES%d.%d\n", omap_rev() >> 16, + ((omap_rev() >> 12) & 0xf), ((omap_rev() >> 8) & 0xf)); } #define OMAP3_SHOW_FEATURE(feat) \ diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index b8b49e4ae928..657f3c84687c 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -30,7 +30,6 @@ #include <plat/sram.h> #include <plat/sdrc.h> -#include <plat/gpmc.h> #include <plat/serial.h> #include "clock2xxx.h" @@ -422,7 +421,6 @@ void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0, omap2_sdrc_init(sdrc_cs0, sdrc_cs1); _omap2_init_reprogram_sdrc(); } - gpmc_init(); omap_irq_base_init(); } diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h index be99438d385e..8198bb6cdb5e 100644 --- a/arch/arm/plat-omap/include/plat/cpu.h +++ b/arch/arm/plat-omap/include/plat/cpu.h @@ -5,7 +5,7 @@ * * Copyright (C) 2004, 2008 Nokia Corporation * - * Copyright (C) 2009 Texas Instruments. + * Copyright (C) 2009-11 Texas Instruments. * * Written by Tony Lindgren <tony.lindgren@nokia.com> * @@ -405,8 +405,10 @@ IS_OMAP_TYPE(3517, 0x3517) #define TI8168_REV_ES1_1 (TI816X_CLASS | (OMAP_REVBITS_01 << 8)) #define OMAP443X_CLASS 0x44300044 -#define OMAP4430_REV_ES1_0 OMAP443X_CLASS -#define OMAP4430_REV_ES2_0 0x44301044 +#define OMAP4430_REV_ES1_0 (OMAP443X_CLASS | (0x10 << 8)) +#define OMAP4430_REV_ES2_0 (OMAP443X_CLASS | (0x20 << 8)) +#define OMAP4430_REV_ES2_1 (OMAP443X_CLASS | (0x21 << 8)) +#define OMAP4430_REV_ES2_2 (OMAP443X_CLASS | (0x22 << 8)) /* * omap_chip bits @@ -434,12 +436,16 @@ IS_OMAP_TYPE(3517, 0x3517) #define CHIP_IS_OMAP3630ES1_1 (1 << 9) #define CHIP_IS_OMAP3630ES1_2 (1 << 10) #define CHIP_IS_OMAP4430ES2 (1 << 11) +#define CHIP_IS_OMAP4430ES2_1 (1 << 12) +#define CHIP_IS_OMAP4430ES2_2 (1 << 13) #define CHIP_IS_TI816X (1 << 14) #define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430) -#define CHIP_IS_OMAP4430 (CHIP_IS_OMAP4430ES1 | \ - CHIP_IS_OMAP4430ES2) +#define CHIP_IS_OMAP4430 (CHIP_IS_OMAP4430ES1 | \ + CHIP_IS_OMAP4430ES2 | \ + CHIP_IS_OMAP4430ES2_1 | \ + CHIP_IS_OMAP4430ES2_2) /* * "GE" here represents "greater than or equal to" in terms of ES diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 85ded598853e..12b316165037 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -41,6 +41,8 @@ #define GPMC_NAND_ADDRESS 0x0000000b #define GPMC_NAND_DATA 0x0000000c +#define GPMC_ENABLE_IRQ 0x0000000d + /* ECC commands */ #define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ #define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ @@ -78,6 +80,19 @@ #define WR_RD_PIN_MONITORING 0x00600000 #define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F) #define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) +#define GPMC_IRQ_FIFOEVENTENABLE 0x01 +#define GPMC_IRQ_COUNT_EVENT 0x02 + +#define PREFETCH_FIFOTHRESHOLD_MAX 0x40 +#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8) + +enum omap_ecc { + /* 1-bit ecc: stored at end of spare area */ + OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */ + OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ + /* 1-bit ecc: stored at begining of spare area as romcode */ + OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ +}; /* * Note that all values in this struct are in nanoseconds except sync_clk @@ -130,12 +145,11 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); extern void gpmc_cs_free(int cs); extern int gpmc_cs_set_reserved(int cs, int reserved); extern int gpmc_cs_reserved(int cs); -extern int gpmc_prefetch_enable(int cs, int dma_mode, +extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode, unsigned int u32_count, int is_write); extern int gpmc_prefetch_reset(int cs); extern void omap3_gpmc_save_context(void); extern void omap3_gpmc_restore_context(void); -extern void gpmc_init(void); extern int gpmc_read_status(int cmd); extern int gpmc_cs_configure(int cs, int cmd, int wval); extern int gpmc_nand_read(int cs, int cmd); diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h index 69230d685538..19cbb5e9ece2 100644 --- a/arch/arm/plat-omap/include/plat/iommu.h +++ b/arch/arm/plat-omap/include/plat/iommu.h @@ -154,6 +154,8 @@ extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end); extern void flush_iotlb_all(struct iommu *obj); extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e); +extern void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, + u32 **ppte); extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova); extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end); diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index 2910de921c52..1b911681e911 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h @@ -318,6 +318,7 @@ #define INT_34XX_PRCM_MPU_IRQ 11 #define INT_34XX_MCBSP1_IRQ 16 #define INT_34XX_MCBSP2_IRQ 17 +#define INT_34XX_GPMC_IRQ 20 #define INT_34XX_MCBSP3_IRQ 22 #define INT_34XX_MCBSP4_IRQ 23 #define INT_34XX_CAM_IRQ 24 @@ -411,7 +412,13 @@ #define TWL_IRQ_END TWL6030_IRQ_END #endif -#define NR_IRQS TWL_IRQ_END +/* GPMC related */ +#define OMAP_GPMC_IRQ_BASE (TWL_IRQ_END) +#define OMAP_GPMC_NR_IRQS 7 +#define OMAP_GPMC_IRQ_END (OMAP_GPMC_IRQ_BASE + OMAP_GPMC_NR_IRQS) + + +#define NR_IRQS OMAP_GPMC_IRQ_END #define OMAP_IRQ_BIT(irq) (1 << ((irq) % 32)) diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index 6562cd082bb1..d86d1ecf0068 100644 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -8,8 +8,16 @@ * published by the Free Software Foundation. */ +#include <plat/gpmc.h> #include <linux/mtd/partitions.h> +enum nand_io { + NAND_OMAP_PREFETCH_POLLED = 0, /* prefetch polled mode, default */ + NAND_OMAP_POLLED, /* polled mode, without prefetch */ + NAND_OMAP_PREFETCH_DMA, /* prefetch enabled sDMA mode */ + NAND_OMAP_PREFETCH_IRQ /* prefetch enabled irq mode */ +}; + struct omap_nand_platform_data { unsigned int options; int cs; @@ -20,8 +28,11 @@ struct omap_nand_platform_data { int (*nand_setup)(void); int (*dev_ready)(struct omap_nand_platform_data *); int dma_channel; + int gpmc_irq; + enum nand_io xfer_type; unsigned long phys_base; int devsize; + enum omap_ecc ecc_opt; }; /* minimum size for IO mapping */ diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h index affe87e9ece7..cbe897ca7f9e 100644 --- a/arch/arm/plat-omap/include/plat/onenand.h +++ b/arch/arm/plat-omap/include/plat/onenand.h @@ -15,12 +15,20 @@ #define ONENAND_SYNC_READ (1 << 0) #define ONENAND_SYNC_READWRITE (1 << 1) +struct onenand_freq_info { + u16 maf_id; + u16 dev_id; + u16 ver_id; +}; + struct omap_onenand_platform_data { int cs; int gpio_irq; struct mtd_partition *parts; int nr_parts; - int (*onenand_setup)(void __iomem *, int freq); + int (*onenand_setup)(void __iomem *, int *freq_ptr); + int (*get_freq)(const struct onenand_freq_info *freq_info, + bool *clk_dep); int dma_channel; u8 flags; u8 regulator_can_sleep; diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index aedcb3be4e66..9d80064e979b 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -405,20 +405,6 @@ static inline int omap34xx_sram_init(void) } #endif -#ifdef CONFIG_ARCH_OMAP4 -static int __init omap44xx_sram_init(void) -{ - printk(KERN_ERR "FIXME: %s not implemented\n", __func__); - - return -ENODEV; -} -#else -static inline int omap44xx_sram_init(void) -{ - return 0; -} -#endif - int __init omap_sram_init(void) { omap_detect_sram(); @@ -432,8 +418,6 @@ int __init omap_sram_init(void) omap243x_sram_init(); else if (cpu_is_omap34xx()) omap34xx_sram_init(); - else if (cpu_is_omap44xx()) - omap44xx_sram_init(); return 0; } diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 078fdf11af03..8c42573f42ea 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -260,7 +260,7 @@ static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on, return ret; } -static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, +static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on, int vdd) { struct omap_hsmmc_host *host = @@ -316,6 +316,12 @@ static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, return ret; } +static int omap_hsmmc_4_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + return 0; +} + static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep, int vdd, int cardsleep) { @@ -326,7 +332,7 @@ static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep, return regulator_set_mode(host->vcc, mode); } -static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, +static int omap_hsmmc_235_set_sleep(struct device *dev, int slot, int sleep, int vdd, int cardsleep) { struct omap_hsmmc_host *host = @@ -365,6 +371,12 @@ static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, return regulator_enable(host->vcc_aux); } +static int omap_hsmmc_4_set_sleep(struct device *dev, int slot, int sleep, + int vdd, int cardsleep) +{ + return 0; +} + static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) { struct regulator *reg; @@ -379,10 +391,14 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) break; case OMAP_MMC2_DEVID: case OMAP_MMC3_DEVID: + case OMAP_MMC5_DEVID: /* Off-chip level shifting, or none */ - mmc_slot(host).set_power = omap_hsmmc_23_set_power; - mmc_slot(host).set_sleep = omap_hsmmc_23_set_sleep; + mmc_slot(host).set_power = omap_hsmmc_235_set_power; + mmc_slot(host).set_sleep = omap_hsmmc_235_set_sleep; break; + case OMAP_MMC4_DEVID: + mmc_slot(host).set_power = omap_hsmmc_4_set_power; + mmc_slot(host).set_sleep = omap_hsmmc_4_set_sleep; default: pr_err("MMC%d configuration not supported!\n", host->id); return -EINVAL; diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index c89592239bc7..178e2006063d 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -106,23 +106,6 @@ config MTD_NAND_OMAP2 help Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms. -config MTD_NAND_OMAP_PREFETCH - bool "GPMC prefetch support for NAND Flash device" - depends on MTD_NAND_OMAP2 - default y - help - The NAND device can be accessed for Read/Write using GPMC PREFETCH engine - to improve the performance. - -config MTD_NAND_OMAP_PREFETCH_DMA - depends on MTD_NAND_OMAP_PREFETCH - bool "DMA mode" - default n - help - The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode - or in DMA interrupt mode. - Say y for DMA mode or MPU mode will be used - config MTD_NAND_IDS tristate diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 15682ec8530e..4e33972ad17a 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -11,6 +11,7 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/delay.h> +#include <linux/interrupt.h> #include <linux/jiffies.h> #include <linux/sched.h> #include <linux/mtd/mtd.h> @@ -24,6 +25,7 @@ #include <plat/nand.h> #define DRIVER_NAME "omap2-nand" +#define OMAP_NAND_TIMEOUT_MS 5000 #define NAND_Ecc_P1e (1 << 0) #define NAND_Ecc_P2e (1 << 1) @@ -96,26 +98,19 @@ static const char *part_probes[] = { "cmdlinepart", NULL }; #endif -#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH -static int use_prefetch = 1; - -/* "modprobe ... use_prefetch=0" etc */ -module_param(use_prefetch, bool, 0); -MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH"); - -#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA -static int use_dma = 1; +/* oob info generated runtime depending on ecc algorithm and layout selected */ +static struct nand_ecclayout omap_oobinfo; +/* Define some generic bad / good block scan pattern which are used + * while scanning a device for factory marked good / bad blocks + */ +static uint8_t scan_ff_pattern[] = { 0xff }; +static struct nand_bbt_descr bb_descrip_flashbased = { + .options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES, + .offs = 0, + .len = 1, + .pattern = scan_ff_pattern, +}; -/* "modprobe ... use_dma=0" etc */ -module_param(use_dma, bool, 0); -MODULE_PARM_DESC(use_dma, "enable/disable use of DMA"); -#else -static const int use_dma; -#endif -#else -const int use_prefetch; -static const int use_dma; -#endif struct omap_nand_info { struct nand_hw_control controller; @@ -129,6 +124,13 @@ struct omap_nand_info { unsigned long phys_base; struct completion comp; int dma_ch; + int gpmc_irq; + enum { + OMAP_NAND_IO_READ = 0, /* read */ + OMAP_NAND_IO_WRITE, /* write */ + } iomode; + u_char *buf; + int buf_len; }; /** @@ -256,7 +258,8 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) } /* configure and start prefetch transfer */ - ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0); + ret = gpmc_prefetch_enable(info->gpmc_cs, + PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0); if (ret) { /* PFPW engine is busy, use cpu copy method */ if (info->nand.options & NAND_BUSWIDTH_16) @@ -288,9 +291,10 @@ static void omap_write_buf_pref(struct mtd_info *mtd, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - uint32_t pref_count = 0, w_count = 0; + uint32_t w_count = 0; int i = 0, ret = 0; u16 *p; + unsigned long tim, limit; /* take care of subpage writes */ if (len % 2 != 0) { @@ -300,7 +304,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd, } /* configure and start prefetch transfer */ - ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1); + ret = gpmc_prefetch_enable(info->gpmc_cs, + PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1); if (ret) { /* PFPW engine is busy, use cpu copy method */ if (info->nand.options & NAND_BUSWIDTH_16) @@ -316,15 +321,17 @@ static void omap_write_buf_pref(struct mtd_info *mtd, iowrite16(*p++, info->nand.IO_ADDR_W); } /* wait for data to flushed-out before reset the prefetch */ - do { - pref_count = gpmc_read_status(GPMC_PREFETCH_COUNT); - } while (pref_count); + tim = 0; + limit = (loops_per_jiffy * + msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); + while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit)) + cpu_relax(); + /* disable and stop the PFPW engine */ gpmc_prefetch_reset(info->gpmc_cs); } } -#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA /* * omap_nand_dma_cb: callback on the completion of dma transfer * @lch: logical channel @@ -348,14 +355,15 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - uint32_t prefetch_status = 0; enum dma_data_direction dir = is_write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; dma_addr_t dma_addr; int ret; + unsigned long tim, limit; - /* The fifo depth is 64 bytes. We have a sync at each frame and frame - * length is 64 bytes. + /* The fifo depth is 64 bytes max. + * But configure the FIFO-threahold to 32 to get a sync at each frame + * and frame length is 32 bytes. */ int buf_len = len >> 6; @@ -396,9 +404,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC); } /* configure and start prefetch transfer */ - ret = gpmc_prefetch_enable(info->gpmc_cs, 0x1, len, is_write); + ret = gpmc_prefetch_enable(info->gpmc_cs, + PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write); if (ret) - /* PFPW engine is busy, use cpu copy methode */ + /* PFPW engine is busy, use cpu copy method */ goto out_copy; init_completion(&info->comp); @@ -407,10 +416,11 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, /* setup and start DMA using dma_addr */ wait_for_completion(&info->comp); + tim = 0; + limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); + while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit)) + cpu_relax(); - do { - prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT); - } while (prefetch_status); /* disable and stop the PFPW engine */ gpmc_prefetch_reset(info->gpmc_cs); @@ -426,14 +436,6 @@ out_copy: : omap_write_buf8(mtd, (u_char *) addr, len); return 0; } -#else -static void omap_nand_dma_cb(int lch, u16 ch_status, void *data) {} -static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, - unsigned int len, int is_write) -{ - return 0; -} -#endif /** * omap_read_buf_dma_pref - read data from NAND controller into buffer @@ -466,6 +468,157 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd, omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); } +/* + * omap_nand_irq - GMPC irq handler + * @this_irq: gpmc irq number + * @dev: omap_nand_info structure pointer is passed here + */ +static irqreturn_t omap_nand_irq(int this_irq, void *dev) +{ + struct omap_nand_info *info = (struct omap_nand_info *) dev; + u32 bytes; + u32 irq_stat; + + irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS); + bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT); + bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */ + if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ + if (irq_stat & 0x2) + goto done; + + if (info->buf_len && (info->buf_len < bytes)) + bytes = info->buf_len; + else if (!info->buf_len) + bytes = 0; + iowrite32_rep(info->nand.IO_ADDR_W, + (u32 *)info->buf, bytes >> 2); + info->buf = info->buf + bytes; + info->buf_len -= bytes; + + } else { + ioread32_rep(info->nand.IO_ADDR_R, + (u32 *)info->buf, bytes >> 2); + info->buf = info->buf + bytes; + + if (irq_stat & 0x2) + goto done; + } + gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); + + return IRQ_HANDLED; + +done: + complete(&info->comp); + /* disable irq */ + gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0); + + /* clear status */ + gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); + + return IRQ_HANDLED; +} + +/* + * omap_read_buf_irq_pref - read data from NAND controller into buffer + * @mtd: MTD device structure + * @buf: buffer to store date + * @len: number of bytes to read + */ +static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len) +{ + struct omap_nand_info *info = container_of(mtd, + struct omap_nand_info, mtd); + int ret = 0; + + if (len <= mtd->oobsize) { + omap_read_buf_pref(mtd, buf, len); + return; + } + + info->iomode = OMAP_NAND_IO_READ; + info->buf = buf; + init_completion(&info->comp); + + /* configure and start prefetch transfer */ + ret = gpmc_prefetch_enable(info->gpmc_cs, + PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0); + if (ret) + /* PFPW engine is busy, use cpu copy method */ + goto out_copy; + + info->buf_len = len; + /* enable irq */ + gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, + (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + /* waiting for read to complete */ + wait_for_completion(&info->comp); + + /* disable and stop the PFPW engine */ + gpmc_prefetch_reset(info->gpmc_cs); + return; + +out_copy: + if (info->nand.options & NAND_BUSWIDTH_16) + omap_read_buf16(mtd, buf, len); + else + omap_read_buf8(mtd, buf, len); +} + +/* + * omap_write_buf_irq_pref - write buffer to NAND controller + * @mtd: MTD device structure + * @buf: data buffer + * @len: number of bytes to write + */ +static void omap_write_buf_irq_pref(struct mtd_info *mtd, + const u_char *buf, int len) +{ + struct omap_nand_info *info = container_of(mtd, + struct omap_nand_info, mtd); + int ret = 0; + unsigned long tim, limit; + + if (len <= mtd->oobsize) { + omap_write_buf_pref(mtd, buf, len); + return; + } + + info->iomode = OMAP_NAND_IO_WRITE; + info->buf = (u_char *) buf; + init_completion(&info->comp); + + /* configure and start prefetch transfer : size=24 */ + ret = gpmc_prefetch_enable(info->gpmc_cs, + (PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1); + if (ret) + /* PFPW engine is busy, use cpu copy method */ + goto out_copy; + + info->buf_len = len; + /* enable irq */ + gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, + (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); + + /* waiting for write to complete */ + wait_for_completion(&info->comp); + /* wait for data to flushed-out before reset the prefetch */ + tim = 0; + limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); + while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit)) + cpu_relax(); + + /* disable and stop the PFPW engine */ + gpmc_prefetch_reset(info->gpmc_cs); + return; + +out_copy: + if (info->nand.options & NAND_BUSWIDTH_16) + omap_write_buf16(mtd, buf, len); + else + omap_write_buf8(mtd, buf, len); +} + /** * omap_verify_buf - Verify chip data against buffer * @mtd: MTD device structure @@ -487,8 +640,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len) return 0; } -#ifdef CONFIG_MTD_NAND_OMAP_HWECC - /** * gen_true_ecc - This function will generate true ECC value * @ecc_buf: buffer to store ecc code @@ -708,8 +859,6 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size); } -#endif - /** * omap_wait - wait until the command is done * @mtd: MTD device structure @@ -779,6 +928,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) struct omap_nand_info *info; struct omap_nand_platform_data *pdata; int err; + int i, offset; pdata = pdev->dev.platform_data; if (pdata == NULL) { @@ -804,7 +954,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->mtd.name = dev_name(&pdev->dev); info->mtd.owner = THIS_MODULE; - info->nand.options |= pdata->devsize ? NAND_BUSWIDTH_16 : 0; + info->nand.options = pdata->devsize; info->nand.options |= NAND_SKIP_BBTSCAN; /* NAND write protect off */ @@ -842,28 +992,13 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->nand.chip_delay = 50; } - if (use_prefetch) { - + switch (pdata->xfer_type) { + case NAND_OMAP_PREFETCH_POLLED: info->nand.read_buf = omap_read_buf_pref; info->nand.write_buf = omap_write_buf_pref; - if (use_dma) { - err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND", - omap_nand_dma_cb, &info->comp, &info->dma_ch); - if (err < 0) { - info->dma_ch = -1; - printk(KERN_WARNING "DMA request failed." - " Non-dma data transfer mode\n"); - } else { - omap_set_dma_dest_burst_mode(info->dma_ch, - OMAP_DMA_DATA_BURST_16); - omap_set_dma_src_burst_mode(info->dma_ch, - OMAP_DMA_DATA_BURST_16); - - info->nand.read_buf = omap_read_buf_dma_pref; - info->nand.write_buf = omap_write_buf_dma_pref; - } - } - } else { + break; + + case NAND_OMAP_POLLED: if (info->nand.options & NAND_BUSWIDTH_16) { info->nand.read_buf = omap_read_buf16; info->nand.write_buf = omap_write_buf16; @@ -871,20 +1006,61 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->nand.read_buf = omap_read_buf8; info->nand.write_buf = omap_write_buf8; } + break; + + case NAND_OMAP_PREFETCH_DMA: + err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND", + omap_nand_dma_cb, &info->comp, &info->dma_ch); + if (err < 0) { + info->dma_ch = -1; + dev_err(&pdev->dev, "DMA request failed!\n"); + goto out_release_mem_region; + } else { + omap_set_dma_dest_burst_mode(info->dma_ch, + OMAP_DMA_DATA_BURST_16); + omap_set_dma_src_burst_mode(info->dma_ch, + OMAP_DMA_DATA_BURST_16); + + info->nand.read_buf = omap_read_buf_dma_pref; + info->nand.write_buf = omap_write_buf_dma_pref; + } + break; + + case NAND_OMAP_PREFETCH_IRQ: + err = request_irq(pdata->gpmc_irq, + omap_nand_irq, IRQF_SHARED, "gpmc-nand", info); + if (err) { + dev_err(&pdev->dev, "requesting irq(%d) error:%d", + pdata->gpmc_irq, err); + goto out_release_mem_region; + } else { + info->gpmc_irq = pdata->gpmc_irq; + info->nand.read_buf = omap_read_buf_irq_pref; + info->nand.write_buf = omap_write_buf_irq_pref; + } + break; + + default: + dev_err(&pdev->dev, + "xfer_type(%d) not supported!\n", pdata->xfer_type); + err = -EINVAL; + goto out_release_mem_region; } - info->nand.verify_buf = omap_verify_buf; -#ifdef CONFIG_MTD_NAND_OMAP_HWECC - info->nand.ecc.bytes = 3; - info->nand.ecc.size = 512; - info->nand.ecc.calculate = omap_calculate_ecc; - info->nand.ecc.hwctl = omap_enable_hwecc; - info->nand.ecc.correct = omap_correct_data; - info->nand.ecc.mode = NAND_ECC_HW; + info->nand.verify_buf = omap_verify_buf; -#else - info->nand.ecc.mode = NAND_ECC_SOFT; -#endif + /* selsect the ecc type */ + if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT) + info->nand.ecc.mode = NAND_ECC_SOFT; + else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) || + (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) { + info->nand.ecc.bytes = 3; + info->nand.ecc.size = 512; + info->nand.ecc.calculate = omap_calculate_ecc; + info->nand.ecc.hwctl = omap_enable_hwecc; + info->nand.ecc.correct = omap_correct_data; + info->nand.ecc.mode = NAND_ECC_HW; + } /* DIP switches on some boards change between 8 and 16 bit * bus widths for flash. Try the other width if the first try fails. @@ -897,6 +1073,26 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) } } + /* rom code layout */ + if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) { + + if (info->nand.options & NAND_BUSWIDTH_16) + offset = 2; + else { + offset = 1; + info->nand.badblock_pattern = &bb_descrip_flashbased; + } + omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16); + for (i = 0; i < omap_oobinfo.eccbytes; i++) + omap_oobinfo.eccpos[i] = i+offset; + + omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes; + omap_oobinfo.oobfree->length = info->mtd.oobsize - + (offset + omap_oobinfo.eccbytes); + + info->nand.ecc.layout = &omap_oobinfo; + } + #ifdef CONFIG_MTD_PARTITIONS err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); if (err > 0) @@ -926,9 +1122,12 @@ static int omap_nand_remove(struct platform_device *pdev) mtd); platform_set_drvdata(pdev, NULL); - if (use_dma) + if (info->dma_ch != -1) omap_free_dma(info->dma_ch); + if (info->gpmc_irq) + free_irq(info->gpmc_irq, info); + /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); iounmap(info->nand.IO_ADDR_R); @@ -947,16 +1146,8 @@ static struct platform_driver omap_nand_driver = { static int __init omap_nand_init(void) { - printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME); + pr_info("%s driver initializing\n", DRIVER_NAME); - /* This check is required if driver is being - * loaded run time as a module - */ - if ((1 == use_dma) && (0 == use_prefetch)) { - printk(KERN_INFO"Wrong parameters: 'use_dma' can not be 1 " - "without use_prefetch'. Prefetch will not be" - " used in either mode (mpu or dma)\n"); - } return platform_driver_register(&omap_nand_driver); } diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index ac31f461cc1c..ec26399e3cf2 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -63,7 +63,7 @@ struct omap2_onenand { struct completion dma_done; int dma_channel; int freq; - int (*setup)(void __iomem *base, int freq); + int (*setup)(void __iomem *base, int *freq_ptr); struct regulator *regulator; }; @@ -148,11 +148,9 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state) wait_err("controller error", state, ctrl, intr); return -EIO; } - if ((intr & intr_flags) != intr_flags) { - wait_err("timeout", state, ctrl, intr); - return -EIO; - } - return 0; + if ((intr & intr_flags) == intr_flags) + return 0; + /* Continue in wait for interrupt branch */ } if (state != FL_READING) { @@ -581,7 +579,7 @@ static int __adjust_timing(struct device *dev, void *data) /* DMA is not in use so this is all that is needed */ /* Revisit for OMAP3! */ - ret = c->setup(c->onenand.base, c->freq); + ret = c->setup(c->onenand.base, &c->freq); return ret; } @@ -673,7 +671,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) } if (pdata->onenand_setup != NULL) { - r = pdata->onenand_setup(c->onenand.base, c->freq); + r = pdata->onenand_setup(c->onenand.base, &c->freq); if (r < 0) { dev_err(&pdev->dev, "Onenand platform setup failed: " "%d\n", r); @@ -718,8 +716,8 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) } dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual " - "base %p\n", c->gpmc_cs, c->phys_base, - c->onenand.base); + "base %p, freq %d MHz\n", c->gpmc_cs, c->phys_base, + c->onenand.base, c->freq); c->pdev = pdev; c->mtd.name = dev_name(&pdev->dev); @@ -754,24 +752,6 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev) if ((r = onenand_scan(&c->mtd, 1)) < 0) goto err_release_regulator; - switch ((c->onenand.version_id >> 4) & 0xf) { - case 0: - c->freq = 40; - break; - case 1: - c->freq = 54; - break; - case 2: - c->freq = 66; - break; - case 3: - c->freq = 83; - break; - case 4: - c->freq = 104; - break; - } - #ifdef CONFIG_MTD_PARTITIONS r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0); if (r > 0) diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h index cd6f3b431195..d60130f88eed 100644 --- a/include/linux/mtd/onenand_regs.h +++ b/include/linux/mtd/onenand_regs.h @@ -168,6 +168,7 @@ #define ONENAND_SYS_CFG1_INT (1 << 6) #define ONENAND_SYS_CFG1_IOBE (1 << 5) #define ONENAND_SYS_CFG1_RDY_CONF (1 << 4) +#define ONENAND_SYS_CFG1_VHF (1 << 3) #define ONENAND_SYS_CFG1_HF (1 << 2) #define ONENAND_SYS_CFG1_SYNC_WRITE (1 << 1) |