patch-2.4.23 linux-2.4.23/arch/sparc64/kernel/pci_psycho.c
Next file: linux-2.4.23/arch/sparc64/kernel/pci_sabre.c
Previous file: linux-2.4.23/arch/sparc64/kernel/pci_iommu.c
Back to the patch index
Back to the overall index
- Lines: 318
- Date:
2003-11-28 10:26:19.000000000 -0800
- Orig file:
linux-2.4.22/arch/sparc64/kernel/pci_psycho.c
- Orig date:
2002-08-02 17:39:43.000000000 -0700
diff -urN linux-2.4.22/arch/sparc64/kernel/pci_psycho.c linux-2.4.23/arch/sparc64/kernel/pci_psycho.c
@@ -388,7 +388,6 @@
struct pci_dev *pdev,
unsigned int ino)
{
- struct pci_controller_info *p = pbm->parent;
struct ino_bucket *bucket;
unsigned long imap, iclr;
unsigned long imap_off, iclr_off;
@@ -413,11 +412,11 @@
if (PIL_RESERVED(pil))
BUG();
- imap = p->controller_regs + imap_off;
+ imap = pbm->controller_regs + imap_off;
imap += 4;
iclr_off = psycho_iclr_offset(ino);
- iclr = p->controller_regs + iclr_off;
+ iclr = pbm->controller_regs + iclr_off;
iclr += 4;
if ((ino & 0x20) == 0)
@@ -484,7 +483,7 @@
int is_pbm_a)
{
struct pci_strbuf *strbuf = &pbm->stc;
- unsigned long regbase = p->controller_regs;
+ unsigned long regbase = p->pbm_A.controller_regs;
unsigned long err_base, tag_base, line_base;
u64 control;
int i;
@@ -679,7 +678,7 @@
psycho_write(iommu->iommu_control,
control | PSYCHO_IOMMU_CTRL_DENAB);
for (i = 0; i < 16; i++) {
- unsigned long base = p->controller_regs;
+ unsigned long base = p->pbm_A.controller_regs;
iommu_tag[i] =
psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL));
@@ -756,8 +755,8 @@
static void psycho_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct pci_controller_info *p = dev_id;
- unsigned long afsr_reg = p->controller_regs + PSYCHO_UE_AFSR;
- unsigned long afar_reg = p->controller_regs + PSYCHO_UE_AFAR;
+ unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFSR;
+ unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_UE_AFAR;
unsigned long afsr, afar, error_bits;
int reported;
@@ -831,8 +830,8 @@
static void psycho_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct pci_controller_info *p = dev_id;
- unsigned long afsr_reg = p->controller_regs + PSYCHO_CE_AFSR;
- unsigned long afar_reg = p->controller_regs + PSYCHO_CE_AFAR;
+ unsigned long afsr_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFSR;
+ unsigned long afar_reg = p->pbm_A.controller_regs + PSYCHO_CE_AFAR;
unsigned long afsr, afar, error_bits;
int reported;
@@ -911,6 +910,42 @@
#define PSYCHO_PCI_AFAR_A 0x2018UL
#define PSYCHO_PCI_AFAR_B 0x4018UL
+static void psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm_a)
+{
+ unsigned long csr_reg, csr, csr_error_bits;
+ u16 stat;
+
+ if (is_pbm_a) {
+ csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL;
+ } else {
+ csr_reg = pbm->controller_regs + PSYCHO_PCIB_CTRL;
+ }
+ csr = psycho_read(csr_reg);
+ csr_error_bits =
+ csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR);
+ if (csr_error_bits) {
+ /* Clear the errors. */
+ psycho_write(csr_reg, csr);
+
+ /* Log 'em. */
+ if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR)
+ printk("%s: PCI streaming byte hole error asserted.\n",
+ pbm->name);
+ if (csr_error_bits & PSYCHO_PCICTRL_SERR)
+ printk("%s: PCI SERR signal asserted.\n", pbm->name);
+ }
+ pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat);
+ if (stat & (PCI_STATUS_PARITY |
+ PCI_STATUS_SIG_TARGET_ABORT |
+ PCI_STATUS_REC_TARGET_ABORT |
+ PCI_STATUS_REC_MASTER_ABORT |
+ PCI_STATUS_SIG_SYSTEM_ERROR)) {
+ printk("%s: PCI bus error, PCI_STATUS[%04x]\n",
+ pbm->name, stat);
+ pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff);
+ }
+}
+
static void psycho_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
{
struct pci_pbm_info *pbm = dev_id;
@@ -921,11 +956,11 @@
is_pbm_a = (pbm == &pbm->parent->pbm_A);
if (is_pbm_a) {
- afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_A;
- afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_A;
+ afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A;
+ afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A;
} else {
- afsr_reg = p->controller_regs + PSYCHO_PCI_AFSR_B;
- afar_reg = p->controller_regs + PSYCHO_PCI_AFAR_B;
+ afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B;
+ afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B;
}
/* Latch error status. */
@@ -939,7 +974,7 @@
PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA |
PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR);
if (!error_bits)
- return;
+ return psycho_pcierr_intr_other(pbm, is_pbm_a);
psycho_write(afsr_reg, error_bits);
/* Log the error. */
@@ -1022,8 +1057,8 @@
static void __init psycho_register_error_handlers(struct pci_controller_info *p)
{
struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
- unsigned long base = p->controller_regs;
- unsigned int irq, portid = p->portid;
+ unsigned long base = p->pbm_A.controller_regs;
+ unsigned int irq, portid = pbm->portid;
u64 tmp;
/* Build IRQs and register handlers. */
@@ -1043,6 +1078,7 @@
prom_halt();
}
+ pbm = &p->pbm_A;
irq = psycho_irq_build(pbm, NULL, (portid << 6) | PSYCHO_PCIERR_A_INO);
if (request_irq(irq, psycho_pcierr_intr,
SA_SHIRQ, "PSYCHO PCIERR", &p->pbm_A) < 0) {
@@ -1051,6 +1087,7 @@
prom_halt();
}
+ pbm = &p->pbm_B;
irq = psycho_irq_build(pbm, NULL, (portid << 6) | PSYCHO_PCIERR_B_INO);
if (request_irq(irq, psycho_pcierr_intr,
SA_SHIRQ, "PSYCHO PCIERR", &p->pbm_B) < 0) {
@@ -1310,26 +1347,26 @@
iommu->iommu_cur_ctx = 0;
/* Register addresses. */
- iommu->iommu_control = p->controller_regs + PSYCHO_IOMMU_CONTROL;
- iommu->iommu_tsbbase = p->controller_regs + PSYCHO_IOMMU_TSBBASE;
- iommu->iommu_flush = p->controller_regs + PSYCHO_IOMMU_FLUSH;
+ iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
+ iommu->iommu_tsbbase = p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE;
+ iommu->iommu_flush = p->pbm_A.controller_regs + PSYCHO_IOMMU_FLUSH;
/* PSYCHO's IOMMU lacks ctx flushing. */
iommu->iommu_ctxflush = 0;
/* We use the main control register of PSYCHO as the write
* completion register.
*/
- iommu->write_complete_reg = p->controller_regs + PSYCHO_CONTROL;
+ iommu->write_complete_reg = p->pbm_A.controller_regs + PSYCHO_CONTROL;
/*
* Invalidate TLB Entries.
*/
- control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+ control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL);
control |= PSYCHO_IOMMU_CTRL_DENAB;
- psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control);
for(i = 0; i < 16; i++) {
- psycho_write(p->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
- psycho_write(p->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
}
/* Leave diag mode enabled for full-flushing done
@@ -1360,16 +1397,16 @@
iommu->alloc_info[i].next = 0;
}
- psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
- control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
+ control = psycho_read(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL);
control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ);
control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB);
- psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL, control);
/* If necessary, hook us up for starfire IRQ translations. */
if(this_is_starfire)
- p->starfire_cookie = starfire_hookup(p->portid);
+ p->starfire_cookie = starfire_hookup(p->pbm_A.portid);
else
p->starfire_cookie = NULL;
}
@@ -1391,28 +1428,28 @@
u64 tmp;
/* PROM sets the IRQ retry value too low, increase it. */
- psycho_write(p->controller_regs + PSYCHO_IRQ_RETRY, 0xff);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_IRQ_RETRY, 0xff);
/* Enable arbiter for all PCI slots. */
- tmp = psycho_read(p->controller_regs + PSYCHO_PCIA_CTRL);
+ tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL);
tmp |= PSYCHO_PCICTRL_AEN;
- psycho_write(p->controller_regs + PSYCHO_PCIA_CTRL, tmp);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_CTRL, tmp);
- tmp = psycho_read(p->controller_regs + PSYCHO_PCIB_CTRL);
+ tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL);
tmp |= PSYCHO_PCICTRL_AEN;
- psycho_write(p->controller_regs + PSYCHO_PCIB_CTRL, tmp);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_CTRL, tmp);
/* Disable DMA write / PIO read synchronization on
* both PCI bus segments.
* [ U2P Erratum 1243770, STP2223BGA data sheet ]
*/
- tmp = psycho_read(p->controller_regs + PSYCHO_PCIA_DIAG);
+ tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG);
tmp |= PSYCHO_PCIDIAG_DDWSYNC;
- psycho_write(p->controller_regs + PSYCHO_PCIA_DIAG, tmp);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIA_DIAG, tmp);
- tmp = psycho_read(p->controller_regs + PSYCHO_PCIB_DIAG);
+ tmp = psycho_read(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG);
tmp |= PSYCHO_PCIDIAG_DDWSYNC;
- psycho_write(p->controller_regs + PSYCHO_PCIB_DIAG, tmp);
+ psycho_write(p->pbm_A.controller_regs + PSYCHO_PCIB_DIAG, tmp);
}
static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
@@ -1435,7 +1472,7 @@
struct pci_pbm_info *pbm,
int is_pbm_a)
{
- unsigned long base = p->controller_regs;
+ unsigned long base = pbm->controller_regs;
u64 control;
if (is_pbm_a) {
@@ -1500,14 +1537,21 @@
if (is_pbm_a) {
pbm = &p->pbm_A;
pbm->pci_first_slot = 1;
- pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_A;
- pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_A;
+ pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_A;
+ pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_A;
} else {
pbm = &p->pbm_B;
pbm->pci_first_slot = 2;
- pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_B;
- pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_B;
+ pbm->io_space.start = pbm->controller_regs + PSYCHO_IOSPACE_B;
+ pbm->mem_space.start = pbm->controller_regs + PSYCHO_MEMSPACE_B;
}
+
+ pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
+ pbm->chip_version =
+ prom_getintdefault(prom_node, "version#", 0);
+ pbm->chip_revision =
+ prom_getintdefault(prom_node, "module-revision#", 0);
+
pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
pbm->io_space.flags = IORESOURCE_IO;
pbm->mem_space.end = pbm->mem_space.start + PSYCHO_MEMSPACE_SIZE;
@@ -1575,7 +1619,7 @@
spin_lock_irqsave(&pci_controller_lock, flags);
for(p = pci_controller_root; p; p = p->next) {
- if (p->portid == upa_portid) {
+ if (p->pbm_A.portid == upa_portid) {
spin_unlock_irqrestore(&pci_controller_lock, flags);
is_pbm_a = (p->pbm_A.prom_node == 0);
psycho_pbm_init(p, node, is_pbm_a);
@@ -1603,7 +1647,8 @@
pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags);
- p->portid = upa_portid;
+ p->pbm_A.portid = upa_portid;
+ p->pbm_B.portid = upa_portid;
p->index = pci_num_controllers++;
p->pbms_same_domain = 0;
p->scan_bus = psycho_scan_bus;
@@ -1620,9 +1665,10 @@
prom_halt();
}
- p->controller_regs = pr_regs[2].phys_addr;
+ p->pbm_A.controller_regs = pr_regs[2].phys_addr;
+ p->pbm_B.controller_regs = pr_regs[2].phys_addr;
printk("PCI: Found PSYCHO, control regs at %016lx\n",
- p->controller_regs);
+ p->pbm_A.controller_regs);
p->pbm_A.config_space = p->pbm_B.config_space =
(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)