Skip to contentSkip to conversation

OMAP GPMC driver conversion

PATCH New Afzal Mohammed 1 participant 40 messages May 1, 2012

Subsystems (10)
lore
Share & tools
lore
#0 lore raw

cover OMAP GPMC driver conversion

Hi,

GPMC driver conversion patch series. Some peripherals has GPMC helper functions, these has been modified to cater to the needs of GPMC driver. All the boards using GPMC has been adapted to use the new GPMC driver.

GPMC HWMOD entry for OMAP2/3 has been added. On OMAP3, kernel does spit "omap_hwmod: gpmc: cannot be enabled for reset (3)", but peripherals connected via GPMC are working. Really shaky about OMAP2 GPMC HWMOD entry. Would be helpful if someone can help me in resolving warning on OMAP3 & verify whether OMAP2 entry is proper. The series adapts to HWMOD.

Drivers, NAND & OneNAND of OMAP has been modified to make use of GPMC changes & cleaned up the now unnecessary exported symbol usages.

This series has been made on top of,
5e136da Linux-omap rebuilt: Updated to -rc5,
A patch by Javier Martinez Canillas <[email protected]>,
OMAP3: igep0020: Add support for Micron NAND Flash storage memory, has also been incorporated into the series as this was necessary for igep0020 board.

This has been tested on omap3 evm (SMSC911x) & beagle board (NAND)

I would need help to get these changes tested on other boards using GPMC. Expected problematic boards are those having OMAP2xxx SoCs, apollon board. In the case of apollon, in addition to it being OMAP2xxx, it was modified to use gpmc_smc91x_init instead of directly writing to configuration registers.

Additional features that currently boards in mainline does not make use of like, waitpin interrupt handling, changes to leverage revision 6 IP differences has not been incorporated.

GPMC driver now provides NAND driver with GPMC-NAND registers so that OMAP NAND driver can handle those by itself instead of using exported symbols.

Acquiring CS for NAND has also been incorporated, it has been made as a separate patch as it is felt that this should probably go away, explained in the relevant patch.

GPMC (General Purpose Memory Controller) in brief:
GPMC is an unified memory controller dedicated to interfacing external memory devices like
Asynchronous SRAM like memories and application specific integrated circuit devices. Asynchronous, synchronous, and page mode burst NOR flash devices NAND flash Pseudo-SRAM devices

GPMC details can be referred in AM335X Technical Reference Manual @ http://www.ti.com/lit/pdf/spruh73

v4: Handle wait pin (except for interrupts), enhance configuration
& timing interface of GPMC to take care of all boards. Dynamic allocation of interrupt instead of static. Convert remaining peripherals to work with GPMC driver. Handle acquiring NAND CS#, adapt to HWMOD, update HWMOD OMAP2/3 entries, other minor commenst on v3.
v3: Single device structure passed from platform for peripherals using
multiple CS instead of using multiple device structure having a few redundant data, handle interrupts, GPMC NAND handling by GPMC NAND driver instead of GPMC driver
v2: Avoid code movement that kept similar code together (for easy review)

TODO: Cleanup

Regards
Afzal

Afzal Mohammed (38):
ARM: OMAP2+: gpmc: driver conversion
ARM: OMAP2+: gpmc: Adapt to HWMOD
ARM: OMAP2+: gpmc: register details for nand driver
ARM: OMAP2+: gpmc: Acquire NAND CS value
ARM: OMAP2+: nand: create platform data structure
ARM: OMAP2+: onenand: return value in init function
ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
ARM: OMAP2+: flash: Adapt to gpmc driver
ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver
ARM: OMAP3: hwmod data: add gpmc
ARM: OMAP2xxx: hwmod data: add gpmc
mtd: nand: omap2: obtain memory from resource
mtd: nand: omap2: use gpmc provided irqs
mtd: nand: omap2: handle nand on gpmc
mtd: onenand: omap: obtain memory from resource
ARM: OMAP2+: board omap3evm: gpmc driver adaptation
ARM: OMAP2+: board omap3beagle: gpmc driver adaptation
ARM: OMAP2+: board apollon: gpmc driver adaptation
ARM: OMAP2+: board h4: gpmc driver adaptation
ARM: OMAP2+: board 3630sdp: gpmc driver adaptation
ARM: OMAP2+: board 3430sdp: gpmc driver adaptation
ARM: OMAP2+: board 2430sdp: gpmc driver adaptation
ARM: OMAP2+: board cm-t3517: gpmc driver adaptation
ARM: OMAP2+: board cm-t35: gpmc driver adaptation
ARM: OMAP2+: board ldp: gpmc driver adaptation
ARM: OMAP2+: board n8x0: gpmc driver adaptation
ARM: OMAP2+: board omap3logic: gpmc driver adaptation
ARM: OMAP2+: board omap3pandora: gpmc driver adaptation
ARM: OMAP2+: board omap3stalker: gpmc driver adaptation
ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation
ARM: OMAP2+: board overo: gpmc driver adaptation
ARM: OMAP2+: board rm680: gpmc driver adaptation
ARM: OMAP2+: board rx51: gpmc driver adaptation
ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation
ARM: OMAP2+: board igep0020: gpmc driver adaptation

Javier Martinez Canillas (1):
OMAP3: igep0020: Add support for Micron NAND Flash storage memory

 arch/arm/mach-omap2/board-2430sdp.c                |   44 +-
 arch/arm/mach-omap2/board-3430sdp.c                |   18 +-
 arch/arm/mach-omap2/board-3630sdp.c                |   23 +-
 arch/arm/mach-omap2/board-apollon.c                |  152 +--
 arch/arm/mach-omap2/board-cm-t35.c                 |   21 +-
 arch/arm/mach-omap2/board-cm-t3517.c               |   10 +-
 arch/arm/mach-omap2/board-devkit8000.c             |    6 +-
 arch/arm/mach-omap2/board-flash.c                  |  160 ++--
 arch/arm/mach-omap2/board-flash.h                  |   36 +-
 arch/arm/mach-omap2/board-h4.c                     |  130 +--
 arch/arm/mach-omap2/board-igep0020.c               |   99 +-
 arch/arm/mach-omap2/board-ldp.c                    |   26 +-
 arch/arm/mach-omap2/board-n8x0.c                   |   18 +-
 arch/arm/mach-omap2/board-omap3beagle.c            |   22 +-
 arch/arm/mach-omap2/board-omap3evm.c               |   14 +-
 arch/arm/mach-omap2/board-omap3logic.c             |   13 +-
 arch/arm/mach-omap2/board-omap3pandora.c           |   11 +-
 arch/arm/mach-omap2/board-omap3stalker.c           |   13 +-
 arch/arm/mach-omap2/board-omap3touchbook.c         |    6 +-
 arch/arm/mach-omap2/board-omap4pcm049.c            |   13 +-
 arch/arm/mach-omap2/board-overo.c                  |   32 +-
 arch/arm/mach-omap2/board-rm680.c                  |   10 +-
 arch/arm/mach-omap2/board-rx51-peripherals.c       |   17 +-
 arch/arm/mach-omap2/board-zoom-debugboard.c        |   47 +-
 arch/arm/mach-omap2/board-zoom.c                   |    5 +-
 arch/arm/mach-omap2/common-board-devices.c         |   46 -
 arch/arm/mach-omap2/common-board-devices.h         |    1 -
 arch/arm/mach-omap2/gpmc-nand.c                    |   84 +-
 arch/arm/mach-omap2/gpmc-onenand.c                 |  111 +--
 arch/arm/mach-omap2/gpmc-smc91x.c                  |   87 +-
 arch/arm/mach-omap2/gpmc-smsc911x.c                |   59 +-
 arch/arm/mach-omap2/gpmc.c                         |  980 +++++++++++++++++---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   18 +
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   18 +
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   41 +
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c         |   52 ++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
 arch/arm/mach-omap2/prcm-common.h                  |    2 +
 arch/arm/mach-omap2/usb-tusb6010.c                 |  177 ++--
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h      |   10 +-
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h    |    9 +-
 arch/arm/plat-omap/include/plat/gpmc.h             |  110 ++-
 arch/arm/plat-omap/include/plat/nand.h             |   10 +-
 arch/arm/plat-omap/include/plat/onenand.h          |    7 +-
 drivers/mtd/nand/omap2.c                           |  296 ++++--
 drivers/mtd/onenand/omap2.c                        |   29 +-
 include/linux/usb/musb.h                           |    4 +-
 47 files changed, 2110 insertions(+), 988 deletions(-)
Signature · 1 line
1.7.10
#1 lore raw

PATCH 1/39 ARM: OMAP2+: gpmc: driver conversion

Convert GPMC code to driver. Boards using GPMC should provide driver with type of configuration, timing, CS. Platform devices would then be created for each connected peripheral (details also to be passed by board so that it reaches respective driver). And GPMC driver would populate memory resource details for the connected peripheral driver. Boards should inform gpmc driver with platform data destined for peripheral driver. gpmc driver will provide the same information to peripheral driver.

A peripheral connected to GPMC can have multiple address spaces using different chip select. Hence GPMC driver has been provided capability to create platform device for peripheral using mutiple CS. The peripheral that made it necessary was tusb6010.

Interrupts of GPMC are presented to drivers of connected peripherals as resource. A fictitious interrupt controller chip handles these interrupts at GPMC hardware level. Clients can use normal interrupt APIs. Platform information of peripheral passed to GPMC driver should indicate interrupts to be used via flags.

Driver is capable of configuring waitpin, waitpin details has to be provided per CS. Wait pin has been considered as exclusive resource as multiple peripherals should not using the same pin, at the same it is valid for mutiple CS to use same waitpin provided they are a part of single peripheral (eg. tusb6010)

An exported symbol for reconfiguring GPMC settings has been provided. OneNAND is the one that neccessitated this.

Acquiring CS# for NAND is done on a few boards. It means, depending on bootloader to embed this information. Probably CS# being used can be set in the Kernel, and acquiring it can be removed. If ever this capbility is needed, GPMC driver has to be made aware of handling it.

Modifications has been made keeping in mind that the driver would have to move to driver folder. This explains requirement of clk_prd field; even though clk_prd variable is not necessary as gpmc_get_fclk_period is present in the same file as of now, this will help in moving the driver easily to drivers folder.

Code related to GPMC clock may have to continue live in platform folders as input clock is beyond the control of GPMC and calculating timing for the peripheral may need other helpers. This explains presence of 'gpmc_cs_calc_divider' along with 'gpmc_calc_divider', both doing same work, latter meant to go with driver, former for calculation in platform code.

Thanks to Vaibhav Hiremath & Jonathan Hunter on their various good suggestions which resulted in improving the code.

Cc Vaibhav Hiremath <[email protected]>
Cc Jon Hunter <[email protected]>
---
 arch/arm/mach-omap2/gpmc.c             |  877 ++++++++++++++++++++++++++++----
 arch/arm/plat-omap/include/plat/gpmc.h |   93 +++-
 2 files changed, 872 insertions(+), 98 deletions(-)
arch/arm/mach-omap2/gpmc.c +783 -94
index 580e684..12916f3 100644
@@ -14,8 +14,11 @@
  */
 #undef DEBUG
 
+#include <linux/platform_device.h>
+
 #include <linux/irq.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/clk.h>
@@ -53,6 +56,45 @@
 #define GPMC_CS0_OFFSET		0x60
 #define GPMC_CS_SIZE		0x30
 
+/* GPMC register bits */
+#define	GPMC_CONFIG1_TIMEPARAGRANULARITY	BIT(4)
+#define	GPMC_CONFIG1_DEVICETYPE_NAND		GPMC_CONFIG1_DEVICETYPE(0x2)
+#define	GPMC_CONFIG1_WAIT_PIN_SEL_MASK		GPMC_CONFIG1_WAIT_PIN_SEL(0x3)
+#define	GPMC_CONFIG1_WAIT_MON_TIME(val)		((val & 0x3) << 18)
+#define	GPMC_CONFIG1_WRITEMULTIPLE		BIT(28)
+#define	GPMC_CONFIG1_READMULTIPLE		BIT(30)
+#define	GPMC_CONFIG1_WRAPBURST			BIT(31)
+#define	GPMC_CONFIG_WAITPIN_POLARITY_SHIFT	0x8
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME(val)	((val & 0x3) << 18)
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1	\
+				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x1)
+#define	GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2	\
+				GPMC_CONFIG1_WAITPIN_MONITOR_TIME(0x2)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME(val)	((val & 0x3) << 25)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_1	\
+				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x1)
+#define	GPMC_CONFIG1_CLOCKACTIVATION_TIME_2	\
+				GPMC_CONFIG1_CLOCKACTIVATION_TIME(0x2)
+
+#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
+
+#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
+
+#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
+
+#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
+#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
+
+#define	GPMC_IRQ_BIT_FIFOEVENT		BIT(0)
+#define	GPMC_IRQ_BIT_TERMINALCOUNT	BIT(1)
+
+#define	GPMC_WAITPIN_IDX0			0x0
+#define	GPMC_WAITPIN_IDX1			0x1
+#define	GPMC_WAITPIN_IDX2			0x2
+#define	GPMC_WAITPIN_IDX3			0x3
+#define	GPMC_NR_WAITPIN				0x4
+
 #define GPMC_MEM_START		0x00000000
 #define GPMC_MEM_END		0x3FFFFFFF
 #define BOOT_ROM_SPACE		0x100000	/* 1MB */
@@ -64,6 +106,55 @@
 #define ENABLE_PREFETCH		(0x1 << 7)
 #define DMA_MPU_MODE		2
 
+#define	DRIVER_NAME	"omap-gpmc"
+
+#define	GPMC_NR_IRQ		2
+
+#define	HIGH			1
+#define	LOW			-1
+
+struct gpmc_device {
+	char			*name;
+	int			id;
+	void			*pdata;
+	unsigned		pdata_size;
+	struct resource		*per_res;
+	unsigned		per_res_cnt;
+	struct resource		*gpmc_res;
+	unsigned		gpmc_res_cnt;
+	bool			have_waitpin;
+	unsigned		waitpin;
+	int			waitpin_polarity;
+};
+
+struct gpmc_irq	{
+	unsigned		irq;
+	u32			bitmask;
+};
+
+struct gpmc {
+	struct device		*dev;
+	unsigned long		clk_prd;
+	void __iomem		*io_base;
+	unsigned long		phys_base;
+	u32			memsize;
+	unsigned		cs_map;
+	int			ecc_used;
+	spinlock_t		mem_lock;
+	struct resource		mem_root;
+	struct resource		cs_mem[GPMC_CS_NUM];
+	/* XXX: Or allocate dynamically ? */
+	struct gpmc_device	device[GPMC_CS_NUM];
+	unsigned		num_device;
+	unsigned		master_irq;
+	unsigned		irq_start;
+	struct gpmc_irq		irq[GPMC_NR_IRQ];
+	struct irq_chip		irq_chip;
+	bool			wp;
+	unsigned		waitpin_map;
+	unsigned		revision;
+};
+
 /* Structure to save gpmc cs context */
 struct gpmc_cs_config {
 	u32 config1;
@@ -91,58 +182,50 @@ struct omap3_gpmc_regs {
 	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
 };
 
-static struct resource	gpmc_mem_root;
-static struct resource	gpmc_cs_mem[GPMC_CS_NUM];
-static DEFINE_SPINLOCK(gpmc_mem_lock);
-static unsigned int gpmc_cs_map;	/* flag for cs which are initialized */
-static int gpmc_ecc_used = -EINVAL;	/* cs using ecc engine */
-
-static void __iomem *gpmc_base;
-
 static struct clk *gpmc_l3_clk;
 
-static irqreturn_t gpmc_handle_irq(int irq, void *dev);
+static struct gpmc *gpmc;
 
 static void gpmc_write_reg(int idx, u32 val)
 {
-	__raw_writel(val, gpmc_base + idx);
+	writel(val, gpmc->io_base + idx);
 }
 
 static u32 gpmc_read_reg(int idx)
 {
-	return __raw_readl(gpmc_base + idx);
+	return readl(gpmc->io_base + idx);
 }
 
 static void gpmc_cs_write_byte(int cs, int idx, u8 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writeb(val, reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writeb(val, reg_addr);
 }
 
 static u8 gpmc_cs_read_byte(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readb(reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readb(reg_addr);
 }
 
 void gpmc_cs_write_reg(int cs, int idx, u32 val)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	__raw_writel(val, reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writel(val, reg_addr);
 }
 
 u32 gpmc_cs_read_reg(int cs, int idx)
 {
 	void __iomem *reg_addr;
 
-	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
-	return __raw_readl(reg_addr);
+	reg_addr = gpmc->io_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readl(reg_addr);
 }
 
 /* TODO: Add support for gpmc_fck to clock framework and use it */
@@ -207,7 +290,8 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 	if (time == 0)
 		ticks = 0;
 	else
-		ticks = gpmc_ns_to_ticks(time);
+		ticks = (time * 1000 + gpmc->clk_prd - 1) / gpmc->clk_prd;
+
 	nr_bits = end_bit - st_bit + 1;
 	if (ticks >= 1 << nr_bits) {
 #ifdef DEBUG
@@ -222,7 +306,7 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 #ifdef DEBUG
 	printk(KERN_INFO
 		"GPMC CS%d: %-10s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
-	       cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000,
+	       cs, name, ticks, gpmc->clk_prd * ticks / 1000,
 			(l >> st_bit) & mask, time);
 #endif
 	l &= ~(mask << st_bit);
@@ -243,6 +327,21 @@ static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 		return -1
 #endif
 
+int gpmc_calc_divider(unsigned int sync_clk)
+{
+	int div;
+	u32 l;
+
+	l = sync_clk + (gpmc->clk_prd - 1);
+	div = l / gpmc->clk_prd;
+	if (div > 4)
+		return -1;
+	if (div <= 0)
+		div = 1;
+
+	return div;
+}
+
 int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
 {
 	int div;
@@ -258,12 +357,53 @@ int gpmc_cs_calc_divider(int cs, unsigned int sync_clk)
 	return div;
 }
 
+static void gpmc_cs_onoff_timings(int cs, const struct gpmc_onoff_timings *p)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
+	if (p->cs_extra_delay)
+		l |= GPMC_CONFIG2_CSEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG2_CSEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
+	if (p->adv_extra_delay)
+		l |= GPMC_CONFIG3_ADVEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG3_ADVEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
+	if (p->oe_extra_delay)
+		l |= GPMC_CONFIG4_OEEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG4_OEEXTRADELAY;
+	if (p->we_extra_delay)
+		l |= GPMC_CONFIG4_WEEXTRADELAY;
+	else
+		l &= ~GPMC_CONFIG4_WEEXTRADELAY;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, l);
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG6);
+	if (p->cycle2cyclesamecsen)
+		l |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
+	else
+		l &= ~GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
+	if (p->cycle2cyclediffcsen)
+		l |= GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
+	else
+		l &= ~GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG6, l);
+}
+
 int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 {
 	int div;
 	u32 l;
 
-	div = gpmc_cs_calc_divider(cs, t->sync_clk);
+	div = gpmc_calc_divider(t->sync_clk);
 	if (div < 0)
 		return -1;
 
@@ -286,7 +426,10 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 
 	GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
 
-	if (cpu_is_omap34xx()) {
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
+	GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, busturnaround);
+
+	if (gpmc->revision >= 5) {
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
 		GPMC_SET_ONE(GPMC_CS_CONFIG6, 24, 28, wr_access);
 	}
@@ -298,13 +441,15 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
 	if (l & (GPMC_CONFIG1_READTYPE_SYNC | GPMC_CONFIG1_WRITETYPE_SYNC)) {
 #ifdef DEBUG
 		printk(KERN_INFO "GPMC CS%d CLK period is %lu ns (div %d)\n",
-				cs, (div * gpmc_get_fclk_period()) / 1000, div);
+				cs, (div * gpmc->clk_prd) / 1000, div);
 #endif
 		l &= ~0x03;
 		l |= (div - 1);
 		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
 	}
 
+	gpmc_cs_onoff_timings(cs, &t->control);
+
 	return 0;
 }
 
@@ -332,7 +477,7 @@ static void gpmc_cs_disable_mem(int cs)
 	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
 }
 
-static void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
+static __devinit void gpmc_cs_get_memconf(int cs, u32 *base, u32 *size)
 {
 	u32 l;
 	u32 mask;
@@ -351,23 +496,23 @@ static int gpmc_cs_mem_enabled(int cs)
 	return l & GPMC_CONFIG7_CSVALID;
 }
 
-int gpmc_cs_set_reserved(int cs, int reserved)
+static int gpmc_cs_set_reserved(int cs, int reserved)
 {
 	if (cs > GPMC_CS_NUM)
 		return -ENODEV;
 
-	gpmc_cs_map &= ~(1 << cs);
-	gpmc_cs_map |= (reserved ? 1 : 0) << cs;
+	gpmc->cs_map &= ~(1 << cs);
+	gpmc->cs_map |= (reserved ? 1 : 0) << cs;
 
 	return 0;
 }
 
-int gpmc_cs_reserved(int cs)
+static int gpmc_cs_reserved(int cs)
 {
 	if (cs > GPMC_CS_NUM)
 		return -ENODEV;
 
-	return gpmc_cs_map & (1 << cs);
+	return gpmc->cs_map & (1 << cs);
 }
 
 static unsigned long gpmc_mem_align(unsigned long size)
@@ -384,24 +529,25 @@ static unsigned long gpmc_mem_align(unsigned long size)
 	return size;
 }
 
-static int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
+static __devinit
+int gpmc_cs_insert_mem(int cs, unsigned long base, unsigned long size)
 {
-	struct resource	*res = &gpmc_cs_mem[cs];
+	struct resource	*res = &gpmc->cs_mem[cs];
 	int r;
 
 	size = gpmc_mem_align(size);
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	res->start = base;
 	res->end = base + size - 1;
-	r = request_resource(&gpmc_mem_root, res);
-	spin_unlock(&gpmc_mem_lock);
+	r = request_resource(&gpmc->mem_root, res);
+	spin_unlock(&gpmc->mem_lock);
 
 	return r;
 }
 
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
-	struct resource *res = &gpmc_cs_mem[cs];
+	struct resource *res = &gpmc->cs_mem[cs];
 	int r = -1;
 
 	if (cs > GPMC_CS_NUM)
@@ -411,7 +557,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (size > (1 << GPMC_SECTION_SHIFT))
 		return -ENOMEM;
 
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	if (gpmc_cs_reserved(cs)) {
 		r = -EBUSY;
 		goto out;
@@ -419,7 +565,7 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	if (gpmc_cs_mem_enabled(cs))
 		r = adjust_resource(res, res->start & ~(size - 1), size);
 	if (r < 0)
-		r = allocate_resource(&gpmc_mem_root, res, size, 0, ~0,
+		r = allocate_resource(&gpmc->mem_root, res, size, 0, ~0,
 				      size, NULL, NULL);
 	if (r < 0)
 		goto out;
@@ -428,24 +574,24 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 	*base = res->start;
 	gpmc_cs_set_reserved(cs, 1);
 out:
-	spin_unlock(&gpmc_mem_lock);
+	spin_unlock(&gpmc->mem_lock);
 	return r;
 }
 EXPORT_SYMBOL(gpmc_cs_request);
 
 void gpmc_cs_free(int cs)
 {
-	spin_lock(&gpmc_mem_lock);
+	spin_lock(&gpmc->mem_lock);
 	if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
 		printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
 		BUG();
-		spin_unlock(&gpmc_mem_lock);
+		spin_unlock(&gpmc->mem_lock);
 		return;
 	}
 	gpmc_cs_disable_mem(cs);
-	release_resource(&gpmc_cs_mem[cs]);
+	release_resource(&gpmc->cs_mem[cs]);
 	gpmc_cs_set_reserved(cs, 0);
-	spin_unlock(&gpmc_mem_lock);
+	spin_unlock(&gpmc->mem_lock);
 }
 EXPORT_SYMBOL(gpmc_cs_free);
 
@@ -668,7 +814,7 @@ int gpmc_prefetch_reset(int cs)
 }
 EXPORT_SYMBOL(gpmc_prefetch_reset);
 
-static void __init gpmc_mem_init(void)
+static __devinit void gpmc_mem_init(void)
 {
 	int cs;
 	unsigned long boot_rom_space = 0;
@@ -680,8 +826,8 @@ static void __init gpmc_mem_init(void)
 	/* In apollon the CS0 is mapped as 0x0000 0000 */
 	if (machine_is_omap_apollon())
 		boot_rom_space = 0;
-	gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
-	gpmc_mem_root.end = GPMC_MEM_END;
+	gpmc->mem_root.start = GPMC_MEM_START + boot_rom_space;
+	gpmc->mem_root.end = GPMC_MEM_END;
 
 	/* Reserve all regions that has been set up by bootloader */
 	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
@@ -697,26 +843,15 @@ static void __init gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	u32 l, irq;
-	int cs, ret = -EINVAL;
-	int gpmc_irq;
+	int ret = -EINVAL;
 	char *ck = NULL;
 
 	if (cpu_is_omap24xx()) {
 		ck = "core_l3_ck";
-		if (cpu_is_omap2420())
-			l = OMAP2420_GPMC_BASE;
-		else
-			l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap34xx()) {
 		ck = "gpmc_fck";
-		l = OMAP34XX_GPMC_BASE;
-		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap44xx()) {
 		ck = "gpmc_ck";
-		l = OMAP44XX_GPMC_BASE;
-		gpmc_irq = OMAP44XX_IRQ_GPMC;
 	}
 
 	if (WARN_ON(!ck))
@@ -728,53 +863,607 @@ static int __init gpmc_init(void)
 		BUG();
 	}
 
-	gpmc_base = ioremap(l, SZ_4K);
-	if (!gpmc_base) {
-		clk_put(gpmc_l3_clk);
-		printk(KERN_ERR "Could not get GPMC register memory\n");
-		BUG();
+	clk_enable(gpmc_l3_clk);
+
+	return 0;
+}
+postcore_initcall(gpmc_init);
+
+static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
+{
+	return gpmc->waitpin_map & (0x1 << waitpin);
+}
+
+static inline void gpmc_reserve_waitpin(struct gpmc *gpmc, unsigned waitpin)
+{
+	gpmc->waitpin_map &= ~(0x1 << waitpin);
+	gpmc->waitpin_map |= (0x1 << waitpin);
+}
+
+static int gpmc_waitpin_request(struct gpmc *gpmc, unsigned waitpin)
+{
+	if (!(waitpin < GPMC_NR_WAITPIN))
+		return -ENODEV;
+
+	if (gpmc_waitpin_is_reserved(gpmc, waitpin))
+		return -EBUSY;
+	else
+		gpmc_reserve_waitpin(gpmc, waitpin);
+
+	return 0;
+}
+
+static int gpmc_setup_waitpin(struct gpmc *gpmc, struct gpmc_device *gd)
+{
+	int ret;
+
+	if (!gd->have_waitpin)
+		return 0;
+
+	ret = gpmc_waitpin_request(gpmc, gd->waitpin);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(gpmc->dev, "waitpin %u reserved\n", gd->waitpin);
+		return ret;
+	} else if (gd->waitpin_polarity) {
+		u32 l = gpmc_read_reg(GPMC_CONFIG);
+		u32 shift = gd->waitpin + GPMC_CONFIG_WAITPIN_POLARITY_SHIFT;
+
+		if (gd->waitpin_polarity == HIGH)
+			l |= 1 << shift;
+		else
+			l &= ~(1 << shift);
+
+		gpmc_write_reg(GPMC_CONFIG, l);
 	}
+	return 0;
+}
 
-	clk_enable(gpmc_l3_clk);
+static int gpmc_setup_cs_waitpin(struct gpmc *gpmc, struct gpmc_device *gd,
+						unsigned cs, unsigned conf)
+{
+	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+	unsigned idx = ~0x0;
+	int polarity = 0;
 
-	l = gpmc_read_reg(GPMC_REVISION);
-	printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);
-	/* Set smart idle mode and automatic L3 clock gating */
-	l = gpmc_read_reg(GPMC_SYSCONFIG);
-	l &= 0x03 << 3;
-	l |= (0x02 << 3) | (1 << 0);
-	gpmc_write_reg(GPMC_SYSCONFIG, l);
-	gpmc_mem_init();
+	switch (conf & GPMC_WAITPIN_MASK) {
+	case GPMC_WAITPIN_0:
+		idx =  GPMC_WAITPIN_IDX0;
+		break;
+	case GPMC_WAITPIN_1:
+		idx =  GPMC_WAITPIN_IDX1;
+		break;
+	case GPMC_WAITPIN_2:
+		idx =  GPMC_WAITPIN_IDX2;
+		break;
+	case GPMC_WAITPIN_3:
+		idx =  GPMC_WAITPIN_IDX3;
+		break;
+	/* no waitpin */
+	case 0:
+		break;
+	default:
+		dev_err(gpmc->dev, "multiple waitpins selected on CS:%u\n", cs);
+		return -EINVAL;
+		break;
+	}
 
-	/* initalize the irq_chained */
-	irq = OMAP_GPMC_IRQ_BASE;
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		irq_set_chip_and_handler(irq, &dummy_irq_chip,
-						handle_simple_irq);
-		set_irq_flags(irq, IRQF_VALID);
-		irq++;
+	switch (conf & GPMC_WAITPIN_POLARITY_MASK) {
+	case GPMC_WAITPIN_ACTIVE_LOW:
+		polarity = LOW;
+		break;
+	case GPMC_WAITPIN_ACTIVE_HIGH:
+		polarity = HIGH;
+		break;
+	/* no waitpin */
+	case 0:
+		break;
+	default:
+		dev_err(gpmc->dev, "waitpin polarity set to low & high\n");
+		return -EINVAL;
+		break;
 	}
 
-	ret = request_irq(gpmc_irq, gpmc_handle_irq, IRQF_SHARED, "gpmc", NULL);
-	if (ret)
-		pr_err("gpmc: irq-%d could not claim: err %d\n",
-						gpmc_irq, ret);
-	return ret;
+	if (idx != ~0x0) {
+		if (gd->have_waitpin) {
+			if (gd->waitpin != idx ||
+					gd->waitpin_polarity != polarity) {
+				dev_err(gpmc->dev, "error: conflict: waitpin %u with polarity %d on device %s.%d\n",
+					gd->waitpin, gd->waitpin_polarity,
+					gd->name, gd->id);
+				return -EBUSY;
+			}
+		} else {
+			gd->have_waitpin = true;
+			gd->waitpin = idx;
+			gd->waitpin_polarity = polarity;
+		}
+
+		l &= ~GPMC_CONFIG1_WAIT_PIN_SEL_MASK;
+		l |= GPMC_CONFIG1_WAIT_PIN_SEL(idx);
+		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+	} else if (polarity) {
+		dev_err(gpmc->dev, "error: waitpin polarity specified with out wait pin number on device %s.%d\n",
+							gd->name, gd->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void gpmc_setup_cs_config(struct gpmc *gpmc, unsigned cs, unsigned conf)
+{
+	u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+	l &= ~(GPMC_CONFIG1_TIMEPARAGRANULARITY |
+		GPMC_CONFIG1_MUXADDDATA |
+		GPMC_CONFIG1_DEVICETYPE(~0) |
+		GPMC_CONFIG1_DEVICESIZE(~0) |
+		GPMC_CONFIG1_WAIT_WRITE_MON |
+		GPMC_CONFIG1_WAIT_READ_MON |
+		GPMC_CONFIG1_PAGE_LEN(~0) |
+		GPMC_CONFIG1_WRITETYPE_SYNC |
+		GPMC_CONFIG1_WRITEMULTIPLE |
+		GPMC_CONFIG1_READTYPE_SYNC |
+		GPMC_CONFIG1_READMULTIPLE |
+		GPMC_CONFIG1_WRAPBURST |
+		GPMC_CONFIG1_WAITPIN_MONITOR_TIME(~0) |
+		GPMC_CONFIG1_CLOCKACTIVATION_TIME(~0));
+
+	if (conf & GPMC_TIMEPARAGRANULARITY)
+		l |= GPMC_CONFIG1_TIMEPARAGRANULARITY;
+	if (conf & GPMC_MUXADDDATA)
+		l |= GPMC_CONFIG1_MUXADDDATA;
+	if (conf & GPMC_DEVICETYPE_NAND)
+		l |= GPMC_CONFIG1_DEVICETYPE_NAND;
+	if (conf & GPMC_DEVICESIZE_16)
+		l |= GPMC_CONFIG1_DEVICESIZE_16;
+	if (conf & GPMC_WAIT_WRITE_MON)
+		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
+	if (conf & GPMC_WAIT_READ_MON)
+		l |= GPMC_CONFIG1_WAIT_READ_MON;
+	if (conf & GPMC_PAGE_LEN_16)
+		l |= GPMC_CONFIG1_PAGE_LEN_16;
+	else if (conf & GPMC_PAGE_LEN_8)
+		l |= GPMC_CONFIG1_PAGE_LEN_8;
+	if (conf & GPMC_WRITETYPE_SYNC)
+		l |= GPMC_CONFIG1_WRITETYPE_SYNC;
+	if (conf & GPMC_WRITEMULTIPLE)
+		l |= GPMC_CONFIG1_WRITEMULTIPLE;
+	if (conf & GPMC_READTYPE_SYNC)
+		l |= GPMC_CONFIG1_READTYPE_SYNC;
+	if (conf & GPMC_READMULTIPLE)
+		l |= GPMC_CONFIG1_READMULTIPLE;
+	if (conf & GPMC_WRAPBURST)
+		l |= GPMC_CONFIG1_WRAPBURST;
+	if (conf & GPMC_WAITPIN_MONITOR_TIME_1)
+		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_1;
+	else if (conf & GPMC_WAITPIN_MONITOR_TIME_2)
+		l |= GPMC_CONFIG1_WAITPIN_MONITOR_TIME_2;
+	if (conf & GPMC_CLOCKACTIVATION_TIME_1)
+		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_1;
+	else if (conf & GPMC_CLOCKACTIVATION_TIME_2)
+		l |= GPMC_CONFIG1_CLOCKACTIVATION_TIME_2;
+
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+
+	if (conf & GPMC_WRITEPROTECT)
+		gpmc->wp = true;
+}
+
+static int gpmc_setup_cs_nonres(struct gpmc *gpmc,
+			struct gpmc_device *gd, struct gpmc_cs_data *cs)
+{
+	int ret;
+
+	/* some boards rely on bootloader for configuration */
+	if (cs->have_config) {
+		gpmc_setup_cs_config(gpmc, cs->cs, cs->config);
+		ret = gpmc_setup_cs_waitpin(gpmc, gd, cs->cs, cs->config);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(gpmc->dev, "error: waitpin on CS %d\n", cs->cs);
+			return ret;
+		}
+	} else
+		dev_warn(gpmc->dev, "config not present for CS: %d\n", cs->cs);
+
+	if (cs->timing) {
+		ret = gpmc_cs_set_timings(cs->cs, cs->timing);
+		if (IS_ERR_VALUE(ret)) {
+			dev_err(gpmc->dev, "error: timing on CS: %d\n", cs->cs);
+			return ret;
+		}
+	} else
+		dev_warn(gpmc->dev, "timing not present for CS: %u\n", cs->cs);
+
+	return 0;
+}
+
+static int gpmc_match_device(struct gpmc *gpmc, char *name, int id)
+{
+	int i;
+	struct gpmc_device *gd;
+
+	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
+		if (!strcmp(gd->name, name) && gd->id == id)
+			return i;
+
+	return -ENOENT;
+}
+
+int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs)
+{
+	int i;
+
+	i = gpmc_match_device(gpmc, name, id);
+	if (IS_ERR_VALUE(i)) {
+		dev_err(gpmc->dev, "no device %s.%d to configure\n", name, id);
+		return i;
+	}
+
+	i = gpmc_setup_cs_nonres(gpmc, gpmc->device + i, cs);
+	if (IS_ERR_VALUE(i)) {
+		dev_err(gpmc->dev, "error: configure device %s.%d\n", name, id);
+		return i;
+	}
+
+	return gpmc_setup_waitpin(gpmc, gpmc->device + i);
+
+}
+EXPORT_SYMBOL_GPL(gpmc_cs_reconfigure);
+
+static inline unsigned int gpmc_bit_to_irq(unsigned bitmask)
+{
+	if (bitmask & GPMC_IRQ_BIT_FIFOEVENT)
+		return GPMC_IRQ_FIFOEVENTENABLE;
+	else if (bitmask & GPMC_IRQ_BIT_TERMINALCOUNT)
+		return GPMC_IRQ_COUNT_EVENT;
+	else
+		return 0;
+}
+
+static __devinit int gpmc_setup_cs_irq(struct gpmc *gpmc,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	int i, n;
+
+	for (i = 0, n = 0; i < GPMC_NR_IRQ; i++)
+		if (gpmc_bit_to_irq(gpmc->irq[i].bitmask) & cs->irq_config) {
+			res[n].start = res[n].end = gpmc->irq[i].irq;
+			res[n].flags = IORESOURCE_IRQ;
+			dev_info(gpmc->dev, "irq %u on CS %d\n",
+						res[n].start, cs->cs);
+			n++;
+		}
+
+	return n;
+}
+
+static __devinit int gpmc_setup_cs_mem(struct gpmc *gpmc,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	unsigned long start;
+	int ret;
+
+	ret = gpmc_cs_request(cs->cs, cs->mem_size, &start);
+	if (IS_ERR_VALUE(ret)) {
+		dev_err(gpmc->dev, "error: gpmc request on CS: %d\n", cs->cs);
+		return ret;
+	}
+
+	res->start = start + cs->mem_offset;
+	res->end = res->start + cs->mem_size - 1;
+	res->flags = IORESOURCE_MEM;
+
+	dev_info(gpmc->dev, "memory 0x%x-0x%x on CS %d\n", res->start,
+							res->end, cs->cs);
+
+	return 1;
+}
+
+static __devinit int gpmc_setup_cs(struct gpmc *gpmc, struct gpmc_device *gd,
+			struct gpmc_cs_data *cs, struct resource *res)
+{
+	int num, ret;
+
+	num = gpmc_setup_cs_mem(gpmc, cs, res);
+	if (IS_ERR_VALUE(num))
+		return num;
+
+	ret = gpmc_setup_cs_nonres(gpmc, gd, cs);
+	if (IS_ERR_VALUE(ret))
+		return ret;
+
+	num += gpmc_setup_cs_irq(gpmc, cs, res + num);
+
+	return num;
+}
+
+static __devinit int gpmc_setup_device(struct gpmc *gpmc,
+		struct gpmc_device *gd, struct gpmc_device_pdata *gdp)
+{
+	int i, n, ret;
+	struct gpmc_cs_data *cs;
+
+	for (i = 0, n = gdp->num_cs, cs = gdp->cs_data;
+				i < gdp->num_cs; i++, cs++)
+		n += hweight32(cs->irq_config);
+
+	gd->gpmc_res = devm_kzalloc(gpmc->dev, sizeof(*gd->gpmc_res) * n,
+								GFP_KERNEL);
+	if (gd->gpmc_res == NULL) {
+		dev_err(gpmc->dev, "error: memory allocation\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0, cs = gdp->cs_data, gd->gpmc_res_cnt = 0;
+			i < gdp->num_cs; cs++, i++) {
+		ret = gpmc_setup_cs(gpmc, gd, cs,
+					gd->gpmc_res + gd->gpmc_res_cnt);
+		if (IS_ERR_VALUE(ret) ||
+				IS_ERR_VALUE(gpmc_setup_waitpin(gpmc, gd))) {
+			dev_err(gpmc->dev, "error: setup for %s\n", gdp->name);
+			devm_kfree(gpmc->dev, gd->gpmc_res);
+			gd->gpmc_res = NULL;
+			gd->gpmc_res_cnt = 0;
+			return -EINVAL;
+		} else
+			gd->gpmc_res_cnt += ret;
+	}
+
+	gd->name = gdp->name;
+	gd->id = gdp->id;
+	gd->pdata = gdp->pdata;
+	gd->pdata_size = gdp->pdata_size;
+	gd->per_res = gdp->per_res;
+	gd->per_res_cnt = gdp->per_res_cnt;
+
+	return 0;
+}
+
+static __devinit
+struct platform_device *gpmc_create_device(struct gpmc *gpmc,
+					struct gpmc_device *p)
+{
+	int num = p->per_res_cnt + p->gpmc_res_cnt;
+	struct resource *res;
+	struct platform_device *pdev;
+
+	res = devm_kzalloc(gpmc->dev, sizeof(struct resource) * num,
+								GFP_KERNEL);
+	if (!res) {
+		dev_err(gpmc->dev, "error: allocating memory\n");
+		return NULL;
+	}
+
+	memcpy((char *)res, (const char *) p->gpmc_res,
+				sizeof(struct resource) * p->gpmc_res_cnt);
+	memcpy((char *)(res + p->gpmc_res_cnt), (const char *)p->per_res,
+				sizeof(struct resource) * p->per_res_cnt);
+
+	pdev = platform_device_register_resndata(gpmc->dev, p->name, p->id,
+					res, num, p->pdata, p->pdata_size);
+
+	devm_kfree(gpmc->dev, res);
+
+	return pdev;
 }
-postcore_initcall(gpmc_init);
 
 static irqreturn_t gpmc_handle_irq(int irq, void *dev)
 {
-	u8 cs;
+	int i;
+	u32 regval;
+	struct gpmc *gpmc = dev;
+
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
 
-	/* check cs to invoke the irq */
-	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
-	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
-		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (regval & gpmc->irq[i].bitmask)
+			generic_handle_irq(gpmc->irq[i].irq);
+
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
 
 	return IRQ_HANDLED;
 }
 
+static int gpmc_irq_endis(struct gpmc *gpmc, unsigned irq, bool endis)
+{
+	int i;
+	u32 regval;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++)
+		if (irq == gpmc->irq[i].irq) {
+			regval = gpmc_read_reg(GPMC_IRQENABLE);
+			if (endis)
+				regval |= gpmc->irq[i].bitmask;
+			else
+				regval &= ~gpmc->irq[i].bitmask;
+			gpmc_write_reg(GPMC_IRQENABLE, regval);
+			break;
+		}
+
+	return 0;
+}
+
+static void gpmc_irq_disable(struct irq_data *p)
+{
+	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, false);
+}
+
+static void gpmc_irq_enable(struct irq_data *p)
+{
+	gpmc_irq_endis(irq_data_get_irq_chip_data(p), p->irq, true);
+}
+
+static void gpmc_irq_noop(struct irq_data *data) { }
+
+static unsigned int gpmc_irq_noop_ret(struct irq_data *data) { return 0; }
+
+static __devinit int gpmc_setup_irq(struct gpmc *gpmc)
+{
+	int i;
+	u32 regval;
+
+	if (!gpmc->master_irq)
+		return -EINVAL;
+
+	gpmc->irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
+	if (IS_ERR_VALUE(gpmc->irq_start)) {
+		dev_err(gpmc->dev, "irq_alloc_descs failed\n");
+		return gpmc->irq_start;
+	}
+
+	gpmc->irq_chip.name = "gpmc";
+	gpmc->irq_chip.irq_startup = gpmc_irq_noop_ret;
+	gpmc->irq_chip.irq_enable = gpmc_irq_enable;
+	gpmc->irq_chip.irq_disable = gpmc_irq_disable;
+	gpmc->irq_chip.irq_shutdown = gpmc_irq_noop;
+	gpmc->irq_chip.irq_ack = gpmc_irq_noop;
+	gpmc->irq_chip.irq_mask = gpmc_irq_noop;
+	gpmc->irq_chip.irq_unmask = gpmc_irq_noop;
+
+	gpmc->irq[0].bitmask = GPMC_IRQ_BIT_FIFOEVENT;
+	gpmc->irq[1].bitmask = GPMC_IRQ_BIT_TERMINALCOUNT;
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		gpmc->irq[i].irq = gpmc->irq_start + i;
+		irq_set_chip_and_handler(gpmc->irq[i].irq,
+					&gpmc->irq_chip, handle_simple_irq);
+		irq_set_chip_data(gpmc->irq[i].irq, gpmc);
+		set_irq_flags(gpmc->irq[i].irq, IRQF_VALID | IRQF_NOAUTOEN);
+	}
+
+	/* Disable interrupts */
+	gpmc_write_reg(GPMC_IRQENABLE, 0);
+
+	/* clear interrupts */
+	regval = gpmc_read_reg(GPMC_IRQSTATUS);
+	gpmc_write_reg(GPMC_IRQSTATUS, regval);
+
+	return request_irq(gpmc->master_irq, gpmc_handle_irq, IRQF_SHARED,
+							"gpmc", gpmc);
+}
+
+static __devinit void gpmc_setup_writeprotect(struct gpmc *gpmc)
+{
+	u32 l;
+
+	l = gpmc_read_reg(GPMC_CONFIG);
+	if (gpmc->wp == true) {
+		l &= ~GPMC_CONFIG_WRITEPROTECT;
+		dev_info(gpmc->dev, "write protect enabled\n");
+	} else
+		l |= GPMC_CONFIG_WRITEPROTECT;
+	gpmc_write_reg(GPMC_CONFIG, l);
+}
+
+static __devinit int gpmc_probe(struct platform_device *pdev)
+{
+	u32 l;
+	int i;
+	int ret = 0;
+	struct resource *res = NULL;
+	struct gpmc_pdata *gp = dev_get_platdata(&pdev->dev);
+	struct gpmc_device_pdata **gdq = NULL;
+	struct gpmc_device *gd = NULL;
+
+	gpmc = devm_kzalloc(&pdev->dev, sizeof(struct gpmc), GFP_KERNEL);
+	if (gpmc == NULL)
+		return -ENOMEM;
+
+	gpmc->dev = &pdev->dev;
+	gpmc->clk_prd = gp->clk_prd;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL)
+		return -ENOENT;
+
+	gpmc->phys_base = res->start;
+	gpmc->memsize = resource_size(res);
+
+	gpmc->io_base = devm_request_and_ioremap(gpmc->dev, res);
+	if (!gpmc->io_base)
+		return -EADDRNOTAVAIL;
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res == NULL)
+		dev_warn(gpmc->dev, "Failed to get resource: irq\n");
+	else
+		gpmc->master_irq = res->start;
+
+	if (IS_ERR_VALUE(gpmc_setup_irq(gpmc)))
+		dev_warn(gpmc->dev, "gpmc_setup_irq failed\n");
+
+	gpmc->ecc_used = -EINVAL;
+	spin_lock_init(&gpmc->mem_lock);
+	platform_set_drvdata(pdev, gpmc);
+
+	l = gpmc_read_reg(GPMC_REVISION);
+	gpmc->revision = (l >> 4) & 0xf;
+	dev_info(gpmc->dev, "GPMC revision %u.%u\n", gpmc->revision, l & 0x0f);
+
+	gpmc_mem_init();
+
+	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
+			(i < gp->num_device) && (*gdq); i++, gdq++) {
+		ret = gpmc_setup_device(gpmc, gd, *gdq);
+		if (IS_ERR_VALUE(ret))
+			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
+								(*gdq)->name);
+		else
+			gd++;
+	}
+	gpmc->num_device = gd - gpmc->device;
+
+	gpmc_setup_writeprotect(gpmc);
+
+	for (i = 0, gd = gpmc->device; i < gpmc->num_device; i++, gd++)
+		if (IS_ERR(gpmc_create_device(gpmc, gd)))
+			dev_err(gpmc->dev, "device creation on %s failed\n",
+								gd->name);
+
+	return 0;
+}
+
+static __devexit int gpmc_free_irq(struct gpmc *gpmc)
+{
+	int i;
+
+	if (gpmc->master_irq)
+		free_irq(gpmc->master_irq, gpmc);
+
+	for (i = 0; i < GPMC_NR_IRQ; i++) {
+		irq_set_handler(gpmc->irq[i].irq, NULL);
+		irq_set_chip(gpmc->irq[i].irq, &no_irq_chip);
+		irq_set_chip_data(gpmc->irq[i].irq, NULL);
+		irq_modify_status(gpmc->irq[i].irq, 0, 0);
+	}
+
+	irq_free_descs(gpmc->irq_start, GPMC_NR_IRQ);
+
+	return 0;
+}
+
+static __devexit int gpmc_remove(struct platform_device *pdev)
+{
+	struct gpmc *gpmc = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	gpmc_free_irq(gpmc);
+
+	return 0;
+}
+
+static struct platform_driver gpmc_driver = {
+	.probe		= gpmc_probe,
+	.remove		= __devexit_p(gpmc_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+module_platform_driver(gpmc_driver);
+
 #ifdef CONFIG_ARCH_OMAP3
 static struct omap3_gpmc_regs gpmc_context;
 
@@ -854,10 +1543,10 @@ int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size)
 	unsigned int val;
 
 	/* check if ecc module is in used */
-	if (gpmc_ecc_used != -EINVAL)
+	if (gpmc->ecc_used != -EINVAL)
 		return -EINVAL;
 
-	gpmc_ecc_used = cs;
+	gpmc->ecc_used = cs;
 
 	/* clear ecc and enable bits */
 	val = ((0x00000001<<8) | 0x00000001);
@@ -905,7 +1594,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
 {
 	unsigned int val = 0x0;
 
-	if (gpmc_ecc_used != cs)
+	if (gpmc->ecc_used != cs)
 		return -EINVAL;
 
 	/* read ecc result */
@@ -915,7 +1604,7 @@ int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code)
 	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
 	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
 
-	gpmc_ecc_used = -EINVAL;
+	gpmc->ecc_used = -EINVAL;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gpmc_calculate_ecc);
arch/arm/plat-omap/include/plat/gpmc.h +89 -4

135 lines not on this page · raw message

Signature · 1 line
1.7.10
#2 lore raw

PATCH 2/39 ARM: OMAP2+: gpmc: Adapt to HWMOD

In reply to Afzal Mohammed

Create API for platforms to adapt gpmc to HWMOD

---
 arch/arm/mach-omap2/gpmc.c             |   52 +++++++++++++++++++++++---------
 arch/arm/plat-omap/include/plat/gpmc.h |    1 +
 2 files changed, 38 insertions(+), 15 deletions(-)
arch/arm/mach-omap2/gpmc.c +37 -15
index 12916f3..c8d07bb 100644
@@ -33,6 +33,8 @@
 
 #include <plat/sdrc.h>
 
+#include <plat/omap_device.h>
+
 /* GPMC register offsets */
 #define GPMC_REVISION		0x00
 #define GPMC_SYSCONFIG		0x10
@@ -276,6 +278,31 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
 	return ticks * gpmc_get_fclk_period() / 1000;
 }
 
+int __init omap_init_gpmc(struct gpmc_pdata *pdata)
+{
+	struct omap_hwmod *oh;
+	struct platform_device *pdev;
+	char *name = "omap-gpmc";
+	char *oh_name = "gpmc";
+
+	pdata->clk_prd = gpmc_get_fclk_period();
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
+
+	pdev = omap_device_build(name, -1, oh, pdata,
+					sizeof(*pdata), NULL, 0, 0);
+	if (IS_ERR(pdev)) {
+		WARN(1, "Can't build omap_device for %s:%s.\n",
+						name, oh->name);
+		return PTR_ERR(pdev);
+	}
+
+	return 0;
+}
 #ifdef DEBUG
 static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
 			       int time, const char *name)
@@ -843,24 +870,19 @@ static __devinit void gpmc_mem_init(void)
 
 static int __init gpmc_init(void)
 {
-	int ret = -EINVAL;
-	char *ck = NULL;
-
-	if (cpu_is_omap24xx()) {
-		ck = "core_l3_ck";
-	} else if (cpu_is_omap34xx()) {
-		ck = "gpmc_fck";
-	} else if (cpu_is_omap44xx()) {
-		ck = "gpmc_ck";
-	}
+	char *oh_name = "gpmc";
+	struct omap_hwmod *oh;
 
-	if (WARN_ON(!ck))
-		return ret;
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
 
-	gpmc_l3_clk = clk_get(NULL, ck);
+	gpmc_l3_clk = clk_get(NULL, oh->main_clk);
 	if (IS_ERR(gpmc_l3_clk)) {
-		printk(KERN_ERR "Could not get GPMC clock %s\n", ck);
-		BUG();
+		pr_err("error: clk_get on %s\n", oh->main_clk);
+		return -EINVAL;
 	}
 
 	clk_enable(gpmc_l3_clk);
arch/arm/plat-omap/include/plat/gpmc.h +1 -0
index 2eedd99..c5cf020 100644
@@ -217,6 +217,7 @@ struct gpmc_pdata {
 };
 
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
+extern int omap_init_gpmc(struct gpmc_pdata *pdata);
 
 extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
 extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
Signature · 1 line
1.7.10
#3 lore raw

PATCH 3/39 ARM: OMAP2+: gpmc: register details for nand driver

In reply to Afzal Mohammed

If peripheral connected is NAND, update NAND drivers platform data with NAND related register addresses so that NAND driver can handle GPMC NAND operations by itself

---
 arch/arm/mach-omap2/gpmc.c             |   25 +++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/gpmc.h |   16 ++++++++++++++++
 arch/arm/plat-omap/include/plat/nand.h |    1 +
 3 files changed, 42 insertions(+)
arch/arm/mach-omap2/gpmc.c +25 -0
index c8d07bb..657ce95 100644
@@ -30,6 +30,7 @@
 
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
+#include <plat/nand.h>
 
 #include <plat/sdrc.h>
 
@@ -891,6 +892,28 @@ static int __init gpmc_init(void)
 }
 postcore_initcall(gpmc_init);
 
+static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
+				struct omap_nand_platform_data *nand)
+{
+	int cs = nand->cs;
+
+	nand->reg.gpmc_status = gpmc->io_base + GPMC_STATUS;
+	nand->reg.gpmc_nand_command = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_nand_address = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_nand_data = gpmc->io_base + GPMC_CS0_OFFSET +
+				GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
+	nand->reg.gpmc_prefetch_config1 = gpmc->io_base + GPMC_PREFETCH_CONFIG1;
+	nand->reg.gpmc_prefetch_config2 = gpmc->io_base + GPMC_PREFETCH_CONFIG2;
+	nand->reg.gpmc_prefetch_control = gpmc->io_base + GPMC_PREFETCH_CONTROL;
+	nand->reg.gpmc_prefetch_status = gpmc->io_base + GPMC_PREFETCH_STATUS;
+	nand->reg.gpmc_ecc_config = gpmc->io_base + GPMC_ECC_CONFIG;
+	nand->reg.gpmc_ecc_control = gpmc->io_base + GPMC_ECC_CONTROL;
+	nand->reg.gpmc_ecc_size_config = gpmc->io_base + GPMC_ECC_SIZE_CONFIG;
+	nand->reg.gpmc_ecc1_result = gpmc->io_base + GPMC_ECC1_RESULT;
+}
+
 static inline int gpmc_waitpin_is_reserved(struct gpmc *gpmc, unsigned waitpin)
 {
 	return gpmc->waitpin_map & (0x1 << waitpin);
@@ -1427,6 +1450,8 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
 
 	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
 			(i < gp->num_device) && (*gdq); i++, gdq++) {
+		if ((*gdq)->is_nand)
+			gpmc_update_nand_reg(gpmc, (*gdq)->pdata);
 		ret = gpmc_setup_device(gpmc, gd, *gdq);
 		if (IS_ERR_VALUE(ret))
 			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
arch/arm/plat-omap/include/plat/gpmc.h +16 -0
index c5cf020..976a8f0 100644
@@ -207,6 +207,7 @@ struct gpmc_device_pdata {
 	unsigned		per_res_cnt;
 	struct gpmc_cs_data	*cs_data;
 	unsigned		num_cs;
+	bool			is_nand;
 };
 
 struct gpmc_pdata {
@@ -216,6 +217,21 @@ struct gpmc_pdata {
 	struct gpmc_device_pdata	**device_pdata;
 };
 
+struct gpmc_nand_regs {
+	void __iomem	*gpmc_status;
+	void __iomem	*gpmc_nand_command;
+	void __iomem	*gpmc_nand_address;
+	void __iomem	*gpmc_nand_data;
+	void __iomem	*gpmc_prefetch_config1;
+	void __iomem	*gpmc_prefetch_config2;
+	void __iomem	*gpmc_prefetch_control;
+	void __iomem	*gpmc_prefetch_status;
+	void __iomem	*gpmc_ecc_config;
+	void __iomem	*gpmc_ecc_control;
+	void __iomem	*gpmc_ecc_size_config;
+	void __iomem	*gpmc_ecc1_result;
+};
+
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *cs);
 extern int omap_init_gpmc(struct gpmc_pdata *pdata);
 
arch/arm/plat-omap/include/plat/nand.h +1 -0
index 67fc506..86e4d9c 100644
@@ -29,6 +29,7 @@ struct omap_nand_platform_data {
 	unsigned long		phys_base;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
+	struct gpmc_nand_regs	reg;
 };
 
 /* minimum size for IO mapping */
Signature · 1 line
1.7.10
#4 lore raw

PATCH 4/39 ARM: OMAP2+: gpmc: Acquire NAND CS value

In reply to Afzal Mohammed

Some boards depend on bootloader to update chip select value for NAND. It is felt that Kernel should not depend on bootloader to get CS, as for a particular board CS is hardwired and is fixed, hence this can directly be updated in Kernel. But as CS value for boards that depend on this behaviour is not available, educate gpmc driver to acquire chip select value for NAND. this ideally should be removed once CS for those boards are available.

---
 arch/arm/mach-omap2/gpmc.c |   32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/gpmc.c +31 -1
index 657ce95..ecd3384 100644
@@ -892,6 +892,30 @@ static int __init gpmc_init(void)
 }
 postcore_initcall(gpmc_init);
 
+static __devinit int gpmc_acquire_nand_cs(struct gpmc *gpmc,
+					struct gpmc_device_pdata *gdp)
+{
+	int cs = 0;
+	struct omap_nand_platform_data *nand = gdp->pdata;
+
+	if ((nand->cs >= 0) && (nand->cs < GPMC_CS_NUM))
+		return 0;
+
+	while (cs < GPMC_CS_NUM) {
+		u32 l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+		if ((l & GPMC_CONFIG1_DEVICETYPE(~0)) ==
+				GPMC_CONFIG1_DEVICETYPE_NAND) {
+			dev_info(gpmc->dev, "found NAND on CS: %d\n", cs);
+			nand->cs = cs;
+			gdp->cs_data->cs = cs;
+			return 0;
+		}
+		cs++;
+	}
+	return -ENODEV;
+}
+
 static __devinit void gpmc_update_nand_reg(struct gpmc *gpmc,
 				struct omap_nand_platform_data *nand)
 {
@@ -1450,8 +1474,14 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
 
 	for (i = 0, gdq = gp->device_pdata, gd = gpmc->device;
 			(i < gp->num_device) && (*gdq); i++, gdq++) {
-		if ((*gdq)->is_nand)
+		if ((*gdq)->is_nand) {
+			ret = gpmc_acquire_nand_cs(gpmc, *gdq);
+			if (IS_ERR_VALUE(ret)) {
+				dev_err(gpmc->dev, "CS error: %d\n", ret);
+				continue;
+			}
 			gpmc_update_nand_reg(gpmc, (*gdq)->pdata);
+		}
 		ret = gpmc_setup_device(gpmc, gd, *gdq);
 		if (IS_ERR_VALUE(ret))
 			dev_err(gpmc->dev, "gpmc setup on %s failed\n",
Signature · 1 line
1.7.10
#5 lore raw

PATCH 5/39 ARM: OMAP2+: nand: create platform data structure

In reply to Afzal Mohammed

New API for updating nand platform data. This has been created by unifying the two existing ones and taking out gpmc hardware handling.

Quoted 1 line

From now on, platforms can call omap_nand_init to

initialize platform nand structures, it's fields. Or can statically create the same.

Acquiring gpmc CS for has been removed. Acquiring CS is done in GPMC driver. To leverage this feature, pass CS # as any value outside the allowed range of 0 - 7 (this is valid only for connected NAND), eg. GPMC_CS_NUM (8)

---
 arch/arm/mach-omap2/board-devkit8000.c     |    6 ++-
 arch/arm/mach-omap2/board-flash.c          |   61 ++++++++++++++--------------
 arch/arm/mach-omap2/board-flash.h          |   13 ++++--
 arch/arm/mach-omap2/board-ldp.c            |    4 +-
 arch/arm/mach-omap2/board-omap3beagle.c    |    6 ++-
 arch/arm/mach-omap2/board-omap3touchbook.c |    6 ++-
 arch/arm/mach-omap2/board-overo.c          |    5 ++-
 arch/arm/mach-omap2/board-zoom.c           |    5 ++-
 arch/arm/mach-omap2/common-board-devices.c |   46 ---------------------
 arch/arm/mach-omap2/common-board-devices.h |    1 -
 10 files changed, 60 insertions(+), 93 deletions(-)
arch/arm/mach-omap2/board-devkit8000.c +4 -2
index a2010f0..aa352d1 100644
@@ -59,6 +59,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #define OMAP_DM9000_GPIO_IRQ	25
@@ -648,8 +649,9 @@ static void __init devkit8000_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions,
-			     ARRAY_SIZE(devkit8000_nand_partitions));
+	board_nand_init(devkit8000_nand_partitions,
+		ARRAY_SIZE(devkit8000_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
arch/arm/mach-omap2/board-flash.c +31 -30

81 lines not on this page · raw message

arch/arm/mach-omap2/board-flash.h +9 -4
index d25503a..052964c 100644
@@ -39,11 +39,16 @@ static inline void board_flash_init(struct flash_partitions part[],
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type);
+extern struct gpmc_timings nand_default_timings[];
+extern struct omap_nand_platform_data *
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t);
 #else
-static inline void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs, int nand_type)
+#define	nand_default_timings	NULL
+static inline struct omap_nand_platform_data *
+board_nand_init(struct mtd_partition *nand_parts,
+		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t)
 {
+	return NULL;
 }
 #endif
arch/arm/mach-omap2/board-ldp.c +2 -2
index 1b60495..b76f28d 100644
@@ -427,8 +427,8 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions,
-		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
+	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
+				ZOOM_NAND_CS, 0, nand_default_timings);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
arch/arm/mach-omap2/board-omap3beagle.c +4 -2
index 7be8d65..671ac1c 100644
@@ -51,6 +51,7 @@
 #include "mux.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 /*
@@ -542,8 +543,9 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions,
-			     ARRAY_SIZE(omap3beagle_nand_partitions));
+	board_nand_init(omap3beagle_nand_partitions,
+		ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
arch/arm/mach-omap2/board-omap3touchbook.c +4 -2
index ae2251f..b691728 100644
@@ -52,6 +52,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #include <asm/setup.h>
@@ -370,8 +371,9 @@ static void __init omap3_touchbook_init(void)
 	omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	omap_nand_flash_init(NAND_BUSWIDTH_16, omap3touchbook_nand_partitions,
-			     ARRAY_SIZE(omap3touchbook_nand_partitions));
+	board_nand_init(omap3touchbook_nand_partitions,
+		ARRAY_SIZE(omap3touchbook_nand_partitions), GPMC_CS_NUM,
+		NAND_BUSWIDTH_16, NULL);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
arch/arm/mach-omap2/board-overo.c +3 -2
index 33aa391..e08479a 100644
@@ -57,6 +57,7 @@
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "hsmmc.h"
+#include "board-flash.h"
 #include "common-board-devices.h"
 
 #define OVERO_GPIO_BT_XGATE	15
@@ -517,8 +518,8 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_nand_flash_init(0, overo_nand_partitions,
-			     ARRAY_SIZE(overo_nand_partitions));
+	board_nand_init(overo_nand_partitions,
+		ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL);
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
arch/arm/mach-omap2/board-zoom.c +3 -2
index 5c20bcc..664e913 100644
@@ -114,8 +114,9 @@ static void __init omap_zoom_init(void)
 		usbhs_init(&usbhs_bdata);
 	}
 
-	board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions),
-						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
+	board_nand_init(zoom_nand_partitions,
+			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS,
+			NAND_BUSWIDTH_16, nand_default_timings);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
 
arch/arm/mach-omap2/common-board-devices.c +0 -46

49 lines not on this page · raw message

arch/arm/mach-omap2/common-board-devices.h +0 -1
index a0b4a428..72bb41b 100644
@@ -10,6 +10,5 @@ struct ads7846_platform_data;
 
 void omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
 		       struct ads7846_platform_data *board_pdata);
-void omap_nand_flash_init(int opts, struct mtd_partition *parts, int n_parts);
 
 #endif /* __OMAP_COMMON_BOARD_DEVICES__ */
Signature · 1 line
1.7.10
#6 lore raw

PATCH 6/39 ARM: OMAP2+: onenand: return value in init function

In reply to Afzal Mohammed

Modify board_onenand_init to return platform data. This would be required for boards to be able to pass it to gpmc driver so that it finally reaches onenand driver.

Also un-static the function so that boards can use it.

---
 arch/arm/mach-omap2/board-flash.c |   14 ++++----------
 arch/arm/mach-omap2/board-flash.h |   12 ++++++++++++
 2 files changed, 16 insertions(+), 10 deletions(-)
arch/arm/mach-omap2/board-flash.c +4 -10
index 091aaf6..8727c05 100644
@@ -87,22 +87,16 @@ static struct omap_onenand_platform_data board_onenand_data = {
 	.dma_channel	= -1,   /* disable DMA in OMAP OneNAND driver */
 };
 
-static void
-__init board_onenand_init(struct mtd_partition *onenand_parts,
-				u8 nr_parts, u8 cs)
+struct omap_onenand_platform_data * __init
+board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs)
 {
 	board_onenand_data.cs		= cs;
 	board_onenand_data.parts	= onenand_parts;
 	board_onenand_data.nr_parts	= nr_parts;
 
-	gpmc_onenand_init(&board_onenand_data);
-}
-#else
-static void
-__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
-{
+	return &board_onenand_data;
 }
-#endif /* CONFIG_MTD_ONENAND_OMAP2 || CONFIG_MTD_ONENAND_OMAP2_MODULE */
+#endif
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE)
arch/arm/mach-omap2/board-flash.h +12 -0
index 052964c..75ba49f 100644
@@ -52,3 +52,15 @@ board_nand_init(struct mtd_partition *nand_parts,
 	return NULL;
 }
 #endif
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+extern struct omap_onenand_platform_data * __init
+board_onenand_init(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs);
+#else
+static inline struct omap_onenand_platform_data *
+__init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+{
+	return NULL;
+}
+#endif
Signature · 1 line
1.7.10
#7 lore raw

PATCH 7/39 ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver

In reply to Afzal Mohammed

Currently gpmc is configured in platform for nand. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information.

---
 arch/arm/mach-omap2/gpmc-nand.c        |   84 ++++++++++++--------------------
 arch/arm/plat-omap/include/plat/nand.h |    8 +--
 2 files changed, 35 insertions(+), 57 deletions(-)
arch/arm/mach-omap2/gpmc-nand.c +30 -54
index 386dec8..190cdc1 100644
@@ -21,24 +21,30 @@
 #include <plat/board.h>
 #include <plat/gpmc.h>
 
-static struct resource gpmc_nand_resource = {
-	.flags		= IORESOURCE_MEM,
+
+static struct gpmc_cs_data gpmc_nand_cs_info = {
+	.have_config	= true,
+	.config		= GPMC_DEVICETYPE_NAND,
+	.irq_config	= GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT,
 };
 
-static struct platform_device gpmc_nand_device = {
+static struct gpmc_device_pdata gpmc_nand_info = {
 	.name		= "omap2-nand",
 	.id		= 0,
-	.num_resources	= 1,
-	.resource	= &gpmc_nand_resource,
+	.cs_data	= &gpmc_nand_cs_info,
+	.num_cs		= 1,
+	.is_nand	= true,
 };
 
-static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data)
-{
-	struct gpmc_timings t;
-	int err;
+static struct gpmc_timings t;
 
-	if (!gpmc_nand_data->gpmc_t)
+static struct gpmc_timings *
+gpmc_nand_retime(struct omap_nand_platform_data *gpmc_nand_data)
+{
+	if (!gpmc_nand_data->gpmc_t) {
+		pr_warn("gpmc timings not provided\n");
 		return 0;
+	}
 
 	memset(&t, 0, sizeof(t));
 	t.sync_clk = gpmc_nand_data->gpmc_t->sync_clk;
@@ -68,56 +74,26 @@ static int omap2_nand_gpmc_retime(struct omap_nand_platform_data *gpmc_nand_data
 	t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->cs_wr_off);
 	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
 
-	/* Configure GPMC */
-	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
-	else
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
-	gpmc_cs_configure(gpmc_nand_data->cs,
-			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
-	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
-	if (err)
-		return err;
-
-	return 0;
+	return &t;
 }
 
-int __init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
+struct gpmc_device_pdata *
+__init gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data)
 {
-	int err	= 0;
-	struct device *dev = &gpmc_nand_device.dev;
+	gpmc_nand_info.pdata = gpmc_nand_data;
+	gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data);
 
-	gpmc_nand_device.dev.platform_data = gpmc_nand_data;
+	gpmc_nand_cs_info.cs = gpmc_nand_data->cs;
+	gpmc_nand_cs_info.mem_size = NAND_IO_SIZE;
 
-	err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
-				&gpmc_nand_data->phys_base);
-	if (err < 0) {
-		dev_err(dev, "Cannot request GPMC CS\n");
-		return err;
-	}
+	gpmc_nand_cs_info.timing = gpmc_nand_retime(gpmc_nand_data);
 
-	 /* Set timings in GPMC */
-	err = omap2_nand_gpmc_retime(gpmc_nand_data);
-	if (err < 0) {
-		dev_err(dev, "Unable to set gpmc timings: %d\n", err);
-		return err;
-	}
-
-	/* Enable RD PIN Monitoring Reg */
-	if (gpmc_nand_data->dev_ready) {
-		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
-	}
-
-	err = platform_device_register(&gpmc_nand_device);
-	if (err < 0) {
-		dev_err(dev, "Unable to register NAND device\n");
-		goto out_free_cs;
-	}
-
-	return 0;
+	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+		gpmc_nand_cs_info.config |= GPMC_DEVICESIZE_16;
 
-out_free_cs:
-	gpmc_cs_free(gpmc_nand_data->cs);
+	if (gpmc_nand_data->dev_ready)
+		gpmc_nand_cs_info.config |= GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON;
 
-	return err;
+	return &gpmc_nand_info;
 }
arch/arm/plat-omap/include/plat/nand.h +5 -3
index 86e4d9c..30c61c9 100644
@@ -36,10 +36,12 @@ struct omap_nand_platform_data {
 #define	NAND_IO_SIZE	4
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
-extern int gpmc_nand_init(struct omap_nand_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_nand_init(struct omap_nand_platform_data *d);
 #else
-static inline int gpmc_nand_init(struct omap_nand_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_nand_init(struct omap_nand_platform_data *d)
 {
-	return 0;
+	return NULL;
 }
 #endif
Signature · 1 line
1.7.10
#8 lore raw

PATCH 8/39 ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver

In reply to Afzal Mohammed

Currently gpmc is configured in platform for onenand. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information.

---
 arch/arm/mach-omap2/gpmc-onenand.c        |  111 +++++++++++++++--------------
 arch/arm/plat-omap/include/plat/onenand.h |    7 +-
 2 files changed, 61 insertions(+), 57 deletions(-)
arch/arm/mach-omap2/gpmc-onenand.c +56 -55
index a0fa9bb..d7775d5 100644
@@ -25,9 +25,17 @@
 
 static struct omap_onenand_platform_data *gpmc_onenand_data;
 
-static struct platform_device gpmc_onenand_device = {
+#define ONENAND_IO_SIZE		SZ_128K
+
+static struct gpmc_cs_data gpmc_onenand_cs_info = {
+	.mem_size	= ONENAND_IO_SIZE,
+};
+
+static struct gpmc_device_pdata gpmc_onenand_info = {
 	.name		= "omap2-onenand",
 	.id		= -1,
+	.cs_data	= &gpmc_onenand_cs_info,
+	.num_cs		= 1,
 };
 
 static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
@@ -79,13 +87,17 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
 	t.wr_cycle  = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
 
 	/* Configure GPMC for asynchronous read */
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
+	gpmc_onenand_cs_info.have_config = true;
+	gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 |
+					GPMC_MUXADDDATA |
+					GPMC_DEVICETYPE_NOR;
+	gpmc_onenand_cs_info.timing = &t;
+	err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+			gpmc_onenand_info.id, &gpmc_onenand_cs_info);
+	if (err) {
+		pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
 		return err;
+	}
 
 	/* Ensure sync read and sync write are disabled */
 	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
@@ -180,7 +192,6 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
 	int err, ticks_cez;
 	int cs = cfg->cs, freq = *freq_ptr;
-	u32 reg;
 	bool clk_dep = false;
 
 	if (cfg->flags & ONENAND_SYNC_READ) {
@@ -276,27 +287,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 					sync_read, sync_write, hf, vhf);
 
 	if (div == 1) {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg |= (1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg |= (1 << 7);
-		reg |= (1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
-	} else {
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
-		reg &= ~(1 << 7);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
-		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
-		reg &= ~(1 << 7);
-		reg &= ~(1 << 23);
-		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
+		t.control.cs_extra_delay = true;
+		t.control.adv_extra_delay = true;
+		t.control.oe_extra_delay = true;
+		t.control.we_extra_delay = true;
 	}
 
 	/* Set synchronous read timings */
@@ -348,24 +342,31 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	}
 
 	/* Configure GPMC for synchronous read */
-	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_WRAPBURST_SUPP |
-			  GPMC_CONFIG1_READMULTIPLE_SUPP |
-			  (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
-			  (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-			  GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
-			  GPMC_CONFIG1_PAGE_LEN(2) |
-			  (cpu_is_omap34xx() ? 0 :
-				(GPMC_CONFIG1_WAIT_READ_MON |
-				 GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
-			  GPMC_CONFIG1_DEVICESIZE_16 |
-			  GPMC_CONFIG1_DEVICETYPE_NOR |
-			  GPMC_CONFIG1_MUXADDDATA);
-
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
+	gpmc_onenand_cs_info.have_config = true;
+	gpmc_onenand_cs_info.config = GPMC_DEVICESIZE_16 | GPMC_MUXADDDATA |
+					GPMC_DEVICETYPE_NOR | GPMC_WRAPBURST |
+					GPMC_READMULTIPLE | GPMC_PAGE_LEN_16;
+	if (!cpu_is_omap34xx())
+		gpmc_onenand_cs_info.config |= GPMC_WAIT_READ_MON |
+						GPMC_WAITPIN_0;
+	if (sync_read)
+		gpmc_onenand_cs_info.config |= GPMC_READTYPE_SYNC;
+	if (sync_write)
+		gpmc_onenand_cs_info.config |= GPMC_WRITETYPE_SYNC |
+						GPMC_WRITEMULTIPLE;
+	if (fclk_offset == 0)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_0;
+	else if (fclk_offset == 1)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_1;
+	else if (fclk_offset == 2)
+		gpmc_onenand_cs_info.config |= GPMC_CLOCKACTIVATIONTIME_2;
+	gpmc_onenand_cs_info.timing = &t;
+	err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+			gpmc_onenand_info.id, &gpmc_onenand_cs_info);
+	if (err) {
+		pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
 		return err;
+	}
 
 	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
 
@@ -376,23 +377,21 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 
 static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 {
-	struct device *dev = &gpmc_onenand_device.dev;
-
 	/* Set sync timings in GPMC */
 	if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
 			freq_ptr) < 0) {
-		dev_err(dev, "Unable to set synchronous mode\n");
+		pr_err("%s: Unable to set synchronous mode\n", __func__);
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
-void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
+struct gpmc_device_pdata *
+__init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
 	gpmc_onenand_data = _onenand_data;
 	gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
-	gpmc_onenand_device.dev.platform_data = gpmc_onenand_data;
 
 	if (cpu_is_omap24xx() &&
 			(gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
@@ -401,8 +400,10 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
 	}
 
-	if (platform_device_register(&gpmc_onenand_device) < 0) {
-		printk(KERN_ERR "Unable to register OneNAND device\n");
-		return;
-	}
+	gpmc_onenand_info.pdata = gpmc_onenand_data;
+	gpmc_onenand_info.pdata_size = sizeof(*gpmc_onenand_data);
+
+	gpmc_onenand_cs_info.cs = gpmc_onenand_data->cs;
+
+	return &gpmc_onenand_info;
 }
arch/arm/plat-omap/include/plat/onenand.h +5 -2
index 2858667..47cd710 100644
@@ -40,14 +40,17 @@ struct omap_onenand_platform_data {
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 
-extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
+extern struct gpmc_device_pdata *
+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)
+static inline struct gpmc_device_pdata *
+gpmc_onenand_init(struct omap_onenand_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
Signature · 1 line
1.7.10
#9 lore raw

PATCH 9/39 ARM: OMAP2+: flash: Adapt to gpmc driver

In reply to Afzal Mohammed

gpmc driver has been converted to driver. Modify board_flash_init so that it can setup gpmc driver platform details for boards

---
 arch/arm/mach-omap2/board-3430sdp.c |    2 +-
 arch/arm/mach-omap2/board-3630sdp.c |    3 +-
 arch/arm/mach-omap2/board-flash.c   |   89 +++++++++++++++++++----------------
 arch/arm/mach-omap2/board-flash.h   |   11 +++--
 4 files changed, 58 insertions(+), 47 deletions(-)
arch/arm/mach-omap2/board-3430sdp.c +1 -1
index da75f23..ac2e398 100644
@@ -620,7 +620,7 @@ static void __init omap_3430sdp_init(void)
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
+	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL);
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
arch/arm/mach-omap2/board-3630sdp.c +2 -1
index 6ef350d..74195b7 100644
@@ -204,7 +204,8 @@ static void __init omap_sdp_init(void)
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
+	board_flash_init(sdp_flash_partitions, chip_sel_sdp,
+		NAND_BUSWIDTH_16, NULL);
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
arch/arm/mach-omap2/board-flash.c +48 -41

134 lines not on this page · raw message

arch/arm/mach-omap2/board-flash.h +7 -4
index 75ba49f..4dd733d 100644
@@ -28,12 +28,15 @@ struct flash_partitions {
 		defined(CONFIG_MTD_NAND_OMAP2_MODULE) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
-extern void board_flash_init(struct flash_partitions [],
-				char chip_sel[][GPMC_CS_NUM], int nand_type);
+extern struct gpmc_device_pdata **board_flash_init(
+		struct flash_partitions [], char chip_sel[][GPMC_CS_NUM],
+		int nand_type, struct gpmc_device_pdata **gpmc_data);
 #else
-static inline void board_flash_init(struct flash_partitions part[],
-				char chip_sel[][GPMC_CS_NUM], int nand_type)
+static inline struct gpmc_device_pdata **board_flash_init(
+	struct flash_partitions part[], char chip_sel[][GPMC_CS_NUM],
+	int nand_type, struct gpmc_device_pdata **gpmc_data)
 {
+	return NULL;
 }
 #endif
 
Signature · 1 line
1.7.10
#10 lore raw

PATCH 10/39 ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver

In reply to Afzal Mohammed

gpmc has been converted to driver. And all gpmc related configuration would be done by gpmc driver. Provide gpmc driver with sufficient information so that it can configure.

---
 arch/arm/mach-omap2/gpmc-smsc911x.c             |   59 ++++++++++++-----------
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |    9 +++-
 2 files changed, 39 insertions(+), 29 deletions(-)
arch/arm/mach-omap2/gpmc-smsc911x.c +32 -27
index b6c77be..2c89685 100644
@@ -24,13 +24,8 @@
 #include <plat/gpmc.h>
 #include <plat/gpmc-smsc911x.h>
 
-static struct resource gpmc_smsc911x_resources[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
-	},
+static struct resource gpmc_smsc911x_resources = {
+	.flags		= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
 };
 
 static struct smsc911x_platform_config gpmc_smsc911x_config = {
@@ -44,26 +39,42 @@ static struct smsc911x_platform_config gpmc_smsc911x_config = {
  * assume that pin multiplexing is done in the board-*.c file,
  * or in the bootloader.
  */
-void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
+__init struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 {
-	struct platform_device *pdev;
-	unsigned long cs_mem_base;
 	int ret;
+	struct gpmc_device_pdata *gpmc_pdev;
+	struct gpmc_cs_data *gpmc_cs;
 
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		pr_err("Failed to request GPMC mem region\n");
-		return;
+	gpmc_pdev = kzalloc(sizeof(*gpmc_pdev), GFP_KERNEL);
+	if (gpmc_pdev == NULL)
+		return gpmc_pdev;
+
+	gpmc_cs = kzalloc(sizeof(*gpmc_cs), GFP_KERNEL);
+	if (gpmc_pdev == NULL) {
+		kfree(gpmc_pdev);
+		return NULL;
 	}
 
-	gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
-	gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
+	gpmc_pdev->cs_data = gpmc_cs;
+	gpmc_pdev->num_cs = 1;
+	gpmc_pdev->name = "smsc911x";
+	gpmc_pdev->id = gpmc_cfg->id;
+	gpmc_pdev->pdata = &gpmc_smsc911x_config;
+	gpmc_pdev->pdata_size = sizeof(gpmc_smsc911x_config);
+
+	gpmc_cs->cs = gpmc_cfg->cs;
+	gpmc_cs->mem_size = 0x100;
+
+	gpmc_pdev->per_res = &gpmc_smsc911x_resources;
+	gpmc_pdev->per_res_cnt = 1;
 
 	if (gpio_request_one(gpmc_cfg->gpio_irq, GPIOF_IN, "smsc911x irq")) {
 		pr_err("Failed to request IRQ GPIO%d\n", gpmc_cfg->gpio_irq);
 		goto free1;
 	}
 
-	gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+	gpmc_smsc911x_resources.start = gpio_to_irq(gpmc_cfg->gpio_irq);
 
 	if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
 		ret = gpio_request_one(gpmc_cfg->gpio_reset,
@@ -81,21 +92,15 @@ void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
 
 	gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT;
 
-	pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id,
-		 gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources),
-		 &gpmc_smsc911x_config, sizeof(gpmc_smsc911x_config));
-	if (!pdev) {
-		pr_err("Unable to register platform device\n");
-		gpio_free(gpmc_cfg->gpio_reset);
-		goto free2;
-	}
-
-	return;
+	return gpmc_pdev;
 
 free2:
 	gpio_free(gpmc_cfg->gpio_irq);
 free1:
-	gpmc_cs_free(gpmc_cfg->cs);
+	kfree(gpmc_cs);
+	kfree(gpmc_pdev);
 
 	pr_err("Could not initialize smsc911x device\n");
+
+	return NULL;
 }
arch/arm/plat-omap/include/plat/gpmc-smsc911x.h +7 -2
index ea6c9c8..66dc7f1 100644
@@ -11,6 +11,8 @@
  * published by the Free Software Foundation.
  */
 
+#include<plat/gpmc.h>
+
 #ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
 
 struct omap_smsc911x_platform_data {
@@ -23,12 +25,15 @@ struct omap_smsc911x_platform_data {
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 
-extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
+extern struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
 
 #else
 
-static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
+static inline struct gpmc_device_pdata *
+gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
Signature · 1 line
1.7.10
#11 lore raw

PATCH 11/39 ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver

In reply to Afzal Mohammed

Currently gpmc is configured in platform for smc91x. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information.

---
 arch/arm/mach-omap2/board-2430sdp.c           |    2 +-
 arch/arm/mach-omap2/board-3430sdp.c           |    1 +
 arch/arm/mach-omap2/board-3630sdp.c           |    1 +
 arch/arm/mach-omap2/gpmc-smc91x.c             |   87 +++++++++++--------------
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h |   10 ++-
 5 files changed, 47 insertions(+), 54 deletions(-)
arch/arm/mach-omap2/board-2430sdp.c +1 -1
index e658f83..68679a8 100644
@@ -175,7 +175,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 	.gpio_irq	= 149,
 	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
 				IORESOURCE_IRQ_LOWLEVEL,
-
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
arch/arm/mach-omap2/board-3430sdp.c +1 -0
index ac2e398..367a466 100644
@@ -434,6 +434,7 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs		= 3,
 	.flags		= GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 |
 				IORESOURCE_IRQ_LOWLEVEL,
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
arch/arm/mach-omap2/board-3630sdp.c +1 -0
index 74195b7..143e47f 100644
@@ -32,6 +32,7 @@
 static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs             = 3,
 	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
+	.skip_timing	= true,
 };
 
 static void __init board_smc91x_init(void)
arch/arm/mach-omap2/gpmc-smc91x.c +37 -50

161 lines not on this page · raw message

arch/arm/plat-omap/include/plat/gpmc-smc91x.h +7 -3
index b64fbee..f3a01b1 100644
@@ -22,20 +22,24 @@ struct omap_smc91x_platform_data {
 	int	gpio_reset;
 	int	wait_pin;	/* Optional GPMC_CONFIG1_WAITPINSELECT */
 	u32	flags;
-	int	(*retime)(void);
+	bool	skip_timing;
+	void	(*retime)(void);
 };
 
 #if defined(CONFIG_SMC91X) || \
 	defined(CONFIG_SMC91X_MODULE)
 
-extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d);
+extern struct gpmc_device_pdata *
+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)
+static inline struct gpmc_device_pdata *
+gpmc_smc91x_init(struct omap_smc91x_platform_data *d)
 {
+	return NULL;
 }
 
 #endif
Signature · 1 line
1.7.10
#12 lore raw

PATCH 12/39 ARM: OMAP2+: gpmc-tusb6010: Adapt to gpmc driver

In reply to Afzal Mohammed

Currently gpmc is configured in platform for tusb6010. As configuring gpmc has been moved to gpmc driver, populate details needed for the driver to configure gpmc. gpmc driver would configure based on this information.

---
 arch/arm/mach-omap2/usb-tusb6010.c |  177 ++++++++++++++----------------------
 include/linux/usb/musb.h           |    4 +-
 2 files changed, 70 insertions(+), 111 deletions(-)
arch/arm/mach-omap2/usb-tusb6010.c +69 -108
index db84a46..d7817d2 100644
@@ -22,6 +22,24 @@
 
 #include "mux.h"
 
+static struct resource tusb_resources = {
+	.name	= "mc",
+	.flags	= IORESOURCE_IRQ,
+};
+
+#define	TUSB_GPMC_CS_ASYNC_IDX	1
+#define	TUSB_GPMC_CS_SYNC_IDX	2
+#define	TUSB_GPMC_CS_NUM	2
+
+static struct gpmc_cs_data gpmc_tusb_cs_data[TUSB_GPMC_CS_NUM];
+
+static struct gpmc_device_pdata gpmc_tusb_data = {
+	.name		= "musb-tusb",
+	.id		= -1,
+	.per_res	= &tusb_resources,
+	.per_res_cnt	= 1,
+};
+
 static u8		async_cs, sync_cs;
 static unsigned		refclk_psec;
 
@@ -51,9 +69,9 @@ next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
 
 /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
 
-static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
+static void tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
 {
-	struct gpmc_timings	t;
+	static struct gpmc_timings t;
 	unsigned		t_acsnh_advnh = sysclk_ps + 3000;
 	unsigned		tmp;
 
@@ -106,12 +124,12 @@ static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
 	tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
-	return gpmc_cs_set_timings(async_cs, &t);
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].timing = &t;
 }
 
 static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
 {
-	struct gpmc_timings	t;
+	static struct gpmc_timings t;
 	unsigned		t_scsnh_advnh = sysclk_ps + 3000;
 	unsigned		tmp;
 
@@ -174,71 +192,30 @@ static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
 	tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
 	t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
 
-	return gpmc_cs_set_timings(sync_cs, &t);
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].timing = &t;
+
+	return 0;
 }
 
 extern unsigned long gpmc_get_fclk_period(void);
 
 /* tusb driver calls this when it changes the chip's clocking */
-int tusb6010_platform_retime(unsigned is_refclk)
+static int tusb6010_platform_retime(unsigned is_refclk)
 {
-	static const char	error[] =
-		KERN_ERR "tusb6010 %s retime error %d\n";
-
 	unsigned	fclk_ps = gpmc_get_fclk_period();
 	unsigned	sysclk_ps;
-	int		status;
 
 	if (!refclk_psec || fclk_ps == 0)
 		return -ENODEV;
 
 	sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
 
-	status = tusb_set_async_mode(sysclk_ps, fclk_ps);
-	if (status < 0) {
-		printk(error, "async", status);
-		goto done;
-	}
-	status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
-	if (status < 0)
-		printk(error, "sync", status);
-done:
-	return status;
+	tusb_set_async_mode(sysclk_ps, fclk_ps);
+	return tusb_set_sync_mode(sysclk_ps, fclk_ps);
 }
-EXPORT_SYMBOL_GPL(tusb6010_platform_retime);
-
-static struct resource tusb_resources[] = {
-	/* Order is significant!  The start/end fields
-	 * are updated during setup..
-	 */
-	{ /* Asynchronous access */
-		.flags	= IORESOURCE_MEM,
-	},
-	{ /* Synchronous access */
-		.flags	= IORESOURCE_MEM,
-	},
-	{ /* IRQ */
-		.name	= "mc",
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 tusb_dmamask = ~(u32)0;
-
-static struct platform_device tusb_device = {
-	.name		= "musb-tusb",
-	.id		= -1,
-	.dev = {
-		.dma_mask		= &tusb_dmamask,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(tusb_resources),
-	.resource	= tusb_resources,
-};
-
 
 /* this may be called only from board-*.c setup code */
-int __init
+__init struct gpmc_device_pdata *
 tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		unsigned ps_refclk, unsigned waitpin,
 		unsigned async, unsigned sync,
@@ -249,82 +226,72 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 		KERN_ERR "tusb6010 init error %d, %d\n";
 
 	/* ASYNC region, primarily for PIO */
-	status = gpmc_cs_request(async, SZ_16M, (unsigned long *)
-				&tusb_resources[0].start);
-	if (status < 0) {
-		printk(error, 1, status);
-		return status;
-	}
-	tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].cs		= async;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].mem_size	= 0x1000;
+
 	async_cs = async;
-	gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_READTYPE_ASYNC
-			| GPMC_CONFIG1_WRITETYPE_ASYNC
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA);
 
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].have_config = true;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_ASYNC_IDX].config = GPMC_DEVICESIZE_16 |
+						GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON |
+						GPMC_READTYPE_ASYNC |
+						GPMC_WRITETYPE_ASYNC |
+						GPMC_DEVICETYPE_NOR |
+						GPMC_MUXADDDATA |
+						GPMC_PAGE_LEN_16 |
+						waitpin;
 
 	/* SYNC region, primarily for DMA */
-	status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
-				&tusb_resources[1].start);
-	if (status < 0) {
-		printk(error, 2, status);
-		return status;
-	}
-	tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].cs		= sync;
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].mem_size	= 0x1000;
+
 	sync_cs = sync;
-	gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
-			  GPMC_CONFIG1_READMULTIPLE_SUPP
-			| GPMC_CONFIG1_READTYPE_SYNC
-			| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
-			| GPMC_CONFIG1_WRITETYPE_SYNC
-			| GPMC_CONFIG1_CLKACTIVATIONTIME(1)
-			| GPMC_CONFIG1_PAGE_LEN(2)
-			| GPMC_CONFIG1_WAIT_READ_MON
-			| GPMC_CONFIG1_WAIT_WRITE_MON
-			| GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-			| GPMC_CONFIG1_DEVICESIZE_16
-			| GPMC_CONFIG1_DEVICETYPE_NOR
-			| GPMC_CONFIG1_MUXADDDATA
-			/* fclk divider gets set later */
-			);
+
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].have_config = true;
+	/* fclk divider gets set later */
+	gpmc_tusb_cs_data[TUSB_GPMC_CS_SYNC_IDX].config = GPMC_DEVICESIZE_16 |
+						GPMC_WAIT_READ_MON |
+						GPMC_WAIT_WRITE_MON |
+						GPMC_READTYPE_SYNC |
+						GPMC_WRITETYPE_SYNC |
+						GPMC_DEVICETYPE_NOR |
+						GPMC_MUXADDDATA |
+						GPMC_PAGE_LEN_16 |
+						GPMC_CLOCKACTIVATION_TIME_1 |
+						GPMC_READMULTIPLE |
+						GPMC_WRITEMULTIPLE |
+						waitpin;
 
 	/* IRQ */
 	status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
 	if (status < 0) {
 		printk(error, 3, status);
-		return status;
+		return NULL;
 	}
-	tusb_resources[2].start = irq + IH_GPIO_BASE;
+	tusb_resources.start = irq + IH_GPIO_BASE;
 
 	/* set up memory timings ... can speed them up later */
 	if (!ps_refclk) {
 		printk(error, 4, status);
-		return -ENODEV;
+		return NULL;
 	}
 	refclk_psec = ps_refclk;
 	status = tusb6010_platform_retime(1);
 	if (status < 0) {
 		printk(error, 5, status);
-		return status;
+		return NULL;
 	}
 
-	/* finish device setup ... */
 	if (!data) {
 		printk(error, 6, status);
-		return -ENODEV;
+		return NULL;
 	}
-	tusb_device.dev.platform_data = data;
+	gpmc_tusb_data.pdata = data;
+	gpmc_tusb_data.pdata_size = sizeof(*data);
 
 	/* REVISIT let the driver know what DMA channels work */
-	if (!dmachan)
-		tusb_device.dev.dma_mask = NULL;
-	else {
+	if (dmachan) {
 		/* assume OMAP 2420 ES2.0 and later */
 		if (dmachan & (1 << 0))
 			omap_mux_init_signal("sys_ndmareq0", 0);
@@ -340,11 +307,5 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 			omap_mux_init_signal("sys_ndmareq5", 0);
 	}
 
-	/* so far so good ... register the device */
-	status = platform_device_register(&tusb_device);
-	if (status < 0) {
-		printk(error, 7, status);
-		return status;
-	}
-	return 0;
+	return &gpmc_tusb_data;
 }
include/linux/usb/musb.h +1 -3
index eb50525..a7de510 100644
@@ -139,14 +139,12 @@ struct musb_hdrc_platform_data {
 
 #ifdef	CONFIG_ARCH_OMAP2
 
-extern int __init tusb6010_setup_interface(
+extern __init struct gpmc_device_pdata *tusb6010_setup_interface(
 		struct musb_hdrc_platform_data *data,
 		unsigned ps_refclk, unsigned waitpin,
 		unsigned async_cs, unsigned sync_cs,
 		unsigned irq, unsigned dmachan);
 
-extern int tusb6010_platform_retime(unsigned is_refclk);
-
 #endif	/* OMAP2 */
 
 #endif /* __LINUX_USB_MUSB_H */
Signature · 1 line
1.7.10
#13 lore raw

PATCH 13/39 ARM: OMAP3: hwmod data: add gpmc

In reply to Afzal Mohammed

Add gpmc hwmod and associated interconnect data

---
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   52 ++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +52 -0
index 0c65079..4da8394 100644
@@ -1981,6 +1981,40 @@ static struct omap_hwmod omap3xxx_usb_tll_hs_hwmod = {
 };
 
 /*
+ * 'gpmc' class
+ * general purpose memory controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_gpmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_gpmc_hwmod_class = {
+	.name	= "gpmc",
+	.sysc	= &omap3xxx_gpmc_sysc,
+};
+
+static struct omap_hwmod_irq_info omap3xxx_gpmc_irqs[] = {
+	{ .irq = 20 },
+	{ .irq = -1 }
+};
+
+static struct omap_hwmod omap3xxx_gpmc_hwmod = {
+	.name		= "gpmc",
+	.class		= &omap3xxx_gpmc_hwmod_class,
+	.clkdm_name	= "l3_init_clkdm",
+	.mpu_irqs	= omap3xxx_gpmc_irqs,
+	.main_clk	= "gpmc_fck",
+	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
+};
+
+/*
  * interfaces
  */
 
@@ -3059,6 +3093,23 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__usb_tll_hs = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap3xxx_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6E000000,
+		.pa_end		= 0x6E000FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l3_main__gpmc = {
+	.master		= &omap3xxx_l3_main_hwmod,
+	.slave		= &omap3xxx_gpmc_hwmod,
+	.clk		= "core_l3_ick",
+	.addr		= omap3xxx_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap3xxx_l3_main__l4_core,
 	&omap3xxx_l3_main__l4_per,
@@ -3103,6 +3154,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
 	&omap34xx_l4_core__mcspi2,
 	&omap34xx_l4_core__mcspi3,
 	&omap34xx_l4_core__mcspi4,
+	&omap3xxx_l3_main__gpmc,
 	NULL,
 };
 
Signature · 1 line
1.7.10
#14 lore raw

PATCH 14/39 ARM: OMAP2xxx: hwmod data: add gpmc

In reply to Afzal Mohammed

Add gpmc hwmod and associated interconnect data

---
 arch/arm/mach-omap2/omap_hwmod_2420_data.c         |   18 +++++++++
 arch/arm/mach-omap2/omap_hwmod_2430_data.c         |   18 +++++++++
 arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c |   41 ++++++++++++++++++++
 arch/arm/mach-omap2/omap_hwmod_common_data.h       |    1 +
 arch/arm/mach-omap2/prcm-common.h                  |    2 +
 5 files changed, 80 insertions(+)
arch/arm/mach-omap2/omap_hwmod_2420_data.c +18 -0
index 2c087ff..55c8c7b 100644
@@ -428,6 +428,23 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap2420_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6800A000,
+		.pa_end		= 0x6800AFFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap2420_l3__gpmc = {
+	.master		= &omap2xxx_l3_main_hwmod,
+	.slave		= &omap2xxx_gpmc_hwmod,
+	.clk		= "core_l3_ck",
+	.addr		= omap2420_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2xxx_l3_main__l4_core,
 	&omap2xxx_mpu__l3_main,
@@ -468,6 +485,7 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 	&omap2420_l4_core__mailbox,
 	&omap2420_l4_core__mcbsp1,
 	&omap2420_l4_core__mcbsp2,
+	&omap2420_l3__gpmc,
 	NULL,
 };
 
arch/arm/mach-omap2/omap_hwmod_2430_data.c +18 -0
index 71d9f88..dd224cca 100644
@@ -838,6 +838,23 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap2430_gpmc_addrs[] = {
+	{
+		.pa_start	= 0x6E000000,
+		.pa_end		= 0x6E000FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+	{ }
+};
+
+static struct omap_hwmod_ocp_if omap2430_l3__gpmc = {
+	.master		= &omap2xxx_l3_main_hwmod,
+	.slave		= &omap2xxx_gpmc_hwmod,
+	.clk		= "core_l3_ck",
+	.addr		= omap2430_gpmc_addrs,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2xxx_l3_main__l4_core,
 	&omap2xxx_mpu__l3_main,
@@ -886,6 +903,7 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 	&omap2430_l4_core__mcbsp3,
 	&omap2430_l4_core__mcbsp4,
 	&omap2430_l4_core__mcbsp5,
+	&omap2430_l3__gpmc,
 	NULL,
 };
 
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +41 -0

50 lines not on this page · raw message

arch/arm/mach-omap2/omap_hwmod_common_data.h +1 -0
index 7aa9156..63e0134 100644
@@ -74,6 +74,7 @@ extern struct omap_hwmod omap2xxx_gpio3_hwmod;
 extern struct omap_hwmod omap2xxx_gpio4_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi1_hwmod;
 extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
+extern struct omap_hwmod omap2xxx_gpmc_hwmod;
 
 /* Common interface data across OMAP2xxx */
 extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
arch/arm/mach-omap2/prcm-common.h +2 -0
index 5aa5435..48c722a 100644
@@ -109,6 +109,8 @@
 #define OMAP2430_EN_MDM_INTC_MASK			(1 << 11)
 #define OMAP2430_EN_USBHS_SHIFT				6
 #define OMAP2430_EN_USBHS_MASK				(1 << 6)
+#define OMAP24XX_EN_GPMC_SHIFT				1
+#define OMAP24XX_EN_GPMC_MASK				(1 << 1)
 
 /* CM_IDLEST1_CORE, PM_WKST1_CORE shared bits */
 #define OMAP2420_ST_MMC_SHIFT				26
Signature · 1 line
1.7.10
#15 lore raw

PATCH 15/39 mtd: nand: omap2: obtain memory from resource

In reply to Afzal Mohammed

gpmc being converted to driver, provides drivers
of peripheral connected memory space used by the
peripheral as memory resource.

Modify nand omap driver to obtain memory detials
from resource structure.

---
 arch/arm/plat-omap/include/plat/nand.h |    1 -
 drivers/mtd/nand/omap2.c               |   20 ++++++++++++++------
 2 files changed, 14 insertions(+), 7 deletions(-)
arch/arm/plat-omap/include/plat/nand.h +0 -1
index 30c61c9..570c4f4 100644
@@ -26,7 +26,6 @@ struct omap_nand_platform_data {
 	bool			dev_ready;
 	int			gpmc_irq;
 	enum nand_io		xfer_type;
-	unsigned long		phys_base;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
 	struct gpmc_nand_regs	reg;
drivers/mtd/nand/omap2.c +14 -6
index c2b0bba..be4b321 100644
@@ -118,6 +118,7 @@ struct omap_nand_info {
 
 	int				gpmc_cs;
 	unsigned long			phys_base;
+	unsigned long			mem_size;
 	struct completion		comp;
 	int				dma_ch;
 	int				gpmc_irq;
@@ -931,6 +932,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	struct omap_nand_platform_data	*pdata;
 	int				err;
 	int				i, offset;
+	struct resource			*res;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -950,7 +952,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
-	info->phys_base		= pdata->phys_base;
 
 	info->mtd.priv		= &info->nand;
 	info->mtd.name		= dev_name(&pdev->dev);
@@ -959,16 +960,23 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->nand.options	= pdata->devsize;
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
 
-	/* NAND write protect off */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_CONFIG_WP, 0);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		err = -EINVAL;
+		dev_err(&pdev->dev, "error getting memory resource\n");
+		goto out_free_info;
+	}
+
+	info->phys_base = res->start;
+	info->mem_size = resource_size(res);
 
-	if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
+	if (!request_mem_region(info->phys_base, info->mem_size,
 				pdev->dev.driver->name)) {
 		err = -EBUSY;
 		goto out_free_info;
 	}
 
-	info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE);
+	info->nand.IO_ADDR_R = ioremap(info->phys_base, info->mem_size);
 	if (!info->nand.IO_ADDR_R) {
 		err = -ENOMEM;
 		goto out_release_mem_region;
@@ -1110,7 +1118,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	return 0;
 
 out_release_mem_region:
-	release_mem_region(info->phys_base, NAND_IO_SIZE);
+	release_mem_region(info->phys_base, info->mem_size);
 out_free_info:
 	kfree(info);
 
Signature · 1 line
1.7.10
#16 lore raw

PATCH 16/39 mtd: nand: omap2: use gpmc provided irqs

In reply to Afzal Mohammed

GPMC driver provides it's clientsd with interrupts that can be used through struct resource. Make use of it for irq mode functionality.

---
 drivers/mtd/nand/omap2.c |   67 +++++++++++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 25 deletions(-)
drivers/mtd/nand/omap2.c +42 -25
index be4b321..440536b 100644
@@ -121,7 +121,8 @@ struct omap_nand_info {
 	unsigned long			mem_size;
 	struct completion		comp;
 	int				dma_ch;
-	int				gpmc_irq;
+	int				gpmc_irq_fifo;
+	int				gpmc_irq_count;
 	enum {
 		OMAP_NAND_IO_READ = 0,	/* read */
 		OMAP_NAND_IO_WRITE,	/* write */
@@ -472,13 +473,11 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 {
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
-	u32 irq_stat;
 
-	irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
 	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
-		if (irq_stat & 0x2)
+		if (this_irq == info->gpmc_irq_count)
 			goto done;
 
 		if (info->buf_len && (info->buf_len < bytes))
@@ -495,20 +494,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 						(u32 *)info->buf, bytes >> 2);
 		info->buf = info->buf + bytes;
 
-		if (irq_stat & 0x2)
+		if (this_irq == info->gpmc_irq_count)
 			goto done;
 	}
-	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
 
 	return IRQ_HANDLED;
 
 done:
 	complete(&info->comp);
-	/* disable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0);
 
-	/* clear status */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+	disable_irq_nosync(info->gpmc_irq_fifo);
+	disable_irq_nosync(info->gpmc_irq_count);
 
 	return IRQ_HANDLED;
 }
@@ -542,9 +538,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 		goto out_copy;
 
 	info->buf_len = len;
-	/* enable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
-		(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	enable_irq(info->gpmc_irq_count);
+	enable_irq(info->gpmc_irq_fifo);
 
 	/* waiting for read to complete */
 	wait_for_completion(&info->comp);
@@ -591,12 +587,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 		goto out_copy;
 
 	info->buf_len = len;
-	/* enable irq */
-	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
-			(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	enable_irq(info->gpmc_irq_count);
+	enable_irq(info->gpmc_irq_fifo);
 
 	/* waiting for write to complete */
 	wait_for_completion(&info->comp);
+
 	/* wait for data to flushed-out before reset the prefetch */
 	tim = 0;
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
@@ -982,6 +979,14 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
+	info->gpmc_irq_fifo = platform_get_irq(pdev, 0);
+	if (info->gpmc_irq_fifo == -ENXIO)
+		dev_warn(&pdev->dev, "error getting FIFO IRQ\n");
+
+	info->gpmc_irq_count = platform_get_irq(pdev, 1);
+	if (info->gpmc_irq_fifo == -ENXIO)
+		dev_warn(&pdev->dev, "error getting TERMINALCOUNT IRQ\n");
+
 	info->nand.controller = &info->controller;
 
 	info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
@@ -1037,17 +1042,24 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		break;
 
 	case NAND_OMAP_PREFETCH_IRQ:
-		err = request_irq(pdata->gpmc_irq,
-				omap_nand_irq, IRQF_SHARED, "gpmc-nand", info);
+		err = request_irq(info->gpmc_irq_fifo,	omap_nand_irq,
+					IRQF_SHARED, "gpmc-nand-fifo", info);
 		if (err) {
 			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
-							pdata->gpmc_irq, err);
+						info->gpmc_irq_fifo, err);
 			goto out_release_mem_region;
-		} else {
-			info->gpmc_irq	     = pdata->gpmc_irq;
-			info->nand.read_buf  = omap_read_buf_irq_pref;
-			info->nand.write_buf = omap_write_buf_irq_pref;
 		}
+		err = request_irq(info->gpmc_irq_count,	omap_nand_irq,
+					IRQF_SHARED, "gpmc-nand-count", info);
+		if (err) {
+			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
+						info->gpmc_irq_count, err);
+			goto out_free_irq_gpmc_fifo;
+		}
+
+		info->nand.read_buf  = omap_read_buf_irq_pref;
+		info->nand.write_buf = omap_write_buf_irq_pref;
+
 		break;
 
 	default:
@@ -1117,6 +1129,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 
 	return 0;
 
+out_free_irq_gpmc_fifo:
+	free_irq(info->gpmc_irq_fifo, info);
 out_release_mem_region:
 	release_mem_region(info->phys_base, info->mem_size);
 out_free_info:
@@ -1135,8 +1149,11 @@ static int omap_nand_remove(struct platform_device *pdev)
 	if (info->dma_ch != -1)
 		omap_free_dma(info->dma_ch);
 
-	if (info->gpmc_irq)
-		free_irq(info->gpmc_irq, info);
+	if (info->gpmc_irq_fifo > 0)
+		free_irq(info->gpmc_irq_fifo, info);
+
+	if (info->gpmc_irq_count > 0)
+		free_irq(info->gpmc_irq_count, info);
 
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
Signature · 1 line
1.7.10
#17 lore raw

PATCH 17/39 mtd: nand: omap2: handle nand on gpmc

In reply to Afzal Mohammed

GPMC driver has been modified to fill NAND platform data with GPMC NAND register details. As these registers are accessible in NAND driver itself, configure NAND in GPMC by itself.

Note: Verfying that other CS have not yet enabled for prefetch & ecc has to be incorporated. Currently this causes no issues as there are no boards that use NAND on multiple CS. With GPMC modifications, perhaps it would be better to consider NAND connected on multiple CS as a single peripheral using multiple CS. This would make handling multiple CS issues easier.

---
 drivers/mtd/nand/omap2.c |  209 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 165 insertions(+), 44 deletions(-)
drivers/mtd/nand/omap2.c +165 -44
index 440536b..34fb726 100644
@@ -129,8 +129,79 @@ struct omap_nand_info {
 	} iomode;
 	u_char				*buf;
 	int					buf_len;
+	struct gpmc_nand_regs		reg;
 };
 
+#define	PREFETCH_CONFIG1_CS_SHIFT	24
+#define	ECC_CONFIG_CS_SHIFT		1
+#define	CS_MASK				0x7
+#define	ENABLE_PREFETCH			(0x1 << 7)
+#define	DMA_MPU_MODE_SHIFT		2
+#define	ECCSIZE1_SHIFT			22
+#define	ECC1RESULTSIZE			0x1
+#define	ECC_CLEAR_SHIFT			8
+#define	ECC1				0x1
+
+/**
+ * omap_prefetch_enable - configures and starts prefetch transfer
+ * @cs: cs (chip select) number
+ * @fifo_th: fifo threshold to be used for read/ write
+ * @dma_mode: dma mode enable (1) or disable (0)
+ * @u32_count: number of bytes to be transferred
+ * @is_write: prefetch read(0) or write post(1) mode
+ */
+static int omap_prefetch_enable(int cs, int fifo_th, int dma_mode,
+	unsigned int u32_count, int is_write, struct omap_nand_info *info)
+{
+	u32 val;
+
+	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
+		pr_err("gpmc: fifo threshold is not supported\n");
+		return -1;
+	} else if (!(readl(info->reg.gpmc_prefetch_control))) {
+		/* Set the amount of bytes to be prefetched */
+		writel(u32_count, info->reg.gpmc_prefetch_config2);
+
+		/* Set dma/mpu mode, the prefetch read / post write and
+		 * enable the engine. Set which cs is has requested for.
+		 */
+		val = ((cs << PREFETCH_CONFIG1_CS_SHIFT) |
+					PREFETCH_FIFOTHRESHOLD(fifo_th) |
+					ENABLE_PREFETCH |
+					(dma_mode << DMA_MPU_MODE_SHIFT) |
+					(0x1 & is_write));
+		writel(val, info->reg.gpmc_prefetch_config1);
+
+		/*  Start the prefetch engine */
+		writel(0x1, info->reg.gpmc_prefetch_control);
+	} else {
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+/**
+ * omap_prefetch_reset - disables and stops the prefetch engine
+ */
+static int omap_prefetch_reset(int cs, struct omap_nand_info *info)
+{
+	u32 config1;
+
+	/* check if the same module/cs is trying to reset */
+	config1 = readl(info->reg.gpmc_prefetch_config1);
+	if (((config1 >> PREFETCH_CONFIG1_CS_SHIFT) & CS_MASK) != cs)
+		return -EINVAL;
+
+	/* Stop the PFPW engine */
+	writel(0x0, info->reg.gpmc_prefetch_control);
+
+	/* Reset/disable the PFPW engine */
+	writel(0x0, info->reg.gpmc_prefetch_config1);
+
+	return 0;
+}
+
 /**
  * omap_hwcontrol - hardware specific access to control-lines
  * @mtd: MTD device structure
@@ -149,13 +220,13 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
 	if (cmd != NAND_CMD_NONE) {
 		if (ctrl & NAND_CLE)
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_COMMAND, cmd);
+			writeb(cmd, info->reg.gpmc_nand_command);
 
 		else if (ctrl & NAND_ALE)
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_ADDRESS, cmd);
+			writeb(cmd, info->reg.gpmc_nand_address);
 
 		else /* NAND_NCE */
-			gpmc_nand_write(info->gpmc_cs, GPMC_NAND_DATA, cmd);
+			writeb(cmd, info->reg.gpmc_nand_data);
 	}
 }
 
@@ -189,7 +260,8 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
 		iowrite8(*p++, info->nand.IO_ADDR_W);
 		/* wait until buffer is available for write */
 		do {
-			status = gpmc_read_status(GPMC_STATUS_BUFFER);
+			status = readl(info->reg.gpmc_status) &
+					GPMC_STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -226,7 +298,8 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
 		iowrite16(*p++, info->nand.IO_ADDR_W);
 		/* wait until buffer is available for write */
 		do {
-			status = gpmc_read_status(GPMC_STATUS_BUFFER);
+			status = readl(info->reg.gpmc_status) &
+					GPMC_STATUS_BUFF_EMPTY;
 		} while (!status);
 	}
 }
@@ -256,8 +329,8 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 	}
 
 	/* configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0, info);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -266,14 +339,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 			omap_read_buf8(mtd, (u_char *)p, len);
 	} else {
 		do {
-			r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+			r_count = readl(info->reg.gpmc_prefetch_status);
+			r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
 			r_count = r_count >> 2;
 			ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
 			p += r_count;
 			len -= r_count << 2;
 		} while (len);
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset(info->gpmc_cs);
+		omap_prefetch_reset(info->gpmc_cs, info);
 	}
 }
 
@@ -292,6 +366,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	int i = 0, ret = 0;
 	u16 *p = (u16 *)buf;
 	unsigned long tim, limit;
+	u32 val;
 
 	/* take care of subpage writes */
 	if (len % 2 != 0) {
@@ -301,8 +376,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	}
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1, info);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -311,7 +386,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 			omap_write_buf8(mtd, (u_char *)p, len);
 	} else {
 		while (len) {
-			w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+			w_count = readl(info->reg.gpmc_prefetch_status);
+			w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
 			w_count = w_count >> 1;
 			for (i = 0; (i < w_count) && len; i++, len -= 2)
 				iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -320,11 +396,14 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 		tim = 0;
 		limit = (loops_per_jiffy *
 					msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-		while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+		do {
 			cpu_relax();
+			val = readl(info->reg.gpmc_prefetch_status);
+			val = GPMC_PREFETCH_STATUS_COUNT(val);
+		} while (val && (tim++ < limit));
 
 		/* disable and stop the PFPW engine */
-		gpmc_prefetch_reset(info->gpmc_cs);
+		omap_prefetch_reset(info->gpmc_cs, info);
 	}
 }
 
@@ -356,6 +435,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	dma_addr_t dma_addr;
 	int ret;
 	unsigned long tim, limit;
+	u32 val;
 
 	/* The fifo depth is 64 bytes max.
 	 * But configure the FIFO-threahold to 32 to get a sync at each frame
@@ -400,8 +480,8 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 					OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
 	}
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -414,11 +494,15 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 	wait_for_completion(&info->comp);
 	tim = 0;
 	limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+
+	do {
 		cpu_relax();
+		val = readl(info->reg.gpmc_prefetch_status);
+		val = GPMC_PREFETCH_STATUS_COUNT(val);
+	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 
 	dma_unmap_single(&info->pdev->dev, dma_addr, len, dir);
 	return 0;
@@ -474,7 +558,8 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
 
-	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+	bytes = readl(info->reg.gpmc_prefetch_status);
+	bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
 	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
 	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
 		if (this_irq == info->gpmc_irq_count)
@@ -531,8 +616,8 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	init_completion(&info->comp);
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -546,7 +631,7 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	wait_for_completion(&info->comp);
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 	return;
 
 out_copy:
@@ -569,6 +654,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 						struct omap_nand_info, mtd);
 	int ret = 0;
 	unsigned long tim, limit;
+	u32 val;
 
 	if (len <= mtd->oobsize) {
 		omap_write_buf_pref(mtd, buf, len);
@@ -580,8 +666,8 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	init_completion(&info->comp);
 
 	/* configure and start prefetch transfer : size=24 */
-	ret = gpmc_prefetch_enable(info->gpmc_cs,
-			(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1);
+	ret = omap_prefetch_enable(info->gpmc_cs,
+		(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1, info);
 	if (ret)
 		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
@@ -597,11 +683,14 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	/* wait for data to flushed-out before reset the prefetch */
 	tim = 0;
 	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
-	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+	do {
+		val = readl(info->reg.gpmc_prefetch_status);
+		val = GPMC_PREFETCH_STATUS_COUNT(val);
 		cpu_relax();
+	} while (val && (tim++ < limit));
 
 	/* disable and stop the PFPW engine */
-	gpmc_prefetch_reset(info->gpmc_cs);
+	omap_prefetch_reset(info->gpmc_cs, info);
 	return;
 
 out_copy:
@@ -841,7 +930,20 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 {
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
-	return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code);
+	u32 val;
+
+	val = readl(info->reg.gpmc_ecc_config);
+	if (((val >> ECC_CONFIG_CS_SHIFT)  & ~CS_MASK) != info->gpmc_cs)
+		return -EINVAL;
+
+	/* read ecc result */
+	val = readl(info->reg.gpmc_ecc1_result);
+	*ecc_code++ = val;          /* P128e, ..., P1e */
+	*ecc_code++ = val >> 16;    /* P128o, ..., P1o */
+	/* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
+	*ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
+
+	return 0;
 }
 
 /**
@@ -855,8 +957,36 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
 							mtd);
 	struct nand_chip *chip = mtd->priv;
 	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+	u32 val;
+
+	/* clear ecc and enable bits */
+	val = ((0x1 << ECC_CLEAR_SHIFT) | ECC1);
+	writel(val, info->reg.gpmc_ecc_control);
+
+	/* program ecc and result sizes */
+	val = ((((info->nand.ecc.size >> 1) - 1) << ECCSIZE1_SHIFT) |
+			 ECC1RESULTSIZE);
+	writel(val, info->reg.gpmc_ecc_size_config);
+
+	switch (mode) {
+	case NAND_ECC_READ:
+		writel(0x101, info->reg.gpmc_ecc_control);
+		break;
+	case NAND_ECC_READSYN:
+		 writel(0x100, info->reg.gpmc_ecc_control);
+		break;
+	case NAND_ECC_WRITE:
+		writel(0x101, info->reg.gpmc_ecc_control);
+		break;
+	default:
+		dev_info(&info->pdev->dev,
+			"error: unrecognized Mode[%d]!\n", mode);
+		break;
+	}
 
-	gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
+	/* (ECC 16 or 8 bit col) | ( CS  )  | ECC Enable */
+	val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
+	writel(val, info->reg.gpmc_ecc_config);
 }
 
 /**
@@ -884,10 +1014,9 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	else
 		timeo += (HZ * 20) / 1000;
 
-	gpmc_nand_write(info->gpmc_cs,
-			GPMC_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF));
+	writeb(NAND_CMD_STATUS & 0xFF, info->reg.gpmc_nand_command);
 	while (time_before(jiffies, timeo)) {
-		status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+		status = readb(info->reg.gpmc_nand_data);
 		if (status & NAND_STATUS_READY)
 			break;
 		cond_resched();
@@ -905,22 +1034,13 @@ static int omap_dev_ready(struct mtd_info *mtd)
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
 
-	val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+	val = readl(info->reg.gpmc_status);
+
 	if ((val & 0x100) == 0x100) {
-		/* Clear IRQ Interrupt */
-		val |= 0x100;
-		val &= ~(0x0);
-		gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, val);
+		return 1;
 	} else {
-		unsigned int cnt = 0;
-		while (cnt++ < 0x1FF) {
-			if  ((val & 0x100) == 0x100)
-				return 0;
-			val = gpmc_read_status(GPMC_GET_IRQ_STATUS);
-		}
+		return 0;
 	}
-
-	return 1;
 }
 
 static int __devinit omap_nand_probe(struct platform_device *pdev)
@@ -949,6 +1069,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->pdev = pdev;
 
 	info->gpmc_cs		= pdata->cs;
+	info->reg		= pdata->reg;
 
 	info->mtd.priv		= &info->nand;
 	info->mtd.name		= dev_name(&pdev->dev);
Signature · 1 line
1.7.10
#18 lore raw

PATCH 18/39 mtd: onenand: omap: obtain memory from resource

In reply to Afzal Mohammed

gpmc being converted to driver, provides drivers of peripheral connected memory space used by the peripheral as memory resource. Modify nand omap driver to obtain memory detials from resource structure. And so remove usage of gpmc exported symbols.

---
 drivers/mtd/onenand/omap2.c |   29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)
drivers/mtd/onenand/omap2.c +16 -13
index 398a827..3ff893d 100644
@@ -48,13 +48,13 @@
 
 #define DRIVER_NAME "omap2-onenand"
 
-#define ONENAND_IO_SIZE		SZ_128K
 #define ONENAND_BUFRAM_SIZE	(1024 * 5)
 
 struct omap2_onenand {
 	struct platform_device *pdev;
 	int gpmc_cs;
 	unsigned long phys_base;
+	unsigned int mem_size;
 	int gpio_irq;
 	struct mtd_info mtd;
 	struct onenand_chip onenand;
@@ -626,6 +626,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	struct omap2_onenand *c;
 	struct onenand_chip *this;
 	int r;
+	struct resource *res;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -647,20 +648,24 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 		c->gpio_irq = 0;
 	}
 
-	r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
-	if (r < 0) {
-		dev_err(&pdev->dev, "Cannot request GPMC CS\n");
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		r = -EINVAL;
+		dev_err(&pdev->dev, "error getting memory resource\n");
 		goto err_kfree;
 	}
 
-	if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
+	c->phys_base = res->start;
+	c->mem_size = resource_size(res);
+
+	if (request_mem_region(c->phys_base, c->mem_size,
 			       pdev->dev.driver->name) == NULL) {
-		dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
-			"size: 0x%x\n",	c->phys_base, ONENAND_IO_SIZE);
+		dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, size: 0x%x\n",
+						c->phys_base, c->mem_size);
 		r = -EBUSY;
-		goto err_free_cs;
+		goto err_kfree;
 	}
-	c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
+	c->onenand.base = ioremap(c->phys_base, c->mem_size);
 	if (c->onenand.base == NULL) {
 		r = -ENOMEM;
 		goto err_release_mem_region;
@@ -776,9 +781,7 @@ err_release_gpio:
 err_iounmap:
 	iounmap(c->onenand.base);
 err_release_mem_region:
-	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
-err_free_cs:
-	gpmc_cs_free(c->gpmc_cs);
+	release_mem_region(c->phys_base, c->mem_size);
 err_kfree:
 	kfree(c);
 
@@ -800,7 +803,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 		gpio_free(c->gpio_irq);
 	}
 	iounmap(c->onenand.base);
-	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+	release_mem_region(c->phys_base, c->mem_size);
 	gpmc_cs_free(c->gpmc_cs);
 	kfree(c);
 
Signature · 1 line
1.7.10
#19 lore raw

PATCH 19/39 ARM: OMAP2+: board omap3evm: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information

---
 arch/arm/mach-omap2/board-omap3evm.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/board-omap3evm.c +13 -1
index fd1b481..b00765e 100644
@@ -43,6 +43,7 @@
 
 #include <plat/board.h>
 #include <plat/usb.h>
+#include <plat/gpmc.h>
 #include "common.h"
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
@@ -102,6 +103,12 @@ static void __init omap3_evm_get_revision(void)
 	}
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <plat/gpmc-smsc911x.h>
 
@@ -122,7 +129,11 @@ static inline void __init omap3evm_init_smsc911x(void)
 			smsc911x_cfg.gpio_reset = OMAP3EVM_GEN2_ETHR_GPIO_RST;
 	}
 
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_device_data = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -679,6 +690,7 @@ static void __init omap3_evm_init(void)
 	usbhs_init(&usbhs_bdata);
 	omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
 	omap3evm_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	omap3_evm_display_init();
 	omap3_evm_wl12xx_init();
 }
Signature · 1 line
1.7.10
#20 lore raw

PATCH 20/39 ARM: OMAP2+: board omap3beagle: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information

---
 arch/arm/mach-omap2/board-omap3beagle.c |   18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/board-omap3beagle.c +17 -1
index 671ac1c..74bc7f6 100644
@@ -517,8 +517,16 @@ static void __init beagle_opp_init(void)
 	return;
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static void __init omap3_beagle_init(void)
 {
+	struct omap_nand_platform_data *nand_data;
+
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap3_beagle_init_rev();
 
@@ -543,9 +551,17 @@ static void __init omap3_beagle_init(void)
 
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
-	board_nand_init(omap3beagle_nand_partitions,
+	nand_data = board_nand_init(omap3beagle_nand_partitions,
 		ARRAY_SIZE(omap3beagle_nand_partitions), GPMC_CS_NUM,
 		NAND_BUSWIDTH_16, NULL);
+	if (nand_data != NULL) {
+		*gpmc_device_data = gpmc_nand_init(nand_data);
+		if (*gpmc_device_data)
+			gpmc_data.num_device++;
+	} else
+		pr_err("error: %s: nand init\n", __func__);
+
+	omap_init_gpmc(&gpmc_data);
 
 	/* Ensure msecure is mux'd to be able to set the RTC. */
 	omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
Signature · 1 line
1.7.10
#21 lore raw

PATCH 21/39 ARM: OMAP2+: board apollon: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. It is believed that apollon board was added before gpmc-smc91x helper functions were added. Reuse the now available gpmc_smc91x_init adapted for gpmc driver.

Note: Timing values were hardcoded and written onto registers, whether making use of gpmc_smc91x_init would configure timing properly has to be tested.

---
 arch/arm/mach-omap2/board-apollon.c |  152 +++++++++--------------------------
 1 file changed, 38 insertions(+), 114 deletions(-)
arch/arm/mach-omap2/board-apollon.c +38 -114
index 768ece2..6a402e1 100644
@@ -39,6 +39,7 @@
 #include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
+#include <plat/gpmc-smc91x.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -58,6 +59,12 @@
 #define APOLLON_ETH_CS		1
 #define APOLLON_ETHR_GPIO_IRQ	74
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition apollon_partitions[] = {
 	{
 		.name		= "X-Loader + U-Boot",
@@ -97,57 +104,26 @@ static struct onenand_platform_data apollon_flash_data = {
 	.nr_parts	= ARRAY_SIZE(apollon_partitions),
 };
 
-static struct resource apollon_flash_resource[] = {
-	[0] = {
-		.flags		= IORESOURCE_MEM,
-	},
+static struct gpmc_cs_data apollon_gpmc_onenand_cs_data = {
+	.cs		= APOLLON_FLASH_CS,
+	.mem_size	= SZ_128K,
 };
 
-static struct platform_device apollon_onenand_device = {
+static struct gpmc_device_pdata apollon_gpmc_onenand_data = {
 	.name		= "onenand-flash",
 	.id		= -1,
-	.dev		= {
-		.platform_data	= &apollon_flash_data,
-	},
-	.num_resources	= ARRAY_SIZE(apollon_flash_resource),
-	.resource	= apollon_flash_resource,
-};
-
-static void __init apollon_flash_init(void)
-{
-	unsigned long base;
-
-	if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) {
-		printk(KERN_ERR "Cannot request OneNAND GPMC CS\n");
-		return;
-	}
-	apollon_flash_resource[0].start = base;
-	apollon_flash_resource[0].end   = base + SZ_128K - 1;
-}
-
-static struct smc91x_platdata appolon_smc91x_info = {
-	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
-	.leda	= RPC_LED_100_10,
-	.ledb	= RPC_LED_TX_RX,
+	.pdata		= &apollon_flash_data,
+	.pdata_size	= sizeof(apollon_flash_data),
+	.cs_data	= &apollon_gpmc_onenand_cs_data,
+	.num_cs		= 1,
 };
 
-static struct resource apollon_smc91x_resources[] = {
-	[0] = {
-		.flags  = IORESOURCE_MEM,
-	},
-	[1] = {
-		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
-	},
-};
-
-static struct platform_device apollon_smc91x_device = {
-	.name		= "smc91x",
-	.id		= -1,
-	.dev	= {
-		.platform_data	= &appolon_smc91x_info,
-	},
-	.num_resources	= ARRAY_SIZE(apollon_smc91x_resources),
-	.resource	= apollon_smc91x_resources,
+static struct omap_smc91x_platform_data apollon_smc91x_data = {
+	.gpio_irq	= APOLLON_ETHR_GPIO_IRQ,
+	.cs		= APOLLON_ETH_CS,
+	.wait_pin	= GPMC_WAITPIN_1,
+	.flags		= GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHEDGE |
+				GPMC_MUXADDDATA,
 };
 
 static struct omap_led_config apollon_led_config[] = {
@@ -185,74 +161,9 @@ static struct platform_device apollon_led_device = {
 };
 
 static struct platform_device *apollon_devices[] __initdata = {
-	&apollon_onenand_device,
-	&apollon_smc91x_device,
 	&apollon_led_device,
 };
 
-static inline void __init apollon_init_smc91x(void)
-{
-	unsigned long base;
-
-	unsigned int rate;
-	struct clk *gpmc_fck;
-	int eth_cs;
-	int err;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
-
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
-
-	eth_cs = APOLLON_ETH_CS;
-
-	/* Make sure CS1 timings are correct */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
-
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else {/* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
-
-	if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
-		goto out;
-	}
-	apollon_smc91x_resources[0].start = base + 0x300;
-	apollon_smc91x_resources[0].end   = base + 0x30f;
-	udelay(100);
-
-	omap_mux_init_gpio(APOLLON_ETHR_GPIO_IRQ, 0);
-	err = gpio_request_one(APOLLON_ETHR_GPIO_IRQ, GPIOF_IN, "SMC91x irq");
-	if (err) {
-		printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
-			APOLLON_ETHR_GPIO_IRQ);
-		gpmc_cs_free(APOLLON_ETH_CS);
-	}
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-}
-
 static struct omap_usb_config apollon_usb_config __initdata = {
 	.register_dev	= 1,
 	.hmc_mode	= 0x14,	/* 0:dev 1:host1 2:disable */
@@ -315,12 +226,27 @@ static struct omap_board_mux board_mux[] __initdata = {
 static void __init omap_apollon_init(void)
 {
 	u32 v;
+	int err, idx = 0;
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
-	apollon_init_smc91x();
+	gpmc_device_data[idx++] = &apollon_gpmc_onenand_data;
+	gpmc_data.num_device++;
+
+	omap_mux_init_gpio(apollon_smc91x_data.gpio_irq, 0);
+	err = gpio_request_one(apollon_smc91x_data.gpio_irq,
+			GPIOF_IN, "SMC91x irq");
+	if (err) {
+		pr_err("error: %s: Failed to request GPIO%d for smc91x IRQ\n",
+			__func__, apollon_smc91x_data.gpio_irq);
+	} else {
+		gpmc_device_data[idx++] =
+			gpmc_smc91x_init(&apollon_smc91x_data);
+		gpmc_data.num_device++;
+	}
+	omap_init_gpmc(&gpmc_data);
+
 	apollon_led_init();
-	apollon_flash_init();
 	apollon_usb_init();
 
 	/* REVISIT: where's the correct place */
@@ -339,8 +265,6 @@ static void __init omap_apollon_init(void)
 	 * You have to mux them off in device drivers later on
 	 * if not needed.
 	 */
-	apollon_smc91x_resources[1].start = gpio_to_irq(APOLLON_ETHR_GPIO_IRQ);
-	apollon_smc91x_resources[1].end = gpio_to_irq(APOLLON_ETHR_GPIO_IRQ);
 	platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
Signature · 1 line
1.7.10
#22 lore raw

PATCH 22/39 ARM: OMAP2+: board h4: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information. Remove unused h4_init_debug too.

---
 arch/arm/mach-omap2/board-h4.c |  130 +++++-----------------------------------
 1 file changed, 15 insertions(+), 115 deletions(-)
arch/arm/mach-omap2/board-h4.c +15 -115
index 0bbbabe..7926082 100644
@@ -186,22 +186,24 @@ static struct physmap_flash_data h4_flash_data = {
 	.nr_parts	= ARRAY_SIZE(h4_partitions),
 };
 
-static struct resource h4_flash_resource = {
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data h4_gpmc_cs_flash_data = {
+	.cs		= H4_FLASH_CS,
+	.mem_size	= SZ_64M,
 };
 
-static struct platform_device h4_flash_device = {
+static struct gpmc_device_pdata h4_gpmc_flash_data = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev		= {
-		.platform_data	= &h4_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &h4_flash_resource,
+	.pdata		= &h4_flash_data,
+	.pdata_size	= sizeof(h4_flash_data),
+	.cs_data	= &h4_gpmc_cs_flash_data,
+	.num_cs		= 1,
 };
 
-static struct platform_device *h4_devices[] __initdata = {
-	&h4_flash_device,
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
 };
 
 static struct panel_generic_dpi_data h4_panel_data = {
@@ -226,109 +228,6 @@ static struct omap_dss_board_info h4_dss_data = {
 	.default_device	= &h4_lcd_device,
 };
 
-/* 2420 Sysboot setup (2430 is different) */
-static u32 get_sysboot_value(void)
-{
-	return (omap_ctrl_readl(OMAP24XX_CONTROL_STATUS) &
-		(OMAP2_SYSBOOT_5_MASK | OMAP2_SYSBOOT_4_MASK |
-		 OMAP2_SYSBOOT_3_MASK | OMAP2_SYSBOOT_2_MASK |
-		 OMAP2_SYSBOOT_1_MASK | OMAP2_SYSBOOT_0_MASK));
-}
-
-/* H4-2420's always used muxed mode, H4-2422's always use non-muxed
- *
- * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423
- *  correctly.  The macro needs to look at production_id not just hawkeye.
- */
-static u32 is_gpmc_muxed(void)
-{
-	u32 mux;
-	mux = get_sysboot_value();
-	if ((mux & 0xF) == 0xd)
-		return 1;	/* NAND config (could be either) */
-	if (mux & 0x2)		/* if mux'ed */
-		return 1;
-	else
-		return 0;
-}
-
-static inline void __init h4_init_debug(void)
-{
-	int eth_cs;
-	unsigned long cs_mem_base;
-	unsigned int muxed, rate;
-	struct clk *gpmc_fck;
-
-	eth_cs	= H4_SMC91X_CS;
-
-	gpmc_fck = clk_get(NULL, "gpmc_fck");	/* Always on ENABLE_ON_INIT */
-	if (IS_ERR(gpmc_fck)) {
-		WARN_ON(1);
-		return;
-	}
-
-	clk_enable(gpmc_fck);
-	rate = clk_get_rate(gpmc_fck);
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-
-	if (is_gpmc_muxed())
-		muxed = 0x200;
-	else
-		muxed = 0;
-
-	/* Make sure CS1 timings are correct */
-	gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1,
-			  0x00011000 | muxed);
-
-	if (rate >= 160000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else if (rate >= 130000000) {
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
-	} else {/* rate = 100000000 */
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
-		gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
-	}
-
-	if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		goto out;
-	}
-
-	udelay(100);
-
-	omap_mux_init_gpio(92, 0);
-	if (debug_card_init(cs_mem_base, H4_ETHR_GPIO_IRQ) < 0)
-		gpmc_cs_free(eth_cs);
-
-out:
-	clk_disable(gpmc_fck);
-	clk_put(gpmc_fck);
-}
-
-static void __init h4_init_flash(void)
-{
-	unsigned long base;
-
-	if (gpmc_cs_request(H4_FLASH_CS, SZ_64M, &base) < 0) {
-		printk("Can't request GPMC CS for flash\n");
-		return;
-	}
-	h4_flash_resource.start	= base;
-	h4_flash_resource.end	= base + SZ_64M - 1;
-}
-
 static struct omap_usb_config h4_usb_config __initdata = {
 	/* S1.10 OFF -- usb "download port"
 	 * usb0 switched to Mini-B port and isp1105 transceiver;
@@ -380,11 +279,12 @@ static void __init omap_h4_init(void)
 	i2c_register_board_info(1, h4_i2c_board_info,
 			ARRAY_SIZE(h4_i2c_board_info));
 
-	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	h4_init_flash();
+	*gpmc_device_data = &h4_gpmc_flash_data;
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 
 	omap_display_init(&h4_dss_data);
 }
Signature · 1 line
1.7.10
#23 lore raw

PATCH 23/39 ARM: OMAP2+: board 3630sdp: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-3630sdp.c |   23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/board-3630sdp.c +19 -4
index 143e47f..4e0298a 100644
@@ -27,18 +27,29 @@
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[4];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
 	.cs             = 3,
 	.flags          = GPMC_MUX_ADD_DATA | IORESOURCE_IRQ_LOWLEVEL,
 	.skip_timing	= true,
+	.gpio_irq	= 158,
 };
 
 static void __init board_smc91x_init(void)
 {
-	board_smc91x_data.gpio_irq = 158;
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -204,9 +215,13 @@ static void __init omap_sdp_init(void)
 	omap_sdrc_init(h8mbx00u0mer0em_sdrc_params,
 				  h8mbx00u0mer0em_sdrc_params);
 	zoom_display_init();
+
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp,
-		NAND_BUSWIDTH_16, NULL);
+	gpmc_data.num_device += board_flash_init(sdp_flash_partitions,
+					chip_sel_sdp, NAND_BUSWIDTH_16,
+					gpmc_cur) - gpmc_cur;
+	omap_init_gpmc(&gpmc_data);
+
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
 }
Signature · 1 line
1.7.10
#24 lore raw

PATCH 24/39 ARM: OMAP2+: board 3430sdp: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-3430sdp.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/board-3430sdp.c +15 -2
index 367a466..cea5ca5 100644
@@ -59,6 +59,12 @@
 
 #define TWL4030_MSECURE_GPIO 22
 
+static struct gpmc_device_pdata *gpmc_device_data[4];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_LEFT),
 	KEY(0, 1, KEY_RIGHT),
@@ -444,7 +450,11 @@ static void __init board_smc91x_init(void)
 	else
 		board_smc91x_data.gpio_irq = 29;
 
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -621,7 +631,10 @@ static void __init omap_3430sdp_init(void)
 	omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
 	usb_musb_init(NULL);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0, NULL);
+	gpmc_data.num_device += board_flash_init(sdp_flash_partitions,
+					chip_sel_3430, 0, gpmc_cur) - gpmc_cur;
+	omap_init_gpmc(&gpmc_data);
+
 	sdp3430_display_init();
 	enable_board_wakeup_source();
 	usbhs_init(&usbhs_bdata);
Signature · 1 line
1.7.10
#25 lore raw

PATCH 25/39 ARM: OMAP2+: board 2430sdp: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-2430sdp.c |   42 +++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 17 deletions(-)
arch/arm/mach-omap2/board-2430sdp.c +25 -17
index 68679a8..d94ada4 100644
@@ -46,9 +46,16 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
-#define SDP2430_CS0_BASE	0x04000000
+#define SDP2430_FLASH_CS		0
 #define SECONDARY_LCD_GPIO		147
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition sdp2430_partitions[] = {
 	/* bootloader (U-Boot, etc) in first sector */
 	{
@@ -86,24 +93,18 @@ static struct physmap_flash_data sdp2430_flash_data = {
 	.nr_parts	= ARRAY_SIZE(sdp2430_partitions),
 };
 
-static struct resource sdp2430_flash_resource = {
-	.start		= SDP2430_CS0_BASE,
-	.end		= SDP2430_CS0_BASE + SZ_64M - 1,
-	.flags		= IORESOURCE_MEM,
+static struct gpmc_cs_data sdp2430_gpmc_cs_flash_data = {
+	.cs		= SDP2430_FLASH_CS,
+	.mem_size	= SZ_64M,
 };
 
-static struct platform_device sdp2430_flash_device = {
+static struct gpmc_device_pdata sdp2430_gpmc_flash_device = {
 	.name		= "physmap-flash",
 	.id		= 0,
-	.dev = {
-		.platform_data	= &sdp2430_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &sdp2430_flash_resource,
-};
-
-static struct platform_device *sdp2430_devices[] __initdata = {
-	&sdp2430_flash_device,
+	.pdata		= &sdp2430_flash_data,
+	.pdata_size	= sizeof(sdp2430_flash_data),
+	.cs_data	= &sdp2430_gpmc_cs_flash_data,
+	.num_cs		= 1,
 };
 
 /* LCD */
@@ -181,7 +182,11 @@ static struct omap_smc91x_platform_data board_smc91x_data = {
 static void __init board_smc91x_init(void)
 {
 	omap_mux_init_gpio(149, OMAP_PIN_INPUT);
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -276,7 +281,9 @@ static void __init omap_2430sdp_init(void)
 
 	omap2430_i2c_init();
 
-	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
+	*gpmc_cur++ = &sdp2430_gpmc_flash_device;
+	gpmc_data.num_device++;
+
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	omap_hsmmc_init(mmc);
@@ -286,6 +293,7 @@ static void __init omap_2430sdp_init(void)
 	usb_musb_init(NULL);
 
 	board_smc91x_init();
+	omap_init_gpmc(&gpmc_data);
 
 	/* Turn off secondary LCD backlight */
 	gpio_request_one(SECONDARY_LCD_GPIO, GPIOF_OUT_INIT_LOW,
Signature · 1 line
1.7.10
#26 lore raw

PATCH 26/39 ARM: OMAP2+: board cm-t3517: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-cm-t3517.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/board-cm-t3517.c +8 -2
index 9e66e16..6aa6b4a 100644
@@ -234,6 +234,11 @@ static struct mtd_partition cm_t3517_nand_partitions[] = {
 	},
 };
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
 static struct omap_nand_platform_data cm_t3517_nand_data = {
 	.parts			= cm_t3517_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(cm_t3517_nand_partitions),
@@ -242,8 +247,8 @@ static struct omap_nand_platform_data cm_t3517_nand_data = {
 
 static void __init cm_t3517_init_nand(void)
 {
-	if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
-		pr_err("CM-T3517: NAND initialization failed\n");
+	*gpmc_device_data = gpmc_nand_init(&cm_t3517_nand_data);
+	gpmc_data.num_device++;
 }
 #else
 static inline void cm_t3517_init_nand(void) {}
@@ -289,6 +294,7 @@ static void __init cm_t3517_init(void)
 	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
 	cm_t3517_init_nand();
+	omap_init_gpmc(&gpmc_data);
 	cm_t3517_init_rtc();
 	cm_t3517_init_usbh();
 	cm_t3517_init_hecc();
Signature · 1 line
1.7.10
#27 lore raw

PATCH 27/39 ARM: OMAP2+: board cm-t35: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-cm-t35.c |   21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/board-cm-t35.c +19 -2
index 909a8b9..5b0b637 100644
@@ -66,6 +66,13 @@
 #include <linux/smsc911x.h>
 #include <plat/gpmc-smsc911x.h>
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct omap_smsc911x_platform_data cm_t35_smsc911x_cfg = {
 	.id		= 0,
 	.cs             = CM_T35_SMSC911X_CS,
@@ -99,8 +106,17 @@ static void __init cm_t35_init_ethernet(void)
 	regulator_register_fixed(1, sb_t35_smsc911x_supplies,
 				 ARRAY_SIZE(sb_t35_smsc911x_supplies));
 
-	gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
-	gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: initilaizing gpmc smsc911x instance 1\n");
+
+	*gpmc_cur = gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: initilaizing gpmc smsc911x instance 2\n");
 }
 #else
 static inline void __init cm_t35_init_ethernet(void) { return; }
@@ -658,6 +674,7 @@ static void __init cm_t3x_common_init(void)
 	cm_t35_init_i2c();
 	omap_ads7846_init(1, CM_T35_GPIO_PENDOWN, 0, NULL);
 	cm_t35_init_ethernet();
+	omap_init_gpmc(&gpmc_data);
 	cm_t35_init_led();
 	cm_t35_init_display();
 
Signature · 1 line
1.7.10
#28 lore raw

PATCH 28/39 ARM: OMAP2+: board ldp: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-ldp.c |   26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/board-ldp.c +23 -3
index b76f28d..1ebc024 100644
@@ -43,6 +43,7 @@
 #include <asm/delay.h>
 #include <plat/usb.h>
 #include <plat/gpmc-smsc911x.h>
+#include <plat/nand.h>
 
 #include <video/omapdss.h>
 #include <video/omap-panel-generic-dpi.h>
@@ -58,6 +59,13 @@
 #define DEBUG_BASE		0x08000000
 #define LDP_ETHR_START		DEBUG_BASE
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(1, 0, KEY_2),
@@ -180,7 +188,9 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init ldp_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
 }
 
 /* LCD */
@@ -418,6 +428,8 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 
 static void __init omap_ldp_init(void)
 {
+	struct omap_nand_platform_data *nand_data;
+
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	ldp_init_smsc911x();
@@ -427,8 +439,16 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	omap_sdrc_init(NULL, NULL);
 	usb_musb_init(NULL);
-	board_nand_init(ldp_nand_partitions, ARRAY_SIZE(ldp_nand_partitions),
-				ZOOM_NAND_CS, 0, nand_default_timings);
+
+	nand_data = board_nand_init(ldp_nand_partitions,
+			ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS,
+			0, nand_default_timings);
+	if (nand_data != NULL) {
+		*gpmc_cur++ = gpmc_nand_init(nand_data);
+		gpmc_data.num_device++;
+	}
+
+	omap_init_gpmc(&gpmc_data);
 
 	omap_hsmmc_init(mmc);
 	ldp_display_init();
Signature · 1 line
1.7.10
#29 lore raw

PATCH 29/39 ARM: OMAP2+: board n8x0: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-n8x0.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/board-n8x0.c +15 -3
index 94f6077..d3d866a 100644
@@ -36,6 +36,7 @@
 #include <plat/onenand.h>
 #include <plat/mmc.h>
 #include <plat/serial.h>
+#include <plat/gpmc.h>
 
 #include "mux.h"
 
@@ -45,6 +46,13 @@
 #define TUSB6010_GPIO_ENABLE	0
 #define TUSB6010_DMACHAN	0x3f
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
 /*
  * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
@@ -114,10 +122,12 @@ static void __init n8x0_usb_init(void)
 	}
 	tusb_set_power(0);
 
-	ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
+	*gpmc_cur = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
 					TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS,
 					TUSB6010_GPIO_INT, TUSB6010_DMACHAN);
-	if (ret != 0)
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
 		goto err;
 
 	printk(announce);
@@ -785,7 +795,9 @@ static void __init n8x0_init_machine(void)
 					ARRAY_SIZE(n810_i2c_board_info_2));
 	board_serial_init();
 	omap_sdrc_init(NULL, NULL);
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_cur++ = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 	n8x0_mmc_init();
 	n8x0_usb_init();
 }
Signature · 1 line
1.7.10
#30 lore raw

PATCH 30/39 ARM: OMAP2+: board omap3logic: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-omap3logic.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/board-omap3logic.c +12 -1
index 9b3c141..9867fc8 100644
@@ -55,6 +55,12 @@
 #define OMAP3_TORPEDO_MMC_GPIO_CD		127
 #define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ		129
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct regulator_consumer_supply omap3logic_vmmc1_supply[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
 };
@@ -180,7 +186,11 @@ static inline void __init board_smsc911x_init(void)
 		return;
 	}
 
-	gpmc_smsc911x_init(&board_smsc911x_data);
+	*gpmc_device_data = gpmc_smsc911x_init(&board_smsc911x_data);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -204,6 +214,7 @@ static void __init omap3logic_init(void)
 	omap_sdrc_init(NULL, NULL);
 	board_mmc_init();
 	board_smsc911x_init();
+	omap_init_gpmc(&gpmc_data);
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
Signature · 1 line
1.7.10
#31 lore raw

PATCH 31/39 ARM: OMAP2+: board omap3pandora: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-omap3pandora.c |   11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/board-omap3pandora.c +9 -2
index 33d995d..25b2de6 100644
@@ -57,6 +57,12 @@
 #define PANDORA_WIFI_NRESET_GPIO	23
 #define OMAP3_PANDORA_TS_GPIO		94
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct mtd_partition omap3pandora_nand_partitions[] = {
 	{
 		.name           = "xloader",
@@ -607,8 +613,9 @@ static void __init omap3pandora_init(void)
 	omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
 	usbhs_init(&usbhs_bdata);
 	usb_musb_init(NULL);
-	gpmc_nand_init(&pandora_nand_data);
-
+	*gpmc_device_data = gpmc_nand_init(&pandora_nand_data);
+	gpmc_data.num_device++;
+	omap_init_gpmc(&gpmc_data);
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
 	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
Signature · 1 line
1.7.10
#32 lore raw

PATCH 32/39 ARM: OMAP2+: board omap3stalker: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-omap3stalker.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/board-omap3stalker.c +12 -1
index 4dffc95..5e92d54 100644
@@ -56,6 +56,12 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #include <plat/gpmc-smsc911x.h>
 
@@ -74,7 +80,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 static inline void __init omap3stalker_init_eth(void)
 {
 	omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP);
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_device_data = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -443,6 +453,7 @@ static void __init omap3_stalker_init(void)
 	omap_mux_init_gpio(18, OMAP_PIN_INPUT_PULLUP);
 
 	omap3stalker_init_eth();
+	omap_init_gpmc(&gpmc_data);
 	omap3_stalker_display_init();
 /* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdr_cke0", OMAP_PIN_OUTPUT);
Signature · 1 line
1.7.10
#33 lore raw

PATCH 33/39 ARM: OMAP2+: board omap4pcm049: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-omap4pcm049.c |   13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/board-omap4pcm049.c +12 -1
index 81de7d5..b4ead86 100644
@@ -130,6 +130,12 @@ static struct omap2_hsmmc_info mmc[] = {
 	}, {}	/* Terminator */
 };
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
@@ -147,7 +153,11 @@ static inline void __init pcm049_init_smsc911x(void)
 {
 	omap_mux_init_gpio(OMAP4_PCM049_ETH_GPIO_IRQ, OMAP_PIN_INPUT);
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
-	gpmc_smsc911x_init(&board_smsc911x_data);
+	*gpmc_device_data = gpmc_smsc911x_init(&board_smsc911x_data);
+	if (*gpmc_device_data)
+		gpmc_data.num_device++;
+	else
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 #else
 static inline void __init pcm049_init_smsc911x(void) { return; }
@@ -562,6 +572,7 @@ static void __init pcm049_init(void)
 	pm_power_off = pcm049_power_off;
 	omap4_mux_init(board_mux, NULL, OMAP_PACKAGE_CBS);
 	pcm049_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	pcm049_i2c_init();
 	platform_add_devices(pcm049_devices, ARRAY_SIZE(pcm049_devices));
 	board_serial_init();
Signature · 1 line
1.7.10
#34 lore raw

PATCH 34/39 ARM: OMAP2+: board overo: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-overo.c |   29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)
arch/arm/mach-omap2/board-overo.c +26 -3
index e08479a..fa0197e 100644
@@ -72,6 +72,13 @@
 #define OVERO_SMSC911X2_CS     4
 #define OVERO_SMSC911X2_GPIO   65
 
+static struct gpmc_device_pdata *gpmc_device_data[3];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
 	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 
@@ -137,8 +144,16 @@ static struct omap_smsc911x_platform_data smsc911x2_cfg = {
 
 static void __init overo_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
-	gpmc_smsc911x_init(&smsc911x2_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: smsc911x instance 1 setup\n", __func__);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x2_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: smsc911x instance 1 setup\n", __func__);
 }
 
 #else
@@ -509,6 +524,7 @@ static struct regulator_consumer_supply dummy_supplies[] = {
 static void __init overo_init(void)
 {
 	int ret;
+	struct omap_nand_platform_data *nand_data;
 
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -518,12 +534,19 @@ static void __init overo_init(void)
 	omap_serial_init();
 	omap_sdrc_init(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	board_nand_init(overo_nand_partitions,
+
+	nand_data = board_nand_init(overo_nand_partitions,
 		ARRAY_SIZE(overo_nand_partitions), GPMC_CS_NUM, 0, NULL);
+	if (nand_data != NULL) {
+		*gpmc_cur++ = gpmc_nand_init(nand_data);
+		gpmc_data.num_device++;
+	}
+
 	usb_musb_init(NULL);
 	usbhs_init(&usbhs_bdata);
 	overo_spi_init();
 	overo_init_smsc911x();
+	omap_init_gpmc(&gpmc_data);
 	overo_display_init();
 	overo_init_led();
 	overo_init_keys();
Signature · 1 line
1.7.10
#35 lore raw

PATCH 35/39 ARM: OMAP2+: board rm680: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-rm680.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/board-rm680.c +9 -1
index ae53d71..e28e606 100644
@@ -33,6 +33,12 @@
 #include "sdram-nokia.h"
 #include "common-board-devices.h"
 
+static struct gpmc_device_pdata *gpmc_device_data[1];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
@@ -119,7 +125,8 @@ static void __init rm680_peripherals_init(void)
 	platform_add_devices(rm680_peripherals_devices,
 				ARRAY_SIZE(rm680_peripherals_devices));
 	rm680_i2c_init();
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_device_data = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
 	omap_hsmmc_init(mmc);
 }
 
@@ -141,6 +148,7 @@ static void __init rm680_init(void)
 
 	usb_musb_init(NULL);
 	rm680_peripherals_init();
+	omap_init_gpmc(&gpmc_data);
 }
 
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
Signature · 1 line
1.7.10
#36 lore raw

PATCH 36/39 ARM: OMAP2+: board rx51: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-rx51-peripherals.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/board-rx51-peripherals.c +15 -2
index ae957c9..af7909e 100644
@@ -73,6 +73,13 @@ enum {
 static struct wl12xx_platform_data wl1251_pdata;
 static struct tsc2005_platform_data tsc2005_pdata;
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_SENSORS_TSL2563) || defined(CONFIG_SENSORS_TSL2563_MODULE)
 static struct tsl2563_platform_data rx51_tsl2563_platform_data = {
 	.cover_comp_gain = 16,
@@ -1039,7 +1046,11 @@ static void __init board_smc91x_init(void)
 	omap_mux_init_gpio(86, OMAP_PIN_OUTPUT);
 	omap_mux_init_gpio(164, OMAP_PIN_OUTPUT);
 
-	gpmc_smc91x_init(&board_smc91x_data);
+	*gpmc_cur = gpmc_smc91x_init(&board_smc91x_data);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: gpmc smsc911x setup\n");
 }
 
 #else
@@ -1136,8 +1147,10 @@ void __init rx51_peripherals_init(void)
 {
 	rx51_i2c_init();
 	regulator_has_full_constraints();
-	gpmc_onenand_init(board_onenand_data);
+	*gpmc_cur++ = gpmc_onenand_init(board_onenand_data);
+	gpmc_data.num_device++;
 	board_smc91x_init();
+	omap_init_gpmc(&gpmc_data);
 	rx51_add_gpio_keys();
 	rx51_init_wl1251();
 	rx51_init_tsc2005();
Signature · 1 line
1.7.10
#37 lore raw

PATCH 37/39 ARM: OMAP2+: board zoom-debugboard: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-zoom-debugboard.c |   47 +++++++++++++++------------
 1 file changed, 27 insertions(+), 20 deletions(-)
arch/arm/mach-omap2/board-zoom-debugboard.c +27 -20
index f64f441..dae7df2 100644
@@ -31,6 +31,13 @@
 #define DEBUG_BASE		0x08000000
 #define ZOOM_ETHR_START	DEBUG_BASE
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
 	.cs             = ZOOM_SMSC911X_CS,
 	.gpio_irq       = ZOOM_SMSC911X_GPIO,
@@ -40,7 +47,11 @@ static struct omap_smsc911x_platform_data zoom_smsc911x_cfg = {
 
 static inline void __init zoom_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&zoom_smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&zoom_smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: %s: gpmc smsc911x setup\n", __func__);
 }
 
 static struct plat_serial8250_port serial_platform_data[] = {
@@ -56,18 +67,22 @@ static struct plat_serial8250_port serial_platform_data[] = {
 	}
 };
 
-static struct platform_device zoom_debugboard_serial_device = {
+static struct gpmc_cs_data zoom_debugboard_gpmc_cs_serial_data = {
+	.cs		= ZOOM_QUADUART_CS,
+	.mem_size	= SZ_1M,
+};
+
+static struct gpmc_device_pdata zoom_debugboard_gpmc_serial_data = {
 	.name			= "serial8250",
 	.id			= PLAT8250_DEV_PLATFORM,
-	.dev			= {
-		.platform_data	= serial_platform_data,
-	},
+	.pdata			= serial_platform_data,
+	.pdata_size		= sizeof(serial_platform_data),
+	.cs_data		= &zoom_debugboard_gpmc_cs_serial_data,
+	.num_cs			= 1,
 };
 
 static inline void __init zoom_init_quaduart(void)
 {
-	int quart_cs;
-	unsigned long cs_mem_base;
 	int quart_gpio = 0;
 
 	if (gpio_request_one(ZOOM_QUADUART_RST_GPIO,
@@ -78,14 +93,6 @@ static inline void __init zoom_init_quaduart(void)
 		return;
 	}
 
-	quart_cs = ZOOM_QUADUART_CS;
-
-	if (gpmc_cs_request(quart_cs, SZ_1M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem"
-				"for Quad UART(TL16CP754C)\n");
-		return;
-	}
-
 	quart_gpio = ZOOM_QUADUART_GPIO;
 
 	if (gpio_request_one(quart_gpio, GPIOF_IN, "TL16CP754C GPIO") < 0)
@@ -93,6 +100,9 @@ static inline void __init zoom_init_quaduart(void)
 								quart_gpio);
 
 	serial_platform_data[0].irq = gpio_to_irq(102);
+
+	*gpmc_cur++ = &zoom_debugboard_gpmc_serial_data;
+	gpmc_data.num_device++;
 }
 
 static inline int omap_zoom_debugboard_detect(void)
@@ -116,10 +126,6 @@ static inline int omap_zoom_debugboard_detect(void)
 	return ret;
 }
 
-static struct platform_device *zoom_devices[] __initdata = {
-	&zoom_debugboard_serial_device,
-};
-
 static struct regulator_consumer_supply dummy_supplies[] = {
 	REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
 	REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
@@ -133,5 +139,6 @@ int __init zoom_debugboard_init(void)
 	regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 	zoom_init_smsc911x();
 	zoom_init_quaduart();
-	return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
+	omap_init_gpmc(&gpmc_data);
+	return 0;
 }
Signature · 1 line
1.7.10
#38 lore raw

PATCH 38/39 OMAP3: igep0020: Add support for Micron NAND Flash storage memory

In reply to Afzal Mohammed

From: Javier Martinez Canillas <[email protected]>

IGEP-based boards can have two different flash memories, a OneNAND or a NAND device. The boot configuration pins (sys_boot) are used to specify which memory is available.

Also, this patch removes unnecesary code for registering the OneNAND.

afzal at ti.com: Update to use modified board_nand_init

fixup: igep

---
 arch/arm/mach-omap2/board-igep0020.c |   75 ++++++++++++++--------------------
 1 file changed, 31 insertions(+), 44 deletions(-)
arch/arm/mach-omap2/board-igep0020.c +31 -44
index 930c0d3..6d171ca 100644
@@ -24,6 +24,8 @@
 #include <linux/i2c/twl.h>
 #include <linux/mmc/host.h>
 
+#include <linux/mtd/nand.h>
+
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -39,6 +41,8 @@
 #include "hsmmc.h"
 #include "sdram-numonyx-m65kxxxxam.h"
 #include "common-board-devices.h"
+#include "board-flash.h"
+#include "control.h"
 
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
@@ -60,6 +64,10 @@
 #define IGEP3_GPIO_LED1_RED	16
 #define IGEP3_GPIO_USBH_NRESET  183
 
+#define IGEP_SYSBOOT_MASK           0x1f
+#define IGEP_SYSBOOT_NAND           0x0f
+#define IGEP_SYSBOOT_ONENAND        0x10
+
 /*
  * IGEP2 Hardware Revision Table
  *
@@ -110,8 +118,10 @@ static void __init igep2_get_revision(void)
 	gpio_free(IGEP2_GPIO_LED1_RED);
 }
 
-#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
-	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+#if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
+	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
+	defined(CONFIG_MTD_NAND_OMAP2) ||		\
+	defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 
 #define ONENAND_MAP             0x20000000
 
@@ -123,7 +133,7 @@ static void __init igep2_get_revision(void)
  * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
  */
 
-static struct mtd_partition igep_onenand_partitions[] = {
+static struct mtd_partition igep_flash_partitions[] = {
 	{
 		.name           = "X-Loader",
 		.offset         = 0,
@@ -151,50 +161,27 @@ static struct mtd_partition igep_onenand_partitions[] = {
 	},
 };
 
-static struct omap_onenand_platform_data igep_onenand_data = {
-	.parts = igep_onenand_partitions,
-	.nr_parts = ARRAY_SIZE(igep_onenand_partitions),
-	.dma_channel	= -1,	/* disable DMA in OMAP OneNAND driver */
-};
-
-static struct platform_device igep_onenand_device = {
-	.name		= "omap2-onenand",
-	.id		= -1,
-	.dev = {
-		.platform_data = &igep_onenand_data,
-	},
-};
+static inline u32 igep_get_sysboot_value(void)
+{
+	return omap_ctrl_readl(OMAP343X_CONTROL_STATUS) & IGEP_SYSBOOT_MASK;
+}
 
 static void __init igep_flash_init(void)
 {
-	u8 cs = 0;
-	u8 onenandcs = GPMC_CS_NUM + 1;
-
-	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
-		u32 ret;
-		ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-		/* Check if NAND/oneNAND is configured */
-		if ((ret & 0xC00) == 0x800)
-			/* NAND found */
-			pr_err("IGEP: Unsupported NAND found\n");
-		else {
-			ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
-			if ((ret & 0x3F) == (ONENAND_MAP >> 24))
-				/* ONENAND found */
-				onenandcs = cs;
-		}
-	}
-
-	if (onenandcs > GPMC_CS_NUM) {
-		pr_err("IGEP: Unable to find configuration in GPMC\n");
-		return;
-	}
-
-	igep_onenand_data.cs = onenandcs;
-
-	if (platform_device_register(&igep_onenand_device) < 0)
-		pr_err("IGEP: Unable to register OneNAND device\n");
+	u32 mux;
+	mux = igep_get_sysboot_value();
+
+	if (mux == IGEP_SYSBOOT_NAND) {
+		pr_info("IGEP: initializing NAND memory device\n");
+		board_nand_init(igep_flash_partitions,
+				ARRAY_SIZE(igep_flash_partitions),
+				0, NAND_BUSWIDTH_16, NULL);
+	} else if (mux == IGEP_SYSBOOT_ONENAND) {
+		pr_info("IGEP: initializing OneNAND memory device\n");
+		board_onenand_init(igep_flash_partitions,
+				   ARRAY_SIZE(igep_flash_partitions), 0);
+	} else
+		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
 }
 
 #else
Signature · 1 line
1.7.10
#39 lore raw

PATCH 39/39 ARM: OMAP2+: board igep0020: gpmc driver adaptation

In reply to Afzal Mohammed

gpmc code has been converted to driver. Modify the board code to provide gpmc driver with required information.

---
 arch/arm/mach-omap2/board-igep0020.c |   32 ++++++++++++++++++++++++++++----
 1 file changed, 28 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/board-igep0020.c +28 -4
index 6d171ca..91de8ce 100644
@@ -36,6 +36,7 @@
 #include <video/omapdss.h>
 #include <video/omap-panel-dvi.h>
 #include <plat/onenand.h>
+#include <plat/nand.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -118,6 +119,13 @@ static void __init igep2_get_revision(void)
 	gpio_free(IGEP2_GPIO_LED1_RED);
 }
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+static struct gpmc_device_pdata **gpmc_cur = gpmc_device_data;
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 #if defined(CONFIG_MTD_ONENAND_OMAP2) ||		\
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) ||	\
 	defined(CONFIG_MTD_NAND_OMAP2) ||		\
@@ -172,14 +180,26 @@ static void __init igep_flash_init(void)
 	mux = igep_get_sysboot_value();
 
 	if (mux == IGEP_SYSBOOT_NAND) {
+		struct omap_nand_platform_data *nand_data;
+
 		pr_info("IGEP: initializing NAND memory device\n");
-		board_nand_init(igep_flash_partitions,
+		nand_data = board_nand_init(igep_flash_partitions,
 				ARRAY_SIZE(igep_flash_partitions),
-				0, NAND_BUSWIDTH_16, NULL);
+				0, NAND_BUSWIDTH_16, nand_default_timings);
+		if (nand_data != NULL) {
+			*gpmc_cur++ = gpmc_nand_init(nand_data);
+			gpmc_data.num_device++;
+		}
 	} else if (mux == IGEP_SYSBOOT_ONENAND) {
+		struct omap_onenand_platform_data *onenand_data;
+
 		pr_info("IGEP: initializing OneNAND memory device\n");
-		board_onenand_init(igep_flash_partitions,
+		onenand_data = board_onenand_init(igep_flash_partitions,
 				   ARRAY_SIZE(igep_flash_partitions), 0);
+		if (onenand_data != NULL) {
+			*gpmc_cur++ = gpmc_onenand_init(onenand_data);
+			gpmc_data.num_device++;
+		}
 	} else
 		pr_err("IGEP: Flash: unsupported sysboot sequence found\n");
 }
@@ -202,7 +222,11 @@ static struct omap_smsc911x_platform_data smsc911x_cfg = {
 
 static inline void __init igep2_init_smsc911x(void)
 {
-	gpmc_smsc911x_init(&smsc911x_cfg);
+	*gpmc_cur = gpmc_smsc911x_init(&smsc911x_cfg);
+	if (*gpmc_cur)
+		gpmc_data.num_device++, gpmc_cur++;
+	else
+		pr_err("error: gpmc smsc911x setup\n");
 }
 
 #else
Signature · 1 line
1.7.10