|
@@ -111,3 +111,94 @@ static int ks8695_pci_writeconfig(struct pci_bus *bus,
|
|
|
case 4:
|
|
|
__raw_writel(value, KS8695_PCI_VA + KS8695_PBCD);
|
|
|
break;
|
|
|
+ case 2:
|
|
|
+ tmp = __raw_readl(KS8695_PCI_VA + KS8695_PBCD);
|
|
|
+ tmp &= ~(0xffff << ((where & 2) * 8));
|
|
|
+ tmp |= value << ((where & 2) * 8);
|
|
|
+
|
|
|
+ __raw_writel(tmp, KS8695_PCI_VA + KS8695_PBCD);
|
|
|
+ break;
|
|
|
+ case 1:
|
|
|
+ tmp = __raw_readl(KS8695_PCI_VA + KS8695_PBCD);
|
|
|
+ tmp &= ~(0xff << ((where & 3) * 8));
|
|
|
+ tmp |= value << ((where & 3) * 8);
|
|
|
+
|
|
|
+ __raw_writel(tmp, KS8695_PCI_VA + KS8695_PBCD);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return PCIBIOS_SUCCESSFUL;
|
|
|
+}
|
|
|
+
|
|
|
+static void ks8695_local_writeconfig(int where, u32 value)
|
|
|
+{
|
|
|
+ ks8695_pci_setupconfig(0, 0, where);
|
|
|
+ __raw_writel(value, KS8695_PCI_VA + KS8695_PBCD);
|
|
|
+}
|
|
|
+
|
|
|
+static struct pci_ops ks8695_pci_ops = {
|
|
|
+ .read = ks8695_pci_readconfig,
|
|
|
+ .write = ks8695_pci_writeconfig,
|
|
|
+};
|
|
|
+
|
|
|
+static struct resource pci_mem = {
|
|
|
+ .name = "PCI Memory space",
|
|
|
+ .start = KS8695_PCIMEM_PA,
|
|
|
+ .end = KS8695_PCIMEM_PA + (KS8695_PCIMEM_SIZE - 1),
|
|
|
+ .flags = IORESOURCE_MEM,
|
|
|
+};
|
|
|
+
|
|
|
+static struct resource pci_io = {
|
|
|
+ .name = "PCI IO space",
|
|
|
+ .start = KS8695_PCIIO_PA,
|
|
|
+ .end = KS8695_PCIIO_PA + (KS8695_PCIIO_SIZE - 1),
|
|
|
+ .flags = IORESOURCE_IO,
|
|
|
+};
|
|
|
+
|
|
|
+static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys)
|
|
|
+{
|
|
|
+ if (nr > 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ request_resource(&iomem_resource, &pci_mem);
|
|
|
+ request_resource(&ioport_resource, &pci_io);
|
|
|
+
|
|
|
+ pci_add_resource_offset(&sys->resources, &pci_io, sys->io_offset);
|
|
|
+ pci_add_resource_offset(&sys->resources, &pci_mem, sys->mem_offset);
|
|
|
+
|
|
|
+ /* Assign and enable processor bridge */
|
|
|
+ ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA);
|
|
|
+
|
|
|
+ /* Enable bus-master & Memory Space access */
|
|
|
+ ks8695_local_writeconfig(PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
|
|
|
+
|
|
|
+ /* Set cache-line size & latency. */
|
|
|
+ ks8695_local_writeconfig(PCI_CACHE_LINE_SIZE, (32 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
|
|
|
+
|
|
|
+ /* Reserve PCI memory space for PCI-AHB resources */
|
|
|
+ if (!request_mem_region(KS8695_PCIMEM_PA, SZ_64M, "PCI-AHB Bridge")) {
|
|
|
+ printk(KERN_ERR "Cannot allocate PCI-AHB Bridge memory.\n");
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static inline unsigned int size_mask(unsigned long size)
|
|
|
+{
|
|
|
+ return (~size) + 1;
|
|
|
+}
|
|
|
+
|
|
|
+static int ks8695_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|
|
+{
|
|
|
+ unsigned long pc = instruction_pointer(regs);
|
|
|
+ unsigned long instr = *(unsigned long *)pc;
|
|
|
+ unsigned long cmdstat;
|
|
|
+
|
|
|
+ cmdstat = __raw_readl(KS8695_PCI_VA + KS8695_CRCFCS);
|
|
|
+
|
|
|
+ printk(KERN_ERR "PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx [%s%s%s%s%s]\n",
|
|
|
+ addr, fsr, regs->ARM_pc, regs->ARM_lr,
|
|
|
+ cmdstat & (PCI_STATUS_SIG_TARGET_ABORT << 16) ? "GenTarget" : " ",
|
|
|
+ cmdstat & (PCI_STATUS_REC_TARGET_ABORT << 16) ? "RecvTarget" : " ",
|
|
|
+ cmdstat & (PCI_STATUS_REC_MASTER_ABORT << 16) ? "MasterAbort" : " ",
|