diff --git a/Documentation/devicetree/bindings/usb/renesas,upd720201-pci.yaml b/Documentation/devicetree/bindings/usb/renesas,upd720201-pci.yaml new file mode 100644 index 0000000000000..8b8be572c930a --- /dev/null +++ b/Documentation/devicetree/bindings/usb/renesas,upd720201-pci.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/usb/renesas,upd720201-pci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: UPD720201/UPD720202 USB 3.0 xHCI Host Controller (PCIe) + +maintainers: + - Neil Armstrong + +description: + UPD720201 USB 3.0 xHCI Host Controller via PCIe x1 Gen2 interface. + The UPD720202 supports up to two downstream ports, while UPD720201 + supports up to four downstream USB 3.0 rev1.0 ports. + +properties: + compatible: + const: pci1912,0014 + + reg: + maxItems: 1 + + avdd33-supply: + description: +3.3 V power supply for analog circuit + + vdd10-supply: + description: +1.05 V power supply + + vdd33-supply: + description: +3.3 V power supply + +required: + - compatible + - reg + - avdd33-supply + - vdd10-supply + - vdd33-supply + +allOf: + - $ref: usb-xhci.yaml + +additionalProperties: true + +examples: + - | + pcie@0 { + reg = <0x0 0x1000>; + ranges = <0x02000000 0x0 0x100000 0x10000000 0x0 0x0>; + #address-cells = <3>; + #size-cells = <2>; + device_type = "pci"; + + usb-controller@0 { + compatible = "pci1912,0014"; + reg = <0x0 0x0 0x0 0x0 0x0>; + avdd33-supply = <&avdd33_reg>; + vdd10-supply = <&vdd10_reg>; + vdd33-supply = <&vdd33_reg>; + }; + }; diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index d0aa031397fab..4bd36e133ca64 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -309,7 +309,7 @@ config PCIE_QCOM select CRC8 select PCIE_QCOM_COMMON select PCI_HOST_COMMON - select PCI_PWRCTRL_SLOT + select PCI_PWRCTRL_GENERIC help Say Y here to enable PCIe controller support on Qualcomm SoCs. The PCIe controller uses the DesignWare core plus Qualcomm-specific @@ -431,7 +431,7 @@ config PCIE_SPACEMIT_K1 depends on ARCH_SPACEMIT || COMPILE_TEST depends on HAS_IOMEM select PCIE_DW_HOST - select PCI_PWRCTRL_SLOT + select PCI_PWRCTRL_GENERIC default ARCH_SPACEMIT help Enables support for the DesignWare based PCIe controller in diff --git a/drivers/pci/pwrctrl/Kconfig b/drivers/pci/pwrctrl/Kconfig index cd3aa15bad009..ff67bec5b5001 100644 --- a/drivers/pci/pwrctrl/Kconfig +++ b/drivers/pci/pwrctrl/Kconfig @@ -11,17 +11,18 @@ config PCI_PWRCTRL_PWRSEQ select POWER_SEQUENCING select PCI_PWRCTRL -config PCI_PWRCTRL_SLOT - tristate "PCI Power Control driver for PCI slots" +config PCI_PWRCTRL_GENERIC + tristate "Generic PCI Power Control driver for PCI slots and endpoints" select POWER_SEQUENCING select PCI_PWRCTRL help - Say Y here to enable the PCI Power Control driver to control the power - state of PCI slots. + Say Y here to enable the generic PCI Power Control driver to control + the power state of PCI slots and endpoints. This is a generic driver that controls the power state of different - PCI slots. The voltage regulators powering the rails of the PCI slots - are expected to be defined in the devicetree node of the PCI bridge. + PCI slots and endpoints. The voltage regulators powering the rails + of the PCI slots or endpoints are expected to be defined in the + devicetree node of the PCI bridge. config PCI_PWRCTRL_TC9563 tristate "PCI Power Control driver for TC9563 PCIe switch" diff --git a/drivers/pci/pwrctrl/Makefile b/drivers/pci/pwrctrl/Makefile index 13b02282106c2..f6bb4fb9a410b 100644 --- a/drivers/pci/pwrctrl/Makefile +++ b/drivers/pci/pwrctrl/Makefile @@ -5,7 +5,7 @@ pci-pwrctrl-core-y := core.o obj-$(CONFIG_PCI_PWRCTRL_PWRSEQ) += pci-pwrctrl-pwrseq.o -obj-$(CONFIG_PCI_PWRCTRL_SLOT) += pci-pwrctrl-slot.o -pci-pwrctrl-slot-y := slot.o +obj-$(CONFIG_PCI_PWRCTRL_GENERIC) += pci-pwrctrl-generic.o +pci-pwrctrl-generic-y := generic.o obj-$(CONFIG_PCI_PWRCTRL_TC9563) += pci-pwrctrl-tc9563.o diff --git a/drivers/pci/pwrctrl/generic.c b/drivers/pci/pwrctrl/generic.c new file mode 100644 index 0000000000000..a48896118d5e3 --- /dev/null +++ b/drivers/pci/pwrctrl/generic.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024 Linaro Ltd. + * Author: Manivannan Sadhasivam + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct generic_pwrctrl { + struct pci_pwrctrl pwrctrl; + struct regulator_bulk_data *supplies; + int num_supplies; + struct clk *clk; + struct pwrseq_desc *pwrseq; +}; + +static int generic_pwrctrl_power_on(struct pci_pwrctrl *pwrctrl) +{ + struct generic_pwrctrl *generic = + container_of(pwrctrl, + struct generic_pwrctrl, pwrctrl); + int ret; + + if (generic->pwrseq) { + pwrseq_power_on(generic->pwrseq); + return 0; + } + + ret = regulator_bulk_enable(generic->num_supplies, generic->supplies); + if (ret < 0) { + dev_err(generic->pwrctrl.dev, "Failed to enable generic regulators\n"); + return ret; + } + + return clk_prepare_enable(generic->clk); +} + +static int generic_pwrctrl_power_off(struct pci_pwrctrl *pwrctrl) +{ + struct generic_pwrctrl *generic = + container_of(pwrctrl, + struct generic_pwrctrl, pwrctrl); + + if (generic->pwrseq) { + pwrseq_power_off(generic->pwrseq); + return 0; + } + + regulator_bulk_disable(generic->num_supplies, generic->supplies); + clk_disable_unprepare(generic->clk); + + return 0; +} + +static void devm_generic_pwrctrl_release(void *data) +{ + struct generic_pwrctrl *generic = data; + + generic_pwrctrl_power_off(&generic->pwrctrl); + regulator_bulk_free(generic->num_supplies, generic->supplies); +} + +static int generic_pwrctrl_probe(struct platform_device *pdev) +{ + struct generic_pwrctrl *generic; + struct device *dev = &pdev->dev; + int ret; + + generic = devm_kzalloc(dev, sizeof(*generic), GFP_KERNEL); + if (!generic) + return -ENOMEM; + + if (of_graph_is_present(dev_of_node(dev))) { + generic->pwrseq = devm_pwrseq_get(dev, "pcie"); + if (IS_ERR(generic->pwrseq)) + return dev_err_probe(dev, PTR_ERR(generic->pwrseq), + "Failed to get the power sequencer\n"); + + goto skip_resources; + } + + ret = of_regulator_bulk_get_all(dev, dev_of_node(dev), + &generic->supplies); + if (ret < 0) + return dev_err_probe(dev, ret, "Failed to get generic regulators\n"); + + generic->num_supplies = ret; + + generic->clk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(generic->clk)) + return dev_err_probe(dev, PTR_ERR(generic->clk), + "Failed to enable generic clock\n"); + +skip_resources: + generic->pwrctrl.power_on = generic_pwrctrl_power_on; + generic->pwrctrl.power_off = generic_pwrctrl_power_off; + + ret = devm_add_action_or_reset(dev, devm_generic_pwrctrl_release, generic); + if (ret) + return ret; + + pci_pwrctrl_init(&generic->pwrctrl, dev); + + ret = devm_pci_pwrctrl_device_set_ready(dev, &generic->pwrctrl); + if (ret) + return dev_err_probe(dev, ret, "Failed to register pwrctrl driver\n"); + + return 0; +} + +static const struct of_device_id generic_pwrctrl_of_match[] = { + { + .compatible = "pciclass,0604", + }, + /* Renesas UPD720201/UPD720202 USB 3.0 xHCI Host Controller */ + { + .compatible = "pci1912,0014", + }, + { } +}; +MODULE_DEVICE_TABLE(of, generic_pwrctrl_of_match); + +static struct platform_driver generic_pwrctrl_driver = { + .driver = { + .name = "pci-pwrctrl-generic", + .of_match_table = generic_pwrctrl_of_match, + }, + .probe = generic_pwrctrl_probe, +}; +module_platform_driver(generic_pwrctrl_driver); + +MODULE_AUTHOR("Manivannan Sadhasivam "); +MODULE_DESCRIPTION("Generic PCI Power Control driver for PCI Slots and Endpoints"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pci/pwrctrl/slot.c b/drivers/pci/pwrctrl/slot.c deleted file mode 100644 index 082af81efe254..0000000000000 --- a/drivers/pci/pwrctrl/slot.c +++ /dev/null @@ -1,140 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2024 Linaro Ltd. - * Author: Manivannan Sadhasivam - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct slot_pwrctrl { - struct pci_pwrctrl pwrctrl; - struct regulator_bulk_data *supplies; - int num_supplies; - struct clk *clk; - struct pwrseq_desc *pwrseq; -}; - -static int slot_pwrctrl_power_on(struct pci_pwrctrl *pwrctrl) -{ - struct slot_pwrctrl *slot = container_of(pwrctrl, - struct slot_pwrctrl, pwrctrl); - int ret; - - if (slot->pwrseq) { - pwrseq_power_on(slot->pwrseq); - return 0; - } - - ret = regulator_bulk_enable(slot->num_supplies, slot->supplies); - if (ret < 0) { - dev_err(slot->pwrctrl.dev, "Failed to enable slot regulators\n"); - return ret; - } - - return clk_prepare_enable(slot->clk); -} - -static int slot_pwrctrl_power_off(struct pci_pwrctrl *pwrctrl) -{ - struct slot_pwrctrl *slot = container_of(pwrctrl, - struct slot_pwrctrl, pwrctrl); - - if (slot->pwrseq) { - pwrseq_power_off(slot->pwrseq); - return 0; - } - - regulator_bulk_disable(slot->num_supplies, slot->supplies); - clk_disable_unprepare(slot->clk); - - return 0; -} - -static void devm_slot_pwrctrl_release(void *data) -{ - struct slot_pwrctrl *slot = data; - - slot_pwrctrl_power_off(&slot->pwrctrl); - regulator_bulk_free(slot->num_supplies, slot->supplies); -} - -static int slot_pwrctrl_probe(struct platform_device *pdev) -{ - struct slot_pwrctrl *slot; - struct device *dev = &pdev->dev; - int ret; - - slot = devm_kzalloc(dev, sizeof(*slot), GFP_KERNEL); - if (!slot) - return -ENOMEM; - - if (of_graph_is_present(dev_of_node(dev))) { - slot->pwrseq = devm_pwrseq_get(dev, "pcie"); - if (IS_ERR(slot->pwrseq)) - return dev_err_probe(dev, PTR_ERR(slot->pwrseq), - "Failed to get the power sequencer\n"); - - goto skip_resources; - } - - ret = of_regulator_bulk_get_all(dev, dev_of_node(dev), - &slot->supplies); - if (ret < 0) { - dev_err_probe(dev, ret, "Failed to get slot regulators\n"); - return ret; - } - - slot->num_supplies = ret; - - slot->clk = devm_clk_get_optional(dev, NULL); - if (IS_ERR(slot->clk)) { - return dev_err_probe(dev, PTR_ERR(slot->clk), - "Failed to enable slot clock\n"); - } - -skip_resources: - slot->pwrctrl.power_on = slot_pwrctrl_power_on; - slot->pwrctrl.power_off = slot_pwrctrl_power_off; - - ret = devm_add_action_or_reset(dev, devm_slot_pwrctrl_release, slot); - if (ret) - return ret; - - pci_pwrctrl_init(&slot->pwrctrl, dev); - - ret = devm_pci_pwrctrl_device_set_ready(dev, &slot->pwrctrl); - if (ret) - return dev_err_probe(dev, ret, "Failed to register pwrctrl driver\n"); - - return 0; -} - -static const struct of_device_id slot_pwrctrl_of_match[] = { - { - .compatible = "pciclass,0604", - }, - { } -}; -MODULE_DEVICE_TABLE(of, slot_pwrctrl_of_match); - -static struct platform_driver slot_pwrctrl_driver = { - .driver = { - .name = "pci-pwrctrl-slot", - .of_match_table = slot_pwrctrl_of_match, - }, - .probe = slot_pwrctrl_probe, -}; -module_platform_driver(slot_pwrctrl_driver); - -MODULE_AUTHOR("Manivannan Sadhasivam "); -MODULE_DESCRIPTION("Generic PCI Power Control driver for PCI Slots"); -MODULE_LICENSE("GPL");