diff options
Diffstat (limited to 'arch/mips/pci')
-rw-r--r-- | arch/mips/pci/ops-tx3927.c | 80 | ||||
-rw-r--r-- | arch/mips/pci/ops-tx4927.c | 118 | ||||
-rw-r--r-- | arch/mips/pci/pci-tx4927.c | 10 | ||||
-rw-r--r-- | arch/mips/pci/pci-tx4938.c | 10 | ||||
-rw-r--r-- | arch/mips/pci/pci.c | 6 |
5 files changed, 196 insertions, 28 deletions
diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c index 8a17a39e5bf2..31c150196595 100644 --- a/arch/mips/pci/ops-tx3927.c +++ b/arch/mips/pci/ops-tx3927.c | |||
@@ -37,45 +37,48 @@ | |||
37 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/interrupt.h> | ||
40 | 41 | ||
41 | #include <asm/addrspace.h> | 42 | #include <asm/addrspace.h> |
43 | #include <asm/txx9irq.h> | ||
44 | #include <asm/txx9/pci.h> | ||
42 | #include <asm/txx9/tx3927.h> | 45 | #include <asm/txx9/tx3927.h> |
43 | 46 | ||
44 | static inline int mkaddr(unsigned char bus, unsigned char dev_fn, | 47 | static int mkaddr(struct pci_bus *bus, unsigned char devfn, unsigned char where) |
45 | unsigned char where) | ||
46 | { | 48 | { |
47 | if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0)) | 49 | if (bus->parent == NULL && |
48 | return PCIBIOS_DEVICE_NOT_FOUND; | 50 | devfn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0)) |
49 | 51 | return -1; | |
50 | tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) | | 52 | tx3927_pcicptr->ica = |
51 | ((dev_fn & 0xff) << 0x08) | | 53 | ((bus->number & 0xff) << 0x10) | |
52 | (where & 0xfc); | 54 | ((devfn & 0xff) << 0x08) | |
55 | (where & 0xfc) | (bus->parent ? 1 : 0); | ||
53 | 56 | ||
54 | /* clear M_ABORT and Disable M_ABORT Int. */ | 57 | /* clear M_ABORT and Disable M_ABORT Int. */ |
55 | tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; | 58 | tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; |
56 | tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT; | 59 | tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT; |
57 | 60 | return 0; | |
58 | return PCIBIOS_SUCCESSFUL; | ||
59 | } | 61 | } |
60 | 62 | ||
61 | static inline int check_abort(void) | 63 | static inline int check_abort(void) |
62 | { | 64 | { |
63 | if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) | 65 | if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) { |
64 | tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; | 66 | tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; |
65 | tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; | 67 | tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; |
68 | /* flush write buffer */ | ||
69 | iob(); | ||
66 | return PCIBIOS_DEVICE_NOT_FOUND; | 70 | return PCIBIOS_DEVICE_NOT_FOUND; |
67 | 71 | } | |
68 | return PCIBIOS_SUCCESSFUL; | 72 | return PCIBIOS_SUCCESSFUL; |
69 | } | 73 | } |
70 | 74 | ||
71 | static int tx3927_pci_read_config(struct pci_bus *bus, unsigned int devfn, | 75 | static int tx3927_pci_read_config(struct pci_bus *bus, unsigned int devfn, |
72 | int where, int size, u32 * val) | 76 | int where, int size, u32 * val) |
73 | { | 77 | { |
74 | int ret; | 78 | if (mkaddr(bus, devfn, where)) { |
75 | 79 | *val = 0xffffffff; | |
76 | ret = mkaddr(bus->number, devfn, where); | 80 | return PCIBIOS_DEVICE_NOT_FOUND; |
77 | if (ret) | 81 | } |
78 | return ret; | ||
79 | 82 | ||
80 | switch (size) { | 83 | switch (size) { |
81 | case 1: | 84 | case 1: |
@@ -97,11 +100,8 @@ static int tx3927_pci_read_config(struct pci_bus *bus, unsigned int devfn, | |||
97 | static int tx3927_pci_write_config(struct pci_bus *bus, unsigned int devfn, | 100 | static int tx3927_pci_write_config(struct pci_bus *bus, unsigned int devfn, |
98 | int where, int size, u32 val) | 101 | int where, int size, u32 val) |
99 | { | 102 | { |
100 | int ret; | 103 | if (mkaddr(bus, devfn, where)) |
101 | 104 | return PCIBIOS_DEVICE_NOT_FOUND; | |
102 | ret = mkaddr(bus->number, devfn, where); | ||
103 | if (ret) | ||
104 | return ret; | ||
105 | 105 | ||
106 | switch (size) { | 106 | switch (size) { |
107 | case 1: | 107 | case 1: |
@@ -117,11 +117,6 @@ static int tx3927_pci_write_config(struct pci_bus *bus, unsigned int devfn, | |||
117 | tx3927_pcicptr->icd = cpu_to_le32(val); | 117 | tx3927_pcicptr->icd = cpu_to_le32(val); |
118 | } | 118 | } |
119 | 119 | ||
120 | if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) | ||
121 | tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; | ||
122 | tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; | ||
123 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
124 | |||
125 | return check_abort(); | 120 | return check_abort(); |
126 | } | 121 | } |
127 | 122 | ||
@@ -202,3 +197,34 @@ void __init tx3927_pcic_setup(struct pci_controller *channel, | |||
202 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; | 197 | PCI_COMMAND_PARITY | PCI_COMMAND_SERR; |
203 | local_irq_restore(flags); | 198 | local_irq_restore(flags); |
204 | } | 199 | } |
200 | |||
201 | static irqreturn_t tx3927_pcierr_interrupt(int irq, void *dev_id) | ||
202 | { | ||
203 | struct pt_regs *regs = get_irq_regs(); | ||
204 | |||
205 | if (txx9_pci_err_action != TXX9_PCI_ERR_IGNORE) { | ||
206 | printk(KERN_WARNING "PCI error interrupt at 0x%08lx.\n", | ||
207 | regs->cp0_epc); | ||
208 | printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n", | ||
209 | tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat); | ||
210 | } | ||
211 | if (txx9_pci_err_action != TXX9_PCI_ERR_PANIC) { | ||
212 | /* clear all pci errors */ | ||
213 | tx3927_pcicptr->pcistat |= TX3927_PCIC_PCISTATIM_ALL; | ||
214 | tx3927_pcicptr->istat = TX3927_PCIC_IIM_ALL; | ||
215 | tx3927_pcicptr->tstat = TX3927_PCIC_TIM_ALL; | ||
216 | tx3927_pcicptr->lbstat = TX3927_PCIC_LBIM_ALL; | ||
217 | return IRQ_HANDLED; | ||
218 | } | ||
219 | console_verbose(); | ||
220 | panic("PCI error."); | ||
221 | } | ||
222 | |||
223 | void __init tx3927_setup_pcierr_irq(void) | ||
224 | { | ||
225 | if (request_irq(TXX9_IRQ_BASE + TX3927_IR_PCI, | ||
226 | tx3927_pcierr_interrupt, | ||
227 | IRQF_DISABLED, "PCI error", | ||
228 | (void *)TX3927_PCIC_REG)) | ||
229 | printk(KERN_WARNING "Failed to request irq for PCIERR\n"); | ||
230 | } | ||
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c index c6b49bccd274..5989e747527f 100644 --- a/arch/mips/pci/ops-tx4927.c +++ b/arch/mips/pci/ops-tx4927.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * option) any later version. | 16 | * option) any later version. |
17 | */ | 17 | */ |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/interrupt.h> | ||
20 | #include <asm/txx9/pci.h> | ||
19 | #include <asm/txx9/tx4927pcic.h> | 21 | #include <asm/txx9/tx4927pcic.h> |
20 | 22 | ||
21 | static struct { | 23 | static struct { |
@@ -85,6 +87,8 @@ static int check_abort(struct tx4927_pcic_reg __iomem *pcicptr) | |||
85 | __raw_writel((__raw_readl(&pcicptr->pcistatus) & 0x0000ffff) | 87 | __raw_writel((__raw_readl(&pcicptr->pcistatus) & 0x0000ffff) |
86 | | (PCI_STATUS_REC_MASTER_ABORT << 16), | 88 | | (PCI_STATUS_REC_MASTER_ABORT << 16), |
87 | &pcicptr->pcistatus); | 89 | &pcicptr->pcistatus); |
90 | /* flush write buffer */ | ||
91 | iob(); | ||
88 | code = PCIBIOS_DEVICE_NOT_FOUND; | 92 | code = PCIBIOS_DEVICE_NOT_FOUND; |
89 | } | 93 | } |
90 | return code; | 94 | return code; |
@@ -192,6 +196,28 @@ static struct { | |||
192 | .gbwc = 0xfe0, /* 4064 GBUSCLK for CCFG.GTOT=0b11 */ | 196 | .gbwc = 0xfe0, /* 4064 GBUSCLK for CCFG.GTOT=0b11 */ |
193 | }; | 197 | }; |
194 | 198 | ||
199 | char *__devinit tx4927_pcibios_setup(char *str) | ||
200 | { | ||
201 | unsigned long val; | ||
202 | |||
203 | if (!strncmp(str, "trdyto=", 7)) { | ||
204 | if (strict_strtoul(str + 7, 0, &val) == 0) | ||
205 | tx4927_pci_opts.trdyto = val; | ||
206 | return NULL; | ||
207 | } | ||
208 | if (!strncmp(str, "retryto=", 8)) { | ||
209 | if (strict_strtoul(str + 8, 0, &val) == 0) | ||
210 | tx4927_pci_opts.retryto = val; | ||
211 | return NULL; | ||
212 | } | ||
213 | if (!strncmp(str, "gbwc=", 5)) { | ||
214 | if (strict_strtoul(str + 5, 0, &val) == 0) | ||
215 | tx4927_pci_opts.gbwc = val; | ||
216 | return NULL; | ||
217 | } | ||
218 | return str; | ||
219 | } | ||
220 | |||
195 | void __init tx4927_pcic_setup(struct tx4927_pcic_reg __iomem *pcicptr, | 221 | void __init tx4927_pcic_setup(struct tx4927_pcic_reg __iomem *pcicptr, |
196 | struct pci_controller *channel, int extarb) | 222 | struct pci_controller *channel, int extarb) |
197 | { | 223 | { |
@@ -406,3 +432,95 @@ void tx4927_report_pcic_status(void) | |||
406 | tx4927_report_pcic_status1(pcicptrs[i].pcicptr); | 432 | tx4927_report_pcic_status1(pcicptrs[i].pcicptr); |
407 | } | 433 | } |
408 | } | 434 | } |
435 | |||
436 | static void tx4927_dump_pcic_settings1(struct tx4927_pcic_reg __iomem *pcicptr) | ||
437 | { | ||
438 | int i; | ||
439 | __u32 __iomem *preg = (__u32 __iomem *)pcicptr; | ||
440 | |||
441 | printk(KERN_INFO "tx4927 pcic (0x%p) settings:", pcicptr); | ||
442 | for (i = 0; i < sizeof(struct tx4927_pcic_reg); i += 4, preg++) { | ||
443 | if (i % 32 == 0) { | ||
444 | printk(KERN_CONT "\n"); | ||
445 | printk(KERN_INFO "%04x:", i); | ||
446 | } | ||
447 | /* skip registers with side-effects */ | ||
448 | if (i == offsetof(struct tx4927_pcic_reg, g2pintack) | ||
449 | || i == offsetof(struct tx4927_pcic_reg, g2pspc) | ||
450 | || i == offsetof(struct tx4927_pcic_reg, g2pcfgadrs) | ||
451 | || i == offsetof(struct tx4927_pcic_reg, g2pcfgdata)) { | ||
452 | printk(KERN_CONT " XXXXXXXX"); | ||
453 | continue; | ||
454 | } | ||
455 | printk(KERN_CONT " %08x", __raw_readl(preg)); | ||
456 | } | ||
457 | printk(KERN_CONT "\n"); | ||
458 | } | ||
459 | |||
460 | void tx4927_dump_pcic_settings(void) | ||
461 | { | ||
462 | int i; | ||
463 | |||
464 | for (i = 0; i < ARRAY_SIZE(pcicptrs); i++) { | ||
465 | if (pcicptrs[i].pcicptr) | ||
466 | tx4927_dump_pcic_settings1(pcicptrs[i].pcicptr); | ||
467 | } | ||
468 | } | ||
469 | |||
470 | irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id) | ||
471 | { | ||
472 | struct pt_regs *regs = get_irq_regs(); | ||
473 | struct tx4927_pcic_reg __iomem *pcicptr = | ||
474 | (struct tx4927_pcic_reg __iomem *)(unsigned long)dev_id; | ||
475 | |||
476 | if (txx9_pci_err_action != TXX9_PCI_ERR_IGNORE) { | ||
477 | printk(KERN_WARNING "PCIERR interrupt at 0x%0*lx\n", | ||
478 | (int)(2 * sizeof(unsigned long)), regs->cp0_epc); | ||
479 | tx4927_report_pcic_status1(pcicptr); | ||
480 | } | ||
481 | if (txx9_pci_err_action != TXX9_PCI_ERR_PANIC) { | ||
482 | /* clear all pci errors */ | ||
483 | __raw_writel((__raw_readl(&pcicptr->pcistatus) & 0x0000ffff) | ||
484 | | (TX4927_PCIC_PCISTATUS_ALL << 16), | ||
485 | &pcicptr->pcistatus); | ||
486 | __raw_writel(TX4927_PCIC_G2PSTATUS_ALL, &pcicptr->g2pstatus); | ||
487 | __raw_writel(TX4927_PCIC_PBASTATUS_ALL, &pcicptr->pbastatus); | ||
488 | __raw_writel(TX4927_PCIC_PCICSTATUS_ALL, &pcicptr->pcicstatus); | ||
489 | return IRQ_HANDLED; | ||
490 | } | ||
491 | console_verbose(); | ||
492 | tx4927_dump_pcic_settings1(pcicptr); | ||
493 | panic("PCI error."); | ||
494 | } | ||
495 | |||
496 | #ifdef CONFIG_TOSHIBA_FPCIB0 | ||
497 | static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev) | ||
498 | { | ||
499 | struct tx4927_pcic_reg __iomem *pcicptr = pci_bus_to_pcicptr(dev->bus); | ||
500 | |||
501 | if (!pcicptr) | ||
502 | return; | ||
503 | if (__raw_readl(&pcicptr->pbacfg) & TX4927_PCIC_PBACFG_PBAEN) { | ||
504 | /* Reset Bus Arbiter */ | ||
505 | __raw_writel(TX4927_PCIC_PBACFG_RPBA, &pcicptr->pbacfg); | ||
506 | /* | ||
507 | * swap reqBP and reqXP (raise priority of SLC90E66). | ||
508 | * SLC90E66(PCI-ISA bridge) is connected to REQ2 on | ||
509 | * PCI Backplane board. | ||
510 | */ | ||
511 | __raw_writel(0x72543610, &pcicptr->pbareqport); | ||
512 | __raw_writel(0, &pcicptr->pbabm); | ||
513 | /* Use Fixed ParkMaster (required by SLC90E66) */ | ||
514 | __raw_writel(TX4927_PCIC_PBACFG_FIXPA, &pcicptr->pbacfg); | ||
515 | /* Enable Bus Arbiter */ | ||
516 | __raw_writel(TX4927_PCIC_PBACFG_FIXPA | | ||
517 | TX4927_PCIC_PBACFG_PBAEN, | ||
518 | &pcicptr->pbacfg); | ||
519 | printk(KERN_INFO "PCI: Use Fixed Park Master (REQPORT %08x)\n", | ||
520 | __raw_readl(&pcicptr->pbareqport)); | ||
521 | } | ||
522 | } | ||
523 | #define PCI_DEVICE_ID_EFAR_SLC90E66_0 0x9460 | ||
524 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_0, | ||
525 | tx4927_quirk_slc90e66_bridge); | ||
526 | #endif | ||
diff --git a/arch/mips/pci/pci-tx4927.c b/arch/mips/pci/pci-tx4927.c index 27e86a09dd41..aaa900596792 100644 --- a/arch/mips/pci/pci-tx4927.c +++ b/arch/mips/pci/pci-tx4927.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/interrupt.h> | ||
18 | #include <asm/txx9/generic.h> | 19 | #include <asm/txx9/generic.h> |
19 | #include <asm/txx9/tx4927.h> | 20 | #include <asm/txx9/tx4927.h> |
20 | 21 | ||
@@ -81,3 +82,12 @@ int __init tx4927_pciclk66_setup(void) | |||
81 | pciclk = -1; | 82 | pciclk = -1; |
82 | return pciclk; | 83 | return pciclk; |
83 | } | 84 | } |
85 | |||
86 | void __init tx4927_setup_pcierr_irq(void) | ||
87 | { | ||
88 | if (request_irq(TXX9_IRQ_BASE + TX4927_IR_PCIERR, | ||
89 | tx4927_pcierr_interrupt, | ||
90 | IRQF_DISABLED, "PCI error", | ||
91 | (void *)TX4927_PCIC_REG)) | ||
92 | printk(KERN_WARNING "Failed to request irq for PCIERR\n"); | ||
93 | } | ||
diff --git a/arch/mips/pci/pci-tx4938.c b/arch/mips/pci/pci-tx4938.c index e5375511c2b7..60e2c52c2c5e 100644 --- a/arch/mips/pci/pci-tx4938.c +++ b/arch/mips/pci/pci-tx4938.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/pci.h> | 16 | #include <linux/pci.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/interrupt.h> | ||
18 | #include <asm/txx9/generic.h> | 19 | #include <asm/txx9/generic.h> |
19 | #include <asm/txx9/tx4938.h> | 20 | #include <asm/txx9/tx4938.h> |
20 | 21 | ||
@@ -132,3 +133,12 @@ int tx4938_pcic1_map_irq(const struct pci_dev *dev, u8 slot) | |||
132 | } | 133 | } |
133 | return -1; | 134 | return -1; |
134 | } | 135 | } |
136 | |||
137 | void __init tx4938_setup_pcierr_irq(void) | ||
138 | { | ||
139 | if (request_irq(TXX9_IRQ_BASE + TX4938_IR_PCIERR, | ||
140 | tx4927_pcierr_interrupt, | ||
141 | IRQF_DISABLED, "PCI error", | ||
142 | (void *)TX4927_PCIC_REG)) | ||
143 | printk(KERN_WARNING "Failed to request irq for PCIERR\n"); | ||
144 | } | ||
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 77bd5b68dc43..c7fe6ec621e6 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c | |||
@@ -328,7 +328,11 @@ EXPORT_SYMBOL(PCIBIOS_MIN_IO); | |||
328 | EXPORT_SYMBOL(PCIBIOS_MIN_MEM); | 328 | EXPORT_SYMBOL(PCIBIOS_MIN_MEM); |
329 | #endif | 329 | #endif |
330 | 330 | ||
331 | char *pcibios_setup(char *str) | 331 | char * (*pcibios_plat_setup)(char *str) __devinitdata; |
332 | |||
333 | char *__devinit pcibios_setup(char *str) | ||
332 | { | 334 | { |
335 | if (pcibios_plat_setup) | ||
336 | return pcibios_plat_setup(str); | ||
333 | return str; | 337 | return str; |
334 | } | 338 | } |