...
...
12
The device tree files adds Octo Memory Manager and its 2 associated Octo
12
The device tree files adds Octo Memory Manager and its 2 associated Octo
13
SPI chidren in stm32mp251.dtsi and adds SPI NOR support in stm32mp257f-ev1
13
SPI chidren in stm32mp251.dtsi and adds SPI NOR support in stm32mp257f-ev1
14
board.
14
board.
15
15
16
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
16
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
17
18
Changes in v7:
19
- update OMM's dt-bindings by updating :
20
- clock-names and reset-names properties.
21
- spi unit-address node.
22
- example.
23
- update stm32mp251.dtsi to match with OMM's bindings update.
24
- update stm32mp257f-ev1.dts to match with OMM's bindings update.
25
- Link to v6: https://lore.kernel.org/r/20250321-upstream_ospi_v6-v6-0-37bbcab43439@foss.st.com
17
26
18
Changes in v6:
27
Changes in v6:
19
- Update MAINTAINERS file.
28
- Update MAINTAINERS file.
20
- Remove previous patch 1/8 and 2/8, merged by Mark Brown in spi git tree.
29
- Remove previous patch 1/8 and 2/8, merged by Mark Brown in spi git tree.
21
- Fix Signed-off-by order for patch 3.
30
- Fix Signed-off-by order for patch 3.
...
...
diff view generated by jsdifflib
1
Add myself as STM32 OCTO MEMORY MANAGER maintainer.
1
Add myself as STM32 OCTO MEMORY MANAGER maintainer.
2
2
3
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
3
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
4
---
4
---
5
MAINTAINERS | 6 ++++++
5
MAINTAINERS | 6 ++++++
6
1 file changed, 6 insertions(+)
6
1 file changed, 6 insertions(+)
7
7
8
diff --git a/MAINTAINERS b/MAINTAINERS
8
diff --git a/MAINTAINERS b/MAINTAINERS
9
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
10
--- a/MAINTAINERS
10
--- a/MAINTAINERS
11
+++ b/MAINTAINERS
11
+++ b/MAINTAINERS
12
@@ -XXX,XX +XXX,XX @@ L:    linux-i2c@vger.kernel.org
12
@@ -XXX,XX +XXX,XX @@ L:    linux-i2c@vger.kernel.org
13
S:    Maintained
13
S:    Maintained
14
F:    drivers/i2c/busses/i2c-stm32*
14
F:    drivers/i2c/busses/i2c-stm32*
15
15
16
+ST STM32 OCTO MEMORY MANAGER
16
+ST STM32 OCTO MEMORY MANAGER
17
+M:    Patrice Chotard <patrice.chotard@foss.st.com>
17
+M:    Patrice Chotard <patrice.chotard@foss.st.com>
18
+S:    Maintained
18
+S:    Maintained
19
+F:    Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
19
+F:    Documentation/devicetree/bindings/memory-controllers/st,stm32mp25-omm.yaml
20
+F:    drivers/memory/stm32_omm.c
20
+F:    drivers/memory/stm32_omm.c
21
+
21
+
22
ST STM32 SPI DRIVER
22
ST STM32 SPI DRIVER
23
M:    Alain Volmat <alain.volmat@foss.st.com>
23
M:    Alain Volmat <alain.volmat@foss.st.com>
24
L:    linux-spi@vger.kernel.org
24
L:    linux-spi@vger.kernel.org
25
25
26
--
26
--
27
2.25.1
27
2.25.1
diff view generated by jsdifflib
...
...
53
+ "#size-cells":
53
+ "#size-cells":
54
+ const: 1
54
+ const: 1
55
+
55
+
56
+ ranges:
56
+ ranges:
57
+ description: |
57
+ description: |
58
+ Reflects the memory layout with four integer values per OSPI instance.
58
+ Reflects the memory layout per OSPI instance.
59
+ Format:
59
+ Format:
60
+ <chip-select> 0 <registers base address> <size>
60
+ <chip-select> 0 <registers base address> <size>
61
+ minItems: 2
61
+ minItems: 2
62
+ maxItems: 2
62
+ maxItems: 2
63
+
63
+
...
...
70
+ items:
70
+ items:
71
+ - const: regs
71
+ - const: regs
72
+ - const: memory_map
72
+ - const: memory_map
73
+
73
+
74
+ memory-region:
74
+ memory-region:
75
+ description: |
75
+ description:
76
+ Memory region shared between the 2 OCTOSPI instance.
76
+ Memory region shared between the 2 OCTOSPI instance.
77
+ 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
78
+ depending of child number.
78
+ depending of child number.
79
+ minItems: 1
79
+ minItems: 1
80
+ maxItems: 2
80
+ maxItems: 2
81
+
81
+
82
+ memory-region-names:
82
+ memory-region-names:
83
+ description: |
83
+ description:
84
+ OCTOSPI instance's name to which memory region is associated
84
+ Identify to which OSPI instance the memory region belongs to.
85
+ items:
85
+ items:
86
+ enum: [ospi1, ospi2]
86
+ enum: [ospi1, ospi2]
87
+ minItems: 1
87
+ minItems: 1
88
+ maxItems: 2
88
+ maxItems: 2
89
+
89
+
90
+ clocks:
90
+ clocks:
91
+ minItems: 3
91
+ minItems: 3
92
+ maxItems: 3
92
+ maxItems: 3
93
+
93
+
94
+ clock-names:
94
+ clock-names:
95
+ items:
95
+ items:
96
+ enum: [omm, ospi1, ospi2]
96
+ - const: omm
97
+ minItems: 3
97
+ - const: ospi1
98
+ maxItems: 3
98
+ - const: ospi2
99
+
99
+
100
+ resets:
100
+ resets:
101
+ minItems: 3
101
+ minItems: 3
102
+ maxItems: 3
102
+ maxItems: 3
103
+
103
+
104
+ reset-names:
104
+ reset-names:
105
+ items:
105
+ items:
106
+ enum: [omm, ospi1, ospi2]
106
+ - const: omm
107
+ minItems: 3
107
+ - const: ospi1
108
+ maxItems: 3
108
+ - const: ospi2
109
+
109
+
110
+ access-controllers:
110
+ access-controllers:
111
+ maxItems: 1
111
+ maxItems: 1
112
+
112
+
113
+ st,syscfg-amcr:
113
+ st,syscfg-amcr:
...
...
126
+ - description: phandle to syscfg
126
+ - description: phandle to syscfg
127
+ - description: register offset within syscfg
127
+ - description: register offset within syscfg
128
+ - description: register bitmask for memory split
128
+ - description: register bitmask for memory split
129
+
129
+
130
+ st,omm-req2ack-ns:
130
+ st,omm-req2ack-ns:
131
+ description: |
131
+ description:
132
+ In multiplexed mode (MUXEN = 1), this field defines the time in
132
+ In multiplexed mode (MUXEN = 1), this field defines the time in
133
+ nanoseconds between two transactions.
133
+ nanoseconds between two transactions.
134
+ default: 0
134
+ default: 0
135
+
135
+
136
+ st,omm-cssel-ovr:
136
+ st,omm-cssel-ovr:
...
...
159
+
159
+
160
+ power-domains:
160
+ power-domains:
161
+ maxItems: 1
161
+ maxItems: 1
162
+
162
+
163
+patternProperties:
163
+patternProperties:
164
+ ^spi@[a-f0-9]+$:
164
+ ^spi@[0-9]:
165
+ type: object
165
+ type: object
166
+ $ref: /schemas/spi/st,stm32mp25-ospi.yaml#
166
+ $ref: /schemas/spi/st,stm32mp25-ospi.yaml#
167
+ description: Required spi child node
167
+ description: Required spi child node
168
+
168
+
169
+required:
169
+required:
...
...
215
+ st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
215
+ st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
216
+ st,omm-req2ack-ns = <0>;
216
+ st,omm-req2ack-ns = <0>;
217
+ st,omm-mux = <0>;
217
+ st,omm-mux = <0>;
218
+ st,omm-cssel-ovr = <0>;
218
+ st,omm-cssel-ovr = <0>;
219
+
219
+
220
+ spi@40430000 {
220
+ spi@0 {
221
+ compatible = "st,stm32mp25-ospi";
221
+ compatible = "st,stm32mp25-ospi";
222
+ reg = <0 0 0x400>;
222
+ reg = <0 0 0x400>;
223
+ memory-region = <&mm_ospi1>;
223
+ memory-region = <&mm_ospi1>;
224
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
224
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
225
+ dmas = <&hpdma 2 0x62 0x00003121 0x0>,
225
+ dmas = <&hpdma 2 0x62 0x00003121 0x0>,
...
...
232
+ #address-cells = <1>;
232
+ #address-cells = <1>;
233
+ #size-cells = <0>;
233
+ #size-cells = <0>;
234
+ st,syscfg-dlyb = <&syscfg 0x1000>;
234
+ st,syscfg-dlyb = <&syscfg 0x1000>;
235
+ };
235
+ };
236
+
236
+
237
+ spi@40440000 {
237
+ spi@1 {
238
+ compatible = "st,stm32mp25-ospi";
238
+ compatible = "st,stm32mp25-ospi";
239
+ reg = <1 0 0x400>;
239
+ reg = <1 0 0x400>;
240
+ memory-region = <&mm_ospi1>;
240
+ memory-region = <&mm_ospi1>;
241
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
241
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
242
+ dmas = <&hpdma 3 0x62 0x00003121 0x0>,
242
+ dmas = <&hpdma 3 0x62 0x00003121 0x0>,
...
...
diff view generated by jsdifflib
1
Octo Memory Manager driver (OMM) manages:
1
Octo Memory Manager driver (OMM) manages:
2
- the muxing between 2 OSPI busses and 2 output ports.
2
- the muxing between 2 OSPI busses and 2 output ports.
3
There are 4 possible muxing configurations:
3
There are 4 possible muxing configurations:
4
- 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
5
output is on port 2
5
output is on port 2
6
- OSPI1 and OSPI2 are multiplexed over the same output port 1
6
- OSPI1 and OSPI2 are multiplexed over the same output port 1
7
- swapped mode (no multiplexing), OSPI1 output is on port 2,
7
- swapped mode (no multiplexing), OSPI1 output is on port 2,
8
OSPI2 output is on port 1
8
OSPI2 output is on port 1
9
- OSPI1 and OSPI2 are multiplexed over the same output port 2
9
- OSPI1 and OSPI2 are multiplexed over the same output port 2
10
- 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.
11
- chip select selection override.
11
- chip select selection override.
12
- the time between 2 transactions in multiplexed mode.
12
- the time between 2 transactions in multiplexed mode.
13
- check firewall access.
13
- check firewall access.
14
14
15
Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com>
15
Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com>
16
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
16
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
17
---
17
---
18
drivers/memory/Kconfig | 17 ++
18
drivers/memory/Kconfig | 17 ++
19
drivers/memory/Makefile | 1 +
19
drivers/memory/Makefile | 1 +
20
drivers/memory/stm32_omm.c | 474 +++++++++++++++++++++++++++++++++++++++++++++
20
drivers/memory/stm32_omm.c | 474 +++++++++++++++++++++++++++++++++++++++++++++
21
3 files changed, 492 insertions(+)
21
3 files changed, 492 insertions(+)
22
22
23
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
23
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
24
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
25
--- a/drivers/memory/Kconfig
25
--- a/drivers/memory/Kconfig
26
+++ b/drivers/memory/Kconfig
26
+++ b/drivers/memory/Kconfig
27
@@ -XXX,XX +XXX,XX @@ config STM32_FMC2_EBI
27
@@ -XXX,XX +XXX,XX @@ config STM32_FMC2_EBI
28
     devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
28
     devices (like SRAM, ethernet adapters, FPGAs, LCD displays, ...) on
29
     SOCs containing the FMC2 External Bus Interface.
29
     SOCs containing the FMC2 External Bus Interface.
30
30
31
+config STM32_OMM
31
+config STM32_OMM
32
+    tristate "STM32 Octo Memory Manager"
32
+    tristate "STM32 Octo Memory Manager"
33
+    depends on SPI_STM32_OSPI || COMPILE_TEST
33
+    depends on SPI_STM32_OSPI || COMPILE_TEST
34
+    help
34
+    help
35
+     This driver manages the muxing between the 2 OSPI busses and
35
+     This driver manages the muxing between the 2 OSPI busses and
36
+     the 2 output ports. There are 4 possible muxing configurations:
36
+     the 2 output ports. There are 4 possible muxing configurations:
37
+     - 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
38
+     output is on port 2
38
+     output is on port 2
39
+     - OSPI1 and OSPI2 are multiplexed over the same output port 1
39
+     - OSPI1 and OSPI2 are multiplexed over the same output port 1
40
+     - swapped mode (no multiplexing), OSPI1 output is on port 2,
40
+     - swapped mode (no multiplexing), OSPI1 output is on port 2,
41
+     OSPI2 output is on port 1
41
+     OSPI2 output is on port 1
42
+     - OSPI1 and OSPI2 are multiplexed over the same output port 2
42
+     - OSPI1 and OSPI2 are multiplexed over the same output port 2
43
+     It also manages :
43
+     It also manages :
44
+     - the split of the memory area shared between the 2 OSPI instances.
44
+     - the split of the memory area shared between the 2 OSPI instances.
45
+     - chip select selection override.
45
+     - chip select selection override.
46
+     - the time between 2 transactions in multiplexed mode.
46
+     - the time between 2 transactions in multiplexed mode.
47
+
47
+
48
source "drivers/memory/samsung/Kconfig"
48
source "drivers/memory/samsung/Kconfig"
49
source "drivers/memory/tegra/Kconfig"
49
source "drivers/memory/tegra/Kconfig"
50
50
51
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
51
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
52
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
53
--- a/drivers/memory/Makefile
53
--- a/drivers/memory/Makefile
54
+++ b/drivers/memory/Makefile
54
+++ b/drivers/memory/Makefile
55
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DA8XX_DDRCTL)    += da8xx-ddrctl.o
55
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_DA8XX_DDRCTL)    += da8xx-ddrctl.o
56
obj-$(CONFIG_PL353_SMC)        += pl353-smc.o
56
obj-$(CONFIG_PL353_SMC)        += pl353-smc.o
57
obj-$(CONFIG_RENESAS_RPCIF)    += renesas-rpc-if.o
57
obj-$(CONFIG_RENESAS_RPCIF)    += renesas-rpc-if.o
58
obj-$(CONFIG_STM32_FMC2_EBI)    += stm32-fmc2-ebi.o
58
obj-$(CONFIG_STM32_FMC2_EBI)    += stm32-fmc2-ebi.o
59
+obj-$(CONFIG_STM32_OMM)        += stm32_omm.o
59
+obj-$(CONFIG_STM32_OMM)        += stm32_omm.o
60
60
61
obj-$(CONFIG_SAMSUNG_MC)    += samsung/
61
obj-$(CONFIG_SAMSUNG_MC)    += samsung/
62
obj-$(CONFIG_TEGRA_MC)        += tegra/
62
obj-$(CONFIG_TEGRA_MC)        += tegra/
63
diff --git a/drivers/memory/stm32_omm.c b/drivers/memory/stm32_omm.c
63
diff --git a/drivers/memory/stm32_omm.c b/drivers/memory/stm32_omm.c
64
new file mode 100644
64
new file mode 100644
65
index XXXXXXX..XXXXXXX
65
index XXXXXXX..XXXXXXX
66
--- /dev/null
66
--- /dev/null
67
+++ b/drivers/memory/stm32_omm.c
67
+++ b/drivers/memory/stm32_omm.c
68
@@ -XXX,XX +XXX,XX @@
68
@@ -XXX,XX +XXX,XX @@
69
+// SPDX-License-Identifier: GPL-2.0
69
+// SPDX-License-Identifier: GPL-2.0
70
+/*
70
+/*
71
+ * Copyright (C) STMicroelectronics 2025 - All Rights Reserved
71
+ * Copyright (C) STMicroelectronics 2025 - All Rights Reserved
72
+ * Author(s): Patrice Chotard <patrice.chotard@foss.st.com> for STMicroelectronics.
72
+ * Author(s): Patrice Chotard <patrice.chotard@foss.st.com> for STMicroelectronics.
73
+ */
73
+ */
74
+
74
+
75
+#include <linux/bitfield.h>
75
+#include <linux/bitfield.h>
76
+#include <linux/bus/stm32_firewall_device.h>
76
+#include <linux/bus/stm32_firewall_device.h>
77
+#include <linux/clk.h>
77
+#include <linux/clk.h>
78
+#include <linux/err.h>
78
+#include <linux/err.h>
79
+#include <linux/mfd/syscon.h>
79
+#include <linux/mfd/syscon.h>
80
+#include <linux/mod_devicetable.h>
80
+#include <linux/mod_devicetable.h>
81
+#include <linux/module.h>
81
+#include <linux/module.h>
82
+#include <linux/of_address.h>
82
+#include <linux/of_address.h>
83
+#include <linux/of_platform.h>
83
+#include <linux/of_platform.h>
84
+#include <linux/pinctrl/consumer.h>
84
+#include <linux/pinctrl/consumer.h>
85
+#include <linux/pm_runtime.h>
85
+#include <linux/pm_runtime.h>
86
+#include <linux/regmap.h>
86
+#include <linux/regmap.h>
87
+#include <linux/reset.h>
87
+#include <linux/reset.h>
88
+
88
+
89
+#define OMM_CR            0
89
+#define OMM_CR            0
90
+#define CR_MUXEN        BIT(0)
90
+#define CR_MUXEN        BIT(0)
91
+#define CR_MUXENMODE_MASK    GENMASK(1, 0)
91
+#define CR_MUXENMODE_MASK    GENMASK(1, 0)
92
+#define CR_CSSEL_OVR_EN        BIT(4)
92
+#define CR_CSSEL_OVR_EN        BIT(4)
93
+#define CR_CSSEL_OVR_MASK    GENMASK(6, 5)
93
+#define CR_CSSEL_OVR_MASK    GENMASK(6, 5)
94
+#define CR_REQ2ACK_MASK        GENMASK(23, 16)
94
+#define CR_REQ2ACK_MASK        GENMASK(23, 16)
95
+
95
+
96
+#define OMM_CHILD_NB        2
96
+#define OMM_CHILD_NB        2
97
+#define OMM_CLK_NB        3
97
+#define OMM_CLK_NB        3
98
+
98
+
99
+struct stm32_omm {
99
+struct stm32_omm {
100
+    struct resource *mm_res;
100
+    struct resource *mm_res;
101
+    struct clk_bulk_data clk_bulk[OMM_CLK_NB];
101
+    struct clk_bulk_data clk_bulk[OMM_CLK_NB];
102
+    void __iomem *io_base;
102
+    void __iomem *io_base;
103
+    u32 cr;
103
+    u32 cr;
104
+    u8 nb_child;
104
+    u8 nb_child;
105
+    bool restore_omm;
105
+    bool restore_omm;
106
+};
106
+};
107
+
107
+
108
+static int stm32_omm_set_amcr(struct device *dev, bool set)
108
+static int stm32_omm_set_amcr(struct device *dev, bool set)
109
+{
109
+{
110
+    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;
111
+    resource_size_t mm_ospi2_size = 0;
112
+    static const char * const mm_name[] = { "ospi1", "ospi2" };
112
+    static const char * const mm_name[] = { "ospi1", "ospi2" };
113
+    struct regmap *syscfg_regmap;
113
+    struct regmap *syscfg_regmap;
114
+    struct device_node *node;
114
+    struct device_node *node;
115
+    struct resource res, res1;
115
+    struct resource res, res1;
116
+    u32 amcr_base, amcr_mask;
116
+    u32 amcr_base, amcr_mask;
117
+    int ret, idx;
117
+    int ret, idx;
118
+    unsigned int i, amcr, read_amcr;
118
+    unsigned int i, amcr, read_amcr;
119
+
119
+
120
+    for (i = 0; i < omm->nb_child; i++) {
120
+    for (i = 0; i < omm->nb_child; i++) {
121
+        idx = of_property_match_string(dev->of_node,
121
+        idx = of_property_match_string(dev->of_node,
122
+                     "memory-region-names",
122
+                     "memory-region-names",
123
+                     mm_name[i]);
123
+                     mm_name[i]);
124
+        if (idx < 0)
124
+        if (idx < 0)
125
+            continue;
125
+            continue;
126
+
126
+
127
+        /* res1 only used on second loop iteration */
127
+        /* res1 only used on second loop iteration */
128
+        res1.start = res.start;
128
+        res1.start = res.start;
129
+        res1.end = res.end;
129
+        res1.end = res.end;
130
+
130
+
131
+        node = of_parse_phandle(dev->of_node, "memory-region", idx);
131
+        node = of_parse_phandle(dev->of_node, "memory-region", idx);
132
+        if (!node)
132
+        if (!node)
133
+            continue;
133
+            continue;
134
+
134
+
135
+        ret = of_address_to_resource(node, 0, &res);
135
+        ret = of_address_to_resource(node, 0, &res);
136
+        if (ret) {
136
+        if (ret) {
137
+            dev_err(dev, "unable to resolve memory region\n");
137
+            dev_err(dev, "unable to resolve memory region\n");
138
+            return ret;
138
+            return ret;
139
+        }
139
+        }
140
+
140
+
141
+        /* check that memory region fits inside OMM memory map area */
141
+        /* check that memory region fits inside OMM memory map area */
142
+        if (!resource_contains(omm->mm_res, &res)) {
142
+        if (!resource_contains(omm->mm_res, &res)) {
143
+            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",
144
+                mm_name[i]);
144
+                mm_name[i]);
145
+            dev_err(dev, "%pR doesn't fit inside %pR\n", &res, omm->mm_res);
145
+            dev_err(dev, "%pR doesn't fit inside %pR\n", &res, omm->mm_res);
146
+
146
+
147
+            return -EFAULT;
147
+            return -EFAULT;
148
+        }
148
+        }
149
+
149
+
150
+        if (i == 1) {
150
+        if (i == 1) {
151
+            mm_ospi2_size = resource_size(&res);
151
+            mm_ospi2_size = resource_size(&res);
152
+
152
+
153
+            /* 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 */
154
+            if (resource_overlaps(&res, &res1)) {
154
+            if (resource_overlaps(&res, &res1)) {
155
+                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",
156
+                    mm_name[0], mm_name[1]);
156
+                    mm_name[0], mm_name[1]);
157
+                dev_err(dev, "%pR overlaps %pR\n", &res1, &res);
157
+                dev_err(dev, "%pR overlaps %pR\n", &res1, &res);
158
+
158
+
159
+                return -EFAULT;
159
+                return -EFAULT;
160
+            }
160
+            }
161
+        }
161
+        }
162
+    }
162
+    }
163
+
163
+
164
+    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");
165
+    if (IS_ERR(syscfg_regmap))
165
+    if (IS_ERR(syscfg_regmap))
166
+        return dev_err_probe(dev, PTR_ERR(syscfg_regmap),
166
+        return dev_err_probe(dev, PTR_ERR(syscfg_regmap),
167
+                 "Failed to get st,syscfg-amcr property\n");
167
+                 "Failed to get st,syscfg-amcr property\n");
168
+
168
+
169
+    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,
170
+                     &amcr_base);
170
+                     &amcr_base);
171
+    if (ret)
171
+    if (ret)
172
+        return ret;
172
+        return ret;
173
+
173
+
174
+    ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 2,
174
+    ret = of_property_read_u32_index(dev->of_node, "st,syscfg-amcr", 2,
175
+                     &amcr_mask);
175
+                     &amcr_mask);
176
+    if (ret)
176
+    if (ret)
177
+        return ret;
177
+        return ret;
178
+
178
+
179
+    amcr = mm_ospi2_size / SZ_64M;
179
+    amcr = mm_ospi2_size / SZ_64M;
180
+
180
+
181
+    if (set)
181
+    if (set)
182
+        regmap_update_bits(syscfg_regmap, amcr_base, amcr_mask, amcr);
182
+        regmap_update_bits(syscfg_regmap, amcr_base, amcr_mask, amcr);
183
+
183
+
184
+    /* read AMCR and check coherency with memory-map areas defined in DT */
184
+    /* read AMCR and check coherency with memory-map areas defined in DT */
185
+    regmap_read(syscfg_regmap, amcr_base, &read_amcr);
185
+    regmap_read(syscfg_regmap, amcr_base, &read_amcr);
186
+    read_amcr = read_amcr >> (ffs(amcr_mask) - 1);
186
+    read_amcr = read_amcr >> (ffs(amcr_mask) - 1);
187
+
187
+
188
+    if (amcr != read_amcr) {
188
+    if (amcr != read_amcr) {
189
+        dev_err(dev, "AMCR value not coherent with DT memory-map areas\n");
189
+        dev_err(dev, "AMCR value not coherent with DT memory-map areas\n");
190
+        ret = -EINVAL;
190
+        ret = -EINVAL;
191
+    }
191
+    }
192
+
192
+
193
+    return ret;
193
+    return ret;
194
+}
194
+}
195
+
195
+
196
+static int stm32_omm_toggle_child_clock(struct device *dev, bool enable)
196
+static int stm32_omm_toggle_child_clock(struct device *dev, bool enable)
197
+{
197
+{
198
+    /* 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 */
199
+    struct clk *first_child_clk = NULL;
199
+    struct clk *first_child_clk = NULL;
200
+    struct stm32_omm *omm = dev_get_drvdata(dev);
200
+    struct stm32_omm *omm = dev_get_drvdata(dev);
201
+    u8 i;
201
+    u8 i;
202
+    int ret;
202
+    int ret;
203
+
203
+
204
+    for (i = 0; i < omm->nb_child; i++) {
204
+    for (i = 0; i < omm->nb_child; i++) {
205
+        if (enable) {
205
+        if (enable) {
206
+            ret = clk_prepare_enable(omm->clk_bulk[i + 1].clk);
206
+            ret = clk_prepare_enable(omm->clk_bulk[i + 1].clk);
207
+            if (ret) {
207
+            if (ret) {
208
+                if (first_child_clk)
208
+                if (first_child_clk)
209
+                    clk_disable_unprepare(first_child_clk);
209
+                    clk_disable_unprepare(first_child_clk);
210
+
210
+
211
+                dev_err(dev, "Can not enable clock\n");
211
+                dev_err(dev, "Can not enable clock\n");
212
+                return ret;
212
+                return ret;
213
+            }
213
+            }
214
+        } else {
214
+        } else {
215
+            clk_disable_unprepare(omm->clk_bulk[i + 1].clk);
215
+            clk_disable_unprepare(omm->clk_bulk[i + 1].clk);
216
+        }
216
+        }
217
+
217
+
218
+        first_child_clk = omm->clk_bulk[i + 1].clk;
218
+        first_child_clk = omm->clk_bulk[i + 1].clk;
219
+    }
219
+    }
220
+
220
+
221
+    return 0;
221
+    return 0;
222
+}
222
+}
223
+
223
+
224
+static int stm32_omm_disable_child(struct device *dev)
224
+static int stm32_omm_disable_child(struct device *dev)
225
+{
225
+{
226
+    static const char * const resets_name[] = {"ospi1", "ospi2"};
226
+    static const char * const resets_name[] = {"ospi1", "ospi2"};
227
+    struct stm32_omm *omm = dev_get_drvdata(dev);
227
+    struct stm32_omm *omm = dev_get_drvdata(dev);
228
+    struct reset_control *reset;
228
+    struct reset_control *reset;
229
+    int ret;
229
+    int ret;
230
+    u8 i;
230
+    u8 i;
231
+
231
+
232
+    ret = stm32_omm_toggle_child_clock(dev, true);
232
+    ret = stm32_omm_toggle_child_clock(dev, true);
233
+    if (!ret)
233
+    if (!ret)
234
+        return ret;
234
+        return ret;
235
+
235
+
236
+    for (i = 0; i < omm->nb_child; i++) {
236
+    for (i = 0; i < omm->nb_child; i++) {
237
+        reset = reset_control_get_exclusive(dev, resets_name[i]);
237
+        reset = reset_control_get_exclusive(dev, resets_name[i]);
238
+        if (IS_ERR(reset)) {
238
+        if (IS_ERR(reset)) {
239
+            dev_err(dev, "Can't get %s reset\n", resets_name[i]);
239
+            dev_err(dev, "Can't get %s reset\n", resets_name[i]);
240
+            return PTR_ERR(reset);
240
+            return PTR_ERR(reset);
241
+        };
241
+        };
242
+
242
+
243
+        /* reset OSPI to ensure CR_EN bit is set to 0 */
243
+        /* reset OSPI to ensure CR_EN bit is set to 0 */
244
+        reset_control_assert(reset);
244
+        reset_control_assert(reset);
245
+        udelay(2);
245
+        udelay(2);
246
+        reset_control_deassert(reset);
246
+        reset_control_deassert(reset);
247
+
247
+
248
+        reset_control_put(reset);
248
+        reset_control_put(reset);
249
+    }
249
+    }
250
+
250
+
251
+    return stm32_omm_toggle_child_clock(dev, false);
251
+    return stm32_omm_toggle_child_clock(dev, false);
252
+}
252
+}
253
+
253
+
254
+static int stm32_omm_configure(struct device *dev)
254
+static int stm32_omm_configure(struct device *dev)
255
+{
255
+{
256
+    static const char * const clocks_name[] = {"omm", "ospi1", "ospi2"};
256
+    static const char * const clocks_name[] = {"omm", "ospi1", "ospi2"};
257
+    struct stm32_omm *omm = dev_get_drvdata(dev);
257
+    struct stm32_omm *omm = dev_get_drvdata(dev);
258
+    unsigned long clk_rate_max = 0;
258
+    unsigned long clk_rate_max = 0;
259
+    u32 mux = 0;
259
+    u32 mux = 0;
260
+    u32 cssel_ovr = 0;
260
+    u32 cssel_ovr = 0;
261
+    u32 req2ack = 0;
261
+    u32 req2ack = 0;
262
+    struct reset_control *rstc;
262
+    struct reset_control *rstc;
263
+    unsigned long clk_rate;
263
+    unsigned long clk_rate;
264
+    int ret;
264
+    int ret;
265
+    u8 i;
265
+    u8 i;
266
+
266
+
267
+    for (i = 0; i < OMM_CLK_NB; i++)
267
+    for (i = 0; i < OMM_CLK_NB; i++)
268
+        omm->clk_bulk[i].id = clocks_name[i];
268
+        omm->clk_bulk[i].id = clocks_name[i];
269
+
269
+
270
+    /* retrieve OMM, OSPI1 and OSPI2 clocks */
270
+    /* retrieve OMM, OSPI1 and OSPI2 clocks */
271
+    ret = devm_clk_bulk_get(dev, OMM_CLK_NB, omm->clk_bulk);
271
+    ret = devm_clk_bulk_get(dev, OMM_CLK_NB, omm->clk_bulk);
272
+    if (ret)
272
+    if (ret)
273
+        return dev_err_probe(dev, ret, "Failed to get OMM/OSPI's clocks\n");
273
+        return dev_err_probe(dev, ret, "Failed to get OMM/OSPI's clocks\n");
274
+
274
+
275
+    /* Ensure both OSPI instance are disabled before configuring OMM */
275
+    /* Ensure both OSPI instance are disabled before configuring OMM */
276
+    ret = stm32_omm_disable_child(dev);
276
+    ret = stm32_omm_disable_child(dev);
277
+    if (ret)
277
+    if (ret)
278
+        return ret;
278
+        return ret;
279
+
279
+
280
+    ret = pm_runtime_resume_and_get(dev);
280
+    ret = pm_runtime_resume_and_get(dev);
281
+    if (ret < 0)
281
+    if (ret < 0)
282
+        return ret;
282
+        return ret;
283
+
283
+
284
+    /* parse children's clock */
284
+    /* parse children's clock */
285
+    for (i = 1; i <= omm->nb_child; i++) {
285
+    for (i = 1; i <= omm->nb_child; i++) {
286
+        clk_rate = clk_get_rate(omm->clk_bulk[i].clk);
286
+        clk_rate = clk_get_rate(omm->clk_bulk[i].clk);
287
+        if (!clk_rate) {
287
+        if (!clk_rate) {
288
+            dev_err(dev, "Invalid clock rate\n");
288
+            dev_err(dev, "Invalid clock rate\n");
289
+            goto err_clk_disable;
289
+            goto err_clk_disable;
290
+        }
290
+        }
291
+
291
+
292
+        if (clk_rate > clk_rate_max)
292
+        if (clk_rate > clk_rate_max)
293
+            clk_rate_max = clk_rate;
293
+            clk_rate_max = clk_rate;
294
+    }
294
+    }
295
+
295
+
296
+    rstc = devm_reset_control_get_exclusive(dev, "omm");
296
+    rstc = devm_reset_control_get_exclusive(dev, "omm");
297
+    if (IS_ERR(rstc))
297
+    if (IS_ERR(rstc))
298
+        return dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n");
298
+        return dev_err_probe(dev, PTR_ERR(rstc), "reset get failed\n");
299
+
299
+
300
+    reset_control_assert(rstc);
300
+    reset_control_assert(rstc);
301
+    udelay(2);
301
+    udelay(2);
302
+    reset_control_deassert(rstc);
302
+    reset_control_deassert(rstc);
303
+
303
+
304
+    omm->cr = readl_relaxed(omm->io_base + OMM_CR);
304
+    omm->cr = readl_relaxed(omm->io_base + OMM_CR);
305
+    /* optional */
305
+    /* optional */
306
+    ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux);
306
+    ret = of_property_read_u32(dev->of_node, "st,omm-mux", &mux);
307
+    if (!ret) {
307
+    if (!ret) {
308
+        if (mux & CR_MUXEN) {
308
+        if (mux & CR_MUXEN) {
309
+            ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns",
309
+            ret = of_property_read_u32(dev->of_node, "st,omm-req2ack-ns",
310
+                         &req2ack);
310
+                         &req2ack);
311
+            if (!ret && !req2ack) {
311
+            if (!ret && !req2ack) {
312
+                req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1;
312
+                req2ack = DIV_ROUND_UP(req2ack, NSEC_PER_SEC / clk_rate_max) - 1;
313
+
313
+
314
+                if (req2ack > 256)
314
+                if (req2ack > 256)
315
+                    req2ack = 256;
315
+                    req2ack = 256;
316
+            }
316
+            }
317
+
317
+
318
+            req2ack = FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
318
+            req2ack = FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
319
+
319
+
320
+            omm->cr &= ~CR_REQ2ACK_MASK;
320
+            omm->cr &= ~CR_REQ2ACK_MASK;
321
+            omm->cr |= FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
321
+            omm->cr |= FIELD_PREP(CR_REQ2ACK_MASK, req2ack);
322
+
322
+
323
+            /*
323
+            /*
324
+             * 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
325
+             * always enabled
325
+             * always enabled
326
+             */
326
+             */
327
+            ret = stm32_omm_toggle_child_clock(dev, true);
327
+            ret = stm32_omm_toggle_child_clock(dev, true);
328
+            if (ret)
328
+            if (ret)
329
+                goto err_clk_disable;
329
+                goto err_clk_disable;
330
+        }
330
+        }
331
+
331
+
332
+        omm->cr &= ~CR_MUXENMODE_MASK;
332
+        omm->cr &= ~CR_MUXENMODE_MASK;
333
+        omm->cr |= FIELD_PREP(CR_MUXENMODE_MASK, mux);
333
+        omm->cr |= FIELD_PREP(CR_MUXENMODE_MASK, mux);
334
+    }
334
+    }
335
+
335
+
336
+    /* optional */
336
+    /* optional */
337
+    ret = of_property_read_u32(dev->of_node, "st,omm-cssel-ovr", &cssel_ovr);
337
+    ret = of_property_read_u32(dev->of_node, "st,omm-cssel-ovr", &cssel_ovr);
338
+    if (!ret) {
338
+    if (!ret) {
339
+        omm->cr &= ~CR_CSSEL_OVR_MASK;
339
+        omm->cr &= ~CR_CSSEL_OVR_MASK;
340
+        omm->cr |= FIELD_PREP(CR_CSSEL_OVR_MASK, cssel_ovr);
340
+        omm->cr |= FIELD_PREP(CR_CSSEL_OVR_MASK, cssel_ovr);
341
+        omm->cr |= CR_CSSEL_OVR_EN;
341
+        omm->cr |= CR_CSSEL_OVR_EN;
342
+    }
342
+    }
343
+
343
+
344
+    omm->restore_omm = true;
344
+    omm->restore_omm = true;
345
+    writel_relaxed(omm->cr, omm->io_base + OMM_CR);
345
+    writel_relaxed(omm->cr, omm->io_base + OMM_CR);
346
+
346
+
347
+    ret = stm32_omm_set_amcr(dev, true);
347
+    ret = stm32_omm_set_amcr(dev, true);
348
+
348
+
349
+err_clk_disable:
349
+err_clk_disable:
350
+    pm_runtime_put_sync_suspend(dev);
350
+    pm_runtime_put_sync_suspend(dev);
351
+
351
+
352
+    return ret;
352
+    return ret;
353
+}
353
+}
354
+
354
+
355
+static int stm32_omm_check_access(struct device_node *np)
355
+static int stm32_omm_check_access(struct device_node *np)
356
+{
356
+{
357
+    struct stm32_firewall firewall;
357
+    struct stm32_firewall firewall;
358
+    int ret;
358
+    int ret;
359
+
359
+
360
+    ret = stm32_firewall_get_firewall(np, &firewall, 1);
360
+    ret = stm32_firewall_get_firewall(np, &firewall, 1);
361
+    if (ret)
361
+    if (ret)
362
+        return ret;
362
+        return ret;
363
+
363
+
364
+    return stm32_firewall_grant_access(&firewall);
364
+    return stm32_firewall_grant_access(&firewall);
365
+}
365
+}
366
+
366
+
367
+static int stm32_omm_probe(struct platform_device *pdev)
367
+static int stm32_omm_probe(struct platform_device *pdev)
368
+{
368
+{
369
+    struct device *dev = &pdev->dev;
369
+    struct device *dev = &pdev->dev;
370
+    u8 child_access_granted = 0;
370
+    u8 child_access_granted = 0;
371
+    struct stm32_omm *omm;
371
+    struct stm32_omm *omm;
372
+    int ret;
372
+    int ret;
373
+
373
+
374
+    omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
374
+    omm = devm_kzalloc(dev, sizeof(*omm), GFP_KERNEL);
375
+    if (!omm)
375
+    if (!omm)
376
+        return -ENOMEM;
376
+        return -ENOMEM;
377
+
377
+
378
+    omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
378
+    omm->io_base = devm_platform_ioremap_resource_byname(pdev, "regs");
379
+    if (IS_ERR(omm->io_base))
379
+    if (IS_ERR(omm->io_base))
380
+        return PTR_ERR(omm->io_base);
380
+        return PTR_ERR(omm->io_base);
381
+
381
+
382
+    omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
382
+    omm->mm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "memory_map");
383
+    if (IS_ERR(omm->mm_res))
383
+    if (IS_ERR(omm->mm_res))
384
+        return PTR_ERR(omm->mm_res);
384
+        return PTR_ERR(omm->mm_res);
385
+
385
+
386
+    /* check child's access */
386
+    /* check child's access */
387
+    for_each_child_of_node_scoped(dev->of_node, child) {
387
+    for_each_child_of_node_scoped(dev->of_node, child) {
388
+        if (omm->nb_child >= OMM_CHILD_NB) {
388
+        if (omm->nb_child >= OMM_CHILD_NB) {
389
+            dev_err(dev, "Bad DT, found too much children\n");
389
+            dev_err(dev, "Bad DT, found too much children\n");
390
+            return -E2BIG;
390
+            return -E2BIG;
391
+        }
391
+        }
392
+
392
+
393
+        if (!of_device_is_compatible(child, "st,stm32mp25-omi"))
393
+        if (!of_device_is_compatible(child, "st,stm32mp25-omi"))
394
+            return -EINVAL;
394
+            return -EINVAL;
395
+
395
+
396
+        ret = stm32_omm_check_access(child);
396
+        ret = stm32_omm_check_access(child);
397
+        if (ret < 0 && ret != -EACCES)
397
+        if (ret < 0 && ret != -EACCES)
398
+            return ret;
398
+            return ret;
399
+
399
+
400
+        if (!ret)
400
+        if (!ret)
401
+            child_access_granted++;
401
+            child_access_granted++;
402
+
402
+
403
+        omm->nb_child++;
403
+        omm->nb_child++;
404
+    }
404
+    }
405
+
405
+
406
+    if (omm->nb_child != OMM_CHILD_NB)
406
+    if (omm->nb_child != OMM_CHILD_NB)
407
+        return -EINVAL;
407
+        return -EINVAL;
408
+
408
+
409
+    platform_set_drvdata(pdev, omm);
409
+    platform_set_drvdata(pdev, omm);
410
+
410
+
411
+    pm_runtime_enable(dev);
411
+    pm_runtime_enable(dev);
412
+
412
+
413
+    /* check if OMM's resource access is granted */
413
+    /* check if OMM's resource access is granted */
414
+    ret = stm32_omm_check_access(dev->of_node);
414
+    ret = stm32_omm_check_access(dev->of_node);
415
+    if (ret < 0 && ret != -EACCES)
415
+    if (ret < 0 && ret != -EACCES)
416
+        goto error;
416
+        goto error;
417
+
417
+
418
+    if (!ret && child_access_granted == OMM_CHILD_NB) {
418
+    if (!ret && child_access_granted == OMM_CHILD_NB) {
419
+        ret = stm32_omm_configure(dev);
419
+        ret = stm32_omm_configure(dev);
420
+        if (ret)
420
+        if (ret)
421
+            goto error;
421
+            goto error;
422
+    } else {
422
+    } else {
423
+        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");
424
+        /*
424
+        /*
425
+         * 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
426
+         * with memory-map areas defined in DT
426
+         * with memory-map areas defined in DT
427
+         */
427
+         */
428
+        ret = stm32_omm_set_amcr(dev, false);
428
+        ret = stm32_omm_set_amcr(dev, false);
429
+        if (ret)
429
+        if (ret)
430
+            goto error;
430
+            goto error;
431
+    }
431
+    }
432
+
432
+
433
+    ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
433
+    ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
434
+    if (ret) {
434
+    if (ret) {
435
+        dev_err(dev, "Failed to create Octo Memory Manager child\n");
435
+        dev_err(dev, "Failed to create Octo Memory Manager child\n");
436
+        of_platform_depopulate(dev);
436
+        of_platform_depopulate(dev);
437
+        ret = -EINVAL;
437
+        ret = -EINVAL;
438
+        goto error;
438
+        goto error;
439
+    }
439
+    }
440
+
440
+
441
+    return ret;
441
+    return ret;
442
+
442
+
443
+error:
443
+error:
444
+    pm_runtime_disable(dev);
444
+    pm_runtime_disable(dev);
445
+
445
+
446
+    return ret;
446
+    return ret;
447
+
447
+
448
+}
448
+}
449
+
449
+
450
+static void stm32_omm_remove(struct platform_device *pdev)
450
+static void stm32_omm_remove(struct platform_device *pdev)
451
+{
451
+{
452
+    struct stm32_omm *omm = platform_get_drvdata(pdev);
452
+    struct stm32_omm *omm = platform_get_drvdata(pdev);
453
+
453
+
454
+    of_platform_depopulate(&pdev->dev);
454
+    of_platform_depopulate(&pdev->dev);
455
+    if (omm->cr & CR_MUXEN)
455
+    if (omm->cr & CR_MUXEN)
456
+        stm32_omm_toggle_child_clock(&pdev->dev, false);
456
+        stm32_omm_toggle_child_clock(&pdev->dev, false);
457
+
457
+
458
+    pm_runtime_disable(&pdev->dev);
458
+    pm_runtime_disable(&pdev->dev);
459
+}
459
+}
460
+
460
+
461
+static const struct of_device_id stm32_omm_of_match[] = {
461
+static const struct of_device_id stm32_omm_of_match[] = {
462
+    { .compatible = "st,stm32mp25-omm", },
462
+    { .compatible = "st,stm32mp25-omm", },
463
+    {}
463
+    {}
464
+};
464
+};
465
+MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
465
+MODULE_DEVICE_TABLE(of, stm32_omm_of_match);
466
+
466
+
467
+static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
467
+static int __maybe_unused stm32_omm_runtime_suspend(struct device *dev)
468
+{
468
+{
469
+    struct stm32_omm *omm = dev_get_drvdata(dev);
469
+    struct stm32_omm *omm = dev_get_drvdata(dev);
470
+
470
+
471
+    clk_disable_unprepare(omm->clk_bulk[0].clk);
471
+    clk_disable_unprepare(omm->clk_bulk[0].clk);
472
+
472
+
473
+    return 0;
473
+    return 0;
474
+}
474
+}
475
+
475
+
476
+static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
476
+static int __maybe_unused stm32_omm_runtime_resume(struct device *dev)
477
+{
477
+{
478
+    struct stm32_omm *omm = dev_get_drvdata(dev);
478
+    struct stm32_omm *omm = dev_get_drvdata(dev);
479
+
479
+
480
+    return clk_prepare_enable(omm->clk_bulk[0].clk);
480
+    return clk_prepare_enable(omm->clk_bulk[0].clk);
481
+}
481
+}
482
+
482
+
483
+static int __maybe_unused stm32_omm_suspend(struct device *dev)
483
+static int __maybe_unused stm32_omm_suspend(struct device *dev)
484
+{
484
+{
485
+    struct stm32_omm *omm = dev_get_drvdata(dev);
485
+    struct stm32_omm *omm = dev_get_drvdata(dev);
486
+
486
+
487
+    if (omm->restore_omm && omm->cr & CR_MUXEN)
487
+    if (omm->restore_omm && omm->cr & CR_MUXEN)
488
+        stm32_omm_toggle_child_clock(dev, false);
488
+        stm32_omm_toggle_child_clock(dev, false);
489
+
489
+
490
+    return pinctrl_pm_select_sleep_state(dev);
490
+    return pinctrl_pm_select_sleep_state(dev);
491
+}
491
+}
492
+
492
+
493
+static int __maybe_unused stm32_omm_resume(struct device *dev)
493
+static int __maybe_unused stm32_omm_resume(struct device *dev)
494
+{
494
+{
495
+    struct stm32_omm *omm = dev_get_drvdata(dev);
495
+    struct stm32_omm *omm = dev_get_drvdata(dev);
496
+    int ret;
496
+    int ret;
497
+
497
+
498
+    pinctrl_pm_select_default_state(dev);
498
+    pinctrl_pm_select_default_state(dev);
499
+
499
+
500
+    if (!omm->restore_omm)
500
+    if (!omm->restore_omm)
501
+        return 0;
501
+        return 0;
502
+
502
+
503
+    /* Ensure both OSPI instance are disabled before configuring OMM */
503
+    /* Ensure both OSPI instance are disabled before configuring OMM */
504
+    ret = stm32_omm_disable_child(dev);
504
+    ret = stm32_omm_disable_child(dev);
505
+    if (ret)
505
+    if (ret)
506
+        return ret;
506
+        return ret;
507
+
507
+
508
+    ret = pm_runtime_resume_and_get(dev);
508
+    ret = pm_runtime_resume_and_get(dev);
509
+    if (ret < 0)
509
+    if (ret < 0)
510
+        return ret;
510
+        return ret;
511
+
511
+
512
+    writel_relaxed(omm->cr, omm->io_base + OMM_CR);
512
+    writel_relaxed(omm->cr, omm->io_base + OMM_CR);
513
+    ret = stm32_omm_set_amcr(dev, true);
513
+    ret = stm32_omm_set_amcr(dev, true);
514
+    pm_runtime_put_sync_suspend(dev);
514
+    pm_runtime_put_sync_suspend(dev);
515
+    if (ret)
515
+    if (ret)
516
+        return ret;
516
+        return ret;
517
+
517
+
518
+    if (omm->cr & CR_MUXEN)
518
+    if (omm->cr & CR_MUXEN)
519
+        ret = stm32_omm_toggle_child_clock(dev, true);
519
+        ret = stm32_omm_toggle_child_clock(dev, true);
520
+
520
+
521
+    return ret;
521
+    return ret;
522
+}
522
+}
523
+
523
+
524
+static const struct dev_pm_ops stm32_omm_pm_ops = {
524
+static const struct dev_pm_ops stm32_omm_pm_ops = {
525
+    SET_RUNTIME_PM_OPS(stm32_omm_runtime_suspend,
525
+    SET_RUNTIME_PM_OPS(stm32_omm_runtime_suspend,
526
+             stm32_omm_runtime_resume, NULL)
526
+             stm32_omm_runtime_resume, NULL)
527
+    SET_SYSTEM_SLEEP_PM_OPS(stm32_omm_suspend, stm32_omm_resume)
527
+    SET_SYSTEM_SLEEP_PM_OPS(stm32_omm_suspend, stm32_omm_resume)
528
+};
528
+};
529
+
529
+
530
+static struct platform_driver stm32_omm_driver = {
530
+static struct platform_driver stm32_omm_driver = {
531
+    .probe    = stm32_omm_probe,
531
+    .probe    = stm32_omm_probe,
532
+    .remove = stm32_omm_remove,
532
+    .remove = stm32_omm_remove,
533
+    .driver    = {
533
+    .driver    = {
534
+        .name = "stm32-omm",
534
+        .name = "stm32-omm",
535
+        .of_match_table = stm32_omm_of_match,
535
+        .of_match_table = stm32_omm_of_match,
536
+        .pm = &stm32_omm_pm_ops,
536
+        .pm = &stm32_omm_pm_ops,
537
+    },
537
+    },
538
+};
538
+};
539
+module_platform_driver(stm32_omm_driver);
539
+module_platform_driver(stm32_omm_driver);
540
+
540
+
541
+MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
541
+MODULE_DESCRIPTION("STMicroelectronics Octo Memory Manager driver");
542
+MODULE_LICENSE("GPL");
542
+MODULE_LICENSE("GPL");
543
543
544
--
544
--
545
2.25.1
545
2.25.1
diff view generated by jsdifflib
...
...
33
+                #address-cells = <2>;
33
+                #address-cells = <2>;
34
+                #size-cells = <1>;
34
+                #size-cells = <1>;
35
+                st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
35
+                st,syscfg-amcr = <&syscfg 0x2c00 0x7>;
36
+                status = "disabled";
36
+                status = "disabled";
37
+
37
+
38
+                ospi1: spi@40430000 {
38
+                ospi1: spi@0 {
39
+                    compatible = "st,stm32mp25-ospi";
39
+                    compatible = "st,stm32mp25-ospi";
40
+                    reg = <0 0 0x400>;
40
+                    reg = <0 0 0x400>;
41
+                    interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
41
+                    interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
42
+                    dmas = <&hpdma 2 0x62 0x00003121>,
42
+                    dmas = <&hpdma 2 0x62 0x00003121>,
43
+                     <&hpdma 2 0x42 0x00003112>;
43
+                     <&hpdma 2 0x42 0x00003112>;
...
...
49
+                    power-domains = <&CLUSTER_PD>;
49
+                    power-domains = <&CLUSTER_PD>;
50
+                    st,syscfg-dlyb = <&syscfg 0x1000>;
50
+                    st,syscfg-dlyb = <&syscfg 0x1000>;
51
+                    status = "disabled";
51
+                    status = "disabled";
52
+                };
52
+                };
53
+
53
+
54
+                ospi2: spi@40440000 {
54
+                ospi2: spi@1 {
55
+                    compatible = "st,stm32mp25-ospi";
55
+                    compatible = "st,stm32mp25-ospi";
56
+                    reg = <1 0 0x400>;
56
+                    reg = <1 0 0x400>;
57
+                    interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
57
+                    interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
58
+                    dmas = <&hpdma 3 0x62 0x00003121>,
58
+                    dmas = <&hpdma 3 0x62 0x00003121>,
59
+                     <&hpdma 3 0x42 0x00003112>;
59
+                     <&hpdma 3 0x42 0x00003112>;
...
...
diff view generated by jsdifflib
1
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
2
2
3
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
3
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
4
---
4
---
5
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +++++++++++++++++++++++++++
5
arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi | 51 +++++++++++++++++++++++++++
6
1 file changed, 51 insertions(+)
6
1 file changed, 51 insertions(+)
7
7
8
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
9
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
10
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
10
--- a/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
11
+++ b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
11
+++ b/arch/arm64/boot/dts/st/stm32mp25-pinctrl.dtsi
12
@@ -XXX,XX +XXX,XX @@ pins2 {
12
@@ -XXX,XX +XXX,XX @@ pins2 {
13
        };
13
        };
14
    };
14
    };
15
15
16
+    ospi_port1_clk_pins_a: ospi-port1-clk-0 {
16
+    ospi_port1_clk_pins_a: ospi-port1-clk-0 {
17
+        pins {
17
+        pins {
18
+            pinmux = <STM32_PINMUX('D', 0, AF10)>; /* OSPI1_CLK */
18
+            pinmux = <STM32_PINMUX('D', 0, AF10)>; /* OSPI1_CLK */
19
+            bias-disable;
19
+            bias-disable;
20
+            drive-push-pull;
20
+            drive-push-pull;
21
+            slew-rate = <2>;
21
+            slew-rate = <2>;
22
+        };
22
+        };
23
+    };
23
+    };
24
+
24
+
25
+    ospi_port1_clk_sleep_pins_a: ospi-port1-clk-sleep-0 {
25
+    ospi_port1_clk_sleep_pins_a: ospi-port1-clk-sleep-0 {
26
+        pins {
26
+        pins {
27
+            pinmux = <STM32_PINMUX('D', 0, ANALOG)>; /* OSPI1_CLK */
27
+            pinmux = <STM32_PINMUX('D', 0, ANALOG)>; /* OSPI1_CLK */
28
+        };
28
+        };
29
+    };
29
+    };
30
+
30
+
31
+    ospi_port1_cs0_pins_a: ospi-port1-cs0-0 {
31
+    ospi_port1_cs0_pins_a: ospi-port1-cs0-0 {
32
+        pins {
32
+        pins {
33
+            pinmux = <STM32_PINMUX('D', 3, AF10)>; /* OSPI_NCS0 */
33
+            pinmux = <STM32_PINMUX('D', 3, AF10)>; /* OSPI_NCS0 */
34
+            bias-pull-up;
34
+            bias-pull-up;
35
+            drive-push-pull;
35
+            drive-push-pull;
36
+            slew-rate = <0>;
36
+            slew-rate = <0>;
37
+        };
37
+        };
38
+    };
38
+    };
39
+
39
+
40
+    ospi_port1_cs0_sleep_pins_a: ospi-port1-cs0-sleep-0 {
40
+    ospi_port1_cs0_sleep_pins_a: ospi-port1-cs0-sleep-0 {
41
+        pins {
41
+        pins {
42
+            pinmux = <STM32_PINMUX('D', 3, ANALOG)>; /* OSPI_NCS0 */
42
+            pinmux = <STM32_PINMUX('D', 3, ANALOG)>; /* OSPI_NCS0 */
43
+        };
43
+        };
44
+    };
44
+    };
45
+
45
+
46
+    ospi_port1_io03_pins_a: ospi-port1-io03-0 {
46
+    ospi_port1_io03_pins_a: ospi-port1-io03-0 {
47
+        pins {
47
+        pins {
48
+            pinmux = <STM32_PINMUX('D', 4, AF10)>, /* OSPI_IO0 */
48
+            pinmux = <STM32_PINMUX('D', 4, AF10)>, /* OSPI_IO0 */
49
+                 <STM32_PINMUX('D', 5, AF10)>, /* OSPI_IO1 */
49
+                 <STM32_PINMUX('D', 5, AF10)>, /* OSPI_IO1 */
50
+                 <STM32_PINMUX('D', 6, AF10)>, /* OSPI_IO2 */
50
+                 <STM32_PINMUX('D', 6, AF10)>, /* OSPI_IO2 */
51
+                 <STM32_PINMUX('D', 7, AF10)>; /* OSPI_IO3 */
51
+                 <STM32_PINMUX('D', 7, AF10)>; /* OSPI_IO3 */
52
+            bias-disable;
52
+            bias-disable;
53
+            drive-push-pull;
53
+            drive-push-pull;
54
+            slew-rate = <0>;
54
+            slew-rate = <0>;
55
+        };
55
+        };
56
+    };
56
+    };
57
+
57
+
58
+    ospi_port1_io03_sleep_pins_a: ospi-port1-io03-sleep-0 {
58
+    ospi_port1_io03_sleep_pins_a: ospi-port1-io03-sleep-0 {
59
+        pins {
59
+        pins {
60
+            pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* OSPI_IO0 */
60
+            pinmux = <STM32_PINMUX('D', 4, ANALOG)>, /* OSPI_IO0 */
61
+                 <STM32_PINMUX('D', 5, ANALOG)>, /* OSPI_IO1 */
61
+                 <STM32_PINMUX('D', 5, ANALOG)>, /* OSPI_IO1 */
62
+                 <STM32_PINMUX('D', 6, ANALOG)>, /* OSPI_IO2 */
62
+                 <STM32_PINMUX('D', 6, ANALOG)>, /* OSPI_IO2 */
63
+                 <STM32_PINMUX('D', 7, ANALOG)>; /* OSPI_IO3 */
63
+                 <STM32_PINMUX('D', 7, ANALOG)>; /* OSPI_IO3 */
64
+        };
64
+        };
65
+    };
65
+    };
66
+
66
+
67
    sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
67
    sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {
68
        pins1 {
68
        pins1 {
69
            pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */
69
            pinmux = <STM32_PINMUX('E', 4, AF10)>, /* SDMMC1_D0 */
70
70
71
--
71
--
72
2.25.1
72
2.25.1
diff view generated by jsdifflib
...
...
34
+         &ospi_port1_io03_sleep_pins_a
34
+         &ospi_port1_io03_sleep_pins_a
35
+         &ospi_port1_cs0_sleep_pins_a>;
35
+         &ospi_port1_cs0_sleep_pins_a>;
36
+    pinctrl-names = "default", "sleep";
36
+    pinctrl-names = "default", "sleep";
37
+    status = "okay";
37
+    status = "okay";
38
+
38
+
39
+    spi@40430000 {
39
+    spi@0 {
40
+        #address-cells = <1>;
40
+        #address-cells = <1>;
41
+        #size-cells = <0>;
41
+        #size-cells = <0>;
42
+        memory-region = <&mm_ospi1>;
42
+        memory-region = <&mm_ospi1>;
43
+        status = "okay";
43
+        status = "okay";
44
+
44
+
...
...
diff view generated by jsdifflib
1
Enable STM32 OctoSPI driver.
1
Enable STM32 OctoSPI driver.
2
Enable STM32 Octo Memory Manager (OMM) driver which is needed
2
Enable STM32 Octo Memory Manager (OMM) driver which is needed
3
for OSPI usage on STM32MP257F-EV1 board.
3
for OSPI usage on STM32MP257F-EV1 board.
4
4
5
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
5
Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
6
---
6
---
7
arch/arm64/configs/defconfig | 2 ++
7
arch/arm64/configs/defconfig | 2 ++
8
1 file changed, 2 insertions(+)
8
1 file changed, 2 insertions(+)
9
9
10
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
10
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
11
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
12
--- a/arch/arm64/configs/defconfig
12
--- a/arch/arm64/configs/defconfig
13
+++ b/arch/arm64/configs/defconfig
13
+++ b/arch/arm64/configs/defconfig
14
@@ -XXX,XX +XXX,XX @@ CONFIG_SPI_QUP=y
14
@@ -XXX,XX +XXX,XX @@ CONFIG_SPI_QUP=y
15
CONFIG_SPI_QCOM_GENI=m
15
CONFIG_SPI_QCOM_GENI=m
16
CONFIG_SPI_S3C64XX=y
16
CONFIG_SPI_S3C64XX=y
17
CONFIG_SPI_SH_MSIOF=m
17
CONFIG_SPI_SH_MSIOF=m
18
+CONFIG_SPI_STM32_OSPI=m
18
+CONFIG_SPI_STM32_OSPI=m
19
CONFIG_SPI_SUN6I=y
19
CONFIG_SPI_SUN6I=y
20
CONFIG_SPI_TEGRA210_QUAD=m
20
CONFIG_SPI_TEGRA210_QUAD=m
21
CONFIG_SPI_TEGRA114=m
21
CONFIG_SPI_TEGRA114=m
22
@@ -XXX,XX +XXX,XX @@ CONFIG_EXTCON_USB_GPIO=y
22
@@ -XXX,XX +XXX,XX @@ CONFIG_EXTCON_USB_GPIO=y
23
CONFIG_EXTCON_USBC_CROS_EC=y
23
CONFIG_EXTCON_USBC_CROS_EC=y
24
CONFIG_FSL_IFC=y
24
CONFIG_FSL_IFC=y
25
CONFIG_RENESAS_RPCIF=m
25
CONFIG_RENESAS_RPCIF=m
26
+CONFIG_STM32_OMM=m
26
+CONFIG_STM32_OMM=m
27
CONFIG_IIO=y
27
CONFIG_IIO=y
28
CONFIG_EXYNOS_ADC=y
28
CONFIG_EXYNOS_ADC=y
29
CONFIG_IMX8QXP_ADC=m
29
CONFIG_IMX8QXP_ADC=m
30
30
31
--
31
--
32
2.25.1
32
2.25.1
diff view generated by jsdifflib