Skip to contentSkip to conversation

Adapt GPMC peripherals, platforms to driver

PATCH New Afzal Mohammed 2 participants 18 messages Jun 11, 2012 – Jun 14, 2012

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

cover Adapt GPMC peripherals, platforms to driver

Hi,

This series provides new interface for GPMC peripherals that use helper functions for initialization and configures omap3evm & beagleboard GPMC in Kernel. Existing interface would continue to serve its purpose as before.

New interface for smsc911x has been provided the runtime timing calculation capability. This had to be tested on different boards. omap3evm has been converted to use this new smsc911x runtime calculation capability, thus is being configured in Kernel.

beagleboard nand has been modified to use new interface in addition to making use of runtime calculation, and is being configured in Kernel

This series is based on 3.5-rc1, and is dependent on [1,2,3,4] and has been tested on omap3evm (smsc911x) rev G & C and beagle board(nand)

Also using private patches, nand & onenand was tested on omap3evm, rev G & C respectively (as support for these were not in mainline)

omap3evm & beagleboard are the two boards that could be tested here. Within a couple of days, series for converting other boards (but which can't be tested) would be posted (unless there are strong objections to the way these patch series are going) along with updation of feature-removal-schedule.txt regarding deprecation of GPMC bootloader dependency (feature-removal-schedule.txt patch would make sense only with the modification of remaining boards to work gpmc driver)

Regards
Afzal

[1] http://www.mail-archive.com/linux-omap at vger.kernel.org/msg69501.html
[2] http://www.mail-archive.com/linux-omap at vger.kernel.org/msg69881.html
[3] http://www.mail-archive.com/linux-omap at vger.kernel.org/msg69891.html
[4] http://www.mail-archive.com/linux-omap at vger.kernel.org/msg69897.html

Afzal Mohammed (9):
ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver
ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver
ARM: OMAP2+: flash: Adapt to use gpmc driver
ARM: OMAP2+: gpmc-tusb6010: Adapt to use gpmc driver
ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver
ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver
ARM: OMAP2+: gpmc-smsc911x: runtime time calculation
ARM: OMAP2+: board omap3evm: use gpmc driver
ARM: OMAP2+: board omap3beagle: use gpmc driver

 arch/arm/mach-omap2/board-flash.c               |  126 +++++++++++++++++++++++
 arch/arm/mach-omap2/board-flash.h               |   29 ++++++
 arch/arm/mach-omap2/board-omap3beagle.c         |   16 ++-
 arch/arm/mach-omap2/board-omap3evm.c            |   12 ++-
 arch/arm/mach-omap2/gpmc-nand.c                 |   41 ++++++++
 arch/arm/mach-omap2/gpmc-onenand.c              |  117 ++++++++++++++++++---
 arch/arm/mach-omap2/gpmc-smc91x.c               |   69 +++++++++++--
 arch/arm/mach-omap2/gpmc-smsc911x.c             |  119 +++++++++++++++++++++
 arch/arm/mach-omap2/usb-tusb6010.c              |  113 +++++++++++++++++++-
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h   |   12 ++-
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |   25 ++++-
 arch/arm/plat-omap/include/plat/gpmc.h          |    8 ++
 arch/arm/plat-omap/include/plat/nand.h          |    7 ++
 arch/arm/plat-omap/include/plat/onenand.h       |    8 +-
 14 files changed, 662 insertions(+), 40 deletions(-)
Signature · 1 line
1.7.10.2
#1 lore raw

PATCH 1/9 ARM: OMAP2+: gpmc-nand: Adapt to use gpmc driver

Currently gpmc is configured in platform for nand. As now gpmc driver is present, populate details needed for the driver to configure gpmc, gpmc driver would configure based on this information. Old interface has been left as is so that platforms can continue configuring gpmc using old interface too. This is done so that driver conversion can be done gradually without breaking any.

---
 arch/arm/mach-omap2/gpmc-nand.c        |   41 ++++++++++++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/nand.h |    7 ++++++
 2 files changed, 48 insertions(+)
arch/arm/mach-omap2/gpmc-nand.c +41 -0
index 045596a..13248d7 100644
@@ -21,6 +21,20 @@
 #include <plat/board.h>
 #include <plat/gpmc.h>
 
+static struct gpmc_cs_data gpmc_nand_cs_info = {
+	.have_config	= true,
+	.config		= GPMC_CONFIG1_DEVICETYPE_NAND,
+	.irq_config	= GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT,
+};
+
+static struct gpmc_device_pdata gpmc_nand_info = {
+	.name		= "omap2-nand",
+	.id		= 0,
+	.cs_data	= &gpmc_nand_cs_info,
+	.num_cs		= 1,
+	.is_nand	= true,
+};
+
 static struct resource gpmc_nand_resource[] = {
 	{
 		.flags		= IORESOURCE_MEM,
@@ -76,6 +90,13 @@ 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);
 
+	/* gpmc driver interface being used */
+	if (gpmc_nand_info.pdata != NULL) {
+		gpmc_nand_cs_info.time_ctrl.type = has_period;
+		gpmc_nand_cs_info.time_ctrl.timings = t;
+		return 0;
+	}
+
 	/* Configure GPMC */
 	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
 		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
@@ -139,3 +160,23 @@ out_free_cs:
 
 	return err;
 }
+
+struct gpmc_device_pdata *
+__init gpmc_nand_update(struct omap_nand_platform_data *gpmc_nand_data)
+{
+	gpmc_nand_info.pdata = gpmc_nand_data;
+	gpmc_nand_info.pdata_size = sizeof(*gpmc_nand_data);
+
+	gpmc_nand_cs_info.cs = gpmc_nand_data->cs;
+	gpmc_nand_cs_info.mem_size = NAND_IO_SIZE;
+
+	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+		gpmc_nand_cs_info.config |= GPMC_CONFIG1_DEVICESIZE_16;
+	if (gpmc_nand_data->dev_ready)
+		gpmc_nand_cs_info.config |= GPMC_CONFIG1_WAIT_READ_MON |
+						GPMC_CONFIG1_WAIT_WRITE_MON;
+
+	omap2_nand_gpmc_retime(gpmc_nand_data);
+
+	return &gpmc_nand_info;
+}
arch/arm/plat-omap/include/plat/nand.h +7 -0
index 290cef5..27700e1 100644
@@ -36,9 +36,16 @@ struct omap_nand_platform_data {
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
 extern int gpmc_nand_init(struct omap_nand_platform_data *d);
+struct gpmc_device_pdata *
+gpmc_nand_update(struct omap_nand_platform_data *gpmc_nand_data);
 #else
 static inline int gpmc_nand_init(struct omap_nand_platform_data *d)
 {
 	return 0;
 }
+static inline struct gpmc_device_pdata *
+gpmc_nand_update(struct omap_nand_platform_data *gpmc_nand_data)
+{
+	return NULL;
+};
 #endif
Signature · 1 line
1.7.10.2
#2 lore raw

PATCH 2/9 ARM: OMAP2+: gpmc-onenand: Adapt to use gpmc driver

In reply to Afzal Mohammed

Currently gpmc is configured in platform for onenand. As gpmc driver is now present, populate details needed for the driver to configure gpmc, gpmc driver would configure based on this information. Old interface has been left as is so that platforms can continue configuring gpmc using old interface too. This is done so that driver conversion can be done gradually without breaking any.

---
 arch/arm/mach-omap2/gpmc-onenand.c        |  117 +++++++++++++++++++++++++----
 arch/arm/plat-omap/include/plat/onenand.h |    8 +-
 2 files changed, 109 insertions(+), 16 deletions(-)
arch/arm/mach-omap2/gpmc-onenand.c +102 -15
index fd4c48d..0601284 100644
@@ -27,6 +27,20 @@
 
 static struct omap_onenand_platform_data *gpmc_onenand_data;
 
+static struct gpmc_cs_data gpmc_onenand_cs_info = {
+	.mem_size	= ONENAND_IO_SIZE,
+	.have_config	= true,
+	.config		= GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_MUXADDDATA |
+				GPMC_CONFIG1_DEVICETYPE_NOR,
+};
+
+static struct gpmc_device_pdata gpmc_onenand_info = {
+	.name		= "omap2-onenand",
+	.id		= -1,
+	.cs_data	= &gpmc_onenand_cs_info,
+	.num_cs		= 1,
+};
+
 static struct resource gpmc_onenand_resource = {
 	.flags		= IORESOURCE_MEM,
 };
@@ -80,15 +94,22 @@ static int omap2_onenand_set_async_mode(int cs)
 	t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
 	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)
-		return err;
-
+	/* gpmc driver interface being used */
+	if (gpmc_onenand_info.pdata != NULL) {
+		gpmc_onenand_cs_info.time_ctrl.type = has_period;
+		gpmc_onenand_cs_info.time_ctrl.timings = t;
+		return 0;
+	/* older interface */
+	} else {
+		/* 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)
+			return err;
+	}
 
 	return 0;
 }
@@ -180,6 +201,9 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	int cs = cfg->cs, freq = *freq_ptr;
 	u32 reg;
 	bool clk_dep = false;
+	struct gpmc_cs_data cs_info;
+
+	memset(&cs_info, 0, sizeof(cs_info));
 
 	/* Ensure sync read and sync write are disabled */
 	reg = readw(onenand_base + ONENAND_REG_SYS_CFG1);
@@ -275,7 +299,16 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 		set_onenand_cfg(onenand_base, latency,
 					sync_read, sync_write, hf, vhf);
 
-	if (div == 1) {
+	/* gpmc driver interface */
+	if (gpmc_onenand_info.pdata != NULL) {
+		if (div == 1) {
+			cs_info.time_ctrl.bool_timings.cs_extra_delay = true;
+			cs_info.time_ctrl.bool_timings.adv_extra_delay = true;
+			cs_info.time_ctrl.bool_timings.oe_extra_delay = true;
+			cs_info.time_ctrl.bool_timings.we_extra_delay = true;
+		}
+	/* old interface */
+	} else if (div == 1) {
 		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
 		reg |= (1 << 7);
 		gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
@@ -347,8 +380,39 @@ 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 driver interface */
+	if (gpmc_onenand_info.pdata != NULL) {
+		cs_info.have_config = true;
+		cs_info.config = GPMC_CONFIG1_DEVICESIZE_16 |
+					GPMC_CONFIG1_MUXADDDATA |
+					GPMC_CONFIG1_DEVICETYPE_NOR |
+					GPMC_CONFIG1_WRAPBURST_SUPP |
+					GPMC_CONFIG1_READMULTIPLE_SUPP |
+					GPMC_CONFIG1_PAGE_LEN_16;
+
+		if (!cpu_is_omap34xx())
+			cs_info.config |= GPMC_WAITPIN_0 |
+						GPMC_CONFIG1_WAIT_READ_MON;
+		if (sync_read)
+			cs_info.config |=
+						GPMC_CONFIG1_READTYPE_SYNC;
+		if (sync_write)
+			cs_info.config |=
+						GPMC_CONFIG1_WRITETYPE_SYNC |
+						GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+		t.clk_activation = fclk_offset_ns;
+		cs_info.time_ctrl.type = has_period;
+		cs_info.time_ctrl.timings = t;
+		err = gpmc_cs_reconfigure(gpmc_onenand_info.name,
+				gpmc_onenand_info.id, &cs_info);
+		if (err) {
+			pr_err("%s: gpmc_cs_reconfigure failed\n", __func__);
+			return err;
+		}
+	/* old interface */
+	} else {
+		/* 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) |
@@ -363,9 +427,10 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 			  GPMC_CONFIG1_DEVICETYPE_NOR |
 			  GPMC_CONFIG1_MUXADDDATA);
 
-	err = gpmc_cs_set_timings(cs, &t);
-	if (err)
-		return err;
+		err = gpmc_cs_set_timings(cs, &t);
+		if (err)
+			return err;
+	}
 
 	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
 
@@ -421,3 +486,25 @@ void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 		return;
 	}
 }
+
+struct gpmc_device_pdata *
+__init gpmc_onenand_update(struct omap_onenand_platform_data *_onenand_data)
+{
+	gpmc_onenand_data = _onenand_data;
+	gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
+
+	if (cpu_is_omap24xx() &&
+			(gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
+		pr_warn("error: onenand using only SYNC_READ on 24xx\n");
+		gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
+		gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
+	}
+
+	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;
+
+	omap2_onenand_set_async_mode(gpmc_onenand_data->cs);
+
+	return &gpmc_onenand_info;
+}
arch/arm/plat-omap/include/plat/onenand.h +7 -1
index 2858667..0e082d8 100644
@@ -41,7 +41,8 @@ struct omap_onenand_platform_data {
 	defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 
 extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
-
+extern struct gpmc_device_pdata *
+gpmc_onenand_update(struct omap_onenand_platform_data *_onenand_data);
 #else
 
 #define board_onenand_data	NULL
@@ -49,5 +50,10 @@ extern void gpmc_onenand_init(struct omap_onenand_platform_data *d);
 static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d)
 {
 }
+static inline struct gpmc_device_pdata *
+gpmc_onenand_update(struct omap_onenand_platform_data *_onenand_data)
+{
+	return NULL;
+}
 
 #endif
Signature · 1 line
1.7.10.2
#3 lore raw

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

In reply to Afzal Mohammed

Currently gpmc is configured in platform for various flash devices. As gpmc driver is now present, populate details needed for the driver to configure gpmc, gpmc driver would configure based on this information. Old interface has been left as is so that platforms can continue configuring gpmc using old interface too. This is done so that driver conversion can be done gradually without breaking any.

---
 arch/arm/mach-omap2/board-flash.c |  126 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/board-flash.h |   29 +++++++++
 2 files changed, 155 insertions(+)
arch/arm/mach-omap2/board-flash.c +126 -0
index 0ee820b..f3be964 100644
@@ -53,6 +53,15 @@ static struct platform_device board_nor_device = {
 	.resource	= &board_nor_resource,
 };
 
+static struct gpmc_cs_data gpmc_nor_cs_data;
+
+static struct gpmc_device_pdata gpmc_nor_data = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.cs_data	= &gpmc_nor_cs_data,
+	.num_cs		= 1,
+};
+
 static void
 __init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 {
@@ -81,6 +90,25 @@ __init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 		pr_err("Unable to register NOR device\n");
 }
 
+static __init struct gpmc_device_pdata *
+gpmc_nor_update(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
+{
+	board_nor_data.parts	= nor_parts;
+	board_nor_data.nr_parts	= nr_parts;
+
+	gpmc_nor_cs_data.cs	= cs;
+
+	if (omap_rev() >= OMAP3430_REV_ES1_0)
+		gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV2;
+	else
+		gpmc_nor_cs_data.mem_size = FLASH_SIZE_SDPV1;
+
+	gpmc_nor_data.pdata = &board_nor_data;
+	gpmc_nor_data.pdata_size = sizeof(board_nor_data);
+
+	return &gpmc_nor_data;
+}
+
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
 		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 static struct omap_onenand_platform_data board_onenand_data = {
@@ -97,6 +125,16 @@ __init board_onenand_init(struct mtd_partition *onenand_parts,
 
 	gpmc_onenand_init(&board_onenand_data);
 }
+
+struct omap_onenand_platform_data * __init
+board_onenand_update(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;
+
+	return &board_onenand_data;
+}
 #else
 void
 __init board_onenand_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
@@ -148,6 +186,19 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
 	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
 	gpmc_nand_init(&board_nand_data);
 }
+
+struct omap_nand_platform_data *
+__init board_nand_update(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t)
+{
+	board_nand_data.cs		= cs;
+	board_nand_data.parts		= nand_parts;
+	board_nand_data.nr_parts	= nr_parts;
+	board_nand_data.devsize		= nand_type;
+	board_nand_data.gpmc_t		= gpmc_t;
+
+	return &board_nand_data;
+}
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
 
 /**
@@ -246,3 +297,78 @@ void __init board_flash_init(struct flash_partitions partition_info[],
 			partition_info[2].nr_parts, nandcs,
 			nand_type, nand_default_timings);
 }
+
+struct gpmc_device_pdata __init **board_flash_update(
+				struct flash_partitions partition_info[],
+				char chip_sel_board[][GPMC_CS_NUM],
+				int nand_type,
+				struct gpmc_device_pdata **gpmc_data)
+{
+	u8		cs = 0;
+	u8		norcs = GPMC_CS_NUM + 1;
+	u8		nandcs = GPMC_CS_NUM + 1;
+	u8		onenandcs = GPMC_CS_NUM + 1;
+	u8		idx;
+	unsigned char	*config_sel = NULL;
+
+	if (gpmc_data == NULL) {
+		pr_err("%s: NULL arguement passed\n", __func__);
+		return NULL;
+	}
+
+	idx = get_gpmc0_type();
+	if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
+		pr_err("%s: Invalid chip select: %d\n", __func__, cs);
+		return gpmc_data;
+	}
+	config_sel = (unsigned char *)(chip_sel_board[idx]);
+
+	while (cs < GPMC_CS_NUM) {
+		switch (config_sel[cs]) {
+		case PDC_NOR:
+			if (norcs > GPMC_CS_NUM)
+				norcs = cs;
+			break;
+		case PDC_NAND:
+			if (nandcs > GPMC_CS_NUM)
+				nandcs = cs;
+			break;
+		case PDC_ONENAND:
+			if (onenandcs > GPMC_CS_NUM)
+				onenandcs = cs;
+			break;
+		};
+		cs++;
+	}
+
+	if (norcs > GPMC_CS_NUM)
+		pr_err("NOR: Unable to find configuration in GPMC\n");
+	else
+		*gpmc_data++ = gpmc_nor_update(partition_info[0].parts,
+				partition_info[0].nr_parts, norcs);
+
+	if (onenandcs > GPMC_CS_NUM)
+		pr_err("OneNAND: Unable to find configuration in GPMC\n");
+	else {
+		struct omap_onenand_platform_data *onenand_data;
+
+		onenand_data = board_onenand_update(partition_info[1].parts,
+				partition_info[1].nr_parts, onenandcs);
+		if (onenand_data != NULL)
+			*gpmc_data++ = gpmc_onenand_update(onenand_data);
+	}
+
+	if (nandcs > GPMC_CS_NUM)
+		pr_err("NAND: Unable to find configuration in GPMC\n");
+	else {
+		struct omap_nand_platform_data *nand_data;
+
+		nand_data = board_nand_update(partition_info[2].parts,
+				partition_info[2].nr_parts, nandcs,
+				nand_type, nand_default_timings);
+		if (nand_data != NULL)
+			*gpmc_data++ = gpmc_nand_update(nand_data);
+	}
+
+	return gpmc_data;
+}
arch/arm/mach-omap2/board-flash.h +29 -0
index a3aa5fc..534afe2 100644
@@ -30,11 +30,24 @@ struct flash_partitions {
 		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_update(
+				struct flash_partitions partition_info[],
+				char chip_sel_board[][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_update(
+				struct flash_partitions partition_info[],
+				char chip_sel_board[][GPMC_CS_NUM],
+				int nand_type,
+				struct gpmc_device_pdata **gpmc_data)
+{
+	return NULL;
+}
 #endif
 
 #if defined(CONFIG_MTD_NAND_OMAP2) || \
@@ -42,11 +55,20 @@ static inline void board_flash_init(struct flash_partitions part[],
 extern void board_nand_init(struct mtd_partition *nand_parts,
 		u8 nr_parts, u8 cs, int nand_type, struct gpmc_timings *gpmc_t);
 extern struct gpmc_timings nand_default_timings[];
+extern struct omap_nand_platform_data *
+board_nand_update(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, struct gpmc_timings *gpmc_t)
 {
 }
+static inline struct omap_nand_platform_data *
+board_nand_update(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
+				int nand_type, struct gpmc_timings *gpmc_t)
+{
+	return NULL;
+}
 #define	nand_default_timings	NULL
 #endif
 
@@ -54,9 +76,16 @@ static inline void board_nand_init(struct mtd_partition *nand_parts,
 		defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
 extern void board_onenand_init(struct mtd_partition *nand_parts,
 					u8 nr_parts, u8 cs);
+extern struct omap_onenand_platform_data *
+board_onenand_update(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs);
 #else
 static inline void board_onenand_init(struct mtd_partition *nand_parts,
 					u8 nr_parts, u8 cs)
 {
 }
+static inline struct omap_onenand_platform_data *
+board_onenand_update(struct mtd_partition *onenand_parts, u8 nr_parts, u8 cs)
+{
+	return NULL;
+}
 #endif
Signature · 1 line
1.7.10.2
#4 lore raw

PATCH 4/9 ARM: OMAP2+: gpmc-tusb6010: Adapt to use gpmc driver

In reply to Afzal Mohammed

Currently gpmc is configured in platform for tusb6010. As gpmc driver is now present, populate details needed for the driver to configure gpmc, gpmc driver would configure based on this information. Old interface has been left as is so that platforms can continue configuring gpmc using old interface too. This is done so that driver conversion can be done gradually without breaking any.

---
 arch/arm/mach-omap2/usb-tusb6010.c     |  113 +++++++++++++++++++++++++++++++-
 arch/arm/plat-omap/include/plat/gpmc.h |    8 +++
 2 files changed, 119 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/usb-tusb6010.c +111 -2
index db84a46..0e17337 100644
@@ -22,9 +22,26 @@
 
 #include "mux.h"
 
+#define	CS_ASYNC_IDX	0
+#define	CS_SYNC_IDX	1
+#define	CS_NUM		2
+
 static u8		async_cs, sync_cs;
 static unsigned		refclk_psec;
 
+static struct resource tusb_resource = {
+	.name	= "mc",
+	.flags	= IORESOURCE_IRQ,
+};
+
+static struct gpmc_cs_data gpmc_tusb_cs_data[CS_NUM];
+
+static struct gpmc_device_pdata gpmc_tusb_data = {
+	.name		= "musb-tusb",
+	.id		= -1,
+	.per_res	= &tusb_resource,
+	.per_res_cnt	= 1,
+};
 
 /* t2_ps, when quantized to fclk units, must happen no earlier than
  * the clock after after t1_NS.
@@ -106,7 +123,14 @@ 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 driver interface */
+	if (gpmc_tusb_data.pdata != NULL) {
+		gpmc_tusb_cs_data[CS_ASYNC_IDX].time_ctrl.type = has_period;
+		gpmc_tusb_cs_data[CS_ASYNC_IDX].time_ctrl.timings = t;
+		return 0;
+	/* old interface */
+	} else
+		return gpmc_cs_set_timings(async_cs, &t);
 }
 
 static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
@@ -174,7 +198,16 @@ 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);
+	t.clk_activation = gpmc_ticks_to_ns(1);
+
+	/* gpmc driver interface */
+	if (gpmc_tusb_data.pdata != NULL) {
+		gpmc_tusb_cs_data[CS_SYNC_IDX].time_ctrl.type = has_period;
+		gpmc_tusb_cs_data[CS_SYNC_IDX].time_ctrl.timings = t;
+		return 0;
+	/* old interface */
+	} else
+		return gpmc_cs_set_timings(sync_cs, &t);
 }
 
 extern unsigned long gpmc_get_fclk_period(void);
@@ -348,3 +381,79 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
 	}
 	return 0;
 }
+
+struct gpmc_device_pdata *
+__init gpmc_tusb6010_update(struct musb_hdrc_platform_data *data,
+		unsigned ps_refclk, unsigned waitpin,
+		unsigned async, unsigned sync,
+		unsigned irq, unsigned dmachan)
+{
+	int ret;
+
+	if (!data) {
+		pr_err("error: %s: data: NULL\n", __func__);
+		return NULL;
+	}
+
+	gpmc_tusb_data.pdata = data;
+	gpmc_tusb_data.pdata_size = sizeof(*data);
+
+	/* ASYNC region, primarily for PIO */
+	gpmc_tusb_cs_data[CS_ASYNC_IDX].cs = async;
+	gpmc_tusb_cs_data[CS_ASYNC_IDX].mem_size = 0x1000;
+
+	async_cs = async;
+
+	gpmc_tusb_cs_data[CS_ASYNC_IDX].have_config = true;
+	gpmc_tusb_cs_data[CS_ASYNC_IDX].config = waitpin |
+		GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_WAIT_READ_MON |
+		GPMC_CONFIG1_WAIT_WRITE_MON | GPMC_CONFIG1_READTYPE_ASYNC |
+		GPMC_CONFIG1_WRITETYPE_ASYNC | GPMC_CONFIG1_DEVICETYPE_NOR |
+		GPMC_CONFIG1_MUXADDDATA | GPMC_CONFIG1_PAGE_LEN_16;
+
+	/* SYNC region, primarily for DMA */
+	gpmc_tusb_cs_data[CS_SYNC_IDX].cs = sync;
+	gpmc_tusb_cs_data[CS_SYNC_IDX].mem_size	= 0x1000;
+
+	sync_cs = sync;
+
+	gpmc_tusb_cs_data[CS_SYNC_IDX].have_config = true;
+	gpmc_tusb_cs_data[CS_SYNC_IDX].config = waitpin |
+		GPMC_CONFIG1_DEVICESIZE_16 | GPMC_CONFIG1_WAIT_READ_MON |
+		GPMC_CONFIG1_WAIT_WRITE_MON | GPMC_CONFIG1_READTYPE_SYNC |
+		GPMC_CONFIG1_WRITETYPE_SYNC | GPMC_CONFIG1_DEVICETYPE_NOR |
+		GPMC_CONFIG1_MUXADDDATA | GPMC_CONFIG1_READMULTIPLE_SUPP |
+		GPMC_CONFIG1_WRITEMULTIPLE_SUPP | GPMC_CONFIG1_PAGE_LEN_16;
+
+	/* IRQ */
+	ret = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
+	if (ret < 0) {
+		pr_err("error: %s: gpio_request_one: %d\n", __func__, ret);
+		return NULL;
+	}
+	tusb_resource.start = irq + IH_GPIO_BASE;
+
+	if (!ps_refclk) {
+		pr_err("error: %s: ps_refclk: 0\n", __func__);
+		return NULL;
+	}
+	refclk_psec = ps_refclk;
+	tusb6010_platform_retime(1);
+
+	if (dmachan) {
+		if (dmachan & (1 << 0))
+			omap_mux_init_signal("sys_ndmareq0", 0);
+		if (dmachan & (1 << 1))
+			omap_mux_init_signal("sys_ndmareq1", 0);
+		if (dmachan & (1 << 2))
+			omap_mux_init_signal("sys_ndmareq2", 0);
+		if (dmachan & (1 << 3))
+			omap_mux_init_signal("sys_ndmareq3", 0);
+		if (dmachan & (1 << 4))
+			omap_mux_init_signal("sys_ndmareq4", 0);
+		if (dmachan & (1 << 5))
+			omap_mux_init_signal("sys_ndmareq5", 0);
+	}
+
+	return &gpmc_tusb_data;
+}
arch/arm/plat-omap/include/plat/gpmc.h +8 -0
index 32d7f3d..25fb27d 100644
@@ -11,6 +11,8 @@
 #ifndef __OMAP2_GPMC_H
 #define __OMAP2_GPMC_H
 
+#include <linux/usb/musb.h>
+
 /* Maximum Number of Chip Selects */
 #define GPMC_CS_NUM		8
 
@@ -250,6 +252,12 @@ extern int gpmc_nand_write(int cs, int cmd, int wval);
 
 extern int gpmc_cs_reconfigure(char *name, int id, struct gpmc_cs_data *c);
 
+/* A better place would have been musb.h, but as it is now in include/linux/
+ */
+extern struct gpmc_device_pdata *
+gpmc_tusb6010_update(struct musb_hdrc_platform_data *data, unsigned ps_refclk,
+				unsigned waitpin, unsigned async, unsigned sync,
+				unsigned irq, unsigned dmachan);
 int gpmc_enable_hwecc(int cs, int mode, int dev_width, int ecc_size);
 int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code);
 
Signature · 1 line
1.7.10.2
maintainer
#5 lore raw

PATCH 4/9 ARM: OMAP2+: gpmc-tusb6010: Adapt to use gpmc driver

Quoted 22 lines · Afzal Mohammed
arch/arm/mach-omap2/usb-tusb6010.c +9 -2
@@ -106,7 +123,14 @@ 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 driver interface */
+	if (gpmc_tusb_data.pdata != NULL) {
+		gpmc_tusb_cs_data[CS_ASYNC_IDX].time_ctrl.type = has_period;
+		gpmc_tusb_cs_data[CS_ASYNC_IDX].time_ctrl.timings = t;
+		return 0;
+	/* old interface */
+	} else
+		return gpmc_cs_set_timings(async_cs, &t);
 }
 
 static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
@@ -174,7 +198,16 @@ 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);
+	t.clk_activation = gpmc_ticks_to_ns(1);

arch/arm/mach-omap2/usb-tusb6010.c static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps) · line 211

Quoted 10 lines
arch/arm/mach-omap2/usb-tusb6010.c +9 -0
+
+	/* gpmc driver interface */
+	if (gpmc_tusb_data.pdata != NULL) {
+		gpmc_tusb_cs_data[CS_SYNC_IDX].time_ctrl.type = has_period;
+		gpmc_tusb_cs_data[CS_SYNC_IDX].time_ctrl.timings = t;
+		return 0;
+	/* old interface */
+	} else
+		return gpmc_cs_set_timings(sync_cs, &t);
 }

We can drop the old interface for non-mainline cases. In this case tusb6010 is only used by board-n8x0.c, so it's best to just convert it all to use the new interface.

Regards,

Tony

#6 lore raw

PATCH 4/9 ARM: OMAP2+: gpmc-tusb6010: Adapt to use gpmc driver

Hi Tony,

Quoted 3 lines · Tony Lindgren

We can drop the old interface for non-mainline cases. In this case tusb6010 is only used by board-n8x0.c, so it's best to just convert it all to use the new interface.

Right, I will do accordingly

Regards
Afzal

#7 lore raw

PATCH 5/9 ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver

In reply to Afzal Mohammed

Currently gpmc is configured in platform for smc91x. As now gpmc driver is present, populate details needed for the driver to configure gpmc, gpmc driver would configure based on this information. Old interface has been left as is so that platforms can continue configuring gpmc using old interface too. This is done so that driver conversion can be done gradually without breaking any.

---
 arch/arm/mach-omap2/gpmc-smc91x.c             |   69 +++++++++++++++++++++----
 arch/arm/plat-omap/include/plat/gpmc-smc91x.h |   12 +++--
 2 files changed, 66 insertions(+), 15 deletions(-)
arch/arm/mach-omap2/gpmc-smc91x.c +59 -10
index ba10c24..06f7e73 100644
@@ -48,6 +48,19 @@ static struct platform_device gpmc_smc91x_device = {
 	.resource	= gpmc_smc91x_resources,
 };
 
+static struct gpmc_cs_data gpmc_smc91x_cs_data;
+
+static struct gpmc_device_pdata gpmc_smc91x_data = {
+	.name		= "smc91x",
+	.id		= -1,
+	.pdata		= &gpmc_smc91x_info,
+	.pdata_size	= sizeof(gpmc_smc91x_info),
+	.per_res	= gpmc_smc91x_resources + 1,
+	.per_res_cnt	= 1,
+	.cs_data	= &gpmc_smc91x_cs_data,
+	.num_cs		= 1,
+};
+
 /*
  * Set the gpmc timings for smc91c96. The timings are taken
  * from the data sheet available at:
@@ -100,9 +113,18 @@ static int smc91c96_gpmc_retime(void)
 		l |= GPMC_CONFIG1_WAIT_READ_MON;
 	if (gpmc_cfg->flags & GPMC_WRITE_MON)
 		l |= GPMC_CONFIG1_WAIT_WRITE_MON;
-	if (gpmc_cfg->wait_pin)
-		l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
-	gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
+
+	/* gpmc driver interface */
+	if (gpmc_smc91x_cs_data.mem_size == 0x10) {
+		gpmc_smc91x_cs_data.have_config = true;
+		/* waitpin macro, not waitpin number */
+		gpmc_smc91x_cs_data.config |= l |
+				(gpmc_cfg->wait_pin & GPMC_WAITPIN_MASK);
+	} else {
+		if (gpmc_cfg->wait_pin)
+			l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
+		gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
+	}
 
 	/*
 	 * FIXME: Calculate the address and data bus muxed timings.
@@ -114,7 +136,13 @@ static int smc91c96_gpmc_retime(void)
 	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
 		return 0;
 
-	return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
+	/* gpmc driver interface */
+	if (gpmc_smc91x_cs_data.mem_size == 0x10) {
+		gpmc_smc91x_cs_data.time_ctrl.type = has_period;
+		gpmc_smc91x_cs_data.time_ctrl.timings = t;
+		return 0;
+	} else
+		return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
 }
 
 /*
@@ -132,13 +160,17 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 	if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96)
 		gpmc_cfg->retime = smc91c96_gpmc_retime;
 
-	if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
-		printk(KERN_ERR "Failed to request GPMC mem for smc91x\n");
-		return;
+	/* old interface */
+	if (gpmc_smc91x_cs_data.mem_size != 0x10) {
+		if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
+			pr_err("error: gpmc_cs_request on smc91x\n");
+			return;
+		}
+
+		gpmc_smc91x_resources[0].start = cs_mem_base + 0x300;
+		gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
 	}
 
-	gpmc_smc91x_resources[0].start = cs_mem_base + 0x300;
-	gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
 	gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
 
 	if (gpmc_cfg->retime) {
@@ -170,6 +202,10 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
 		gpio_set_value(gpmc_cfg->gpio_reset, 0);
 	}
 
+	/* gpmc driver interface */
+	if (gpmc_smc91x_cs_data.mem_size == 0x10)
+		return;
+
 	if (platform_device_register(&gpmc_smc91x_device) < 0) {
 		printk(KERN_ERR "Unable to register smc91x device\n");
 		gpio_free(gpmc_cfg->gpio_reset);
@@ -184,7 +220,20 @@ free3:
 free2:
 	gpio_free(gpmc_cfg->gpio_irq);
 free1:
-	gpmc_cs_free(gpmc_cfg->cs);
+	if (gpmc_smc91x_cs_data.mem_size != 0x10)
+		gpmc_cs_free(gpmc_cfg->cs);
 
 	printk(KERN_ERR "Could not initialize smc91x\n");
 }
+
+struct gpmc_device_pdata *
+__init gpmc_smc91x_update(struct omap_smc91x_platform_data *board_data)
+{
+	gpmc_smc91x_cs_data.cs		= gpmc_cfg->cs;
+	gpmc_smc91x_cs_data.mem_offset	= 0x300;
+	gpmc_smc91x_cs_data.mem_size	= 0x10;
+
+	gpmc_smc91x_init(board_data);
+
+	return &gpmc_smc91x_data;
+}
arch/arm/plat-omap/include/plat/gpmc-smc91x.h +7 -5
index b64fbee..91cc7ef 100644
@@ -27,16 +27,18 @@ struct omap_smc91x_platform_data {
 
 #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_update(struct omap_smc91x_platform_data *board_data);
 #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_update(struct omap_smc91x_platform_data *board_data)
+{
+	return NULL;
+}
 #endif
 #endif
Signature · 1 line
1.7.10.2
maintainer
#8 lore raw

PATCH 5/9 ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver

Quoted 7 lines · Afzal Mohammed
arch/arm/mach-omap2/gpmc-smc91x.c +0 -1
@@ -114,7 +136,13 @@ static int smc91c96_gpmc_retime(void)
 	if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
 		return 0;
 
-	return gpmc_cs_set_timings(gpmc_cfg->cs, &t);

arch/arm/mach-omap2/gpmc-smc91x.c static int smc91c96_gpmc_retime(void) · line 148

Quoted 10 lines
arch/arm/mach-omap2/gpmc-smc91x.c +7 -0
+	/* gpmc driver interface */
+	if (gpmc_smc91x_cs_data.mem_size == 0x10) {
+		gpmc_smc91x_cs_data.time_ctrl.type = has_period;
+		gpmc_smc91x_cs_data.time_ctrl.timings = t;
+		return 0;
+	} else
+		return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
 }
 
 /*

Here too we just need to care about the mainline kernel users and convert them to use the new interface. No need to keep gpmc_cs_set_timings around. The same applies for other similar patches.

Regards,

Tony

#9 lore raw

PATCH 5/9 ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver

Hi Tony,

Quoted 4 lines · Tony Lindgren

Here too we just need to care about the mainline kernel users and convert them to use the new interface. No need to keep gpmc_cs_set_timings around. The same applies for other similar patches.

Not sure whether I follow you here.

Do you mean for all the gpmc-* helpers existing initialization needs to be modified to use the new interface, the previous version was doing so. But then that will cause all boards using the same gpmc-* helper to be converted at once (tusb6010 is not an issue as only one board uses it), then the problem will be that there would be a few commits where gpmc may not work properly.

And for a particular board, either it has to use old interface or either the new interface, it cannot use both.

Consider the case of this one, smc91x, all sdp boards use it, that requires nand, onenand, nor gpmc-* helpers to be converted before board migration for say 3430sdp board, that would mean that 2430sdp board would be broken w.r.t gpmc at that commit as board modifications are not yet done for 2430. That in turn means all the boards using nand, onenand would be broken at that point.

Regards
Afzal

maintainer
#10 lore raw

PATCH 5/9 ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver

Quoted 21 lines · Mohammed, Afzal

Hi Tony,

Quoted 4 lines · Tony Lindgren

Here too we just need to care about the mainline kernel users and convert them to use the new interface. No need to keep gpmc_cs_set_timings around. The same applies for other similar patches.

Not sure whether I follow you here.

Do you mean for all the gpmc-* helpers existing initialization needs to be modified to use the new interface, the previous version was doing so. But then that will cause all boards using the same gpmc-* helper to be converted at once (tusb6010 is not an issue as only one board uses it), then the problem will be that there would be a few commits where gpmc may not work properly.

And for a particular board, either it has to use old interface or either the new interface, it cannot use both.

Quoted 6 lines

Consider the case of this one, smc91x, all sdp boards use it, that requires nand, onenand, nor gpmc-* helpers to be converted before board migration for say 3430sdp board, that would mean that 2430sdp board would be broken w.r.t gpmc at that commit as board modifications are not yet done for 2430. That in turn means all the boards using nand, onenand would be broken at that point.

What I mean is keep the old interface in gpmc.c, then convert users one at a time to the new interface, and remove the old interface code from the users. But yeah you're right, it may not be immediately doable for the smc91x case before we dump out the register values. But at least tusb6010 should be able to just convert to use the new interface and drop the old code.

Tony

#11 lore raw

PATCH 5/9 ARM: OMAP2+: gpmc-smc91x: Adapt to use gpmc driver

Hi Tony,

Quoted 19 lines · Tony Lindgren
Quoted 10 lines · Mohammed, Afzal

Do you mean for all the gpmc-* helpers existing initialization needs to be modified to use the new interface, the previous version was doing so. But then that will cause all boards using the same gpmc-* helper to be converted at once (tusb6010 is not an issue as only one board uses it), then the problem will be that there would be a few commits where gpmc may not work properly.

And for a particular board, either it has to use old interface or either the new interface, it cannot use both.

Quoted 6 lines

Consider the case of this one, smc91x, all sdp boards use it, that requires nand, onenand, nor gpmc-* helpers to be converted before board migration for say 3430sdp board, that would mean that 2430sdp board would be broken w.r.t gpmc at that commit as board modifications are not yet done for 2430. That in turn means all the boards using nand, onenand would be broken at that point.

Quoted 6 lines

What I mean is keep the old interface in gpmc.c, then convert users one at a time to the new interface, and remove the old interface code from the users. But yeah you're right, it may not be immediately doable for the smc91x case before we dump out the register values. But at least tusb6010 should be able to just convert to use the new interface and drop the old code.

Yesterday, I overlooked the fact that n8x0 have onenand in addition to tusb6010. As that is the case, to have boards work properly, we may need to keep old interface along with new interface for at least a few commits even for tusb6010.

Straightaway if existing tusb6010 interface is modified (without having new interface alongside), it will create problem for n8x0 as it has onenand still using old interface. And a board at a time cannot use both.

And if we proceed in the reverse, i.e. convert onenand to use new interface first (w/o having new interface alongside), still n8x0 would have problems as tusb6010 would be using the old interface then

So it seems, both interface has to live side-by-side till all boards are converted (or at least till all boards using the peripheral in question has to get converted to use new interface)

Regards
Afzal

#12 lore raw

PATCH 6/9 ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver

In reply to Afzal Mohammed

Currently gpmc is configured in platform for smsc911x. As gpmc driver is now present, populate details needed for the driver to configure gpmc, gpmc driver would configure based on this information. Old interface has been left as is so that platforms can continue configuring gpmc using old interface too. This is done so that driver conversion can be done gradually without breaking any.

---
 arch/arm/mach-omap2/gpmc-smsc911x.c             |   66 +++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |   11 ++--
 2 files changed, 73 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/gpmc-smsc911x.c +66 -0
index b6c77be..93a534e 100644
@@ -99,3 +99,69 @@ free1:
 
 	pr_err("Could not initialize smsc911x device\n");
 }
+
+struct gpmc_device_pdata *
+__init gpmc_smsc911x_update(struct omap_smsc911x_platform_data *gpmc_cfg)
+{
+	int ret;
+	struct gpmc_device_pdata *gpmc_pdev;
+	struct gpmc_cs_data *gpmc_cs;
+
+	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_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 + 1;
+	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);
+
+	if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
+		ret = gpio_request_one(gpmc_cfg->gpio_reset,
+				       GPIOF_OUT_INIT_HIGH, "smsc911x reset");
+		if (ret) {
+			pr_err("Failed to request reset GPIO%d\n",
+			       gpmc_cfg->gpio_reset);
+			goto free2;
+		}
+
+		gpio_set_value(gpmc_cfg->gpio_reset, 0);
+		msleep(100);
+		gpio_set_value(gpmc_cfg->gpio_reset, 1);
+	}
+
+	gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT;
+
+	return gpmc_pdev;
+
+free2:
+	gpio_free(gpmc_cfg->gpio_irq);
+free1:
+	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 -4
index ea6c9c8..50af49e 100644
@@ -22,14 +22,17 @@ 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_update(struct omap_smsc911x_platform_data *gpmc_cfg);
 #else
-
 static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
 {
 }
-
+static inline struct gpmc_device_pdata *
+gpmc_smsc911x_update(struct omap_smsc911x_platform_data *gpmc_cfg)
+{
+	return NULL;
+}
 #endif
 #endif
Signature · 1 line
1.7.10.2
maintainer
#13 lore raw

PATCH 6/9 ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver

Quoted 5 lines · Afzal Mohammed
arch/arm/mach-omap2/gpmc-smsc911x.c +5 -0
+__init gpmc_smsc911x_update(struct omap_smsc911x_platform_data *gpmc_cfg)
+{
+	int ret;
+	struct gpmc_device_pdata *gpmc_pdev;
+	struct gpmc_cs_data *gpmc_cs;

arch/arm/mach-omap2/gpmc-smsc911x.c free1: · line 118

Quoted 10 lines
arch/arm/mach-omap2/gpmc-smsc911x.c +10 -0
+
+	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;
+	}

Here your should check for if (!gpmc_cs), not gpmc_cs. Might be worth checking all your patches for similar copy and paste typos.

Where do gpmc_pdev and gpmc_cs get used? Where are they stored to the pdata?

Tony

#14 lore raw

PATCH 6/9 ARM: OMAP2+: gpmc-smsc911x: Adapt to use gpmc driver

Hi Tony,

Quoted 10 lines · Tony Lindgren
Quoted 9 lines · Afzal Mohammed
(quoted diff) +9 -0
+__init gpmc_smsc911x_update(struct omap_smsc911x_platform_data *gpmc_cfg)
+{
+	int ret;
+	struct gpmc_device_pdata *gpmc_pdev;
+	struct gpmc_cs_data *gpmc_cs;
+
+	gpmc_pdev = kzalloc(sizeof(*gpmc_pdev), GFP_KERNEL);
+	if (gpmc_pdev == NULL)
+		return gpmc_pdev;
Quoted 8 lines

Review

Quoted 6 lines
(quoted diff) +6 -0
+
+	gpmc_cs = kzalloc(sizeof(*gpmc_cs), GFP_KERNEL);
+	if (gpmc_pdev == NULL) {
+		kfree(gpmc_pdev);
+		return NULL;
+	}

Here your should check for if (!gpmc_cs), not gpmc_cs. Might

My mistake, I will correct it

Quoted 2 lines

Where do gpmc_pdev and gpmc_cs get used? Where are they stored to the pdata?

It is done in board file, as in [1]

Regards
Afzal

[1]

ARM: OMAP2+: board omap3evm: use gpmc driver

arch/arm/mach-omap2/board-omap3evm.c +11 -1
index 639bd07..aa9429d 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[2];
+
+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,9 @@ 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_update(&smsc911x_cfg);
+       if (!*gpmc_device_data)
+               pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -658,6 +667,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_gpmc_init(&gpmc_data);
        omap3_evm_display_init();
        omap3_evm_wl12xx_init();
 }
#15 lore raw

PATCH 7/9 ARM: OMAP2+: gpmc-smsc911x: runtime time calculation

In reply to Afzal Mohammed

OMAP Peripherals using SMSC911X driver were not configured in Kernel. Here timing has been calculated so that it is runtime configurable. As different SMSC devices like 9115, 9220, 9221 can be used with smsc911x driver, option has been given for the boards to provide timing as per the part used, if it is not provided, default one used is that of 9220.

---
 arch/arm/mach-omap2/gpmc-smsc911x.c             |   53 +++++++++++++++++++++++
 arch/arm/plat-omap/include/plat/gpmc-smsc911x.h |   14 ++++++
 2 files changed, 67 insertions(+)
arch/arm/mach-omap2/gpmc-smsc911x.c +53 -0
index 93a534e..4bfe721 100644
@@ -100,6 +100,53 @@ free1:
 	pr_err("Could not initialize smsc911x device\n");
 }
 
+static void gpmc_smsc911x_timing(struct gpmc_time_ctrl *time_ctrl,
+					struct smsc911x_timing *timing)
+{
+	struct gpmc_timings t;
+	/* SMSC 9220 timings */
+	unsigned tcycle_r = 165;
+	unsigned tcsl_r = 32;
+	unsigned tcsh_r = 133;
+	unsigned tcsdv_r = 30;
+	unsigned tdoff_r = 9;
+	unsigned tcycle_w = 165;
+	unsigned tcsl_w = 32;
+	unsigned tcsh_w = 133;
+	unsigned tdsu_w = 7;
+
+	/* take timings from board, else use default */
+	if (timing) {
+		tcycle_r = timing->tcycle_r;
+		tcsl_r = timing->tcsl_r;
+		tcsh_r = timing->tcsh_r;
+		tcsdv_r = timing->tcsdv_r;
+		tdoff_r = tdoff_r;
+		tcycle_w = timing->tcycle_r;
+		tcsl_w = timing->tcsl_w;
+		tcsh_w = timing->tcsh_w;
+		tdsu_w = timing->tdsu_w;
+	}
+
+	memset(&t, sizeof(t), 0);
+
+	t.cs_on = 0;
+	t.oe_on = 0;
+	t.access = tcsdv_r;
+	t.oe_off = max_t(unsigned, t.access + gpmc_ticks_to_ns(1), tcsl_r);
+	t.cs_rd_off = t.oe_off;
+	t.rd_cycle = tcsl_r + max(tcsh_r, tdoff_r);
+	t.rd_cycle = max_t(unsigned, tcycle_r, t.rd_cycle);
+
+	t.we_on = 0;
+	t.we_off = max(tcsl_w, tdsu_w);
+	t.cs_wr_off = t.we_off;
+	t.wr_cycle = max_t(unsigned, t.we_off + gpmc_ticks_to_ns(1), tcycle_w);
+
+	time_ctrl->type = has_period;
+	time_ctrl->timings = t;
+}
+
 struct gpmc_device_pdata *
 __init gpmc_smsc911x_update(struct omap_smsc911x_platform_data *gpmc_cfg)
 {
@@ -127,6 +174,12 @@ __init gpmc_smsc911x_update(struct omap_smsc911x_platform_data *gpmc_cfg)
 	gpmc_cs->cs = gpmc_cfg->cs;
 	gpmc_cs->mem_size = 0x100;
 
+	gpmc_cs->have_config = true;
+	gpmc_cs->config = GPMC_CONFIG1_DEVICESIZE_16 |
+		GPMC_CONFIG1_DEVICETYPE_NOR;
+
+	gpmc_smsc911x_timing(&gpmc_cs->time_ctrl, gpmc_cfg->timing);
+
 	gpmc_pdev->per_res = gpmc_smsc911x_resources + 1;
 	gpmc_pdev->per_res_cnt = 1;
 
arch/arm/plat-omap/include/plat/gpmc-smsc911x.h +14 -0
index 50af49e..8be3343 100644
@@ -13,12 +13,26 @@
 
 #ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
 
+/* timing in ns */
+struct smsc911x_timing {
+	unsigned tcycle_r;
+	unsigned tcsl_r;
+	unsigned tcsh_r;
+	unsigned tcsdv_r;
+	unsigned tdoff_r;
+	unsigned tcycle_w;
+	unsigned tcsl_w;
+	unsigned tcsh_w;
+	unsigned tdsu_w;
+};
+
 struct omap_smsc911x_platform_data {
 	int	id;
 	int	cs;
 	int	gpio_irq;
 	int	gpio_reset;
 	u32	flags;
+	struct smsc911x_timing *timing;
 };
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
Signature · 1 line
1.7.10.2
#16 lore raw

PATCH 8/9 ARM: OMAP2+: board omap3evm: use gpmc driver

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 |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
arch/arm/mach-omap2/board-omap3evm.c +11 -1
index 639bd07..aa9429d 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[2];
+
+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,9 @@ 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_update(&smsc911x_cfg);
+	if (!*gpmc_device_data)
+		pr_err("error: unable to initilaize gpmc smsc911x\n");
 }
 
 #else
@@ -658,6 +667,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_gpmc_init(&gpmc_data);
 	omap3_evm_display_init();
 	omap3_evm_wl12xx_init();
 }
Signature · 1 line
1.7.10.2
#17 lore raw

PATCH 9/9 ARM: OMAP2+: board omap3beagle: use gpmc driver

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 |   16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
arch/arm/mach-omap2/board-omap3beagle.c +14 -2
index 5aa8f28..0fe70ed 100644
@@ -77,6 +77,12 @@ enum {
 
 static u8 omap3_beagle_version;
 
+static struct gpmc_device_pdata *gpmc_device_data[2];
+
+static struct gpmc_pdata gpmc_data = {
+	.device_pdata = gpmc_device_data,
+};
+
 /*
  * Board-specific configuration
  * Defaults to BeagleBoard-xMC
@@ -499,6 +505,8 @@ static void __init beagle_opp_init(void)
 
 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();
 
@@ -524,9 +532,13 @@ 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_update(omap3beagle_nand_partitions,
 		ARRAY_SIZE(omap3beagle_nand_partitions), NAND_CS,
-		NAND_BUSWIDTH_16, NULL);
+		NAND_BUSWIDTH_16, nand_default_timings);
+	*gpmc_device_data = gpmc_nand_update(nand_data);
+	if (!*gpmc_device_data)
+		pr_err("error: unable to initilaize gpmc nand\n");
+	omap_gpmc_init(&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.2