1/* 2 * arch/arm/mach-ks8695/pci.c 3 * 4 * Copyright (C) 2003, Micrel Semiconductors 5 * Copyright (C) 2006, Greg Ungerer <gerg@snapgear.com> 6 * Copyright (C) 2006, Ben Dooks 7 * Copyright (C) 2007, Andrew Victor 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24#include <linux/kernel.h> 25#include <linux/pci.h> 26#include <linux/mm.h> 27#include <linux/init.h> 28#include <linux/irq.h> 29#include <linux/delay.h> 30#include <linux/io.h> 31 32#include <asm/signal.h> 33#include <asm/mach/pci.h> 34#include <mach/hardware.h> 35 36#include <mach/devices.h> 37#include <mach/regs-pci.h> 38 39 40static int pci_dbg; 41 42static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsigned int where) 43{ 44 unsigned long pbca; 45 46 pbca = PBCA_ENABLE | (where & ~3); 47 pbca |= PCI_SLOT(devfn) << 11 ; 48 pbca |= PCI_FUNC(devfn) << 8; 49 pbca |= bus_nr << 16; 50 51 if (bus_nr == 0) { 52 /* use Type-0 transaction */ 53 __raw_writel(pbca, KS8695_PCI_VA + KS8695_PBCA); 54 } else { 55 /* use Type-1 transaction */ 56 __raw_writel(pbca | PBCA_TYPE1, KS8695_PCI_VA + KS8695_PBCA); 57 } 58} 59 60static void __iomem *ks8695_pci_map_bus(struct pci_bus *bus, unsigned int devfn, 61 int where) 62{ 63 ks8695_pci_setupconfig(bus->number, devfn, where); 64 return KS8695_PCI_VA + KS8695_PBCD; 65} 66 67static void ks8695_local_writeconfig(int where, u32 value) 68{ 69 ks8695_pci_setupconfig(0, 0, where); 70 __raw_writel(value, KS8695_PCI_VA + KS8695_PBCD); 71} 72 73static struct pci_ops ks8695_pci_ops = { 74 .map_bus = ks8695_pci_map_bus, 75 .read = pci_generic_config_read32, 76 .write = pci_generic_config_write32, 77}; 78 79static struct resource pci_mem = { 80 .name = "PCI Memory space", 81 .start = KS8695_PCIMEM_PA, 82 .end = KS8695_PCIMEM_PA + (KS8695_PCIMEM_SIZE - 1), 83 .flags = IORESOURCE_MEM, 84}; 85 86static struct resource pci_io = { 87 .name = "PCI IO space", 88 .start = KS8695_PCIIO_PA, 89 .end = KS8695_PCIIO_PA + (KS8695_PCIIO_SIZE - 1), 90 .flags = IORESOURCE_IO, 91}; 92 93static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys) 94{ 95 if (nr > 0) 96 return 0; 97 98 request_resource(&iomem_resource, &pci_mem); 99 request_resource(&ioport_resource, &pci_io); 100 101 pci_add_resource_offset(&sys->resources, &pci_io, sys->io_offset); 102 pci_add_resource_offset(&sys->resources, &pci_mem, sys->mem_offset); 103 104 /* Assign and enable processor bridge */ 105 ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA); 106 107 /* Enable bus-master & Memory Space access */ 108 ks8695_local_writeconfig(PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); 109 110 /* Set cache-line size & latency. */ 111 ks8695_local_writeconfig(PCI_CACHE_LINE_SIZE, (32 << 8) | (L1_CACHE_BYTES / sizeof(u32))); 112 113 /* Reserve PCI memory space for PCI-AHB resources */ 114 if (!request_mem_region(KS8695_PCIMEM_PA, SZ_64M, "PCI-AHB Bridge")) { 115 printk(KERN_ERR "Cannot allocate PCI-AHB Bridge memory.\n"); 116 return -EBUSY; 117 } 118 119 return 1; 120} 121 122static inline unsigned int size_mask(unsigned long size) 123{ 124 return (~size) + 1; 125} 126 127static int ks8695_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) 128{ 129 unsigned long pc = instruction_pointer(regs); 130 unsigned long instr = *(unsigned long *)pc; 131 unsigned long cmdstat; 132 133 cmdstat = __raw_readl(KS8695_PCI_VA + KS8695_CRCFCS); 134 135 printk(KERN_ERR "PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx [%s%s%s%s%s]\n", 136 addr, fsr, regs->ARM_pc, regs->ARM_lr, 137 cmdstat & (PCI_STATUS_SIG_TARGET_ABORT << 16) ? "GenTarget" : " ", 138 cmdstat & (PCI_STATUS_REC_TARGET_ABORT << 16) ? "RecvTarget" : " ", 139 cmdstat & (PCI_STATUS_REC_MASTER_ABORT << 16) ? "MasterAbort" : " ", 140 cmdstat & (PCI_STATUS_SIG_SYSTEM_ERROR << 16) ? "SysError" : " ", 141 cmdstat & (PCI_STATUS_DETECTED_PARITY << 16) ? "Parity" : " " 142 ); 143 144 __raw_writel(cmdstat, KS8695_PCI_VA + KS8695_CRCFCS); 145 146 /* 147 * If the instruction being executed was a read, 148 * make it look like it read all-ones. 149 */ 150 if ((instr & 0x0c100000) == 0x04100000) { 151 int reg = (instr >> 12) & 15; 152 unsigned long val; 153 154 if (instr & 0x00400000) 155 val = 255; 156 else 157 val = -1; 158 159 regs->uregs[reg] = val; 160 regs->ARM_pc += 4; 161 return 0; 162 } 163 164 if ((instr & 0x0e100090) == 0x00100090) { 165 int reg = (instr >> 12) & 15; 166 167 regs->uregs[reg] = -1; 168 regs->ARM_pc += 4; 169 return 0; 170 } 171 172 return 1; 173} 174 175static void __init ks8695_pci_preinit(void) 176{ 177 /* make software reset to avoid freeze if PCI bus was messed up */ 178 __raw_writel(0x80000000, KS8695_PCI_VA + KS8695_PBCS); 179 180 /* stage 1 initialization, subid, subdevice = 0x0001 */ 181 __raw_writel(0x00010001, KS8695_PCI_VA + KS8695_CRCSID); 182 183 /* stage 2 initialization */ 184 /* prefetch limits with 16 words, retry enable */ 185 __raw_writel(0x40000000, KS8695_PCI_VA + KS8695_PBCS); 186 187 /* configure memory mapping */ 188 __raw_writel(KS8695_PCIMEM_PA, KS8695_PCI_VA + KS8695_PMBA); 189 __raw_writel(size_mask(KS8695_PCIMEM_SIZE), KS8695_PCI_VA + KS8695_PMBAM); 190 __raw_writel(KS8695_PCIMEM_PA, KS8695_PCI_VA + KS8695_PMBAT); 191 __raw_writel(0, KS8695_PCI_VA + KS8695_PMBAC); 192 193 /* configure IO mapping */ 194 __raw_writel(KS8695_PCIIO_PA, KS8695_PCI_VA + KS8695_PIOBA); 195 __raw_writel(size_mask(KS8695_PCIIO_SIZE), KS8695_PCI_VA + KS8695_PIOBAM); 196 __raw_writel(KS8695_PCIIO_PA, KS8695_PCI_VA + KS8695_PIOBAT); 197 __raw_writel(0, KS8695_PCI_VA + KS8695_PIOBAC); 198 199 /* hook in fault handlers */ 200 hook_fault_code(8, ks8695_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); 201 hook_fault_code(10, ks8695_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); 202} 203 204static void ks8695_show_pciregs(void) 205{ 206 if (!pci_dbg) 207 return; 208 209 printk(KERN_INFO "PCI: CRCFID = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFID)); 210 printk(KERN_INFO "PCI: CRCFCS = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFCS)); 211 printk(KERN_INFO "PCI: CRCFRV = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFRV)); 212 printk(KERN_INFO "PCI: CRCFLT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFLT)); 213 printk(KERN_INFO "PCI: CRCBMA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCBMA)); 214 printk(KERN_INFO "PCI: CRCSID = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCSID)); 215 printk(KERN_INFO "PCI: CRCFIT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFIT)); 216 217 printk(KERN_INFO "PCI: PBM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PBM)); 218 printk(KERN_INFO "PCI: PBCS = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PBCS)); 219 220 printk(KERN_INFO "PCI: PMBA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBA)); 221 printk(KERN_INFO "PCI: PMBAC = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAC)); 222 printk(KERN_INFO "PCI: PMBAM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAM)); 223 printk(KERN_INFO "PCI: PMBAT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAT)); 224 225 printk(KERN_INFO "PCI: PIOBA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBA)); 226 printk(KERN_INFO "PCI: PIOBAC = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAC)); 227 printk(KERN_INFO "PCI: PIOBAM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAM)); 228 printk(KERN_INFO "PCI: PIOBAT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAT)); 229} 230 231 232static struct hw_pci ks8695_pci __initdata = { 233 .nr_controllers = 1, 234 .ops = &ks8695_pci_ops, 235 .preinit = ks8695_pci_preinit, 236 .setup = ks8695_pci_setup, 237 .postinit = NULL, 238 .map_irq = NULL, 239}; 240 241void __init ks8695_init_pci(struct ks8695_pci_cfg *cfg) 242{ 243 if (__raw_readl(KS8695_PCI_VA + KS8695_CRCFRV) & CFRV_GUEST) { 244 printk("PCI: KS8695 in guest mode, not initialising\n"); 245 return; 246 } 247 248 pcibios_min_io = 0; 249 pcibios_min_mem = 0; 250 251 printk(KERN_INFO "PCI: Initialising\n"); 252 ks8695_show_pciregs(); 253 254 /* set Mode */ 255 __raw_writel(cfg->mode << 29, KS8695_PCI_VA + KS8695_PBM); 256 257 ks8695_pci.map_irq = cfg->map_irq; /* board-specific map_irq method */ 258 259 pci_common_init(&ks8695_pci); 260} 261