2023-09-27 10:21:01

by Minda Chen

[permalink] [raw]
Subject: [PATCH v7 0/19] Refactoring Microchip PCIe driver and add StarFive PCIe

This patchset final purpose is add PCIe driver for StarFive JH7110 SoC.
JH7110 using PLDA XpressRICH PCIe IP. Microchip PolarFire Using the
same IP and have commit their codes, which are mixed with PLDA
controller codes and Microchip platform codes.

For re-use the PLDA controller codes, I request refactoring microchip
codes, move PLDA common codes to PLDA files.
Desigware and Cadence is good example for refactoring codes.

So first step is extract the PLDA common codes from microchip, and
refactoring the microchip codes.(patch1 - 16)
Then, add Starfive codes. (patch17 - 19)

This patchset is base on v6.6-rc3

patch1 is move PLDA XpressRICH PCIe host common properties dt-binding
docs from microchip,pcie-host.yaml
patch2 is move PolarFire codes to PLDA directory.
patch3 is move PLDA IP register macros to plda-pcie.h
patch4 is rename data structure in microchip codes.
patch5 is rename two setup functions in microchip codes, prepare to move
to common file.
patch6 is change the arguments of plda_pcie_setup_iomems()
patch7 is move the two setup functions to common file pcie-plda-host.c
patch8 is Add PLDA event interrupt codes and IRQ domain ops.
patch9 is rename the IRQ related functions, prepare to move to
pcie-plda-host.
patch10 - 14 is modify the event codes, preparing for support starfive
and microchip two platforms.
patch15 is move IRQ related functions to pcie-plda-host.c
patch16 is set plda_event_handler to static.
patch17 is add StarFive JH7110 PCIe dt-binding doc.
patch18 is add StarFive JH7110 Soc PCIe codes.
patch19 is Starfive dts config

previous version:
v1:https://patchwork.kernel.org/project/linux-pci/cover/[email protected]/
v2:https://patchwork.kernel.org/project/linux-pci/cover/[email protected]/
v3:https://patchwork.kernel.org/project/linux-pci/cover/[email protected]/
v4:https://patchwork.kernel.org/project/linux-pci/cover/[email protected]/
v5:https://patchwork.kernel.org/project/linux-pci/cover/[email protected]/
v6:https://patchwork.kernel.org/project/linux-pci/cover/[email protected]/

change:
v7:
patch8: fix the build warning.
patch18: Some format changes (Emil's comment)
patch19: change the pcie node sequences by alphabetical
delete the "interupt-parent" in pcie node.

v6:
v5 patch 4 split to patch 4 -6. New patches just contain one
function modification. It is more reguluar.
patch 7: Just move the two setup functions only
patch 8 : draw a graph of PLDA local register, make it easier to
review the codes.
v5 patch 7 split to patch 9- 14. Each patch just contain one
function modification. It is more regular.
patch 9: rename IRQ related functions.
patch 10 - 14 : modify the events codes, total five patch.
patch 15: move IRQ related functions to pcie-plda-host.c
patch 16: Add new patch 16.
patch 18- 19 using "linux,pci-domain" dts setting.

v5:
patch 9 -14:
- Some variables names changed (evt->event).
- plda_handle_event() using a unify callback function to get events
num.
- Add plda_event_ops data structure.
patch 18:
plda_event_ops changed which is related to patch 6- 8 changed.

v4:
patch 3:
Copy the interrupt events macros to pcie-plda-host.c
patch 13:
get_events() change in patch 7. Patch 8 is just move the codes.
other change:
All the functions in commit message add ().
v3:
patch 2- 16:
- splite refactoring patches to multiple patch.
- rename plda_pcie to plda_pcie_rp. Maybe other vendor will
upstream PLDA ep codes.
patch 17:
- Remove the redundant reference.
- move the offset value to codes in starfive,stg-syscon
- change reset-gpio to prest-gpio.
patch18:
- Add 100ms delay after preset for PCIe 6.0 spec.
- stg-syscon related modification.
patch19:
- Add dts configure.
v2:
patch1:
- squash dt-bindings patches to patch1
- add 'required' list.
- plda doc rename to plda,xpressrich-axi-common.yaml
patch2 - 16:
- squash the microchip modification patch.
patch17:
- remove the plda common required property.
patch18:
- Sync the hide rc bar ops with config read function.
- Revert the T_PVPERL to 100ms and add comments for the source.
- Replace the link check function by the standard link ops.
- Convert to new pm ops marcos.
- Some formats modification.
- pcie-plda-host modification merge to patch4.
other:
- remove the pcie-plda-plat.c
- remove the starfive dts patch first. for it depends on
stg clock and syscon setting.

Minda Chen (19):
dt-bindings: PCI: Add PLDA XpressRICH PCIe host common properties
PCI: microchip: Move pcie-microchip-host.c to plda directory
PCI: microchip: Move PLDA IP register macros to pcie-plda.h
PCI: microchip: Rename data structure
PCI: microchip: Rename two setup functions
PCI: microchip: Change the argument of plda_pcie_setup_iomems()
PCI: plda: Move the setup functions to pcie-plda-host.c
PCI: plda: Add event interrupt codes and IRQ domain ops
PCI: microchip: Rename interrupt related functions
PCI: microchip: Add num_events field to struct plda_pcie_rp
PCI: microchip: Add request_event_irq() callback function
PCI: microchip: Add INTx and MSI event num to struct plda_event
PCI: microchip: Add get_events() callback function
PCI: microchip: Add event IRQ domain ops to struct plda_event
PCI: microchip: Move IRQ functions to pcie-plda-host.c
PCI: plda: Set plda_event_handler() and event ops to static
dt-bindings: PCI: Add StarFive JH7110 PCIe controller
PCI: starfive: Add JH7110 PCIe controller
riscv: dts: starfive: add PCIe dts configuration for JH7110

.../bindings/pci/microchip,pcie-host.yaml | 55 +-
.../pci/plda,xpressrich3-axi-common.yaml | 75 ++
.../bindings/pci/starfive,jh7110-pcie.yaml | 120 ++++
MAINTAINERS | 19 +-
.../jh7110-starfive-visionfive-2.dtsi | 64 ++
arch/riscv/boot/dts/starfive/jh7110.dtsi | 86 +++
drivers/pci/controller/Kconfig | 9 +-
drivers/pci/controller/Makefile | 2 +-
drivers/pci/controller/plda/Kconfig | 30 +
drivers/pci/controller/plda/Makefile | 4 +
.../{ => plda}/pcie-microchip-host.c | 603 ++--------------
drivers/pci/controller/plda/pcie-plda-host.c | 659 ++++++++++++++++++
drivers/pci/controller/plda/pcie-plda.h | 266 +++++++
drivers/pci/controller/plda/pcie-starfive.c | 448 ++++++++++++
14 files changed, 1835 insertions(+), 605 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
create mode 100644 Documentation/devicetree/bindings/pci/starfive,jh7110-pcie.yaml
create mode 100644 drivers/pci/controller/plda/Kconfig
create mode 100644 drivers/pci/controller/plda/Makefile
rename drivers/pci/controller/{ => plda}/pcie-microchip-host.c (54%)
create mode 100644 drivers/pci/controller/plda/pcie-plda-host.c
create mode 100644 drivers/pci/controller/plda/pcie-plda.h
create mode 100644 drivers/pci/controller/plda/pcie-starfive.c


base-commit: 6465e260f48790807eef06b583b38ca9789b6072
--
2.17.1


2023-09-27 10:21:02

by Minda Chen

[permalink] [raw]
Subject: [PATCH v7 01/19] dt-bindings: PCI: Add PLDA XpressRICH PCIe host common properties

Add PLDA XpressRICH PCIe host common properties dt-binding doc.
Microchip PolarFire PCIe host using PLDA IP.
Move common properties from Microchip PolarFire PCIe host
to PLDA files.

Signed-off-by: Minda Chen <[email protected]>
Reviewed-by: Hal Feng <[email protected]>
Reviewed-by: Conor Dooley <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
.../bindings/pci/microchip,pcie-host.yaml | 55 +-------------
.../pci/plda,xpressrich3-axi-common.yaml | 75 +++++++++++++++++++
2 files changed, 76 insertions(+), 54 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml

diff --git a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
index f7a3c2636355..7c2d51221f65 100644
--- a/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
+++ b/Documentation/devicetree/bindings/pci/microchip,pcie-host.yaml
@@ -10,21 +10,13 @@ maintainers:
- Daire McNamara <[email protected]>

allOf:
- - $ref: /schemas/pci/pci-bus.yaml#
+ - $ref: plda,xpressrich3-axi-common.yaml#
- $ref: /schemas/interrupt-controller/msi-controller.yaml#

properties:
compatible:
const: microchip,pcie-host-1.0 # PolarFire

- reg:
- maxItems: 2
-
- reg-names:
- items:
- - const: cfg
- - const: apb
-
clocks:
description:
Fabric Interface Controllers, FICs, are the interface between the FPGA
@@ -52,18 +44,6 @@ properties:
items:
pattern: '^fic[0-3]$'

- interrupts:
- minItems: 1
- items:
- - description: PCIe host controller
- - description: builtin MSI controller
-
- interrupt-names:
- minItems: 1
- items:
- - const: pcie
- - const: msi
-
ranges:
maxItems: 1

@@ -71,39 +51,6 @@ properties:
minItems: 1
maxItems: 6

- msi-controller:
- description: Identifies the node as an MSI controller.
-
- msi-parent:
- description: MSI controller the device is capable of using.
-
- interrupt-controller:
- type: object
- properties:
- '#address-cells':
- const: 0
-
- '#interrupt-cells':
- const: 1
-
- interrupt-controller: true
-
- required:
- - '#address-cells'
- - '#interrupt-cells'
- - interrupt-controller
-
- additionalProperties: false
-
-required:
- - reg
- - reg-names
- - "#interrupt-cells"
- - interrupts
- - interrupt-map-mask
- - interrupt-map
- - msi-controller
-
unevaluatedProperties: false

examples:
diff --git a/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
new file mode 100644
index 000000000000..31bb17b11e58
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/plda,xpressrich3-axi-common.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/plda,xpressrich3-axi-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: PLDA XpressRICH PCIe host common properties
+
+maintainers:
+ - Daire McNamara <[email protected]>
+ - Kevin Xie <[email protected]>
+
+description:
+ Generic PLDA XpressRICH PCIe host common properties.
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+ reg:
+ maxItems: 2
+
+ reg-names:
+ items:
+ - const: cfg
+ - const: apb
+
+ interrupts:
+ minItems: 1
+ items:
+ - description: PCIe host controller
+ - description: builtin MSI controller
+
+ interrupt-names:
+ minItems: 1
+ items:
+ - const: pcie
+ - const: msi
+
+ msi-controller:
+ description: Identifies the node as an MSI controller.
+
+ msi-parent:
+ description: MSI controller the device is capable of using.
+
+ interrupt-controller:
+ type: object
+ properties:
+ '#address-cells':
+ const: 0
+
+ '#interrupt-cells':
+ const: 1
+
+ interrupt-controller: true
+
+ required:
+ - '#address-cells'
+ - '#interrupt-cells'
+ - interrupt-controller
+
+ additionalProperties: false
+
+required:
+ - reg
+ - reg-names
+ - interrupts
+ - msi-controller
+ - "#interrupt-cells"
+ - interrupt-map-mask
+ - interrupt-map
+
+additionalProperties: true
+
+...
--
2.17.1

2023-09-27 10:21:27

by Minda Chen

[permalink] [raw]
Subject: [PATCH v7 10/19] PCI: microchip: Add num_events field to struct plda_pcie_rp

Avoid using NUM_EVENTS macros in common codes.

Signed-off-by: Minda Chen <[email protected]>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 7 ++++---
drivers/pci/controller/plda/pcie-plda.h | 1 +
2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 81aac2d72a2f..d9dd63084e2b 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -648,7 +648,7 @@ static void plda_handle_event(struct irq_desc *desc)

events = mc_get_events(port);

- for_each_set_bit(bit, &events, NUM_EVENTS)
+ for_each_set_bit(bit, &events, port->num_events)
generic_handle_domain_irq(port->event_domain, bit);

chained_irq_exit(chip, desc);
@@ -811,7 +811,7 @@ static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
return -EINVAL;
}

- port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
+ port->event_domain = irq_domain_add_linear(pcie_intc_node, port->num_events,
&mc_event_domain_ops, port);
if (!port->event_domain) {
dev_err(dev, "failed to get event domain\n");
@@ -914,7 +914,7 @@ static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_r
if (irq < 0)
return -ENODEV;

- for (i = 0; i < NUM_EVENTS; i++) {
+ for (i = 0; i < port->num_events; i++) {
event_irq = irq_create_mapping(port->event_domain, i);
if (!event_irq) {
dev_err(dev, "failed to map hwirq %d\n", i);
@@ -1006,6 +1006,7 @@ static int mc_host_probe(struct platform_device *pdev)

bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
plda->bridge_addr = bridge_base_addr;
+ plda->num_events = NUM_EVENTS;

/* Allow enabling MSI by disabling MSI-X */
val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index 32a913d4101f..5b09ffed623c 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -150,6 +150,7 @@ struct plda_pcie_rp {
raw_spinlock_t lock;
struct plda_msi msi;
void __iomem *bridge_addr;
+ int num_events;
};

irqreturn_t plda_event_handler(int irq, void *dev_id);
--
2.17.1

2023-09-27 10:21:45

by Minda Chen

[permalink] [raw]
Subject: [PATCH v7 16/19] PCI: plda: Set plda_event_handler() and event ops to static

Set plda_event_handler() function and event ops
structure to static.

Signed-off-by: Minda Chen <[email protected]>
---
drivers/pci/controller/plda/pcie-plda-host.c | 4 ++--
drivers/pci/controller/plda/pcie-plda.h | 1 -
2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
index c73953bcd1f8..11cdda2f6e5f 100644
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -254,7 +254,7 @@ static const struct irq_domain_ops intx_domain_ops = {
.map = plda_pcie_intx_map,
};

-irqreturn_t plda_event_handler(int irq, void *dev_id)
+static irqreturn_t plda_event_handler(int irq, void *dev_id)
{
return IRQ_HANDLED;
}
@@ -362,7 +362,7 @@ static int plda_pcie_event_map(struct irq_domain *domain, unsigned int irq,
return 0;
}

-struct irq_domain_ops plda_evt_dom_ops = {
+static const struct irq_domain_ops plda_evt_dom_ops = {
.map = plda_pcie_event_map,
};

diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index e59369f23329..b7420598a326 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -163,7 +163,6 @@ struct plda_event {
int msi_event;
};

-irqreturn_t plda_event_handler(int irq, void *dev_id);
int plda_init_interrupts(struct platform_device *pdev,
struct plda_pcie_rp *port,
const struct plda_event *event);
--
2.17.1

2023-09-27 10:22:06

by Minda Chen

[permalink] [raw]
Subject: [PATCH v7 19/19] riscv: dts: starfive: add PCIe dts configuration for JH7110

Add PCIe dts configuraion for JH7110 SoC platform.

Signed-off-by: Minda Chen <[email protected]>
Reviewed-by: Hal Feng <[email protected]>
---
.../jh7110-starfive-visionfive-2.dtsi | 64 ++++++++++++++
arch/riscv/boot/dts/starfive/jh7110.dtsi | 86 +++++++++++++++++++
2 files changed, 150 insertions(+)

diff --git a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
index d79f94432b27..7c168246cf2e 100644
--- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
@@ -232,6 +232,22 @@
status = "okay";
};

+&pcie0 {
+ perst-gpios = <&sysgpio 26 GPIO_ACTIVE_LOW>;
+ phys = <&pciephy0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_pins>;
+ status = "okay";
+};
+
+&pcie1 {
+ perst-gpios = <&sysgpio 28 GPIO_ACTIVE_LOW>;
+ phys = <&pciephy1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_pins>;
+ status = "okay";
+};
+
&qspi {
#address-cells = <1>;
#size-cells = <0>;
@@ -402,6 +418,54 @@
};
};

+ pcie0_pins: pcie0-0 {
+ clkreq-pins {
+ pinmux = <GPIOMUX(27, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-down;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ wake-pins {
+ pinmux = <GPIOMUX(32, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-up;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
+ pcie1_pins: pcie1-0 {
+ clkreq-pins {
+ pinmux = <GPIOMUX(29, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-down;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+
+ wake-pins {
+ pinmux = <GPIOMUX(21, GPOUT_LOW,
+ GPOEN_DISABLE,
+ GPI_NONE)>;
+ bias-pull-up;
+ drive-strength = <2>;
+ input-enable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+
spi0_pins: spi0-0 {
mosi-pins {
pinmux = <GPIOMUX(52, GPOUT_SYS_SPI0_TXD,
diff --git a/arch/riscv/boot/dts/starfive/jh7110.dtsi b/arch/riscv/boot/dts/starfive/jh7110.dtsi
index e85464c328d0..1a1e97287c5e 100644
--- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
@@ -1045,5 +1045,91 @@
#reset-cells = <1>;
power-domains = <&pwrc JH7110_PD_VOUT>;
};
+
+ pcie0: pcie@940000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0x40000000 0x0 0x1000000>,
+ <0x0 0x2b000000 0x0 0x100000>;
+ reg-names = "cfg", "apb";
+ linux,pci-domain = <0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0x0 0x30000000 0x0 0x30000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x00000000 0x9 0x00000000 0x0 0x40000000>;
+ interrupts = <56>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc0 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc0 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc0 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc0 0x4>;
+ msi-controller;
+ device_type = "pci";
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
+ <&stgcrg JH7110_STGCLK_PCIE0_TL>,
+ <&stgcrg JH7110_STGCLK_PCIE0_AXI_MST0>,
+ <&stgcrg JH7110_STGCLK_PCIE0_APB>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg JH7110_STGRST_PCIE0_AXI_MST0>,
+ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV0>,
+ <&stgcrg JH7110_STGRST_PCIE0_AXI_SLV>,
+ <&stgcrg JH7110_STGRST_PCIE0_BRG>,
+ <&stgcrg JH7110_STGRST_PCIE0_CORE>,
+ <&stgcrg JH7110_STGRST_PCIE0_APB>;
+ reset-names = "mst0", "slv0", "slv", "brg",
+ "core", "apb";
+ status = "disabled";
+
+ pcie_intc0: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
+
+ pcie1: pcie@9c0000000 {
+ compatible = "starfive,jh7110-pcie";
+ reg = <0x9 0xc0000000 0x0 0x1000000>,
+ <0x0 0x2c000000 0x0 0x100000>;
+ reg-names = "cfg", "apb";
+ linux,pci-domain = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges = <0x82000000 0x0 0x38000000 0x0 0x38000000 0x0 0x08000000>,
+ <0xc3000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>;
+ interrupts = <57>;
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc1 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc1 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc1 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc1 0x4>;
+ msi-controller;
+ device_type = "pci";
+ starfive,stg-syscon = <&stg_syscon>;
+ bus-range = <0x0 0xff>;
+ clocks = <&syscrg JH7110_SYSCLK_NOC_BUS_STG_AXI>,
+ <&stgcrg JH7110_STGCLK_PCIE1_TL>,
+ <&stgcrg JH7110_STGCLK_PCIE1_AXI_MST0>,
+ <&stgcrg JH7110_STGCLK_PCIE1_APB>;
+ clock-names = "noc", "tl", "axi_mst0", "apb";
+ resets = <&stgcrg JH7110_STGRST_PCIE1_AXI_MST0>,
+ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV0>,
+ <&stgcrg JH7110_STGRST_PCIE1_AXI_SLV>,
+ <&stgcrg JH7110_STGRST_PCIE1_BRG>,
+ <&stgcrg JH7110_STGRST_PCIE1_CORE>,
+ <&stgcrg JH7110_STGRST_PCIE1_APB>;
+ reset-names = "mst0", "slv0", "slv", "brg",
+ "core", "apb";
+ status = "disabled";
+
+ pcie_intc1: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
+ };
};
};
--
2.17.1

2023-09-27 10:23:37

by Minda Chen

[permalink] [raw]
Subject: [PATCH v7 15/19] PCI: microchip: Move IRQ functions to pcie-plda-host.c

Move IRQ functions to pcie-plda-host.c.
Including MSI, INTx, event interrupts and IRQ
init functions.

Signed-off-by: Minda Chen <[email protected]>
---
.../pci/controller/plda/pcie-microchip-host.c | 364 -----------------
drivers/pci/controller/plda/pcie-plda-host.c | 365 ++++++++++++++++++
drivers/pci/controller/plda/pcie-plda.h | 3 +
3 files changed, 368 insertions(+), 364 deletions(-)

diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index 49e09d24eb8f..016915d42f73 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -317,240 +317,6 @@ static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam)
ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
}

-static void plda_handle_msi(struct irq_desc *desc)
-{
- struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
- struct device *dev = port->dev;
- struct plda_msi *msi = &port->msi;
- void __iomem *bridge_base_addr = port->bridge_addr;
- unsigned long status;
- u32 bit;
- int ret;
-
- chained_irq_enter(chip, desc);
-
- status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
- if (status & PM_MSI_INT_MSI_MASK) {
- writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL);
- status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
- for_each_set_bit(bit, &status, msi->num_vectors) {
- ret = generic_handle_domain_irq(msi->dev_domain, bit);
- if (ret)
- dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
- bit);
- }
- }
-
- chained_irq_exit(chip, desc);
-}
-
-static void plda_msi_bottom_irq_ack(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr = port->bridge_addr;
- u32 bitpos = data->hwirq;
-
- writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
-}
-
-static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- phys_addr_t addr = port->msi.vector_phy;
-
- msg->address_lo = lower_32_bits(addr);
- msg->address_hi = upper_32_bits(addr);
- msg->data = data->hwirq;
-
- dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
- (int)data->hwirq, msg->address_hi, msg->address_lo);
-}
-
-static int plda_msi_set_affinity(struct irq_data *irq_data,
- const struct cpumask *mask, bool force)
-{
- return -EINVAL;
-}
-
-static struct irq_chip plda_msi_bottom_irq_chip = {
- .name = "PLDA MSI",
- .irq_ack = plda_msi_bottom_irq_ack,
- .irq_compose_msi_msg = plda_compose_msi_msg,
- .irq_set_affinity = plda_msi_set_affinity,
-};
-
-static int plda_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
- unsigned int nr_irqs, void *args)
-{
- struct plda_pcie_rp *port = domain->host_data;
- struct plda_msi *msi = &port->msi;
- unsigned long bit;
-
- mutex_lock(&msi->lock);
- bit = find_first_zero_bit(msi->used, msi->num_vectors);
- if (bit >= msi->num_vectors) {
- mutex_unlock(&msi->lock);
- return -ENOSPC;
- }
-
- set_bit(bit, msi->used);
-
- irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
- domain->host_data, handle_edge_irq, NULL, NULL);
-
- mutex_unlock(&msi->lock);
-
- return 0;
-}
-
-static void plda_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
- unsigned int nr_irqs)
-{
- struct irq_data *d = irq_domain_get_irq_data(domain, virq);
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
- struct plda_msi *msi = &port->msi;
-
- mutex_lock(&msi->lock);
-
- if (test_bit(d->hwirq, msi->used))
- __clear_bit(d->hwirq, msi->used);
- else
- dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
-
- mutex_unlock(&msi->lock);
-}
-
-static const struct irq_domain_ops msi_domain_ops = {
- .alloc = plda_irq_msi_domain_alloc,
- .free = plda_irq_msi_domain_free,
-};
-
-static struct irq_chip plda_msi_irq_chip = {
- .name = "PLDA PCIe MSI",
- .irq_ack = irq_chip_ack_parent,
- .irq_mask = pci_msi_mask_irq,
- .irq_unmask = pci_msi_unmask_irq,
-};
-
-static struct msi_domain_info plda_msi_domain_info = {
- .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
- MSI_FLAG_PCI_MSIX),
- .chip = &plda_msi_irq_chip,
-};
-
-static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
-{
- struct device *dev = port->dev;
- struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
- struct plda_msi *msi = &port->msi;
-
- mutex_init(&port->msi.lock);
-
- msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
- &msi_domain_ops, port);
- if (!msi->dev_domain) {
- dev_err(dev, "failed to create IRQ domain\n");
- return -ENOMEM;
- }
-
- msi->msi_domain = pci_msi_create_irq_domain(fwnode, &plda_msi_domain_info,
- msi->dev_domain);
- if (!msi->msi_domain) {
- dev_err(dev, "failed to create MSI domain\n");
- irq_domain_remove(msi->dev_domain);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static void plda_handle_intx(struct irq_desc *desc)
-{
- struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
- struct device *dev = port->dev;
- void __iomem *bridge_base_addr = port->bridge_addr;
- unsigned long status;
- u32 bit;
- int ret;
-
- chained_irq_enter(chip, desc);
-
- status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
- if (status & PM_MSI_INT_INTX_MASK) {
- status &= PM_MSI_INT_INTX_MASK;
- status >>= PM_MSI_INT_INTX_SHIFT;
- for_each_set_bit(bit, &status, PCI_NUM_INTX) {
- ret = generic_handle_domain_irq(port->intx_domain, bit);
- if (ret)
- dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
- bit);
- }
- }
-
- chained_irq_exit(chip, desc);
-}
-
-static void plda_ack_intx_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr = port->bridge_addr;
- u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
-
- writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
-}
-
-static void plda_mask_intx_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr = port->bridge_addr;
- unsigned long flags;
- u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
- u32 val;
-
- raw_spin_lock_irqsave(&port->lock, flags);
- val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
- val &= ~mask;
- writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
- raw_spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static void plda_unmask_intx_irq(struct irq_data *data)
-{
- struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
- void __iomem *bridge_base_addr = port->bridge_addr;
- unsigned long flags;
- u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
- u32 val;
-
- raw_spin_lock_irqsave(&port->lock, flags);
- val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
- val |= mask;
- writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
- raw_spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static struct irq_chip plda_intx_irq_chip = {
- .name = "PLDA PCIe INTx",
- .irq_ack = plda_ack_intx_irq,
- .irq_mask = plda_mask_intx_irq,
- .irq_unmask = plda_unmask_intx_irq,
-};
-
-static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
- irq_set_chip_data(irq, domain->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops intx_domain_ops = {
- .map = plda_pcie_intx_map,
-};
-
static inline u32 reg_to_event(u32 reg, struct event_map field)
{
return (reg & field.reg_mask) ? BIT(field.event_bit) : 0;
@@ -637,23 +403,6 @@ static irqreturn_t mc_event_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}

-static void plda_handle_event(struct irq_desc *desc)
-{
- struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
- unsigned long events;
- u32 bit;
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- chained_irq_enter(chip, desc);
-
- events = port->event_ops->get_events(port);
-
- for_each_set_bit(bit, &events, port->num_events)
- generic_handle_domain_irq(port->event_domain, bit);
-
- chained_irq_exit(chip, desc);
-}
-
static void mc_ack_event_irq(struct irq_data *data)
{
struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
@@ -817,47 +566,6 @@ static const struct plda_event mc_event = {
.msi_event = EVENT_LOCAL_PM_MSI_INT_MSI,
};

-static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port,
- const struct irq_domain_ops *ops)
-{
- struct device *dev = port->dev;
- struct device_node *node = dev->of_node;
- struct device_node *pcie_intc_node;
-
- /* Setup INTx */
- pcie_intc_node = of_get_next_child(node, NULL);
- if (!pcie_intc_node) {
- dev_err(dev, "failed to find PCIe Intc node\n");
- return -EINVAL;
- }
-
- port->event_domain = irq_domain_add_linear(pcie_intc_node, port->num_events,
- ops, port);
-
- if (!port->event_domain) {
- dev_err(dev, "failed to get event domain\n");
- of_node_put(pcie_intc_node);
- return -ENOMEM;
- }
-
- irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
-
- port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
- &intx_domain_ops, port);
- if (!port->intx_domain) {
- dev_err(dev, "failed to get an INTx IRQ domain\n");
- of_node_put(pcie_intc_node);
- return -ENOMEM;
- }
-
- irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
-
- of_node_put(pcie_intc_node);
- raw_spin_lock_init(&port->lock);
-
- return plda_allocate_msi_domains(port);
-}
-
static inline void mc_clear_secs(struct mc_pcie *port)
{
void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
@@ -918,78 +626,6 @@ static void mc_disable_interrupts(struct mc_pcie *port)
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
}

-static int plda_init_interrupts(struct platform_device *pdev,
- struct plda_pcie_rp *port,
- const struct plda_event *event)
-{
- struct device *dev = &pdev->dev;
- int irq;
- int i, intx_irq, msi_irq, event_irq;
- int ret;
- const struct irq_domain_ops *irq_dom_ops;
-
- if (!event->event_ops || !event->event_ops->get_events) {
- dev_err(dev, "no get events ops\n");
- return -EINVAL;
- }
-
- irq_dom_ops = event->domain_ops ? event->domain_ops : &mc_event_domain_ops;
-
- ret = plda_pcie_init_irq_domains(port, irq_dom_ops);
- if (ret) {
- dev_err(dev, "failed creating IRQ domains\n");
- return ret;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- return -ENODEV;
-
- port->event_ops = event->event_ops;
-
- for (i = 0; i < port->num_events; i++) {
- event_irq = irq_create_mapping(port->event_domain, i);
- if (!event_irq) {
- dev_err(dev, "failed to map hwirq %d\n", i);
- return -ENXIO;
- }
-
- if (event->request_event_irq)
- ret = event->request_event_irq(port, event_irq, i);
- else
- ret = devm_request_irq(dev, event_irq, plda_event_handler,
- 0, NULL, port);
-
- if (ret) {
- dev_err(dev, "failed to request IRQ %d\n", event_irq);
- return ret;
- }
- }
-
- intx_irq = irq_create_mapping(port->event_domain,
- event->intx_event);
- if (!intx_irq) {
- dev_err(dev, "failed to map INTx interrupt\n");
- return -ENXIO;
- }
-
- /* Plug the INTx chained handler */
- irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
-
- msi_irq = irq_create_mapping(port->event_domain,
- event->msi_event);
- if (!msi_irq)
- return -ENXIO;
-
- /* Plug the MSI chained handler */
- irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
-
- /* Plug the main event chained handler */
- irq_set_chained_handler_and_data(irq, plda_handle_event, port);
-
- return 0;
-}
-
static int mc_platform_init(struct pci_config_window *cfg)
{
struct device *dev = cfg->parent;
diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
index 197eda731c71..c73953bcd1f8 100644
--- a/drivers/pci/controller/plda/pcie-plda-host.c
+++ b/drivers/pci/controller/plda/pcie-plda-host.c
@@ -20,6 +20,240 @@

#include "pcie-plda.h"

+static void plda_handle_msi(struct irq_desc *desc)
+{
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct device *dev = port->dev;
+ struct plda_msi *msi = &port->msi;
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ unsigned long status;
+ u32 bit;
+ int ret;
+
+ chained_irq_enter(chip, desc);
+
+ status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
+ if (status & PM_MSI_INT_MSI_MASK) {
+ writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL);
+ status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
+ for_each_set_bit(bit, &status, msi->num_vectors) {
+ ret = generic_handle_domain_irq(msi->dev_domain, bit);
+ if (ret)
+ dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
+ bit);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void plda_msi_bottom_irq_ack(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ u32 bitpos = data->hwirq;
+
+ writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
+}
+
+static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ phys_addr_t addr = port->msi.vector_phy;
+
+ msg->address_lo = lower_32_bits(addr);
+ msg->address_hi = upper_32_bits(addr);
+ msg->data = data->hwirq;
+
+ dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
+ (int)data->hwirq, msg->address_hi, msg->address_lo);
+}
+
+static int plda_msi_set_affinity(struct irq_data *irq_data,
+ const struct cpumask *mask, bool force)
+{
+ return -EINVAL;
+}
+
+static struct irq_chip plda_msi_bottom_irq_chip = {
+ .name = "PLDA MSI",
+ .irq_ack = plda_msi_bottom_irq_ack,
+ .irq_compose_msi_msg = plda_compose_msi_msg,
+ .irq_set_affinity = plda_msi_set_affinity,
+};
+
+static int plda_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs, void *args)
+{
+ struct plda_pcie_rp *port = domain->host_data;
+ struct plda_msi *msi = &port->msi;
+ unsigned long bit;
+
+ mutex_lock(&msi->lock);
+ bit = find_first_zero_bit(msi->used, msi->num_vectors);
+ if (bit >= msi->num_vectors) {
+ mutex_unlock(&msi->lock);
+ return -ENOSPC;
+ }
+
+ set_bit(bit, msi->used);
+
+ irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
+ domain->host_data, handle_edge_irq, NULL, NULL);
+
+ mutex_unlock(&msi->lock);
+
+ return 0;
+}
+
+static void plda_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq);
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
+ struct plda_msi *msi = &port->msi;
+
+ mutex_lock(&msi->lock);
+
+ if (test_bit(d->hwirq, msi->used))
+ __clear_bit(d->hwirq, msi->used);
+ else
+ dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
+
+ mutex_unlock(&msi->lock);
+}
+
+static const struct irq_domain_ops msi_domain_ops = {
+ .alloc = plda_irq_msi_domain_alloc,
+ .free = plda_irq_msi_domain_free,
+};
+
+static struct irq_chip plda_msi_irq_chip = {
+ .name = "PLDA PCIe MSI",
+ .irq_ack = irq_chip_ack_parent,
+ .irq_mask = pci_msi_mask_irq,
+ .irq_unmask = pci_msi_unmask_irq,
+};
+
+static struct msi_domain_info plda_msi_domain_info = {
+ .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+ MSI_FLAG_PCI_MSIX),
+ .chip = &plda_msi_irq_chip,
+};
+
+static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
+{
+ struct device *dev = port->dev;
+ struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
+ struct plda_msi *msi = &port->msi;
+
+ mutex_init(&port->msi.lock);
+
+ msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
+ &msi_domain_ops, port);
+ if (!msi->dev_domain) {
+ dev_err(dev, "failed to create IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ msi->msi_domain = pci_msi_create_irq_domain(fwnode, &plda_msi_domain_info,
+ msi->dev_domain);
+ if (!msi->msi_domain) {
+ dev_err(dev, "failed to create MSI domain\n");
+ irq_domain_remove(msi->dev_domain);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void plda_handle_intx(struct irq_desc *desc)
+{
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ struct device *dev = port->dev;
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ unsigned long status;
+ u32 bit;
+ int ret;
+
+ chained_irq_enter(chip, desc);
+
+ status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
+ if (status & PM_MSI_INT_INTX_MASK) {
+ status &= PM_MSI_INT_INTX_MASK;
+ status >>= PM_MSI_INT_INTX_SHIFT;
+ for_each_set_bit(bit, &status, PCI_NUM_INTX) {
+ ret = generic_handle_domain_irq(port->intx_domain, bit);
+ if (ret)
+ dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
+ bit);
+ }
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void plda_ack_intx_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
+
+ writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
+}
+
+static void plda_mask_intx_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ unsigned long flags;
+ u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
+ u32 val;
+
+ raw_spin_lock_irqsave(&port->lock, flags);
+ val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
+ val &= ~mask;
+ writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
+ raw_spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void plda_unmask_intx_irq(struct irq_data *data)
+{
+ struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
+ void __iomem *bridge_base_addr = port->bridge_addr;
+ unsigned long flags;
+ u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
+ u32 val;
+
+ raw_spin_lock_irqsave(&port->lock, flags);
+ val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
+ val |= mask;
+ writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
+ raw_spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static struct irq_chip plda_intx_irq_chip = {
+ .name = "PLDA PCIe INTx",
+ .irq_ack = plda_ack_intx_irq,
+ .irq_mask = plda_mask_intx_irq,
+ .irq_unmask = plda_unmask_intx_irq,
+};
+
+static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, domain->host_data);
+
+ return 0;
+}
+
+static const struct irq_domain_ops intx_domain_ops = {
+ .map = plda_pcie_intx_map,
+};
+
irqreturn_t plda_event_handler(int irq, void *dev_id)
{
return IRQ_HANDLED;
@@ -45,6 +279,23 @@ static u32 plda_get_events(struct plda_pcie_rp *port)
return events;
}

+static void plda_handle_event(struct irq_desc *desc)
+{
+ struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ u32 bit;
+ unsigned long events;
+
+ chained_irq_enter(chip, desc);
+
+ events = port->event_ops->get_events(port);
+
+ for_each_set_bit(bit, &events, port->num_events)
+ generic_handle_domain_irq(port->event_domain, bit);
+
+ chained_irq_exit(chip, desc);
+}
+
static u32 plda_hwirq_to_mask(int hwirq)
{
u32 mask;
@@ -119,6 +370,120 @@ struct plda_event_ops plda_event_ops = {
.get_events = plda_get_events,
};

+static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port,
+ const struct irq_domain_ops *ops)
+{
+ struct device *dev = port->dev;
+ struct device_node *node = dev->of_node;
+ struct device_node *pcie_intc_node;
+
+ /* Setup INTx */
+ pcie_intc_node = of_get_next_child(node, NULL);
+ if (!pcie_intc_node) {
+ dev_err(dev, "failed to find PCIe Intc node\n");
+ return -EINVAL;
+ }
+
+ port->event_domain = irq_domain_add_linear(pcie_intc_node, port->num_events,
+ ops, port);
+
+ if (!port->event_domain) {
+ dev_err(dev, "failed to get event domain\n");
+ of_node_put(pcie_intc_node);
+ return -ENOMEM;
+ }
+
+ irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
+
+ port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
+ &intx_domain_ops, port);
+ if (!port->intx_domain) {
+ dev_err(dev, "failed to get an INTx IRQ domain\n");
+ of_node_put(pcie_intc_node);
+ return -ENOMEM;
+ }
+
+ irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
+
+ of_node_put(pcie_intc_node);
+ raw_spin_lock_init(&port->lock);
+
+ return plda_allocate_msi_domains(port);
+}
+
+int plda_init_interrupts(struct platform_device *pdev,
+ struct plda_pcie_rp *port,
+ const struct plda_event *event)
+{
+ struct device *dev = &pdev->dev;
+ int irq;
+ int i, intx_irq, msi_irq, event_irq;
+ int ret;
+ const struct irq_domain_ops *irq_dom_ops;
+
+ if (!event->event_ops || !event->event_ops->get_events) {
+ dev_err(dev, "no get events ops\n");
+ return -EINVAL;
+ }
+
+ irq_dom_ops = event->domain_ops ? event->domain_ops : &plda_evt_dom_ops;
+
+ ret = plda_pcie_init_irq_domains(port, irq_dom_ops);
+ if (ret) {
+ dev_err(dev, "failed creating IRQ domains\n");
+ return ret;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENODEV;
+
+ port->event_ops = event->event_ops;
+
+ for (i = 0; i < port->num_events; i++) {
+ event_irq = irq_create_mapping(port->event_domain, i);
+ if (!event_irq) {
+ dev_err(dev, "failed to map hwirq %d\n", i);
+ return -ENXIO;
+ }
+
+ if (event->request_event_irq)
+ ret = event->request_event_irq(port, event_irq, i);
+ else
+ ret = devm_request_irq(dev, event_irq, plda_event_handler,
+ 0, NULL, port);
+
+ if (ret) {
+ dev_err(dev, "failed to request IRQ %d\n", event_irq);
+ return ret;
+ }
+ }
+
+ intx_irq = irq_create_mapping(port->event_domain,
+ event->intx_event);
+ if (!intx_irq) {
+ dev_err(dev, "failed to map INTx interrupt\n");
+ return -ENXIO;
+ }
+
+ /* Plug the INTx chained handler */
+ irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
+
+ msi_irq = irq_create_mapping(port->event_domain,
+ event->msi_event);
+ if (!msi_irq)
+ return -ENXIO;
+
+ /* Plug the MSI chained handler */
+ irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
+
+ /* Plug the main event chained handler */
+ irq_set_chained_handler_and_data(irq, plda_handle_event, port);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(plda_init_interrupts);
+
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
phys_addr_t axi_addr, phys_addr_t pci_addr,
size_t size)
diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index 122084a3318a..e59369f23329 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -164,6 +164,9 @@ struct plda_event {
};

irqreturn_t plda_event_handler(int irq, void *dev_id);
+int plda_init_interrupts(struct platform_device *pdev,
+ struct plda_pcie_rp *port,
+ const struct plda_event *event);
void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
phys_addr_t axi_addr, phys_addr_t pci_addr,
size_t size);
--
2.17.1

2023-09-27 10:44:16

by Minda Chen

[permalink] [raw]
Subject: [PATCH v7 12/19] PCI: microchip: Add INTx and MSI event num to struct plda_event

The INTx and MSI interrupt event num is different
in Microchip and StarFive platform.

Signed-off-by: Minda Chen <[email protected]>
---
drivers/pci/controller/plda/pcie-microchip-host.c | 6 ++++--
drivers/pci/controller/plda/pcie-plda.h | 2 ++
2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
index e3c7d5e66150..fb09b6c34e01 100644
--- a/drivers/pci/controller/plda/pcie-microchip-host.c
+++ b/drivers/pci/controller/plda/pcie-microchip-host.c
@@ -807,6 +807,8 @@ static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq,

static const struct plda_event mc_event = {
.request_event_irq = mc_request_event_irq,
+ .intx_event = EVENT_LOCAL_PM_MSI_INT_INTX,
+ .msi_event = EVENT_LOCAL_PM_MSI_INT_MSI,
};

static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
@@ -947,7 +949,7 @@ static int plda_init_interrupts(struct platform_device *pdev,
}

intx_irq = irq_create_mapping(port->event_domain,
- EVENT_LOCAL_PM_MSI_INT_INTX);
+ event->intx_event);
if (!intx_irq) {
dev_err(dev, "failed to map INTx interrupt\n");
return -ENXIO;
@@ -957,7 +959,7 @@ static int plda_init_interrupts(struct platform_device *pdev,
irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);

msi_irq = irq_create_mapping(port->event_domain,
- EVENT_LOCAL_PM_MSI_INT_MSI);
+ event->msi_event);
if (!msi_irq)
return -ENXIO;

diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
index 4e0712c9365e..af5e69718342 100644
--- a/drivers/pci/controller/plda/pcie-plda.h
+++ b/drivers/pci/controller/plda/pcie-plda.h
@@ -156,6 +156,8 @@ struct plda_pcie_rp {
struct plda_event {
int (*request_event_irq)(struct plda_pcie_rp *pcie,
int event_irq, int event);
+ int intx_event;
+ int msi_event;
};

irqreturn_t plda_event_handler(int irq, void *dev_id);
--
2.17.1

2023-10-09 10:59:22

by Minda Chen

[permalink] [raw]
Subject: Re: [PATCH v7 0/19] Refactoring Microchip PCIe driver and add StarFive PCIe



On 2023/9/27 18:07, Minda Chen wrote:
> This patchset final purpose is add PCIe driver for StarFive JH7110 SoC.
> JH7110 using PLDA XpressRICH PCIe IP. Microchip PolarFire Using the
> same IP and have commit their codes, which are mixed with PLDA
> controller codes and Microchip platform codes.
>
> For re-use the PLDA controller codes, I request refactoring microchip
> codes, move PLDA common codes to PLDA files.
> Desigware and Cadence is good example for refactoring codes.
>
> So first step is extract the PLDA common codes from microchip, and
> refactoring the microchip codes.(patch1 - 16)
> Then, add Starfive codes. (patch17 - 19)
>
> This patchset is base on v6.6-rc3
>
> patch1 is move PLDA XpressRICH PCIe host common properties dt-binding
> docs from microchip,pcie-host.yaml
> patch2 is move PolarFire codes to PLDA directory.
> patch3 is move PLDA IP register macros to plda-pcie.h
> patch4 is rename data structure in microchip codes.
> patch5 is rename two setup functions in microchip codes, prepare to move
> to common file.
> patch6 is change the arguments of plda_pcie_setup_iomems()
> patch7 is move the two setup functions to common file pcie-plda-host.c
> patch8 is Add PLDA event interrupt codes and IRQ domain ops.
> patch9 is rename the IRQ related functions, prepare to move to
> pcie-plda-host.
> patch10 - 14 is modify the event codes, preparing for support starfive
> and microchip two platforms.
> patch15 is move IRQ related functions to pcie-plda-host.c
> patch16 is set plda_event_handler to static.
> patch17 is add StarFive JH7110 PCIe dt-binding doc.
> patch18 is add StarFive JH7110 Soc PCIe codes.
> patch19 is Starfive dts config
>
Hi Conor and Daire
Have you ever test this patchset? I'm sure I am not change logic of the PolarFire PCIe driver,
But I can not test it.
Since this series patch is delegate to nobody and no response now. I don't know when this patch set can be accepted.
I still hope the refactoring patches can be accepted first.
(I know you want to add the function of inbound and outbound address translation, Hope this series patch do not influence your upstream plan)

2023-10-09 11:19:19

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH v7 0/19] Refactoring Microchip PCIe driver and add StarFive PCIe

On Mon, Oct 09, 2023 at 06:58:42PM +0800, Minda Chen wrote:
>
>
> On 2023/9/27 18:07, Minda Chen wrote:
> > This patchset final purpose is add PCIe driver for StarFive JH7110 SoC.
> > JH7110 using PLDA XpressRICH PCIe IP. Microchip PolarFire Using the
> > same IP and have commit their codes, which are mixed with PLDA
> > controller codes and Microchip platform codes.
> >
> > For re-use the PLDA controller codes, I request refactoring microchip
> > codes, move PLDA common codes to PLDA files.
> > Desigware and Cadence is good example for refactoring codes.
> >
> > So first step is extract the PLDA common codes from microchip, and
> > refactoring the microchip codes.(patch1 - 16)
> > Then, add Starfive codes. (patch17 - 19)
> >
> > This patchset is base on v6.6-rc3
> >
> > patch1 is move PLDA XpressRICH PCIe host common properties dt-binding
> > docs from microchip,pcie-host.yaml
> > patch2 is move PolarFire codes to PLDA directory.
> > patch3 is move PLDA IP register macros to plda-pcie.h
> > patch4 is rename data structure in microchip codes.
> > patch5 is rename two setup functions in microchip codes, prepare to move
> > to common file.
> > patch6 is change the arguments of plda_pcie_setup_iomems()
> > patch7 is move the two setup functions to common file pcie-plda-host.c
> > patch8 is Add PLDA event interrupt codes and IRQ domain ops.
> > patch9 is rename the IRQ related functions, prepare to move to
> > pcie-plda-host.
> > patch10 - 14 is modify the event codes, preparing for support starfive
> > and microchip two platforms.
> > patch15 is move IRQ related functions to pcie-plda-host.c
> > patch16 is set plda_event_handler to static.
> > patch17 is add StarFive JH7110 PCIe dt-binding doc.
> > patch18 is add StarFive JH7110 Soc PCIe codes.
> > patch19 is Starfive dts config
> >
> Hi Conor and Daire
> Have you ever test this patchset? I'm sure I am not change logic of the PolarFire PCIe driver,
> But I can not test it.
> Since this series patch is delegate to nobody and no response now. I don't know when this patch set can be accepted.

I'll try to look at this series again this week. I've been AFK a bit
with holidays etc recently, and been a bit delayed in general. I was
mostly happy with it before, and had left reviewed-bys on most of the
series I think.

> I still hope the refactoring patches can be accepted first

The last patchset Daire sent has been applied:
https://lore.kernel.org/all/[email protected]/

> (I know you want to add the function of inbound and outbound address translation, Hope this series patch do not influence your upstream plan)

I'd expect this series to go in before the inbound/outbound translation
one, since this is a lot closer to ready & is being resent more often.

Cheers,
Conor.


Attachments:
(No filename) (2.81 kB)
signature.asc (235.00 B)
Download all attachments

2023-10-09 13:41:58

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH v7 10/19] PCI: microchip: Add num_events field to struct plda_pcie_rp

On Wed, Sep 27, 2023 at 06:07:53PM +0800, Minda Chen wrote:
> Avoid using NUM_EVENTS macros in common codes.

This isn't common code though, this code is in the Microchip driver.
It may become common code later, but for now the commit message is
inaccurate. Otherwise, the change itself seems okay to me, so with an
accurate commit message
Reviewed-by: Conor Dooley <[email protected]>

Thanks,
Conor.

>
> Signed-off-by: Minda Chen <[email protected]>
> ---
> drivers/pci/controller/plda/pcie-microchip-host.c | 7 ++++---
> drivers/pci/controller/plda/pcie-plda.h | 1 +
> 2 files changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
> index 81aac2d72a2f..d9dd63084e2b 100644
> --- a/drivers/pci/controller/plda/pcie-microchip-host.c
> +++ b/drivers/pci/controller/plda/pcie-microchip-host.c
> @@ -648,7 +648,7 @@ static void plda_handle_event(struct irq_desc *desc)
>
> events = mc_get_events(port);
>
> - for_each_set_bit(bit, &events, NUM_EVENTS)
> + for_each_set_bit(bit, &events, port->num_events)
> generic_handle_domain_irq(port->event_domain, bit);
>
> chained_irq_exit(chip, desc);
> @@ -811,7 +811,7 @@ static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
> return -EINVAL;
> }
>
> - port->event_domain = irq_domain_add_linear(pcie_intc_node, NUM_EVENTS,
> + port->event_domain = irq_domain_add_linear(pcie_intc_node, port->num_events,
> &mc_event_domain_ops, port);
> if (!port->event_domain) {
> dev_err(dev, "failed to get event domain\n");
> @@ -914,7 +914,7 @@ static int plda_init_interrupts(struct platform_device *pdev, struct plda_pcie_r
> if (irq < 0)
> return -ENODEV;
>
> - for (i = 0; i < NUM_EVENTS; i++) {
> + for (i = 0; i < port->num_events; i++) {
> event_irq = irq_create_mapping(port->event_domain, i);
> if (!event_irq) {
> dev_err(dev, "failed to map hwirq %d\n", i);
> @@ -1006,6 +1006,7 @@ static int mc_host_probe(struct platform_device *pdev)
>
> bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
> plda->bridge_addr = bridge_base_addr;
> + plda->num_events = NUM_EVENTS;
>
> /* Allow enabling MSI by disabling MSI-X */
> val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
> diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
> index 32a913d4101f..5b09ffed623c 100644
> --- a/drivers/pci/controller/plda/pcie-plda.h
> +++ b/drivers/pci/controller/plda/pcie-plda.h
> @@ -150,6 +150,7 @@ struct plda_pcie_rp {
> raw_spinlock_t lock;
> struct plda_msi msi;
> void __iomem *bridge_addr;
> + int num_events;
> };
>
> irqreturn_t plda_event_handler(int irq, void *dev_id);
> --
> 2.17.1
>


Attachments:
(No filename) (2.81 kB)
signature.asc (235.00 B)
Download all attachments

2023-10-09 13:47:41

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH v7 12/19] PCI: microchip: Add INTx and MSI event num to struct plda_event

Hey,

On Wed, Sep 27, 2023 at 06:07:55PM +0800, Minda Chen wrote:
> The INTx and MSI interrupt event num is different
> in Microchip and StarFive platform.

BTW, please use the full 72 columns, not just 50, for your commit
messages.

Acked-by: Conor Dooley <[email protected]>

Thanks,
Conor.


>
> Signed-off-by: Minda Chen <[email protected]>
> ---
> drivers/pci/controller/plda/pcie-microchip-host.c | 6 ++++--
> drivers/pci/controller/plda/pcie-plda.h | 2 ++
> 2 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
> index e3c7d5e66150..fb09b6c34e01 100644
> --- a/drivers/pci/controller/plda/pcie-microchip-host.c
> +++ b/drivers/pci/controller/plda/pcie-microchip-host.c
> @@ -807,6 +807,8 @@ static int mc_request_event_irq(struct plda_pcie_rp *plda, int event_irq,
>
> static const struct plda_event mc_event = {
> .request_event_irq = mc_request_event_irq,
> + .intx_event = EVENT_LOCAL_PM_MSI_INT_INTX,
> + .msi_event = EVENT_LOCAL_PM_MSI_INT_MSI,
> };
>
> static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
> @@ -947,7 +949,7 @@ static int plda_init_interrupts(struct platform_device *pdev,
> }
>
> intx_irq = irq_create_mapping(port->event_domain,
> - EVENT_LOCAL_PM_MSI_INT_INTX);
> + event->intx_event);
> if (!intx_irq) {
> dev_err(dev, "failed to map INTx interrupt\n");
> return -ENXIO;
> @@ -957,7 +959,7 @@ static int plda_init_interrupts(struct platform_device *pdev,
> irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
>
> msi_irq = irq_create_mapping(port->event_domain,
> - EVENT_LOCAL_PM_MSI_INT_MSI);
> + event->msi_event);
> if (!msi_irq)
> return -ENXIO;
>
> diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
> index 4e0712c9365e..af5e69718342 100644
> --- a/drivers/pci/controller/plda/pcie-plda.h
> +++ b/drivers/pci/controller/plda/pcie-plda.h
> @@ -156,6 +156,8 @@ struct plda_pcie_rp {
> struct plda_event {
> int (*request_event_irq)(struct plda_pcie_rp *pcie,
> int event_irq, int event);
> + int intx_event;
> + int msi_event;
> };
>
> irqreturn_t plda_event_handler(int irq, void *dev_id);
> --
> 2.17.1
>


Attachments:
(No filename) (2.39 kB)
signature.asc (235.00 B)
Download all attachments

2023-10-09 14:16:15

by Conor Dooley

[permalink] [raw]
Subject: Re: [PATCH v7 15/19] PCI: microchip: Move IRQ functions to pcie-plda-host.c

Hey,

On Wed, Sep 27, 2023 at 06:07:58PM +0800, Minda Chen wrote:
> Move IRQ functions to pcie-plda-host.c.
> Including MSI, INTx, event interrupts and IRQ
> init functions.

Same comments about missing motivation for the changes in the commit
message. This just gives a summary of what's being done, without
mentioning the why.

> Signed-off-by: Minda Chen <[email protected]>

Otherwise:
Acked-by: Conor Dooley <[email protected]>

Thanks,
Conor.

> ---
> .../pci/controller/plda/pcie-microchip-host.c | 364 -----------------
> drivers/pci/controller/plda/pcie-plda-host.c | 365 ++++++++++++++++++
> drivers/pci/controller/plda/pcie-plda.h | 3 +
> 3 files changed, 368 insertions(+), 364 deletions(-)
>
> diff --git a/drivers/pci/controller/plda/pcie-microchip-host.c b/drivers/pci/controller/plda/pcie-microchip-host.c
> index 49e09d24eb8f..016915d42f73 100644
> --- a/drivers/pci/controller/plda/pcie-microchip-host.c
> +++ b/drivers/pci/controller/plda/pcie-microchip-host.c
> @@ -317,240 +317,6 @@ static void mc_pcie_enable_msi(struct mc_pcie *port, void __iomem *ecam)
> ecam + MC_MSI_CAP_CTRL_OFFSET + PCI_MSI_ADDRESS_HI);
> }
>
> -static void plda_handle_msi(struct irq_desc *desc)
> -{
> - struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
> - struct irq_chip *chip = irq_desc_get_chip(desc);
> - struct device *dev = port->dev;
> - struct plda_msi *msi = &port->msi;
> - void __iomem *bridge_base_addr = port->bridge_addr;
> - unsigned long status;
> - u32 bit;
> - int ret;
> -
> - chained_irq_enter(chip, desc);
> -
> - status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
> - if (status & PM_MSI_INT_MSI_MASK) {
> - writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL);
> - status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
> - for_each_set_bit(bit, &status, msi->num_vectors) {
> - ret = generic_handle_domain_irq(msi->dev_domain, bit);
> - if (ret)
> - dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
> - bit);
> - }
> - }
> -
> - chained_irq_exit(chip, desc);
> -}
> -
> -static void plda_msi_bottom_irq_ack(struct irq_data *data)
> -{
> - struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> - void __iomem *bridge_base_addr = port->bridge_addr;
> - u32 bitpos = data->hwirq;
> -
> - writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
> -}
> -
> -static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
> -{
> - struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> - phys_addr_t addr = port->msi.vector_phy;
> -
> - msg->address_lo = lower_32_bits(addr);
> - msg->address_hi = upper_32_bits(addr);
> - msg->data = data->hwirq;
> -
> - dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
> - (int)data->hwirq, msg->address_hi, msg->address_lo);
> -}
> -
> -static int plda_msi_set_affinity(struct irq_data *irq_data,
> - const struct cpumask *mask, bool force)
> -{
> - return -EINVAL;
> -}
> -
> -static struct irq_chip plda_msi_bottom_irq_chip = {
> - .name = "PLDA MSI",
> - .irq_ack = plda_msi_bottom_irq_ack,
> - .irq_compose_msi_msg = plda_compose_msi_msg,
> - .irq_set_affinity = plda_msi_set_affinity,
> -};
> -
> -static int plda_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
> - unsigned int nr_irqs, void *args)
> -{
> - struct plda_pcie_rp *port = domain->host_data;
> - struct plda_msi *msi = &port->msi;
> - unsigned long bit;
> -
> - mutex_lock(&msi->lock);
> - bit = find_first_zero_bit(msi->used, msi->num_vectors);
> - if (bit >= msi->num_vectors) {
> - mutex_unlock(&msi->lock);
> - return -ENOSPC;
> - }
> -
> - set_bit(bit, msi->used);
> -
> - irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
> - domain->host_data, handle_edge_irq, NULL, NULL);
> -
> - mutex_unlock(&msi->lock);
> -
> - return 0;
> -}
> -
> -static void plda_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
> - unsigned int nr_irqs)
> -{
> - struct irq_data *d = irq_domain_get_irq_data(domain, virq);
> - struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
> - struct plda_msi *msi = &port->msi;
> -
> - mutex_lock(&msi->lock);
> -
> - if (test_bit(d->hwirq, msi->used))
> - __clear_bit(d->hwirq, msi->used);
> - else
> - dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
> -
> - mutex_unlock(&msi->lock);
> -}
> -
> -static const struct irq_domain_ops msi_domain_ops = {
> - .alloc = plda_irq_msi_domain_alloc,
> - .free = plda_irq_msi_domain_free,
> -};
> -
> -static struct irq_chip plda_msi_irq_chip = {
> - .name = "PLDA PCIe MSI",
> - .irq_ack = irq_chip_ack_parent,
> - .irq_mask = pci_msi_mask_irq,
> - .irq_unmask = pci_msi_unmask_irq,
> -};
> -
> -static struct msi_domain_info plda_msi_domain_info = {
> - .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
> - MSI_FLAG_PCI_MSIX),
> - .chip = &plda_msi_irq_chip,
> -};
> -
> -static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
> -{
> - struct device *dev = port->dev;
> - struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
> - struct plda_msi *msi = &port->msi;
> -
> - mutex_init(&port->msi.lock);
> -
> - msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
> - &msi_domain_ops, port);
> - if (!msi->dev_domain) {
> - dev_err(dev, "failed to create IRQ domain\n");
> - return -ENOMEM;
> - }
> -
> - msi->msi_domain = pci_msi_create_irq_domain(fwnode, &plda_msi_domain_info,
> - msi->dev_domain);
> - if (!msi->msi_domain) {
> - dev_err(dev, "failed to create MSI domain\n");
> - irq_domain_remove(msi->dev_domain);
> - return -ENOMEM;
> - }
> -
> - return 0;
> -}
> -
> -static void plda_handle_intx(struct irq_desc *desc)
> -{
> - struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
> - struct irq_chip *chip = irq_desc_get_chip(desc);
> - struct device *dev = port->dev;
> - void __iomem *bridge_base_addr = port->bridge_addr;
> - unsigned long status;
> - u32 bit;
> - int ret;
> -
> - chained_irq_enter(chip, desc);
> -
> - status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
> - if (status & PM_MSI_INT_INTX_MASK) {
> - status &= PM_MSI_INT_INTX_MASK;
> - status >>= PM_MSI_INT_INTX_SHIFT;
> - for_each_set_bit(bit, &status, PCI_NUM_INTX) {
> - ret = generic_handle_domain_irq(port->intx_domain, bit);
> - if (ret)
> - dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
> - bit);
> - }
> - }
> -
> - chained_irq_exit(chip, desc);
> -}
> -
> -static void plda_ack_intx_irq(struct irq_data *data)
> -{
> - struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> - void __iomem *bridge_base_addr = port->bridge_addr;
> - u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
> -
> - writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
> -}
> -
> -static void plda_mask_intx_irq(struct irq_data *data)
> -{
> - struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> - void __iomem *bridge_base_addr = port->bridge_addr;
> - unsigned long flags;
> - u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
> - u32 val;
> -
> - raw_spin_lock_irqsave(&port->lock, flags);
> - val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
> - val &= ~mask;
> - writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
> - raw_spin_unlock_irqrestore(&port->lock, flags);
> -}
> -
> -static void plda_unmask_intx_irq(struct irq_data *data)
> -{
> - struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> - void __iomem *bridge_base_addr = port->bridge_addr;
> - unsigned long flags;
> - u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
> - u32 val;
> -
> - raw_spin_lock_irqsave(&port->lock, flags);
> - val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
> - val |= mask;
> - writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
> - raw_spin_unlock_irqrestore(&port->lock, flags);
> -}
> -
> -static struct irq_chip plda_intx_irq_chip = {
> - .name = "PLDA PCIe INTx",
> - .irq_ack = plda_ack_intx_irq,
> - .irq_mask = plda_mask_intx_irq,
> - .irq_unmask = plda_unmask_intx_irq,
> -};
> -
> -static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> - irq_hw_number_t hwirq)
> -{
> - irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
> - irq_set_chip_data(irq, domain->host_data);
> -
> - return 0;
> -}
> -
> -static const struct irq_domain_ops intx_domain_ops = {
> - .map = plda_pcie_intx_map,
> -};
> -
> static inline u32 reg_to_event(u32 reg, struct event_map field)
> {
> return (reg & field.reg_mask) ? BIT(field.event_bit) : 0;
> @@ -637,23 +403,6 @@ static irqreturn_t mc_event_handler(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> -static void plda_handle_event(struct irq_desc *desc)
> -{
> - struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
> - unsigned long events;
> - u32 bit;
> - struct irq_chip *chip = irq_desc_get_chip(desc);
> -
> - chained_irq_enter(chip, desc);
> -
> - events = port->event_ops->get_events(port);
> -
> - for_each_set_bit(bit, &events, port->num_events)
> - generic_handle_domain_irq(port->event_domain, bit);
> -
> - chained_irq_exit(chip, desc);
> -}
> -
> static void mc_ack_event_irq(struct irq_data *data)
> {
> struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> @@ -817,47 +566,6 @@ static const struct plda_event mc_event = {
> .msi_event = EVENT_LOCAL_PM_MSI_INT_MSI,
> };
>
> -static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port,
> - const struct irq_domain_ops *ops)
> -{
> - struct device *dev = port->dev;
> - struct device_node *node = dev->of_node;
> - struct device_node *pcie_intc_node;
> -
> - /* Setup INTx */
> - pcie_intc_node = of_get_next_child(node, NULL);
> - if (!pcie_intc_node) {
> - dev_err(dev, "failed to find PCIe Intc node\n");
> - return -EINVAL;
> - }
> -
> - port->event_domain = irq_domain_add_linear(pcie_intc_node, port->num_events,
> - ops, port);
> -
> - if (!port->event_domain) {
> - dev_err(dev, "failed to get event domain\n");
> - of_node_put(pcie_intc_node);
> - return -ENOMEM;
> - }
> -
> - irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
> -
> - port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> - &intx_domain_ops, port);
> - if (!port->intx_domain) {
> - dev_err(dev, "failed to get an INTx IRQ domain\n");
> - of_node_put(pcie_intc_node);
> - return -ENOMEM;
> - }
> -
> - irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
> -
> - of_node_put(pcie_intc_node);
> - raw_spin_lock_init(&port->lock);
> -
> - return plda_allocate_msi_domains(port);
> -}
> -
> static inline void mc_clear_secs(struct mc_pcie *port)
> {
> void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
> @@ -918,78 +626,6 @@ static void mc_disable_interrupts(struct mc_pcie *port)
> writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
> }
>
> -static int plda_init_interrupts(struct platform_device *pdev,
> - struct plda_pcie_rp *port,
> - const struct plda_event *event)
> -{
> - struct device *dev = &pdev->dev;
> - int irq;
> - int i, intx_irq, msi_irq, event_irq;
> - int ret;
> - const struct irq_domain_ops *irq_dom_ops;
> -
> - if (!event->event_ops || !event->event_ops->get_events) {
> - dev_err(dev, "no get events ops\n");
> - return -EINVAL;
> - }
> -
> - irq_dom_ops = event->domain_ops ? event->domain_ops : &mc_event_domain_ops;
> -
> - ret = plda_pcie_init_irq_domains(port, irq_dom_ops);
> - if (ret) {
> - dev_err(dev, "failed creating IRQ domains\n");
> - return ret;
> - }
> -
> - irq = platform_get_irq(pdev, 0);
> - if (irq < 0)
> - return -ENODEV;
> -
> - port->event_ops = event->event_ops;
> -
> - for (i = 0; i < port->num_events; i++) {
> - event_irq = irq_create_mapping(port->event_domain, i);
> - if (!event_irq) {
> - dev_err(dev, "failed to map hwirq %d\n", i);
> - return -ENXIO;
> - }
> -
> - if (event->request_event_irq)
> - ret = event->request_event_irq(port, event_irq, i);
> - else
> - ret = devm_request_irq(dev, event_irq, plda_event_handler,
> - 0, NULL, port);
> -
> - if (ret) {
> - dev_err(dev, "failed to request IRQ %d\n", event_irq);
> - return ret;
> - }
> - }
> -
> - intx_irq = irq_create_mapping(port->event_domain,
> - event->intx_event);
> - if (!intx_irq) {
> - dev_err(dev, "failed to map INTx interrupt\n");
> - return -ENXIO;
> - }
> -
> - /* Plug the INTx chained handler */
> - irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
> -
> - msi_irq = irq_create_mapping(port->event_domain,
> - event->msi_event);
> - if (!msi_irq)
> - return -ENXIO;
> -
> - /* Plug the MSI chained handler */
> - irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
> -
> - /* Plug the main event chained handler */
> - irq_set_chained_handler_and_data(irq, plda_handle_event, port);
> -
> - return 0;
> -}
> -
> static int mc_platform_init(struct pci_config_window *cfg)
> {
> struct device *dev = cfg->parent;
> diff --git a/drivers/pci/controller/plda/pcie-plda-host.c b/drivers/pci/controller/plda/pcie-plda-host.c
> index 197eda731c71..c73953bcd1f8 100644
> --- a/drivers/pci/controller/plda/pcie-plda-host.c
> +++ b/drivers/pci/controller/plda/pcie-plda-host.c
> @@ -20,6 +20,240 @@
>
> #include "pcie-plda.h"
>
> +static void plda_handle_msi(struct irq_desc *desc)
> +{
> + struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + struct device *dev = port->dev;
> + struct plda_msi *msi = &port->msi;
> + void __iomem *bridge_base_addr = port->bridge_addr;
> + unsigned long status;
> + u32 bit;
> + int ret;
> +
> + chained_irq_enter(chip, desc);
> +
> + status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
> + if (status & PM_MSI_INT_MSI_MASK) {
> + writel_relaxed(status & PM_MSI_INT_MSI_MASK, bridge_base_addr + ISTATUS_LOCAL);
> + status = readl_relaxed(bridge_base_addr + ISTATUS_MSI);
> + for_each_set_bit(bit, &status, msi->num_vectors) {
> + ret = generic_handle_domain_irq(msi->dev_domain, bit);
> + if (ret)
> + dev_err_ratelimited(dev, "bad MSI IRQ %d\n",
> + bit);
> + }
> + }
> +
> + chained_irq_exit(chip, desc);
> +}
> +
> +static void plda_msi_bottom_irq_ack(struct irq_data *data)
> +{
> + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> + void __iomem *bridge_base_addr = port->bridge_addr;
> + u32 bitpos = data->hwirq;
> +
> + writel_relaxed(BIT(bitpos), bridge_base_addr + ISTATUS_MSI);
> +}
> +
> +static void plda_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
> +{
> + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> + phys_addr_t addr = port->msi.vector_phy;
> +
> + msg->address_lo = lower_32_bits(addr);
> + msg->address_hi = upper_32_bits(addr);
> + msg->data = data->hwirq;
> +
> + dev_dbg(port->dev, "msi#%x address_hi %#x address_lo %#x\n",
> + (int)data->hwirq, msg->address_hi, msg->address_lo);
> +}
> +
> +static int plda_msi_set_affinity(struct irq_data *irq_data,
> + const struct cpumask *mask, bool force)
> +{
> + return -EINVAL;
> +}
> +
> +static struct irq_chip plda_msi_bottom_irq_chip = {
> + .name = "PLDA MSI",
> + .irq_ack = plda_msi_bottom_irq_ack,
> + .irq_compose_msi_msg = plda_compose_msi_msg,
> + .irq_set_affinity = plda_msi_set_affinity,
> +};
> +
> +static int plda_irq_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
> + unsigned int nr_irqs, void *args)
> +{
> + struct plda_pcie_rp *port = domain->host_data;
> + struct plda_msi *msi = &port->msi;
> + unsigned long bit;
> +
> + mutex_lock(&msi->lock);
> + bit = find_first_zero_bit(msi->used, msi->num_vectors);
> + if (bit >= msi->num_vectors) {
> + mutex_unlock(&msi->lock);
> + return -ENOSPC;
> + }
> +
> + set_bit(bit, msi->used);
> +
> + irq_domain_set_info(domain, virq, bit, &plda_msi_bottom_irq_chip,
> + domain->host_data, handle_edge_irq, NULL, NULL);
> +
> + mutex_unlock(&msi->lock);
> +
> + return 0;
> +}
> +
> +static void plda_irq_msi_domain_free(struct irq_domain *domain, unsigned int virq,
> + unsigned int nr_irqs)
> +{
> + struct irq_data *d = irq_domain_get_irq_data(domain, virq);
> + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(d);
> + struct plda_msi *msi = &port->msi;
> +
> + mutex_lock(&msi->lock);
> +
> + if (test_bit(d->hwirq, msi->used))
> + __clear_bit(d->hwirq, msi->used);
> + else
> + dev_err(port->dev, "trying to free unused MSI%lu\n", d->hwirq);
> +
> + mutex_unlock(&msi->lock);
> +}
> +
> +static const struct irq_domain_ops msi_domain_ops = {
> + .alloc = plda_irq_msi_domain_alloc,
> + .free = plda_irq_msi_domain_free,
> +};
> +
> +static struct irq_chip plda_msi_irq_chip = {
> + .name = "PLDA PCIe MSI",
> + .irq_ack = irq_chip_ack_parent,
> + .irq_mask = pci_msi_mask_irq,
> + .irq_unmask = pci_msi_unmask_irq,
> +};
> +
> +static struct msi_domain_info plda_msi_domain_info = {
> + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
> + MSI_FLAG_PCI_MSIX),
> + .chip = &plda_msi_irq_chip,
> +};
> +
> +static int plda_allocate_msi_domains(struct plda_pcie_rp *port)
> +{
> + struct device *dev = port->dev;
> + struct fwnode_handle *fwnode = of_node_to_fwnode(dev->of_node);
> + struct plda_msi *msi = &port->msi;
> +
> + mutex_init(&port->msi.lock);
> +
> + msi->dev_domain = irq_domain_add_linear(NULL, msi->num_vectors,
> + &msi_domain_ops, port);
> + if (!msi->dev_domain) {
> + dev_err(dev, "failed to create IRQ domain\n");
> + return -ENOMEM;
> + }
> +
> + msi->msi_domain = pci_msi_create_irq_domain(fwnode, &plda_msi_domain_info,
> + msi->dev_domain);
> + if (!msi->msi_domain) {
> + dev_err(dev, "failed to create MSI domain\n");
> + irq_domain_remove(msi->dev_domain);
> + return -ENOMEM;
> + }
> +
> + return 0;
> +}
> +
> +static void plda_handle_intx(struct irq_desc *desc)
> +{
> + struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + struct device *dev = port->dev;
> + void __iomem *bridge_base_addr = port->bridge_addr;
> + unsigned long status;
> + u32 bit;
> + int ret;
> +
> + chained_irq_enter(chip, desc);
> +
> + status = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
> + if (status & PM_MSI_INT_INTX_MASK) {
> + status &= PM_MSI_INT_INTX_MASK;
> + status >>= PM_MSI_INT_INTX_SHIFT;
> + for_each_set_bit(bit, &status, PCI_NUM_INTX) {
> + ret = generic_handle_domain_irq(port->intx_domain, bit);
> + if (ret)
> + dev_err_ratelimited(dev, "bad INTx IRQ %d\n",
> + bit);
> + }
> + }
> +
> + chained_irq_exit(chip, desc);
> +}
> +
> +static void plda_ack_intx_irq(struct irq_data *data)
> +{
> + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> + void __iomem *bridge_base_addr = port->bridge_addr;
> + u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
> +
> + writel_relaxed(mask, bridge_base_addr + ISTATUS_LOCAL);
> +}
> +
> +static void plda_mask_intx_irq(struct irq_data *data)
> +{
> + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> + void __iomem *bridge_base_addr = port->bridge_addr;
> + unsigned long flags;
> + u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
> + u32 val;
> +
> + raw_spin_lock_irqsave(&port->lock, flags);
> + val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
> + val &= ~mask;
> + writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
> + raw_spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static void plda_unmask_intx_irq(struct irq_data *data)
> +{
> + struct plda_pcie_rp *port = irq_data_get_irq_chip_data(data);
> + void __iomem *bridge_base_addr = port->bridge_addr;
> + unsigned long flags;
> + u32 mask = BIT(data->hwirq + PM_MSI_INT_INTX_SHIFT);
> + u32 val;
> +
> + raw_spin_lock_irqsave(&port->lock, flags);
> + val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
> + val |= mask;
> + writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
> + raw_spin_unlock_irqrestore(&port->lock, flags);
> +}
> +
> +static struct irq_chip plda_intx_irq_chip = {
> + .name = "PLDA PCIe INTx",
> + .irq_ack = plda_ack_intx_irq,
> + .irq_mask = plda_mask_intx_irq,
> + .irq_unmask = plda_unmask_intx_irq,
> +};
> +
> +static int plda_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
> + irq_hw_number_t hwirq)
> +{
> + irq_set_chip_and_handler(irq, &plda_intx_irq_chip, handle_level_irq);
> + irq_set_chip_data(irq, domain->host_data);
> +
> + return 0;
> +}
> +
> +static const struct irq_domain_ops intx_domain_ops = {
> + .map = plda_pcie_intx_map,
> +};
> +
> irqreturn_t plda_event_handler(int irq, void *dev_id)
> {
> return IRQ_HANDLED;
> @@ -45,6 +279,23 @@ static u32 plda_get_events(struct plda_pcie_rp *port)
> return events;
> }
>
> +static void plda_handle_event(struct irq_desc *desc)
> +{
> + struct plda_pcie_rp *port = irq_desc_get_handler_data(desc);
> + struct irq_chip *chip = irq_desc_get_chip(desc);
> + u32 bit;
> + unsigned long events;
> +
> + chained_irq_enter(chip, desc);
> +
> + events = port->event_ops->get_events(port);
> +
> + for_each_set_bit(bit, &events, port->num_events)
> + generic_handle_domain_irq(port->event_domain, bit);
> +
> + chained_irq_exit(chip, desc);
> +}
> +
> static u32 plda_hwirq_to_mask(int hwirq)
> {
> u32 mask;
> @@ -119,6 +370,120 @@ struct plda_event_ops plda_event_ops = {
> .get_events = plda_get_events,
> };
>
> +static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port,
> + const struct irq_domain_ops *ops)
> +{
> + struct device *dev = port->dev;
> + struct device_node *node = dev->of_node;
> + struct device_node *pcie_intc_node;
> +
> + /* Setup INTx */
> + pcie_intc_node = of_get_next_child(node, NULL);
> + if (!pcie_intc_node) {
> + dev_err(dev, "failed to find PCIe Intc node\n");
> + return -EINVAL;
> + }
> +
> + port->event_domain = irq_domain_add_linear(pcie_intc_node, port->num_events,
> + ops, port);
> +
> + if (!port->event_domain) {
> + dev_err(dev, "failed to get event domain\n");
> + of_node_put(pcie_intc_node);
> + return -ENOMEM;
> + }
> +
> + irq_domain_update_bus_token(port->event_domain, DOMAIN_BUS_NEXUS);
> +
> + port->intx_domain = irq_domain_add_linear(pcie_intc_node, PCI_NUM_INTX,
> + &intx_domain_ops, port);
> + if (!port->intx_domain) {
> + dev_err(dev, "failed to get an INTx IRQ domain\n");
> + of_node_put(pcie_intc_node);
> + return -ENOMEM;
> + }
> +
> + irq_domain_update_bus_token(port->intx_domain, DOMAIN_BUS_WIRED);
> +
> + of_node_put(pcie_intc_node);
> + raw_spin_lock_init(&port->lock);
> +
> + return plda_allocate_msi_domains(port);
> +}
> +
> +int plda_init_interrupts(struct platform_device *pdev,
> + struct plda_pcie_rp *port,
> + const struct plda_event *event)
> +{
> + struct device *dev = &pdev->dev;
> + int irq;
> + int i, intx_irq, msi_irq, event_irq;
> + int ret;
> + const struct irq_domain_ops *irq_dom_ops;
> +
> + if (!event->event_ops || !event->event_ops->get_events) {
> + dev_err(dev, "no get events ops\n");
> + return -EINVAL;
> + }
> +
> + irq_dom_ops = event->domain_ops ? event->domain_ops : &plda_evt_dom_ops;
> +
> + ret = plda_pcie_init_irq_domains(port, irq_dom_ops);
> + if (ret) {
> + dev_err(dev, "failed creating IRQ domains\n");
> + return ret;
> + }
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return -ENODEV;
> +
> + port->event_ops = event->event_ops;
> +
> + for (i = 0; i < port->num_events; i++) {
> + event_irq = irq_create_mapping(port->event_domain, i);
> + if (!event_irq) {
> + dev_err(dev, "failed to map hwirq %d\n", i);
> + return -ENXIO;
> + }
> +
> + if (event->request_event_irq)
> + ret = event->request_event_irq(port, event_irq, i);
> + else
> + ret = devm_request_irq(dev, event_irq, plda_event_handler,
> + 0, NULL, port);
> +
> + if (ret) {
> + dev_err(dev, "failed to request IRQ %d\n", event_irq);
> + return ret;
> + }
> + }
> +
> + intx_irq = irq_create_mapping(port->event_domain,
> + event->intx_event);
> + if (!intx_irq) {
> + dev_err(dev, "failed to map INTx interrupt\n");
> + return -ENXIO;
> + }
> +
> + /* Plug the INTx chained handler */
> + irq_set_chained_handler_and_data(intx_irq, plda_handle_intx, port);
> +
> + msi_irq = irq_create_mapping(port->event_domain,
> + event->msi_event);
> + if (!msi_irq)
> + return -ENXIO;
> +
> + /* Plug the MSI chained handler */
> + irq_set_chained_handler_and_data(msi_irq, plda_handle_msi, port);
> +
> + /* Plug the main event chained handler */
> + irq_set_chained_handler_and_data(irq, plda_handle_event, port);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(plda_init_interrupts);
> +
> void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
> phys_addr_t axi_addr, phys_addr_t pci_addr,
> size_t size)
> diff --git a/drivers/pci/controller/plda/pcie-plda.h b/drivers/pci/controller/plda/pcie-plda.h
> index 122084a3318a..e59369f23329 100644
> --- a/drivers/pci/controller/plda/pcie-plda.h
> +++ b/drivers/pci/controller/plda/pcie-plda.h
> @@ -164,6 +164,9 @@ struct plda_event {
> };
>
> irqreturn_t plda_event_handler(int irq, void *dev_id);
> +int plda_init_interrupts(struct platform_device *pdev,
> + struct plda_pcie_rp *port,
> + const struct plda_event *event);
> void plda_pcie_setup_window(void __iomem *bridge_base_addr, u32 index,
> phys_addr_t axi_addr, phys_addr_t pci_addr,
> size_t size);
> --
> 2.17.1
>


Attachments:
(No filename) (25.69 kB)
signature.asc (235.00 B)
Download all attachments

2023-10-10 02:33:23

by Minda Chen

[permalink] [raw]
Subject: Re: [PATCH v7 0/19] Refactoring Microchip PCIe driver and add StarFive PCIe



On 2023/10/9 19:16, Conor Dooley wrote:
> On Mon, Oct 09, 2023 at 06:58:42PM +0800, Minda Chen wrote:
>>
>>
>> On 2023/9/27 18:07, Minda Chen wrote:
>> > This patchset final purpose is add PCIe driver for StarFive JH7110 SoC.
>> > JH7110 using PLDA XpressRICH PCIe IP. Microchip PolarFire Using the
>> > same IP and have commit their codes, which are mixed with PLDA
>> > controller codes and Microchip platform codes.
>> >
>> > For re-use the PLDA controller codes, I request refactoring microchip
>> > codes, move PLDA common codes to PLDA files.
>> > Desigware and Cadence is good example for refactoring codes.
>> >
>> > So first step is extract the PLDA common codes from microchip, and
>> > refactoring the microchip codes.(patch1 - 16)
>> > Then, add Starfive codes. (patch17 - 19)
>> >
>> > This patchset is base on v6.6-rc3
>> >
>> > patch1 is move PLDA XpressRICH PCIe host common properties dt-binding
>> > docs from microchip,pcie-host.yaml
>> > patch2 is move PolarFire codes to PLDA directory.
>> > patch3 is move PLDA IP register macros to plda-pcie.h
>> > patch4 is rename data structure in microchip codes.
>> > patch5 is rename two setup functions in microchip codes, prepare to move
>> > to common file.
>> > patch6 is change the arguments of plda_pcie_setup_iomems()
>> > patch7 is move the two setup functions to common file pcie-plda-host.c
>> > patch8 is Add PLDA event interrupt codes and IRQ domain ops.
>> > patch9 is rename the IRQ related functions, prepare to move to
>> > pcie-plda-host.
>> > patch10 - 14 is modify the event codes, preparing for support starfive
>> > and microchip two platforms.
>> > patch15 is move IRQ related functions to pcie-plda-host.c
>> > patch16 is set plda_event_handler to static.
>> > patch17 is add StarFive JH7110 PCIe dt-binding doc.
>> > patch18 is add StarFive JH7110 Soc PCIe codes.
>> > patch19 is Starfive dts config
>> >
>> Hi Conor and Daire
>> Have you ever test this patchset? I'm sure I am not change logic of the PolarFire PCIe driver,
>> But I can not test it.
>> Since this series patch is delegate to nobody and no response now. I don't know when this patch set can be accepted.
>
> I'll try to look at this series again this week. I've been AFK a bit
> with holidays etc recently, and been a bit delayed in general. I was
> mostly happy with it before, and had left reviewed-bys on most of the
> series I think.
>
>> I still hope the refactoring patches can be accepted first
>
> The last patchset Daire sent has been applied:
> https://lore.kernel.org/all/[email protected]/
>
>> (I know you want to add the function of inbound and outbound address translation, Hope this series patch do not influence your upstream plan)
>
> I'd expect this series to go in before the inbound/outbound translation
> one, since this is a lot closer to ready & is being resent more often.
>
> Cheers,
> Conor.
Thanks! I will follow the comments and send v8 in this week.