diff options
author | Ben Dooks <ben.dooks@codethink.co.uk> | 2014-02-17 21:11:01 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-02-18 15:19:50 -0500 |
commit | 80a595d941a2ce2953e6c77d822d8a4c3d8fa5a0 (patch) | |
tree | d5e0ca035ad52edd0807b3585d3e651a9237b295 /drivers/pci/host | |
parent | ed65b78881c713b41051310780f94bde3c010db9 (diff) |
PCI: rcar: Add error interrupt handling
Add option to enable interrupts to report any errors from the AHB-PCI
bridge to help find any issues with the bridge when in use.
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'drivers/pci/host')
-rw-r--r-- | drivers/pci/host/pci-rcar-gen2.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c index 201e4a450340..11e444e79f45 100644 --- a/drivers/pci/host/pci-rcar-gen2.c +++ b/drivers/pci/host/pci-rcar-gen2.c | |||
@@ -39,9 +39,26 @@ | |||
39 | 39 | ||
40 | #define RCAR_PCI_INT_ENABLE_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x20) | 40 | #define RCAR_PCI_INT_ENABLE_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x20) |
41 | #define RCAR_PCI_INT_STATUS_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x24) | 41 | #define RCAR_PCI_INT_STATUS_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x24) |
42 | #define RCAR_PCI_INT_SIGTABORT (1 << 0) | ||
43 | #define RCAR_PCI_INT_SIGRETABORT (1 << 1) | ||
44 | #define RCAR_PCI_INT_REMABORT (1 << 2) | ||
45 | #define RCAR_PCI_INT_PERR (1 << 3) | ||
46 | #define RCAR_PCI_INT_SIGSERR (1 << 4) | ||
47 | #define RCAR_PCI_INT_RESERR (1 << 5) | ||
48 | #define RCAR_PCI_INT_WIN1ERR (1 << 12) | ||
49 | #define RCAR_PCI_INT_WIN2ERR (1 << 13) | ||
42 | #define RCAR_PCI_INT_A (1 << 16) | 50 | #define RCAR_PCI_INT_A (1 << 16) |
43 | #define RCAR_PCI_INT_B (1 << 17) | 51 | #define RCAR_PCI_INT_B (1 << 17) |
44 | #define RCAR_PCI_INT_PME (1 << 19) | 52 | #define RCAR_PCI_INT_PME (1 << 19) |
53 | #define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT | \ | ||
54 | RCAR_PCI_INT_SIGRETABORT | \ | ||
55 | RCAR_PCI_INT_SIGRETABORT | \ | ||
56 | RCAR_PCI_INT_REMABORT | \ | ||
57 | RCAR_PCI_INT_PERR | \ | ||
58 | RCAR_PCI_INT_SIGSERR | \ | ||
59 | RCAR_PCI_INT_RESERR | \ | ||
60 | RCAR_PCI_INT_WIN1ERR | \ | ||
61 | RCAR_PCI_INT_WIN2ERR) | ||
45 | 62 | ||
46 | #define RCAR_AHB_BUS_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x30) | 63 | #define RCAR_AHB_BUS_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x30) |
47 | #define RCAR_AHB_BUS_MMODE_HTRANS (1 << 0) | 64 | #define RCAR_AHB_BUS_MMODE_HTRANS (1 << 0) |
@@ -164,6 +181,46 @@ static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | |||
164 | return priv->irq; | 181 | return priv->irq; |
165 | } | 182 | } |
166 | 183 | ||
184 | #ifdef CONFIG_PCI_DEBUG | ||
185 | /* if debug enabled, then attach an error handler irq to the bridge */ | ||
186 | |||
187 | static irqreturn_t rcar_pci_err_irq(int irq, void *pw) | ||
188 | { | ||
189 | struct rcar_pci_priv *priv = pw; | ||
190 | u32 status = ioread32(priv->reg + RCAR_PCI_INT_STATUS_REG); | ||
191 | |||
192 | if (status & RCAR_PCI_INT_ALLERRORS) { | ||
193 | dev_err(priv->dev, "error irq: status %08x\n", status); | ||
194 | |||
195 | /* clear the error(s) */ | ||
196 | iowrite32(status & RCAR_PCI_INT_ALLERRORS, | ||
197 | priv->reg + RCAR_PCI_INT_STATUS_REG); | ||
198 | return IRQ_HANDLED; | ||
199 | } | ||
200 | |||
201 | return IRQ_NONE; | ||
202 | } | ||
203 | |||
204 | static void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) | ||
205 | { | ||
206 | int ret; | ||
207 | u32 val; | ||
208 | |||
209 | ret = devm_request_irq(priv->dev, priv->irq, rcar_pci_err_irq, | ||
210 | IRQF_SHARED, "error irq", priv); | ||
211 | if (ret) { | ||
212 | dev_err(priv->dev, "cannot claim IRQ for error handling\n"); | ||
213 | return; | ||
214 | } | ||
215 | |||
216 | val = ioread32(priv->reg + RCAR_PCI_INT_ENABLE_REG); | ||
217 | val |= RCAR_PCI_INT_ALLERRORS; | ||
218 | iowrite32(val, priv->reg + RCAR_PCI_INT_ENABLE_REG); | ||
219 | } | ||
220 | #else | ||
221 | static inline void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) { } | ||
222 | #endif | ||
223 | |||
167 | /* PCI host controller setup */ | 224 | /* PCI host controller setup */ |
168 | static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys) | 225 | static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys) |
169 | { | 226 | { |
@@ -224,6 +281,9 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys) | |||
224 | iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, | 281 | iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, |
225 | reg + RCAR_PCI_INT_ENABLE_REG); | 282 | reg + RCAR_PCI_INT_ENABLE_REG); |
226 | 283 | ||
284 | if (priv->irq > 0) | ||
285 | rcar_pci_setup_errirq(priv); | ||
286 | |||
227 | /* Add PCI resources */ | 287 | /* Add PCI resources */ |
228 | pci_add_resource(&sys->resources, &priv->io_res); | 288 | pci_add_resource(&sys->resources, &priv->io_res); |
229 | pci_add_resource(&sys->resources, &priv->mem_res); | 289 | pci_add_resource(&sys->resources, &priv->mem_res); |