arch/sh/drivers/pci/pci-sh7780.c

Source file repositories/reference/linux-study-clean/arch/sh/drivers/pci/pci-sh7780.c

File Facts

System
Linux kernel
Corpus path
arch/sh/drivers/pci/pci-sh7780.c
Extension
.c
Size
11184 bytes
Lines
408
Domain
Architecture Layer
Bucket
arch/sh
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct pci_errors {
	unsigned int	mask;
	const char	*str;
} pci_arbiter_errors[] = {
	{ SH4_PCIAINT_MBKN,	"master broken" },
	{ SH4_PCIAINT_TBTO,	"target bus time out" },
	{ SH4_PCIAINT_MBTO,	"master bus time out" },
	{ SH4_PCIAINT_TABT,	"target abort" },
	{ SH4_PCIAINT_MABT,	"master abort" },
	{ SH4_PCIAINT_RDPE,	"read data parity error" },
	{ SH4_PCIAINT_WDPE,	"write data parity error" },
}, pci_interrupt_errors[] = {
	{ SH4_PCIINT_MLCK,	"master lock error" },
	{ SH4_PCIINT_TABT,	"target-target abort" },
	{ SH4_PCIINT_TRET,	"target retry time out" },
	{ SH4_PCIINT_MFDE,	"master function disable error" },
	{ SH4_PCIINT_PRTY,	"address parity error" },
	{ SH4_PCIINT_SERR,	"SERR" },
	{ SH4_PCIINT_TWDP,	"data parity error for target write" },
	{ SH4_PCIINT_TRDP,	"PERR detected for target read" },
	{ SH4_PCIINT_MTABT,	"target abort for master" },
	{ SH4_PCIINT_MMABT,	"master abort for master" },
	{ SH4_PCIINT_MWPD,	"master write data parity error" },
	{ SH4_PCIINT_MRPD,	"master read data parity error" },
};

static irqreturn_t sh7780_pci_err_irq(int irq, void *dev_id)
{
	struct pci_channel *hose = dev_id;
	unsigned long addr;
	unsigned int status;
	unsigned int cmd;
	int i;

	addr = __raw_readl(hose->reg_base + SH4_PCIALR);

	/*
	 * Handle status errors.
	 */
	status = __raw_readw(hose->reg_base + PCI_STATUS);
	if (status & (PCI_STATUS_PARITY |
		      PCI_STATUS_DETECTED_PARITY |
		      PCI_STATUS_SIG_TARGET_ABORT |
		      PCI_STATUS_REC_TARGET_ABORT |
		      PCI_STATUS_REC_MASTER_ABORT)) {
		cmd = pcibios_handle_status_errors(addr, status, hose);
		if (likely(cmd))
			__raw_writew(cmd, hose->reg_base + PCI_STATUS);
	}

	/*
	 * Handle arbiter errors.
	 */
	status = __raw_readl(hose->reg_base + SH4_PCIAINT);
	for (i = cmd = 0; i < ARRAY_SIZE(pci_arbiter_errors); i++) {
		if (status & pci_arbiter_errors[i].mask) {
			printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
			       pci_arbiter_errors[i].str, addr);
			cmd |= pci_arbiter_errors[i].mask;
		}
	}
	__raw_writel(cmd, hose->reg_base + SH4_PCIAINT);

	/*
	 * Handle the remaining PCI errors.
	 */
	status = __raw_readl(hose->reg_base + SH4_PCIINT);
	for (i = cmd = 0; i < ARRAY_SIZE(pci_interrupt_errors); i++) {
		if (status & pci_interrupt_errors[i].mask) {
			printk(KERN_DEBUG "PCI: %s, addr=%08lx\n",
			       pci_interrupt_errors[i].str, addr);
			cmd |= pci_interrupt_errors[i].mask;
		}
	}
	__raw_writel(cmd, hose->reg_base + SH4_PCIINT);

	return IRQ_HANDLED;
}

static irqreturn_t sh7780_pci_serr_irq(int irq, void *dev_id)
{
	struct pci_channel *hose = dev_id;

	printk(KERN_DEBUG "PCI: system error received: ");
	pcibios_report_status(PCI_STATUS_SIG_SYSTEM_ERROR, 1);
	pr_cont("\n");

	/* Deassert SERR */
	__raw_writel(SH4_PCIINTM_SDIM, hose->reg_base + SH4_PCIINTM);

Annotation

Implementation Notes