Add support for DesignWare-based PCIe controller in SG2044 SoC.
Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
---
drivers/pci/controller/dwc/Kconfig | 10 +
drivers/pci/controller/dwc/Makefile | 1 +
drivers/pci/controller/dwc/pcie-dw-sophgo.c | 282 ++++++++++++++++++++
3 files changed, 293 insertions(+)
create mode 100644 drivers/pci/controller/dwc/pcie-dw-sophgo.c
diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index b6d6778b0698..202014acf260 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -341,6 +341,16 @@ config PCIE_ROCKCHIP_DW_EP
Enables support for the DesignWare PCIe controller in the
Rockchip SoC (except RK3399) to work in endpoint mode.
+config PCIE_SOPHGO_DW
+ bool "SOPHGO DesignWare PCIe controller"
+ depends on ARCH_SOPHGO || COMPILE_TEST
+ depends on PCI_MSI
+ depends on OF
+ select PCIE_DW_HOST
+ help
+ Enables support for the DesignWare PCIe controller in the
+ SOPHGO SoC.
+
config PCI_EXYNOS
tristate "Samsung Exynos PCIe controller"
depends on ARCH_EXYNOS || COMPILE_TEST
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index a8308d9ea986..193150056dd3 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_PCIE_QCOM_EP) += pcie-qcom-ep.o
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
obj-$(CONFIG_PCIE_ROCKCHIP_DW) += pcie-dw-rockchip.o
+obj-$(CONFIG_PCIE_SOPHGO_DW) += pcie-dw-sophgo.o
obj-$(CONFIG_PCIE_INTEL_GW) += pcie-intel-gw.o
obj-$(CONFIG_PCIE_KEEMBAY) += pcie-keembay.o
obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o
diff --git a/drivers/pci/controller/dwc/pcie-dw-sophgo.c b/drivers/pci/controller/dwc/pcie-dw-sophgo.c
new file mode 100644
index 000000000000..a4ca4f1e26e0
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-dw-sophgo.c
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Sophgo SoCs.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/property.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "pcie-designware.h"
+
+#define to_sophgo_pcie(x) dev_get_drvdata((x)->dev)
+
+#define PCIE_INT_SIGNAL 0xc48
+#define PCIE_INT_EN 0xca0
+
+#define PCIE_SIGNAL_INTX_SHIFT 5
+
+#define PCIE_INT_EN_INTX_SHIFT 1
+#define PCIE_INT_EN_INT_SII BIT(0)
+#define PCIE_INT_EN_INT_INTA BIT(1)
+#define PCIE_INT_EN_INT_INTB BIT(2)
+#define PCIE_INT_EN_INT_INTC BIT(3)
+#define PCIE_INT_EN_INT_INTD BIT(4)
+#define PCIE_INT_EN_INT_MSI BIT(5)
+
+struct sophgo_pcie {
+ struct dw_pcie pci;
+ void __iomem *app_base;
+ struct clk_bulk_data *clks;
+ unsigned int clk_cnt;
+ struct reset_control *rst;
+ struct irq_domain *irq_domain;
+};
+
+static int sophgo_pcie_readl_app(struct sophgo_pcie *sophgo, u32 reg)
+{
+ return readl_relaxed(sophgo->app_base + reg);
+}
+
+static void sophgo_pcie_writel_app(struct sophgo_pcie *sophgo, u32 val, u32 reg)
+{
+ writel_relaxed(val, sophgo->app_base + reg);
+}
+
+static void sophgo_pcie_intx_handler(struct irq_desc *desc)
+{
+ struct dw_pcie_rp *pp = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
+ unsigned long hwirq = PCIE_SIGNAL_INTX_SHIFT;
+ unsigned long reg;
+
+ chained_irq_enter(chip, desc);
+
+ reg = sophgo_pcie_readl_app(sophgo, PCIE_INT_SIGNAL);
+
+ for_each_set_bit_from(hwirq, ®, PCI_NUM_INTX + PCIE_SIGNAL_INTX_SHIFT)
+ generic_handle_domain_irq(sophgo->irq_domain,
+ hwirq - PCIE_SIGNAL_INTX_SHIFT);
+
+ chained_irq_exit(chip, desc);
+}
+
+static void sophgo_intx_mask(struct irq_data *d)
+{
+ struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
+ unsigned long flags;
+ u32 val;
+
+ raw_spin_lock_irqsave(&pp->lock, flags);
+
+ val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
+ val &= ~BIT(d->hwirq + PCIE_INT_EN_INTX_SHIFT);
+ sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);
+
+ raw_spin_unlock_irqrestore(&pp->lock, flags);
+};
+
+static void sophgo_intx_unmask(struct irq_data *d)
+{
+ struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
+ unsigned long flags;
+ u32 val;
+
+ raw_spin_lock_irqsave(&pp->lock, flags);
+
+ val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
+ val |= BIT(d->hwirq + PCIE_INT_EN_INTX_SHIFT);
+ sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);
+
+ raw_spin_unlock_irqrestore(&pp->lock, flags);
+};
+
+static void sophgo_intx_eoi(struct irq_data *d)
+{
+}
+
+static struct irq_chip sophgo_intx_irq_chip = {
+ .name = "INTx",
+ .irq_mask = sophgo_intx_mask,
+ .irq_unmask = sophgo_intx_unmask,
+ .irq_eoi = sophgo_intx_eoi,
+};
+
+static int sophgo_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &sophgo_intx_irq_chip, handle_fasteoi_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops intx_domain_ops = {
+ .map = sophgo_pcie_intx_map,
+};
+
+static int sophgo_pcie_init_irq_domain(struct dw_pcie_rp *pp)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
+ struct device *dev = sophgo->pci.dev;
+ struct fwnode_handle *intc;
+ int irq;
+
+ intc = device_get_named_child_node(dev, "interrupt-controller");
+ if (!intc) {
+ dev_err(dev, "missing child interrupt-controller node\n");
+ return -ENODEV;
+ }
+
+ irq = fwnode_irq_get(intc, 0);
+ if (irq < 0) {
+ dev_err(dev, "failed to get INTx irq number\n");
+ fwnode_handle_put(intc);
+ return irq;
+ }
+
+ sophgo->irq_domain = irq_domain_create_linear(intc, PCI_NUM_INTX,
+ &intx_domain_ops, sophgo);
+ fwnode_handle_put(intc);
+ if (!sophgo->irq_domain) {
+ dev_err(dev, "failed to get a INTx irq domain\n");
+ return -EINVAL;
+ }
+
+ return irq;
+}
+
+static void sophgo_pcie_msi_enable(struct dw_pcie_rp *pp)
+{
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
+ unsigned long flags;
+ u32 val;
+
+ raw_spin_lock_irqsave(&pp->lock, flags);
+
+ val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
+ val |= PCIE_INT_EN_INT_MSI;
+ sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);
+
+ raw_spin_unlock_irqrestore(&pp->lock, flags);
+}
+
+static int sophgo_pcie_host_init(struct dw_pcie_rp *pp)
+{
+ int irq;
+
+ irq = sophgo_pcie_init_irq_domain(pp);
+ if (irq < 0)
+ return irq;
+
+ irq_set_chained_handler_and_data(irq, sophgo_pcie_intx_handler,
+ pp);
+
+ sophgo_pcie_msi_enable(pp);
+
+ return 0;
+}
+
+static const struct dw_pcie_host_ops sophgo_pcie_host_ops = {
+ .init = sophgo_pcie_host_init,
+};
+
+static int sophgo_pcie_clk_init(struct sophgo_pcie *sophgo)
+{
+ struct device *dev = sophgo->pci.dev;
+ int ret;
+
+ ret = devm_clk_bulk_get_all_enabled(dev, &sophgo->clks);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to get clocks\n");
+
+ sophgo->clk_cnt = ret;
+
+ return 0;
+}
+
+static int sophgo_pcie_resource_get(struct platform_device *pdev,
+ struct sophgo_pcie *sophgo)
+{
+ sophgo->app_base = devm_platform_ioremap_resource_byname(pdev, "app");
+ if (IS_ERR(sophgo->app_base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sophgo->app_base),
+ "failed to map app registers\n");
+
+ return 0;
+}
+
+static int sophgo_pcie_configure_rc(struct sophgo_pcie *sophgo)
+{
+ struct dw_pcie_rp *pp;
+
+ pp = &sophgo->pci.pp;
+ pp->ops = &sophgo_pcie_host_ops;
+
+ return dw_pcie_host_init(pp);
+}
+
+static int sophgo_pcie_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sophgo_pcie *sophgo;
+ int ret;
+
+ sophgo = devm_kzalloc(dev, sizeof(*sophgo), GFP_KERNEL);
+ if (!sophgo)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, sophgo);
+
+ sophgo->pci.dev = dev;
+
+ ret = sophgo_pcie_resource_get(pdev, sophgo);
+ if (ret)
+ return ret;
+
+ ret = sophgo_pcie_clk_init(sophgo);
+ if (ret)
+ return ret;
+
+ return sophgo_pcie_configure_rc(sophgo);
+}
+
+static const struct of_device_id sophgo_pcie_of_match[] = {
+ { .compatible = "sophgo,sg2044-pcie" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sophgo_pcie_acpi_match);
+
+static const struct acpi_device_id sophgo_pcie_acpi_match[] = {
+ { "SOPHO000", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, sophgo_pcie_acpi_match);
+
+static struct platform_driver sophgo_pcie_driver = {
+ .driver = {
+ .name = "sophgo-dw-pcie",
+ .of_match_table = sophgo_pcie_of_match,
+ .acpi_match_table = sophgo_pcie_acpi_match,
+ .suppress_bind_attrs = true,
+ },
+ .probe = sophgo_pcie_probe,
+};
+builtin_platform_driver(sophgo_pcie_driver);
--
2.48.1
On Fri, Feb 21, 2025 at 09:37:56AM +0800, Inochi Amaoto wrote:
> Add support for DesignWare-based PCIe controller in SG2044 SoC.
> @@ -341,6 +341,16 @@ config PCIE_ROCKCHIP_DW_EP
> Enables support for the DesignWare PCIe controller in the
> Rockchip SoC (except RK3399) to work in endpoint mode.
>
> +config PCIE_SOPHGO_DW
> + bool "SOPHGO DesignWare PCIe controller"
What's the canonical styling of "SOPHGO"? I see "Sophgo" in the
subject line and in Chen Wang's SG2042 series. Pick the official
styling and use it consistently.
Reorder this so the menuconfig menu items remain alphabetically
sorted.
> + depends on ARCH_SOPHGO || COMPILE_TEST
> + depends on PCI_MSI
> + depends on OF
> + select PCIE_DW_HOST
> + help
> + Enables support for the DesignWare PCIe controller in the
> + SOPHGO SoC.
> +
> config PCI_EXYNOS
> tristate "Samsung Exynos PCIe controller"
> depends on ARCH_EXYNOS || COMPILE_TEST
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe host controller driver for Sophgo SoCs.
Looks too generic, since Chen Wang's series says Sophgo SG2042 SoC is
Cadence-based, so this driver apparently doesn't cover all Sophgo
SoCs.
> + *
Spurious blank line.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/property.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +#include "pcie-designware.h"
> +
> +#define to_sophgo_pcie(x) dev_get_drvdata((x)->dev)
> +
> +#define PCIE_INT_SIGNAL 0xc48
> +#define PCIE_INT_EN 0xca0
> +
> +#define PCIE_SIGNAL_INTX_SHIFT 5
> +#define PCIE_INT_EN_INTX_SHIFT 1
Define masks with GENMASK() and get rid of the _SHIFT #defines.
> +#define PCIE_INT_EN_INT_SII BIT(0)
> +#define PCIE_INT_EN_INT_INTA BIT(1)
> +#define PCIE_INT_EN_INT_INTB BIT(2)
> +#define PCIE_INT_EN_INT_INTC BIT(3)
> +#define PCIE_INT_EN_INT_INTD BIT(4)
These are unused, drop them.
> +#define PCIE_INT_EN_INT_MSI BIT(5)
> +
> +struct sophgo_pcie {
> + struct dw_pcie pci;
> + void __iomem *app_base;
> + struct clk_bulk_data *clks;
> + unsigned int clk_cnt;
> + struct reset_control *rst;
> + struct irq_domain *irq_domain;
Indent the member names to align vertically as most other drivers do.
> +};
> +
> +static int sophgo_pcie_readl_app(struct sophgo_pcie *sophgo, u32 reg)
> +{
> + return readl_relaxed(sophgo->app_base + reg);
> +}
> +
> +static void sophgo_pcie_writel_app(struct sophgo_pcie *sophgo, u32 val, u32 reg)
> +{
> + writel_relaxed(val, sophgo->app_base + reg);
> +}
> +
> +static void sophgo_pcie_intx_handler(struct irq_desc *desc)
> +{
> + struct dw_pcie_rp *pp = irq_desc_get_handler_data(desc);
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
> + unsigned long hwirq = PCIE_SIGNAL_INTX_SHIFT;
> + unsigned long reg;
> +
> + chained_irq_enter(chip, desc);
> +
> + reg = sophgo_pcie_readl_app(sophgo, PCIE_INT_SIGNAL);
> +
> + for_each_set_bit_from(hwirq, ®, PCI_NUM_INTX + PCIE_SIGNAL_INTX_SHIFT)
Use FIELD_GET() here and iterate through PCI_NUM_INTX. Then you don't
need for_each_set_bit_from() and shouldn't need PCIE_SIGNAL_INTX_SHIFT
here and below.
> + generic_handle_domain_irq(sophgo->irq_domain,
> + hwirq - PCIE_SIGNAL_INTX_SHIFT);
> +
> + chained_irq_exit(chip, desc);
> +}
> +
> +static void sophgo_intx_mask(struct irq_data *d)
> +{
> + struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
> + unsigned long flags;
> + u32 val;
> +
> + raw_spin_lock_irqsave(&pp->lock, flags);
> +
> + val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
> + val &= ~BIT(d->hwirq + PCIE_INT_EN_INTX_SHIFT);
FIELD_PREP().
> + sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);
> +
> + raw_spin_unlock_irqrestore(&pp->lock, flags);
> +};
> +
> +static void sophgo_intx_unmask(struct irq_data *d)
> +{
> + struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
> + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
> + unsigned long flags;
> + u32 val;
> +
> + raw_spin_lock_irqsave(&pp->lock, flags);
> +
> + val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
> + val |= BIT(d->hwirq + PCIE_INT_EN_INTX_SHIFT);
Ditto.
> + sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);
> +
> + raw_spin_unlock_irqrestore(&pp->lock, flags);
> +};
> +
> +static void sophgo_intx_eoi(struct irq_data *d)
> +{
> +}
> +
> +static struct irq_chip sophgo_intx_irq_chip = {
> + .name = "INTx",
> + .irq_mask = sophgo_intx_mask,
> + .irq_unmask = sophgo_intx_unmask,
> + .irq_eoi = sophgo_intx_eoi,
Name these ending with the irq_chip field names, e.g.,
sophgo_intx_irq_mask(), to make them easier to find with grep.
Bjorn
On Fri, Feb 21, 2025 at 05:49:58PM -0600, Bjorn Helgaas wrote:
> On Fri, Feb 21, 2025 at 09:37:56AM +0800, Inochi Amaoto wrote:
> > Add support for DesignWare-based PCIe controller in SG2044 SoC.
>
> > @@ -341,6 +341,16 @@ config PCIE_ROCKCHIP_DW_EP
> > Enables support for the DesignWare PCIe controller in the
> > Rockchip SoC (except RK3399) to work in endpoint mode.
> >
> > +config PCIE_SOPHGO_DW
> > + bool "SOPHGO DesignWare PCIe controller"
>
> What's the canonical styling of "SOPHGO"? I see "Sophgo" in the
> subject line and in Chen Wang's SG2042 series. Pick the official
> styling and use it consistently.
>
This is my mistake. It should be "Sophgo", I will change it.
> Reorder this so the menuconfig menu items remain alphabetically
> sorted.
>
I think this order is applied to the entry title in menuconfig,
and is not the config key? If so, I will change it.
> > + depends on ARCH_SOPHGO || COMPILE_TEST
> > + depends on PCI_MSI
> > + depends on OF
> > + select PCIE_DW_HOST
> > + help
> > + Enables support for the DesignWare PCIe controller in the
> > + SOPHGO SoC.
> > +
> > config PCI_EXYNOS
> > tristate "Samsung Exynos PCIe controller"
> > depends on ARCH_EXYNOS || COMPILE_TEST
>
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * PCIe host controller driver for Sophgo SoCs.
>
> Looks too generic, since Chen Wang's series says Sophgo SG2042 SoC is
> Cadence-based, so this driver apparently doesn't cover all Sophgo
> SoCs.
>
OK, I will change the description to point it only cover
the controller based on the DesignWare core.
> > + *
>
> Spurious blank line.
>
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/irqchip/chained_irq.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/module.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/property.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +#include <linux/reset.h>
> > +
> > +#include "pcie-designware.h"
> > +
> > +#define to_sophgo_pcie(x) dev_get_drvdata((x)->dev)
> > +
> > +#define PCIE_INT_SIGNAL 0xc48
> > +#define PCIE_INT_EN 0xca0
> > +
> > +#define PCIE_SIGNAL_INTX_SHIFT 5
> > +#define PCIE_INT_EN_INTX_SHIFT 1
>
> Define masks with GENMASK() and get rid of the _SHIFT #defines.
>
> > +#define PCIE_INT_EN_INT_SII BIT(0)
> > +#define PCIE_INT_EN_INT_INTA BIT(1)
> > +#define PCIE_INT_EN_INT_INTB BIT(2)
> > +#define PCIE_INT_EN_INT_INTC BIT(3)
> > +#define PCIE_INT_EN_INT_INTD BIT(4)
>
> These are unused, drop them.
>
> > +#define PCIE_INT_EN_INT_MSI BIT(5)
> > +
> > +struct sophgo_pcie {
> > + struct dw_pcie pci;
> > + void __iomem *app_base;
> > + struct clk_bulk_data *clks;
> > + unsigned int clk_cnt;
> > + struct reset_control *rst;
> > + struct irq_domain *irq_domain;
>
> Indent the member names to align vertically as most other drivers do.
>
> > +};
> > +
> > +static int sophgo_pcie_readl_app(struct sophgo_pcie *sophgo, u32 reg)
> > +{
> > + return readl_relaxed(sophgo->app_base + reg);
> > +}
> > +
> > +static void sophgo_pcie_writel_app(struct sophgo_pcie *sophgo, u32 val, u32 reg)
> > +{
> > + writel_relaxed(val, sophgo->app_base + reg);
> > +}
> > +
> > +static void sophgo_pcie_intx_handler(struct irq_desc *desc)
> > +{
> > + struct dw_pcie_rp *pp = irq_desc_get_handler_data(desc);
> > + struct irq_chip *chip = irq_desc_get_chip(desc);
> > + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
> > + unsigned long hwirq = PCIE_SIGNAL_INTX_SHIFT;
> > + unsigned long reg;
> > +
> > + chained_irq_enter(chip, desc);
> > +
> > + reg = sophgo_pcie_readl_app(sophgo, PCIE_INT_SIGNAL);
> > +
> > + for_each_set_bit_from(hwirq, ®, PCI_NUM_INTX + PCIE_SIGNAL_INTX_SHIFT)
>
> Use FIELD_GET() here and iterate through PCI_NUM_INTX. Then you don't
> need for_each_set_bit_from() and shouldn't need PCIE_SIGNAL_INTX_SHIFT
> here and below.
>
OK, I will change it
> > + generic_handle_domain_irq(sophgo->irq_domain,
> > + hwirq - PCIE_SIGNAL_INTX_SHIFT);
> > +
> > + chained_irq_exit(chip, desc);
> > +}
> > +
> > +static void sophgo_intx_mask(struct irq_data *d)
> > +{
> > + struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
> > + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
> > + unsigned long flags;
> > + u32 val;
> > +
> > + raw_spin_lock_irqsave(&pp->lock, flags);
> > +
> > + val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
> > + val &= ~BIT(d->hwirq + PCIE_INT_EN_INTX_SHIFT);
>
> FIELD_PREP().
>
> > + sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);
> > +
> > + raw_spin_unlock_irqrestore(&pp->lock, flags);
> > +};
> > +
> > +static void sophgo_intx_unmask(struct irq_data *d)
> > +{
> > + struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
> > + struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
> > + struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
> > + unsigned long flags;
> > + u32 val;
> > +
> > + raw_spin_lock_irqsave(&pp->lock, flags);
> > +
> > + val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
> > + val |= BIT(d->hwirq + PCIE_INT_EN_INTX_SHIFT);
>
> Ditto.
>
> > + sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);
> > +
> > + raw_spin_unlock_irqrestore(&pp->lock, flags);
> > +};
> > +
> > +static void sophgo_intx_eoi(struct irq_data *d)
> > +{
> > +}
> > +
> > +static struct irq_chip sophgo_intx_irq_chip = {
> > + .name = "INTx",
> > + .irq_mask = sophgo_intx_mask,
> > + .irq_unmask = sophgo_intx_unmask,
> > + .irq_eoi = sophgo_intx_eoi,
>
> Name these ending with the irq_chip field names, e.g.,
> sophgo_intx_irq_mask(), to make them easier to find with grep.
>
> Bjorn
Thanks, I will take all the comments and improve the driver.
Regards,
Inochi
On Sat, Feb 22, 2025 at 08:43:46AM +0800, Inochi Amaoto wrote: > On Fri, Feb 21, 2025 at 05:49:58PM -0600, Bjorn Helgaas wrote: > > On Fri, Feb 21, 2025 at 09:37:56AM +0800, Inochi Amaoto wrote: > > > Add support for DesignWare-based PCIe controller in SG2044 SoC. > > > > > @@ -341,6 +341,16 @@ config PCIE_ROCKCHIP_DW_EP > > > Enables support for the DesignWare PCIe controller in the > > > Rockchip SoC (except RK3399) to work in endpoint mode. > > > > > > +config PCIE_SOPHGO_DW > > > + bool "SOPHGO DesignWare PCIe controller" > > > > What's the canonical styling of "SOPHGO"? I see "Sophgo" in the > > subject line and in Chen Wang's SG2042 series. Pick the official > > styling and use it consistently. > > This is my mistake. It should be "Sophgo", I will change it. > > > Reorder this so the menuconfig menu items remain alphabetically > > sorted. > > I think this order is applied to the entry title in menuconfig, > and is not the config key? If so, I will change it. It's the title shown by menuconfig, i.e., "SOPHGO DesignWare PCIe controller" here.
On Mon, Feb 24, 2025 at 01:47:25PM -0600, Bjorn Helgaas wrote: > On Sat, Feb 22, 2025 at 08:43:46AM +0800, Inochi Amaoto wrote: > > On Fri, Feb 21, 2025 at 05:49:58PM -0600, Bjorn Helgaas wrote: > > > On Fri, Feb 21, 2025 at 09:37:56AM +0800, Inochi Amaoto wrote: > > > > Add support for DesignWare-based PCIe controller in SG2044 SoC. > > > > > > > @@ -341,6 +341,16 @@ config PCIE_ROCKCHIP_DW_EP > > > > Enables support for the DesignWare PCIe controller in the > > > > Rockchip SoC (except RK3399) to work in endpoint mode. > > > > > > > > +config PCIE_SOPHGO_DW > > > > + bool "SOPHGO DesignWare PCIe controller" > > > > > > What's the canonical styling of "SOPHGO"? I see "Sophgo" in the > > > subject line and in Chen Wang's SG2042 series. Pick the official > > > styling and use it consistently. > > > > This is my mistake. It should be "Sophgo", I will change it. > > > > > Reorder this so the menuconfig menu items remain alphabetically > > > sorted. > > > > I think this order is applied to the entry title in menuconfig, > > and is not the config key? If so, I will change it. > > It's the title shown by menuconfig, i.e., "SOPHGO DesignWare PCIe > controller" here. Thanks, I will reorder it. Regards, Inochi
On Fr, 2025-02-21 at 09:37 +0800, Inochi Amaoto wrote:
> Add support for DesignWare-based PCIe controller in SG2044 SoC.
>
> Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> ---
> drivers/pci/controller/dwc/Kconfig | 10 +
> drivers/pci/controller/dwc/Makefile | 1 +
> drivers/pci/controller/dwc/pcie-dw-sophgo.c | 282 ++++++++++++++++++++
> 3 files changed, 293 insertions(+)
> create mode 100644 drivers/pci/controller/dwc/pcie-dw-sophgo.c
>
[...]
> diff --git a/drivers/pci/controller/dwc/pcie-dw-sophgo.c b/drivers/pci/controller/dwc/pcie-dw-sophgo.c
> new file mode 100644
> index 000000000000..a4ca4f1e26e0
> --- /dev/null
> +++ b/drivers/pci/controller/dwc/pcie-dw-sophgo.c
> @@ -0,0 +1,282 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * PCIe host controller driver for Sophgo SoCs.
> + *
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/irqchip/chained_irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/property.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
Drop this ...
> +
> +#include "pcie-designware.h"
> +
> +#define to_sophgo_pcie(x) dev_get_drvdata((x)->dev)
> +
> +#define PCIE_INT_SIGNAL 0xc48
> +#define PCIE_INT_EN 0xca0
> +
> +#define PCIE_SIGNAL_INTX_SHIFT 5
> +
> +#define PCIE_INT_EN_INTX_SHIFT 1
> +#define PCIE_INT_EN_INT_SII BIT(0)
> +#define PCIE_INT_EN_INT_INTA BIT(1)
> +#define PCIE_INT_EN_INT_INTB BIT(2)
> +#define PCIE_INT_EN_INT_INTC BIT(3)
> +#define PCIE_INT_EN_INT_INTD BIT(4)
> +#define PCIE_INT_EN_INT_MSI BIT(5)
> +
> +struct sophgo_pcie {
> + struct dw_pcie pci;
> + void __iomem *app_base;
> + struct clk_bulk_data *clks;
> + unsigned int clk_cnt;
> + struct reset_control *rst;
... and this. It is unused.
regards
Philipp
On Fri, Feb 21, 2025 at 10:07:54AM +0100, Philipp Zabel wrote:
> On Fr, 2025-02-21 at 09:37 +0800, Inochi Amaoto wrote:
> > Add support for DesignWare-based PCIe controller in SG2044 SoC.
> >
> > Signed-off-by: Inochi Amaoto <inochiama@gmail.com>
> > ---
> > drivers/pci/controller/dwc/Kconfig | 10 +
> > drivers/pci/controller/dwc/Makefile | 1 +
> > drivers/pci/controller/dwc/pcie-dw-sophgo.c | 282 ++++++++++++++++++++
> > 3 files changed, 293 insertions(+)
> > create mode 100644 drivers/pci/controller/dwc/pcie-dw-sophgo.c
> >
> [...]
> > diff --git a/drivers/pci/controller/dwc/pcie-dw-sophgo.c b/drivers/pci/controller/dwc/pcie-dw-sophgo.c
> > new file mode 100644
> > index 000000000000..a4ca4f1e26e0
> > --- /dev/null
> > +++ b/drivers/pci/controller/dwc/pcie-dw-sophgo.c
> > @@ -0,0 +1,282 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * PCIe host controller driver for Sophgo SoCs.
> > + *
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/gpio/consumer.h>
> > +#include <linux/irqchip/chained_irq.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/module.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/property.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/regmap.h>
> > +#include <linux/reset.h>
>
> Drop this ...
>
> > +
> > +#include "pcie-designware.h"
> > +
> > +#define to_sophgo_pcie(x) dev_get_drvdata((x)->dev)
> > +
> > +#define PCIE_INT_SIGNAL 0xc48
> > +#define PCIE_INT_EN 0xca0
> > +
> > +#define PCIE_SIGNAL_INTX_SHIFT 5
> > +
> > +#define PCIE_INT_EN_INTX_SHIFT 1
> > +#define PCIE_INT_EN_INT_SII BIT(0)
> > +#define PCIE_INT_EN_INT_INTA BIT(1)
> > +#define PCIE_INT_EN_INT_INTB BIT(2)
> > +#define PCIE_INT_EN_INT_INTC BIT(3)
> > +#define PCIE_INT_EN_INT_INTD BIT(4)
> > +#define PCIE_INT_EN_INT_MSI BIT(5)
> > +
> > +struct sophgo_pcie {
> > + struct dw_pcie pci;
> > + void __iomem *app_base;
> > + struct clk_bulk_data *clks;
> > + unsigned int clk_cnt;
> > + struct reset_control *rst;
>
> ... and this. It is unused.
>
>
> regards
> Philipp
Thanks, I will remove this.
Regards,
Inochi
© 2016 - 2025 Red Hat, Inc.