All of lore.kernel.org
 help / color / mirror / Atom feed
* [u-boot][PATCH v2 0/4] Introduce MEMORY uclass and TI GPMC driver
@ 2022-10-06 13:23 Roger Quadros
  2022-10-06 13:23 ` [u-boot][PATCH v2 1/4] dm: memory: Introduce new uclass Roger Quadros
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Roger Quadros @ 2022-10-06 13:23 UTC (permalink / raw)
  To: trini, sjg; +Cc: u-boot, praneeth, kishon, Roger Quadros

Hi,

This series introduces the MEMORY controller uclass for the drivers
that exist in drivers/memory directory.

With that, we add the TI GPMC Memory controller driver as the first
user of this uclass.

The GPMC is a unified memory controller dedicated for interfacing
with external memory devices like
 - Asynchronous SRAM-like memories and ASICs
 - Asynchronous, synchronous, and page mode burst NOR flash
 - NAND flash
 - Pseudo-SRAM devices

The driver is pulled straight from the Linux kernel and adapted
for u-boot.
    
This driver will take care of setting up the GPMC based on
the settings specified in the Device tree and then
probe its children.

Roger Quadros (4):
  dm: memory: Introduce new uclass
  scripts: Makefile.spl: Enable memory drivers to be built for SPL
  dt/bindings: memory: Add bindings for TI GPMC driver
  memory: Add TI GPMC driver

 arch/sandbox/dts/test.dts                     |    4 +
 .../memory/ti,gpmc-child.yaml                 |  252 ++++
 doc/device-tree-bindings/memory/ti,gpmc.yaml  |  190 +++
 drivers/memory/Kconfig                        |   36 +
 drivers/memory/Makefile                       |    3 +
 drivers/memory/memory-sandbox.c               |   18 +
 drivers/memory/memory-uclass.c                |   13 +
 drivers/memory/ti-gpmc.c                      | 1240 +++++++++++++++++
 drivers/memory/ti-gpmc.h                      |  298 ++++
 include/dm/uclass-id.h                        |    1 +
 include/linux/mtd/omap_gpmc.h                 |    3 +
 scripts/Makefile.spl                          |    1 +
 test/dm/Makefile                              |    1 +
 test/dm/memory.c                              |   21 +
 14 files changed, 2081 insertions(+)
 create mode 100644 doc/device-tree-bindings/memory/ti,gpmc-child.yaml
 create mode 100644 doc/device-tree-bindings/memory/ti,gpmc.yaml
 create mode 100644 drivers/memory/memory-sandbox.c
 create mode 100644 drivers/memory/memory-uclass.c
 create mode 100644 drivers/memory/ti-gpmc.c
 create mode 100644 drivers/memory/ti-gpmc.h
 create mode 100644 test/dm/memory.c

-- 
2.17.1


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

* [u-boot][PATCH v2 1/4] dm: memory: Introduce new uclass
  2022-10-06 13:23 [u-boot][PATCH v2 0/4] Introduce MEMORY uclass and TI GPMC driver Roger Quadros
@ 2022-10-06 13:23 ` Roger Quadros
  2022-10-06 19:07   ` Simon Glass
  2022-10-06 13:23 ` [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 15+ messages in thread
From: Roger Quadros @ 2022-10-06 13:23 UTC (permalink / raw)
  To: trini, sjg; +Cc: u-boot, praneeth, kishon, Roger Quadros

Introduce UCLASS_MEMORY for future Memory Controller
device drivers.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 arch/sandbox/dts/test.dts       |  4 ++++
 drivers/memory/Kconfig          | 17 +++++++++++++++++
 drivers/memory/Makefile         |  2 ++
 drivers/memory/memory-sandbox.c | 18 ++++++++++++++++++
 drivers/memory/memory-uclass.c  | 13 +++++++++++++
 include/dm/uclass-id.h          |  1 +
 test/dm/Makefile                |  1 +
 test/dm/memory.c                | 21 +++++++++++++++++++++
 8 files changed, 77 insertions(+)
 create mode 100644 drivers/memory/memory-sandbox.c
 create mode 100644 drivers/memory/memory-uclass.c
 create mode 100644 test/dm/memory.c

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2761588f0d..d65b2d2dcb 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -926,6 +926,10 @@
 		};
 	};
 
+	memory-controller {
+		compatible = "sandbox,memory";
+	};
+
 	misc-test {
 		#address-cells = <1>;
 		#size-cells = <1>;
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 7271892763..632feb3aaa 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -4,6 +4,23 @@
 
 menu "Memory Controller drivers"
 
+config DM_MEMORY
+	bool "Enable Driver Model for Memory Controller drivers"
+	depends on DM
+	help
+	  Enable driver model for Memory Controller devices.
+	  These devices provide Memory bus interface to various devices like
+	  SRAM, Ethernet adapters, FPGAs, etc.
+	  For now this uclass has no methods yet.
+
+config SANDBOX_MEMORY
+	bool "Enable Sandbox Memory Controller driver"
+	depends on SANDBOX && DM_MEMORY
+	help
+	  This is a driver model based Memory Controller driver for sandbox.
+	  Currently it is a stub only, as there are no usable uclass methods
+	  yet.
+
 config STM32_FMC2_EBI
 	bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
 	depends on ARCH_STM32MP
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index fec52efb60..1d68b2b296 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -1,3 +1,5 @@
 
+obj-$(CONFIG_DM_MEMORY) += memory-uclass.o
+obj-$(CONFIG_SANDBOX_MEMORY) += memory-sandbox.o
 obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
 obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
diff --git a/drivers/memory/memory-sandbox.c b/drivers/memory/memory-sandbox.c
new file mode 100644
index 0000000000..f2ede50863
--- /dev/null
+++ b/drivers/memory/memory-sandbox.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022
+ *     Texas Instruments Incorporated, <www.ti.com>
+ */
+
+#include <dm.h>
+
+static const struct udevice_id sandbox_memory_match[] = {
+	{ .compatible = "sandbox,memory" },
+	{ /* sentinel */ }
+};
+
+U_BOOT_DRIVER(sandbox_memory) = {
+	.name	= "sandbox_memory",
+	.id	= UCLASS_MEMORY,
+	.of_match = sandbox_memory_match,
+};
diff --git a/drivers/memory/memory-uclass.c b/drivers/memory/memory-uclass.c
new file mode 100644
index 0000000000..d6d37fe777
--- /dev/null
+++ b/drivers/memory/memory-uclass.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022
+ *     Texas Instruments Incorporated, <www.ti.com>
+ */
+
+#include <dm.h>
+
+UCLASS_DRIVER(memory) = {
+	.name = "memory",
+	.id = UCLASS_MEMORY,
+	.post_bind = dm_scan_fdt_dev,
+};
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index a432e43871..936a16c5d9 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -76,6 +76,7 @@ enum uclass_id {
 	UCLASS_MASS_STORAGE,	/* Mass storage device */
 	UCLASS_MDIO,		/* MDIO bus */
 	UCLASS_MDIO_MUX,	/* MDIO MUX/switch */
+	UCLASS_MEMORY,		/* Memory Controller device */
 	UCLASS_MISC,		/* Miscellaneous device */
 	UCLASS_MMC,		/* SD / MMC card or chip */
 	UCLASS_MOD_EXP,		/* RSA Mod Exp device */
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7543df8823..01275db2cd 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -47,6 +47,7 @@ ifneq ($(CONFIG_EFI_PARTITION),)
 obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fastboot.o
 endif
 obj-$(CONFIG_FIRMWARE) += firmware.o
+obj-$(CONFIG_DM_MEMORY) += memory.o
 obj-$(CONFIG_DM_HWSPINLOCK) += hwspinlock.o
 obj-$(CONFIG_DM_I2C) += i2c.o
 obj-$(CONFIG_SOUND) += i2s.o
diff --git a/test/dm/memory.c b/test/dm/memory.c
new file mode 100644
index 0000000000..7d9500aa91
--- /dev/null
+++ b/test/dm/memory.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022
+ *     Texas Instruments Incorporated, <www.ti.com>
+ */
+
+#include <dm.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+static int dm_test_memory(struct unit_test_state *uts)
+{
+	struct udevice *dev;
+
+	ut_assertok(uclass_first_device_err(UCLASS_MEMORY, &dev));
+
+	return 0;
+}
+
+DM_TEST(dm_test_memory, UT_TESTF_SCAN_FDT);
-- 
2.17.1


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

* [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-06 13:23 [u-boot][PATCH v2 0/4] Introduce MEMORY uclass and TI GPMC driver Roger Quadros
  2022-10-06 13:23 ` [u-boot][PATCH v2 1/4] dm: memory: Introduce new uclass Roger Quadros
@ 2022-10-06 13:23 ` Roger Quadros
  2022-10-18 17:40   ` Tom Rini
  2022-10-06 13:23 ` [u-boot][PATCH v2 3/4] dt/bindings: memory: Add bindings for TI GPMC driver Roger Quadros
  2022-10-06 13:24 ` [u-boot][PATCH v2 4/4] memory: Add " Roger Quadros
  3 siblings, 1 reply; 15+ messages in thread
From: Roger Quadros @ 2022-10-06 13:23 UTC (permalink / raw)
  To: trini, sjg; +Cc: u-boot, praneeth, kishon, Roger Quadros

We will need ti-gpmc driver for SPL. Allow memory drivers
do be built for SPL.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 scripts/Makefile.spl | 1 +
 1 file changed, 1 insertion(+)

diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 3bafeb4fe9..110076b22f 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
 endif
 
 libs-y += drivers/
+libs-y += drivers/memory/
 libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
 libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
 libs-y += dts/
-- 
2.17.1


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

* [u-boot][PATCH v2 3/4] dt/bindings: memory: Add bindings for TI GPMC driver
  2022-10-06 13:23 [u-boot][PATCH v2 0/4] Introduce MEMORY uclass and TI GPMC driver Roger Quadros
  2022-10-06 13:23 ` [u-boot][PATCH v2 1/4] dm: memory: Introduce new uclass Roger Quadros
  2022-10-06 13:23 ` [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
@ 2022-10-06 13:23 ` Roger Quadros
  2022-10-06 13:24 ` [u-boot][PATCH v2 4/4] memory: Add " Roger Quadros
  3 siblings, 0 replies; 15+ messages in thread
From: Roger Quadros @ 2022-10-06 13:23 UTC (permalink / raw)
  To: trini, sjg; +Cc: u-boot, praneeth, kishon, Roger Quadros

GPMC stands for General Purpose Memory Controller and it is
present on many Texas Instruments SoCs.

It supports a number of Asynchronous and Synchronous interfaces
and has various settings to configure the bus interface.

The DT bindings define all the various GPMC settings.

As the GPMC supports multiple devices on the bus, each
device is represented as a child and the respective
GPMC settings are situated there. (see ti,gpmc-child.yaml)

These binding docs are picked up from the Linux kernel.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 .../memory/ti,gpmc-child.yaml                 | 252 ++++++++++++++++++
 doc/device-tree-bindings/memory/ti,gpmc.yaml  | 190 +++++++++++++
 2 files changed, 442 insertions(+)
 create mode 100644 doc/device-tree-bindings/memory/ti,gpmc-child.yaml
 create mode 100644 doc/device-tree-bindings/memory/ti,gpmc.yaml

diff --git a/doc/device-tree-bindings/memory/ti,gpmc-child.yaml b/doc/device-tree-bindings/memory/ti,gpmc-child.yaml
new file mode 100644
index 0000000000..8e541acdb1
--- /dev/null
+++ b/doc/device-tree-bindings/memory/ti,gpmc-child.yaml
@@ -0,0 +1,252 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ti,gpmc-child.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: device tree bindings for children of the Texas Instruments GPMC
+
+maintainers:
+  - Tony Lindgren <tony@atomide.com>
+  - Roger Quadros <rogerq@kernel.org>
+
+description:
+  This binding is meant for the child nodes of the GPMC node. The node
+  represents any device connected to the GPMC bus. It may be a Flash chip,
+  RAM chip or Ethernet controller, etc. These properties are meant for
+  configuring the GPMC settings/timings and will accompany the bindings
+  supported by the respective device.
+
+properties:
+  reg: true
+
+# GPMC Timing properties for child nodes. All are optional and default to 0.
+  gpmc,sync-clk-ps:
+    description: Minimum clock period for synchronous mode
+    default: 0
+
+# Chip-select signal timings corresponding to GPMC_CONFIG2:
+  gpmc,cs-on-ns:
+    description: Assertion time
+    default: 0
+
+  gpmc,cs-rd-off-ns:
+    description: Read deassertion time
+    default: 0
+
+  gpmc,cs-wr-off-ns:
+    description: Write deassertion time
+    default: 0
+
+# ADV signal timings corresponding to GPMC_CONFIG3:
+  gpmc,adv-on-ns:
+    description: Assertion time
+    default: 0
+
+  gpmc,adv-rd-off-ns:
+    description: Read deassertion time
+    default: 0
+
+  gpmc,adv-wr-off-ns:
+    description: Write deassertion time
+    default: 0
+
+  gpmc,adv-aad-mux-on-ns:
+    description: Assertion time for AAD
+    default: 0
+
+  gpmc,adv-aad-mux-rd-off-ns:
+    description: Read deassertion time for AAD
+    default: 0
+
+  gpmc,adv-aad-mux-wr-off-ns:
+    description: Write deassertion time for AAD
+    default: 0
+
+# WE signals timings corresponding to GPMC_CONFIG4:
+  gpmc,we-on-ns:
+    description: Assertion time
+    default: 0
+
+  gpmc,we-off-ns:
+    description: Deassertion time
+    default: 0
+
+# OE signals timings corresponding to GPMC_CONFIG4:
+  gpmc,oe-on-ns:
+    description: Assertion time
+    default: 0
+
+  gpmc,oe-off-ns:
+    description: Deassertion time
+    default: 0
+
+  gpmc,oe-aad-mux-on-ns:
+    description: Assertion time for AAD
+    default: 0
+
+  gpmc,oe-aad-mux-off-ns:
+    description: Deassertion time for AAD
+    default: 0
+
+# Access time and cycle time timings (in nanoseconds) corresponding to
+# GPMC_CONFIG5:
+  gpmc,page-burst-access-ns:
+    description: Multiple access word delay
+    default: 0
+
+  gpmc,access-ns:
+    description: Start-cycle to first data valid delay
+    default: 0
+
+  gpmc,rd-cycle-ns:
+    description: Total read cycle time
+    default: 0
+
+  gpmc,wr-cycle-ns:
+    description: Total write cycle time
+    default: 0
+
+  gpmc,bus-turnaround-ns:
+    description: Turn-around time between successive accesses
+    default: 0
+
+  gpmc,cycle2cycle-delay-ns:
+    description: Delay between chip-select pulses
+    default: 0
+
+  gpmc,clk-activation-ns:
+    description: GPMC clock activation time
+    default: 0
+
+  gpmc,wait-monitoring-ns:
+    description: Start of wait monitoring with regard to valid data
+    default: 0
+
+# Boolean timing parameters. If property is present, parameter is enabled
+# otherwise disabled.
+  gpmc,adv-extra-delay:
+    description: ADV signal is delayed by half GPMC clock
+    type: boolean
+
+  gpmc,cs-extra-delay:
+    description: CS signal is delayed by half GPMC clock
+    type: boolean
+
+  gpmc,cycle2cycle-diffcsen:
+    description: |
+      Add "cycle2cycle-delay" between successive accesses
+      to a different CS
+    type: boolean
+
+  gpmc,cycle2cycle-samecsen:
+    description: |
+      Add "cycle2cycle-delay" between successive accesses
+      to the same CS
+    type: boolean
+
+  gpmc,oe-extra-delay:
+    description: OE signal is delayed by half GPMC clock
+    type: boolean
+
+  gpmc,we-extra-delay:
+    description: WE signal is delayed by half GPMC clock
+    type: boolean
+
+  gpmc,time-para-granularity:
+    description: Multiply all access times by 2
+    type: boolean
+
+# The following two properties are applicable only to OMAP3+ and AM335x:
+  gpmc,wr-access-ns:
+    description: |
+      In synchronous write mode, for single or
+      burst accesses, defines the number of
+      GPMC_FCLK cycles from start access time
+      to the GPMC_CLK rising edge used by the
+      memory device for the first data capture.
+    default: 0
+
+  gpmc,wr-data-mux-bus-ns:
+    description: |
+      In address-data multiplex mode, specifies
+      the time when the first data is driven on
+      the address-data bus.
+    default: 0
+
+# GPMC chip-select settings properties for child nodes. All are optional.
+  gpmc,burst-length:
+    description: Page/burst length.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 4, 8, 16]
+    default: 0
+
+  gpmc,burst-wrap:
+    description: Enables wrap bursting
+    type: boolean
+
+  gpmc,burst-read:
+    description: Enables read page/burst mode
+    type: boolean
+
+  gpmc,burst-write:
+    description: Enables write page/burst mode
+    type: boolean
+
+  gpmc,device-width:
+    description: |
+      Total width of device(s) connected to a GPMC
+      chip-select in bytes. The GPMC supports 8-bit
+      and 16-bit devices and so this property must be
+      1 or 2.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [1, 2]
+    default: 1
+
+  gpmc,mux-add-data:
+    description: |
+      Address and data multiplexing configuration.
+      Valid values are
+      0 for Non multiplexed mode
+      1 for address-address-data multiplexing mode and
+      2 for address-data multiplexing mode.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2]
+
+  gpmc,sync-read:
+    description: |
+      Enables synchronous read. Defaults to asynchronous
+      is this is not set.
+    type: boolean
+
+  gpmc,sync-write:
+    description: |
+      Enables synchronous writes. Defaults to asynchronous
+      is this is not set.
+    type: boolean
+
+  gpmc,wait-pin:
+    description: |
+      Wait-pin used by client. Must be less than "gpmc,num-waitpins".
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  gpmc,wait-pin-polarity:
+    description: |
+      Set the desired polarity for the selected wait pin.
+      0 for active low, 1 for active high.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1]
+
+  gpmc,wait-on-read:
+    description: Enables wait monitoring on reads.
+    type: boolean
+
+  gpmc,wait-on-write:
+    description: Enables wait monitoring on writes.
+    type: boolean
+
+required:
+  - reg
+
+# the GPMC child will have its own native properties
+additionalProperties: true
diff --git a/doc/device-tree-bindings/memory/ti,gpmc.yaml b/doc/device-tree-bindings/memory/ti,gpmc.yaml
new file mode 100644
index 0000000000..e188a4bf75
--- /dev/null
+++ b/doc/device-tree-bindings/memory/ti,gpmc.yaml
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ti,gpmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments GPMC Memory Controller device-tree bindings
+
+maintainers:
+  - Tony Lindgren <tony@atomide.com>
+  - Roger Quadros <rogerq@kernel.org>
+
+description:
+  The GPMC is a unified memory controller dedicated for interfacing
+  with external memory devices like
+  - Asynchronous SRAM-like memories and ASICs
+  - Asynchronous, synchronous, and page mode burst NOR flash
+  - NAND flash
+  - Pseudo-SRAM devices
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - ti,am3352-gpmc
+          - ti,am64-gpmc
+          - ti,omap2420-gpmc
+          - ti,omap2430-gpmc
+          - ti,omap3430-gpmc
+          - ti,omap4430-gpmc
+
+  reg:
+    minItems: 1
+    maxItems: 2
+
+  reg-names:
+    items:
+      - const: cfg
+      - const: data
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: |
+      Functional clock. Used for bus timing calculations and
+      GPMC configuration.
+
+  clock-names:
+    items:
+      - const: fck
+
+  power-domains:
+    maxItems: 1
+
+  dmas:
+    items:
+      - description: DMA channel for GPMC NAND prefetch
+
+  dma-names:
+    items:
+      - const: rxtx
+
+  "#address-cells": true
+
+  "#size-cells": true
+
+  gpmc,num-cs:
+    description: maximum number of supported chip-select lines.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  gpmc,num-waitpins:
+    description: maximum number of supported wait pins.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  ranges:
+    minItems: 1
+    description: |
+      Must be set up to reflect the memory layout with four
+      integer values for each chip-select line in use,
+      <cs-number> 0 <physical address of mapping> <size>
+    items:
+      - description: NAND bank 0
+      - description: NOR/SRAM bank 0
+      - description: NOR/SRAM bank 1
+
+  '#interrupt-cells':
+    const: 2
+
+  interrupt-controller:
+    description: |
+      The GPMC driver implements and interrupt controller for
+      the NAND events "fifoevent" and "termcount" plus the
+      rising/falling edges on the GPMC_WAIT pins.
+      The interrupt number mapping is as follows
+      0 - NAND_fifoevent
+      1 - NAND_termcount
+      2 - GPMC_WAIT0 pin edge
+      3 - GPMC_WAIT1 pin edge, and so on.
+
+  '#gpio-cells':
+    const: 2
+
+  gpio-controller:
+    description: |
+      The GPMC driver implements a GPIO controller for the
+      GPMC WAIT pins that can be used as general purpose inputs.
+      0 maps to GPMC_WAIT0 pin.
+
+  ti,hwmods:
+    description:
+      Name of the HWMOD associated with GPMC. This is for legacy
+      omap2/3 platforms only.
+    $ref: /schemas/types.yaml#/definitions/string
+    deprecated: true
+
+  ti,no-idle-on-init:
+    description:
+      Prevent idling the module at init. This is for legacy omap2/3
+      platforms only.
+    type: boolean
+    deprecated: true
+
+patternProperties:
+  "@[0-7],[a-f0-9]+$":
+    type: object
+    description: |
+      The child device node represents the device connected to the GPMC
+      bus. The device can be a NAND chip, SRAM device, NOR device
+      or an ASIC.
+    $ref: "ti,gpmc-child.yaml"
+
+
+required:
+  - compatible
+  - reg
+  - gpmc,num-cs
+  - gpmc,num-waitpins
+  - "#address-cells"
+  - "#size-cells"
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,am64-gpmc
+    then:
+      required:
+        - reg-names
+        - power-domains
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/gpio/gpio.h>
+
+    gpmc: memory-controller@50000000 {
+      compatible = "ti,am3352-gpmc";
+      reg = <0x50000000 0x2000>;
+      interrupts = <100>;
+      clocks = <&l3s_clkctrl>;
+      clock-names = "fck";
+      dmas = <&edma 52 0>;
+      dma-names = "rxtx";
+      gpmc,num-cs = <8>;
+      gpmc,num-waitpins = <2>;
+      #address-cells = <2>;
+      #size-cells = <1>;
+      ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
+      interrupt-controller;
+      #interrupt-cells = <2>;
+      gpio-controller;
+      #gpio-cells = <2>;
+
+      nand@0,0 {
+        compatible = "ti,omap2-nand";
+        reg = <0 0 4>;
+        interrupt-parent = <&gpmc>;
+        interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+                     <1 IRQ_TYPE_NONE>; /* termcount */
+        ti,nand-xfer-type = "prefetch-dma";
+        ti,nand-ecc-opt = "bch16";
+        ti,elm-id = <&elm>;
+        rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */
+      };
+    };
-- 
2.17.1


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

* [u-boot][PATCH v2 4/4] memory: Add TI GPMC driver
  2022-10-06 13:23 [u-boot][PATCH v2 0/4] Introduce MEMORY uclass and TI GPMC driver Roger Quadros
                   ` (2 preceding siblings ...)
  2022-10-06 13:23 ` [u-boot][PATCH v2 3/4] dt/bindings: memory: Add bindings for TI GPMC driver Roger Quadros
@ 2022-10-06 13:24 ` Roger Quadros
  3 siblings, 0 replies; 15+ messages in thread
From: Roger Quadros @ 2022-10-06 13:24 UTC (permalink / raw)
  To: trini, sjg; +Cc: u-boot, praneeth, kishon, Roger Quadros

The GPMC is a unified memory controller dedicated for interfacing
with external memory devices like
 - Asynchronous SRAM-like memories and ASICs
 - Asynchronous, synchronous, and page mode burst NOR flash
 - NAND flash
 - Pseudo-SRAM devices

This driver will take care of setting up the GPMC based on
the settings specified in the Device tree and then
probe its children.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/memory/Kconfig        |   19 +
 drivers/memory/Makefile       |    1 +
 drivers/memory/ti-gpmc.c      | 1240 +++++++++++++++++++++++++++++++++
 drivers/memory/ti-gpmc.h      |  298 ++++++++
 include/linux/mtd/omap_gpmc.h |    3 +
 5 files changed, 1561 insertions(+)
 create mode 100644 drivers/memory/ti-gpmc.c
 create mode 100644 drivers/memory/ti-gpmc.h

diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 632feb3aaa..d057c9883b 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -41,4 +41,23 @@ config TI_AEMIF
 	  of 256M bytes of any of these memories can be accessed at a given
 	  time via four chip selects with 64M byte access per chip select.
 
+config TI_GPMC
+	bool "Texas Instruments GPMC driver"
+	depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || ARCH_K3
+	depends on DM_MEMORY
+	help
+	  This driver is for the General Purpose Memory Controller (GPMC)
+          present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows
+          interfacing to a variety of asynchronous as well as synchronous
+          memory drives like NOR, NAND, OneNAND, SRAM.
+
+if TI_GPMC
+config TI_GPMC_DEBUG
+	bool "Debug Texas Instruments GPMC timings"
+	default n
+	help
+	  Enable this to print GPMC timings before and after the GPMC registers
+	  are programmed. This should not be left enabled on production systems.
+endif
+
 endmenu
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 1d68b2b296..7ce0b98e42 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_DM_MEMORY) += memory-uclass.o
 obj-$(CONFIG_SANDBOX_MEMORY) += memory-sandbox.o
 obj-$(CONFIG_STM32_FMC2_EBI) += stm32-fmc2-ebi.o
 obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
+obj-$(CONFIG_TI_GPMC) += ti-gpmc.o
diff --git a/drivers/memory/ti-gpmc.c b/drivers/memory/ti-gpmc.c
new file mode 100644
index 0000000000..f511a529b1
--- /dev/null
+++ b/drivers/memory/ti-gpmc.c
@@ -0,0 +1,1240 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Texas Instruments GPMC Driver
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+#include <clk.h>
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <dm/device_compat.h>
+#include <dm/devres.h>
+#include <dm/lists.h>
+#include <linux/mtd/omap_gpmc.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include "ti-gpmc.h"
+
+enum gpmc_clk_domain {
+	GPMC_CD_FCLK,
+	GPMC_CD_CLK
+};
+
+struct gpmc_cs_data {
+	const char *name;
+#define GPMC_CS_RESERVED	BIT(0)
+	u32 flags;
+};
+
+struct ti_gpmc {
+	void __iomem *base;
+	u32 cs_num;
+	u32 nr_waitpins;
+	struct clk *l3_clk;
+	u32 capability_flags;
+	struct resource data;
+};
+
+static struct gpmc_cs_data gpmc_cs[GPMC_CS_NUM];
+static unsigned int gpmc_cs_num = GPMC_CS_NUM;
+static unsigned int gpmc_nr_waitpins;
+static unsigned int gpmc_capability;
+static void __iomem *gpmc_base;
+static struct clk *gpmc_l3_clk;
+
+/* Public, as required by nand/raw/omap_gpmc.c */
+const struct gpmc *gpmc_cfg;
+
+/*
+ * 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
+
+static void gpmc_write_reg(int idx, u32 val)
+{
+	writel_relaxed(val, gpmc_base + idx);
+}
+
+static u32 gpmc_read_reg(int idx)
+{
+	return readl_relaxed(gpmc_base + idx);
+}
+
+static void gpmc_cs_write_reg(int cs, int idx, u32 val)
+{
+	void __iomem *reg_addr;
+
+	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	writel_relaxed(val, reg_addr);
+}
+
+static u32 gpmc_cs_read_reg(int cs, int idx)
+{
+	void __iomem *reg_addr;
+
+	reg_addr = gpmc_base + GPMC_CS0_OFFSET + (cs * GPMC_CS_SIZE) + idx;
+	return readl_relaxed(reg_addr);
+}
+
+static unsigned long gpmc_get_fclk_period(void)
+{
+	unsigned long rate = clk_get_rate(gpmc_l3_clk);
+
+	rate /= 1000;
+	rate = 1000000000 / rate;	/* In picoseconds */
+
+	return rate;
+}
+
+/**
+ * gpmc_get_clk_period - get period of selected clock domain in ps
+ * @cs: Chip Select Region.
+ * @cd: Clock Domain.
+ *
+ * GPMC_CS_CONFIG1 GPMCFCLKDIVIDER for cs has to be setup
+ * prior to calling this function with GPMC_CD_CLK.
+ */
+static unsigned long gpmc_get_clk_period(int cs, enum gpmc_clk_domain cd)
+{
+	unsigned long tick_ps = gpmc_get_fclk_period();
+	u32 l;
+	int div;
+
+	switch (cd) {
+	case GPMC_CD_CLK:
+		/* get current clk divider */
+		l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+		div = (l & 0x03) + 1;
+		/* get GPMC_CLK period */
+		tick_ps *= div;
+		break;
+	case GPMC_CD_FCLK:
+	default:
+		break;
+	}
+
+	return tick_ps;
+}
+
+static unsigned int gpmc_ns_to_clk_ticks(unsigned int time_ns, int cs,
+					 enum gpmc_clk_domain cd)
+{
+	unsigned long tick_ps;
+
+	/* Calculate in picosecs to yield more exact results */
+	tick_ps = gpmc_get_clk_period(cs, cd);
+
+	return (time_ns * 1000 + tick_ps - 1) / tick_ps;
+}
+
+static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+{
+	return gpmc_ns_to_clk_ticks(time_ns, /* any CS */ 0, GPMC_CD_FCLK);
+}
+
+static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
+{
+	unsigned long tick_ps;
+
+	/* Calculate in picosecs to yield more exact results */
+	tick_ps = gpmc_get_fclk_period();
+
+	return (time_ps + tick_ps - 1) / tick_ps;
+}
+
+static __maybe_unused unsigned int gpmc_clk_ticks_to_ns(unsigned int ticks, int cs,
+							enum gpmc_clk_domain cd)
+{
+	return ticks * gpmc_get_clk_period(cs, cd) / 1000;
+}
+
+static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, reg);
+	if (value)
+		l |= mask;
+	else
+		l &= ~mask;
+	gpmc_cs_write_reg(cs, reg, l);
+}
+
+static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
+{
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1,
+			   GPMC_CONFIG1_TIME_PARA_GRAN,
+			   p->time_para_granularity);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2,
+			   GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3,
+			   GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+			   GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
+			   GPMC_CONFIG4_WEEXTRADELAY, p->we_extra_delay);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+			   GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
+			   p->cycle2cyclesamecsen);
+	gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
+			   GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN,
+			   p->cycle2cyclediffcsen);
+}
+
+#if IS_ENABLED(CONFIG_TI_GPMC_DEBUG)
+/**
+ * get_gpmc_timing_reg - read a timing parameter and print DTS settings for it.
+ * @cs:      Chip Select Region
+ * @reg:     GPMC_CS_CONFIGn register offset.
+ * @st_bit:  Start Bit
+ * @end_bit: End Bit. Must be >= @st_bit.
+ * @max:     Maximum parameter value (before optional @shift).
+ *           If 0, maximum is as high as @st_bit and @end_bit allow.
+ * @name:    DTS node name, w/o "gpmc,"
+ * @cd:      Clock Domain of timing parameter.
+ * @shift:   Parameter value left shifts @shift, which is then printed instead of value.
+ * @raw:     Raw Format Option.
+ *           raw format:  gpmc,name = <value>
+ *           tick format: gpmc,name = <value> /&zwj;* x ns -- y ns; x ticks *&zwj;/
+ *           Where x ns -- y ns result in the same tick value.
+ *           When @max is exceeded, "invalid" is printed inside comment.
+ * @noval:   Parameter values equal to 0 are not printed.
+ * @return:  Specified timing parameter (after optional @shift).
+ *
+ */
+static int get_gpmc_timing_reg(/* timing specifiers */
+	int cs, int reg, int st_bit, int end_bit, int max,
+	const char *name, const enum gpmc_clk_domain cd,
+	/* value transform */
+	int shift,
+	/* format specifiers */
+	bool raw, bool noval)
+{
+	u32 l;
+	int nr_bits;
+	int mask;
+	bool invalid;
+
+	l = gpmc_cs_read_reg(cs, reg);
+	nr_bits = end_bit - st_bit + 1;
+	mask = (1 << nr_bits) - 1;
+	l = (l >> st_bit) & mask;
+	if (!max)
+		max = mask;
+	invalid = l > max;
+	if (shift)
+		l = (shift << l);
+	if (noval && l == 0)
+		return 0;
+	if (!raw) {
+		/* DTS tick format for timings in ns */
+		unsigned int time_ns;
+		unsigned int time_ns_min = 0;
+
+		if (l)
+			time_ns_min = gpmc_clk_ticks_to_ns(l - 1, cs, cd) + 1;
+		time_ns = gpmc_clk_ticks_to_ns(l, cs, cd);
+		pr_info("gpmc,%s = <%u>; /* %u ns - %u ns; %i ticks%s*/\n",
+			name, time_ns, time_ns_min, time_ns, l,
+			invalid ? "; invalid " : " ");
+	} else {
+		/* raw format */
+		pr_info("gpmc,%s = <%u>;%s\n", name, l,
+			invalid ? " /* invalid */" : "");
+	}
+
+	return l;
+}
+
+#define GPMC_PRINT_CONFIG(cs, config) \
+	pr_info("CS%i %s: 0x%08x\n", cs, #config, \
+		gpmc_cs_read_reg(cs, config))
+#define GPMC_GET_RAW(reg, st, end, field) \
+	get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 1, 0)
+#define GPMC_GET_RAW_MAX(reg, st, end, max, field) \
+	get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, GPMC_CD_FCLK, 0, 1, 0)
+#define GPMC_GET_RAW_BOOL(reg, st, end, field) \
+	get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 1, 1)
+#define GPMC_GET_RAW_SHIFT_MAX(reg, st, end, shift, max, field) \
+	get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, GPMC_CD_FCLK, (shift), 1, 1)
+#define GPMC_GET_TICKS(reg, st, end, field) \
+	get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, GPMC_CD_FCLK, 0, 0, 0)
+#define GPMC_GET_TICKS_CD(reg, st, end, field, cd) \
+	get_gpmc_timing_reg(cs, (reg), (st), (end), 0, field, (cd), 0, 0, 0)
+#define GPMC_GET_TICKS_CD_MAX(reg, st, end, max, field, cd) \
+	get_gpmc_timing_reg(cs, (reg), (st), (end), (max), field, (cd), 0, 0, 0)
+
+static void gpmc_show_regs(int cs, const char *desc)
+{
+	pr_info("gpmc cs%i %s:\n", cs, desc);
+	GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG1);
+	GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG2);
+	GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG3);
+	GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG4);
+	GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG5);
+	GPMC_PRINT_CONFIG(cs, GPMC_CS_CONFIG6);
+}
+
+/*
+ * Note that gpmc,wait-pin handing wrongly assumes bit 8 is available,
+ * see commit c9fb809.
+ */
+static void gpmc_cs_show_timings(int cs, const char *desc)
+{
+	gpmc_show_regs(cs, desc);
+
+	pr_info("gpmc cs%i access configuration:\n", cs);
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1,  4,  4, "time-para-granularity");
+	GPMC_GET_RAW(GPMC_CS_CONFIG1,  8,  9, "mux-add-data");
+	GPMC_GET_RAW_SHIFT_MAX(GPMC_CS_CONFIG1, 12, 13, 1,
+			       GPMC_CONFIG1_DEVICESIZE_MAX, "device-width");
+	GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 22, 22, "wait-on-read");
+	GPMC_GET_RAW_SHIFT_MAX(GPMC_CS_CONFIG1, 23, 24, 4,
+			       GPMC_CONFIG1_ATTACHEDDEVICEPAGELENGTH_MAX,
+			       "burst-length");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 27, 27, "sync-write");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 28, 28, "burst-write");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 29, 29, "gpmc,sync-read");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 30, 30, "burst-read");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 31, 31, "burst-wrap");
+
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG2,  7,  7, "cs-extra-delay");
+
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG3,  7,  7, "adv-extra-delay");
+
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG4, 23, 23, "we-extra-delay");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG4,  7,  7, "oe-extra-delay");
+
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG6,  7,  7, "cycle2cycle-samecsen");
+	GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG6,  6,  6, "cycle2cycle-diffcsen");
+
+	pr_info("gpmc cs%i timings configuration:\n", cs);
+	GPMC_GET_TICKS(GPMC_CS_CONFIG2,  0,  3, "cs-on-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG2,  8, 12, "cs-rd-off-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG2, 16, 20, "cs-wr-off-ns");
+
+	GPMC_GET_TICKS(GPMC_CS_CONFIG3,  0,  3, "adv-on-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG3,  8, 12, "adv-rd-off-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG3, 16, 20, "adv-wr-off-ns");
+	if (gpmc_capability & GPMC_HAS_MUX_AAD) {
+		GPMC_GET_TICKS(GPMC_CS_CONFIG3, 4, 6, "adv-aad-mux-on-ns");
+		GPMC_GET_TICKS(GPMC_CS_CONFIG3, 24, 26,
+			       "adv-aad-mux-rd-off-ns");
+		GPMC_GET_TICKS(GPMC_CS_CONFIG3, 28, 30,
+			       "adv-aad-mux-wr-off-ns");
+	}
+
+	GPMC_GET_TICKS(GPMC_CS_CONFIG4,  0,  3, "oe-on-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG4,  8, 12, "oe-off-ns");
+	if (gpmc_capability & GPMC_HAS_MUX_AAD) {
+		GPMC_GET_TICKS(GPMC_CS_CONFIG4,  4,  6, "oe-aad-mux-on-ns");
+		GPMC_GET_TICKS(GPMC_CS_CONFIG4, 13, 15, "oe-aad-mux-off-ns");
+	}
+	GPMC_GET_TICKS(GPMC_CS_CONFIG4, 16, 19, "we-on-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG4, 24, 28, "we-off-ns");
+
+	GPMC_GET_TICKS(GPMC_CS_CONFIG5,  0,  4, "rd-cycle-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG5,  8, 12, "wr-cycle-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG5, 16, 20, "access-ns");
+
+	GPMC_GET_TICKS(GPMC_CS_CONFIG5, 24, 27, "page-burst-access-ns");
+
+	GPMC_GET_TICKS(GPMC_CS_CONFIG6, 0, 3, "bus-turnaround-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG6, 8, 11, "cycle2cycle-delay-ns");
+
+	GPMC_GET_TICKS_CD_MAX(GPMC_CS_CONFIG1, 18, 19,
+			      GPMC_CONFIG1_WAITMONITORINGTIME_MAX,
+			      "wait-monitoring-ns", GPMC_CD_CLK);
+	GPMC_GET_TICKS_CD_MAX(GPMC_CS_CONFIG1, 25, 26,
+			      GPMC_CONFIG1_CLKACTIVATIONTIME_MAX,
+			      "clk-activation-ns", GPMC_CD_FCLK);
+
+	GPMC_GET_TICKS(GPMC_CS_CONFIG6, 16, 19, "wr-data-mux-bus-ns");
+	GPMC_GET_TICKS(GPMC_CS_CONFIG6, 24, 28, "wr-access-ns");
+}
+#else
+static inline void gpmc_cs_show_timings(int cs, const char *desc)
+{
+}
+#endif
+
+/**
+ * set_gpmc_timing_reg - set a single timing parameter for Chip Select Region.
+ * Caller is expected to have initialized CONFIG1 GPMCFCLKDIVIDER
+ * prior to calling this function with @cd equal to GPMC_CD_CLK.
+ *
+ * @cs:      Chip Select Region.
+ * @reg:     GPMC_CS_CONFIGn register offset.
+ * @st_bit:  Start Bit
+ * @end_bit: End Bit. Must be >= @st_bit.
+ * @max:     Maximum parameter value.
+ *           If 0, maximum is as high as @st_bit and @end_bit allow.
+ * @time:    Timing parameter in ns.
+ * @cd:      Timing parameter clock domain.
+ * @name:    Timing parameter name.
+ * @return:  0 on success, -1 on error.
+ */
+static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, int max,
+			       int time, enum gpmc_clk_domain cd, const char *name)
+{
+	u32 l;
+	int ticks, mask, nr_bits;
+
+	if (time == 0)
+		ticks = 0;
+	else
+		ticks = gpmc_ns_to_clk_ticks(time, cs, cd);
+	nr_bits = end_bit - st_bit + 1;
+	mask = (1 << nr_bits) - 1;
+
+	if (!max)
+		max = mask;
+
+	if (ticks > max) {
+		pr_err("%s: GPMC CS%d: %s %d ns, %d ticks > %d ticks\n",
+		       __func__, cs, name, time, ticks, max);
+
+		return -1;
+	}
+
+	l = gpmc_cs_read_reg(cs, reg);
+	if (IS_ENABLED(CONFIG_TI_GPMC_DEBUG)) {
+		pr_info("GPMC CS%d: %-17s: %3d ticks, %3lu ns (was %3i ticks) %3d ns\n",
+			cs, name, ticks, gpmc_get_clk_period(cs, cd) * ticks / 1000,
+				(l >> st_bit) & mask, time);
+	}
+
+	l &= ~(mask << st_bit);
+	l |= ticks << st_bit;
+	gpmc_cs_write_reg(cs, reg, l);
+
+	return 0;
+}
+
+/**
+ * gpmc_calc_waitmonitoring_divider - calculate proper GPMCFCLKDIVIDER based on WAITMONITORINGTIME
+ * WAITMONITORINGTIME will be _at least_ as long as desired, i.e.
+ * read  --> don't sample bus too early
+ * write --> data is longer on bus
+ *
+ * Formula:
+ * gpmc_clk_div + 1 = ceil(ceil(waitmonitoringtime_ns / gpmc_fclk_ns)
+ *                    / waitmonitoring_ticks)
+ * WAITMONITORINGTIME resulting in 0 or 1 tick with div = 1 are caught by
+ * div <= 0 check.
+ *
+ * @wait_monitoring: WAITMONITORINGTIME in ns.
+ * @return:          -1 on failure to scale, else proper divider > 0.
+ */
+static int gpmc_calc_waitmonitoring_divider(unsigned int wait_monitoring)
+{
+	int div = gpmc_ns_to_ticks(wait_monitoring);
+
+	div += GPMC_CONFIG1_WAITMONITORINGTIME_MAX - 1;
+	div /= GPMC_CONFIG1_WAITMONITORINGTIME_MAX;
+
+	if (div > 4)
+		return -1;
+	if (div <= 0)
+		div = 1;
+
+	return div;
+}
+
+/**
+ * gpmc_calc_divider - calculate GPMC_FCLK divider for sync_clk GPMC_CLK period.
+ * @sync_clk: GPMC_CLK period in ps.
+ * @return:   Returns at least 1 if GPMC_FCLK can be divided to GPMC_CLK.
+ *            Else, returns -1.
+ */
+static int gpmc_calc_divider(unsigned int sync_clk)
+{
+	int div = gpmc_ps_to_ticks(sync_clk);
+
+	if (div > 4)
+		return -1;
+	if (div <= 0)
+		div = 1;
+
+	return div;
+}
+
+/**
+ * gpmc_cs_set_timings - program timing parameters for Chip Select Region.
+ * @cs:     Chip Select Region.
+ * @t:      GPMC timing parameters.
+ * @s:      GPMC timing settings.
+ * @return: 0 on success, -1 on error.
+ */
+static int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
+			       const struct gpmc_settings *s)
+{
+	int div, ret;
+	u32 l;
+
+	div = gpmc_calc_divider(t->sync_clk);
+	if (div < 0)
+		return -EINVAL;
+
+	/*
+	 * See if we need to change the divider for waitmonitoringtime.
+	 *
+	 * Calculate GPMCFCLKDIVIDER independent of gpmc,sync-clk-ps in DT for
+	 * pure asynchronous accesses, i.e. both read and write asynchronous.
+	 * However, only do so if WAITMONITORINGTIME is actually used, i.e.
+	 * either WAITREADMONITORING or WAITWRITEMONITORING is set.
+	 *
+	 * This statement must not change div to scale async WAITMONITORINGTIME
+	 * to protect mixed synchronous and asynchronous accesses.
+	 *
+	 * We raise an error later if WAITMONITORINGTIME does not fit.
+	 */
+	if (!s->sync_read && !s->sync_write &&
+	    (s->wait_on_read || s->wait_on_write)
+	   ) {
+		div = gpmc_calc_waitmonitoring_divider(t->wait_monitoring);
+		if (div < 0) {
+			pr_err("%s: waitmonitoringtime %3d ns too large for greatest gpmcfclkdivider.\n",
+			       __func__,
+			       t->wait_monitoring
+			       );
+			return -ENXIO;
+		}
+	}
+
+	ret = 0;
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 0, 3, 0, t->cs_on,
+				   GPMC_CD_FCLK, "cs_on");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 8, 12, 0, t->cs_rd_off,
+				   GPMC_CD_FCLK, "cs_rd_off");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG2, 16, 20, 0, t->cs_wr_off,
+				   GPMC_CD_FCLK, "cs_wr_off");
+	if (ret)
+		return -ENXIO;
+
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 0, 3, 0, t->adv_on,
+				   GPMC_CD_FCLK, "adv_on");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 8, 12, 0, t->adv_rd_off,
+				   GPMC_CD_FCLK, "adv_rd_off");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 16, 20, 0, t->adv_wr_off,
+				   GPMC_CD_FCLK, "adv_wr_off");
+	if (ret)
+		return -ENXIO;
+
+	if (gpmc_capability & GPMC_HAS_MUX_AAD) {
+		ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 4, 6, 0,
+					   t->adv_aad_mux_on, GPMC_CD_FCLK,
+					   "adv_aad_mux_on");
+		ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 24, 26, 0,
+					   t->adv_aad_mux_rd_off, GPMC_CD_FCLK,
+					   "adv_aad_mux_rd_off");
+		ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG3, 28, 30, 0,
+					   t->adv_aad_mux_wr_off, GPMC_CD_FCLK,
+					   "adv_aad_mux_wr_off");
+		if (ret)
+			return -ENXIO;
+	}
+
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 0, 3, 0, t->oe_on,
+				   GPMC_CD_FCLK, "oe_on");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 8, 12, 0, t->oe_off,
+				   GPMC_CD_FCLK, "oe_off");
+	if (gpmc_capability & GPMC_HAS_MUX_AAD) {
+		ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 4, 6, 0,
+					   t->oe_aad_mux_on, GPMC_CD_FCLK,
+					   "oe_aad_mux_on");
+		ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 13, 15, 0,
+					   t->oe_aad_mux_off, GPMC_CD_FCLK,
+					   "oe_aad_mux_off");
+	}
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 16, 19, 0, t->we_on,
+				   GPMC_CD_FCLK, "we_on");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG4, 24, 28, 0, t->we_off,
+				   GPMC_CD_FCLK, "we_off");
+	if (ret)
+		return -ENXIO;
+
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 0, 4, 0, t->rd_cycle,
+				   GPMC_CD_FCLK, "rd_cycle");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 8, 12, 0, t->wr_cycle,
+				   GPMC_CD_FCLK, "wr_cycle");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 16, 20, 0, t->access,
+				   GPMC_CD_FCLK, "access");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG5, 24, 27, 0,
+				   t->page_burst_access, GPMC_CD_FCLK,
+				   "page_burst_access");
+	if (ret)
+		return -ENXIO;
+
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 0, 3, 0,
+				   t->bus_turnaround, GPMC_CD_FCLK,
+				   "bus_turnaround");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 8, 11, 0,
+				   t->cycle2cycle_delay, GPMC_CD_FCLK,
+				   "cycle2cycle_delay");
+	if (ret)
+		return -ENXIO;
+
+	if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS) {
+		ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 16, 19, 0,
+					   t->wr_data_mux_bus, GPMC_CD_FCLK,
+					   "wr_data_mux_bus");
+		if (ret)
+			return -ENXIO;
+	}
+	if (gpmc_capability & GPMC_HAS_WR_ACCESS) {
+		ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG6, 24, 28, 0,
+					   t->wr_access, GPMC_CD_FCLK,
+					   "wr_access");
+		if (ret)
+			return -ENXIO;
+	}
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+	l &= ~0x03;
+	l |= (div - 1);
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
+
+	ret = 0;
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG1, 18, 19,
+				   GPMC_CONFIG1_WAITMONITORINGTIME_MAX,
+				   t->wait_monitoring, GPMC_CD_CLK,
+				   "wait_monitoring");
+	ret |= set_gpmc_timing_reg(cs, GPMC_CS_CONFIG1, 25, 26,
+				   GPMC_CONFIG1_CLKACTIVATIONTIME_MAX,
+				   t->clk_activation, GPMC_CD_FCLK,
+				   "clk_activation");
+	if (ret)
+		return -ENXIO;
+
+	if (IS_ENABLED(CONFIG_TI_GPMC_DEBUG)) {
+		pr_info("GPMC CS%d CLK period is %lu ns (div %d)\n",
+			cs, (div * gpmc_get_fclk_period()) / 1000, div);
+	}
+
+	gpmc_cs_bool_timings(cs, &t->bool_timings);
+	gpmc_cs_show_timings(cs, "after gpmc_set_timings");
+
+	return 0;
+}
+
+static int gpmc_cs_set_memconf(int cs, resource_size_t base, u32 size)
+{
+	u32 l;
+	u32 mask;
+
+	/*
+	 * Ensure that base address is aligned on a
+	 * boundary equal to or greater than size.
+	 */
+	if (base & (size - 1))
+		return -EINVAL;
+
+	base >>= GPMC_CHUNK_SHIFT;
+	mask = (1 << GPMC_SECTION_SHIFT) - size;
+	mask >>= GPMC_CHUNK_SHIFT;
+	mask <<= GPMC_CONFIG7_MASKADDRESS_OFFSET;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+	l &= ~GPMC_CONFIG7_MASK;
+	l |= base & GPMC_CONFIG7_BASEADDRESS_MASK;
+	l |= mask & GPMC_CONFIG7_MASKADDRESS_MASK;
+	l |= GPMC_CONFIG7_CSVALID;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+
+	return 0;
+}
+
+static void gpmc_cs_enable_mem(int cs)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+	l |= GPMC_CONFIG7_CSVALID;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_disable_mem(int cs)
+{
+	u32 l;
+
+	l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+	l &= ~GPMC_CONFIG7_CSVALID;
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+}
+
+static void gpmc_cs_set_reserved(int cs, int reserved)
+{
+	struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+	gpmc->flags |= GPMC_CS_RESERVED;
+}
+
+static bool gpmc_cs_reserved(int cs)
+{
+	struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+	return gpmc->flags & GPMC_CS_RESERVED;
+}
+
+static unsigned long gpmc_mem_align(unsigned long size)
+{
+	int order;
+
+	size = (size - 1) >> (GPMC_CHUNK_SHIFT - 1);
+	order = GPMC_CHUNK_SHIFT - 1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	size = 1 << order;
+	return size;
+}
+
+static int gpmc_cs_request(ofnode node, int cs, struct resource *res)
+{
+	int r = -1;
+	u32 size;
+	resource_size_t addr_base = res->start;
+
+	if (cs >= gpmc_cs_num) {
+		pr_err("%s: requested chip-select is disabled\n", __func__);
+		return -ENODEV;
+	}
+
+	size = gpmc_mem_align(resource_size(res));
+	if (size > (1 << GPMC_SECTION_SHIFT))
+		return -ENOMEM;
+
+	if (gpmc_cs_reserved(cs)) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	if (addr_base & (SZ_16M - 1)) {
+		pr_err("CS region should be aligned to 16M boundary\n");
+		goto out;
+	}
+
+	/* Disable CS while changing base address and size mask */
+	gpmc_cs_disable_mem(cs);
+
+	r = gpmc_cs_set_memconf(cs, addr_base, size);
+	if (r < 0)
+		goto out;
+
+	/* Enable CS */
+	gpmc_cs_enable_mem(cs);
+	gpmc_cs_set_reserved(cs, 1);
+out:
+	return r;
+}
+
+static void gpmc_cs_free(int cs)
+{
+	if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
+		pr_warn("Trying to free non-reserved GPMC CS%d\n", cs);
+		return;
+	}
+
+	gpmc_cs_disable_mem(cs);
+	gpmc_cs_set_reserved(cs, 0);
+}
+
+/**
+ * gpmc_configure - write request to configure gpmc
+ * @cmd: command type
+ * @wval: value to write
+ * @return status of the operation
+ */
+static 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;
+}
+
+/**
+ * gpmc_cs_program_settings - programs non-timing related settings
+ * @cs:		GPMC chip-select to program
+ * @p:		pointer to GPMC settings structure
+ *
+ * Programs non-timing related settings for a GPMC chip-select, such as
+ * bus-width, burst configuration, etc. Function should be called once
+ * for each chip-select that is being used and must be called before
+ * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1
+ * register will be initialised to zero by this function. Returns 0 on
+ * success and appropriate negative error code on failure.
+ */
+static int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
+{
+	u32 config1;
+
+	if (!p->device_width || p->device_width > GPMC_DEVWIDTH_16BIT) {
+		pr_err("%s: invalid width %d!", __func__, p->device_width);
+		return -EINVAL;
+	}
+
+	/* Address-data multiplexing not supported for NAND devices */
+	if (p->device_nand && p->mux_add_data) {
+		pr_err("%s: invalid configuration!\n", __func__);
+		return -EINVAL;
+	}
+
+	if (p->mux_add_data > GPMC_MUX_AD ||
+	    (p->mux_add_data == GPMC_MUX_AAD &&
+	     !(gpmc_capability & GPMC_HAS_MUX_AAD))) {
+		pr_err("%s: invalid multiplex configuration!\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Page/burst mode supports lengths of 4, 8 and 16 bytes */
+	if (p->burst_read || p->burst_write) {
+		switch (p->burst_len) {
+		case GPMC_BURST_4:
+		case GPMC_BURST_8:
+		case GPMC_BURST_16:
+			break;
+		default:
+			pr_err("%s: invalid page/burst-length (%d)\n",
+			       __func__, p->burst_len);
+			return -EINVAL;
+		}
+	}
+
+	if (p->wait_pin > gpmc_nr_waitpins) {
+		pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
+		return -EINVAL;
+	}
+
+	config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
+
+	if (p->sync_read)
+		config1 |= GPMC_CONFIG1_READTYPE_SYNC;
+	if (p->sync_write)
+		config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
+	if (p->wait_on_read)
+		config1 |= GPMC_CONFIG1_WAIT_READ_MON;
+	if (p->wait_on_write)
+		config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
+	if (p->wait_on_read || p->wait_on_write)
+		config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
+	if (p->device_nand)
+		config1	|= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
+	if (p->mux_add_data)
+		config1	|= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
+	if (p->burst_read)
+		config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
+	if (p->burst_write)
+		config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+	if (p->burst_read || p->burst_write) {
+		config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+		config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+	}
+
+	gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
+
+	return 0;
+}
+
+static void gpmc_cs_set_name(int cs, const char *name)
+{
+	struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+	gpmc->name = name;
+}
+
+static const char *gpmc_cs_get_name(int cs)
+{
+	struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
+
+	return gpmc->name;
+}
+
+/**
+ * gpmc_read_settings_dt - read gpmc settings from device-tree
+ * @np:		pointer to device-tree node for a gpmc child device
+ * @p:		pointer to gpmc settings structure
+ *
+ * Reads the GPMC settings for a GPMC child device from device-tree and
+ * stores them in the GPMC settings structure passed. The GPMC settings
+ * structure is initialised to zero by this function and so any
+ * previously stored settings will be cleared.
+ */
+static void gpmc_read_settings_dt(ofnode np, struct gpmc_settings *p)
+{
+	memset(p, 0, sizeof(struct gpmc_settings));
+
+	p->sync_read = ofnode_read_bool(np, "gpmc,sync-read");
+	p->sync_write = ofnode_read_bool(np, "gpmc,sync-write");
+	ofnode_read_u32(np, "gpmc,device-width", &p->device_width);
+	ofnode_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
+
+	if (!ofnode_read_u32(np, "gpmc,burst-length", &p->burst_len)) {
+		p->burst_wrap = ofnode_read_bool(np, "gpmc,burst-wrap");
+		p->burst_read = ofnode_read_bool(np, "gpmc,burst-read");
+		p->burst_write = ofnode_read_bool(np, "gpmc,burst-write");
+		if (!p->burst_read && !p->burst_write)
+			pr_warn("%s: page/burst-length set but not used!\n",
+				__func__);
+	}
+
+	if (!ofnode_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) {
+		p->wait_on_read = ofnode_read_bool(np,
+						   "gpmc,wait-on-read");
+		p->wait_on_write = ofnode_read_bool(np,
+						    "gpmc,wait-on-write");
+		if (!p->wait_on_read && !p->wait_on_write)
+			pr_debug("%s: rd/wr wait monitoring not enabled!\n",
+				 __func__);
+	}
+}
+
+static void gpmc_read_timings_dt(ofnode np,
+				 struct gpmc_timings *gpmc_t)
+{
+	struct gpmc_bool_timings *p;
+
+	if (!gpmc_t)
+		return;
+
+	memset(gpmc_t, 0, sizeof(*gpmc_t));
+
+	/* minimum clock period for syncronous mode */
+	ofnode_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk);
+
+	/* chip select timtings */
+	ofnode_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on);
+	ofnode_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off);
+	ofnode_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off);
+
+	/* ADV signal timings */
+	ofnode_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on);
+	ofnode_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off);
+	ofnode_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off);
+	ofnode_read_u32(np, "gpmc,adv-aad-mux-on-ns",
+			&gpmc_t->adv_aad_mux_on);
+	ofnode_read_u32(np, "gpmc,adv-aad-mux-rd-off-ns",
+			&gpmc_t->adv_aad_mux_rd_off);
+	ofnode_read_u32(np, "gpmc,adv-aad-mux-wr-off-ns",
+			&gpmc_t->adv_aad_mux_wr_off);
+
+	/* WE signal timings */
+	ofnode_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on);
+	ofnode_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off);
+
+	/* OE signal timings */
+	ofnode_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on);
+	ofnode_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off);
+	ofnode_read_u32(np, "gpmc,oe-aad-mux-on-ns",
+			&gpmc_t->oe_aad_mux_on);
+	ofnode_read_u32(np, "gpmc,oe-aad-mux-off-ns",
+			&gpmc_t->oe_aad_mux_off);
+
+	/* access and cycle timings */
+	ofnode_read_u32(np, "gpmc,page-burst-access-ns",
+			&gpmc_t->page_burst_access);
+	ofnode_read_u32(np, "gpmc,access-ns", &gpmc_t->access);
+	ofnode_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle);
+	ofnode_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle);
+	ofnode_read_u32(np, "gpmc,bus-turnaround-ns",
+			&gpmc_t->bus_turnaround);
+	ofnode_read_u32(np, "gpmc,cycle2cycle-delay-ns",
+			&gpmc_t->cycle2cycle_delay);
+	ofnode_read_u32(np, "gpmc,wait-monitoring-ns",
+			&gpmc_t->wait_monitoring);
+	ofnode_read_u32(np, "gpmc,clk-activation-ns",
+			&gpmc_t->clk_activation);
+
+	/* only applicable to OMAP3+ */
+	ofnode_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access);
+	ofnode_read_u32(np, "gpmc,wr-data-mux-bus-ns",
+			&gpmc_t->wr_data_mux_bus);
+
+	/* bool timing parameters */
+	p = &gpmc_t->bool_timings;
+
+	p->cycle2cyclediffcsen =
+		ofnode_read_bool(np, "gpmc,cycle2cycle-diffcsen");
+	p->cycle2cyclesamecsen =
+		ofnode_read_bool(np, "gpmc,cycle2cycle-samecsen");
+	p->we_extra_delay = ofnode_read_bool(np, "gpmc,we-extra-delay");
+	p->oe_extra_delay = ofnode_read_bool(np, "gpmc,oe-extra-delay");
+	p->adv_extra_delay = ofnode_read_bool(np, "gpmc,adv-extra-delay");
+	p->cs_extra_delay = ofnode_read_bool(np, "gpmc,cs-extra-delay");
+	p->time_para_granularity =
+		ofnode_read_bool(np, "gpmc,time-para-granularity");
+}
+
+/**
+ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @dev:	pointer to gpmc platform device
+ * @child:	pointer to device-tree node for child device
+ *
+ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_generic_child(struct udevice *dev,
+				    ofnode child)
+{
+	struct gpmc_settings gpmc_s;
+	struct gpmc_timings gpmc_t;
+	struct resource res;
+	const char *name;
+	int ret;
+	u32 val, cs;
+
+	if (ofnode_read_u32(child, "reg", &cs) < 0) {
+		dev_err(dev, "can't get reg property of child %s\n",
+			ofnode_get_name(child));
+		return -ENODEV;
+	}
+
+	if (ofnode_read_resource(child, 0, &res) < 0) {
+		dev_err(dev, "%s has malformed 'reg' property\n",
+			ofnode_get_name(child));
+		return -ENODEV;
+	}
+
+	/*
+	 * Check if we have multiple instances of the same device
+	 * on a single chip select. If so, use the already initialized
+	 * timings.
+	 */
+	name = gpmc_cs_get_name(cs);
+	if (name && !strcmp(name, ofnode_get_name(child)))
+		goto no_timings;
+
+	ret = gpmc_cs_request(child, cs, &res);
+	if (ret < 0) {
+		dev_err(dev, "cannot request GPMC CS %d\n", cs);
+		return ret;
+	}
+	gpmc_cs_set_name(cs, ofnode_get_name(child));
+
+	gpmc_read_settings_dt(child, &gpmc_s);
+	gpmc_read_timings_dt(child, &gpmc_t);
+
+	/*
+	 * For some GPMC devices we still need to rely on the bootloader
+	 * timings because the devices can be connected via FPGA.
+	 * REVISIT: Add timing support from slls644g.pdf.
+	 */
+	if (!gpmc_t.cs_rd_off) {
+		pr_warn("enable GPMC debug to configure .dts timings for CS%i\n",
+			cs);
+		gpmc_cs_show_timings(cs,
+				     "please add GPMC bootloader timings to .dts");
+		goto no_timings;
+	}
+
+	/* CS must be disabled while making changes to gpmc configuration */
+	gpmc_cs_disable_mem(cs);
+
+	if (!ofnode_read_u32(child, "nand-bus-width", &val)) {
+		/* NAND specific setup */
+		ofnode_read_u32(child, "nand-bus-width", &val);
+		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(dev, "%s: invalid 'nand-bus-width'\n",
+				ofnode_get_name(child));
+			ret = -EINVAL;
+			goto err;
+		}
+
+		/* disable write protect */
+		gpmc_configure(GPMC_CONFIG_WP, 0);
+		gpmc_s.device_nand = true;
+	} else {
+		ret = ofnode_read_u32(child, "bank-width",
+				      &gpmc_s.device_width);
+		if (ret < 0 && !gpmc_s.device_width) {
+			dev_err(dev,
+				"%s has no 'gpmc,device-width' property\n",
+				ofnode_get_name(child));
+			goto err;
+		}
+	}
+
+	gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings");
+
+	ret = gpmc_cs_program_settings(cs, &gpmc_s);
+	if (ret < 0)
+		goto err;
+
+	ret = gpmc_cs_set_timings(cs, &gpmc_t, &gpmc_s);
+	if (ret) {
+		dev_err(dev, "failed to set gpmc timings for: %s\n",
+			ofnode_get_name(child));
+		goto err;
+	}
+
+	/* Clear limited address i.e. enable A26-A11 */
+	val = gpmc_read_reg(GPMC_CONFIG);
+	val &= ~GPMC_CONFIG_LIMITEDADDRESS;
+	gpmc_write_reg(GPMC_CONFIG, val);
+
+	/* Enable CS region */
+	gpmc_cs_enable_mem(cs);
+
+no_timings:
+
+	return 0;
+
+err:
+	gpmc_cs_free(cs);
+
+	return ret;
+}
+
+static void gpmc_probe_dt_children(struct udevice *dev)
+{
+	int ret;
+	ofnode child;
+
+	ofnode_for_each_subnode(child, dev_ofnode(dev)) {
+		ret = gpmc_probe_generic_child(dev, child);
+		if (ret) {
+			dev_err(dev, "Cannot parse child %s:%d",
+				ofnode_get_name(child), ret);
+		}
+	}
+}
+
+static int gpmc_parse_dt(struct udevice *dev, struct ti_gpmc *gpmc)
+{
+	int ret;
+	u32 val;
+
+	ret = ofnode_read_u32(dev_ofnode(dev), "gpmc,num-cs",
+			      &val);
+	if (ret < 0) {
+		pr_err("%s: number of chip-selects not defined\n", __func__);
+		return ret;
+	} else if (val < 1) {
+		pr_err("%s: all chip-selects are disabled\n", __func__);
+		return -EINVAL;
+	} else if (val > GPMC_CS_NUM) {
+		pr_err("%s: number of supported chip-selects cannot be > %d\n",
+		       __func__, GPMC_CS_NUM);
+		return -EINVAL;
+	}
+
+	gpmc->cs_num = val;
+	gpmc_cs_num = val;
+
+	ret = ofnode_read_u32(dev_ofnode(dev), "gpmc,num-waitpins",
+			      &gpmc->nr_waitpins);
+	if (ret < 0) {
+		pr_err("%s: number of wait pins not found!\n", __func__);
+		return ret;
+	}
+
+	gpmc_nr_waitpins = gpmc->nr_waitpins;
+
+	return 0;
+}
+
+static int gpmc_probe(struct udevice *dev)
+{
+	struct ti_gpmc *priv = dev_get_priv(dev);
+	int ret;
+	struct resource res;
+
+	ret = dev_read_resource_byname(dev, "cfg", &res);
+	if (ret) {
+		/* Legacy DT */
+		dev_read_resource(dev, 0, &res);
+		priv->base = devm_ioremap(dev, res.start, resource_size(&res));
+
+		priv->data.start = GPMC_MEM_START;
+		priv->data.end = GPMC_MEM_END;
+	} else {
+		priv->base = devm_ioremap(dev, res.start, resource_size(&res));
+		ret = dev_read_resource_byname(dev, "data", &res);
+		if (ret)
+			return -ENOENT;
+
+		priv->data = res;
+	}
+
+	if (!priv->base)
+		return -ENOMEM;
+
+	gpmc_cfg = (struct gpmc *)priv->base;
+	gpmc_base = priv->base;
+
+	priv->l3_clk = devm_clk_get(dev, "fck");
+	if (IS_ERR(priv->l3_clk))
+		return PTR_ERR(priv->l3_clk);
+
+	if (!clk_get_rate(priv->l3_clk))
+		return -EINVAL;
+
+	gpmc_l3_clk = priv->l3_clk;
+
+	ret = gpmc_parse_dt(dev, priv);
+	if (ret)
+		return ret;
+
+	priv->capability_flags = dev->driver->of_match->data;
+	gpmc_capability = priv->capability_flags;
+
+	gpmc_probe_dt_children(dev);
+
+	return 0;
+}
+
+#define GPMC_DATA_REV2_4 0
+#define GPMC_DATA_REV5 (GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS)
+#define GPMC_DATA_REV6 (GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS | GPMC_HAS_MUX_AAD)
+
+static const struct udevice_id gpmc_dt_ids[] = {
+	{ .compatible = "ti,am64-gpmc", .data = GPMC_DATA_REV6, },
+	{ .compatible = "ti,am3352-gpmc", .data = GPMC_DATA_REV5, },
+	{ .compatible = "ti,omap2420-gpmc", .data = GPMC_DATA_REV2_4, },
+	{ .compatible = "ti,omap2430-gpmc", .data = GPMC_DATA_REV2_4, },
+	{ .compatible = "ti,omap3430-gpmc", .data = GPMC_DATA_REV5, },
+	{ .compatible = "ti,omap4430-gpmc", .data = GPMC_DATA_REV6, },
+	{ } /* sentinel */
+};
+
+U_BOOT_DRIVER(ti_gpmc) = {
+	.name   = "ti-gpmc",
+	.id     = UCLASS_MEMORY,
+	.of_match = gpmc_dt_ids,
+	.probe  = gpmc_probe,
+	.flags  = DM_FLAG_ALLOC_PRIV_DMA,
+};
diff --git a/drivers/memory/ti-gpmc.h b/drivers/memory/ti-gpmc.h
new file mode 100644
index 0000000000..90f8e656c8
--- /dev/null
+++ b/drivers/memory/ti-gpmc.h
@@ -0,0 +1,298 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Texas Instruments GPMC Driver
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/* 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_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 */
+
+/* GPMC ECC control settings */
+#define GPMC_ECC_CTRL_ECCCLEAR		0x100
+#define GPMC_ECC_CTRL_ECCDISABLE	0x000
+#define GPMC_ECC_CTRL_ECCREG1		0x001
+#define GPMC_ECC_CTRL_ECCREG2		0x002
+#define GPMC_ECC_CTRL_ECCREG3		0x003
+#define GPMC_ECC_CTRL_ECCREG4		0x004
+#define GPMC_ECC_CTRL_ECCREG5		0x005
+#define GPMC_ECC_CTRL_ECCREG6		0x006
+#define GPMC_ECC_CTRL_ECCREG7		0x007
+#define GPMC_ECC_CTRL_ECCREG8		0x008
+#define GPMC_ECC_CTRL_ECCREG9		0x009
+
+#define GPMC_CONFIG_LIMITEDADDRESS		BIT(1)
+
+#define GPMC_STATUS_EMPTYWRITEBUFFERSTATUS	BIT(0)
+
+#define	GPMC_CONFIG2_CSEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG3_ADVEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG4_OEEXTRADELAY		BIT(7)
+#define	GPMC_CONFIG4_WEEXTRADELAY		BIT(23)
+#define	GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN	BIT(6)
+#define	GPMC_CONFIG6_CYCLE2CYCLESAMECSEN	BIT(7)
+
+#define GPMC_CS0_OFFSET		0x60
+#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 */
+#define GPMC_SECTION_SHIFT	28		/* 128 MB */
+
+#define CS_NUM_SHIFT		24
+#define ENABLE_PREFETCH		(0x1 << 7)
+#define DMA_MPU_MODE		2
+
+#define	GPMC_REVISION_MAJOR(l)		(((l) >> 4) & 0xf)
+#define	GPMC_REVISION_MINOR(l)		((l) & 0xf)
+
+#define	GPMC_HAS_WR_ACCESS		0x1
+#define	GPMC_HAS_WR_DATA_MUX_BUS	0x2
+#define	GPMC_HAS_MUX_AAD		0x4
+
+#define GPMC_NR_WAITPINS		4
+
+#define GPMC_CS_CONFIG1		0x00
+#define GPMC_CS_CONFIG2		0x04
+#define GPMC_CS_CONFIG3		0x08
+#define GPMC_CS_CONFIG4		0x0c
+#define GPMC_CS_CONFIG5		0x10
+#define GPMC_CS_CONFIG6		0x14
+#define GPMC_CS_CONFIG7		0x18
+#define GPMC_CS_NAND_COMMAND	0x1c
+#define GPMC_CS_NAND_ADDRESS	0x20
+#define GPMC_CS_NAND_DATA	0x24
+
+/* Control Commands */
+#define GPMC_CONFIG_RDY_BSY	0x00000001
+#define GPMC_CONFIG_DEV_SIZE	0x00000002
+#define GPMC_CONFIG_DEV_TYPE	0x00000003
+
+#define GPMC_CONFIG_WP          0x00000005
+
+#define GPMC_CONFIG1_WRAPBURST_SUPP     BIT(31)
+#define GPMC_CONFIG1_READMULTIPLE_SUPP  BIT(30)
+#define GPMC_CONFIG1_READTYPE_ASYNC     (0 << 29)
+#define GPMC_CONFIG1_READTYPE_SYNC      BIT(29)
+#define GPMC_CONFIG1_WRITEMULTIPLE_SUPP BIT(28)
+#define GPMC_CONFIG1_WRITETYPE_ASYNC    (0 << 27)
+#define GPMC_CONFIG1_WRITETYPE_SYNC     BIT(27)
+#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) (((val) & 3) << 25)
+/** CLKACTIVATIONTIME Max Ticks */
+#define GPMC_CONFIG1_CLKACTIVATIONTIME_MAX 2
+#define GPMC_CONFIG1_PAGE_LEN(val)      (((val) & 3) << 23)
+/** ATTACHEDDEVICEPAGELENGTH Max Value */
+#define GPMC_CONFIG1_ATTACHEDDEVICEPAGELENGTH_MAX 2
+#define GPMC_CONFIG1_WAIT_READ_MON      BIT(22)
+#define GPMC_CONFIG1_WAIT_WRITE_MON     BIT(21)
+#define GPMC_CONFIG1_WAIT_MON_TIME(val) (((val) & 3) << 18)
+/** WAITMONITORINGTIME Max Ticks */
+#define GPMC_CONFIG1_WAITMONITORINGTIME_MAX  2
+#define GPMC_CONFIG1_WAIT_PIN_SEL(val)  (((val) & 3) << 16)
+#define GPMC_CONFIG1_DEVICESIZE(val)    (((val) & 3) << 12)
+#define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
+/** DEVICESIZE Max Value */
+#define GPMC_CONFIG1_DEVICESIZE_MAX     1
+#define GPMC_CONFIG1_DEVICETYPE(val)    (((val) & 3) << 10)
+#define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
+#define GPMC_CONFIG1_MUXTYPE(val)       (((val) & 3) << 8)
+#define GPMC_CONFIG1_TIME_PARA_GRAN     BIT(4)
+#define GPMC_CONFIG1_FCLK_DIV(val)      ((val) & 3)
+#define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
+#define GPMC_CONFIG1_FCLK_DIV3          (GPMC_CONFIG1_FCLK_DIV(2))
+#define GPMC_CONFIG1_FCLK_DIV4          (GPMC_CONFIG1_FCLK_DIV(3))
+#define GPMC_CONFIG7_CSVALID		BIT(6)
+
+#define GPMC_CONFIG7_BASEADDRESS_MASK	0x3f
+#define GPMC_CONFIG7_CSVALID_MASK	BIT(6)
+#define GPMC_CONFIG7_MASKADDRESS_OFFSET	8
+#define GPMC_CONFIG7_MASKADDRESS_MASK	(0xf << GPMC_CONFIG7_MASKADDRESS_OFFSET)
+/* All CONFIG7 bits except reserved bits */
+#define GPMC_CONFIG7_MASK		(GPMC_CONFIG7_BASEADDRESS_MASK | \
+					 GPMC_CONFIG7_CSVALID_MASK |     \
+					 GPMC_CONFIG7_MASKADDRESS_MASK)
+
+#define GPMC_DEVICETYPE_NOR		0
+#define GPMC_DEVICETYPE_NAND		2
+#define GPMC_CONFIG_WRITEPROTECT	0x00000010
+#define WR_RD_PIN_MONITORING		0x00600000
+
+/* ECC commands */
+#define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
+#define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
+#define GPMC_ECC_READSYN	2 /* Reset before syndrom is read back */
+
+#define	GPMC_NR_NAND_IRQS	2 /* number of NAND specific IRQs */
+
+/* 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 */
+	u32 adv_aad_mux_on;	/* ADV assertion time for AAD */
+	u32 adv_aad_mux_rd_off;	/* ADV read deassertion time for AAD */
+	u32 adv_aad_mux_wr_off;	/* ADV write deassertion time for AAD */
+
+	/* 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 */
+	u32 oe_aad_mux_on;	/* OE assertion time for AAD */
+	u32 oe_aad_mux_off;	/* OE deassertion time for AAD */
+
+	/* 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 */
+};
diff --git a/include/linux/mtd/omap_gpmc.h b/include/linux/mtd/omap_gpmc.h
index 864b05e432..f08e700a1d 100644
--- a/include/linux/mtd/omap_gpmc.h
+++ b/include/linux/mtd/omap_gpmc.h
@@ -8,6 +8,9 @@
 #ifndef __ASM_OMAP_GPMC_H
 #define __ASM_OMAP_GPMC_H
 
+/* Maximum Number of Chip Selects */
+#define GPMC_CS_NUM	8
+
 #define GPMC_BUF_EMPTY	0
 #define GPMC_BUF_FULL	1
 #define GPMC_MAX_SECTORS	8
-- 
2.17.1


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

* Re: [u-boot][PATCH v2 1/4] dm: memory: Introduce new uclass
  2022-10-06 13:23 ` [u-boot][PATCH v2 1/4] dm: memory: Introduce new uclass Roger Quadros
@ 2022-10-06 19:07   ` Simon Glass
  0 siblings, 0 replies; 15+ messages in thread
From: Simon Glass @ 2022-10-06 19:07 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Tom Rini, U-Boot Mailing List, Praneeth Bajjuri, Kishon Vijay Abraham I

Hi Roger,

On Thu, 6 Oct 2022 at 07:24, Roger Quadros <rogerq@kernel.org> wrote:
>
> Introduce UCLASS_MEMORY for future Memory Controller
> device drivers.
>
> Signed-off-by: Roger Quadros <rogerq@kernel.org>
> ---
>  arch/sandbox/dts/test.dts       |  4 ++++
>  drivers/memory/Kconfig          | 17 +++++++++++++++++
>  drivers/memory/Makefile         |  2 ++
>  drivers/memory/memory-sandbox.c | 18 ++++++++++++++++++
>  drivers/memory/memory-uclass.c  | 13 +++++++++++++
>  include/dm/uclass-id.h          |  1 +
>  test/dm/Makefile                |  1 +
>  test/dm/memory.c                | 21 +++++++++++++++++++++
>  8 files changed, 77 insertions(+)
>  create mode 100644 drivers/memory/memory-sandbox.c
>  create mode 100644 drivers/memory/memory-uclass.c
>  create mode 100644 test/dm/memory.c
>

Reviewed-by: Simon Glass <sjg@chromium.org>
(with change below)

> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index 2761588f0d..d65b2d2dcb 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -926,6 +926,10 @@
>                 };
>         };
>
> +       memory-controller {
> +               compatible = "sandbox,memory";
> +       };
> +
>         misc-test {
>                 #address-cells = <1>;
>                 #size-cells = <1>;
> diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
> index 7271892763..632feb3aaa 100644
> --- a/drivers/memory/Kconfig
> +++ b/drivers/memory/Kconfig
> @@ -4,6 +4,23 @@
>
>  menu "Memory Controller drivers"
>
> +config DM_MEMORY

Please use MEMORY since there is no non-DM memory option.

> +       bool "Enable Driver Model for Memory Controller drivers"
> +       depends on DM
> +       help
> +         Enable driver model for Memory Controller devices.
> +         These devices provide Memory bus interface to various devices like
> +         SRAM, Ethernet adapters, FPGAs, etc.
> +         For now this uclass has no methods yet.
> +
> +config SANDBOX_MEMORY
> +       bool "Enable Sandbox Memory Controller driver"
> +       depends on SANDBOX && DM_MEMORY
> +       help
> +         This is a driver model based Memory Controller driver for sandbox.
> +         Currently it is a stub only, as there are no usable uclass methods
> +         yet.
> +
>  config STM32_FMC2_EBI
>         bool "Support for FMC2 External Bus Interface on STM32MP SoCs"
>         depends on ARCH_STM32MP
[..]

Regards,
Simon

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-06 13:23 ` [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
@ 2022-10-18 17:40   ` Tom Rini
  2022-10-19  8:17     ` Roger Quadros
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Rini @ 2022-10-18 17:40 UTC (permalink / raw)
  To: Roger Quadros
  Cc: sjg, u-boot, praneeth, kishon, Patrick Delaunay, Patrice Chotard

[-- Attachment #1: Type: text/plain, Size: 936 bytes --]

On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
> We will need ti-gpmc driver for SPL. Allow memory drivers
> do be built for SPL.
> 
> Signed-off-by: Roger Quadros <rogerq@kernel.org>
> ---
>  scripts/Makefile.spl | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> index 3bafeb4fe9..110076b22f 100644
> --- a/scripts/Makefile.spl
> +++ b/scripts/Makefile.spl
> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
>  endif
>  
>  libs-y += drivers/
> +libs-y += drivers/memory/
>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
>  libs-y += dts/

This ends up being the wrong approach as it then pulls in
drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
is not what's intended. We need an SPL_MEMORY symbol and then gate the
directory on that.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-18 17:40   ` Tom Rini
@ 2022-10-19  8:17     ` Roger Quadros
  2022-10-19 12:54       ` Tom Rini
  0 siblings, 1 reply; 15+ messages in thread
From: Roger Quadros @ 2022-10-19  8:17 UTC (permalink / raw)
  To: Tom Rini; +Cc: sjg, u-boot, praneeth, kishon, Patrick Delaunay, Patrice Chotard



On 18/10/2022 20:40, Tom Rini wrote:
> On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
>> We will need ti-gpmc driver for SPL. Allow memory drivers
>> do be built for SPL.
>>
>> Signed-off-by: Roger Quadros <rogerq@kernel.org>
>> ---
>>  scripts/Makefile.spl | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
>> index 3bafeb4fe9..110076b22f 100644
>> --- a/scripts/Makefile.spl
>> +++ b/scripts/Makefile.spl
>> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
>>  endif
>>  
>>  libs-y += drivers/
>> +libs-y += drivers/memory/
>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
>>  libs-y += dts/
> 
> This ends up being the wrong approach as it then pulls in
> drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
> is not what's intended. We need an SPL_MEMORY symbol and then gate the
> directory on that.
> 

That's right. I'll fix it up. Will wait for your comments on the rest
of the series before re-spin.

cheers,
-roger

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-19  8:17     ` Roger Quadros
@ 2022-10-19 12:54       ` Tom Rini
  2022-10-20 12:23         ` Roger Quadros
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Rini @ 2022-10-19 12:54 UTC (permalink / raw)
  To: Roger Quadros
  Cc: sjg, u-boot, praneeth, kishon, Patrick Delaunay, Patrice Chotard

[-- Attachment #1: Type: text/plain, Size: 1391 bytes --]

On Wed, Oct 19, 2022 at 11:17:35AM +0300, Roger Quadros wrote:
> 
> 
> On 18/10/2022 20:40, Tom Rini wrote:
> > On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
> >> We will need ti-gpmc driver for SPL. Allow memory drivers
> >> do be built for SPL.
> >>
> >> Signed-off-by: Roger Quadros <rogerq@kernel.org>
> >> ---
> >>  scripts/Makefile.spl | 1 +
> >>  1 file changed, 1 insertion(+)
> >>
> >> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> >> index 3bafeb4fe9..110076b22f 100644
> >> --- a/scripts/Makefile.spl
> >> +++ b/scripts/Makefile.spl
> >> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
> >>  endif
> >>  
> >>  libs-y += drivers/
> >> +libs-y += drivers/memory/
> >>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
> >>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
> >>  libs-y += dts/
> > 
> > This ends up being the wrong approach as it then pulls in
> > drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
> > is not what's intended. We need an SPL_MEMORY symbol and then gate the
> > directory on that.
> > 
> 
> That's right. I'll fix it up. Will wait for your comments on the rest
> of the series before re-spin.

Everything else is fine, I was about to merge it (with a
%s/DM_MEMORY/MEMORY) when I saw the stm32 platforms increasing in size
and dug in.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-19 12:54       ` Tom Rini
@ 2022-10-20 12:23         ` Roger Quadros
  2022-10-20 12:29           ` Tom Rini
  0 siblings, 1 reply; 15+ messages in thread
From: Roger Quadros @ 2022-10-20 12:23 UTC (permalink / raw)
  To: Tom Rini; +Cc: sjg, u-boot, praneeth, kishon, Patrick Delaunay, Patrice Chotard

Hi Tom,

On 19/10/2022 15:54, Tom Rini wrote:
> On Wed, Oct 19, 2022 at 11:17:35AM +0300, Roger Quadros wrote:
>>
>>
>> On 18/10/2022 20:40, Tom Rini wrote:
>>> On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
>>>> We will need ti-gpmc driver for SPL. Allow memory drivers
>>>> do be built for SPL.
>>>>
>>>> Signed-off-by: Roger Quadros <rogerq@kernel.org>
>>>> ---
>>>>  scripts/Makefile.spl | 1 +
>>>>  1 file changed, 1 insertion(+)
>>>>
>>>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
>>>> index 3bafeb4fe9..110076b22f 100644
>>>> --- a/scripts/Makefile.spl
>>>> +++ b/scripts/Makefile.spl
>>>> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
>>>>  endif
>>>>  
>>>>  libs-y += drivers/
>>>> +libs-y += drivers/memory/
>>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
>>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
>>>>  libs-y += dts/
>>>
>>> This ends up being the wrong approach as it then pulls in
>>> drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
>>> is not what's intended. We need an SPL_MEMORY symbol and then gate the
>>> directory on that.
>>>

I have a question about how CONFIG_SPL_MEMORY works together with CONFIG_MEMORY.

Do we use CONFIG_SPL_MEMORY only to gate the drivers/memory directory inclusion?
Then continue to use CONFIG_MEMORY and others to enable/disable driver
build for both non-SPL and SPL case?

So drivers/memory/Makefile remains as it is?

>>
>> That's right. I'll fix it up. Will wait for your comments on the rest
>> of the series before re-spin.
> 
> Everything else is fine, I was about to merge it (with a
> %s/DM_MEMORY/MEMORY) when I saw the stm32 platforms increasing in size
> and dug in.
> 

cheers,
-roger

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-20 12:23         ` Roger Quadros
@ 2022-10-20 12:29           ` Tom Rini
  2022-10-25 23:35             ` Simon Glass
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Rini @ 2022-10-20 12:29 UTC (permalink / raw)
  To: Roger Quadros
  Cc: sjg, u-boot, praneeth, kishon, Patrick Delaunay, Patrice Chotard

[-- Attachment #1: Type: text/plain, Size: 1780 bytes --]

On Thu, Oct 20, 2022 at 03:23:42PM +0300, Roger Quadros wrote:
> Hi Tom,
> 
> On 19/10/2022 15:54, Tom Rini wrote:
> > On Wed, Oct 19, 2022 at 11:17:35AM +0300, Roger Quadros wrote:
> >>
> >>
> >> On 18/10/2022 20:40, Tom Rini wrote:
> >>> On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
> >>>> We will need ti-gpmc driver for SPL. Allow memory drivers
> >>>> do be built for SPL.
> >>>>
> >>>> Signed-off-by: Roger Quadros <rogerq@kernel.org>
> >>>> ---
> >>>>  scripts/Makefile.spl | 1 +
> >>>>  1 file changed, 1 insertion(+)
> >>>>
> >>>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> >>>> index 3bafeb4fe9..110076b22f 100644
> >>>> --- a/scripts/Makefile.spl
> >>>> +++ b/scripts/Makefile.spl
> >>>> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
> >>>>  endif
> >>>>  
> >>>>  libs-y += drivers/
> >>>> +libs-y += drivers/memory/
> >>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
> >>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
> >>>>  libs-y += dts/
> >>>
> >>> This ends up being the wrong approach as it then pulls in
> >>> drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
> >>> is not what's intended. We need an SPL_MEMORY symbol and then gate the
> >>> directory on that.
> >>>
> 
> I have a question about how CONFIG_SPL_MEMORY works together with CONFIG_MEMORY.
> 
> Do we use CONFIG_SPL_MEMORY only to gate the drivers/memory directory inclusion?
> Then continue to use CONFIG_MEMORY and others to enable/disable driver
> build for both non-SPL and SPL case?
> 
> So drivers/memory/Makefile remains as it is?

Well, for consistency code should use IS_ENABLED(MEMORY) which will be
true for CONFIG_MEMORY or CONFIG_SPL_MEMORY.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-20 12:29           ` Tom Rini
@ 2022-10-25 23:35             ` Simon Glass
  2022-10-26 10:41               ` Roger Quadros
  2022-10-26 13:53               ` Tom Rini
  0 siblings, 2 replies; 15+ messages in thread
From: Simon Glass @ 2022-10-25 23:35 UTC (permalink / raw)
  To: Tom Rini
  Cc: Roger Quadros, u-boot, praneeth, kishon, Patrick Delaunay,
	Patrice Chotard

Hi Tom,

On Thu, 20 Oct 2022 at 06:29, Tom Rini <trini@konsulko.com> wrote:
>
> On Thu, Oct 20, 2022 at 03:23:42PM +0300, Roger Quadros wrote:
> > Hi Tom,
> >
> > On 19/10/2022 15:54, Tom Rini wrote:
> > > On Wed, Oct 19, 2022 at 11:17:35AM +0300, Roger Quadros wrote:
> > >>
> > >>
> > >> On 18/10/2022 20:40, Tom Rini wrote:
> > >>> On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
> > >>>> We will need ti-gpmc driver for SPL. Allow memory drivers
> > >>>> do be built for SPL.
> > >>>>
> > >>>> Signed-off-by: Roger Quadros <rogerq@kernel.org>
> > >>>> ---
> > >>>>  scripts/Makefile.spl | 1 +
> > >>>>  1 file changed, 1 insertion(+)
> > >>>>
> > >>>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> > >>>> index 3bafeb4fe9..110076b22f 100644
> > >>>> --- a/scripts/Makefile.spl
> > >>>> +++ b/scripts/Makefile.spl
> > >>>> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
> > >>>>  endif
> > >>>>
> > >>>>  libs-y += drivers/
> > >>>> +libs-y += drivers/memory/
> > >>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
> > >>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
> > >>>>  libs-y += dts/
> > >>>
> > >>> This ends up being the wrong approach as it then pulls in
> > >>> drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
> > >>> is not what's intended. We need an SPL_MEMORY symbol and then gate the
> > >>> directory on that.
> > >>>
> >
> > I have a question about how CONFIG_SPL_MEMORY works together with CONFIG_MEMORY.
> >
> > Do we use CONFIG_SPL_MEMORY only to gate the drivers/memory directory inclusion?
> > Then continue to use CONFIG_MEMORY and others to enable/disable driver
> > build for both non-SPL and SPL case?
> >
> > So drivers/memory/Makefile remains as it is?
>
> Well, for consistency code should use IS_ENABLED(MEMORY) which will be
> true for CONFIG_MEMORY or CONFIG_SPL_MEMORY.

nit: CONFIG_IS_ENABLED(MEMORY)

Perhaps we can look at my Kconfig series so it can become
CONFIG(MEMORY) and we can drop all the SPL_TPL_ stuff in Makefiles?

Regards,
SImon

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-25 23:35             ` Simon Glass
@ 2022-10-26 10:41               ` Roger Quadros
  2022-10-26 13:52                 ` Tom Rini
  2022-10-26 13:53               ` Tom Rini
  1 sibling, 1 reply; 15+ messages in thread
From: Roger Quadros @ 2022-10-26 10:41 UTC (permalink / raw)
  To: Simon Glass, Tom Rini
  Cc: u-boot, praneeth, kishon, Patrick Delaunay, Patrice Chotard

Tom,

On 26/10/2022 02:35, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 20 Oct 2022 at 06:29, Tom Rini <trini@konsulko.com> wrote:
>>
>> On Thu, Oct 20, 2022 at 03:23:42PM +0300, Roger Quadros wrote:
>>> Hi Tom,
>>>
>>> On 19/10/2022 15:54, Tom Rini wrote:
>>>> On Wed, Oct 19, 2022 at 11:17:35AM +0300, Roger Quadros wrote:
>>>>>
>>>>>
>>>>> On 18/10/2022 20:40, Tom Rini wrote:
>>>>>> On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
>>>>>>> We will need ti-gpmc driver for SPL. Allow memory drivers
>>>>>>> do be built for SPL.
>>>>>>>
>>>>>>> Signed-off-by: Roger Quadros <rogerq@kernel.org>
>>>>>>> ---
>>>>>>>  scripts/Makefile.spl | 1 +
>>>>>>>  1 file changed, 1 insertion(+)
>>>>>>>
>>>>>>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
>>>>>>> index 3bafeb4fe9..110076b22f 100644
>>>>>>> --- a/scripts/Makefile.spl
>>>>>>> +++ b/scripts/Makefile.spl
>>>>>>> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
>>>>>>>  endif
>>>>>>>
>>>>>>>  libs-y += drivers/
>>>>>>> +libs-y += drivers/memory/
>>>>>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
>>>>>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
>>>>>>>  libs-y += dts/
>>>>>>
>>>>>> This ends up being the wrong approach as it then pulls in
>>>>>> drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
>>>>>> is not what's intended. We need an SPL_MEMORY symbol and then gate the
>>>>>> directory on that.
>>>>>>
>>>
>>> I have a question about how CONFIG_SPL_MEMORY works together with CONFIG_MEMORY.
>>>
>>> Do we use CONFIG_SPL_MEMORY only to gate the drivers/memory directory inclusion?
>>> Then continue to use CONFIG_MEMORY and others to enable/disable driver
>>> build for both non-SPL and SPL case?
>>>
>>> So drivers/memory/Makefile remains as it is?
>>
>> Well, for consistency code should use IS_ENABLED(MEMORY) which will be
>> true for CONFIG_MEMORY or CONFIG_SPL_MEMORY.
> 
> nit: CONFIG_IS_ENABLED(MEMORY)

CONFIG_IS_ENABLED* is used in code but not by any Makefile.
My question was on what basis do we gate drivers/memory inclusion in build from Makefile.

Can CONFIG_MEMORY and CONFIG_SPL_MEMORY co-exist or that should never happen?

> 
> Perhaps we can look at my Kconfig series so it can become
> CONFIG(MEMORY) and we can drop all the SPL_TPL_ stuff in Makefiles?
> 
> Regards,
> SImon

cheers,
-roger

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-26 10:41               ` Roger Quadros
@ 2022-10-26 13:52                 ` Tom Rini
  0 siblings, 0 replies; 15+ messages in thread
From: Tom Rini @ 2022-10-26 13:52 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Simon Glass, u-boot, praneeth, kishon, Patrick Delaunay, Patrice Chotard

[-- Attachment #1: Type: text/plain, Size: 2538 bytes --]

On Wed, Oct 26, 2022 at 01:41:12PM +0300, Roger Quadros wrote:
> Tom,
> 
> On 26/10/2022 02:35, Simon Glass wrote:
> > Hi Tom,
> > 
> > On Thu, 20 Oct 2022 at 06:29, Tom Rini <trini@konsulko.com> wrote:
> >>
> >> On Thu, Oct 20, 2022 at 03:23:42PM +0300, Roger Quadros wrote:
> >>> Hi Tom,
> >>>
> >>> On 19/10/2022 15:54, Tom Rini wrote:
> >>>> On Wed, Oct 19, 2022 at 11:17:35AM +0300, Roger Quadros wrote:
> >>>>>
> >>>>>
> >>>>> On 18/10/2022 20:40, Tom Rini wrote:
> >>>>>> On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
> >>>>>>> We will need ti-gpmc driver for SPL. Allow memory drivers
> >>>>>>> do be built for SPL.
> >>>>>>>
> >>>>>>> Signed-off-by: Roger Quadros <rogerq@kernel.org>
> >>>>>>> ---
> >>>>>>>  scripts/Makefile.spl | 1 +
> >>>>>>>  1 file changed, 1 insertion(+)
> >>>>>>>
> >>>>>>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> >>>>>>> index 3bafeb4fe9..110076b22f 100644
> >>>>>>> --- a/scripts/Makefile.spl
> >>>>>>> +++ b/scripts/Makefile.spl
> >>>>>>> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
> >>>>>>>  endif
> >>>>>>>
> >>>>>>>  libs-y += drivers/
> >>>>>>> +libs-y += drivers/memory/
> >>>>>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
> >>>>>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
> >>>>>>>  libs-y += dts/
> >>>>>>
> >>>>>> This ends up being the wrong approach as it then pulls in
> >>>>>> drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
> >>>>>> is not what's intended. We need an SPL_MEMORY symbol and then gate the
> >>>>>> directory on that.
> >>>>>>
> >>>
> >>> I have a question about how CONFIG_SPL_MEMORY works together with CONFIG_MEMORY.
> >>>
> >>> Do we use CONFIG_SPL_MEMORY only to gate the drivers/memory directory inclusion?
> >>> Then continue to use CONFIG_MEMORY and others to enable/disable driver
> >>> build for both non-SPL and SPL case?
> >>>
> >>> So drivers/memory/Makefile remains as it is?
> >>
> >> Well, for consistency code should use IS_ENABLED(MEMORY) which will be
> >> true for CONFIG_MEMORY or CONFIG_SPL_MEMORY.
> > 
> > nit: CONFIG_IS_ENABLED(MEMORY)
> 
> CONFIG_IS_ENABLED* is used in code but not by any Makefile.
> My question was on what basis do we gate drivers/memory inclusion in build from Makefile.
> 
> Can CONFIG_MEMORY and CONFIG_SPL_MEMORY co-exist or that should never happen?

What we have for now in your patch is fine and we can tweak slightly if
needed if other cases arise.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

* Re: [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-25 23:35             ` Simon Glass
  2022-10-26 10:41               ` Roger Quadros
@ 2022-10-26 13:53               ` Tom Rini
  1 sibling, 0 replies; 15+ messages in thread
From: Tom Rini @ 2022-10-26 13:53 UTC (permalink / raw)
  To: Simon Glass
  Cc: Roger Quadros, u-boot, praneeth, kishon, Patrick Delaunay,
	Patrice Chotard

[-- Attachment #1: Type: text/plain, Size: 2529 bytes --]

On Tue, Oct 25, 2022 at 05:35:29PM -0600, Simon Glass wrote:
> Hi Tom,
> 
> On Thu, 20 Oct 2022 at 06:29, Tom Rini <trini@konsulko.com> wrote:
> >
> > On Thu, Oct 20, 2022 at 03:23:42PM +0300, Roger Quadros wrote:
> > > Hi Tom,
> > >
> > > On 19/10/2022 15:54, Tom Rini wrote:
> > > > On Wed, Oct 19, 2022 at 11:17:35AM +0300, Roger Quadros wrote:
> > > >>
> > > >>
> > > >> On 18/10/2022 20:40, Tom Rini wrote:
> > > >>> On Thu, Oct 06, 2022 at 04:23:58PM +0300, Roger Quadros wrote:
> > > >>>> We will need ti-gpmc driver for SPL. Allow memory drivers
> > > >>>> do be built for SPL.
> > > >>>>
> > > >>>> Signed-off-by: Roger Quadros <rogerq@kernel.org>
> > > >>>> ---
> > > >>>>  scripts/Makefile.spl | 1 +
> > > >>>>  1 file changed, 1 insertion(+)
> > > >>>>
> > > >>>> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> > > >>>> index 3bafeb4fe9..110076b22f 100644
> > > >>>> --- a/scripts/Makefile.spl
> > > >>>> +++ b/scripts/Makefile.spl
> > > >>>> @@ -114,6 +114,7 @@ libs-$(CONFIG_PARTITIONS) += disk/
> > > >>>>  endif
> > > >>>>
> > > >>>>  libs-y += drivers/
> > > >>>> +libs-y += drivers/memory/
> > > >>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/dwc3/
> > > >>>>  libs-$(CONFIG_SPL_USB_GADGET) += drivers/usb/cdns3/
> > > >>>>  libs-y += dts/
> > > >>>
> > > >>> This ends up being the wrong approach as it then pulls in
> > > >>> drivers/memory/stm32-fmc2-ebi.o on all of those platforms, in SPL, which
> > > >>> is not what's intended. We need an SPL_MEMORY symbol and then gate the
> > > >>> directory on that.
> > > >>>
> > >
> > > I have a question about how CONFIG_SPL_MEMORY works together with CONFIG_MEMORY.
> > >
> > > Do we use CONFIG_SPL_MEMORY only to gate the drivers/memory directory inclusion?
> > > Then continue to use CONFIG_MEMORY and others to enable/disable driver
> > > build for both non-SPL and SPL case?
> > >
> > > So drivers/memory/Makefile remains as it is?
> >
> > Well, for consistency code should use IS_ENABLED(MEMORY) which will be
> > true for CONFIG_MEMORY or CONFIG_SPL_MEMORY.
> 
> nit: CONFIG_IS_ENABLED(MEMORY)
> 
> Perhaps we can look at my Kconfig series so it can become
> CONFIG(MEMORY) and we can drop all the SPL_TPL_ stuff in Makefiles?

I think that was the part I had some reservations about, but we should
re-visit that idea as I wasn't disagreeing (I believe) with making the
logic easier, but I think that we need to re-evaluate how we manage the
SPL/TPL/full U-Boot idea.

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

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

end of thread, other threads:[~2022-10-26 13:54 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-06 13:23 [u-boot][PATCH v2 0/4] Introduce MEMORY uclass and TI GPMC driver Roger Quadros
2022-10-06 13:23 ` [u-boot][PATCH v2 1/4] dm: memory: Introduce new uclass Roger Quadros
2022-10-06 19:07   ` Simon Glass
2022-10-06 13:23 ` [u-boot][PATCH v2 2/4] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
2022-10-18 17:40   ` Tom Rini
2022-10-19  8:17     ` Roger Quadros
2022-10-19 12:54       ` Tom Rini
2022-10-20 12:23         ` Roger Quadros
2022-10-20 12:29           ` Tom Rini
2022-10-25 23:35             ` Simon Glass
2022-10-26 10:41               ` Roger Quadros
2022-10-26 13:52                 ` Tom Rini
2022-10-26 13:53               ` Tom Rini
2022-10-06 13:23 ` [u-boot][PATCH v2 3/4] dt/bindings: memory: Add bindings for TI GPMC driver Roger Quadros
2022-10-06 13:24 ` [u-boot][PATCH v2 4/4] memory: Add " Roger Quadros

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.