linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms
@ 2015-07-10 12:23 Roger Quadros
  2015-07-10 12:23 ` [PATCH 01/12] ARM: OMAP2+: gpmc: Add platform data Roger Quadros
                   ` (11 more replies)
  0 siblings, 12 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Hi,

The OMAP GPMC IP is being used on non-OMAP platforms as well
and this series aims at cleaning up device tree implementation
for GPMC NAND so that it can be used on non-OMAP platforms.

NAND is now treated as any other generic GPMC child and has to
have its own compatible-id and address+interrupt resource.

Tested NAND on following boards
- dra7-evm
- am437x-gp-evm
- beagleboard C4

--
cheers,
-roger

Roger Quadros (12):
  ARM: OMAP2+: gpmc: Add platform data
  ARM: OMAP2+: gpmc: Add gpmc timings and settings to platform data
  mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
  mtd: nand: omap: Move gpmc_update_nand_reg to nand driver
  mtd: nand: omap: Move NAND write protect code from GPMC to NAND driver
  mtd: nand: omap: Copy platform data parameters to omap_nand_info data
  mtd: nand: omap: Clean up device tree support
  mtd: nand: omap: Update DT binding documentation
  memory: omap-gpmc: use module_platform_driver()
  memory: omap-gpmc: Prevent mapping into 1st 16MB
  ARM: dts: OMAP2+: Fix NAND device nodes
  ARM: dts: omap3: Fix gpmc memory resource size

 .../devicetree/bindings/mtd/gpmc-nand.txt          |  16 +-
 arch/arm/boot/dts/am335x-baltos-ir5221.dts         |   9 +-
 arch/arm/boot/dts/am335x-chilisom.dtsi             |   8 +-
 arch/arm/boot/dts/am335x-evm.dts                   |   8 +-
 arch/arm/boot/dts/am335x-igep0033.dtsi             |   8 +-
 arch/arm/boot/dts/am437x-gp-evm.dts                |   8 +-
 arch/arm/boot/dts/am43x-epos-evm.dts               |   8 +-
 arch/arm/boot/dts/dm8168-evm.dts                   |   8 +-
 arch/arm/boot/dts/dra7-evm.dts                     |   8 +-
 arch/arm/boot/dts/dra72-evm.dts                    |   8 +-
 arch/arm/boot/dts/logicpd-torpedo-som.dtsi         |   9 +-
 arch/arm/boot/dts/omap3-beagle.dts                 |   7 +-
 arch/arm/boot/dts/omap3-cm-t3x.dtsi                |   8 +-
 arch/arm/boot/dts/omap3-devkit8000.dts             |   9 +-
 arch/arm/boot/dts/omap3-evm-37xx.dts               |  10 +-
 arch/arm/boot/dts/omap3-gta04.dtsi                 |   8 +-
 arch/arm/boot/dts/omap3-igep.dtsi                  |   5 +-
 arch/arm/boot/dts/omap3-igep0020-common.dtsi       |   5 +-
 arch/arm/boot/dts/omap3-igep0030-common.dtsi       |   6 +
 arch/arm/boot/dts/omap3-ldp.dts                    |  10 +-
 arch/arm/boot/dts/omap3-lilly-a83x.dtsi            |   8 +-
 arch/arm/boot/dts/omap3-lilly-dbb056.dts           |   7 +-
 arch/arm/boot/dts/omap3-pandora-common.dtsi        |   8 +-
 arch/arm/boot/dts/omap3-tao3530.dtsi               |   8 +-
 arch/arm/boot/dts/omap3.dtsi                       |   2 +-
 arch/arm/boot/dts/omap3430-sdp.dts                 |   8 +-
 arch/arm/mach-omap2/gpmc-nand.c                    |  19 +-
 drivers/memory/omap-gpmc.c                         | 427 +++------------------
 drivers/mtd/nand/omap2.c                           | 380 ++++++++++++++----
 include/linux/omap-gpmc.h                          | 148 +------
 include/linux/platform_data/gpmc-omap.h            | 169 ++++++++
 include/linux/platform_data/mtd-nand-omap2.h       |  10 +-
 32 files changed, 705 insertions(+), 655 deletions(-)
 create mode 100644 include/linux/platform_data/gpmc-omap.h

-- 
2.1.4


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/12] ARM: OMAP2+: gpmc: Add platform data
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 02/12] ARM: OMAP2+: gpmc: Add gpmc timings and settings to " Roger Quadros
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Add a platform data structure for GPMC. It contains all the necessary
platform information that needs to be passed from platform init code
to GPMC driver.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 include/linux/omap-gpmc.h               |  3 +--
 include/linux/platform_data/gpmc-omap.h | 30 ++++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 2 deletions(-)
 create mode 100644 include/linux/platform_data/gpmc-omap.h

diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h
index 7dee0014..5c79190 100644
--- a/include/linux/omap-gpmc.h
+++ b/include/linux/omap-gpmc.h
@@ -7,8 +7,7 @@
  *  option) any later version.
  */
 
-/* Maximum Number of Chip Selects */
-#define GPMC_CS_NUM		8
+#include <linux/platform_data/gpmc-omap.h>
 
 #define GPMC_CONFIG_WP		0x00000005
 
diff --git a/include/linux/platform_data/gpmc-omap.h b/include/linux/platform_data/gpmc-omap.h
new file mode 100644
index 0000000..d32d9de
--- /dev/null
+++ b/include/linux/platform_data/gpmc-omap.h
@@ -0,0 +1,30 @@
+/*
+ * OMAP GPMC Platform data
+ *
+ * Copyright (C) 2014 Texas Instruments, Inc. - http://www.ti.com
+ *	Roger Quadros <rogerq@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef _GPMC_OMAP_H_
+#define _GPMC_OMAP_H_
+
+/* Maximum Number of Chip Selects */
+#define GPMC_CS_NUM		8
+
+/* Data for each chip select */
+struct gpmc_omap_cs_data {
+	bool valid;			/* data is valid */
+	bool is_nand;			/* device within this CS is NAND */
+	struct platform_device *pdev;	/* device within this CS region */
+	unsigned pdata_size;
+};
+
+struct gpmc_omap_platform_data {
+	struct gpmc_omap_cs_data cs[GPMC_CS_NUM];
+};
+
+#endif /* _GPMC_OMAP_H */
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 02/12] ARM: OMAP2+: gpmc: Add gpmc timings and settings to platform data
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
  2015-07-10 12:23 ` [PATCH 01/12] ARM: OMAP2+: gpmc: Add platform data Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-13 13:31   ` Tony Lindgren
  2015-07-10 12:23 ` [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver Roger Quadros
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Add device_timings, gpmc_timings and gpmc_setting to
gpmc platform data.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 include/linux/omap-gpmc.h               | 134 ------------------------------
 include/linux/platform_data/gpmc-omap.h | 139 ++++++++++++++++++++++++++++++++
 2 files changed, 139 insertions(+), 134 deletions(-)

diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h
index 5c79190..2dcef1c 100644
--- a/include/linux/omap-gpmc.h
+++ b/include/linux/omap-gpmc.h
@@ -14,140 +14,6 @@
 #define GPMC_IRQ_FIFOEVENTENABLE	0x01
 #define GPMC_IRQ_COUNT_EVENT		0x02
 
-#define GPMC_BURST_4			4	/* 4 word burst */
-#define GPMC_BURST_8			8	/* 8 word burst */
-#define GPMC_BURST_16			16	/* 16 word burst */
-#define GPMC_DEVWIDTH_8BIT		1	/* 8-bit device width */
-#define GPMC_DEVWIDTH_16BIT		2	/* 16-bit device width */
-#define GPMC_MUX_AAD			1	/* Addr-Addr-Data multiplex */
-#define GPMC_MUX_AD			2	/* Addr-Data multiplex */
-
-/* bool type time settings */
-struct gpmc_bool_timings {
-	bool cycle2cyclediffcsen;
-	bool cycle2cyclesamecsen;
-	bool we_extra_delay;
-	bool oe_extra_delay;
-	bool adv_extra_delay;
-	bool cs_extra_delay;
-	bool time_para_granularity;
-};
-
-/*
- * Note that all values in this struct are in nanoseconds except sync_clk
- * (which is in picoseconds), while the register values are in gpmc_fck cycles.
- */
-struct gpmc_timings {
-	/* Minimum clock period for synchronous mode (in picoseconds) */
-	u32 sync_clk;
-
-	/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
-	u32 cs_on;		/* Assertion time */
-	u32 cs_rd_off;		/* Read deassertion time */
-	u32 cs_wr_off;		/* Write deassertion time */
-
-	/* ADV signal timings corresponding to GPMC_CONFIG3 */
-	u32 adv_on;		/* Assertion time */
-	u32 adv_rd_off;		/* Read deassertion time */
-	u32 adv_wr_off;		/* Write deassertion time */
-
-	/* WE signals timings corresponding to GPMC_CONFIG4 */
-	u32 we_on;		/* WE assertion time */
-	u32 we_off;		/* WE deassertion time */
-
-	/* OE signals timings corresponding to GPMC_CONFIG4 */
-	u32 oe_on;		/* OE assertion time */
-	u32 oe_off;		/* OE deassertion time */
-
-	/* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
-	u32 page_burst_access;	/* Multiple access word delay */
-	u32 access;		/* Start-cycle to first data valid delay */
-	u32 rd_cycle;		/* Total read cycle time */
-	u32 wr_cycle;		/* Total write cycle time */
-
-	u32 bus_turnaround;
-	u32 cycle2cycle_delay;
-
-	u32 wait_monitoring;
-	u32 clk_activation;
-
-	/* The following are only on OMAP3430 */
-	u32 wr_access;		/* WRACCESSTIME */
-	u32 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
-
-	struct gpmc_bool_timings bool_timings;
-};
-
-/* Device timings in picoseconds */
-struct gpmc_device_timings {
-	u32 t_ceasu;	/* address setup to CS valid */
-	u32 t_avdasu;	/* address setup to ADV valid */
-	/* XXX: try to combine t_avdp_r & t_avdp_w. Issue is
-	 * of tusb using these timings even for sync whilst
-	 * ideally for adv_rd/(wr)_off it should have considered
-	 * t_avdh instead. This indirectly necessitates r/w
-	 * variations of t_avdp as it is possible to have one
-	 * sync & other async
-	 */
-	u32 t_avdp_r;	/* ADV low time (what about t_cer ?) */
-	u32 t_avdp_w;
-	u32 t_aavdh;	/* address hold time */
-	u32 t_oeasu;	/* address setup to OE valid */
-	u32 t_aa;	/* access time from ADV assertion */
-	u32 t_iaa;	/* initial access time */
-	u32 t_oe;	/* access time from OE assertion */
-	u32 t_ce;	/* access time from CS asertion */
-	u32 t_rd_cycle;	/* read cycle time */
-	u32 t_cez_r;	/* read CS deassertion to high Z */
-	u32 t_cez_w;	/* write CS deassertion to high Z */
-	u32 t_oez;	/* OE deassertion to high Z */
-	u32 t_weasu;	/* address setup to WE valid */
-	u32 t_wpl;	/* write assertion time */
-	u32 t_wph;	/* write deassertion time */
-	u32 t_wr_cycle;	/* write cycle time */
-
-	u32 clk;
-	u32 t_bacc;	/* burst access valid clock to output delay */
-	u32 t_ces;	/* CS setup time to clk */
-	u32 t_avds;	/* ADV setup time to clk */
-	u32 t_avdh;	/* ADV hold time from clk */
-	u32 t_ach;	/* address hold time from clk */
-	u32 t_rdyo;	/* clk to ready valid */
-
-	u32 t_ce_rdyz;	/* XXX: description ?, or use t_cez instead */
-	u32 t_ce_avd;	/* CS on to ADV on delay */
-
-	/* XXX: check the possibility of combining
-	 * cyc_aavhd_oe & cyc_aavdh_we
-	 */
-	u8 cyc_aavdh_oe;/* read address hold time in cycles */
-	u8 cyc_aavdh_we;/* write address hold time in cycles */
-	u8 cyc_oe;	/* access time from OE assertion in cycles */
-	u8 cyc_wpl;	/* write deassertion time in cycles */
-	u32 cyc_iaa;	/* initial access time in cycles */
-
-	/* extra delays */
-	bool ce_xdelay;
-	bool avd_xdelay;
-	bool oe_xdelay;
-	bool we_xdelay;
-};
-
-struct gpmc_settings {
-	bool burst_wrap;	/* enables wrap bursting */
-	bool burst_read;	/* enables read page/burst mode */
-	bool burst_write;	/* enables write page/burst mode */
-	bool device_nand;	/* device is NAND */
-	bool sync_read;		/* enables synchronous reads */
-	bool sync_write;	/* enables synchronous writes */
-	bool wait_on_read;	/* monitor wait on reads */
-	bool wait_on_write;	/* monitor wait on writes */
-	u32 burst_len;		/* page/burst length */
-	u32 device_width;	/* device bus width (8 or 16 bit) */
-	u32 mux_add_data;	/* multiplex address & data */
-	u32 wait_pin;		/* wait-pin to be used */
-};
-
 extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
 			     struct gpmc_settings *gpmc_s,
 			     struct gpmc_device_timings *dev_t);
diff --git a/include/linux/platform_data/gpmc-omap.h b/include/linux/platform_data/gpmc-omap.h
index d32d9de..e861112 100644
--- a/include/linux/platform_data/gpmc-omap.h
+++ b/include/linux/platform_data/gpmc-omap.h
@@ -15,10 +15,149 @@
 /* Maximum Number of Chip Selects */
 #define GPMC_CS_NUM		8
 
+/* bool type time settings */
+struct gpmc_bool_timings {
+	bool cycle2cyclediffcsen;
+	bool cycle2cyclesamecsen;
+	bool we_extra_delay;
+	bool oe_extra_delay;
+	bool adv_extra_delay;
+	bool cs_extra_delay;
+	bool time_para_granularity;
+};
+
+/*
+ * Note that all values in this struct are in nanoseconds except sync_clk
+ * (which is in picoseconds), while the register values are in gpmc_fck cycles.
+ */
+struct gpmc_timings {
+	/* Minimum clock period for synchronous mode (in picoseconds) */
+	u32 sync_clk;
+
+	/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
+	u32 cs_on;		/* Assertion time */
+	u32 cs_rd_off;		/* Read deassertion time */
+	u32 cs_wr_off;		/* Write deassertion time */
+
+	/* ADV signal timings corresponding to GPMC_CONFIG3 */
+	u32 adv_on;		/* Assertion time */
+	u32 adv_rd_off;		/* Read deassertion time */
+	u32 adv_wr_off;		/* Write deassertion time */
+
+	/* WE signals timings corresponding to GPMC_CONFIG4 */
+	u32 we_on;		/* WE assertion time */
+	u32 we_off;		/* WE deassertion time */
+
+	/* OE signals timings corresponding to GPMC_CONFIG4 */
+	u32 oe_on;		/* OE assertion time */
+	u32 oe_off;		/* OE deassertion time */
+
+	/* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
+	u32 page_burst_access;	/* Multiple access word delay */
+	u32 access;		/* Start-cycle to first data valid delay */
+	u32 rd_cycle;		/* Total read cycle time */
+	u32 wr_cycle;		/* Total write cycle time */
+
+	u32 bus_turnaround;
+	u32 cycle2cycle_delay;
+
+	u32 wait_monitoring;
+	u32 clk_activation;
+
+	/* The following are only on OMAP3430 */
+	u32 wr_access;		/* WRACCESSTIME */
+	u32 wr_data_mux_bus;	/* WRDATAONADMUXBUS */
+
+	struct gpmc_bool_timings bool_timings;
+};
+
+
+/* Device timings in picoseconds */
+struct gpmc_device_timings {
+	u32 t_ceasu;	/* address setup to CS valid */
+	u32 t_avdasu;	/* address setup to ADV valid */
+	/* XXX: try to combine t_avdp_r & t_avdp_w. Issue is
+	 * of tusb using these timings even for sync whilst
+	 * ideally for adv_rd/(wr)_off it should have considered
+	 * t_avdh instead. This indirectly necessitates r/w
+	 * variations of t_avdp as it is possible to have one
+	 * sync & other async
+	 */
+	u32 t_avdp_r;	/* ADV low time (what about t_cer ?) */
+	u32 t_avdp_w;
+	u32 t_aavdh;	/* address hold time */
+	u32 t_oeasu;	/* address setup to OE valid */
+	u32 t_aa;	/* access time from ADV assertion */
+	u32 t_iaa;	/* initial access time */
+	u32 t_oe;	/* access time from OE assertion */
+	u32 t_ce;	/* access time from CS asertion */
+	u32 t_rd_cycle;	/* read cycle time */
+	u32 t_cez_r;	/* read CS deassertion to high Z */
+	u32 t_cez_w;	/* write CS deassertion to high Z */
+	u32 t_oez;	/* OE deassertion to high Z */
+	u32 t_weasu;	/* address setup to WE valid */
+	u32 t_wpl;	/* write assertion time */
+	u32 t_wph;	/* write deassertion time */
+	u32 t_wr_cycle;	/* write cycle time */
+
+	u32 clk;
+	u32 t_bacc;	/* burst access valid clock to output delay */
+	u32 t_ces;	/* CS setup time to clk */
+	u32 t_avds;	/* ADV setup time to clk */
+	u32 t_avdh;	/* ADV hold time from clk */
+	u32 t_ach;	/* address hold time from clk */
+	u32 t_rdyo;	/* clk to ready valid */
+
+	u32 t_ce_rdyz;	/* XXX: description ?, or use t_cez instead */
+	u32 t_ce_avd;	/* CS on to ADV on delay */
+
+	/* XXX: check the possibility of combining
+	 * cyc_aavhd_oe & cyc_aavdh_we
+	 */
+	u8 cyc_aavdh_oe;/* read address hold time in cycles */
+	u8 cyc_aavdh_we;/* write address hold time in cycles */
+	u8 cyc_oe;	/* access time from OE assertion in cycles */
+	u8 cyc_wpl;	/* write deassertion time in cycles */
+	u32 cyc_iaa;	/* initial access time in cycles */
+
+	/* extra delays */
+	bool ce_xdelay;
+	bool avd_xdelay;
+	bool oe_xdelay;
+	bool we_xdelay;
+};
+
+#define GPMC_BURST_4			4	/* 4 word burst */
+#define GPMC_BURST_8			8	/* 8 word burst */
+#define GPMC_BURST_16			16	/* 16 word burst */
+#define GPMC_DEVWIDTH_8BIT		1	/* 8-bit device width */
+#define GPMC_DEVWIDTH_16BIT		2	/* 16-bit device width */
+#define GPMC_MUX_AAD			1	/* Addr-Addr-Data multiplex */
+#define GPMC_MUX_AD			2	/* Addr-Data multiplex */
+
+struct gpmc_settings {
+	bool burst_wrap;	/* enables wrap bursting */
+	bool burst_read;	/* enables read page/burst mode */
+	bool burst_write;	/* enables write page/burst mode */
+	bool device_nand;	/* device is NAND */
+	bool sync_read;		/* enables synchronous reads */
+	bool sync_write;	/* enables synchronous writes */
+	bool wait_on_read;	/* monitor wait on reads */
+	bool wait_on_write;	/* monitor wait on writes */
+	u32 burst_len;		/* page/burst length */
+	u32 device_width;	/* device bus width (8 or 16 bit) */
+	u32 mux_add_data;	/* multiplex address & data */
+	u32 wait_pin;		/* wait-pin to be used */
+};
+
+
 /* Data for each chip select */
 struct gpmc_omap_cs_data {
 	bool valid;			/* data is valid */
 	bool is_nand;			/* device within this CS is NAND */
+	struct gpmc_settings *settings;
+	struct gpmc_device_timings *device_timings;
+	struct gpmc_timings *gpmc_timings;
 	struct platform_device *pdev;	/* device within this CS region */
 	unsigned pdata_size;
 };
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
  2015-07-10 12:23 ` [PATCH 01/12] ARM: OMAP2+: gpmc: Add platform data Roger Quadros
  2015-07-10 12:23 ` [PATCH 02/12] ARM: OMAP2+: gpmc: Add gpmc timings and settings to " Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-13  7:10   ` Tony Lindgren
  2015-07-10 12:23 ` [PATCH 04/12] mtd: nand: omap: Move gpmc_update_nand_reg to nand driver Roger Quadros
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Since the Interrupt Events are used only by the NAND driver,
there is no point in managing the Interrupt registers
in the GPMC driver and complicating it with irqchip modeling.

Let's manage the interrupt registers directly in the NAND driver
and get rid of irqchip model from GPMC driver.

Get rid of IRQ commands and unused commands from gpmc_configure() in
the GPMC driver.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/mach-omap2/gpmc-nand.c              |   4 +-
 drivers/memory/omap-gpmc.c                   | 176 ++-------------------------
 drivers/mtd/nand/omap2.c                     |  76 ++++++------
 include/linux/omap-gpmc.h                    |   5 +-
 include/linux/platform_data/mtd-nand-omap2.h |   2 +
 5 files changed, 56 insertions(+), 207 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 72918c4..b960876 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -80,7 +80,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 	struct resource gpmc_nand_res[] = {
 		{ .flags = IORESOURCE_MEM, },
 		{ .flags = IORESOURCE_IRQ, },
-		{ .flags = IORESOURCE_IRQ, },
 	};
 
 	BUG_ON(gpmc_nand_data->cs >= GPMC_CS_NUM);
@@ -93,8 +92,7 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 		return err;
 	}
 	gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1;
-	gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE);
-	gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT);
+	gpmc_nand_res[1].start = gpmc_get_irq();
 
 	memset(&s, 0, sizeof(struct gpmc_settings));
 	if (gpmc_nand_data->of_node)
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 3a27a84..50806e7 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -121,12 +121,6 @@
 #define GPMC_CS_NAND_ADDRESS	0x20
 #define GPMC_CS_NAND_DATA	0x24
 
-/* Control Commands */
-#define GPMC_CONFIG_RDY_BSY	0x00000001
-#define GPMC_CONFIG_DEV_SIZE	0x00000002
-#define GPMC_CONFIG_DEV_TYPE	0x00000003
-#define GPMC_SET_IRQ_STATUS	0x00000004
-
 #define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
 #define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
 #define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
@@ -174,17 +168,11 @@
 #define GPMC_CONFIG_WRITEPROTECT	0x00000010
 #define WR_RD_PIN_MONITORING		0x00600000
 
-#define GPMC_ENABLE_IRQ		0x0000000d
-
 /* ECC commands */
 #define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
 #define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
 #define GPMC_ECC_READSYN	2 /* Reset before syndrom is read back */
 
-/* XXX: Only NAND irq has been considered,currently these are the only ones used
- */
-#define	GPMC_NR_IRQ		2
-
 enum gpmc_clk_domain {
 	GPMC_CD_FCLK,
 	GPMC_CD_CLK
@@ -199,11 +187,6 @@ struct gpmc_cs_data {
 	struct resource mem;
 };
 
-struct gpmc_client_irq	{
-	unsigned		irq;
-	u32			bitmask;
-};
-
 /* Structure to save gpmc cs context */
 struct gpmc_cs_config {
 	u32 config1;
@@ -231,10 +214,6 @@ struct omap3_gpmc_regs {
 	struct gpmc_cs_config cs_context[GPMC_CS_NUM];
 };
 
-static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ];
-static struct irq_chip gpmc_irq_chip;
-static int gpmc_irq_start;
-
 static struct resource	gpmc_mem_root;
 static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
@@ -242,15 +221,13 @@ static DEFINE_SPINLOCK(gpmc_mem_lock);
 static unsigned int gpmc_cs_num = GPMC_CS_NUM;
 static unsigned int gpmc_nr_waitpins;
 static struct device *gpmc_dev;
-static int gpmc_irq;
+static int gpmc_irq = -EINVAL;
 static resource_size_t phys_base, mem_size;
 static unsigned gpmc_capability;
 static void __iomem *gpmc_base;
 
 static struct clk *gpmc_l3_clk;
 
-static irqreturn_t gpmc_handle_irq(int irq, void *dev);
-
 static void gpmc_write_reg(int idx, u32 val)
 {
 	writel_relaxed(val, gpmc_base + idx);
@@ -1035,14 +1012,6 @@ int gpmc_configure(int cmd, int wval)
 	u32 regval;
 
 	switch (cmd) {
-	case GPMC_ENABLE_IRQ:
-		gpmc_write_reg(GPMC_IRQENABLE, wval);
-		break;
-
-	case GPMC_SET_IRQ_STATUS:
-		gpmc_write_reg(GPMC_IRQSTATUS, wval);
-		break;
-
 	case GPMC_CONFIG_WP:
 		regval = gpmc_read_reg(GPMC_CONFIG);
 		if (wval)
@@ -1066,6 +1035,8 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 	int i;
 
 	reg->gpmc_status = gpmc_base + GPMC_STATUS;
+	reg->gpmc_irqstatus = gpmc_base + GPMC_IRQSTATUS;
+	reg->gpmc_irqenable = gpmc_base + GPMC_IRQENABLE;
 	reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET +
 				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
 	reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET +
@@ -1099,113 +1070,9 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 	}
 }
 
-int gpmc_get_client_irq(unsigned irq_config)
-{
-	int i;
-
-	if (hweight32(irq_config) > 1)
-		return 0;
-
-	for (i = 0; i < GPMC_NR_IRQ; i++)
-		if (gpmc_client_irq[i].bitmask & irq_config)
-			return gpmc_client_irq[i].irq;
-
-	return 0;
-}
-
-static int gpmc_irq_endis(unsigned irq, bool endis)
-{
-	int i;
-	u32 regval;
-
-	for (i = 0; i < GPMC_NR_IRQ; i++)
-		if (irq == gpmc_client_irq[i].irq) {
-			regval = gpmc_read_reg(GPMC_IRQENABLE);
-			if (endis)
-				regval |= gpmc_client_irq[i].bitmask;
-			else
-				regval &= ~gpmc_client_irq[i].bitmask;
-			gpmc_write_reg(GPMC_IRQENABLE, regval);
-			break;
-		}
-
-	return 0;
-}
-
-static void gpmc_irq_disable(struct irq_data *p)
-{
-	gpmc_irq_endis(p->irq, false);
-}
-
-static void gpmc_irq_enable(struct irq_data *p)
-{
-	gpmc_irq_endis(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 int gpmc_setup_irq(void)
-{
-	int i;
-	u32 regval;
-
-	if (!gpmc_irq)
-		return -EINVAL;
-
-	gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
-	if (gpmc_irq_start < 0) {
-		pr_err("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_client_irq[0].bitmask = GPMC_IRQ_FIFOEVENTENABLE;
-	gpmc_client_irq[1].bitmask = GPMC_IRQ_COUNT_EVENT;
-
-	for (i = 0; i < GPMC_NR_IRQ; i++) {
-		gpmc_client_irq[i].irq = gpmc_irq_start + i;
-		irq_set_chip_and_handler(gpmc_client_irq[i].irq,
-					&gpmc_irq_chip, handle_simple_irq);
-		set_irq_flags(gpmc_client_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_irq, gpmc_handle_irq, 0, "gpmc", NULL);
-}
-
-static int gpmc_free_irq(void)
+int gpmc_get_irq(void)
 {
-	int i;
-
-	if (gpmc_irq)
-		free_irq(gpmc_irq, NULL);
-
-	for (i = 0; i < GPMC_NR_IRQ; i++) {
-		irq_set_handler(gpmc_client_irq[i].irq, NULL);
-		irq_set_chip(gpmc_client_irq[i].irq, &no_irq_chip);
-		irq_modify_status(gpmc_client_irq[i].irq, 0, 0);
-	}
-
-	irq_free_descs(gpmc_irq_start, GPMC_NR_IRQ);
-
-	return 0;
+	return gpmc_irq;
 }
 
 static void gpmc_mem_exit(void)
@@ -2105,10 +1972,12 @@ static int gpmc_probe(struct platform_device *pdev)
 		return PTR_ERR(gpmc_base);
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res == NULL)
-		dev_warn(&pdev->dev, "Failed to get resource: irq\n");
-	else
-		gpmc_irq = res->start;
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get resource: irq\n");
+		return -EINVAL;
+	}
+
+	gpmc_irq = res->start;
 
 	gpmc_l3_clk = devm_clk_get(&pdev->dev, "fck");
 	if (IS_ERR(gpmc_l3_clk)) {
@@ -2150,9 +2019,6 @@ static int gpmc_probe(struct platform_device *pdev)
 
 	gpmc_mem_init();
 
-	if (gpmc_setup_irq() < 0)
-		dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
-
 	if (!pdev->dev.of_node) {
 		gpmc_cs_num	 = GPMC_CS_NUM;
 		gpmc_nr_waitpins = GPMC_NR_WAITPINS;
@@ -2170,7 +2036,6 @@ static int gpmc_probe(struct platform_device *pdev)
 
 static int gpmc_remove(struct platform_device *pdev)
 {
-	gpmc_free_irq();
 	gpmc_mem_exit();
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
@@ -2220,25 +2085,6 @@ static __exit void gpmc_exit(void)
 postcore_initcall(gpmc_init);
 module_exit(gpmc_exit);
 
-static irqreturn_t gpmc_handle_irq(int irq, void *dev)
-{
-	int i;
-	u32 regval;
-
-	regval = gpmc_read_reg(GPMC_IRQSTATUS);
-
-	if (!regval)
-		return IRQ_NONE;
-
-	for (i = 0; i < GPMC_NR_IRQ; i++)
-		if (regval & gpmc_client_irq[i].bitmask)
-			generic_handle_irq(gpmc_client_irq[i].irq);
-
-	gpmc_write_reg(GPMC_IRQSTATUS, regval);
-
-	return IRQ_HANDLED;
-}
-
 static struct omap3_gpmc_regs gpmc_context;
 
 void omap3_gpmc_save_context(void)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 60fa899..9dbb2be 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -136,6 +136,10 @@
 
 #define BADBLOCK_MARKER_LENGTH		2
 
+/* GPMC IRQ REGISTER bits */
+#define GPMC_IRQ_FIFOEVENT	BIT(0)
+#define GPMC_IRQ_TERMCOUNT	BIT(1)
+
 static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55,
 				0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78,
 				0x48, 0x76, 0xa9, 0x3b, 0x97, 0xd1, 0x7a, 0x93,
@@ -161,8 +165,7 @@ struct omap_nand_info {
 	enum omap_ecc			ecc_opt;
 	struct completion		comp;
 	struct dma_chan			*dma;
-	int				gpmc_irq_fifo;
-	int				gpmc_irq_count;
+	int				gpmc_irq;
 	enum {
 		OMAP_NAND_IO_READ = 0,	/* read */
 		OMAP_NAND_IO_WRITE,	/* write */
@@ -578,12 +581,16 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 {
 	struct omap_nand_info *info = (struct omap_nand_info *) dev;
 	u32 bytes;
+	u32 irqstatus;
+	u32 irqenable;
+
+	irqstatus = readl(info->reg.gpmc_irqstatus);
 
 	bytes = readl(info->reg.gpmc_prefetch_status);
 	bytes = 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)
+		if (irqstatus & GPMC_IRQ_TERMCOUNT)
 			goto done;
 
 		if (info->buf_len && (info->buf_len < bytes))
@@ -600,17 +607,27 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 						(u32 *)info->buf, bytes >> 2);
 		info->buf = info->buf + bytes;
 
-		if (this_irq == info->gpmc_irq_count)
+		if (irqstatus & GPMC_IRQ_TERMCOUNT)
 			goto done;
 	}
 
+	/* Clear FIFOEVENT STATUS */
+	irqstatus &= ~GPMC_IRQ_FIFOEVENT;
+	writel(irqstatus, info->reg.gpmc_irqstatus);
+
 	return IRQ_HANDLED;
 
 done:
 	complete(&info->comp);
 
-	disable_irq_nosync(info->gpmc_irq_fifo);
-	disable_irq_nosync(info->gpmc_irq_count);
+	/* Clear FIFOEVENT and TERMCOUNT STATUS */
+	irqstatus &= ~(GPMC_IRQ_TERMCOUNT | GPMC_IRQ_FIFOEVENT);
+	writel(irqstatus, info->reg.gpmc_irqstatus);
+
+	/* Disable Interrupt generation */
+	irqenable = readl(info->reg.gpmc_irqenable);
+	irqenable &= ~(GPMC_IRQ_TERMCOUNT | GPMC_IRQ_FIFOEVENT);
+	writel(irqenable, info->reg.gpmc_irqenable);
 
 	return IRQ_HANDLED;
 }
@@ -626,6 +643,7 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 	struct omap_nand_info *info = container_of(mtd,
 						struct omap_nand_info, mtd);
 	int ret = 0;
+	u32 irqenable;
 
 	if (len <= mtd->oobsize) {
 		omap_read_buf_pref(mtd, buf, len);
@@ -645,8 +663,10 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
 
 	info->buf_len = len;
 
-	enable_irq(info->gpmc_irq_count);
-	enable_irq(info->gpmc_irq_fifo);
+	/* Enable Interrupt generation */
+	irqenable = readl(info->reg.gpmc_irqenable);
+	irqenable |= (GPMC_IRQ_FIFOEVENT | GPMC_IRQ_TERMCOUNT);
+	writel(irqenable, info->reg.gpmc_irqenable);
 
 	/* waiting for read to complete */
 	wait_for_completion(&info->comp);
@@ -676,6 +696,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 	int ret = 0;
 	unsigned long tim, limit;
 	u32 val;
+	u32 irqenable;
 
 	if (len <= mtd->oobsize) {
 		omap_write_buf_pref(mtd, buf, len);
@@ -695,8 +716,10 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
 
 	info->buf_len = len;
 
-	enable_irq(info->gpmc_irq_count);
-	enable_irq(info->gpmc_irq_fifo);
+	/* Enable Interrupt generation */
+	irqenable = readl(info->reg.gpmc_irqenable);
+	irqenable |= (GPMC_IRQ_FIFOEVENT | GPMC_IRQ_TERMCOUNT);
+	writel(irqenable, info->reg.gpmc_irqenable);
 
 	/* waiting for write to complete */
 	wait_for_completion(&info->comp);
@@ -1771,35 +1794,18 @@ static int omap_nand_probe(struct platform_device *pdev)
 		break;
 
 	case NAND_OMAP_PREFETCH_IRQ:
-		info->gpmc_irq_fifo = platform_get_irq(pdev, 0);
-		if (info->gpmc_irq_fifo <= 0) {
-			dev_err(&pdev->dev, "error getting fifo irq\n");
-			err = -ENODEV;
-			goto return_error;
-		}
-		err = devm_request_irq(&pdev->dev, info->gpmc_irq_fifo,
-					omap_nand_irq, IRQF_SHARED,
-					"gpmc-nand-fifo", info);
-		if (err) {
-			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
-						info->gpmc_irq_fifo, err);
-			info->gpmc_irq_fifo = 0;
-			goto return_error;
-		}
-
-		info->gpmc_irq_count = platform_get_irq(pdev, 1);
-		if (info->gpmc_irq_count <= 0) {
-			dev_err(&pdev->dev, "error getting count irq\n");
-			err = -ENODEV;
+		info->gpmc_irq = platform_get_irq(pdev, 0);
+		if (info->gpmc_irq < 0) {
+			dev_err(&pdev->dev, "error getting GPMC irq\n");
+			err = info->gpmc_irq;
 			goto return_error;
 		}
-		err = devm_request_irq(&pdev->dev, info->gpmc_irq_count,
-					omap_nand_irq, IRQF_SHARED,
-					"gpmc-nand-count", info);
+		err = devm_request_irq(&pdev->dev, info->gpmc_irq,
+				       omap_nand_irq, IRQF_SHARED,
+				       DRIVER_NAME, info);
 		if (err) {
 			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
-						info->gpmc_irq_count, err);
-			info->gpmc_irq_count = 0;
+				info->gpmc_irq, err);
 			goto return_error;
 		}
 
diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h
index 2dcef1c..c7d291c 100644
--- a/include/linux/omap-gpmc.h
+++ b/include/linux/omap-gpmc.h
@@ -11,9 +11,6 @@
 
 #define GPMC_CONFIG_WP		0x00000005
 
-#define GPMC_IRQ_FIFOEVENTENABLE	0x01
-#define GPMC_IRQ_COUNT_EVENT		0x02
-
 extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
 			     struct gpmc_settings *gpmc_s,
 			     struct gpmc_device_timings *dev_t);
@@ -22,7 +19,7 @@ struct gpmc_nand_regs;
 struct device_node;
 
 extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
-extern int gpmc_get_client_irq(unsigned irq_config);
+extern int gpmc_get_irq(void);
 
 extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
 
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 090bbab..5a48a43 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -46,6 +46,8 @@ enum omap_ecc {
 
 struct gpmc_nand_regs {
 	void __iomem	*gpmc_status;
+	void __iomem	*gpmc_irqstatus;
+	void __iomem	*gpmc_irqenable;
 	void __iomem	*gpmc_nand_command;
 	void __iomem	*gpmc_nand_address;
 	void __iomem	*gpmc_nand_data;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 04/12] mtd: nand: omap: Move gpmc_update_nand_reg to nand driver
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (2 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 05/12] mtd: nand: omap: Move NAND write protect code from GPMC to NAND driver Roger Quadros
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

GPMC and NAND drivers share the same register space but never use the
same registers. As there is no clear address seperation between the
registers for GPMC and NAND, we can't easily split it up into 2 regions
i.e. one for GPMC and other for NAND. Instead, we simply remap the entire
register space in both the drivers. The NAND driver doesn't re-request
the region as it is already requested by the GPMC driver (parent).

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/mach-omap2/gpmc-nand.c              |   8 +-
 drivers/memory/omap-gpmc.c                   |  54 +----------
 drivers/mtd/nand/omap2.c                     | 132 ++++++++++++++++++++++++---
 include/linux/omap-gpmc.h                    |   3 +-
 include/linux/platform_data/mtd-nand-omap2.h |   3 +-
 5 files changed, 129 insertions(+), 71 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index b960876..ff578d4 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -78,7 +78,8 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 	struct gpmc_settings s;
 	struct platform_device *pdev;
 	struct resource gpmc_nand_res[] = {
-		{ .flags = IORESOURCE_MEM, },
+		{ .flags = IORESOURCE_MEM, },	/* GPMC I/O space */
+		{ .flags = IORESOURCE_MEM, },	/* GPMC register space */
 		{ .flags = IORESOURCE_IRQ, },
 	};
 
@@ -92,7 +93,8 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 		return err;
 	}
 	gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1;
-	gpmc_nand_res[1].start = gpmc_get_irq();
+	gpmc_get_mem_resource(&gpmc_nand_res[1]);
+	gpmc_nand_res[2].start = gpmc_get_irq();
 
 	memset(&s, 0, sizeof(struct gpmc_settings));
 	if (gpmc_nand_data->of_node)
@@ -119,8 +121,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 	if (err < 0)
 		goto out_free_cs;
 
-	gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
-
 	if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
 		pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
 		err = -EINVAL;
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 50806e7..dd55a51 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -54,17 +54,6 @@
 #define GPMC_PREFETCH_CONFIG2	0x1e4
 #define GPMC_PREFETCH_CONTROL	0x1ec
 #define GPMC_PREFETCH_STATUS	0x1f0
-#define GPMC_ECC_CONFIG		0x1f4
-#define GPMC_ECC_CONTROL	0x1f8
-#define GPMC_ECC_SIZE_CONFIG	0x1fc
-#define GPMC_ECC1_RESULT        0x200
-#define GPMC_ECC_BCH_RESULT_0   0x240   /* not available on OMAP2 */
-#define	GPMC_ECC_BCH_RESULT_1	0x244	/* not available on OMAP2 */
-#define	GPMC_ECC_BCH_RESULT_2	0x248	/* not available on OMAP2 */
-#define	GPMC_ECC_BCH_RESULT_3	0x24c	/* not available on OMAP2 */
-#define	GPMC_ECC_BCH_RESULT_4	0x300	/* not available on OMAP2 */
-#define	GPMC_ECC_BCH_RESULT_5	0x304	/* not available on OMAP2 */
-#define	GPMC_ECC_BCH_RESULT_6	0x308	/* not available on OMAP2 */
 
 /* GPMC ECC control settings */
 #define GPMC_ECC_CTRL_ECCCLEAR		0x100
@@ -117,9 +106,6 @@
 #define GPMC_CS_CONFIG5		0x10
 #define GPMC_CS_CONFIG6		0x14
 #define GPMC_CS_CONFIG7		0x18
-#define GPMC_CS_NAND_COMMAND	0x1c
-#define GPMC_CS_NAND_ADDRESS	0x20
-#define GPMC_CS_NAND_DATA	0x24
 
 #define GPMC_CONFIG1_WRAPBURST_SUPP     (1 << 31)
 #define GPMC_CONFIG1_READMULTIPLE_SUPP  (1 << 30)
@@ -1030,44 +1016,10 @@ int gpmc_configure(int cmd, int wval)
 }
 EXPORT_SYMBOL(gpmc_configure);
 
-void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
+void gpmc_get_mem_resource(struct resource *res)
 {
-	int i;
-
-	reg->gpmc_status = gpmc_base + GPMC_STATUS;
-	reg->gpmc_irqstatus = gpmc_base + GPMC_IRQSTATUS;
-	reg->gpmc_irqenable = gpmc_base + GPMC_IRQENABLE;
-	reg->gpmc_nand_command = gpmc_base + GPMC_CS0_OFFSET +
-				GPMC_CS_NAND_COMMAND + GPMC_CS_SIZE * cs;
-	reg->gpmc_nand_address = gpmc_base + GPMC_CS0_OFFSET +
-				GPMC_CS_NAND_ADDRESS + GPMC_CS_SIZE * cs;
-	reg->gpmc_nand_data = gpmc_base + GPMC_CS0_OFFSET +
-				GPMC_CS_NAND_DATA + GPMC_CS_SIZE * cs;
-	reg->gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1;
-	reg->gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2;
-	reg->gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL;
-	reg->gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS;
-	reg->gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG;
-	reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL;
-	reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG;
-	reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT;
-
-	for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) {
-		reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 +
-					   GPMC_BCH_SIZE * i;
-		reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 +
-					   GPMC_BCH_SIZE * i;
-		reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 +
-					   GPMC_BCH_SIZE * i;
-		reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
-					   GPMC_BCH_SIZE * i;
-		reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 +
-					   i * GPMC_BCH_SIZE;
-		reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 +
-					   i * GPMC_BCH_SIZE;
-		reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 +
-					   i * GPMC_BCH_SIZE;
-	}
+	res->start =  phys_base;
+	res->end = res->start + mem_size - 1;
 }
 
 int gpmc_get_irq(void)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 9dbb2be..3d0f73c 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -140,6 +140,39 @@
 #define GPMC_IRQ_FIFOEVENT	BIT(0)
 #define GPMC_IRQ_TERMCOUNT	BIT(1)
 
+/* GPMC register offsets */
+#define GPMC_REVISION		0x00
+#define GPMC_SYSCONFIG		0x10
+#define GPMC_SYSSTATUS		0x14
+#define GPMC_IRQSTATUS		0x18
+#define GPMC_IRQENABLE		0x1c
+#define GPMC_TIMEOUT_CONTROL	0x40
+#define GPMC_ERR_ADDRESS	0x44
+#define GPMC_ERR_TYPE		0x48
+#define GPMC_CONFIG		0x50
+#define GPMC_STATUS		0x54
+#define GPMC_CS_NAND_COMMAND	0x7c
+#define GPMC_CS_NAND_ADDRESS	0x80
+#define GPMC_CS_NAND_DATA	0x84
+#define GPMC_PREFETCH_CONFIG1	0x1e0
+#define GPMC_PREFETCH_CONFIG2	0x1e4
+#define GPMC_PREFETCH_CONTROL	0x1ec
+#define GPMC_PREFETCH_STATUS	0x1f0
+#define GPMC_ECC_CONFIG		0x1f4
+#define GPMC_ECC_CONTROL	0x1f8
+#define GPMC_ECC_SIZE_CONFIG	0x1fc
+#define GPMC_ECC1_RESULT        0x200
+#define GPMC_ECC_BCH_RESULT_0   0x240   /* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_1	0x244	/* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_2	0x248	/* not available on OMAP2 */
+#define	GPMC_ECC_BCH_RESULT_3	0x24c	/* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_4	0x300	/* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_5	0x304	/* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_6	0x308	/* not available on OMAP2 */
+
+#define GPMC_CS_SIZE		0x30
+#define	GPMC_BCH_SIZE		0x10
+
 static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55,
 				0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78,
 				0x48, 0x76, 0xa9, 0x3b, 0x97, 0xd1, 0x7a, 0x93,
@@ -162,6 +195,7 @@ struct omap_nand_info {
 
 	int				gpmc_cs;
 	unsigned long			phys_base;
+	void __iomem			*gpmc_base;
 	enum omap_ecc			ecc_opt;
 	struct completion		comp;
 	struct dma_chan			*dma;
@@ -1672,20 +1706,64 @@ static bool omap2_nand_ecc_check(struct omap_nand_info *info,
 	return true;
 }
 
+static void gpmc_update_nand_reg(struct omap_nand_info *info)
+{
+	int i;
+	struct gpmc_nand_regs *reg = &info->reg;
+	int cs = info->gpmc_cs;
+	void __iomem *gpmc_base = info->gpmc_base;
+
+	reg->gpmc_status = gpmc_base + GPMC_STATUS;
+	reg->gpmc_irqstatus = gpmc_base + GPMC_IRQSTATUS;
+	reg->gpmc_irqenable = gpmc_base + GPMC_IRQENABLE;
+	reg->gpmc_nand_command = gpmc_base + GPMC_CS_NAND_COMMAND +
+				 GPMC_CS_SIZE * cs;
+	reg->gpmc_nand_address = gpmc_base + GPMC_CS_NAND_ADDRESS +
+				 GPMC_CS_SIZE * cs;
+	reg->gpmc_nand_data = gpmc_base + GPMC_CS_NAND_DATA +
+				 GPMC_CS_SIZE * cs;
+	reg->gpmc_prefetch_config1 = gpmc_base + GPMC_PREFETCH_CONFIG1;
+	reg->gpmc_prefetch_config2 = gpmc_base + GPMC_PREFETCH_CONFIG2;
+	reg->gpmc_prefetch_control = gpmc_base + GPMC_PREFETCH_CONTROL;
+	reg->gpmc_prefetch_status = gpmc_base + GPMC_PREFETCH_STATUS;
+	reg->gpmc_ecc_config = gpmc_base + GPMC_ECC_CONFIG;
+	reg->gpmc_ecc_control = gpmc_base + GPMC_ECC_CONTROL;
+	reg->gpmc_ecc_size_config = gpmc_base + GPMC_ECC_SIZE_CONFIG;
+	reg->gpmc_ecc1_result = gpmc_base + GPMC_ECC1_RESULT;
+
+	for (i = 0; i < GPMC_BCH_NUM_REMAINDER; i++) {
+		reg->gpmc_bch_result0[i] = gpmc_base + GPMC_ECC_BCH_RESULT_0 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result1[i] = gpmc_base + GPMC_ECC_BCH_RESULT_1 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result2[i] = gpmc_base + GPMC_ECC_BCH_RESULT_2 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 +
+					   GPMC_BCH_SIZE * i;
+		reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 +
+					   GPMC_BCH_SIZE * i;
+	}
+}
+
 static int omap_nand_probe(struct platform_device *pdev)
 {
-	struct omap_nand_info		*info;
-	struct omap_nand_platform_data	*pdata;
-	struct mtd_info			*mtd;
-	struct nand_chip		*nand_chip;
-	struct nand_ecclayout		*ecclayout;
-	int				err;
-	int				i;
-	dma_cap_mask_t			mask;
-	unsigned			sig;
-	unsigned			oob_index;
-	struct resource			*res;
-	struct mtd_part_parser_data	ppdata = {};
+	struct omap_nand_info *info;
+	struct omap_nand_platform_data *pdata;
+	struct mtd_info	*mtd;
+	struct nand_chip *nand_chip;
+	struct nand_ecclayout *ecclayout;
+	int err;
+	int i;
+	dma_cap_mask_t mask;
+	unsigned sig;
+	unsigned oob_index;
+	struct resource	*res;
+	struct mtd_part_parser_data ppdata = {};
+	struct device *dev = &pdev->dev;
 
 	pdata = dev_get_platdata(&pdev->dev);
 	if (pdata == NULL) {
@@ -1702,7 +1780,6 @@ static int omap_nand_probe(struct platform_device *pdev)
 
 	info->pdev		= pdev;
 	info->gpmc_cs		= pdata->cs;
-	info->reg		= pdata->reg;
 	info->of_node		= pdata->of_node;
 	info->ecc_opt		= pdata->ecc_opt;
 	mtd			= &info->mtd;
@@ -1712,8 +1789,14 @@ static int omap_nand_probe(struct platform_device *pdev)
 	nand_chip		= &info->nand;
 	nand_chip->ecc.priv	= NULL;
 
+	/* GPMC external I/O space */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
+	if (!res) {
+		dev_err(dev, "Can't get memory resource 0\n");
+		return -EINVAL;
+	}
+
+	nand_chip->IO_ADDR_R = devm_ioremap_resource(dev, res);
 	if (IS_ERR(nand_chip->IO_ADDR_R))
 		return PTR_ERR(nand_chip->IO_ADDR_R);
 
@@ -1724,6 +1807,27 @@ static int omap_nand_probe(struct platform_device *pdev)
 	nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
 	nand_chip->cmd_ctrl  = omap_hwcontrol;
 
+	/* GPMC internal registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(dev, "Can't get memory resource 1\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * This resource is already requested by the GPMC driver
+	 * so we can't request it again. Instead, we just ioremap it.
+	 * This driver doesn't access the same registers as the GPMC
+	 * driver so it is safe.
+	 */
+	info->gpmc_base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!info->gpmc_base) {
+		dev_err(dev, "Can't ioremap resource 1\n");
+		return -EADDRNOTAVAIL;
+	}
+
+	gpmc_update_nand_reg(info);
+
 	/*
 	 * If RDY/BSY line is connected to OMAP then use the omap ready
 	 * function and the generic nand_wait function which reads the status
diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h
index c7d291c..36f33ba 100644
--- a/include/linux/omap-gpmc.h
+++ b/include/linux/omap-gpmc.h
@@ -8,6 +8,7 @@
  */
 
 #include <linux/platform_data/gpmc-omap.h>
+#include <linux/ioport.h>
 
 #define GPMC_CONFIG_WP		0x00000005
 
@@ -18,7 +19,7 @@ extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
 struct gpmc_nand_regs;
 struct device_node;
 
-extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
+extern void gpmc_get_mem_resource(struct resource *res);
 extern int gpmc_get_irq(void);
 
 extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 5a48a43..4427f92 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -77,10 +77,11 @@ struct omap_nand_platform_data {
 	enum nand_io		xfer_type;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
-	struct gpmc_nand_regs	reg;
 
 	/* for passing the partitions */
 	struct device_node	*of_node;
 	struct device_node	*elm_of_node;
+
+	struct gpmc_nand_regs	reg;		/* deprecated */
 };
 #endif
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 05/12] mtd: nand: omap: Move NAND write protect code from GPMC to NAND driver
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (3 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 04/12] mtd: nand: omap: Move gpmc_update_nand_reg to nand driver Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 06/12] mtd: nand: omap: Copy platform data parameters to omap_nand_info data Roger Quadros
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

The write protect (WP) pin is only used for NAND devices. So move
the code into the NAND driver.

Get rid of gpmc_configure() as it is no longer used.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/mach-omap2/gpmc-nand.c              |  4 ----
 drivers/memory/omap-gpmc.c                   | 30 ----------------------------
 drivers/mtd/nand/omap2.c                     | 23 +++++++++++++++++++++
 include/linux/omap-gpmc.h                    |  3 ---
 include/linux/platform_data/mtd-nand-omap2.h |  1 +
 5 files changed, 24 insertions(+), 37 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index ff578d4..9cb8ce6 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -117,10 +117,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 	if (err < 0)
 		goto out_free_cs;
 
-	err = gpmc_configure(GPMC_CONFIG_WP, 0);
-	if (err < 0)
-		goto out_free_cs;
-
 	if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) {
 		pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n");
 		err = -EINVAL;
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index dd55a51..650f9b8 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -151,7 +151,6 @@
 
 #define GPMC_DEVICETYPE_NOR		0
 #define GPMC_DEVICETYPE_NAND		2
-#define GPMC_CONFIG_WRITEPROTECT	0x00000010
 #define WR_RD_PIN_MONITORING		0x00600000
 
 /* ECC commands */
@@ -987,35 +986,6 @@ void gpmc_cs_free(int cs)
 }
 EXPORT_SYMBOL(gpmc_cs_free);
 
-/**
- * gpmc_configure - write request to configure gpmc
- * @cmd: command type
- * @wval: value to write
- * @return status of the operation
- */
-int gpmc_configure(int cmd, int wval)
-{
-	u32 regval;
-
-	switch (cmd) {
-	case GPMC_CONFIG_WP:
-		regval = gpmc_read_reg(GPMC_CONFIG);
-		if (wval)
-			regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */
-		else
-			regval |= GPMC_CONFIG_WRITEPROTECT;  /* WP is OFF */
-		gpmc_write_reg(GPMC_CONFIG, regval);
-		break;
-
-	default:
-		pr_err("%s: command not supported\n", __func__);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(gpmc_configure);
-
 void gpmc_get_mem_resource(struct resource *res)
 {
 	res->start =  phys_base;
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 3d0f73c..25a3d05 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -140,6 +140,9 @@
 #define GPMC_IRQ_FIFOEVENT	BIT(0)
 #define GPMC_IRQ_TERMCOUNT	BIT(1)
 
+/* GPMC_CONFIG register bits */
+#define GPMC_CONFIG_WRITEPROTECT	BIT(4)
+
 /* GPMC register offsets */
 #define GPMC_REVISION		0x00
 #define GPMC_SYSCONFIG		0x10
@@ -215,6 +218,22 @@ struct omap_nand_info {
 };
 
 /**
+ * omap_nand_writeprotect - Control the WP line to the NAND chip
+ */
+static void omap_nand_writeprotect(struct omap_nand_info *info, bool on)
+{
+	u32 val;
+
+	val = readl(info->reg.gpmc_config);
+	if (on)
+		val &= GPMC_CONFIG_WRITEPROTECT; /* WP pin is active low */
+	else
+		val |= GPMC_CONFIG_WRITEPROTECT;
+
+	writel(val, info->reg.gpmc_config);
+}
+
+/**
  * omap_prefetch_enable - configures and starts prefetch transfer
  * @cs: cs (chip select) number
  * @fifo_th: fifo threshold to be used for read/ write
@@ -1713,6 +1732,7 @@ static void gpmc_update_nand_reg(struct omap_nand_info *info)
 	int cs = info->gpmc_cs;
 	void __iomem *gpmc_base = info->gpmc_base;
 
+	reg->gpmc_config = gpmc_base + GPMC_CONFIG;
 	reg->gpmc_status = gpmc_base + GPMC_STATUS;
 	reg->gpmc_irqstatus = gpmc_base + GPMC_IRQSTATUS;
 	reg->gpmc_irqenable = gpmc_base + GPMC_IRQENABLE;
@@ -2141,6 +2161,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 	nand_chip->ecc.layout = ecclayout;
 
 scan_tail:
+	/* turn off write protect */
+	omap_nand_writeprotect(info, false);
+
 	/* second phase scan */
 	if (nand_scan_tail(mtd)) {
 		err = -ENXIO;
diff --git a/include/linux/omap-gpmc.h b/include/linux/omap-gpmc.h
index 36f33ba..d13e172 100644
--- a/include/linux/omap-gpmc.h
+++ b/include/linux/omap-gpmc.h
@@ -10,8 +10,6 @@
 #include <linux/platform_data/gpmc-omap.h>
 #include <linux/ioport.h>
 
-#define GPMC_CONFIG_WP		0x00000005
-
 extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
 			     struct gpmc_settings *gpmc_s,
 			     struct gpmc_device_timings *dev_t);
@@ -31,7 +29,6 @@ extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
 extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p);
 extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
-extern int gpmc_configure(int cmd, int wval);
 extern void gpmc_read_settings_dt(struct device_node *np,
 				  struct gpmc_settings *p);
 
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 4427f92..e9b16b5 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -45,6 +45,7 @@ enum omap_ecc {
 };
 
 struct gpmc_nand_regs {
+	void __iomem	*gpmc_config;
 	void __iomem	*gpmc_status;
 	void __iomem	*gpmc_irqstatus;
 	void __iomem	*gpmc_irqenable;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 06/12] mtd: nand: omap: Copy platform data parameters to omap_nand_info data
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (4 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 05/12] mtd: nand: omap: Move NAND write protect code from GPMC to NAND driver Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 07/12] mtd: nand: omap: Clean up device tree support Roger Quadros
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Copy all the platform data parameters to the driver's local data
structure 'omap_nand_info' and use it in the entire driver. This will
make it easer for device tree migration.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/mtd/nand/omap2.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 25a3d05..407aecf9 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -191,15 +191,19 @@ static struct nand_hw_control omap_gpmc_controller = {
 };
 
 struct omap_nand_info {
-	struct omap_nand_platform_data	*pdata;
 	struct mtd_info			mtd;
 	struct nand_chip		nand;
 	struct platform_device		*pdev;
 
 	int				gpmc_cs;
+	bool				dev_ready;
+	enum nand_io			xfer_type;
+	int				devsize;
+	enum omap_ecc			ecc_opt;
+	struct device_node		*elm_of_node;
+
 	unsigned long			phys_base;
 	void __iomem			*gpmc_base;
-	enum omap_ecc			ecc_opt;
 	struct completion		comp;
 	struct dma_chan			*dma;
 	int				gpmc_irq;
@@ -1717,7 +1721,7 @@ static bool omap2_nand_ecc_check(struct omap_nand_info *info,
 			"CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
 		return false;
 	}
-	if (ecc_needs_elm && !is_elm_present(info, pdata->elm_of_node)) {
+	if (ecc_needs_elm && !is_elm_present(info, info->elm_of_node)) {
 		dev_err(&info->pdev->dev, "ELM not available\n");
 		return false;
 	}
@@ -1802,6 +1806,11 @@ static int omap_nand_probe(struct platform_device *pdev)
 	info->gpmc_cs		= pdata->cs;
 	info->of_node		= pdata->of_node;
 	info->ecc_opt		= pdata->ecc_opt;
+	info->dev_ready	= pdata->dev_ready;
+	info->xfer_type = pdata->xfer_type;
+	info->devsize = pdata->devsize;
+	info->elm_of_node = pdata->elm_of_node;
+
 	mtd			= &info->mtd;
 	mtd->priv		= &info->nand;
 	mtd->name		= dev_name(&pdev->dev);
@@ -1855,7 +1864,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 	 * chip delay which is slightly more than tR (AC Timing) of the NAND
 	 * device and read status register until you get a failure or success
 	 */
-	if (pdata->dev_ready) {
+	if (info->dev_ready) {
 		nand_chip->dev_ready = omap_dev_ready;
 		nand_chip->chip_delay = 0;
 	} else {
@@ -1869,15 +1878,16 @@ static int omap_nand_probe(struct platform_device *pdev)
 		nand_chip->options |= NAND_SKIP_BBTSCAN;
 
 	/* scan NAND device connected to chip controller */
-	nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16;
+	nand_chip->options |= info->devsize & NAND_BUSWIDTH_16;
 	if (nand_scan_ident(mtd, 1, NULL)) {
-		dev_err(&info->pdev->dev, "scan failed, may be bus-width mismatch\n");
+		dev_err(&info->pdev->dev,
+			"scan failed, may be bus-width mismatch\n");
 		err = -ENXIO;
 		goto return_error;
 	}
 
 	/* re-populate low-level callbacks based on xfer modes */
-	switch (pdata->xfer_type) {
+	switch (info->xfer_type) {
 	case NAND_OMAP_PREFETCH_POLLED:
 		nand_chip->read_buf   = omap_read_buf_pref;
 		nand_chip->write_buf  = omap_write_buf_pref;
@@ -1940,7 +1950,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 
 	default:
 		dev_err(&pdev->dev,
-			"xfer_type(%d) not supported!\n", pdata->xfer_type);
+			"xfer_type(%d) not supported!\n", info->xfer_type);
 		err = -EINVAL;
 		goto return_error;
 	}
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 07/12] mtd: nand: omap: Clean up device tree support
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (5 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 06/12] mtd: nand: omap: Copy platform data parameters to omap_nand_info data Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 08/12] mtd: nand: omap: Update DT binding documentation Roger Quadros
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Move NAND specific device tree parsing to NAND driver.

The NAND controller node must have a compatible id, register space
resource and interrupt resource.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/mach-omap2/gpmc-nand.c              |   5 +-
 drivers/memory/omap-gpmc.c                   | 133 ++++++---------------------
 drivers/mtd/nand/omap2.c                     | 133 +++++++++++++++++++++++----
 include/linux/platform_data/mtd-nand-omap2.h |   4 +-
 4 files changed, 142 insertions(+), 133 deletions(-)

diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 9cb8ce6..d7b8dcc 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -97,10 +97,7 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
 	gpmc_nand_res[2].start = gpmc_get_irq();
 
 	memset(&s, 0, sizeof(struct gpmc_settings));
-	if (gpmc_nand_data->of_node)
-		gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
-	else
-		gpmc_set_legacy(gpmc_nand_data, &s);
+	gpmc_set_legacy(gpmc_nand_data, &s);
 
 	s.device_nand = true;
 
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 650f9b8..995e9b8 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -29,7 +29,6 @@
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/omap-gpmc.h>
-#include <linux/mtd/nand.h>
 #include <linux/pm_runtime.h>
 
 #include <linux/platform_data/mtd-nand-omap2.h>
@@ -1557,105 +1556,6 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
 		of_property_read_bool(np, "gpmc,time-para-granularity");
 }
 
-#if IS_ENABLED(CONFIG_MTD_NAND)
-
-static const char * const nand_xfer_types[] = {
-	[NAND_OMAP_PREFETCH_POLLED]		= "prefetch-polled",
-	[NAND_OMAP_POLLED]			= "polled",
-	[NAND_OMAP_PREFETCH_DMA]		= "prefetch-dma",
-	[NAND_OMAP_PREFETCH_IRQ]		= "prefetch-irq",
-};
-
-static int gpmc_probe_nand_child(struct platform_device *pdev,
-				 struct device_node *child)
-{
-	u32 val;
-	const char *s;
-	struct gpmc_timings gpmc_t;
-	struct omap_nand_platform_data *gpmc_nand_data;
-
-	if (of_property_read_u32(child, "reg", &val) < 0) {
-		dev_err(&pdev->dev, "%s has no 'reg' property\n",
-			child->full_name);
-		return -ENODEV;
-	}
-
-	gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
-				      GFP_KERNEL);
-	if (!gpmc_nand_data)
-		return -ENOMEM;
-
-	gpmc_nand_data->cs = val;
-	gpmc_nand_data->of_node = child;
-
-	/* Detect availability of ELM module */
-	gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
-	if (gpmc_nand_data->elm_of_node == NULL)
-		gpmc_nand_data->elm_of_node =
-					of_parse_phandle(child, "elm_id", 0);
-
-	/* select ecc-scheme for NAND */
-	if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
-		pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
-		return -ENODEV;
-	}
-
-	if (!strcmp(s, "sw"))
-		gpmc_nand_data->ecc_opt = OMAP_ECC_HAM1_CODE_SW;
-	else if (!strcmp(s, "ham1") ||
-		 !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
-		gpmc_nand_data->ecc_opt =
-				OMAP_ECC_HAM1_CODE_HW;
-	else if (!strcmp(s, "bch4"))
-		if (gpmc_nand_data->elm_of_node)
-			gpmc_nand_data->ecc_opt =
-				OMAP_ECC_BCH4_CODE_HW;
-		else
-			gpmc_nand_data->ecc_opt =
-				OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
-	else if (!strcmp(s, "bch8"))
-		if (gpmc_nand_data->elm_of_node)
-			gpmc_nand_data->ecc_opt =
-				OMAP_ECC_BCH8_CODE_HW;
-		else
-			gpmc_nand_data->ecc_opt =
-				OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
-	else if (!strcmp(s, "bch16"))
-		if (gpmc_nand_data->elm_of_node)
-			gpmc_nand_data->ecc_opt =
-				OMAP_ECC_BCH16_CODE_HW;
-		else
-			pr_err("%s: BCH16 requires ELM support\n", __func__);
-	else
-		pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
-
-	/* select data transfer mode for NAND controller */
-	if (!of_property_read_string(child, "ti,nand-xfer-type", &s))
-		for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++)
-			if (!strcasecmp(s, nand_xfer_types[val])) {
-				gpmc_nand_data->xfer_type = val;
-				break;
-			}
-
-	gpmc_nand_data->flash_bbt = of_get_nand_on_flash_bbt(child);
-
-	val = of_get_nand_bus_width(child);
-	if (val == 16)
-		gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
-
-	gpmc_read_timings_dt(child, &gpmc_t);
-	gpmc_nand_init(gpmc_nand_data, &gpmc_t);
-
-	return 0;
-}
-#else
-static int gpmc_probe_nand_child(struct platform_device *pdev,
-				 struct device_node *child)
-{
-	return 0;
-}
-#endif
-
 #if IS_ENABLED(CONFIG_MTD_ONENAND)
 static int gpmc_probe_onenand_child(struct platform_device *pdev,
 				 struct device_node *child)
@@ -1774,9 +1674,32 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
 		goto err;
 	}
 
-	ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
-	if (ret < 0)
-		goto err;
+	if (of_node_cmp(child->name, "nand") == 0) {
+		/* NAND specific setup */
+		u32 val;
+
+		val = of_get_nand_bus_width(child);
+		switch (val) {
+		case 8:
+			gpmc_s.device_width = GPMC_DEVWIDTH_8BIT;
+			break;
+		case 16:
+			gpmc_s.device_width = GPMC_DEVWIDTH_16BIT;
+			break;
+		default:
+			dev_err(&pdev->dev, "%s: invalid 'nand-bus-width'\n",
+				child->name);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		gpmc_s.device_nand = true;
+	} else {
+		ret = of_property_read_u32(child, "bank-width",
+					   &gpmc_s.device_width);
+		if (ret < 0)
+			goto err;
+	}
 
 	ret = gpmc_cs_program_settings(cs, &gpmc_s);
 	if (ret < 0)
@@ -1859,9 +1782,7 @@ static int gpmc_probe_dt(struct platform_device *pdev)
 		if (!child->name)
 			continue;
 
-		if (of_node_cmp(child->name, "nand") == 0)
-			ret = gpmc_probe_nand_child(pdev, child);
-		else if (of_node_cmp(child->name, "onenand") == 0)
+		if (of_node_cmp(child->name, "onenand") == 0)
 			ret = gpmc_probe_onenand_child(pdev, child);
 		else
 			ret = gpmc_probe_generic_child(pdev, child);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 407aecf9..fecc054 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_mtd.h>
 
 #include <linux/mtd/nand_bch.h>
 #include <linux/platform_data/elm.h>
@@ -214,7 +215,8 @@ struct omap_nand_info {
 	u_char				*buf;
 	int					buf_len;
 	struct gpmc_nand_regs		reg;
-	/* generated at runtime depending on ECC algorithm and layout selected */
+	bool				flash_bbt;
+	/* generated at runtime depending on ECC algorithm and layout */
 	struct nand_ecclayout		oobinfo;
 	/* fields specific for BCHx_HW ECC scheme */
 	struct device			*elm_dev;
@@ -1773,10 +1775,83 @@ static void gpmc_update_nand_reg(struct omap_nand_info *info)
 	}
 }
 
+static const char * const nand_xfer_types[] = {
+	[NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled",
+	[NAND_OMAP_POLLED] = "polled",
+	[NAND_OMAP_PREFETCH_DMA] = "prefetch-dma",
+	[NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq",
+};
+
+static int omap_get_dt_info(struct device *dev, struct omap_nand_info *info)
+{
+	struct device_node *child = dev->of_node;
+	int i;
+	const char *s;
+
+	/* In old bindings, CS num is embedded in reg property */
+	if (of_property_read_u32(child, "reg", &info->gpmc_cs) < 0) {
+		dev_err(dev, "reg not found in DT\n");
+		return -EINVAL;
+	}
+
+	/* detect availability of ELM module. Won't be present pre-OMAP4 */
+	info->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
+	if (info->elm_of_node == NULL)
+		dev_dbg(dev, "ti,elm-id not in DT\n");
+
+	/* select ecc-scheme for NAND */
+	if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
+		dev_err(dev, "ti,nand-ecc-opt not found\n");
+		return -EINVAL;
+	}
+
+	if (!strcmp(s, "sw"))
+		info->ecc_opt = OMAP_ECC_HAM1_CODE_SW;
+	else if (!strcmp(s, "ham1") ||
+		 !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
+		info->ecc_opt =	OMAP_ECC_HAM1_CODE_HW;
+	else if (!strcmp(s, "bch4")) {
+		if (info->elm_of_node)
+			info->ecc_opt = OMAP_ECC_BCH4_CODE_HW;
+		else
+			info->ecc_opt = OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
+	} else if (!strcmp(s, "bch8")) {
+		if (info->elm_of_node)
+			info->ecc_opt = OMAP_ECC_BCH8_CODE_HW;
+		else
+			info->ecc_opt = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+	} else if (!strcmp(s, "bch16")) {
+		info->ecc_opt =	OMAP_ECC_BCH16_CODE_HW;
+	} else {
+		dev_err(dev, "unrecognized value for ti,nand-ecc-opt\n");
+		return -EINVAL;
+	}
+
+	/* select data transfer mode */
+	if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) {
+		for (i = 0; i < ARRAY_SIZE(nand_xfer_types); i++) {
+			if (!strcasecmp(s, nand_xfer_types[i])) {
+				info->xfer_type = i;
+				break;
+			}
+		}
+
+		dev_err(dev, "unrecognized value for ti,nand-xfer-type\n");
+		return -EINVAL;
+	}
+
+	of_get_nand_on_flash_bbt(child);
+
+	if (of_get_nand_bus_width(child) == 16)
+		info->devsize = NAND_BUSWIDTH_16;
+
+	return 0;
+}
+
 static int omap_nand_probe(struct platform_device *pdev)
 {
 	struct omap_nand_info *info;
-	struct omap_nand_platform_data *pdata;
+	struct omap_nand_platform_data *pdata = NULL;
 	struct mtd_info	*mtd;
 	struct nand_chip *nand_chip;
 	struct nand_ecclayout *ecclayout;
@@ -1789,27 +1864,35 @@ static int omap_nand_probe(struct platform_device *pdev)
 	struct mtd_part_parser_data ppdata = {};
 	struct device *dev = &pdev->dev;
 
-	pdata = dev_get_platdata(&pdev->dev);
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "platform data missing\n");
-		return -ENODEV;
-	}
 
 	info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
 				GFP_KERNEL);
 	if (!info)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, info);
+	info->pdev = pdev;
+
+	if (dev->of_node) {
+		if (omap_get_dt_info(dev, info))
+			return -EINVAL;
+	} else {
+		pdata = dev_get_platdata(&pdev->dev);
+		if (pdata == NULL) {
+			dev_err(&pdev->dev, "platform data missing\n");
+			return -EINVAL;
+		}
 
-	info->pdev		= pdev;
-	info->gpmc_cs		= pdata->cs;
-	info->of_node		= pdata->of_node;
-	info->ecc_opt		= pdata->ecc_opt;
-	info->dev_ready	= pdata->dev_ready;
-	info->xfer_type = pdata->xfer_type;
-	info->devsize = pdata->devsize;
-	info->elm_of_node = pdata->elm_of_node;
+		info->gpmc_cs = pdata->cs;
+		info->of_node = pdata->of_node;
+		info->ecc_opt = pdata->ecc_opt;
+		info->dev_ready	= pdata->dev_ready;
+		info->xfer_type = pdata->xfer_type;
+		info->devsize = pdata->devsize;
+		info->elm_of_node = pdata->elm_of_node;
+		info->flash_bbt = pdata->flash_bbt;
+	}
+
+	platform_set_drvdata(pdev, info);
 
 	mtd			= &info->mtd;
 	mtd->priv		= &info->nand;
@@ -1872,7 +1955,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 		nand_chip->chip_delay = 50;
 	}
 
-	if (pdata->flash_bbt)
+	if (info->flash_bbt)
 		nand_chip->bbt_options |= NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB;
 	else
 		nand_chip->options |= NAND_SKIP_BBTSCAN;
@@ -2180,9 +2263,13 @@ scan_tail:
 		goto return_error;
 	}
 
-	ppdata.of_node = pdata->of_node;
-	mtd_device_parse_register(mtd, NULL, &ppdata, pdata->parts,
-				  pdata->nr_parts);
+	if (dev->of_node) {
+		ppdata.of_node = dev->of_node;
+		mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
+
+	} else {
+		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
+	}
 
 	platform_set_drvdata(pdev, mtd);
 
@@ -2214,11 +2301,17 @@ static int omap_nand_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id omap_nand_ids[] = {
+	{ .compatible = "ti,omap2-nand", },
+	{},
+};
+
 static struct platform_driver omap_nand_driver = {
 	.probe		= omap_nand_probe,
 	.remove		= omap_nand_remove,
 	.driver		= {
 		.name	= DRIVER_NAME,
+		.of_match_table = of_match_ptr(omap_nand_ids),
 	},
 };
 
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index e9b16b5..733bc91e 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -78,11 +78,9 @@ struct omap_nand_platform_data {
 	enum nand_io		xfer_type;
 	int			devsize;
 	enum omap_ecc           ecc_opt;
-
-	/* for passing the partitions */
-	struct device_node	*of_node;
 	struct device_node	*elm_of_node;
 
 	struct gpmc_nand_regs	reg;		/* deprecated */
+	struct device_node	*of_node;	/* deprecated */
 };
 #endif
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 08/12] mtd: nand: omap: Update DT binding documentation
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (6 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 07/12] mtd: nand: omap: Clean up device tree support Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 09/12] memory: omap-gpmc: use module_platform_driver() Roger Quadros
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Add compatible id, interrupts and update reg property description.
As the NAND controller needs access to GPMC register space, we need
to pass a second memory resource to the NAND controller node.

Due to the weird way the reg property has been implemented (i.e.
CS number required in 1st number of reg property) we will need to
use a number outside the possible CS numbers for the GPMC register space.

As a SoC can have fewer than 10 chip selects, 255 seems like a safe
bet for the GPMC register space.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 Documentation/devicetree/bindings/mtd/gpmc-nand.txt | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
index fb733c4..3a8ebfa 100644
--- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
@@ -13,7 +13,13 @@ Documentation/devicetree/bindings/mtd/nand.txt
 
 Required properties:
 
+ - compatible:	"ti,omap2-nand"
  - reg:		The CS line the peripheral is connected to
+		Should contain 2 resource specifiers
+		- range id (CS number), base offset and length of the
+		  NAND I/O space
+		- range id,  base offset and length of the GPMC register space.
+ - interrupts:	Interrupt resource specifier for GPMC interrupt.
 
 Optional properties:
 
@@ -55,17 +61,21 @@ Example for an AM33xx board:
 	gpmc: gpmc@50000000 {
 		compatible = "ti,am3352-gpmc";
 		ti,hwmods = "gpmc";
-		reg = <0x50000000 0x1000000>;
+		reg = <0x50000000 0x36c>;
 		interrupts = <100>;
 		gpmc,num-cs = <8>;
 		gpmc,num-waitpins = <2>;
 		#address-cells = <2>;
 		#size-cells = <1>;
-		ranges = <0 0 0x08000000 0x2000>;	/* CS0: NAND */
+		ranges = <0 0 0x08000000 0x1000000	/* CS0 space, 16MB */
+			  255 0 0x50000000 0x36c>;	/* GPMC reg space */
 		elm_id = <&elm>;
 
 		nand@0,0 {
-			reg = <0 0 0>; /* CS0, offset 0 */
+			compatible = "ti,omap2-nand";
+			reg = <0 0 4		/* CS0, offset 0, NAND I/O window 4 */
+			       255 0 0x36c>;	/* GPMC reg space */
+			interrupts = <100>;
 			nand-bus-width = <16>;
 			ti,nand-ecc-opt = "bch8";
 			ti,nand-xfer-type = "polled";
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 09/12] memory: omap-gpmc: use module_platform_driver()
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (7 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 08/12] mtd: nand: omap: Update DT binding documentation Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 10/12] memory: omap-gpmc: Prevent mapping into 1st 16MB Roger Quadros
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Stop registering driver at postcore and do it
the standard way.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/memory/omap-gpmc.c | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 995e9b8..f19edc2 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -1914,19 +1914,7 @@ static struct platform_driver gpmc_driver = {
 	},
 };
 
-static __init int gpmc_init(void)
-{
-	return platform_driver_register(&gpmc_driver);
-}
-
-static __exit void gpmc_exit(void)
-{
-	platform_driver_unregister(&gpmc_driver);
-
-}
-
-postcore_initcall(gpmc_init);
-module_exit(gpmc_exit);
+module_platform_driver(gpmc_driver);
 
 static struct omap3_gpmc_regs gpmc_context;
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 10/12] memory: omap-gpmc: Prevent mapping into 1st 16MB
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (8 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 09/12] memory: omap-gpmc: use module_platform_driver() Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 11/12] ARM: dts: OMAP2+: Fix NAND device nodes Roger Quadros
  2015-07-10 12:23 ` [PATCH 12/12] ARM: dts: omap3: Fix gpmc memory resource size Roger Quadros
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

We have been preventing mapping GPMC children in the
first 1MB but really it has to be the first 16MB as
the minimum GPMC partition size is 16MB.

Also print an error message if CS mapping fails
due to DT requesting address outside the GPMC
map.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/memory/omap-gpmc.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index f19edc2..8b434fc 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -80,6 +80,14 @@
 #define GPMC_CS_SIZE		0x30
 #define	GPMC_BCH_SIZE		0x10
 
+/*
+ * The first 1MB of GPMC address space is typically mapped to
+ * the internal ROM. Never allocate the first page, to
+ * facilitate bug detection; even if we didn't boot from ROM.
+ * As GPMC minimum partition size is 16MB we can only start from
+ * there.
+ */
+#define GPMC_MEM_START		0x1000000
 #define GPMC_MEM_END		0x3FFFFFFF
 
 #define GPMC_CHUNK_SHIFT	24		/* 16 MB */
@@ -1012,12 +1020,7 @@ static void gpmc_mem_init(void)
 {
 	int cs;
 
-	/*
-	 * The first 1MB of GPMC address space is typically mapped to
-	 * the internal ROM. Never allocate the first page, to
-	 * facilitate bug detection; even if we didn't boot from ROM.
-	 */
-	gpmc_mem_root.start = SZ_1M;
+	gpmc_mem_root.start = GPMC_MEM_START;
 	gpmc_mem_root.end = GPMC_MEM_END;
 
 	/* Reserve all regions that has been set up by bootloader */
@@ -1671,6 +1674,15 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
 	if (ret < 0) {
 		dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n",
 			cs, &res.start);
+		if (res.start < GPMC_MEM_START) {
+			dev_info(&pdev->dev,
+				 "GPMC CS %d start cannot be lesser than 0x%x\n",
+				 cs, GPMC_MEM_START);
+		} else if (res.end > GPMC_MEM_END) {
+			dev_info(&pdev->dev,
+				 "GPMC CS %d end cannot be greater than 0x%x\n",
+				 cs, GPMC_MEM_END);
+		}
 		goto err;
 	}
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 11/12] ARM: dts: OMAP2+: Fix NAND device nodes
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (9 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 10/12] memory: omap-gpmc: Prevent mapping into 1st 16MB Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  2015-07-10 12:23 ` [PATCH 12/12] ARM: dts: omap3: Fix gpmc memory resource size Roger Quadros
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

Add compatible id, GPMC register resource and interrupt
resource to NAND controller nodes.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/boot/dts/am335x-baltos-ir5221.dts   |  9 +++++++--
 arch/arm/boot/dts/am335x-chilisom.dtsi       |  8 ++++++--
 arch/arm/boot/dts/am335x-evm.dts             |  8 ++++++--
 arch/arm/boot/dts/am335x-igep0033.dtsi       |  8 ++++++--
 arch/arm/boot/dts/am437x-gp-evm.dts          |  8 ++++++--
 arch/arm/boot/dts/am43x-epos-evm.dts         |  8 ++++++--
 arch/arm/boot/dts/dm8168-evm.dts             |  8 ++++++--
 arch/arm/boot/dts/dra7-evm.dts               |  8 ++++++--
 arch/arm/boot/dts/dra72-evm.dts              |  8 ++++++--
 arch/arm/boot/dts/logicpd-torpedo-som.dtsi   |  9 +++++++--
 arch/arm/boot/dts/omap3-beagle.dts           |  7 +++++--
 arch/arm/boot/dts/omap3-cm-t3x.dtsi          |  8 ++++++--
 arch/arm/boot/dts/omap3-devkit8000.dts       |  9 +++++++--
 arch/arm/boot/dts/omap3-evm-37xx.dts         | 10 +++++++---
 arch/arm/boot/dts/omap3-gta04.dtsi           |  8 ++++++--
 arch/arm/boot/dts/omap3-igep.dtsi            |  5 ++++-
 arch/arm/boot/dts/omap3-igep0020-common.dtsi |  5 +++--
 arch/arm/boot/dts/omap3-igep0030-common.dtsi |  6 ++++++
 arch/arm/boot/dts/omap3-ldp.dts              | 10 +++++++---
 arch/arm/boot/dts/omap3-lilly-a83x.dtsi      |  8 ++++++--
 arch/arm/boot/dts/omap3-lilly-dbb056.dts     |  7 ++++---
 arch/arm/boot/dts/omap3-pandora-common.dtsi  |  8 ++++++--
 arch/arm/boot/dts/omap3-tao3530.dtsi         |  8 ++++++--
 arch/arm/boot/dts/omap3430-sdp.dts           |  8 ++++++--
 24 files changed, 141 insertions(+), 48 deletions(-)

diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
index 7d36601..9a504dd 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
@@ -236,11 +236,16 @@
 &gpmc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&nandflash_pins_s0>;
-	ranges = <0 0 0x08000000 0x10000000>;	/* CS0: NAND */
+	ranges = <0 0 0x08000000 0x10000000>,	/* CS0: NAND */
+		 <255 0 0x50000000 0x36c>;	/* GPMC reg */
+
 	status = "okay";
 
 	nand@0,0 {
-		reg = <0 0 0>; /* CS0, offset 0 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x36c>;	/* GPMC reg */
+		interrupts = <100>;
 		nand-bus-width = <8>;
 		ti,nand-ecc-opt = "bch8";
 		ti,nand-xfer-type = "polled";
diff --git a/arch/arm/boot/dts/am335x-chilisom.dtsi b/arch/arm/boot/dts/am335x-chilisom.dtsi
index 7e9a34d..e7a82ea 100644
--- a/arch/arm/boot/dts/am335x-chilisom.dtsi
+++ b/arch/arm/boot/dts/am335x-chilisom.dtsi
@@ -206,9 +206,13 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&nandflash_pins>;
-	ranges = <0 0 0x08000000 0x01000000>; /* CS0 0 @addr 0x08000000, size 0x01000000 */
+	ranges = <0 0 0x08000000 0x01000000>,	/* CS0 0 @addr 0x08000000, size 0x01000000 */
+		 <255 0 0x50000000 0x36c>;	/* GPMC reg */
 	nand@0,0 {
-		reg = <0 0 4>;	/* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x36c>;	/* GPMC reg */
+		interrupts = <100>;
 		ti,nand-ecc-opt = "bch8";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 765be27..11d536c 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -494,9 +494,13 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&nandflash_pins_s0>;
-	ranges = <0 0 0x08000000 0x1000000>;	/* CS0: 16MB for NAND */
+	ranges = <0 0 0x08000000 0x1000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x50000000 0x36c>;	/* GPMC reg */
 	nand@0,0 {
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x36c>;	/* GPMC reg */
+		interrupts = <100>;
 		ti,nand-ecc-opt = "bch8";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/am335x-igep0033.dtsi
index c0e1135..6197dc6 100644
--- a/arch/arm/boot/dts/am335x-igep0033.dtsi
+++ b/arch/arm/boot/dts/am335x-igep0033.dtsi
@@ -126,10 +126,14 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&nandflash_pins>;
 
-	ranges = <0 0 0x08000000 0x1000000>;	/* CS0: 16MB for NAND */
+	ranges = <0 0 0x08000000 0x1000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x50000000 0x36c>;	/* GPMC reg */
 
 	nand@0,0 {
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x36c>;	/* GPMC reg */
+		interrupts = <100>;
 		nand-bus-width = <8>;
 		ti,nand-ecc-opt = "bch8";
 		gpmc,device-width = <1>;
diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index 84aa30c..542c42e 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -654,9 +654,13 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&nand_flash_x8>;
-	ranges = <0 0 0 0x01000000>;	/* minimum GPMC partition = 16MB */
+	ranges = <0 0 0x08000000 0x01000000>,	/* CS0 space. Min partition = 16MB */
+		 <255 0 0x50000000 0x36c>;	/* GPMC reg */
 	nand@0,0 {
-		reg = <0 0 4>;		/* device IO registers */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, I/O window 4 bytes */
+		      <255 0 0x400>;	/* GPMC reg */
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
 		ti,nand-ecc-opt = "bch16";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index 795d68a..0b9336b 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -473,9 +473,13 @@
 	status = "okay";	/* Disable QSPI when enabling GPMC (NAND) */
 	pinctrl-names = "default";
 	pinctrl-0 = <&nand_flash_x8>;
-	ranges = <0 0 0x08000000 0x1000000>;	/* CS0: 16MB for NAND */
+	ranges = <0 0 0x08000000 0x1000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x50000000 0x36c>;	/* GPMC reg */
 	nand@0,0 {
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x36c>;	/* GPMC reg */
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
 		ti,nand-ecc-opt = "bch16";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <8>;
diff --git a/arch/arm/boot/dts/dm8168-evm.dts b/arch/arm/boot/dts/dm8168-evm.dts
index 169a855..b7acb37 100644
--- a/arch/arm/boot/dts/dm8168-evm.dts
+++ b/arch/arm/boot/dts/dm8168-evm.dts
@@ -82,11 +82,15 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x04000000 0x01000000>;	/* CS0: 16MB for NAND */
+	ranges = <0 0 0x04000000 0x01000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x6e000000 0x02d4>;	/* register space */
 
 	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC register space */
+		interrupts = <100>;
 		linux,mtd-name= "micron,mt29f2g16aadwp";
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index aa46590..f520987 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -569,9 +569,13 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&nand_flash_x16>;
-	ranges = <0 0 0 0x01000000>;	/* minimum GPMC partition = 16MB */
+	ranges = <0 0 0x08000000 0x01000000>,	/* minimum GPMC partition = 16MB */
+		 <255 0 0x50000000 0x37c>;	/* GPMC reg */
 	nand@0,0 {
-		reg = <0 0 4>;		/* device IO registers */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* device IO registers */
+		      <255 0 0x37c>;	/* GPMC reg */
+		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
 		ti,nand-ecc-opt = "bch8";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <16>;
diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts
index 4e1b605..10975a4 100644
--- a/arch/arm/boot/dts/dra72-evm.dts
+++ b/arch/arm/boot/dts/dra72-evm.dts
@@ -379,13 +379,17 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&nand_default>;
-	ranges = <0 0 0 0x01000000>;	/* minimum GPMC partition = 16MB */
+	ranges = <0 0 0x08000000 0x01000000>,	/* minimum GPMC partition = 16MB */
+		 <255 0 0x50000000 0x37c>;	/* GPMC reg */
 	nand@0,0 {
 		/* To use NAND, DIP switch SW5 must be set like so:
 		 * SW5.1 (NAND_SELn) = ON (LOW)
 		 * SW5.9 (GPMC_WPN) = OFF (HIGH)
 		 */
-		reg = <0 0 4>;		/* device IO registers */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* device IO registers */
+		      <255 0 0x37c>;	/* GPMC reg */
+		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
 		ti,nand-ecc-opt = "bch8";
 		ti,elm-id = <&elm>;
 		nand-bus-width = <16>;
diff --git a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
index 36387b1..c66ff60 100644
--- a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
+++ b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
@@ -35,11 +35,16 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x00000000 0x1000000>;	/* CS0: 16MB for NAND */
+	ranges = <0 0 0x08000000 0x1000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x6e000000 0x02d4>;	/* register space */
+
 
 	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC register space */
+		interrupts = <20>;
 		linux,mtd-name = "micron,mt29f4g16abbda3w";
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
 		nand-bus-width = <16>;
 		ti,nand-ecc-opt = "bch8";
 		gpmc,sync-clk-ps = <0>;
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
index a547411..4619490 100644
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -380,11 +380,14 @@
 
 &gpmc {
 	status = "ok";
-	ranges = <0 0 0x30000000 0x1000000>;	/* CS0 space, 16MB */
+	ranges = <0 0 0x30000000 0x1000000>,	/* CS0 space, 16MB */
+		 <255 0 0x6e000000 0x02d4>;	/* register space */
 
 	/* Chip select 0 */
 	nand@0,0 {
-		reg = <0 0 4>;		/* NAND I/O window, 4 bytes */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC register space */
 		interrupts = <20>;
 		ti,nand-ecc-opt = "ham1";
 		nand-bus-width = <16>;
diff --git a/arch/arm/boot/dts/omap3-cm-t3x.dtsi b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
index 4d091ca..b16f811 100644
--- a/arch/arm/boot/dts/omap3-cm-t3x.dtsi
+++ b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
@@ -261,10 +261,14 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x00000000 0x01000000>;
+	ranges = <0 0 0x30000000 0x01000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x6e000000 0x02d4>;	/* register space */
 
 	nand@0,0 {
-		reg = <0 0 4>;	/* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC register space */
+		interrupts = <20>;
 		nand-bus-width = <8>;
 		gpmc,device-width = <1>;
 		ti,nand-ecc-opt = "sw";
diff --git a/arch/arm/boot/dts/omap3-devkit8000.dts b/arch/arm/boot/dts/omap3-devkit8000.dts
index be22971..6f7a9fd 100644
--- a/arch/arm/boot/dts/omap3-devkit8000.dts
+++ b/arch/arm/boot/dts/omap3-devkit8000.dts
@@ -105,10 +105,15 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x30000000 0x1000000>;       /* CS0: 16MB for NAND */
+	ranges = <0 0 0x30000000 0x1000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x6e000000 0x02d4>;	/* register space */
 
+	/* Chip select 0 */
 	nand@0,0 {
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC register space */
+		interrupts = <20>;
 		nand-bus-width = <16>;
 		gpmc,device-width = <2>;
 		ti,nand-ecc-opt = "sw";
diff --git a/arch/arm/boot/dts/omap3-evm-37xx.dts b/arch/arm/boot/dts/omap3-evm-37xx.dts
index 16e8ce3..1840eb5 100644
--- a/arch/arm/boot/dts/omap3-evm-37xx.dts
+++ b/arch/arm/boot/dts/omap3-evm-37xx.dts
@@ -154,12 +154,16 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x00000000 0x1000000>,	/* CS0: 16MB for NAND */
-		 <5 0 0x2c000000 0x01000000>;
+	ranges = <0 0 0x30000000 0x1000000>,	/* CS0: 16MB for NAND */
+		 <5 0 0x2c000000 0x1000000>,	/* CS5: 16MB for ethernet */
+		 <255 0 0x6e000000 0x02d4>;	/* GPMC reg */
 
 	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC reg */
+		interrupts = <20>;
 		linux,mtd-name= "hynix,h8kds0un0mer-4em";
-		reg = <0 0 4>;	/* CS0, offset 0, IO size 4 */
 		nand-bus-width = <16>;
 		gpmc,device-width = <2>;
 		ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index 7166d88..bbab05a 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -489,10 +489,14 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x30000000 0x1000000>; /* CS0: 16MB for NAND */
+	ranges = <0 0 0x30000000 0x1000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x6e000000 0x02d4>;	/* register space */
 
 	nand@0,0 {
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC register space */
+		interrupts = <20>;
 		nand-bus-width = <16>;
 		ti,nand-ecc-opt = "bch8";
 
diff --git a/arch/arm/boot/dts/omap3-igep.dtsi b/arch/arm/boot/dts/omap3-igep.dtsi
index d5e5cd4..50be7f8 100644
--- a/arch/arm/boot/dts/omap3-igep.dtsi
+++ b/arch/arm/boot/dts/omap3-igep.dtsi
@@ -101,8 +101,11 @@
 
 &gpmc {
 	nand@0,0 {
+		compatible = "ti,omap2-nand";
 		linux,mtd-name= "micron,mt29c4g96maz";
-		reg = <0 0 4>;	/* CS0, offset 0, IO size 4 */
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;   /* GPMC reg */
+		interrupts = <20>;
 		nand-bus-width = <16>;
 		gpmc,device-width = <2>;
 		ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/omap3-igep0020-common.dtsi b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
index e458c21..fad69b5 100644
--- a/arch/arm/boot/dts/omap3-igep0020-common.dtsi
+++ b/arch/arm/boot/dts/omap3-igep0020-common.dtsi
@@ -204,8 +204,9 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x00000000 0x20000000>,
-		 <5 0 0x2c000000 0x01000000>;
+	ranges = <0 0 0x30000000 0x01000000>,	/* CS0: 16MB for NAND */
+		 <5 0 0x2c000000 0x01000000>,	/* CS5: 16MB for ethernet */
+		 <255 0 0x6e000000 0x02d4>;     /* GPMC reg */
 
 	ethernet@gpmc {
 		pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/omap3-igep0030-common.dtsi b/arch/arm/boot/dts/omap3-igep0030-common.dtsi
index 0cb1527..8f8685f 100644
--- a/arch/arm/boot/dts/omap3-igep0030-common.dtsi
+++ b/arch/arm/boot/dts/omap3-igep0030-common.dtsi
@@ -58,3 +58,9 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart2_pins>;
 };
+
+&gpmc {
+	ranges = <0 0 0x30000000 0x01000000>,   /* CS0: 16MB for NAND */
+		 <255 0 0x6e000000 0x02d4>;     /* GPMC reg */
+
+};
diff --git a/arch/arm/boot/dts/omap3-ldp.dts b/arch/arm/boot/dts/omap3-ldp.dts
index bd6e676..a1555d8 100644
--- a/arch/arm/boot/dts/omap3-ldp.dts
+++ b/arch/arm/boot/dts/omap3-ldp.dts
@@ -97,12 +97,16 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x00000000 0x01000000>,
-		 <1 0 0x08000000 0x01000000>;
+	ranges = <0 0 0x30000000 0x1000000>,	/* CS0 space, 16MB */
+		 <1 0 0x08000000 0x1000000>,	/* CS1 space, 16MB */
+		 <255 0 0x6e000000 0x02d4>;	/* GPMC reg */
 
 	nand@0,0 {
+		compatible = "ti,omap2-nand";
+		interrupts = <20>;
 		linux,mtd-name= "micron,nand";
-		reg = <0 0 4>;	/* CS0, offset 0, IO size 4 */
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC reg */
 		nand-bus-width = <16>;
 		gpmc,device-width = <2>;
 		ti,nand-ecc-opt = "bch8";
diff --git a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
index e631333..71c8c34 100644
--- a/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
+++ b/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
@@ -359,10 +359,14 @@
 
 &gpmc {
 	ranges = <0 0 0x30000000 0x1000000>,
-		<7 0 0x15000000 0x01000000>;
+		 <7 0 0x15000000 0x1000000>,
+		 <255 0 0x6e000000 0x02d4>;	/* GPMC reg */
 
 	nand@0,0 {
-		reg = <0 0 4>;	/* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC reg */
+		interrupts = <20>;
 		nand-bus-width = <16>;
 		ti,nand-ecc-opt = "bch8";
 		/* no elm on omap3 */
diff --git a/arch/arm/boot/dts/omap3-lilly-dbb056.dts b/arch/arm/boot/dts/omap3-lilly-dbb056.dts
index 834f7c6..80b19a1 100644
--- a/arch/arm/boot/dts/omap3-lilly-dbb056.dts
+++ b/arch/arm/boot/dts/omap3-lilly-dbb056.dts
@@ -128,9 +128,10 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x30000000 0x1000000>,   /* nand assigned by COM a83x */
-		<4 0 0x20000000 0x01000000>,
-		<7 0 0x15000000 0x01000000>;   /* eth assigend by COM a83x */
+	ranges = <0 0 0x30000000 0x1000000>,	/* nand assigned by COM a83x */
+		 <4 0 0x20000000 0x1000000>,
+		 <7 0 0x15000000 0x1000000>,	/* eth assigend by COM a83x */
+		 <255 0 0x6e000000 0x02d4>;	/* GPMC reg */
 
 	ethernet@4,0 {
 		compatible = "smsc,lan9117", "smsc,lan9115";
diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/omap3-pandora-common.dtsi
index 782ab1f..320b240 100644
--- a/arch/arm/boot/dts/omap3-pandora-common.dtsi
+++ b/arch/arm/boot/dts/omap3-pandora-common.dtsi
@@ -497,10 +497,14 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x30000000 0x1000000>; /* CS0: 16MB for NAND */
+	ranges = <0 0 0x30000000 0x1000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x6e000000 0x02d4>;	/* register space */
 
 	nand@0,0 {
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC register space */
+		interrupts = <20>;
 		nand-bus-width = <16>;
 		ti,nand-ecc-opt = "sw";
 
diff --git a/arch/arm/boot/dts/omap3-tao3530.dtsi b/arch/arm/boot/dts/omap3-tao3530.dtsi
index 7bd8d9a..0332638 100644
--- a/arch/arm/boot/dts/omap3-tao3530.dtsi
+++ b/arch/arm/boot/dts/omap3-tao3530.dtsi
@@ -275,10 +275,14 @@
 };
 
 &gpmc {
-	ranges = <0 0 0x00000000 0x01000000>;
+	ranges = <0 0 0x30000000 0x01000000>,	/* CS0: 16MB for NAND */
+		 <255 0 0x6e000000 0x02d4>;	/* register space */
 
 	nand@0,0 {
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		compatible = "ti,omap2-nand";
+		reg = <0 0 4>,		/* CS0, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC register space */
+		interrupts = <20>;
 		nand-bus-width = <16>;
 		gpmc,device-width = <2>;	/* GPMC_DEVWIDTH_16BIT */
 		ti,nand-ecc-opt = "sw";
diff --git a/arch/arm/boot/dts/omap3430-sdp.dts b/arch/arm/boot/dts/omap3430-sdp.dts
index 16b0cdf..4389d4b 100644
--- a/arch/arm/boot/dts/omap3430-sdp.dts
+++ b/arch/arm/boot/dts/omap3430-sdp.dts
@@ -52,7 +52,8 @@
 &gpmc {
 	ranges = <0 0 0x10000000 0x08000000>,
 		 <1 0 0x28000000 0x1000000>,	/* CS1: 16MB for NAND */
-		 <2 0 0x20000000 0x1000000>;	/* CS2: 16MB for OneNAND */
+		 <2 0 0x20000000 0x1000000>,	/* CS2: 16MB for OneNAND */
+		 <255 0 0x6e000000 0x02d4>;	/* GPMC reg */
 
 	nor@0,0 {
 		compatible = "cfi-flash";
@@ -103,10 +104,13 @@
 	};
 
 	nand@1,0 {
+		compatible = "ti,omap2-nand";
+		interrupts = <20>;
 		linux,mtd-name= "micron,mt29f1g08abb";
 		#address-cells = <1>;
 		#size-cells = <1>;
-		reg = <1 0 4>;	/* CS1, offset 0, IO size 4 */
+		reg = <1 0 4>,		/* CS1, offset 0, IO size 4 */
+		      <255 0 0x02d4>;	/* GPMC reg */
 		ti,nand-ecc-opt = "sw";
 		nand-bus-width = <8>;
 		gpmc,cs-on-ns = <0>;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 12/12] ARM: dts: omap3: Fix gpmc memory resource size
  2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
                   ` (10 preceding siblings ...)
  2015-07-10 12:23 ` [PATCH 11/12] ARM: dts: OMAP2+: Fix NAND device nodes Roger Quadros
@ 2015-07-10 12:23 ` Roger Quadros
  11 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-10 12:23 UTC (permalink / raw)
  To: tony, dwmw2, computersforpeace, bcousson
  Cc: ezequiel, linux-mtd, linux-omap, devicetree, linux-kernel, Roger Quadros

The last register address is offset at 0x2d0 but is a
4 bit register. So total GPMC register resource size
is 0x2d4

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/boot/dts/omap3.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 69a40cf..f9623f7 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -714,7 +714,7 @@
 		gpmc: gpmc@6e000000 {
 			compatible = "ti,omap3430-gpmc";
 			ti,hwmods = "gpmc";
-			reg = <0x6e000000 0x02d0>;
+			reg = <0x6e000000 0x02d4>;
 			interrupts = <20>;
 			gpmc,num-cs = <8>;
 			gpmc,num-waitpins = <4>;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
  2015-07-10 12:23 ` [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver Roger Quadros
@ 2015-07-13  7:10   ` Tony Lindgren
  2015-07-13 10:04     ` Roger Quadros
  0 siblings, 1 reply; 28+ messages in thread
From: Tony Lindgren @ 2015-07-13  7:10 UTC (permalink / raw)
  To: Roger Quadros
  Cc: dwmw2, computersforpeace, bcousson, ezequiel, linux-mtd,
	linux-omap, devicetree, linux-kernel

* Roger Quadros <rogerq@ti.com> [150710 05:26]:
> Since the Interrupt Events are used only by the NAND driver,
> there is no point in managing the Interrupt registers
> in the GPMC driver and complicating it with irqchip modeling.

I don't think it's a good idea to allow external drivers to
tinker directly with GPMC registers. How about just set up GPMC
as an irqchip for the edge detection interrupts?

I think we already have devices with multiple NAND chips. And
there's nothing stopping other drivers from using the edge
detection interrupts.

Regards,

Tony

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
  2015-07-13  7:10   ` Tony Lindgren
@ 2015-07-13 10:04     ` Roger Quadros
  2015-07-13 12:40       ` Tony Lindgren
  0 siblings, 1 reply; 28+ messages in thread
From: Roger Quadros @ 2015-07-13 10:04 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: dwmw2, computersforpeace, bcousson, ezequiel, linux-mtd,
	linux-omap, devicetree, linux-kernel

Tony,

On 13/07/15 10:10, Tony Lindgren wrote:
> * Roger Quadros <rogerq@ti.com> [150710 05:26]:
>> Since the Interrupt Events are used only by the NAND driver,
>> there is no point in managing the Interrupt registers
>> in the GPMC driver and complicating it with irqchip modeling.
> 
> I don't think it's a good idea to allow external drivers to
> tinker directly with GPMC registers. How about just set up GPMC
> as an irqchip for the edge detection interrupts?
> 
> I think we already have devices with multiple NAND chips. And
> there's nothing stopping other drivers from using the edge
> detection interrupts.

OK. The GPMC_IRQ registers manage 2 NAND specific interrupts
(terminalcount and fifo) and 'n' WAIT pin edge interrupts.

So we can model this as a irqchip with 'n + 2' interrupts.

We need to take care that if a GPMC chip select needs a
wait pin then it can't be used as a generic interrupt.

We need to get rid of omap_dev_ready() in nand/omap2.c as
it accesses the GPMC_STATUS register directly. Plus it is
hard coded to only monitor wait0 pin.

What is the best map we should use for irqchip?
Some Socs have 4 WAIT pins, some have 3 and some have 2.

Should we start with 0,1,2, for the wait pins and use the next
available free one for the NAND?

cheers,
-roger

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
  2015-07-13 10:04     ` Roger Quadros
@ 2015-07-13 12:40       ` Tony Lindgren
       [not found]         ` <55A3B467.8030409@gmail.com>
  2015-07-29 12:06         ` Roger Quadros
  0 siblings, 2 replies; 28+ messages in thread
From: Tony Lindgren @ 2015-07-13 12:40 UTC (permalink / raw)
  To: Roger Quadros
  Cc: dwmw2, computersforpeace, bcousson, ezequiel, linux-mtd,
	linux-omap, devicetree, linux-kernel

* Roger Quadros <rogerq@ti.com> [150713 03:07]:
> Tony,
> 
> On 13/07/15 10:10, Tony Lindgren wrote:
> > * Roger Quadros <rogerq@ti.com> [150710 05:26]:
> >> Since the Interrupt Events are used only by the NAND driver,
> >> there is no point in managing the Interrupt registers
> >> in the GPMC driver and complicating it with irqchip modeling.
> > 
> > I don't think it's a good idea to allow external drivers to
> > tinker directly with GPMC registers. How about just set up GPMC
> > as an irqchip for the edge detection interrupts?
> > 
> > I think we already have devices with multiple NAND chips. And
> > there's nothing stopping other drivers from using the edge
> > detection interrupts.
> 
> OK. The GPMC_IRQ registers manage 2 NAND specific interrupts
> (terminalcount and fifo) and 'n' WAIT pin edge interrupts.
> 
>  So we can model this as a irqchip with 'n + 2' interrupts.

OK
 
> We need to take care that if a GPMC chip select needs a
> wait pin then it can't be used as a generic interrupt.
> 
> We need to get rid of omap_dev_ready() in nand/omap2.c as
> it accesses the GPMC_STATUS register directly. Plus it is
> hard coded to only monitor wait0 pin.

OK
 
> What is the best map we should use for irqchip?
> Some Socs have 4 WAIT pins, some have 3 and some have 2.
> 
> Should we start with 0,1,2, for the wait pins and use the next
> available free one for the NAND?

Maybe we can just use the bits defined for each SoC in the
GPMC_IRQSTATUS register for the mapping?  
Regards,

Tony

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
       [not found]         ` <55A3B467.8030409@gmail.com>
@ 2015-07-13 13:01           ` Tony Lindgren
       [not found]             ` <55A3B73C.9040604@gmail.com>
  0 siblings, 1 reply; 28+ messages in thread
From: Tony Lindgren @ 2015-07-13 13:01 UTC (permalink / raw)
  To: nick
  Cc: Roger Quadros, devicetree, computersforpeace, linux-kernel,
	linux-mtd, ezequiel, bcousson, linux-omap, dwmw2

* nick <xerofoify@gmail.com> [150713 05:54]:
> On 2015-07-13 08:40 AM, Tony Lindgren wrote:
> > * Roger Quadros <rogerq@ti.com> [150713 03:07]:
> >  
> >> What is the best map we should use for irqchip?
> >> Some Socs have 4 WAIT pins, some have 3 and some have 2.
> >>
> >> Should we start with 0,1,2, for the wait pins and use the next
> >> available free one for the NAND?
> > 
> > Maybe we can just use the bits defined for each SoC in the
> > GPMC_IRQSTATUS register for the mapping?  
> > Regards,
>
> Is that a good idea as to my knowledge of OMAP platforms that register is hardware
> dependent and therefore that may be an issue unless your idea is to create device
> tables like the way they do in the nand subsystems to support various vendor's 
> nand flash expect here for the pins on OMAP SOCs.

Do you mean mapping irqs based on the GPMC_IRQSTATUS register
bits? If so, that's pretty much how all the GPIO drivers
handle them. We can have a SoC specific irqmask of the valid
bits passed from the dts files, and if necessary we can also
add custom SoC specific IRQ handlers to the GPMC driver if
needed.

The idea is that the NAND driver can just request the irq
from the GPMC driver and do whatever it wants with the
interrupt.

Regards,

Tony

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
       [not found]             ` <55A3B73C.9040604@gmail.com>
@ 2015-07-13 13:12               ` Roger Quadros
       [not found]                 ` <55A3B9DD.60705@gmail.com>
  0 siblings, 1 reply; 28+ messages in thread
From: Roger Quadros @ 2015-07-13 13:12 UTC (permalink / raw)
  To: nick, Tony Lindgren
  Cc: devicetree, computersforpeace, linux-kernel, linux-mtd, ezequiel,
	bcousson, linux-omap, dwmw2

On 13/07/15 16:03, nick wrote:
> 
> 
> On 2015-07-13 09:01 AM, Tony Lindgren wrote:
>> * nick <xerofoify@gmail.com> [150713 05:54]:
>>> On 2015-07-13 08:40 AM, Tony Lindgren wrote:
>>>> * Roger Quadros <rogerq@ti.com> [150713 03:07]:
>>>>  
>>>>> What is the best map we should use for irqchip?
>>>>> Some Socs have 4 WAIT pins, some have 3 and some have 2.
>>>>>
>>>>> Should we start with 0,1,2, for the wait pins and use the next
>>>>> available free one for the NAND?
>>>>
>>>> Maybe we can just use the bits defined for each SoC in the
>>>> GPMC_IRQSTATUS register for the mapping?  
>>>> Regards,
>>>
>>> Is that a good idea as to my knowledge of OMAP platforms that register is hardware
>>> dependent and therefore that may be an issue unless your idea is to create device
>>> tables like the way they do in the nand subsystems to support various vendor's 
>>> nand flash expect here for the pins on OMAP SOCs.
>>
>> Do you mean mapping irqs based on the GPMC_IRQSTATUS register
>> bits? If so, that's pretty much how all the GPIO drivers
>> handle them. We can have a SoC specific irqmask of the valid
>> bits passed from the dts files, and if necessary we can also
>> add custom SoC specific IRQ handlers to the GPMC driver if
>> needed.
>>
>> The idea is that the NAND driver can just request the irq
>> from the GPMC driver and do whatever it wants with the
>> interrupt.
>>
>> Regards,
>>
>> Tony
>>
> Tony,
> That is what I was hoping the code was doing. So what appears to be the problem with the 
> patches related to irq requesting from the GPMC driver.
> Cheers,
> Nick 
> 

The problem with this patch is that it expects GPMC_IRQ registers
to be accessible by the NAND driver and looses the 2 to 4 pins
of WAIT pin edge detection interrupt capability if it is needed
for generic use. (not NAND/GPMC memory specific)

cheers,
-roger

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
       [not found]                 ` <55A3B9DD.60705@gmail.com>
@ 2015-07-13 13:21                   ` Roger Quadros
       [not found]                     ` <55A3BDE3.2080004@gmail.com>
  0 siblings, 1 reply; 28+ messages in thread
From: Roger Quadros @ 2015-07-13 13:21 UTC (permalink / raw)
  To: nick, Tony Lindgren
  Cc: devicetree, computersforpeace, linux-kernel, linux-mtd, ezequiel,
	bcousson, linux-omap, dwmw2

On 13/07/15 16:15, nick wrote:
> 
> 
> On 2015-07-13 09:12 AM, Roger Quadros wrote:
>> On 13/07/15 16:03, nick wrote:
>>>
>>>
>>> On 2015-07-13 09:01 AM, Tony Lindgren wrote:
>>>> * nick <xerofoify@gmail.com> [150713 05:54]:
>>>>> On 2015-07-13 08:40 AM, Tony Lindgren wrote:
>>>>>> * Roger Quadros <rogerq@ti.com> [150713 03:07]:
>>>>>>  
>>>>>>> What is the best map we should use for irqchip?
>>>>>>> Some Socs have 4 WAIT pins, some have 3 and some have 2.
>>>>>>>
>>>>>>> Should we start with 0,1,2, for the wait pins and use the next
>>>>>>> available free one for the NAND?
>>>>>>
>>>>>> Maybe we can just use the bits defined for each SoC in the
>>>>>> GPMC_IRQSTATUS register for the mapping?  
>>>>>> Regards,
>>>>>
>>>>> Is that a good idea as to my knowledge of OMAP platforms that register is hardware
>>>>> dependent and therefore that may be an issue unless your idea is to create device
>>>>> tables like the way they do in the nand subsystems to support various vendor's 
>>>>> nand flash expect here for the pins on OMAP SOCs.
>>>>
>>>> Do you mean mapping irqs based on the GPMC_IRQSTATUS register
>>>> bits? If so, that's pretty much how all the GPIO drivers
>>>> handle them. We can have a SoC specific irqmask of the valid
>>>> bits passed from the dts files, and if necessary we can also
>>>> add custom SoC specific IRQ handlers to the GPMC driver if
>>>> needed.
>>>>
>>>> The idea is that the NAND driver can just request the irq
>>>> from the GPMC driver and do whatever it wants with the
>>>> interrupt.
>>>>
>>>> Regards,
>>>>
>>>> Tony
>>>>
>>> Tony,
>>> That is what I was hoping the code was doing. So what appears to be the problem with the 
>>> patches related to irq requesting from the GPMC driver.
>>> Cheers,
>>> Nick 
>>>
>>
>> The problem with this patch is that it expects GPMC_IRQ registers
>> to be accessible by the NAND driver and looses the 2 to 4 pins
>> of WAIT pin edge detection interrupt capability if it is needed
>> for generic use. (not NAND/GPMC memory specific)
>>
>> cheers,
>> -roger
>>
> I am not sure if this is possible with OMAP boards but can we split the pins
> into 1 or 2 for NAND/GPMC memory specific and use the others for WAIT interrupt
> capability.
> Nick
> 
Yes if the wait pins are not used for NAND/GPMC memory then they can be used
as generic edge detect interrupt or probably even a GPI.
I don't see what would prevent it.

I'm not sure if anyone will dare to use them though as they weren't originally meant
for that use and none of the existing kernels support that. So it is really a
chicken and egg situation here. :)

But I see value in doing it the way Tony says cause it is much cleaner to specify
which interrupt (or wait pin) you want for NAND use.

cheers,
-roger

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 02/12] ARM: OMAP2+: gpmc: Add gpmc timings and settings to platform data
  2015-07-10 12:23 ` [PATCH 02/12] ARM: OMAP2+: gpmc: Add gpmc timings and settings to " Roger Quadros
@ 2015-07-13 13:31   ` Tony Lindgren
  2015-07-13 13:34     ` Roger Quadros
  0 siblings, 1 reply; 28+ messages in thread
From: Tony Lindgren @ 2015-07-13 13:31 UTC (permalink / raw)
  To: Roger Quadros
  Cc: dwmw2, computersforpeace, bcousson, ezequiel, linux-mtd,
	linux-omap, devicetree, linux-kernel

* Roger Quadros <rogerq@ti.com> [150710 05:26]:
> Add device_timings, gpmc_timings and gpmc_setting to
> gpmc platform data.

Move timings to platform data instead of add them?

Regards,

Tony

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 02/12] ARM: OMAP2+: gpmc: Add gpmc timings and settings to platform data
  2015-07-13 13:31   ` Tony Lindgren
@ 2015-07-13 13:34     ` Roger Quadros
  0 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-13 13:34 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: devicetree, computersforpeace, linux-kernel, linux-mtd, ezequiel,
	bcousson, linux-omap, dwmw2

On 13/07/15 16:31, Tony Lindgren wrote:
> * Roger Quadros <rogerq@ti.com> [150710 05:26]:
>> Add device_timings, gpmc_timings and gpmc_setting to
>> gpmc platform data.
> 
> Move timings to platform data instead of add them?

Will update it.

cheers,
-roger

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
       [not found]                     ` <55A3BDE3.2080004@gmail.com>
@ 2015-07-13 13:35                       ` Roger Quadros
  0 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-13 13:35 UTC (permalink / raw)
  To: nick, Tony Lindgren
  Cc: devicetree, computersforpeace, linux-kernel, linux-mtd, ezequiel,
	bcousson, linux-omap, dwmw2

On 13/07/15 16:32, nick wrote:
> 
> 
> On 2015-07-13 09:21 AM, Roger Quadros wrote:
>> On 13/07/15 16:15, nick wrote:
>>>
>>>
>>> On 2015-07-13 09:12 AM, Roger Quadros wrote:
>>>> On 13/07/15 16:03, nick wrote:
>>>>>
>>>>>
>>>>> On 2015-07-13 09:01 AM, Tony Lindgren wrote:
>>>>>> * nick <xerofoify@gmail.com> [150713 05:54]:
>>>>>>> On 2015-07-13 08:40 AM, Tony Lindgren wrote:
>>>>>>>> * Roger Quadros <rogerq@ti.com> [150713 03:07]:
>>>>>>>>  
>>>>>>>>> What is the best map we should use for irqchip?
>>>>>>>>> Some Socs have 4 WAIT pins, some have 3 and some have 2.
>>>>>>>>>
>>>>>>>>> Should we start with 0,1,2, for the wait pins and use the next
>>>>>>>>> available free one for the NAND?
>>>>>>>>
>>>>>>>> Maybe we can just use the bits defined for each SoC in the
>>>>>>>> GPMC_IRQSTATUS register for the mapping?  
>>>>>>>> Regards,
>>>>>>>
>>>>>>> Is that a good idea as to my knowledge of OMAP platforms that register is hardware
>>>>>>> dependent and therefore that may be an issue unless your idea is to create device
>>>>>>> tables like the way they do in the nand subsystems to support various vendor's 
>>>>>>> nand flash expect here for the pins on OMAP SOCs.
>>>>>>
>>>>>> Do you mean mapping irqs based on the GPMC_IRQSTATUS register
>>>>>> bits? If so, that's pretty much how all the GPIO drivers
>>>>>> handle them. We can have a SoC specific irqmask of the valid
>>>>>> bits passed from the dts files, and if necessary we can also
>>>>>> add custom SoC specific IRQ handlers to the GPMC driver if
>>>>>> needed.
>>>>>>
>>>>>> The idea is that the NAND driver can just request the irq
>>>>>> from the GPMC driver and do whatever it wants with the
>>>>>> interrupt.
>>>>>>
>>>>>> Regards,
>>>>>>
>>>>>> Tony
>>>>>>
>>>>> Tony,
>>>>> That is what I was hoping the code was doing. So what appears to be the problem with the 
>>>>> patches related to irq requesting from the GPMC driver.
>>>>> Cheers,
>>>>> Nick 
>>>>>
>>>>
>>>> The problem with this patch is that it expects GPMC_IRQ registers
>>>> to be accessible by the NAND driver and looses the 2 to 4 pins
>>>> of WAIT pin edge detection interrupt capability if it is needed
>>>> for generic use. (not NAND/GPMC memory specific)
>>>>
>>>> cheers,
>>>> -roger
>>>>
>>> I am not sure if this is possible with OMAP boards but can we split the pins
>>> into 1 or 2 for NAND/GPMC memory specific and use the others for WAIT interrupt
>>> capability.
>>> Nick
>>>
>> Yes if the wait pins are not used for NAND/GPMC memory then they can be used
>> as generic edge detect interrupt or probably even a GPI.
>> I don't see what would prevent it.
>>
>> I'm not sure if anyone will dare to use them though as they weren't originally meant
>> for that use and none of the existing kernels support that. So it is really a
>> chicken and egg situation here. :)
>>
>> But I see value in doing it the way Tony says cause it is much cleaner to specify
>> which interrupt (or wait pin) you want for NAND use.
>>
>> cheers,
>> -roger
>>
> I would also have to agree with Tony about this issue and feel his solution 
> seems fine. However why don't recent kernel's support this feature?
> Nick 
> 

kernel supports the feature but OMAP GPMC/NAND driver never supported it because
nobody implemented it.

cheers,
-roger

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
  2015-07-13 12:40       ` Tony Lindgren
       [not found]         ` <55A3B467.8030409@gmail.com>
@ 2015-07-29 12:06         ` Roger Quadros
       [not found]           ` <55B8C364.4030203@gmail.com>
  2015-07-31 10:21           ` Roger Quadros
  1 sibling, 2 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-29 12:06 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: dwmw2, computersforpeace, bcousson, ezequiel, linux-mtd,
	linux-omap, devicetree, linux-kernel

Tony,

On 13/07/15 15:40, Tony Lindgren wrote:
> * Roger Quadros <rogerq@ti.com> [150713 03:07]:
>> Tony,
>>
>> On 13/07/15 10:10, Tony Lindgren wrote:
>>> * Roger Quadros <rogerq@ti.com> [150710 05:26]:
>>>> Since the Interrupt Events are used only by the NAND driver,
>>>> there is no point in managing the Interrupt registers
>>>> in the GPMC driver and complicating it with irqchip modeling.
>>>
>>> I don't think it's a good idea to allow external drivers to
>>> tinker directly with GPMC registers. How about just set up GPMC
>>> as an irqchip for the edge detection interrupts?
>>>
>>> I think we already have devices with multiple NAND chips. And
>>> there's nothing stopping other drivers from using the edge
>>> detection interrupts.
>>
>> OK. The GPMC_IRQ registers manage 2 NAND specific interrupts
>> (terminalcount and fifo) and 'n' WAIT pin edge interrupts.
>>
>>  So we can model this as a irqchip with 'n + 2' interrupts.
> 
> OK

For the wait pins irqchip is not sufficient and it needs to be gpiochip
with irqchip. Waitpin status can be read from GPIO_STATUS register.

Just getting the interrupt is not enough and we want to know if the
line is high or low. That is how nand->dev_ready works.

How about having 2 IRQ domains?
One is irqchip with 2 interrupts (terminalcount and fifo) and second is
gpiochip + irqchip for the n wait pins.

The nand driver can then be modified to use GPIO to get Read/Busy
pin status from the wait pin.

cheers,
-roger

>  
>> We need to take care that if a GPMC chip select needs a
>> wait pin then it can't be used as a generic interrupt.
>>
>> We need to get rid of omap_dev_ready() in nand/omap2.c as
>> it accesses the GPMC_STATUS register directly. Plus it is
>> hard coded to only monitor wait0 pin.
> 
> OK
>  
>> What is the best map we should use for irqchip?
>> Some Socs have 4 WAIT pins, some have 3 and some have 2.
>>
>> Should we start with 0,1,2, for the wait pins and use the next
>> available free one for the NAND?
> 
> Maybe we can just use the bits defined for each SoC in the
> GPMC_IRQSTATUS register for the mapping?  
> Regards,
> 
> Tony
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
       [not found]           ` <55B8C364.4030203@gmail.com>
@ 2015-07-29 13:52             ` Roger Quadros
       [not found]               ` <55B8DE44.4070608@gmail.com>
  0 siblings, 1 reply; 28+ messages in thread
From: Roger Quadros @ 2015-07-29 13:52 UTC (permalink / raw)
  To: nick, Tony Lindgren
  Cc: devicetree, computersforpeace, linux-kernel, linux-mtd, ezequiel,
	bcousson, linux-omap, dwmw2

On 29/07/15 15:13, nick wrote:
> 
> 
> On 2015-07-29 08:06 AM, Roger Quadros wrote:
>> Tony,
>>
>> On 13/07/15 15:40, Tony Lindgren wrote:
>>> * Roger Quadros <rogerq@ti.com> [150713 03:07]:
>>>> Tony,
>>>>
>>>> On 13/07/15 10:10, Tony Lindgren wrote:
>>>>> * Roger Quadros <rogerq@ti.com> [150710 05:26]:
>>>>>> Since the Interrupt Events are used only by the NAND driver,
>>>>>> there is no point in managing the Interrupt registers
>>>>>> in the GPMC driver and complicating it with irqchip modeling.
>>>>>
>>>>> I don't think it's a good idea to allow external drivers to
>>>>> tinker directly with GPMC registers. How about just set up GPMC
>>>>> as an irqchip for the edge detection interrupts?
>>>>>
>>>>> I think we already have devices with multiple NAND chips. And
>>>>> there's nothing stopping other drivers from using the edge
>>>>> detection interrupts.
>>>>
>>>> OK. The GPMC_IRQ registers manage 2 NAND specific interrupts
>>>> (terminalcount and fifo) and 'n' WAIT pin edge interrupts.
>>>>
>>>>  So we can model this as a irqchip with 'n + 2' interrupts.
>>>
>>> OK
>>
>> For the wait pins irqchip is not sufficient and it needs to be gpiochip
>> with irqchip. Waitpin status can be read from GPIO_STATUS register.
>>
>> Just getting the interrupt is not enough and we want to know if the
>> line is high or low. That is how nand->dev_ready works.
>>
>> How about having 2 IRQ domains?
>> One is irqchip with 2 interrupts (terminalcount and fifo) and second is
>> gpiochip + irqchip for the n wait pins.
>>
>> The nand driver can then be modified to use GPIO to get Read/Busy
>> pin status from the wait pin.
>>
>> cheers,
>> -roger
>>
> Doesn't OMAP boards support shared IRQs and if so why not share them across one
> IRQ domain if possible to save IRQ domains for other hardware that needs its 
> own IRQ domain. This is just a suggestion through as I don't have the hardware
> spec sheet on me Roger.

IRQ domain is a virtual abstraction introduced to prevent kernel irq number overlapping
in a single flat domain. I don't see what you can save by domain reuse.
Some memory maybe at most.

Shared interrupt is something totally different but we're trying to add real
hardware interrupts here. Didn't understand what you will share it with.

cheers,
-roger

> Nick 
>>>  
>>>> We need to take care that if a GPMC chip select needs a
>>>> wait pin then it can't be used as a generic interrupt.
>>>>
>>>> We need to get rid of omap_dev_ready() in nand/omap2.c as
>>>> it accesses the GPMC_STATUS register directly. Plus it is
>>>> hard coded to only monitor wait0 pin.
>>>
>>> OK
>>>  
>>>> What is the best map we should use for irqchip?
>>>> Some Socs have 4 WAIT pins, some have 3 and some have 2.
>>>>
>>>> Should we start with 0,1,2, for the wait pins and use the next
>>>> available free one for the NAND?
>>>
>>> Maybe we can just use the bits defined for each SoC in the
>>> GPMC_IRQSTATUS register for the mapping?  
>>> Regards,
>>>
>>> Tony
>>>
>>
>> ______________________________________________________
>> Linux MTD discussion mailing list
>> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
       [not found]               ` <55B8DE44.4070608@gmail.com>
@ 2015-07-29 15:12                 ` Roger Quadros
       [not found]                   ` <55B8F0B3.5000009@gmail.com>
  0 siblings, 1 reply; 28+ messages in thread
From: Roger Quadros @ 2015-07-29 15:12 UTC (permalink / raw)
  To: nick, Tony Lindgren
  Cc: devicetree, computersforpeace, linux-kernel, linux-mtd, ezequiel,
	bcousson, linux-omap, dwmw2

On 29/07/15 17:08, nick wrote:
> 
> 
> On 2015-07-29 09:52 AM, Roger Quadros wrote:
>> On 29/07/15 15:13, nick wrote:
>>>
>>>
>>> On 2015-07-29 08:06 AM, Roger Quadros wrote:
>>>> Tony,
>>>>
>>>> On 13/07/15 15:40, Tony Lindgren wrote:
>>>>> * Roger Quadros <rogerq@ti.com> [150713 03:07]:
>>>>>> Tony,
>>>>>>
>>>>>> On 13/07/15 10:10, Tony Lindgren wrote:
>>>>>>> * Roger Quadros <rogerq@ti.com> [150710 05:26]:
>>>>>>>> Since the Interrupt Events are used only by the NAND driver,
>>>>>>>> there is no point in managing the Interrupt registers
>>>>>>>> in the GPMC driver and complicating it with irqchip modeling.
>>>>>>>
>>>>>>> I don't think it's a good idea to allow external drivers to
>>>>>>> tinker directly with GPMC registers. How about just set up GPMC
>>>>>>> as an irqchip for the edge detection interrupts?
>>>>>>>
>>>>>>> I think we already have devices with multiple NAND chips. And
>>>>>>> there's nothing stopping other drivers from using the edge
>>>>>>> detection interrupts.
>>>>>>
>>>>>> OK. The GPMC_IRQ registers manage 2 NAND specific interrupts
>>>>>> (terminalcount and fifo) and 'n' WAIT pin edge interrupts.
>>>>>>
>>>>>>  So we can model this as a irqchip with 'n + 2' interrupts.
>>>>>
>>>>> OK
>>>>
>>>> For the wait pins irqchip is not sufficient and it needs to be gpiochip
>>>> with irqchip. Waitpin status can be read from GPIO_STATUS register.
>>>>
>>>> Just getting the interrupt is not enough and we want to know if the
>>>> line is high or low. That is how nand->dev_ready works.
>>>>
>>>> How about having 2 IRQ domains?
>>>> One is irqchip with 2 interrupts (terminalcount and fifo) and second is
>>>> gpiochip + irqchip for the n wait pins.
>>>>
>>>> The nand driver can then be modified to use GPIO to get Read/Busy
>>>> pin status from the wait pin.
>>>>
>>>> cheers,
>>>> -roger
>>>>
>>> Doesn't OMAP boards support shared IRQs and if so why not share them across one
>>> IRQ domain if possible to save IRQ domains for other hardware that needs its 
>>> own IRQ domain. This is just a suggestion through as I don't have the hardware
>>> spec sheet on me Roger.
>>
>> IRQ domain is a virtual abstraction introduced to prevent kernel irq number overlapping
>> in a single flat domain. I don't see what you can save by domain reuse.
>> Some memory maybe at most.
>>
>> Shared interrupt is something totally different but we're trying to add real
>> hardware interrupts here. Didn't understand what you will share it with.
>>
>> cheers,
>> -roger
>>
> My question then is do these hardware interrupts need to be on their own interrupt line
> for the CPU or can they share a CPU line as my concern is if possible we may be able to
> save a interrupt line for other use. I known on Intel CPUs this is a very limited resource
> but not sure on OMAP based boards if not then just avoid my recommendations.

It is like adding an external interrupt controller to expand the number of available
hardware interrupts.
This interrupt controller will still use the same GPMC IRQ line to propagate the
irq event upwards.

cheers,
-roger

> Nick 
>>> Nick 
>>>>>  
>>>>>> We need to take care that if a GPMC chip select needs a
>>>>>> wait pin then it can't be used as a generic interrupt.
>>>>>>
>>>>>> We need to get rid of omap_dev_ready() in nand/omap2.c as
>>>>>> it accesses the GPMC_STATUS register directly. Plus it is
>>>>>> hard coded to only monitor wait0 pin.
>>>>>
>>>>> OK
>>>>>  
>>>>>> What is the best map we should use for irqchip?
>>>>>> Some Socs have 4 WAIT pins, some have 3 and some have 2.
>>>>>>
>>>>>> Should we start with 0,1,2, for the wait pins and use the next
>>>>>> available free one for the NAND?
>>>>>
>>>>> Maybe we can just use the bits defined for each SoC in the
>>>>> GPMC_IRQSTATUS register for the mapping?  
>>>>> Regards,
>>>>>
>>>>> Tony
>>>>>
>>>>
>>>> ______________________________________________________
>>>> Linux MTD discussion mailing list
>>>> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>>>>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
       [not found]                   ` <55B8F0B3.5000009@gmail.com>
@ 2015-07-29 15:39                     ` Roger Quadros
  0 siblings, 0 replies; 28+ messages in thread
From: Roger Quadros @ 2015-07-29 15:39 UTC (permalink / raw)
  To: nick, Tony Lindgren
  Cc: devicetree, computersforpeace, linux-kernel, linux-mtd, ezequiel,
	bcousson, linux-omap, dwmw2

On 29/07/15 18:26, nick wrote:
> 
> 
> On 2015-07-29 11:12 AM, Roger Quadros wrote:
>> On 29/07/15 17:08, nick wrote:
>>>
>>>
>>> On 2015-07-29 09:52 AM, Roger Quadros wrote:
>>>> On 29/07/15 15:13, nick wrote:
>>>>>
>>>>>
>>>>> On 2015-07-29 08:06 AM, Roger Quadros wrote:
>>>>>> Tony,
>>>>>>
>>>>>> On 13/07/15 15:40, Tony Lindgren wrote:
>>>>>>> * Roger Quadros <rogerq@ti.com> [150713 03:07]:
>>>>>>>> Tony,
>>>>>>>>
>>>>>>>> On 13/07/15 10:10, Tony Lindgren wrote:
>>>>>>>>> * Roger Quadros <rogerq@ti.com> [150710 05:26]:
>>>>>>>>>> Since the Interrupt Events are used only by the NAND driver,
>>>>>>>>>> there is no point in managing the Interrupt registers
>>>>>>>>>> in the GPMC driver and complicating it with irqchip modeling.
>>>>>>>>>
>>>>>>>>> I don't think it's a good idea to allow external drivers to
>>>>>>>>> tinker directly with GPMC registers. How about just set up GPMC
>>>>>>>>> as an irqchip for the edge detection interrupts?
>>>>>>>>>
>>>>>>>>> I think we already have devices with multiple NAND chips. And
>>>>>>>>> there's nothing stopping other drivers from using the edge
>>>>>>>>> detection interrupts.
>>>>>>>>
>>>>>>>> OK. The GPMC_IRQ registers manage 2 NAND specific interrupts
>>>>>>>> (terminalcount and fifo) and 'n' WAIT pin edge interrupts.
>>>>>>>>
>>>>>>>>  So we can model this as a irqchip with 'n + 2' interrupts.
>>>>>>>
>>>>>>> OK
>>>>>>
>>>>>> For the wait pins irqchip is not sufficient and it needs to be gpiochip
>>>>>> with irqchip. Waitpin status can be read from GPIO_STATUS register.
>>>>>>
>>>>>> Just getting the interrupt is not enough and we want to know if the
>>>>>> line is high or low. That is how nand->dev_ready works.
>>>>>>
>>>>>> How about having 2 IRQ domains?
>>>>>> One is irqchip with 2 interrupts (terminalcount and fifo) and second is
>>>>>> gpiochip + irqchip for the n wait pins.
>>>>>>
>>>>>> The nand driver can then be modified to use GPIO to get Read/Busy
>>>>>> pin status from the wait pin.
>>>>>>
>>>>>> cheers,
>>>>>> -roger
>>>>>>
>>>>> Doesn't OMAP boards support shared IRQs and if so why not share them across one
>>>>> IRQ domain if possible to save IRQ domains for other hardware that needs its 
>>>>> own IRQ domain. This is just a suggestion through as I don't have the hardware
>>>>> spec sheet on me Roger.
>>>>
>>>> IRQ domain is a virtual abstraction introduced to prevent kernel irq number overlapping
>>>> in a single flat domain. I don't see what you can save by domain reuse.
>>>> Some memory maybe at most.
>>>>
>>>> Shared interrupt is something totally different but we're trying to add real
>>>> hardware interrupts here. Didn't understand what you will share it with.
>>>>
>>>> cheers,
>>>> -roger
>>>>
>>> My question then is do these hardware interrupts need to be on their own interrupt line
>>> for the CPU or can they share a CPU line as my concern is if possible we may be able to
>>> save a interrupt line for other use. I known on Intel CPUs this is a very limited resource
>>> but not sure on OMAP based boards if not then just avoid my recommendations.
>>
>> It is like adding an external interrupt controller to expand the number of available
>> hardware interrupts.
>> This interrupt controller will still use the same GPMC IRQ line to propagate the
>> irq event upwards.
>>
>> cheers,
>> -roger
>>
> That was my other suggestion for IRQ issues. Would you mind sending me a link to a spec sheet so
> I can review your patches better as you stated you wanted me to do this for you.

Sure. You can pick up any of omap3/4 or 5 Technical Reference Manuals.
e.g. omap5 TRM is here
http://www.ti.com/product/OMAP5432/technicaldocuments

cheers,
-roger

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
  2015-07-29 12:06         ` Roger Quadros
       [not found]           ` <55B8C364.4030203@gmail.com>
@ 2015-07-31 10:21           ` Roger Quadros
  2015-08-03 13:08             ` Tony Lindgren
  1 sibling, 1 reply; 28+ messages in thread
From: Roger Quadros @ 2015-07-31 10:21 UTC (permalink / raw)
  To: Tony Lindgren
  Cc: dwmw2, computersforpeace, bcousson, ezequiel, linux-mtd,
	linux-omap, devicetree, linux-kernel

On 29/07/15 15:06, Roger Quadros wrote:
> Tony,
> 
> On 13/07/15 15:40, Tony Lindgren wrote:
>> * Roger Quadros <rogerq@ti.com> [150713 03:07]:
>>> Tony,
>>>
>>> On 13/07/15 10:10, Tony Lindgren wrote:
>>>> * Roger Quadros <rogerq@ti.com> [150710 05:26]:
>>>>> Since the Interrupt Events are used only by the NAND driver,
>>>>> there is no point in managing the Interrupt registers
>>>>> in the GPMC driver and complicating it with irqchip modeling.
>>>>
>>>> I don't think it's a good idea to allow external drivers to
>>>> tinker directly with GPMC registers. How about just set up GPMC
>>>> as an irqchip for the edge detection interrupts?
>>>>
>>>> I think we already have devices with multiple NAND chips. And
>>>> there's nothing stopping other drivers from using the edge
>>>> detection interrupts.
>>>
>>> OK. The GPMC_IRQ registers manage 2 NAND specific interrupts
>>> (terminalcount and fifo) and 'n' WAIT pin edge interrupts.
>>>
>>>  So we can model this as a irqchip with 'n + 2' interrupts.
>>
>> OK
> 
> For the wait pins irqchip is not sufficient and it needs to be gpiochip
> with irqchip. Waitpin status can be read from GPIO_STATUS register.
> 
> Just getting the interrupt is not enough and we want to know if the
> line is high or low. That is how nand->dev_ready works.
> 
> How about having 2 IRQ domains?
> One is irqchip with 2 interrupts (terminalcount and fifo) and second is
> gpiochip + irqchip for the n wait pins.
> 
> The nand driver can then be modified to use GPIO to get Read/Busy
> pin status from the wait pin.

One more observation I've had is that using irqchip modelling for
the 2 NAND events causes a performance impact.

Using mtd_oobtest I see the following on dra7-evm

1) v4.2-rc4 with prefetch-polled (no IRQs used)
mtd_speedtest: eraseblock write speed is 7142 KiB/s
mtd_speedtest: eraseblock read speed is 13721 KiB/s

2) v4.2-rc4 with prefetch-irq (IRQchip model)
eraseblock write speed is 5475 KiB/s
eraseblock read speed is 6420 KiB/s

3) this series (*) with prefetch-irq (no IRQchip model, nand driver
directly accesses irqstatus/irqenable)
eraseblock write speed is 6564 KiB/s
eraseblock read speed is 10850 KiB/s

(*) diff at the end is required on top to fix an issue with this series.

So should we continue IRQchip modelling for the NAND events
or use the GPMC interrupt as shared and add APIs to access
the NAND bits of the IRQSTATUS/ENABLE register.

cheers,
-roger

--

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index fecc054..26ef2bd 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1832,13 +1832,14 @@ static int omap_get_dt_info(struct device *dev, struct omap_nand_info *info)
 		for (i = 0; i < ARRAY_SIZE(nand_xfer_types); i++) {
 			if (!strcasecmp(s, nand_xfer_types[i])) {
 				info->xfer_type = i;
-				break;
+				goto next;
 			}
 		}
 
 		dev_err(dev, "unrecognized value for ti,nand-xfer-type\n");
 		return -EINVAL;
 	}
+next:
 
 	of_get_nand_on_flash_bbt(child);
 
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 26ef2bd..e8bdff5 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -670,17 +670,12 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
 			goto done;
 	}
 
-	/* Clear FIFOEVENT STATUS */
-	irqstatus &= ~GPMC_IRQ_FIFOEVENT;
-	writel(irqstatus, info->reg.gpmc_irqstatus);
-
 	return IRQ_HANDLED;
 
 done:
 	complete(&info->comp);
 
-	/* Clear FIFOEVENT and TERMCOUNT STATUS */
-	irqstatus &= ~(GPMC_IRQ_TERMCOUNT | GPMC_IRQ_FIFOEVENT);
+	/* Clear IRQ STATUS */
 	writel(irqstatus, info->reg.gpmc_irqstatus);
 
 	/* Disable Interrupt generation */


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver
  2015-07-31 10:21           ` Roger Quadros
@ 2015-08-03 13:08             ` Tony Lindgren
  0 siblings, 0 replies; 28+ messages in thread
From: Tony Lindgren @ 2015-08-03 13:08 UTC (permalink / raw)
  To: Roger Quadros
  Cc: dwmw2, computersforpeace, bcousson, ezequiel, linux-mtd,
	linux-omap, devicetree, linux-kernel

* Roger Quadros <rogerq@ti.com> [150731 03:24]:
> 
> One more observation I've had is that using irqchip modelling for
> the 2 NAND events causes a performance impact.
> 
> Using mtd_oobtest I see the following on dra7-evm
> 
> 1) v4.2-rc4 with prefetch-polled (no IRQs used)
> mtd_speedtest: eraseblock write speed is 7142 KiB/s
> mtd_speedtest: eraseblock read speed is 13721 KiB/s
> 
> 2) v4.2-rc4 with prefetch-irq (IRQchip model)
> eraseblock write speed is 5475 KiB/s
> eraseblock read speed is 6420 KiB/s
> 
> 3) this series (*) with prefetch-irq (no IRQchip model, nand driver
> directly accesses irqstatus/irqenable)
> eraseblock write speed is 6564 KiB/s
> eraseblock read speed is 10850 KiB/s
> 
> (*) diff at the end is required on top to fix an issue with this series.
> 
> So should we continue IRQchip modelling for the NAND events
> or use the GPMC interrupt as shared and add APIs to access
> the NAND bits of the IRQSTATUS/ENABLE register.

In the long run chained IRQ would be the most flexible solution
for sure.

It might be worth checking why we have so much overhead with
the irqchip modelling compared to shared IRQ. If the overhead
is really all the extra IRQ handling then it seems the shared
interrupt plus an API to access IRQSTATUS/ENABLE is the way
to go. Up to you.

Regards,

Tony

 
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index fecc054..26ef2bd 100644
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -1832,13 +1832,14 @@ static int omap_get_dt_info(struct device *dev, struct omap_nand_info *info)
>  		for (i = 0; i < ARRAY_SIZE(nand_xfer_types); i++) {
>  			if (!strcasecmp(s, nand_xfer_types[i])) {
>  				info->xfer_type = i;
> -				break;
> +				goto next;
>  			}
>  		}
>  
>  		dev_err(dev, "unrecognized value for ti,nand-xfer-type\n");
>  		return -EINVAL;
>  	}
> +next:
>  
>  	of_get_nand_on_flash_bbt(child);
>  
> diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
> index 26ef2bd..e8bdff5 100644
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -670,17 +670,12 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
>  			goto done;
>  	}
>  
> -	/* Clear FIFOEVENT STATUS */
> -	irqstatus &= ~GPMC_IRQ_FIFOEVENT;
> -	writel(irqstatus, info->reg.gpmc_irqstatus);
> -
>  	return IRQ_HANDLED;
>  
>  done:
>  	complete(&info->comp);
>  
> -	/* Clear FIFOEVENT and TERMCOUNT STATUS */
> -	irqstatus &= ~(GPMC_IRQ_TERMCOUNT | GPMC_IRQ_FIFOEVENT);
> +	/* Clear IRQ STATUS */
>  	writel(irqstatus, info->reg.gpmc_irqstatus);
>  
>  	/* Disable Interrupt generation */
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2015-08-03 13:08 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-10 12:23 [PATCH 00/12] ARM: omap: mtd: nand: Support GPMC NAND on non-OMAP platforms Roger Quadros
2015-07-10 12:23 ` [PATCH 01/12] ARM: OMAP2+: gpmc: Add platform data Roger Quadros
2015-07-10 12:23 ` [PATCH 02/12] ARM: OMAP2+: gpmc: Add gpmc timings and settings to " Roger Quadros
2015-07-13 13:31   ` Tony Lindgren
2015-07-13 13:34     ` Roger Quadros
2015-07-10 12:23 ` [PATCH 03/12] mtd: nand: omap: Move IRQ handling from GPMC to NAND driver Roger Quadros
2015-07-13  7:10   ` Tony Lindgren
2015-07-13 10:04     ` Roger Quadros
2015-07-13 12:40       ` Tony Lindgren
     [not found]         ` <55A3B467.8030409@gmail.com>
2015-07-13 13:01           ` Tony Lindgren
     [not found]             ` <55A3B73C.9040604@gmail.com>
2015-07-13 13:12               ` Roger Quadros
     [not found]                 ` <55A3B9DD.60705@gmail.com>
2015-07-13 13:21                   ` Roger Quadros
     [not found]                     ` <55A3BDE3.2080004@gmail.com>
2015-07-13 13:35                       ` Roger Quadros
2015-07-29 12:06         ` Roger Quadros
     [not found]           ` <55B8C364.4030203@gmail.com>
2015-07-29 13:52             ` Roger Quadros
     [not found]               ` <55B8DE44.4070608@gmail.com>
2015-07-29 15:12                 ` Roger Quadros
     [not found]                   ` <55B8F0B3.5000009@gmail.com>
2015-07-29 15:39                     ` Roger Quadros
2015-07-31 10:21           ` Roger Quadros
2015-08-03 13:08             ` Tony Lindgren
2015-07-10 12:23 ` [PATCH 04/12] mtd: nand: omap: Move gpmc_update_nand_reg to nand driver Roger Quadros
2015-07-10 12:23 ` [PATCH 05/12] mtd: nand: omap: Move NAND write protect code from GPMC to NAND driver Roger Quadros
2015-07-10 12:23 ` [PATCH 06/12] mtd: nand: omap: Copy platform data parameters to omap_nand_info data Roger Quadros
2015-07-10 12:23 ` [PATCH 07/12] mtd: nand: omap: Clean up device tree support Roger Quadros
2015-07-10 12:23 ` [PATCH 08/12] mtd: nand: omap: Update DT binding documentation Roger Quadros
2015-07-10 12:23 ` [PATCH 09/12] memory: omap-gpmc: use module_platform_driver() Roger Quadros
2015-07-10 12:23 ` [PATCH 10/12] memory: omap-gpmc: Prevent mapping into 1st 16MB Roger Quadros
2015-07-10 12:23 ` [PATCH 11/12] ARM: dts: OMAP2+: Fix NAND device nodes Roger Quadros
2015-07-10 12:23 ` [PATCH 12/12] ARM: dts: omap3: Fix gpmc memory resource size Roger Quadros

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).