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