diff --git a/MAINTAINERS b/MAINTAINERS
index e3a96e42193c90a6ab1356c10f6a7d0a39660ff6..0d6469a2cf708d66f7a2a050237c1f250d64f96f 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 f4d06aea84605993bc2464313adf4f79628ab914..6e249324fdd775e594582e6cb6c3380716499a92 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 3b653b3ac268399e59e5254f057a1f6e1cb87c10..08cc94474d1749c8b3be489ed7daa884b25f35ab 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 d21a3048d06b6846c926b066ba21a2661645540b..0000000000000000000000000000000000000000
--- 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 212c3160de183810438a3f8ca2e725674231edb3..8168ddabaeda93004228eaf87b1ca3e44c7bd379 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 c6df8eec45532d2ed26d0180480e416aecf2696f..91738a14ecbe424ad31ee1140946f16f50c7c84b 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 8a2c1677964cbb5c0d60c56bb27645b237e1b2fb..794756df8529a13a986343ac108765bdf68117f7 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 2d245c2e641cd9314378def624b45093951a59cc..70b21cc279ba45c5ada11bdffea8051b18f5fb0a 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 2fb5d41a9fae2679781a9c759913a032b1a69e9e..ea9aaebe11e7f1e0c85df5851f074a0de50d6d52 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 e0ad64fde20ee9409c9d3db648de21b52a11a8f6..b6443a4e0c78002d6665479a608e7915b1801015 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 f32201656cf30b5af416d53176c282d467ea2491..7f1708738c3079227377806376a794dafb5aed46 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 3d5040f82e90a40e53320a40202afa20f27b29d2..03502abe4f2efbd82d3140c3cddd0a244275d0ee 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 6273c286e1d8fc877bfc6d20d7cdfa50530119c8..0000000000000000000000000000000000000000
--- 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 492ef1607115781b0db260389724b1421d549c82..a7bc4ce81e19e3ebc979c56b158a58afd79b461b 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 cb7764314f1736206c9dba849e2e777c76cbb1e7..d5951b17b7368c0713b5bddd56e03cff34b6cc17 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 d59e1281e8517c9c951f3bd7a405e0705388e54f..0000000000000000000000000000000000000000
--- 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 8b6876c98ce1a320c793e7485c35d23bd3a5b923..53d197e0c1f34525b828e256bff935e41ebe7d33 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 216f23a8b45c639091657d25a6bfaca7fd432bc9..0000000000000000000000000000000000000000
--- 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 61a063595e66fb1c2d01bca46c561873aa2fd643..0000000000000000000000000000000000000000
--- 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 b64fbee4d5672d9827e54794b27fe43a85817302..0000000000000000000000000000000000000000
--- 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 707f6d58edd53d300a1b266cc229b3f9c1edd8f3..9caa41a6cb04e011621371d9b9fd58ea65a22319 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 175564c88a3035dcdaba4d1be9d2d00e5437078e..88721df6001d0ef7741aa377ef853dc89cb67bca 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 08bd4cfca2a4adf53384715683126a40a85fabf5..191383d8c94d6e1d8e6d67bfc3e0ec5494b1d323 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 ad98bb232623cacf24adf591a07f718b253c933a..6b6548124473350a453b8982e341e4bb27264458 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
similarity index 83%
rename from arch/arm/mach-omap2/gpmc.c
rename to drivers/memory/omap-gpmc.c
index 8fb5bbce102fa6274ee31710a9a86582be6db27c..ffc5e60c0664fafc54207a6174ce8ce5189ce20c 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 0000000000000000000000000000000000000000..c2080eebbb479f42f97de28ae0ee45a48a81ddf1
--- /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