linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/12] add STM32 FMC2 controller drivers
@ 2020-04-15 15:57 Christophe Kerello
  2020-04-15 15:57 ` [PATCH v2 01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation Christophe Kerello
                   ` (11 more replies)
  0 siblings, 12 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

The FMC2 functional block makes the interface with: synchronous and
asynchronous static devices (such as PSNOR, PSRAM or other memory-mapped
peripherals) and NAND flash memories.
Its main purposes are:
  - to translate AXI transactions into the appropriate external device
    protocol
  - to meet the access time requirements of the external devices
All external devices share the addresses, data and control signals with the
controller. Each external device is accessed by means of a unique Chip
Select. The FMC2 performs only one access at a time to an external device.

Changes in v2:
 - use of regmap_bulk_write/regmap_bulk_read APIs
 - remove ops from stm32_fmc2 structure
 - add 2 APIs to manage FMC2 enable/disable
 - add 2 APIs to manage FMC2 NWAIT shared signal

Christophe Kerello (12):
  dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation
  mfd: stm32-fmc2: add STM32 FMC2 controller driver
  bus: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  mtd: rawnand: stm32_fmc2: remove useless inline comments
  mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  mtd: rawnand: stm32_fmc2: cleanup
  mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
  mtd: rawnand: stm32_fmc2: move all registers
  mtd: rawnand: stm32_fmc2: use regmap APIs
  mtd: rawnand: stm32_fmc2: use stm32_fmc2 structure in nfc controller
  mtd: rawnand: stm32_fmc2: add new MP1 compatible string

 .../devicetree/bindings/mfd/st,stm32-fmc2.yaml     |  370 ++++++
 drivers/bus/Kconfig                                |   11 +
 drivers/bus/Makefile                               |    1 +
 drivers/bus/stm32-fmc2-ebi.c                       | 1091 +++++++++++++++++
 drivers/mfd/Kconfig                                |   12 +
 drivers/mfd/Makefile                               |    1 +
 drivers/mfd/stm32-fmc2.c                           |  136 +++
 drivers/mtd/nand/raw/Kconfig                       |    3 +
 drivers/mtd/nand/raw/stm32_fmc2_nand.c             | 1277 +++++++++-----------
 include/linux/mfd/stm32-fmc2.h                     |  225 ++++
 10 files changed, 2413 insertions(+), 714 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
 create mode 100644 drivers/bus/stm32-fmc2-ebi.c
 create mode 100644 drivers/mfd/stm32-fmc2.c
 create mode 100644 include/linux/mfd/stm32-fmc2.h

-- 
1.9.1


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

* [PATCH v2 01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-28 15:28   ` Rob Herring
  2020-04-15 15:57 ` [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver Christophe Kerello
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch adds the documentation of the device tree bindings for the STM32
FMC2 controller.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 .../devicetree/bindings/mfd/st,stm32-fmc2.yaml     | 370 +++++++++++++++++++++
 1 file changed, 370 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml

diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
new file mode 100644
index 0000000..0ce1340
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
@@ -0,0 +1,370 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/st,stm32-fmc2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics Flexible Memory Controller 2 (FMC2) Bindings
+
+description: |
+  The FMC2 functional block makes the interface with: synchronous and
+  asynchronous static devices (such as PSNOR, PSRAM or other memory-mapped
+  peripherals) and NAND flash memories.
+  Its main purposes are:
+    - to translate AXI transactions into the appropriate external device
+      protocol
+    - to meet the access time requirements of the external devices
+  All external devices share the addresses, data and control signals with the
+  controller. Each external device is accessed by means of a unique Chip
+  Select. The FMC2 performs only one access at a time to an external device.
+
+maintainers:
+  - Christophe Kerello <christophe.kerello@st.com>
+
+properties:
+  compatible:
+    const: st,stm32mp1-fmc2
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 1
+
+  ranges: true
+
+patternProperties:
+  "^ebi(@.*)?":
+    type: object
+
+    properties:
+      compatible:
+        const: st,stm32mp1-fmc2-ebi
+
+      "#address-cells":
+        const: 2
+
+      "#size-cells":
+        const: 1
+
+      ranges: true
+
+    patternProperties:
+      "^[a-zA-Z]*-ebi@[a-f0-9,]*$":
+        type: object
+
+        properties:
+          reg:
+            maxItems: 1
+
+          st,fmc2_ebi_cs_transaction_type:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+              - minimum: 0
+                maximum: 11
+            description: |
+                         Select one of the transactions type supported
+                           0: Asynchronous mode 1 SRAM/FRAM
+                           1: Asynchronous mode 1 PSRAM.
+                           2: Asynchronous mode A SRAM/FRAM.
+                           3: Asynchronous mode A PSRAM.
+                           4: Asynchronous mode 2 NOR.
+                           5: Asynchronous mode B NOR.
+                           6: Asynchronous mode C NOR.
+                           7: Asynchronous mode D NOR.
+                           8: Synchronous read synchronous write PSRAM.
+                           9: Synchronous read asynchronous write PSRAM.
+                           10: Synchronous read synchronous write NOR.
+                           11: Synchronous read asynchronous write NOR.
+
+          st,fmc2_ebi_cs_cclk_enable:
+            $ref: /schemas/types.yaml#/definitions/flag
+            description: Continuous clock enable (first bank must be configured
+                         in synchronous mode). The FMC_CLK is generated continuously
+                         during asynchronous and synchronous access. By default, the
+                         FMC_CLK is only generated during synchronous access.
+
+          st,fmc2_ebi_cs_mux_enable:
+            $ref: /schemas/types.yaml#/definitions/flag
+            description: Address/Data multiplexed on databus (valid only with
+                         NOR and PSRAM transactions type). By default, Address/Data are
+                         not multiplexed.
+
+          st,fmc2_ebi_cs_buswidth:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+              - enum: [ 8, 16 ]
+              - default: 16
+            description: Data bus width
+
+          st,fmc2_ebi_cs_waitpol_high:
+            $ref: /schemas/types.yaml#/definitions/flag
+            description: Wait signal polarity (NWAIT signal active high).
+                         By default, NWAIT is active low.
+
+          st,fmc2_ebi_cs_waitcfg_enable:
+            $ref: /schemas/types.yaml#/definitions/flag
+            description: The NWAIT signal indicates wheither the data from the
+                         device are valid or if a wait state must be inserted when
+                         accessing the device in synchronous mode. By default, the NWAIT
+                         signal is active one data cycle before wait state.
+
+          st,fmc2_ebi_cs_wait_enable:
+            $ref: /schemas/types.yaml#/definitions/flag
+            description: The NWAIT signal is enabled (its level is taken into
+                         account after the programmed latency period to insert wait states
+                         if asserted). By default, the NWAIT signal is disabled.
+
+          st,fmc2_ebi_cs_asyncwait_enable:
+            $ref: /schemas/types.yaml#/definitions/flag
+            description: The NWAIT signal is taken into account during
+                         asynchronous transactions. By default, the NWAIT signal is not
+                         taken into account during asynchronous transactions.
+
+          st,fmc2_ebi_cs_cpsize:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+              - enum: [ 0, 128, 256, 512, 1024 ]
+              - default: 0
+            description: CRAM page size. The controller splits the burst access
+                         when the memory page is reached. By default, no burst split when
+                         crossing page boundary.
+
+          st,fmc2_ebi_cs_byte_lane_setup:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property configures the byte lane setup timing
+                         defined in ns from NBLx low to Chip Select NEx low.
+
+          st,fmc2_ebi_cs_address_setup:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the duration of the address
+                         setup phase in ns used for asynchronous read/write transactions.
+
+          st,fmc2_ebi_cs_address_hold:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the duration of the address
+                         hold phase in ns used for asynchronous multiplexed
+                         read/write transactions.
+
+          st,fmc2_ebi_cs_data_setup:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the duration of the data
+                         setup phase in ns used for asynchronous read/write transactions.
+
+          st,fmc2_ebi_cs_bus_turnaround:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the delay between the end of
+                         current read/write transaction and the next transaction.
+
+          st,fmc2_ebi_cs_data_hold:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the duration of the data
+                         hold phase in ns used for asynchronous read/write transactions.
+
+          st,fmc2_ebi_cs_clk_period:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the FMC_CLK output signal period in ns.
+
+          st,fmc2_ebi_cs_data_latency:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the data latency before reading or writing
+                         the first data. This timing is expressed in FMC_CLK periods.
+
+          st,fmc2_ebi_cs_write_address_setup:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the duration of the address
+                         setup phase in ns used for asynchronous write transactions.
+
+          st,fmc2_ebi_cs_write_address_hold:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the duration of the address hold phase in
+                         ns used for asynchronous multiplexed write transactions.
+
+          st,fmc2_ebi_cs_write_data_setup:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the duration of the data setup phase in
+                         ns used for asynchronous write transactions.
+
+          st,fmc2_ebi_cs_write_bus_turnaround:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the delay between the end of current
+                         write transaction and the next transaction.
+
+          st,fmc2_ebi_cs_write_data_hold:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the duration of the data hold phase
+                         in ns used for asynchronous write transactions.
+
+          st,fmc2_ebi_cs_max_low_pulse:
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
+            description: This property defines the maximum chip select low pulse duration
+                         in ns for synchronous transactions. When this timing reaches 0,
+                         the controller splits the current access, toggles NE to allow
+                         device refresh and restarts a new access.
+
+        required:
+          - reg
+          - st,fmc2_ebi_cs_transaction_type
+
+    additionalProperties: false
+
+    required:
+      - compatible
+      - "#address-cells"
+      - "#size-cells"
+      - ranges
+
+  nand-controller:
+    allOf:
+      - $ref: "../mtd/nand-controller.yaml#"
+
+    type: object
+
+    properties:
+      compatible:
+        const: st,stm32mp1-fmc2-nand
+
+      reg:
+        items:
+          - description: Chip select 0 data
+          - description: Chip select 0 command
+          - description: Chip select 0 address space
+          - description: Chip select 1 data
+          - description: Chip select 1 command
+          - description: Chip select 1 address space
+
+      interrupts:
+        maxItems: 1
+
+      dmas:
+        items:
+          - description: tx DMA channel
+          - description: rx DMA channel
+          - description: ecc DMA channel
+
+      dma-names:
+        items:
+          - const: tx
+          - const: rx
+          - const: ecc
+
+      "#address-cells":
+        const: 1
+
+      "#size-cells":
+        const: 0
+
+    patternProperties:
+      "^nand@[a-f0-9]$":
+        type: object
+
+        properties:
+          nand-ecc-step-size:
+            const: 512
+
+          nand-ecc-strength:
+            enum: [1, 4 ,8 ]
+
+    additionalProperties: false
+
+    required:
+      - "#address-cells"
+      - "#size-cells"
+      - compatible
+      - reg
+      - interrupts
+
+  additionalProperties: false
+
+required:
+  - "#address-cells"
+  - "#size-cells"
+  - compatible
+  - reg
+  - clocks
+  - ranges
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/stm32mp1-clks.h>
+    #include <dt-bindings/reset/stm32mp1-resets.h>
+    fmc@58002000 {
+      #address-cells = <1>;
+      #size-cells = <1>;
+      compatible = "st,stm32mp1-fmc2";
+      reg = <0x58002000 0x1000>;
+      clocks = <&rcc FMC_K>;
+      resets = <&rcc FMC_R>;
+      ranges;
+
+      ebi@0 {
+        #address-cells = <2>;
+        #size-cells = <1>;
+        compatible = "st,stm32mp1-fmc2-ebi";
+        ranges = <0 0 0x60000000 0x4000000>,
+                 <1 0 0x64000000 0x4000000>,
+                 <2 0 0x68000000 0x4000000>,
+                 <3 0 0x6c000000 0x4000000>;
+
+        psram-ebi@0,0 {
+          compatible = "mtd-ram";
+          reg = <0 0x00000000 0x100000>;
+          bank-width = <2>;
+
+          st,fmc2_ebi_cs_transaction_type = <1>;
+          st,fmc2_ebi_cs_address_setup = <60>;
+          st,fmc2_ebi_cs_data_setup = <30>;
+          st,fmc2_ebi_cs_bus_turnaround = <5>;
+        };
+      };
+
+      nand-controller@1 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+        compatible = "st,stm32mp1-fmc2-nand";
+        reg = <0x80000000 0x1000>,
+              <0x88010000 0x1000>,
+              <0x88020000 0x1000>,
+              <0x81000000 0x1000>,
+              <0x89010000 0x1000>,
+              <0x89020000 0x1000>;
+        interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+        dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
+               <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
+               <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
+        dma-names = "tx", "rx", "ecc";
+
+        nand@0 {
+          reg = <0>;
+          nand-on-flash-bbt;
+          #address-cells = <1>;
+          #size-cells = <1>;
+        };
+      };
+    };
+
+...
-- 
1.9.1


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

* [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
  2020-04-15 15:57 ` [PATCH v2 01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-24  7:45   ` Lee Jones
  2020-04-15 15:57 ` [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI " Christophe Kerello
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

The driver adds the support for the STMicroelectronics FMC2 controller
found on STM32MP SOCs.

The FMC2 functional block makes the interface with: synchronous and
asynchronous static memories (such as PSNOR, PSRAM or other
memory-mapped peripherals) and NAND flash memories.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
Changes in v2:
 - remove ops from stm32_fmc2 structure
 - add 2 APIs to manage FMC2 enable/disable
 - add 2 APIs to manage FMC2 NWAIT shared signal

 drivers/mfd/Kconfig            |  12 +++
 drivers/mfd/Makefile           |   1 +
 drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
 include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 374 insertions(+)
 create mode 100644 drivers/mfd/stm32-fmc2.c
 create mode 100644 include/linux/mfd/stm32-fmc2.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2b20329..5260582 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
 	  Also included is a Coulomb counter, a real-time clock (RTC), and
 	  a 32.768 kHz clock gate.
 
+config MFD_STM32_FMC2
+	tristate "Support for FMC2 controllers on STM32MP SoCs"
+	depends on MACH_STM32MP157 || COMPILE_TEST
+	select MFD_CORE
+	select REGMAP
+	select REGMAP_MMIO
+	help
+	  Select this option to enable STM32 FMC2 driver used for FMC2 External
+	  Bus Interface controller and FMC2 NAND flash controller. This driver
+	  provides core support for the STM32 FMC2 controllers, in order to use
+	  the actual functionality of the device other drivers must be enabled.
+
 config MFD_STM32_LPTIMER
 	tristate "Support for STM32 Low-Power Timer"
 	depends on (ARCH_STM32 && OF) || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index b83f172..880de3c 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -256,5 +256,6 @@ obj-$(CONFIG_MFD_ROHM_BD70528)	+= rohm-bd70528.o
 obj-$(CONFIG_MFD_ROHM_BD71828)	+= rohm-bd71828.o
 obj-$(CONFIG_MFD_ROHM_BD718XX)	+= rohm-bd718x7.o
 obj-$(CONFIG_MFD_STMFX) 	+= stmfx.o
+obj-$(CONFIG_MFD_STM32_FMC2) 	+= stm32-fmc2.o
 
 obj-$(CONFIG_SGI_MFD_IOC3)	+= ioc3.o
diff --git a/drivers/mfd/stm32-fmc2.c b/drivers/mfd/stm32-fmc2.c
new file mode 100644
index 0000000..764c077
--- /dev/null
+++ b/drivers/mfd/stm32-fmc2.c
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2020
+ */
+
+#include <linux/mfd/stm32-fmc2.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/reset.h>
+
+/* Regmap registers configuration */
+#define FMC2_MAX_REGISTER		0x3fc
+
+static const struct regmap_config stm32_fmc2_regmap_cfg = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = sizeof(u32),
+	.max_register = FMC2_MAX_REGISTER,
+};
+
+void stm32_fmc2_enable(struct stm32_fmc2 *fmc2)
+{
+	if (atomic_inc_return(&fmc2->nb_ctrl_used) == 1)
+		regmap_update_bits(fmc2->regmap, FMC2_BCR1,
+				   FMC2_BCR1_FMC2EN, FMC2_BCR1_FMC2EN);
+}
+EXPORT_SYMBOL_GPL(stm32_fmc2_enable);
+
+void stm32_fmc2_disable(struct stm32_fmc2 *fmc2)
+{
+	if (atomic_dec_and_test(&fmc2->nb_ctrl_used))
+		regmap_update_bits(fmc2->regmap, FMC2_BCR1,
+				   FMC2_BCR1_FMC2EN, 0);
+}
+EXPORT_SYMBOL_GPL(stm32_fmc2_disable);
+
+bool stm32_fmc2_get_nwait(struct stm32_fmc2 *fmc2)
+{
+	if (atomic_inc_return(&fmc2->nwait_is_used) > 1) {
+		atomic_dec(&fmc2->nwait_is_used);
+		return false;
+	}
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(stm32_fmc2_get_nwait);
+
+void stm32_fmc2_put_nwait(struct stm32_fmc2 *fmc2)
+{
+	atomic_dec(&fmc2->nwait_is_used);
+}
+EXPORT_SYMBOL_GPL(stm32_fmc2_put_nwait);
+
+static int stm32_fmc2_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct reset_control *rstc;
+	struct stm32_fmc2 *fmc2;
+	struct resource *res;
+	void __iomem *mmio;
+	int ret;
+
+	fmc2 = devm_kzalloc(dev, sizeof(*fmc2), GFP_KERNEL);
+	if (!fmc2)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(mmio))
+		return PTR_ERR(mmio);
+
+	fmc2->regmap = devm_regmap_init_mmio(dev, mmio,
+					     &stm32_fmc2_regmap_cfg);
+	if (IS_ERR(fmc2->regmap))
+		return PTR_ERR(fmc2->regmap);
+
+	fmc2->reg_phys_addr = res->start;
+
+	fmc2->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(fmc2->clk))
+		return PTR_ERR(fmc2->clk);
+
+	rstc = devm_reset_control_get(dev, NULL);
+	if (PTR_ERR(rstc) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	ret = clk_prepare_enable(fmc2->clk);
+	if (ret)
+		return ret;
+
+	if (!IS_ERR(rstc)) {
+		reset_control_assert(rstc);
+		reset_control_deassert(rstc);
+	}
+
+	platform_set_drvdata(pdev, fmc2);
+
+	clk_disable_unprepare(fmc2->clk);
+
+	return devm_of_platform_populate(dev);
+}
+
+static int __maybe_unused stm32_fmc2_suspend(struct device *dev)
+{
+	return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int __maybe_unused stm32_fmc2_resume(struct device *dev)
+{
+	return pinctrl_pm_select_default_state(dev);
+}
+
+static SIMPLE_DEV_PM_OPS(stm32_fmc2_pm_ops, stm32_fmc2_suspend,
+			 stm32_fmc2_resume);
+
+static const struct of_device_id stm32_fmc2_match[] = {
+	{.compatible = "st,stm32mp1-fmc2"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, stm32_fmc2_match);
+
+static struct platform_driver stm32_fmc2_driver = {
+	.probe	= stm32_fmc2_probe,
+	.driver	= {
+		.name = "stm32_fmc2",
+		.of_match_table = stm32_fmc2_match,
+		.pm = &stm32_fmc2_pm_ops,
+	},
+};
+module_platform_driver(stm32_fmc2_driver);
+
+MODULE_ALIAS("platform:stm32_fmc2");
+MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/stm32-fmc2.h b/include/linux/mfd/stm32-fmc2.h
new file mode 100644
index 0000000..0e549f8
--- /dev/null
+++ b/include/linux/mfd/stm32-fmc2.h
@@ -0,0 +1,225 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2020
+ */
+
+#ifndef _LINUX_STM32_FMC2_H_
+#define _LINUX_STM32_FMC2_H_
+
+#include <linux/atomic.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/regmap.h>
+
+/* FMC2 Controller Registers */
+#define FMC2_BCR1			0x0
+#define FMC2_BTR1			0x4
+#define FMC2_BCR(x)			((x) * 0x8 + FMC2_BCR1)
+#define FMC2_BTR(x)			((x) * 0x8 + FMC2_BTR1)
+#define FMC2_PCSCNTR			0x20
+#define FMC2_PCR			0x80
+#define FMC2_SR				0x84
+#define FMC2_PMEM			0x88
+#define FMC2_PATT			0x8c
+#define FMC2_HECCR			0x94
+#define FMC2_BWTR1			0x104
+#define FMC2_BWTR(x)			((x) * 0x8 + FMC2_BWTR1)
+#define FMC2_ISR			0x184
+#define FMC2_ICR			0x188
+#define FMC2_CSQCR			0x200
+#define FMC2_CSQCFGR1			0x204
+#define FMC2_CSQCFGR2			0x208
+#define FMC2_CSQCFGR3			0x20c
+#define FMC2_CSQAR1			0x210
+#define FMC2_CSQAR2			0x214
+#define FMC2_CSQIER			0x220
+#define FMC2_CSQISR			0x224
+#define FMC2_CSQICR			0x228
+#define FMC2_CSQEMSR			0x230
+#define FMC2_BCHIER			0x250
+#define FMC2_BCHISR			0x254
+#define FMC2_BCHICR			0x258
+#define FMC2_BCHPBR1			0x260
+#define FMC2_BCHPBR2			0x264
+#define FMC2_BCHPBR3			0x268
+#define FMC2_BCHPBR4			0x26c
+#define FMC2_BCHDSR0			0x27c
+#define FMC2_BCHDSR1			0x280
+#define FMC2_BCHDSR2			0x284
+#define FMC2_BCHDSR3			0x288
+#define FMC2_BCHDSR4			0x28c
+
+/* Register: FMC2_BCR1 */
+#define FMC2_BCR1_CCLKEN		BIT(20)
+#define FMC2_BCR1_FMC2EN		BIT(31)
+
+/* Register: FMC2_BCRx */
+#define FMC2_BCR_MBKEN			BIT(0)
+#define FMC2_BCR_MUXEN			BIT(1)
+#define FMC2_BCR_MTYP			GENMASK(3, 2)
+#define FMC2_BCR_MWID			GENMASK(5, 4)
+#define FMC2_BCR_FACCEN			BIT(6)
+#define FMC2_BCR_BURSTEN		BIT(8)
+#define FMC2_BCR_WAITPOL		BIT(9)
+#define FMC2_BCR_WAITCFG		BIT(11)
+#define FMC2_BCR_WREN			BIT(12)
+#define FMC2_BCR_WAITEN			BIT(13)
+#define FMC2_BCR_EXTMOD			BIT(14)
+#define FMC2_BCR_ASYNCWAIT		BIT(15)
+#define FMC2_BCR_CPSIZE			GENMASK(18, 16)
+#define FMC2_BCR_CBURSTRW		BIT(19)
+#define FMC2_BCR_NBLSET			GENMASK(23, 22)
+
+/* Register: FMC2_BTRx/FMC2_BWTRx */
+#define FMC2_BXTR_ADDSET		GENMASK(3, 0)
+#define FMC2_BXTR_ADDHLD		GENMASK(7, 4)
+#define FMC2_BXTR_DATAST		GENMASK(15, 8)
+#define FMC2_BXTR_BUSTURN		GENMASK(19, 16)
+#define FMC2_BTR_CLKDIV			GENMASK(23, 20)
+#define FMC2_BTR_DATLAT			GENMASK(27, 24)
+#define FMC2_BXTR_ACCMOD		GENMASK(29, 28)
+#define FMC2_BXTR_DATAHLD		GENMASK(31, 30)
+
+/* Register: FMC2_PCSCNTR */
+#define FMC2_PCSCNTR_CSCOUNT		GENMASK(15, 0)
+#define FMC2_PCSCNTR_CNTBEN(x)		BIT((x) + 16)
+
+/* Register: FMC2_PCR */
+#define FMC2_PCR_PWAITEN		BIT(1)
+#define FMC2_PCR_PBKEN			BIT(2)
+#define FMC2_PCR_PWID			GENMASK(5, 4)
+#define FMC2_PCR_PWID_BUSWIDTH_8	0
+#define FMC2_PCR_PWID_BUSWIDTH_16	1
+#define FMC2_PCR_ECCEN			BIT(6)
+#define FMC2_PCR_ECCALG			BIT(8)
+#define FMC2_PCR_TCLR			GENMASK(12, 9)
+#define FMC2_PCR_TAR			GENMASK(16, 13)
+#define FMC2_PCR_ECCSS			GENMASK(19, 17)
+#define FMC2_PCR_ECCSS_512		1
+#define FMC2_PCR_ECCSS_2048		3
+#define FMC2_PCR_BCHECC			BIT(24)
+#define FMC2_PCR_WEN			BIT(25)
+
+/* Register: FMC2_SR */
+#define FMC2_SR_NWRF			BIT(6)
+
+/* Register: FMC2_PMEM */
+#define FMC2_PMEM_MEMSET		GENMASK(7, 0)
+#define FMC2_PMEM_MEMWAIT		GENMASK(15, 8)
+#define FMC2_PMEM_MEMHOLD		GENMASK(23, 16)
+#define FMC2_PMEM_MEMHIZ		GENMASK(31, 24)
+
+/* Register: FMC2_PATT */
+#define FMC2_PATT_ATTSET		GENMASK(7, 0)
+#define FMC2_PATT_ATTWAIT		GENMASK(15, 8)
+#define FMC2_PATT_ATTHOLD		GENMASK(23, 16)
+#define FMC2_PATT_ATTHIZ		GENMASK(31, 24)
+
+/* Register: FMC2_ISR */
+#define FMC2_ISR_IHLF			BIT(1)
+
+/* Register: FMC2_ICR */
+#define FMC2_ICR_CIHLF			BIT(1)
+
+/* Register: FMC2_CSQCR */
+#define FMC2_CSQCR_CSQSTART		BIT(0)
+
+/* Register: FMC2_CSQCFGR1 */
+#define FMC2_CSQCFGR1_CMD2EN		BIT(1)
+#define FMC2_CSQCFGR1_DMADEN		BIT(2)
+#define FMC2_CSQCFGR1_ACYNBR		GENMASK(6, 4)
+#define FMC2_CSQCFGR1_CMD1		GENMASK(15, 8)
+#define FMC2_CSQCFGR1_CMD2		GENMASK(23, 16)
+#define FMC2_CSQCFGR1_CMD1T		BIT(24)
+#define FMC2_CSQCFGR1_CMD2T		BIT(25)
+
+/* Register: FMC2_CSQCFGR2 */
+#define FMC2_CSQCFGR2_SQSDTEN		BIT(0)
+#define FMC2_CSQCFGR2_RCMD2EN		BIT(1)
+#define FMC2_CSQCFGR2_DMASEN		BIT(2)
+#define FMC2_CSQCFGR2_RCMD1		GENMASK(15, 8)
+#define FMC2_CSQCFGR2_RCMD2		GENMASK(23, 16)
+#define FMC2_CSQCFGR2_RCMD1T		BIT(24)
+#define FMC2_CSQCFGR2_RCMD2T		BIT(25)
+
+/* Register: FMC2_CSQCFGR3 */
+#define FMC2_CSQCFGR3_SNBR		GENMASK(13, 8)
+#define FMC2_CSQCFGR3_AC1T		BIT(16)
+#define FMC2_CSQCFGR3_AC2T		BIT(17)
+#define FMC2_CSQCFGR3_AC3T		BIT(18)
+#define FMC2_CSQCFGR3_AC4T		BIT(19)
+#define FMC2_CSQCFGR3_AC5T		BIT(20)
+#define FMC2_CSQCFGR3_SDT		BIT(21)
+#define FMC2_CSQCFGR3_RAC1T		BIT(22)
+#define FMC2_CSQCFGR3_RAC2T		BIT(23)
+
+/* Register: FMC2_CSQCAR1 */
+#define FMC2_CSQCAR1_ADDC1		GENMASK(7, 0)
+#define FMC2_CSQCAR1_ADDC2		GENMASK(15, 8)
+#define FMC2_CSQCAR1_ADDC3		GENMASK(23, 16)
+#define FMC2_CSQCAR1_ADDC4		GENMASK(31, 24)
+
+/* Register: FMC2_CSQCAR2 */
+#define FMC2_CSQCAR2_ADDC5		GENMASK(7, 0)
+#define FMC2_CSQCAR2_NANDCEN		GENMASK(11, 10)
+#define FMC2_CSQCAR2_SAO		GENMASK(31, 16)
+
+/* Register: FMC2_CSQIER */
+#define FMC2_CSQIER_TCIE		BIT(0)
+
+/* Register: FMC2_CSQICR */
+#define FMC2_CSQICR_CLEAR_IRQ		GENMASK(4, 0)
+
+/* Register: FMC2_CSQEMSR */
+#define FMC2_CSQEMSR_SEM		GENMASK(15, 0)
+
+/* Register: FMC2_BCHIER */
+#define FMC2_BCHIER_DERIE		BIT(1)
+#define FMC2_BCHIER_EPBRIE		BIT(4)
+
+/* Register: FMC2_BCHICR */
+#define FMC2_BCHICR_CLEAR_IRQ		GENMASK(4, 0)
+
+/* Register: FMC2_BCHDSR0 */
+#define FMC2_BCHDSR0_DUE		BIT(0)
+#define FMC2_BCHDSR0_DEF		BIT(1)
+#define FMC2_BCHDSR0_DEN		GENMASK(7, 4)
+
+/* Register: FMC2_BCHDSR1 */
+#define FMC2_BCHDSR1_EBP1		GENMASK(12, 0)
+#define FMC2_BCHDSR1_EBP2		GENMASK(28, 16)
+
+/* Register: FMC2_BCHDSR2 */
+#define FMC2_BCHDSR2_EBP3		GENMASK(12, 0)
+#define FMC2_BCHDSR2_EBP4		GENMASK(28, 16)
+
+/* Register: FMC2_BCHDSR3 */
+#define FMC2_BCHDSR3_EBP5		GENMASK(12, 0)
+#define FMC2_BCHDSR3_EBP6		GENMASK(28, 16)
+
+/* Register: FMC2_BCHDSR4 */
+#define FMC2_BCHDSR4_EBP7		GENMASK(12, 0)
+#define FMC2_BCHDSR4_EBP8		GENMASK(28, 16)
+
+/*
+ * struct stm32_fmc2 - STM32 FMC2 data assigned by parent device
+ * @clk: clock reference for this instance
+ * @regmap: register map reference for this instance
+ * @reg_phys_addr: physical address of the register map
+ * @nb_ctrl_used: number of used controller
+ * @nwait_is_used: NWAIT signal in used by a controller
+ */
+struct stm32_fmc2 {
+	struct clk *clk;
+	struct regmap *regmap;
+	phys_addr_t reg_phys_addr;
+	atomic_t nb_ctrl_used;
+	atomic_t nwait_is_used;
+};
+
+void stm32_fmc2_enable(struct stm32_fmc2 *fmc2);
+void stm32_fmc2_disable(struct stm32_fmc2 *fmc2);
+bool stm32_fmc2_get_nwait(struct stm32_fmc2 *fmc2);
+void stm32_fmc2_put_nwait(struct stm32_fmc2 *fmc2);
+
+#endif
-- 
1.9.1


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

* [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
  2020-04-15 15:57 ` [PATCH v2 01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation Christophe Kerello
  2020-04-15 15:57 ` [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-16 19:53   ` Boris Brezillon
  2020-04-15 15:57 ` [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time Christophe Kerello
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

The driver adds the support for the STMicroelectronics FMC2 EBI controller
found on STM32MP SOCs.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
Tested-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
 - call 2 APIs to manage FMC2 enable/disable instead of ops
 - call 2 APIs to manage FMC2 NWAIT shared signal instead of ops

 drivers/bus/Kconfig          |   11 +
 drivers/bus/Makefile         |    1 +
 drivers/bus/stm32-fmc2-ebi.c | 1091 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1103 insertions(+)
 create mode 100644 drivers/bus/stm32-fmc2-ebi.c

diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 6095b6d..367f015 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -200,6 +200,17 @@ config DA8XX_MSTPRI
 	  configuration. Allows to adjust the priorities of all master
 	  peripherals.
 
+config STM32_FMC2_EBI
+	tristate "Support for FMC2 External Bus Interface on STM32MP SoCs"
+	depends on MACH_STM32MP157 || COMPILE_TEST
+	select REGMAP
+	select MFD_STM32_FMC2
+	help
+	  Select this option to enable the STM32 FMC2 External Bus Interface
+	  controller. This driver configures the transactions with external
+	  devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
+	  SOCs containing the FMC2 External Bus Interface.
+
 source "drivers/bus/fsl-mc/Kconfig"
 
 endmenu
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index 1320bcf..e2d7992 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_QCOM_EBI2)		+= qcom-ebi2.o
 obj-$(CONFIG_SUN50I_DE2_BUS)	+= sun50i-de2.o
 obj-$(CONFIG_SUNXI_RSB)		+= sunxi-rsb.o
 obj-$(CONFIG_SIMPLE_PM_BUS)	+= simple-pm-bus.o
+obj-$(CONFIG_STM32_FMC2_EBI)	+= stm32-fmc2-ebi.o
 obj-$(CONFIG_TEGRA_ACONNECT)	+= tegra-aconnect.o
 obj-$(CONFIG_TEGRA_GMI)		+= tegra-gmi.o
 obj-$(CONFIG_TI_PWMSS)		+= ti-pwmss.o
diff --git a/drivers/bus/stm32-fmc2-ebi.c b/drivers/bus/stm32-fmc2-ebi.c
new file mode 100644
index 0000000..0ec327c
--- /dev/null
+++ b/drivers/bus/stm32-fmc2-ebi.c
@@ -0,0 +1,1091 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) STMicroelectronics 2020
+ */
+
+#include <linux/mfd/stm32-fmc2.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+#define FMC2_MAX_EBI_CE			4
+
+#define FMC2_BCR_CPSIZE_0		0x0
+#define FMC2_BCR_CPSIZE_128		0x1
+#define FMC2_BCR_CPSIZE_256		0x2
+#define FMC2_BCR_CPSIZE_512		0x3
+#define FMC2_BCR_CPSIZE_1024		0x4
+
+#define FMC2_BCR_MWID_8			0x0
+#define FMC2_BCR_MWID_16		0x1
+
+#define FMC2_BCR_MTYP_SRAM		0x0
+#define FMC2_BCR_MTYP_PSRAM		0x1
+#define FMC2_BCR_MTYP_NOR		0x2
+
+#define FMC2_BXTR_EXTMOD_A		0x0
+#define FMC2_BXTR_EXTMOD_B		0x1
+#define FMC2_BXTR_EXTMOD_C		0x2
+#define FMC2_BXTR_EXTMOD_D		0x3
+
+#define FMC2_BCR_NBLSET_MAX		0x3
+#define FMC2_BXTR_ADDSET_MAX		0xf
+#define FMC2_BXTR_ADDHLD_MAX		0xf
+#define FMC2_BXTR_DATAST_MAX		0xff
+#define FMC2_BXTR_BUSTURN_MAX		0xf
+#define FMC2_BXTR_DATAHLD_MAX		0x3
+#define FMC2_BTR_CLKDIV_MAX		0xf
+#define FMC2_BTR_DATLAT_MAX		0xf
+#define FMC2_PCSCNTR_CSCOUNT_MAX	0xff
+
+enum stm32_fmc2_ebi_register_type {
+	FMC2_REG_BCR = 1,
+	FMC2_REG_BTR,
+	FMC2_REG_BWTR,
+	FMC2_REG_PCSCNTR
+};
+
+enum stm32_fmc2_ebi_transaction_type {
+	FMC2_ASYNC_MODE_1_SRAM = 0,
+	FMC2_ASYNC_MODE_1_PSRAM,
+	FMC2_ASYNC_MODE_A_SRAM,
+	FMC2_ASYNC_MODE_A_PSRAM,
+	FMC2_ASYNC_MODE_2_NOR,
+	FMC2_ASYNC_MODE_B_NOR,
+	FMC2_ASYNC_MODE_C_NOR,
+	FMC2_ASYNC_MODE_D_NOR,
+	FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
+	FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
+	FMC2_SYNC_READ_SYNC_WRITE_NOR,
+	FMC2_SYNC_READ_ASYNC_WRITE_NOR
+};
+
+enum stm32_fmc2_ebi_buswidth {
+	FMC2_BUSWIDTH_8 = 8,
+	FMC2_BUSWIDTH_16 = 16
+};
+
+enum stm32_fmc2_ebi_cpsize {
+	FMC2_CPSIZE_0 = 0,
+	FMC2_CPSIZE_128 = 128,
+	FMC2_CPSIZE_256 = 256,
+	FMC2_CPSIZE_512 = 512,
+	FMC2_CPSIZE_1024 = 1024
+};
+
+struct stm32_fmc2_ebi {
+	u32 bcr[FMC2_MAX_EBI_CE];
+	u32 btr[FMC2_MAX_EBI_CE];
+	u32 bwtr[FMC2_MAX_EBI_CE];
+	u32 pcscntr;
+	u8 cs_assigned;
+};
+
+/*
+ * struct stm32_fmc2_prop - STM32 FMC2 EBI property
+ * @name: the device tree binding name of the property
+ * @bprop: indicate that it is a boolean property
+ * @mprop: indicate that it is a mandatory property
+ * @reg_type: the register that have to be modified
+ * @reg_mask: the bit that have to be modified in the selected register
+ *            in case of it is a boolean property
+ * @reset_val: the default value that have to be set in case the property
+ *             has not been defined in the device tree
+ * @check: this callback ckecks that the property is compliant with the
+ *         transaction type selected
+ * @calculate: this callback is called to calculate for exemple a timing
+ *             set in ns in the device tree in clock cycles
+ * @set: this callback applies the values in the registers
+ */
+struct stm32_fmc2_prop {
+	const char *name;
+	bool bprop;
+	bool mprop;
+	int reg_type;
+	u32 reg_mask;
+	u32 reset_val;
+	int (*check)(struct stm32_fmc2 *fmc2,
+		     const struct stm32_fmc2_prop *prop, int cs);
+	u32 (*calculate)(struct stm32_fmc2 *fmc2, u32 setup);
+	int (*set)(struct stm32_fmc2 *fmc2, const struct stm32_fmc2_prop *prop,
+		   int cs, u32 setup);
+};
+
+static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2 *fmc2,
+				    const struct stm32_fmc2_prop *prop,
+				    int cs)
+{
+	u32 bcr;
+
+	regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+
+	if (bcr & FMC2_BCR_MTYP)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2 *fmc2,
+					const struct stm32_fmc2_prop *prop,
+					int cs)
+{
+	u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+
+	regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+
+	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2 *fmc2,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs)
+{
+	u32 bcr;
+
+	regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+
+	if (bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2 *fmc2,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs)
+{
+	u32 bcr;
+
+	regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+
+	if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2 *fmc2,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs)
+{
+	u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+
+	regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+
+	if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2 *fmc2,
+					     const struct stm32_fmc2_prop *prop,
+					     int cs)
+{
+	u32 bcr, bxtr, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+
+	regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+	if (prop->reg_type == FMC2_REG_BWTR)
+		regmap_read(fmc2->regmap, FMC2_BWTR(cs), &bxtr);
+	else
+		regmap_read(fmc2->regmap, FMC2_BTR(cs), &bxtr);
+
+	if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
+	    ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2 *fmc2,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs)
+{
+	u32 bcr, bcr1;
+
+	regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+	if (cs)
+		regmap_read(fmc2->regmap, FMC2_BCR(0), &bcr1);
+	else
+		bcr1 = bcr;
+
+	if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
+		return 0;
+
+	return -EINVAL;
+}
+
+static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2 *fmc2,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs)
+{
+	if (cs)
+		return -EINVAL;
+
+	return stm32_fmc2_ebi_check_sync_trans(fmc2, prop, cs);
+}
+
+static u32 stm32_fmc2_ebi_timing_ns_to_clock_cycles(struct stm32_fmc2 *fmc2,
+						    u32 setup)
+{
+	unsigned long hclk = clk_get_rate(fmc2->clk);
+	unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000);
+
+	return DIV_ROUND_UP(setup * 1000, hclkp);
+}
+
+static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
+{
+	switch (reg_type) {
+	case FMC2_REG_BCR:
+		*reg = FMC2_BCR(cs);
+		break;
+	case FMC2_REG_BTR:
+		*reg = FMC2_BTR(cs);
+		break;
+	case FMC2_REG_BWTR:
+		*reg = FMC2_BWTR(cs);
+		break;
+	case FMC2_REG_PCSCNTR:
+		*reg = FMC2_PCSCNTR;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2 *fmc2,
+					const struct stm32_fmc2_prop *prop,
+					int cs, u32 setup)
+{
+	u32 reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(fmc2->regmap, reg, prop->reg_mask,
+			   setup ? prop->reg_mask : 0);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2 *fmc2,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 bcr_mask, bcr = FMC2_BCR_WREN;
+	u32 btr_mask, btr = 0;
+	u32 bwtr_mask, bwtr = 0;
+
+	bwtr_mask = FMC2_BXTR_ACCMOD;
+	btr_mask = FMC2_BXTR_ACCMOD;
+	bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN |
+		   FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN |
+		   FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW;
+
+	switch (setup) {
+	case FMC2_ASYNC_MODE_1_SRAM:
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
+		/*
+		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		break;
+	case FMC2_ASYNC_MODE_1_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		break;
+	case FMC2_ASYNC_MODE_A_SRAM:
+		/*
+		 * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
+		bcr |= FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		break;
+	case FMC2_ASYNC_MODE_A_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
+		break;
+	case FMC2_ASYNC_MODE_2_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN;
+		break;
+	case FMC2_ASYNC_MODE_B_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
+		break;
+	case FMC2_ASYNC_MODE_C_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
+		break;
+	case FMC2_ASYNC_MODE_D_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
+		btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+		bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+		break;
+	case FMC2_SYNC_READ_SYNC_WRITE_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
+		break;
+	case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM:
+		/*
+		 * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
+		bcr |= FMC2_BCR_BURSTEN;
+		break;
+	case FMC2_SYNC_READ_SYNC_WRITE_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
+		break;
+	case FMC2_SYNC_READ_ASYNC_WRITE_NOR:
+		/*
+		 * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
+		 * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
+		 */
+		bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
+		bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN;
+		break;
+	default:
+		/* Type of transaction not supported */
+		return -EINVAL;
+	}
+
+	if (bcr & FMC2_BCR_EXTMOD)
+		regmap_update_bits(fmc2->regmap, FMC2_BWTR(cs),
+				   bwtr_mask, bwtr);
+	regmap_update_bits(fmc2->regmap, FMC2_BTR(cs), btr_mask, btr);
+	regmap_update_bits(fmc2->regmap, FMC2_BCR(cs), bcr_mask, bcr);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2 *fmc2,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs, u32 setup)
+{
+	u32 val;
+
+	switch (setup) {
+	case FMC2_BUSWIDTH_8:
+		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8);
+		break;
+	case FMC2_BUSWIDTH_16:
+		val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16);
+		break;
+	default:
+		/* Buswidth not supported */
+		return -EINVAL;
+	}
+
+	regmap_update_bits(fmc2->regmap, FMC2_BCR(cs), FMC2_BCR_MWID, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2 *fmc2,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs, u32 setup)
+{
+	u32 val;
+
+	switch (setup) {
+	case FMC2_CPSIZE_0:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0);
+		break;
+	case FMC2_CPSIZE_128:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128);
+		break;
+	case FMC2_CPSIZE_256:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256);
+		break;
+	case FMC2_CPSIZE_512:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512);
+		break;
+	case FMC2_CPSIZE_1024:
+		val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024);
+		break;
+	default:
+		/* Cpsize not supported */
+		return -EINVAL;
+	}
+
+	regmap_update_bits(fmc2->regmap, FMC2_BCR(cs), FMC2_BCR_CPSIZE, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2 *fmc2,
+				       const struct stm32_fmc2_prop *prop,
+				       int cs, u32 setup)
+{
+	u32 val;
+
+	val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX);
+	val = FIELD_PREP(FMC2_BCR_NBLSET, val);
+	regmap_update_bits(fmc2->regmap, FMC2_BCR(cs), FMC2_BCR_NBLSET, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2 *fmc2,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs, u32 setup)
+{
+	u32 bcr, bxtr, reg;
+	u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+	if (prop->reg_type == FMC2_REG_BWTR)
+		regmap_read(fmc2->regmap, FMC2_BWTR(cs), &bxtr);
+	else
+		regmap_read(fmc2->regmap, FMC2_BTR(cs), &bxtr);
+
+	if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)
+		val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX);
+	else
+		val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX);
+	val = FIELD_PREP(FMC2_BXTR_ADDSET, val);
+	regmap_update_bits(fmc2->regmap, reg, FMC2_BXTR_ADDSET, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2 *fmc2,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX);
+	val = FIELD_PREP(FMC2_BXTR_ADDHLD, val);
+	regmap_update_bits(fmc2->regmap, reg, FMC2_BXTR_ADDHLD, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2 *fmc2,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX);
+	val = FIELD_PREP(FMC2_BXTR_DATAST, val);
+	regmap_update_bits(fmc2->regmap, reg, FMC2_BXTR_DATAST, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2 *fmc2,
+					     const struct stm32_fmc2_prop *prop,
+					     int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0;
+	val = FIELD_PREP(FMC2_BXTR_BUSTURN, val);
+	regmap_update_bits(fmc2->regmap, reg, FMC2_BXTR_BUSTURN, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2 *fmc2,
+					const struct stm32_fmc2_prop *prop,
+					int cs, u32 setup)
+{
+	u32 val, reg;
+	int ret;
+
+	ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, &reg);
+	if (ret)
+		return ret;
+
+	if (prop->reg_type == FMC2_REG_BWTR)
+		val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0;
+	else
+		val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX);
+	val = FIELD_PREP(FMC2_BXTR_DATAHLD, val);
+	regmap_update_bits(fmc2->regmap, reg, FMC2_BXTR_DATAHLD, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2 *fmc2,
+					 const struct stm32_fmc2_prop *prop,
+					 int cs, u32 setup)
+{
+	u32 val;
+
+	val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1;
+	val = FIELD_PREP(FMC2_BTR_CLKDIV, val);
+	regmap_update_bits(fmc2->regmap, FMC2_BTR(cs), FMC2_BTR_CLKDIV, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2 *fmc2,
+					   const struct stm32_fmc2_prop *prop,
+					   int cs, u32 setup)
+{
+	u32 val;
+
+	val = min_t(u32, setup, FMC2_BTR_DATLAT_MAX);
+	val = FIELD_PREP(FMC2_BTR_DATLAT, val);
+	regmap_update_bits(fmc2->regmap, FMC2_BTR(cs), FMC2_BTR_DATLAT, val);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2 *fmc2,
+					    const struct stm32_fmc2_prop *prop,
+					    int cs, u32 setup)
+{
+	u32 old_val, new_val, pcscntr;
+
+	if (setup < 1)
+		return 0;
+
+	regmap_read(fmc2->regmap, FMC2_PCSCNTR, &pcscntr);
+
+	/* Enable counter for the bank */
+	regmap_update_bits(fmc2->regmap, FMC2_PCSCNTR,
+			   FMC2_PCSCNTR_CNTBEN(cs),
+			   FMC2_PCSCNTR_CNTBEN(cs));
+
+	new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX);
+	old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr);
+	if (old_val && new_val > old_val)
+		/* Keep current counter value */
+		return 0;
+
+	new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val);
+	regmap_update_bits(fmc2->regmap, FMC2_PCSCNTR,
+			   FMC2_PCSCNTR_CSCOUNT, new_val);
+
+	return 0;
+}
+
+static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = {
+	/* st,fmc2_ebi_cs_trans_type must be the first property */
+	{
+		.name = "st,fmc2_ebi_cs_transaction_type",
+		.mprop = true,
+		.set = stm32_fmc2_ebi_set_trans_type,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_cclk_enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR1_CCLKEN,
+		.check = stm32_fmc2_ebi_check_cclk,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_mux_enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_MUXEN,
+		.check = stm32_fmc2_ebi_check_mux,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_buswidth",
+		.reset_val = FMC2_BUSWIDTH_16,
+		.set = stm32_fmc2_ebi_set_buswidth,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_waitpol_high",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITPOL,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_waitcfg_enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITCFG,
+		.check = stm32_fmc2_ebi_check_waitcfg,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_wait_enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_WAITEN,
+		.check = stm32_fmc2_ebi_check_sync_trans,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_asyncwait_enable",
+		.bprop = true,
+		.reg_type = FMC2_REG_BCR,
+		.reg_mask = FMC2_BCR_ASYNCWAIT,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.set = stm32_fmc2_ebi_set_bit_field,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_cpsize",
+		.check = stm32_fmc2_ebi_check_cpsize,
+		.set = stm32_fmc2_ebi_set_cpsize,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_byte_lane_setup",
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bl_setup,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_address_setup",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_ADDSET_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_setup,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_address_hold",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_ADDHLD_MAX,
+		.check = stm32_fmc2_ebi_check_address_hold,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_hold,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_data_setup",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_DATAST_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_setup,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_bus_turnaround",
+		.reg_type = FMC2_REG_BTR,
+		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bus_turnaround,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_data_hold",
+		.reg_type = FMC2_REG_BTR,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_hold,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_clk_period",
+		.reset_val = FMC2_BTR_CLKDIV_MAX + 1,
+		.check = stm32_fmc2_ebi_check_clk_period,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_clk_period,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_data_latency",
+		.check = stm32_fmc2_ebi_check_sync_trans,
+		.set = stm32_fmc2_ebi_set_data_latency,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_write_address_setup",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_ADDSET_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_setup,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_write_address_hold",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_ADDHLD_MAX,
+		.check = stm32_fmc2_ebi_check_address_hold,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_address_hold,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_write_data_setup",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_DATAST_MAX,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_setup,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_write_bus_turnaround",
+		.reg_type = FMC2_REG_BWTR,
+		.reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_bus_turnaround,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_write_data_hold",
+		.reg_type = FMC2_REG_BWTR,
+		.check = stm32_fmc2_ebi_check_async_trans,
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_data_hold,
+	},
+	{
+		.name = "st,fmc2_ebi_cs_max_low_pulse",
+		.calculate = stm32_fmc2_ebi_timing_ns_to_clock_cycles,
+		.set = stm32_fmc2_ebi_set_max_low_pulse,
+	},
+};
+
+static void stm32_fmc2_ebi_set_bank(struct stm32_fmc2 *fmc2,
+				    int cs, bool enable)
+{
+	regmap_update_bits(fmc2->regmap, FMC2_BCR(cs), FMC2_BCR_MBKEN,
+			   enable ? FMC2_BCR_MBKEN : 0);
+}
+
+static int stm32_fmc2_ebi_parse_prop(struct device *dev,
+				     struct device_node *dev_node,
+				     const struct stm32_fmc2_prop *prop,
+				     int cs)
+{
+	struct stm32_fmc2 *fmc2 = dev_get_drvdata(dev->parent);
+	u32 setup = 0;
+
+	if (!prop->set) {
+		dev_err(dev, "property %s is not well defined\n", prop->name);
+		return -EINVAL;
+	}
+
+	if (prop->check && prop->check(fmc2, prop, cs))
+		/* Skeep this property */
+		return 0;
+
+	if (prop->bprop) {
+		const __be32 *bprop = of_get_property(dev_node,
+						      prop->name, NULL);
+
+		if (prop->mprop && !bprop) {
+			dev_err(dev, "mandatory property %s not defined in the device tree\n",
+				prop->name);
+			return -EINVAL;
+		}
+
+		if (bprop)
+			setup = 1;
+	} else {
+		u32 val;
+		int ret;
+
+		ret = of_property_read_u32(dev_node, prop->name, &val);
+		if (prop->mprop && ret) {
+			dev_err(dev, "mandatory property %s not defined in the device tree\n",
+				prop->name);
+			return ret;
+		}
+
+		if (ret)
+			setup = prop->reset_val;
+		else if (prop->calculate)
+			setup = prop->calculate(fmc2, val);
+		else
+			setup = val;
+	}
+
+	return prop->set(fmc2, prop, cs, setup);
+}
+
+static int stm32_fmc2_ebi_setup_cs(struct device *dev,
+				   struct device_node *dev_node,
+				   u32 cs)
+{
+	struct stm32_fmc2 *fmc2 = dev_get_drvdata(dev->parent);
+	unsigned int i;
+	int ret;
+
+	/* Disable the bank */
+	stm32_fmc2_ebi_set_bank(fmc2, cs, false);
+
+	for (i = 0; i < ARRAY_SIZE(stm32_fmc2_child_props); i++) {
+		const struct stm32_fmc2_prop *p = &stm32_fmc2_child_props[i];
+
+		ret = stm32_fmc2_ebi_parse_prop(dev, dev_node, p, cs);
+		if (ret) {
+			dev_err(dev, "property %s could not be set: %d\n",
+				p->name, ret);
+			return ret;
+		}
+	}
+
+	/* Enable the bank */
+	stm32_fmc2_ebi_set_bank(fmc2, cs, true);
+
+	return 0;
+}
+
+static int stm32_fmc2_ebi_parse_dt(struct device *dev,
+				   struct stm32_fmc2_ebi *ebi)
+{
+	struct device_node *child;
+	bool child_found = false;
+	u32 cs;
+	int ret;
+
+	for_each_available_child_of_node(dev->of_node, child) {
+		ret = of_property_read_u32(child, "reg", &cs);
+		if (ret) {
+			dev_err(dev, "could not retrieve reg property: %d\n",
+				ret);
+			return ret;
+		}
+
+		if (cs > FMC2_MAX_EBI_CE) {
+			dev_err(dev, "invalid reg value: %d\n", cs);
+			return -EINVAL;
+		}
+
+		if (ebi->cs_assigned & BIT(cs)) {
+			dev_err(dev, "cs already assigned: %d\n", cs);
+			return -EINVAL;
+		}
+
+		ret = stm32_fmc2_ebi_setup_cs(dev, child, cs);
+		if (ret) {
+			dev_err(dev, "setup chip select %d failed: %d\n",
+				cs, ret);
+			return ret;
+		}
+
+		ebi->cs_assigned |= BIT(cs);
+		child_found = true;
+	}
+
+	if (!child_found) {
+		dev_warn(dev, "no subnodes found, disable the driver.\n");
+		return -ENODEV;
+	}
+
+	return of_platform_default_populate(dev->of_node, NULL, dev);
+}
+
+static void stm32_fmc2_ebi_save_setup(struct stm32_fmc2 *fmc2,
+				      struct stm32_fmc2_ebi *ebi)
+{
+	unsigned int cs;
+
+	for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
+		regmap_read(fmc2->regmap, FMC2_BCR(cs), &ebi->bcr[cs]);
+		regmap_read(fmc2->regmap, FMC2_BTR(cs), &ebi->btr[cs]);
+		regmap_read(fmc2->regmap, FMC2_BWTR(cs), &ebi->bwtr[cs]);
+	}
+
+	regmap_read(fmc2->regmap, FMC2_PCSCNTR, &ebi->pcscntr);
+}
+
+static void stm32_fmc2_ebi_set_setup(struct stm32_fmc2 *fmc2,
+				     struct stm32_fmc2_ebi *ebi)
+{
+	unsigned int cs;
+
+	for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
+		regmap_write(fmc2->regmap, FMC2_BCR(cs), ebi->bcr[cs]);
+		regmap_write(fmc2->regmap, FMC2_BTR(cs), ebi->btr[cs]);
+		regmap_write(fmc2->regmap, FMC2_BWTR(cs), ebi->bwtr[cs]);
+	}
+
+	regmap_write(fmc2->regmap, FMC2_PCSCNTR, ebi->pcscntr);
+}
+
+static bool stm32_fmc2_ebi_check_nwait_is_used(struct stm32_fmc2 *fmc2,
+					       struct stm32_fmc2_ebi *ebi)
+{
+	unsigned int cs;
+	u32 bcr;
+
+	for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
+		if (!(ebi->cs_assigned & BIT(cs)))
+			continue;
+
+		regmap_read(fmc2->regmap, FMC2_BCR(cs), &bcr);
+		if (bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT)
+			return true;
+	}
+
+	return false;
+}
+
+static void stm32_fmc2_ebi_disable_banks(struct stm32_fmc2 *fmc2,
+					 struct stm32_fmc2_ebi *ebi)
+{
+	unsigned int cs;
+
+	for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
+		if (!(ebi->cs_assigned & BIT(cs)))
+			continue;
+
+		stm32_fmc2_ebi_set_bank(fmc2, cs, false);
+	}
+}
+
+static int stm32_fmc2_ebi_probe(struct platform_device *pdev)
+{
+	struct stm32_fmc2 *fmc2 = dev_get_drvdata(pdev->dev.parent);
+	struct stm32_fmc2_ebi *ebi;
+	int ret;
+
+	ebi = devm_kzalloc(&pdev->dev, sizeof(*ebi), GFP_KERNEL);
+	if (!ebi)
+		return -ENOMEM;
+
+	ret = clk_prepare_enable(fmc2->clk);
+	if (ret)
+		return ret;
+
+	ret = stm32_fmc2_ebi_parse_dt(&pdev->dev, ebi);
+	if (ret)
+		goto out;
+
+	if (stm32_fmc2_ebi_check_nwait_is_used(fmc2, ebi) &&
+	    !stm32_fmc2_get_nwait(fmc2)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	stm32_fmc2_ebi_save_setup(fmc2, ebi);
+	stm32_fmc2_enable(fmc2);
+	platform_set_drvdata(pdev, ebi);
+
+	return 0;
+
+out:
+	stm32_fmc2_ebi_disable_banks(fmc2, ebi);
+	clk_disable_unprepare(fmc2->clk);
+
+	return ret;
+}
+
+static int stm32_fmc2_ebi_remove(struct platform_device *pdev)
+{
+	struct stm32_fmc2 *fmc2 = dev_get_drvdata(pdev->dev.parent);
+	struct stm32_fmc2_ebi *ebi = platform_get_drvdata(pdev);
+
+	if (stm32_fmc2_ebi_check_nwait_is_used(fmc2, ebi))
+		stm32_fmc2_put_nwait(fmc2);
+	stm32_fmc2_ebi_disable_banks(fmc2, ebi);
+	stm32_fmc2_disable(fmc2);
+	clk_disable_unprepare(fmc2->clk);
+
+	return 0;
+}
+
+static int __maybe_unused stm32_fmc2_ebi_suspend(struct device *dev)
+{
+	struct stm32_fmc2 *fmc2 = dev_get_drvdata(dev->parent);
+
+	stm32_fmc2_disable(fmc2);
+	clk_disable_unprepare(fmc2->clk);
+
+	return 0;
+}
+
+static int __maybe_unused stm32_fmc2_ebi_resume(struct device *dev)
+{
+	struct stm32_fmc2 *fmc2 = dev_get_drvdata(dev->parent);
+	struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(fmc2->clk);
+	if (ret)
+		return ret;
+
+	stm32_fmc2_ebi_set_setup(fmc2, ebi);
+	stm32_fmc2_enable(fmc2);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(stm32_fmc2_ebi_pm_ops, stm32_fmc2_ebi_suspend,
+			 stm32_fmc2_ebi_resume);
+
+static const struct of_device_id stm32_fmc2_ebi_match[] = {
+	{.compatible = "st,stm32mp1-fmc2-ebi"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, stm32_fmc2_ebi_match);
+
+static struct platform_driver stm32_fmc2_ebi_driver = {
+	.probe	= stm32_fmc2_ebi_probe,
+	.remove	= stm32_fmc2_ebi_remove,
+	.driver	= {
+		.name = "stm32_fmc2_ebi",
+		.of_match_table = stm32_fmc2_ebi_match,
+		.pm = &stm32_fmc2_ebi_pm_ops,
+	},
+};
+module_platform_driver(stm32_fmc2_ebi_driver);
+
+MODULE_ALIAS("platform:stm32_fmc2_ebi");
+MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 ebi driver");
+MODULE_LICENSE("GPL v2");
-- 
1.9.1


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

* [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (2 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI " Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-27 17:47   ` Miquel Raynal
  2020-04-15 15:57 ` [PATCH v2 05/12] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch defers its probe when the expected reset control is not
yet ready. This patch also handles properly all errors cases at probe
time.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index b6d45cd..0a96797 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -1967,7 +1967,11 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 	}
 
 	rstc = devm_reset_control_get(dev, NULL);
-	if (!IS_ERR(rstc)) {
+	if (IS_ERR(rstc)) {
+		ret = PTR_ERR(rstc);
+		if (ret == -EPROBE_DEFER)
+			goto err_clk_disable;
+	} else {
 		reset_control_assert(rstc);
 		reset_control_deassert(rstc);
 	}
@@ -1975,7 +1979,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 	/* DMA setup */
 	ret = stm32_fmc2_dma_setup(fmc2);
 	if (ret)
-		return ret;
+		goto err_dma_setup;
 
 	/* FMC2 init routine */
 	stm32_fmc2_init(fmc2);
@@ -1997,7 +2001,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 	/* Scan to find existence of the device */
 	ret = nand_scan(chip, nand->ncs);
 	if (ret)
-		goto err_scan;
+		goto err_dma_setup;
 
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret)
@@ -2010,7 +2014,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 err_device_register:
 	nand_cleanup(chip);
 
-err_scan:
+err_dma_setup:
 	if (fmc2->dma_ecc_ch)
 		dma_release_channel(fmc2->dma_ecc_ch);
 	if (fmc2->dma_tx_ch)
@@ -2021,6 +2025,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 	sg_free_table(&fmc2->dma_data_sg);
 	sg_free_table(&fmc2->dma_ecc_sg);
 
+err_clk_disable:
 	clk_disable_unprepare(fmc2->clk);
 
 	return ret;
-- 
1.9.1


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

* [PATCH v2 05/12] mtd: rawnand: stm32_fmc2: remove useless inline comments
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (3 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-27 17:48   ` Miquel Raynal
  2020-04-15 15:57 ` [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts Christophe Kerello
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

Remove inline comments that are useless since function label are
self explanatory.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 40 ----------------------------------
 1 file changed, 40 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 0a96797..ab53314 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -281,7 +281,6 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_controller *base)
 	return container_of(base, struct stm32_fmc2_nfc, base);
 }
 
-/* Timings configuration */
 static void stm32_fmc2_timings_init(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -313,7 +312,6 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
 	writel_relaxed(patt, fmc2->io_base + FMC2_PATT);
 }
 
-/* Controller configuration */
 static void stm32_fmc2_setup(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -341,7 +339,6 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
 	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
 }
 
-/* Select target */
 static int stm32_fmc2_select_chip(struct nand_chip *chip, int chipnr)
 {
 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -353,11 +350,7 @@ static int stm32_fmc2_select_chip(struct nand_chip *chip, int chipnr)
 		return 0;
 
 	fmc2->cs_sel = nand->cs_used[chipnr];
-
-	/* FMC2 setup routine */
 	stm32_fmc2_setup(chip);
-
-	/* Apply timings */
 	stm32_fmc2_timings_init(chip);
 
 	if (fmc2->dma_tx_ch && fmc2->dma_rx_ch) {
@@ -407,7 +400,6 @@ static int stm32_fmc2_select_chip(struct nand_chip *chip, int chipnr)
 	return 0;
 }
 
-/* Set bus width to 16-bit or 8-bit */
 static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
 {
 	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
@@ -418,7 +410,6 @@ static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
 	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
 }
 
-/* Enable/disable ECC */
 static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
 {
 	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
@@ -429,7 +420,6 @@ static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
 	writel(pcr, fmc2->io_base + FMC2_PCR);
 }
 
-/* Enable irq sources in case of the sequencer is used */
 static inline void stm32_fmc2_enable_seq_irq(struct stm32_fmc2_nfc *fmc2)
 {
 	u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER);
@@ -441,7 +431,6 @@ static inline void stm32_fmc2_enable_seq_irq(struct stm32_fmc2_nfc *fmc2)
 	writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER);
 }
 
-/* Disable irq sources in case of the sequencer is used */
 static inline void stm32_fmc2_disable_seq_irq(struct stm32_fmc2_nfc *fmc2)
 {
 	u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER);
@@ -453,13 +442,11 @@ static inline void stm32_fmc2_disable_seq_irq(struct stm32_fmc2_nfc *fmc2)
 	fmc2->irq_state = FMC2_IRQ_UNKNOWN;
 }
 
-/* Clear irq sources in case of the sequencer is used */
 static inline void stm32_fmc2_clear_seq_irq(struct stm32_fmc2_nfc *fmc2)
 {
 	writel_relaxed(FMC2_CSQICR_CLEAR_IRQ, fmc2->io_base + FMC2_CSQICR);
 }
 
-/* Enable irq sources in case of bch is used */
 static inline void stm32_fmc2_enable_bch_irq(struct stm32_fmc2_nfc *fmc2,
 					     int mode)
 {
@@ -475,7 +462,6 @@ static inline void stm32_fmc2_enable_bch_irq(struct stm32_fmc2_nfc *fmc2,
 	writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER);
 }
 
-/* Disable irq sources in case of bch is used */
 static inline void stm32_fmc2_disable_bch_irq(struct stm32_fmc2_nfc *fmc2)
 {
 	u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER);
@@ -488,7 +474,6 @@ static inline void stm32_fmc2_disable_bch_irq(struct stm32_fmc2_nfc *fmc2)
 	fmc2->irq_state = FMC2_IRQ_UNKNOWN;
 }
 
-/* Clear irq sources in case of bch is used */
 static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
 {
 	writel_relaxed(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
@@ -549,10 +534,7 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
 	}
 
 	heccr = readl_relaxed(fmc2->io_base + FMC2_HECCR);
-
 	stm32_fmc2_ham_set_ecc(heccr, ecc);
-
-	/* Disable ECC */
 	stm32_fmc2_set_ecc(fmc2, false);
 
 	return 0;
@@ -654,13 +636,11 @@ static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data,
 		ecc[12] = bchpbr;
 	}
 
-	/* Disable ECC */
 	stm32_fmc2_set_ecc(fmc2, false);
 
 	return 0;
 }
 
-/* BCH algorithm correction */
 static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta)
 {
 	u32 bchdsr0 = ecc_sta[0];
@@ -720,7 +700,6 @@ static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat,
 	ecc_sta[3] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR3);
 	ecc_sta[4] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR4);
 
-	/* Disable ECC */
 	stm32_fmc2_set_ecc(fmc2, false);
 
 	return stm32_fmc2_bch_decode(chip->ecc.size, dat, ecc_sta);
@@ -1054,7 +1033,6 @@ static int stm32_fmc2_sequencer_write_page(struct nand_chip *chip,
 {
 	int ret;
 
-	/* Select the target */
 	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
 	if (ret)
 		return ret;
@@ -1069,7 +1047,6 @@ static int stm32_fmc2_sequencer_write_page_raw(struct nand_chip *chip,
 {
 	int ret;
 
-	/* Select the target */
 	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
 	if (ret)
 		return ret;
@@ -1153,7 +1130,6 @@ static int stm32_fmc2_sequencer_read_page(struct nand_chip *chip, u8 *buf,
 	u16 sta_map;
 	int ret;
 
-	/* Select the target */
 	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
 	if (ret)
 		return ret;
@@ -1199,7 +1175,6 @@ static int stm32_fmc2_sequencer_read_page_raw(struct nand_chip *chip, u8 *buf,
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	int ret;
 
-	/* Select the target */
 	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
 	if (ret)
 		return ret;
@@ -1409,7 +1384,6 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip,
 	return ret;
 }
 
-/* Controller initialization */
 static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
 {
 	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
@@ -1452,7 +1426,6 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
 	writel_relaxed(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
 }
 
-/* Controller timings */
 static void stm32_fmc2_calc_timings(struct nand_chip *chip,
 				    const struct nand_sdr_timings *sdrt)
 {
@@ -1596,14 +1569,11 @@ static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr,
 		return 0;
 
 	stm32_fmc2_calc_timings(chip, sdrt);
-
-	/* Apply timings */
 	stm32_fmc2_timings_init(chip);
 
 	return 0;
 }
 
-/* DMA configuration */
 static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2)
 {
 	int ret = 0;
@@ -1667,7 +1637,6 @@ static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2)
 	return ret;
 }
 
-/* NAND callbacks setup */
 static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -1708,7 +1677,6 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
 }
 
-/* FMC2 layout */
 static int stm32_fmc2_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
 					 struct mtd_oob_region *oobregion)
 {
@@ -1744,7 +1712,6 @@ static int stm32_fmc2_nand_ooblayout_free(struct mtd_info *mtd, int section,
 	.free = stm32_fmc2_nand_ooblayout_free,
 };
 
-/* FMC2 caps */
 static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
 {
 	/* Hamming */
@@ -1763,7 +1730,6 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
 		     FMC2_ECC_STEP_SIZE,
 		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
 
-/* FMC2 controller ops */
 static int stm32_fmc2_attach_chip(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
@@ -1797,13 +1763,10 @@ static int stm32_fmc2_attach_chip(struct nand_chip *chip)
 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		chip->bbt_options |= NAND_BBT_NO_OOB;
 
-	/* NAND callbacks setup */
 	stm32_fmc2_nand_callbacks_setup(chip);
 
-	/* Define ECC layout */
 	mtd_set_ooblayout(mtd, &stm32_fmc2_nand_ooblayout_ops);
 
-	/* Configure bus width to 16-bit */
 	if (chip->options & NAND_BUSWIDTH_16)
 		stm32_fmc2_set_buswidth_16(fmc2, true);
 
@@ -1816,7 +1779,6 @@ static int stm32_fmc2_attach_chip(struct nand_chip *chip)
 	.setup_data_interface = stm32_fmc2_setup_interface,
 };
 
-/* FMC2 probe */
 static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 				  struct device_node *dn)
 {
@@ -1976,12 +1938,10 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 		reset_control_deassert(rstc);
 	}
 
-	/* DMA setup */
 	ret = stm32_fmc2_dma_setup(fmc2);
 	if (ret)
 		goto err_dma_setup;
 
-	/* FMC2 init routine */
 	stm32_fmc2_init(fmc2);
 
 	nand = &fmc2->nand;
-- 
1.9.1


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

* [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (4 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 05/12] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-27 18:22   ` Miquel Raynal
  2020-04-15 15:57 ` [PATCH v2 07/12] mtd: rawnand: stm32_fmc2: cleanup Christophe Kerello
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch removes the constant FMC2_TIMEOUT_US.
FMC2_TIMEOUT_MS is set to 5 seconds and this constant is used
each time that we need to wait (except when the timeout value
is set by the framework)

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index ab53314..f159c39 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -37,8 +37,7 @@
 /* Max ECC buffer length */
 #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
 
-#define FMC2_TIMEOUT_US			1000
-#define FMC2_TIMEOUT_MS			1000
+#define FMC2_TIMEOUT_MS			5000
 
 /* Timings */
 #define FMC2_THIZ			1
@@ -525,9 +524,9 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
 	u32 sr, heccr;
 	int ret;
 
-	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
-					 sr, sr & FMC2_SR_NWRF, 10,
-					 FMC2_TIMEOUT_MS);
+	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
+						sr, sr & FMC2_SR_NWRF, 1,
+						1000 * FMC2_TIMEOUT_MS);
 	if (ret) {
 		dev_err(fmc2->dev, "ham timeout\n");
 		return ret;
@@ -1315,7 +1314,7 @@ static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
 	/* Check if there is no pending requests to the NAND flash */
 	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
 					      sr & FMC2_SR_NWRF, 1,
-					      FMC2_TIMEOUT_US))
+					      1000 * FMC2_TIMEOUT_MS))
 		dev_warn(fmc2->dev, "Waitrdy timeout\n");
 
 	/* Wait tWB before R/B# signal is low */
-- 
1.9.1


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

* [PATCH v2 07/12] mtd: rawnand: stm32_fmc2: cleanup
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (5 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-27 18:33   ` Miquel Raynal
  2020-04-15 15:57 ` [PATCH v2 08/12] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch renames functions and local variables to be ready to use
stm32_fmc2 structure.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 812 ++++++++++++++++-----------------
 1 file changed, 404 insertions(+), 408 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index f159c39..9ce405d 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -280,12 +280,12 @@ static inline struct stm32_fmc2_nfc *to_stm32_nfc(struct nand_controller *base)
 	return container_of(base, struct stm32_fmc2_nfc, base);
 }
 
-static void stm32_fmc2_timings_init(struct nand_chip *chip)
+static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *timings = &nand->timings;
-	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
@@ -306,15 +306,15 @@ static void stm32_fmc2_timings_init(struct nand_chip *chip)
 	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
 	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
 
-	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
-	writel_relaxed(pmem, fmc2->io_base + FMC2_PMEM);
-	writel_relaxed(patt, fmc2->io_base + FMC2_PATT);
+	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
+	writel_relaxed(pmem, nfc->io_base + FMC2_PMEM);
+	writel_relaxed(patt, nfc->io_base + FMC2_PATT);
 }
 
-static void stm32_fmc2_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
-	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
 
 	/* Configure ECC algorithm (default configuration is Hamming) */
 	pcr &= ~FMC2_PCR_ECCALG;
@@ -335,174 +335,174 @@ static void stm32_fmc2_setup(struct nand_chip *chip)
 	pcr &= ~FMC2_PCR_ECCSS_MASK;
 	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
 
-	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
 }
 
-static int stm32_fmc2_select_chip(struct nand_chip *chip, int chipnr)
+static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct dma_slave_config dma_cfg;
 	int ret;
 
-	if (nand->cs_used[chipnr] == fmc2->cs_sel)
+	if (nand->cs_used[chipnr] == nfc->cs_sel)
 		return 0;
 
-	fmc2->cs_sel = nand->cs_used[chipnr];
-	stm32_fmc2_setup(chip);
-	stm32_fmc2_timings_init(chip);
+	nfc->cs_sel = nand->cs_used[chipnr];
+	stm32_fmc2_nfc_setup(chip);
+	stm32_fmc2_nfc_timings_init(chip);
 
-	if (fmc2->dma_tx_ch && fmc2->dma_rx_ch) {
+	if (nfc->dma_tx_ch && nfc->dma_rx_ch) {
 		memset(&dma_cfg, 0, sizeof(dma_cfg));
-		dma_cfg.src_addr = fmc2->data_phys_addr[fmc2->cs_sel];
-		dma_cfg.dst_addr = fmc2->data_phys_addr[fmc2->cs_sel];
+		dma_cfg.src_addr = nfc->data_phys_addr[nfc->cs_sel];
+		dma_cfg.dst_addr = nfc->data_phys_addr[nfc->cs_sel];
 		dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		dma_cfg.src_maxburst = 32;
 		dma_cfg.dst_maxburst = 32;
 
-		ret = dmaengine_slave_config(fmc2->dma_tx_ch, &dma_cfg);
+		ret = dmaengine_slave_config(nfc->dma_tx_ch, &dma_cfg);
 		if (ret) {
-			dev_err(fmc2->dev, "tx DMA engine slave config failed\n");
+			dev_err(nfc->dev, "tx DMA engine slave config failed\n");
 			return ret;
 		}
 
-		ret = dmaengine_slave_config(fmc2->dma_rx_ch, &dma_cfg);
+		ret = dmaengine_slave_config(nfc->dma_rx_ch, &dma_cfg);
 		if (ret) {
-			dev_err(fmc2->dev, "rx DMA engine slave config failed\n");
+			dev_err(nfc->dev, "rx DMA engine slave config failed\n");
 			return ret;
 		}
 	}
 
-	if (fmc2->dma_ecc_ch) {
+	if (nfc->dma_ecc_ch) {
 		/*
 		 * Hamming: we read HECCR register
 		 * BCH4/BCH8: we read BCHDSRSx registers
 		 */
 		memset(&dma_cfg, 0, sizeof(dma_cfg));
-		dma_cfg.src_addr = fmc2->io_phys_addr;
+		dma_cfg.src_addr = nfc->io_phys_addr;
 		dma_cfg.src_addr += chip->ecc.strength == FMC2_ECC_HAM ?
 				    FMC2_HECCR : FMC2_BCHDSR0;
 		dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 
-		ret = dmaengine_slave_config(fmc2->dma_ecc_ch, &dma_cfg);
+		ret = dmaengine_slave_config(nfc->dma_ecc_ch, &dma_cfg);
 		if (ret) {
-			dev_err(fmc2->dev, "ECC DMA engine slave config failed\n");
+			dev_err(nfc->dev, "ECC DMA engine slave config failed\n");
 			return ret;
 		}
 
 		/* Calculate ECC length needed for one sector */
-		fmc2->dma_ecc_len = chip->ecc.strength == FMC2_ECC_HAM ?
-				    FMC2_HECCR_LEN : FMC2_BCHDSRS_LEN;
+		nfc->dma_ecc_len = chip->ecc.strength == FMC2_ECC_HAM ?
+				   FMC2_HECCR_LEN : FMC2_BCHDSRS_LEN;
 	}
 
 	return 0;
 }
 
-static void stm32_fmc2_set_buswidth_16(struct stm32_fmc2_nfc *fmc2, bool set)
+static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc, bool set)
 {
-	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
 
 	pcr &= ~FMC2_PCR_PWID_MASK;
 	if (set)
 		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
-	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
 }
 
-static void stm32_fmc2_set_ecc(struct stm32_fmc2_nfc *fmc2, bool enable)
+static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
 {
-	u32 pcr = readl(fmc2->io_base + FMC2_PCR);
+	u32 pcr = readl(nfc->io_base + FMC2_PCR);
 
 	pcr &= ~FMC2_PCR_ECCEN;
 	if (enable)
 		pcr |= FMC2_PCR_ECCEN;
-	writel(pcr, fmc2->io_base + FMC2_PCR);
+	writel(pcr, nfc->io_base + FMC2_PCR);
 }
 
-static inline void stm32_fmc2_enable_seq_irq(struct stm32_fmc2_nfc *fmc2)
+static inline void stm32_fmc2_nfc_enable_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER);
+	u32 csqier = readl_relaxed(nfc->io_base + FMC2_CSQIER);
 
 	csqier |= FMC2_CSQIER_TCIE;
 
-	fmc2->irq_state = FMC2_IRQ_SEQ;
+	nfc->irq_state = FMC2_IRQ_SEQ;
 
-	writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER);
+	writel_relaxed(csqier, nfc->io_base + FMC2_CSQIER);
 }
 
-static inline void stm32_fmc2_disable_seq_irq(struct stm32_fmc2_nfc *fmc2)
+static inline void stm32_fmc2_nfc_disable_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	u32 csqier = readl_relaxed(fmc2->io_base + FMC2_CSQIER);
+	u32 csqier = readl_relaxed(nfc->io_base + FMC2_CSQIER);
 
 	csqier &= ~FMC2_CSQIER_TCIE;
 
-	writel_relaxed(csqier, fmc2->io_base + FMC2_CSQIER);
+	writel_relaxed(csqier, nfc->io_base + FMC2_CSQIER);
 
-	fmc2->irq_state = FMC2_IRQ_UNKNOWN;
+	nfc->irq_state = FMC2_IRQ_UNKNOWN;
 }
 
-static inline void stm32_fmc2_clear_seq_irq(struct stm32_fmc2_nfc *fmc2)
+static inline void stm32_fmc2_nfc_clear_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	writel_relaxed(FMC2_CSQICR_CLEAR_IRQ, fmc2->io_base + FMC2_CSQICR);
+	writel_relaxed(FMC2_CSQICR_CLEAR_IRQ, nfc->io_base + FMC2_CSQICR);
 }
 
-static inline void stm32_fmc2_enable_bch_irq(struct stm32_fmc2_nfc *fmc2,
-					     int mode)
+static inline void stm32_fmc2_nfc_enable_bch_irq(struct stm32_fmc2_nfc *nfc,
+						 int mode)
 {
-	u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER);
+	u32 bchier = readl_relaxed(nfc->io_base + FMC2_BCHIER);
 
 	if (mode == NAND_ECC_WRITE)
 		bchier |= FMC2_BCHIER_EPBRIE;
 	else
 		bchier |= FMC2_BCHIER_DERIE;
 
-	fmc2->irq_state = FMC2_IRQ_BCH;
+	nfc->irq_state = FMC2_IRQ_BCH;
 
-	writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER);
+	writel_relaxed(bchier, nfc->io_base + FMC2_BCHIER);
 }
 
-static inline void stm32_fmc2_disable_bch_irq(struct stm32_fmc2_nfc *fmc2)
+static inline void stm32_fmc2_nfc_disable_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	u32 bchier = readl_relaxed(fmc2->io_base + FMC2_BCHIER);
+	u32 bchier = readl_relaxed(nfc->io_base + FMC2_BCHIER);
 
 	bchier &= ~FMC2_BCHIER_DERIE;
 	bchier &= ~FMC2_BCHIER_EPBRIE;
 
-	writel_relaxed(bchier, fmc2->io_base + FMC2_BCHIER);
+	writel_relaxed(bchier, nfc->io_base + FMC2_BCHIER);
 
-	fmc2->irq_state = FMC2_IRQ_UNKNOWN;
+	nfc->irq_state = FMC2_IRQ_UNKNOWN;
 }
 
-static inline void stm32_fmc2_clear_bch_irq(struct stm32_fmc2_nfc *fmc2)
+static inline void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	writel_relaxed(FMC2_BCHICR_CLEAR_IRQ, fmc2->io_base + FMC2_BCHICR);
+	writel_relaxed(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
 }
 
 /*
  * Enable ECC logic and reset syndrome/parity bits previously calculated
  * Syndrome/parity bits is cleared by setting the ECCEN bit to 0
  */
-static void stm32_fmc2_hwctl(struct nand_chip *chip, int mode)
+static void stm32_fmc2_nfc_hwctl(struct nand_chip *chip, int mode)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	if (chip->ecc.strength != FMC2_ECC_HAM) {
-		u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+		u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
 
 		if (mode == NAND_ECC_WRITE)
 			pcr |= FMC2_PCR_WEN;
 		else
 			pcr &= ~FMC2_PCR_WEN;
-		writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+		writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
 
-		reinit_completion(&fmc2->complete);
-		stm32_fmc2_clear_bch_irq(fmc2);
-		stm32_fmc2_enable_bch_irq(fmc2, mode);
+		reinit_completion(&nfc->complete);
+		stm32_fmc2_nfc_clear_bch_irq(nfc);
+		stm32_fmc2_nfc_enable_bch_irq(nfc, mode);
 	}
 
-	stm32_fmc2_set_ecc(fmc2, true);
+	stm32_fmc2_nfc_set_ecc(nfc, true);
 }
 
 /*
@@ -510,37 +510,37 @@ static void stm32_fmc2_hwctl(struct nand_chip *chip, int mode)
  * ECC is 3 bytes for 512 bytes of data (supports error correction up to
  * max of 1-bit)
  */
-static inline void stm32_fmc2_ham_set_ecc(const u32 ecc_sta, u8 *ecc)
+static inline void stm32_fmc2_nfc_ham_set_ecc(const u32 ecc_sta, u8 *ecc)
 {
 	ecc[0] = ecc_sta;
 	ecc[1] = ecc_sta >> 8;
 	ecc[2] = ecc_sta >> 16;
 }
 
-static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
-				    u8 *ecc)
+static int stm32_fmc2_nfc_ham_calculate(struct nand_chip *chip, const u8 *data,
+					u8 *ecc)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 sr, heccr;
 	int ret;
 
-	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
+	ret = readl_relaxed_poll_timeout_atomic(nfc->io_base + FMC2_SR,
 						sr, sr & FMC2_SR_NWRF, 1,
 						1000 * FMC2_TIMEOUT_MS);
 	if (ret) {
-		dev_err(fmc2->dev, "ham timeout\n");
+		dev_err(nfc->dev, "ham timeout\n");
 		return ret;
 	}
 
-	heccr = readl_relaxed(fmc2->io_base + FMC2_HECCR);
-	stm32_fmc2_ham_set_ecc(heccr, ecc);
-	stm32_fmc2_set_ecc(fmc2, false);
+	heccr = readl_relaxed(nfc->io_base + FMC2_HECCR);
+	stm32_fmc2_nfc_ham_set_ecc(heccr, ecc);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	return 0;
 }
 
-static int stm32_fmc2_ham_correct(struct nand_chip *chip, u8 *dat,
-				  u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_ham_correct(struct nand_chip *chip, u8 *dat,
+				      u8 *read_ecc, u8 *calc_ecc)
 {
 	u8 bit_position = 0, b0, b1, b2;
 	u32 byte_addr = 0, b;
@@ -596,28 +596,28 @@ static int stm32_fmc2_ham_correct(struct nand_chip *chip, u8 *dat,
  * ECC is 7/13 bytes for 512 bytes of data (supports error correction up to
  * max of 4-bit/8-bit)
  */
-static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data,
-				    u8 *ecc)
+static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
+					u8 *ecc)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 bchpbr;
 
 	/* Wait until the BCH code is ready */
-	if (!wait_for_completion_timeout(&fmc2->complete,
+	if (!wait_for_completion_timeout(&nfc->complete,
 					 msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
-		dev_err(fmc2->dev, "bch timeout\n");
-		stm32_fmc2_disable_bch_irq(fmc2);
+		dev_err(nfc->dev, "bch timeout\n");
+		stm32_fmc2_nfc_disable_bch_irq(nfc);
 		return -ETIMEDOUT;
 	}
 
 	/* Read parity bits */
-	bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR1);
+	bchpbr = readl_relaxed(nfc->io_base + FMC2_BCHPBR1);
 	ecc[0] = bchpbr;
 	ecc[1] = bchpbr >> 8;
 	ecc[2] = bchpbr >> 16;
 	ecc[3] = bchpbr >> 24;
 
-	bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR2);
+	bchpbr = readl_relaxed(nfc->io_base + FMC2_BCHPBR2);
 	ecc[4] = bchpbr;
 	ecc[5] = bchpbr >> 8;
 	ecc[6] = bchpbr >> 16;
@@ -625,22 +625,22 @@ static int stm32_fmc2_bch_calculate(struct nand_chip *chip, const u8 *data,
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		ecc[7] = bchpbr >> 24;
 
-		bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR3);
+		bchpbr = readl_relaxed(nfc->io_base + FMC2_BCHPBR3);
 		ecc[8] = bchpbr;
 		ecc[9] = bchpbr >> 8;
 		ecc[10] = bchpbr >> 16;
 		ecc[11] = bchpbr >> 24;
 
-		bchpbr = readl_relaxed(fmc2->io_base + FMC2_BCHPBR4);
+		bchpbr = readl_relaxed(nfc->io_base + FMC2_BCHPBR4);
 		ecc[12] = bchpbr;
 	}
 
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	return 0;
 }
 
-static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta)
+static int stm32_fmc2_nfc_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta)
 {
 	u32 bchdsr0 = ecc_sta[0];
 	u32 bchdsr1 = ecc_sta[1];
@@ -679,33 +679,33 @@ static int stm32_fmc2_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta)
 	return nb_errs;
 }
 
-static int stm32_fmc2_bch_correct(struct nand_chip *chip, u8 *dat,
-				  u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_bch_correct(struct nand_chip *chip, u8 *dat,
+				      u8 *read_ecc, u8 *calc_ecc)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u32 ecc_sta[5];
 
 	/* Wait until the decoding error is ready */
-	if (!wait_for_completion_timeout(&fmc2->complete,
+	if (!wait_for_completion_timeout(&nfc->complete,
 					 msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
-		dev_err(fmc2->dev, "bch timeout\n");
-		stm32_fmc2_disable_bch_irq(fmc2);
+		dev_err(nfc->dev, "bch timeout\n");
+		stm32_fmc2_nfc_disable_bch_irq(nfc);
 		return -ETIMEDOUT;
 	}
 
-	ecc_sta[0] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR0);
-	ecc_sta[1] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR1);
-	ecc_sta[2] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR2);
-	ecc_sta[3] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR3);
-	ecc_sta[4] = readl_relaxed(fmc2->io_base + FMC2_BCHDSR4);
+	ecc_sta[0] = readl_relaxed(nfc->io_base + FMC2_BCHDSR0);
+	ecc_sta[1] = readl_relaxed(nfc->io_base + FMC2_BCHDSR1);
+	ecc_sta[2] = readl_relaxed(nfc->io_base + FMC2_BCHDSR2);
+	ecc_sta[3] = readl_relaxed(nfc->io_base + FMC2_BCHDSR3);
+	ecc_sta[4] = readl_relaxed(nfc->io_base + FMC2_BCHDSR4);
 
-	stm32_fmc2_set_ecc(fmc2, false);
+	stm32_fmc2_nfc_set_ecc(nfc, false);
 
-	return stm32_fmc2_bch_decode(chip->ecc.size, dat, ecc_sta);
+	return stm32_fmc2_nfc_bch_decode(chip->ecc.size, dat, ecc_sta);
 }
 
-static int stm32_fmc2_read_page(struct nand_chip *chip, u8 *buf,
-				int oob_required, int page)
+static int stm32_fmc2_nfc_read_page(struct nand_chip *chip, u8 *buf,
+				    int oob_required, int page)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	int ret, i, s, stat, eccsize = chip->ecc.size;
@@ -767,21 +767,21 @@ static int stm32_fmc2_read_page(struct nand_chip *chip, u8 *buf,
 }
 
 /* Sequencer read/write configuration */
-static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page,
-				    int raw, bool write_data)
+static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
+					int raw, bool write_data)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	u32 csqcfgr1, csqcfgr2, csqcfgr3;
 	u32 csqar1, csqar2;
 	u32 ecc_offset = mtd->writesize + FMC2_BBM_LEN;
-	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
+	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
 
 	if (write_data)
 		pcr |= FMC2_PCR_WEN;
 	else
 		pcr &= ~FMC2_PCR_WEN;
-	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
+	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
 
 	/*
 	 * - Set Program Page/Page Read command
@@ -843,7 +843,7 @@ static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page,
 	 * - Calculate the number of address cycles to be issued
 	 * - Set byte 5 of address cycle if needed
 	 */
-	csqar2 = FMC2_CSQCAR2_NANDCEN(fmc2->cs_sel);
+	csqar2 = FMC2_CSQCAR2_NANDCEN(nfc->cs_sel);
 	if (chip->options & NAND_BUSWIDTH_16)
 		csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset >> 1);
 	else
@@ -855,31 +855,32 @@ static void stm32_fmc2_rw_page_init(struct nand_chip *chip, int page,
 		csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(4);
 	}
 
-	writel_relaxed(csqcfgr1, fmc2->io_base + FMC2_CSQCFGR1);
-	writel_relaxed(csqcfgr2, fmc2->io_base + FMC2_CSQCFGR2);
-	writel_relaxed(csqcfgr3, fmc2->io_base + FMC2_CSQCFGR3);
-	writel_relaxed(csqar1, fmc2->io_base + FMC2_CSQAR1);
-	writel_relaxed(csqar2, fmc2->io_base + FMC2_CSQAR2);
+	writel_relaxed(csqcfgr1, nfc->io_base + FMC2_CSQCFGR1);
+	writel_relaxed(csqcfgr2, nfc->io_base + FMC2_CSQCFGR2);
+	writel_relaxed(csqcfgr3, nfc->io_base + FMC2_CSQCFGR3);
+	writel_relaxed(csqar1, nfc->io_base + FMC2_CSQAR1);
+	writel_relaxed(csqar2, nfc->io_base + FMC2_CSQAR2);
 }
 
-static void stm32_fmc2_dma_callback(void *arg)
+static void stm32_fmc2_nfc_dma_callback(void *arg)
 {
 	complete((struct completion *)arg);
 }
 
 /* Read/write data from/to a page */
-static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
-			   int raw, bool write_data)
+static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
+			       int raw, bool write_data)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct dma_async_tx_descriptor *desc_data, *desc_ecc;
 	struct scatterlist *sg;
-	struct dma_chan *dma_ch = fmc2->dma_rx_ch;
+	struct dma_chan *dma_ch = nfc->dma_rx_ch;
 	enum dma_data_direction dma_data_dir = DMA_FROM_DEVICE;
 	enum dma_transfer_direction dma_transfer_dir = DMA_DEV_TO_MEM;
-	u32 csqcr = readl_relaxed(fmc2->io_base + FMC2_CSQCR);
+	u32 csqcr = readl_relaxed(nfc->io_base + FMC2_CSQCR);
 	int eccsteps = chip->ecc.steps;
 	int eccsize = chip->ecc.size;
+	unsigned long timeout = msecs_to_jiffies(FMC2_TIMEOUT_MS);
 	const u8 *p = buf;
 	int s, ret;
 
@@ -887,20 +888,20 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
 	if (write_data) {
 		dma_data_dir = DMA_TO_DEVICE;
 		dma_transfer_dir = DMA_MEM_TO_DEV;
-		dma_ch = fmc2->dma_tx_ch;
+		dma_ch = nfc->dma_tx_ch;
 	}
 
-	for_each_sg(fmc2->dma_data_sg.sgl, sg, eccsteps, s) {
+	for_each_sg(nfc->dma_data_sg.sgl, sg, eccsteps, s) {
 		sg_set_buf(sg, p, eccsize);
 		p += eccsize;
 	}
 
-	ret = dma_map_sg(fmc2->dev, fmc2->dma_data_sg.sgl,
+	ret = dma_map_sg(nfc->dev, nfc->dma_data_sg.sgl,
 			 eccsteps, dma_data_dir);
 	if (ret < 0)
 		return ret;
 
-	desc_data = dmaengine_prep_slave_sg(dma_ch, fmc2->dma_data_sg.sgl,
+	desc_data = dmaengine_prep_slave_sg(dma_ch, nfc->dma_data_sg.sgl,
 					    eccsteps, dma_transfer_dir,
 					    DMA_PREP_INTERRUPT);
 	if (!desc_data) {
@@ -908,10 +909,10 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
 		goto err_unmap_data;
 	}
 
-	reinit_completion(&fmc2->dma_data_complete);
-	reinit_completion(&fmc2->complete);
-	desc_data->callback = stm32_fmc2_dma_callback;
-	desc_data->callback_param = &fmc2->dma_data_complete;
+	reinit_completion(&nfc->dma_data_complete);
+	reinit_completion(&nfc->complete);
+	desc_data->callback = stm32_fmc2_nfc_dma_callback;
+	desc_data->callback_param = &nfc->dma_data_complete;
 	ret = dma_submit_error(dmaengine_submit(desc_data));
 	if (ret)
 		goto err_unmap_data;
@@ -920,19 +921,19 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
 
 	if (!write_data && !raw) {
 		/* Configure DMA ECC status */
-		p = fmc2->ecc_buf;
-		for_each_sg(fmc2->dma_ecc_sg.sgl, sg, eccsteps, s) {
-			sg_set_buf(sg, p, fmc2->dma_ecc_len);
-			p += fmc2->dma_ecc_len;
+		p = nfc->ecc_buf;
+		for_each_sg(nfc->dma_ecc_sg.sgl, sg, eccsteps, s) {
+			sg_set_buf(sg, p, nfc->dma_ecc_len);
+			p += nfc->dma_ecc_len;
 		}
 
-		ret = dma_map_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl,
+		ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
 				 eccsteps, dma_data_dir);
 		if (ret < 0)
 			goto err_unmap_data;
 
-		desc_ecc = dmaengine_prep_slave_sg(fmc2->dma_ecc_ch,
-						   fmc2->dma_ecc_sg.sgl,
+		desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch,
+						   nfc->dma_ecc_sg.sgl,
 						   eccsteps, dma_transfer_dir,
 						   DMA_PREP_INTERRUPT);
 		if (!desc_ecc) {
@@ -940,76 +941,73 @@ static int stm32_fmc2_xfer(struct nand_chip *chip, const u8 *buf,
 			goto err_unmap_ecc;
 		}
 
-		reinit_completion(&fmc2->dma_ecc_complete);
-		desc_ecc->callback = stm32_fmc2_dma_callback;
-		desc_ecc->callback_param = &fmc2->dma_ecc_complete;
+		reinit_completion(&nfc->dma_ecc_complete);
+		desc_ecc->callback = stm32_fmc2_nfc_dma_callback;
+		desc_ecc->callback_param = &nfc->dma_ecc_complete;
 		ret = dma_submit_error(dmaengine_submit(desc_ecc));
 		if (ret)
 			goto err_unmap_ecc;
 
-		dma_async_issue_pending(fmc2->dma_ecc_ch);
+		dma_async_issue_pending(nfc->dma_ecc_ch);
 	}
 
-	stm32_fmc2_clear_seq_irq(fmc2);
-	stm32_fmc2_enable_seq_irq(fmc2);
+	stm32_fmc2_nfc_clear_seq_irq(nfc);
+	stm32_fmc2_nfc_enable_seq_irq(nfc);
 
 	/* Start the transfer */
 	csqcr |= FMC2_CSQCR_CSQSTART;
-	writel_relaxed(csqcr, fmc2->io_base + FMC2_CSQCR);
+	writel_relaxed(csqcr, nfc->io_base + FMC2_CSQCR);
 
 	/* Wait end of sequencer transfer */
-	if (!wait_for_completion_timeout(&fmc2->complete,
-					 msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
-		dev_err(fmc2->dev, "seq timeout\n");
-		stm32_fmc2_disable_seq_irq(fmc2);
+	if (!wait_for_completion_timeout(&nfc->complete, timeout)) {
+		dev_err(nfc->dev, "seq timeout\n");
+		stm32_fmc2_nfc_disable_seq_irq(nfc);
 		dmaengine_terminate_all(dma_ch);
 		if (!write_data && !raw)
-			dmaengine_terminate_all(fmc2->dma_ecc_ch);
+			dmaengine_terminate_all(nfc->dma_ecc_ch);
 		ret = -ETIMEDOUT;
 		goto err_unmap_ecc;
 	}
 
 	/* Wait DMA data transfer completion */
-	if (!wait_for_completion_timeout(&fmc2->dma_data_complete,
-					 msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
-		dev_err(fmc2->dev, "data DMA timeout\n");
+	if (!wait_for_completion_timeout(&nfc->dma_data_complete, timeout)) {
+		dev_err(nfc->dev, "data DMA timeout\n");
 		dmaengine_terminate_all(dma_ch);
 		ret = -ETIMEDOUT;
 	}
 
 	/* Wait DMA ECC transfer completion */
 	if (!write_data && !raw) {
-		if (!wait_for_completion_timeout(&fmc2->dma_ecc_complete,
-					msecs_to_jiffies(FMC2_TIMEOUT_MS))) {
-			dev_err(fmc2->dev, "ECC DMA timeout\n");
-			dmaengine_terminate_all(fmc2->dma_ecc_ch);
+		if (!wait_for_completion_timeout(&nfc->dma_ecc_complete,
+						 timeout)) {
+			dev_err(nfc->dev, "ECC DMA timeout\n");
+			dmaengine_terminate_all(nfc->dma_ecc_ch);
 			ret = -ETIMEDOUT;
 		}
 	}
 
 err_unmap_ecc:
 	if (!write_data && !raw)
-		dma_unmap_sg(fmc2->dev, fmc2->dma_ecc_sg.sgl,
+		dma_unmap_sg(nfc->dev, nfc->dma_ecc_sg.sgl,
 			     eccsteps, dma_data_dir);
 
 err_unmap_data:
-	dma_unmap_sg(fmc2->dev, fmc2->dma_data_sg.sgl, eccsteps, dma_data_dir);
+	dma_unmap_sg(nfc->dev, nfc->dma_data_sg.sgl, eccsteps, dma_data_dir);
 
 	return ret;
 }
 
-static int stm32_fmc2_sequencer_write(struct nand_chip *chip,
-				      const u8 *buf, int oob_required,
-				      int page, int raw)
+static int stm32_fmc2_nfc_seq_write(struct nand_chip *chip, const u8 *buf,
+				    int oob_required, int page, int raw)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	int ret;
 
 	/* Configure the sequencer */
-	stm32_fmc2_rw_page_init(chip, page, raw, true);
+	stm32_fmc2_nfc_rw_page_init(chip, page, raw, true);
 
 	/* Write the page */
-	ret = stm32_fmc2_xfer(chip, buf, raw, true);
+	ret = stm32_fmc2_nfc_xfer(chip, buf, raw, true);
 	if (ret)
 		return ret;
 
@@ -1025,53 +1023,50 @@ static int stm32_fmc2_sequencer_write(struct nand_chip *chip,
 	return nand_prog_page_end_op(chip);
 }
 
-static int stm32_fmc2_sequencer_write_page(struct nand_chip *chip,
-					   const u8 *buf,
-					   int oob_required,
-					   int page)
+static int stm32_fmc2_nfc_seq_write_page(struct nand_chip *chip, const u8 *buf,
+					 int oob_required, int page)
 {
 	int ret;
 
-	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
+	ret = stm32_fmc2_nfc_select_chip(chip, chip->cur_cs);
 	if (ret)
 		return ret;
 
-	return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, false);
+	return stm32_fmc2_nfc_seq_write(chip, buf, oob_required, page, false);
 }
 
-static int stm32_fmc2_sequencer_write_page_raw(struct nand_chip *chip,
-					       const u8 *buf,
-					       int oob_required,
-					       int page)
+static int stm32_fmc2_nfc_seq_write_page_raw(struct nand_chip *chip,
+					     const u8 *buf, int oob_required,
+					     int page)
 {
 	int ret;
 
-	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
+	ret = stm32_fmc2_nfc_select_chip(chip, chip->cur_cs);
 	if (ret)
 		return ret;
 
-	return stm32_fmc2_sequencer_write(chip, buf, oob_required, page, true);
+	return stm32_fmc2_nfc_seq_write(chip, buf, oob_required, page, true);
 }
 
 /* Get a status indicating which sectors have errors */
-static inline u16 stm32_fmc2_get_mapping_status(struct stm32_fmc2_nfc *fmc2)
+static inline u16 stm32_fmc2_nfc_get_mapping_status(struct stm32_fmc2_nfc *nfc)
 {
-	u32 csqemsr = readl_relaxed(fmc2->io_base + FMC2_CSQEMSR);
+	u32 csqemsr = readl_relaxed(nfc->io_base + FMC2_CSQEMSR);
 
 	return csqemsr & FMC2_CSQEMSR_SEM;
 }
 
-static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat,
-					u8 *read_ecc, u8 *calc_ecc)
+static int stm32_fmc2_nfc_seq_correct(struct nand_chip *chip, u8 *dat,
+				      u8 *read_ecc, u8 *calc_ecc)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	int eccbytes = chip->ecc.bytes;
 	int eccsteps = chip->ecc.steps;
 	int eccstrength = chip->ecc.strength;
 	int i, s, eccsize = chip->ecc.size;
-	u32 *ecc_sta = (u32 *)fmc2->ecc_buf;
-	u16 sta_map = stm32_fmc2_get_mapping_status(fmc2);
+	u32 *ecc_sta = (u32 *)nfc->ecc_buf;
+	u16 sta_map = stm32_fmc2_nfc_get_mapping_status(nfc);
 	unsigned int max_bitflips = 0;
 
 	for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, dat += eccsize) {
@@ -1080,10 +1075,11 @@ static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat,
 		if (eccstrength == FMC2_ECC_HAM) {
 			/* Ecc_sta = FMC2_HECCR */
 			if (sta_map & BIT(s)) {
-				stm32_fmc2_ham_set_ecc(*ecc_sta, &calc_ecc[i]);
-				stat = stm32_fmc2_ham_correct(chip, dat,
-							      &read_ecc[i],
-							      &calc_ecc[i]);
+				stm32_fmc2_nfc_ham_set_ecc(*ecc_sta,
+							   &calc_ecc[i]);
+				stat = stm32_fmc2_nfc_ham_correct(chip, dat,
+								  &read_ecc[i],
+								  &calc_ecc[i]);
 			}
 			ecc_sta++;
 		} else {
@@ -1095,8 +1091,8 @@ static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat,
 			 * Ecc_sta[4] = FMC2_BCHDSR4
 			 */
 			if (sta_map & BIT(s))
-				stat = stm32_fmc2_bch_decode(eccsize, dat,
-							     ecc_sta);
+				stat = stm32_fmc2_nfc_bch_decode(eccsize, dat,
+								 ecc_sta);
 			ecc_sta += 5;
 		}
 
@@ -1119,29 +1115,29 @@ static int stm32_fmc2_sequencer_correct(struct nand_chip *chip, u8 *dat,
 	return max_bitflips;
 }
 
-static int stm32_fmc2_sequencer_read_page(struct nand_chip *chip, u8 *buf,
-					  int oob_required, int page)
+static int stm32_fmc2_nfc_seq_read_page(struct nand_chip *chip, u8 *buf,
+					int oob_required, int page)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	u8 *ecc_calc = chip->ecc.calc_buf;
 	u8 *ecc_code = chip->ecc.code_buf;
 	u16 sta_map;
 	int ret;
 
-	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
+	ret = stm32_fmc2_nfc_select_chip(chip, chip->cur_cs);
 	if (ret)
 		return ret;
 
 	/* Configure the sequencer */
-	stm32_fmc2_rw_page_init(chip, page, 0, false);
+	stm32_fmc2_nfc_rw_page_init(chip, page, 0, false);
 
 	/* Read the page */
-	ret = stm32_fmc2_xfer(chip, buf, 0, false);
+	ret = stm32_fmc2_nfc_xfer(chip, buf, 0, false);
 	if (ret)
 		return ret;
 
-	sta_map = stm32_fmc2_get_mapping_status(fmc2);
+	sta_map = stm32_fmc2_nfc_get_mapping_status(nfc);
 
 	/* Check if errors happen */
 	if (likely(!sta_map)) {
@@ -1168,21 +1164,21 @@ static int stm32_fmc2_sequencer_read_page(struct nand_chip *chip, u8 *buf,
 	return chip->ecc.correct(chip, buf, ecc_code, ecc_calc);
 }
 
-static int stm32_fmc2_sequencer_read_page_raw(struct nand_chip *chip, u8 *buf,
-					      int oob_required, int page)
+static int stm32_fmc2_nfc_seq_read_page_raw(struct nand_chip *chip, u8 *buf,
+					    int oob_required, int page)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	int ret;
 
-	ret = stm32_fmc2_select_chip(chip, chip->cur_cs);
+	ret = stm32_fmc2_nfc_select_chip(chip, chip->cur_cs);
 	if (ret)
 		return ret;
 
 	/* Configure the sequencer */
-	stm32_fmc2_rw_page_init(chip, page, 1, false);
+	stm32_fmc2_nfc_rw_page_init(chip, page, 1, false);
 
 	/* Read the page */
-	ret = stm32_fmc2_xfer(chip, buf, 1, false);
+	ret = stm32_fmc2_nfc_xfer(chip, buf, 1, false);
 	if (ret)
 		return ret;
 
@@ -1195,31 +1191,31 @@ static int stm32_fmc2_sequencer_read_page_raw(struct nand_chip *chip, u8 *buf,
 	return 0;
 }
 
-static irqreturn_t stm32_fmc2_irq(int irq, void *dev_id)
+static irqreturn_t stm32_fmc2_nfc_irq(int irq, void *dev_id)
 {
-	struct stm32_fmc2_nfc *fmc2 = (struct stm32_fmc2_nfc *)dev_id;
+	struct stm32_fmc2_nfc *nfc = (struct stm32_fmc2_nfc *)dev_id;
 
-	if (fmc2->irq_state == FMC2_IRQ_SEQ)
+	if (nfc->irq_state == FMC2_IRQ_SEQ)
 		/* Sequencer is used */
-		stm32_fmc2_disable_seq_irq(fmc2);
-	else if (fmc2->irq_state == FMC2_IRQ_BCH)
+		stm32_fmc2_nfc_disable_seq_irq(nfc);
+	else if (nfc->irq_state == FMC2_IRQ_BCH)
 		/* BCH is used */
-		stm32_fmc2_disable_bch_irq(fmc2);
+		stm32_fmc2_nfc_disable_bch_irq(nfc);
 
-	complete(&fmc2->complete);
+	complete(&nfc->complete);
 
 	return IRQ_HANDLED;
 }
 
-static void stm32_fmc2_read_data(struct nand_chip *chip, void *buf,
-				 unsigned int len, bool force_8bit)
+static void stm32_fmc2_nfc_read_data(struct nand_chip *chip, void *buf,
+				     unsigned int len, bool force_8bit)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
-	void __iomem *io_addr_r = fmc2->data_base[fmc2->cs_sel];
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	void __iomem *io_addr_r = nfc->data_base[nfc->cs_sel];
 
 	if (force_8bit && chip->options & NAND_BUSWIDTH_16)
 		/* Reconfigure bus width to 8-bit */
-		stm32_fmc2_set_buswidth_16(fmc2, false);
+		stm32_fmc2_nfc_set_buswidth_16(nfc, false);
 
 	if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) {
 		if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) {
@@ -1255,18 +1251,18 @@ static void stm32_fmc2_read_data(struct nand_chip *chip, void *buf,
 
 	if (force_8bit && chip->options & NAND_BUSWIDTH_16)
 		/* Reconfigure bus width to 16-bit */
-		stm32_fmc2_set_buswidth_16(fmc2, true);
+		stm32_fmc2_nfc_set_buswidth_16(nfc, true);
 }
 
-static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf,
-				  unsigned int len, bool force_8bit)
+static void stm32_fmc2_nfc_write_data(struct nand_chip *chip, const void *buf,
+				      unsigned int len, bool force_8bit)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
-	void __iomem *io_addr_w = fmc2->data_base[fmc2->cs_sel];
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	void __iomem *io_addr_w = nfc->data_base[nfc->cs_sel];
 
 	if (force_8bit && chip->options & NAND_BUSWIDTH_16)
 		/* Reconfigure bus width to 8-bit */
-		stm32_fmc2_set_buswidth_16(fmc2, false);
+		stm32_fmc2_nfc_set_buswidth_16(nfc, false);
 
 	if (!IS_ALIGNED((uintptr_t)buf, sizeof(u32))) {
 		if (!IS_ALIGNED((uintptr_t)buf, sizeof(u16)) && len) {
@@ -1302,44 +1298,45 @@ static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf,
 
 	if (force_8bit && chip->options & NAND_BUSWIDTH_16)
 		/* Reconfigure bus width to 16-bit */
-		stm32_fmc2_set_buswidth_16(fmc2, true);
+		stm32_fmc2_nfc_set_buswidth_16(nfc, true);
 }
 
-static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
+static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
+				  unsigned long timeout_ms)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	const struct nand_sdr_timings *timings;
 	u32 isr, sr;
 
 	/* Check if there is no pending requests to the NAND flash */
-	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
+	if (readl_relaxed_poll_timeout_atomic(nfc->io_base + FMC2_SR, sr,
 					      sr & FMC2_SR_NWRF, 1,
 					      1000 * FMC2_TIMEOUT_MS))
-		dev_warn(fmc2->dev, "Waitrdy timeout\n");
+		dev_warn(nfc->dev, "Waitrdy timeout\n");
 
 	/* Wait tWB before R/B# signal is low */
 	timings = nand_get_sdr_timings(&chip->data_interface);
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	/* R/B# signal is low, clear high level flag */
-	writel_relaxed(FMC2_ICR_CIHLF, fmc2->io_base + FMC2_ICR);
+	writel_relaxed(FMC2_ICR_CIHLF, nfc->io_base + FMC2_ICR);
 
 	/* Wait R/B# signal is high */
-	return readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_ISR,
+	return readl_relaxed_poll_timeout_atomic(nfc->io_base + FMC2_ISR,
 						 isr, isr & FMC2_ISR_IHLF,
 						 5, 1000 * timeout_ms);
 }
 
-static int stm32_fmc2_exec_op(struct nand_chip *chip,
-			      const struct nand_operation *op,
-			      bool check_only)
+static int stm32_fmc2_nfc_exec_op(struct nand_chip *chip,
+				  const struct nand_operation *op,
+				  bool check_only)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	const struct nand_op_instr *instr = NULL;
-	unsigned int op_id, i;
+	unsigned int op_id, i, timeout;
 	int ret;
 
-	ret = stm32_fmc2_select_chip(chip, op->cs);
+	ret = stm32_fmc2_nfc_select_chip(chip, op->cs);
 	if (ret)
 		return ret;
 
@@ -1352,30 +1349,30 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip,
 		switch (instr->type) {
 		case NAND_OP_CMD_INSTR:
 			writeb_relaxed(instr->ctx.cmd.opcode,
-				       fmc2->cmd_base[fmc2->cs_sel]);
+				       nfc->cmd_base[nfc->cs_sel]);
 			break;
 
 		case NAND_OP_ADDR_INSTR:
 			for (i = 0; i < instr->ctx.addr.naddrs; i++)
 				writeb_relaxed(instr->ctx.addr.addrs[i],
-					       fmc2->addr_base[fmc2->cs_sel]);
+					       nfc->addr_base[nfc->cs_sel]);
 			break;
 
 		case NAND_OP_DATA_IN_INSTR:
-			stm32_fmc2_read_data(chip, instr->ctx.data.buf.in,
-					     instr->ctx.data.len,
-					     instr->ctx.data.force_8bit);
+			stm32_fmc2_nfc_read_data(chip, instr->ctx.data.buf.in,
+						 instr->ctx.data.len,
+						 instr->ctx.data.force_8bit);
 			break;
 
 		case NAND_OP_DATA_OUT_INSTR:
-			stm32_fmc2_write_data(chip, instr->ctx.data.buf.out,
-					      instr->ctx.data.len,
-					      instr->ctx.data.force_8bit);
+			stm32_fmc2_nfc_write_data(chip, instr->ctx.data.buf.out,
+						  instr->ctx.data.len,
+						  instr->ctx.data.force_8bit);
 			break;
 
 		case NAND_OP_WAITRDY_INSTR:
-			ret = stm32_fmc2_waitrdy(chip,
-						 instr->ctx.waitrdy.timeout_ms);
+			timeout = instr->ctx.waitrdy.timeout_ms;
+			ret = stm32_fmc2_nfc_waitrdy(chip, timeout);
 			break;
 		}
 	}
@@ -1383,13 +1380,13 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip,
 	return ret;
 }
 
-static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
+static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 {
-	u32 pcr = readl_relaxed(fmc2->io_base + FMC2_PCR);
-	u32 bcr1 = readl_relaxed(fmc2->io_base + FMC2_BCR1);
+	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
+	u32 bcr1 = readl_relaxed(nfc->io_base + FMC2_BCR1);
 
 	/* Set CS used to undefined */
-	fmc2->cs_sel = -1;
+	nfc->cs_sel = -1;
 
 	/* Enable wait feature and nand flash memory bank */
 	pcr |= FMC2_PCR_PWAITEN;
@@ -1419,19 +1416,19 @@ static void stm32_fmc2_init(struct stm32_fmc2_nfc *fmc2)
 	/* Enable FMC2 controller */
 	bcr1 |= FMC2_BCR1_FMC2EN;
 
-	writel_relaxed(bcr1, fmc2->io_base + FMC2_BCR1);
-	writel_relaxed(pcr, fmc2->io_base + FMC2_PCR);
-	writel_relaxed(FMC2_PMEM_DEFAULT, fmc2->io_base + FMC2_PMEM);
-	writel_relaxed(FMC2_PATT_DEFAULT, fmc2->io_base + FMC2_PATT);
+	writel_relaxed(bcr1, nfc->io_base + FMC2_BCR1);
+	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
+	writel_relaxed(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
+	writel_relaxed(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
 }
 
-static void stm32_fmc2_calc_timings(struct nand_chip *chip,
-				    const struct nand_sdr_timings *sdrt)
+static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
+					const struct nand_sdr_timings *sdrt)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *tims = &nand->timings;
-	unsigned long hclk = clk_get_rate(fmc2->clk);
+	unsigned long hclk = clk_get_rate(nfc->clk);
 	unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000);
 	unsigned long timing, tar, tclr, thiz, twait;
 	unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -1555,80 +1552,79 @@ static void stm32_fmc2_calc_timings(struct nand_chip *chip,
 	tims->thold_att = clamp_val(timing, 1, FMC2_PMEM_PATT_TIMING_MASK);
 }
 
-static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr,
-				      const struct nand_data_interface *conf)
+static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr,
+					  const struct nand_data_interface *cf)
 {
 	const struct nand_sdr_timings *sdrt;
 
-	sdrt = nand_get_sdr_timings(conf);
+	sdrt = nand_get_sdr_timings(cf);
 	if (IS_ERR(sdrt))
 		return PTR_ERR(sdrt);
 
 	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
 		return 0;
 
-	stm32_fmc2_calc_timings(chip, sdrt);
-	stm32_fmc2_timings_init(chip);
+	stm32_fmc2_nfc_calc_timings(chip, sdrt);
+	stm32_fmc2_nfc_timings_init(chip);
 
 	return 0;
 }
 
-static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2)
+static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc)
 {
 	int ret = 0;
 
-	fmc2->dma_tx_ch = dma_request_chan(fmc2->dev, "tx");
-	if (IS_ERR(fmc2->dma_tx_ch)) {
-		ret = PTR_ERR(fmc2->dma_tx_ch);
+	nfc->dma_tx_ch = dma_request_chan(nfc->dev, "tx");
+	if (IS_ERR(nfc->dma_tx_ch)) {
+		ret = PTR_ERR(nfc->dma_tx_ch);
 		if (ret != -ENODEV)
-			dev_err(fmc2->dev,
+			dev_err(nfc->dev,
 				"failed to request tx DMA channel: %d\n", ret);
-		fmc2->dma_tx_ch = NULL;
+		nfc->dma_tx_ch = NULL;
 		goto err_dma;
 	}
 
-	fmc2->dma_rx_ch = dma_request_chan(fmc2->dev, "rx");
-	if (IS_ERR(fmc2->dma_rx_ch)) {
-		ret = PTR_ERR(fmc2->dma_rx_ch);
+	nfc->dma_rx_ch = dma_request_chan(nfc->dev, "rx");
+	if (IS_ERR(nfc->dma_rx_ch)) {
+		ret = PTR_ERR(nfc->dma_rx_ch);
 		if (ret != -ENODEV)
-			dev_err(fmc2->dev,
+			dev_err(nfc->dev,
 				"failed to request rx DMA channel: %d\n", ret);
-		fmc2->dma_rx_ch = NULL;
+		nfc->dma_rx_ch = NULL;
 		goto err_dma;
 	}
 
-	fmc2->dma_ecc_ch = dma_request_chan(fmc2->dev, "ecc");
-	if (IS_ERR(fmc2->dma_ecc_ch)) {
-		ret = PTR_ERR(fmc2->dma_ecc_ch);
+	nfc->dma_ecc_ch = dma_request_chan(nfc->dev, "ecc");
+	if (IS_ERR(nfc->dma_ecc_ch)) {
+		ret = PTR_ERR(nfc->dma_ecc_ch);
 		if (ret != -ENODEV)
-			dev_err(fmc2->dev,
+			dev_err(nfc->dev,
 				"failed to request ecc DMA channel: %d\n", ret);
-		fmc2->dma_ecc_ch = NULL;
+		nfc->dma_ecc_ch = NULL;
 		goto err_dma;
 	}
 
-	ret = sg_alloc_table(&fmc2->dma_ecc_sg, FMC2_MAX_SG, GFP_KERNEL);
+	ret = sg_alloc_table(&nfc->dma_ecc_sg, FMC2_MAX_SG, GFP_KERNEL);
 	if (ret)
 		return ret;
 
 	/* Allocate a buffer to store ECC status registers */
-	fmc2->ecc_buf = devm_kzalloc(fmc2->dev, FMC2_MAX_ECC_BUF_LEN,
-				     GFP_KERNEL);
-	if (!fmc2->ecc_buf)
+	nfc->ecc_buf = devm_kzalloc(nfc->dev, FMC2_MAX_ECC_BUF_LEN, GFP_KERNEL);
+	if (!nfc->ecc_buf)
 		return -ENOMEM;
 
-	ret = sg_alloc_table(&fmc2->dma_data_sg, FMC2_MAX_SG, GFP_KERNEL);
+	ret = sg_alloc_table(&nfc->dma_data_sg, FMC2_MAX_SG, GFP_KERNEL);
 	if (ret)
 		return ret;
 
-	init_completion(&fmc2->dma_data_complete);
-	init_completion(&fmc2->dma_ecc_complete);
+	init_completion(&nfc->dma_data_complete);
+	init_completion(&nfc->dma_ecc_complete);
 
 	return 0;
 
 err_dma:
 	if (ret == -ENODEV) {
-		dev_warn(fmc2->dev,
+		dev_warn(nfc->dev,
 			 "DMAs not defined in the DT, polling mode is used\n");
 		ret = 0;
 	}
@@ -1636,34 +1632,34 @@ static int stm32_fmc2_dma_setup(struct stm32_fmc2_nfc *fmc2)
 	return ret;
 }
 
-static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
+static void stm32_fmc2_nfc_nand_callbacks_setup(struct nand_chip *chip)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 
 	/*
 	 * Specific callbacks to read/write a page depending on
 	 * the mode (polling/sequencer) and the algo used (Hamming, BCH).
 	 */
-	if (fmc2->dma_tx_ch && fmc2->dma_rx_ch && fmc2->dma_ecc_ch) {
+	if (nfc->dma_tx_ch && nfc->dma_rx_ch && nfc->dma_ecc_ch) {
 		/* DMA => use sequencer mode callbacks */
-		chip->ecc.correct = stm32_fmc2_sequencer_correct;
-		chip->ecc.write_page = stm32_fmc2_sequencer_write_page;
-		chip->ecc.read_page = stm32_fmc2_sequencer_read_page;
-		chip->ecc.write_page_raw = stm32_fmc2_sequencer_write_page_raw;
-		chip->ecc.read_page_raw = stm32_fmc2_sequencer_read_page_raw;
+		chip->ecc.correct = stm32_fmc2_nfc_seq_correct;
+		chip->ecc.write_page = stm32_fmc2_nfc_seq_write_page;
+		chip->ecc.read_page = stm32_fmc2_nfc_seq_read_page;
+		chip->ecc.write_page_raw = stm32_fmc2_nfc_seq_write_page_raw;
+		chip->ecc.read_page_raw = stm32_fmc2_nfc_seq_read_page_raw;
 	} else {
 		/* No DMA => use polling mode callbacks */
-		chip->ecc.hwctl = stm32_fmc2_hwctl;
+		chip->ecc.hwctl = stm32_fmc2_nfc_hwctl;
 		if (chip->ecc.strength == FMC2_ECC_HAM) {
 			/* Hamming is used */
-			chip->ecc.calculate = stm32_fmc2_ham_calculate;
-			chip->ecc.correct = stm32_fmc2_ham_correct;
+			chip->ecc.calculate = stm32_fmc2_nfc_ham_calculate;
+			chip->ecc.correct = stm32_fmc2_nfc_ham_correct;
 			chip->ecc.options |= NAND_ECC_GENERIC_ERASED_CHECK;
 		} else {
 			/* BCH is used */
-			chip->ecc.calculate = stm32_fmc2_bch_calculate;
-			chip->ecc.correct = stm32_fmc2_bch_correct;
-			chip->ecc.read_page = stm32_fmc2_read_page;
+			chip->ecc.calculate = stm32_fmc2_nfc_bch_calculate;
+			chip->ecc.correct = stm32_fmc2_nfc_bch_correct;
+			chip->ecc.read_page = stm32_fmc2_nfc_read_page;
 		}
 	}
 
@@ -1676,8 +1672,8 @@ static void stm32_fmc2_nand_callbacks_setup(struct nand_chip *chip)
 		chip->ecc.bytes = chip->options & NAND_BUSWIDTH_16 ? 8 : 7;
 }
 
-static int stm32_fmc2_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
-					 struct mtd_oob_region *oobregion)
+static int stm32_fmc2_nfc_ooblayout_ecc(struct mtd_info *mtd, int section,
+					struct mtd_oob_region *oobregion)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
@@ -1691,8 +1687,8 @@ static int stm32_fmc2_nand_ooblayout_ecc(struct mtd_info *mtd, int section,
 	return 0;
 }
 
-static int stm32_fmc2_nand_ooblayout_free(struct mtd_info *mtd, int section,
-					  struct mtd_oob_region *oobregion)
+static int stm32_fmc2_nfc_ooblayout_free(struct mtd_info *mtd, int section,
+					 struct mtd_oob_region *oobregion)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
@@ -1706,12 +1702,12 @@ static int stm32_fmc2_nand_ooblayout_free(struct mtd_info *mtd, int section,
 	return 0;
 }
 
-static const struct mtd_ooblayout_ops stm32_fmc2_nand_ooblayout_ops = {
-	.ecc = stm32_fmc2_nand_ooblayout_ecc,
-	.free = stm32_fmc2_nand_ooblayout_free,
+static const struct mtd_ooblayout_ops stm32_fmc2_nfc_ooblayout_ops = {
+	.ecc = stm32_fmc2_nfc_ooblayout_ecc,
+	.free = stm32_fmc2_nfc_ooblayout_free,
 };
 
-static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
+static int stm32_fmc2_nfc_calc_ecc_bytes(int step_size, int strength)
 {
 	/* Hamming */
 	if (strength == FMC2_ECC_HAM)
@@ -1725,13 +1721,13 @@ static int stm32_fmc2_calc_ecc_bytes(int step_size, int strength)
 	return 8;
 }
 
-NAND_ECC_CAPS_SINGLE(stm32_fmc2_ecc_caps, stm32_fmc2_calc_ecc_bytes,
+NAND_ECC_CAPS_SINGLE(stm32_fmc2_nfc_ecc_caps, stm32_fmc2_nfc_calc_ecc_bytes,
 		     FMC2_ECC_STEP_SIZE,
 		     FMC2_ECC_HAM, FMC2_ECC_BCH4, FMC2_ECC_BCH8);
 
-static int stm32_fmc2_attach_chip(struct nand_chip *chip)
+static int stm32_fmc2_nfc_attach_chip(struct nand_chip *chip)
 {
-	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	int ret;
 
@@ -1743,45 +1739,45 @@ static int stm32_fmc2_attach_chip(struct nand_chip *chip)
 	 * ECC sector size = 512
 	 */
 	if (chip->ecc.mode != NAND_ECC_HW) {
-		dev_err(fmc2->dev, "nand_ecc_mode is not well defined in the DT\n");
+		dev_err(nfc->dev, "nand_ecc_mode is not well defined in the DT\n");
 		return -EINVAL;
 	}
 
-	ret = nand_ecc_choose_conf(chip, &stm32_fmc2_ecc_caps,
+	ret = nand_ecc_choose_conf(chip, &stm32_fmc2_nfc_ecc_caps,
 				   mtd->oobsize - FMC2_BBM_LEN);
 	if (ret) {
-		dev_err(fmc2->dev, "no valid ECC settings set\n");
+		dev_err(nfc->dev, "no valid ECC settings set\n");
 		return ret;
 	}
 
 	if (mtd->writesize / chip->ecc.size > FMC2_MAX_SG) {
-		dev_err(fmc2->dev, "nand page size is not supported\n");
+		dev_err(nfc->dev, "nand page size is not supported\n");
 		return -EINVAL;
 	}
 
 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		chip->bbt_options |= NAND_BBT_NO_OOB;
 
-	stm32_fmc2_nand_callbacks_setup(chip);
+	stm32_fmc2_nfc_nand_callbacks_setup(chip);
 
-	mtd_set_ooblayout(mtd, &stm32_fmc2_nand_ooblayout_ops);
+	mtd_set_ooblayout(mtd, &stm32_fmc2_nfc_ooblayout_ops);
 
 	if (chip->options & NAND_BUSWIDTH_16)
-		stm32_fmc2_set_buswidth_16(fmc2, true);
+		stm32_fmc2_nfc_set_buswidth_16(nfc, true);
 
 	return 0;
 }
 
-static const struct nand_controller_ops stm32_fmc2_nand_controller_ops = {
-	.attach_chip = stm32_fmc2_attach_chip,
-	.exec_op = stm32_fmc2_exec_op,
-	.setup_data_interface = stm32_fmc2_setup_interface,
+static const struct nand_controller_ops stm32_fmc2_nfc_controller_ops = {
+	.attach_chip = stm32_fmc2_nfc_attach_chip,
+	.exec_op = stm32_fmc2_nfc_exec_op,
+	.setup_data_interface = stm32_fmc2_nfc_setup_interface,
 };
 
-static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
-				  struct device_node *dn)
+static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
+				      struct device_node *dn)
 {
-	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	struct stm32_fmc2_nand *nand = &nfc->nand;
 	u32 cs;
 	int ret, i;
 
@@ -1790,29 +1786,29 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 
 	nand->ncs /= sizeof(u32);
 	if (!nand->ncs) {
-		dev_err(fmc2->dev, "invalid reg property size\n");
+		dev_err(nfc->dev, "invalid reg property size\n");
 		return -EINVAL;
 	}
 
 	for (i = 0; i < nand->ncs; i++) {
 		ret = of_property_read_u32_index(dn, "reg", i, &cs);
 		if (ret) {
-			dev_err(fmc2->dev, "could not retrieve reg property: %d\n",
+			dev_err(nfc->dev, "could not retrieve reg property: %d\n",
 				ret);
 			return ret;
 		}
 
 		if (cs > FMC2_MAX_CE) {
-			dev_err(fmc2->dev, "invalid reg value: %d\n", cs);
+			dev_err(nfc->dev, "invalid reg value: %d\n", cs);
 			return -EINVAL;
 		}
 
-		if (fmc2->cs_assigned & BIT(cs)) {
-			dev_err(fmc2->dev, "cs already assigned: %d\n", cs);
+		if (nfc->cs_assigned & BIT(cs)) {
+			dev_err(nfc->dev, "cs already assigned: %d\n", cs);
 			return -EINVAL;
 		}
 
-		fmc2->cs_assigned |= BIT(cs);
+		nfc->cs_assigned |= BIT(cs);
 		nand->cs_used[i] = cs;
 	}
 
@@ -1821,25 +1817,25 @@ static int stm32_fmc2_parse_child(struct stm32_fmc2_nfc *fmc2,
 	return 0;
 }
 
-static int stm32_fmc2_parse_dt(struct stm32_fmc2_nfc *fmc2)
+static int stm32_fmc2_nfc_parse_dt(struct stm32_fmc2_nfc *nfc)
 {
-	struct device_node *dn = fmc2->dev->of_node;
+	struct device_node *dn = nfc->dev->of_node;
 	struct device_node *child;
 	int nchips = of_get_child_count(dn);
 	int ret = 0;
 
 	if (!nchips) {
-		dev_err(fmc2->dev, "NAND chip not defined\n");
+		dev_err(nfc->dev, "NAND chip not defined\n");
 		return -EINVAL;
 	}
 
 	if (nchips > 1) {
-		dev_err(fmc2->dev, "too many NAND chips defined\n");
+		dev_err(nfc->dev, "too many NAND chips defined\n");
 		return -EINVAL;
 	}
 
 	for_each_child_of_node(dn, child) {
-		ret = stm32_fmc2_parse_child(fmc2, child);
+		ret = stm32_fmc2_nfc_parse_child(nfc, child);
 		if (ret < 0) {
 			of_node_put(child);
 			return ret;
@@ -1849,79 +1845,79 @@ static int stm32_fmc2_parse_dt(struct stm32_fmc2_nfc *fmc2)
 	return ret;
 }
 
-static int stm32_fmc2_probe(struct platform_device *pdev)
+static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct reset_control *rstc;
-	struct stm32_fmc2_nfc *fmc2;
+	struct stm32_fmc2_nfc *nfc;
 	struct stm32_fmc2_nand *nand;
 	struct resource *res;
 	struct mtd_info *mtd;
 	struct nand_chip *chip;
 	int chip_cs, mem_region, ret, irq;
 
-	fmc2 = devm_kzalloc(dev, sizeof(*fmc2), GFP_KERNEL);
-	if (!fmc2)
+	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
+	if (!nfc)
 		return -ENOMEM;
 
-	fmc2->dev = dev;
-	nand_controller_init(&fmc2->base);
-	fmc2->base.ops = &stm32_fmc2_nand_controller_ops;
+	nfc->dev = dev;
+	nand_controller_init(&nfc->base);
+	nfc->base.ops = &stm32_fmc2_nfc_controller_ops;
 
-	ret = stm32_fmc2_parse_dt(fmc2);
+	ret = stm32_fmc2_nfc_parse_dt(nfc);
 	if (ret)
 		return ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	fmc2->io_base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(fmc2->io_base))
-		return PTR_ERR(fmc2->io_base);
+	nfc->io_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(nfc->io_base))
+		return PTR_ERR(nfc->io_base);
 
-	fmc2->io_phys_addr = res->start;
+	nfc->io_phys_addr = res->start;
 
 	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
 	     chip_cs++, mem_region += 3) {
-		if (!(fmc2->cs_assigned & BIT(chip_cs)))
+		if (!(nfc->cs_assigned & BIT(chip_cs)))
 			continue;
 
 		res = platform_get_resource(pdev, IORESOURCE_MEM, mem_region);
-		fmc2->data_base[chip_cs] = devm_ioremap_resource(dev, res);
-		if (IS_ERR(fmc2->data_base[chip_cs]))
-			return PTR_ERR(fmc2->data_base[chip_cs]);
+		nfc->data_base[chip_cs] = devm_ioremap_resource(dev, res);
+		if (IS_ERR(nfc->data_base[chip_cs]))
+			return PTR_ERR(nfc->data_base[chip_cs]);
 
-		fmc2->data_phys_addr[chip_cs] = res->start;
+		nfc->data_phys_addr[chip_cs] = res->start;
 
 		res = platform_get_resource(pdev, IORESOURCE_MEM,
 					    mem_region + 1);
-		fmc2->cmd_base[chip_cs] = devm_ioremap_resource(dev, res);
-		if (IS_ERR(fmc2->cmd_base[chip_cs]))
-			return PTR_ERR(fmc2->cmd_base[chip_cs]);
+		nfc->cmd_base[chip_cs] = devm_ioremap_resource(dev, res);
+		if (IS_ERR(nfc->cmd_base[chip_cs]))
+			return PTR_ERR(nfc->cmd_base[chip_cs]);
 
 		res = platform_get_resource(pdev, IORESOURCE_MEM,
 					    mem_region + 2);
-		fmc2->addr_base[chip_cs] = devm_ioremap_resource(dev, res);
-		if (IS_ERR(fmc2->addr_base[chip_cs]))
-			return PTR_ERR(fmc2->addr_base[chip_cs]);
+		nfc->addr_base[chip_cs] = devm_ioremap_resource(dev, res);
+		if (IS_ERR(nfc->addr_base[chip_cs]))
+			return PTR_ERR(nfc->addr_base[chip_cs]);
 	}
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
 		return irq;
 
-	ret = devm_request_irq(dev, irq, stm32_fmc2_irq, 0,
-			       dev_name(dev), fmc2);
+	ret = devm_request_irq(dev, irq, stm32_fmc2_nfc_irq, 0,
+			       dev_name(dev), nfc);
 	if (ret) {
 		dev_err(dev, "failed to request irq\n");
 		return ret;
 	}
 
-	init_completion(&fmc2->complete);
+	init_completion(&nfc->complete);
 
-	fmc2->clk = devm_clk_get(dev, NULL);
-	if (IS_ERR(fmc2->clk))
-		return PTR_ERR(fmc2->clk);
+	nfc->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(nfc->clk))
+		return PTR_ERR(nfc->clk);
 
-	ret = clk_prepare_enable(fmc2->clk);
+	ret = clk_prepare_enable(nfc->clk);
 	if (ret) {
 		dev_err(dev, "can not enable the clock\n");
 		return ret;
@@ -1937,18 +1933,18 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 		reset_control_deassert(rstc);
 	}
 
-	ret = stm32_fmc2_dma_setup(fmc2);
+	ret = stm32_fmc2_nfc_dma_setup(nfc);
 	if (ret)
 		goto err_dma_setup;
 
-	stm32_fmc2_init(fmc2);
+	stm32_fmc2_nfc_init(nfc);
 
-	nand = &fmc2->nand;
+	nand = &nfc->nand;
 	chip = &nand->chip;
 	mtd = nand_to_mtd(chip);
 	mtd->dev.parent = dev;
 
-	chip->controller = &fmc2->base;
+	chip->controller = &nfc->base;
 	chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
 			 NAND_USE_BOUNCE_BUFFER;
 
@@ -1966,7 +1962,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_device_register;
 
-	platform_set_drvdata(pdev, fmc2);
+	platform_set_drvdata(pdev, nfc);
 
 	return 0;
 
@@ -1974,73 +1970,73 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
 	nand_cleanup(chip);
 
 err_dma_setup:
-	if (fmc2->dma_ecc_ch)
-		dma_release_channel(fmc2->dma_ecc_ch);
-	if (fmc2->dma_tx_ch)
-		dma_release_channel(fmc2->dma_tx_ch);
-	if (fmc2->dma_rx_ch)
-		dma_release_channel(fmc2->dma_rx_ch);
+	if (nfc->dma_ecc_ch)
+		dma_release_channel(nfc->dma_ecc_ch);
+	if (nfc->dma_tx_ch)
+		dma_release_channel(nfc->dma_tx_ch);
+	if (nfc->dma_rx_ch)
+		dma_release_channel(nfc->dma_rx_ch);
 
-	sg_free_table(&fmc2->dma_data_sg);
-	sg_free_table(&fmc2->dma_ecc_sg);
+	sg_free_table(&nfc->dma_data_sg);
+	sg_free_table(&nfc->dma_ecc_sg);
 
 err_clk_disable:
-	clk_disable_unprepare(fmc2->clk);
+	clk_disable_unprepare(nfc->clk);
 
 	return ret;
 }
 
-static int stm32_fmc2_remove(struct platform_device *pdev)
+static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
 {
-	struct stm32_fmc2_nfc *fmc2 = platform_get_drvdata(pdev);
-	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	struct stm32_fmc2_nfc *nfc = platform_get_drvdata(pdev);
+	struct stm32_fmc2_nand *nand = &nfc->nand;
 
 	nand_release(&nand->chip);
 
-	if (fmc2->dma_ecc_ch)
-		dma_release_channel(fmc2->dma_ecc_ch);
-	if (fmc2->dma_tx_ch)
-		dma_release_channel(fmc2->dma_tx_ch);
-	if (fmc2->dma_rx_ch)
-		dma_release_channel(fmc2->dma_rx_ch);
+	if (nfc->dma_ecc_ch)
+		dma_release_channel(nfc->dma_ecc_ch);
+	if (nfc->dma_tx_ch)
+		dma_release_channel(nfc->dma_tx_ch);
+	if (nfc->dma_rx_ch)
+		dma_release_channel(nfc->dma_rx_ch);
 
-	sg_free_table(&fmc2->dma_data_sg);
-	sg_free_table(&fmc2->dma_ecc_sg);
+	sg_free_table(&nfc->dma_data_sg);
+	sg_free_table(&nfc->dma_ecc_sg);
 
-	clk_disable_unprepare(fmc2->clk);
+	clk_disable_unprepare(nfc->clk);
 
 	return 0;
 }
 
-static int __maybe_unused stm32_fmc2_suspend(struct device *dev)
+static int __maybe_unused stm32_fmc2_nfc_suspend(struct device *dev)
 {
-	struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev);
+	struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev);
 
-	clk_disable_unprepare(fmc2->clk);
+	clk_disable_unprepare(nfc->clk);
 
 	pinctrl_pm_select_sleep_state(dev);
 
 	return 0;
 }
 
-static int __maybe_unused stm32_fmc2_resume(struct device *dev)
+static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev)
 {
-	struct stm32_fmc2_nfc *fmc2 = dev_get_drvdata(dev);
-	struct stm32_fmc2_nand *nand = &fmc2->nand;
+	struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev);
+	struct stm32_fmc2_nand *nand = &nfc->nand;
 	int chip_cs, ret;
 
 	pinctrl_pm_select_default_state(dev);
 
-	ret = clk_prepare_enable(fmc2->clk);
+	ret = clk_prepare_enable(nfc->clk);
 	if (ret) {
 		dev_err(dev, "can not enable the clock\n");
 		return ret;
 	}
 
-	stm32_fmc2_init(fmc2);
+	stm32_fmc2_nfc_init(nfc);
 
 	for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) {
-		if (!(fmc2->cs_assigned & BIT(chip_cs)))
+		if (!(nfc->cs_assigned & BIT(chip_cs)))
 			continue;
 
 		nand_reset(&nand->chip, chip_cs);
@@ -2049,27 +2045,27 @@ static int __maybe_unused stm32_fmc2_resume(struct device *dev)
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(stm32_fmc2_pm_ops, stm32_fmc2_suspend,
-			 stm32_fmc2_resume);
+static SIMPLE_DEV_PM_OPS(stm32_fmc2_nfc_pm_ops, stm32_fmc2_nfc_suspend,
+			 stm32_fmc2_nfc_resume);
 
-static const struct of_device_id stm32_fmc2_match[] = {
+static const struct of_device_id stm32_fmc2_nfc_match[] = {
 	{.compatible = "st,stm32mp15-fmc2"},
 	{}
 };
-MODULE_DEVICE_TABLE(of, stm32_fmc2_match);
+MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match);
 
-static struct platform_driver stm32_fmc2_driver = {
-	.probe	= stm32_fmc2_probe,
-	.remove	= stm32_fmc2_remove,
+static struct platform_driver stm32_fmc2_nfc_driver = {
+	.probe	= stm32_fmc2_nfc_probe,
+	.remove	= stm32_fmc2_nfc_remove,
 	.driver	= {
-		.name = "stm32_fmc2_nand",
-		.of_match_table = stm32_fmc2_match,
-		.pm = &stm32_fmc2_pm_ops,
+		.name = "stm32_fmc2_nfc",
+		.of_match_table = stm32_fmc2_nfc_match,
+		.pm = &stm32_fmc2_nfc_pm_ops,
 	},
 };
-module_platform_driver(stm32_fmc2_driver);
+module_platform_driver(stm32_fmc2_nfc_driver);
 
-MODULE_ALIAS("platform:stm32_fmc2_nand");
+MODULE_ALIAS("platform:stm32_fmc2_nfc");
 MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
-MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nand driver");
+MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nfc driver");
 MODULE_LICENSE("GPL v2");
-- 
1.9.1


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

* [PATCH v2 08/12] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (6 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 07/12] mtd: rawnand: stm32_fmc2: cleanup Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-16 19:45   ` Boris Brezillon
  2020-04-15 15:57 ` [PATCH v2 09/12] mtd: rawnand: stm32_fmc2: move all registers Christophe Kerello
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 177 ++++++++++++++++-----------------
 1 file changed, 85 insertions(+), 92 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 9ce405d..e0a7c08 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -4,6 +4,7 @@
  * Author: Christophe Kerello <christophe.kerello@st.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
@@ -84,20 +85,16 @@
 /* Register: FMC2_PCR */
 #define FMC2_PCR_PWAITEN		BIT(1)
 #define FMC2_PCR_PBKEN			BIT(2)
-#define FMC2_PCR_PWID_MASK		GENMASK(5, 4)
-#define FMC2_PCR_PWID(x)		(((x) & 0x3) << 4)
+#define FMC2_PCR_PWID			GENMASK(5, 4)
 #define FMC2_PCR_PWID_BUSWIDTH_8	0
 #define FMC2_PCR_PWID_BUSWIDTH_16	1
 #define FMC2_PCR_ECCEN			BIT(6)
 #define FMC2_PCR_ECCALG			BIT(8)
-#define FMC2_PCR_TCLR_MASK		GENMASK(12, 9)
-#define FMC2_PCR_TCLR(x)		(((x) & 0xf) << 9)
+#define FMC2_PCR_TCLR			GENMASK(12, 9)
 #define FMC2_PCR_TCLR_DEFAULT		0xf
-#define FMC2_PCR_TAR_MASK		GENMASK(16, 13)
-#define FMC2_PCR_TAR(x)			(((x) & 0xf) << 13)
+#define FMC2_PCR_TAR			GENMASK(16, 13)
 #define FMC2_PCR_TAR_DEFAULT		0xf
-#define FMC2_PCR_ECCSS_MASK		GENMASK(19, 17)
-#define FMC2_PCR_ECCSS(x)		(((x) & 0x7) << 17)
+#define FMC2_PCR_ECCSS			GENMASK(19, 17)
 #define FMC2_PCR_ECCSS_512		1
 #define FMC2_PCR_ECCSS_2048		3
 #define FMC2_PCR_BCHECC			BIT(24)
@@ -107,17 +104,17 @@
 #define FMC2_SR_NWRF			BIT(6)
 
 /* Register: FMC2_PMEM */
-#define FMC2_PMEM_MEMSET(x)		(((x) & 0xff) << 0)
-#define FMC2_PMEM_MEMWAIT(x)		(((x) & 0xff) << 8)
-#define FMC2_PMEM_MEMHOLD(x)		(((x) & 0xff) << 16)
-#define FMC2_PMEM_MEMHIZ(x)		(((x) & 0xff) << 24)
+#define FMC2_PMEM_MEMSET		GENMASK(7, 0)
+#define FMC2_PMEM_MEMWAIT		GENMASK(15, 8)
+#define FMC2_PMEM_MEMHOLD		GENMASK(23, 16)
+#define FMC2_PMEM_MEMHIZ		GENMASK(31, 24)
 #define FMC2_PMEM_DEFAULT		0x0a0a0a0a
 
 /* Register: FMC2_PATT */
-#define FMC2_PATT_ATTSET(x)		(((x) & 0xff) << 0)
-#define FMC2_PATT_ATTWAIT(x)		(((x) & 0xff) << 8)
-#define FMC2_PATT_ATTHOLD(x)		(((x) & 0xff) << 16)
-#define FMC2_PATT_ATTHIZ(x)		(((x) & 0xff) << 24)
+#define FMC2_PATT_ATTSET		GENMASK(7, 0)
+#define FMC2_PATT_ATTWAIT		GENMASK(15, 8)
+#define FMC2_PATT_ATTHOLD		GENMASK(23, 16)
+#define FMC2_PATT_ATTHIZ		GENMASK(31, 24)
 #define FMC2_PATT_DEFAULT		0x0a0a0a0a
 
 /* Register: FMC2_ISR */
@@ -132,9 +129,9 @@
 /* Register: FMC2_CSQCFGR1 */
 #define FMC2_CSQCFGR1_CMD2EN		BIT(1)
 #define FMC2_CSQCFGR1_DMADEN		BIT(2)
-#define FMC2_CSQCFGR1_ACYNBR(x)		(((x) & 0x7) << 4)
-#define FMC2_CSQCFGR1_CMD1(x)		(((x) & 0xff) << 8)
-#define FMC2_CSQCFGR1_CMD2(x)		(((x) & 0xff) << 16)
+#define FMC2_CSQCFGR1_ACYNBR		GENMASK(6, 4)
+#define FMC2_CSQCFGR1_CMD1		GENMASK(15, 8)
+#define FMC2_CSQCFGR1_CMD2		GENMASK(23, 16)
 #define FMC2_CSQCFGR1_CMD1T		BIT(24)
 #define FMC2_CSQCFGR1_CMD2T		BIT(25)
 
@@ -142,13 +139,13 @@
 #define FMC2_CSQCFGR2_SQSDTEN		BIT(0)
 #define FMC2_CSQCFGR2_RCMD2EN		BIT(1)
 #define FMC2_CSQCFGR2_DMASEN		BIT(2)
-#define FMC2_CSQCFGR2_RCMD1(x)		(((x) & 0xff) << 8)
-#define FMC2_CSQCFGR2_RCMD2(x)		(((x) & 0xff) << 16)
+#define FMC2_CSQCFGR2_RCMD1		GENMASK(15, 8)
+#define FMC2_CSQCFGR2_RCMD2		GENMASK(23, 16)
 #define FMC2_CSQCFGR2_RCMD1T		BIT(24)
 #define FMC2_CSQCFGR2_RCMD2T		BIT(25)
 
 /* Register: FMC2_CSQCFGR3 */
-#define FMC2_CSQCFGR3_SNBR(x)		(((x) & 0x1f) << 8)
+#define FMC2_CSQCFGR3_SNBR		GENMASK(13, 8)
 #define FMC2_CSQCFGR3_AC1T		BIT(16)
 #define FMC2_CSQCFGR3_AC2T		BIT(17)
 #define FMC2_CSQCFGR3_AC3T		BIT(18)
@@ -159,15 +156,15 @@
 #define FMC2_CSQCFGR3_RAC2T		BIT(23)
 
 /* Register: FMC2_CSQCAR1 */
-#define FMC2_CSQCAR1_ADDC1(x)		(((x) & 0xff) << 0)
-#define FMC2_CSQCAR1_ADDC2(x)		(((x) & 0xff) << 8)
-#define FMC2_CSQCAR1_ADDC3(x)		(((x) & 0xff) << 16)
-#define FMC2_CSQCAR1_ADDC4(x)		(((x) & 0xff) << 24)
+#define FMC2_CSQCAR1_ADDC1		GENMASK(7, 0)
+#define FMC2_CSQCAR1_ADDC2		GENMASK(15, 8)
+#define FMC2_CSQCAR1_ADDC3		GENMASK(23, 16)
+#define FMC2_CSQCAR1_ADDC4		GENMASK(31, 24)
 
 /* Register: FMC2_CSQCAR2 */
-#define FMC2_CSQCAR2_ADDC5(x)		(((x) & 0xff) << 0)
-#define FMC2_CSQCAR2_NANDCEN(x)		(((x) & 0x3) << 10)
-#define FMC2_CSQCAR2_SAO(x)		(((x) & 0xffff) << 16)
+#define FMC2_CSQCAR2_ADDC5		GENMASK(7, 0)
+#define FMC2_CSQCAR2_NANDCEN		GENMASK(11, 10)
+#define FMC2_CSQCAR2_SAO		GENMASK(31, 16)
 
 /* Register: FMC2_CSQIER */
 #define FMC2_CSQIER_TCIE		BIT(0)
@@ -188,28 +185,23 @@
 /* Register: FMC2_BCHDSR0 */
 #define FMC2_BCHDSR0_DUE		BIT(0)
 #define FMC2_BCHDSR0_DEF		BIT(1)
-#define FMC2_BCHDSR0_DEN_MASK		GENMASK(7, 4)
-#define FMC2_BCHDSR0_DEN_SHIFT		4
+#define FMC2_BCHDSR0_DEN		GENMASK(7, 4)
 
 /* Register: FMC2_BCHDSR1 */
-#define FMC2_BCHDSR1_EBP1_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR1_EBP2_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR1_EBP2_SHIFT		16
+#define FMC2_BCHDSR1_EBP1		GENMASK(12, 0)
+#define FMC2_BCHDSR1_EBP2		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR2 */
-#define FMC2_BCHDSR2_EBP3_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR2_EBP4_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR2_EBP4_SHIFT		16
+#define FMC2_BCHDSR2_EBP3		GENMASK(12, 0)
+#define FMC2_BCHDSR2_EBP4		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR3 */
-#define FMC2_BCHDSR3_EBP5_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR3_EBP6_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR3_EBP6_SHIFT		16
+#define FMC2_BCHDSR3_EBP5		GENMASK(12, 0)
+#define FMC2_BCHDSR3_EBP6		GENMASK(28, 16)
 
 /* Register: FMC2_BCHDSR4 */
-#define FMC2_BCHDSR4_EBP7_MASK		GENMASK(12, 0)
-#define FMC2_BCHDSR4_EBP8_MASK		GENMASK(28, 16)
-#define FMC2_BCHDSR4_EBP8_SHIFT		16
+#define FMC2_BCHDSR4_EBP7		GENMASK(12, 0)
+#define FMC2_BCHDSR4_EBP8		GENMASK(28, 16)
 
 enum stm32_fmc2_ecc {
 	FMC2_ECC_HAM = 1,
@@ -289,22 +281,22 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
-	pcr &= ~FMC2_PCR_TCLR_MASK;
-	pcr |= FMC2_PCR_TCLR(timings->tclr);
-	pcr &= ~FMC2_PCR_TAR_MASK;
-	pcr |= FMC2_PCR_TAR(timings->tar);
+	pcr &= ~FMC2_PCR_TCLR;
+	pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
+	pcr &= ~FMC2_PCR_TAR;
+	pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
 
 	/* Set tset/twait/thold/thiz timings in common bank */
-	pmem = FMC2_PMEM_MEMSET(timings->tset_mem);
-	pmem |= FMC2_PMEM_MEMWAIT(timings->twait);
-	pmem |= FMC2_PMEM_MEMHOLD(timings->thold_mem);
-	pmem |= FMC2_PMEM_MEMHIZ(timings->thiz);
+	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
+	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
 
 	/* Set tset/twait/thold/thiz timings in attribut bank */
-	patt = FMC2_PATT_ATTSET(timings->tset_att);
-	patt |= FMC2_PATT_ATTWAIT(timings->twait);
-	patt |= FMC2_PATT_ATTHOLD(timings->thold_att);
-	patt |= FMC2_PATT_ATTHIZ(timings->thiz);
+	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
+	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
+	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
+	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
 
 	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
 	writel_relaxed(pmem, nfc->io_base + FMC2_PMEM);
@@ -327,13 +319,13 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 	}
 
 	/* Set buswidth */
-	pcr &= ~FMC2_PCR_PWID_MASK;
+	pcr &= ~FMC2_PCR_PWID;
 	if (chip->options & NAND_BUSWIDTH_16)
-		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
 
 	/* Set ECC sector size */
-	pcr &= ~FMC2_PCR_ECCSS_MASK;
-	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512);
+	pcr &= ~FMC2_PCR_ECCSS;
+	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
 
 	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
 }
@@ -403,9 +395,9 @@ static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc, bool set)
 {
 	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
 
-	pcr &= ~FMC2_PCR_PWID_MASK;
+	pcr &= ~FMC2_PCR_PWID;
 	if (set)
-		pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_BUSWIDTH_16);
+		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
 	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
 }
 
@@ -659,16 +651,16 @@ static int stm32_fmc2_nfc_bch_decode(int eccsize, u8 *dat, u32 *ecc_sta)
 	if (unlikely(bchdsr0 & FMC2_BCHDSR0_DUE))
 		return -EBADMSG;
 
-	pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK;
-	pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT;
-	pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK;
-	pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT;
-	pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK;
-	pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT;
-	pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK;
-	pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT;
+	pos[0] = FIELD_GET(FMC2_BCHDSR1_EBP1, bchdsr1);
+	pos[1] = FIELD_GET(FMC2_BCHDSR1_EBP2, bchdsr1);
+	pos[2] = FIELD_GET(FMC2_BCHDSR2_EBP3, bchdsr2);
+	pos[3] = FIELD_GET(FMC2_BCHDSR2_EBP4, bchdsr2);
+	pos[4] = FIELD_GET(FMC2_BCHDSR3_EBP5, bchdsr3);
+	pos[5] = FIELD_GET(FMC2_BCHDSR3_EBP6, bchdsr3);
+	pos[6] = FIELD_GET(FMC2_BCHDSR4_EBP7, bchdsr4);
+	pos[7] = FIELD_GET(FMC2_BCHDSR4_EBP8, bchdsr4);
 
-	den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT;
+	den = FIELD_GET(FMC2_BCHDSR0_DEN, bchdsr0);
 	for (i = 0; i < den; i++) {
 		if (pos[i] < eccsize * 8) {
 			change_bit(pos[i], (unsigned long *)dat);
@@ -790,11 +782,11 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 */
 	csqcfgr1 = FMC2_CSQCFGR1_DMADEN | FMC2_CSQCFGR1_CMD1T;
 	if (write_data)
-		csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_SEQIN);
+		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_CMD1, NAND_CMD_SEQIN);
 	else
-		csqcfgr1 |= FMC2_CSQCFGR1_CMD1(NAND_CMD_READ0) |
+		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_CMD1, NAND_CMD_READ0) |
 			    FMC2_CSQCFGR1_CMD2EN |
-			    FMC2_CSQCFGR1_CMD2(NAND_CMD_READSTART) |
+			    FIELD_PREP(FMC2_CSQCFGR1_CMD2, NAND_CMD_READSTART) |
 			    FMC2_CSQCFGR1_CMD2T;
 
 	/*
@@ -804,11 +796,12 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 * - Set timings
 	 */
 	if (write_data)
-		csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDIN);
+		csqcfgr2 = FIELD_PREP(FMC2_CSQCFGR2_RCMD1, NAND_CMD_RNDIN);
 	else
-		csqcfgr2 = FMC2_CSQCFGR2_RCMD1(NAND_CMD_RNDOUT) |
+		csqcfgr2 = FIELD_PREP(FMC2_CSQCFGR2_RCMD1, NAND_CMD_RNDOUT) |
 			   FMC2_CSQCFGR2_RCMD2EN |
-			   FMC2_CSQCFGR2_RCMD2(NAND_CMD_RNDOUTSTART) |
+			   FIELD_PREP(FMC2_CSQCFGR2_RCMD2,
+				      NAND_CMD_RNDOUTSTART) |
 			   FMC2_CSQCFGR2_RCMD1T |
 			   FMC2_CSQCFGR2_RCMD2T;
 	if (!raw) {
@@ -820,7 +813,7 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 * - Set the number of sectors to be written
 	 * - Set timings
 	 */
-	csqcfgr3 = FMC2_CSQCFGR3_SNBR(chip->ecc.steps - 1);
+	csqcfgr3 = FIELD_PREP(FMC2_CSQCFGR3_SNBR, chip->ecc.steps - 1);
 	if (write_data) {
 		csqcfgr3 |= FMC2_CSQCFGR3_RAC2T;
 		if (chip->options & NAND_ROW_ADDR_3)
@@ -834,8 +827,8 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 * Byte 1 and byte 2 => column, we start at 0x0
 	 * Byte 3 and byte 4 => page
 	 */
-	csqar1 = FMC2_CSQCAR1_ADDC3(page);
-	csqar1 |= FMC2_CSQCAR1_ADDC4(page >> 8);
+	csqar1 = FIELD_PREP(FMC2_CSQCAR1_ADDC3, page);
+	csqar1 |= FIELD_PREP(FMC2_CSQCAR1_ADDC4, page >> 8);
 
 	/*
 	 * - Set chip enable number
@@ -843,16 +836,16 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 * - Calculate the number of address cycles to be issued
 	 * - Set byte 5 of address cycle if needed
 	 */
-	csqar2 = FMC2_CSQCAR2_NANDCEN(nfc->cs_sel);
+	csqar2 = FIELD_PREP(FMC2_CSQCAR2_NANDCEN, nfc->cs_sel);
 	if (chip->options & NAND_BUSWIDTH_16)
-		csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset >> 1);
+		csqar2 |= FIELD_PREP(FMC2_CSQCAR2_SAO, ecc_offset >> 1);
 	else
-		csqar2 |= FMC2_CSQCAR2_SAO(ecc_offset);
+		csqar2 |= FIELD_PREP(FMC2_CSQCAR2_SAO, ecc_offset);
 	if (chip->options & NAND_ROW_ADDR_3) {
-		csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(5);
-		csqar2 |= FMC2_CSQCAR2_ADDC5(page >> 16);
+		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 5);
+		csqar2 |= FIELD_PREP(FMC2_CSQCAR2_ADDC5, page >> 16);
 	} else {
-		csqcfgr1 |= FMC2_CSQCFGR1_ACYNBR(4);
+		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 4);
 	}
 
 	writel_relaxed(csqcfgr1, nfc->io_base + FMC2_CSQCFGR1);
@@ -1393,7 +1386,7 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr |= FMC2_PCR_PBKEN;
 
 	/* Set buswidth to 8 bits mode for identification */
-	pcr &= ~FMC2_PCR_PWID_MASK;
+	pcr &= ~FMC2_PCR_PWID;
 
 	/* ECC logic is disabled */
 	pcr &= ~FMC2_PCR_ECCEN;
@@ -1404,14 +1397,14 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr &= ~FMC2_PCR_WEN;
 
 	/* Set default ECC sector size */
-	pcr &= ~FMC2_PCR_ECCSS_MASK;
-	pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048);
+	pcr &= ~FMC2_PCR_ECCSS;
+	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_2048);
 
 	/* Set default tclr/tar timings */
-	pcr &= ~FMC2_PCR_TCLR_MASK;
-	pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT);
-	pcr &= ~FMC2_PCR_TAR_MASK;
-	pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT);
+	pcr &= ~FMC2_PCR_TCLR;
+	pcr |= FIELD_PREP(FMC2_PCR_TCLR, FMC2_PCR_TCLR_DEFAULT);
+	pcr &= ~FMC2_PCR_TAR;
+	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
 
 	/* Enable FMC2 controller */
 	bcr1 |= FMC2_BCR1_FMC2EN;
-- 
1.9.1


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

* [PATCH v2 09/12] mtd: rawnand: stm32_fmc2: move all registers
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (7 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 08/12] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-15 15:57 ` [PATCH v2 10/12] mtd: rawnand: stm32_fmc2: use regmap APIs Christophe Kerello
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch moves all constants/structures based on regmap used
to stm32-fmc2.h

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 154 +--------------------------------
 1 file changed, 1 insertion(+), 153 deletions(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index e0a7c08..9f12a59 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -4,13 +4,12 @@
  * Author: Christophe Kerello <christophe.kerello@st.com>
  */
 
-#include <linux/bitfield.h>
-#include <linux/clk.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/iopoll.h>
+#include <linux/mfd/stm32-fmc2.h>
 #include <linux/module.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/pinctrl/consumer.h>
@@ -47,162 +46,11 @@
 #define FMC2_PCR_TIMING_MASK		0xf
 #define FMC2_PMEM_PATT_TIMING_MASK	0xff
 
-/* FMC2 Controller Registers */
-#define FMC2_BCR1			0x0
-#define FMC2_PCR			0x80
-#define FMC2_SR				0x84
-#define FMC2_PMEM			0x88
-#define FMC2_PATT			0x8c
-#define FMC2_HECCR			0x94
-#define FMC2_ISR			0x184
-#define FMC2_ICR			0x188
-#define FMC2_CSQCR			0x200
-#define FMC2_CSQCFGR1			0x204
-#define FMC2_CSQCFGR2			0x208
-#define FMC2_CSQCFGR3			0x20c
-#define FMC2_CSQAR1			0x210
-#define FMC2_CSQAR2			0x214
-#define FMC2_CSQIER			0x220
-#define FMC2_CSQISR			0x224
-#define FMC2_CSQICR			0x228
-#define FMC2_CSQEMSR			0x230
-#define FMC2_BCHIER			0x250
-#define FMC2_BCHISR			0x254
-#define FMC2_BCHICR			0x258
-#define FMC2_BCHPBR1			0x260
-#define FMC2_BCHPBR2			0x264
-#define FMC2_BCHPBR3			0x268
-#define FMC2_BCHPBR4			0x26c
-#define FMC2_BCHDSR0			0x27c
-#define FMC2_BCHDSR1			0x280
-#define FMC2_BCHDSR2			0x284
-#define FMC2_BCHDSR3			0x288
-#define FMC2_BCHDSR4			0x28c
-
-/* Register: FMC2_BCR1 */
-#define FMC2_BCR1_FMC2EN		BIT(31)
-
-/* Register: FMC2_PCR */
-#define FMC2_PCR_PWAITEN		BIT(1)
-#define FMC2_PCR_PBKEN			BIT(2)
-#define FMC2_PCR_PWID			GENMASK(5, 4)
-#define FMC2_PCR_PWID_BUSWIDTH_8	0
-#define FMC2_PCR_PWID_BUSWIDTH_16	1
-#define FMC2_PCR_ECCEN			BIT(6)
-#define FMC2_PCR_ECCALG			BIT(8)
-#define FMC2_PCR_TCLR			GENMASK(12, 9)
 #define FMC2_PCR_TCLR_DEFAULT		0xf
-#define FMC2_PCR_TAR			GENMASK(16, 13)
 #define FMC2_PCR_TAR_DEFAULT		0xf
-#define FMC2_PCR_ECCSS			GENMASK(19, 17)
-#define FMC2_PCR_ECCSS_512		1
-#define FMC2_PCR_ECCSS_2048		3
-#define FMC2_PCR_BCHECC			BIT(24)
-#define FMC2_PCR_WEN			BIT(25)
-
-/* Register: FMC2_SR */
-#define FMC2_SR_NWRF			BIT(6)
-
-/* Register: FMC2_PMEM */
-#define FMC2_PMEM_MEMSET		GENMASK(7, 0)
-#define FMC2_PMEM_MEMWAIT		GENMASK(15, 8)
-#define FMC2_PMEM_MEMHOLD		GENMASK(23, 16)
-#define FMC2_PMEM_MEMHIZ		GENMASK(31, 24)
 #define FMC2_PMEM_DEFAULT		0x0a0a0a0a
-
-/* Register: FMC2_PATT */
-#define FMC2_PATT_ATTSET		GENMASK(7, 0)
-#define FMC2_PATT_ATTWAIT		GENMASK(15, 8)
-#define FMC2_PATT_ATTHOLD		GENMASK(23, 16)
-#define FMC2_PATT_ATTHIZ		GENMASK(31, 24)
 #define FMC2_PATT_DEFAULT		0x0a0a0a0a
 
-/* Register: FMC2_ISR */
-#define FMC2_ISR_IHLF			BIT(1)
-
-/* Register: FMC2_ICR */
-#define FMC2_ICR_CIHLF			BIT(1)
-
-/* Register: FMC2_CSQCR */
-#define FMC2_CSQCR_CSQSTART		BIT(0)
-
-/* Register: FMC2_CSQCFGR1 */
-#define FMC2_CSQCFGR1_CMD2EN		BIT(1)
-#define FMC2_CSQCFGR1_DMADEN		BIT(2)
-#define FMC2_CSQCFGR1_ACYNBR		GENMASK(6, 4)
-#define FMC2_CSQCFGR1_CMD1		GENMASK(15, 8)
-#define FMC2_CSQCFGR1_CMD2		GENMASK(23, 16)
-#define FMC2_CSQCFGR1_CMD1T		BIT(24)
-#define FMC2_CSQCFGR1_CMD2T		BIT(25)
-
-/* Register: FMC2_CSQCFGR2 */
-#define FMC2_CSQCFGR2_SQSDTEN		BIT(0)
-#define FMC2_CSQCFGR2_RCMD2EN		BIT(1)
-#define FMC2_CSQCFGR2_DMASEN		BIT(2)
-#define FMC2_CSQCFGR2_RCMD1		GENMASK(15, 8)
-#define FMC2_CSQCFGR2_RCMD2		GENMASK(23, 16)
-#define FMC2_CSQCFGR2_RCMD1T		BIT(24)
-#define FMC2_CSQCFGR2_RCMD2T		BIT(25)
-
-/* Register: FMC2_CSQCFGR3 */
-#define FMC2_CSQCFGR3_SNBR		GENMASK(13, 8)
-#define FMC2_CSQCFGR3_AC1T		BIT(16)
-#define FMC2_CSQCFGR3_AC2T		BIT(17)
-#define FMC2_CSQCFGR3_AC3T		BIT(18)
-#define FMC2_CSQCFGR3_AC4T		BIT(19)
-#define FMC2_CSQCFGR3_AC5T		BIT(20)
-#define FMC2_CSQCFGR3_SDT		BIT(21)
-#define FMC2_CSQCFGR3_RAC1T		BIT(22)
-#define FMC2_CSQCFGR3_RAC2T		BIT(23)
-
-/* Register: FMC2_CSQCAR1 */
-#define FMC2_CSQCAR1_ADDC1		GENMASK(7, 0)
-#define FMC2_CSQCAR1_ADDC2		GENMASK(15, 8)
-#define FMC2_CSQCAR1_ADDC3		GENMASK(23, 16)
-#define FMC2_CSQCAR1_ADDC4		GENMASK(31, 24)
-
-/* Register: FMC2_CSQCAR2 */
-#define FMC2_CSQCAR2_ADDC5		GENMASK(7, 0)
-#define FMC2_CSQCAR2_NANDCEN		GENMASK(11, 10)
-#define FMC2_CSQCAR2_SAO		GENMASK(31, 16)
-
-/* Register: FMC2_CSQIER */
-#define FMC2_CSQIER_TCIE		BIT(0)
-
-/* Register: FMC2_CSQICR */
-#define FMC2_CSQICR_CLEAR_IRQ		GENMASK(4, 0)
-
-/* Register: FMC2_CSQEMSR */
-#define FMC2_CSQEMSR_SEM		GENMASK(15, 0)
-
-/* Register: FMC2_BCHIER */
-#define FMC2_BCHIER_DERIE		BIT(1)
-#define FMC2_BCHIER_EPBRIE		BIT(4)
-
-/* Register: FMC2_BCHICR */
-#define FMC2_BCHICR_CLEAR_IRQ		GENMASK(4, 0)
-
-/* Register: FMC2_BCHDSR0 */
-#define FMC2_BCHDSR0_DUE		BIT(0)
-#define FMC2_BCHDSR0_DEF		BIT(1)
-#define FMC2_BCHDSR0_DEN		GENMASK(7, 4)
-
-/* Register: FMC2_BCHDSR1 */
-#define FMC2_BCHDSR1_EBP1		GENMASK(12, 0)
-#define FMC2_BCHDSR1_EBP2		GENMASK(28, 16)
-
-/* Register: FMC2_BCHDSR2 */
-#define FMC2_BCHDSR2_EBP3		GENMASK(12, 0)
-#define FMC2_BCHDSR2_EBP4		GENMASK(28, 16)
-
-/* Register: FMC2_BCHDSR3 */
-#define FMC2_BCHDSR3_EBP5		GENMASK(12, 0)
-#define FMC2_BCHDSR3_EBP6		GENMASK(28, 16)
-
-/* Register: FMC2_BCHDSR4 */
-#define FMC2_BCHDSR4_EBP7		GENMASK(12, 0)
-#define FMC2_BCHDSR4_EBP8		GENMASK(28, 16)
-
 enum stm32_fmc2_ecc {
 	FMC2_ECC_HAM = 1,
 	FMC2_ECC_BCH4 = 4,
-- 
1.9.1


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

* [PATCH v2 10/12] mtd: rawnand: stm32_fmc2: use regmap APIs
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (8 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 09/12] mtd: rawnand: stm32_fmc2: move all registers Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-27 18:52   ` Miquel Raynal
  2020-04-15 15:57 ` [PATCH v2 11/12] mtd: rawnand: stm32_fmc2: use stm32_fmc2 structure in nfc controller Christophe Kerello
  2020-04-15 15:57 ` [PATCH v2 12/12] mtd: rawnand: stm32_fmc2: add new MP1 compatible string Christophe Kerello
  11 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch uses regmap APIs to access all FMC2 registers.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
Changes in v2:
 - use of regmap_bulk_write/regmap_bulk_read APIs

 drivers/mtd/nand/raw/Kconfig           |   2 +
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 267 +++++++++++++++------------------
 2 files changed, 126 insertions(+), 143 deletions(-)

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index a80a46b..12b715a 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -419,6 +419,8 @@ config MTD_NAND_TEGRA
 config MTD_NAND_STM32_FMC2
 	tristate "Support for NAND controller on STM32MP SoCs"
 	depends on MACH_STM32MP157 || COMPILE_TEST
+	select REGMAP
+	select REGMAP_MMIO
 	help
 	  Enables support for NAND Flash chips on SoCs containing the FMC2
 	  NAND controller. This controller is found on STM32MP SoCs.
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 9f12a59..a3c2a11 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -51,6 +51,16 @@
 #define FMC2_PMEM_DEFAULT		0x0a0a0a0a
 #define FMC2_PATT_DEFAULT		0x0a0a0a0a
 
+/* Regmap registers configuration */
+#define FMC2_MAX_REGISTER		0x3fc
+
+static const struct regmap_config stm32_fmc2_regmap_cfg = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = sizeof(u32),
+	.max_register = FMC2_MAX_REGISTER,
+};
+
 enum stm32_fmc2_ecc {
 	FMC2_ECC_HAM = 1,
 	FMC2_ECC_BCH4 = 4,
@@ -90,7 +100,7 @@ struct stm32_fmc2_nfc {
 	struct nand_controller base;
 	struct stm32_fmc2_nand nand;
 	struct device *dev;
-	void __iomem *io_base;
+	struct regmap *regmap;
 	void __iomem *data_base[FMC2_MAX_CE];
 	void __iomem *cmd_base[FMC2_MAX_CE];
 	void __iomem *addr_base[FMC2_MAX_CE];
@@ -125,40 +135,37 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *timings = &nand->timings;
-	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
-	pcr &= ~FMC2_PCR_TCLR;
-	pcr |= FIELD_PREP(FMC2_PCR_TCLR, timings->tclr);
-	pcr &= ~FMC2_PCR_TAR;
-	pcr |= FIELD_PREP(FMC2_PCR_TAR, timings->tar);
+	regmap_update_bits(nfc->regmap, FMC2_PCR,
+			   FMC2_PCR_TCLR | FMC2_PCR_TAR,
+			   FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
+			   FIELD_PREP(FMC2_PCR_TAR, timings->tar));
 
 	/* Set tset/twait/thold/thiz timings in common bank */
 	pmem = FIELD_PREP(FMC2_PMEM_MEMSET, timings->tset_mem);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
+	regmap_write(nfc->regmap, FMC2_PMEM, pmem);
 
 	/* Set tset/twait/thold/thiz timings in attribut bank */
 	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
 	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
 	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
 	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
-
-	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
-	writel_relaxed(pmem, nfc->io_base + FMC2_PMEM);
-	writel_relaxed(patt, nfc->io_base + FMC2_PATT);
+	regmap_write(nfc->regmap, FMC2_PATT, patt);
 }
 
 static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
-	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
+	u32 pcr = 0, pcr_mask;
 
 	/* Configure ECC algorithm (default configuration is Hamming) */
-	pcr &= ~FMC2_PCR_ECCALG;
-	pcr &= ~FMC2_PCR_BCHECC;
+	pcr_mask = FMC2_PCR_ECCALG;
+	pcr_mask |= FMC2_PCR_BCHECC;
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		pcr |= FMC2_PCR_ECCALG;
 		pcr |= FMC2_PCR_BCHECC;
@@ -167,15 +174,15 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 	}
 
 	/* Set buswidth */
-	pcr &= ~FMC2_PCR_PWID;
+	pcr_mask |= FMC2_PCR_PWID;
 	if (chip->options & NAND_BUSWIDTH_16)
 		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
 
 	/* Set ECC sector size */
-	pcr &= ~FMC2_PCR_ECCSS;
+	pcr_mask |= FMC2_PCR_ECCSS;
 	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
 
-	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
+	regmap_update_bits(nfc->regmap, FMC2_PCR, pcr_mask, pcr);
 }
 
 static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
@@ -241,81 +248,63 @@ static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
 
 static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc, bool set)
 {
-	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
+	u32 pcr;
 
-	pcr &= ~FMC2_PCR_PWID;
-	if (set)
-		pcr |= FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16);
-	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
+	pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
+		    FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
+
+	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_PWID, pcr);
 }
 
 static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
 {
-	u32 pcr = readl(nfc->io_base + FMC2_PCR);
-
-	pcr &= ~FMC2_PCR_ECCEN;
-	if (enable)
-		pcr |= FMC2_PCR_ECCEN;
-	writel(pcr, nfc->io_base + FMC2_PCR);
+	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_ECCEN,
+			   enable ? FMC2_PCR_ECCEN : 0);
 }
 
-static inline void stm32_fmc2_nfc_enable_seq_irq(struct stm32_fmc2_nfc *nfc)
+static void stm32_fmc2_nfc_enable_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	u32 csqier = readl_relaxed(nfc->io_base + FMC2_CSQIER);
-
-	csqier |= FMC2_CSQIER_TCIE;
-
 	nfc->irq_state = FMC2_IRQ_SEQ;
 
-	writel_relaxed(csqier, nfc->io_base + FMC2_CSQIER);
+	regmap_update_bits(nfc->regmap, FMC2_CSQIER,
+			   FMC2_CSQIER_TCIE, FMC2_CSQIER_TCIE);
 }
 
-static inline void stm32_fmc2_nfc_disable_seq_irq(struct stm32_fmc2_nfc *nfc)
+static void stm32_fmc2_nfc_disable_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	u32 csqier = readl_relaxed(nfc->io_base + FMC2_CSQIER);
-
-	csqier &= ~FMC2_CSQIER_TCIE;
-
-	writel_relaxed(csqier, nfc->io_base + FMC2_CSQIER);
+	regmap_update_bits(nfc->regmap, FMC2_CSQIER, FMC2_CSQIER_TCIE, 0);
 
 	nfc->irq_state = FMC2_IRQ_UNKNOWN;
 }
 
-static inline void stm32_fmc2_nfc_clear_seq_irq(struct stm32_fmc2_nfc *nfc)
+static void stm32_fmc2_nfc_clear_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	writel_relaxed(FMC2_CSQICR_CLEAR_IRQ, nfc->io_base + FMC2_CSQICR);
+	regmap_write(nfc->regmap, FMC2_CSQICR, FMC2_CSQICR_CLEAR_IRQ);
 }
 
-static inline void stm32_fmc2_nfc_enable_bch_irq(struct stm32_fmc2_nfc *nfc,
-						 int mode)
+static void stm32_fmc2_nfc_enable_bch_irq(struct stm32_fmc2_nfc *nfc, int mode)
 {
-	u32 bchier = readl_relaxed(nfc->io_base + FMC2_BCHIER);
+	nfc->irq_state = FMC2_IRQ_BCH;
 
 	if (mode == NAND_ECC_WRITE)
-		bchier |= FMC2_BCHIER_EPBRIE;
+		regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+				   FMC2_BCHIER_EPBRIE, FMC2_BCHIER_EPBRIE);
 	else
-		bchier |= FMC2_BCHIER_DERIE;
-
-	nfc->irq_state = FMC2_IRQ_BCH;
-
-	writel_relaxed(bchier, nfc->io_base + FMC2_BCHIER);
+		regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+				   FMC2_BCHIER_DERIE, FMC2_BCHIER_DERIE);
 }
 
-static inline void stm32_fmc2_nfc_disable_bch_irq(struct stm32_fmc2_nfc *nfc)
+static void stm32_fmc2_nfc_disable_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	u32 bchier = readl_relaxed(nfc->io_base + FMC2_BCHIER);
-
-	bchier &= ~FMC2_BCHIER_DERIE;
-	bchier &= ~FMC2_BCHIER_EPBRIE;
-
-	writel_relaxed(bchier, nfc->io_base + FMC2_BCHIER);
+	regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+			   FMC2_BCHIER_DERIE | FMC2_BCHIER_EPBRIE, 0);
 
 	nfc->irq_state = FMC2_IRQ_UNKNOWN;
 }
 
-static inline void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
+static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	writel_relaxed(FMC2_BCHICR_CLEAR_IRQ, nfc->io_base + FMC2_BCHICR);
+	regmap_write(nfc->regmap, FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ);
 }
 
 /*
@@ -329,13 +318,8 @@ static void stm32_fmc2_nfc_hwctl(struct nand_chip *chip, int mode)
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	if (chip->ecc.strength != FMC2_ECC_HAM) {
-		u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
-
-		if (mode == NAND_ECC_WRITE)
-			pcr |= FMC2_PCR_WEN;
-		else
-			pcr &= ~FMC2_PCR_WEN;
-		writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
+		regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_WEN,
+				   mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
 
 		reinit_completion(&nfc->complete);
 		stm32_fmc2_nfc_clear_bch_irq(nfc);
@@ -350,7 +334,7 @@ static void stm32_fmc2_nfc_hwctl(struct nand_chip *chip, int mode)
  * ECC is 3 bytes for 512 bytes of data (supports error correction up to
  * max of 1-bit)
  */
-static inline void stm32_fmc2_nfc_ham_set_ecc(const u32 ecc_sta, u8 *ecc)
+static void stm32_fmc2_nfc_ham_set_ecc(const u32 ecc_sta, u8 *ecc)
 {
 	ecc[0] = ecc_sta;
 	ecc[1] = ecc_sta >> 8;
@@ -364,15 +348,15 @@ static int stm32_fmc2_nfc_ham_calculate(struct nand_chip *chip, const u8 *data,
 	u32 sr, heccr;
 	int ret;
 
-	ret = readl_relaxed_poll_timeout_atomic(nfc->io_base + FMC2_SR,
-						sr, sr & FMC2_SR_NWRF, 1,
-						1000 * FMC2_TIMEOUT_MS);
+	ret = regmap_read_poll_timeout(nfc->regmap, FMC2_SR, sr,
+				       sr & FMC2_SR_NWRF, 1,
+				       1000 * FMC2_TIMEOUT_MS);
 	if (ret) {
 		dev_err(nfc->dev, "ham timeout\n");
 		return ret;
 	}
 
-	heccr = readl_relaxed(nfc->io_base + FMC2_HECCR);
+	regmap_read(nfc->regmap, FMC2_HECCR, &heccr);
 	stm32_fmc2_nfc_ham_set_ecc(heccr, ecc);
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
@@ -451,13 +435,13 @@ static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
 	}
 
 	/* Read parity bits */
-	bchpbr = readl_relaxed(nfc->io_base + FMC2_BCHPBR1);
+	regmap_read(nfc->regmap, FMC2_BCHPBR1, &bchpbr);
 	ecc[0] = bchpbr;
 	ecc[1] = bchpbr >> 8;
 	ecc[2] = bchpbr >> 16;
 	ecc[3] = bchpbr >> 24;
 
-	bchpbr = readl_relaxed(nfc->io_base + FMC2_BCHPBR2);
+	regmap_read(nfc->regmap, FMC2_BCHPBR2, &bchpbr);
 	ecc[4] = bchpbr;
 	ecc[5] = bchpbr >> 8;
 	ecc[6] = bchpbr >> 16;
@@ -465,13 +449,13 @@ static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		ecc[7] = bchpbr >> 24;
 
-		bchpbr = readl_relaxed(nfc->io_base + FMC2_BCHPBR3);
+		regmap_read(nfc->regmap, FMC2_BCHPBR3, &bchpbr);
 		ecc[8] = bchpbr;
 		ecc[9] = bchpbr >> 8;
 		ecc[10] = bchpbr >> 16;
 		ecc[11] = bchpbr >> 24;
 
-		bchpbr = readl_relaxed(nfc->io_base + FMC2_BCHPBR4);
+		regmap_read(nfc->regmap, FMC2_BCHPBR4, &bchpbr);
 		ecc[12] = bchpbr;
 	}
 
@@ -533,11 +517,7 @@ static int stm32_fmc2_nfc_bch_correct(struct nand_chip *chip, u8 *dat,
 		return -ETIMEDOUT;
 	}
 
-	ecc_sta[0] = readl_relaxed(nfc->io_base + FMC2_BCHDSR0);
-	ecc_sta[1] = readl_relaxed(nfc->io_base + FMC2_BCHDSR1);
-	ecc_sta[2] = readl_relaxed(nfc->io_base + FMC2_BCHDSR2);
-	ecc_sta[3] = readl_relaxed(nfc->io_base + FMC2_BCHDSR3);
-	ecc_sta[4] = readl_relaxed(nfc->io_base + FMC2_BCHDSR4);
+	regmap_bulk_read(nfc->regmap, FMC2_BCHDSR0, ecc_sta, 5);
 
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
@@ -612,30 +592,29 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct mtd_info *mtd = nand_to_mtd(chip);
-	u32 csqcfgr1, csqcfgr2, csqcfgr3;
-	u32 csqar1, csqar2;
 	u32 ecc_offset = mtd->writesize + FMC2_BBM_LEN;
-	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
+	/*
+	 * cfg[0] => csqcfgr1, cfg[1] => csqcfgr2, cfg[2] => csqcfgr3
+	 * cfg[3] => csqar1, cfg[4] => csqar2
+	 */
+	u32 cfg[5];
 
-	if (write_data)
-		pcr |= FMC2_PCR_WEN;
-	else
-		pcr &= ~FMC2_PCR_WEN;
-	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
+	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_WEN,
+			   write_data ? FMC2_PCR_WEN : 0);
 
 	/*
 	 * - Set Program Page/Page Read command
 	 * - Enable DMA request data
 	 * - Set timings
 	 */
-	csqcfgr1 = FMC2_CSQCFGR1_DMADEN | FMC2_CSQCFGR1_CMD1T;
+	cfg[0] = FMC2_CSQCFGR1_DMADEN | FMC2_CSQCFGR1_CMD1T;
 	if (write_data)
-		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_CMD1, NAND_CMD_SEQIN);
+		cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_CMD1, NAND_CMD_SEQIN);
 	else
-		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_CMD1, NAND_CMD_READ0) |
-			    FMC2_CSQCFGR1_CMD2EN |
-			    FIELD_PREP(FMC2_CSQCFGR1_CMD2, NAND_CMD_READSTART) |
-			    FMC2_CSQCFGR1_CMD2T;
+		cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_CMD1, NAND_CMD_READ0) |
+			  FMC2_CSQCFGR1_CMD2EN |
+			  FIELD_PREP(FMC2_CSQCFGR1_CMD2, NAND_CMD_READSTART) |
+			  FMC2_CSQCFGR1_CMD2T;
 
 	/*
 	 * - Set Random Data Input/Random Data Read command
@@ -644,30 +623,29 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 * - Set timings
 	 */
 	if (write_data)
-		csqcfgr2 = FIELD_PREP(FMC2_CSQCFGR2_RCMD1, NAND_CMD_RNDIN);
+		cfg[1] = FIELD_PREP(FMC2_CSQCFGR2_RCMD1, NAND_CMD_RNDIN);
 	else
-		csqcfgr2 = FIELD_PREP(FMC2_CSQCFGR2_RCMD1, NAND_CMD_RNDOUT) |
-			   FMC2_CSQCFGR2_RCMD2EN |
-			   FIELD_PREP(FMC2_CSQCFGR2_RCMD2,
-				      NAND_CMD_RNDOUTSTART) |
-			   FMC2_CSQCFGR2_RCMD1T |
-			   FMC2_CSQCFGR2_RCMD2T;
+		cfg[1] = FIELD_PREP(FMC2_CSQCFGR2_RCMD1, NAND_CMD_RNDOUT) |
+			 FMC2_CSQCFGR2_RCMD2EN |
+			 FIELD_PREP(FMC2_CSQCFGR2_RCMD2, NAND_CMD_RNDOUTSTART) |
+			 FMC2_CSQCFGR2_RCMD1T |
+			 FMC2_CSQCFGR2_RCMD2T;
 	if (!raw) {
-		csqcfgr2 |= write_data ? 0 : FMC2_CSQCFGR2_DMASEN;
-		csqcfgr2 |= FMC2_CSQCFGR2_SQSDTEN;
+		cfg[1] |= write_data ? 0 : FMC2_CSQCFGR2_DMASEN;
+		cfg[1] |= FMC2_CSQCFGR2_SQSDTEN;
 	}
 
 	/*
 	 * - Set the number of sectors to be written
 	 * - Set timings
 	 */
-	csqcfgr3 = FIELD_PREP(FMC2_CSQCFGR3_SNBR, chip->ecc.steps - 1);
+	cfg[2] = FIELD_PREP(FMC2_CSQCFGR3_SNBR, chip->ecc.steps - 1);
 	if (write_data) {
-		csqcfgr3 |= FMC2_CSQCFGR3_RAC2T;
+		cfg[2] |= FMC2_CSQCFGR3_RAC2T;
 		if (chip->options & NAND_ROW_ADDR_3)
-			csqcfgr3 |= FMC2_CSQCFGR3_AC5T;
+			cfg[2] |= FMC2_CSQCFGR3_AC5T;
 		else
-			csqcfgr3 |= FMC2_CSQCFGR3_AC4T;
+			cfg[2] |= FMC2_CSQCFGR3_AC4T;
 	}
 
 	/*
@@ -675,8 +653,8 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 * Byte 1 and byte 2 => column, we start at 0x0
 	 * Byte 3 and byte 4 => page
 	 */
-	csqar1 = FIELD_PREP(FMC2_CSQCAR1_ADDC3, page);
-	csqar1 |= FIELD_PREP(FMC2_CSQCAR1_ADDC4, page >> 8);
+	cfg[3] = FIELD_PREP(FMC2_CSQCAR1_ADDC3, page);
+	cfg[3] |= FIELD_PREP(FMC2_CSQCAR1_ADDC4, page >> 8);
 
 	/*
 	 * - Set chip enable number
@@ -684,23 +662,19 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 * - Calculate the number of address cycles to be issued
 	 * - Set byte 5 of address cycle if needed
 	 */
-	csqar2 = FIELD_PREP(FMC2_CSQCAR2_NANDCEN, nfc->cs_sel);
+	cfg[4] = FIELD_PREP(FMC2_CSQCAR2_NANDCEN, nfc->cs_sel);
 	if (chip->options & NAND_BUSWIDTH_16)
-		csqar2 |= FIELD_PREP(FMC2_CSQCAR2_SAO, ecc_offset >> 1);
+		cfg[4] |= FIELD_PREP(FMC2_CSQCAR2_SAO, ecc_offset >> 1);
 	else
-		csqar2 |= FIELD_PREP(FMC2_CSQCAR2_SAO, ecc_offset);
+		cfg[4] |= FIELD_PREP(FMC2_CSQCAR2_SAO, ecc_offset);
 	if (chip->options & NAND_ROW_ADDR_3) {
-		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 5);
-		csqar2 |= FIELD_PREP(FMC2_CSQCAR2_ADDC5, page >> 16);
+		cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 5);
+		cfg[4] |= FIELD_PREP(FMC2_CSQCAR2_ADDC5, page >> 16);
 	} else {
-		csqcfgr1 |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 4);
+		cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 4);
 	}
 
-	writel_relaxed(csqcfgr1, nfc->io_base + FMC2_CSQCFGR1);
-	writel_relaxed(csqcfgr2, nfc->io_base + FMC2_CSQCFGR2);
-	writel_relaxed(csqcfgr3, nfc->io_base + FMC2_CSQCFGR3);
-	writel_relaxed(csqar1, nfc->io_base + FMC2_CSQAR1);
-	writel_relaxed(csqar2, nfc->io_base + FMC2_CSQAR2);
+	regmap_bulk_write(nfc->regmap, FMC2_CSQCFGR1, cfg, 5);
 }
 
 static void stm32_fmc2_nfc_dma_callback(void *arg)
@@ -718,7 +692,6 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
 	struct dma_chan *dma_ch = nfc->dma_rx_ch;
 	enum dma_data_direction dma_data_dir = DMA_FROM_DEVICE;
 	enum dma_transfer_direction dma_transfer_dir = DMA_DEV_TO_MEM;
-	u32 csqcr = readl_relaxed(nfc->io_base + FMC2_CSQCR);
 	int eccsteps = chip->ecc.steps;
 	int eccsize = chip->ecc.size;
 	unsigned long timeout = msecs_to_jiffies(FMC2_TIMEOUT_MS);
@@ -796,8 +769,8 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
 	stm32_fmc2_nfc_enable_seq_irq(nfc);
 
 	/* Start the transfer */
-	csqcr |= FMC2_CSQCR_CSQSTART;
-	writel_relaxed(csqcr, nfc->io_base + FMC2_CSQCR);
+	regmap_update_bits(nfc->regmap, FMC2_CSQCR,
+			   FMC2_CSQCR_CSQSTART, FMC2_CSQCR_CSQSTART);
 
 	/* Wait end of sequencer transfer */
 	if (!wait_for_completion_timeout(&nfc->complete, timeout)) {
@@ -890,11 +863,13 @@ static int stm32_fmc2_nfc_seq_write_page_raw(struct nand_chip *chip,
 }
 
 /* Get a status indicating which sectors have errors */
-static inline u16 stm32_fmc2_nfc_get_mapping_status(struct stm32_fmc2_nfc *nfc)
+static u16 stm32_fmc2_nfc_get_mapping_status(struct stm32_fmc2_nfc *nfc)
 {
-	u32 csqemsr = readl_relaxed(nfc->io_base + FMC2_CSQEMSR);
+	u32 csqemsr;
+
+	regmap_read(nfc->regmap, FMC2_CSQEMSR, &csqemsr);
 
-	return csqemsr & FMC2_CSQEMSR_SEM;
+	return FIELD_GET(FMC2_CSQEMSR_SEM, csqemsr);
 }
 
 static int stm32_fmc2_nfc_seq_correct(struct nand_chip *chip, u8 *dat,
@@ -1150,9 +1125,9 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
 	u32 isr, sr;
 
 	/* Check if there is no pending requests to the NAND flash */
-	if (readl_relaxed_poll_timeout_atomic(nfc->io_base + FMC2_SR, sr,
-					      sr & FMC2_SR_NWRF, 1,
-					      1000 * FMC2_TIMEOUT_MS))
+	if (regmap_read_poll_timeout(nfc->regmap, FMC2_SR, sr,
+				     sr & FMC2_SR_NWRF, 1,
+				     1000 * FMC2_TIMEOUT_MS))
 		dev_warn(nfc->dev, "Waitrdy timeout\n");
 
 	/* Wait tWB before R/B# signal is low */
@@ -1160,12 +1135,12 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	/* R/B# signal is low, clear high level flag */
-	writel_relaxed(FMC2_ICR_CIHLF, nfc->io_base + FMC2_ICR);
+	regmap_write(nfc->regmap, FMC2_ICR, FMC2_ICR_CIHLF);
 
 	/* Wait R/B# signal is high */
-	return readl_relaxed_poll_timeout_atomic(nfc->io_base + FMC2_ISR,
-						 isr, isr & FMC2_ISR_IHLF,
-						 5, 1000 * timeout_ms);
+	return regmap_read_poll_timeout(nfc->regmap, FMC2_ISR, isr,
+					isr & FMC2_ISR_IHLF, 5,
+					1000 * FMC2_TIMEOUT_MS);
 }
 
 static int stm32_fmc2_nfc_exec_op(struct nand_chip *chip,
@@ -1223,8 +1198,9 @@ static int stm32_fmc2_nfc_exec_op(struct nand_chip *chip,
 
 static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 {
-	u32 pcr = readl_relaxed(nfc->io_base + FMC2_PCR);
-	u32 bcr1 = readl_relaxed(nfc->io_base + FMC2_BCR1);
+	u32 pcr;
+
+	regmap_read(nfc->regmap, FMC2_PCR, &pcr);
 
 	/* Set CS used to undefined */
 	nfc->cs_sel = -1;
@@ -1255,12 +1231,12 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
 
 	/* Enable FMC2 controller */
-	bcr1 |= FMC2_BCR1_FMC2EN;
+	regmap_update_bits(nfc->regmap, FMC2_BCR1,
+			   FMC2_BCR1_FMC2EN, FMC2_BCR1_FMC2EN);
 
-	writel_relaxed(bcr1, nfc->io_base + FMC2_BCR1);
-	writel_relaxed(pcr, nfc->io_base + FMC2_PCR);
-	writel_relaxed(FMC2_PMEM_DEFAULT, nfc->io_base + FMC2_PMEM);
-	writel_relaxed(FMC2_PATT_DEFAULT, nfc->io_base + FMC2_PATT);
+	regmap_write(nfc->regmap, FMC2_PCR, pcr);
+	regmap_write(nfc->regmap, FMC2_PMEM, FMC2_PMEM_DEFAULT);
+	regmap_write(nfc->regmap, FMC2_PATT, FMC2_PATT_DEFAULT);
 }
 
 static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
@@ -1695,6 +1671,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct mtd_info *mtd;
 	struct nand_chip *chip;
+	void __iomem *mmio;
 	int chip_cs, mem_region, ret, irq;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
@@ -1710,9 +1687,13 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 		return ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	nfc->io_base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(nfc->io_base))
-		return PTR_ERR(nfc->io_base);
+	mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(mmio))
+		return PTR_ERR(mmio);
+
+	nfc->regmap = devm_regmap_init_mmio(dev, mmio, &stm32_fmc2_regmap_cfg);
+	if (IS_ERR(nfc->regmap))
+		return PTR_ERR(nfc->regmap);
 
 	nfc->io_phys_addr = res->start;
 
-- 
1.9.1


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

* [PATCH v2 11/12] mtd: rawnand: stm32_fmc2: use stm32_fmc2 structure in nfc controller
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (9 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 10/12] mtd: rawnand: stm32_fmc2: use regmap APIs Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  2020-04-15 15:57 ` [PATCH v2 12/12] mtd: rawnand: stm32_fmc2: add new MP1 compatible string Christophe Kerello
  11 siblings, 0 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch moves common used resources (registers base, clocks, ...)
in stm32_fmc2 structure.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
Changes in v2:
 - call 2 APIs to manage FMC2 enable/disable instead of ops
 - call 2 APIs to manage FMC2 NWAIT shared signal instead of ops

 drivers/mtd/nand/raw/Kconfig           |   1 +
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 188 ++++++++++++++++++++++-----------
 2 files changed, 128 insertions(+), 61 deletions(-)

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 12b715a..ad7d887 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -421,6 +421,7 @@ config MTD_NAND_STM32_FMC2
 	depends on MACH_STM32MP157 || COMPILE_TEST
 	select REGMAP
 	select REGMAP_MMIO
+	select MFD_STM32_FMC2
 	help
 	  Enables support for NAND Flash chips on SoCs containing the FMC2
 	  NAND controller. This controller is found on STM32MP SoCs.
diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index a3c2a11..4f931e2 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -99,14 +99,12 @@ static inline struct stm32_fmc2_nand *to_fmc2_nand(struct nand_chip *chip)
 struct stm32_fmc2_nfc {
 	struct nand_controller base;
 	struct stm32_fmc2_nand nand;
+	struct stm32_fmc2 *fmc2;
 	struct device *dev;
-	struct regmap *regmap;
 	void __iomem *data_base[FMC2_MAX_CE];
 	void __iomem *cmd_base[FMC2_MAX_CE];
 	void __iomem *addr_base[FMC2_MAX_CE];
-	phys_addr_t io_phys_addr;
 	phys_addr_t data_phys_addr[FMC2_MAX_CE];
-	struct clk *clk;
 	u8 irq_state;
 
 	struct dma_chan *dma_tx_ch;
@@ -135,10 +133,11 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *timings = &nand->timings;
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 pmem, patt;
 
 	/* Set tclr/tar timings */
-	regmap_update_bits(nfc->regmap, FMC2_PCR,
+	regmap_update_bits(fmc2->regmap, FMC2_PCR,
 			   FMC2_PCR_TCLR | FMC2_PCR_TAR,
 			   FIELD_PREP(FMC2_PCR_TCLR, timings->tclr) |
 			   FIELD_PREP(FMC2_PCR_TAR, timings->tar));
@@ -148,19 +147,20 @@ static void stm32_fmc2_nfc_timings_init(struct nand_chip *chip)
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMWAIT, timings->twait);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMHOLD, timings->thold_mem);
 	pmem |= FIELD_PREP(FMC2_PMEM_MEMHIZ, timings->thiz);
-	regmap_write(nfc->regmap, FMC2_PMEM, pmem);
+	regmap_write(fmc2->regmap, FMC2_PMEM, pmem);
 
 	/* Set tset/twait/thold/thiz timings in attribut bank */
 	patt = FIELD_PREP(FMC2_PATT_ATTSET, timings->tset_att);
 	patt |= FIELD_PREP(FMC2_PATT_ATTWAIT, timings->twait);
 	patt |= FIELD_PREP(FMC2_PATT_ATTHOLD, timings->thold_att);
 	patt |= FIELD_PREP(FMC2_PATT_ATTHIZ, timings->thiz);
-	regmap_write(nfc->regmap, FMC2_PATT, patt);
+	regmap_write(fmc2->regmap, FMC2_PATT, patt);
 }
 
 static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 pcr = 0, pcr_mask;
 
 	/* Configure ECC algorithm (default configuration is Hamming) */
@@ -182,13 +182,14 @@ static void stm32_fmc2_nfc_setup(struct nand_chip *chip)
 	pcr_mask |= FMC2_PCR_ECCSS;
 	pcr |= FIELD_PREP(FMC2_PCR_ECCSS, FMC2_PCR_ECCSS_512);
 
-	regmap_update_bits(nfc->regmap, FMC2_PCR, pcr_mask, pcr);
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, pcr_mask, pcr);
 }
 
 static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	struct dma_slave_config dma_cfg;
 	int ret;
 
@@ -227,7 +228,7 @@ static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
 		 * BCH4/BCH8: we read BCHDSRSx registers
 		 */
 		memset(&dma_cfg, 0, sizeof(dma_cfg));
-		dma_cfg.src_addr = nfc->io_phys_addr;
+		dma_cfg.src_addr = fmc2->reg_phys_addr;
 		dma_cfg.src_addr += chip->ecc.strength == FMC2_ECC_HAM ?
 				    FMC2_HECCR : FMC2_BCHDSR0;
 		dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -248,55 +249,68 @@ static int stm32_fmc2_nfc_select_chip(struct nand_chip *chip, int chipnr)
 
 static void stm32_fmc2_nfc_set_buswidth_16(struct stm32_fmc2_nfc *nfc, bool set)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 pcr;
 
 	pcr = set ? FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_16) :
 		    FIELD_PREP(FMC2_PCR_PWID, FMC2_PCR_PWID_BUSWIDTH_8);
 
-	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_PWID, pcr);
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_PWID, pcr);
 }
 
 static void stm32_fmc2_nfc_set_ecc(struct stm32_fmc2_nfc *nfc, bool enable)
 {
-	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_ECCEN,
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_ECCEN,
 			   enable ? FMC2_PCR_ECCEN : 0);
 }
 
 static void stm32_fmc2_nfc_enable_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
 	nfc->irq_state = FMC2_IRQ_SEQ;
 
-	regmap_update_bits(nfc->regmap, FMC2_CSQIER,
+	regmap_update_bits(fmc2->regmap, FMC2_CSQIER,
 			   FMC2_CSQIER_TCIE, FMC2_CSQIER_TCIE);
 }
 
 static void stm32_fmc2_nfc_disable_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	regmap_update_bits(nfc->regmap, FMC2_CSQIER, FMC2_CSQIER_TCIE, 0);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_update_bits(fmc2->regmap, FMC2_CSQIER, FMC2_CSQIER_TCIE, 0);
 
 	nfc->irq_state = FMC2_IRQ_UNKNOWN;
 }
 
 static void stm32_fmc2_nfc_clear_seq_irq(struct stm32_fmc2_nfc *nfc)
 {
-	regmap_write(nfc->regmap, FMC2_CSQICR, FMC2_CSQICR_CLEAR_IRQ);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_write(fmc2->regmap, FMC2_CSQICR, FMC2_CSQICR_CLEAR_IRQ);
 }
 
 static void stm32_fmc2_nfc_enable_bch_irq(struct stm32_fmc2_nfc *nfc, int mode)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
 	nfc->irq_state = FMC2_IRQ_BCH;
 
 	if (mode == NAND_ECC_WRITE)
-		regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+		regmap_update_bits(fmc2->regmap, FMC2_BCHIER,
 				   FMC2_BCHIER_EPBRIE, FMC2_BCHIER_EPBRIE);
 	else
-		regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+		regmap_update_bits(fmc2->regmap, FMC2_BCHIER,
 				   FMC2_BCHIER_DERIE, FMC2_BCHIER_DERIE);
 }
 
 static void stm32_fmc2_nfc_disable_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	regmap_update_bits(nfc->regmap, FMC2_BCHIER,
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_update_bits(fmc2->regmap, FMC2_BCHIER,
 			   FMC2_BCHIER_DERIE | FMC2_BCHIER_EPBRIE, 0);
 
 	nfc->irq_state = FMC2_IRQ_UNKNOWN;
@@ -304,7 +318,9 @@ static void stm32_fmc2_nfc_disable_bch_irq(struct stm32_fmc2_nfc *nfc)
 
 static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
 {
-	regmap_write(nfc->regmap, FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+
+	regmap_write(fmc2->regmap, FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ);
 }
 
 /*
@@ -314,11 +330,12 @@ static void stm32_fmc2_nfc_clear_bch_irq(struct stm32_fmc2_nfc *nfc)
 static void stm32_fmc2_nfc_hwctl(struct nand_chip *chip, int mode)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
 	if (chip->ecc.strength != FMC2_ECC_HAM) {
-		regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_WEN,
+		regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_WEN,
 				   mode == NAND_ECC_WRITE ? FMC2_PCR_WEN : 0);
 
 		reinit_completion(&nfc->complete);
@@ -345,10 +362,11 @@ static int stm32_fmc2_nfc_ham_calculate(struct nand_chip *chip, const u8 *data,
 					u8 *ecc)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 sr, heccr;
 	int ret;
 
-	ret = regmap_read_poll_timeout(nfc->regmap, FMC2_SR, sr,
+	ret = regmap_read_poll_timeout(fmc2->regmap, FMC2_SR, sr,
 				       sr & FMC2_SR_NWRF, 1,
 				       1000 * FMC2_TIMEOUT_MS);
 	if (ret) {
@@ -356,7 +374,7 @@ static int stm32_fmc2_nfc_ham_calculate(struct nand_chip *chip, const u8 *data,
 		return ret;
 	}
 
-	regmap_read(nfc->regmap, FMC2_HECCR, &heccr);
+	regmap_read(fmc2->regmap, FMC2_HECCR, &heccr);
 	stm32_fmc2_nfc_ham_set_ecc(heccr, ecc);
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
@@ -424,6 +442,7 @@ static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
 					u8 *ecc)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 bchpbr;
 
 	/* Wait until the BCH code is ready */
@@ -435,13 +454,13 @@ static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
 	}
 
 	/* Read parity bits */
-	regmap_read(nfc->regmap, FMC2_BCHPBR1, &bchpbr);
+	regmap_read(fmc2->regmap, FMC2_BCHPBR1, &bchpbr);
 	ecc[0] = bchpbr;
 	ecc[1] = bchpbr >> 8;
 	ecc[2] = bchpbr >> 16;
 	ecc[3] = bchpbr >> 24;
 
-	regmap_read(nfc->regmap, FMC2_BCHPBR2, &bchpbr);
+	regmap_read(fmc2->regmap, FMC2_BCHPBR2, &bchpbr);
 	ecc[4] = bchpbr;
 	ecc[5] = bchpbr >> 8;
 	ecc[6] = bchpbr >> 16;
@@ -449,13 +468,13 @@ static int stm32_fmc2_nfc_bch_calculate(struct nand_chip *chip, const u8 *data,
 	if (chip->ecc.strength == FMC2_ECC_BCH8) {
 		ecc[7] = bchpbr >> 24;
 
-		regmap_read(nfc->regmap, FMC2_BCHPBR3, &bchpbr);
+		regmap_read(fmc2->regmap, FMC2_BCHPBR3, &bchpbr);
 		ecc[8] = bchpbr;
 		ecc[9] = bchpbr >> 8;
 		ecc[10] = bchpbr >> 16;
 		ecc[11] = bchpbr >> 24;
 
-		regmap_read(nfc->regmap, FMC2_BCHPBR4, &bchpbr);
+		regmap_read(fmc2->regmap, FMC2_BCHPBR4, &bchpbr);
 		ecc[12] = bchpbr;
 	}
 
@@ -507,6 +526,7 @@ static int stm32_fmc2_nfc_bch_correct(struct nand_chip *chip, u8 *dat,
 				      u8 *read_ecc, u8 *calc_ecc)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 ecc_sta[5];
 
 	/* Wait until the decoding error is ready */
@@ -517,7 +537,7 @@ static int stm32_fmc2_nfc_bch_correct(struct nand_chip *chip, u8 *dat,
 		return -ETIMEDOUT;
 	}
 
-	regmap_bulk_read(nfc->regmap, FMC2_BCHDSR0, ecc_sta, 5);
+	regmap_bulk_read(fmc2->regmap, FMC2_BCHDSR0, ecc_sta, 5);
 
 	stm32_fmc2_nfc_set_ecc(nfc, false);
 
@@ -591,6 +611,7 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 					int raw, bool write_data)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	u32 ecc_offset = mtd->writesize + FMC2_BBM_LEN;
 	/*
@@ -599,7 +620,7 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 	 */
 	u32 cfg[5];
 
-	regmap_update_bits(nfc->regmap, FMC2_PCR, FMC2_PCR_WEN,
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_WEN,
 			   write_data ? FMC2_PCR_WEN : 0);
 
 	/*
@@ -674,7 +695,7 @@ static void stm32_fmc2_nfc_rw_page_init(struct nand_chip *chip, int page,
 		cfg[0] |= FIELD_PREP(FMC2_CSQCFGR1_ACYNBR, 4);
 	}
 
-	regmap_bulk_write(nfc->regmap, FMC2_CSQCFGR1, cfg, 5);
+	regmap_bulk_write(fmc2->regmap, FMC2_CSQCFGR1, cfg, 5);
 }
 
 static void stm32_fmc2_nfc_dma_callback(void *arg)
@@ -687,6 +708,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
 			       int raw, bool write_data)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	struct dma_async_tx_descriptor *desc_data, *desc_ecc;
 	struct scatterlist *sg;
 	struct dma_chan *dma_ch = nfc->dma_rx_ch;
@@ -769,7 +791,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf,
 	stm32_fmc2_nfc_enable_seq_irq(nfc);
 
 	/* Start the transfer */
-	regmap_update_bits(nfc->regmap, FMC2_CSQCR,
+	regmap_update_bits(fmc2->regmap, FMC2_CSQCR,
 			   FMC2_CSQCR_CSQSTART, FMC2_CSQCR_CSQSTART);
 
 	/* Wait end of sequencer transfer */
@@ -865,9 +887,10 @@ static int stm32_fmc2_nfc_seq_write_page_raw(struct nand_chip *chip,
 /* Get a status indicating which sectors have errors */
 static u16 stm32_fmc2_nfc_get_mapping_status(struct stm32_fmc2_nfc *nfc)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 csqemsr;
 
-	regmap_read(nfc->regmap, FMC2_CSQEMSR, &csqemsr);
+	regmap_read(fmc2->regmap, FMC2_CSQEMSR, &csqemsr);
 
 	return FIELD_GET(FMC2_CSQEMSR_SEM, csqemsr);
 }
@@ -1121,11 +1144,12 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
 				  unsigned long timeout_ms)
 {
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	const struct nand_sdr_timings *timings;
 	u32 isr, sr;
 
 	/* Check if there is no pending requests to the NAND flash */
-	if (regmap_read_poll_timeout(nfc->regmap, FMC2_SR, sr,
+	if (regmap_read_poll_timeout(fmc2->regmap, FMC2_SR, sr,
 				     sr & FMC2_SR_NWRF, 1,
 				     1000 * FMC2_TIMEOUT_MS))
 		dev_warn(nfc->dev, "Waitrdy timeout\n");
@@ -1135,10 +1159,10 @@ static int stm32_fmc2_nfc_waitrdy(struct nand_chip *chip,
 	ndelay(PSEC_TO_NSEC(timings->tWB_max));
 
 	/* R/B# signal is low, clear high level flag */
-	regmap_write(nfc->regmap, FMC2_ICR, FMC2_ICR_CIHLF);
+	regmap_write(fmc2->regmap, FMC2_ICR, FMC2_ICR_CIHLF);
 
 	/* Wait R/B# signal is high */
-	return regmap_read_poll_timeout(nfc->regmap, FMC2_ISR, isr,
+	return regmap_read_poll_timeout(fmc2->regmap, FMC2_ISR, isr,
 					isr & FMC2_ISR_IHLF, 5,
 					1000 * FMC2_TIMEOUT_MS);
 }
@@ -1198,9 +1222,10 @@ static int stm32_fmc2_nfc_exec_op(struct nand_chip *chip,
 
 static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 {
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	u32 pcr;
 
-	regmap_read(nfc->regmap, FMC2_PCR, &pcr);
+	regmap_read(fmc2->regmap, FMC2_PCR, &pcr);
 
 	/* Set CS used to undefined */
 	nfc->cs_sel = -1;
@@ -1230,13 +1255,9 @@ static void stm32_fmc2_nfc_init(struct stm32_fmc2_nfc *nfc)
 	pcr &= ~FMC2_PCR_TAR;
 	pcr |= FIELD_PREP(FMC2_PCR_TAR, FMC2_PCR_TAR_DEFAULT);
 
-	/* Enable FMC2 controller */
-	regmap_update_bits(nfc->regmap, FMC2_BCR1,
-			   FMC2_BCR1_FMC2EN, FMC2_BCR1_FMC2EN);
-
-	regmap_write(nfc->regmap, FMC2_PCR, pcr);
-	regmap_write(nfc->regmap, FMC2_PMEM, FMC2_PMEM_DEFAULT);
-	regmap_write(nfc->regmap, FMC2_PATT, FMC2_PATT_DEFAULT);
+	regmap_write(fmc2->regmap, FMC2_PCR, pcr);
+	regmap_write(fmc2->regmap, FMC2_PMEM, FMC2_PMEM_DEFAULT);
+	regmap_write(fmc2->regmap, FMC2_PATT, FMC2_PATT_DEFAULT);
 }
 
 static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
@@ -1245,7 +1266,8 @@ static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip,
 	struct stm32_fmc2_nfc *nfc = to_stm32_nfc(chip->controller);
 	struct stm32_fmc2_nand *nand = to_fmc2_nand(chip);
 	struct stm32_fmc2_timings *tims = &nand->timings;
-	unsigned long hclk = clk_get_rate(nfc->clk);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
+	unsigned long hclk = clk_get_rate(fmc2->clk);
 	unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000);
 	unsigned long timing, tar, tclr, thiz, twait;
 	unsigned long tset_mem, tset_att, thold_mem, thold_att;
@@ -1662,17 +1684,43 @@ static int stm32_fmc2_nfc_parse_dt(struct stm32_fmc2_nfc *nfc)
 	return ret;
 }
 
+static int stm32_fmc2_nfc_set_mmio_clk(struct platform_device *pdev,
+				       struct stm32_fmc2 *fmc2)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	void __iomem *mmio;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(mmio))
+		return PTR_ERR(mmio);
+
+	fmc2->regmap = devm_regmap_init_mmio(dev, mmio, &stm32_fmc2_regmap_cfg);
+	if (IS_ERR(fmc2->regmap))
+		return PTR_ERR(fmc2->regmap);
+
+	fmc2->reg_phys_addr = res->start;
+
+	fmc2->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(fmc2->clk))
+		return PTR_ERR(fmc2->clk);
+
+	return 0;
+}
+
 static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct reset_control *rstc;
+	struct stm32_fmc2 *fmc2;
 	struct stm32_fmc2_nfc *nfc;
 	struct stm32_fmc2_nand *nand;
 	struct resource *res;
 	struct mtd_info *mtd;
 	struct nand_chip *chip;
-	void __iomem *mmio;
 	int chip_cs, mem_region, ret, irq;
+	int num_region = 0;
 
 	nfc = devm_kzalloc(dev, sizeof(*nfc), GFP_KERNEL);
 	if (!nfc)
@@ -1686,18 +1734,21 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	mmio = devm_ioremap_resource(dev, res);
-	if (IS_ERR(mmio))
-		return PTR_ERR(mmio);
+	fmc2 = dev_get_drvdata(dev->parent);
+	if (!fmc2) {
+		num_region = 1;
 
-	nfc->regmap = devm_regmap_init_mmio(dev, mmio, &stm32_fmc2_regmap_cfg);
-	if (IS_ERR(nfc->regmap))
-		return PTR_ERR(nfc->regmap);
+		fmc2 = devm_kzalloc(dev, sizeof(*fmc2), GFP_KERNEL);
+		if (!fmc2)
+			return -ENOMEM;
 
-	nfc->io_phys_addr = res->start;
+		ret = stm32_fmc2_nfc_set_mmio_clk(pdev, fmc2);
+		if (ret)
+			return ret;
+	}
+	nfc->fmc2 = fmc2;
 
-	for (chip_cs = 0, mem_region = 1; chip_cs < FMC2_MAX_CE;
+	for (chip_cs = 0, mem_region = num_region; chip_cs < FMC2_MAX_CE;
 	     chip_cs++, mem_region += 3) {
 		if (!(nfc->cs_assigned & BIT(chip_cs)))
 			continue;
@@ -1735,11 +1786,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 
 	init_completion(&nfc->complete);
 
-	nfc->clk = devm_clk_get(dev, NULL);
-	if (IS_ERR(nfc->clk))
-		return PTR_ERR(nfc->clk);
-
-	ret = clk_prepare_enable(nfc->clk);
+	ret = clk_prepare_enable(fmc2->clk);
 	if (ret) {
 		dev_err(dev, "can not enable the clock\n");
 		return ret;
@@ -1759,6 +1806,12 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_dma_setup;
 
+	if (!stm32_fmc2_get_nwait(fmc2)) {
+		ret = -EINVAL;
+		goto err_dma_setup;
+	}
+
+	stm32_fmc2_enable(fmc2);
 	stm32_fmc2_nfc_init(nfc);
 
 	nand = &nfc->nand;
@@ -1778,7 +1831,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	/* Scan to find existence of the device */
 	ret = nand_scan(chip, nand->ncs);
 	if (ret)
-		goto err_dma_setup;
+		goto err_nand_scan;
 
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret)
@@ -1791,6 +1844,11 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 err_device_register:
 	nand_cleanup(chip);
 
+err_nand_scan:
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_PBKEN, 0);
+	stm32_fmc2_put_nwait(fmc2);
+	stm32_fmc2_disable(fmc2);
+
 err_dma_setup:
 	if (nfc->dma_ecc_ch)
 		dma_release_channel(nfc->dma_ecc_ch);
@@ -1803,7 +1861,7 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	sg_free_table(&nfc->dma_ecc_sg);
 
 err_clk_disable:
-	clk_disable_unprepare(nfc->clk);
+	clk_disable_unprepare(fmc2->clk);
 
 	return ret;
 }
@@ -1812,7 +1870,11 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
 {
 	struct stm32_fmc2_nfc *nfc = platform_get_drvdata(pdev);
 	struct stm32_fmc2_nand *nand = &nfc->nand;
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 
+	regmap_update_bits(fmc2->regmap, FMC2_PCR, FMC2_PCR_PBKEN, 0);
+	stm32_fmc2_put_nwait(fmc2);
+	stm32_fmc2_disable(fmc2);
 	nand_release(&nand->chip);
 
 	if (nfc->dma_ecc_ch)
@@ -1825,7 +1887,7 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
 	sg_free_table(&nfc->dma_data_sg);
 	sg_free_table(&nfc->dma_ecc_sg);
 
-	clk_disable_unprepare(nfc->clk);
+	clk_disable_unprepare(fmc2->clk);
 
 	return 0;
 }
@@ -1833,8 +1895,10 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
 static int __maybe_unused stm32_fmc2_nfc_suspend(struct device *dev)
 {
 	struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev);
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 
-	clk_disable_unprepare(nfc->clk);
+	stm32_fmc2_disable(fmc2);
+	clk_disable_unprepare(fmc2->clk);
 
 	pinctrl_pm_select_sleep_state(dev);
 
@@ -1845,16 +1909,18 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev)
 {
 	struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev);
 	struct stm32_fmc2_nand *nand = &nfc->nand;
+	struct stm32_fmc2 *fmc2 = nfc->fmc2;
 	int chip_cs, ret;
 
 	pinctrl_pm_select_default_state(dev);
 
-	ret = clk_prepare_enable(nfc->clk);
+	ret = clk_prepare_enable(fmc2->clk);
 	if (ret) {
 		dev_err(dev, "can not enable the clock\n");
 		return ret;
 	}
 
+	stm32_fmc2_enable(fmc2);
 	stm32_fmc2_nfc_init(nfc);
 
 	for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) {
-- 
1.9.1


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

* [PATCH v2 12/12] mtd: rawnand: stm32_fmc2: add new MP1 compatible string
  2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
                   ` (10 preceding siblings ...)
  2020-04-15 15:57 ` [PATCH v2 11/12] mtd: rawnand: stm32_fmc2: use stm32_fmc2 structure in nfc controller Christophe Kerello
@ 2020-04-15 15:57 ` Christophe Kerello
  11 siblings, 0 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-15 15:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, marex,
	Christophe Kerello

This patch adds "st,stm32mp1-fmc2-nand" compatible string.

Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
---
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 4f931e2..f82c7dd 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -1938,6 +1938,7 @@ static SIMPLE_DEV_PM_OPS(stm32_fmc2_nfc_pm_ops, stm32_fmc2_nfc_suspend,
 
 static const struct of_device_id stm32_fmc2_nfc_match[] = {
 	{.compatible = "st,stm32mp15-fmc2"},
+	{.compatible = "st,stm32mp1-fmc2-nand"},
 	{}
 };
 MODULE_DEVICE_TABLE(of, stm32_fmc2_nfc_match);
-- 
1.9.1


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

* Re: [PATCH v2 08/12] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
  2020-04-15 15:57 ` [PATCH v2 08/12] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
@ 2020-04-16 19:45   ` Boris Brezillon
  2020-04-27 18:50     ` Miquel Raynal
  0 siblings, 1 reply; 51+ messages in thread
From: Boris Brezillon @ 2020-04-16 19:45 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: miquel.raynal, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, marex, devicetree, linux-kernel, linux-mtd,
	linux-stm32

On Wed, 15 Apr 2020 17:57:32 +0200
Christophe Kerello <christophe.kerello@st.com> wrote:

> This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.

Oh, nice. I didn't know about these macros. This could have saved me
from defining a whole bunch of setters/getters in driver code...



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

* Re: [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-04-15 15:57 ` [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI " Christophe Kerello
@ 2020-04-16 19:53   ` Boris Brezillon
  2020-04-17 15:29     ` Christophe Kerello
  0 siblings, 1 reply; 51+ messages in thread
From: Boris Brezillon @ 2020-04-16 19:53 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: miquel.raynal, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, marex, devicetree, linux-kernel, linux-mtd,
	linux-stm32

On Wed, 15 Apr 2020 17:57:27 +0200
Christophe Kerello <christophe.kerello@st.com> wrote:

> The driver adds the support for the STMicroelectronics FMC2 EBI controller
> found on STM32MP SOCs.
> 
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> Tested-by: Marek Vasut <marex@denx.de>
> ---
> Changes in v2:
>  - call 2 APIs to manage FMC2 enable/disable instead of ops
>  - call 2 APIs to manage FMC2 NWAIT shared signal instead of ops
> 
>  drivers/bus/Kconfig          |   11 +
>  drivers/bus/Makefile         |    1 +
>  drivers/bus/stm32-fmc2-ebi.c | 1091 ++++++++++++++++++++++++++++++++++++++++++

Hm, I see that other memory bus controller drivers are placed under
drivers/memory/, any reason for choosing drivers/bus/? If that's where
we want to have all generic memory bus controllers to live it might be
worth moving existing drivers to the drivers/bus/ directory at some
point.

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

* Re: [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-04-16 19:53   ` Boris Brezillon
@ 2020-04-17 15:29     ` Christophe Kerello
  2020-04-17 15:31       ` Marek Vasut
  0 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-17 15:29 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: miquel.raynal, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, marex, devicetree, linux-kernel, linux-mtd,
	linux-stm32



On 4/16/20 9:53 PM, Boris Brezillon wrote:
> On Wed, 15 Apr 2020 17:57:27 +0200
> Christophe Kerello <christophe.kerello@st.com> wrote:
> 
>> The driver adds the support for the STMicroelectronics FMC2 EBI controller
>> found on STM32MP SOCs.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> Tested-by: Marek Vasut <marex@denx.de>
>> ---
>> Changes in v2:
>>   - call 2 APIs to manage FMC2 enable/disable instead of ops
>>   - call 2 APIs to manage FMC2 NWAIT shared signal instead of ops
>>
>>   drivers/bus/Kconfig          |   11 +
>>   drivers/bus/Makefile         |    1 +
>>   drivers/bus/stm32-fmc2-ebi.c | 1091 ++++++++++++++++++++++++++++++++++++++++++
> 
> Hm, I see that other memory bus controller drivers are placed under
> drivers/memory/, any reason for choosing drivers/bus/? If that's where
> we want to have all generic memory bus controllers to live it might be
> worth moving existing drivers to the drivers/bus/ directory at some
> point.
> 

Hi Boris,

I see this controller as an external bus interface as we are able to 
attach different devices on it, like a PSRAM, an ethernet controller, a 
FPGA, a LCD display, ...

When I had a look at bus/Kconfig file, I have found similar drivers 
(like IMX_WEIM or QCOM_EBI2 drivers). These drivers are able to connect 
devices like NAND Flash, SRAM, ethernet adapters, FPGAs and LCD displays 
as it is written in the Kconfig file.

But, after checking memory/Kconfig file, it is also possible to find 
similar drivers (like ATMEL_EBI driver that is inspired by the WEIM bus 
driver).

So, I will follow the recommendation and I will move it to 
drivers/memory folder if it is the place where this driver should be.

Regards,
Christophe Kerello.


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

* Re: [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-04-17 15:29     ` Christophe Kerello
@ 2020-04-17 15:31       ` Marek Vasut
  2020-04-17 15:41         ` Boris Brezillon
  0 siblings, 1 reply; 51+ messages in thread
From: Marek Vasut @ 2020-04-17 15:31 UTC (permalink / raw)
  To: Christophe Kerello, Boris Brezillon
  Cc: miquel.raynal, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, devicetree, linux-kernel, linux-mtd,
	linux-stm32

On 4/17/20 5:29 PM, Christophe Kerello wrote:
> 
> 
> On 4/16/20 9:53 PM, Boris Brezillon wrote:
>> On Wed, 15 Apr 2020 17:57:27 +0200
>> Christophe Kerello <christophe.kerello@st.com> wrote:
>>
>>> The driver adds the support for the STMicroelectronics FMC2 EBI
>>> controller
>>> found on STM32MP SOCs.
>>>
>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>>> Tested-by: Marek Vasut <marex@denx.de>
>>> ---
>>> Changes in v2:
>>>   - call 2 APIs to manage FMC2 enable/disable instead of ops
>>>   - call 2 APIs to manage FMC2 NWAIT shared signal instead of ops
>>>
>>>   drivers/bus/Kconfig          |   11 +
>>>   drivers/bus/Makefile         |    1 +
>>>   drivers/bus/stm32-fmc2-ebi.c | 1091
>>> ++++++++++++++++++++++++++++++++++++++++++
>>
>> Hm, I see that other memory bus controller drivers are placed under
>> drivers/memory/, any reason for choosing drivers/bus/? If that's where
>> we want to have all generic memory bus controllers to live it might be
>> worth moving existing drivers to the drivers/bus/ directory at some
>> point.
>>
> 
> Hi Boris,
> 
> I see this controller as an external bus interface as we are able to
> attach different devices on it, like a PSRAM, an ethernet controller, a
> FPGA, a LCD display, ...
> 
> When I had a look at bus/Kconfig file, I have found similar drivers
> (like IMX_WEIM or QCOM_EBI2 drivers). These drivers are able to connect
> devices like NAND Flash, SRAM, ethernet adapters, FPGAs and LCD displays
> as it is written in the Kconfig file.
> 
> But, after checking memory/Kconfig file, it is also possible to find
> similar drivers (like ATMEL_EBI driver that is inspired by the WEIM bus
> driver).
> 
> So, I will follow the recommendation and I will move it to
> drivers/memory folder if it is the place where this driver should be.

The EBI isn't a memory bus, you can very well have a non-memory device,
like an external parallel bus memory controller on it. So why should it
be in drivers/memory ?

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

* Re: [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-04-17 15:31       ` Marek Vasut
@ 2020-04-17 15:41         ` Boris Brezillon
  2020-04-17 15:44           ` Marek Vasut
  0 siblings, 1 reply; 51+ messages in thread
From: Boris Brezillon @ 2020-04-17 15:41 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Christophe Kerello, miquel.raynal, richard, vigneshr, lee.jones,
	robh+dt, mark.rutland, tony, devicetree, linux-kernel, linux-mtd,
	linux-stm32

On Fri, 17 Apr 2020 17:31:49 +0200
Marek Vasut <marex@denx.de> wrote:

> On 4/17/20 5:29 PM, Christophe Kerello wrote:
> > 
> > 
> > On 4/16/20 9:53 PM, Boris Brezillon wrote:  
> >> On Wed, 15 Apr 2020 17:57:27 +0200
> >> Christophe Kerello <christophe.kerello@st.com> wrote:
> >>  
> >>> The driver adds the support for the STMicroelectronics FMC2 EBI
> >>> controller
> >>> found on STM32MP SOCs.
> >>>
> >>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> >>> Tested-by: Marek Vasut <marex@denx.de>
> >>> ---
> >>> Changes in v2:
> >>>   - call 2 APIs to manage FMC2 enable/disable instead of ops
> >>>   - call 2 APIs to manage FMC2 NWAIT shared signal instead of ops
> >>>
> >>>   drivers/bus/Kconfig          |   11 +
> >>>   drivers/bus/Makefile         |    1 +
> >>>   drivers/bus/stm32-fmc2-ebi.c | 1091
> >>> ++++++++++++++++++++++++++++++++++++++++++  
> >>
> >> Hm, I see that other memory bus controller drivers are placed under
> >> drivers/memory/, any reason for choosing drivers/bus/? If that's where
> >> we want to have all generic memory bus controllers to live it might be
> >> worth moving existing drivers to the drivers/bus/ directory at some
> >> point.
> >>  
> > 
> > Hi Boris,
> > 
> > I see this controller as an external bus interface as we are able to
> > attach different devices on it, like a PSRAM, an ethernet controller, a
> > FPGA, a LCD display, ...
> > 
> > When I had a look at bus/Kconfig file, I have found similar drivers
> > (like IMX_WEIM or QCOM_EBI2 drivers). These drivers are able to connect
> > devices like NAND Flash, SRAM, ethernet adapters, FPGAs and LCD displays
> > as it is written in the Kconfig file.
> > 
> > But, after checking memory/Kconfig file, it is also possible to find
> > similar drivers (like ATMEL_EBI driver that is inspired by the WEIM bus
> > driver).
> > 
> > So, I will follow the recommendation and I will move it to
> > drivers/memory folder if it is the place where this driver should be.  
> 
> The EBI isn't a memory bus, you can very well have a non-memory device,
> like an external parallel bus memory controller on it. So why should it
> be in drivers/memory ?

Just like most of those so-called memory bus controllers we have under
drivers/memory/ => they are most of the time used to interact with
memories but can also be used for other things (Christophe listed a few
uses cases). And I'm not pushing one way or the other, all I said was
that we should makes things consistent instead of having half of
those controller drivers in drivers/memory/ and the other half in
drivers/bus/.


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

* Re: [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI controller driver
  2020-04-17 15:41         ` Boris Brezillon
@ 2020-04-17 15:44           ` Marek Vasut
  0 siblings, 0 replies; 51+ messages in thread
From: Marek Vasut @ 2020-04-17 15:44 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Christophe Kerello, miquel.raynal, richard, vigneshr, lee.jones,
	robh+dt, mark.rutland, tony, devicetree, linux-kernel, linux-mtd,
	linux-stm32

On 4/17/20 5:41 PM, Boris Brezillon wrote:
> On Fri, 17 Apr 2020 17:31:49 +0200
> Marek Vasut <marex@denx.de> wrote:
> 
>> On 4/17/20 5:29 PM, Christophe Kerello wrote:
>>>
>>>
>>> On 4/16/20 9:53 PM, Boris Brezillon wrote:  
>>>> On Wed, 15 Apr 2020 17:57:27 +0200
>>>> Christophe Kerello <christophe.kerello@st.com> wrote:
>>>>  
>>>>> The driver adds the support for the STMicroelectronics FMC2 EBI
>>>>> controller
>>>>> found on STM32MP SOCs.
>>>>>
>>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>>>>> Tested-by: Marek Vasut <marex@denx.de>
>>>>> ---
>>>>> Changes in v2:
>>>>>   - call 2 APIs to manage FMC2 enable/disable instead of ops
>>>>>   - call 2 APIs to manage FMC2 NWAIT shared signal instead of ops
>>>>>
>>>>>   drivers/bus/Kconfig          |   11 +
>>>>>   drivers/bus/Makefile         |    1 +
>>>>>   drivers/bus/stm32-fmc2-ebi.c | 1091
>>>>> ++++++++++++++++++++++++++++++++++++++++++  
>>>>
>>>> Hm, I see that other memory bus controller drivers are placed under
>>>> drivers/memory/, any reason for choosing drivers/bus/? If that's where
>>>> we want to have all generic memory bus controllers to live it might be
>>>> worth moving existing drivers to the drivers/bus/ directory at some
>>>> point.
>>>>  
>>>
>>> Hi Boris,
>>>
>>> I see this controller as an external bus interface as we are able to
>>> attach different devices on it, like a PSRAM, an ethernet controller, a
>>> FPGA, a LCD display, ...
>>>
>>> When I had a look at bus/Kconfig file, I have found similar drivers
>>> (like IMX_WEIM or QCOM_EBI2 drivers). These drivers are able to connect
>>> devices like NAND Flash, SRAM, ethernet adapters, FPGAs and LCD displays
>>> as it is written in the Kconfig file.
>>>
>>> But, after checking memory/Kconfig file, it is also possible to find
>>> similar drivers (like ATMEL_EBI driver that is inspired by the WEIM bus
>>> driver).
>>>
>>> So, I will follow the recommendation and I will move it to
>>> drivers/memory folder if it is the place where this driver should be.  
>>
>> The EBI isn't a memory bus, you can very well have a non-memory device,
>> like an external parallel bus memory controller on it. So why should it
>> be in drivers/memory ?
> 
> Just like most of those so-called memory bus controllers we have under
> drivers/memory/ => they are most of the time used to interact with
> memories but can also be used for other things (Christophe listed a few
> uses cases). And I'm not pushing one way or the other, all I said was
> that we should makes things consistent instead of having half of
> those controller drivers in drivers/memory/ and the other half in
> drivers/bus/.

I agree with that.

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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-15 15:57 ` [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver Christophe Kerello
@ 2020-04-24  7:45   ` Lee Jones
  2020-04-24 10:27     ` Marek Vasut
  0 siblings, 1 reply; 51+ messages in thread
From: Lee Jones @ 2020-04-24  7:45 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: miquel.raynal, richard, vigneshr, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

On Wed, 15 Apr 2020, Christophe Kerello wrote:

> The driver adds the support for the STMicroelectronics FMC2 controller
> found on STM32MP SOCs.
> 
> The FMC2 functional block makes the interface with: synchronous and
> asynchronous static memories (such as PSNOR, PSRAM or other
> memory-mapped peripherals) and NAND flash memories.
> 
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
> Changes in v2:
>  - remove ops from stm32_fmc2 structure
>  - add 2 APIs to manage FMC2 enable/disable
>  - add 2 APIs to manage FMC2 NWAIT shared signal
> 
>  drivers/mfd/Kconfig            |  12 +++
>  drivers/mfd/Makefile           |   1 +
>  drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
>  include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 374 insertions(+)
>  create mode 100644 drivers/mfd/stm32-fmc2.c
>  create mode 100644 include/linux/mfd/stm32-fmc2.h
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 2b20329..5260582 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
>  	  Also included is a Coulomb counter, a real-time clock (RTC), and
>  	  a 32.768 kHz clock gate.
>  
> +config MFD_STM32_FMC2
> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
> +	depends on MACH_STM32MP157 || COMPILE_TEST
> +	select MFD_CORE
> +	select REGMAP
> +	select REGMAP_MMIO
> +	help
> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
> +	  provides core support for the STM32 FMC2 controllers, in order to use
> +	  the actual functionality of the device other drivers must be enabled.

Not sure how many times I have to say this before people stop
attempting to pass these kinds of relationships off as MFDs:

A memory device and its bus is not an MFD.  In a similar vain to the
thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
either.

Please find another way to associate your device with its bus.

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24  7:45   ` Lee Jones
@ 2020-04-24 10:27     ` Marek Vasut
  2020-04-24 10:50       ` Lee Jones
  0 siblings, 1 reply; 51+ messages in thread
From: Marek Vasut @ 2020-04-24 10:27 UTC (permalink / raw)
  To: Lee Jones, Christophe Kerello
  Cc: miquel.raynal, richard, vigneshr, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree,
	Geert Uytterhoeven

On 4/24/20 9:45 AM, Lee Jones wrote:
> On Wed, 15 Apr 2020, Christophe Kerello wrote:
> 
>> The driver adds the support for the STMicroelectronics FMC2 controller
>> found on STM32MP SOCs.
>>
>> The FMC2 functional block makes the interface with: synchronous and
>> asynchronous static memories (such as PSNOR, PSRAM or other
>> memory-mapped peripherals) and NAND flash memories.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>> Changes in v2:
>>  - remove ops from stm32_fmc2 structure
>>  - add 2 APIs to manage FMC2 enable/disable
>>  - add 2 APIs to manage FMC2 NWAIT shared signal
>>
>>  drivers/mfd/Kconfig            |  12 +++
>>  drivers/mfd/Makefile           |   1 +
>>  drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
>>  include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 374 insertions(+)
>>  create mode 100644 drivers/mfd/stm32-fmc2.c
>>  create mode 100644 include/linux/mfd/stm32-fmc2.h
>>
>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>> index 2b20329..5260582 100644
>> --- a/drivers/mfd/Kconfig
>> +++ b/drivers/mfd/Kconfig
>> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
>>  	  Also included is a Coulomb counter, a real-time clock (RTC), and
>>  	  a 32.768 kHz clock gate.
>>  
>> +config MFD_STM32_FMC2
>> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
>> +	depends on MACH_STM32MP157 || COMPILE_TEST
>> +	select MFD_CORE
>> +	select REGMAP
>> +	select REGMAP_MMIO
>> +	help
>> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
>> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
>> +	  provides core support for the STM32 FMC2 controllers, in order to use
>> +	  the actual functionality of the device other drivers must be enabled.
> 
> Not sure how many times I have to say this before people stop
> attempting to pass these kinds of relationships off as MFDs:
> 
> A memory device and its bus is not an MFD.  In a similar vain to the
> thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
> either.
> 
> Please find another way to associate your device with its bus.

This FMC2 is however an IP which can either operate external devices
(like ethernet chip on this parallel bus) or external flashes (like NOR
and NAND chips).

Can you provide a suggestion how this should be handled, if not as MFD?
It seems to me, that this is a Multi-Function Device .

If this discussion is a recurring topic, is there some documentation
which explains how such devices should be handled ?

Thank you

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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24 10:27     ` Marek Vasut
@ 2020-04-24 10:50       ` Lee Jones
  2020-04-24 11:06         ` Marek Vasut
  0 siblings, 1 reply; 51+ messages in thread
From: Lee Jones @ 2020-04-24 10:50 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Christophe Kerello, miquel.raynal, richard, vigneshr, robh+dt,
	mark.rutland, tony, linux-mtd, linux-kernel, linux-stm32,
	devicetree, Geert Uytterhoeven

On Fri, 24 Apr 2020, Marek Vasut wrote:

> On 4/24/20 9:45 AM, Lee Jones wrote:
> > On Wed, 15 Apr 2020, Christophe Kerello wrote:
> > 
> >> The driver adds the support for the STMicroelectronics FMC2 controller
> >> found on STM32MP SOCs.
> >>
> >> The FMC2 functional block makes the interface with: synchronous and
> >> asynchronous static memories (such as PSNOR, PSRAM or other
> >> memory-mapped peripherals) and NAND flash memories.
> >>
> >> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> >> ---
> >> Changes in v2:
> >>  - remove ops from stm32_fmc2 structure
> >>  - add 2 APIs to manage FMC2 enable/disable
> >>  - add 2 APIs to manage FMC2 NWAIT shared signal
> >>
> >>  drivers/mfd/Kconfig            |  12 +++
> >>  drivers/mfd/Makefile           |   1 +
> >>  drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
> >>  include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
> >>  4 files changed, 374 insertions(+)
> >>  create mode 100644 drivers/mfd/stm32-fmc2.c
> >>  create mode 100644 include/linux/mfd/stm32-fmc2.h
> >>
> >> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> >> index 2b20329..5260582 100644
> >> --- a/drivers/mfd/Kconfig
> >> +++ b/drivers/mfd/Kconfig
> >> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
> >>  	  Also included is a Coulomb counter, a real-time clock (RTC), and
> >>  	  a 32.768 kHz clock gate.
> >>  
> >> +config MFD_STM32_FMC2
> >> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
> >> +	depends on MACH_STM32MP157 || COMPILE_TEST
> >> +	select MFD_CORE
> >> +	select REGMAP
> >> +	select REGMAP_MMIO
> >> +	help
> >> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
> >> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
> >> +	  provides core support for the STM32 FMC2 controllers, in order to use
> >> +	  the actual functionality of the device other drivers must be enabled.
> > 
> > Not sure how many times I have to say this before people stop
> > attempting to pass these kinds of relationships off as MFDs:
> > 
> > A memory device and its bus is not an MFD.  In a similar vain to the
> > thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
> > either.
> > 
> > Please find another way to associate your device with its bus.
> 
> This FMC2 is however an IP which can either operate external devices
> (like ethernet chip on this parallel bus) or external flashes (like NOR
> and NAND chips).

I'm sure that it *can*.  Although that's not its main purpose.  The
clue is in the nomenclature ("Flexible *Memory* Controller").  Nor is
it how the device is being used in this submission:

  "The FMC2 functional block makes the interface with: synchronous and
   asynchronous static memories (such as PSNOR, PSRAM or other
   memory-mapped peripherals) and NAND flash memories."

As I mentioned, this is just another memory device and its bus.

> Can you provide a suggestion how this should be handled, if not as MFD?
> It seems to me, that this is a Multi-Function Device .

Simply move it into the MTD or Memory subsystems and set up the
dependencies via Kconfig.

> If this discussion is a recurring topic, is there some documentation
> which explains how such devices should be handled ?

Not that I'm aware of.

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24 10:50       ` Lee Jones
@ 2020-04-24 11:06         ` Marek Vasut
  2020-04-24 11:47           ` Christophe Kerello
  0 siblings, 1 reply; 51+ messages in thread
From: Marek Vasut @ 2020-04-24 11:06 UTC (permalink / raw)
  To: Lee Jones
  Cc: Christophe Kerello, miquel.raynal, richard, vigneshr, robh+dt,
	mark.rutland, tony, linux-mtd, linux-kernel, linux-stm32,
	devicetree, Geert Uytterhoeven

On 4/24/20 12:50 PM, Lee Jones wrote:
> On Fri, 24 Apr 2020, Marek Vasut wrote:
> 
>> On 4/24/20 9:45 AM, Lee Jones wrote:
>>> On Wed, 15 Apr 2020, Christophe Kerello wrote:
>>>
>>>> The driver adds the support for the STMicroelectronics FMC2 controller
>>>> found on STM32MP SOCs.
>>>>
>>>> The FMC2 functional block makes the interface with: synchronous and
>>>> asynchronous static memories (such as PSNOR, PSRAM or other
>>>> memory-mapped peripherals) and NAND flash memories.
>>>>
>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>>>> ---
>>>> Changes in v2:
>>>>  - remove ops from stm32_fmc2 structure
>>>>  - add 2 APIs to manage FMC2 enable/disable
>>>>  - add 2 APIs to manage FMC2 NWAIT shared signal
>>>>
>>>>  drivers/mfd/Kconfig            |  12 +++
>>>>  drivers/mfd/Makefile           |   1 +
>>>>  drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
>>>>  include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
>>>>  4 files changed, 374 insertions(+)
>>>>  create mode 100644 drivers/mfd/stm32-fmc2.c
>>>>  create mode 100644 include/linux/mfd/stm32-fmc2.h
>>>>
>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>>> index 2b20329..5260582 100644
>>>> --- a/drivers/mfd/Kconfig
>>>> +++ b/drivers/mfd/Kconfig
>>>> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
>>>>  	  Also included is a Coulomb counter, a real-time clock (RTC), and
>>>>  	  a 32.768 kHz clock gate.
>>>>  
>>>> +config MFD_STM32_FMC2
>>>> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
>>>> +	depends on MACH_STM32MP157 || COMPILE_TEST
>>>> +	select MFD_CORE
>>>> +	select REGMAP
>>>> +	select REGMAP_MMIO
>>>> +	help
>>>> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
>>>> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
>>>> +	  provides core support for the STM32 FMC2 controllers, in order to use
>>>> +	  the actual functionality of the device other drivers must be enabled.
>>>
>>> Not sure how many times I have to say this before people stop
>>> attempting to pass these kinds of relationships off as MFDs:
>>>
>>> A memory device and its bus is not an MFD.  In a similar vain to the
>>> thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
>>> either.
>>>
>>> Please find another way to associate your device with its bus.
>>
>> This FMC2 is however an IP which can either operate external devices
>> (like ethernet chip on this parallel bus) or external flashes (like NOR
>> and NAND chips).
> 
> I'm sure that it *can*.  Although that's not its main purpose.

I use it to operate KSZ8851-16MLL ethernet chip, which has async bus
interface. Linux just didn't have support for that mode of operation
thus far and the FMC was used to operate NANDs and NORs only. This
series, or rather, the first three patches in this series, add support
for operating other bus devices, like this ethernet controller.

> The
> clue is in the nomenclature ("Flexible *Memory* Controller").  Nor is
> it how the device is being used in this submission:
> 
>   "The FMC2 functional block makes the interface with: synchronous and
>    asynchronous static memories (such as PSNOR, PSRAM or other
>    memory-mapped peripherals) and NAND flash memories."
> 
> As I mentioned, this is just another memory device and its bus.

I don't think it's _just_ a memory controller, it's more universal than
that, see above. Note that SRAM interface basically boils down to
anything which has external parallel bus, e.g. Davicom DM9000, that
KSZ8851-16MLL etc.

>> Can you provide a suggestion how this should be handled, if not as MFD?
>> It seems to me, that this is a Multi-Function Device .
> 
> Simply move it into the MTD or Memory subsystems and set up the
> dependencies via Kconfig.
> 
>> If this discussion is a recurring topic, is there some documentation
>> which explains how such devices should be handled ?
> 
> Not that I'm aware of.

I see.

-- 
Best regards,
Marek Vasut

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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24 11:06         ` Marek Vasut
@ 2020-04-24 11:47           ` Christophe Kerello
  2020-04-24 14:50             ` Lee Jones
  2020-04-24 15:14             ` Boris Brezillon
  0 siblings, 2 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-24 11:47 UTC (permalink / raw)
  To: Marek Vasut, Lee Jones
  Cc: miquel.raynal, richard, vigneshr, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree,
	Geert Uytterhoeven



On 4/24/20 1:06 PM, Marek Vasut wrote:
> On 4/24/20 12:50 PM, Lee Jones wrote:
>> On Fri, 24 Apr 2020, Marek Vasut wrote:
>>
>>> On 4/24/20 9:45 AM, Lee Jones wrote:
>>>> On Wed, 15 Apr 2020, Christophe Kerello wrote:
>>>>
>>>>> The driver adds the support for the STMicroelectronics FMC2 controller
>>>>> found on STM32MP SOCs.
>>>>>
>>>>> The FMC2 functional block makes the interface with: synchronous and
>>>>> asynchronous static memories (such as PSNOR, PSRAM or other
>>>>> memory-mapped peripherals) and NAND flash memories.
>>>>>
>>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>>>>> ---
>>>>> Changes in v2:
>>>>>   - remove ops from stm32_fmc2 structure
>>>>>   - add 2 APIs to manage FMC2 enable/disable
>>>>>   - add 2 APIs to manage FMC2 NWAIT shared signal
>>>>>
>>>>>   drivers/mfd/Kconfig            |  12 +++
>>>>>   drivers/mfd/Makefile           |   1 +
>>>>>   drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
>>>>>   include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
>>>>>   4 files changed, 374 insertions(+)
>>>>>   create mode 100644 drivers/mfd/stm32-fmc2.c
>>>>>   create mode 100644 include/linux/mfd/stm32-fmc2.h
>>>>>
>>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>>>> index 2b20329..5260582 100644
>>>>> --- a/drivers/mfd/Kconfig
>>>>> +++ b/drivers/mfd/Kconfig
>>>>> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
>>>>>   	  Also included is a Coulomb counter, a real-time clock (RTC), and
>>>>>   	  a 32.768 kHz clock gate.
>>>>>   
>>>>> +config MFD_STM32_FMC2
>>>>> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
>>>>> +	depends on MACH_STM32MP157 || COMPILE_TEST
>>>>> +	select MFD_CORE
>>>>> +	select REGMAP
>>>>> +	select REGMAP_MMIO
>>>>> +	help
>>>>> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
>>>>> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
>>>>> +	  provides core support for the STM32 FMC2 controllers, in order to use
>>>>> +	  the actual functionality of the device other drivers must be enabled.
>>>>
>>>> Not sure how many times I have to say this before people stop
>>>> attempting to pass these kinds of relationships off as MFDs:
>>>>
>>>> A memory device and its bus is not an MFD.  In a similar vain to the
>>>> thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
>>>> either.
>>>>
>>>> Please find another way to associate your device with its bus.
>>>
>>> This FMC2 is however an IP which can either operate external devices
>>> (like ethernet chip on this parallel bus) or external flashes (like NOR
>>> and NAND chips).
>>
>> I'm sure that it *can*.  Although that's not its main purpose.
> 
> I use it to operate KSZ8851-16MLL ethernet chip, which has async bus
> interface. Linux just didn't have support for that mode of operation
> thus far and the FMC was used to operate NANDs and NORs only. This
> series, or rather, the first three patches in this series, add support
> for operating other bus devices, like this ethernet controller.
> 
>> The
>> clue is in the nomenclature ("Flexible *Memory* Controller").  Nor is
>> it how the device is being used in this submission:
>>
>>    "The FMC2 functional block makes the interface with: synchronous and
>>     asynchronous static memories (such as PSNOR, PSRAM or other
>>     memory-mapped peripherals) and NAND flash memories."
>>
>> As I mentioned, this is just another memory device and its bus.
> 
> I don't think it's _just_ a memory controller, it's more universal than
> that, see above. Note that SRAM interface basically boils down to
> anything which has external parallel bus, e.g. Davicom DM9000, that
> KSZ8851-16MLL etc.
> 
>>> Can you provide a suggestion how this should be handled, if not as MFD?
>>> It seems to me, that this is a Multi-Function Device .
>>
>> Simply move it into the MTD or Memory subsystems and set up the
>> dependencies via Kconfig.
>>
>>> If this discussion is a recurring topic, is there some documentation
>>> which explains how such devices should be handled ?
>>
>> Not that I'm aware of.
> 
> I see.
>

Hi Lee, Marek,

I will move this source code in the FMC2 bus driver. I think that I 
should be able to manage the 2 controllers with 2 drivers (the FMC2 bus 
driver and the FMC2 raw NAND driver). I will have to modify some part of 
the proposed bindings, and some updates will have to be done in the FMC2 
bus driver. All these modifications will be part of V3.

Regards,
Christophe Kerello.

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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24 11:47           ` Christophe Kerello
@ 2020-04-24 14:50             ` Lee Jones
  2020-04-24 15:14             ` Boris Brezillon
  1 sibling, 0 replies; 51+ messages in thread
From: Lee Jones @ 2020-04-24 14:50 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: Marek Vasut, miquel.raynal, richard, vigneshr, robh+dt,
	mark.rutland, tony, linux-mtd, linux-kernel, linux-stm32,
	devicetree, Geert Uytterhoeven

On Fri, 24 Apr 2020, Christophe Kerello wrote:

> 
> 
> On 4/24/20 1:06 PM, Marek Vasut wrote:
> > On 4/24/20 12:50 PM, Lee Jones wrote:
> > > On Fri, 24 Apr 2020, Marek Vasut wrote:
> > > 
> > > > On 4/24/20 9:45 AM, Lee Jones wrote:
> > > > > On Wed, 15 Apr 2020, Christophe Kerello wrote:
> > > > > 
> > > > > > The driver adds the support for the STMicroelectronics FMC2 controller
> > > > > > found on STM32MP SOCs.
> > > > > > 
> > > > > > The FMC2 functional block makes the interface with: synchronous and
> > > > > > asynchronous static memories (such as PSNOR, PSRAM or other
> > > > > > memory-mapped peripherals) and NAND flash memories.
> > > > > > 
> > > > > > Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> > > > > > ---
> > > > > > Changes in v2:
> > > > > >   - remove ops from stm32_fmc2 structure
> > > > > >   - add 2 APIs to manage FMC2 enable/disable
> > > > > >   - add 2 APIs to manage FMC2 NWAIT shared signal
> > > > > > 
> > > > > >   drivers/mfd/Kconfig            |  12 +++
> > > > > >   drivers/mfd/Makefile           |   1 +
> > > > > >   drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
> > > > > >   include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
> > > > > >   4 files changed, 374 insertions(+)
> > > > > >   create mode 100644 drivers/mfd/stm32-fmc2.c
> > > > > >   create mode 100644 include/linux/mfd/stm32-fmc2.h
> > > > > > 
> > > > > > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> > > > > > index 2b20329..5260582 100644
> > > > > > --- a/drivers/mfd/Kconfig
> > > > > > +++ b/drivers/mfd/Kconfig
> > > > > > @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
> > > > > >   	  Also included is a Coulomb counter, a real-time clock (RTC), and
> > > > > >   	  a 32.768 kHz clock gate.
> > > > > > +config MFD_STM32_FMC2
> > > > > > +	tristate "Support for FMC2 controllers on STM32MP SoCs"
> > > > > > +	depends on MACH_STM32MP157 || COMPILE_TEST
> > > > > > +	select MFD_CORE
> > > > > > +	select REGMAP
> > > > > > +	select REGMAP_MMIO
> > > > > > +	help
> > > > > > +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
> > > > > > +	  Bus Interface controller and FMC2 NAND flash controller. This driver
> > > > > > +	  provides core support for the STM32 FMC2 controllers, in order to use
> > > > > > +	  the actual functionality of the device other drivers must be enabled.
> > > > > 
> > > > > Not sure how many times I have to say this before people stop
> > > > > attempting to pass these kinds of relationships off as MFDs:
> > > > > 
> > > > > A memory device and its bus is not an MFD.  In a similar vain to the
> > > > > thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
> > > > > either.
> > > > > 
> > > > > Please find another way to associate your device with its bus.
> > > > 
> > > > This FMC2 is however an IP which can either operate external devices
> > > > (like ethernet chip on this parallel bus) or external flashes (like NOR
> > > > and NAND chips).
> > > 
> > > I'm sure that it *can*.  Although that's not its main purpose.
> > 
> > I use it to operate KSZ8851-16MLL ethernet chip, which has async bus
> > interface. Linux just didn't have support for that mode of operation
> > thus far and the FMC was used to operate NANDs and NORs only. This
> > series, or rather, the first three patches in this series, add support
> > for operating other bus devices, like this ethernet controller.
> > 
> > > The
> > > clue is in the nomenclature ("Flexible *Memory* Controller").  Nor is
> > > it how the device is being used in this submission:
> > > 
> > >    "The FMC2 functional block makes the interface with: synchronous and
> > >     asynchronous static memories (such as PSNOR, PSRAM or other
> > >     memory-mapped peripherals) and NAND flash memories."
> > > 
> > > As I mentioned, this is just another memory device and its bus.
> > 
> > I don't think it's _just_ a memory controller, it's more universal than
> > that, see above. Note that SRAM interface basically boils down to
> > anything which has external parallel bus, e.g. Davicom DM9000, that
> > KSZ8851-16MLL etc.
> > 
> > > > Can you provide a suggestion how this should be handled, if not as MFD?
> > > > It seems to me, that this is a Multi-Function Device .
> > > 
> > > Simply move it into the MTD or Memory subsystems and set up the
> > > dependencies via Kconfig.
> > > 
> > > > If this discussion is a recurring topic, is there some documentation
> > > > which explains how such devices should be handled ?
> > > 
> > > Not that I'm aware of.
> > 
> > I see.
> > 
> 
> Hi Lee, Marek,
> 
> I will move this source code in the FMC2 bus driver. I think that I should
> be able to manage the 2 controllers with 2 drivers (the FMC2 bus driver and
> the FMC2 raw NAND driver). I will have to modify some part of the proposed
> bindings, and some updates will have to be done in the FMC2 bus driver. All
> these modifications will be part of V3.

That sounds like a very reasonable solution.

From a purist's PoV, the bindings should not change.  As they should
describe the hardware, rather than the implementation.

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24 11:47           ` Christophe Kerello
  2020-04-24 14:50             ` Lee Jones
@ 2020-04-24 15:14             ` Boris Brezillon
  2020-04-24 16:42               ` Christophe Kerello
  1 sibling, 1 reply; 51+ messages in thread
From: Boris Brezillon @ 2020-04-24 15:14 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: Marek Vasut, Lee Jones, mark.rutland, devicetree, vigneshr, tony,
	richard, linux-kernel, robh+dt, linux-mtd, miquel.raynal,
	Geert Uytterhoeven, linux-stm32

On Fri, 24 Apr 2020 13:47:34 +0200
Christophe Kerello <christophe.kerello@st.com> wrote:

> On 4/24/20 1:06 PM, Marek Vasut wrote:
> > On 4/24/20 12:50 PM, Lee Jones wrote:  
> >> On Fri, 24 Apr 2020, Marek Vasut wrote:
> >>  
> >>> On 4/24/20 9:45 AM, Lee Jones wrote:  
> >>>> On Wed, 15 Apr 2020, Christophe Kerello wrote:
> >>>>  
> >>>>> The driver adds the support for the STMicroelectronics FMC2 controller
> >>>>> found on STM32MP SOCs.
> >>>>>
> >>>>> The FMC2 functional block makes the interface with: synchronous and
> >>>>> asynchronous static memories (such as PSNOR, PSRAM or other
> >>>>> memory-mapped peripherals) and NAND flash memories.
> >>>>>
> >>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> >>>>> ---
> >>>>> Changes in v2:
> >>>>>   - remove ops from stm32_fmc2 structure
> >>>>>   - add 2 APIs to manage FMC2 enable/disable
> >>>>>   - add 2 APIs to manage FMC2 NWAIT shared signal
> >>>>>
> >>>>>   drivers/mfd/Kconfig            |  12 +++
> >>>>>   drivers/mfd/Makefile           |   1 +
> >>>>>   drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
> >>>>>   include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
> >>>>>   4 files changed, 374 insertions(+)
> >>>>>   create mode 100644 drivers/mfd/stm32-fmc2.c
> >>>>>   create mode 100644 include/linux/mfd/stm32-fmc2.h
> >>>>>
> >>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> >>>>> index 2b20329..5260582 100644
> >>>>> --- a/drivers/mfd/Kconfig
> >>>>> +++ b/drivers/mfd/Kconfig
> >>>>> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
> >>>>>   	  Also included is a Coulomb counter, a real-time clock (RTC), and
> >>>>>   	  a 32.768 kHz clock gate.
> >>>>>   
> >>>>> +config MFD_STM32_FMC2
> >>>>> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
> >>>>> +	depends on MACH_STM32MP157 || COMPILE_TEST
> >>>>> +	select MFD_CORE
> >>>>> +	select REGMAP
> >>>>> +	select REGMAP_MMIO
> >>>>> +	help
> >>>>> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
> >>>>> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
> >>>>> +	  provides core support for the STM32 FMC2 controllers, in order to use
> >>>>> +	  the actual functionality of the device other drivers must be enabled.  
> >>>>
> >>>> Not sure how many times I have to say this before people stop
> >>>> attempting to pass these kinds of relationships off as MFDs:
> >>>>
> >>>> A memory device and its bus is not an MFD.  In a similar vain to the
> >>>> thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
> >>>> either.
> >>>>
> >>>> Please find another way to associate your device with its bus.  
> >>>
> >>> This FMC2 is however an IP which can either operate external devices
> >>> (like ethernet chip on this parallel bus) or external flashes (like NOR
> >>> and NAND chips).  
> >>
> >> I'm sure that it *can*.  Although that's not its main purpose.  
> > 
> > I use it to operate KSZ8851-16MLL ethernet chip, which has async bus
> > interface. Linux just didn't have support for that mode of operation
> > thus far and the FMC was used to operate NANDs and NORs only. This
> > series, or rather, the first three patches in this series, add support
> > for operating other bus devices, like this ethernet controller.
> >   
> >> The
> >> clue is in the nomenclature ("Flexible *Memory* Controller").  Nor is
> >> it how the device is being used in this submission:
> >>
> >>    "The FMC2 functional block makes the interface with: synchronous and
> >>     asynchronous static memories (such as PSNOR, PSRAM or other
> >>     memory-mapped peripherals) and NAND flash memories."
> >>
> >> As I mentioned, this is just another memory device and its bus.  
> > 
> > I don't think it's _just_ a memory controller, it's more universal than
> > that, see above. Note that SRAM interface basically boils down to
> > anything which has external parallel bus, e.g. Davicom DM9000, that
> > KSZ8851-16MLL etc.
> >   
> >>> Can you provide a suggestion how this should be handled, if not as MFD?
> >>> It seems to me, that this is a Multi-Function Device .  
> >>
> >> Simply move it into the MTD or Memory subsystems and set up the
> >> dependencies via Kconfig.
> >>  
> >>> If this discussion is a recurring topic, is there some documentation
> >>> which explains how such devices should be handled ?  
> >>
> >> Not that I'm aware of.  
> > 
> > I see.
> >  
> 
> Hi Lee, Marek,
> 
> I will move this source code in the FMC2 bus driver. I think that I 
> should be able to manage the 2 controllers with 2 drivers (the FMC2 bus 
> driver and the FMC2 raw NAND driver).

FWIW, that's what I did for the Atmel EBI (External Bus Interface)
controller (see [1]).

[1]https://elixir.bootlin.com/linux/v5.6/source/drivers/memory/atmel-ebi.c

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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24 15:14             ` Boris Brezillon
@ 2020-04-24 16:42               ` Christophe Kerello
  2020-04-24 17:22                 ` Boris Brezillon
  0 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-24 16:42 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Marek Vasut, Lee Jones, mark.rutland, devicetree, vigneshr, tony,
	richard, linux-kernel, robh+dt, linux-mtd, miquel.raynal,
	Geert Uytterhoeven, linux-stm32



On 4/24/20 5:14 PM, Boris Brezillon wrote:
> On Fri, 24 Apr 2020 13:47:34 +0200
> Christophe Kerello <christophe.kerello@st.com> wrote:
> 
>> On 4/24/20 1:06 PM, Marek Vasut wrote:
>>> On 4/24/20 12:50 PM, Lee Jones wrote:
>>>> On Fri, 24 Apr 2020, Marek Vasut wrote:
>>>>   
>>>>> On 4/24/20 9:45 AM, Lee Jones wrote:
>>>>>> On Wed, 15 Apr 2020, Christophe Kerello wrote:
>>>>>>   
>>>>>>> The driver adds the support for the STMicroelectronics FMC2 controller
>>>>>>> found on STM32MP SOCs.
>>>>>>>
>>>>>>> The FMC2 functional block makes the interface with: synchronous and
>>>>>>> asynchronous static memories (such as PSNOR, PSRAM or other
>>>>>>> memory-mapped peripherals) and NAND flash memories.
>>>>>>>
>>>>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>>>>>>> ---
>>>>>>> Changes in v2:
>>>>>>>    - remove ops from stm32_fmc2 structure
>>>>>>>    - add 2 APIs to manage FMC2 enable/disable
>>>>>>>    - add 2 APIs to manage FMC2 NWAIT shared signal
>>>>>>>
>>>>>>>    drivers/mfd/Kconfig            |  12 +++
>>>>>>>    drivers/mfd/Makefile           |   1 +
>>>>>>>    drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
>>>>>>>    include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
>>>>>>>    4 files changed, 374 insertions(+)
>>>>>>>    create mode 100644 drivers/mfd/stm32-fmc2.c
>>>>>>>    create mode 100644 include/linux/mfd/stm32-fmc2.h
>>>>>>>
>>>>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>>>>>> index 2b20329..5260582 100644
>>>>>>> --- a/drivers/mfd/Kconfig
>>>>>>> +++ b/drivers/mfd/Kconfig
>>>>>>> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
>>>>>>>    	  Also included is a Coulomb counter, a real-time clock (RTC), and
>>>>>>>    	  a 32.768 kHz clock gate.
>>>>>>>    
>>>>>>> +config MFD_STM32_FMC2
>>>>>>> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
>>>>>>> +	depends on MACH_STM32MP157 || COMPILE_TEST
>>>>>>> +	select MFD_CORE
>>>>>>> +	select REGMAP
>>>>>>> +	select REGMAP_MMIO
>>>>>>> +	help
>>>>>>> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
>>>>>>> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
>>>>>>> +	  provides core support for the STM32 FMC2 controllers, in order to use
>>>>>>> +	  the actual functionality of the device other drivers must be enabled.
>>>>>>
>>>>>> Not sure how many times I have to say this before people stop
>>>>>> attempting to pass these kinds of relationships off as MFDs:
>>>>>>
>>>>>> A memory device and its bus is not an MFD.  In a similar vain to the
>>>>>> thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
>>>>>> either.
>>>>>>
>>>>>> Please find another way to associate your device with its bus.
>>>>>
>>>>> This FMC2 is however an IP which can either operate external devices
>>>>> (like ethernet chip on this parallel bus) or external flashes (like NOR
>>>>> and NAND chips).
>>>>
>>>> I'm sure that it *can*.  Although that's not its main purpose.
>>>
>>> I use it to operate KSZ8851-16MLL ethernet chip, which has async bus
>>> interface. Linux just didn't have support for that mode of operation
>>> thus far and the FMC was used to operate NANDs and NORs only. This
>>> series, or rather, the first three patches in this series, add support
>>> for operating other bus devices, like this ethernet controller.
>>>    
>>>> The
>>>> clue is in the nomenclature ("Flexible *Memory* Controller").  Nor is
>>>> it how the device is being used in this submission:
>>>>
>>>>     "The FMC2 functional block makes the interface with: synchronous and
>>>>      asynchronous static memories (such as PSNOR, PSRAM or other
>>>>      memory-mapped peripherals) and NAND flash memories."
>>>>
>>>> As I mentioned, this is just another memory device and its bus.
>>>
>>> I don't think it's _just_ a memory controller, it's more universal than
>>> that, see above. Note that SRAM interface basically boils down to
>>> anything which has external parallel bus, e.g. Davicom DM9000, that
>>> KSZ8851-16MLL etc.
>>>    
>>>>> Can you provide a suggestion how this should be handled, if not as MFD?
>>>>> It seems to me, that this is a Multi-Function Device .
>>>>
>>>> Simply move it into the MTD or Memory subsystems and set up the
>>>> dependencies via Kconfig.
>>>>   
>>>>> If this discussion is a recurring topic, is there some documentation
>>>>> which explains how such devices should be handled ?
>>>>
>>>> Not that I'm aware of.
>>>
>>> I see.
>>>   
>>
>> Hi Lee, Marek,
>>
>> I will move this source code in the FMC2 bus driver. I think that I
>> should be able to manage the 2 controllers with 2 drivers (the FMC2 bus
>> driver and the FMC2 raw NAND driver).
> 
> FWIW, that's what I did for the Atmel EBI (External Bus Interface)
> controller (see [1]).
> 
> [1]https://elixir.bootlin.com/linux/v5.6/source/drivers/memory/atmel-ebi.c
> 

Hi Boris,

Thanks for your help.

I was thinking about the bindings and I think that the bindings below 
are close to what has been done for Atmel EBI/Raw NAND bindings (in 
terms of structure of bindings if I have well understood).
I think that these proposed bindings are very close to the first 
proposed version (V1/V2).

     fmc@58002000 {
       #address-cells = <2>;
       #size-cells = <1>;
       compatible = "st,stm32mp1-fmc2";
       reg = <0x58002000 0x1000>;
       clocks = <&rcc FMC_K>;
       resets = <&rcc FMC_R>;

       ranges = <0 0 0x60000000 0x4000000>, /* EBI bank 1 */
                <1 0 0x64000000 0x4000000>, /* EBI bank 2 */
                <2 0 0x68000000 0x4000000>, /* EBI bank 3 */
                <3 0 0x6c000000 0x4000000>, /* EBI bank 4 */
                <4 0 0x80000000 0x4000000>, /* NAND common memory space */
                <5 0 0x88000000 0x4000000>; /* NAND attribute memory 
space */
	
       psram@0 {
         compatible = "mtd-ram";
         reg = <0 0x00000000 0x100000>;
         bank-width = <2>;

         st,fmc2_ebi_cs_transaction_type = <1>;
         st,fmc2_ebi_cs_address_setup = <60>;
         st,fmc2_ebi_cs_data_setup = <30>;
         st,fmc2_ebi_cs_bus_turnaround = <5>;
       };

       nand-controller@4 {
         #address-cells = <1>;
         #size-cells = <0>;
         compatible = "st,stm32mp15-fmc2";
         reg = <4 0x00000000 0x1000>,
               <5 0x00010000 0x1000>,
               <5 0x00020000 0x1000>,
               <4 0x01000000 0x1000>,
               <5 0x01010000 0x1000>,
               <5 0x01020000 0x1000>;
         interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
         dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
                <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
                <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
         dma-names = "tx", "rx", "ecc";

         nand@0 {
           reg = <0>;
           nand-on-flash-bbt;
           #address-cells = <1>;
           #size-cells = <1>;
         };
       };
     };

Regards,
Christophe Kerello.


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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24 16:42               ` Christophe Kerello
@ 2020-04-24 17:22                 ` Boris Brezillon
  2020-04-24 17:34                   ` Christophe Kerello
  0 siblings, 1 reply; 51+ messages in thread
From: Boris Brezillon @ 2020-04-24 17:22 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: Marek Vasut, Lee Jones, mark.rutland, devicetree, vigneshr, tony,
	richard, linux-kernel, robh+dt, linux-mtd, miquel.raynal,
	Geert Uytterhoeven, linux-stm32

On Fri, 24 Apr 2020 18:42:59 +0200
Christophe Kerello <christophe.kerello@st.com> wrote:

> On 4/24/20 5:14 PM, Boris Brezillon wrote:
> > On Fri, 24 Apr 2020 13:47:34 +0200
> > Christophe Kerello <christophe.kerello@st.com> wrote:
> >   
> >> On 4/24/20 1:06 PM, Marek Vasut wrote:  
> >>> On 4/24/20 12:50 PM, Lee Jones wrote:  
> >>>> On Fri, 24 Apr 2020, Marek Vasut wrote:
> >>>>     
> >>>>> On 4/24/20 9:45 AM, Lee Jones wrote:  
> >>>>>> On Wed, 15 Apr 2020, Christophe Kerello wrote:
> >>>>>>     
> >>>>>>> The driver adds the support for the STMicroelectronics FMC2 controller
> >>>>>>> found on STM32MP SOCs.
> >>>>>>>
> >>>>>>> The FMC2 functional block makes the interface with: synchronous and
> >>>>>>> asynchronous static memories (such as PSNOR, PSRAM or other
> >>>>>>> memory-mapped peripherals) and NAND flash memories.
> >>>>>>>
> >>>>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> >>>>>>> ---
> >>>>>>> Changes in v2:
> >>>>>>>    - remove ops from stm32_fmc2 structure
> >>>>>>>    - add 2 APIs to manage FMC2 enable/disable
> >>>>>>>    - add 2 APIs to manage FMC2 NWAIT shared signal
> >>>>>>>
> >>>>>>>    drivers/mfd/Kconfig            |  12 +++
> >>>>>>>    drivers/mfd/Makefile           |   1 +
> >>>>>>>    drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
> >>>>>>>    include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
> >>>>>>>    4 files changed, 374 insertions(+)
> >>>>>>>    create mode 100644 drivers/mfd/stm32-fmc2.c
> >>>>>>>    create mode 100644 include/linux/mfd/stm32-fmc2.h
> >>>>>>>
> >>>>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> >>>>>>> index 2b20329..5260582 100644
> >>>>>>> --- a/drivers/mfd/Kconfig
> >>>>>>> +++ b/drivers/mfd/Kconfig
> >>>>>>> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
> >>>>>>>    	  Also included is a Coulomb counter, a real-time clock (RTC), and
> >>>>>>>    	  a 32.768 kHz clock gate.
> >>>>>>>    
> >>>>>>> +config MFD_STM32_FMC2
> >>>>>>> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
> >>>>>>> +	depends on MACH_STM32MP157 || COMPILE_TEST
> >>>>>>> +	select MFD_CORE
> >>>>>>> +	select REGMAP
> >>>>>>> +	select REGMAP_MMIO
> >>>>>>> +	help
> >>>>>>> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
> >>>>>>> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
> >>>>>>> +	  provides core support for the STM32 FMC2 controllers, in order to use
> >>>>>>> +	  the actual functionality of the device other drivers must be enabled.  
> >>>>>>
> >>>>>> Not sure how many times I have to say this before people stop
> >>>>>> attempting to pass these kinds of relationships off as MFDs:
> >>>>>>
> >>>>>> A memory device and its bus is not an MFD.  In a similar vain to the
> >>>>>> thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
> >>>>>> either.
> >>>>>>
> >>>>>> Please find another way to associate your device with its bus.  
> >>>>>
> >>>>> This FMC2 is however an IP which can either operate external devices
> >>>>> (like ethernet chip on this parallel bus) or external flashes (like NOR
> >>>>> and NAND chips).  
> >>>>
> >>>> I'm sure that it *can*.  Although that's not its main purpose.  
> >>>
> >>> I use it to operate KSZ8851-16MLL ethernet chip, which has async bus
> >>> interface. Linux just didn't have support for that mode of operation
> >>> thus far and the FMC was used to operate NANDs and NORs only. This
> >>> series, or rather, the first three patches in this series, add support
> >>> for operating other bus devices, like this ethernet controller.
> >>>      
> >>>> The
> >>>> clue is in the nomenclature ("Flexible *Memory* Controller").  Nor is
> >>>> it how the device is being used in this submission:
> >>>>
> >>>>     "The FMC2 functional block makes the interface with: synchronous and
> >>>>      asynchronous static memories (such as PSNOR, PSRAM or other
> >>>>      memory-mapped peripherals) and NAND flash memories."
> >>>>
> >>>> As I mentioned, this is just another memory device and its bus.  
> >>>
> >>> I don't think it's _just_ a memory controller, it's more universal than
> >>> that, see above. Note that SRAM interface basically boils down to
> >>> anything which has external parallel bus, e.g. Davicom DM9000, that
> >>> KSZ8851-16MLL etc.
> >>>      
> >>>>> Can you provide a suggestion how this should be handled, if not as MFD?
> >>>>> It seems to me, that this is a Multi-Function Device .  
> >>>>
> >>>> Simply move it into the MTD or Memory subsystems and set up the
> >>>> dependencies via Kconfig.
> >>>>     
> >>>>> If this discussion is a recurring topic, is there some documentation
> >>>>> which explains how such devices should be handled ?  
> >>>>
> >>>> Not that I'm aware of.  
> >>>
> >>> I see.
> >>>     
> >>
> >> Hi Lee, Marek,
> >>
> >> I will move this source code in the FMC2 bus driver. I think that I
> >> should be able to manage the 2 controllers with 2 drivers (the FMC2 bus
> >> driver and the FMC2 raw NAND driver).  
> > 
> > FWIW, that's what I did for the Atmel EBI (External Bus Interface)
> > controller (see [1]).
> > 
> > [1]https://elixir.bootlin.com/linux/v5.6/source/drivers/memory/atmel-ebi.c
> >   
> 
> Hi Boris,
> 
> Thanks for your help.
> 
> I was thinking about the bindings and I think that the bindings below 
> are close to what has been done for Atmel EBI/Raw NAND bindings (in 
> terms of structure of bindings if I have well understood).
> I think that these proposed bindings are very close to the first 
> proposed version (V1/V2).

Yep, makes sense to me, just one minor comment.

> 
>      fmc@58002000 {
>        #address-cells = <2>;
>        #size-cells = <1>;
>        compatible = "st,stm32mp1-fmc2";
>        reg = <0x58002000 0x1000>;
>        clocks = <&rcc FMC_K>;
>        resets = <&rcc FMC_R>;
> 
>        ranges = <0 0 0x60000000 0x4000000>, /* EBI bank 1 */
>                 <1 0 0x64000000 0x4000000>, /* EBI bank 2 */
>                 <2 0 0x68000000 0x4000000>, /* EBI bank 3 */
>                 <3 0 0x6c000000 0x4000000>, /* EBI bank 4 */
>                 <4 0 0x80000000 0x4000000>, /* NAND common memory space */
>                 <5 0 0x88000000 0x4000000>; /* NAND attribute memory 
> space */
> 	
>        psram@0 {
>          compatible = "mtd-ram";
>          reg = <0 0x00000000 0x100000>;
>          bank-width = <2>;
> 
>          st,fmc2_ebi_cs_transaction_type = <1>;
>          st,fmc2_ebi_cs_address_setup = <60>;
>          st,fmc2_ebi_cs_data_setup = <30>;
>          st,fmc2_ebi_cs_bus_turnaround = <5>;

Not sure what the unit is for those timings, but I'd recommend using a
time unit (nanoseconds?) and not clk-cycles here.

>        };
> 
>        nand-controller@4 {
>          #address-cells = <1>;
>          #size-cells = <0>;
>          compatible = "st,stm32mp15-fmc2";
>          reg = <4 0x00000000 0x1000>,
>                <5 0x00010000 0x1000>,
>                <5 0x00020000 0x1000>,
>                <4 0x01000000 0x1000>,
>                <5 0x01010000 0x1000>,
>                <5 0x01020000 0x1000>;
>          interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
>          dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
>                 <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
>                 <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
>          dma-names = "tx", "rx", "ecc";
> 
>          nand@0 {
>            reg = <0>;
>            nand-on-flash-bbt;
>            #address-cells = <1>;
>            #size-cells = <1>;
>          };
>        };
>      };
> 
> Regards,
> Christophe Kerello.
> 


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

* Re: [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver
  2020-04-24 17:22                 ` Boris Brezillon
@ 2020-04-24 17:34                   ` Christophe Kerello
  0 siblings, 0 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-24 17:34 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Marek Vasut, Lee Jones, mark.rutland, devicetree, vigneshr, tony,
	richard, linux-kernel, robh+dt, linux-mtd, miquel.raynal,
	Geert Uytterhoeven, linux-stm32



On 4/24/20 7:22 PM, Boris Brezillon wrote:
> On Fri, 24 Apr 2020 18:42:59 +0200
> Christophe Kerello <christophe.kerello@st.com> wrote:
> 
>> On 4/24/20 5:14 PM, Boris Brezillon wrote:
>>> On Fri, 24 Apr 2020 13:47:34 +0200
>>> Christophe Kerello <christophe.kerello@st.com> wrote:
>>>    
>>>> On 4/24/20 1:06 PM, Marek Vasut wrote:
>>>>> On 4/24/20 12:50 PM, Lee Jones wrote:
>>>>>> On Fri, 24 Apr 2020, Marek Vasut wrote:
>>>>>>      
>>>>>>> On 4/24/20 9:45 AM, Lee Jones wrote:
>>>>>>>> On Wed, 15 Apr 2020, Christophe Kerello wrote:
>>>>>>>>      
>>>>>>>>> The driver adds the support for the STMicroelectronics FMC2 controller
>>>>>>>>> found on STM32MP SOCs.
>>>>>>>>>
>>>>>>>>> The FMC2 functional block makes the interface with: synchronous and
>>>>>>>>> asynchronous static memories (such as PSNOR, PSRAM or other
>>>>>>>>> memory-mapped peripherals) and NAND flash memories.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>>>>>>>>> ---
>>>>>>>>> Changes in v2:
>>>>>>>>>     - remove ops from stm32_fmc2 structure
>>>>>>>>>     - add 2 APIs to manage FMC2 enable/disable
>>>>>>>>>     - add 2 APIs to manage FMC2 NWAIT shared signal
>>>>>>>>>
>>>>>>>>>     drivers/mfd/Kconfig            |  12 +++
>>>>>>>>>     drivers/mfd/Makefile           |   1 +
>>>>>>>>>     drivers/mfd/stm32-fmc2.c       | 136 +++++++++++++++++++++++++
>>>>>>>>>     include/linux/mfd/stm32-fmc2.h | 225 +++++++++++++++++++++++++++++++++++++++++
>>>>>>>>>     4 files changed, 374 insertions(+)
>>>>>>>>>     create mode 100644 drivers/mfd/stm32-fmc2.c
>>>>>>>>>     create mode 100644 include/linux/mfd/stm32-fmc2.h
>>>>>>>>>
>>>>>>>>> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
>>>>>>>>> index 2b20329..5260582 100644
>>>>>>>>> --- a/drivers/mfd/Kconfig
>>>>>>>>> +++ b/drivers/mfd/Kconfig
>>>>>>>>> @@ -1922,6 +1922,18 @@ config MFD_ROHM_BD71828
>>>>>>>>>     	  Also included is a Coulomb counter, a real-time clock (RTC), and
>>>>>>>>>     	  a 32.768 kHz clock gate.
>>>>>>>>>     
>>>>>>>>> +config MFD_STM32_FMC2
>>>>>>>>> +	tristate "Support for FMC2 controllers on STM32MP SoCs"
>>>>>>>>> +	depends on MACH_STM32MP157 || COMPILE_TEST
>>>>>>>>> +	select MFD_CORE
>>>>>>>>> +	select REGMAP
>>>>>>>>> +	select REGMAP_MMIO
>>>>>>>>> +	help
>>>>>>>>> +	  Select this option to enable STM32 FMC2 driver used for FMC2 External
>>>>>>>>> +	  Bus Interface controller and FMC2 NAND flash controller. This driver
>>>>>>>>> +	  provides core support for the STM32 FMC2 controllers, in order to use
>>>>>>>>> +	  the actual functionality of the device other drivers must be enabled.
>>>>>>>>
>>>>>>>> Not sure how many times I have to say this before people stop
>>>>>>>> attempting to pass these kinds of relationships off as MFDs:
>>>>>>>>
>>>>>>>> A memory device and its bus is not an MFD.  In a similar vain to the
>>>>>>>> thousands of USB, I2C, SPI, PCI and the like devices that aren't MFDs
>>>>>>>> either.
>>>>>>>>
>>>>>>>> Please find another way to associate your device with its bus.
>>>>>>>
>>>>>>> This FMC2 is however an IP which can either operate external devices
>>>>>>> (like ethernet chip on this parallel bus) or external flashes (like NOR
>>>>>>> and NAND chips).
>>>>>>
>>>>>> I'm sure that it *can*.  Although that's not its main purpose.
>>>>>
>>>>> I use it to operate KSZ8851-16MLL ethernet chip, which has async bus
>>>>> interface. Linux just didn't have support for that mode of operation
>>>>> thus far and the FMC was used to operate NANDs and NORs only. This
>>>>> series, or rather, the first three patches in this series, add support
>>>>> for operating other bus devices, like this ethernet controller.
>>>>>       
>>>>>> The
>>>>>> clue is in the nomenclature ("Flexible *Memory* Controller").  Nor is
>>>>>> it how the device is being used in this submission:
>>>>>>
>>>>>>      "The FMC2 functional block makes the interface with: synchronous and
>>>>>>       asynchronous static memories (such as PSNOR, PSRAM or other
>>>>>>       memory-mapped peripherals) and NAND flash memories."
>>>>>>
>>>>>> As I mentioned, this is just another memory device and its bus.
>>>>>
>>>>> I don't think it's _just_ a memory controller, it's more universal than
>>>>> that, see above. Note that SRAM interface basically boils down to
>>>>> anything which has external parallel bus, e.g. Davicom DM9000, that
>>>>> KSZ8851-16MLL etc.
>>>>>       
>>>>>>> Can you provide a suggestion how this should be handled, if not as MFD?
>>>>>>> It seems to me, that this is a Multi-Function Device .
>>>>>>
>>>>>> Simply move it into the MTD or Memory subsystems and set up the
>>>>>> dependencies via Kconfig.
>>>>>>      
>>>>>>> If this discussion is a recurring topic, is there some documentation
>>>>>>> which explains how such devices should be handled ?
>>>>>>
>>>>>> Not that I'm aware of.
>>>>>
>>>>> I see.
>>>>>      
>>>>
>>>> Hi Lee, Marek,
>>>>
>>>> I will move this source code in the FMC2 bus driver. I think that I
>>>> should be able to manage the 2 controllers with 2 drivers (the FMC2 bus
>>>> driver and the FMC2 raw NAND driver).
>>>
>>> FWIW, that's what I did for the Atmel EBI (External Bus Interface)
>>> controller (see [1]).
>>>
>>> [1]https://elixir.bootlin.com/linux/v5.6/source/drivers/memory/atmel-ebi.c
>>>    
>>
>> Hi Boris,
>>
>> Thanks for your help.
>>
>> I was thinking about the bindings and I think that the bindings below
>> are close to what has been done for Atmel EBI/Raw NAND bindings (in
>> terms of structure of bindings if I have well understood).
>> I think that these proposed bindings are very close to the first
>> proposed version (V1/V2).
> 
> Yep, makes sense to me, just one minor comment.
> 
>>
>>       fmc@58002000 {
>>         #address-cells = <2>;
>>         #size-cells = <1>;
>>         compatible = "st,stm32mp1-fmc2";
>>         reg = <0x58002000 0x1000>;
>>         clocks = <&rcc FMC_K>;
>>         resets = <&rcc FMC_R>;
>>
>>         ranges = <0 0 0x60000000 0x4000000>, /* EBI bank 1 */
>>                  <1 0 0x64000000 0x4000000>, /* EBI bank 2 */
>>                  <2 0 0x68000000 0x4000000>, /* EBI bank 3 */
>>                  <3 0 0x6c000000 0x4000000>, /* EBI bank 4 */
>>                  <4 0 0x80000000 0x4000000>, /* NAND common memory space */
>>                  <5 0 0x88000000 0x4000000>; /* NAND attribute memory
>> space */
>> 	
>>         psram@0 {
>>           compatible = "mtd-ram";
>>           reg = <0 0x00000000 0x100000>;
>>           bank-width = <2>;
>>
>>           st,fmc2_ebi_cs_transaction_type = <1>;
>>           st,fmc2_ebi_cs_address_setup = <60>;
>>           st,fmc2_ebi_cs_data_setup = <30>;
>>           st,fmc2_ebi_cs_bus_turnaround = <5>;
> 
> Not sure what the unit is for those timings, but I'd recommend using a
> time unit (nanoseconds?) and not clk-cycles here.
>

Hi Boris,

Yes, it is the case in the documentation. The time unit is nanoseconds:
       st,fmc2_ebi_cs_address_setup:
         description: This property defines the duration of the address
                      setup phase in ns used for asynchronous read/write 
transactions.
         $ref: /schemas/types.yaml#/definitions/uint32

Thanks to have review this proposal.

Regards,
Christophe Kerello.

>>         };
>>
>>         nand-controller@4 {
>>           #address-cells = <1>;
>>           #size-cells = <0>;
>>           compatible = "st,stm32mp15-fmc2";
>>           reg = <4 0x00000000 0x1000>,
>>                 <5 0x00010000 0x1000>,
>>                 <5 0x00020000 0x1000>,
>>                 <4 0x01000000 0x1000>,
>>                 <5 0x01010000 0x1000>,
>>                 <5 0x01020000 0x1000>;
>>           interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
>>           dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
>>                  <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
>>                  <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
>>           dma-names = "tx", "rx", "ecc";
>>
>>           nand@0 {
>>             reg = <0>;
>>             nand-on-flash-bbt;
>>             #address-cells = <1>;
>>             #size-cells = <1>;
>>           };
>>         };
>>       };
>>
>> Regards,
>> Christophe Kerello.
>>
> 

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

* Re: [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-15 15:57 ` [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time Christophe Kerello
@ 2020-04-27 17:47   ` Miquel Raynal
  2020-04-27 17:59     ` Marek Vasut
  0 siblings, 1 reply; 51+ messages in thread
From: Miquel Raynal @ 2020-04-27 17:47 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Christophe,

Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
2020 17:57:28 +0200:

> This patch defers its probe when the expected reset control is not
> yet ready. This patch also handles properly all errors cases at probe
> time.
> 
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index b6d45cd..0a96797 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -1967,7 +1967,11 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>  	}
>  
>  	rstc = devm_reset_control_get(dev, NULL);
> -	if (!IS_ERR(rstc)) {
> +	if (IS_ERR(rstc)) {
> +		ret = PTR_ERR(rstc);
> +		if (ret == -EPROBE_DEFER)
> +			goto err_clk_disable;
> +	} else {
>  		reset_control_assert(rstc);
>  		reset_control_deassert(rstc);
>  	}
> @@ -1975,7 +1979,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>  	/* DMA setup */
>  	ret = stm32_fmc2_dma_setup(fmc2);
>  	if (ret)
> -		return ret;
> +		goto err_dma_setup;
>  
>  	/* FMC2 init routine */
>  	stm32_fmc2_init(fmc2);
> @@ -1997,7 +2001,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>  	/* Scan to find existence of the device */
>  	ret = nand_scan(chip, nand->ncs);
>  	if (ret)
> -		goto err_scan;
> +		goto err_dma_setup;
>  
>  	ret = mtd_device_register(mtd, NULL, 0);
>  	if (ret)
> @@ -2010,7 +2014,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>  err_device_register:
>  	nand_cleanup(chip);
>  
> -err_scan:
> +err_dma_setup:
>  	if (fmc2->dma_ecc_ch)
>  		dma_release_channel(fmc2->dma_ecc_ch);
>  	if (fmc2->dma_tx_ch)
> @@ -2021,6 +2025,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>  	sg_free_table(&fmc2->dma_data_sg);
>  	sg_free_table(&fmc2->dma_ecc_sg);
>  
> +err_clk_disable:
>  	clk_disable_unprepare(fmc2->clk);
>  
>  	return ret;

I didn't spot it during my earlier reviews but I really prefer using
labels explaining what you do than having the same name of the function
which failed. This way you don't have to rework the error path when
you handle an additional error.

So, would you mind doing this in two steps:

1/
Replace

    err_scan:

with, eg.

    release_dma_objs:

2/
Add a

    goto release_dma_objs;

in *_dma_setup() error path, and define and use a

    release_clk

label like you already do.


Thanks,
Miquèl

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

* Re: [PATCH v2 05/12] mtd: rawnand: stm32_fmc2: remove useless inline comments
  2020-04-15 15:57 ` [PATCH v2 05/12] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
@ 2020-04-27 17:48   ` Miquel Raynal
  0 siblings, 0 replies; 51+ messages in thread
From: Miquel Raynal @ 2020-04-27 17:48 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Christophe,

Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
2020 17:57:29 +0200:

> Remove inline comments that are useless since function label are
> self explanatory.
> 
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>


Thanks,
Miquèl

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

* Re: [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-27 17:47   ` Miquel Raynal
@ 2020-04-27 17:59     ` Marek Vasut
  2020-04-27 18:08       ` Miquel Raynal
  0 siblings, 1 reply; 51+ messages in thread
From: Marek Vasut @ 2020-04-27 17:59 UTC (permalink / raw)
  To: Miquel Raynal, Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree

On 4/27/20 7:47 PM, Miquel Raynal wrote:
> Hi Christophe,
> 
> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
> 2020 17:57:28 +0200:
> 
>> This patch defers its probe when the expected reset control is not
>> yet ready. This patch also handles properly all errors cases at probe
>> time.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 13 +++++++++----
>>  1 file changed, 9 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index b6d45cd..0a96797 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -1967,7 +1967,11 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>  	}
>>  
>>  	rstc = devm_reset_control_get(dev, NULL);
>> -	if (!IS_ERR(rstc)) {
>> +	if (IS_ERR(rstc)) {
>> +		ret = PTR_ERR(rstc);
>> +		if (ret == -EPROBE_DEFER)
>> +			goto err_clk_disable;
>> +	} else {
>>  		reset_control_assert(rstc);
>>  		reset_control_deassert(rstc);
>>  	}
>> @@ -1975,7 +1979,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>  	/* DMA setup */
>>  	ret = stm32_fmc2_dma_setup(fmc2);
>>  	if (ret)
>> -		return ret;
>> +		goto err_dma_setup;
>>  
>>  	/* FMC2 init routine */
>>  	stm32_fmc2_init(fmc2);
>> @@ -1997,7 +2001,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>  	/* Scan to find existence of the device */
>>  	ret = nand_scan(chip, nand->ncs);
>>  	if (ret)
>> -		goto err_scan;
>> +		goto err_dma_setup;
>>  
>>  	ret = mtd_device_register(mtd, NULL, 0);
>>  	if (ret)
>> @@ -2010,7 +2014,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>  err_device_register:
>>  	nand_cleanup(chip);
>>  
>> -err_scan:
>> +err_dma_setup:
>>  	if (fmc2->dma_ecc_ch)
>>  		dma_release_channel(fmc2->dma_ecc_ch);
>>  	if (fmc2->dma_tx_ch)
>> @@ -2021,6 +2025,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>  	sg_free_table(&fmc2->dma_data_sg);
>>  	sg_free_table(&fmc2->dma_ecc_sg);
>>  
>> +err_clk_disable:
>>  	clk_disable_unprepare(fmc2->clk);
>>  
>>  	return ret;
> 
> I didn't spot it during my earlier reviews but I really prefer using
> labels explaining what you do than having the same name of the function
> which failed. This way you don't have to rework the error path when
> you handle an additional error.
> 
> So, would you mind doing this in two steps:
> 
> 1/
> Replace
> 
>     err_scan:
> 
> with, eg.
> 
>     release_dma_objs:

The ^err_ prefix in failpath labels is useful, since it's easily
possible to match on it with regexes ; not so much on arbitrary label name.

btw would it make sense to split the first three patches of this series
into a separate series ? This rawnand part seems more like an unrelated
cleanup.

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

* Re: [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-27 17:59     ` Marek Vasut
@ 2020-04-27 18:08       ` Miquel Raynal
  2020-04-27 19:46         ` Marek Vasut
  0 siblings, 1 reply; 51+ messages in thread
From: Miquel Raynal @ 2020-04-27 18:08 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Christophe Kerello, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, linux-mtd, linux-kernel, linux-stm32,
	devicetree

Hi Marek,

Marek Vasut <marex@denx.de> wrote on Mon, 27 Apr 2020 19:59:34 +0200:

> On 4/27/20 7:47 PM, Miquel Raynal wrote:
> > Hi Christophe,
> > 
> > Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
> > 2020 17:57:28 +0200:
> >   
> >> This patch defers its probe when the expected reset control is not
> >> yet ready. This patch also handles properly all errors cases at probe
> >> time.
> >>
> >> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> >> ---
> >>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 13 +++++++++----
> >>  1 file changed, 9 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >> index b6d45cd..0a96797 100644
> >> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >> @@ -1967,7 +1967,11 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
> >>  	}
> >>  
> >>  	rstc = devm_reset_control_get(dev, NULL);
> >> -	if (!IS_ERR(rstc)) {
> >> +	if (IS_ERR(rstc)) {
> >> +		ret = PTR_ERR(rstc);
> >> +		if (ret == -EPROBE_DEFER)
> >> +			goto err_clk_disable;
> >> +	} else {
> >>  		reset_control_assert(rstc);
> >>  		reset_control_deassert(rstc);
> >>  	}
> >> @@ -1975,7 +1979,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
> >>  	/* DMA setup */
> >>  	ret = stm32_fmc2_dma_setup(fmc2);
> >>  	if (ret)
> >> -		return ret;
> >> +		goto err_dma_setup;
> >>  
> >>  	/* FMC2 init routine */
> >>  	stm32_fmc2_init(fmc2);
> >> @@ -1997,7 +2001,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
> >>  	/* Scan to find existence of the device */
> >>  	ret = nand_scan(chip, nand->ncs);
> >>  	if (ret)
> >> -		goto err_scan;
> >> +		goto err_dma_setup;
> >>  
> >>  	ret = mtd_device_register(mtd, NULL, 0);
> >>  	if (ret)
> >> @@ -2010,7 +2014,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
> >>  err_device_register:
> >>  	nand_cleanup(chip);
> >>  
> >> -err_scan:
> >> +err_dma_setup:
> >>  	if (fmc2->dma_ecc_ch)
> >>  		dma_release_channel(fmc2->dma_ecc_ch);
> >>  	if (fmc2->dma_tx_ch)
> >> @@ -2021,6 +2025,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
> >>  	sg_free_table(&fmc2->dma_data_sg);
> >>  	sg_free_table(&fmc2->dma_ecc_sg);
> >>  
> >> +err_clk_disable:
> >>  	clk_disable_unprepare(fmc2->clk);
> >>  
> >>  	return ret;  
> > 
> > I didn't spot it during my earlier reviews but I really prefer using
> > labels explaining what you do than having the same name of the function
> > which failed. This way you don't have to rework the error path when
> > you handle an additional error.
> > 
> > So, would you mind doing this in two steps:
> > 
> > 1/
> > Replace
> > 
> >     err_scan:
> > 
> > with, eg.
> > 
> >     release_dma_objs:  
> 
> The ^err_ prefix in failpath labels is useful, since it's easily
> possible to match on it with regexes ; not so much on arbitrary label name.

I guess so, but is it actually useful to catch labels in a regex? (real
question)

Any way I suppose catching ":\n" is already a good approximation to
find labels?

> 
> btw would it make sense to split the first three patches of this series
> into a separate series ? This rawnand part seems more like an unrelated
> cleanup.

As it seems that the MFD discussion can take longer, then I would say
yes, at least for the cleanup/misc changes part.


Thanks,
Miquèl

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

* Re: [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  2020-04-15 15:57 ` [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts Christophe Kerello
@ 2020-04-27 18:22   ` Miquel Raynal
  2020-04-29  9:27     ` Christophe Kerello
  0 siblings, 1 reply; 51+ messages in thread
From: Miquel Raynal @ 2020-04-27 18:22 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Christophe,

Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
2020 17:57:30 +0200:

> This patch removes the constant FMC2_TIMEOUT_US.
> FMC2_TIMEOUT_MS is set to 5 seconds and this constant is used
> each time that we need to wait (except when the timeout value
> is set by the framework)
> 
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>  drivers/mtd/nand/raw/stm32_fmc2_nand.c | 11 +++++------
>  1 file changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> index ab53314..f159c39 100644
> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> @@ -37,8 +37,7 @@
>  /* Max ECC buffer length */
>  #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
>  
> -#define FMC2_TIMEOUT_US			1000
> -#define FMC2_TIMEOUT_MS			1000
> +#define FMC2_TIMEOUT_MS			5000
>  
>  /* Timings */
>  #define FMC2_THIZ			1
> @@ -525,9 +524,9 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
>  	u32 sr, heccr;
>  	int ret;
>  
> -	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
> -					 sr, sr & FMC2_SR_NWRF, 10,
> -					 FMC2_TIMEOUT_MS);
> +	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
> +						sr, sr & FMC2_SR_NWRF, 1,
> +						1000 * FMC2_TIMEOUT_MS);

Is the _atomic suffix needed here? If yes it would deserve a separate
patch with Fixes/Stable tags.

>  	if (ret) {
>  		dev_err(fmc2->dev, "ham timeout\n");
>  		return ret;
> @@ -1315,7 +1314,7 @@ static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
>  	/* Check if there is no pending requests to the NAND flash */
>  	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
>  					      sr & FMC2_SR_NWRF, 1,
> -					      FMC2_TIMEOUT_US))
> +					      1000 * FMC2_TIMEOUT_MS))
>  		dev_warn(fmc2->dev, "Waitrdy timeout\n");
>  
>  	/* Wait tWB before R/B# signal is low */

You change the timeouts from 1ms to 5s.

Maybe 5s is a little bit too much IMHO but we don't really care as this
is a timeout. However 1ms is tight. If you are changing this value
because it triggers error (eg. when the machine is loaded), then it is
a fix and should appear like it.

Thanks,
Miquèl

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

* Re: [PATCH v2 07/12] mtd: rawnand: stm32_fmc2: cleanup
  2020-04-15 15:57 ` [PATCH v2 07/12] mtd: rawnand: stm32_fmc2: cleanup Christophe Kerello
@ 2020-04-27 18:33   ` Miquel Raynal
  2020-04-29  9:31     ` Christophe Kerello
  0 siblings, 1 reply; 51+ messages in thread
From: Miquel Raynal @ 2020-04-27 18:33 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Christophe,

Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
2020 17:57:31 +0200:

> This patch renames functions and local variables to be ready to use
> stm32_fmc2 structure.
> 
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---

> -static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr,
> -				      const struct nand_data_interface *conf)
> +static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr,
> +					  const struct nand_data_interface *cf)

I suppose you s/conf/cf/ because of the 80 chars boundary. In this case
I don't mind crossing it, I don't think it is better to rename the
conf parameter for this reason.

>  {
>  	const struct nand_sdr_timings *sdrt;
>  
> -	sdrt = nand_get_sdr_timings(conf);
> +	sdrt = nand_get_sdr_timings(cf);
>  	if (IS_ERR(sdrt))
>  		return PTR_ERR(sdrt);
>  
>  	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
>  		return 0;
>  
> -	stm32_fmc2_calc_timings(chip, sdrt);
> -	stm32_fmc2_timings_init(chip);
> +	stm32_fmc2_nfc_calc_timings(chip, sdrt);
> +	stm32_fmc2_nfc_timings_init(chip);
>  
>  	return 0;
>  }
>  

[...]

>  
> -static struct platform_driver stm32_fmc2_driver = {
> -	.probe	= stm32_fmc2_probe,
> -	.remove	= stm32_fmc2_remove,
> +static struct platform_driver stm32_fmc2_nfc_driver = {
> +	.probe	= stm32_fmc2_nfc_probe,
> +	.remove	= stm32_fmc2_nfc_remove,
>  	.driver	= {
> -		.name = "stm32_fmc2_nand",
> -		.of_match_table = stm32_fmc2_match,
> -		.pm = &stm32_fmc2_pm_ops,
> +		.name = "stm32_fmc2_nfc",
> +		.of_match_table = stm32_fmc2_nfc_match,
> +		.pm = &stm32_fmc2_nfc_pm_ops,
>  	},
>  };
> -module_platform_driver(stm32_fmc2_driver);
> +module_platform_driver(stm32_fmc2_nfc_driver);
>  
> -MODULE_ALIAS("platform:stm32_fmc2_nand");
> +MODULE_ALIAS("platform:stm32_fmc2_nfc");
>  MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
> -MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nand driver");
> +MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nfc driver");

I would prefer: s/nfc/NFC/ here please.

>  MODULE_LICENSE("GPL v2");

With these two nits,

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Thanks,
Miquèl

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

* Re: [PATCH v2 08/12] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros
  2020-04-16 19:45   ` Boris Brezillon
@ 2020-04-27 18:50     ` Miquel Raynal
  0 siblings, 0 replies; 51+ messages in thread
From: Miquel Raynal @ 2020-04-27 18:50 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Christophe Kerello, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, marex, devicetree, linux-kernel, linux-mtd,
	linux-stm32

Hello,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Thu, 16 Apr
2020 21:45:13 +0200:

> On Wed, 15 Apr 2020 17:57:32 +0200
> Christophe Kerello <christophe.kerello@st.com> wrote:
> 
> > This patch removes custom macros and uses FIELD_PREP and FIELD_GET macros.  
> 
> Oh, nice. I didn't know about these macros. This could have saved me
> from defining a whole bunch of setters/getters in driver code...
> 
> 

Love these too! I will definitely use them in the future.

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>

Thanks,
Miquèl

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

* Re: [PATCH v2 10/12] mtd: rawnand: stm32_fmc2: use regmap APIs
  2020-04-15 15:57 ` [PATCH v2 10/12] mtd: rawnand: stm32_fmc2: use regmap APIs Christophe Kerello
@ 2020-04-27 18:52   ` Miquel Raynal
  0 siblings, 0 replies; 51+ messages in thread
From: Miquel Raynal @ 2020-04-27 18:52 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Christophe,

Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
2020 17:57:34 +0200:

> This patch uses regmap APIs to access all FMC2 registers.
> 
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---

Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>


Thanks,
Miquèl

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

* Re: [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-27 18:08       ` Miquel Raynal
@ 2020-04-27 19:46         ` Marek Vasut
  2020-04-27 20:08           ` Miquel Raynal
  0 siblings, 1 reply; 51+ messages in thread
From: Marek Vasut @ 2020-04-27 19:46 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Christophe Kerello, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, linux-mtd, linux-kernel, linux-stm32,
	devicetree

On 4/27/20 8:08 PM, Miquel Raynal wrote:
[...]
>>>>  	/* FMC2 init routine */
>>>>  	stm32_fmc2_init(fmc2);
>>>> @@ -1997,7 +2001,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>  	/* Scan to find existence of the device */
>>>>  	ret = nand_scan(chip, nand->ncs);
>>>>  	if (ret)
>>>> -		goto err_scan;
>>>> +		goto err_dma_setup;
>>>>  
>>>>  	ret = mtd_device_register(mtd, NULL, 0);
>>>>  	if (ret)
>>>> @@ -2010,7 +2014,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>  err_device_register:
>>>>  	nand_cleanup(chip);
>>>>  
>>>> -err_scan:
>>>> +err_dma_setup:
>>>>  	if (fmc2->dma_ecc_ch)
>>>>  		dma_release_channel(fmc2->dma_ecc_ch);
>>>>  	if (fmc2->dma_tx_ch)
>>>> @@ -2021,6 +2025,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>  	sg_free_table(&fmc2->dma_data_sg);
>>>>  	sg_free_table(&fmc2->dma_ecc_sg);
>>>>  
>>>> +err_clk_disable:
>>>>  	clk_disable_unprepare(fmc2->clk);
>>>>  
>>>>  	return ret;  
>>>
>>> I didn't spot it during my earlier reviews but I really prefer using
>>> labels explaining what you do than having the same name of the function
>>> which failed. This way you don't have to rework the error path when
>>> you handle an additional error.
>>>
>>> So, would you mind doing this in two steps:
>>>
>>> 1/
>>> Replace
>>>
>>>     err_scan:
>>>
>>> with, eg.
>>>
>>>     release_dma_objs:  
>>
>> The ^err_ prefix in failpath labels is useful, since it's easily
>> possible to match on it with regexes ; not so much on arbitrary label name.
> 
> I guess so, but is it actually useful to catch labels in a regex? (real
> question)

I find it useful to have a unified way to find those labels, e.g.
err_because_foo:
err_because_bar:
err_last_one:
is much nicer than:
foo_failed:
bar_also_failed:
its_total_randomness:

> Any way I suppose catching ":\n" is already a good approximation to
> find labels?

Not very practical with git grep (^err.*: works nicely though)

>> btw would it make sense to split the first three patches of this series
>> into a separate series ? This rawnand part seems more like an unrelated
>> cleanup.
> 
> As it seems that the MFD discussion can take longer, then I would say
> yes, at least for the cleanup/misc changes part.
Right

-- 
Best regards,
Marek Vasut

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

* Re: [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-27 19:46         ` Marek Vasut
@ 2020-04-27 20:08           ` Miquel Raynal
  2020-04-27 20:10             ` Marek Vasut
  2020-04-29  9:07             ` Christophe Kerello
  0 siblings, 2 replies; 51+ messages in thread
From: Miquel Raynal @ 2020-04-27 20:08 UTC (permalink / raw)
  To: Marek Vasut
  Cc: Christophe Kerello, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, linux-mtd, linux-kernel, linux-stm32,
	devicetree

Hi Marek,

Marek Vasut <marex@denx.de> wrote on Mon, 27 Apr 2020 21:46:44 +0200:

> On 4/27/20 8:08 PM, Miquel Raynal wrote:
> [...]
> >>>>  	/* FMC2 init routine */
> >>>>  	stm32_fmc2_init(fmc2);
> >>>> @@ -1997,7 +2001,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
> >>>>  	/* Scan to find existence of the device */
> >>>>  	ret = nand_scan(chip, nand->ncs);
> >>>>  	if (ret)
> >>>> -		goto err_scan;
> >>>> +		goto err_dma_setup;
> >>>>  
> >>>>  	ret = mtd_device_register(mtd, NULL, 0);
> >>>>  	if (ret)
> >>>> @@ -2010,7 +2014,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
> >>>>  err_device_register:
> >>>>  	nand_cleanup(chip);
> >>>>  
> >>>> -err_scan:
> >>>> +err_dma_setup:
> >>>>  	if (fmc2->dma_ecc_ch)
> >>>>  		dma_release_channel(fmc2->dma_ecc_ch);
> >>>>  	if (fmc2->dma_tx_ch)
> >>>> @@ -2021,6 +2025,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
> >>>>  	sg_free_table(&fmc2->dma_data_sg);
> >>>>  	sg_free_table(&fmc2->dma_ecc_sg);
> >>>>  
> >>>> +err_clk_disable:
> >>>>  	clk_disable_unprepare(fmc2->clk);
> >>>>  
> >>>>  	return ret;    
> >>>
> >>> I didn't spot it during my earlier reviews but I really prefer using
> >>> labels explaining what you do than having the same name of the function
> >>> which failed. This way you don't have to rework the error path when
> >>> you handle an additional error.
> >>>
> >>> So, would you mind doing this in two steps:
> >>>
> >>> 1/
> >>> Replace
> >>>
> >>>     err_scan:
> >>>
> >>> with, eg.
> >>>
> >>>     release_dma_objs:    
> >>
> >> The ^err_ prefix in failpath labels is useful, since it's easily
> >> possible to match on it with regexes ; not so much on arbitrary label name.  
> > 
> > I guess so, but is it actually useful to catch labels in a regex? (real
> > question)  
> 
> I find it useful to have a unified way to find those labels, e.g.
> err_because_foo:
> err_because_bar:
> err_last_one:
> is much nicer than:
> foo_failed:
> bar_also_failed:
> its_total_randomness:

My point being, Christophe, you can use err_ as a prefix but I think
it's better to use:

    err_do_this_cleanup

than

   err_this_failed

> 
> > Any way I suppose catching ":\n" is already a good approximation to
> > find labels?  
> 
> Not very practical with git grep (^err.*: works nicely though)

I suppose ^.*:$ would work the same ;)

> 
> >> btw would it make sense to split the first three patches of this series
> >> into a separate series ? This rawnand part seems more like an unrelated
> >> cleanup.  
> > 
> > As it seems that the MFD discussion can take longer, then I would say
> > yes, at least for the cleanup/misc changes part.  
> Right
> 

Cheers,
Miquèl

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

* Re: [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-27 20:08           ` Miquel Raynal
@ 2020-04-27 20:10             ` Marek Vasut
  2020-04-29  8:00               ` Christophe Kerello
  2020-04-29  9:07             ` Christophe Kerello
  1 sibling, 1 reply; 51+ messages in thread
From: Marek Vasut @ 2020-04-27 20:10 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Christophe Kerello, richard, vigneshr, lee.jones, robh+dt,
	mark.rutland, tony, linux-mtd, linux-kernel, linux-stm32,
	devicetree

On 4/27/20 10:08 PM, Miquel Raynal wrote:
> Hi Marek,
> 
> Marek Vasut <marex@denx.de> wrote on Mon, 27 Apr 2020 21:46:44 +0200:
> 
>> On 4/27/20 8:08 PM, Miquel Raynal wrote:
>> [...]
>>>>>>  	/* FMC2 init routine */
>>>>>>  	stm32_fmc2_init(fmc2);
>>>>>> @@ -1997,7 +2001,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>>>  	/* Scan to find existence of the device */
>>>>>>  	ret = nand_scan(chip, nand->ncs);
>>>>>>  	if (ret)
>>>>>> -		goto err_scan;
>>>>>> +		goto err_dma_setup;
>>>>>>  
>>>>>>  	ret = mtd_device_register(mtd, NULL, 0);
>>>>>>  	if (ret)
>>>>>> @@ -2010,7 +2014,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>>>  err_device_register:
>>>>>>  	nand_cleanup(chip);
>>>>>>  
>>>>>> -err_scan:
>>>>>> +err_dma_setup:
>>>>>>  	if (fmc2->dma_ecc_ch)
>>>>>>  		dma_release_channel(fmc2->dma_ecc_ch);
>>>>>>  	if (fmc2->dma_tx_ch)
>>>>>> @@ -2021,6 +2025,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>>>  	sg_free_table(&fmc2->dma_data_sg);
>>>>>>  	sg_free_table(&fmc2->dma_ecc_sg);
>>>>>>  
>>>>>> +err_clk_disable:
>>>>>>  	clk_disable_unprepare(fmc2->clk);
>>>>>>  
>>>>>>  	return ret;    
>>>>>
>>>>> I didn't spot it during my earlier reviews but I really prefer using
>>>>> labels explaining what you do than having the same name of the function
>>>>> which failed. This way you don't have to rework the error path when
>>>>> you handle an additional error.
>>>>>
>>>>> So, would you mind doing this in two steps:
>>>>>
>>>>> 1/
>>>>> Replace
>>>>>
>>>>>     err_scan:
>>>>>
>>>>> with, eg.
>>>>>
>>>>>     release_dma_objs:    
>>>>
>>>> The ^err_ prefix in failpath labels is useful, since it's easily
>>>> possible to match on it with regexes ; not so much on arbitrary label name.  
>>>
>>> I guess so, but is it actually useful to catch labels in a regex? (real
>>> question)  
>>
>> I find it useful to have a unified way to find those labels, e.g.
>> err_because_foo:
>> err_because_bar:
>> err_last_one:
>> is much nicer than:
>> foo_failed:
>> bar_also_failed:
>> its_total_randomness:
> 
> My point being, Christophe, you can use err_ as a prefix but I think
> it's better to use:
> 
>     err_do_this_cleanup
> 
> than
> 
>    err_this_failed

That's fine either way.

>>> Any way I suppose catching ":\n" is already a good approximation to
>>> find labels?  
>>
>> Not very practical with git grep (^err.*: works nicely though)
> 
> I suppose ^.*:$ would work the same ;)

Try and see how much other irrelevant stuff that sucks in ;-)

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

* Re: [PATCH v2 01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation
  2020-04-15 15:57 ` [PATCH v2 01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation Christophe Kerello
@ 2020-04-28 15:28   ` Rob Herring
  2020-04-29  9:35     ` Christophe Kerello
  0 siblings, 1 reply; 51+ messages in thread
From: Rob Herring @ 2020-04-28 15:28 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: miquel.raynal, richard, vigneshr, lee.jones, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

On Wed, Apr 15, 2020 at 05:57:25PM +0200, Christophe Kerello wrote:
> This patch adds the documentation of the device tree bindings for the STM32
> FMC2 controller.
> 
> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> ---
>  .../devicetree/bindings/mfd/st,stm32-fmc2.yaml     | 370 +++++++++++++++++++++
>  1 file changed, 370 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
> new file mode 100644
> index 0000000..0ce1340
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
> @@ -0,0 +1,370 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/st,stm32-fmc2.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: STMicroelectronics Flexible Memory Controller 2 (FMC2) Bindings
> +
> +description: |
> +  The FMC2 functional block makes the interface with: synchronous and
> +  asynchronous static devices (such as PSNOR, PSRAM or other memory-mapped
> +  peripherals) and NAND flash memories.
> +  Its main purposes are:
> +    - to translate AXI transactions into the appropriate external device
> +      protocol
> +    - to meet the access time requirements of the external devices
> +  All external devices share the addresses, data and control signals with the
> +  controller. Each external device is accessed by means of a unique Chip
> +  Select. The FMC2 performs only one access at a time to an external device.
> +
> +maintainers:
> +  - Christophe Kerello <christophe.kerello@st.com>
> +
> +properties:
> +  compatible:
> +    const: st,stm32mp1-fmc2
> +
> +  reg:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  resets:
> +    maxItems: 1
> +
> +  "#address-cells":
> +    const: 1
> +
> +  "#size-cells":
> +    const: 1
> +
> +  ranges: true
> +
> +patternProperties:
> +  "^ebi(@.*)?":
> +    type: object
> +
> +    properties:
> +      compatible:
> +        const: st,stm32mp1-fmc2-ebi
> +
> +      "#address-cells":
> +        const: 2
> +
> +      "#size-cells":
> +        const: 1
> +
> +      ranges: true
> +
> +    patternProperties:
> +      "^[a-zA-Z]*-ebi@[a-f0-9,]*$":

These nodes should be named based on the device connected and we can be 
a bit more precise on the unit-address:

"@[0-9a-f],[0-9a-f]+$"

Adjust for how many chip selects there are. 15 seems unlikely.

> +        type: object
> +
> +        properties:
> +          reg:
> +            maxItems: 1
> +
> +          st,fmc2_ebi_cs_transaction_type:

s/_/-/

And for the rest of the vendor properties...

> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +              - minimum: 0
> +                maximum: 11
> +            description: |
> +                         Select one of the transactions type supported
> +                           0: Asynchronous mode 1 SRAM/FRAM
> +                           1: Asynchronous mode 1 PSRAM.
> +                           2: Asynchronous mode A SRAM/FRAM.
> +                           3: Asynchronous mode A PSRAM.
> +                           4: Asynchronous mode 2 NOR.
> +                           5: Asynchronous mode B NOR.
> +                           6: Asynchronous mode C NOR.
> +                           7: Asynchronous mode D NOR.
> +                           8: Synchronous read synchronous write PSRAM.
> +                           9: Synchronous read asynchronous write PSRAM.
> +                           10: Synchronous read synchronous write NOR.
> +                           11: Synchronous read asynchronous write NOR.
> +
> +          st,fmc2_ebi_cs_cclk_enable:
> +            $ref: /schemas/types.yaml#/definitions/flag
> +            description: Continuous clock enable (first bank must be configured
> +                         in synchronous mode). The FMC_CLK is generated continuously
> +                         during asynchronous and synchronous access. By default, the
> +                         FMC_CLK is only generated during synchronous access.
> +
> +          st,fmc2_ebi_cs_mux_enable:
> +            $ref: /schemas/types.yaml#/definitions/flag
> +            description: Address/Data multiplexed on databus (valid only with
> +                         NOR and PSRAM transactions type). By default, Address/Data are
> +                         not multiplexed.
> +
> +          st,fmc2_ebi_cs_buswidth:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +              - enum: [ 8, 16 ]
> +              - default: 16
> +            description: Data bus width
> +
> +          st,fmc2_ebi_cs_waitpol_high:
> +            $ref: /schemas/types.yaml#/definitions/flag
> +            description: Wait signal polarity (NWAIT signal active high).
> +                         By default, NWAIT is active low.
> +
> +          st,fmc2_ebi_cs_waitcfg_enable:
> +            $ref: /schemas/types.yaml#/definitions/flag
> +            description: The NWAIT signal indicates wheither the data from the
> +                         device are valid or if a wait state must be inserted when
> +                         accessing the device in synchronous mode. By default, the NWAIT
> +                         signal is active one data cycle before wait state.
> +
> +          st,fmc2_ebi_cs_wait_enable:
> +            $ref: /schemas/types.yaml#/definitions/flag
> +            description: The NWAIT signal is enabled (its level is taken into
> +                         account after the programmed latency period to insert wait states
> +                         if asserted). By default, the NWAIT signal is disabled.
> +
> +          st,fmc2_ebi_cs_asyncwait_enable:
> +            $ref: /schemas/types.yaml#/definitions/flag
> +            description: The NWAIT signal is taken into account during
> +                         asynchronous transactions. By default, the NWAIT signal is not
> +                         taken into account during asynchronous transactions.
> +
> +          st,fmc2_ebi_cs_cpsize:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +              - enum: [ 0, 128, 256, 512, 1024 ]
> +              - default: 0
> +            description: CRAM page size. The controller splits the burst access
> +                         when the memory page is reached. By default, no burst split when
> +                         crossing page boundary.
> +
> +          st,fmc2_ebi_cs_byte_lane_setup:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property configures the byte lane setup timing
> +                         defined in ns from NBLx low to Chip Select NEx low.

If units are nsec, then use the standard unit suffixes. Then you don't 
need to define the type either.

> +
> +          st,fmc2_ebi_cs_address_setup:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the duration of the address
> +                         setup phase in ns used for asynchronous read/write transactions.
> +
> +          st,fmc2_ebi_cs_address_hold:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the duration of the address
> +                         hold phase in ns used for asynchronous multiplexed
> +                         read/write transactions.
> +
> +          st,fmc2_ebi_cs_data_setup:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the duration of the data
> +                         setup phase in ns used for asynchronous read/write transactions.
> +
> +          st,fmc2_ebi_cs_bus_turnaround:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the delay between the end of
> +                         current read/write transaction and the next transaction.
> +
> +          st,fmc2_ebi_cs_data_hold:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the duration of the data
> +                         hold phase in ns used for asynchronous read/write transactions.
> +
> +          st,fmc2_ebi_cs_clk_period:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the FMC_CLK output signal period in ns.
> +
> +          st,fmc2_ebi_cs_data_latency:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the data latency before reading or writing
> +                         the first data. This timing is expressed in FMC_CLK periods.
> +
> +          st,fmc2_ebi_cs_write_address_setup:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the duration of the address
> +                         setup phase in ns used for asynchronous write transactions.
> +
> +          st,fmc2_ebi_cs_write_address_hold:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the duration of the address hold phase in
> +                         ns used for asynchronous multiplexed write transactions.
> +
> +          st,fmc2_ebi_cs_write_data_setup:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the duration of the data setup phase in
> +                         ns used for asynchronous write transactions.
> +
> +          st,fmc2_ebi_cs_write_bus_turnaround:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the delay between the end of current
> +                         write transaction and the next transaction.
> +
> +          st,fmc2_ebi_cs_write_data_hold:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the duration of the data hold phase
> +                         in ns used for asynchronous write transactions.
> +
> +          st,fmc2_ebi_cs_max_low_pulse:
> +            allOf:
> +              - $ref: /schemas/types.yaml#/definitions/uint32
> +            description: This property defines the maximum chip select low pulse duration
> +                         in ns for synchronous transactions. When this timing reaches 0,
> +                         the controller splits the current access, toggles NE to allow
> +                         device refresh and restarts a new access.
> +
> +        required:
> +          - reg
> +          - st,fmc2_ebi_cs_transaction_type
> +
> +    additionalProperties: false
> +
> +    required:
> +      - compatible
> +      - "#address-cells"
> +      - "#size-cells"
> +      - ranges
> +
> +  nand-controller:
> +    allOf:
> +      - $ref: "../mtd/nand-controller.yaml#"
> +
> +    type: object
> +
> +    properties:
> +      compatible:
> +        const: st,stm32mp1-fmc2-nand
> +
> +      reg:
> +        items:
> +          - description: Chip select 0 data
> +          - description: Chip select 0 command
> +          - description: Chip select 0 address space
> +          - description: Chip select 1 data
> +          - description: Chip select 1 command
> +          - description: Chip select 1 address space
> +
> +      interrupts:
> +        maxItems: 1
> +
> +      dmas:
> +        items:
> +          - description: tx DMA channel
> +          - description: rx DMA channel
> +          - description: ecc DMA channel
> +
> +      dma-names:
> +        items:
> +          - const: tx
> +          - const: rx
> +          - const: ecc
> +
> +      "#address-cells":
> +        const: 1
> +
> +      "#size-cells":
> +        const: 0
> +
> +    patternProperties:
> +      "^nand@[a-f0-9]$":
> +        type: object
> +
> +        properties:
> +          nand-ecc-step-size:
> +            const: 512
> +
> +          nand-ecc-strength:
> +            enum: [1, 4 ,8 ]
> +
> +    additionalProperties: false
> +
> +    required:
> +      - "#address-cells"
> +      - "#size-cells"
> +      - compatible
> +      - reg
> +      - interrupts
> +
> +  additionalProperties: false

Wrong indentation. You are defining a DT property called 
'additionalProperties'. You need 2 of these at 0 and 4 spaces 
indentation. I have a check for this error in dt-schema pending.

> +
> +required:
> +  - "#address-cells"
> +  - "#size-cells"
> +  - compatible
> +  - reg
> +  - clocks
> +  - ranges
> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
> +    #include <dt-bindings/clock/stm32mp1-clks.h>
> +    #include <dt-bindings/reset/stm32mp1-resets.h>
> +    fmc@58002000 {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      compatible = "st,stm32mp1-fmc2";
> +      reg = <0x58002000 0x1000>;
> +      clocks = <&rcc FMC_K>;
> +      resets = <&rcc FMC_R>;
> +      ranges;
> +
> +      ebi@0 {
> +        #address-cells = <2>;
> +        #size-cells = <1>;
> +        compatible = "st,stm32mp1-fmc2-ebi";
> +        ranges = <0 0 0x60000000 0x4000000>,
> +                 <1 0 0x64000000 0x4000000>,
> +                 <2 0 0x68000000 0x4000000>,
> +                 <3 0 0x6c000000 0x4000000>;
> +
> +        psram-ebi@0,0 {
> +          compatible = "mtd-ram";
> +          reg = <0 0x00000000 0x100000>;
> +          bank-width = <2>;
> +
> +          st,fmc2_ebi_cs_transaction_type = <1>;
> +          st,fmc2_ebi_cs_address_setup = <60>;
> +          st,fmc2_ebi_cs_data_setup = <30>;
> +          st,fmc2_ebi_cs_bus_turnaround = <5>;
> +        };
> +      };
> +
> +      nand-controller@1 {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +        compatible = "st,stm32mp1-fmc2-nand";
> +        reg = <0x80000000 0x1000>,
> +              <0x88010000 0x1000>,
> +              <0x88020000 0x1000>,
> +              <0x81000000 0x1000>,
> +              <0x89010000 0x1000>,
> +              <0x89020000 0x1000>;
> +        interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
> +        dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
> +               <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
> +               <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
> +        dma-names = "tx", "rx", "ecc";
> +
> +        nand@0 {
> +          reg = <0>;
> +          nand-on-flash-bbt;
> +          #address-cells = <1>;
> +          #size-cells = <1>;
> +        };
> +      };
> +    };
> +
> +...
> -- 
> 1.9.1
> 

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

* Re: [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-27 20:10             ` Marek Vasut
@ 2020-04-29  8:00               ` Christophe Kerello
  0 siblings, 0 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-29  8:00 UTC (permalink / raw)
  To: Marek Vasut, Miquel Raynal
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree



On 4/27/20 10:10 PM, Marek Vasut wrote:
> On 4/27/20 10:08 PM, Miquel Raynal wrote:
>> Hi Marek,
>>
>> Marek Vasut <marex@denx.de> wrote on Mon, 27 Apr 2020 21:46:44 +0200:
>>
>>> On 4/27/20 8:08 PM, Miquel Raynal wrote:
>>> [...]
>>>>>>>   	/* FMC2 init routine */
>>>>>>>   	stm32_fmc2_init(fmc2);
>>>>>>> @@ -1997,7 +2001,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>>>>   	/* Scan to find existence of the device */
>>>>>>>   	ret = nand_scan(chip, nand->ncs);
>>>>>>>   	if (ret)
>>>>>>> -		goto err_scan;
>>>>>>> +		goto err_dma_setup;
>>>>>>>   
>>>>>>>   	ret = mtd_device_register(mtd, NULL, 0);
>>>>>>>   	if (ret)
>>>>>>> @@ -2010,7 +2014,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>>>>   err_device_register:
>>>>>>>   	nand_cleanup(chip);
>>>>>>>   
>>>>>>> -err_scan:
>>>>>>> +err_dma_setup:
>>>>>>>   	if (fmc2->dma_ecc_ch)
>>>>>>>   		dma_release_channel(fmc2->dma_ecc_ch);
>>>>>>>   	if (fmc2->dma_tx_ch)
>>>>>>> @@ -2021,6 +2025,7 @@ static int stm32_fmc2_probe(struct platform_device *pdev)
>>>>>>>   	sg_free_table(&fmc2->dma_data_sg);
>>>>>>>   	sg_free_table(&fmc2->dma_ecc_sg);
>>>>>>>   
>>>>>>> +err_clk_disable:
>>>>>>>   	clk_disable_unprepare(fmc2->clk);
>>>>>>>   
>>>>>>>   	return ret;
>>>>>>
>>>>>> I didn't spot it during my earlier reviews but I really prefer using
>>>>>> labels explaining what you do than having the same name of the function
>>>>>> which failed. This way you don't have to rework the error path when
>>>>>> you handle an additional error.
>>>>>>
>>>>>> So, would you mind doing this in two steps:
>>>>>>
>>>>>> 1/
>>>>>> Replace
>>>>>>
>>>>>>      err_scan:
>>>>>>
>>>>>> with, eg.
>>>>>>
>>>>>>      release_dma_objs:
>>>>>
>>>>> The ^err_ prefix in failpath labels is useful, since it's easily
>>>>> possible to match on it with regexes ; not so much on arbitrary label name.
>>>>
>>>> I guess so, but is it actually useful to catch labels in a regex? (real
>>>> question)
>>>
>>> I find it useful to have a unified way to find those labels, e.g.
>>> err_because_foo:
>>> err_because_bar:
>>> err_last_one:
>>> is much nicer than:
>>> foo_failed:
>>> bar_also_failed:
>>> its_total_randomness:
>>
>> My point being, Christophe, you can use err_ as a prefix but I think
>> it's better to use:
>>
>>      err_do_this_cleanup
>>
>> than
>>
>>     err_this_failed
> 
> That's fine either way.

Hi Miquel,

I will rename the label in v3:
  - err_device_register => err_nand_cleanup
  - err_dma_setup => err_release_dma
  - err_clk_disable => will keep this one

Regards,
Christophe Kerello.

> 
>>>> Any way I suppose catching ":\n" is already a good approximation to
>>>> find labels?
>>>
>>> Not very practical with git grep (^err.*: works nicely though)
>>
>> I suppose ^.*:$ would work the same ;)
> 
> Try and see how much other irrelevant stuff that sucks in ;-)
> 

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

* Re: [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time
  2020-04-27 20:08           ` Miquel Raynal
  2020-04-27 20:10             ` Marek Vasut
@ 2020-04-29  9:07             ` Christophe Kerello
  1 sibling, 0 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-29  9:07 UTC (permalink / raw)
  To: Miquel Raynal, Marek Vasut
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree

Hi Miquèl,

On 4/27/20 10:08 PM, Miquel Raynal wrote:
[...]
>>>> btw would it make sense to split the first three patches of this series
>>>> into a separate series ? This rawnand part seems more like an unrelated
>>>> cleanup.
>>> As it seems that the MFD discussion can take longer, then I would say
>>> yes, at least for the cleanup/misc changes part.
>> Right
>>

I think that it is better to only have one set of patches as there is 
different maintainers that will review the whole set of patches.
I expect to be able to propose a v3 next week to add the EBI driver and 
the updates on NAND driver (as some patches are linked)
A proposal could be to put all the NAND patches that you have started to 
review at the beginning of the set of patches (patch 4/5/6/7/8).
You will be free to apply them after the review and I will only resubmit 
the patches that have not been applied in the next version.

Regards,
Christophe Kerello.

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

* Re: [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  2020-04-27 18:22   ` Miquel Raynal
@ 2020-04-29  9:27     ` Christophe Kerello
  2020-04-29  9:35       ` Miquel Raynal
  0 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-29  9:27 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Miquèl,

On 4/27/20 8:22 PM, Miquel Raynal wrote:
> Hi Christophe,
> 
> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
> 2020 17:57:30 +0200:
> 
>> This patch removes the constant FMC2_TIMEOUT_US.
>> FMC2_TIMEOUT_MS is set to 5 seconds and this constant is used
>> each time that we need to wait (except when the timeout value
>> is set by the framework)
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>   drivers/mtd/nand/raw/stm32_fmc2_nand.c | 11 +++++------
>>   1 file changed, 5 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> index ab53314..f159c39 100644
>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>> @@ -37,8 +37,7 @@
>>   /* Max ECC buffer length */
>>   #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
>>   
>> -#define FMC2_TIMEOUT_US			1000
>> -#define FMC2_TIMEOUT_MS			1000
>> +#define FMC2_TIMEOUT_MS			5000
>>   
>>   /* Timings */
>>   #define FMC2_THIZ			1
>> @@ -525,9 +524,9 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
>>   	u32 sr, heccr;
>>   	int ret;
>>   
>> -	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
>> -					 sr, sr & FMC2_SR_NWRF, 10,
>> -					 FMC2_TIMEOUT_MS);
>> +	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
>> +						sr, sr & FMC2_SR_NWRF, 1,
>> +						1000 * FMC2_TIMEOUT_MS);
> 
> Is the _atomic suffix needed here? If yes it would deserve a separate
> patch with Fixes/Stable tags.
> 

I have currently not seen any issues. So, I will remove this 
modification as we will move to regmap_read_poll_timeout in patch 10.

>>   	if (ret) {
>>   		dev_err(fmc2->dev, "ham timeout\n");
>>   		return ret;
>> @@ -1315,7 +1314,7 @@ static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
>>   	/* Check if there is no pending requests to the NAND flash */
>>   	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
>>   					      sr & FMC2_SR_NWRF, 1,
>> -					      FMC2_TIMEOUT_US))
>> +					      1000 * FMC2_TIMEOUT_MS))
>>   		dev_warn(fmc2->dev, "Waitrdy timeout\n");
>>   
>>   	/* Wait tWB before R/B# signal is low */
> 
> You change the timeouts from 1ms to 5s.
> 
> Maybe 5s is a little bit too much IMHO but we don't really care as this
> is a timeout. However 1ms is tight. If you are changing this value
> because it triggers error (eg. when the machine is loaded), then it is
> a fix and should appear like it.
> 
> Thanks,
> Miquèl
> 

No errors currently happens.
During our stress tests, in a overloaded system, we have seen that we 
could be close to 1 second, even if we never met this value.
So, to be safe, I have set this timeout to 5 seconds.
As it is just a timeout value, I have not seen any side effect.
I am using the same timeout constant to avoid to have one timeout per 
cases.

Regards,
Christophe Kerello.

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

* Re: [PATCH v2 07/12] mtd: rawnand: stm32_fmc2: cleanup
  2020-04-27 18:33   ` Miquel Raynal
@ 2020-04-29  9:31     ` Christophe Kerello
  0 siblings, 0 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-29  9:31 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Miquèl,

On 4/27/20 8:33 PM, Miquel Raynal wrote:
> Hi Christophe,
> 
> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
> 2020 17:57:31 +0200:
> 
>> This patch renames functions and local variables to be ready to use
>> stm32_fmc2 structure.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
> 
>> -static int stm32_fmc2_setup_interface(struct nand_chip *chip, int chipnr,
>> -				      const struct nand_data_interface *conf)
>> +static int stm32_fmc2_nfc_setup_interface(struct nand_chip *chip, int chipnr,
>> +					  const struct nand_data_interface *cf)
> 
> I suppose you s/conf/cf/ because of the 80 chars boundary. In this case
> I don't mind crossing it, I don't think it is better to rename the
> conf parameter for this reason.
> 

Yes, you are right. I have modified it because of 80 chars boundary.
I will keep conf in v3.

>>   {
>>   	const struct nand_sdr_timings *sdrt;
>>   
>> -	sdrt = nand_get_sdr_timings(conf);
>> +	sdrt = nand_get_sdr_timings(cf);
>>   	if (IS_ERR(sdrt))
>>   		return PTR_ERR(sdrt);
>>   
>>   	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
>>   		return 0;
>>   
>> -	stm32_fmc2_calc_timings(chip, sdrt);
>> -	stm32_fmc2_timings_init(chip);
>> +	stm32_fmc2_nfc_calc_timings(chip, sdrt);
>> +	stm32_fmc2_nfc_timings_init(chip);
>>   
>>   	return 0;
>>   }
>>   
> 
> [...]
> 
>>   
>> -static struct platform_driver stm32_fmc2_driver = {
>> -	.probe	= stm32_fmc2_probe,
>> -	.remove	= stm32_fmc2_remove,
>> +static struct platform_driver stm32_fmc2_nfc_driver = {
>> +	.probe	= stm32_fmc2_nfc_probe,
>> +	.remove	= stm32_fmc2_nfc_remove,
>>   	.driver	= {
>> -		.name = "stm32_fmc2_nand",
>> -		.of_match_table = stm32_fmc2_match,
>> -		.pm = &stm32_fmc2_pm_ops,
>> +		.name = "stm32_fmc2_nfc",
>> +		.of_match_table = stm32_fmc2_nfc_match,
>> +		.pm = &stm32_fmc2_nfc_pm_ops,
>>   	},
>>   };
>> -module_platform_driver(stm32_fmc2_driver);
>> +module_platform_driver(stm32_fmc2_nfc_driver);
>>   
>> -MODULE_ALIAS("platform:stm32_fmc2_nand");
>> +MODULE_ALIAS("platform:stm32_fmc2_nfc");
>>   MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
>> -MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nand driver");
>> +MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 nfc driver");
> 
> I would prefer: s/nfc/NFC/ here please.
> 

It will be modified in v3.

Regards,
Christophe Kerello.

>>   MODULE_LICENSE("GPL v2");
> 
> With these two nits,
> 
> Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com>
> 
> Thanks,
> Miquèl
> 

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

* Re: [PATCH v2 01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation
  2020-04-28 15:28   ` Rob Herring
@ 2020-04-29  9:35     ` Christophe Kerello
  0 siblings, 0 replies; 51+ messages in thread
From: Christophe Kerello @ 2020-04-29  9:35 UTC (permalink / raw)
  To: Rob Herring
  Cc: miquel.raynal, richard, vigneshr, lee.jones, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi rob,

On 4/28/20 5:28 PM, Rob Herring wrote:
> On Wed, Apr 15, 2020 at 05:57:25PM +0200, Christophe Kerello wrote:
>> This patch adds the documentation of the device tree bindings for the STM32
>> FMC2 controller.
>>
>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>> ---
>>   .../devicetree/bindings/mfd/st,stm32-fmc2.yaml     | 370 +++++++++++++++++++++
>>   1 file changed, 370 insertions(+)
>>   create mode 100644 Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
>> new file mode 100644
>> index 0000000..0ce1340
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mfd/st,stm32-fmc2.yaml
>> @@ -0,0 +1,370 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/mfd/st,stm32-fmc2.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: STMicroelectronics Flexible Memory Controller 2 (FMC2) Bindings
>> +
>> +description: |
>> +  The FMC2 functional block makes the interface with: synchronous and
>> +  asynchronous static devices (such as PSNOR, PSRAM or other memory-mapped
>> +  peripherals) and NAND flash memories.
>> +  Its main purposes are:
>> +    - to translate AXI transactions into the appropriate external device
>> +      protocol
>> +    - to meet the access time requirements of the external devices
>> +  All external devices share the addresses, data and control signals with the
>> +  controller. Each external device is accessed by means of a unique Chip
>> +  Select. The FMC2 performs only one access at a time to an external device.
>> +
>> +maintainers:
>> +  - Christophe Kerello <christophe.kerello@st.com>
>> +
>> +properties:
>> +  compatible:
>> +    const: st,stm32mp1-fmc2
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  clocks:
>> +    maxItems: 1
>> +
>> +  resets:
>> +    maxItems: 1
>> +
>> +  "#address-cells":
>> +    const: 1
>> +
>> +  "#size-cells":
>> +    const: 1
>> +
>> +  ranges: true
>> +
>> +patternProperties:
>> +  "^ebi(@.*)?":
>> +    type: object
>> +
>> +    properties:
>> +      compatible:
>> +        const: st,stm32mp1-fmc2-ebi
>> +
>> +      "#address-cells":
>> +        const: 2
>> +
>> +      "#size-cells":
>> +        const: 1
>> +
>> +      ranges: true
>> +
>> +    patternProperties:
>> +      "^[a-zA-Z]*-ebi@[a-f0-9,]*$":
> 
> These nodes should be named based on the device connected and we can be
> a bit more precise on the unit-address:
> 
> "@[0-9a-f],[0-9a-f]+$"
> 
> Adjust for how many chip selects there are. 15 seems unlikely.
> 

Ok. It will be modified in v3.

>> +        type: object
>> +
>> +        properties:
>> +          reg:
>> +            maxItems: 1
>> +
>> +          st,fmc2_ebi_cs_transaction_type:
> 
> s/_/-/
> 
> And for the rest of the vendor properties...
> 

Ok. It will be modified in v3.

>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +              - minimum: 0
>> +                maximum: 11
>> +            description: |
>> +                         Select one of the transactions type supported
>> +                           0: Asynchronous mode 1 SRAM/FRAM
>> +                           1: Asynchronous mode 1 PSRAM.
>> +                           2: Asynchronous mode A SRAM/FRAM.
>> +                           3: Asynchronous mode A PSRAM.
>> +                           4: Asynchronous mode 2 NOR.
>> +                           5: Asynchronous mode B NOR.
>> +                           6: Asynchronous mode C NOR.
>> +                           7: Asynchronous mode D NOR.
>> +                           8: Synchronous read synchronous write PSRAM.
>> +                           9: Synchronous read asynchronous write PSRAM.
>> +                           10: Synchronous read synchronous write NOR.
>> +                           11: Synchronous read asynchronous write NOR.
>> +
>> +          st,fmc2_ebi_cs_cclk_enable:
>> +            $ref: /schemas/types.yaml#/definitions/flag
>> +            description: Continuous clock enable (first bank must be configured
>> +                         in synchronous mode). The FMC_CLK is generated continuously
>> +                         during asynchronous and synchronous access. By default, the
>> +                         FMC_CLK is only generated during synchronous access.
>> +
>> +          st,fmc2_ebi_cs_mux_enable:
>> +            $ref: /schemas/types.yaml#/definitions/flag
>> +            description: Address/Data multiplexed on databus (valid only with
>> +                         NOR and PSRAM transactions type). By default, Address/Data are
>> +                         not multiplexed.
>> +
>> +          st,fmc2_ebi_cs_buswidth:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +              - enum: [ 8, 16 ]
>> +              - default: 16
>> +            description: Data bus width
>> +
>> +          st,fmc2_ebi_cs_waitpol_high:
>> +            $ref: /schemas/types.yaml#/definitions/flag
>> +            description: Wait signal polarity (NWAIT signal active high).
>> +                         By default, NWAIT is active low.
>> +
>> +          st,fmc2_ebi_cs_waitcfg_enable:
>> +            $ref: /schemas/types.yaml#/definitions/flag
>> +            description: The NWAIT signal indicates wheither the data from the
>> +                         device are valid or if a wait state must be inserted when
>> +                         accessing the device in synchronous mode. By default, the NWAIT
>> +                         signal is active one data cycle before wait state.
>> +
>> +          st,fmc2_ebi_cs_wait_enable:
>> +            $ref: /schemas/types.yaml#/definitions/flag
>> +            description: The NWAIT signal is enabled (its level is taken into
>> +                         account after the programmed latency period to insert wait states
>> +                         if asserted). By default, the NWAIT signal is disabled.
>> +
>> +          st,fmc2_ebi_cs_asyncwait_enable:
>> +            $ref: /schemas/types.yaml#/definitions/flag
>> +            description: The NWAIT signal is taken into account during
>> +                         asynchronous transactions. By default, the NWAIT signal is not
>> +                         taken into account during asynchronous transactions.
>> +
>> +          st,fmc2_ebi_cs_cpsize:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +              - enum: [ 0, 128, 256, 512, 1024 ]
>> +              - default: 0
>> +            description: CRAM page size. The controller splits the burst access
>> +                         when the memory page is reached. By default, no burst split when
>> +                         crossing page boundary.
>> +
>> +          st,fmc2_ebi_cs_byte_lane_setup:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property configures the byte lane setup timing
>> +                         defined in ns from NBLx low to Chip Select NEx low.
> 
> If units are nsec, then use the standard unit suffixes. Then you don't
> need to define the type either.
> 

Ok. It will be modified in v3.

>> +
>> +          st,fmc2_ebi_cs_address_setup:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the duration of the address
>> +                         setup phase in ns used for asynchronous read/write transactions.
>> +
>> +          st,fmc2_ebi_cs_address_hold:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the duration of the address
>> +                         hold phase in ns used for asynchronous multiplexed
>> +                         read/write transactions.
>> +
>> +          st,fmc2_ebi_cs_data_setup:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the duration of the data
>> +                         setup phase in ns used for asynchronous read/write transactions.
>> +
>> +          st,fmc2_ebi_cs_bus_turnaround:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the delay between the end of
>> +                         current read/write transaction and the next transaction.
>> +
>> +          st,fmc2_ebi_cs_data_hold:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the duration of the data
>> +                         hold phase in ns used for asynchronous read/write transactions.
>> +
>> +          st,fmc2_ebi_cs_clk_period:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the FMC_CLK output signal period in ns.
>> +
>> +          st,fmc2_ebi_cs_data_latency:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the data latency before reading or writing
>> +                         the first data. This timing is expressed in FMC_CLK periods.
>> +
>> +          st,fmc2_ebi_cs_write_address_setup:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the duration of the address
>> +                         setup phase in ns used for asynchronous write transactions.
>> +
>> +          st,fmc2_ebi_cs_write_address_hold:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the duration of the address hold phase in
>> +                         ns used for asynchronous multiplexed write transactions.
>> +
>> +          st,fmc2_ebi_cs_write_data_setup:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the duration of the data setup phase in
>> +                         ns used for asynchronous write transactions.
>> +
>> +          st,fmc2_ebi_cs_write_bus_turnaround:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the delay between the end of current
>> +                         write transaction and the next transaction.
>> +
>> +          st,fmc2_ebi_cs_write_data_hold:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the duration of the data hold phase
>> +                         in ns used for asynchronous write transactions.
>> +
>> +          st,fmc2_ebi_cs_max_low_pulse:
>> +            allOf:
>> +              - $ref: /schemas/types.yaml#/definitions/uint32
>> +            description: This property defines the maximum chip select low pulse duration
>> +                         in ns for synchronous transactions. When this timing reaches 0,
>> +                         the controller splits the current access, toggles NE to allow
>> +                         device refresh and restarts a new access.
>> +
>> +        required:
>> +          - reg
>> +          - st,fmc2_ebi_cs_transaction_type
>> +
>> +    additionalProperties: false
>> +
>> +    required:
>> +      - compatible
>> +      - "#address-cells"
>> +      - "#size-cells"
>> +      - ranges
>> +
>> +  nand-controller:
>> +    allOf:
>> +      - $ref: "../mtd/nand-controller.yaml#"
>> +
>> +    type: object
>> +
>> +    properties:
>> +      compatible:
>> +        const: st,stm32mp1-fmc2-nand
>> +
>> +      reg:
>> +        items:
>> +          - description: Chip select 0 data
>> +          - description: Chip select 0 command
>> +          - description: Chip select 0 address space
>> +          - description: Chip select 1 data
>> +          - description: Chip select 1 command
>> +          - description: Chip select 1 address space
>> +
>> +      interrupts:
>> +        maxItems: 1
>> +
>> +      dmas:
>> +        items:
>> +          - description: tx DMA channel
>> +          - description: rx DMA channel
>> +          - description: ecc DMA channel
>> +
>> +      dma-names:
>> +        items:
>> +          - const: tx
>> +          - const: rx
>> +          - const: ecc
>> +
>> +      "#address-cells":
>> +        const: 1
>> +
>> +      "#size-cells":
>> +        const: 0
>> +
>> +    patternProperties:
>> +      "^nand@[a-f0-9]$":
>> +        type: object
>> +
>> +        properties:
>> +          nand-ecc-step-size:
>> +            const: 512
>> +
>> +          nand-ecc-strength:
>> +            enum: [1, 4 ,8 ]
>> +
>> +    additionalProperties: false
>> +
>> +    required:
>> +      - "#address-cells"
>> +      - "#size-cells"
>> +      - compatible
>> +      - reg
>> +      - interrupts
>> +
>> +  additionalProperties: false
> 
> Wrong indentation. You are defining a DT property called
> 'additionalProperties'. You need 2 of these at 0 and 4 spaces
> indentation. I have a check for this error in dt-schema pending.
> 

Ok. It will be modified in v3.

Regards,
Christophe Kerello.

>> +
>> +required:
>> +  - "#address-cells"
>> +  - "#size-cells"
>> +  - compatible
>> +  - reg
>> +  - clocks
>> +  - ranges
>> +
>> +examples:
>> +  - |
>> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
>> +    #include <dt-bindings/clock/stm32mp1-clks.h>
>> +    #include <dt-bindings/reset/stm32mp1-resets.h>
>> +    fmc@58002000 {
>> +      #address-cells = <1>;
>> +      #size-cells = <1>;
>> +      compatible = "st,stm32mp1-fmc2";
>> +      reg = <0x58002000 0x1000>;
>> +      clocks = <&rcc FMC_K>;
>> +      resets = <&rcc FMC_R>;
>> +      ranges;
>> +
>> +      ebi@0 {
>> +        #address-cells = <2>;
>> +        #size-cells = <1>;
>> +        compatible = "st,stm32mp1-fmc2-ebi";
>> +        ranges = <0 0 0x60000000 0x4000000>,
>> +                 <1 0 0x64000000 0x4000000>,
>> +                 <2 0 0x68000000 0x4000000>,
>> +                 <3 0 0x6c000000 0x4000000>;
>> +
>> +        psram-ebi@0,0 {
>> +          compatible = "mtd-ram";
>> +          reg = <0 0x00000000 0x100000>;
>> +          bank-width = <2>;
>> +
>> +          st,fmc2_ebi_cs_transaction_type = <1>;
>> +          st,fmc2_ebi_cs_address_setup = <60>;
>> +          st,fmc2_ebi_cs_data_setup = <30>;
>> +          st,fmc2_ebi_cs_bus_turnaround = <5>;
>> +        };
>> +      };
>> +
>> +      nand-controller@1 {
>> +        #address-cells = <1>;
>> +        #size-cells = <0>;
>> +        compatible = "st,stm32mp1-fmc2-nand";
>> +        reg = <0x80000000 0x1000>,
>> +              <0x88010000 0x1000>,
>> +              <0x88020000 0x1000>,
>> +              <0x81000000 0x1000>,
>> +              <0x89010000 0x1000>,
>> +              <0x89020000 0x1000>;
>> +        interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
>> +        dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
>> +               <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
>> +               <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
>> +        dma-names = "tx", "rx", "ecc";
>> +
>> +        nand@0 {
>> +          reg = <0>;
>> +          nand-on-flash-bbt;
>> +          #address-cells = <1>;
>> +          #size-cells = <1>;
>> +        };
>> +      };
>> +    };
>> +
>> +...
>> -- 
>> 1.9.1
>>

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

* Re: [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  2020-04-29  9:27     ` Christophe Kerello
@ 2020-04-29  9:35       ` Miquel Raynal
  2020-04-29  9:41         ` Christophe Kerello
  0 siblings, 1 reply; 51+ messages in thread
From: Miquel Raynal @ 2020-04-29  9:35 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Christophe,

Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
2020 11:27:43 +0200:

> Hi Miquèl,
> 
> On 4/27/20 8:22 PM, Miquel Raynal wrote:
> > Hi Christophe,
> > 
> > Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
> > 2020 17:57:30 +0200:
> >   
> >> This patch removes the constant FMC2_TIMEOUT_US.
> >> FMC2_TIMEOUT_MS is set to 5 seconds and this constant is used
> >> each time that we need to wait (except when the timeout value
> >> is set by the framework)
> >>
> >> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> >> ---
> >>   drivers/mtd/nand/raw/stm32_fmc2_nand.c | 11 +++++------
> >>   1 file changed, 5 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >> index ab53314..f159c39 100644
> >> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >> @@ -37,8 +37,7 @@
> >>   /* Max ECC buffer length */
> >>   #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)  
> >>   >> -#define FMC2_TIMEOUT_US			1000  
> >> -#define FMC2_TIMEOUT_MS			1000
> >> +#define FMC2_TIMEOUT_MS			5000  
> >>   >>   /* Timings */  
> >>   #define FMC2_THIZ			1
> >> @@ -525,9 +524,9 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
> >>   	u32 sr, heccr;
> >>   	int ret;  
> >>   >> -	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,  
> >> -					 sr, sr & FMC2_SR_NWRF, 10,
> >> -					 FMC2_TIMEOUT_MS);
> >> +	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
> >> +						sr, sr & FMC2_SR_NWRF, 1,
> >> +						1000 * FMC2_TIMEOUT_MS);  
> > 
> > Is the _atomic suffix needed here? If yes it would deserve a separate
> > patch with Fixes/Stable tags.
> >   
> 
> I have currently not seen any issues. So, I will remove this modification as we will move to regmap_read_poll_timeout in patch 10.
> 
> >>   	if (ret) {
> >>   		dev_err(fmc2->dev, "ham timeout\n");
> >>   		return ret;
> >> @@ -1315,7 +1314,7 @@ static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
> >>   	/* Check if there is no pending requests to the NAND flash */
> >>   	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
> >>   					      sr & FMC2_SR_NWRF, 1,
> >> -					      FMC2_TIMEOUT_US))
> >> +					      1000 * FMC2_TIMEOUT_MS))
> >>   		dev_warn(fmc2->dev, "Waitrdy timeout\n");  
> >>   >>   	/* Wait tWB before R/B# signal is low */  
> > 
> > You change the timeouts from 1ms to 5s.
> > 
> > Maybe 5s is a little bit too much IMHO but we don't really care as this
> > is a timeout. However 1ms is tight. If you are changing this value
> > because it triggers error (eg. when the machine is loaded), then it is
> > a fix and should appear like it.
> > 
> > Thanks,
> > Miquèl
> >   
> 
> No errors currently happens.
> During our stress tests, in a overloaded system, we have seen that we could be close to 1 second, even if we never met this value.
> So, to be safe, I have set this timeout to 5 seconds.
> As it is just a timeout value, I have not seen any side effect.
> I am using the same timeout constant to avoid to have one timeout per cases.

Something is wrong in my mind:
You say you observe delays of almost up to 1 second, but the polling
currently happens on 1000 us = 1ms, either you had timeouts or I
misread something?

Thanks,
Miquèl

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

* Re: [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  2020-04-29  9:35       ` Miquel Raynal
@ 2020-04-29  9:41         ` Christophe Kerello
  2020-04-29 10:06           ` Miquel Raynal
  0 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-29  9:41 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex



On 4/29/20 11:35 AM, Miquel Raynal wrote:
> Hi Christophe,
> 
> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
> 2020 11:27:43 +0200:
> 
>> Hi Miquèl,
>>
>> On 4/27/20 8:22 PM, Miquel Raynal wrote:
>>> Hi Christophe,
>>>
>>> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
>>> 2020 17:57:30 +0200:
>>>    
>>>> This patch removes the constant FMC2_TIMEOUT_US.
>>>> FMC2_TIMEOUT_MS is set to 5 seconds and this constant is used
>>>> each time that we need to wait (except when the timeout value
>>>> is set by the framework)
>>>>
>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>>>> ---
>>>>    drivers/mtd/nand/raw/stm32_fmc2_nand.c | 11 +++++------
>>>>    1 file changed, 5 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>>>> index ab53314..f159c39 100644
>>>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>>>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>>>> @@ -37,8 +37,7 @@
>>>>    /* Max ECC buffer length */
>>>>    #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
>>>>    >> -#define FMC2_TIMEOUT_US			1000
>>>> -#define FMC2_TIMEOUT_MS			1000
>>>> +#define FMC2_TIMEOUT_MS			5000
>>>>    >>   /* Timings */
>>>>    #define FMC2_THIZ			1
>>>> @@ -525,9 +524,9 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
>>>>    	u32 sr, heccr;
>>>>    	int ret;
>>>>    >> -	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
>>>> -					 sr, sr & FMC2_SR_NWRF, 10,
>>>> -					 FMC2_TIMEOUT_MS);
>>>> +	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
>>>> +						sr, sr & FMC2_SR_NWRF, 1,
>>>> +						1000 * FMC2_TIMEOUT_MS);
>>>
>>> Is the _atomic suffix needed here? If yes it would deserve a separate
>>> patch with Fixes/Stable tags.
>>>    
>>
>> I have currently not seen any issues. So, I will remove this modification as we will move to regmap_read_poll_timeout in patch 10.
>>
>>>>    	if (ret) {
>>>>    		dev_err(fmc2->dev, "ham timeout\n");
>>>>    		return ret;
>>>> @@ -1315,7 +1314,7 @@ static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
>>>>    	/* Check if there is no pending requests to the NAND flash */
>>>>    	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
>>>>    					      sr & FMC2_SR_NWRF, 1,
>>>> -					      FMC2_TIMEOUT_US))
>>>> +					      1000 * FMC2_TIMEOUT_MS))
>>>>    		dev_warn(fmc2->dev, "Waitrdy timeout\n");
>>>>    >>   	/* Wait tWB before R/B# signal is low */
>>>
>>> You change the timeouts from 1ms to 5s.
>>>
>>> Maybe 5s is a little bit too much IMHO but we don't really care as this
>>> is a timeout. However 1ms is tight. If you are changing this value
>>> because it triggers error (eg. when the machine is loaded), then it is
>>> a fix and should appear like it.
>>>
>>> Thanks,
>>> Miquèl
>>>    
>>
>> No errors currently happens.
>> During our stress tests, in a overloaded system, we have seen that we could be close to 1 second, even if we never met this value.
>> So, to be safe, I have set this timeout to 5 seconds.
>> As it is just a timeout value, I have not seen any side effect.
>> I am using the same timeout constant to avoid to have one timeout per cases.
> 
> Something is wrong in my mind:
> You say you observe delays of almost up to 1 second, but the polling
> currently happens on 1000 us = 1ms, either you had timeouts or I
> misread something?
> 
> Thanks,
> Miquèl
> 

Hi Miquèl,

My fault. For this polling, we never met 1 ms.
The 1 second observed was on the sequencer when we read/write a page (as 
it the same timeout value that is used)

Regards,
Christophe Kerello.

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

* Re: [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  2020-04-29  9:41         ` Christophe Kerello
@ 2020-04-29 10:06           ` Miquel Raynal
  2020-04-29 10:13             ` Christophe Kerello
  0 siblings, 1 reply; 51+ messages in thread
From: Miquel Raynal @ 2020-04-29 10:06 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Christophe,

Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
2020 11:41:44 +0200:

> On 4/29/20 11:35 AM, Miquel Raynal wrote:
> > Hi Christophe,
> > 
> > Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
> > 2020 11:27:43 +0200:
> >   
> >> Hi Miquèl,
> >>
> >> On 4/27/20 8:22 PM, Miquel Raynal wrote:  
> >>> Hi Christophe,
> >>>
> >>> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
> >>> 2020 17:57:30 +0200:  
> >>>    >>>> This patch removes the constant FMC2_TIMEOUT_US.  
> >>>> FMC2_TIMEOUT_MS is set to 5 seconds and this constant is used
> >>>> each time that we need to wait (except when the timeout value
> >>>> is set by the framework)
> >>>>
> >>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> >>>> ---
> >>>>    drivers/mtd/nand/raw/stm32_fmc2_nand.c | 11 +++++------
> >>>>    1 file changed, 5 insertions(+), 6 deletions(-)
> >>>>
> >>>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >>>> index ab53314..f159c39 100644
> >>>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >>>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >>>> @@ -37,8 +37,7 @@
> >>>>    /* Max ECC buffer length */
> >>>>    #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)  
> >>>>    >> -#define FMC2_TIMEOUT_US			1000  
> >>>> -#define FMC2_TIMEOUT_MS			1000
> >>>> +#define FMC2_TIMEOUT_MS			5000  
> >>>>    >>   /* Timings */  
> >>>>    #define FMC2_THIZ			1
> >>>> @@ -525,9 +524,9 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
> >>>>    	u32 sr, heccr;
> >>>>    	int ret;  
> >>>>    >> -	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,  
> >>>> -					 sr, sr & FMC2_SR_NWRF, 10,
> >>>> -					 FMC2_TIMEOUT_MS);
> >>>> +	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
> >>>> +						sr, sr & FMC2_SR_NWRF, 1,
> >>>> +						1000 * FMC2_TIMEOUT_MS);  
> >>>
> >>> Is the _atomic suffix needed here? If yes it would deserve a separate
> >>> patch with Fixes/Stable tags.  
> >>>    >>  
> >> I have currently not seen any issues. So, I will remove this modification as we will move to regmap_read_poll_timeout in patch 10.
> >>  
> >>>>    	if (ret) {
> >>>>    		dev_err(fmc2->dev, "ham timeout\n");
> >>>>    		return ret;
> >>>> @@ -1315,7 +1314,7 @@ static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
> >>>>    	/* Check if there is no pending requests to the NAND flash */
> >>>>    	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
> >>>>    					      sr & FMC2_SR_NWRF, 1,
> >>>> -					      FMC2_TIMEOUT_US))
> >>>> +					      1000 * FMC2_TIMEOUT_MS))
> >>>>    		dev_warn(fmc2->dev, "Waitrdy timeout\n");  
> >>>>    >>   	/* Wait tWB before R/B# signal is low */  
> >>>
> >>> You change the timeouts from 1ms to 5s.
> >>>
> >>> Maybe 5s is a little bit too much IMHO but we don't really care as this
> >>> is a timeout. However 1ms is tight. If you are changing this value
> >>> because it triggers error (eg. when the machine is loaded), then it is
> >>> a fix and should appear like it.
> >>>
> >>> Thanks,
> >>> Miquèl  
> >>>    >>  
> >> No errors currently happens.
> >> During our stress tests, in a overloaded system, we have seen that we could be close to 1 second, even if we never met this value.
> >> So, to be safe, I have set this timeout to 5 seconds.
> >> As it is just a timeout value, I have not seen any side effect.
> >> I am using the same timeout constant to avoid to have one timeout per cases.  
> > 
> > Something is wrong in my mind:
> > You say you observe delays of almost up to 1 second, but the polling
> > currently happens on 1000 us = 1ms, either you had timeouts or I
> > misread something?
> > 
> > Thanks,
> > Miquèl
> >   
> 
> Hi Miquèl,
> 
> My fault. For this polling, we never met 1 ms.
> The 1 second observed was on the sequencer when we read/write a page (as it the same timeout value that is used)

OK I get it. So perhaps you can give these details in the commit log to
explain why you use 5 seconds instead of one.

Thanks,
Miquèl

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

* Re: [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  2020-04-29 10:06           ` Miquel Raynal
@ 2020-04-29 10:13             ` Christophe Kerello
  2020-04-29 10:27               ` Miquel Raynal
  0 siblings, 1 reply; 51+ messages in thread
From: Christophe Kerello @ 2020-04-29 10:13 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex



On 4/29/20 12:06 PM, Miquel Raynal wrote:
> Hi Christophe,
> 
> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
> 2020 11:41:44 +0200:
> 
>> On 4/29/20 11:35 AM, Miquel Raynal wrote:
>>> Hi Christophe,
>>>
>>> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
>>> 2020 11:27:43 +0200:
>>>    
>>>> Hi Miquèl,
>>>>
>>>> On 4/27/20 8:22 PM, Miquel Raynal wrote:
>>>>> Hi Christophe,
>>>>>
>>>>> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
>>>>> 2020 17:57:30 +0200:
>>>>>     >>>> This patch removes the constant FMC2_TIMEOUT_US.
>>>>>> FMC2_TIMEOUT_MS is set to 5 seconds and this constant is used
>>>>>> each time that we need to wait (except when the timeout value
>>>>>> is set by the framework)
>>>>>>
>>>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
>>>>>> ---
>>>>>>     drivers/mtd/nand/raw/stm32_fmc2_nand.c | 11 +++++------
>>>>>>     1 file changed, 5 insertions(+), 6 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>>>>>> index ab53314..f159c39 100644
>>>>>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>>>>>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
>>>>>> @@ -37,8 +37,7 @@
>>>>>>     /* Max ECC buffer length */
>>>>>>     #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
>>>>>>     >> -#define FMC2_TIMEOUT_US			1000
>>>>>> -#define FMC2_TIMEOUT_MS			1000
>>>>>> +#define FMC2_TIMEOUT_MS			5000
>>>>>>     >>   /* Timings */
>>>>>>     #define FMC2_THIZ			1
>>>>>> @@ -525,9 +524,9 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
>>>>>>     	u32 sr, heccr;
>>>>>>     	int ret;
>>>>>>     >> -	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,
>>>>>> -					 sr, sr & FMC2_SR_NWRF, 10,
>>>>>> -					 FMC2_TIMEOUT_MS);
>>>>>> +	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
>>>>>> +						sr, sr & FMC2_SR_NWRF, 1,
>>>>>> +						1000 * FMC2_TIMEOUT_MS);
>>>>>
>>>>> Is the _atomic suffix needed here? If yes it would deserve a separate
>>>>> patch with Fixes/Stable tags.
>>>>>     >>
>>>> I have currently not seen any issues. So, I will remove this modification as we will move to regmap_read_poll_timeout in patch 10.
>>>>   
>>>>>>     	if (ret) {
>>>>>>     		dev_err(fmc2->dev, "ham timeout\n");
>>>>>>     		return ret;
>>>>>> @@ -1315,7 +1314,7 @@ static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
>>>>>>     	/* Check if there is no pending requests to the NAND flash */
>>>>>>     	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
>>>>>>     					      sr & FMC2_SR_NWRF, 1,
>>>>>> -					      FMC2_TIMEOUT_US))
>>>>>> +					      1000 * FMC2_TIMEOUT_MS))
>>>>>>     		dev_warn(fmc2->dev, "Waitrdy timeout\n");
>>>>>>     >>   	/* Wait tWB before R/B# signal is low */
>>>>>
>>>>> You change the timeouts from 1ms to 5s.
>>>>>
>>>>> Maybe 5s is a little bit too much IMHO but we don't really care as this
>>>>> is a timeout. However 1ms is tight. If you are changing this value
>>>>> because it triggers error (eg. when the machine is loaded), then it is
>>>>> a fix and should appear like it.
>>>>>
>>>>> Thanks,
>>>>> Miquèl
>>>>>     >>
>>>> No errors currently happens.
>>>> During our stress tests, in a overloaded system, we have seen that we could be close to 1 second, even if we never met this value.
>>>> So, to be safe, I have set this timeout to 5 seconds.
>>>> As it is just a timeout value, I have not seen any side effect.
>>>> I am using the same timeout constant to avoid to have one timeout per cases.
>>>
>>> Something is wrong in my mind:
>>> You say you observe delays of almost up to 1 second, but the polling
>>> currently happens on 1000 us = 1ms, either you had timeouts or I
>>> misread something?
>>>
>>> Thanks,
>>> Miquèl
>>>    
>>
>> Hi Miquèl,
>>
>> My fault. For this polling, we never met 1 ms.
>> The 1 second observed was on the sequencer when we read/write a page (as it the same timeout value that is used)
> 
> OK I get it. So perhaps you can give these details in the commit log to
> explain why you use 5 seconds instead of one.
> 
> Thanks,
> Miquèl
> 

Hi Miquèl,

A proposal could also be to split this patch:
  - a first patch that is using only one timeout value.
  - a second patch that is increasing the value to 5 seconds.

Regards,
Christophe Kerello.

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

* Re: [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts
  2020-04-29 10:13             ` Christophe Kerello
@ 2020-04-29 10:27               ` Miquel Raynal
  0 siblings, 0 replies; 51+ messages in thread
From: Miquel Raynal @ 2020-04-29 10:27 UTC (permalink / raw)
  To: Christophe Kerello
  Cc: richard, vigneshr, lee.jones, robh+dt, mark.rutland, tony,
	linux-mtd, linux-kernel, linux-stm32, devicetree, marex

Hi Christophe,

Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
2020 12:13:18 +0200:

> On 4/29/20 12:06 PM, Miquel Raynal wrote:
> > Hi Christophe,
> > 
> > Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
> > 2020 11:41:44 +0200:
> >   
> >> On 4/29/20 11:35 AM, Miquel Raynal wrote:  
> >>> Hi Christophe,
> >>>
> >>> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 29 Apr
> >>> 2020 11:27:43 +0200:  
> >>>    >>>> Hi Miquèl,  
> >>>>
> >>>> On 4/27/20 8:22 PM, Miquel Raynal wrote:  
> >>>>> Hi Christophe,
> >>>>>
> >>>>> Christophe Kerello <christophe.kerello@st.com> wrote on Wed, 15 Apr
> >>>>> 2020 17:57:30 +0200:  
> >>>>>     >>>> This patch removes the constant FMC2_TIMEOUT_US.  
> >>>>>> FMC2_TIMEOUT_MS is set to 5 seconds and this constant is used
> >>>>>> each time that we need to wait (except when the timeout value
> >>>>>> is set by the framework)
> >>>>>>
> >>>>>> Signed-off-by: Christophe Kerello <christophe.kerello@st.com>
> >>>>>> ---
> >>>>>>     drivers/mtd/nand/raw/stm32_fmc2_nand.c | 11 +++++------
> >>>>>>     1 file changed, 5 insertions(+), 6 deletions(-)
> >>>>>>
> >>>>>> diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >>>>>> index ab53314..f159c39 100644
> >>>>>> --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >>>>>> +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
> >>>>>> @@ -37,8 +37,7 @@
> >>>>>>     /* Max ECC buffer length */
> >>>>>>     #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)  
> >>>>>>     >> -#define FMC2_TIMEOUT_US			1000  
> >>>>>> -#define FMC2_TIMEOUT_MS			1000
> >>>>>> +#define FMC2_TIMEOUT_MS			5000  
> >>>>>>     >>   /* Timings */  
> >>>>>>     #define FMC2_THIZ			1
> >>>>>> @@ -525,9 +524,9 @@ static int stm32_fmc2_ham_calculate(struct nand_chip *chip, const u8 *data,
> >>>>>>     	u32 sr, heccr;
> >>>>>>     	int ret;  
> >>>>>>     >> -	ret = readl_relaxed_poll_timeout(fmc2->io_base + FMC2_SR,  
> >>>>>> -					 sr, sr & FMC2_SR_NWRF, 10,
> >>>>>> -					 FMC2_TIMEOUT_MS);
> >>>>>> +	ret = readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR,
> >>>>>> +						sr, sr & FMC2_SR_NWRF, 1,
> >>>>>> +						1000 * FMC2_TIMEOUT_MS);  
> >>>>>
> >>>>> Is the _atomic suffix needed here? If yes it would deserve a separate
> >>>>> patch with Fixes/Stable tags.  
> >>>>>     >>  
> >>>> I have currently not seen any issues. So, I will remove this modification as we will move to regmap_read_poll_timeout in patch 10.  
> >>>>   >>>>>>     	if (ret) {  
> >>>>>>     		dev_err(fmc2->dev, "ham timeout\n");
> >>>>>>     		return ret;
> >>>>>> @@ -1315,7 +1314,7 @@ static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
> >>>>>>     	/* Check if there is no pending requests to the NAND flash */
> >>>>>>     	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
> >>>>>>     					      sr & FMC2_SR_NWRF, 1,
> >>>>>> -					      FMC2_TIMEOUT_US))
> >>>>>> +					      1000 * FMC2_TIMEOUT_MS))
> >>>>>>     		dev_warn(fmc2->dev, "Waitrdy timeout\n");  
> >>>>>>     >>   	/* Wait tWB before R/B# signal is low */  
> >>>>>
> >>>>> You change the timeouts from 1ms to 5s.
> >>>>>
> >>>>> Maybe 5s is a little bit too much IMHO but we don't really care as this
> >>>>> is a timeout. However 1ms is tight. If you are changing this value
> >>>>> because it triggers error (eg. when the machine is loaded), then it is
> >>>>> a fix and should appear like it.
> >>>>>
> >>>>> Thanks,
> >>>>> Miquèl  
> >>>>>     >>  
> >>>> No errors currently happens.
> >>>> During our stress tests, in a overloaded system, we have seen that we could be close to 1 second, even if we never met this value.
> >>>> So, to be safe, I have set this timeout to 5 seconds.
> >>>> As it is just a timeout value, I have not seen any side effect.
> >>>> I am using the same timeout constant to avoid to have one timeout per cases.  
> >>>
> >>> Something is wrong in my mind:
> >>> You say you observe delays of almost up to 1 second, but the polling
> >>> currently happens on 1000 us = 1ms, either you had timeouts or I
> >>> misread something?
> >>>
> >>> Thanks,
> >>> Miquèl  
> >>>    >>  
> >> Hi Miquèl,
> >>
> >> My fault. For this polling, we never met 1 ms.
> >> The 1 second observed was on the sequencer when we read/write a page (as it the same timeout value that is used)  
> > 
> > OK I get it. So perhaps you can give these details in the commit log to
> > explain why you use 5 seconds instead of one.
> > 
> > Thanks,
> > Miquèl
> >   
> 
> Hi Miquèl,
> 
> A proposal could also be to split this patch:
>   - a first patch that is using only one timeout value.
>   - a second patch that is increasing the value to 5 seconds.
> 
> Regards,
> Christophe Kerello.


Given the situation, both are fine as long as everything is clearly
explained in the commit log :)

Thanks,
Miquèl

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

end of thread, other threads:[~2020-04-29 10:27 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-15 15:57 [PATCH v2 00/12] add STM32 FMC2 controller drivers Christophe Kerello
2020-04-15 15:57 ` [PATCH v2 01/12] dt-bindings: mfd: stm32-fmc2: add STM32 FMC2 controller documentation Christophe Kerello
2020-04-28 15:28   ` Rob Herring
2020-04-29  9:35     ` Christophe Kerello
2020-04-15 15:57 ` [PATCH v2 02/12] mfd: stm32-fmc2: add STM32 FMC2 controller driver Christophe Kerello
2020-04-24  7:45   ` Lee Jones
2020-04-24 10:27     ` Marek Vasut
2020-04-24 10:50       ` Lee Jones
2020-04-24 11:06         ` Marek Vasut
2020-04-24 11:47           ` Christophe Kerello
2020-04-24 14:50             ` Lee Jones
2020-04-24 15:14             ` Boris Brezillon
2020-04-24 16:42               ` Christophe Kerello
2020-04-24 17:22                 ` Boris Brezillon
2020-04-24 17:34                   ` Christophe Kerello
2020-04-15 15:57 ` [PATCH v2 03/12] bus: stm32-fmc2-ebi: add STM32 FMC2 EBI " Christophe Kerello
2020-04-16 19:53   ` Boris Brezillon
2020-04-17 15:29     ` Christophe Kerello
2020-04-17 15:31       ` Marek Vasut
2020-04-17 15:41         ` Boris Brezillon
2020-04-17 15:44           ` Marek Vasut
2020-04-15 15:57 ` [PATCH v2 04/12] mtd: rawnand: stm32_fmc2: manage all errors cases at probe time Christophe Kerello
2020-04-27 17:47   ` Miquel Raynal
2020-04-27 17:59     ` Marek Vasut
2020-04-27 18:08       ` Miquel Raynal
2020-04-27 19:46         ` Marek Vasut
2020-04-27 20:08           ` Miquel Raynal
2020-04-27 20:10             ` Marek Vasut
2020-04-29  8:00               ` Christophe Kerello
2020-04-29  9:07             ` Christophe Kerello
2020-04-15 15:57 ` [PATCH v2 05/12] mtd: rawnand: stm32_fmc2: remove useless inline comments Christophe Kerello
2020-04-27 17:48   ` Miquel Raynal
2020-04-15 15:57 ` [PATCH v2 06/12] mtd: rawnand: stm32_fmc2: use FMC2_TIMEOUT_MS for timeouts Christophe Kerello
2020-04-27 18:22   ` Miquel Raynal
2020-04-29  9:27     ` Christophe Kerello
2020-04-29  9:35       ` Miquel Raynal
2020-04-29  9:41         ` Christophe Kerello
2020-04-29 10:06           ` Miquel Raynal
2020-04-29 10:13             ` Christophe Kerello
2020-04-29 10:27               ` Miquel Raynal
2020-04-15 15:57 ` [PATCH v2 07/12] mtd: rawnand: stm32_fmc2: cleanup Christophe Kerello
2020-04-27 18:33   ` Miquel Raynal
2020-04-29  9:31     ` Christophe Kerello
2020-04-15 15:57 ` [PATCH v2 08/12] mtd: rawnand: stm32_fmc2: use FIELD_PREP/FIELD_GET macros Christophe Kerello
2020-04-16 19:45   ` Boris Brezillon
2020-04-27 18:50     ` Miquel Raynal
2020-04-15 15:57 ` [PATCH v2 09/12] mtd: rawnand: stm32_fmc2: move all registers Christophe Kerello
2020-04-15 15:57 ` [PATCH v2 10/12] mtd: rawnand: stm32_fmc2: use regmap APIs Christophe Kerello
2020-04-27 18:52   ` Miquel Raynal
2020-04-15 15:57 ` [PATCH v2 11/12] mtd: rawnand: stm32_fmc2: use stm32_fmc2 structure in nfc controller Christophe Kerello
2020-04-15 15:57 ` [PATCH v2 12/12] mtd: rawnand: stm32_fmc2: add new MP1 compatible string Christophe Kerello

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