mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
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
This commit is contained in:
commit
7b5d234e69
@ -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>;
|
||||
|
@ -18,12 +18,18 @@ allOf:
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 2
|
||||
maxItems: 3
|
||||
minItems: 2
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: cfg
|
||||
- const: apb
|
||||
oneOf:
|
||||
- items:
|
||||
- const: cfg
|
||||
- const: apb
|
||||
- items:
|
||||
- const: cfg
|
||||
- const: bridge
|
||||
- const: ctrl
|
||||
|
||||
interrupts:
|
||||
minItems: 1
|
||||
|
@ -16,6 +16,13 @@ properties:
|
||||
compatible:
|
||||
const: starfive,jh7110-pcie
|
||||
|
||||
|
||||
reg:
|
||||
maxItems: 2
|
||||
|
||||
reg-names:
|
||||
maxItems: 2
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: NOC bus clock
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user