// SPDX-License-Identifier: GPL-2.0 /* pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999, 2007 David S. Miller (davem@davemloft.net) * Copyright (C) 1998, 1999 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
*/
/* Helper function of IOMMU error checking, which checks out * the state of the streaming buffers. The IOMMU lock is * held when this is called. * * For the PCI error case we know which PBM (and thus which * streaming buffer) caused the error, but for the uncorrectable * error case we do not. So we always check both streaming caches.
*/ #define PSYCHO_STRBUF_CONTROL_A 0x2800UL #define PSYCHO_STRBUF_CONTROL_B 0x4800UL #define PSYCHO_STRBUF_CTRL_LPTR 0x00000000000000f0UL /* LRU Lock Pointer */ #define PSYCHO_STRBUF_CTRL_LENAB 0x0000000000000008UL /* LRU Lock Enable */ #define PSYCHO_STRBUF_CTRL_RRDIS 0x0000000000000004UL /* Rerun Disable */ #define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002UL /* Diagnostic Mode Enable */ #define PSYCHO_STRBUF_CTRL_ENAB 0x0000000000000001UL /* Streaming Buffer Enable */ #define PSYCHO_STRBUF_FLUSH_A 0x2808UL #define PSYCHO_STRBUF_FLUSH_B 0x4808UL #define PSYCHO_STRBUF_FSYNC_A 0x2810UL #define PSYCHO_STRBUF_FSYNC_B 0x4810UL #define PSYCHO_STC_DATA_A 0xb000UL #define PSYCHO_STC_DATA_B 0xc000UL #define PSYCHO_STC_ERR_A 0xb400UL #define PSYCHO_STC_ERR_B 0xc400UL #define PSYCHO_STC_TAG_A 0xb800UL #define PSYCHO_STC_TAG_B 0xc800UL #define PSYCHO_STC_LINE_A 0xb900UL #define PSYCHO_STC_LINE_B 0xc900UL
/* Uncorrectable Errors. Cause of the error and the address are * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors * relating to UPA interface transactions.
*/ #define PSYCHO_UE_AFSR 0x0030UL #define PSYCHO_UEAFSR_PPIO 0x8000000000000000UL /* Primary PIO is cause */ #define PSYCHO_UEAFSR_PDRD 0x4000000000000000UL /* Primary DVMA read is cause */ #define PSYCHO_UEAFSR_PDWR 0x2000000000000000UL /* Primary DVMA write is cause */ #define PSYCHO_UEAFSR_SPIO 0x1000000000000000UL /* Secondary PIO is cause */ #define PSYCHO_UEAFSR_SDRD 0x0800000000000000UL /* Secondary DVMA read is cause */ #define PSYCHO_UEAFSR_SDWR 0x0400000000000000UL /* Secondary DVMA write is cause*/ #define PSYCHO_UEAFSR_RESV1 0x03ff000000000000UL /* Reserved */ #define PSYCHO_UEAFSR_BMSK 0x0000ffff00000000UL /* Bytemask of failed transfer */ #define PSYCHO_UEAFSR_DOFF 0x00000000e0000000UL /* Doubleword Offset */ #define PSYCHO_UEAFSR_MID 0x000000001f000000UL /* UPA MID causing the fault */ #define PSYCHO_UEAFSR_BLK 0x0000000000800000UL /* Trans was block operation */ #define PSYCHO_UEAFSR_RESV2 0x00000000007fffffUL /* Reserved */ #define PSYCHO_UE_AFAR 0x0038UL
/* XXX Use syndrome and afar to print out module string just like * XXX UDB CE trap handler does... -DaveM
*/
printk("%s: syndrome[%02lx] bytemask[%04lx] dword_offset[%lx] " "UPA_MID[%02lx] was_block(%d)\n",
pbm->name,
(afsr & PSYCHO_CEAFSR_ESYND) >> 48UL,
(afsr & PSYCHO_CEAFSR_BMSK) >> 32UL,
(afsr & PSYCHO_CEAFSR_DOFF) >> 29UL,
(afsr & PSYCHO_CEAFSR_MID) >> 24UL,
((afsr & PSYCHO_CEAFSR_BLK) ? 1 : 0));
printk("%s: CE AFAR [%016lx]\n", pbm->name, afar);
printk("%s: CE Secondary errors [", pbm->name);
reported = 0; if (afsr & PSYCHO_CEAFSR_SPIO) {
reported++;
printk("(PIO)");
} if (afsr & PSYCHO_CEAFSR_SDRD) {
reported++;
printk("(DMA Read)");
} if (afsr & PSYCHO_CEAFSR_SDWR) {
reported++;
printk("(DMA Write)");
} if (!reported)
printk("(none)");
printk("]\n");
return IRQ_HANDLED;
}
/* PCI Errors. They are signalled by the PCI bus module since they * are associated with a specific bus segment.
*/ #define PSYCHO_PCI_AFSR_A 0x2010UL #define PSYCHO_PCI_AFSR_B 0x4010UL #define PSYCHO_PCI_AFAR_A 0x2018UL #define PSYCHO_PCI_AFAR_B 0x4018UL
/* Psycho interrupt property order is: * 0: PCIERR INO for this PBM * 1: UE ERR * 2: CE ERR * 3: POWER FAIL * 4: SPARE HARDWARE * 5: POWER MANAGEMENT
*/
if (op->archdata.num_irqs < 6) return;
/* We really mean to ignore the return result here. Two * PCI controller share the same interrupt numbers and * drive the same front-end hardware.
*/
err = request_irq(op->archdata.irqs[1], psycho_ue_intr, IRQF_SHARED, "PSYCHO_UE", pbm);
err = request_irq(op->archdata.irqs[2], psycho_ce_intr, IRQF_SHARED, "PSYCHO_CE", pbm);
/* This one, however, ought not to fail. We can just warn * about it since the system can still operate properly even * if this fails.
*/
err = request_irq(op->archdata.irqs[0], psycho_pcierr_intr, IRQF_SHARED, "PSYCHO_PCIERR", pbm); if (err)
printk(KERN_WARNING "%s: Could not register PCIERR, " "err=%d\n", pbm->name, err);
/* Enable UE and CE interrupts for controller. */
upa_writeq((PSYCHO_ECCCTRL_EE |
PSYCHO_ECCCTRL_UE |
PSYCHO_ECCCTRL_CE), base + PSYCHO_ECC_CTRL);
/* Enable PCI Error interrupts and clear error * bits for each PBM.
*/
tmp = upa_readq(base + PSYCHO_PCIA_CTRL);
tmp |= (PSYCHO_PCICTRL_SERR |
PSYCHO_PCICTRL_SBH_ERR |
PSYCHO_PCICTRL_EEN);
tmp &= ~(PSYCHO_PCICTRL_SBH_INT);
upa_writeq(tmp, base + PSYCHO_PCIA_CTRL);
/* PSYCHO boot time probing and initialization. */ staticvoid pbm_config_busmastering(struct pci_pbm_info *pbm)
{
u8 *addr;
/* Set cache-line size to 64 bytes, this is actually * a nop but I do it for completeness.
*/
addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno,
0, PCI_CACHE_LINE_SIZE);
pci_config_write8(addr, 64 / sizeof(u32));
/* Set PBM latency timer to 64 PCI clocks. */
addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno,
0, PCI_LATENCY_TIMER);
pci_config_write8(addr, 64);
}
/* Enable the streaming buffer. We have to be careful * just in case OBP left it with LRU locking enabled. * * It is possible to control if PBM will be rerun on * line misses. Currently I just retain whatever setting * OBP left us with. All checks so far show it having * a value of zero.
*/ #undef PSYCHO_STRBUF_RERUN_ENABLE #undef PSYCHO_STRBUF_RERUN_DISABLE
control = upa_readq(pbm->stc.strbuf_control);
control |= PSYCHO_STRBUF_CTRL_ENAB;
control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR); #ifdef PSYCHO_STRBUF_RERUN_ENABLE
control &= ~(PSYCHO_STRBUF_CTRL_RRDIS); #else #ifdef PSYCHO_STRBUF_RERUN_DISABLE
control |= PSYCHO_STRBUF_CTRL_RRDIS; #endif #endif
upa_writeq(control, pbm->stc.strbuf_control);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.