Commit 7b5d234e authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branch 'pci/controller/microchip'

- Add DT and driver support for using either of the two PolarFire Root
  Ports (Conor Dooley)

* pci/controller/microchip:
  PCI: microchip: Add support for using either Root Port 1 or 2
  dt-bindings: PCI: microchip,pcie-host: Add reg for Root Port 2
parents 42681061 ac7f53b7
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -17,6 +17,12 @@ properties:
  compatible:
    const: microchip,pcie-host-1.0 # PolarFire

  reg:
    minItems: 3

  reg-names:
    minItems: 3

  clocks:
    description:
      Fabric Interface Controllers, FICs, are the interface between the FPGA
@@ -62,8 +68,9 @@ examples:
            pcie0: pcie@2030000000 {
                    compatible = "microchip,pcie-host-1.0";
                    reg = <0x0 0x70000000 0x0 0x08000000>,
                          <0x0 0x43000000 0x0 0x00010000>;
                    reg-names = "cfg", "apb";
                          <0x0 0x43008000 0x0 0x00002000>,
                          <0x0 0x4300a000 0x0 0x00002000>;
                    reg-names = "cfg", "bridge", "ctrl";
                    device_type = "pci";
                    #address-cells = <3>;
                    #size-cells = <2>;
+10 −4
Original line number Diff line number Diff line
@@ -18,12 +18,18 @@ allOf:

properties:
  reg:
    maxItems: 2
    maxItems: 3
    minItems: 2

  reg-names:
    items:
    oneOf:
      - items:
          - const: cfg
          - const: apb
      - items:
          - const: cfg
          - const: bridge
          - const: ctrl

  interrupts:
    minItems: 1
+7 −0
Original line number Diff line number Diff line
@@ -16,6 +16,13 @@ properties:
  compatible:
    const: starfive,jh7110-pcie


  reg:
    maxItems: 2

  reg-names:
    maxItems: 2

  clocks:
    items:
      - description: NOC bus clock
+67 −59
Original line number Diff line number Diff line
@@ -25,9 +25,6 @@
#define MC_PCIE1_BRIDGE_ADDR			0x00008000u
#define MC_PCIE1_CTRL_ADDR			0x0000a000u

#define MC_PCIE_BRIDGE_ADDR			(MC_PCIE1_BRIDGE_ADDR)
#define MC_PCIE_CTRL_ADDR			(MC_PCIE1_CTRL_ADDR)

/* PCIe Controller Phy Regs */
#define SEC_ERROR_EVENT_CNT			0x20
#define DED_ERROR_EVENT_CNT			0x24
@@ -128,7 +125,6 @@
	[EVENT_LOCAL_ ## x] = { __stringify(x), s }

#define PCIE_EVENT(x) \
	.base = MC_PCIE_CTRL_ADDR, \
	.offset = PCIE_EVENT_INT, \
	.mask_offset = PCIE_EVENT_INT, \
	.mask_high = 1, \
@@ -136,7 +132,6 @@
	.enb_mask = PCIE_EVENT_INT_ENB_MASK

#define SEC_EVENT(x) \
	.base = MC_PCIE_CTRL_ADDR, \
	.offset = SEC_ERROR_INT, \
	.mask_offset = SEC_ERROR_INT_MASK, \
	.mask = SEC_ERROR_INT_ ## x ## _INT, \
@@ -144,7 +139,6 @@
	.enb_mask = 0

#define DED_EVENT(x) \
	.base = MC_PCIE_CTRL_ADDR, \
	.offset = DED_ERROR_INT, \
	.mask_offset = DED_ERROR_INT_MASK, \
	.mask_high = 1, \
@@ -152,7 +146,6 @@
	.enb_mask = 0

#define LOCAL_EVENT(x) \
	.base = MC_PCIE_BRIDGE_ADDR, \
	.offset = ISTATUS_LOCAL, \
	.mask_offset = IMASK_LOCAL, \
	.mask_high = 0, \
@@ -179,7 +172,8 @@ struct event_map {

struct mc_pcie {
	struct plda_pcie_rp plda;
	void __iomem *axi_base_addr;
	void __iomem *bridge_base_addr;
	void __iomem *ctrl_base_addr;
};

struct cause {
@@ -253,7 +247,6 @@ static struct event_map local_status_to_event[] = {
};

static struct {
	u32 base;
	u32 offset;
	u32 mask;
	u32 shift;
@@ -325,8 +318,7 @@ static inline u32 reg_to_event(u32 reg, struct event_map field)

static u32 pcie_events(struct mc_pcie *port)
{
	void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
	u32 reg = readl_relaxed(ctrl_base_addr + PCIE_EVENT_INT);
	u32 reg = readl_relaxed(port->ctrl_base_addr + PCIE_EVENT_INT);
	u32 val = 0;
	int i;

@@ -338,8 +330,7 @@ static u32 pcie_events(struct mc_pcie *port)

static u32 sec_errors(struct mc_pcie *port)
{
	void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
	u32 reg = readl_relaxed(ctrl_base_addr + SEC_ERROR_INT);
	u32 reg = readl_relaxed(port->ctrl_base_addr + SEC_ERROR_INT);
	u32 val = 0;
	int i;

@@ -351,8 +342,7 @@ static u32 sec_errors(struct mc_pcie *port)

static u32 ded_errors(struct mc_pcie *port)
{
	void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
	u32 reg = readl_relaxed(ctrl_base_addr + DED_ERROR_INT);
	u32 reg = readl_relaxed(port->ctrl_base_addr + DED_ERROR_INT);
	u32 val = 0;
	int i;

@@ -364,8 +354,7 @@ static u32 ded_errors(struct mc_pcie *port)

static u32 local_events(struct mc_pcie *port)
{
	void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
	u32 reg = readl_relaxed(bridge_base_addr + ISTATUS_LOCAL);
	u32 reg = readl_relaxed(port->bridge_base_addr + ISTATUS_LOCAL);
	u32 val = 0;
	int i;

@@ -412,8 +401,12 @@ static void mc_ack_event_irq(struct irq_data *data)
	void __iomem *addr;
	u32 mask;

	addr = mc_port->axi_base_addr + event_descs[event].base +
		event_descs[event].offset;
	if (event_descs[event].offset == ISTATUS_LOCAL)
		addr = mc_port->bridge_base_addr;
	else
		addr = mc_port->ctrl_base_addr;

	addr += event_descs[event].offset;
	mask = event_descs[event].mask;
	mask |= event_descs[event].enb_mask;

@@ -429,8 +422,12 @@ static void mc_mask_event_irq(struct irq_data *data)
	u32 mask;
	u32 val;

	addr = mc_port->axi_base_addr + event_descs[event].base +
		event_descs[event].mask_offset;
	if (event_descs[event].offset == ISTATUS_LOCAL)
		addr = mc_port->bridge_base_addr;
	else
		addr = mc_port->ctrl_base_addr;

	addr += event_descs[event].mask_offset;
	mask = event_descs[event].mask;
	if (event_descs[event].enb_mask) {
		mask <<= PCIE_EVENT_INT_ENB_SHIFT;
@@ -460,8 +457,12 @@ static void mc_unmask_event_irq(struct irq_data *data)
	u32 mask;
	u32 val;

	addr = mc_port->axi_base_addr + event_descs[event].base +
		event_descs[event].mask_offset;
	if (event_descs[event].offset == ISTATUS_LOCAL)
		addr = mc_port->bridge_base_addr;
	else
		addr = mc_port->ctrl_base_addr;

	addr += event_descs[event].mask_offset;
	mask = event_descs[event].mask;

	if (event_descs[event].enb_mask)
@@ -554,26 +555,20 @@ static const struct plda_event mc_event = {

static inline void mc_clear_secs(struct mc_pcie *port)
{
	void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;

	writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
		       SEC_ERROR_INT);
	writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT);
	writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT,
		       port->ctrl_base_addr + SEC_ERROR_INT);
	writel_relaxed(0, port->ctrl_base_addr + SEC_ERROR_EVENT_CNT);
}

static inline void mc_clear_deds(struct mc_pcie *port)
{
	void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;

	writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
		       DED_ERROR_INT);
	writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT);
	writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT,
		       port->ctrl_base_addr + DED_ERROR_INT);
	writel_relaxed(0, port->ctrl_base_addr + DED_ERROR_EVENT_CNT);
}

static void mc_disable_interrupts(struct mc_pcie *port)
{
	void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
	void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
	u32 val;

	/* Ensure ECC bypass is enabled */
@@ -581,22 +576,22 @@ static void mc_disable_interrupts(struct mc_pcie *port)
	      ECC_CONTROL_RX_RAM_ECC_BYPASS |
	      ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS |
	      ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS;
	writel_relaxed(val, ctrl_base_addr + ECC_CONTROL);
	writel_relaxed(val, port->ctrl_base_addr + ECC_CONTROL);

	/* Disable SEC errors and clear any outstanding */
	writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
		       SEC_ERROR_INT_MASK);
	writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT,
		       port->ctrl_base_addr + SEC_ERROR_INT_MASK);
	mc_clear_secs(port);

	/* Disable DED errors and clear any outstanding */
	writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
		       DED_ERROR_INT_MASK);
	writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT,
		       port->ctrl_base_addr + DED_ERROR_INT_MASK);
	mc_clear_deds(port);

	/* Disable local interrupts and clear any outstanding */
	writel_relaxed(0, bridge_base_addr + IMASK_LOCAL);
	writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_LOCAL);
	writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_MSI);
	writel_relaxed(0, port->bridge_base_addr + IMASK_LOCAL);
	writel_relaxed(GENMASK(31, 0), port->bridge_base_addr + ISTATUS_LOCAL);
	writel_relaxed(GENMASK(31, 0), port->bridge_base_addr + ISTATUS_MSI);

	/* Disable PCIe events and clear any outstanding */
	val = PCIE_EVENT_INT_L2_EXIT_INT |
@@ -605,11 +600,11 @@ static void mc_disable_interrupts(struct mc_pcie *port)
	      PCIE_EVENT_INT_L2_EXIT_INT_MASK |
	      PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK |
	      PCIE_EVENT_INT_DLUP_EXIT_INT_MASK;
	writel_relaxed(val, ctrl_base_addr + PCIE_EVENT_INT);
	writel_relaxed(val, port->ctrl_base_addr + PCIE_EVENT_INT);

	/* Disable host interrupts and clear any outstanding */
	writel_relaxed(0, bridge_base_addr + IMASK_HOST);
	writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
	writel_relaxed(0, port->bridge_base_addr + IMASK_HOST);
	writel_relaxed(GENMASK(31, 0), port->bridge_base_addr + ISTATUS_HOST);
}

static int mc_platform_init(struct pci_config_window *cfg)
@@ -617,12 +612,10 @@ static int mc_platform_init(struct pci_config_window *cfg)
	struct device *dev = cfg->parent;
	struct platform_device *pdev = to_platform_device(dev);
	struct pci_host_bridge *bridge = platform_get_drvdata(pdev);
	void __iomem *bridge_base_addr =
		port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
	int ret;

	/* Configure address translation table 0 for PCIe config space */
	plda_pcie_setup_window(bridge_base_addr, 0, cfg->res.start,
	plda_pcie_setup_window(port->bridge_base_addr, 0, cfg->res.start,
			       cfg->res.start,
			       resource_size(&cfg->res));

@@ -649,7 +642,7 @@ static int mc_platform_init(struct pci_config_window *cfg)
static int mc_host_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	void __iomem *bridge_base_addr;
	void __iomem *apb_base_addr;
	struct plda_pcie_rp *plda;
	int ret;
	u32 val;
@@ -661,30 +654,45 @@ static int mc_host_probe(struct platform_device *pdev)
	plda = &port->plda;
	plda->dev = dev;

	port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
	if (IS_ERR(port->axi_base_addr))
		return PTR_ERR(port->axi_base_addr);
	port->bridge_base_addr = devm_platform_ioremap_resource_byname(pdev,
								    "bridge");
	port->ctrl_base_addr = devm_platform_ioremap_resource_byname(pdev,
								    "ctrl");
	if (!IS_ERR(port->bridge_base_addr) && !IS_ERR(port->ctrl_base_addr))
		goto addrs_set;

	/*
	 * The original, incorrect, binding that lumped the control and
	 * bridge addresses together still needs to be handled by the driver.
	 */
	apb_base_addr = devm_platform_ioremap_resource_byname(pdev, "apb");
	if (IS_ERR(apb_base_addr))
		return dev_err_probe(dev, PTR_ERR(apb_base_addr),
				     "both legacy apb register and ctrl/bridge regions missing");

	port->bridge_base_addr = apb_base_addr + MC_PCIE1_BRIDGE_ADDR;
	port->ctrl_base_addr = apb_base_addr + MC_PCIE1_CTRL_ADDR;

addrs_set:
	mc_disable_interrupts(port);

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

	/* Allow enabling MSI by disabling MSI-X */
	val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
	val = readl(port->bridge_base_addr + PCIE_PCI_IRQ_DW0);
	val &= ~MSIX_CAP_MASK;
	writel(val, bridge_base_addr + PCIE_PCI_IRQ_DW0);
	writel(val, port->bridge_base_addr + PCIE_PCI_IRQ_DW0);

	/* Pick num vectors from bitfile programmed onto FPGA fabric */
	val = readl(bridge_base_addr + PCIE_PCI_IRQ_DW0);
	val = readl(port->bridge_base_addr + PCIE_PCI_IRQ_DW0);
	val &= NUM_MSI_MSGS_MASK;
	val >>= NUM_MSI_MSGS_SHIFT;

	plda->msi.num_vectors = 1 << val;

	/* Pick vector address from design */
	plda->msi.vector_phy = readl_relaxed(bridge_base_addr + IMSI_ADDR);
	plda->msi.vector_phy = readl_relaxed(port->bridge_base_addr + IMSI_ADDR);

	ret = mc_pcie_init_clks(dev);
	if (ret) {