Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'pci/controller/stm32'

- Update pinctrl documentation of initial states and use in runtime
suspend/resume (Christian Bruel)

- Add pinctrl_pm_select_init_state() for use by stm32 driver, which needs
it during resume (Christian Bruel)

- Add devicetree bindings and drivers for the STMicroelectronics STM32MP25
in host and endpoint modes (Christian Bruel)

* pci/controller/stm32:
MAINTAINERS: Add entry for ST STM32MP25 PCIe drivers
PCI: stm32-ep: Add PCIe Endpoint support for STM32MP25
dt-bindings: PCI: Add STM32MP25 PCIe Endpoint bindings
PCI: stm32: Add PCIe host support for STM32MP25
dt-bindings: PCI: Add STM32MP25 PCIe Root Complex bindings
pinctrl: Add pinctrl_pm_select_init_state helper function
Documentation: pinctrl: Describe PM helper functions for standard states.

+1067 -2
+33
Documentation/devicetree/bindings/pci/st,stm32-pcie-common.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/st,stm32-pcie-common.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: STM32MP25 PCIe RC/EP controller 8 + 9 + maintainers: 10 + - Christian Bruel <christian.bruel@foss.st.com> 11 + 12 + description: 13 + STM32MP25 PCIe RC/EP common properties 14 + 15 + properties: 16 + clocks: 17 + maxItems: 1 18 + description: PCIe system clock 19 + 20 + resets: 21 + maxItems: 1 22 + 23 + power-domains: 24 + maxItems: 1 25 + 26 + access-controllers: 27 + maxItems: 1 28 + 29 + required: 30 + - clocks 31 + - resets 32 + 33 + additionalProperties: true
+73
Documentation/devicetree/bindings/pci/st,stm32-pcie-ep.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/st,stm32-pcie-ep.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: STMicroelectronics STM32MP25 PCIe Endpoint 8 + 9 + maintainers: 10 + - Christian Bruel <christian.bruel@foss.st.com> 11 + 12 + description: 13 + PCIe endpoint controller based on the Synopsys DesignWare PCIe core. 14 + 15 + allOf: 16 + - $ref: /schemas/pci/snps,dw-pcie-ep.yaml# 17 + - $ref: /schemas/pci/st,stm32-pcie-common.yaml# 18 + 19 + properties: 20 + compatible: 21 + const: st,stm32mp25-pcie-ep 22 + 23 + reg: 24 + items: 25 + - description: Data Bus Interface (DBI) registers. 26 + - description: Data Bus Interface (DBI) shadow registers. 27 + - description: Internal Address Translation Unit (iATU) registers. 28 + - description: PCIe configuration registers. 29 + 30 + reg-names: 31 + items: 32 + - const: dbi 33 + - const: dbi2 34 + - const: atu 35 + - const: addr_space 36 + 37 + reset-gpios: 38 + description: GPIO controlled connection to PERST# signal 39 + maxItems: 1 40 + 41 + phys: 42 + maxItems: 1 43 + 44 + required: 45 + - phys 46 + - reset-gpios 47 + 48 + unevaluatedProperties: false 49 + 50 + examples: 51 + - | 52 + #include <dt-bindings/clock/st,stm32mp25-rcc.h> 53 + #include <dt-bindings/gpio/gpio.h> 54 + #include <dt-bindings/phy/phy.h> 55 + #include <dt-bindings/reset/st,stm32mp25-rcc.h> 56 + 57 + pcie-ep@48400000 { 58 + compatible = "st,stm32mp25-pcie-ep"; 59 + reg = <0x48400000 0x400000>, 60 + <0x48500000 0x100000>, 61 + <0x48700000 0x80000>, 62 + <0x10000000 0x10000000>; 63 + reg-names = "dbi", "dbi2", "atu", "addr_space"; 64 + clocks = <&rcc CK_BUS_PCIE>; 65 + phys = <&combophy PHY_TYPE_PCIE>; 66 + resets = <&rcc PCIE_R>; 67 + pinctrl-names = "default", "init"; 68 + pinctrl-0 = <&pcie_pins_a>; 69 + pinctrl-1 = <&pcie_init_pins_a>; 70 + reset-gpios = <&gpioj 8 GPIO_ACTIVE_LOW>; 71 + access-controllers = <&rifsc 68>; 72 + power-domains = <&CLUSTER_PD>; 73 + };
+112
Documentation/devicetree/bindings/pci/st,stm32-pcie-host.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/pci/st,stm32-pcie-host.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: STMicroelectronics STM32MP25 PCIe Root Complex 8 + 9 + maintainers: 10 + - Christian Bruel <christian.bruel@foss.st.com> 11 + 12 + description: 13 + PCIe root complex controller based on the Synopsys DesignWare PCIe core. 14 + 15 + allOf: 16 + - $ref: /schemas/pci/snps,dw-pcie.yaml# 17 + - $ref: /schemas/pci/st,stm32-pcie-common.yaml# 18 + 19 + properties: 20 + compatible: 21 + const: st,stm32mp25-pcie-rc 22 + 23 + reg: 24 + items: 25 + - description: Data Bus Interface (DBI) registers. 26 + - description: PCIe configuration registers. 27 + 28 + reg-names: 29 + items: 30 + - const: dbi 31 + - const: config 32 + 33 + msi-parent: 34 + maxItems: 1 35 + 36 + patternProperties: 37 + '^pcie@[0-2],0$': 38 + type: object 39 + $ref: /schemas/pci/pci-pci-bridge.yaml# 40 + 41 + properties: 42 + reg: 43 + maxItems: 1 44 + 45 + phys: 46 + maxItems: 1 47 + 48 + reset-gpios: 49 + description: GPIO controlled connection to PERST# signal 50 + maxItems: 1 51 + 52 + wake-gpios: 53 + description: GPIO used as WAKE# input signal 54 + maxItems: 1 55 + 56 + required: 57 + - phys 58 + - ranges 59 + 60 + unevaluatedProperties: false 61 + 62 + required: 63 + - interrupt-map 64 + - interrupt-map-mask 65 + - ranges 66 + - dma-ranges 67 + 68 + unevaluatedProperties: false 69 + 70 + examples: 71 + - | 72 + #include <dt-bindings/clock/st,stm32mp25-rcc.h> 73 + #include <dt-bindings/gpio/gpio.h> 74 + #include <dt-bindings/interrupt-controller/arm-gic.h> 75 + #include <dt-bindings/phy/phy.h> 76 + #include <dt-bindings/reset/st,stm32mp25-rcc.h> 77 + 78 + pcie@48400000 { 79 + compatible = "st,stm32mp25-pcie-rc"; 80 + device_type = "pci"; 81 + reg = <0x48400000 0x400000>, 82 + <0x10000000 0x10000>; 83 + reg-names = "dbi", "config"; 84 + #interrupt-cells = <1>; 85 + interrupt-map-mask = <0 0 0 7>; 86 + interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>, 87 + <0 0 0 2 &intc 0 0 GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>, 88 + <0 0 0 3 &intc 0 0 GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>, 89 + <0 0 0 4 &intc 0 0 GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>; 90 + #address-cells = <3>; 91 + #size-cells = <2>; 92 + ranges = <0x01000000 0x0 0x00000000 0x10010000 0x0 0x10000>, 93 + <0x02000000 0x0 0x10020000 0x10020000 0x0 0x7fe0000>, 94 + <0x42000000 0x0 0x18000000 0x18000000 0x0 0x8000000>; 95 + dma-ranges = <0x42000000 0x0 0x80000000 0x80000000 0x0 0x80000000>; 96 + clocks = <&rcc CK_BUS_PCIE>; 97 + resets = <&rcc PCIE_R>; 98 + msi-parent = <&v2m0>; 99 + access-controllers = <&rifsc 68>; 100 + power-domains = <&CLUSTER_PD>; 101 + 102 + pcie@0,0 { 103 + device_type = "pci"; 104 + reg = <0x0 0x0 0x0 0x0 0x0>; 105 + phys = <&combophy PHY_TYPE_PCIE>; 106 + wake-gpios = <&gpioh 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; 107 + reset-gpios = <&gpioj 8 GPIO_ACTIVE_LOW>; 108 + #address-cells = <3>; 109 + #size-cells = <2>; 110 + ranges; 111 + }; 112 + };
+55 -2
Documentation/driver-api/pin-control.rst
··· 1162 1162 Pin control requests from drivers 1163 1163 ================================= 1164 1164 1165 - When a device driver is about to probe the device core will automatically 1166 - attempt to issue ``pinctrl_get_select_default()`` on these devices. 1165 + When a device driver is about to probe, the device core attaches the 1166 + standard states if they are defined in the device tree by calling 1167 + ``pinctrl_bind_pins()`` on these devices. 1168 + Possible standard state names are: "default", "init", "sleep" and "idle". 1169 + 1170 + - if ``default`` is defined in the device tree, it is selected before 1171 + device probe. 1172 + 1173 + - if ``init`` and ``default`` are defined in the device tree, the "init" 1174 + state is selected before the driver probe and the "default" state is 1175 + selected after the driver probe. 1176 + 1177 + - the ``sleep`` and ``idle`` states are for power management and can only 1178 + be selected with the PM API bellow. 1179 + 1180 + PM interfaces 1181 + ================= 1182 + PM runtime suspend/resume might need to execute the same init sequence as 1183 + during probe. Since the predefined states are already attached to the 1184 + device, the driver can activate these states explicitly with the 1185 + following helper functions: 1186 + 1187 + - ``pinctrl_pm_select_default_state()`` 1188 + - ``pinctrl_pm_select_init_state()`` 1189 + - ``pinctrl_pm_select_sleep_state()`` 1190 + - ``pinctrl_pm_select_idle_state()`` 1191 + 1192 + For example, if resuming the device depend on certain pinmux states 1193 + 1194 + .. code-block:: c 1195 + 1196 + foo_suspend() 1197 + { 1198 + /* suspend device */ 1199 + ... 1200 + 1201 + pinctrl_pm_select_sleep_state(dev); 1202 + } 1203 + 1204 + foo_resume() 1205 + { 1206 + pinctrl_pm_select_init_state(dev); 1207 + 1208 + /* resuming device */ 1209 + ... 1210 + 1211 + pinctrl_pm_select_default_state(dev); 1212 + } 1213 + 1167 1214 This way driver writers do not need to add any of the boilerplate code 1168 1215 of the type found below. However when doing fine-grained state selection 1169 1216 and not using the "default" state, you may have to do some device driver ··· 1231 1184 operation and going to sleep, moving from the ``PINCTRL_STATE_DEFAULT`` to 1232 1185 ``PINCTRL_STATE_SLEEP`` at runtime, re-biasing or even re-muxing pins to save 1233 1186 current in sleep mode. 1187 + 1188 + Another case is when the pinctrl needs to switch to a certain mode during 1189 + probe and then revert to the default state at the end of probe. For example 1190 + a PINMUX may need to be configured as a GPIO during probe. In this case, use 1191 + ``PINCTRL_STATE_INIT`` to switch state before probe, then move to 1192 + ``PINCTRL_STATE_DEFAULT`` at the end of probe for normal operation. 1234 1193 1235 1194 A driver may request a certain control state to be activated, usually just the 1236 1195 default state like this:
+7
MAINTAINERS
··· 19377 19377 S: Maintained 19378 19378 F: drivers/pci/controller/dwc/pci-exynos.c 19379 19379 19380 + PCI DRIVER FOR STM32MP25 19381 + M: Christian Bruel <christian.bruel@foss.st.com> 19382 + L: linux-pci@vger.kernel.org 19383 + S: Maintained 19384 + F: Documentation/devicetree/bindings/pci/st,stm32-pcie-*.yaml 19385 + F: drivers/pci/controller/dwc/*stm32* 19386 + 19380 19387 PCI DRIVER FOR SYNOPSYS DESIGNWARE 19381 19388 M: Jingoo Han <jingoohan1@gmail.com> 19382 19389 M: Manivannan Sadhasivam <mani@kernel.org>
+24
drivers/pci/controller/dwc/Kconfig
··· 424 424 help 425 425 Say Y here if you want PCIe support on SPEAr13XX SoCs. 426 426 427 + config PCIE_STM32_HOST 428 + tristate "STMicroelectronics STM32MP25 PCIe Controller (host mode)" 429 + depends on ARCH_STM32 || COMPILE_TEST 430 + depends on PCI_MSI 431 + select PCIE_DW_HOST 432 + help 433 + Enables Root Complex (RC) support for the DesignWare core based PCIe 434 + controller found in STM32MP25 SoC. 435 + 436 + This driver can also be built as a module. If so, the module 437 + will be called pcie-stm32. 438 + 439 + config PCIE_STM32_EP 440 + tristate "STMicroelectronics STM32MP25 PCIe Controller (endpoint mode)" 441 + depends on ARCH_STM32 || COMPILE_TEST 442 + depends on PCI_ENDPOINT 443 + select PCIE_DW_EP 444 + help 445 + Enables Endpoint (EP) support for the DesignWare core based PCIe 446 + controller found in STM32MP25 SoC. 447 + 448 + This driver can also be built as a module. If so, the module 449 + will be called pcie-stm32-ep. 450 + 427 451 config PCI_DRA7XX 428 452 tristate 429 453
+2
drivers/pci/controller/dwc/Makefile
··· 31 31 obj-$(CONFIG_PCIE_UNIPHIER_EP) += pcie-uniphier-ep.o 32 32 obj-$(CONFIG_PCIE_VISCONTI_HOST) += pcie-visconti.o 33 33 obj-$(CONFIG_PCIE_RCAR_GEN4) += pcie-rcar-gen4.o 34 + obj-$(CONFIG_PCIE_STM32_HOST) += pcie-stm32.o 35 + obj-$(CONFIG_PCIE_STM32_EP) += pcie-stm32-ep.o 34 36 35 37 # The following drivers are for devices that use the generic ACPI 36 38 # pci_root.c driver but don't support standard ECAM config access.
+364
drivers/pci/controller/dwc/pcie-stm32-ep.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * STMicroelectronics STM32MP25 PCIe endpoint driver. 4 + * 5 + * Copyright (C) 2025 STMicroelectronics 6 + * Author: Christian Bruel <christian.bruel@foss.st.com> 7 + */ 8 + 9 + #include <linux/clk.h> 10 + #include <linux/mfd/syscon.h> 11 + #include <linux/of_platform.h> 12 + #include <linux/of_gpio.h> 13 + #include <linux/phy/phy.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/pm_runtime.h> 16 + #include <linux/regmap.h> 17 + #include <linux/reset.h> 18 + #include "pcie-designware.h" 19 + #include "pcie-stm32.h" 20 + 21 + struct stm32_pcie { 22 + struct dw_pcie pci; 23 + struct regmap *regmap; 24 + struct reset_control *rst; 25 + struct phy *phy; 26 + struct clk *clk; 27 + struct gpio_desc *perst_gpio; 28 + unsigned int perst_irq; 29 + }; 30 + 31 + static void stm32_pcie_ep_init(struct dw_pcie_ep *ep) 32 + { 33 + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 34 + enum pci_barno bar; 35 + 36 + for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) 37 + dw_pcie_ep_reset_bar(pci, bar); 38 + } 39 + 40 + static int stm32_pcie_enable_link(struct dw_pcie *pci) 41 + { 42 + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 43 + 44 + regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 45 + STM32MP25_PCIECR_LTSSM_EN, 46 + STM32MP25_PCIECR_LTSSM_EN); 47 + 48 + return dw_pcie_wait_for_link(pci); 49 + } 50 + 51 + static void stm32_pcie_disable_link(struct dw_pcie *pci) 52 + { 53 + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 54 + 55 + regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, STM32MP25_PCIECR_LTSSM_EN, 0); 56 + } 57 + 58 + static int stm32_pcie_start_link(struct dw_pcie *pci) 59 + { 60 + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 61 + int ret; 62 + 63 + dev_dbg(pci->dev, "Enable link\n"); 64 + 65 + ret = stm32_pcie_enable_link(pci); 66 + if (ret) { 67 + dev_err(pci->dev, "PCIe cannot establish link: %d\n", ret); 68 + return ret; 69 + } 70 + 71 + enable_irq(stm32_pcie->perst_irq); 72 + 73 + return 0; 74 + } 75 + 76 + static void stm32_pcie_stop_link(struct dw_pcie *pci) 77 + { 78 + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 79 + 80 + dev_dbg(pci->dev, "Disable link\n"); 81 + 82 + disable_irq(stm32_pcie->perst_irq); 83 + 84 + stm32_pcie_disable_link(pci); 85 + } 86 + 87 + static int stm32_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, 88 + unsigned int type, u16 interrupt_num) 89 + { 90 + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); 91 + 92 + switch (type) { 93 + case PCI_IRQ_INTX: 94 + return dw_pcie_ep_raise_intx_irq(ep, func_no); 95 + case PCI_IRQ_MSI: 96 + return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); 97 + default: 98 + dev_err(pci->dev, "UNKNOWN IRQ type\n"); 99 + return -EINVAL; 100 + } 101 + } 102 + 103 + static const struct pci_epc_features stm32_pcie_epc_features = { 104 + .msi_capable = true, 105 + .align = SZ_64K, 106 + }; 107 + 108 + static const struct pci_epc_features* 109 + stm32_pcie_get_features(struct dw_pcie_ep *ep) 110 + { 111 + return &stm32_pcie_epc_features; 112 + } 113 + 114 + static const struct dw_pcie_ep_ops stm32_pcie_ep_ops = { 115 + .init = stm32_pcie_ep_init, 116 + .raise_irq = stm32_pcie_raise_irq, 117 + .get_features = stm32_pcie_get_features, 118 + }; 119 + 120 + static const struct dw_pcie_ops dw_pcie_ops = { 121 + .start_link = stm32_pcie_start_link, 122 + .stop_link = stm32_pcie_stop_link, 123 + }; 124 + 125 + static int stm32_pcie_enable_resources(struct stm32_pcie *stm32_pcie) 126 + { 127 + int ret; 128 + 129 + ret = phy_init(stm32_pcie->phy); 130 + if (ret) 131 + return ret; 132 + 133 + ret = clk_prepare_enable(stm32_pcie->clk); 134 + if (ret) 135 + phy_exit(stm32_pcie->phy); 136 + 137 + return ret; 138 + } 139 + 140 + static void stm32_pcie_disable_resources(struct stm32_pcie *stm32_pcie) 141 + { 142 + clk_disable_unprepare(stm32_pcie->clk); 143 + 144 + phy_exit(stm32_pcie->phy); 145 + } 146 + 147 + static void stm32_pcie_perst_assert(struct dw_pcie *pci) 148 + { 149 + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 150 + struct dw_pcie_ep *ep = &stm32_pcie->pci.ep; 151 + struct device *dev = pci->dev; 152 + 153 + dev_dbg(dev, "PERST asserted by host\n"); 154 + 155 + pci_epc_deinit_notify(ep->epc); 156 + 157 + stm32_pcie_disable_resources(stm32_pcie); 158 + 159 + pm_runtime_put_sync(dev); 160 + } 161 + 162 + static void stm32_pcie_perst_deassert(struct dw_pcie *pci) 163 + { 164 + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 165 + struct device *dev = pci->dev; 166 + struct dw_pcie_ep *ep = &pci->ep; 167 + int ret; 168 + 169 + dev_dbg(dev, "PERST de-asserted by host\n"); 170 + 171 + ret = pm_runtime_resume_and_get(dev); 172 + if (ret < 0) { 173 + dev_err(dev, "Failed to resume runtime PM: %d\n", ret); 174 + return; 175 + } 176 + 177 + ret = stm32_pcie_enable_resources(stm32_pcie); 178 + if (ret) { 179 + dev_err(dev, "Failed to enable resources: %d\n", ret); 180 + goto err_pm_put_sync; 181 + } 182 + 183 + /* 184 + * Reprogram the configuration space registers here because the DBI 185 + * registers were reset by the PHY RCC during phy_init(). 186 + */ 187 + ret = dw_pcie_ep_init_registers(ep); 188 + if (ret) { 189 + dev_err(dev, "Failed to complete initialization: %d\n", ret); 190 + goto err_disable_resources; 191 + } 192 + 193 + pci_epc_init_notify(ep->epc); 194 + 195 + return; 196 + 197 + err_disable_resources: 198 + stm32_pcie_disable_resources(stm32_pcie); 199 + 200 + err_pm_put_sync: 201 + pm_runtime_put_sync(dev); 202 + } 203 + 204 + static irqreturn_t stm32_pcie_ep_perst_irq_thread(int irq, void *data) 205 + { 206 + struct stm32_pcie *stm32_pcie = data; 207 + struct dw_pcie *pci = &stm32_pcie->pci; 208 + u32 perst; 209 + 210 + perst = gpiod_get_value(stm32_pcie->perst_gpio); 211 + if (perst) 212 + stm32_pcie_perst_assert(pci); 213 + else 214 + stm32_pcie_perst_deassert(pci); 215 + 216 + irq_set_irq_type(gpiod_to_irq(stm32_pcie->perst_gpio), 217 + (perst ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW)); 218 + 219 + return IRQ_HANDLED; 220 + } 221 + 222 + static int stm32_add_pcie_ep(struct stm32_pcie *stm32_pcie, 223 + struct platform_device *pdev) 224 + { 225 + struct dw_pcie_ep *ep = &stm32_pcie->pci.ep; 226 + struct device *dev = &pdev->dev; 227 + int ret; 228 + 229 + ret = regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 230 + STM32MP25_PCIECR_TYPE_MASK, 231 + STM32MP25_PCIECR_EP); 232 + if (ret) 233 + return ret; 234 + 235 + reset_control_assert(stm32_pcie->rst); 236 + reset_control_deassert(stm32_pcie->rst); 237 + 238 + ep->ops = &stm32_pcie_ep_ops; 239 + 240 + ret = dw_pcie_ep_init(ep); 241 + if (ret) { 242 + dev_err(dev, "Failed to initialize ep: %d\n", ret); 243 + return ret; 244 + } 245 + 246 + ret = stm32_pcie_enable_resources(stm32_pcie); 247 + if (ret) { 248 + dev_err(dev, "Failed to enable resources: %d\n", ret); 249 + dw_pcie_ep_deinit(ep); 250 + return ret; 251 + } 252 + 253 + return 0; 254 + } 255 + 256 + static int stm32_pcie_probe(struct platform_device *pdev) 257 + { 258 + struct stm32_pcie *stm32_pcie; 259 + struct device *dev = &pdev->dev; 260 + int ret; 261 + 262 + stm32_pcie = devm_kzalloc(dev, sizeof(*stm32_pcie), GFP_KERNEL); 263 + if (!stm32_pcie) 264 + return -ENOMEM; 265 + 266 + stm32_pcie->pci.dev = dev; 267 + stm32_pcie->pci.ops = &dw_pcie_ops; 268 + 269 + stm32_pcie->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg"); 270 + if (IS_ERR(stm32_pcie->regmap)) 271 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->regmap), 272 + "No syscfg specified\n"); 273 + 274 + stm32_pcie->phy = devm_phy_get(dev, NULL); 275 + if (IS_ERR(stm32_pcie->phy)) 276 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->phy), 277 + "failed to get pcie-phy\n"); 278 + 279 + stm32_pcie->clk = devm_clk_get(dev, NULL); 280 + if (IS_ERR(stm32_pcie->clk)) 281 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->clk), 282 + "Failed to get PCIe clock source\n"); 283 + 284 + stm32_pcie->rst = devm_reset_control_get_exclusive(dev, NULL); 285 + if (IS_ERR(stm32_pcie->rst)) 286 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->rst), 287 + "Failed to get PCIe reset\n"); 288 + 289 + stm32_pcie->perst_gpio = devm_gpiod_get(dev, "reset", GPIOD_IN); 290 + if (IS_ERR(stm32_pcie->perst_gpio)) 291 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->perst_gpio), 292 + "Failed to get reset GPIO\n"); 293 + 294 + ret = phy_set_mode(stm32_pcie->phy, PHY_MODE_PCIE); 295 + if (ret) 296 + return ret; 297 + 298 + platform_set_drvdata(pdev, stm32_pcie); 299 + 300 + pm_runtime_get_noresume(dev); 301 + 302 + ret = devm_pm_runtime_enable(dev); 303 + if (ret < 0) { 304 + pm_runtime_put_noidle(&pdev->dev); 305 + return dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); 306 + } 307 + 308 + stm32_pcie->perst_irq = gpiod_to_irq(stm32_pcie->perst_gpio); 309 + 310 + /* Will be enabled in start_link when device is initialized. */ 311 + irq_set_status_flags(stm32_pcie->perst_irq, IRQ_NOAUTOEN); 312 + 313 + ret = devm_request_threaded_irq(dev, stm32_pcie->perst_irq, NULL, 314 + stm32_pcie_ep_perst_irq_thread, 315 + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, 316 + "perst_irq", stm32_pcie); 317 + if (ret) { 318 + pm_runtime_put_noidle(&pdev->dev); 319 + return dev_err_probe(dev, ret, "Failed to request PERST IRQ\n"); 320 + } 321 + 322 + ret = stm32_add_pcie_ep(stm32_pcie, pdev); 323 + if (ret) 324 + pm_runtime_put_noidle(&pdev->dev); 325 + 326 + return ret; 327 + } 328 + 329 + static void stm32_pcie_remove(struct platform_device *pdev) 330 + { 331 + struct stm32_pcie *stm32_pcie = platform_get_drvdata(pdev); 332 + struct dw_pcie *pci = &stm32_pcie->pci; 333 + struct dw_pcie_ep *ep = &pci->ep; 334 + 335 + dw_pcie_stop_link(pci); 336 + 337 + pci_epc_deinit_notify(ep->epc); 338 + dw_pcie_ep_deinit(ep); 339 + 340 + stm32_pcie_disable_resources(stm32_pcie); 341 + 342 + pm_runtime_put_sync(&pdev->dev); 343 + } 344 + 345 + static const struct of_device_id stm32_pcie_ep_of_match[] = { 346 + { .compatible = "st,stm32mp25-pcie-ep" }, 347 + {}, 348 + }; 349 + 350 + static struct platform_driver stm32_pcie_ep_driver = { 351 + .probe = stm32_pcie_probe, 352 + .remove = stm32_pcie_remove, 353 + .driver = { 354 + .name = "stm32-ep-pcie", 355 + .of_match_table = stm32_pcie_ep_of_match, 356 + }, 357 + }; 358 + 359 + module_platform_driver(stm32_pcie_ep_driver); 360 + 361 + MODULE_AUTHOR("Christian Bruel <christian.bruel@foss.st.com>"); 362 + MODULE_DESCRIPTION("STM32MP25 PCIe Endpoint Controller driver"); 363 + MODULE_LICENSE("GPL"); 364 + MODULE_DEVICE_TABLE(of, stm32_pcie_ep_of_match);
+358
drivers/pci/controller/dwc/pcie-stm32.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * STMicroelectronics STM32MP25 PCIe root complex driver. 4 + * 5 + * Copyright (C) 2025 STMicroelectronics 6 + * Author: Christian Bruel <christian.bruel@foss.st.com> 7 + */ 8 + 9 + #include <linux/clk.h> 10 + #include <linux/mfd/syscon.h> 11 + #include <linux/of_platform.h> 12 + #include <linux/phy/phy.h> 13 + #include <linux/pinctrl/consumer.h> 14 + #include <linux/platform_device.h> 15 + #include <linux/pm_runtime.h> 16 + #include <linux/pm_wakeirq.h> 17 + #include <linux/regmap.h> 18 + #include <linux/reset.h> 19 + #include "pcie-designware.h" 20 + #include "pcie-stm32.h" 21 + #include "../../pci.h" 22 + 23 + struct stm32_pcie { 24 + struct dw_pcie pci; 25 + struct regmap *regmap; 26 + struct reset_control *rst; 27 + struct phy *phy; 28 + struct clk *clk; 29 + struct gpio_desc *perst_gpio; 30 + struct gpio_desc *wake_gpio; 31 + }; 32 + 33 + static void stm32_pcie_deassert_perst(struct stm32_pcie *stm32_pcie) 34 + { 35 + if (stm32_pcie->perst_gpio) { 36 + msleep(PCIE_T_PVPERL_MS); 37 + gpiod_set_value(stm32_pcie->perst_gpio, 0); 38 + } 39 + 40 + msleep(PCIE_RESET_CONFIG_WAIT_MS); 41 + } 42 + 43 + static void stm32_pcie_assert_perst(struct stm32_pcie *stm32_pcie) 44 + { 45 + gpiod_set_value(stm32_pcie->perst_gpio, 1); 46 + } 47 + 48 + static int stm32_pcie_start_link(struct dw_pcie *pci) 49 + { 50 + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 51 + 52 + return regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 53 + STM32MP25_PCIECR_LTSSM_EN, 54 + STM32MP25_PCIECR_LTSSM_EN); 55 + } 56 + 57 + static void stm32_pcie_stop_link(struct dw_pcie *pci) 58 + { 59 + struct stm32_pcie *stm32_pcie = to_stm32_pcie(pci); 60 + 61 + regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 62 + STM32MP25_PCIECR_LTSSM_EN, 0); 63 + } 64 + 65 + static int stm32_pcie_suspend_noirq(struct device *dev) 66 + { 67 + struct stm32_pcie *stm32_pcie = dev_get_drvdata(dev); 68 + int ret; 69 + 70 + ret = dw_pcie_suspend_noirq(&stm32_pcie->pci); 71 + if (ret) 72 + return ret; 73 + 74 + stm32_pcie_assert_perst(stm32_pcie); 75 + 76 + clk_disable_unprepare(stm32_pcie->clk); 77 + 78 + if (!device_wakeup_path(dev)) 79 + phy_exit(stm32_pcie->phy); 80 + 81 + return pinctrl_pm_select_sleep_state(dev); 82 + } 83 + 84 + static int stm32_pcie_resume_noirq(struct device *dev) 85 + { 86 + struct stm32_pcie *stm32_pcie = dev_get_drvdata(dev); 87 + int ret; 88 + 89 + /* 90 + * The core clock is gated with CLKREQ# from the COMBOPHY REFCLK, 91 + * thus if no device is present, must deassert it with a GPIO from 92 + * pinctrl pinmux before accessing the DBI registers. 93 + */ 94 + ret = pinctrl_pm_select_init_state(dev); 95 + if (ret) { 96 + dev_err(dev, "Failed to activate pinctrl pm state: %d\n", ret); 97 + return ret; 98 + } 99 + 100 + if (!device_wakeup_path(dev)) { 101 + ret = phy_init(stm32_pcie->phy); 102 + if (ret) { 103 + pinctrl_pm_select_default_state(dev); 104 + return ret; 105 + } 106 + } 107 + 108 + ret = clk_prepare_enable(stm32_pcie->clk); 109 + if (ret) 110 + goto err_phy_exit; 111 + 112 + stm32_pcie_deassert_perst(stm32_pcie); 113 + 114 + ret = dw_pcie_resume_noirq(&stm32_pcie->pci); 115 + if (ret) 116 + goto err_disable_clk; 117 + 118 + pinctrl_pm_select_default_state(dev); 119 + 120 + return 0; 121 + 122 + err_disable_clk: 123 + stm32_pcie_assert_perst(stm32_pcie); 124 + clk_disable_unprepare(stm32_pcie->clk); 125 + 126 + err_phy_exit: 127 + phy_exit(stm32_pcie->phy); 128 + pinctrl_pm_select_default_state(dev); 129 + 130 + return ret; 131 + } 132 + 133 + static const struct dev_pm_ops stm32_pcie_pm_ops = { 134 + NOIRQ_SYSTEM_SLEEP_PM_OPS(stm32_pcie_suspend_noirq, 135 + stm32_pcie_resume_noirq) 136 + }; 137 + 138 + static const struct dw_pcie_host_ops stm32_pcie_host_ops = { 139 + }; 140 + 141 + static const struct dw_pcie_ops dw_pcie_ops = { 142 + .start_link = stm32_pcie_start_link, 143 + .stop_link = stm32_pcie_stop_link 144 + }; 145 + 146 + static int stm32_add_pcie_port(struct stm32_pcie *stm32_pcie) 147 + { 148 + struct device *dev = stm32_pcie->pci.dev; 149 + unsigned int wake_irq; 150 + int ret; 151 + 152 + ret = phy_set_mode(stm32_pcie->phy, PHY_MODE_PCIE); 153 + if (ret) 154 + return ret; 155 + 156 + ret = phy_init(stm32_pcie->phy); 157 + if (ret) 158 + return ret; 159 + 160 + ret = regmap_update_bits(stm32_pcie->regmap, SYSCFG_PCIECR, 161 + STM32MP25_PCIECR_TYPE_MASK, 162 + STM32MP25_PCIECR_RC); 163 + if (ret) 164 + goto err_phy_exit; 165 + 166 + stm32_pcie_deassert_perst(stm32_pcie); 167 + 168 + if (stm32_pcie->wake_gpio) { 169 + wake_irq = gpiod_to_irq(stm32_pcie->wake_gpio); 170 + ret = dev_pm_set_dedicated_wake_irq(dev, wake_irq); 171 + if (ret) { 172 + dev_err(dev, "Failed to enable wakeup irq %d\n", ret); 173 + goto err_assert_perst; 174 + } 175 + irq_set_irq_type(wake_irq, IRQ_TYPE_EDGE_FALLING); 176 + } 177 + 178 + return 0; 179 + 180 + err_assert_perst: 181 + stm32_pcie_assert_perst(stm32_pcie); 182 + 183 + err_phy_exit: 184 + phy_exit(stm32_pcie->phy); 185 + 186 + return ret; 187 + } 188 + 189 + static void stm32_remove_pcie_port(struct stm32_pcie *stm32_pcie) 190 + { 191 + dev_pm_clear_wake_irq(stm32_pcie->pci.dev); 192 + 193 + stm32_pcie_assert_perst(stm32_pcie); 194 + 195 + phy_exit(stm32_pcie->phy); 196 + } 197 + 198 + static int stm32_pcie_parse_port(struct stm32_pcie *stm32_pcie) 199 + { 200 + struct device *dev = stm32_pcie->pci.dev; 201 + struct device_node *root_port; 202 + 203 + root_port = of_get_next_available_child(dev->of_node, NULL); 204 + 205 + stm32_pcie->phy = devm_of_phy_get(dev, root_port, NULL); 206 + if (IS_ERR(stm32_pcie->phy)) { 207 + of_node_put(root_port); 208 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->phy), 209 + "Failed to get pcie-phy\n"); 210 + } 211 + 212 + stm32_pcie->perst_gpio = devm_fwnode_gpiod_get(dev, of_fwnode_handle(root_port), 213 + "reset", GPIOD_OUT_HIGH, NULL); 214 + if (IS_ERR(stm32_pcie->perst_gpio)) { 215 + if (PTR_ERR(stm32_pcie->perst_gpio) != -ENOENT) { 216 + of_node_put(root_port); 217 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->perst_gpio), 218 + "Failed to get reset GPIO\n"); 219 + } 220 + stm32_pcie->perst_gpio = NULL; 221 + } 222 + 223 + stm32_pcie->wake_gpio = devm_fwnode_gpiod_get(dev, of_fwnode_handle(root_port), 224 + "wake", GPIOD_IN, NULL); 225 + 226 + if (IS_ERR(stm32_pcie->wake_gpio)) { 227 + if (PTR_ERR(stm32_pcie->wake_gpio) != -ENOENT) { 228 + of_node_put(root_port); 229 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->wake_gpio), 230 + "Failed to get wake GPIO\n"); 231 + } 232 + stm32_pcie->wake_gpio = NULL; 233 + } 234 + 235 + of_node_put(root_port); 236 + 237 + return 0; 238 + } 239 + 240 + static int stm32_pcie_probe(struct platform_device *pdev) 241 + { 242 + struct stm32_pcie *stm32_pcie; 243 + struct device *dev = &pdev->dev; 244 + int ret; 245 + 246 + stm32_pcie = devm_kzalloc(dev, sizeof(*stm32_pcie), GFP_KERNEL); 247 + if (!stm32_pcie) 248 + return -ENOMEM; 249 + 250 + stm32_pcie->pci.dev = dev; 251 + stm32_pcie->pci.ops = &dw_pcie_ops; 252 + stm32_pcie->pci.pp.ops = &stm32_pcie_host_ops; 253 + 254 + stm32_pcie->regmap = syscon_regmap_lookup_by_compatible("st,stm32mp25-syscfg"); 255 + if (IS_ERR(stm32_pcie->regmap)) 256 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->regmap), 257 + "No syscfg specified\n"); 258 + 259 + stm32_pcie->clk = devm_clk_get(dev, NULL); 260 + if (IS_ERR(stm32_pcie->clk)) 261 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->clk), 262 + "Failed to get PCIe clock source\n"); 263 + 264 + stm32_pcie->rst = devm_reset_control_get_exclusive(dev, NULL); 265 + if (IS_ERR(stm32_pcie->rst)) 266 + return dev_err_probe(dev, PTR_ERR(stm32_pcie->rst), 267 + "Failed to get PCIe reset\n"); 268 + 269 + ret = stm32_pcie_parse_port(stm32_pcie); 270 + if (ret) 271 + return ret; 272 + 273 + platform_set_drvdata(pdev, stm32_pcie); 274 + 275 + ret = stm32_add_pcie_port(stm32_pcie); 276 + if (ret) 277 + return ret; 278 + 279 + reset_control_assert(stm32_pcie->rst); 280 + reset_control_deassert(stm32_pcie->rst); 281 + 282 + ret = clk_prepare_enable(stm32_pcie->clk); 283 + if (ret) { 284 + dev_err(dev, "Core clock enable failed %d\n", ret); 285 + goto err_remove_port; 286 + } 287 + 288 + ret = pm_runtime_set_active(dev); 289 + if (ret < 0) { 290 + dev_err_probe(dev, ret, "Failed to activate runtime PM\n"); 291 + goto err_disable_clk; 292 + } 293 + 294 + pm_runtime_no_callbacks(dev); 295 + 296 + ret = devm_pm_runtime_enable(dev); 297 + if (ret < 0) { 298 + dev_err_probe(dev, ret, "Failed to enable runtime PM\n"); 299 + goto err_disable_clk; 300 + } 301 + 302 + ret = dw_pcie_host_init(&stm32_pcie->pci.pp); 303 + if (ret) 304 + goto err_disable_clk; 305 + 306 + if (stm32_pcie->wake_gpio) 307 + device_init_wakeup(dev, true); 308 + 309 + return 0; 310 + 311 + err_disable_clk: 312 + clk_disable_unprepare(stm32_pcie->clk); 313 + 314 + err_remove_port: 315 + stm32_remove_pcie_port(stm32_pcie); 316 + 317 + return ret; 318 + } 319 + 320 + static void stm32_pcie_remove(struct platform_device *pdev) 321 + { 322 + struct stm32_pcie *stm32_pcie = platform_get_drvdata(pdev); 323 + struct dw_pcie_rp *pp = &stm32_pcie->pci.pp; 324 + 325 + if (stm32_pcie->wake_gpio) 326 + device_init_wakeup(&pdev->dev, false); 327 + 328 + dw_pcie_host_deinit(pp); 329 + 330 + clk_disable_unprepare(stm32_pcie->clk); 331 + 332 + stm32_remove_pcie_port(stm32_pcie); 333 + 334 + pm_runtime_put_noidle(&pdev->dev); 335 + } 336 + 337 + static const struct of_device_id stm32_pcie_of_match[] = { 338 + { .compatible = "st,stm32mp25-pcie-rc" }, 339 + {}, 340 + }; 341 + 342 + static struct platform_driver stm32_pcie_driver = { 343 + .probe = stm32_pcie_probe, 344 + .remove = stm32_pcie_remove, 345 + .driver = { 346 + .name = "stm32-pcie", 347 + .of_match_table = stm32_pcie_of_match, 348 + .pm = &stm32_pcie_pm_ops, 349 + .probe_type = PROBE_PREFER_ASYNCHRONOUS, 350 + }, 351 + }; 352 + 353 + module_platform_driver(stm32_pcie_driver); 354 + 355 + MODULE_AUTHOR("Christian Bruel <christian.bruel@foss.st.com>"); 356 + MODULE_DESCRIPTION("STM32MP25 PCIe Controller driver"); 357 + MODULE_LICENSE("GPL"); 358 + MODULE_DEVICE_TABLE(of, stm32_pcie_of_match);
+16
drivers/pci/controller/dwc/pcie-stm32.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * ST PCIe driver definitions for STM32-MP25 SoC 4 + * 5 + * Copyright (C) 2025 STMicroelectronics - All Rights Reserved 6 + * Author: Christian Bruel <christian.bruel@foss.st.com> 7 + */ 8 + 9 + #define to_stm32_pcie(x) dev_get_drvdata((x)->dev) 10 + 11 + #define STM32MP25_PCIECR_TYPE_MASK GENMASK(11, 8) 12 + #define STM32MP25_PCIECR_EP 0 13 + #define STM32MP25_PCIECR_LTSSM_EN BIT(2) 14 + #define STM32MP25_PCIECR_RC BIT(10) 15 + 16 + #define SYSCFG_PCIECR 0x6000
+13
drivers/pinctrl/core.c
··· 1656 1656 EXPORT_SYMBOL_GPL(pinctrl_pm_select_default_state); 1657 1657 1658 1658 /** 1659 + * pinctrl_pm_select_init_state() - select init pinctrl state for PM 1660 + * @dev: device to select init state for 1661 + */ 1662 + int pinctrl_pm_select_init_state(struct device *dev) 1663 + { 1664 + if (!dev->pins) 1665 + return 0; 1666 + 1667 + return pinctrl_select_bound_state(dev, dev->pins->init_state); 1668 + } 1669 + EXPORT_SYMBOL_GPL(pinctrl_pm_select_init_state); 1670 + 1671 + /** 1659 1672 * pinctrl_pm_select_sleep_state() - select sleep pinctrl state for PM 1660 1673 * @dev: device to select sleep state for 1661 1674 */
+10
include/linux/pinctrl/consumer.h
··· 48 48 49 49 #ifdef CONFIG_PM 50 50 int pinctrl_pm_select_default_state(struct device *dev); 51 + int pinctrl_pm_select_init_state(struct device *dev); 51 52 int pinctrl_pm_select_sleep_state(struct device *dev); 52 53 int pinctrl_pm_select_idle_state(struct device *dev); 53 54 #else 54 55 static inline int pinctrl_pm_select_default_state(struct device *dev) 56 + { 57 + return 0; 58 + } 59 + static inline int pinctrl_pm_select_init_state(struct device *dev) 55 60 { 56 61 return 0; 57 62 } ··· 144 139 } 145 140 146 141 static inline int pinctrl_pm_select_default_state(struct device *dev) 142 + { 143 + return 0; 144 + } 145 + 146 + static inline int pinctrl_pm_select_init_state(struct device *dev) 147 147 { 148 148 return 0; 149 149 }