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>
11
17
12
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
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.
13
61
14
Changes in v3:
62
Changes in v3:
15
- Squash defconfig patches 8 and 9.
63
- Squash defconfig patches 8 and 9.
16
- Update STM32 Octo Memory Manager controller bindings.
64
- Update STM32 Octo Memory Manager controller bindings.
17
- Rename st,stm32-omm.yaml to st,stm32mp25-omm.yaml.
65
- Rename st,stm32-omm.yaml to st,stm32mp25-omm.yaml.
18
- Update STM32 OSPI controller bindings.
66
- Update STM32 OSPI controller bindings.
19
- Reorder DT properties in .dtsi and .dts files.
67
- Reorder DT properties in .dtsi and .dts files.
20
- Replace devm_reset_control_get_optional() by devm_reset_control_get_optional_exclusive() in stm32_omm.c.
68
- Replace devm_reset_control_get_optional() by
69
devm_reset_control_get_optional_exclusive() in stm32_omm.c.
21
- Reintroduce region-memory-names management in stm32_omm.c.
70
- Reintroduce region-memory-names management in stm32_omm.c.
22
- Rename stm32_ospi_tx_poll() to stm32_ospi_poll() in spi-stm32-ospi.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.
23
- Set SPI_CONTROLLER_HALF_DUPLEX in controller flags in spi-stm32-ospi.c.
73
- Set SPI_CONTROLLER_HALF_DUPLEX in controller flags in spi-stm32-ospi.c.
24
74
25
Changes in v2:
75
Changes in v2:
26
- Move STM32 Octo Memory Manager controller driver and bindings from
76
- Move STM32 Octo Memory Manager controller driver and bindings from
27
misc to memory-controllers.
77
misc to memory-controllers.
28
- Update STM32 OSPI controller bindings.
78
- Update STM32 OSPI controller bindings.
29
- Update STM32 Octo Memory Manager controller bindings.
79
- Update STM32 Octo Memory Manager controller bindings.
30
- Update STM32 Octo Memory Manager driver to match bindings update.
80
- Update STM32 Octo Memory Manager driver to match bindings update.
31
- Update DT to match bindings update.
81
- Update DT to match bindings update.
32
82
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
33
93
94
.../memory-controllers/st,stm32mp25-omm.yaml | 227 ++++++++++
95
MAINTAINERS | 6 +
96
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +++
97
arch/arm64/boot/dts/st/stm32mp251.dtsi | 54 +++
98
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 32 ++
99
arch/arm64/configs/defconfig | 2 +
100
drivers/memory/Kconfig | 17 +
101
drivers/memory/Makefile | 1 +
102
drivers/memory/stm32_omm.c | 474 +++++++++++++++++++++
103
9 files changed, 864 insertions(+)
104
---
105
base-commit: 88424abd55ab36c3565898a656589a0a25ecd92f
106
change-id: 20250320-upstream_ospi_v6-d432a8172105
34
107
35
Patrice Chotard (8):
108
Best regards,
36
dt-bindings: spi: Add STM32 OSPI controller
37
spi: stm32: Add OSPI driver
38
dt-bindings: memory-controllers: Add STM32 Octo Memory Manager
39
controller
40
memory: Add STM32 Octo Memory Manager driver
41
arm64: dts: st: Add OMM node on stm32mp251
42
arm64: dts: st: Add ospi port1 pinctrl entries in
43
stm32mp25-pinctrl.dtsi
44
arm64: dts: st: Add SPI NOR flash support on stm32mp257f-ev1 board
45
arm64: defconfig: Enable STM32 Octo Memory Manager and OcstoSPI driver
46
47
.../memory-controllers/st,stm32mp25-omm.yaml | 201 ++++
48
.../bindings/spi/st,stm32mp25-ospi.yaml | 105 ++
49
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +
50
arch/arm64/boot/dts/st/stm32mp251.dtsi | 48 +
51
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 32 +
52
arch/arm64/configs/defconfig | 2 +
53
drivers/memory/Kconfig | 17 +
54
drivers/memory/Makefile | 1 +
55
drivers/memory/stm32_omm.c | 520 ++++++++
56
drivers/spi/Kconfig | 10 +
57
drivers/spi/Makefile | 1 +
58
drivers/spi/spi-stm32-ospi.c | 1065 +++++++++++++++++
59
12 files changed, 2053 insertions(+)
60
create mode 100644 Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
61
create mode 100644 Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
62
create mode 100644 drivers/memory/stm32_omm.c
63
create mode 100644 drivers/spi/spi-stm32-ospi.c
64
65
--
109
--
66
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,stm32mp25-ospi.yaml | 105 ++++++++++++++++++
25
1 file changed, 105 insertions(+)
26
create mode 100644 Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
27
28
diff --git a/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml b/Documentation/devicetree/bindings/spi/st,stm32mp25-ospi.yaml
29
new file mode 100644
30
index XXXXXXX..XXXXXXX
31
--- /dev/null
32
+++ b/Documentation/devicetree/bindings/spi/st,stm32mp25-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,stm32mp25-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
+ maxItems: 1
54
+
55
+ memory-region:
56
+ description:
57
+ Memory region to be used for memory-map read access.
58
+ In memory-mapped mode, read access are performed from the memory
59
+ device using the direct mapping.
60
+ maxItems: 1
61
+
62
+ clocks:
63
+ maxItems: 1
64
+
65
+ interrupts:
66
+ maxItems: 1
67
+
68
+ resets:
69
+ items:
70
+ - description: phandle to OSPI block reset
71
+ - description: phandle to delay block reset
72
+
73
+ dmas:
74
+ maxItems: 2
75
+
76
+ dma-names:
77
+ items:
78
+ - const: tx
79
+ - const: rx
80
+
81
+ st,syscfg-dlyb:
82
+ description: configure OCTOSPI delay block.
83
+ $ref: /schemas/types.yaml#/definitions/phandle-array
84
+ items:
85
+ - description: phandle to syscfg
86
+ - description: register offset within syscfg
87
+
88
+ access-controllers:
89
+ description: phandle to the rifsc device to check access right
90
+ and in some cases, an additional phandle to the rcc device for
91
+ secure clock control.
92
+ items:
93
+ - description: phandle to bus controller
94
+ - description: phandle to clock controller
95
+ minItems: 1
96
+
97
+ power-domains:
98
+ maxItems: 1
99
+
100
+required:
101
+ - compatible
102
+ - reg
103
+ - clocks
104
+ - interrupts
105
+ - st,syscfg-dlyb
106
+
107
+unevaluatedProperties: false
108
+
109
+examples:
110
+ - |
111
+ #include <dt-bindings/clock/st,stm32mp25-rcc.h>
112
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
113
+ #include <dt-bindings/reset/st,stm32mp25-rcc.h>
114
+
115
+ spi@40430000 {
116
+ compatible = "st,stm32mp25-ospi";
117
+ reg = <0x40430000 0x400>;
118
+ memory-region = <&mm_ospi1>;
119
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
120
+ dmas = <&hpdma 2 0x62 0x00003121 0x0>,
121
+ <&hpdma 2 0x42 0x00003112 0x0>;
122
+ dma-names = "tx", "rx";
123
+ clocks = <&scmi_clk CK_SCMI_OSPI1>;
124
+ resets = <&scmi_reset RST_SCMI_OSPI1>, <&scmi_reset RST_SCMI_OSPI1DLL>;
125
+ access-controllers = <&rifsc 74>;
126
+ power-domains = <&CLUSTER_PD>;
127
+ st,syscfg-dlyb = <&syscfg 0x1000>;
128
+
129
+ #address-cells = <1>;
130
+ #size-cells = <0>;
131
+
132
+ flash@0 {
133
+ compatible = "jedec,spi-nor";
134
+ reg = <0>;
135
+ spi-rx-bus-width = <4>;
136
+ spi-max-frequency = <108000000>;
137
+ };
138
+ };
139
--
140
2.25.1
141
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
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
2
12
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
3
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
13
---
4
---
14
drivers/spi/Kconfig | 10 +
5
MAINTAINERS | 6 ++++++
15
drivers/spi/Makefile | 1 +
6
1 file changed, 6 insertions(+)
16
drivers/spi/spi-stm32-ospi.c | 1065 ++++++++++++++++++++++++++++++++++
17
3 files changed, 1076 insertions(+)
18
create mode 100644 drivers/spi/spi-stm32-ospi.c
19
7
20
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
8
diff --git a/MAINTAINERS b/MAINTAINERS
21
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
22
--- a/drivers/spi/Kconfig
10
--- a/MAINTAINERS
23
+++ b/drivers/spi/Kconfig
11
+++ b/MAINTAINERS
24
@@ -XXX,XX +XXX,XX @@ config SPI_STM32
12
@@ -XXX,XX +XXX,XX @@ L:    linux-i2c@vger.kernel.org
25
     is not available, the driver automatically falls back to
13
S:    Maintained
26
     PIO mode.
14
F:    drivers/i2c/busses/i2c-stm32*
27
15
28
+config SPI_STM32_OSPI
16
+ST STM32 OCTO MEMORY MANAGER
29
+    tristate "STMicroelectronics STM32 OCTO SPI controller"
17
+M:    Patrice Chotard <patrice.chotard@foss.st.com>
30
+    depends on ARCH_STM32 || COMPILE_TEST
18
+S:    Maintained
31
+    depends on OF
19
+F:    Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
32
+    depends on SPI_MEM
20
+F:    drivers/memory/stm32_omm.c
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
+
21
+
38
config SPI_STM32_QSPI
22
ST STM32 SPI DRIVER
39
    tristate "STMicroelectronics STM32 QUAD SPI controller"
23
M:    Alain Volmat <alain.volmat@foss.st.com>
40
    depends on ARCH_STM32 || COMPILE_TEST
24
L:    linux-spi@vger.kernel.org
41
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
25
42
index XXXXXXX..XXXXXXX 100644
43
--- a/drivers/spi/Makefile
44
+++ b/drivers/spi/Makefile
45
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_SPI_SN_F_OSPI)        += spi-sn-f-ospi.o
46
obj-$(CONFIG_SPI_SPRD)            += spi-sprd.o
47
obj-$(CONFIG_SPI_SPRD_ADI)        += spi-sprd-adi.o
48
obj-$(CONFIG_SPI_STM32)         += spi-stm32.o
49
+obj-$(CONFIG_SPI_STM32_OSPI)         += spi-stm32-ospi.o
50
obj-$(CONFIG_SPI_STM32_QSPI)         += spi-stm32-qspi.o
51
obj-$(CONFIG_SPI_ST_SSC4)        += spi-st-ssc4.o
52
obj-$(CONFIG_SPI_SUN4I)            += spi-sun4i.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_poll(struct stm32_ospi *ospi, u8 *buf, u32 len, bool read)
234
+{
235
+    void __iomem *regs_base = ospi->regs_base;
236
+    void (*fifo)(u8 *val, void __iomem *addr);
237
+    u32 sr;
238
+    int ret;
239
+
240
+    if (read)
241
+        fifo = stm32_ospi_read_fifo;
242
+    else
243
+        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
+        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_xfer(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_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_xfer(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->flags = SPI_CONTROLLER_HALF_DUPLEX;
983
+    ctrl->setup = stm32_ospi_setup;
984
+    ctrl->bus_num = -1;
985
+    ctrl->mem_ops = &stm32_ospi_mem_ops;
986
+    ctrl->use_gpio_descriptors = true;
987
+    ctrl->transfer_one_message = stm32_ospi_transfer_one_message;
988
+    ctrl->num_chipselect = STM32_OSPI_MAX_NORCHIP;
989
+    ctrl->dev.of_node = dev->of_node;
990
+
991
+    pm_runtime_enable(ospi->dev);
992
+    pm_runtime_set_autosuspend_delay(ospi->dev, STM32_AUTOSUSPEND_DELAY);
993
+    pm_runtime_use_autosuspend(ospi->dev);
994
+
995
+    ret = pm_runtime_resume_and_get(ospi->dev);
996
+    if (ret < 0)
997
+        goto err_pm_enable;
998
+
999
+    if (ospi->rstc) {
1000
+        reset_control_assert(ospi->rstc);
1001
+        udelay(2);
1002
+        reset_control_deassert(ospi->rstc);
1003
+    }
1004
+
1005
+    ret = spi_register_controller(ctrl);
1006
+    if (ret) {
1007
+        /* Disable ospi */
1008
+        writel_relaxed(0, ospi->regs_base + OSPI_CR);
1009
+        goto err_pm_resume;
1010
+    }
1011
+
1012
+    pm_runtime_mark_last_busy(ospi->dev);
1013
+    pm_runtime_put_autosuspend(ospi->dev);
1014
+
1015
+    return 0;
1016
+
1017
+err_pm_resume:
1018
+    pm_runtime_put_sync_suspend(ospi->dev);
1019
+
1020
+err_pm_enable:
1021
+    pm_runtime_force_suspend(ospi->dev);
1022
+    mutex_destroy(&ospi->lock);
1023
+
1024
+    return ret;
1025
+}
1026
+
1027
+static void stm32_ospi_remove(struct platform_device *pdev)
1028
+{
1029
+    struct stm32_ospi *ospi = platform_get_drvdata(pdev);
1030
+    int ret;
1031
+
1032
+    ret = pm_runtime_resume_and_get(ospi->dev);
1033
+    if (ret < 0)
1034
+        return;
1035
+
1036
+    spi_unregister_controller(ospi->ctrl);
1037
+    /* Disable ospi */
1038
+    writel_relaxed(0, ospi->regs_base + OSPI_CR);
1039
+    mutex_destroy(&ospi->lock);
1040
+
1041
+    if (ospi->dma_chtx)
1042
+        dma_release_channel(ospi->dma_chtx);
1043
+    if (ospi->dma_chrx)
1044
+        dma_release_channel(ospi->dma_chrx);
1045
+
1046
+    pm_runtime_put_sync_suspend(ospi->dev);
1047
+    pm_runtime_force_suspend(ospi->dev);
1048
+}
1049
+
1050
+static int __maybe_unused stm32_ospi_suspend(struct device *dev)
1051
+{
1052
+    struct stm32_ospi *ospi = dev_get_drvdata(dev);
1053
+
1054
+    pinctrl_pm_select_sleep_state(dev);
1055
+
1056
+    return pm_runtime_force_suspend(ospi->dev);
1057
+}
1058
+
1059
+static int __maybe_unused stm32_ospi_resume(struct device *dev)
1060
+{
1061
+    struct stm32_ospi *ospi = dev_get_drvdata(dev);
1062
+    void __iomem *regs_base = ospi->regs_base;
1063
+    int ret;
1064
+
1065
+    ret = pm_runtime_force_resume(ospi->dev);
1066
+    if (ret < 0)
1067
+        return ret;
1068
+
1069
+    pinctrl_pm_select_default_state(dev);
1070
+
1071
+    ret = pm_runtime_resume_and_get(ospi->dev);
1072
+    if (ret < 0)
1073
+        return ret;
1074
+
1075
+    writel_relaxed(ospi->cr_reg, regs_base + OSPI_CR);
1076
+    writel_relaxed(ospi->dcr_reg, regs_base + OSPI_DCR1);
1077
+    pm_runtime_mark_last_busy(ospi->dev);
1078
+    pm_runtime_put_autosuspend(ospi->dev);
1079
+
1080
+    return 0;
1081
+}
1082
+
1083
+static int __maybe_unused stm32_ospi_runtime_suspend(struct device *dev)
1084
+{
1085
+    struct stm32_ospi *ospi = dev_get_drvdata(dev);
1086
+
1087
+    clk_disable_unprepare(ospi->clk);
1088
+
1089
+    return 0;
1090
+}
1091
+
1092
+static int __maybe_unused stm32_ospi_runtime_resume(struct device *dev)
1093
+{
1094
+    struct stm32_ospi *ospi = dev_get_drvdata(dev);
1095
+
1096
+    return clk_prepare_enable(ospi->clk);
1097
+}
1098
+
1099
+static const struct dev_pm_ops stm32_ospi_pm_ops = {
1100
+    SET_SYSTEM_SLEEP_PM_OPS(stm32_ospi_suspend, stm32_ospi_resume)
1101
+    SET_RUNTIME_PM_OPS(stm32_ospi_runtime_suspend,
1102
+             stm32_ospi_runtime_resume, NULL)
1103
+};
1104
+
1105
+static const struct of_device_id stm32_ospi_of_match[] = {
1106
+    { .compatible = "st,stm32mp25-ospi" },
1107
+    {},
1108
+};
1109
+MODULE_DEVICE_TABLE(of, stm32_ospi_of_match);
1110
+
1111
+static struct platform_driver stm32_ospi_driver = {
1112
+    .probe    = stm32_ospi_probe,
1113
+    .remove    = stm32_ospi_remove,
1114
+    .driver    = {
1115
+        .name = "stm32-ospi",
1116
+        .pm = &stm32_ospi_pm_ops,
1117
+        .of_match_table = stm32_ospi_of_match,
1118
+    },
1119
+};
1120
+module_platform_driver(stm32_ospi_driver);
1121
+
1122
+MODULE_DESCRIPTION("STMicroelectronics STM32 OCTO SPI driver");
1123
+MODULE_LICENSE("GPL");
1124
--
26
--
1125
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
.../memory-controllers/st,stm32mp25-omm.yaml | 201 ++++++++++++++++++
18
.../memory-controllers/st,stm32mp25-omm.yaml | 227 +++++++++++++++++++++
21
1 file changed, 201 insertions(+)
19
1 file changed, 227 insertions(+)
22
create mode 100644 Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
23
20
24
diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
21
diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-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
...
...
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>
64
+ minItems: 2
61
+ minItems: 2
65
+ maxItems: 2
62
+ maxItems: 2
66
+
63
+
...
...
73
+ items:
70
+ items:
74
+ - const: regs
71
+ - const: regs
75
+ - const: memory_map
72
+ - const: memory_map
76
+
73
+
77
+ memory-region:
74
+ memory-region:
78
+ description: |
75
+ description:
79
+ Memory region shared between the 2 OCTOSPI instance.
76
+ Memory region shared between the 2 OCTOSPI instance.
80
+ One or two phandle to a node describing a memory mapped region
77
+ One or two phandle to a node describing a memory mapped region
81
+ depending of child number.
78
+ depending of child number.
82
+ minItems: 1
79
+ minItems: 1
83
+ maxItems: 2
80
+ maxItems: 2
84
+
81
+
85
+ memory-region-names:
82
+ memory-region-names:
86
+ description: |
83
+ description:
87
+ OCTOSPI instance's name to which memory region is associated
84
+ Identify to which OSPI instance the memory region belongs to.
88
+ items:
85
+ items:
89
+ enum: [ospi1, ospi2]
86
+ enum: [ospi1, ospi2]
90
+ minItems: 1
87
+ minItems: 1
91
+ maxItems: 2
88
+ maxItems: 2
92
+
89
+
93
+ clocks:
90
+ clocks:
94
+ maxItems: 1
91
+ minItems: 3
92
+ maxItems: 3
93
+
94
+ clock-names:
95
+ items:
96
+ - const: omm
97
+ - const: ospi1
98
+ - const: ospi2
95
+
99
+
96
+ resets:
100
+ resets:
97
+ maxItems: 1
101
+ minItems: 3
102
+ maxItems: 3
103
+
104
+ reset-names:
105
+ items:
106
+ - const: omm
107
+ - const: ospi1
108
+ - const: ospi2
98
+
109
+
99
+ access-controllers:
110
+ access-controllers:
100
+ maxItems: 1
111
+ maxItems: 1
101
+
112
+
102
+ st,syscfg-amcr:
113
+ st,syscfg-amcr:
...
...
115
+ - description: phandle to syscfg
126
+ - description: phandle to syscfg
116
+ - description: register offset within syscfg
127
+ - description: register offset within syscfg
117
+ - description: register bitmask for memory split
128
+ - description: register bitmask for memory split
118
+
129
+
119
+ st,omm-req2ack-ns:
130
+ st,omm-req2ack-ns:
120
+ description: |
131
+ description:
121
+ In multiplexed mode (MUXEN = 1), this field defines the time in
132
+ In multiplexed mode (MUXEN = 1), this field defines the time in
122
+ nanoseconds between two transactions.
133
+ nanoseconds between two transactions.
134
+ default: 0
123
+
135
+
124
+ st,omm-cssel-ovr:
136
+ st,omm-cssel-ovr:
125
+ $ref: /schemas/types.yaml#/definitions/uint32
137
+ $ref: /schemas/types.yaml#/definitions/uint32
126
+ description: |
138
+ description: |
127
+ Configure the chip select selector override for the 2 OCTOSPIs.
139
+ Configure the chip select selector override for the 2 OCTOSPIs.
128
+ - 0: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS1
140
+ - 0: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS1
129
+ - 1: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS1
141
+ - 1: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS1
130
+ - 2: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS2
142
+ - 2: OCTOSPI1 chip select send to NCS1 OCTOSPI2 chip select send to NCS2
131
+ - 3: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS2
143
+ - 3: OCTOSPI1 chip select send to NCS2 OCTOSPI2 chip select send to NCS2
132
+ minimum: 0
144
+ minimum: 0
133
+ maximum: 3
145
+ maximum: 3
146
+ default: 0
134
+
147
+
135
+ st,omm-mux:
148
+ st,omm-mux:
136
+ $ref: /schemas/types.yaml#/definitions/uint32
149
+ $ref: /schemas/types.yaml#/definitions/uint32
137
+ description: |
150
+ description: |
138
+ 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.
139
+ - 0: direct mode, default
152
+ - 0: direct mode
140
+ - 1: mux OCTOSPI1 and OCTOSPI2 to port 1
153
+ - 1: mux OCTOSPI1 and OCTOSPI2 to port 1
141
+ - 2: swapped mode
154
+ - 2: swapped mode
142
+ - 3: mux OCTOSPI1 and OCTOSPI2 to port 2
155
+ - 3: mux OCTOSPI1 and OCTOSPI2 to port 2
143
+ minimum: 0
156
+ minimum: 0
144
+ maximum: 3
157
+ maximum: 3
158
+ default: 0
145
+
159
+
146
+ power-domains:
160
+ power-domains:
147
+ maxItems: 1
161
+ maxItems: 1
148
+
162
+
149
+patternProperties:
163
+patternProperties:
150
+ ^spi@[a-f0-9]+$:
164
+ ^spi@[0-9]:
151
+ type: object
165
+ type: object
152
+ $ref: /schemas/spi/st,stm32mp25-ospi.yaml#
166
+ $ref: /schemas/spi/st,stm32mp25-ospi.yaml#
153
+ description: Required spi child node
167
+ description: Required spi child node
154
+
168
+
155
+required:
169
+required:
156
+ - compatible
170
+ - compatible
157
+ - reg
171
+ - reg
158
+ - "#address-cells"
172
+ - "#address-cells"
159
+ - "#size-cells"
173
+ - "#size-cells"
160
+ - clocks
174
+ - clocks
175
+ - clock-names
176
+ - resets
177
+ - reset-names
161
+ - st,syscfg-amcr
178
+ - st,syscfg-amcr
162
+ - ranges
179
+ - ranges
163
+
180
+
164
+additionalProperties: false
181
+additionalProperties: false
165
+
182
+
...
...
181
+ &ospi_port1_cs0_pins_a>;
198
+ &ospi_port1_cs0_pins_a>;
182
+ pinctrl-1 = <&ospi_port1_clk_sleep_pins_a
199
+ pinctrl-1 = <&ospi_port1_clk_sleep_pins_a
183
+ &ospi_port1_io03_sleep_pins_a
200
+ &ospi_port1_io03_sleep_pins_a
184
+ &ospi_port1_cs0_sleep_pins_a>;
201
+ &ospi_port1_cs0_sleep_pins_a>;
185
+ pinctrl-names = "default", "sleep";
202
+ pinctrl-names = "default", "sleep";
186
+ clocks = <&rcc CK_BUS_OSPIIOM>;
203
+ clocks = <&rcc CK_BUS_OSPIIOM>,
187
+ resets = <&rcc OSPIIOM_R>;
204
+ <&scmi_clk CK_SCMI_OSPI1>,
205
+ <&scmi_clk CK_SCMI_OSPI2>;
206
+ clock-names = "omm", "ospi1", "ospi2";
207
+ resets = <&rcc OSPIIOM_R>,
208
+ <&scmi_reset RST_SCMI_OSPI1>,
209
+ <&scmi_reset RST_SCMI_OSPI2>;
210
+ reset-names = "omm", "ospi1", "ospi2";
188
+ access-controllers = <&rifsc 111>;
211
+ access-controllers = <&rifsc 111>;
189
+ power-domains = <&CLUSTER_PD>;
212
+ power-domains = <&CLUSTER_PD>;
190
+ #address-cells = <2>;
213
+ #address-cells = <2>;
191
+ #size-cells = <1>;
214
+ #size-cells = <1>;
192
+ st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
215
+ st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
193
+ st,omm-req2ack-ns = <0>;
216
+ st,omm-req2ack-ns = <0>;
194
+ st,omm-mux = <0>;
217
+ st,omm-mux = <0>;
195
+ st,omm-cssel-ovr = <0>;
218
+ st,omm-cssel-ovr = <0>;
196
+
219
+
197
+ spi@40430000 {
220
+ spi@0 {
198
+ compatible = "st,stm32mp25-ospi";
221
+ compatible = "st,stm32mp25-ospi";
199
+ reg = <0 0 0x400>;
222
+ reg = <0 0 0x400>;
200
+ memory-region = <&mm_ospi1>;
223
+ memory-region = <&mm_ospi1>;
201
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
224
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
202
+ dmas = <&hpdma 2 0x62 0x00003121 0x0>,
225
+ dmas = <&hpdma 2 0x62 0x00003121 0x0>,
...
...
209
+ #address-cells = <1>;
232
+ #address-cells = <1>;
210
+ #size-cells = <0>;
233
+ #size-cells = <0>;
211
+ st,syscfg-dlyb = <&syscfg 0x1000>;
234
+ st,syscfg-dlyb = <&syscfg 0x1000>;
212
+ };
235
+ };
213
+
236
+
214
+ spi@40440000 {
237
+ spi@1 {
215
+ compatible = "st,stm32mp25-ospi";
238
+ compatible = "st,stm32mp25-ospi";
216
+ reg = <1 0 0x400>;
239
+ reg = <1 0 0x400>;
217
+ memory-region = <&mm_ospi1>;
240
+ memory-region = <&mm_ospi1>;
218
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
241
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
219
+ dmas = <&hpdma 3 0x62 0x00003121 0x0>,
242
+ dmas = <&hpdma 3 0x62 0x00003121 0x0>,
...
...
226
+ #address-cells = <1>;
249
+ #address-cells = <1>;
227
+ #size-cells = <0>;
250
+ #size-cells = <0>;
228
+ st,syscfg-dlyb = <&syscfg 0x1000>;
251
+ st,syscfg-dlyb = <&syscfg 0x1000>;
229
+ };
252
+ };
230
+ };
253
+ };
254
231
--
255
--
232
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/memory/Kconfig | 17 ++
18
drivers/memory/Kconfig | 17 ++
21
drivers/memory/Makefile | 1 +
19
drivers/memory/Makefile | 1 +
22
drivers/memory/stm32_omm.c | 520 +++++++++++++++++++++++++++++++++++++
20
drivers/memory/stm32_omm.c | 474 +++++++++++++++++++++++++++++++++++++++++++++
23
3 files changed, 538 insertions(+)
21
3 files changed, 492 insertions(+)
24
create mode 100644 drivers/memory/stm32_omm.c
25
22
26
diff --git a/drivers/memory/Kconfig b/drivers/memory/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/memory/Kconfig
25
--- a/drivers/memory/Kconfig
29
+++ b/drivers/memory/Kconfig
26
+++ b/drivers/memory/Kconfig
30
@@ -XXX,XX +XXX,XX @@ config STM32_FMC2_EBI
27
@@ -XXX,XX +XXX,XX @@ config STM32_FMC2_EBI
31
     devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
28
     devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
32
     SOCs containing the FMC2 External Bus Interface.
29
     SOCs containing the FMC2 External Bus Interface.
33
30
34
+config STM32_OMM
31
+config STM32_OMM
35
+    tristate "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
...
...
67
new file mode 100644
64
new file mode 100644
68
index XXXXXXX..XXXXXXX
65
index XXXXXXX..XXXXXXX
69
--- /dev/null
66
--- /dev/null
70
+++ b/drivers/memory/stm32_omm.c
67
+++ b/drivers/memory/stm32_omm.c
71
@@ -XXX,XX +XXX,XX @@
68
@@ -XXX,XX +XXX,XX @@
72
+// SPDX-License-Identifier: GPL
69
+// SPDX-License-Identifier: GPL-2.0
73
+/*
70
+/*
74
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
71
+ * Copyright (C) STMicroelectronics 2025 - All Rights Reserved
75
+ * Author(s): Patrice Chotard <patrice.chotard@foss.st.com> for STMicroelectronics.
72
+ * Author(s): Patrice Chotard <patrice.chotard@foss.st.com> for STMicroelectronics.
76
+ */
73
+ */
77
+
74
+
75
+#include <linux/bitfield.h>
78
+#include <linux/bus/stm32_firewall_device.h>
76
+#include <linux/bus/stm32_firewall_device.h>
79
+#include <linux/clk.h>
77
+#include <linux/clk.h>
80
+#include <linux/err.h>
78
+#include <linux/err.h>
81
+#include <linux/mfd/syscon.h>
79
+#include <linux/mfd/syscon.h>
82
+#include <linux/mod_devicetable.h>
80
+#include <linux/mod_devicetable.h>
...
...
94
+#define CR_CSSEL_OVR_EN        BIT(4)
92
+#define CR_CSSEL_OVR_EN        BIT(4)
95
+#define CR_CSSEL_OVR_MASK    GENMASK(6, 5)
93
+#define CR_CSSEL_OVR_MASK    GENMASK(6, 5)
96
+#define CR_REQ2ACK_MASK        GENMASK(23, 16)
94
+#define CR_REQ2ACK_MASK        GENMASK(23, 16)
97
+
95
+
98
+#define OMM_CHILD_NB        2
96
+#define OMM_CHILD_NB        2
99
+
97
+#define OMM_CLK_NB        3
100
+struct ospi_child {
101
+    struct device *dev;
102
+    struct device_node *node;
103
+    struct clk *clk;
104
+};
105
+
98
+
106
+struct stm32_omm {
99
+struct stm32_omm {
107
+    struct ospi_child child[OMM_CHILD_NB];
108
+    struct resource *mm_res;
100
+    struct resource *mm_res;
109
+    struct clk *clk;
101
+    struct clk_bulk_data clk_bulk[OMM_CLK_NB];
110
+    void __iomem *io_base;
102
+    void __iomem *io_base;
111
+    u32 cr;
103
+    u32 cr;
112
+    u8 nb_child;
104
+    u8 nb_child;
113
+    bool restore_omm;
105
+    bool restore_omm;
114
+};
106
+};
115
+
107
+
116
+static int stm32_omm_set_amcr(struct device *dev, bool set)
108
+static int stm32_omm_set_amcr(struct device *dev, bool set)
117
+{
109
+{
118
+    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" };
119
+    struct regmap *syscfg_regmap;
113
+    struct regmap *syscfg_regmap;
120
+    struct device_node *node;
114
+    struct device_node *node;
121
+    struct resource res, res1;
115
+    struct resource res, res1;
122
+    resource_size_t mm_ospi2_size = 0;
123
+    static const char * const mm_name[] = { "ospi1", "ospi2" };
124
+    u32 amcr_base, amcr_mask;
116
+    u32 amcr_base, amcr_mask;
125
+    int ret, i, idx;
117
+    int ret, idx;
126
+    unsigned int amcr, read_amcr;
118
+    unsigned int i, amcr, read_amcr;
127
+
119
+
128
+    for (i = 0; i < omm->nb_child; i++) {
120
+    for (i = 0; i < omm->nb_child; i++) {
129
+        idx = of_property_match_string(dev->of_node,
121
+        idx = of_property_match_string(dev->of_node,
130
+                     "memory-region-names",
122
+                     "memory-region-names",
131
+                     mm_name[i]);
123
+                     mm_name[i]);
...
...
148
+
140
+
149
+        /* check that memory region fits inside OMM memory map area */
141
+        /* check that memory region fits inside OMM memory map area */
150
+        if (!resource_contains(omm->mm_res, &res)) {
142
+        if (!resource_contains(omm->mm_res, &res)) {
151
+            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",
152
+                mm_name[i]);
144
+                mm_name[i]);
153
+            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);
154
+                res.start, res.end,
155
+                omm->mm_res->start, omm->mm_res->end);
156
+
146
+
157
+            return -EFAULT;
147
+            return -EFAULT;
158
+        }
148
+        }
159
+
149
+
160
+        if (i == 1) {
150
+        if (i == 1) {
161
+            mm_ospi2_size = resource_size(&res);
151
+            mm_ospi2_size = resource_size(&res);
162
+
152
+
163
+            /* 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 */
164
+            if (resource_overlaps(&res, &res1)) {
154
+            if (resource_overlaps(&res, &res1)) {
165
+                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",
166
+                    mm_name[0], mm_name[1]);
156
+                    mm_name[0], mm_name[1]);
167
+                dev_err(dev, "[0x%llx-0x%llx] overlaps [0x%llx-0x%llx]\n",
157
+                dev_err(dev, "%pR overlaps %pR\n", &res1, &res);
168
+                    res1.start, res1.end, res.start, res.end);
169
+
158
+
170
+                return -EFAULT;
159
+                return -EFAULT;
171
+            }
160
+            }
172
+        }
161
+        }
173
+    }
162
+    }
174
+
163
+
175
+    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");
176
+    if (IS_ERR(syscfg_regmap)) {
165
+    if (IS_ERR(syscfg_regmap))
177
+        dev_err(dev, "Failed to get st,syscfg-amcr property\n");
166
+        return dev_err_probe(dev, PTR_ERR(syscfg_regmap),
178
+        return PTR_ERR(syscfg_regmap);
167
+                 "Failed to get st,syscfg-amcr property\n");
179
+    }
180
+
168
+
181
+    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,
182
+                     &amcr_base);
170
+                     &amcr_base);
183
+    if (ret)
171
+    if (ret)
184
+        return ret;
172
+        return ret;
...
...
203
+    }
191
+    }
204
+
192
+
205
+    return ret;
193
+    return ret;
206
+}
194
+}
207
+
195
+
208
+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)
209
+{
197
+{
210
+    /* 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 */
211
+    struct clk *first_child_clk = NULL;
199
+    struct clk *first_child_clk = NULL;
212
+    struct stm32_omm *omm = dev_get_drvdata(dev);
200
+    struct stm32_omm *omm = dev_get_drvdata(dev);
213
+    u8 i;
201
+    u8 i;
214
+    int ret;
202
+    int ret;
215
+
203
+
216
+    for (i = 0; i < omm->nb_child; i++) {
204
+    for (i = 0; i < omm->nb_child; i++) {
217
+        if (enable) {
205
+        if (enable) {
218
+            ret = clk_prepare_enable(omm->child[i].clk);
206
+            ret = clk_prepare_enable(omm->clk_bulk[i + 1].clk);
219
+            if (ret) {
207
+            if (ret) {
220
+                if (first_child_clk)
208
+                if (first_child_clk)
221
+                    clk_disable_unprepare(first_child_clk);
209
+                    clk_disable_unprepare(first_child_clk);
222
+
210
+
223
+                dev_err(dev, "Can not enable clock\n");
211
+                dev_err(dev, "Can not enable clock\n");
224
+                return ret;
212
+                return ret;
225
+            }
213
+            }
226
+        } else {
214
+        } else {
227
+            clk_disable_unprepare(omm->child[i].clk);
215
+            clk_disable_unprepare(omm->clk_bulk[i + 1].clk);
228
+        }
216
+        }
229
+
217
+
230
+        first_child_clk = omm->child[i].clk;
218
+        first_child_clk = omm->clk_bulk[i + 1].clk;
231
+    }
219
+    }
232
+
220
+
233
+    return 0;
221
+    return 0;
234
+}
222
+}
235
+
223
+
236
+static int stm32_omm_configure(struct device *dev)
224
+static int stm32_omm_disable_child(struct device *dev)
237
+{
225
+{
238
+    struct stm32_omm *omm = dev_get_drvdata(dev);
226
+    static const char * const resets_name[] = {"ospi1", "ospi2"};
239
+    struct reset_control *rstc;
227
+    struct stm32_omm *omm = dev_get_drvdata(dev);
240
+    unsigned long clk_rate, clk_rate_max = 0;
228
+    struct reset_control *reset;
241
+    int ret;
229
+    int ret;
242
+    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;
243
+    u32 mux = 0;
259
+    u32 mux = 0;
244
+    u32 cssel_ovr = 0;
260
+    u32 cssel_ovr = 0;
245
+    u32 req2ack = 0;
261
+    u32 req2ack = 0;
246
+
262
+    struct reset_control *rstc;
247
+    omm->clk = devm_clk_get(dev, NULL);
263
+    unsigned long clk_rate;
248
+    if (IS_ERR(omm->clk)) {
264
+    int ret;
249
+        dev_err(dev, "Failed to get OMM clock (%ld)\n",
265
+    u8 i;
250
+            PTR_ERR(omm->clk));
266
+
251
+
267
+    for (i = 0; i < OMM_CLK_NB; i++)
252
+        return PTR_ERR(omm->clk);
268
+        omm->clk_bulk[i].id = clocks_name[i];
253
+    }
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;
254
+
279
+
255
+    ret = pm_runtime_resume_and_get(dev);
280
+    ret = pm_runtime_resume_and_get(dev);
256
+    if (ret < 0)
281
+    if (ret < 0)
257
+        return ret;
282
+        return ret;
258
+
283
+
259
+    /* parse children's clock */
284
+    /* parse children's clock */
260
+    for (i = 0; i < omm->nb_child; i++) {
285
+    for (i = 1; i <= omm->nb_child; i++) {
261
+        clk_rate = clk_get_rate(omm->child[i].clk);
286
+        clk_rate = clk_get_rate(omm->clk_bulk[i].clk);
262
+        if (!clk_rate) {
287
+        if (!clk_rate) {
263
+            dev_err(dev, "Invalid clock rate\n");
288
+            dev_err(dev, "Invalid clock rate\n");
264
+            goto err_clk_disable;
289
+            goto err_clk_disable;
265
+        }
290
+        }
266
+
291
+
267
+        if (clk_rate > clk_rate_max)
292
+        if (clk_rate > clk_rate_max)
268
+            clk_rate_max = clk_rate;
293
+            clk_rate_max = clk_rate;
269
+    }
294
+    }
270
+
295
+
271
+    rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
296
+    rstc = devm_reset_control_get_exclusive(dev, "omm");
272
+    if (IS_ERR(rstc)) {
297
+    if (IS_ERR(rstc))
273
+        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");
274
+        goto err_clk_disable;
275
+    }
276
+
299
+
277
+    reset_control_assert(rstc);
300
+    reset_control_assert(rstc);
278
+    udelay(2);
301
+    udelay(2);
279
+    reset_control_deassert(rstc);
302
+    reset_control_deassert(rstc);
280
+
303
+
...
...
299
+
322
+
300
+            /*
323
+            /*
301
+             * 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
302
+             * always enabled
325
+             * always enabled
303
+             */
326
+             */
304
+            ret = stm32_omm_enable_child_clock(dev, true);
327
+            ret = stm32_omm_toggle_child_clock(dev, true);
305
+            if (ret)
328
+            if (ret)
306
+                goto err_clk_disable;
329
+                goto err_clk_disable;
307
+        }
330
+        }
308
+
331
+
309
+        omm->cr &= ~CR_MUXENMODE_MASK;
332
+        omm->cr &= ~CR_MUXENMODE_MASK;
...
...
327
+    pm_runtime_put_sync_suspend(dev);
350
+    pm_runtime_put_sync_suspend(dev);
328
+
351
+
329
+    return ret;
352
+    return ret;
330
+}
353
+}
331
+
354
+
332
+static int stm32_omm_check_access(struct device *dev, struct device_node *np)
355
+static int stm32_omm_check_access(struct device_node *np)
333
+{
356
+{
334
+    struct stm32_firewall firewall;
357
+    struct stm32_firewall firewall;
335
+    int ret;
358
+    int ret;
336
+
359
+
337
+    ret = stm32_firewall_get_firewall(np, &firewall, 1);
360
+    ret = stm32_firewall_get_firewall(np, &firewall, 1);
338
+    if (ret)
361
+    if (ret)
339
+        return ret;
362
+        return ret;
340
+
363
+
341
+    return stm32_firewall_grant_access(&firewall);
364
+    return stm32_firewall_grant_access(&firewall);
342
+}
365
+}
343
+
366
+
344
+static int stm32_omm_disable_child(struct device *dev)
367
+static int stm32_omm_probe(struct platform_device *pdev)
345
+{
368
+{
346
+    struct stm32_omm *omm = dev_get_drvdata(dev);
369
+    struct device *dev = &pdev->dev;
347
+    struct reset_control *reset;
370
+    u8 child_access_granted = 0;
371
+    struct stm32_omm *omm;
348
+    int ret;
372
+    int ret;
349
+    u8 i;
350
+
351
+    for (i = 0; i < omm->nb_child; i++) {
352
+        ret = clk_prepare_enable(omm->child[i].clk);
353
+        if (ret) {
354
+            dev_err(dev, "Can not enable clock\n");
355
+            return ret;
356
+        }
357
+
358
+        reset = of_reset_control_get_exclusive(omm->child[i].node, 0);
359
+        if (IS_ERR(reset)) {
360
+            dev_err(dev, "Can't get child reset\n");
361
+            return PTR_ERR(reset);
362
+        };
363
+
364
+        /* reset OSPI to ensure CR_EN bit is set to 0 */
365
+        reset_control_assert(reset);
366
+        udelay(2);
367
+        reset_control_deassert(reset);
368
+
369
+        reset_control_put(reset);
370
+        clk_disable_unprepare(omm->child[i].clk);
371
+    }
372
+
373
+    return 0;
374
+}
375
+
376
+static int stm32_omm_probe(struct platform_device *pdev)
377
+{
378
+    struct platform_device *vdev;
379
+    struct device *dev = &pdev->dev;
380
+    struct stm32_omm *omm;
381
+    struct clk *clk;
382
+    int ret;
383
+    u8 child_access_granted = 0;
384
+    u8 i, j;
385
+    bool child_access[OMM_CHILD_NB];
386
+
373
+
387
+    omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
374
+    omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
388
+    if (!omm)
375
+    if (!omm)
389
+        return -ENOMEM;
376
+        return -ENOMEM;
390
+
377
+
...
...
398
+
385
+
399
+    /* check child's access */
386
+    /* check child's access */
400
+    for_each_child_of_node_scoped(dev->of_node, child) {
387
+    for_each_child_of_node_scoped(dev->of_node, child) {
401
+        if (omm->nb_child >= OMM_CHILD_NB) {
388
+        if (omm->nb_child >= OMM_CHILD_NB) {
402
+            dev_err(dev, "Bad DT, found too much children\n");
389
+            dev_err(dev, "Bad DT, found too much children\n");
403
+            ret = -E2BIG;
390
+            return -E2BIG;
404
+            goto err_clk_release;
391
+        }
405
+        }
392
+
406
+
393
+        if (!of_device_is_compatible(child, "st,stm32mp25-omi"))
407
+        if (!of_device_is_compatible(child, "st,stm32mp25-ospi")) {
394
+            return -EINVAL;
408
+            ret = -EINVAL;
395
+
409
+            goto err_clk_release;
396
+        ret = stm32_omm_check_access(child);
410
+        }
411
+
412
+        ret = stm32_omm_check_access(dev, child);
413
+        if (ret < 0 && ret != -EACCES)
397
+        if (ret < 0 && ret != -EACCES)
414
+            goto err_clk_release;
398
+            return ret;
415
+
399
+
416
+        child_access[omm->nb_child] = false;
400
+        if (!ret)
417
+        if (!ret) {
418
+            child_access_granted++;
401
+            child_access_granted++;
419
+            child_access[omm->nb_child] = true;
402
+
420
+        }
421
+
422
+        omm->child[omm->nb_child].node = child;
423
+
424
+        clk = of_clk_get(child, 0);
425
+        if (IS_ERR(clk)) {
426
+            dev_err(dev, "Can't get child clock\n");
427
+            ret = PTR_ERR(clk);
428
+            goto err_clk_release;
429
+        };
430
+
431
+        omm->child[omm->nb_child].clk = clk;
432
+        omm->nb_child++;
403
+        omm->nb_child++;
433
+    }
404
+    }
434
+
405
+
435
+    if (omm->nb_child != OMM_CHILD_NB) {
406
+    if (omm->nb_child != OMM_CHILD_NB)
436
+        ret = -EINVAL;
407
+        return -EINVAL;
437
+        goto err_clk_release;
438
+    }
439
+
408
+
440
+    platform_set_drvdata(pdev, omm);
409
+    platform_set_drvdata(pdev, omm);
441
+
410
+
442
+    pm_runtime_enable(dev);
411
+    pm_runtime_enable(dev);
443
+
412
+
444
+    /* check if OMM's resource access is granted */
413
+    /* check if OMM's resource access is granted */
445
+    ret = stm32_omm_check_access(dev, dev->of_node);
414
+    ret = stm32_omm_check_access(dev->of_node);
446
+    if (ret < 0 && ret != -EACCES)
415
+    if (ret < 0 && ret != -EACCES)
447
+        goto err_clk_release;
416
+        goto error;
448
+
417
+
449
+    if (!ret && child_access_granted == OMM_CHILD_NB) {
418
+    if (!ret && child_access_granted == OMM_CHILD_NB) {
450
+        /* Ensure both OSPI instance are disabled before configuring OMM */
451
+        ret = stm32_omm_disable_child(dev);
452
+        if (ret)
453
+            goto err_clk_release;
454
+
455
+        ret = stm32_omm_configure(dev);
419
+        ret = stm32_omm_configure(dev);
456
+        if (ret)
420
+        if (ret)
457
+            goto err_clk_release;
421
+            goto error;
458
+    } else {
422
+    } else {
459
+        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");
460
+        /*
424
+        /*
461
+         * 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
462
+         * with memory-map areas defined in DT
426
+         * with memory-map areas defined in DT
463
+         */
427
+         */
464
+        ret = stm32_omm_set_amcr(dev, false);
428
+        ret = stm32_omm_set_amcr(dev, false);
465
+        if (ret)
429
+        if (ret)
466
+            goto err_clk_release;
430
+            goto error;
467
+    }
431
+    }
468
+
432
+
469
+    /* for each child, if resource access is granted and status "okay", probe it */
433
+    ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
470
+    for (i = 0; i < omm->nb_child; i++) {
434
+    if (ret) {
471
+        if (!child_access[i] || !of_device_is_available(omm->child[i].node))
435
+        dev_err(dev, "Failed to create Octo Memory Manager child\n");
472
+            continue;
436
+        of_platform_depopulate(dev);
473
+
437
+        ret = -EINVAL;
474
+        vdev = of_platform_device_create(omm->child[i].node, NULL, NULL);
438
+        goto error;
475
+        if (!vdev) {
439
+    }
476
+            dev_err(dev, "Failed to create Octo Memory Manager child\n");
477
+            for (j = i; j > 0; --j) {
478
+                if (omm->child[j].dev)
479
+                    of_platform_device_destroy(omm->child[j].dev, NULL);
480
+            }
481
+
482
+            ret = -EINVAL;
483
+            goto err_clk_release;
484
+        }
485
+        omm->child[i].dev = &vdev->dev;
486
+    }
487
+
488
+err_clk_release:
489
+    for (i = 0; i < omm->nb_child; i++)
490
+        clk_put(omm->child[i].clk);
491
+
440
+
492
+    return ret;
441
+    return ret;
442
+
443
+error:
444
+    pm_runtime_disable(dev);
445
+
446
+    return ret;
447
+
493
+}
448
+}
494
+
449
+
495
+static void stm32_omm_remove(struct platform_device *pdev)
450
+static void stm32_omm_remove(struct platform_device *pdev)
496
+{
451
+{
497
+    struct stm32_omm *omm = platform_get_drvdata(pdev);
452
+    struct stm32_omm *omm = platform_get_drvdata(pdev);
498
+    int i;
453
+
499
+
454
+    of_platform_depopulate(&pdev->dev);
500
+    for (i = 0; i < omm->nb_child; i++)
501
+        if (omm->child[i].dev)
502
+            of_platform_device_destroy(omm->child[i].dev, NULL);
503
+
504
+    if (omm->cr & CR_MUXEN)
455
+    if (omm->cr & CR_MUXEN)
505
+        stm32_omm_enable_child_clock(&pdev->dev, false);
456
+        stm32_omm_toggle_child_clock(&pdev->dev, false);
506
+
457
+
507
+    pm_runtime_disable(&pdev->dev);
458
+    pm_runtime_disable(&pdev->dev);
508
+}
459
+}
509
+
460
+
510
+static const struct of_device_id stm32_omm_of_match[] = {
461
+static const struct of_device_id stm32_omm_of_match[] = {
511
+    { .compatible = "st,stm32mp25-omm", },
462
+    { .compatible = "st,stm32mp25-omm", },
512
+    {},
463
+    {}
513
+};
464
+};
514
+MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
465
+MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
515
+
466
+
516
+static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
467
+static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
517
+{
468
+{
518
+    struct stm32_omm *omm = dev_get_drvdata(dev);
469
+    struct stm32_omm *omm = dev_get_drvdata(dev);
519
+
470
+
520
+    clk_disable_unprepare(omm->clk);
471
+    clk_disable_unprepare(omm->clk_bulk[0].clk);
521
+
472
+
522
+    return 0;
473
+    return 0;
523
+}
474
+}
524
+
475
+
525
+static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
476
+static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
526
+{
477
+{
527
+    struct stm32_omm *omm = dev_get_drvdata(dev);
478
+    struct stm32_omm *omm = dev_get_drvdata(dev);
528
+
479
+
529
+    return clk_prepare_enable(omm->clk);
480
+    return clk_prepare_enable(omm->clk_bulk[0].clk);
530
+}
481
+}
531
+
482
+
532
+static int __maybe_unused stm32_omm_suspend(struct device *dev)
483
+static int __maybe_unused stm32_omm_suspend(struct device *dev)
533
+{
484
+{
534
+    struct stm32_omm *omm = dev_get_drvdata(dev);
485
+    struct stm32_omm *omm = dev_get_drvdata(dev);
535
+
486
+
536
+    if (omm->restore_omm && omm->cr & CR_MUXEN)
487
+    if (omm->restore_omm && omm->cr & CR_MUXEN)
537
+        stm32_omm_enable_child_clock(dev, false);
488
+        stm32_omm_toggle_child_clock(dev, false);
538
+
489
+
539
+    return pinctrl_pm_select_sleep_state(dev);
490
+    return pinctrl_pm_select_sleep_state(dev);
540
+}
491
+}
541
+
492
+
542
+static int __maybe_unused stm32_omm_resume(struct device *dev)
493
+static int __maybe_unused stm32_omm_resume(struct device *dev)
...
...
563
+    pm_runtime_put_sync_suspend(dev);
514
+    pm_runtime_put_sync_suspend(dev);
564
+    if (ret)
515
+    if (ret)
565
+        return ret;
516
+        return ret;
566
+
517
+
567
+    if (omm->cr & CR_MUXEN)
518
+    if (omm->cr & CR_MUXEN)
568
+        ret = stm32_omm_enable_child_clock(dev, true);
519
+        ret = stm32_omm_toggle_child_clock(dev, true);
569
+
520
+
570
+    return ret;
521
+    return ret;
571
+}
522
+}
572
+
523
+
573
+static const struct dev_pm_ops stm32_omm_pm_ops = {
524
+static const struct dev_pm_ops stm32_omm_pm_ops = {
...
...
587
+};
538
+};
588
+module_platform_driver(stm32_omm_driver);
539
+module_platform_driver(stm32_omm_driver);
589
+
540
+
590
+MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
541
+MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
591
+MODULE_LICENSE("GPL");
542
+MODULE_LICENSE("GPL");
543
592
--
544
--
593
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
...
...
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 = "regs", "memory_map";
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";
27
+                access-controllers = <&rifsc 111>;
31
+                access-controllers = <&rifsc 111>;
28
+                power-domains = <&CLUSTER_PD>;
32
+                power-domains = <&CLUSTER_PD>;
29
+                #address-cells = <2>;
33
+                #address-cells = <2>;
30
+                #size-cells = <1>;
34
+                #size-cells = <1>;
31
+                st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
35
+                st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
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>;
...
...
45
+                    power-domains = <&CLUSTER_PD>;
49
+                    power-domains = <&CLUSTER_PD>;
46
+                    st,syscfg-dlyb = <&syscfg 0x1000>;
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>;
...
...
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 | 32 ++++++++++++++++++++++
5
arch/arm64/boot/dts/st/stm32mp257f-ev1.dts | 32 ++++++++++++++++++++++++++++++
8
1 file changed, 32 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
...
...
36
+         &ospi_port1_io03_sleep_pins_a
34
+         &ospi_port1_io03_sleep_pins_a
37
+         &ospi_port1_cs0_sleep_pins_a>;
35
+         &ospi_port1_cs0_sleep_pins_a>;
38
+    pinctrl-names = "default", "sleep";
36
+    pinctrl-names = "default", "sleep";
39
+    status = "okay";
37
+    status = "okay";
40
+
38
+
41
+    spi@40430000 {
39
+    spi@0 {
42
+        #address-cells = <1>;
40
+        #address-cells = <1>;
43
+        #size-cells = <0>;
41
+        #size-cells = <0>;
44
+        memory-region = <&mm_ospi1>;
42
+        memory-region = <&mm_ospi1>;
45
+        status = "okay";
43
+        status = "okay";
46
+
44
+
...
...
55
+};
53
+};
56
+
54
+
57
&rtc {
55
&rtc {
58
    status = "okay";
56
    status = "okay";
59
};
57
};
58
60
--
59
--
61
2.25.1
60
2.25.1
diff view generated by jsdifflib
1
From: Patrice Chotard <patrice.chotard@foss.st.com>
2
3
Enable STM32 OctoSPI driver.
1
Enable STM32 OctoSPI driver.
4
Enable STM32 Octo Memory Manager (OMM) driver which is needed
2
Enable STM32 Octo Memory Manager (OMM) driver which is needed
5
for OSPI usage on STM32MP257F-EV1 board.
3
for OSPI usage on STM32MP257F-EV1 board.
6
4
7
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
5
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
...
...
27
CONFIG_RENESAS_RPCIF=m
25
CONFIG_RENESAS_RPCIF=m
28
+CONFIG_STM32_OMM=m
26
+CONFIG_STM32_OMM=m
29
CONFIG_IIO=y
27
CONFIG_IIO=y
30
CONFIG_EXYNOS_ADC=y
28
CONFIG_EXYNOS_ADC=y
31
CONFIG_IMX8QXP_ADC=m
29
CONFIG_IMX8QXP_ADC=m
30
32
--
31
--
33
2.25.1
32
2.25.1
diff view generated by jsdifflib