Skip to content

Commit 4f0b912

Browse files
Daire McNamaraLorenzo Pieralisi
authored andcommitted
PCI: microchip: Clean up initialisation of interrupts
Refactor interrupt handling in _init() function into disable_interrupts(), init_interrupts(), clear_sec_errors() and clear ded_errors() because current code is unwieldy and prone to bugs. Disable interrupts as soon as possible and only enable interrupts after address translation is setup to prevent spurious axi2pcie and pcie2axi translation errors being reported. Link: https://lore.kernel.org/r/20230728131401.1615724-6-daire.mcnamara@microchip.com Signed-off-by: Daire McNamara <daire.mcnamara@microchip.com> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org> Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
1 parent d1d6a0c commit 4f0b912

File tree

1 file changed

+100
-56
lines changed

1 file changed

+100
-56
lines changed

drivers/pci/controller/pcie-microchip-host.c

Lines changed: 100 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,15 @@
112112
#define SEC_ERROR_INT_RX_RAM_SEC_ERR_INT GENMASK(7, 4)
113113
#define SEC_ERROR_INT_PCIE2AXI_RAM_SEC_ERR_INT GENMASK(11, 8)
114114
#define SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT GENMASK(15, 12)
115+
#define SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT GENMASK(15, 0)
115116
#define NUM_SEC_ERROR_INTS (4)
116117
#define SEC_ERROR_INT_MASK 0x2c
117118
#define DED_ERROR_INT 0x30
118119
#define DED_ERROR_INT_TX_RAM_DED_ERR_INT GENMASK(3, 0)
119120
#define DED_ERROR_INT_RX_RAM_DED_ERR_INT GENMASK(7, 4)
120121
#define DED_ERROR_INT_PCIE2AXI_RAM_DED_ERR_INT GENMASK(11, 8)
121122
#define DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT GENMASK(15, 12)
123+
#define DED_ERROR_INT_ALL_RAM_DED_ERR_INT GENMASK(15, 0)
122124
#define NUM_DED_ERROR_INTS (4)
123125
#define DED_ERROR_INT_MASK 0x34
124126
#define ECC_CONTROL 0x38
@@ -986,39 +988,73 @@ static int mc_pcie_setup_windows(struct platform_device *pdev,
986988
return 0;
987989
}
988990

989-
static int mc_platform_init(struct pci_config_window *cfg)
991+
static inline void mc_clear_secs(struct mc_pcie *port)
990992
{
991-
struct device *dev = cfg->parent;
992-
struct platform_device *pdev = to_platform_device(dev);
993-
struct mc_pcie *port;
994-
void __iomem *bridge_base_addr;
995-
void __iomem *ctrl_base_addr;
996-
int ret;
997-
int irq;
998-
int i, intx_irq, msi_irq, event_irq;
993+
void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
994+
995+
writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
996+
SEC_ERROR_INT);
997+
writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT);
998+
}
999+
1000+
static inline void mc_clear_deds(struct mc_pcie *port)
1001+
{
1002+
void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
1003+
1004+
writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
1005+
DED_ERROR_INT);
1006+
writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT);
1007+
}
1008+
1009+
static void mc_disable_interrupts(struct mc_pcie *port)
1010+
{
1011+
void __iomem *bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
1012+
void __iomem *ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
9991013
u32 val;
1000-
int err;
10011014

1002-
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
1003-
if (!port)
1004-
return -ENOMEM;
1005-
port->dev = dev;
1015+
/* Ensure ECC bypass is enabled */
1016+
val = ECC_CONTROL_TX_RAM_ECC_BYPASS |
1017+
ECC_CONTROL_RX_RAM_ECC_BYPASS |
1018+
ECC_CONTROL_PCIE2AXI_RAM_ECC_BYPASS |
1019+
ECC_CONTROL_AXI2PCIE_RAM_ECC_BYPASS;
1020+
writel_relaxed(val, ctrl_base_addr + ECC_CONTROL);
10061021

1007-
ret = mc_pcie_init_clks(dev);
1008-
if (ret) {
1009-
dev_err(dev, "failed to get clock resources, error %d\n", ret);
1010-
return -ENODEV;
1011-
}
1022+
/* Disable SEC errors and clear any outstanding */
1023+
writel_relaxed(SEC_ERROR_INT_ALL_RAM_SEC_ERR_INT, ctrl_base_addr +
1024+
SEC_ERROR_INT_MASK);
1025+
mc_clear_secs(port);
10121026

1013-
port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
1014-
if (IS_ERR(port->axi_base_addr))
1015-
return PTR_ERR(port->axi_base_addr);
1027+
/* Disable DED errors and clear any outstanding */
1028+
writel_relaxed(DED_ERROR_INT_ALL_RAM_DED_ERR_INT, ctrl_base_addr +
1029+
DED_ERROR_INT_MASK);
1030+
mc_clear_deds(port);
10161031

1017-
bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
1018-
ctrl_base_addr = port->axi_base_addr + MC_PCIE_CTRL_ADDR;
1032+
/* Disable local interrupts and clear any outstanding */
1033+
writel_relaxed(0, bridge_base_addr + IMASK_LOCAL);
1034+
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_LOCAL);
1035+
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_MSI);
1036+
1037+
/* Disable PCIe events and clear any outstanding */
1038+
val = PCIE_EVENT_INT_L2_EXIT_INT |
1039+
PCIE_EVENT_INT_HOTRST_EXIT_INT |
1040+
PCIE_EVENT_INT_DLUP_EXIT_INT |
1041+
PCIE_EVENT_INT_L2_EXIT_INT_MASK |
1042+
PCIE_EVENT_INT_HOTRST_EXIT_INT_MASK |
1043+
PCIE_EVENT_INT_DLUP_EXIT_INT_MASK;
1044+
writel_relaxed(val, ctrl_base_addr + PCIE_EVENT_INT);
1045+
1046+
/* Disable host interrupts and clear any outstanding */
1047+
writel_relaxed(0, bridge_base_addr + IMASK_HOST);
1048+
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
1049+
}
1050+
1051+
static int mc_init_interrupts(struct platform_device *pdev, struct mc_pcie *port)
1052+
{
1053+
struct device *dev = &pdev->dev;
1054+
int irq;
1055+
int i, intx_irq, msi_irq, event_irq;
1056+
int ret;
10191057

1020-
port->msi.vector_phy = MSI_ADDR;
1021-
port->msi.num_vectors = MC_NUM_MSI_IRQS;
10221058
ret = mc_pcie_init_irq_domains(port);
10231059
if (ret) {
10241060
dev_err(dev, "failed creating IRQ domains\n");
@@ -1036,11 +1072,11 @@ static int mc_platform_init(struct pci_config_window *cfg)
10361072
return -ENXIO;
10371073
}
10381074

1039-
err = devm_request_irq(dev, event_irq, mc_event_handler,
1075+
ret = devm_request_irq(dev, event_irq, mc_event_handler,
10401076
0, event_cause[i].sym, port);
1041-
if (err) {
1077+
if (ret) {
10421078
dev_err(dev, "failed to request IRQ %d\n", event_irq);
1043-
return err;
1079+
return ret;
10441080
}
10451081
}
10461082

@@ -1065,44 +1101,52 @@ static int mc_platform_init(struct pci_config_window *cfg)
10651101
/* Plug the main event chained handler */
10661102
irq_set_chained_handler_and_data(irq, mc_handle_event, port);
10671103

1068-
/* Hardware doesn't setup MSI by default */
1069-
mc_pcie_enable_msi(port, cfg->win);
1104+
return 0;
1105+
}
10701106

1071-
val = readl_relaxed(bridge_base_addr + IMASK_LOCAL);
1072-
val |= PM_MSI_INT_INTX_MASK;
1073-
writel_relaxed(val, bridge_base_addr + IMASK_LOCAL);
1107+
static int mc_platform_init(struct pci_config_window *cfg)
1108+
{
1109+
struct device *dev = cfg->parent;
1110+
struct platform_device *pdev = to_platform_device(dev);
1111+
struct mc_pcie *port;
1112+
void __iomem *bridge_base_addr;
1113+
int ret;
10741114

1075-
writel_relaxed(val, ctrl_base_addr + ECC_CONTROL);
1115+
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
1116+
if (!port)
1117+
return -ENOMEM;
1118+
port->dev = dev;
10761119

1077-
val = PCIE_EVENT_INT_L2_EXIT_INT |
1078-
PCIE_EVENT_INT_HOTRST_EXIT_INT |
1079-
PCIE_EVENT_INT_DLUP_EXIT_INT;
1080-
writel_relaxed(val, ctrl_base_addr + PCIE_EVENT_INT);
1120+
ret = mc_pcie_init_clks(dev);
1121+
if (ret) {
1122+
dev_err(dev, "failed to get clock resources, error %d\n", ret);
1123+
return -ENODEV;
1124+
}
10811125

1082-
val = SEC_ERROR_INT_TX_RAM_SEC_ERR_INT |
1083-
SEC_ERROR_INT_RX_RAM_SEC_ERR_INT |
1084-
SEC_ERROR_INT_PCIE2AXI_RAM_SEC_ERR_INT |
1085-
SEC_ERROR_INT_AXI2PCIE_RAM_SEC_ERR_INT;
1086-
writel_relaxed(val, ctrl_base_addr + SEC_ERROR_INT);
1087-
writel_relaxed(0, ctrl_base_addr + SEC_ERROR_INT_MASK);
1088-
writel_relaxed(0, ctrl_base_addr + SEC_ERROR_EVENT_CNT);
1126+
port->axi_base_addr = devm_platform_ioremap_resource(pdev, 1);
1127+
if (IS_ERR(port->axi_base_addr))
1128+
return PTR_ERR(port->axi_base_addr);
10891129

1090-
val = DED_ERROR_INT_TX_RAM_DED_ERR_INT |
1091-
DED_ERROR_INT_RX_RAM_DED_ERR_INT |
1092-
DED_ERROR_INT_PCIE2AXI_RAM_DED_ERR_INT |
1093-
DED_ERROR_INT_AXI2PCIE_RAM_DED_ERR_INT;
1094-
writel_relaxed(val, ctrl_base_addr + DED_ERROR_INT);
1095-
writel_relaxed(0, ctrl_base_addr + DED_ERROR_INT_MASK);
1096-
writel_relaxed(0, ctrl_base_addr + DED_ERROR_EVENT_CNT);
1130+
mc_disable_interrupts(port);
10971131

1098-
writel_relaxed(0, bridge_base_addr + IMASK_HOST);
1099-
writel_relaxed(GENMASK(31, 0), bridge_base_addr + ISTATUS_HOST);
1132+
bridge_base_addr = port->axi_base_addr + MC_PCIE_BRIDGE_ADDR;
1133+
1134+
port->msi.vector_phy = MSI_ADDR;
1135+
port->msi.num_vectors = MC_NUM_MSI_IRQS;
1136+
1137+
/* Hardware doesn't setup MSI by default */
1138+
mc_pcie_enable_msi(port, cfg->win);
11001139

11011140
/* Configure Address Translation Table 0 for PCIe config space */
11021141
mc_pcie_setup_window(bridge_base_addr, 0, cfg->res.start & 0xffffffff,
11031142
cfg->res.start, resource_size(&cfg->res));
11041143

1105-
return mc_pcie_setup_windows(pdev, port);
1144+
ret = mc_pcie_setup_windows(pdev, port);
1145+
if (ret)
1146+
return ret;
1147+
1148+
/* Address translation is up; safe to enable interrupts */
1149+
return mc_init_interrupts(pdev, port);
11061150
}
11071151

11081152
static const struct pci_ecam_ops mc_ecam_ops = {

0 commit comments

Comments
 (0)