All of lore.kernel.org
 help / color / mirror / Atom feed
* [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver
@ 2022-09-28 12:11 Roger Quadros
  2022-09-28 12:11 ` [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Roger Quadros @ 2022-09-28 12:11 UTC (permalink / raw)
  To: trini; +Cc: u-boot, Roger Quadros

Hi,

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.

cheers,
-roger

Roger Quadros (3):
  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

 .../memory/ti,gpmc-child.yaml                 |  252 ++++
 doc/device-tree-bindings/memory/ti,gpmc.yaml  |  190 +++
 drivers/memory/Kconfig                        |   16 +
 drivers/memory/Makefile                       |    1 +
 drivers/memory/ti-gpmc.c                      | 1237 +++++++++++++++++
 drivers/memory/ti-gpmc.h                      |  298 ++++
 include/linux/mtd/omap_gpmc.h                 |    3 +
 scripts/Makefile.spl                          |    1 +
 8 files changed, 1998 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/ti-gpmc.c
 create mode 100644 drivers/memory/ti-gpmc.h

-- 
2.17.1


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

* [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-28 12:11 [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Roger Quadros
@ 2022-09-28 12:11 ` Roger Quadros
  2022-09-28 16:27   ` Simon Glass
  2022-09-28 12:11 ` [u-boot][PATCH 2/3] dt/bindings: memory: Add bindings for TI GPMC driver Roger Quadros
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 18+ messages in thread
From: Roger Quadros @ 2022-09-28 12:11 UTC (permalink / raw)
  To: trini; +Cc: u-boot, 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] 18+ messages in thread

* [u-boot][PATCH 2/3] dt/bindings: memory: Add bindings for TI GPMC driver
  2022-09-28 12:11 [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Roger Quadros
  2022-09-28 12:11 ` [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
@ 2022-09-28 12:11 ` Roger Quadros
  2022-09-28 12:11 ` [u-boot][PATCH 3/3] memory: Add " Roger Quadros
  2022-09-29 17:51 ` [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Tom Rini
  3 siblings, 0 replies; 18+ messages in thread
From: Roger Quadros @ 2022-09-28 12:11 UTC (permalink / raw)
  To: trini; +Cc: u-boot, 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] 18+ messages in thread

* [u-boot][PATCH 3/3] memory: Add TI GPMC driver
  2022-09-28 12:11 [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Roger Quadros
  2022-09-28 12:11 ` [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
  2022-09-28 12:11 ` [u-boot][PATCH 2/3] dt/bindings: memory: Add bindings for TI GPMC driver Roger Quadros
@ 2022-09-28 12:11 ` Roger Quadros
  2022-09-29 17:51 ` [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Tom Rini
  3 siblings, 0 replies; 18+ messages in thread
From: Roger Quadros @ 2022-09-28 12:11 UTC (permalink / raw)
  To: trini; +Cc: u-boot, 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        |   16 +
 drivers/memory/Makefile       |    1 +
 drivers/memory/ti-gpmc.c      | 1237 +++++++++++++++++++++++++++++++++
 drivers/memory/ti-gpmc.h      |  298 ++++++++
 include/linux/mtd/omap_gpmc.h |    3 +
 5 files changed, 1555 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 7271892763..6ce48cebf9 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -24,4 +24,20 @@ 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
+	help
+	  This driver is for the General Purpose Memory Controller (GPMC)
+          present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows
+          interfacing to a variety of asynchronous as well as synchronous
+          memory drives like NOR, NAND, OneNAND, SRAM.
+
+config 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.
+
 endmenu
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index fec52efb60..0971880fcf 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -1,3 +1,4 @@
 
 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..58133df16b
--- /dev/null
+++ b/drivers/memory/ti-gpmc.c
@@ -0,0 +1,1237 @@
+// 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;
+const struct gpmc *gpmc_cfg;
+static unsigned int gpmc_capability;
+static void __iomem *gpmc_base;
+static struct clk *gpmc_l3_clk;
+
+/*
+ * 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);
+#endif
+	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);
+#endif
+
+	gpmc_cs_bool_timings(cs, &t->bool_timings);
+	gpmc_cs_show_timings(cs, "after gpmc_cs_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_SIMPLE_BUS,
+	.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] 18+ messages in thread

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-28 12:11 ` [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
@ 2022-09-28 16:27   ` Simon Glass
  2022-09-29  7:02     ` Roger Quadros
  0 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2022-09-28 16:27 UTC (permalink / raw)
  To: Roger Quadros; +Cc: Tom Rini, U-Boot Mailing List

Hi Roger,

On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)

Please can you use the existing drivers/ram directory?

>
> 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
>

Regards,
Simon

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-28 16:27   ` Simon Glass
@ 2022-09-29  7:02     ` Roger Quadros
  2022-09-29 17:51       ` Tom Rini
  2022-09-29 18:06       ` Simon Glass
  0 siblings, 2 replies; 18+ messages in thread
From: Roger Quadros @ 2022-09-29  7:02 UTC (permalink / raw)
  To: Simon Glass; +Cc: Tom Rini, U-Boot Mailing List

Hi Simon,

On 28/09/2022 19:27, Simon Glass wrote:
> Hi Roger,
> 
> On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
> 
> Please can you use the existing drivers/ram directory?

The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
It is a more general purpose controller that can support different peripherals.
It is similar to the drivers already existing in the divers/memory directory.

I was just trying to keep the file layout similar to that in the Linux kernel.

Do you still see a problem with it?

> 
>>
>> 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
>>
> 
> Regards,
> Simon

cheers,
-roger

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-29  7:02     ` Roger Quadros
@ 2022-09-29 17:51       ` Tom Rini
  2022-09-29 18:06       ` Simon Glass
  1 sibling, 0 replies; 18+ messages in thread
From: Tom Rini @ 2022-09-29 17:51 UTC (permalink / raw)
  To: Roger Quadros; +Cc: Simon Glass, U-Boot Mailing List

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

On Thu, Sep 29, 2022 at 10:02:54AM +0300, Roger Quadros wrote:
> Hi Simon,
> 
> On 28/09/2022 19:27, Simon Glass wrote:
> > Hi Roger,
> > 
> > On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
> > 
> > Please can you use the existing drivers/ram directory?
> 
> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
> It is a more general purpose controller that can support different peripherals.
> It is similar to the drivers already existing in the divers/memory directory.
> 
> I was just trying to keep the file layout similar to that in the Linux kernel.
> 
> Do you still see a problem with it?

Yes, this makes sense because it's not a ram controller driver.

-- 
Tom

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

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

* Re: [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver
  2022-09-28 12:11 [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Roger Quadros
                   ` (2 preceding siblings ...)
  2022-09-28 12:11 ` [u-boot][PATCH 3/3] memory: Add " Roger Quadros
@ 2022-09-29 17:51 ` Tom Rini
  2022-09-30 12:42   ` Roger Quadros
  3 siblings, 1 reply; 18+ messages in thread
From: Tom Rini @ 2022-09-29 17:51 UTC (permalink / raw)
  To: Roger Quadros; +Cc: u-boot

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

On Wed, Sep 28, 2022 at 03:11:46PM +0300, Roger Quadros wrote:

> Hi,
> 
> 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.

Does this mean we'll be seeing some updates to (or removal of) the
existing nand/gpmc code under arch/arm/mach-omap2 ?

-- 
Tom

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

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-29  7:02     ` Roger Quadros
  2022-09-29 17:51       ` Tom Rini
@ 2022-09-29 18:06       ` Simon Glass
  2022-09-30 12:47         ` Roger Quadros
  1 sibling, 1 reply; 18+ messages in thread
From: Simon Glass @ 2022-09-29 18:06 UTC (permalink / raw)
  To: Roger Quadros; +Cc: Tom Rini, U-Boot Mailing List

Hi Roger,

On Thu, 29 Sept 2022 at 01:03, Roger Quadros <rogerq@kernel.org> wrote:
>
> Hi Simon,
>
> On 28/09/2022 19:27, Simon Glass wrote:
> > Hi Roger,
> >
> > On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
> >
> > Please can you use the existing drivers/ram directory?
>
> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
> It is a more general purpose controller that can support different peripherals.
> It is similar to the drivers already existing in the divers/memory directory.
>
> I was just trying to keep the file layout similar to that in the Linux kernel.
>
> Do you still see a problem with it?

Well in this case perhaps the RAM device would be a child of this one?

But there is no uclass for your new device. One of the drivers in that
dir uses UCLASS_NOP and your one seems to use UCLASS_SIMPLE_BUS

So let's add a uclass for it and describe exactly what it is for.

Regards,
Simon

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

* Re: [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver
  2022-09-29 17:51 ` [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Tom Rini
@ 2022-09-30 12:42   ` Roger Quadros
  2022-09-30 12:44     ` Tom Rini
  0 siblings, 1 reply; 18+ messages in thread
From: Roger Quadros @ 2022-09-30 12:42 UTC (permalink / raw)
  To: Tom Rini; +Cc: u-boot

Hi Tom,

On 29/09/2022 20:51, Tom Rini wrote:
> On Wed, Sep 28, 2022 at 03:11:46PM +0300, Roger Quadros wrote:
> 
>> Hi,
>>
>> 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.
> 
> Does this mean we'll be seeing some updates to (or removal of) the
> existing nand/gpmc code under arch/arm/mach-omap2 ?
> 

My initial plan was to get AM64 NAND to work without requiring
any arch specific code.
This should eventually be usable for mach-omap2 as well.

We can then get rid of /arch/arm/mach-omap2/mem-common.c 

I have an omap3-beagle with NAND support with me so I could at least
get it working on that board.

It should be pretty much the same for all mach-omap2 boards.

cheers,
-roger

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

* Re: [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver
  2022-09-30 12:42   ` Roger Quadros
@ 2022-09-30 12:44     ` Tom Rini
  0 siblings, 0 replies; 18+ messages in thread
From: Tom Rini @ 2022-09-30 12:44 UTC (permalink / raw)
  To: Roger Quadros; +Cc: u-boot

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

On Fri, Sep 30, 2022 at 03:42:42PM +0300, Roger Quadros wrote:
> Hi Tom,
> 
> On 29/09/2022 20:51, Tom Rini wrote:
> > On Wed, Sep 28, 2022 at 03:11:46PM +0300, Roger Quadros wrote:
> > 
> >> Hi,
> >>
> >> 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.
> > 
> > Does this mean we'll be seeing some updates to (or removal of) the
> > existing nand/gpmc code under arch/arm/mach-omap2 ?
> > 
> 
> My initial plan was to get AM64 NAND to work without requiring
> any arch specific code.
> This should eventually be usable for mach-omap2 as well.
> 
> We can then get rid of /arch/arm/mach-omap2/mem-common.c 
> 
> I have an omap3-beagle with NAND support with me so I could at least
> get it working on that board.
> 
> It should be pretty much the same for all mach-omap2 boards.

Sounds good, thanks!

-- 
Tom

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

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-29 18:06       ` Simon Glass
@ 2022-09-30 12:47         ` Roger Quadros
  2022-09-30 13:28           ` Simon Glass
  0 siblings, 1 reply; 18+ messages in thread
From: Roger Quadros @ 2022-09-30 12:47 UTC (permalink / raw)
  To: Simon Glass; +Cc: Tom Rini, U-Boot Mailing List

Simon,

On 29/09/2022 21:06, Simon Glass wrote:
> Hi Roger,
> 
> On Thu, 29 Sept 2022 at 01:03, Roger Quadros <rogerq@kernel.org> wrote:
>>
>> Hi Simon,
>>
>> On 28/09/2022 19:27, Simon Glass wrote:
>>> Hi Roger,
>>>
>>> On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
>>>
>>> Please can you use the existing drivers/ram directory?
>>
>> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
>> It is a more general purpose controller that can support different peripherals.
>> It is similar to the drivers already existing in the divers/memory directory.
>>
>> I was just trying to keep the file layout similar to that in the Linux kernel.
>>
>> Do you still see a problem with it?
> 
> Well in this case perhaps the RAM device would be a child of this one?

That's right.
> 
> But there is no uclass for your new device. One of the drivers in that
> dir uses UCLASS_NOP and your one seems to use UCLASS_SIMPLE_BUS
> 
> So let's add a uclass for it and describe exactly what it is for.

Why isn't UCLASS_SIMPLE_BUS sufficient?
By itself, the GPMC driver doesn't offer any usable functionality.
It just configures the bus interface and then populates the children.

cheers,
-roger

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-30 12:47         ` Roger Quadros
@ 2022-09-30 13:28           ` Simon Glass
  2022-09-30 14:00             ` Tom Rini
  0 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2022-09-30 13:28 UTC (permalink / raw)
  To: Roger Quadros; +Cc: Tom Rini, U-Boot Mailing List

Hi Roger,

On Fri, 30 Sept 2022 at 06:47, Roger Quadros <rogerq@kernel.org> wrote:
>
> Simon,
>
> On 29/09/2022 21:06, Simon Glass wrote:
> > Hi Roger,
> >
> > On Thu, 29 Sept 2022 at 01:03, Roger Quadros <rogerq@kernel.org> wrote:
> >>
> >> Hi Simon,
> >>
> >> On 28/09/2022 19:27, Simon Glass wrote:
> >>> Hi Roger,
> >>>
> >>> On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
> >>>
> >>> Please can you use the existing drivers/ram directory?
> >>
> >> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
> >> It is a more general purpose controller that can support different peripherals.
> >> It is similar to the drivers already existing in the divers/memory directory.
> >>
> >> I was just trying to keep the file layout similar to that in the Linux kernel.
> >>
> >> Do you still see a problem with it?
> >
> > Well in this case perhaps the RAM device would be a child of this one?
>
> That's right.
> >
> > But there is no uclass for your new device. One of the drivers in that
> > dir uses UCLASS_NOP and your one seems to use UCLASS_SIMPLE_BUS
> >
> > So let's add a uclass for it and describe exactly what it is for.
>
> Why isn't UCLASS_SIMPLE_BUS sufficient?
> By itself, the GPMC driver doesn't offer any usable functionality.
> It just configures the bus interface and then populates the children.

That's OK, but in that case it should go in drivers/bus and perhaps
drivers/memory should go away?

Regards,
Simon

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-30 13:28           ` Simon Glass
@ 2022-09-30 14:00             ` Tom Rini
  2022-09-30 20:17               ` Roger Quadros
  0 siblings, 1 reply; 18+ messages in thread
From: Tom Rini @ 2022-09-30 14:00 UTC (permalink / raw)
  To: Simon Glass; +Cc: Roger Quadros, U-Boot Mailing List

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

On Fri, Sep 30, 2022 at 07:28:51AM -0600, Simon Glass wrote:
> Hi Roger,
> 
> On Fri, 30 Sept 2022 at 06:47, Roger Quadros <rogerq@kernel.org> wrote:
> >
> > Simon,
> >
> > On 29/09/2022 21:06, Simon Glass wrote:
> > > Hi Roger,
> > >
> > > On Thu, 29 Sept 2022 at 01:03, Roger Quadros <rogerq@kernel.org> wrote:
> > >>
> > >> Hi Simon,
> > >>
> > >> On 28/09/2022 19:27, Simon Glass wrote:
> > >>> Hi Roger,
> > >>>
> > >>> On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
> > >>>
> > >>> Please can you use the existing drivers/ram directory?
> > >>
> > >> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
> > >> It is a more general purpose controller that can support different peripherals.
> > >> It is similar to the drivers already existing in the divers/memory directory.
> > >>
> > >> I was just trying to keep the file layout similar to that in the Linux kernel.
> > >>
> > >> Do you still see a problem with it?
> > >
> > > Well in this case perhaps the RAM device would be a child of this one?
> >
> > That's right.
> > >
> > > But there is no uclass for your new device. One of the drivers in that
> > > dir uses UCLASS_NOP and your one seems to use UCLASS_SIMPLE_BUS
> > >
> > > So let's add a uclass for it and describe exactly what it is for.
> >
> > Why isn't UCLASS_SIMPLE_BUS sufficient?
> > By itself, the GPMC driver doesn't offer any usable functionality.
> > It just configures the bus interface and then populates the children.
> 
> That's OK, but in that case it should go in drivers/bus and perhaps
> drivers/memory should go away?

No, drivers/memory/stm32-fmc2-ebi.c is there and is the equivalent (more
or less) of drivers/memory/stm32-fmc2-ebi.c in the linux kernel. So
maybe a question is, are we talking about the equivalent of
drivers/memory/omap-gpmc.c here? Or something else?

-- 
Tom

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

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-30 14:00             ` Tom Rini
@ 2022-09-30 20:17               ` Roger Quadros
  2022-09-30 23:48                 ` Simon Glass
  0 siblings, 1 reply; 18+ messages in thread
From: Roger Quadros @ 2022-09-30 20:17 UTC (permalink / raw)
  To: Tom Rini, Simon Glass; +Cc: U-Boot Mailing List

On 30/09/2022 17:00, Tom Rini wrote:
> On Fri, Sep 30, 2022 at 07:28:51AM -0600, Simon Glass wrote:
>> Hi Roger,
>>
>> On Fri, 30 Sept 2022 at 06:47, Roger Quadros <rogerq@kernel.org> wrote:
>>>
>>> Simon,
>>>
>>> On 29/09/2022 21:06, Simon Glass wrote:
>>>> Hi Roger,
>>>>
>>>> On Thu, 29 Sept 2022 at 01:03, Roger Quadros <rogerq@kernel.org> wrote:
>>>>>
>>>>> Hi Simon,
>>>>>
>>>>> On 28/09/2022 19:27, Simon Glass wrote:
>>>>>> Hi Roger,
>>>>>>
>>>>>> On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
>>>>>>
>>>>>> Please can you use the existing drivers/ram directory?
>>>>>
>>>>> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
>>>>> It is a more general purpose controller that can support different peripherals.
>>>>> It is similar to the drivers already existing in the divers/memory directory.
>>>>>
>>>>> I was just trying to keep the file layout similar to that in the Linux kernel.
>>>>>
>>>>> Do you still see a problem with it?
>>>>
>>>> Well in this case perhaps the RAM device would be a child of this one?
>>>
>>> That's right.
>>>>
>>>> But there is no uclass for your new device. One of the drivers in that
>>>> dir uses UCLASS_NOP and your one seems to use UCLASS_SIMPLE_BUS
>>>>
>>>> So let's add a uclass for it and describe exactly what it is for.
>>>
>>> Why isn't UCLASS_SIMPLE_BUS sufficient?
>>> By itself, the GPMC driver doesn't offer any usable functionality.
>>> It just configures the bus interface and then populates the children.
>>
>> That's OK, but in that case it should go in drivers/bus and perhaps
>> drivers/memory should go away?
> 
> No, drivers/memory/stm32-fmc2-ebi.c is there and is the equivalent (more
> or less) of drivers/memory/stm32-fmc2-ebi.c in the linux kernel. So
> maybe a question is, are we talking about the equivalent of
> drivers/memory/omap-gpmc.c here? Or something else?
> 

Yes, I just picked up that file and adapted it for u-boot. 
As GPMC is not only for OMAP devices anymore I renamed it to ti-gpmc.c.
If it helps we can retain the kernel naming.

cheers,
-roger

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-30 20:17               ` Roger Quadros
@ 2022-09-30 23:48                 ` Simon Glass
  2022-10-01  8:37                   ` Roger Quadros
  0 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2022-09-30 23:48 UTC (permalink / raw)
  To: Roger Quadros; +Cc: Tom Rini, U-Boot Mailing List

Hi,

On Fri, 30 Sept 2022 at 14:18, Roger Quadros <rogerq@kernel.org> wrote:
>
> On 30/09/2022 17:00, Tom Rini wrote:
> > On Fri, Sep 30, 2022 at 07:28:51AM -0600, Simon Glass wrote:
> >> Hi Roger,
> >>
> >> On Fri, 30 Sept 2022 at 06:47, Roger Quadros <rogerq@kernel.org> wrote:
> >>>
> >>> Simon,
> >>>
> >>> On 29/09/2022 21:06, Simon Glass wrote:
> >>>> Hi Roger,
> >>>>
> >>>> On Thu, 29 Sept 2022 at 01:03, Roger Quadros <rogerq@kernel.org> wrote:
> >>>>>
> >>>>> Hi Simon,
> >>>>>
> >>>>> On 28/09/2022 19:27, Simon Glass wrote:
> >>>>>> Hi Roger,
> >>>>>>
> >>>>>> On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
> >>>>>>
> >>>>>> Please can you use the existing drivers/ram directory?
> >>>>>
> >>>>> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
> >>>>> It is a more general purpose controller that can support different peripherals.
> >>>>> It is similar to the drivers already existing in the divers/memory directory.
> >>>>>
> >>>>> I was just trying to keep the file layout similar to that in the Linux kernel.
> >>>>>
> >>>>> Do you still see a problem with it?
> >>>>
> >>>> Well in this case perhaps the RAM device would be a child of this one?
> >>>
> >>> That's right.
> >>>>
> >>>> But there is no uclass for your new device. One of the drivers in that
> >>>> dir uses UCLASS_NOP and your one seems to use UCLASS_SIMPLE_BUS
> >>>>
> >>>> So let's add a uclass for it and describe exactly what it is for.
> >>>
> >>> Why isn't UCLASS_SIMPLE_BUS sufficient?
> >>> By itself, the GPMC driver doesn't offer any usable functionality.
> >>> It just configures the bus interface and then populates the children.
> >>
> >> That's OK, but in that case it should go in drivers/bus and perhaps
> >> drivers/memory should go away?
> >
> > No, drivers/memory/stm32-fmc2-ebi.c is there and is the equivalent (more
> > or less) of drivers/memory/stm32-fmc2-ebi.c in the linux kernel. So
> > maybe a question is, are we talking about the equivalent of
> > drivers/memory/omap-gpmc.c here? Or something else?
> >
>
> Yes, I just picked up that file and adapted it for u-boot.
> As GPMC is not only for OMAP devices anymore I renamed it to ti-gpmc.c.
> If it helps we can retain the kernel naming.

In the fullness of time all driver/xxx directories should have a
uclass associated with them. So in this case, do we want to use
UCLASS_BUS and put it in drivers/bus or add a UCLASS_MEMORY and put it
in drivers/memory?

Regards,
Simon

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-09-30 23:48                 ` Simon Glass
@ 2022-10-01  8:37                   ` Roger Quadros
  2022-10-03  1:10                     ` Simon Glass
  0 siblings, 1 reply; 18+ messages in thread
From: Roger Quadros @ 2022-10-01  8:37 UTC (permalink / raw)
  To: Simon Glass; +Cc: Tom Rini, U-Boot Mailing List

Hi,

On 01/10/2022 02:48, Simon Glass wrote:
> Hi,
> 
> On Fri, 30 Sept 2022 at 14:18, Roger Quadros <rogerq@kernel.org> wrote:
>>
>> On 30/09/2022 17:00, Tom Rini wrote:
>>> On Fri, Sep 30, 2022 at 07:28:51AM -0600, Simon Glass wrote:
>>>> Hi Roger,
>>>>
>>>> On Fri, 30 Sept 2022 at 06:47, Roger Quadros <rogerq@kernel.org> wrote:
>>>>>
>>>>> Simon,
>>>>>
>>>>> On 29/09/2022 21:06, Simon Glass wrote:
>>>>>> Hi Roger,
>>>>>>
>>>>>> On Thu, 29 Sept 2022 at 01:03, Roger Quadros <rogerq@kernel.org> wrote:
>>>>>>>
>>>>>>> Hi Simon,
>>>>>>>
>>>>>>> On 28/09/2022 19:27, Simon Glass wrote:
>>>>>>>> Hi Roger,
>>>>>>>>
>>>>>>>> On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
>>>>>>>>
>>>>>>>> Please can you use the existing drivers/ram directory?
>>>>>>>
>>>>>>> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
>>>>>>> It is a more general purpose controller that can support different peripherals.
>>>>>>> It is similar to the drivers already existing in the divers/memory directory.
>>>>>>>
>>>>>>> I was just trying to keep the file layout similar to that in the Linux kernel.
>>>>>>>
>>>>>>> Do you still see a problem with it?
>>>>>>
>>>>>> Well in this case perhaps the RAM device would be a child of this one?
>>>>>
>>>>> That's right.
>>>>>>
>>>>>> But there is no uclass for your new device. One of the drivers in that
>>>>>> dir uses UCLASS_NOP and your one seems to use UCLASS_SIMPLE_BUS
>>>>>>
>>>>>> So let's add a uclass for it and describe exactly what it is for.
>>>>>
>>>>> Why isn't UCLASS_SIMPLE_BUS sufficient?
>>>>> By itself, the GPMC driver doesn't offer any usable functionality.
>>>>> It just configures the bus interface and then populates the children.
>>>>
>>>> That's OK, but in that case it should go in drivers/bus and perhaps
>>>> drivers/memory should go away?
>>>
>>> No, drivers/memory/stm32-fmc2-ebi.c is there and is the equivalent (more
>>> or less) of drivers/memory/stm32-fmc2-ebi.c in the linux kernel. So
>>> maybe a question is, are we talking about the equivalent of
>>> drivers/memory/omap-gpmc.c here? Or something else?
>>>
>>
>> Yes, I just picked up that file and adapted it for u-boot.
>> As GPMC is not only for OMAP devices anymore I renamed it to ti-gpmc.c.
>> If it helps we can retain the kernel naming.
> 
> In the fullness of time all driver/xxx directories should have a
> uclass associated with them. So in this case, do we want to use
> UCLASS_BUS and put it in drivers/bus or add a UCLASS_MEMORY and put it
> in drivers/memory?

I'd opt for UCLASS_MEMORY.

cheers,
-roger

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

* Re: [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL
  2022-10-01  8:37                   ` Roger Quadros
@ 2022-10-03  1:10                     ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2022-10-03  1:10 UTC (permalink / raw)
  To: Roger Quadros; +Cc: Tom Rini, U-Boot Mailing List

Hi Roger,

On Sat, 1 Oct 2022 at 02:37, Roger Quadros <rogerq@kernel.org> wrote:
>
> Hi,
>
> On 01/10/2022 02:48, Simon Glass wrote:
> > Hi,
> >
> > On Fri, 30 Sept 2022 at 14:18, Roger Quadros <rogerq@kernel.org> wrote:
> >>
> >> On 30/09/2022 17:00, Tom Rini wrote:
> >>> On Fri, Sep 30, 2022 at 07:28:51AM -0600, Simon Glass wrote:
> >>>> Hi Roger,
> >>>>
> >>>> On Fri, 30 Sept 2022 at 06:47, Roger Quadros <rogerq@kernel.org> wrote:
> >>>>>
> >>>>> Simon,
> >>>>>
> >>>>> On 29/09/2022 21:06, Simon Glass wrote:
> >>>>>> Hi Roger,
> >>>>>>
> >>>>>> On Thu, 29 Sept 2022 at 01:03, Roger Quadros <rogerq@kernel.org> wrote:
> >>>>>>>
> >>>>>>> Hi Simon,
> >>>>>>>
> >>>>>>> On 28/09/2022 19:27, Simon Glass wrote:
> >>>>>>>> Hi Roger,
> >>>>>>>>
> >>>>>>>> On Wed, 28 Sept 2022 at 06:12, Roger Quadros <rogerq@kernel.org> 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(+)
> >>>>>>>>
> >>>>>>>> Please can you use the existing drivers/ram directory?
> >>>>>>>
> >>>>>>> The ti-gpmc driver is not actually a RAM only controller. Although it can support SRAM.
> >>>>>>> It is a more general purpose controller that can support different peripherals.
> >>>>>>> It is similar to the drivers already existing in the divers/memory directory.
> >>>>>>>
> >>>>>>> I was just trying to keep the file layout similar to that in the Linux kernel.
> >>>>>>>
> >>>>>>> Do you still see a problem with it?
> >>>>>>
> >>>>>> Well in this case perhaps the RAM device would be a child of this one?
> >>>>>
> >>>>> That's right.
> >>>>>>
> >>>>>> But there is no uclass for your new device. One of the drivers in that
> >>>>>> dir uses UCLASS_NOP and your one seems to use UCLASS_SIMPLE_BUS
> >>>>>>
> >>>>>> So let's add a uclass for it and describe exactly what it is for.
> >>>>>
> >>>>> Why isn't UCLASS_SIMPLE_BUS sufficient?
> >>>>> By itself, the GPMC driver doesn't offer any usable functionality.
> >>>>> It just configures the bus interface and then populates the children.
> >>>>
> >>>> That's OK, but in that case it should go in drivers/bus and perhaps
> >>>> drivers/memory should go away?
> >>>
> >>> No, drivers/memory/stm32-fmc2-ebi.c is there and is the equivalent (more
> >>> or less) of drivers/memory/stm32-fmc2-ebi.c in the linux kernel. So
> >>> maybe a question is, are we talking about the equivalent of
> >>> drivers/memory/omap-gpmc.c here? Or something else?
> >>>
> >>
> >> Yes, I just picked up that file and adapted it for u-boot.
> >> As GPMC is not only for OMAP devices anymore I renamed it to ti-gpmc.c.
> >> If it helps we can retain the kernel naming.
> >
> > In the fullness of time all driver/xxx directories should have a
> > uclass associated with them. So in this case, do we want to use
> > UCLASS_BUS and put it in drivers/bus or add a UCLASS_MEMORY and put it
> > in drivers/memory?
>
> I'd opt for UCLASS_MEMORY.

OK, here is an example patch for adding a new uclass:

https://patchwork.ozlabs.org/project/uboot/patch/20220930120430.42307-2-post@lespocky.de/

It is the bare minimum as it has not methods, but it seems like yours
won't either.

Regards,
Simon

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

end of thread, other threads:[~2022-10-03  1:11 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-28 12:11 [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Roger Quadros
2022-09-28 12:11 ` [u-boot][PATCH 1/3] scripts: Makefile.spl: Enable memory drivers to be built for SPL Roger Quadros
2022-09-28 16:27   ` Simon Glass
2022-09-29  7:02     ` Roger Quadros
2022-09-29 17:51       ` Tom Rini
2022-09-29 18:06       ` Simon Glass
2022-09-30 12:47         ` Roger Quadros
2022-09-30 13:28           ` Simon Glass
2022-09-30 14:00             ` Tom Rini
2022-09-30 20:17               ` Roger Quadros
2022-09-30 23:48                 ` Simon Glass
2022-10-01  8:37                   ` Roger Quadros
2022-10-03  1:10                     ` Simon Glass
2022-09-28 12:11 ` [u-boot][PATCH 2/3] dt/bindings: memory: Add bindings for TI GPMC driver Roger Quadros
2022-09-28 12:11 ` [u-boot][PATCH 3/3] memory: Add " Roger Quadros
2022-09-29 17:51 ` [u-boot][PATCH 0/3] Introduce TI GPMC memory controller driver Tom Rini
2022-09-30 12:42   ` Roger Quadros
2022-09-30 12:44     ` Tom Rini

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.