mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 14:04:27 -04:00
Merge branch 'pci/controller/dwc-ultrarisc'
- Add 'core', 'dbi', and 'aux' clocks to DT binding and manage them in the driver (Jia Wang) - Use module_platform_driver() since this may be built as a module, though not removable because IRQs can't be safely disposed (Jia Wang) * pci/controller/dwc-ultrarisc: PCI: ultrarisc: Use module_platform_driver() PCI: ultrarisc: Get and enable DP1000 PCIe controller clocks dt-bindings: PCI: ultrarisc: Add required DP1000 PCIe clocks
This commit is contained in:
@@ -43,6 +43,18 @@ properties:
|
||||
- description: Legacy INTC interrupt
|
||||
- description: Legacy INTD interrupt
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: PCIe core clock
|
||||
- description: Data Bus Interface (DBI) clock
|
||||
- description: Auxiliary clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: dbi
|
||||
- const: aux
|
||||
|
||||
interrupt-names:
|
||||
items:
|
||||
- const: msi
|
||||
@@ -55,6 +67,8 @@ required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- clocks
|
||||
- clock-names
|
||||
- interrupts
|
||||
- interrupt-names
|
||||
|
||||
@@ -71,6 +85,8 @@ examples:
|
||||
reg = <0x0 0x21000000 0x0 0x01000000>,
|
||||
<0x0 0x4fff0000 0x0 0x00010000>;
|
||||
reg-names = "dbi", "config";
|
||||
clocks = <&clkc 9>, <&clkc 7>, <&clkc 10>;
|
||||
clock-names = "core", "dbi", "aux";
|
||||
ranges = <0x81000000 0x0 0x4fbf0000 0x0 0x4fbf0000 0x0 0x00400000>,
|
||||
<0x82000000 0x0 0x40000000 0x0 0x40000000 0x0 0x0fbf0000>,
|
||||
<0xc3000000 0x40 0x00000000 0x40 0x00000000 0xd 0x00000000>;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* Copyright (C) 2026 UltraRISC Technology (Shanghai) Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
@@ -23,6 +24,12 @@
|
||||
|
||||
#define ULTRARISC_PCIE_COMP_TIMEOUT_65_210MS 0x6
|
||||
|
||||
struct ultrarisc_pcie {
|
||||
struct dw_pcie pci;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
};
|
||||
|
||||
static struct pci_ops ultrarisc_pci_ops = {
|
||||
.map_bus = dw_pcie_own_conf_map_bus,
|
||||
.read = pci_generic_config_read32,
|
||||
@@ -98,17 +105,47 @@ static const struct dw_pcie_ops dw_pcie_ops = {
|
||||
.start_link = ultrarisc_pcie_start_link,
|
||||
};
|
||||
|
||||
static int ultrarisc_pcie_enable_clks(struct ultrarisc_pcie *ultra)
|
||||
{
|
||||
return clk_bulk_prepare_enable(ultra->num_clks, ultra->clks);
|
||||
}
|
||||
|
||||
static void ultrarisc_pcie_disable_clks(void *data)
|
||||
{
|
||||
struct ultrarisc_pcie *ultra = data;
|
||||
|
||||
clk_bulk_disable_unprepare(ultra->num_clks, ultra->clks);
|
||||
}
|
||||
|
||||
static int ultrarisc_pcie_init_clks(struct ultrarisc_pcie *ultra)
|
||||
{
|
||||
struct device *dev = ultra->pci.dev;
|
||||
int ret;
|
||||
|
||||
ultra->num_clks = devm_clk_bulk_get_all(dev, &ultra->clks);
|
||||
if (ultra->num_clks < 0)
|
||||
return dev_err_probe(dev, ultra->num_clks, "Failed to get clocks\n");
|
||||
|
||||
ret = ultrarisc_pcie_enable_clks(ultra);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "Failed to enable clocks\n");
|
||||
|
||||
return devm_add_action_or_reset(dev, ultrarisc_pcie_disable_clks, ultra);
|
||||
}
|
||||
|
||||
static int ultrarisc_pcie_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ultrarisc_pcie *ultra;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dw_pcie_rp *pp;
|
||||
struct dw_pcie *pci;
|
||||
int ret;
|
||||
|
||||
pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
|
||||
if (!pci)
|
||||
ultra = devm_kzalloc(dev, sizeof(*ultra), GFP_KERNEL);
|
||||
if (!ultra)
|
||||
return -ENOMEM;
|
||||
|
||||
pci = &ultra->pci;
|
||||
pci->dev = dev;
|
||||
pci->ops = &dw_pcie_ops;
|
||||
|
||||
@@ -117,7 +154,11 @@ static int ultrarisc_pcie_probe(struct platform_device *pdev)
|
||||
|
||||
pp = &pci->pp;
|
||||
|
||||
platform_set_drvdata(pdev, pci);
|
||||
platform_set_drvdata(pdev, ultra);
|
||||
|
||||
ret = ultrarisc_pcie_init_clks(ultra);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pp->num_vectors = MAX_MSI_IRQS;
|
||||
/* No L2/L3 Ready indication is available on this platform */
|
||||
@@ -135,16 +176,46 @@ static int ultrarisc_pcie_probe(struct platform_device *pdev)
|
||||
|
||||
static int ultrarisc_pcie_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct dw_pcie *pci = dev_get_drvdata(dev);
|
||||
struct ultrarisc_pcie *ultra = dev_get_drvdata(dev);
|
||||
struct dw_pcie *pci = &ultra->pci;
|
||||
int ret;
|
||||
|
||||
return dw_pcie_suspend_noirq(pci);
|
||||
/*
|
||||
* A failed resume leaves the DWC suspended and the clocks disabled.
|
||||
* A later suspend must not access the controller or disable them again.
|
||||
*/
|
||||
if (pci->suspended)
|
||||
return 0;
|
||||
|
||||
ret = dw_pcie_suspend_noirq(pci);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (pci->suspended)
|
||||
ultrarisc_pcie_disable_clks(ultra);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ultrarisc_pcie_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct dw_pcie *pci = dev_get_drvdata(dev);
|
||||
struct ultrarisc_pcie *ultra = dev_get_drvdata(dev);
|
||||
struct dw_pcie *pci = &ultra->pci;
|
||||
int ret;
|
||||
|
||||
return dw_pcie_resume_noirq(pci);
|
||||
if (pci->suspended) {
|
||||
ret = ultrarisc_pcie_enable_clks(ultra);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dw_pcie_resume_noirq(pci);
|
||||
if (ret) {
|
||||
ultrarisc_pcie_disable_clks(ultra);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops ultrarisc_pcie_pm_ops = {
|
||||
@@ -169,7 +240,7 @@ static struct platform_driver ultrarisc_pcie_driver = {
|
||||
},
|
||||
.probe = ultrarisc_pcie_probe,
|
||||
};
|
||||
builtin_platform_driver(ultrarisc_pcie_driver);
|
||||
module_platform_driver(ultrarisc_pcie_driver);
|
||||
|
||||
MODULE_DESCRIPTION("UltraRISC DP1000 DWC PCIe host controller");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
Reference in New Issue
Block a user