1
From: Patrice Chotard <patrice.chotard@foss.st.com>
1
This series adds SPI NOR support for STM32MP25 SoCs from STMicroelectronics.
2
2
3
This series adds SPI NOR support for STM32MP25 SoCs from STMicroelectronics,
3
On STM32MP25 SoCs family, an Octo Memory Manager block manages the muxing,
4
for that it adds support for:
4
the memory area split, the chip select override and the time constraint
5
between its 2 Octo SPI children.
6
7
Due to these depedencies, this series adds support for:
5
- Octo Memory Manager driver.
8
- Octo Memory Manager driver.
6
- Octo SPI driver.
9
- Octo SPI driver.
7
- yaml schema for Octo Memory Manager and Octo SPI drivers.
10
- yaml schema for Octo Memory Manager and Octo SPI drivers.
8
11
9
The device tree files adds Octo Memory Manager and associated Octo SPI instances
12
The device tree files adds Octo Memory Manager and its 2 associated Octo
10
in stm32mp251.dtsi and adds SPI NOR support in stm32mp257f-ev1 board.
13
SPI chidren in stm32mp251.dtsi and adds SPI NOR support in stm32mp257f-ev1
14
board.
15
16
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
17
18
Changes in v7:
19
- update OMM's dt-bindings by updating :
20
- clock-names and reset-names properties.
21
- spi unit-address node.
22
- example.
23
- update stm32mp251.dtsi to match with OMM's bindings update.
24
- update stm32mp257f-ev1.dts to match with OMM's bindings update.
25
- Link to v6: https://lore.kernel.org/r/20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com
26
27
Changes in v6:
28
- Update MAINTAINERS file.
29
- Remove previous patch 1/8 and 2/8, merged by Mark Brown in spi git tree.
30
- Fix Signed-off-by order for patch 3.
31
- OMM driver:
32
- Add dev_err_probe() in error path.
33
- Rename stm32_omm_enable_child_clock() to stm32_omm_toggle_child_clock().
34
- Reorder initialised/non-initialized variable in stm32_omm_configure()
35
and stm32_omm_probe().
36
- Move pm_runtime_disable() calls from stm32_omm_configure() to
37
stm32_omm_probe().
38
- Update children's clocks and reset management.
39
- Use of_platform_populate() to probe children.
40
- Add missing pm_runtime_disable().
41
- Remove useless stm32_omm_check_access's first parameter.
42
- Update OMM's dt-bindings by adding OSPI's clocks and resets.
43
- Update stm32mp251.dtsi by adding OSPI's clock and reset in OMM's node.
44
45
Changes in v5:
46
- Add Reviewed-by Krzysztof Kozlowski for patch 1 and 3.
47
48
Changes in v4:
49
- Add default value requested by Krzysztof for st,omm-req2ack-ns,
50
st,omm-cssel-ovr and st,omm-mux properties in st,stm32mp25-omm.yaml
51
- Remove constraint in free form test for st,omm-mux property.
52
- Fix drivers/memory/Kconfig by replacing TEST_COMPILE_ by COMPILE_TEST.
53
- Fix SPDX-License-Identifier for stm32-omm.c.
54
- Fix Kernel test robot by fixing dev_err() format in stm32-omm.c.
55
- Add missing pm_runtime_disable() in the error handling path in
56
stm32-omm.c.
57
- Replace an int by an unsigned int in stm32-omm.c
58
- Remove uneeded "," after terminator in stm32-omm.c.
59
- Update cover letter description to explain dependecies between
60
Octo Memory Manager and its 2 Octo SPI children.
61
62
Changes in v3:
63
- Squash defconfig patches 8 and 9.
64
- Update STM32 Octo Memory Manager controller bindings.
65
- Rename st,stm32-omm.yaml to st,stm32mp25-omm.yaml.
66
- Update STM32 OSPI controller bindings.
67
- Reorder DT properties in .dtsi and .dts files.
68
- Replace devm_reset_control_get_optional() by
69
devm_reset_control_get_optional_exclusive() in stm32_omm.c.
70
- Reintroduce region-memory-names management in stm32_omm.c.
71
- Rename stm32_ospi_tx_poll() and stm32_ospi_tx() to respectively to
72
stm32_ospi_poll() and stm32_ospi_xfer() in spi-stm32-ospi.c.
73
- Set SPI_CONTROLLER_HALF_DUPLEX in controller flags in spi-stm32-ospi.c.
74
75
Changes in v2:
76
- Move STM32 Octo Memory Manager controller driver and bindings from
77
misc to memory-controllers.
78
- Update STM32 OSPI controller bindings.
79
- Update STM32 Octo Memory Manager controller bindings.
80
- Update STM32 Octo Memory Manager driver to match bindings update.
81
- Update DT to match bindings update.
11
82
12
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
83
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
84
---
85
Patrice Chotard (7):
86
MAINTAINERS: add entry for STM32 OCTO MEMORY MANAGER driver
87
dt-bindings: memory-controllers: Add STM32 Octo Memory Manager controller
88
memory: Add STM32 Octo Memory Manager driver
89
arm64: dts: st: Add OMM node on stm32mp251
90
arm64: dts: st: Add ospi port1 pinctrl entries in stm32mp25-pinctrl.dtsi
91
arm64: dts: st: Add SPI NOR flash support on stm32mp257f-ev1 board
92
arm64: defconfig: Enable STM32 Octo Memory Manager and OcstoSPI driver
13
93
14
Patrice Chotard (9):
94
.../memory-controllers/st,stm32mp25-omm.yaml | 227 ++++++++++
15
dt-bindings: spi: Add STM32 OSPI controller
95
MAINTAINERS | 6 +
16
spi: stm32: Add OSPI driver
96
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +++
17
dt-bindings: misc: Add STM32 Octo Memory Manager controller
97
arch/arm64/boot/dts/st/stm32mp251.dtsi | 54 +++
18
misc: Add STM32 Octo Memory Manager driver
98
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 32 ++
19
arm64: dts: st: Add OMM node on stm32mp251
99
arch/arm64/configs/defconfig | 2 +
20
arm64: dts: st: Add ospi port1 pinctrl entries in
100
drivers/memory/Kconfig | 17 +
21
stm32mp25-pinctrl.dtsi
101
drivers/memory/Makefile | 1 +
22
arm64: dts: st: Add SPI NOR flash support on stm32mp257f-ev1 board
102
drivers/memory/stm32_omm.c | 474 +++++++++++++++++++++
23
arm64: defconfig: Enable STM32 Octo Memory Manager driver
103
9 files changed, 864 insertions(+)
24
arm64: defconfig: Enable STM32 OctoSPI driver
104
---
105
base-commit: 88424abd55ab36c3565898a656589a0a25ecd92f
106
change-id: 20250320-upstream_ospi_v6-d432a8172105
25
107
26
.../bindings/misc/st,stm32-omm.yaml | 194 +++
108
Best regards,
27
.../bindings/spi/st,stm32-ospi.yaml | 109 ++
28
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +
29
arch/arm64/boot/dts/st/stm32mp251.dtsi | 48 +
30
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 33 +
31
arch/arm64/configs/defconfig | 2 +
32
drivers/misc/Kconfig | 17 +
33
drivers/misc/Makefile | 1 +
34
drivers/misc/stm32_omm.c | 510 ++++++++
35
drivers/spi/Kconfig | 10 +
36
drivers/spi/Makefile | 1 +
37
drivers/spi/spi-stm32-ospi.c | 1064 +++++++++++++++++
38
12 files changed, 2040 insertions(+)
39
create mode 100644 Documentation/devicetree/bindings/misc/st,stm32-omm.yaml
40
create mode 100644 Documentation/devicetree/bindings/spi/st,stm32-ospi.yaml
41
create mode 100644 drivers/misc/stm32_omm.c
42
create mode 100644 drivers/spi/spi-stm32-ospi.c
43
44
--
109
--
45
2.25.1
110
Patrice Chotard <patrice.chotard@foss.st.com>
diff view generated by jsdifflib
Deleted patch
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
2
1
3
Add device tree bindings for the STM32 OSPI controller.
4
5
Main features of the Octo-SPI controller :
6
- support sNOR / sNAND / HyperRAM™ and HyperFlash™ devices.
7
- Three functional modes: indirect, automatic-status polling,
8
memory-mapped.
9
- Up to 4 Gbytes of external memory can be addressed in indirect
10
mode (per physical port and per CS), and up to 256 Mbytes in
11
memory-mapped mode (combined for both physical ports and per CS).
12
- Single-, dual-, quad-, and octal-SPI communication.
13
- Dual-quad communication.
14
- Single data rate (SDR) and double transfer rate (DTR).
15
- Maximum target frequency is 133 MHz for SDR and 133 MHz for DTR.
16
- Data strobe support.
17
- DMA channel for indirect mode.
18
- Double CS mapping that allows two external flash devices to be
19
addressed with a single OCTOSPI controller mapped on a single
20
OCTOSPI port.
21
22
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
23
---
24
.../bindings/spi/st,stm32-ospi.yaml | 109 ++++++++++++++++++
25
1 file changed, 109 insertions(+)
26
create mode 100644 Documentation/devicetree/bindings/spi/st,stm32-ospi.yaml
27
28
diff --git a/Documentation/devicetree/bindings/spi/st,stm32-ospi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-ospi.yaml
29
new file mode 100644
30
index XXXXXXX..XXXXXXX
31
--- /dev/null
32
+++ b/Documentation/devicetree/bindings/spi/st,stm32-ospi.yaml
33
@@ -XXX,XX +XXX,XX @@
34
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
35
+%YAML 1.2
36
+---
37
+$id: http://devicetree.org/schemas/spi/st,stm32-ospi.yaml#
38
+$schema: http://devicetree.org/meta-schemas/core.yaml#
39
+
40
+title: STMicroelectronics STM32 Octal Serial Peripheral Interface (OSPI)
41
+
42
+maintainers:
43
+ - Patrice Chotard <patrice.chotard@foss.st.com>
44
+
45
+allOf:
46
+ - $ref: spi-controller.yaml#
47
+
48
+properties:
49
+ compatible:
50
+ const: st,stm32mp25-ospi
51
+
52
+ reg:
53
+ description: registers
54
+
55
+ "#address-cells":
56
+ const: 1
57
+
58
+ "#size-cells":
59
+ const: 0
60
+
61
+ memory-region:
62
+ maxItems: 1
63
+ description: Phandle to a node describing memory-map region to be used
64
+
65
+ clocks:
66
+ maxItems: 1
67
+
68
+ interrupts:
69
+ maxItems: 1
70
+
71
+ resets:
72
+ maxItems: 2
73
+
74
+ dmas:
75
+ items:
76
+ - description: tx DMA channel
77
+ - description: rx DMA channel
78
+
79
+ dma-names:
80
+ items:
81
+ - const: tx
82
+ - const: rx
83
+
84
+ st,syscfg-dlyb:
85
+ description: |
86
+ Use to set the OSPI delay block within SYSCFG to:
87
+ Tune the phase of the RX sampling clock (or DQS) in order
88
+ to sample the data in their valid window.
89
+ Tune the phase of the TX launch clock in order to meet setup
90
+ and hold constraints of TX signals versus the memory clock.
91
+ $ref: /schemas/types.yaml#/definitions/phandle-array
92
+ items:
93
+ minItems: 2
94
+ maxItems: 2
95
+
96
+ access-controllers:
97
+ minItems: 1
98
+ maxItems: 2
99
+
100
+ power-domains:
101
+ maxItems: 1
102
+
103
+required:
104
+ - compatible
105
+ - reg
106
+ - "#address-cells"
107
+ - "#size-cells"
108
+ - clocks
109
+ - interrupts
110
+ - st,syscfg-dlyb
111
+
112
+unevaluatedProperties: false
113
+
114
+examples:
115
+ - |
116
+ #include <dt-bindings/clock/st,stm32mp25-rcc.h>
117
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
118
+ #include <dt-bindings/reset/st,stm32mp25-rcc.h>
119
+ spi@40430000 {
120
+ compatible = "st,stm32mp25-ospi";
121
+ reg = <0x40430000 0x400>;
122
+ memory-region = <&mm_ospi1>;
123
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
124
+ dmas = <&hpdma 2 0x62 0x00003121 0x0>,
125
+ <&hpdma 2 0x42 0x00003112 0x0>;
126
+ dma-names = "tx", "rx";
127
+ clocks = <&scmi_clk CK_SCMI_OSPI1>;
128
+ resets = <&scmi_reset RST_SCMI_OSPI1>, <&scmi_reset RST_SCMI_OSPI1DLL>;
129
+ access-controllers = <&rifsc 74>;
130
+ power-domains = <&CLUSTER_PD>;
131
+ st,syscfg-dlyb = <&syscfg 0x1000>;
132
+
133
+ #address-cells = <1>;
134
+ #size-cells = <0>;
135
+
136
+ flash@0 {
137
+ compatible = "jedec,spi-nor";
138
+ reg = <0>;
139
+ spi-rx-bus-width = <4>;
140
+ spi-max-frequency = <108000000>;
141
+ };
142
+ };
143
--
144
2.25.1
145
diff view generated by jsdifflib
Deleted patch
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
2
1
3
Add STM32 OSPI driver, it supports :
4
- support sNOR / sNAND devices.
5
- Three functional modes: indirect, automatic-status polling,
6
memory-mapped.
7
- Single-, dual-, quad-, and octal-SPI communication.
8
- Dual-quad communication.
9
- Single data rate (SDR).
10
- DMA channel for indirect mode.
11
12
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
13
---
14
drivers/spi/Kconfig | 10 +
15
drivers/spi/Makefile | 1 +
16
drivers/spi/spi-stm32-ospi.c | 1064 ++++++++++++++++++++++++++++++++++
17
3 files changed, 1075 insertions(+)
18
create mode 100644 drivers/spi/spi-stm32-ospi.c
19
20
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
21
index XXXXXXX..XXXXXXX 100644
22
--- a/drivers/spi/Kconfig
23
+++ b/drivers/spi/Kconfig
24
@@ -XXX,XX +XXX,XX @@ config SPI_STM32
25
     is not available, the driver automatically falls back to
26
     PIO mode.
27
28
+config SPI_STM32_OSPI
29
+    tristate "STMicroelectronics STM32 OCTO SPI controller"
30
+    depends on ARCH_STM32 || COMPILE_TEST
31
+    depends on OF
32
+    depends on SPI_MEM
33
+    help
34
+     This enables support for the Octo SPI controller in master mode.
35
+     This driver does not support generic SPI. The implementation only
36
+     supports spi-mem interface.
37
+
38
config SPI_STM32_QSPI
39
    tristate "STMicroelectronics STM32 QUAD SPI controller"
40
    depends on ARCH_STM32 || COMPILE_TEST
41
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
42
index XXXXXXX..XXXXXXX 100644
43
--- a/drivers/spi/Makefile
44
+++ b/drivers/spi/Makefile
45
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_SPI_SPRD)            += spi-sprd.o
46
obj-$(CONFIG_SPI_SPRD_ADI)        += spi-sprd-adi.o
47
obj-$(CONFIG_SPI_STM32)         += spi-stm32.o
48
obj-$(CONFIG_SPI_STM32_QSPI)         += spi-stm32-qspi.o
49
+obj-$(CONFIG_SPI_STM32_OSPI)         += spi-stm32-ospi.o
50
obj-$(CONFIG_SPI_ST_SSC4)        += spi-st-ssc4.o
51
obj-$(CONFIG_SPI_SUN4I)            += spi-sun4i.o
52
obj-$(CONFIG_SPI_SUN6I)            += spi-sun6i.o
53
diff --git a/drivers/spi/spi-stm32-ospi.c b/drivers/spi/spi-stm32-ospi.c
54
new file mode 100644
55
index XXXXXXX..XXXXXXX
56
--- /dev/null
57
+++ b/drivers/spi/spi-stm32-ospi.c
58
@@ -XXX,XX +XXX,XX @@
59
+// SPDX-License-Identifier: GPL-2.0
60
+/*
61
+ * Copyright (C) STMicroelectronics 2025 - All Rights Reserved
62
+ */
63
+
64
+#include <linux/bitfield.h>
65
+#include <linux/clk.h>
66
+#include <linux/delay.h>
67
+#include <linux/dma-mapping.h>
68
+#include <linux/dmaengine.h>
69
+#include <linux/err.h>
70
+#include <linux/errno.h>
71
+#include <linux/interrupt.h>
72
+#include <linux/io.h>
73
+#include <linux/iopoll.h>
74
+#include <linux/mfd/syscon.h>
75
+#include <linux/module.h>
76
+#include <linux/mutex.h>
77
+#include <linux/of.h>
78
+#include <linux/of_address.h>
79
+#include <linux/of_device.h>
80
+#include <linux/of_gpio.h>
81
+#include <linux/of_reserved_mem.h>
82
+#include <linux/pinctrl/consumer.h>
83
+#include <linux/platform_device.h>
84
+#include <linux/pm_runtime.h>
85
+#include <linux/reset.h>
86
+#include <linux/sizes.h>
87
+#include <linux/spi/spi-mem.h>
88
+#include <linux/types.h>
89
+
90
+#define OSPI_CR            0x00
91
+#define CR_EN            BIT(0)
92
+#define CR_ABORT        BIT(1)
93
+#define CR_DMAEN        BIT(2)
94
+#define CR_FTHRES_SHIFT        8
95
+#define CR_TEIE            BIT(16)
96
+#define CR_TCIE            BIT(17)
97
+#define CR_SMIE            BIT(19)
98
+#define CR_APMS            BIT(22)
99
+#define CR_CSSEL        BIT(24)
100
+#define CR_FMODE_MASK        GENMASK(29, 28)
101
+#define CR_FMODE_INDW        (0U)
102
+#define CR_FMODE_INDR        (1U)
103
+#define CR_FMODE_APM        (2U)
104
+#define CR_FMODE_MM        (3U)
105
+
106
+#define OSPI_DCR1        0x08
107
+#define DCR1_DLYBYP        BIT(3)
108
+#define DCR1_DEVSIZE_MASK    GENMASK(20, 16)
109
+#define DCR1_MTYP_MASK        GENMASK(26, 24)
110
+#define DCR1_MTYP_MX_MODE    1
111
+#define DCR1_MTYP_HP_MEMMODE    4
112
+
113
+#define OSPI_DCR2        0x0c
114
+#define DCR2_PRESC_MASK        GENMASK(7, 0)
115
+
116
+#define OSPI_SR            0x20
117
+#define SR_TEF            BIT(0)
118
+#define SR_TCF            BIT(1)
119
+#define SR_FTF            BIT(2)
120
+#define SR_SMF            BIT(3)
121
+#define SR_BUSY            BIT(5)
122
+
123
+#define OSPI_FCR        0x24
124
+#define FCR_CTEF        BIT(0)
125
+#define FCR_CTCF        BIT(1)
126
+#define FCR_CSMF        BIT(3)
127
+
128
+#define OSPI_DLR        0x40
129
+#define OSPI_AR            0x48
130
+#define OSPI_DR            0x50
131
+#define OSPI_PSMKR        0x80
132
+#define OSPI_PSMAR        0x88
133
+
134
+#define OSPI_CCR        0x100
135
+#define CCR_IMODE_MASK        GENMASK(2, 0)
136
+#define CCR_IDTR        BIT(3)
137
+#define CCR_ISIZE_MASK        GENMASK(5, 4)
138
+#define CCR_ADMODE_MASK        GENMASK(10, 8)
139
+#define CCR_ADMODE_8LINES    4
140
+#define CCR_ADDTR        BIT(11)
141
+#define CCR_ADSIZE_MASK        GENMASK(13, 12)
142
+#define CCR_ADSIZE_32BITS    3
143
+#define CCR_DMODE_MASK        GENMASK(26, 24)
144
+#define CCR_DMODE_8LINES    4
145
+#define CCR_DQSE        BIT(29)
146
+#define CCR_DDTR        BIT(27)
147
+#define CCR_BUSWIDTH_0        0x0
148
+#define CCR_BUSWIDTH_1        0x1
149
+#define CCR_BUSWIDTH_2        0x2
150
+#define CCR_BUSWIDTH_4        0x3
151
+#define CCR_BUSWIDTH_8        0x4
152
+
153
+#define OSPI_TCR        0x108
154
+#define TCR_DCYC_MASK        GENMASK(4, 0)
155
+#define TCR_DHQC        BIT(28)
156
+#define TCR_SSHIFT        BIT(30)
157
+
158
+#define OSPI_IR            0x110
159
+
160
+#define STM32_OSPI_MAX_MMAP_SZ    SZ_256M
161
+#define STM32_OSPI_MAX_NORCHIP    2
162
+
163
+#define STM32_FIFO_TIMEOUT_US        30000
164
+#define STM32_ABT_TIMEOUT_US        100000
165
+#define STM32_COMP_TIMEOUT_MS        5000
166
+#define STM32_BUSY_TIMEOUT_US        100000
167
+
168
+
169
+#define STM32_AUTOSUSPEND_DELAY -1
170
+
171
+struct stm32_ospi {
172
+    struct device *dev;
173
+    struct spi_controller *ctrl;
174
+    struct clk *clk;
175
+    struct reset_control *rstc;
176
+
177
+    struct completion data_completion;
178
+    struct completion match_completion;
179
+
180
+    struct dma_chan *dma_chtx;
181
+    struct dma_chan *dma_chrx;
182
+    struct completion dma_completion;
183
+
184
+    void __iomem *regs_base;
185
+    void __iomem *mm_base;
186
+    phys_addr_t regs_phys_base;
187
+    resource_size_t mm_size;
188
+    u32 clk_rate;
189
+    u32 fmode;
190
+    u32 cr_reg;
191
+    u32 dcr_reg;
192
+    u32 flash_presc[STM32_OSPI_MAX_NORCHIP];
193
+    int irq;
194
+    unsigned long status_timeout;
195
+
196
+    /*
197
+     * To protect device configuration, could be different between
198
+     * 2 flash access
199
+     */
200
+    struct mutex lock;
201
+};
202
+
203
+static void stm32_ospi_read_fifo(u8 *val, void __iomem *addr)
204
+{
205
+    *val = readb_relaxed(addr);
206
+}
207
+
208
+static void stm32_ospi_write_fifo(u8 *val, void __iomem *addr)
209
+{
210
+    writeb_relaxed(*val, addr);
211
+}
212
+
213
+static int stm32_ospi_abort(struct stm32_ospi *ospi)
214
+{
215
+    void __iomem *regs_base = ospi->regs_base;
216
+    u32 cr;
217
+    int timeout;
218
+
219
+    cr = readl_relaxed(regs_base + OSPI_CR) | CR_ABORT;
220
+    writel_relaxed(cr, regs_base + OSPI_CR);
221
+
222
+    /* wait clear of abort bit by hw */
223
+    timeout = readl_relaxed_poll_timeout_atomic(regs_base + OSPI_CR,
224
+                         cr, !(cr & CR_ABORT), 1,
225
+                         STM32_ABT_TIMEOUT_US);
226
+
227
+    if (timeout)
228
+        dev_err(ospi->dev, "%s abort timeout:%d\n", __func__, timeout);
229
+
230
+    return timeout;
231
+}
232
+
233
+static int stm32_ospi_tx_poll(struct stm32_ospi *ospi, u8 *buf, u32 len, bool read)
234
+{
235
+    void __iomem *regs_base = ospi->regs_base;
236
+    void (*tx_fifo)(u8 *val, void __iomem *addr);
237
+    u32 sr;
238
+    int ret;
239
+
240
+    if (read)
241
+        tx_fifo = stm32_ospi_read_fifo;
242
+    else
243
+        tx_fifo = stm32_ospi_write_fifo;
244
+
245
+    while (len--) {
246
+        ret = readl_relaxed_poll_timeout_atomic(regs_base + OSPI_SR,
247
+                            sr, sr & SR_FTF, 1,
248
+                            STM32_FIFO_TIMEOUT_US);
249
+        if (ret) {
250
+            dev_err(ospi->dev, "fifo timeout (len:%d stat:%#x)\n",
251
+                len, sr);
252
+            return ret;
253
+        }
254
+        tx_fifo(buf++, regs_base + OSPI_DR);
255
+    }
256
+
257
+    return 0;
258
+}
259
+
260
+static int stm32_ospi_wait_nobusy(struct stm32_ospi *ospi)
261
+{
262
+    u32 sr;
263
+
264
+    return readl_relaxed_poll_timeout_atomic(ospi->regs_base + OSPI_SR,
265
+                         sr, !(sr & SR_BUSY), 1,
266
+                         STM32_BUSY_TIMEOUT_US);
267
+}
268
+
269
+static int stm32_ospi_wait_cmd(struct stm32_ospi *ospi)
270
+{
271
+    void __iomem *regs_base = ospi->regs_base;
272
+    u32 cr, sr;
273
+    int err = 0;
274
+
275
+    if ((readl_relaxed(regs_base + OSPI_SR) & SR_TCF) ||
276
+     ospi->fmode == CR_FMODE_APM)
277
+        goto out;
278
+
279
+    reinit_completion(&ospi->data_completion);
280
+    cr = readl_relaxed(regs_base + OSPI_CR);
281
+    writel_relaxed(cr | CR_TCIE | CR_TEIE, regs_base + OSPI_CR);
282
+
283
+    if (!wait_for_completion_timeout(&ospi->data_completion,
284
+                msecs_to_jiffies(STM32_COMP_TIMEOUT_MS)))
285
+        err = -ETIMEDOUT;
286
+
287
+    sr = readl_relaxed(regs_base + OSPI_SR);
288
+    if (sr & SR_TCF)
289
+        /* avoid false timeout */
290
+        err = 0;
291
+    if (sr & SR_TEF)
292
+        err = -EIO;
293
+
294
+out:
295
+    /* clear flags */
296
+    writel_relaxed(FCR_CTCF | FCR_CTEF, regs_base + OSPI_FCR);
297
+
298
+    if (!err)
299
+        err = stm32_ospi_wait_nobusy(ospi);
300
+
301
+    return err;
302
+}
303
+
304
+static void stm32_ospi_dma_callback(void *arg)
305
+{
306
+    struct completion *dma_completion = arg;
307
+
308
+    complete(dma_completion);
309
+}
310
+
311
+static irqreturn_t stm32_ospi_irq(int irq, void *dev_id)
312
+{
313
+    struct stm32_ospi *ospi = (struct stm32_ospi *)dev_id;
314
+    void __iomem *regs_base = ospi->regs_base;
315
+    u32 cr, sr;
316
+
317
+    cr = readl_relaxed(regs_base + OSPI_CR);
318
+    sr = readl_relaxed(regs_base + OSPI_SR);
319
+
320
+    if (cr & CR_SMIE && sr & SR_SMF) {
321
+        /* disable irq */
322
+        cr &= ~CR_SMIE;
323
+        writel_relaxed(cr, regs_base + OSPI_CR);
324
+        complete(&ospi->match_completion);
325
+
326
+        return IRQ_HANDLED;
327
+    }
328
+
329
+    if (sr & (SR_TEF | SR_TCF)) {
330
+        /* disable irq */
331
+        cr &= ~CR_TCIE & ~CR_TEIE;
332
+        writel_relaxed(cr, regs_base + OSPI_CR);
333
+        complete(&ospi->data_completion);
334
+    }
335
+
336
+    return IRQ_HANDLED;
337
+}
338
+
339
+static void stm32_ospi_dma_setup(struct stm32_ospi *ospi,
340
+             struct dma_slave_config *dma_cfg)
341
+{
342
+    if (dma_cfg && ospi->dma_chrx) {
343
+        if (dmaengine_slave_config(ospi->dma_chrx, dma_cfg)) {
344
+            dev_err(ospi->dev, "dma rx config failed\n");
345
+            dma_release_channel(ospi->dma_chrx);
346
+            ospi->dma_chrx = NULL;
347
+        }
348
+    }
349
+
350
+    if (dma_cfg && ospi->dma_chtx) {
351
+        if (dmaengine_slave_config(ospi->dma_chtx, dma_cfg)) {
352
+            dev_err(ospi->dev, "dma tx config failed\n");
353
+            dma_release_channel(ospi->dma_chtx);
354
+            ospi->dma_chtx = NULL;
355
+        }
356
+    }
357
+
358
+    init_completion(&ospi->dma_completion);
359
+}
360
+
361
+static int stm32_ospi_tx_mm(struct stm32_ospi *ospi,
362
+             const struct spi_mem_op *op)
363
+{
364
+    memcpy_fromio(op->data.buf.in, ospi->mm_base + op->addr.val,
365
+         op->data.nbytes);
366
+    return 0;
367
+}
368
+
369
+static int stm32_ospi_tx_dma(struct stm32_ospi *ospi,
370
+             const struct spi_mem_op *op)
371
+{
372
+    struct dma_async_tx_descriptor *desc;
373
+    void __iomem *regs_base = ospi->regs_base;
374
+    enum dma_transfer_direction dma_dir;
375
+    struct dma_chan *dma_ch;
376
+    struct sg_table sgt;
377
+    dma_cookie_t cookie;
378
+    u32 cr, t_out;
379
+    int err;
380
+
381
+    if (op->data.dir == SPI_MEM_DATA_IN) {
382
+        dma_dir = DMA_DEV_TO_MEM;
383
+        dma_ch = ospi->dma_chrx;
384
+    } else {
385
+        dma_dir = DMA_MEM_TO_DEV;
386
+        dma_ch = ospi->dma_chtx;
387
+    }
388
+
389
+    /*
390
+     * Spi_map_buf return -EINVAL if the buffer is not DMA-able
391
+     * (DMA-able: in vmalloc | kmap | virt_addr_valid)
392
+     */
393
+    err = spi_controller_dma_map_mem_op_data(ospi->ctrl, op, &sgt);
394
+    if (err)
395
+        return err;
396
+
397
+    desc = dmaengine_prep_slave_sg(dma_ch, sgt.sgl, sgt.nents,
398
+                 dma_dir, DMA_PREP_INTERRUPT);
399
+    if (!desc) {
400
+        err = -ENOMEM;
401
+        goto out_unmap;
402
+    }
403
+
404
+    cr = readl_relaxed(regs_base + OSPI_CR);
405
+
406
+    reinit_completion(&ospi->dma_completion);
407
+    desc->callback = stm32_ospi_dma_callback;
408
+    desc->callback_param = &ospi->dma_completion;
409
+    cookie = dmaengine_submit(desc);
410
+    err = dma_submit_error(cookie);
411
+    if (err)
412
+        goto out;
413
+
414
+    dma_async_issue_pending(dma_ch);
415
+
416
+    writel_relaxed(cr | CR_DMAEN, regs_base + OSPI_CR);
417
+
418
+    t_out = sgt.nents * STM32_COMP_TIMEOUT_MS;
419
+    if (!wait_for_completion_timeout(&ospi->dma_completion,
420
+                     msecs_to_jiffies(t_out)))
421
+        err = -ETIMEDOUT;
422
+
423
+    if (err)
424
+        dmaengine_terminate_all(dma_ch);
425
+
426
+out:
427
+    writel_relaxed(cr & ~CR_DMAEN, regs_base + OSPI_CR);
428
+out_unmap:
429
+    spi_controller_dma_unmap_mem_op_data(ospi->ctrl, op, &sgt);
430
+
431
+    return err;
432
+}
433
+
434
+static int stm32_ospi_tx(struct stm32_ospi *ospi, const struct spi_mem_op *op)
435
+{
436
+    u8 *buf;
437
+
438
+    if (!op->data.nbytes)
439
+        return 0;
440
+
441
+    if (ospi->fmode == CR_FMODE_MM)
442
+        return stm32_ospi_tx_mm(ospi, op);
443
+    else if (((op->data.dir == SPI_MEM_DATA_IN && ospi->dma_chrx) ||
444
+         (op->data.dir == SPI_MEM_DATA_OUT && ospi->dma_chtx)) &&
445
+         op->data.nbytes > 8)
446
+        if (!stm32_ospi_tx_dma(ospi, op))
447
+            return 0;
448
+
449
+    if (op->data.dir == SPI_MEM_DATA_IN)
450
+        buf = op->data.buf.in;
451
+    else
452
+        buf = (u8 *)op->data.buf.out;
453
+
454
+    return stm32_ospi_tx_poll(ospi, buf, op->data.nbytes,
455
+                 op->data.dir == SPI_MEM_DATA_IN);
456
+}
457
+
458
+static int stm32_ospi_wait_poll_status(struct stm32_ospi *ospi,
459
+                 const struct spi_mem_op *op)
460
+{
461
+    void __iomem *regs_base = ospi->regs_base;
462
+    u32 cr;
463
+
464
+    reinit_completion(&ospi->match_completion);
465
+    cr = readl_relaxed(regs_base + OSPI_CR);
466
+    writel_relaxed(cr | CR_SMIE, regs_base + OSPI_CR);
467
+
468
+    if (!wait_for_completion_timeout(&ospi->match_completion,
469
+                     msecs_to_jiffies(ospi->status_timeout))) {
470
+        u32 sr = readl_relaxed(regs_base + OSPI_SR);
471
+
472
+        /* Avoid false timeout */
473
+        if (!(sr & SR_SMF))
474
+            return -ETIMEDOUT;
475
+    }
476
+
477
+    writel_relaxed(FCR_CSMF, regs_base + OSPI_FCR);
478
+
479
+    return 0;
480
+}
481
+
482
+static int stm32_ospi_get_mode(u8 buswidth)
483
+{
484
+    switch (buswidth) {
485
+    case 8:
486
+        return CCR_BUSWIDTH_8;
487
+    case 4:
488
+        return CCR_BUSWIDTH_4;
489
+    default:
490
+        return buswidth;
491
+    }
492
+}
493
+
494
+static int stm32_ospi_send(struct spi_device *spi, const struct spi_mem_op *op)
495
+{
496
+    struct stm32_ospi *ospi = spi_controller_get_devdata(spi->controller);
497
+    void __iomem *regs_base = ospi->regs_base;
498
+    u32 ccr, cr, dcr2, tcr;
499
+    int timeout, err = 0, err_poll_status = 0;
500
+    u8 cs = spi->chip_select[ffs(spi->cs_index_mask) - 1];
501
+
502
+    dev_dbg(ospi->dev, "cmd:%#x mode:%d.%d.%d.%d addr:%#llx len:%#x\n",
503
+        op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
504
+        op->dummy.buswidth, op->data.buswidth,
505
+        op->addr.val, op->data.nbytes);
506
+
507
+    cr = readl_relaxed(ospi->regs_base + OSPI_CR);
508
+    cr &= ~CR_CSSEL;
509
+    cr |= FIELD_PREP(CR_CSSEL, cs);
510
+    cr &= ~CR_FMODE_MASK;
511
+    cr |= FIELD_PREP(CR_FMODE_MASK, ospi->fmode);
512
+    writel_relaxed(cr, regs_base + OSPI_CR);
513
+
514
+    if (op->data.nbytes)
515
+        writel_relaxed(op->data.nbytes - 1, regs_base + OSPI_DLR);
516
+
517
+    /* set prescaler */
518
+    dcr2 = readl_relaxed(regs_base + OSPI_DCR2);
519
+    dcr2 |= FIELD_PREP(DCR2_PRESC_MASK, ospi->flash_presc[cs]);
520
+    writel_relaxed(dcr2, regs_base + OSPI_DCR2);
521
+
522
+    ccr = FIELD_PREP(CCR_IMODE_MASK, stm32_ospi_get_mode(op->cmd.buswidth));
523
+
524
+    if (op->addr.nbytes) {
525
+        ccr |= FIELD_PREP(CCR_ADMODE_MASK,
526
+                 stm32_ospi_get_mode(op->addr.buswidth));
527
+        ccr |= FIELD_PREP(CCR_ADSIZE_MASK, op->addr.nbytes - 1);
528
+    }
529
+
530
+    tcr = TCR_SSHIFT;
531
+    if (op->dummy.buswidth && op->dummy.nbytes) {
532
+        tcr |= FIELD_PREP(TCR_DCYC_MASK,
533
+                 op->dummy.nbytes * 8 / op->dummy.buswidth);
534
+    }
535
+    writel_relaxed(tcr, regs_base + OSPI_TCR);
536
+
537
+    if (op->data.nbytes) {
538
+        ccr |= FIELD_PREP(CCR_DMODE_MASK,
539
+                 stm32_ospi_get_mode(op->data.buswidth));
540
+    }
541
+
542
+    writel_relaxed(ccr, regs_base + OSPI_CCR);
543
+
544
+    /* set instruction, must be set after ccr register update */
545
+    writel_relaxed(op->cmd.opcode, regs_base + OSPI_IR);
546
+
547
+    if (op->addr.nbytes && ospi->fmode != CR_FMODE_MM)
548
+        writel_relaxed(op->addr.val, regs_base + OSPI_AR);
549
+
550
+    if (ospi->fmode == CR_FMODE_APM)
551
+        err_poll_status = stm32_ospi_wait_poll_status(ospi, op);
552
+
553
+    err = stm32_ospi_tx(ospi, op);
554
+
555
+    /*
556
+     * Abort in:
557
+     * -error case
558
+     * -read memory map: prefetching must be stopped if we read the last
559
+     * byte of device (device size - fifo size). like device size is not
560
+     * knows, the prefetching is always stop.
561
+     */
562
+    if (err || err_poll_status || ospi->fmode == CR_FMODE_MM)
563
+        goto abort;
564
+
565
+    /* Wait end of tx in indirect mode */
566
+    err = stm32_ospi_wait_cmd(ospi);
567
+    if (err)
568
+        goto abort;
569
+
570
+    return 0;
571
+
572
+abort:
573
+    timeout = stm32_ospi_abort(ospi);
574
+    writel_relaxed(FCR_CTCF | FCR_CSMF, regs_base + OSPI_FCR);
575
+
576
+    if (err || err_poll_status || timeout)
577
+        dev_err(ospi->dev, "%s err:%d err_poll_status:%d abort timeout:%d\n",
578
+            __func__, err, err_poll_status, timeout);
579
+
580
+    return err;
581
+}
582
+
583
+static int stm32_ospi_poll_status(struct spi_mem *mem,
584
+                 const struct spi_mem_op *op,
585
+                 u16 mask, u16 match,
586
+                 unsigned long initial_delay_us,
587
+                 unsigned long polling_rate_us,
588
+                 unsigned long timeout_ms)
589
+{
590
+    struct stm32_ospi *ospi = spi_controller_get_devdata(mem->spi->controller);
591
+    void __iomem *regs_base = ospi->regs_base;
592
+    int ret;
593
+
594
+    ret = pm_runtime_resume_and_get(ospi->dev);
595
+    if (ret < 0)
596
+        return ret;
597
+
598
+    mutex_lock(&ospi->lock);
599
+
600
+    writel_relaxed(mask, regs_base + OSPI_PSMKR);
601
+    writel_relaxed(match, regs_base + OSPI_PSMAR);
602
+    ospi->fmode = CR_FMODE_APM;
603
+    ospi->status_timeout = timeout_ms;
604
+
605
+    ret = stm32_ospi_send(mem->spi, op);
606
+    mutex_unlock(&ospi->lock);
607
+
608
+    pm_runtime_mark_last_busy(ospi->dev);
609
+    pm_runtime_put_autosuspend(ospi->dev);
610
+
611
+    return ret;
612
+}
613
+
614
+static int stm32_ospi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
615
+{
616
+    struct stm32_ospi *ospi = spi_controller_get_devdata(mem->spi->controller);
617
+    int ret;
618
+
619
+    ret = pm_runtime_resume_and_get(ospi->dev);
620
+    if (ret < 0)
621
+        return ret;
622
+
623
+    mutex_lock(&ospi->lock);
624
+    if (op->data.dir == SPI_MEM_DATA_IN && op->data.nbytes)
625
+        ospi->fmode = CR_FMODE_INDR;
626
+    else
627
+        ospi->fmode = CR_FMODE_INDW;
628
+
629
+    ret = stm32_ospi_send(mem->spi, op);
630
+    mutex_unlock(&ospi->lock);
631
+
632
+    pm_runtime_mark_last_busy(ospi->dev);
633
+    pm_runtime_put_autosuspend(ospi->dev);
634
+
635
+    return ret;
636
+}
637
+
638
+static int stm32_ospi_dirmap_create(struct spi_mem_dirmap_desc *desc)
639
+{
640
+    struct stm32_ospi *ospi = spi_controller_get_devdata(desc->mem->spi->controller);
641
+
642
+    if (desc->info.op_tmpl.data.dir == SPI_MEM_DATA_OUT)
643
+        return -EOPNOTSUPP;
644
+
645
+    /* Should never happen, as mm_base == null is an error probe exit condition */
646
+    if (!ospi->mm_base && desc->info.op_tmpl.data.dir == SPI_MEM_DATA_IN)
647
+        return -EOPNOTSUPP;
648
+
649
+    if (!ospi->mm_size)
650
+        return -EOPNOTSUPP;
651
+
652
+    return 0;
653
+}
654
+
655
+static ssize_t stm32_ospi_dirmap_read(struct spi_mem_dirmap_desc *desc,
656
+                 u64 offs, size_t len, void *buf)
657
+{
658
+    struct stm32_ospi *ospi = spi_controller_get_devdata(desc->mem->spi->controller);
659
+    struct spi_mem_op op;
660
+    u32 addr_max;
661
+    int ret;
662
+
663
+    ret = pm_runtime_resume_and_get(ospi->dev);
664
+    if (ret < 0)
665
+        return ret;
666
+
667
+    mutex_lock(&ospi->lock);
668
+    /*
669
+     * Make a local copy of desc op_tmpl and complete dirmap rdesc
670
+     * spi_mem_op template with offs, len and *buf in order to get
671
+     * all needed transfer information into struct spi_mem_op
672
+     */
673
+    memcpy(&op, &desc->info.op_tmpl, sizeof(struct spi_mem_op));
674
+    dev_dbg(ospi->dev, "%s len = 0x%zx offs = 0x%llx buf = 0x%p\n", __func__, len, offs, buf);
675
+
676
+    op.data.nbytes = len;
677
+    op.addr.val = desc->info.offset + offs;
678
+    op.data.buf.in = buf;
679
+
680
+    addr_max = op.addr.val + op.data.nbytes + 1;
681
+    if (addr_max < ospi->mm_size && op.addr.buswidth)
682
+        ospi->fmode = CR_FMODE_MM;
683
+    else
684
+        ospi->fmode = CR_FMODE_INDR;
685
+
686
+    ret = stm32_ospi_send(desc->mem->spi, &op);
687
+    mutex_unlock(&ospi->lock);
688
+
689
+    pm_runtime_mark_last_busy(ospi->dev);
690
+    pm_runtime_put_autosuspend(ospi->dev);
691
+
692
+    return ret ?: len;
693
+}
694
+
695
+static int stm32_ospi_transfer_one_message(struct spi_controller *ctrl,
696
+                     struct spi_message *msg)
697
+{
698
+    struct stm32_ospi *ospi = spi_controller_get_devdata(ctrl);
699
+    struct spi_transfer *transfer;
700
+    struct spi_device *spi = msg->spi;
701
+    struct spi_mem_op op;
702
+    struct gpio_desc *cs_gpiod = spi->cs_gpiod[ffs(spi->cs_index_mask) - 1];
703
+    int ret = 0;
704
+
705
+    if (!cs_gpiod)
706
+        return -EOPNOTSUPP;
707
+
708
+    ret = pm_runtime_resume_and_get(ospi->dev);
709
+    if (ret < 0)
710
+        return ret;
711
+
712
+    mutex_lock(&ospi->lock);
713
+
714
+    gpiod_set_value_cansleep(cs_gpiod, true);
715
+
716
+    list_for_each_entry(transfer, &msg->transfers, transfer_list) {
717
+        u8 dummy_bytes = 0;
718
+
719
+        memset(&op, 0, sizeof(op));
720
+
721
+        dev_dbg(ospi->dev, "tx_buf:%p tx_nbits:%d rx_buf:%p rx_nbits:%d len:%d dummy_data:%d\n",
722
+            transfer->tx_buf, transfer->tx_nbits,
723
+            transfer->rx_buf, transfer->rx_nbits,
724
+            transfer->len, transfer->dummy_data);
725
+
726
+        /*
727
+         * OSPI hardware supports dummy bytes transfer.
728
+         * If current transfer is dummy byte, merge it with the next
729
+         * transfer in order to take into account OSPI block constraint
730
+         */
731
+        if (transfer->dummy_data) {
732
+            op.dummy.buswidth = transfer->tx_nbits;
733
+            op.dummy.nbytes = transfer->len;
734
+            dummy_bytes = transfer->len;
735
+
736
+            /* If happens, means that message is not correctly built */
737
+            if (list_is_last(&transfer->transfer_list, &msg->transfers)) {
738
+                ret = -EINVAL;
739
+                goto end_of_transfer;
740
+            }
741
+
742
+            transfer = list_next_entry(transfer, transfer_list);
743
+        }
744
+
745
+        op.data.nbytes = transfer->len;
746
+
747
+        if (transfer->rx_buf) {
748
+            ospi->fmode = CR_FMODE_INDR;
749
+            op.data.buswidth = transfer->rx_nbits;
750
+            op.data.dir = SPI_MEM_DATA_IN;
751
+            op.data.buf.in = transfer->rx_buf;
752
+        } else {
753
+            ospi->fmode = CR_FMODE_INDW;
754
+            op.data.buswidth = transfer->tx_nbits;
755
+            op.data.dir = SPI_MEM_DATA_OUT;
756
+            op.data.buf.out = transfer->tx_buf;
757
+        }
758
+
759
+        ret = stm32_ospi_send(spi, &op);
760
+        if (ret)
761
+            goto end_of_transfer;
762
+
763
+        msg->actual_length += transfer->len + dummy_bytes;
764
+    }
765
+
766
+end_of_transfer:
767
+    gpiod_set_value_cansleep(cs_gpiod, false);
768
+
769
+    mutex_unlock(&ospi->lock);
770
+
771
+    msg->status = ret;
772
+    spi_finalize_current_message(ctrl);
773
+
774
+    pm_runtime_mark_last_busy(ospi->dev);
775
+    pm_runtime_put_autosuspend(ospi->dev);
776
+
777
+    return ret;
778
+}
779
+
780
+static int stm32_ospi_setup(struct spi_device *spi)
781
+{
782
+    struct spi_controller *ctrl = spi->controller;
783
+    struct stm32_ospi *ospi = spi_controller_get_devdata(ctrl);
784
+    void __iomem *regs_base = ospi->regs_base;
785
+    int ret;
786
+    u8 cs = spi->chip_select[ffs(spi->cs_index_mask) - 1];
787
+
788
+    if (ctrl->busy)
789
+        return -EBUSY;
790
+
791
+    if (!spi->max_speed_hz)
792
+        return -EINVAL;
793
+
794
+    ret = pm_runtime_resume_and_get(ospi->dev);
795
+    if (ret < 0)
796
+        return ret;
797
+
798
+    ospi->flash_presc[cs] = DIV_ROUND_UP(ospi->clk_rate, spi->max_speed_hz) - 1;
799
+
800
+    mutex_lock(&ospi->lock);
801
+
802
+    ospi->cr_reg = CR_APMS | 3 << CR_FTHRES_SHIFT | CR_EN;
803
+    writel_relaxed(ospi->cr_reg, regs_base + OSPI_CR);
804
+
805
+    /* set dcr fsize to max address */
806
+    ospi->dcr_reg = DCR1_DEVSIZE_MASK | DCR1_DLYBYP;
807
+    writel_relaxed(ospi->dcr_reg, regs_base + OSPI_DCR1);
808
+
809
+    mutex_unlock(&ospi->lock);
810
+
811
+    pm_runtime_mark_last_busy(ospi->dev);
812
+    pm_runtime_put_autosuspend(ospi->dev);
813
+
814
+    return 0;
815
+}
816
+
817
+/*
818
+ * No special host constraint, so use default spi_mem_default_supports_op
819
+ * to check supported mode.
820
+ */
821
+static const struct spi_controller_mem_ops stm32_ospi_mem_ops = {
822
+    .exec_op    = stm32_ospi_exec_op,
823
+    .dirmap_create    = stm32_ospi_dirmap_create,
824
+    .dirmap_read    = stm32_ospi_dirmap_read,
825
+    .poll_status    = stm32_ospi_poll_status,
826
+};
827
+
828
+static int stm32_ospi_get_resources(struct platform_device *pdev)
829
+{
830
+    struct device *dev = &pdev->dev;
831
+    struct stm32_ospi *ospi = platform_get_drvdata(pdev);
832
+    struct resource *res;
833
+    struct reserved_mem *rmem = NULL;
834
+    struct device_node *node;
835
+    int ret;
836
+
837
+    ospi->regs_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
838
+    if (IS_ERR(ospi->regs_base))
839
+        return PTR_ERR(ospi->regs_base);
840
+
841
+    ospi->regs_phys_base = res->start;
842
+
843
+    ospi->clk = devm_clk_get(dev, NULL);
844
+    if (IS_ERR(ospi->clk))
845
+        return dev_err_probe(dev, PTR_ERR(ospi->clk),
846
+                 "Can't get clock\n");
847
+
848
+    ospi->clk_rate = clk_get_rate(ospi->clk);
849
+    if (!ospi->clk_rate) {
850
+        dev_err(dev, "Invalid clock rate\n");
851
+        return -EINVAL;
852
+    }
853
+
854
+    ospi->irq = platform_get_irq(pdev, 0);
855
+    if (ospi->irq < 0) {
856
+        dev_err(dev, "Can't get irq %d\n", ospi->irq);
857
+        return ospi->irq;
858
+    }
859
+
860
+    ret = devm_request_irq(dev, ospi->irq, stm32_ospi_irq, 0,
861
+             dev_name(dev), ospi);
862
+    if (ret) {
863
+        dev_err(dev, "Failed to request irq\n");
864
+        return ret;
865
+    }
866
+
867
+    ospi->rstc = devm_reset_control_array_get_optional_exclusive(dev);
868
+    if (IS_ERR(ospi->rstc))
869
+        return dev_err_probe(dev, PTR_ERR(ospi->rstc),
870
+                 "Can't get reset\n");
871
+
872
+    ospi->dma_chrx = dma_request_chan(dev, "rx");
873
+    if (IS_ERR(ospi->dma_chrx)) {
874
+        ret = PTR_ERR(ospi->dma_chrx);
875
+        ospi->dma_chrx = NULL;
876
+        if (ret == -EPROBE_DEFER)
877
+            goto err_dma;
878
+    }
879
+
880
+    ospi->dma_chtx = dma_request_chan(dev, "tx");
881
+    if (IS_ERR(ospi->dma_chtx)) {
882
+        ret = PTR_ERR(ospi->dma_chtx);
883
+        ospi->dma_chtx = NULL;
884
+        if (ret == -EPROBE_DEFER)
885
+            goto err_dma;
886
+    }
887
+
888
+    node = of_parse_phandle(dev->of_node, "memory-region", 0);
889
+    if (node)
890
+        rmem = of_reserved_mem_lookup(node);
891
+    of_node_put(node);
892
+
893
+    if (rmem) {
894
+        ospi->mm_size = rmem->size;
895
+        ospi->mm_base = devm_ioremap(dev, rmem->base, rmem->size);
896
+        if (IS_ERR(ospi->mm_base)) {
897
+            dev_err(dev, "unable to map memory region: %pa+%pa\n",
898
+                &rmem->base, &rmem->size);
899
+            ret = PTR_ERR(ospi->mm_base);
900
+            goto err_dma;
901
+        }
902
+
903
+        if (ospi->mm_size > STM32_OSPI_MAX_MMAP_SZ) {
904
+            dev_err(dev, "Memory map size outsize bounds\n");
905
+            ret = -EINVAL;
906
+            goto err_dma;
907
+        }
908
+    } else {
909
+        dev_info(dev, "No memory-map region found\n");
910
+    }
911
+
912
+    init_completion(&ospi->data_completion);
913
+    init_completion(&ospi->match_completion);
914
+
915
+    return 0;
916
+
917
+err_dma:
918
+    dev_info(dev, "Can't get all resources (%d)\n", ret);
919
+
920
+    if (ospi->dma_chtx)
921
+        dma_release_channel(ospi->dma_chtx);
922
+    if (ospi->dma_chrx)
923
+        dma_release_channel(ospi->dma_chrx);
924
+
925
+    return ret;
926
+};
927
+
928
+static int stm32_ospi_probe(struct platform_device *pdev)
929
+{
930
+    struct device *dev = &pdev->dev;
931
+    struct spi_controller *ctrl;
932
+    struct stm32_ospi *ospi;
933
+    struct dma_slave_config dma_cfg;
934
+    struct device_node *child;
935
+    int ret;
936
+    u8 spi_flash_count = 0;
937
+
938
+    /*
939
+     * Flash subnodes sanity check:
940
+     * 1 or 2 spi-nand/spi-nor flashes        => supported
941
+     *     All other flash node configuration        => not supported
942
+     */
943
+    for_each_available_child_of_node(dev->of_node, child) {
944
+        if (of_device_is_compatible(child, "jedec,spi-nor") ||
945
+         of_device_is_compatible(child, "spi-nand"))
946
+            spi_flash_count++;
947
+    }
948
+
949
+    if (spi_flash_count == 0 || spi_flash_count > 2) {
950
+        dev_err(dev, "Incorrect DT flash node\n");
951
+        return -ENODEV;
952
+    }
953
+
954
+    ctrl = devm_spi_alloc_host(dev, sizeof(*ospi));
955
+    if (!ctrl)
956
+        return -ENOMEM;
957
+
958
+    ospi = spi_controller_get_devdata(ctrl);
959
+    ospi->ctrl = ctrl;
960
+
961
+    ospi->dev = &pdev->dev;
962
+    platform_set_drvdata(pdev, ospi);
963
+
964
+    ret = stm32_ospi_get_resources(pdev);
965
+    if (ret)
966
+        return ret;
967
+
968
+    memset(&dma_cfg, 0, sizeof(dma_cfg));
969
+    dma_cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
970
+    dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
971
+    dma_cfg.src_addr = ospi->regs_phys_base + OSPI_DR;
972
+    dma_cfg.dst_addr = ospi->regs_phys_base + OSPI_DR;
973
+    dma_cfg.src_maxburst = 4;
974
+    dma_cfg.dst_maxburst = 4;
975
+    stm32_ospi_dma_setup(ospi, &dma_cfg);
976
+
977
+    mutex_init(&ospi->lock);
978
+
979
+    ctrl->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD |
980
+             SPI_TX_DUAL | SPI_TX_QUAD |
981
+             SPI_TX_OCTAL | SPI_RX_OCTAL;
982
+    ctrl->setup = stm32_ospi_setup;
983
+    ctrl->bus_num = -1;
984
+    ctrl->mem_ops = &stm32_ospi_mem_ops;
985
+    ctrl->use_gpio_descriptors = true;
986
+    ctrl->transfer_one_message = stm32_ospi_transfer_one_message;
987
+    ctrl->num_chipselect = STM32_OSPI_MAX_NORCHIP;
988
+    ctrl->dev.of_node = dev->of_node;
989
+
990
+    pm_runtime_enable(ospi->dev);
991
+    pm_runtime_set_autosuspend_delay(ospi->dev, STM32_AUTOSUSPEND_DELAY);
992
+    pm_runtime_use_autosuspend(ospi->dev);
993
+
994
+    ret = pm_runtime_resume_and_get(ospi->dev);
995
+    if (ret < 0)
996
+        goto err_pm_enable;
997
+
998
+    if (ospi->rstc) {
999
+        reset_control_assert(ospi->rstc);
1000
+        udelay(2);
1001
+        reset_control_deassert(ospi->rstc);
1002
+    }
1003
+
1004
+    ret = spi_register_controller(ctrl);
1005
+    if (ret) {
1006
+        /* Disable ospi */
1007
+        writel_relaxed(0, ospi->regs_base + OSPI_CR);
1008
+        goto err_pm_resume;
1009
+    }
1010
+
1011
+    pm_runtime_mark_last_busy(ospi->dev);
1012
+    pm_runtime_put_autosuspend(ospi->dev);
1013
+
1014
+    return 0;
1015
+
1016
+err_pm_resume:
1017
+    pm_runtime_put_sync_suspend(ospi->dev);
1018
+
1019
+err_pm_enable:
1020
+    pm_runtime_force_suspend(ospi->dev);
1021
+    mutex_destroy(&ospi->lock);
1022
+
1023
+    return ret;
1024
+}
1025
+
1026
+static void stm32_ospi_remove(struct platform_device *pdev)
1027
+{
1028
+    struct stm32_ospi *ospi = platform_get_drvdata(pdev);
1029
+    int ret;
1030
+
1031
+    ret = pm_runtime_resume_and_get(ospi->dev);
1032
+    if (ret < 0)
1033
+        return;
1034
+
1035
+    spi_unregister_controller(ospi->ctrl);
1036
+    /* Disable ospi */
1037
+    writel_relaxed(0, ospi->regs_base + OSPI_CR);
1038
+    mutex_destroy(&ospi->lock);
1039
+
1040
+    if (ospi->dma_chtx)
1041
+        dma_release_channel(ospi->dma_chtx);
1042
+    if (ospi->dma_chrx)
1043
+        dma_release_channel(ospi->dma_chrx);
1044
+
1045
+    pm_runtime_put_sync_suspend(ospi->dev);
1046
+    pm_runtime_force_suspend(ospi->dev);
1047
+}
1048
+
1049
+static int __maybe_unused stm32_ospi_suspend(struct device *dev)
1050
+{
1051
+    struct stm32_ospi *ospi = dev_get_drvdata(dev);
1052
+
1053
+    pinctrl_pm_select_sleep_state(dev);
1054
+
1055
+    return pm_runtime_force_suspend(ospi->dev);
1056
+}
1057
+
1058
+static int __maybe_unused stm32_ospi_resume(struct device *dev)
1059
+{
1060
+    struct stm32_ospi *ospi = dev_get_drvdata(dev);
1061
+    void __iomem *regs_base = ospi->regs_base;
1062
+    int ret;
1063
+
1064
+    ret = pm_runtime_force_resume(ospi->dev);
1065
+    if (ret < 0)
1066
+        return ret;
1067
+
1068
+    pinctrl_pm_select_default_state(dev);
1069
+
1070
+    ret = pm_runtime_resume_and_get(ospi->dev);
1071
+    if (ret < 0)
1072
+        return ret;
1073
+
1074
+    writel_relaxed(ospi->cr_reg, regs_base + OSPI_CR);
1075
+    writel_relaxed(ospi->dcr_reg, regs_base + OSPI_DCR1);
1076
+    pm_runtime_mark_last_busy(ospi->dev);
1077
+    pm_runtime_put_autosuspend(ospi->dev);
1078
+
1079
+    return 0;
1080
+}
1081
+
1082
+static int __maybe_unused stm32_ospi_runtime_suspend(struct device *dev)
1083
+{
1084
+    struct stm32_ospi *ospi = dev_get_drvdata(dev);
1085
+
1086
+    clk_disable_unprepare(ospi->clk);
1087
+
1088
+    return 0;
1089
+}
1090
+
1091
+static int __maybe_unused stm32_ospi_runtime_resume(struct device *dev)
1092
+{
1093
+    struct stm32_ospi *ospi = dev_get_drvdata(dev);
1094
+
1095
+    return clk_prepare_enable(ospi->clk);
1096
+}
1097
+
1098
+static const struct dev_pm_ops stm32_ospi_pm_ops = {
1099
+    SET_SYSTEM_SLEEP_PM_OPS(stm32_ospi_suspend, stm32_ospi_resume)
1100
+    SET_RUNTIME_PM_OPS(stm32_ospi_runtime_suspend,
1101
+             stm32_ospi_runtime_resume, NULL)
1102
+};
1103
+
1104
+static const struct of_device_id stm32_ospi_of_match[] = {
1105
+    { .compatible = "st,stm32mp25-ospi" },
1106
+    {},
1107
+};
1108
+MODULE_DEVICE_TABLE(of, stm32_ospi_of_match);
1109
+
1110
+static struct platform_driver stm32_ospi_driver = {
1111
+    .probe    = stm32_ospi_probe,
1112
+    .remove    = stm32_ospi_remove,
1113
+    .driver    = {
1114
+        .name = "stm32-ospi",
1115
+        .pm = &stm32_ospi_pm_ops,
1116
+        .of_match_table = stm32_ospi_of_match,
1117
+    },
1118
+};
1119
+module_platform_driver(stm32_ospi_driver);
1120
+
1121
+MODULE_DESCRIPTION("STMicroelectronics STM32 OCTO SPI driver");
1122
+MODULE_LICENSE("GPL");
1123
--
1124
2.25.1
diff view generated by jsdifflib
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
1
Add myself as STM32 OCTO MEMORY MANAGER maintainer.
2
3
Enable STM32 Octo Memory Manager (OMM) driver which is needed
4
for OSPI usage on STM32 platforms.
5
2
6
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
3
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
7
---
4
---
8
arch/arm64/configs/defconfig | 1 +
5
MAINTAINERS | 6 ++++++
9
1 file changed, 1 insertion(+)
6
1 file changed, 6 insertions(+)
10
7
11
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
8
diff --git a/MAINTAINERS b/MAINTAINERS
12
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
13
--- a/arch/arm64/configs/defconfig
10
--- a/MAINTAINERS
14
+++ b/arch/arm64/configs/defconfig
11
+++ b/MAINTAINERS
15
@@ -XXX,XX +XXX,XX @@ CONFIG_BLK_DEV_NVME=m
12
@@ -XXX,XX +XXX,XX @@ L:    linux-i2c@vger.kernel.org
16
CONFIG_QCOM_COINCELL=m
13
S:    Maintained
17
CONFIG_QCOM_FASTRPC=m
14
F:    drivers/i2c/busses/i2c-stm32*
18
CONFIG_SRAM=y
15
19
+CONFIG_STM32_OMM=m
16
+ST STM32 OCTO MEMORY MANAGER
20
CONFIG_PCI_ENDPOINT_TEST=m
17
+M:    Patrice Chotard <patrice.chotard@foss.st.com>
21
CONFIG_EEPROM_AT24=m
18
+S:    Maintained
22
CONFIG_EEPROM_AT25=m
19
+F:    Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
20
+F:    drivers/memory/stm32_omm.c
21
+
22
ST STM32 SPI DRIVER
23
M:    Alain Volmat <alain.volmat@foss.st.com>
24
L:    linux-spi@vger.kernel.org
25
23
--
26
--
24
2.25.1
27
2.25.1
diff view generated by jsdifflib
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
2
3
Add bindings for STM32 Octo Memory Manager (OMM) controller.
1
Add bindings for STM32 Octo Memory Manager (OMM) controller.
4
2
5
OMM manages:
3
OMM manages:
6
- the muxing between 2 OSPI busses and 2 output ports.
4
- the muxing between 2 OSPI busses and 2 output ports.
7
There are 4 possible muxing configurations:
5
There are 4 possible muxing configurations:
...
...
15
- chip select selection override.
13
- chip select selection override.
16
- the time between 2 transactions in multiplexed mode.
14
- the time between 2 transactions in multiplexed mode.
17
15
18
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
16
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
19
---
17
---
20
.../bindings/misc/st,stm32-omm.yaml | 194 ++++++++++++++++++
18
.../memory-controllers/st,stm32mp25-omm.yaml | 227 +++++++++++++++++++++
21
1 file changed, 194 insertions(+)
19
1 file changed, 227 insertions(+)
22
create mode 100644 Documentation/devicetree/bindings/misc/st,stm32-omm.yaml
20
23
21
diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
24
diff --git a/Documentation/devicetree/bindings/misc/st,stm32-omm.yaml b/Documentation/devicetree/bindings/misc/st,stm32-omm.yaml
25
new file mode 100644
22
new file mode 100644
26
index XXXXXXX..XXXXXXX
23
index XXXXXXX..XXXXXXX
27
--- /dev/null
24
--- /dev/null
28
+++ b/Documentation/devicetree/bindings/misc/st,stm32-omm.yaml
25
+++ b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
29
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
30
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
27
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
31
+%YAML 1.2
28
+%YAML 1.2
32
+---
29
+---
33
+$id: http://devicetree.org/schemas/misc/st,stm32-omm.yaml#
30
+$id: http://devicetree.org/schemas/memory-controllers/st,stm32mp25-omm.yaml#
34
+$schema: http://devicetree.org/meta-schemas/core.yaml#
31
+$schema: http://devicetree.org/meta-schemas/core.yaml#
35
+
32
+
36
+title: STM32 Octo Memory Manager (OMM)
33
+title: STM32 Octo Memory Manager (OMM)
37
+
34
+
38
+maintainers:
35
+maintainers:
...
...
56
+ "#size-cells":
53
+ "#size-cells":
57
+ const: 1
54
+ const: 1
58
+
55
+
59
+ ranges:
56
+ ranges:
60
+ description: |
57
+ description: |
61
+ Reflects the memory layout with four integer values per OSPI instance.
58
+ Reflects the memory layout per OSPI instance.
62
+ Format:
59
+ Format:
63
+ <chip-select> 0 <registers base address> <size>
60
+ <chip-select> 0 <registers base address> <size>
61
+ minItems: 2
62
+ maxItems: 2
64
+
63
+
65
+ reg:
64
+ reg:
66
+ items:
65
+ items:
67
+ - description: registers
66
+ - description: OMM registers
68
+ - description: memory mapping
67
+ - description: OMM memory map area
69
+
68
+
70
+ reg-names:
69
+ reg-names:
71
+ items:
70
+ items:
72
+ - const: omm
71
+ - const: regs
73
+ - const: omm_mm
72
+ - const: memory_map
74
+
73
+
75
+ memory-region:
74
+ memory-region:
76
+ description: Phandle to a node describing memory-map region to be used.
75
+ description:
77
+
76
+ Memory region shared between the 2 OCTOSPI instance.
78
+ memory-region-names:
77
+ One or two phandle to a node describing a memory mapped region
79
+ minItems: 1
78
+ depending of child number.
80
+ items:
81
+ - const: mm_ospi1
82
+ - const: mm_ospi2
83
+
84
+ clocks:
85
+ maxItems: 1
86
+
87
+ resets:
88
+ maxItems: 1
89
+
90
+ access-controllers:
91
+ minItems: 1
79
+ minItems: 1
92
+ maxItems: 2
80
+ maxItems: 2
81
+
82
+ memory-region-names:
83
+ description:
84
+ Identify to which OSPI instance the memory region belongs to.
85
+ items:
86
+ enum: [ospi1, ospi2]
87
+ minItems: 1
88
+ maxItems: 2
89
+
90
+ clocks:
91
+ minItems: 3
92
+ maxItems: 3
93
+
94
+ clock-names:
95
+ items:
96
+ - const: omm
97
+ - const: ospi1
98
+ - const: ospi2
99
+
100
+ resets:
101
+ minItems: 3
102
+ maxItems: 3
103
+
104
+ reset-names:
105
+ items:
106
+ - const: omm
107
+ - const: ospi1
108
+ - const: ospi2
109
+
110
+ access-controllers:
111
+ maxItems: 1
93
+
112
+
94
+ st,syscfg-amcr:
113
+ st,syscfg-amcr:
95
+ $ref: /schemas/types.yaml#/definitions/phandle-array
114
+ $ref: /schemas/types.yaml#/definitions/phandle-array
96
+ description: |
115
+ description: |
97
+ The Address Mapping Control Register (AMCR) is used to split the 256MB
116
+ The Address Mapping Control Register (AMCR) is used to split the 256MB
98
+ memory map area shared between the 2 OSPI instance. The Octo Memory
117
+ memory map area shared between the 2 OSPI instance. The Octo Memory
99
+ Manager sets the AMCR depending of the memory-region configuration.
118
+ Manager sets the AMCR depending of the memory-region configuration.
100
+ Format is phandle to syscfg / register offset within syscfg / memory split
101
+ bitmask.
102
+ The memory split bitmask description is:
119
+ The memory split bitmask description is:
103
+ - 000: OCTOSPI1 (256 Mbytes), OCTOSPI2 unmapped
120
+ - 000: OCTOSPI1 (256 Mbytes), OCTOSPI2 unmapped
104
+ - 001: OCTOSPI1 (192 Mbytes), OCTOSPI2 (64 Mbytes)
121
+ - 001: OCTOSPI1 (192 Mbytes), OCTOSPI2 (64 Mbytes)
105
+ - 010: OCTOSPI1 (128 Mbytes), OCTOSPI2 (128 Mbytes)
122
+ - 010: OCTOSPI1 (128 Mbytes), OCTOSPI2 (128 Mbytes)
106
+ - 011: OCTOSPI1 (64 Mbytes), OCTOSPI2 (192 Mbytes)
123
+ - 011: OCTOSPI1 (64 Mbytes), OCTOSPI2 (192 Mbytes)
107
+ - 1xx: OCTOSPI1 unmapped, OCTOSPI2 (256 Mbytes)
124
+ - 1xx: OCTOSPI1 unmapped, OCTOSPI2 (256 Mbytes)
108
+ items:
125
+ items:
109
+ minItems: 3
126
+ - description: phandle to syscfg
110
+ maxItems: 3
127
+ - description: register offset within syscfg
128
+ - description: register bitmask for memory split
111
+
129
+
112
+ st,omm-req2ack-ns:
130
+ st,omm-req2ack-ns:
113
+ description: |
131
+ description:
114
+ In multiplexed mode (MUXEN = 1), this field defines the time in
132
+ In multiplexed mode (MUXEN = 1), this field defines the time in
115
+ nanoseconds between two transactions.
133
+ nanoseconds between two transactions.
134
+ default: 0
116
+
135
+
117
+ st,omm-cssel-ovr:
136
+ st,omm-cssel-ovr:
118
+ $ref: /schemas/types.yaml#/definitions/uint32
137
+ $ref: /schemas/types.yaml#/definitions/uint32
119
+ description: |
138
+ description: |
120
+ Configure the chip select selector override for the 2 OCTOSPIs.
139
+ Configure the chip select selector override for the 2 OCTOSPIs.
121
+ The 2 bits mask muxing description is:
140
+ - 0: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS1
122
+ -bit 0: Chip select selector override setting for OCTOSPI1
141
+ - 1: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS1
123
+ 0x0: the chip select signal from OCTOSPI1 is sent to NCS1
142
+ - 2: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS2
124
+ 0x1: the chip select signal from OCTOSPI1 is sent to NCS2
143
+ - 3: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS2
125
+ -bit 1: Chip select selector override setting for OCTOSPI2
144
+ minimum: 0
126
+ 0x0: the chip select signal from OCTOSPI2 is sent to NCS1
145
+ maximum: 3
127
+ 0x1: the chip select signal from OCTOSPI2 is sent to NCS2
146
+ default: 0
128
+
147
+
129
+ st,omm-mux:
148
+ st,omm-mux:
130
+ $ref: /schemas/types.yaml#/definitions/uint32
149
+ $ref: /schemas/types.yaml#/definitions/uint32
131
+ description: |
150
+ description: |
132
+ Configure the muxing between the 2 OCTOSPIs busses and the 2 output ports.
151
+ Configure the muxing between the 2 OCTOSPIs busses and the 2 output ports.
133
+ The muxing 2 bits mask description is:
152
+ - 0: direct mode
134
+ - 0x0: direct mode, default
153
+ - 1: mux OCTOSPI1 and OCTOSPI2 to port 1
135
+ - 0x1: mux OCTOSPI1 and OCTOSPI2 to port 1
154
+ - 2: swapped mode
136
+ - 0x2: swapped mode
155
+ - 3: mux OCTOSPI1 and OCTOSPI2 to port 2
137
+ - 0x3: mux OCTOSPI1 and OCTOSPI2 to port 2
156
+ minimum: 0
157
+ maximum: 3
158
+ default: 0
138
+
159
+
139
+ power-domains:
160
+ power-domains:
140
+ maxItems: 1
161
+ maxItems: 1
141
+
162
+
142
+patternProperties:
163
+patternProperties:
143
+ "^spi@[a-f0-9]+$":
164
+ ^spi@[0-9]:
144
+ type: object
165
+ type: object
145
+ $ref: "/schemas/spi/st,stm32-ospi.yaml#"
166
+ $ref: /schemas/spi/st,stm32mp25-ospi.yaml#
146
+ description: Required spi child node
167
+ description: Required spi child node
147
+
168
+
148
+required:
169
+required:
149
+ - compatible
170
+ - compatible
150
+ - reg
171
+ - reg
151
+ - "#address-cells"
172
+ - "#address-cells"
152
+ - "#size-cells"
173
+ - "#size-cells"
153
+ - clocks
174
+ - clocks
175
+ - clock-names
176
+ - resets
177
+ - reset-names
154
+ - st,syscfg-amcr
178
+ - st,syscfg-amcr
155
+ - ranges
179
+ - ranges
156
+
180
+
157
+additionalProperties: false
181
+additionalProperties: false
158
+
182
+
...
...
162
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
186
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
163
+ #include <dt-bindings/reset/st,stm32mp25-rcc.h>
187
+ #include <dt-bindings/reset/st,stm32mp25-rcc.h>
164
+ ommanager@40500000 {
188
+ ommanager@40500000 {
165
+ compatible = "st,stm32mp25-omm";
189
+ compatible = "st,stm32mp25-omm";
166
+ reg = <0x40500000 0x400>, <0x60000000 0x10000000>;
190
+ reg = <0x40500000 0x400>, <0x60000000 0x10000000>;
167
+ reg-names = "omm", "omm_mm";
191
+ reg-names = "regs", "memory_map";
192
+ ranges = <0 0 0x40430000 0x400>,
193
+ <1 0 0x40440000 0x400>;
168
+ memory-region = <&mm_ospi1>, <&mm_ospi2>;
194
+ memory-region = <&mm_ospi1>, <&mm_ospi2>;
169
+ memory-region-names = "mm_ospi1", "mm_ospi2";
195
+ memory-region-names = "ospi1", "ospi2";
170
+ pinctrl-names = "default", "sleep";
171
+ pinctrl-0 = <&ospi_port1_clk_pins_a
196
+ pinctrl-0 = <&ospi_port1_clk_pins_a
172
+ &ospi_port1_io03_pins_a
197
+ &ospi_port1_io03_pins_a
173
+ &ospi_port1_cs0_pins_a>;
198
+ &ospi_port1_cs0_pins_a>;
174
+ pinctrl-1 = <&ospi_port1_clk_sleep_pins_a
199
+ pinctrl-1 = <&ospi_port1_clk_sleep_pins_a
175
+ &ospi_port1_io03_sleep_pins_a
200
+ &ospi_port1_io03_sleep_pins_a
176
+ &ospi_port1_cs0_sleep_pins_a>;
201
+ &ospi_port1_cs0_sleep_pins_a>;
177
+ clocks = <&rcc CK_BUS_OSPIIOM>;
202
+ pinctrl-names = "default", "sleep";
178
+ resets = <&rcc OSPIIOM_R>;
203
+ clocks = <&rcc CK_BUS_OSPIIOM>,
179
+ st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
204
+ <&scmi_clk CK_SCMI_OSPI1>,
180
+ st,omm-req2ack-ns = <0x0>;
205
+ <&scmi_clk CK_SCMI_OSPI2>;
181
+ st,omm-mux = <0x0>;
206
+ clock-names = "omm", "ospi1", "ospi2";
182
+ st,omm-cssel-ovr = <0x0>;
207
+ resets = <&rcc OSPIIOM_R>,
208
+ <&scmi_reset RST_SCMI_OSPI1>,
209
+ <&scmi_reset RST_SCMI_OSPI2>;
210
+ reset-names = "omm", "ospi1", "ospi2";
183
+ access-controllers = <&rifsc 111>;
211
+ access-controllers = <&rifsc 111>;
184
+ power-domains = <&CLUSTER_PD>;
212
+ power-domains = <&CLUSTER_PD>;
185
+
186
+ #address-cells = <2>;
213
+ #address-cells = <2>;
187
+ #size-cells = <1>;
214
+ #size-cells = <1>;
188
+
215
+ st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
189
+ ranges = <0 0 0x40430000 0x400>,
216
+ st,omm-req2ack-ns = <0>;
190
+ <1 0 0x40440000 0x400>;
217
+ st,omm-mux = <0>;
191
+
218
+ st,omm-cssel-ovr = <0>;
192
+ spi@40430000 {
219
+
193
+ #address-cells = <1>;
220
+ spi@0 {
194
+ #size-cells = <0>;
195
+ compatible = "st,stm32mp25-ospi";
221
+ compatible = "st,stm32mp25-ospi";
196
+ reg = <0 0 0x400>;
222
+ reg = <0 0 0x400>;
223
+ memory-region = <&mm_ospi1>;
197
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
224
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
198
+ dmas = <&hpdma 2 0x62 0x00003121 0x0>,
225
+ dmas = <&hpdma 2 0x62 0x00003121 0x0>,
199
+ <&hpdma 2 0x42 0x00003112 0x0>;
226
+ <&hpdma 2 0x42 0x00003112 0x0>;
200
+ dma-names = "tx", "rx";
227
+ dma-names = "tx", "rx";
201
+ clocks = <&scmi_clk CK_SCMI_OSPI1>;
228
+ clocks = <&scmi_clk CK_SCMI_OSPI1>;
202
+ resets = <&scmi_reset RST_SCMI_OSPI1>, <&scmi_reset RST_SCMI_OSPI1DLL>;
229
+ resets = <&scmi_reset RST_SCMI_OSPI1>, <&scmi_reset RST_SCMI_OSPI1DLL>;
203
+ access-controllers = <&rifsc 74>;
230
+ access-controllers = <&rifsc 74>;
204
+ power-domains = <&CLUSTER_PD>;
231
+ power-domains = <&CLUSTER_PD>;
232
+ #address-cells = <1>;
233
+ #size-cells = <0>;
205
+ st,syscfg-dlyb = <&syscfg 0x1000>;
234
+ st,syscfg-dlyb = <&syscfg 0x1000>;
206
+ };
235
+ };
207
+
236
+
208
+ spi@40440000 {
237
+ spi@1 {
209
+ #address-cells = <1>;
210
+ #size-cells = <0>;
211
+ compatible = "st,stm32mp25-ospi";
238
+ compatible = "st,stm32mp25-ospi";
212
+ reg = <1 0 0x400>;
239
+ reg = <1 0 0x400>;
240
+ memory-region = <&mm_ospi1>;
213
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
241
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
214
+ dmas = <&hpdma 3 0x62 0x00003121 0x0>,
242
+ dmas = <&hpdma 3 0x62 0x00003121 0x0>,
215
+ <&hpdma 3 0x42 0x00003112 0x0>;
243
+ <&hpdma 3 0x42 0x00003112 0x0>;
216
+ dma-names = "tx", "rx";
244
+ dma-names = "tx", "rx";
217
+ clocks = <&scmi_clk CK_KER_OSPI2>;
245
+ clocks = <&scmi_clk CK_KER_OSPI2>;
218
+ resets = <&scmi_reset RST_SCMI_OSPI2>, <&scmi_reset RST_SCMI_OSPI1DLL>;
246
+ resets = <&scmi_reset RST_SCMI_OSPI2>, <&scmi_reset RST_SCMI_OSPI1DLL>;
219
+ access-controllers = <&rifsc 75>;
247
+ access-controllers = <&rifsc 75>;
220
+ power-domains = <&CLUSTER_PD>;
248
+ power-domains = <&CLUSTER_PD>;
249
+ #address-cells = <1>;
250
+ #size-cells = <0>;
221
+ st,syscfg-dlyb = <&syscfg 0x1000>;
251
+ st,syscfg-dlyb = <&syscfg 0x1000>;
222
+ };
252
+ };
223
+ };
253
+ };
254
224
--
255
--
225
2.25.1
256
2.25.1
diff view generated by jsdifflib
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
2
3
Octo Memory Manager driver (OMM) manages:
1
Octo Memory Manager driver (OMM) manages:
4
- the muxing between 2 OSPI busses and 2 output ports.
2
- the muxing between 2 OSPI busses and 2 output ports.
5
There are 4 possible muxing configurations:
3
There are 4 possible muxing configurations:
6
- direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
4
- direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
7
output is on port 2
5
output is on port 2
...
...
12
- the split of the memory area shared between the 2 OSPI instances.
10
- the split of the memory area shared between the 2 OSPI instances.
13
- chip select selection override.
11
- chip select selection override.
14
- the time between 2 transactions in multiplexed mode.
12
- the time between 2 transactions in multiplexed mode.
15
- check firewall access.
13
- check firewall access.
16
14
15
Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com>
17
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
16
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
18
Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com>
19
---
17
---
20
drivers/misc/Kconfig | 17 ++
18
drivers/memory/Kconfig | 17 ++
21
drivers/misc/Makefile | 1 +
19
drivers/memory/Makefile | 1 +
22
drivers/misc/stm32_omm.c | 510 +++++++++++++++++++++++++++++++++++++++
20
drivers/memory/stm32_omm.c | 474 +++++++++++++++++++++++++++++++++++++++++++++
23
3 files changed, 528 insertions(+)
21
3 files changed, 492 insertions(+)
24
create mode 100644 drivers/misc/stm32_omm.c
25
22
26
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
23
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
27
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
28
--- a/drivers/misc/Kconfig
25
--- a/drivers/memory/Kconfig
29
+++ b/drivers/misc/Kconfig
26
+++ b/drivers/memory/Kconfig
30
@@ -XXX,XX +XXX,XX @@ config DW_XDATA_PCIE
27
@@ -XXX,XX +XXX,XX @@ config STM32_FMC2_EBI
31
28
     devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
32
     If unsure, say N.
29
     SOCs containing the FMC2 External Bus Interface.
33
30
34
+config STM32_OMM
31
+config STM32_OMM
35
+    bool "STM32 Octo Memory Manager"
32
+    tristate "STM32 Octo Memory Manager"
36
+    depends on SPI_STM32_OSPI || TEST_COMPILE
33
+    depends on SPI_STM32_OSPI || COMPILE_TEST
37
+    help
34
+    help
38
+     This driver manages the muxing between the 2 OSPI busses and
35
+     This driver manages the muxing between the 2 OSPI busses and
39
+     the 2 output ports. There are 4 possible muxing configurations:
36
+     the 2 output ports. There are 4 possible muxing configurations:
40
+     - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
37
+     - direct mode (no multiplexing): OSPI1 output is on port 1 and OSPI2
41
+     output is on port 2
38
+     output is on port 2
...
...
46
+     It also manages :
43
+     It also manages :
47
+     - the split of the memory area shared between the 2 OSPI instances.
44
+     - the split of the memory area shared between the 2 OSPI instances.
48
+     - chip select selection override.
45
+     - chip select selection override.
49
+     - the time between 2 transactions in multiplexed mode.
46
+     - the time between 2 transactions in multiplexed mode.
50
+
47
+
51
config PCI_ENDPOINT_TEST
48
source "drivers/memory/samsung/Kconfig"
52
    depends on PCI
49
source "drivers/memory/tegra/Kconfig"
53
    select CRC32
50
54
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
51
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
55
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
56
--- a/drivers/misc/Makefile
53
--- a/drivers/memory/Makefile
57
+++ b/drivers/misc/Makefile
54
+++ b/drivers/memory/Makefile
58
@@ -XXX,XX +XXX,XX @@ lan966x-pci-objs        := lan966x_pci.o
55
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DA8XX_DDRCTL)    += da8xx-ddrctl.o
59
lan966x-pci-objs        += lan966x_pci.dtbo.o
56
obj-$(CONFIG_PL353_SMC)        += pl353-smc.o
60
obj-$(CONFIG_MCHP_LAN966X_PCI)    += lan966x-pci.o
57
obj-$(CONFIG_RENESAS_RPCIF)    += renesas-rpc-if.o
61
obj-y                += keba/
58
obj-$(CONFIG_STM32_FMC2_EBI)    += stm32-fmc2-ebi.o
62
+obj-$(CONFIG_STM32_OMM)        += stm32_omm.o
59
+obj-$(CONFIG_STM32_OMM)        += stm32_omm.o
63
diff --git a/drivers/misc/stm32_omm.c b/drivers/misc/stm32_omm.c
60
61
obj-$(CONFIG_SAMSUNG_MC)    += samsung/
62
obj-$(CONFIG_TEGRA_MC)        += tegra/
63
diff --git a/drivers/memory/stm32_omm.c b/drivers/memory/stm32_omm.c
64
new file mode 100644
64
new file mode 100644
65
index XXXXXXX..XXXXXXX
65
index XXXXXXX..XXXXXXX
66
--- /dev/null
66
--- /dev/null
67
+++ b/drivers/misc/stm32_omm.c
67
+++ b/drivers/memory/stm32_omm.c
68
@@ -XXX,XX +XXX,XX @@
68
@@ -XXX,XX +XXX,XX @@
69
+// SPDX-License-Identifier: GPL
69
+// SPDX-License-Identifier: GPL-2.0
70
+/*
70
+/*
71
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
71
+ * Copyright (C) STMicroelectronics 2025 - All Rights Reserved
72
+ * Author(s): Patrice Chotard <patrice.chotard@foss.st.com> for STMicroelectronics.
72
+ * Author(s): Patrice Chotard <patrice.chotard@foss.st.com> for STMicroelectronics.
73
+ */
73
+ */
74
+
74
+
75
+#include <linux/bitfield.h>
75
+#include <linux/bus/stm32_firewall_device.h>
76
+#include <linux/bus/stm32_firewall_device.h>
76
+#include <linux/clk.h>
77
+#include <linux/clk.h>
77
+#include <linux/err.h>
78
+#include <linux/err.h>
78
+#include <linux/mfd/syscon.h>
79
+#include <linux/mfd/syscon.h>
79
+#include <linux/mod_devicetable.h>
80
+#include <linux/mod_devicetable.h>
...
...
91
+#define CR_CSSEL_OVR_EN        BIT(4)
92
+#define CR_CSSEL_OVR_EN        BIT(4)
92
+#define CR_CSSEL_OVR_MASK    GENMASK(6, 5)
93
+#define CR_CSSEL_OVR_MASK    GENMASK(6, 5)
93
+#define CR_REQ2ACK_MASK        GENMASK(23, 16)
94
+#define CR_REQ2ACK_MASK        GENMASK(23, 16)
94
+
95
+
95
+#define OMM_CHILD_NB        2
96
+#define OMM_CHILD_NB        2
96
+
97
+#define OMM_CLK_NB        3
97
+struct ospi_child {
98
+    struct device *dev;
99
+    struct device_node *node;
100
+    struct clk *clk;
101
+    struct reset_control *reset;
102
+};
103
+
98
+
104
+struct stm32_omm {
99
+struct stm32_omm {
105
+    struct ospi_child child[OMM_CHILD_NB];
106
+    struct resource *mm_res;
100
+    struct resource *mm_res;
107
+    struct clk *clk;
101
+    struct clk_bulk_data clk_bulk[OMM_CLK_NB];
108
+    void __iomem *io_base;
102
+    void __iomem *io_base;
109
+    u32 cr;
103
+    u32 cr;
110
+    u8 nb_child;
104
+    u8 nb_child;
111
+    bool restore_omm;
105
+    bool restore_omm;
112
+};
106
+};
113
+
107
+
114
+static int stm32_omm_set_amcr(struct device *dev, bool set)
108
+static int stm32_omm_set_amcr(struct device *dev, bool set)
115
+{
109
+{
116
+    struct stm32_omm *omm = dev_get_drvdata(dev);
110
+    struct stm32_omm *omm = dev_get_drvdata(dev);
111
+    resource_size_t mm_ospi2_size = 0;
112
+    static const char * const mm_name[] = { "ospi1", "ospi2" };
117
+    struct regmap *syscfg_regmap;
113
+    struct regmap *syscfg_regmap;
118
+    struct device_node *node;
114
+    struct device_node *node;
119
+    struct resource res, res1;
115
+    struct resource res, res1;
120
+    resource_size_t mm_ospi2_size = 0;
121
+    static const char * const mm_name[] = { "mm_ospi1", "mm_ospi2" };
122
+    u32 amcr_base, amcr_mask;
116
+    u32 amcr_base, amcr_mask;
123
+    int ret, i, idx;
117
+    int ret, idx;
124
+    unsigned int amcr, read_amcr;
118
+    unsigned int i, amcr, read_amcr;
125
+
119
+
126
+    for (i = 0; i < omm->nb_child; i++) {
120
+    for (i = 0; i < omm->nb_child; i++) {
127
+        idx = of_property_match_string(dev->of_node,
121
+        idx = of_property_match_string(dev->of_node,
128
+                     "memory-region-names",
122
+                     "memory-region-names",
129
+                     mm_name[i]);
123
+                     mm_name[i]);
...
...
133
+        /* res1 only used on second loop iteration */
127
+        /* res1 only used on second loop iteration */
134
+        res1.start = res.start;
128
+        res1.start = res.start;
135
+        res1.end = res.end;
129
+        res1.end = res.end;
136
+
130
+
137
+        node = of_parse_phandle(dev->of_node, "memory-region", idx);
131
+        node = of_parse_phandle(dev->of_node, "memory-region", idx);
132
+        if (!node)
133
+            continue;
134
+
138
+        ret = of_address_to_resource(node, 0, &res);
135
+        ret = of_address_to_resource(node, 0, &res);
139
+        if (ret) {
136
+        if (ret) {
140
+            dev_err(dev, "unable to resolve memory region\n");
137
+            dev_err(dev, "unable to resolve memory region\n");
141
+            return ret;
138
+            return ret;
142
+        }
139
+        }
143
+
140
+
144
+        /* check that memory region fits inside OMM memory map area */
141
+        /* check that memory region fits inside OMM memory map area */
145
+        if (!resource_contains(omm->mm_res, &res)) {
142
+        if (!resource_contains(omm->mm_res, &res)) {
146
+            dev_err(dev, "%s doesn't fit inside OMM memory map area\n",
143
+            dev_err(dev, "%s doesn't fit inside OMM memory map area\n",
147
+                mm_name[i]);
144
+                mm_name[i]);
148
+            dev_err(dev, "[0x%llx-0x%llx] doesn't fit inside [0x%llx-0x%llx]\n",
145
+            dev_err(dev, "%pR doesn't fit inside %pR\n", &res, omm->mm_res);
149
+                res.start, res.end,
150
+                omm->mm_res->start, omm->mm_res->end);
151
+
146
+
152
+            return -EFAULT;
147
+            return -EFAULT;
153
+        }
148
+        }
154
+
149
+
155
+        if (i == 1) {
150
+        if (i == 1) {
156
+            mm_ospi2_size = resource_size(&res);
151
+            mm_ospi2_size = resource_size(&res);
157
+
152
+
158
+            /* check that OMM memory region 1 doesn't overlap memory region 2 */
153
+            /* check that OMM memory region 1 doesn't overlap memory region 2 */
159
+            if (resource_overlaps(&res, &res1)) {
154
+            if (resource_overlaps(&res, &res1)) {
160
+                dev_err(dev, "OMM memory-region %s overlaps memory region %s\n",
155
+                dev_err(dev, "OMM memory-region %s overlaps memory region %s\n",
161
+                    mm_name[0], mm_name[1]);
156
+                    mm_name[0], mm_name[1]);
162
+                dev_err(dev, "[0x%llx-0x%llx] overlaps [0x%llx-0x%llx]\n",
157
+                dev_err(dev, "%pR overlaps %pR\n", &res1, &res);
163
+                    res1.start, res1.end, res.start, res.end);
164
+
158
+
165
+                return -EFAULT;
159
+                return -EFAULT;
166
+            }
160
+            }
167
+        }
161
+        }
168
+    }
162
+    }
169
+
163
+
170
+    syscfg_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "st,syscfg-amcr");
164
+    syscfg_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "st,syscfg-amcr");
171
+    if (IS_ERR(syscfg_regmap)) {
165
+    if (IS_ERR(syscfg_regmap))
172
+        dev_err(dev, "Failed to get st,syscfg-amcr property\n");
166
+        return dev_err_probe(dev, PTR_ERR(syscfg_regmap),
173
+        return PTR_ERR(syscfg_regmap);
167
+                 "Failed to get st,syscfg-amcr property\n");
174
+    }
175
+
168
+
176
+    ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 1,
169
+    ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 1,
177
+                     &amcr_base);
170
+                     &amcr_base);
178
+    if (ret)
171
+    if (ret)
179
+        return ret;
172
+        return ret;
...
...
198
+    }
191
+    }
199
+
192
+
200
+    return ret;
193
+    return ret;
201
+}
194
+}
202
+
195
+
203
+static int stm32_omm_enable_child_clock(struct device *dev, bool enable)
196
+static int stm32_omm_toggle_child_clock(struct device *dev, bool enable)
204
+{
197
+{
205
+    /* As there is only 2 children, remember first child in case of error */
198
+    /* As there is only 2 children, remember first child in case of error */
206
+    struct clk *first_child_clk = NULL;
199
+    struct clk *first_child_clk = NULL;
207
+    struct stm32_omm *omm = dev_get_drvdata(dev);
200
+    struct stm32_omm *omm = dev_get_drvdata(dev);
208
+    u8 i;
201
+    u8 i;
209
+    int ret;
202
+    int ret;
210
+
203
+
211
+    for (i = 0; i < omm->nb_child; i++) {
204
+    for (i = 0; i < omm->nb_child; i++) {
212
+        if (enable) {
205
+        if (enable) {
213
+            ret = clk_prepare_enable(omm->child[i].clk);
206
+            ret = clk_prepare_enable(omm->clk_bulk[i + 1].clk);
214
+            if (ret) {
207
+            if (ret) {
215
+                if (first_child_clk)
208
+                if (first_child_clk)
216
+                    clk_disable_unprepare(first_child_clk);
209
+                    clk_disable_unprepare(first_child_clk);
217
+
210
+
218
+                dev_err(dev, "Can not enable clock\n");
211
+                dev_err(dev, "Can not enable clock\n");
219
+                return ret;
212
+                return ret;
220
+            }
213
+            }
221
+        } else {
214
+        } else {
222
+            clk_disable_unprepare(omm->child[i].clk);
215
+            clk_disable_unprepare(omm->clk_bulk[i + 1].clk);
223
+        }
216
+        }
224
+
217
+
225
+        first_child_clk = omm->child[i].clk;
218
+        first_child_clk = omm->clk_bulk[i + 1].clk;
226
+    }
219
+    }
227
+
220
+
228
+    return 0;
221
+    return 0;
229
+}
222
+}
230
+
223
+
231
+static int stm32_omm_configure(struct device *dev)
224
+static int stm32_omm_disable_child(struct device *dev)
232
+{
225
+{
233
+    struct stm32_omm *omm = dev_get_drvdata(dev);
226
+    static const char * const resets_name[] = {"ospi1", "ospi2"};
234
+    struct reset_control *rstc;
227
+    struct stm32_omm *omm = dev_get_drvdata(dev);
235
+    unsigned long clk_rate, clk_rate_max = 0;
228
+    struct reset_control *reset;
236
+    int ret;
229
+    int ret;
237
+    u8 i;
230
+    u8 i;
231
+
232
+    ret = stm32_omm_toggle_child_clock(dev, true);
233
+    if (!ret)
234
+        return ret;
235
+
236
+    for (i = 0; i < omm->nb_child; i++) {
237
+        reset = reset_control_get_exclusive(dev, resets_name[i]);
238
+        if (IS_ERR(reset)) {
239
+            dev_err(dev, "Can't get %s reset\n", resets_name[i]);
240
+            return PTR_ERR(reset);
241
+        };
242
+
243
+        /* reset OSPI to ensure CR_EN bit is set to 0 */
244
+        reset_control_assert(reset);
245
+        udelay(2);
246
+        reset_control_deassert(reset);
247
+
248
+        reset_control_put(reset);
249
+    }
250
+
251
+    return stm32_omm_toggle_child_clock(dev, false);
252
+}
253
+
254
+static int stm32_omm_configure(struct device *dev)
255
+{
256
+    static const char * const clocks_name[] = {"omm", "ospi1", "ospi2"};
257
+    struct stm32_omm *omm = dev_get_drvdata(dev);
258
+    unsigned long clk_rate_max = 0;
238
+    u32 mux = 0;
259
+    u32 mux = 0;
239
+    u32 cssel_ovr = 0;
260
+    u32 cssel_ovr = 0;
240
+    u32 req2ack = 0;
261
+    u32 req2ack = 0;
241
+
262
+    struct reset_control *rstc;
242
+    omm->clk = devm_clk_get(dev, NULL);
263
+    unsigned long clk_rate;
243
+    if (IS_ERR(omm->clk)) {
264
+    int ret;
244
+        dev_err(dev, "Failed to get OMM clock (%ld)\n",
265
+    u8 i;
245
+            PTR_ERR(omm->clk));
266
+
246
+
267
+    for (i = 0; i < OMM_CLK_NB; i++)
247
+        return PTR_ERR(omm->clk);
268
+        omm->clk_bulk[i].id = clocks_name[i];
248
+    }
269
+
270
+    /* retrieve OMM, OSPI1 and OSPI2 clocks */
271
+    ret = devm_clk_bulk_get(dev, OMM_CLK_NB, omm->clk_bulk);
272
+    if (ret)
273
+        return dev_err_probe(dev, ret, "Failed to get OMM/OSPI's clocks\n");
274
+
275
+    /* Ensure both OSPI instance are disabled before configuring OMM */
276
+    ret = stm32_omm_disable_child(dev);
277
+    if (ret)
278
+        return ret;
249
+
279
+
250
+    ret = pm_runtime_resume_and_get(dev);
280
+    ret = pm_runtime_resume_and_get(dev);
251
+    if (ret < 0)
281
+    if (ret < 0)
252
+        return ret;
282
+        return ret;
253
+
283
+
254
+    /* parse children's clock */
284
+    /* parse children's clock */
255
+    for (i = 0; i < omm->nb_child; i++) {
285
+    for (i = 1; i <= omm->nb_child; i++) {
256
+        clk_rate = clk_get_rate(omm->child[i].clk);
286
+        clk_rate = clk_get_rate(omm->clk_bulk[i].clk);
257
+        if (!clk_rate) {
287
+        if (!clk_rate) {
258
+            dev_err(dev, "Invalid clock rate\n");
288
+            dev_err(dev, "Invalid clock rate\n");
259
+            goto err_clk_disable;
289
+            goto err_clk_disable;
260
+        }
290
+        }
261
+
291
+
262
+        if (clk_rate > clk_rate_max)
292
+        if (clk_rate > clk_rate_max)
263
+            clk_rate_max = clk_rate;
293
+            clk_rate_max = clk_rate;
264
+    }
294
+    }
265
+
295
+
266
+    rstc = devm_reset_control_get_optional(dev, NULL);
296
+    rstc = devm_reset_control_get_exclusive(dev, "omm");
267
+    if (IS_ERR(rstc)) {
297
+    if (IS_ERR(rstc))
268
+        ret = dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n");
298
+        return dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n");
269
+        goto err_clk_disable;
270
+    }
271
+
299
+
272
+    reset_control_assert(rstc);
300
+    reset_control_assert(rstc);
273
+    udelay(2);
301
+    udelay(2);
274
+    reset_control_deassert(rstc);
302
+    reset_control_deassert(rstc);
275
+
303
+
276
+    omm->cr = readl_relaxed(omm->io_base + OMM_CR);
304
+    omm->cr = readl_relaxed(omm->io_base + OMM_CR);
277
+    /* optional */
305
+    /* optional */
278
+    ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux);
306
+    ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux);
279
+    if (!ret) {
307
+    if (!ret) {
280
+        if (mux & CR_MUXEN) {
308
+        if (mux & CR_MUXEN) {
281
+            ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns",
309
+            ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns",
282
+                         &req2ack);
310
+                         &req2ack);
283
+            if (!ret && !req2ack) {
311
+            if (!ret && !req2ack) {
284
+                req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1;
312
+                req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1;
285
+
313
+
286
+                if (req2ack > 256)
314
+                if (req2ack > 256)
287
+                    req2ack = 256;
315
+                    req2ack = 256;
...
...
294
+
322
+
295
+            /*
323
+            /*
296
+             * If the mux is enabled, the 2 OSPI clocks have to be
324
+             * If the mux is enabled, the 2 OSPI clocks have to be
297
+             * always enabled
325
+             * always enabled
298
+             */
326
+             */
299
+            ret = stm32_omm_enable_child_clock(dev, true);
327
+            ret = stm32_omm_toggle_child_clock(dev, true);
300
+            if (ret)
328
+            if (ret)
301
+                goto err_clk_disable;
329
+                goto err_clk_disable;
302
+        }
330
+        }
303
+
331
+
304
+        omm->cr &= ~CR_MUXENMODE_MASK;
332
+        omm->cr &= ~CR_MUXENMODE_MASK;
...
...
322
+    pm_runtime_put_sync_suspend(dev);
350
+    pm_runtime_put_sync_suspend(dev);
323
+
351
+
324
+    return ret;
352
+    return ret;
325
+}
353
+}
326
+
354
+
327
+static int stm32_omm_check_access(struct device *dev, struct device_node *np)
355
+static int stm32_omm_check_access(struct device_node *np)
328
+{
356
+{
329
+    struct stm32_firewall firewall;
357
+    struct stm32_firewall firewall;
330
+    int ret;
358
+    int ret;
331
+
359
+
332
+    ret = stm32_firewall_get_firewall(np, &firewall, 1);
360
+    ret = stm32_firewall_get_firewall(np, &firewall, 1);
333
+    if (ret)
361
+    if (ret)
334
+        return ret;
362
+        return ret;
335
+
363
+
336
+    return stm32_firewall_grant_access(&firewall);
364
+    return stm32_firewall_grant_access(&firewall);
337
+}
365
+}
338
+
366
+
339
+static int stm32_omm_disable_child(struct device *dev)
340
+{
341
+    struct stm32_omm *omm = dev_get_drvdata(dev);
342
+    u8 i;
343
+    int ret;
344
+
345
+    for (i = 0; i < omm->nb_child; i++) {
346
+        ret = clk_prepare_enable(omm->child[i].clk);
347
+        if (ret) {
348
+            dev_err(dev, "Can not enable clock\n");
349
+            return ret;
350
+        }
351
+
352
+        /* reset OSPI to ensure CR_EN bit is set to 0 */
353
+        reset_control_assert(omm->child[i].reset);
354
+        udelay(2);
355
+        reset_control_deassert(omm->child[i].reset);
356
+
357
+        reset_control_put(omm->child[i].reset);
358
+        clk_disable_unprepare(omm->child[i].clk);
359
+    }
360
+
361
+    return 0;
362
+}
363
+
364
+static int stm32_omm_probe(struct platform_device *pdev)
367
+static int stm32_omm_probe(struct platform_device *pdev)
365
+{
368
+{
366
+    struct platform_device *vdev;
367
+    struct device *dev = &pdev->dev;
369
+    struct device *dev = &pdev->dev;
370
+    u8 child_access_granted = 0;
368
+    struct stm32_omm *omm;
371
+    struct stm32_omm *omm;
369
+    int ret;
372
+    int ret;
370
+    u8 child_access_granted = 0;
371
+    u8 i, j;
372
+    bool child_access[OMM_CHILD_NB];
373
+
373
+
374
+    omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
374
+    omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
375
+    if (!omm)
375
+    if (!omm)
376
+        return -ENOMEM;
376
+        return -ENOMEM;
377
+
377
+
378
+    omm->io_base = devm_platform_ioremap_resource_byname(pdev, "omm");
378
+    omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
379
+    if (IS_ERR(omm->io_base))
379
+    if (IS_ERR(omm->io_base))
380
+        return PTR_ERR(omm->io_base);
380
+        return PTR_ERR(omm->io_base);
381
+
381
+
382
+    omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "omm_mm");
382
+    omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
383
+    if (IS_ERR(omm->mm_res))
384
+        return PTR_ERR(omm->mm_res);
383
+
385
+
384
+    /* check child's access */
386
+    /* check child's access */
385
+    for_each_child_of_node_scoped(dev->of_node, child) {
387
+    for_each_child_of_node_scoped(dev->of_node, child) {
386
+        if (omm->nb_child >= OMM_CHILD_NB) {
388
+        if (omm->nb_child >= OMM_CHILD_NB) {
387
+            dev_err(dev, "Bad DT, found too much children\n");
389
+            dev_err(dev, "Bad DT, found too much children\n");
388
+            ret = -E2BIG;
390
+            return -E2BIG;
389
+            goto err_clk_release;
391
+        }
390
+        }
392
+
391
+
393
+        if (!of_device_is_compatible(child, "st,stm32mp25-omi"))
392
+        if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
394
+            return -EINVAL;
393
+            ret = -EINVAL;
395
+
394
+            goto err_clk_release;
396
+        ret = stm32_omm_check_access(child);
395
+        }
396
+
397
+        ret = stm32_omm_check_access(dev, child);
398
+        if (ret < 0 && ret != -EACCES)
397
+        if (ret < 0 && ret != -EACCES)
399
+            goto err_clk_release;
398
+            return ret;
400
+
399
+
401
+        child_access[omm->nb_child] = false;
400
+        if (!ret)
402
+        if (!ret) {
403
+            child_access_granted++;
401
+            child_access_granted++;
404
+            child_access[omm->nb_child] = true;
402
+
405
+        }
406
+
407
+        omm->child[omm->nb_child].node = child;
408
+        omm->child[omm->nb_child].clk = of_clk_get(child, 0);
409
+        omm->child[omm->nb_child].reset = of_reset_control_get_exclusive(child, 0);
410
+        omm->nb_child++;
403
+        omm->nb_child++;
411
+    }
404
+    }
412
+
405
+
413
+    if (omm->nb_child != OMM_CHILD_NB) {
406
+    if (omm->nb_child != OMM_CHILD_NB)
414
+        ret = -EINVAL;
407
+        return -EINVAL;
415
+        goto err_clk_release;
416
+    }
417
+
408
+
418
+    platform_set_drvdata(pdev, omm);
409
+    platform_set_drvdata(pdev, omm);
419
+
410
+
420
+    pm_runtime_enable(dev);
411
+    pm_runtime_enable(dev);
421
+
412
+
422
+    /* check if OMM's resource access is granted */
413
+    /* check if OMM's resource access is granted */
423
+    ret = stm32_omm_check_access(dev, dev->of_node);
414
+    ret = stm32_omm_check_access(dev->of_node);
424
+    if (ret < 0 && ret != -EACCES)
415
+    if (ret < 0 && ret != -EACCES)
425
+        goto err_clk_release;
416
+        goto error;
426
+
417
+
427
+    if (!ret && child_access_granted == OMM_CHILD_NB) {
418
+    if (!ret && child_access_granted == OMM_CHILD_NB) {
428
+        /* Ensure both OSPI instance are disabled before configuring OMM */
429
+        ret = stm32_omm_disable_child(dev);
430
+        if (ret)
431
+            goto err_clk_release;
432
+
433
+        ret = stm32_omm_configure(dev);
419
+        ret = stm32_omm_configure(dev);
434
+        if (ret)
420
+        if (ret)
435
+            goto err_clk_release;
421
+            goto error;
436
+    } else {
422
+    } else {
437
+        dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
423
+        dev_dbg(dev, "Octo Memory Manager resource's access not granted\n");
438
+        /*
424
+        /*
439
+         * AMCR can't be set, so check if current value is coherent
425
+         * AMCR can't be set, so check if current value is coherent
440
+         * with memory-map areas defined in DT
426
+         * with memory-map areas defined in DT
441
+         */
427
+         */
442
+        ret = stm32_omm_set_amcr(dev, false);
428
+        ret = stm32_omm_set_amcr(dev, false);
443
+        if (ret)
429
+        if (ret)
444
+            goto err_clk_release;
430
+            goto error;
445
+    }
431
+    }
446
+
432
+
447
+    /* for each child, if resource access is granted and status "okay", probe it */
433
+    ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
448
+    for (i = 0; i < omm->nb_child; i++) {
434
+    if (ret) {
449
+        if (!child_access[i] || !of_device_is_available(omm->child[i].node))
435
+        dev_err(dev, "Failed to create Octo Memory Manager child\n");
450
+            continue;
436
+        of_platform_depopulate(dev);
451
+
437
+        ret = -EINVAL;
452
+        vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);
438
+        goto error;
453
+        if (!vdev) {
454
+            dev_err(dev, "Failed to create Octo Memory Manager child\n");
455
+            for (j = i; j > 0; --j) {
456
+                if (omm->child[j].dev)
457
+                    of_platform_device_destroy(omm->child[j].dev, NULL);
458
+            }
459
+
460
+            ret = -EINVAL;
461
+            goto err_clk_release;
462
+        }
463
+        omm->child[i].dev = &vdev->dev;
464
+    }
465
+
466
+    return 0;
467
+
468
+err_clk_release:
469
+    for (i = 0; i < omm->nb_child; i++) {
470
+        clk_put(omm->child[i].clk);
471
+        reset_control_put(omm->child[i].reset);
472
+    }
439
+    }
473
+
440
+
474
+    return ret;
441
+    return ret;
442
+
443
+error:
444
+    pm_runtime_disable(dev);
445
+
446
+    return ret;
447
+
475
+}
448
+}
476
+
449
+
477
+static void stm32_omm_remove(struct platform_device *pdev)
450
+static void stm32_omm_remove(struct platform_device *pdev)
478
+{
451
+{
479
+    struct stm32_omm *omm = platform_get_drvdata(pdev);
452
+    struct stm32_omm *omm = platform_get_drvdata(pdev);
480
+    int i;
453
+
481
+
454
+    of_platform_depopulate(&pdev->dev);
482
+    for (i = 0; i < omm->nb_child; i++)
483
+        if (omm->child[i].dev)
484
+            of_platform_device_destroy(omm->child[i].dev, NULL);
485
+
486
+    if (omm->cr & CR_MUXEN)
455
+    if (omm->cr & CR_MUXEN)
487
+        stm32_omm_enable_child_clock(&pdev->dev, false);
456
+        stm32_omm_toggle_child_clock(&pdev->dev, false);
488
+
489
+    for (i = 0; i < omm->nb_child; i++) {
490
+        clk_put(omm->child[i].clk);
491
+        reset_control_put(omm->child[i].reset);
492
+    };
493
+
457
+
494
+    pm_runtime_disable(&pdev->dev);
458
+    pm_runtime_disable(&pdev->dev);
495
+}
459
+}
496
+
460
+
497
+static const struct of_device_id stm32_omm_of_match[] = {
461
+static const struct of_device_id stm32_omm_of_match[] = {
498
+    { .compatible = "st,stm32mp25-omm", },
462
+    { .compatible = "st,stm32mp25-omm", },
499
+    {},
463
+    {}
500
+};
464
+};
501
+MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
465
+MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
502
+
466
+
503
+static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
467
+static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
504
+{
468
+{
505
+    struct stm32_omm *omm = dev_get_drvdata(dev);
469
+    struct stm32_omm *omm = dev_get_drvdata(dev);
506
+
470
+
507
+    clk_disable_unprepare(omm->clk);
471
+    clk_disable_unprepare(omm->clk_bulk[0].clk);
508
+
472
+
509
+    return 0;
473
+    return 0;
510
+}
474
+}
511
+
475
+
512
+static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
476
+static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
513
+{
477
+{
514
+    struct stm32_omm *omm = dev_get_drvdata(dev);
478
+    struct stm32_omm *omm = dev_get_drvdata(dev);
515
+
479
+
516
+    return clk_prepare_enable(omm->clk);
480
+    return clk_prepare_enable(omm->clk_bulk[0].clk);
517
+}
481
+}
518
+
482
+
519
+static int __maybe_unused stm32_omm_suspend(struct device *dev)
483
+static int __maybe_unused stm32_omm_suspend(struct device *dev)
520
+{
484
+{
521
+    struct stm32_omm *omm = dev_get_drvdata(dev);
485
+    struct stm32_omm *omm = dev_get_drvdata(dev);
522
+
486
+
523
+    if (omm->restore_omm && omm->cr & CR_MUXEN)
487
+    if (omm->restore_omm && omm->cr & CR_MUXEN)
524
+        stm32_omm_enable_child_clock(dev, false);
488
+        stm32_omm_toggle_child_clock(dev, false);
525
+
489
+
526
+    return pinctrl_pm_select_sleep_state(dev);
490
+    return pinctrl_pm_select_sleep_state(dev);
527
+}
491
+}
528
+
492
+
529
+static int __maybe_unused stm32_omm_resume(struct device *dev)
493
+static int __maybe_unused stm32_omm_resume(struct device *dev)
...
...
550
+    pm_runtime_put_sync_suspend(dev);
514
+    pm_runtime_put_sync_suspend(dev);
551
+    if (ret)
515
+    if (ret)
552
+        return ret;
516
+        return ret;
553
+
517
+
554
+    if (omm->cr & CR_MUXEN)
518
+    if (omm->cr & CR_MUXEN)
555
+        ret = stm32_omm_enable_child_clock(dev, true);
519
+        ret = stm32_omm_toggle_child_clock(dev, true);
556
+
520
+
557
+    return ret;
521
+    return ret;
558
+}
522
+}
559
+
523
+
560
+static const struct dev_pm_ops stm32_omm_pm_ops = {
524
+static const struct dev_pm_ops stm32_omm_pm_ops = {
...
...
574
+};
538
+};
575
+module_platform_driver(stm32_omm_driver);
539
+module_platform_driver(stm32_omm_driver);
576
+
540
+
577
+MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
541
+MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
578
+MODULE_LICENSE("GPL");
542
+MODULE_LICENSE("GPL");
543
579
--
544
--
580
2.25.1
545
2.25.1
diff view generated by jsdifflib
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
2
3
Add Octo Memory Manager (OMM) entry on stm32mp251 and its two
1
Add Octo Memory Manager (OMM) entry on stm32mp251 and its two
4
OSPI instance.
2
OSPI instance.
5
3
6
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
4
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
7
---
5
---
8
arch/arm64/boot/dts/st/stm32mp251.dtsi | 48 ++++++++++++++++++++++++++
6
arch/arm64/boot/dts/st/stm32mp251.dtsi | 54 ++++++++++++++++++++++++++++++++++
9
1 file changed, 48 insertions(+)
7
1 file changed, 54 insertions(+)
10
8
11
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
9
diff --git a/arch/arm64/boot/dts/st/stm32mp251.dtsi b/arch/arm64/boot/dts/st/stm32mp251.dtsi
12
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
13
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
11
--- a/arch/arm64/boot/dts/st/stm32mp251.dtsi
14
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
12
+++ b/arch/arm64/boot/dts/st/stm32mp251.dtsi
...
...
17
            };
15
            };
18
16
19
+            ommanager: ommanager@40500000 {
17
+            ommanager: ommanager@40500000 {
20
+                compatible = "st,stm32mp25-omm";
18
+                compatible = "st,stm32mp25-omm";
21
+                reg = <0x40500000 0x400>, <0x60000000 0x10000000>;
19
+                reg = <0x40500000 0x400>, <0x60000000 0x10000000>;
22
+                reg-names = "omm", "omm_mm";
20
+                reg-names = "regs", "memory_map";
23
+                ranges = <0 0 0x40430000 0x400>,
21
+                ranges = <0 0 0x40430000 0x400>,
24
+                     <1 0 0x40440000 0x400>;
22
+                     <1 0 0x40440000 0x400>;
25
+                clocks = <&rcc CK_BUS_OSPIIOM>;
23
+                clocks = <&rcc CK_BUS_OSPIIOM>,
26
+                resets = <&rcc OSPIIOM_R>;
24
+                     <&scmi_clk CK_SCMI_OSPI1>,
25
+                     <&scmi_clk CK_SCMI_OSPI2>;
26
+                clock-names = "omm", "ospi1", "ospi2";
27
+                resets = <&rcc OSPIIOM_R>,
28
+                     <&scmi_reset RST_SCMI_OSPI1>,
29
+                     <&scmi_reset RST_SCMI_OSPI2>;
30
+                reset-names = "omm", "ospi1", "ospi2";
31
+                access-controllers = <&rifsc 111>;
32
+                power-domains = <&CLUSTER_PD>;
27
+                #address-cells = <2>;
33
+                #address-cells = <2>;
28
+                #size-cells = <1>;
34
+                #size-cells = <1>;
29
+                st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
35
+                st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
30
+                access-controllers = <&rifsc 111>;
31
+                power-domains = <&CLUSTER_PD>;
32
+                status = "disabled";
36
+                status = "disabled";
33
+
37
+
34
+                ospi1: spi@40430000 {
38
+                ospi1: spi@0 {
35
+                    compatible = "st,stm32mp25-ospi";
39
+                    compatible = "st,stm32mp25-ospi";
36
+                    reg = <0 0 0x400>;
40
+                    reg = <0 0 0x400>;
37
+                    interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
41
+                    interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
38
+                    dmas = <&hpdma 2 0x62 0x00003121>,
42
+                    dmas = <&hpdma 2 0x62 0x00003121>,
39
+                     <&hpdma 2 0x42 0x00003112>;
43
+                     <&hpdma 2 0x42 0x00003112>;
40
+                    dma-names = "tx", "rx";
44
+                    dma-names = "tx", "rx";
41
+                    st,syscfg-dlyb = <&syscfg 0x1000>;
42
+                    clocks = <&scmi_clk CK_SCMI_OSPI1>;
45
+                    clocks = <&scmi_clk CK_SCMI_OSPI1>;
43
+                    resets = <&scmi_reset RST_SCMI_OSPI1>,
46
+                    resets = <&scmi_reset RST_SCMI_OSPI1>,
44
+                         <&scmi_reset RST_SCMI_OSPI1DLL>;
47
+                         <&scmi_reset RST_SCMI_OSPI1DLL>;
45
+                    access-controllers = <&rifsc 74>;
48
+                    access-controllers = <&rifsc 74>;
46
+                    power-domains = <&CLUSTER_PD>;
49
+                    power-domains = <&CLUSTER_PD>;
50
+                    st,syscfg-dlyb = <&syscfg 0x1000>;
47
+                    status = "disabled";
51
+                    status = "disabled";
48
+                };
52
+                };
49
+
53
+
50
+                ospi2: spi@40440000 {
54
+                ospi2: spi@1 {
51
+                    compatible = "st,stm32mp25-ospi";
55
+                    compatible = "st,stm32mp25-ospi";
52
+                    reg = <1 0 0x400>;
56
+                    reg = <1 0 0x400>;
53
+                    interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
57
+                    interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
54
+                    dmas = <&hpdma 3 0x62 0x00003121>,
58
+                    dmas = <&hpdma 3 0x62 0x00003121>,
55
+                     <&hpdma 3 0x42 0x00003112>;
59
+                     <&hpdma 3 0x42 0x00003112>;
56
+                    dma-names = "tx", "rx";
60
+                    dma-names = "tx", "rx";
57
+                    st,syscfg-dlyb = <&syscfg 0x1400>;
58
+                    clocks = <&scmi_clk CK_SCMI_OSPI2>;
61
+                    clocks = <&scmi_clk CK_SCMI_OSPI2>;
59
+                    resets = <&scmi_reset RST_SCMI_OSPI2>,
62
+                    resets = <&scmi_reset RST_SCMI_OSPI2>,
60
+                         <&scmi_reset RST_SCMI_OSPI2DLL>;
63
+                         <&scmi_reset RST_SCMI_OSPI2DLL>;
61
+                    access-controllers = <&rifsc 75>;
64
+                    access-controllers = <&rifsc 75>;
62
+                    power-domains = <&CLUSTER_PD>;
65
+                    power-domains = <&CLUSTER_PD>;
66
+                    st,syscfg-dlyb = <&syscfg 0x1400>;
63
+                    status = "disabled";
67
+                    status = "disabled";
64
+                };
68
+                };
65
+            };
69
+            };
66
+
70
+
67
            spi8: spi@46020000 {
71
            spi8: spi@46020000 {
68
                #address-cells = <1>;
72
                #address-cells = <1>;
69
                #size-cells = <0>;
73
                #size-cells = <0>;
74
70
--
75
--
71
2.25.1
76
2.25.1
diff view generated by jsdifflib
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
2
3
Add pinctrl entry related to OSPI's port1 in stm32mp25-pinctrl.dtsi
1
Add pinctrl entry related to OSPI's port1 in stm32mp25-pinctrl.dtsi
4
2
5
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
3
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
6
---
4
---
7
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +++++++++++++++++++
5
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +++++++++++++++++++++++++++
8
1 file changed, 51 insertions(+)
6
1 file changed, 51 insertions(+)
9
7
10
diff --git a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
8
diff --git a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
11
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
12
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
10
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
...
...
67
+    };
65
+    };
68
+
66
+
69
    sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
67
    sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
70
        pins1 {
68
        pins1 {
71
            pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */
69
            pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */
70
72
--
71
--
73
2.25.1
72
2.25.1
diff view generated by jsdifflib
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
2
3
Add SPI NOR flash nor support on stm32mp257f-ev1 board.
1
Add SPI NOR flash nor support on stm32mp257f-ev1 board.
4
2
5
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
3
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
6
---
4
---
7
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 33 ++++++++++++++++++++++
5
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 32 ++++++++++++++++++++++++++++++
8
1 file changed, 33 insertions(+)
6
1 file changed, 32 insertions(+)
9
7
10
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
8
diff --git a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
11
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
12
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
10
--- a/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
13
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
11
+++ b/arch/arm64/boot/dts/st/stm32mp257f-ev1.dts
...
...
27
    status = "disabled";
25
    status = "disabled";
28
};
26
};
29
27
30
+&ommanager {
28
+&ommanager {
31
+    memory-region = <&mm_ospi1>;
29
+    memory-region = <&mm_ospi1>;
32
+    memory-region-names = "mm_ospi1";
33
+    pinctrl-names = "default", "sleep";
34
+    pinctrl-0 = <&ospi_port1_clk_pins_a
30
+    pinctrl-0 = <&ospi_port1_clk_pins_a
35
+         &ospi_port1_io03_pins_a
31
+         &ospi_port1_io03_pins_a
36
+         &ospi_port1_cs0_pins_a>;
32
+         &ospi_port1_cs0_pins_a>;
37
+    pinctrl-1 = <&ospi_port1_clk_sleep_pins_a
33
+    pinctrl-1 = <&ospi_port1_clk_sleep_pins_a
38
+         &ospi_port1_io03_sleep_pins_a
34
+         &ospi_port1_io03_sleep_pins_a
39
+         &ospi_port1_cs0_sleep_pins_a>;
35
+         &ospi_port1_cs0_sleep_pins_a>;
36
+    pinctrl-names = "default", "sleep";
40
+    status = "okay";
37
+    status = "okay";
41
+
38
+
42
+    spi@40430000 {
39
+    spi@0 {
43
+        #address-cells = <1>;
40
+        #address-cells = <1>;
44
+        #size-cells = <0>;
41
+        #size-cells = <0>;
45
+        memory-region = <&mm_ospi1>;
42
+        memory-region = <&mm_ospi1>;
46
+        status = "okay";
43
+        status = "okay";
47
+
44
+
...
...
56
+};
53
+};
57
+
54
+
58
&rtc {
55
&rtc {
59
    status = "okay";
56
    status = "okay";
60
};
57
};
58
61
--
59
--
62
2.25.1
60
2.25.1
diff view generated by jsdifflib
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
1
Enable STM32 OctoSPI driver.
2
2
Enable STM32 Octo Memory Manager (OMM) driver which is needed
3
Enable the STM32 OctoSPI driver.
3
for OSPI usage on STM32MP257F-EV1 board.
4
4
5
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
5
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
6
---
6
---
7
arch/arm64/configs/defconfig | 1 +
7
arch/arm64/configs/defconfig | 2 ++
8
1 file changed, 1 insertion(+)
8
1 file changed, 2 insertions(+)
9
9
10
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
10
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
11
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
12
--- a/arch/arm64/configs/defconfig
12
--- a/arch/arm64/configs/defconfig
13
+++ b/arch/arm64/configs/defconfig
13
+++ b/arch/arm64/configs/defconfig
...
...
17
CONFIG_SPI_SH_MSIOF=m
17
CONFIG_SPI_SH_MSIOF=m
18
+CONFIG_SPI_STM32_OSPI=m
18
+CONFIG_SPI_STM32_OSPI=m
19
CONFIG_SPI_SUN6I=y
19
CONFIG_SPI_SUN6I=y
20
CONFIG_SPI_TEGRA210_QUAD=m
20
CONFIG_SPI_TEGRA210_QUAD=m
21
CONFIG_SPI_TEGRA114=m
21
CONFIG_SPI_TEGRA114=m
22
@@ -XXX,XX +XXX,XX @@ CONFIG_EXTCON_USB_GPIO=y
23
CONFIG_EXTCON_USBC_CROS_EC=y
24
CONFIG_FSL_IFC=y
25
CONFIG_RENESAS_RPCIF=m
26
+CONFIG_STM32_OMM=m
27
CONFIG_IIO=y
28
CONFIG_EXYNOS_ADC=y
29
CONFIG_IMX8QXP_ADC=m
30
22
--
31
--
23
2.25.1
32
2.25.1
diff view generated by jsdifflib