|
|
|
@@ -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) {
|
|
|
|
|