diff options
26 files changed, 553 insertions, 1355 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e3a96e42193c..0d6469a2cf70 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6702,6 +6702,14 @@ L: linux-omap@vger.kernel.org S: Maintained F: sound/soc/omap/ +OMAP GENERAL PURPOSE MEMORY CONTROLLER SUPPORT +M: Roger Quadros <rogerq@ti.com> +M: Tony Lindgren <tony@atomide.com> +L: linux-omap@vger.kernel.org +S: Maintained +F: drivers/memory/omap-gpmc.c +F: arch/arm/mach-omap2/*gpmc* + OMAP FRAMEBUFFER SUPPORT M: Tomi Valkeinen <tomi.valkeinen@ti.com> L: linux-fbdev@vger.kernel.org diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index f4d06aea8460..6e249324fdd7 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -79,7 +79,9 @@ config ARCH_OMAP2PLUS select CLKSRC_MMIO select GENERIC_IRQ_CHIP select MACH_OMAP_GENERIC + select MEMORY select OMAP_DM_TIMER + select OMAP_GPMC select PINCTRL select SOC_BUS select TI_PRIV_EDMA @@ -235,12 +237,6 @@ config MACH_TOUCHBOOK default y select OMAP_PACKAGE_CBB -config MACH_OMAP_3430SDP - bool "OMAP 3430 SDP board" - depends on ARCH_OMAP3 - default y - select OMAP_PACKAGE_CBB - config MACH_NOKIA_N810 bool @@ -282,16 +278,6 @@ config MACH_SBC3530 default y select OMAP_PACKAGE_CUS -config MACH_TI8168EVM - bool "TI8168 Evaluation Module" - depends on SOC_TI81XX - default y - -config MACH_TI8148EVM - bool "TI8148 Evaluation Module" - depends on SOC_TI81XX - default y - config OMAP3_EMU bool "OMAP3 debugging peripherals" depends on ARCH_OMAP3 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 3b653b3ac268..08cc94474d17 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -6,7 +6,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ -I$(srctree)/arch/arm/plat-omap/include # Common support -obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o gpmc.o timer.o pm.o \ +obj-y := id.o io.o control.o mux.o devices.o fb.o serial.o timer.o pm.o \ common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o omap_hwmod.o \ omap_device.o sram.o drm.o @@ -246,7 +246,6 @@ obj-$(CONFIG_MACH_OMAP3530_LV_SOM) += board-omap3logic.o obj-$(CONFIG_MACH_OMAP3_TORPEDO) += board-omap3logic.o obj-$(CONFIG_MACH_OVERO) += board-overo.o obj-$(CONFIG_MACH_OMAP3_PANDORA) += board-omap3pandora.o -obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o obj-$(CONFIG_MACH_NOKIA_N8X0) += board-n8x0.o obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o sdram-nokia.o obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51-peripherals.o @@ -260,8 +259,6 @@ obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o obj-$(CONFIG_MACH_SBC3530) += board-omap3stalker.o -obj-$(CONFIG_MACH_TI8168EVM) += board-ti8168evm.o -obj-$(CONFIG_MACH_TI8148EVM) += board-ti8168evm.o # Platform specific device init code @@ -284,9 +281,6 @@ obj-y += $(onenand-m) $(onenand-y) nand-$(CONFIG_MTD_NAND_OMAP2) := gpmc-nand.o obj-y += $(nand-m) $(nand-y) -smc91x-$(CONFIG_SMC91X) := gpmc-smc91x.o -obj-y += $(smc91x-m) $(smc91x-y) - smsc911x-$(CONFIG_SMSC911X) := gpmc-smsc911x.o obj-y += $(smsc911x-m) $(smsc911x-y) ifneq ($(CONFIG_HWSPINLOCK_OMAP),) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c deleted file mode 100644 index d21a3048d06b..000000000000 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/board-3430sdp.c - * - * Copyright (C) 2007 Texas Instruments - * - * Modified from mach-omap2/board-generic.c - * - * Initial code: Syed Mohammed Khasim - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/input.h> -#include <linux/input/matrix_keypad.h> -#include <linux/spi/spi.h> -#include <linux/i2c/twl.h> -#include <linux/regulator/machine.h> -#include <linux/io.h> -#include <linux/gpio.h> -#include <linux/mmc/host.h> -#include <linux/platform_data/spi-omap2-mcspi.h> -#include <linux/platform_data/omap-twl4030.h> -#include <linux/usb/phy.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> - -#include "common.h" -#include <linux/omap-dma.h> -#include <video/omapdss.h> -#include <video/omap-panel-data.h> - -#include "gpmc.h" -#include "gpmc-smc91x.h" - -#include "soc.h" -#include "board-flash.h" -#include "mux.h" -#include "sdram-qimonda-hyb18m512160af-6.h" -#include "hsmmc.h" -#include "pm.h" -#include "control.h" -#include "common-board-devices.h" - -#define CONFIG_DISABLE_HFCLK 1 - -#define SDP3430_TS_GPIO_IRQ_SDPV1 3 -#define SDP3430_TS_GPIO_IRQ_SDPV2 2 - -#define ENABLE_VAUX3_DEDICATED 0x03 -#define ENABLE_VAUX3_DEV_GRP 0x20 - -#define TWL4030_MSECURE_GPIO 22 - -static uint32_t board_keymap[] = { - KEY(0, 0, KEY_LEFT), - KEY(0, 1, KEY_RIGHT), - KEY(0, 2, KEY_A), - KEY(0, 3, KEY_B), - KEY(0, 4, KEY_C), - KEY(1, 0, KEY_DOWN), - KEY(1, 1, KEY_UP), - KEY(1, 2, KEY_E), - KEY(1, 3, KEY_F), - KEY(1, 4, KEY_G), - KEY(2, 0, KEY_ENTER), - KEY(2, 1, KEY_I), - KEY(2, 2, KEY_J), - KEY(2, 3, KEY_K), - KEY(2, 4, KEY_3), - KEY(3, 0, KEY_M), - KEY(3, 1, KEY_N), - KEY(3, 2, KEY_O), - KEY(3, 3, KEY_P), - KEY(3, 4, KEY_Q), - KEY(4, 0, KEY_R), - KEY(4, 1, KEY_4), - KEY(4, 2, KEY_T), - KEY(4, 3, KEY_U), - KEY(4, 4, KEY_D), - KEY(5, 0, KEY_V), - KEY(5, 1, KEY_W), - KEY(5, 2, KEY_L), - KEY(5, 3, KEY_S), - KEY(5, 4, KEY_H), - 0 -}; - -static struct matrix_keymap_data board_map_data = { - .keymap = board_keymap, - .keymap_size = ARRAY_SIZE(board_keymap), -}; - -static struct twl4030_keypad_data sdp3430_kp_data = { - .keymap_data = &board_map_data, - .rows = 5, - .cols = 6, - .rep = 1, -}; - -#define SDP3430_LCD_PANEL_BACKLIGHT_GPIO 8 -#define SDP3430_LCD_PANEL_ENABLE_GPIO 5 - -static void __init sdp3430_display_init(void) -{ - int r; - - /* - * the backlight GPIO doesn't directly go to the panel, it enables - * an internal circuit on 3430sdp to create the signal V_BKL_28V, - * this is connected to LED+ pin of the sharp panel. This GPIO - * is left enabled in the board file, and not passed to the panel - * as platform_data. - */ - r = gpio_request_one(SDP3430_LCD_PANEL_BACKLIGHT_GPIO, - GPIOF_OUT_INIT_HIGH, "LCD Backlight"); - if (r) - pr_err("failed to get LCD Backlight GPIO\n"); - -} - -static struct panel_sharp_ls037v7dw01_platform_data sdp3430_lcd_pdata = { - .name = "lcd", - .source = "dpi.0", - - .data_lines = 16, - - .resb_gpio = SDP3430_LCD_PANEL_ENABLE_GPIO, - .ini_gpio = -1, - .mo_gpio = -1, - .lr_gpio = -1, - .ud_gpio = -1, -}; - -static struct platform_device sdp3430_lcd_device = { - .name = "panel-sharp-ls037v7dw01", - .id = 0, - .dev.platform_data = &sdp3430_lcd_pdata, -}; - -static struct connector_dvi_platform_data sdp3430_dvi_connector_pdata = { - .name = "dvi", - .source = "tfp410.0", - .i2c_bus_num = -1, -}; - -static struct platform_device sdp3430_dvi_connector_device = { - .name = "connector-dvi", - .id = 0, - .dev.platform_data = &sdp3430_dvi_connector_pdata, -}; - -static struct encoder_tfp410_platform_data sdp3430_tfp410_pdata = { - .name = "tfp410.0", - .source = "dpi.0", - .data_lines = 24, - .power_down_gpio = -1, -}; - -static struct platform_device sdp3430_tfp410_device = { - .name = "tfp410", - .id = 0, - .dev.platform_data = &sdp3430_tfp410_pdata, -}; - -static struct connector_atv_platform_data sdp3430_tv_pdata = { - .name = "tv", - .source = "venc.0", - .connector_type = OMAP_DSS_VENC_TYPE_SVIDEO, - .invert_polarity = false, -}; - -static struct platform_device sdp3430_tv_connector_device = { - .name = "connector-analog-tv", - .id = 0, - .dev.platform_data = &sdp3430_tv_pdata, -}; - -static struct omap_dss_board_info sdp3430_dss_data = { - .default_display_name = "lcd", -}; - -static struct omap2_hsmmc_info mmc[] = { - { - .mmc = 1, - /* 8 bits (default) requires S6.3 == ON, - * so the SIM card isn't used; else 4 bits. - */ - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, - .gpio_wp = 4, - .deferred = true, - }, - { - .mmc = 2, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, - .gpio_wp = 7, - .deferred = true, - }, - {} /* Terminator */ -}; - -static struct omap_tw4030_pdata omap_twl4030_audio_data = { - .voice_connected = true, - .custom_routing = true, - - .has_hs = OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT, - .has_hf = OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT, - - .has_mainmic = true, - .has_submic = true, - .has_hsmic = true, - .has_linein = OMAP_TWL4030_LEFT | OMAP_TWL4030_RIGHT, -}; - -static int sdp3430_twl_gpio_setup(struct device *dev, - unsigned gpio, unsigned ngpio) -{ - /* gpio + 0 is "mmc0_cd" (input/IRQ), - * gpio + 1 is "mmc1_cd" (input/IRQ) - */ - mmc[0].gpio_cd = gpio + 0; - mmc[1].gpio_cd = gpio + 1; - omap_hsmmc_late_init(mmc); - - /* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */ - gpio_request_one(gpio + 7, GPIOF_OUT_INIT_LOW, "sub_lcd_en_bkl"); - - /* gpio + 15 is "sub_lcd_nRST" (output) */ - gpio_request_one(gpio + 15, GPIOF_OUT_INIT_LOW, "sub_lcd_nRST"); - - omap_twl4030_audio_data.jack_detect = gpio + 2; - omap_twl4030_audio_init("SDP3430", &omap_twl4030_audio_data); - - return 0; -} - -static struct twl4030_gpio_platform_data sdp3430_gpio_data = { - .pulldowns = BIT(2) | BIT(6) | BIT(8) | BIT(13) - | BIT(16) | BIT(17), - .setup = sdp3430_twl_gpio_setup, -}; - -/* 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_vmmc1_supplies[] = { - REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"), -}; - -static struct regulator_consumer_supply sdp3430_vsim_supplies[] = { - REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"), -}; - -static struct regulator_consumer_supply sdp3430_vmmc2_supplies[] = { - REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"), -}; - -/* - * Apply all the fixed voltages since most versions of U-Boot - * don't bother with that initialization. - */ - -/* VAUX1 for mainboard (irda and sub-lcd) */ -static struct regulator_init_data sdp3430_vaux1 = { - .constraints = { - .min_uV = 2800000, - .max_uV = 2800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -/* VAUX2 for camera module */ -static struct regulator_init_data sdp3430_vaux2 = { - .constraints = { - .min_uV = 2800000, - .max_uV = 2800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, -}; - -/* VAUX3 for LCD board */ -static struct regulator_init_data sdp3430_vaux3 = { - .constraints = { - .min_uV = 2800000, - .max_uV = 2800000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .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) */ -static struct regulator_init_data sdp3430_vaux4 = { - .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, - }, -}; - -/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */ -static struct regulator_init_data sdp3430_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(sdp3430_vmmc1_supplies), - .consumer_supplies = sdp3430_vmmc1_supplies, -}; - -/* VMMC2 for MMC2 card */ -static struct regulator_init_data sdp3430_vmmc2 = { - .constraints = { - .min_uV = 1850000, - .max_uV = 1850000, - .apply_uV = true, - .valid_modes_mask = REGULATOR_MODE_NORMAL - | REGULATOR_MODE_STANDBY, - .valid_ops_mask = REGULATOR_CHANGE_MODE - | REGULATOR_CHANGE_STATUS, - }, - .num_consumer_supplies = ARRAY_SIZE(sdp3430_vmmc2_supplies), - .consumer_supplies = sdp3430_vmmc2_supplies, -}; - -/* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */ -static struct regulator_init_data sdp3430_vsim = { - .constraints = { - .min_uV = 1800000, - .max_uV = 3000000, - .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(sdp3430_vsim_supplies), - .consumer_supplies = sdp3430_vsim_supplies, -}; - -static struct twl4030_platform_data sdp3430_twldata = { - /* platform_data for children goes here */ - .gpio = &sdp3430_gpio_data, - .keypad = &sdp3430_kp_data, - - .vaux1 = &sdp3430_vaux1, - .vaux2 = &sdp3430_vaux2, - .vaux3 = &sdp3430_vaux3, - .vaux4 = &sdp3430_vaux4, - .vmmc1 = &sdp3430_vmmc1, - .vmmc2 = &sdp3430_vmmc2, - .vsim = &sdp3430_vsim, -}; - -static int __init omap3430_i2c_init(void) -{ - /* i2c1 for PMIC only */ - omap3_pmic_get_config(&sdp3430_twldata, - TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_BCI | - TWL_COMMON_PDATA_MADC | TWL_COMMON_PDATA_AUDIO, - TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2); - sdp3430_twldata.vdac->constraints.apply_uV = true; - sdp3430_twldata.vpll2->constraints.apply_uV = true; - sdp3430_twldata.vpll2->constraints.name = "VDVI"; - - sdp3430_twldata.audio->codec->hs_extmute = 1; - sdp3430_twldata.audio->codec->hs_extmute_gpio = -EINVAL; - - omap3_pmic_init("twl4030", &sdp3430_twldata); - - /* i2c2 on camera connector (for sensor control) and optional isp1301 */ - omap_register_i2c_bus(2, 400, NULL, 0); - /* i2c3 on display connector (for DVI, tfp410) */ - omap_register_i2c_bus(3, 400, NULL, 0); - return 0; -} - -#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) - -static struct omap_smc91x_platform_data board_smc91x_data = { - .cs = 3, - .flags = GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 | - IORESOURCE_IRQ_LOWLEVEL, -}; - -static void __init board_smc91x_init(void) -{ - if (omap_rev() > OMAP3430_REV_ES1_0) - board_smc91x_data.gpio_irq = 6; - else - board_smc91x_data.gpio_irq = 29; - - gpmc_smc91x_init(&board_smc91x_data); -} - -#else - -static inline void board_smc91x_init(void) -{ -} - -#endif - -static void enable_board_wakeup_source(void) -{ - /* T2 interrupt line (keypad) */ - omap_mux_init_signal("sys_nirq", - OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP); -} - -static struct usbhs_phy_data phy_data[] __initdata = { - { - .port = 1, - .reset_gpio = 57, - .vcc_gpio = -EINVAL, - }, - { - .port = 2, - .reset_gpio = 61, - .vcc_gpio = -EINVAL, - }, -}; - -static struct usbhs_omap_platform_data usbhs_bdata __initdata = { - - .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, - .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY, -}; - -#ifdef CONFIG_OMAP_MUX -static struct omap_board_mux board_mux[] __initdata = { - { .reg_offset = OMAP_MUX_TERMINATOR }, -}; -#else -#define board_mux NULL -#endif - -/* - * SDP3430 V2 Board CS organization - * Different from SDP3430 V1. Now 4 switches used to specify CS - * - * See also the Switch S8 settings in the comments. - */ -static char chip_sel_3430[][GPMC_CS_NUM] = { - {PDC_NOR, PDC_NAND, PDC_ONENAND, DBG_MPDB, 0, 0, 0, 0}, /* S8:1111 */ - {PDC_ONENAND, PDC_NAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1110 */ - {PDC_NAND, PDC_ONENAND, PDC_NOR, DBG_MPDB, 0, 0, 0, 0}, /* S8:1101 */ -}; - -static struct mtd_partition sdp_nor_partitions[] = { - /* bootloader (U-Boot, etc) in first sector */ - { - .name = "Bootloader-NOR", - .offset = 0, - .size = SZ_256K, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - /* bootloader params in the next sector */ - { - .name = "Params-NOR", - .offset = MTDPART_OFS_APPEND, - .size = SZ_256K, - .mask_flags = 0, - }, - /* kernel */ - { - .name = "Kernel-NOR", - .offset = MTDPART_OFS_APPEND, - .size = SZ_2M, - .mask_flags = 0 - }, - /* file system */ - { - .name = "Filesystem-NOR", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - .mask_flags = 0 - } -}; - -static struct mtd_partition sdp_onenand_partitions[] = { - { - .name = "X-Loader-OneNAND", - .offset = 0, - .size = 4 * (64 * 2048), - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "U-Boot-OneNAND", - .offset = MTDPART_OFS_APPEND, - .size = 2 * (64 * 2048), - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "U-Boot Environment-OneNAND", - .offset = MTDPART_OFS_APPEND, - .size = 1 * (64 * 2048), - }, - { - .name = "Kernel-OneNAND", - .offset = MTDPART_OFS_APPEND, - .size = 16 * (64 * 2048), - }, - { - .name = "File System-OneNAND", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - }, -}; - -static struct mtd_partition sdp_nand_partitions[] = { - /* All the partition sizes are listed in terms of NAND block size */ - { - .name = "X-Loader-NAND", - .offset = 0, - .size = 4 * (64 * 2048), - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { - .name = "U-Boot-NAND", - .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */ - .size = 10 * (64 * 2048), - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, - { - .name = "Boot Env-NAND", - - .offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */ - .size = 6 * (64 * 2048), - }, - { - .name = "Kernel-NAND", - .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */ - .size = 40 * (64 * 2048), - }, - { - .name = "File System - NAND", - .size = MTDPART_SIZ_FULL, - .offset = MTDPART_OFS_APPEND, /* Offset = 0x780000 */ - }, -}; - -static struct flash_partitions sdp_flash_partitions[] = { - { - .parts = sdp_nor_partitions, - .nr_parts = ARRAY_SIZE(sdp_nor_partitions), - }, - { - .parts = sdp_onenand_partitions, - .nr_parts = ARRAY_SIZE(sdp_onenand_partitions), - }, - { - .parts = sdp_nand_partitions, - .nr_parts = ARRAY_SIZE(sdp_nand_partitions), - }, -}; - -static void __init omap_3430sdp_init(void) -{ - int gpio_pendown; - - omap3_mux_init(board_mux, OMAP_PACKAGE_CBB); - omap_hsmmc_init(mmc); - omap3430_i2c_init(); - omap_display_init(&sdp3430_dss_data); - platform_device_register(&sdp3430_lcd_device); - platform_device_register(&sdp3430_tfp410_device); - platform_device_register(&sdp3430_dvi_connector_device); - platform_device_register(&sdp3430_tv_connector_device); - - if (omap_rev() > OMAP3430_REV_ES1_0) - gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV2; - else - gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1; - omap_ads7846_init(1, gpio_pendown, 310, NULL); - omap_serial_init(); - omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL); - usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb"); - usb_musb_init(NULL); - board_smc91x_init(); - board_flash_init(sdp_flash_partitions, chip_sel_3430, 0); - sdp3430_display_init(); - enable_board_wakeup_source(); - - usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data)); - usbhs_init(&usbhs_bdata); -} - -MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board") - /* Maintainer: Syed Khasim - Texas Instruments Inc */ - .atag_offset = 0x100, - .reserve = omap_reserve, - .map_io = omap3_map_io, - .init_early = omap3430_init_early, - .init_irq = omap3_init_irq, - .init_machine = omap_3430sdp_init, - .init_late = omap3430_init_late, - .init_time = omap3_sync32k_timer_init, - .restart = omap3xxx_restart, -MACHINE_END diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c index 212c3160de18..8168ddabaeda 100644 --- a/arch/arm/mach-omap2/board-am3517crane.c +++ b/arch/arm/mach-omap2/board-am3517crane.c @@ -24,6 +24,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> +#include <linux/omap-gpmc.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index c6df8eec4553..91738a14ecbe 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -25,6 +25,7 @@ #include <linux/input/matrix_keypad.h> #include <linux/delay.h> #include <linux/gpio.h> +#include <linux/omap-gpmc.h> #include <linux/platform_data/gpio-omap.h> #include <linux/platform_data/at24.h> @@ -51,8 +52,6 @@ #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" #include "common-board-devices.h" -#include "gpmc.h" -#include "gpmc-nand.h" #define CM_T35_GPIO_PENDOWN 57 #define SB_T35_USB_HUB_RESET_GPIO 167 diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c index 8a2c1677964c..794756df8529 100644 --- a/arch/arm/mach-omap2/board-cm-t3517.c +++ b/arch/arm/mach-omap2/board-cm-t3517.c @@ -28,6 +28,7 @@ #include <linux/delay.h> #include <linux/gpio.h> #include <linux/leds.h> +#include <linux/omap-gpmc.h> #include <linux/rtc-v3020.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -41,7 +42,6 @@ #include "common.h" #include <linux/platform_data/mtd-nand-omap2.h> -#include "gpmc.h" #include "am35xx.h" @@ -50,7 +50,6 @@ #include "hsmmc.h" #include "common-board-devices.h" #include "am35xx-emac.h" -#include "gpmc-nand.h" #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) static struct gpio_led cm_t3517_leds[] = { diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index 2d245c2e641c..70b21cc279ba 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -13,6 +13,7 @@ */ #include <linux/kernel.h> +#include <linux/omap-gpmc.h> #include <linux/platform_device.h> #include <linux/mtd/physmap.h> #include <linux/io.h> @@ -23,8 +24,6 @@ #include "soc.h" #include "common.h" #include "board-flash.h" -#include "gpmc-onenand.h" -#include "gpmc-nand.h" #define REG_FPGA_REV 0x10 #define REG_FPGA_DIP_SWITCH_INPUT2 0x60 diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h index 2fb5d41a9fae..ea9aaebe11e7 100644 --- a/arch/arm/mach-omap2/board-flash.h +++ b/arch/arm/mach-omap2/board-flash.h @@ -12,7 +12,6 @@ */ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> -#include "gpmc.h" #define PDC_NOR 1 #define PDC_NAND 2 diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index e0ad64fde20e..b6443a4e0c78 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -23,7 +23,6 @@ #include <linux/usb/musb.h> #include <linux/mmc/host.h> #include <linux/platform_data/spi-omap2-mcspi.h> -#include <linux/platform_data/mtd-onenand-omap2.h> #include <linux/platform_data/mmc-omap.h> #include <linux/mfd/menelaus.h> #include <sound/tlv320aic3x.h> @@ -34,7 +33,6 @@ #include "common.h" #include "mmc.h" #include "soc.h" -#include "gpmc-onenand.h" #include "common-board-devices.h" #define TUSB6010_ASYNC_CS 1 diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index f32201656cf3..7f1708738c30 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -24,6 +24,7 @@ #include <linux/spi/spi.h> #include <linux/regulator/machine.h> #include <linux/i2c/twl.h> +#include <linux/omap-gpmc.h> #include <linux/wl12xx.h> #include <linux/mtd/partitions.h> #include <linux/mtd/nand.h> @@ -51,7 +52,6 @@ #include "sdram-micron-mt46h32m32lf-6.h" #include "hsmmc.h" #include "common-board-devices.h" -#include "gpmc-nand.h" #define PANDORA_WIFI_IRQ_GPIO 21 #define PANDORA_WIFI_NRESET_GPIO 23 diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 3d5040f82e90..03502abe4f2e 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -23,6 +23,7 @@ #include <linux/regulator/machine.h> #include <linux/gpio.h> #include <linux/gpio_keys.h> +#include <linux/omap-gpmc.h> #include <linux/mmc/host.h> #include <linux/power/isp1704_charger.h> #include <linux/platform_data/spi-omap2-mcspi.h> @@ -32,7 +33,6 @@ #include "common.h" #include <linux/omap-dma.h> -#include "gpmc-smc91x.h" #include "board-rx51.h" @@ -55,8 +55,6 @@ #include "omap-pm.h" #include "hsmmc.h" #include "common-board-devices.h" -#include "gpmc.h" -#include "gpmc-onenand.h" #include "soc.h" #include "omap-secure.h" @@ -1144,33 +1142,6 @@ static struct omap_onenand_platform_data board_onenand_data[] = { }; #endif -#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) - -static struct omap_smc91x_platform_data board_smc91x_data = { - .cs = 1, - .gpio_irq = 54, - .gpio_pwrdwn = 86, - .gpio_reset = 164, - .flags = GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHLEVEL, -}; - -static void __init board_smc91x_init(void) -{ - omap_mux_init_gpio(54, OMAP_PIN_INPUT_PULLDOWN); - omap_mux_init_gpio(86, OMAP_PIN_OUTPUT); - omap_mux_init_gpio(164, OMAP_PIN_OUTPUT); - - gpmc_smc91x_init(&board_smc91x_data); -} - -#else - -static inline void board_smc91x_init(void) -{ -} - -#endif - static struct gpio rx51_wl1251_gpios[] __initdata = { { RX51_WL1251_IRQ_GPIO, GPIOF_IN, "wl1251 irq" }, }; @@ -1301,7 +1272,6 @@ void __init rx51_peripherals_init(void) rx51_i2c_init(); regulator_has_full_constraints(); gpmc_onenand_init(board_onenand_data); - board_smc91x_init(); rx51_add_gpio_keys(); rx51_init_wl1251(); rx51_init_tsc2005(); diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c deleted file mode 100644 index 6273c286e1d8..000000000000 --- a/arch/arm/mach-omap2/board-ti8168evm.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Code for TI8168/TI8148 EVM. - * - * Copyright (C) 2010 Texas Instruments, Inc. - http://www.ti.com/ - * - * 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/platform_device.h> -#include <linux/usb/musb.h> - -#include <asm/mach-types.h> -#include <asm/mach/arch.h> -#include <asm/mach/map.h> - -#include "common.h" - -static struct omap_musb_board_data musb_board_data = { - .set_phy_power = ti81xx_musb_phy_power, - .interface_type = MUSB_INTERFACE_ULPI, - .mode = MUSB_OTG, - .power = 500, -}; - -static void __init ti81xx_evm_init(void) -{ - omap_serial_init(); - omap_sdrc_init(NULL, NULL); - usb_musb_init(&musb_board_data); -} - -MACHINE_START(TI8168EVM, "ti8168evm") - /* Maintainer: Texas Instruments */ - .atag_offset = 0x100, - .map_io = ti81xx_map_io, - .init_early = ti81xx_init_early, - .init_irq = ti81xx_init_irq, - .init_time = omap3_sync32k_timer_init, - .init_machine = ti81xx_evm_init, - .init_late = ti81xx_init_late, - .restart = omap44xx_restart, -MACHINE_END - -MACHINE_START(TI8148EVM, "ti8148evm") - /* Maintainer: Texas Instruments */ - .atag_offset = 0x100, - .map_io = ti81xx_map_io, - .init_early = ti81xx_init_early, - .init_irq = ti81xx_init_irq, - .init_time = omap3_sync32k_timer_init, - .init_machine = ti81xx_evm_init, - .init_late = ti81xx_init_late, - .restart = omap44xx_restart, -MACHINE_END diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 492ef1607115..a7bc4ce81e19 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -411,3 +411,29 @@ static int __init omap2_init_devices(void) return 0; } omap_arch_initcall(omap2_init_devices); + +static int __init omap_gpmc_init(void) +{ + struct omap_hwmod *oh; + struct platform_device *pdev; + char *oh_name = "gpmc"; + + /* + * if the board boots up with a populated DT, do not + * manually add the device from this initcall + */ + if (of_have_populated_dt()) + return -ENODEV; + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("Could not look up %s\n", oh_name); + return -ENODEV; + } + + pdev = omap_device_build("omap-gpmc", -1, oh, NULL, 0); + WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name); + + return PTR_RET(pdev); +} +omap_postcore_initcall(omap_gpmc_init); diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index cb7764314f17..d5951b17b736 100644 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -12,14 +12,13 @@ #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/omap-gpmc.h> #include <linux/mtd/nand.h> #include <linux/platform_data/mtd-nand-omap2.h> #include <asm/mach/flash.h> -#include "gpmc.h" #include "soc.h" -#include "gpmc-nand.h" /* minimum size for IO mapping */ #define NAND_IO_SIZE 4 diff --git a/arch/arm/mach-omap2/gpmc-nand.h b/arch/arm/mach-omap2/gpmc-nand.h deleted file mode 100644 index d59e1281e851..000000000000 --- a/arch/arm/mach-omap2/gpmc-nand.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * arch/arm/mach-omap2/gpmc-nand.h - * - * 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; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef __OMAP2_GPMC_NAND_H -#define __OMAP2_GPMC_NAND_H - -#include "gpmc.h" -#include <linux/platform_data/mtd-nand-omap2.h> - -#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2) -extern int gpmc_nand_init(struct omap_nand_platform_data *d, - struct gpmc_timings *gpmc_t); -#else -static inline int gpmc_nand_init(struct omap_nand_platform_data *d, - struct gpmc_timings *gpmc_t) -{ - return 0; -} -#endif - -#endif diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 8b6876c98ce1..53d197e0c1f3 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -15,14 +15,13 @@ #include <linux/platform_device.h> #include <linux/mtd/onenand_regs.h> #include <linux/io.h> +#include <linux/omap-gpmc.h> #include <linux/platform_data/mtd-onenand-omap2.h> #include <linux/err.h> #include <asm/mach/flash.h> -#include "gpmc.h" #include "soc.h" -#include "gpmc-onenand.h" #define ONENAND_IO_SIZE SZ_128K diff --git a/arch/arm/mach-omap2/gpmc-onenand.h b/arch/arm/mach-omap2/gpmc-onenand.h deleted file mode 100644 index 216f23a8b45c..000000000000 --- a/arch/arm/mach-omap2/gpmc-onenand.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * arch/arm/mach-omap2/gpmc-onenand.h - * - * 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; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef __OMAP2_GPMC_ONENAND_H -#define __OMAP2_GPMC_ONENAND_H - -#include <linux/platform_data/mtd-onenand-omap2.h> - -#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) -extern void gpmc_onenand_init(struct omap_onenand_platform_data *d); -#else -#define board_onenand_data NULL -static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d) -{ -} -#endif - -#endif diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c deleted file mode 100644 index 61a063595e66..000000000000 --- a/arch/arm/mach-omap2/gpmc-smc91x.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/gpmc-smc91x.c - * - * Copyright (C) 2009 Nokia Corporation - * Contact: Tony Lindgren - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/smc91x.h> - -#include "gpmc.h" -#include "gpmc-smc91x.h" - -#include "soc.h" - -static struct omap_smc91x_platform_data *gpmc_cfg; - -static struct resource gpmc_smc91x_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .flags = IORESOURCE_IRQ, - }, -}; - -static struct smc91x_platdata gpmc_smc91x_info = { - .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_0, - .leda = RPC_LED_100_10, - .ledb = RPC_LED_TX_RX, -}; - -static struct platform_device gpmc_smc91x_device = { - .name = "smc91x", - .id = -1, - .dev = { - .platform_data = &gpmc_smc91x_info, - }, - .num_resources = ARRAY_SIZE(gpmc_smc91x_resources), - .resource = gpmc_smc91x_resources, -}; - -static struct gpmc_settings smc91x_settings = { - .device_width = GPMC_DEVWIDTH_16BIT, -}; - -/* - * Set the gpmc timings for smc91c96. The timings are taken - * from the data sheet available at: - * http://www.smsc.com/main/catalog/lan91c96.html - * REVISIT: Level shifters can add at least to the access latency. - */ -static int smc91c96_gpmc_retime(void) -{ - struct gpmc_timings t; - struct gpmc_device_timings dev_t; - const int t3 = 10; /* Figure 12.2 read and 12.4 write */ - const int t4_r = 20; /* Figure 12.2 read */ - const int t4_w = 5; /* Figure 12.4 write */ - const int t5 = 25; /* Figure 12.2 read */ - const int t6 = 15; /* Figure 12.2 read */ - const int t7 = 5; /* Figure 12.4 write */ - const int t8 = 5; /* Figure 12.4 write */ - const int t20 = 185; /* Figure 12.2 read and 12.4 write */ - - /* - * FIXME: Calculate the address and data bus muxed timings. - * Note that at least adv_rd_off needs to be changed according - * to omap3430 TRM Figure 11-11. Are the sdp boards using the - * FPGA in between smc91x and omap as the timings are different - * from above? - */ - if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) - return 0; - - memset(&dev_t, 0, sizeof(dev_t)); - - dev_t.t_oeasu = t3 * 1000; - dev_t.t_oe = t5 * 1000; - dev_t.t_cez_r = t4_r * 1000; - dev_t.t_oez = t6 * 1000; - dev_t.t_rd_cycle = (t20 - t3) * 1000; - - dev_t.t_weasu = t3 * 1000; - dev_t.t_wpl = t7 * 1000; - dev_t.t_wph = t8 * 1000; - dev_t.t_cez_w = t4_w * 1000; - dev_t.t_wr_cycle = (t20 - t3) * 1000; - - gpmc_calc_timings(&t, &smc91x_settings, &dev_t); - - return gpmc_cs_set_timings(gpmc_cfg->cs, &t); -} - -/* - * Initialize smc91x device connected to the GPMC. Note that we - * assume that pin multiplexing is done in the board-*.c file, - * or in the bootloader. - */ -void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data) -{ - unsigned long cs_mem_base; - int ret; - - gpmc_cfg = board_data; - - if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96) - gpmc_cfg->retime = smc91c96_gpmc_retime; - - if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) { - printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); - return; - } - - gpmc_smc91x_resources[0].start = cs_mem_base + 0x300; - gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f; - gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK); - - if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) - smc91x_settings.mux_add_data = GPMC_MUX_AD; - if (gpmc_cfg->flags & GPMC_READ_MON) - smc91x_settings.wait_on_read = true; - if (gpmc_cfg->flags & GPMC_WRITE_MON) - smc91x_settings.wait_on_write = true; - if (gpmc_cfg->wait_pin) - smc91x_settings.wait_pin = gpmc_cfg->wait_pin; - ret = gpmc_cs_program_settings(gpmc_cfg->cs, &smc91x_settings); - if (ret < 0) - goto free1; - - if (gpmc_cfg->retime) { - ret = gpmc_cfg->retime(); - if (ret != 0) - goto free1; - } - - if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "SMC91X irq") < 0) - goto free1; - - gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq); - - if (gpmc_cfg->gpio_pwrdwn) { - ret = gpio_request_one(gpmc_cfg->gpio_pwrdwn, - GPIOF_OUT_INIT_LOW, "SMC91X powerdown"); - if (ret) - goto free2; - } - - if (gpmc_cfg->gpio_reset) { - ret = gpio_request_one(gpmc_cfg->gpio_reset, - GPIOF_OUT_INIT_LOW, "SMC91X reset"); - if (ret) - goto free3; - - gpio_set_value(gpmc_cfg->gpio_reset, 1); - msleep(100); - gpio_set_value(gpmc_cfg->gpio_reset, 0); - } - - if (platform_device_register(&gpmc_smc91x_device) < 0) { - printk(KERN_ERR "Unable to register smc91x device\n"); - gpio_free(gpmc_cfg->gpio_reset); - goto free3; - } - - return; - -free3: - if (gpmc_cfg->gpio_pwrdwn) - gpio_free(gpmc_cfg->gpio_pwrdwn); -free2: - gpio_free(gpmc_cfg->gpio_irq); -free1: - gpmc_cs_free(gpmc_cfg->cs); - - printk(KERN_ERR "Could not initialize smc91x\n"); -} diff --git a/arch/arm/mach-omap2/gpmc-smc91x.h b/arch/arm/mach-omap2/gpmc-smc91x.h deleted file mode 100644 index b64fbee4d567..000000000000 --- a/arch/arm/mach-omap2/gpmc-smc91x.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/gpmc-smc91x.h - * - * Copyright (C) 2009 Nokia Corporation - * - * 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. - */ - -#ifndef __ASM_ARCH_OMAP_GPMC_SMC91X_H__ - -#define GPMC_TIMINGS_SMC91C96 (1 << 4) -#define GPMC_MUX_ADD_DATA (1 << 5) /* GPMC_CONFIG1_MUXADDDATA */ -#define GPMC_READ_MON (1 << 6) /* GPMC_CONFIG1_WAIT_READ_MON */ -#define GPMC_WRITE_MON (1 << 7) /* GPMC_CONFIG1_WAIT_WRITE_MON */ - -struct omap_smc91x_platform_data { - int cs; - int gpio_irq; - int gpio_pwrdwn; - int gpio_reset; - int wait_pin; /* Optional GPMC_CONFIG1_WAITPINSELECT */ - u32 flags; - int (*retime)(void); -}; - -#if defined(CONFIG_SMC91X) || \ - defined(CONFIG_SMC91X_MODULE) - -extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d); - -#else - -#define board_smc91x_data NULL - -static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d) -{ -} - -#endif -#endif diff --git a/arch/arm/mach-omap2/gpmc.h b/arch/arm/mach-omap2/gpmc.h index 707f6d58edd5..9caa41a6cb04 100644 --- a/arch/arm/mach-omap2/gpmc.h +++ b/arch/arm/mach-omap2/gpmc.h @@ -6,226 +6,9 @@ * 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. + * + * Do not include this file in any new code, this will get removed + * once omap3 boots in device tree only mode. + * */ - -#ifndef __OMAP2_GPMC_H -#define __OMAP2_GPMC_H - -#include <linux/platform_data/mtd-nand-omap2.h> - -/* Maximum Number of Chip Selects */ -#define GPMC_CS_NUM 8 - -#define GPMC_CS_CONFIG1 0x00 -#define GPMC_CS_CONFIG2 0x04 -#define GPMC_CS_CONFIG3 0x08 -#define GPMC_CS_CONFIG4 0x0c -#define GPMC_CS_CONFIG5 0x10 -#define GPMC_CS_CONFIG6 0x14 -#define GPMC_CS_CONFIG7 0x18 -#define GPMC_CS_NAND_COMMAND 0x1c -#define GPMC_CS_NAND_ADDRESS 0x20 -#define GPMC_CS_NAND_DATA 0x24 - -/* Control Commands */ -#define GPMC_CONFIG_RDY_BSY 0x00000001 -#define GPMC_CONFIG_DEV_SIZE 0x00000002 -#define GPMC_CONFIG_DEV_TYPE 0x00000003 -#define GPMC_SET_IRQ_STATUS 0x00000004 -#define GPMC_CONFIG_WP 0x00000005 - -#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 */ -#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ - -#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) -#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) -#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29) -#define GPMC_CONFIG1_READTYPE_SYNC (1 << 29) -#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28) -#define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) -#define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) -#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) -#define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) -#define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) -#define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) -#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) -#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) -#define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) -#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) -#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) -#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) -#define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8) -#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) -#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) -#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1)) -#define GPMC_CONFIG1_FCLK_DIV3 (GPMC_CONFIG1_FCLK_DIV(2)) -#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) -#define GPMC_CONFIG7_CSVALID (1 << 6) - -#define GPMC_DEVICETYPE_NOR 0 -#define GPMC_DEVICETYPE_NAND 2 -#define GPMC_CONFIG_WRITEPROTECT 0x00000010 -#define WR_RD_PIN_MONITORING 0x00600000 -#define GPMC_IRQ_FIFOEVENTENABLE 0x01 -#define GPMC_IRQ_COUNT_EVENT 0x02 - -#define GPMC_BURST_4 4 /* 4 word burst */ -#define GPMC_BURST_8 8 /* 8 word burst */ -#define GPMC_BURST_16 16 /* 16 word burst */ -#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ -#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ -#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ -#define GPMC_MUX_AD 2 /* Addr-Data multiplex */ - -/* bool type time settings */ -struct gpmc_bool_timings { - bool cycle2cyclediffcsen; - bool cycle2cyclesamecsen; - bool we_extra_delay; - bool oe_extra_delay; - bool adv_extra_delay; - bool cs_extra_delay; - bool time_para_granularity; -}; - -/* - * Note that all values in this struct are in nanoseconds except sync_clk - * (which is in picoseconds), while the register values are in gpmc_fck cycles. - */ -struct gpmc_timings { - /* Minimum clock period for synchronous mode (in picoseconds) */ - u32 sync_clk; - - /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ - u32 cs_on; /* Assertion time */ - u32 cs_rd_off; /* Read deassertion time */ - u32 cs_wr_off; /* Write deassertion time */ - - /* ADV signal timings corresponding to GPMC_CONFIG3 */ - u32 adv_on; /* Assertion time */ - u32 adv_rd_off; /* Read deassertion time */ - u32 adv_wr_off; /* Write deassertion time */ - - /* WE signals timings corresponding to GPMC_CONFIG4 */ - u32 we_on; /* WE assertion time */ - u32 we_off; /* WE deassertion time */ - - /* OE signals timings corresponding to GPMC_CONFIG4 */ - u32 oe_on; /* OE assertion time */ - u32 oe_off; /* OE deassertion time */ - - /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ - u32 page_burst_access; /* Multiple access word delay */ - u32 access; /* Start-cycle to first data valid delay */ - u32 rd_cycle; /* Total read cycle time */ - u32 wr_cycle; /* Total write cycle time */ - - u32 bus_turnaround; - u32 cycle2cycle_delay; - - u32 wait_monitoring; - u32 clk_activation; - - /* The following are only on OMAP3430 */ - u32 wr_access; /* WRACCESSTIME */ - u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ - - struct gpmc_bool_timings bool_timings; -}; - -/* Device timings in picoseconds */ -struct gpmc_device_timings { - u32 t_ceasu; /* address setup to CS valid */ - u32 t_avdasu; /* address setup to ADV valid */ - /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is - * of tusb using these timings even for sync whilst - * ideally for adv_rd/(wr)_off it should have considered - * t_avdh instead. This indirectly necessitates r/w - * variations of t_avdp as it is possible to have one - * sync & other async - */ - u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ - u32 t_avdp_w; - u32 t_aavdh; /* address hold time */ - u32 t_oeasu; /* address setup to OE valid */ - u32 t_aa; /* access time from ADV assertion */ - u32 t_iaa; /* initial access time */ - u32 t_oe; /* access time from OE assertion */ - u32 t_ce; /* access time from CS asertion */ - u32 t_rd_cycle; /* read cycle time */ - u32 t_cez_r; /* read CS deassertion to high Z */ - u32 t_cez_w; /* write CS deassertion to high Z */ - u32 t_oez; /* OE deassertion to high Z */ - u32 t_weasu; /* address setup to WE valid */ - u32 t_wpl; /* write assertion time */ - u32 t_wph; /* write deassertion time */ - u32 t_wr_cycle; /* write cycle time */ - - u32 clk; - u32 t_bacc; /* burst access valid clock to output delay */ - u32 t_ces; /* CS setup time to clk */ - u32 t_avds; /* ADV setup time to clk */ - u32 t_avdh; /* ADV hold time from clk */ - u32 t_ach; /* address hold time from clk */ - u32 t_rdyo; /* clk to ready valid */ - - u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ - u32 t_ce_avd; /* CS on to ADV on delay */ - - /* XXX: check the possibility of combining - * cyc_aavhd_oe & cyc_aavdh_we - */ - u8 cyc_aavdh_oe;/* read address hold time in cycles */ - u8 cyc_aavdh_we;/* write address hold time in cycles */ - u8 cyc_oe; /* access time from OE assertion in cycles */ - u8 cyc_wpl; /* write deassertion time in cycles */ - u32 cyc_iaa; /* initial access time in cycles */ - - /* extra delays */ - bool ce_xdelay; - bool avd_xdelay; - bool oe_xdelay; - bool we_xdelay; -}; - -struct gpmc_settings { - bool burst_wrap; /* enables wrap bursting */ - bool burst_read; /* enables read page/burst mode */ - bool burst_write; /* enables write page/burst mode */ - bool device_nand; /* device is NAND */ - bool sync_read; /* enables synchronous reads */ - bool sync_write; /* enables synchronous writes */ - bool wait_on_read; /* monitor wait on reads */ - bool wait_on_write; /* monitor wait on writes */ - u32 burst_len; /* page/burst length */ - u32 device_width; /* device bus width (8 or 16 bit) */ - u32 mux_add_data; /* multiplex address & data */ - u32 wait_pin; /* wait-pin to be used */ -}; - -extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, - struct gpmc_settings *gpmc_s, - struct gpmc_device_timings *dev_t); - -extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); -extern int gpmc_get_client_irq(unsigned irq_config); - -extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); - -extern void gpmc_cs_write_reg(int cs, int idx, u32 val); -extern int gpmc_calc_divider(unsigned int sync_clk); -extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); -extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p); -extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); -extern void gpmc_cs_free(int cs); -extern void omap3_gpmc_save_context(void); -extern void omap3_gpmc_restore_context(void); -extern int gpmc_configure(int cmd, int wval); -extern void gpmc_read_settings_dt(struct device_node *np, - struct gpmc_settings *p); - -#endif +#include <linux/omap-gpmc.h> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 175564c88a30..88721df6001d 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -29,6 +29,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/omap-dma.h> +#include <linux/omap-gpmc.h> #include <linux/platform_data/gpio-omap.h> #include <trace/events/power.h> @@ -43,7 +44,6 @@ #include "common.h" #include "cm3xxx.h" #include "cm-regbits-34xx.h" -#include "gpmc.h" #include "prm-regbits-34xx.h" #include "prm3xxx.h" #include "pm.h" diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 08bd4cfca2a4..191383d8c94d 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig @@ -41,6 +41,14 @@ config TI_EMIF parameters and other settings during frequency, voltage and temperature changes +config OMAP_GPMC + bool + help + This driver is for the General Purpose Memory Controller (GPMC) + present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows + interfacing to a variety of asynchronous as well as synchronous + memory drives like NOR, NAND, OneNAND, SRAM. + config MVEBU_DEVBUS bool "Marvell EBU Device Bus Controller" default y diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index ad98bb232623..6b6548124473 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile @@ -8,6 +8,7 @@ endif obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o obj-$(CONFIG_TI_AEMIF) += ti-aemif.o obj-$(CONFIG_TI_EMIF) += emif.o +obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o obj-$(CONFIG_FSL_IFC) += fsl_ifc.o obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o diff --git a/arch/arm/mach-omap2/gpmc.c b/drivers/memory/omap-gpmc.c index 8fb5bbce102f..ffc5e60c0664 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -29,20 +29,15 @@ #include <linux/of_address.h> #include <linux/of_mtd.h> #include <linux/of_device.h> +#include <linux/omap-gpmc.h> #include <linux/mtd/nand.h> #include <linux/pm_runtime.h> #include <linux/platform_data/mtd-nand-omap2.h> +#include <linux/platform_data/mtd-onenand-omap2.h> #include <asm/mach-types.h> -#include "soc.h" -#include "common.h" -#include "omap_device.h" -#include "gpmc.h" -#include "gpmc-nand.h" -#include "gpmc-onenand.h" - #define DEVICE_NAME "omap-gpmc" /* GPMC register offsets */ @@ -85,6 +80,8 @@ #define GPMC_ECC_CTRL_ECCREG8 0x008 #define GPMC_ECC_CTRL_ECCREG9 0x009 +#define GPMC_CONFIG_LIMITEDADDRESS BIT(1) + #define GPMC_CONFIG2_CSEXTRADELAY BIT(7) #define GPMC_CONFIG3_ADVEXTRADELAY BIT(7) #define GPMC_CONFIG4_OEEXTRADELAY BIT(7) @@ -114,10 +111,73 @@ #define GPMC_NR_WAITPINS 4 +#define GPMC_CS_CONFIG1 0x00 +#define GPMC_CS_CONFIG2 0x04 +#define GPMC_CS_CONFIG3 0x08 +#define GPMC_CS_CONFIG4 0x0c +#define GPMC_CS_CONFIG5 0x10 +#define GPMC_CS_CONFIG6 0x14 +#define GPMC_CS_CONFIG7 0x18 +#define GPMC_CS_NAND_COMMAND 0x1c +#define GPMC_CS_NAND_ADDRESS 0x20 +#define GPMC_CS_NAND_DATA 0x24 + +/* Control Commands */ +#define GPMC_CONFIG_RDY_BSY 0x00000001 +#define GPMC_CONFIG_DEV_SIZE 0x00000002 +#define GPMC_CONFIG_DEV_TYPE 0x00000003 +#define GPMC_SET_IRQ_STATUS 0x00000004 + +#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) +#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) +#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29) +#define GPMC_CONFIG1_READTYPE_SYNC (1 << 29) +#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP (1 << 28) +#define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) +#define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) +#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) +#define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) +#define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) +#define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) +#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) +#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) +#define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) +#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) +#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) +#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) +#define GPMC_CONFIG1_MUXTYPE(val) ((val & 3) << 8) +#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) +#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) +#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1)) +#define GPMC_CONFIG1_FCLK_DIV3 (GPMC_CONFIG1_FCLK_DIV(2)) +#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) +#define GPMC_CONFIG7_CSVALID (1 << 6) + +#define GPMC_DEVICETYPE_NOR 0 +#define GPMC_DEVICETYPE_NAND 2 +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 +#define WR_RD_PIN_MONITORING 0x00600000 + +#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 */ +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ + /* XXX: Only NAND irq has been considered,currently these are the only ones used */ #define GPMC_NR_IRQ 2 +struct gpmc_cs_data { + const char *name; + +#define GPMC_CS_RESERVED (1 << 0) + u32 flags; + + struct resource mem; +}; + struct gpmc_client_irq { unsigned irq; u32 bitmask; @@ -155,10 +215,9 @@ static struct irq_chip gpmc_irq_chip; static int gpmc_irq_start; static struct resource gpmc_mem_root; -static struct resource gpmc_cs_mem[GPMC_CS_NUM]; +static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); /* Define chip-selects as reserved by default until probe completes */ -static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1); static unsigned int gpmc_cs_num = GPMC_CS_NUM; static unsigned int gpmc_nr_waitpins; static struct device *gpmc_dev; @@ -202,11 +261,6 @@ static unsigned long gpmc_get_fclk_period(void) { unsigned long rate = clk_get_rate(gpmc_l3_clk); - if (rate == 0) { - printk(KERN_WARNING "gpmc_l3_clk not enabled\n"); - return 0; - } - rate /= 1000; rate = 1000000000 / rate; /* In picoseconds */ @@ -284,12 +338,130 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p) } #ifdef DEBUG -static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, - int time, const char *name) +static int get_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, + bool raw, bool noval, int shift, + const char *name) +{ + u32 l; + int nr_bits, max_value, mask; + + l = gpmc_cs_read_reg(cs, reg); + nr_bits = end_bit - st_bit + 1; + max_value = (1 << nr_bits) - 1; + mask = max_value << st_bit; + l = (l & mask) >> st_bit; + if (shift) + l = (shift << l); + if (noval && (l == 0)) + return 0; + if (!raw) { + unsigned int time_ns_min, time_ns, time_ns_max; + + time_ns_min = gpmc_ticks_to_ns(l ? l - 1 : 0); + time_ns = gpmc_ticks_to_ns(l); + time_ns_max = gpmc_ticks_to_ns(l + 1 > max_value ? + max_value : l + 1); + pr_info("gpmc,%s = <%u> (%u - %u ns, %i ticks)\n", + name, time_ns, time_ns_min, time_ns_max, l); + } else { + pr_info("gpmc,%s = <%u>\n", name, l); + } + + return l; +} + +#define GPMC_PRINT_CONFIG(cs, config) \ + pr_info("cs%i %s: 0x%08x\n", cs, #config, \ + gpmc_cs_read_reg(cs, config)) +#define GPMC_GET_RAW(reg, st, end, field) \ + get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 0, 0, field) +#define GPMC_GET_RAW_BOOL(reg, st, end, field) \ + get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 1, 0, field) +#define GPMC_GET_RAW_SHIFT(reg, st, end, shift, field) \ + get_gpmc_timing_reg(cs, (reg), (st), (end), 1, 1, (shift), field) +#define GPMC_GET_TICKS(reg, st, end, field) \ + get_gpmc_timing_reg(cs, (reg), (st), (end), 0, 0, 0, field) + +static void gpmc_show_regs(int cs, const char *desc) +{ + pr_info("gpmc cs%i %s:\n", cs, desc); + GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG1); + GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG2); + GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG3); + GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG4); + GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG5); + GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG6); +} + +/* + * Note that gpmc,wait-pin handing wrongly assumes bit 8 is available, + * see commit c9fb809. + */ +static void gpmc_cs_show_timings(int cs, const char *desc) +{ + gpmc_show_regs(cs, desc); + + pr_info("gpmc cs%i access configuration:\n", cs); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 4, 4, "time-para-granularity"); + GPMC_GET_RAW(GPMC_CS_CONFIG1, 8, 9, "mux-add-data"); + GPMC_GET_RAW(GPMC_CS_CONFIG1, 12, 13, "device-width"); + GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 22, 22, "wait-on-read"); + GPMC_GET_RAW_SHIFT(GPMC_CS_CONFIG1, 23, 24, 4, "burst-length"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 27, 27, "sync-write"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 28, 28, "burst-write"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 29, 29, "gpmc,sync-read"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 30, 30, "burst-read"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 31, 31, "burst-wrap"); + + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG2, 7, 7, "cs-extra-delay"); + + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG3, 7, 7, "adv-extra-delay"); + + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG4, 23, 23, "we-extra-delay"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG4, 7, 7, "oe-extra-delay"); + + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG6, 7, 7, "cycle2cycle-samecsen"); + GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG6, 6, 6, "cycle2cycle-diffcsen"); + + pr_info("gpmc cs%i timings configuration:\n", cs); + GPMC_GET_TICKS(GPMC_CS_CONFIG2, 0, 3, "cs-on-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG2, 8, 12, "cs-rd-off-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG2, 16, 20, "cs-wr-off-ns"); + + GPMC_GET_TICKS(GPMC_CS_CONFIG3, 0, 3, "adv-on-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG3, 8, 12, "adv-rd-off-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG3, 16, 20, "adv-wr-off-ns"); + + GPMC_GET_TICKS(GPMC_CS_CONFIG4, 0, 3, "oe-on-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG4, 8, 12, "oe-off-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG4, 16, 19, "we-on-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG4, 24, 28, "we-off-ns"); + + GPMC_GET_TICKS(GPMC_CS_CONFIG5, 0, 4, "rd-cycle-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG5, 8, 12, "wr-cycle-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG5, 16, 20, "access-ns"); + + GPMC_GET_TICKS(GPMC_CS_CONFIG5, 24, 27, "page-burst-access-ns"); + + GPMC_GET_TICKS(GPMC_CS_CONFIG6, 0, 3, "bus-turnaround-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG6, 8, 11, "cycle2cycle-delay-ns"); + + GPMC_GET_TICKS(GPMC_CS_CONFIG1, 18, 19, "wait-monitoring-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG1, 25, 26, "clk-activation-ns"); + + GPMC_GET_TICKS(GPMC_CS_CONFIG6, 16, 19, "wr-data-mux-bus-ns"); + GPMC_GET_TICKS(GPMC_CS_CONFIG6, 24, 28, "wr-access-ns"); +} #else -static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, - int time) +static inline void gpmc_cs_show_timings(int cs, const char *desc) +{ +} #endif + +static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, + int time, const char *name) { u32 l; int ticks, mask, nr_bits; @@ -299,15 +471,15 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, else ticks = gpmc_ns_to_ticks(time); nr_bits = end_bit - st_bit + 1; - if (ticks >= 1 << nr_bits) { -#ifdef DEBUG - printk(KERN_INFO "GPMC CS%d: %-10s* %3d ns, %3d ticks >= %d\n", - cs, name, time, ticks, 1 << nr_bits); -#endif + mask = (1 << nr_bits) - 1; + + if (ticks > mask) { + pr_err("%s: GPMC error! CS%d: %s: %d ns, %d ticks > %d\n", + __func__, cs, name, time, ticks, mask); + return -1; } - mask = (1 << nr_bits) - 1; l = gpmc_cs_read_reg(cs, reg); #ifdef DEBUG printk(KERN_INFO @@ -322,16 +494,10 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, return 0; } -#ifdef DEBUG #define GPMC_SET_ONE(reg, st, end, field) \ if (set_gpmc_timing_reg(cs, (reg), (st), (end), \ t->field, #field) < 0) \ return -1 -#else -#define GPMC_SET_ONE(reg, st, end, field) \ - if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \ - return -1 -#endif int gpmc_calc_divider(unsigned int sync_clk) { @@ -353,6 +519,7 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) int div; u32 l; + gpmc_cs_show_timings(cs, "before gpmc_cs_set_timings"); div = gpmc_calc_divider(t->sync_clk); if (div < 0) return div; @@ -402,11 +569,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) } gpmc_cs_bool_timings(cs, &t->bool_timings); + gpmc_cs_show_timings(cs, "after gpmc_cs_set_timings"); return 0; } -static int gpmc_cs_enable_mem(int cs, u32 base, u32 size) +static int gpmc_cs_set_memconf(int cs, u32 base, u32 size) { u32 l; u32 mask; @@ -430,6 +598,15 @@ static int gpmc_cs_enable_mem(int cs, u32 base, u32 size) return 0; } +static void gpmc_cs_enable_mem(int cs) +{ + u32 l; + + l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7); + l |= GPMC_CONFIG7_CSVALID; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l); +} + static void gpmc_cs_disable_mem(int cs) { u32 l; @@ -460,13 +637,30 @@ static int gpmc_cs_mem_enabled(int cs) static void gpmc_cs_set_reserved(int cs, int reserved) { - gpmc_cs_map &= ~(1 << cs); - gpmc_cs_map |= (reserved ? 1 : 0) << cs; + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + + gpmc->flags |= GPMC_CS_RESERVED; } static bool gpmc_cs_reserved(int cs) { - return gpmc_cs_map & (1 << cs); + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + + return gpmc->flags & GPMC_CS_RESERVED; +} + +static void gpmc_cs_set_name(int cs, const char *name) +{ + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + + gpmc->name = name; +} + +const char *gpmc_cs_get_name(int cs) +{ + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + + return gpmc->name; } static unsigned long gpmc_mem_align(unsigned long size) @@ -485,7 +679,8 @@ static unsigned long gpmc_mem_align(unsigned long size) static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size) { - struct resource *res = &gpmc_cs_mem[cs]; + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + struct resource *res = &gpmc->mem; int r; size = gpmc_mem_align(size); @@ -500,7 +695,8 @@ static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size) static int gpmc_cs_delete_mem(int cs) { - struct resource *res = &gpmc_cs_mem[cs]; + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + struct resource *res = &gpmc->mem; int r; spin_lock(&gpmc_mem_lock); @@ -541,23 +737,24 @@ static int gpmc_cs_remap(int cs, u32 base) gpmc_cs_get_memconf(cs, &old_base, &size); if (base == old_base) return 0; - gpmc_cs_disable_mem(cs); + ret = gpmc_cs_delete_mem(cs); if (ret < 0) return ret; + ret = gpmc_cs_insert_mem(cs, base, size); if (ret < 0) return ret; - ret = gpmc_cs_enable_mem(cs, base, size); - if (ret < 0) - return ret; - return 0; + ret = gpmc_cs_set_memconf(cs, base, size); + + return ret; } int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) { - struct resource *res = &gpmc_cs_mem[cs]; + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + struct resource *res = &gpmc->mem; int r = -1; if (cs > gpmc_cs_num) { @@ -581,12 +778,17 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base) if (r < 0) goto out; - r = gpmc_cs_enable_mem(cs, res->start, resource_size(res)); + /* Disable CS while changing base address and size mask */ + gpmc_cs_disable_mem(cs); + + r = gpmc_cs_set_memconf(cs, res->start, resource_size(res)); if (r < 0) { release_resource(res); goto out; } + /* Enable CS */ + gpmc_cs_enable_mem(cs); *base = res->start; gpmc_cs_set_reserved(cs, 1); out: @@ -597,7 +799,8 @@ EXPORT_SYMBOL(gpmc_cs_request); void gpmc_cs_free(int cs) { - struct resource *res = &gpmc_cs_mem[cs]; + struct gpmc_cs_data *gpmc = &gpmc_cs[cs]; + struct resource *res = &gpmc->mem; spin_lock(&gpmc_mem_lock); if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) { @@ -1509,7 +1712,9 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, struct gpmc_timings gpmc_t; struct resource res; unsigned long base; + const char *name; int ret, cs; + u32 val; if (of_property_read_u32(child, "reg", &cs) < 0) { dev_err(&pdev->dev, "%s has no 'reg' property\n", @@ -1523,28 +1728,41 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, return -ENODEV; } + /* + * Check if we have multiple instances of the same device + * on a single chip select. If so, use the already initialized + * timings. + */ + name = gpmc_cs_get_name(cs); + if (name && child->name && of_node_cmp(child->name, name) == 0) + goto no_timings; + ret = gpmc_cs_request(cs, resource_size(&res), &base); if (ret < 0) { dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs); return ret; } + gpmc_cs_set_name(cs, child->name); + + gpmc_read_settings_dt(child, &gpmc_s); + gpmc_read_timings_dt(child, &gpmc_t); /* * For some GPMC devices we still need to rely on the bootloader - * timings because the devices can be connected via FPGA. So far - * the list is smc91x on the omap2 SDP boards, and 8250 on zooms. - * REVISIT: Add timing support from slls644g.pdf and from the - * lan91c96 manual. + * timings because the devices can be connected via FPGA. + * REVISIT: Add timing support from slls644g.pdf. */ - if (of_device_is_compatible(child, "ns16550a") || - of_device_is_compatible(child, "smsc,lan91c94") || - of_device_is_compatible(child, "smsc,lan91c111")) { - dev_warn(&pdev->dev, - "%s using bootloader timings on CS%d\n", - child->name, cs); + if (!gpmc_t.cs_rd_off) { + WARN(1, "enable GPMC debug to configure .dts timings for CS%i\n", + cs); + gpmc_cs_show_timings(cs, + "please add GPMC bootloader timings to .dts"); goto no_timings; } + /* CS must be disabled while making changes to gpmc configuration */ + gpmc_cs_disable_mem(cs); + /* * FIXME: gpmc_cs_request() will map the CS to an arbitary * location in the gpmc address space. When booting with @@ -1560,8 +1778,6 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, goto err; } - gpmc_read_settings_dt(child, &gpmc_s); - ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width); if (ret < 0) goto err; @@ -1570,8 +1786,20 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, if (ret < 0) goto err; - gpmc_read_timings_dt(child, &gpmc_t); - gpmc_cs_set_timings(cs, &gpmc_t); + ret = gpmc_cs_set_timings(cs, &gpmc_t); + if (ret) { + dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n", + child->name); + goto err; + } + + /* Clear limited address i.e. enable A26-A11 */ + val = gpmc_read_reg(GPMC_CONFIG); + val &= ~GPMC_CONFIG_LIMITEDADDRESS; + gpmc_write_reg(GPMC_CONFIG, val); + + /* Enable CS region */ + gpmc_cs_enable_mem(cs); no_timings: if (of_platform_device_create(child, NULL, &pdev->dev)) @@ -1668,13 +1896,18 @@ static int gpmc_probe(struct platform_device *pdev) else gpmc_irq = res->start; - gpmc_l3_clk = clk_get(&pdev->dev, "fck"); + gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck"); if (IS_ERR(gpmc_l3_clk)) { - dev_err(&pdev->dev, "error: clk_get\n"); + dev_err(&pdev->dev, "Failed to get GPMC fck\n"); gpmc_irq = 0; return PTR_ERR(gpmc_l3_clk); } + if (!clk_get_rate(gpmc_l3_clk)) { + dev_err(&pdev->dev, "Invalid GPMC fck clock rate\n"); + return -EINVAL; + } + pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); @@ -1706,9 +1939,6 @@ static int gpmc_probe(struct platform_device *pdev) if (gpmc_setup_irq() < 0) dev_warn(gpmc_dev, "gpmc_setup_irq failed\n"); - /* Now the GPMC is initialised, unreserve the chip-selects */ - gpmc_cs_map = 0; - if (!pdev->dev.of_node) { gpmc_cs_num = GPMC_CS_NUM; gpmc_nr_waitpins = GPMC_NR_WAITPINS; @@ -1717,7 +1947,6 @@ static int gpmc_probe(struct platform_device *pdev) rc = gpmc_probe_dt(pdev); if (rc < 0) { pm_runtime_put_sync(&pdev->dev); - clk_put(gpmc_l3_clk); dev_err(gpmc_dev, "failed to probe DT parameters\n"); return rc; } @@ -1775,35 +2004,9 @@ static __exit void gpmc_exit(void) } -omap_postcore_initcall(gpmc_init); +postcore_initcall(gpmc_init); module_exit(gpmc_exit); -static int __init omap_gpmc_init(void) -{ - struct omap_hwmod *oh; - struct platform_device *pdev; - char *oh_name = "gpmc"; - - /* - * if the board boots up with a populated DT, do not - * manually add the device from this initcall - */ - if (of_have_populated_dt()) - return -ENODEV; - - oh = omap_hwmod_lookup(oh_name); - if (!oh) { - pr_err("Could not look up %s\n", oh_name); - return -ENODEV; - } - - pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0); - WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name); - - return PTR_RET(pdev); -} -omap_postcore_initcall(omap_gpmc_init); - static irqreturn_t gpmc_handle_irq(int irq, void *dev) { int i; diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h new file mode 100644 index 000000000000..c2080eebbb47 --- /dev/null +++ b/include/linux/omap-gpmc.h @@ -0,0 +1,199 @@ +/* + * OMAP GPMC (General Purpose Memory Controller) defines + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +/* Maximum Number of Chip Selects */ +#define GPMC_CS_NUM 8 + +#define GPMC_CONFIG_WP 0x00000005 + +#define GPMC_IRQ_FIFOEVENTENABLE 0x01 +#define GPMC_IRQ_COUNT_EVENT 0x02 + +#define GPMC_BURST_4 4 /* 4 word burst */ +#define GPMC_BURST_8 8 /* 8 word burst */ +#define GPMC_BURST_16 16 /* 16 word burst */ +#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */ +#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */ +#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */ +#define GPMC_MUX_AD 2 /* Addr-Data multiplex */ + +/* bool type time settings */ +struct gpmc_bool_timings { + bool cycle2cyclediffcsen; + bool cycle2cyclesamecsen; + bool we_extra_delay; + bool oe_extra_delay; + bool adv_extra_delay; + bool cs_extra_delay; + bool time_para_granularity; +}; + +/* + * Note that all values in this struct are in nanoseconds except sync_clk + * (which is in picoseconds), while the register values are in gpmc_fck cycles. + */ +struct gpmc_timings { + /* Minimum clock period for synchronous mode (in picoseconds) */ + u32 sync_clk; + + /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ + u32 cs_on; /* Assertion time */ + u32 cs_rd_off; /* Read deassertion time */ + u32 cs_wr_off; /* Write deassertion time */ + + /* ADV signal timings corresponding to GPMC_CONFIG3 */ + u32 adv_on; /* Assertion time */ + u32 adv_rd_off; /* Read deassertion time */ + u32 adv_wr_off; /* Write deassertion time */ + + /* WE signals timings corresponding to GPMC_CONFIG4 */ + u32 we_on; /* WE assertion time */ + u32 we_off; /* WE deassertion time */ + + /* OE signals timings corresponding to GPMC_CONFIG4 */ + u32 oe_on; /* OE assertion time */ + u32 oe_off; /* OE deassertion time */ + + /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ + u32 page_burst_access; /* Multiple access word delay */ + u32 access; /* Start-cycle to first data valid delay */ + u32 rd_cycle; /* Total read cycle time */ + u32 wr_cycle; /* Total write cycle time */ + + u32 bus_turnaround; + u32 cycle2cycle_delay; + + u32 wait_monitoring; + u32 clk_activation; + + /* The following are only on OMAP3430 */ + u32 wr_access; /* WRACCESSTIME */ + u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */ + + struct gpmc_bool_timings bool_timings; +}; + +/* Device timings in picoseconds */ +struct gpmc_device_timings { + u32 t_ceasu; /* address setup to CS valid */ + u32 t_avdasu; /* address setup to ADV valid */ + /* XXX: try to combine t_avdp_r & t_avdp_w. Issue is + * of tusb using these timings even for sync whilst + * ideally for adv_rd/(wr)_off it should have considered + * t_avdh instead. This indirectly necessitates r/w + * variations of t_avdp as it is possible to have one + * sync & other async + */ + u32 t_avdp_r; /* ADV low time (what about t_cer ?) */ + u32 t_avdp_w; + u32 t_aavdh; /* address hold time */ + u32 t_oeasu; /* address setup to OE valid */ + u32 t_aa; /* access time from ADV assertion */ + u32 t_iaa; /* initial access time */ + u32 t_oe; /* access time from OE assertion */ + u32 t_ce; /* access time from CS asertion */ + u32 t_rd_cycle; /* read cycle time */ + u32 t_cez_r; /* read CS deassertion to high Z */ + u32 t_cez_w; /* write CS deassertion to high Z */ + u32 t_oez; /* OE deassertion to high Z */ + u32 t_weasu; /* address setup to WE valid */ + u32 t_wpl; /* write assertion time */ + u32 t_wph; /* write deassertion time */ + u32 t_wr_cycle; /* write cycle time */ + + u32 clk; + u32 t_bacc; /* burst access valid clock to output delay */ + u32 t_ces; /* CS setup time to clk */ + u32 t_avds; /* ADV setup time to clk */ + u32 t_avdh; /* ADV hold time from clk */ + u32 t_ach; /* address hold time from clk */ + u32 t_rdyo; /* clk to ready valid */ + + u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */ + u32 t_ce_avd; /* CS on to ADV on delay */ + + /* XXX: check the possibility of combining + * cyc_aavhd_oe & cyc_aavdh_we + */ + u8 cyc_aavdh_oe;/* read address hold time in cycles */ + u8 cyc_aavdh_we;/* write address hold time in cycles */ + u8 cyc_oe; /* access time from OE assertion in cycles */ + u8 cyc_wpl; /* write deassertion time in cycles */ + u32 cyc_iaa; /* initial access time in cycles */ + + /* extra delays */ + bool ce_xdelay; + bool avd_xdelay; + bool oe_xdelay; + bool we_xdelay; +}; + +struct gpmc_settings { + bool burst_wrap; /* enables wrap bursting */ + bool burst_read; /* enables read page/burst mode */ + bool burst_write; /* enables write page/burst mode */ + bool device_nand; /* device is NAND */ + bool sync_read; /* enables synchronous reads */ + bool sync_write; /* enables synchronous writes */ + bool wait_on_read; /* monitor wait on reads */ + bool wait_on_write; /* monitor wait on writes */ + u32 burst_len; /* page/burst length */ + u32 device_width; /* device bus width (8 or 16 bit) */ + u32 mux_add_data; /* multiplex address & data */ + u32 wait_pin; /* wait-pin to be used */ +}; + +extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t, + struct gpmc_settings *gpmc_s, + struct gpmc_device_timings *dev_t); + +struct gpmc_nand_regs; +struct device_node; + +extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs); +extern int gpmc_get_client_irq(unsigned irq_config); + +extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); + +extern void gpmc_cs_write_reg(int cs, int idx, u32 val); +extern int gpmc_calc_divider(unsigned int sync_clk); +extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); +extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p); +extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); +extern void gpmc_cs_free(int cs); +extern int gpmc_configure(int cmd, int wval); +extern void gpmc_read_settings_dt(struct device_node *np, + struct gpmc_settings *p); + +extern void omap3_gpmc_save_context(void); +extern void omap3_gpmc_restore_context(void); + +struct gpmc_timings; +struct omap_nand_platform_data; +struct omap_onenand_platform_data; + +#if IS_ENABLED(CONFIG_MTD_NAND_OMAP2) +extern int gpmc_nand_init(struct omap_nand_platform_data *d, + struct gpmc_timings *gpmc_t); +#else +static inline int gpmc_nand_init(struct omap_nand_platform_data *d, + struct gpmc_timings *gpmc_t) +{ + return 0; +} +#endif + +#if IS_ENABLED(CONFIG_MTD_ONENAND_OMAP2) +extern void gpmc_onenand_init(struct omap_onenand_platform_data *d); +#else +#define board_onenand_data NULL +static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d) +{ +} +#endif |