|
@@ -202,3 +202,124 @@ static int ks8695_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs
|
|
|
cmdstat & (PCI_STATUS_SIG_TARGET_ABORT << 16) ? "GenTarget" : " ",
|
|
|
cmdstat & (PCI_STATUS_REC_TARGET_ABORT << 16) ? "RecvTarget" : " ",
|
|
|
cmdstat & (PCI_STATUS_REC_MASTER_ABORT << 16) ? "MasterAbort" : " ",
|
|
|
+ cmdstat & (PCI_STATUS_SIG_SYSTEM_ERROR << 16) ? "SysError" : " ",
|
|
|
+ cmdstat & (PCI_STATUS_DETECTED_PARITY << 16) ? "Parity" : " "
|
|
|
+ );
|
|
|
+
|
|
|
+ __raw_writel(cmdstat, KS8695_PCI_VA + KS8695_CRCFCS);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the instruction being executed was a read,
|
|
|
+ * make it look like it read all-ones.
|
|
|
+ */
|
|
|
+ if ((instr & 0x0c100000) == 0x04100000) {
|
|
|
+ int reg = (instr >> 12) & 15;
|
|
|
+ unsigned long val;
|
|
|
+
|
|
|
+ if (instr & 0x00400000)
|
|
|
+ val = 255;
|
|
|
+ else
|
|
|
+ val = -1;
|
|
|
+
|
|
|
+ regs->uregs[reg] = val;
|
|
|
+ regs->ARM_pc += 4;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((instr & 0x0e100090) == 0x00100090) {
|
|
|
+ int reg = (instr >> 12) & 15;
|
|
|
+
|
|
|
+ regs->uregs[reg] = -1;
|
|
|
+ regs->ARM_pc += 4;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static void __init ks8695_pci_preinit(void)
|
|
|
+{
|
|
|
+ /* make software reset to avoid freeze if PCI bus was messed up */
|
|
|
+ __raw_writel(0x80000000, KS8695_PCI_VA + KS8695_PBCS);
|
|
|
+
|
|
|
+ /* stage 1 initialization, subid, subdevice = 0x0001 */
|
|
|
+ __raw_writel(0x00010001, KS8695_PCI_VA + KS8695_CRCSID);
|
|
|
+
|
|
|
+ /* stage 2 initialization */
|
|
|
+ /* prefetch limits with 16 words, retry enable */
|
|
|
+ __raw_writel(0x40000000, KS8695_PCI_VA + KS8695_PBCS);
|
|
|
+
|
|
|
+ /* configure memory mapping */
|
|
|
+ __raw_writel(KS8695_PCIMEM_PA, KS8695_PCI_VA + KS8695_PMBA);
|
|
|
+ __raw_writel(size_mask(KS8695_PCIMEM_SIZE), KS8695_PCI_VA + KS8695_PMBAM);
|
|
|
+ __raw_writel(KS8695_PCIMEM_PA, KS8695_PCI_VA + KS8695_PMBAT);
|
|
|
+ __raw_writel(0, KS8695_PCI_VA + KS8695_PMBAC);
|
|
|
+
|
|
|
+ /* configure IO mapping */
|
|
|
+ __raw_writel(KS8695_PCIIO_PA, KS8695_PCI_VA + KS8695_PIOBA);
|
|
|
+ __raw_writel(size_mask(KS8695_PCIIO_SIZE), KS8695_PCI_VA + KS8695_PIOBAM);
|
|
|
+ __raw_writel(KS8695_PCIIO_PA, KS8695_PCI_VA + KS8695_PIOBAT);
|
|
|
+ __raw_writel(0, KS8695_PCI_VA + KS8695_PIOBAC);
|
|
|
+
|
|
|
+ /* hook in fault handlers */
|
|
|
+ hook_fault_code(8, ks8695_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
|
|
|
+ hook_fault_code(10, ks8695_pci_fault, SIGBUS, 0, "external abort on non-linefetch");
|
|
|
+}
|
|
|
+
|
|
|
+static void ks8695_show_pciregs(void)
|
|
|
+{
|
|
|
+ if (!pci_dbg)
|
|
|
+ return;
|
|
|
+
|
|
|
+ printk(KERN_INFO "PCI: CRCFID = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFID));
|
|
|
+ printk(KERN_INFO "PCI: CRCFCS = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFCS));
|
|
|
+ printk(KERN_INFO "PCI: CRCFRV = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFRV));
|
|
|
+ printk(KERN_INFO "PCI: CRCFLT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFLT));
|
|
|
+ printk(KERN_INFO "PCI: CRCBMA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCBMA));
|
|
|
+ printk(KERN_INFO "PCI: CRCSID = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCSID));
|
|
|
+ printk(KERN_INFO "PCI: CRCFIT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFIT));
|
|
|
+
|
|
|
+ printk(KERN_INFO "PCI: PBM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PBM));
|
|
|
+ printk(KERN_INFO "PCI: PBCS = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PBCS));
|
|
|
+
|
|
|
+ printk(KERN_INFO "PCI: PMBA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBA));
|
|
|
+ printk(KERN_INFO "PCI: PMBAC = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAC));
|
|
|
+ printk(KERN_INFO "PCI: PMBAM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAM));
|
|
|
+ printk(KERN_INFO "PCI: PMBAT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAT));
|
|
|
+
|
|
|
+ printk(KERN_INFO "PCI: PIOBA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBA));
|
|
|
+ printk(KERN_INFO "PCI: PIOBAC = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAC));
|
|
|
+ printk(KERN_INFO "PCI: PIOBAM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAM));
|
|
|
+ printk(KERN_INFO "PCI: PIOBAT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAT));
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static struct hw_pci ks8695_pci __initdata = {
|
|
|
+ .nr_controllers = 1,
|
|
|
+ .ops = &ks8695_pci_ops,
|
|
|
+ .preinit = ks8695_pci_preinit,
|
|
|
+ .setup = ks8695_pci_setup,
|
|
|
+ .postinit = NULL,
|
|
|
+ .map_irq = NULL,
|
|
|
+};
|
|
|
+
|
|
|
+void __init ks8695_init_pci(struct ks8695_pci_cfg *cfg)
|
|
|
+{
|
|
|
+ if (__raw_readl(KS8695_PCI_VA + KS8695_CRCFRV) & CFRV_GUEST) {
|
|
|
+ printk("PCI: KS8695 in guest mode, not initialising\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ pcibios_min_io = 0;
|
|
|
+ pcibios_min_mem = 0;
|
|
|
+
|
|
|
+ printk(KERN_INFO "PCI: Initialising\n");
|
|
|
+ ks8695_show_pciregs();
|
|
|
+
|
|
|
+ /* set Mode */
|
|
|
+ __raw_writel(cfg->mode << 29, KS8695_PCI_VA + KS8695_PBM);
|
|
|
+
|
|
|
+ ks8695_pci.map_irq = cfg->map_irq; /* board-specific map_irq method */
|
|
|
+
|
|
|
+ pci_common_init(&ks8695_pci);
|
|
|
+}
|