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; 41static int pci_cfg_dbg; 42 43 44static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsigned int where) 45{ 46 unsigned long pbca; 47 48 pbca = PBCA_ENABLE | (where & ~3); 49 pbca |= PCI_SLOT(devfn) << 11 ; 50 pbca |= PCI_FUNC(devfn) << 8; 51 pbca |= bus_nr << 16; 52 53 if (bus_nr == 0) { 54 /* use Type-0 transaction */ 55 __raw_writel(pbca, KS8695_PCI_VA + KS8695_PBCA); 56 } else { 57 /* use Type-1 transaction */ 58 __raw_writel(pbca | PBCA_TYPE1, KS8695_PCI_VA + KS8695_PBCA); 59 } 60} 61 62 63/* 64 * The KS8695 datasheet prohibits anything other than 32bit accesses 65 * to the IO registers, so all our configuration must be done with 66 * 32bit operations, and the correct bit masking and shifting. 67 */ 68 69static int ks8695_pci_readconfig(struct pci_bus *bus, 70 unsigned int devfn, int where, int size, u32 *value) 71{ 72 ks8695_pci_setupconfig(bus->number, devfn, where); 73 74 *value = __raw_readl(KS8695_PCI_VA + KS8695_PBCD); 75 76 switch (size) { 77 case 4: 78 break; 79 case 2: 80 *value = *value >> ((where & 2) * 8); 81 *value &= 0xffff; 82 break; 83 case 1: 84 *value = *value >> ((where & 3) * 8); 85 *value &= 0xff; 86 break; 87 } 88 89 if (pci_cfg_dbg) { 90 printk("read: %d,%08x,%02x,%d: %08x (%08x)\n", 91 bus->number, devfn, where, size, *value, 92 __raw_readl(KS8695_PCI_VA + KS8695_PBCD)); 93 } 94 95 return PCIBIOS_SUCCESSFUL; 96} 97 98static int ks8695_pci_writeconfig(struct pci_bus *bus, 99 unsigned int devfn, int where, int size, u32 value) 100{ 101 unsigned long tmp; 102 103 if (pci_cfg_dbg) { 104 printk("write: %d,%08x,%02x,%d: %08x\n", 105 bus->number, devfn, where, size, value); 106 } 107 108 ks8695_pci_setupconfig(bus->number, devfn, where); 109 110 switch (size) { 111 case 4: 112 __raw_writel(value, KS8695_PCI_VA + KS8695_PBCD); 113 break; 114 case 2: 115 tmp = __raw_readl(KS8695_PCI_VA + KS8695_PBCD); 116 tmp &= ~(0xffff << ((where & 2) * 8)); 117 tmp |= value << ((where & 2) * 8); 118 119 __raw_writel(tmp, KS8695_PCI_VA + KS8695_PBCD); 120 break; 121 case 1: 122 tmp = __raw_readl(KS8695_PCI_VA + KS8695_PBCD); 123 tmp &= ~(0xff << ((where & 3) * 8)); 124 tmp |= value << ((where & 3) * 8); 125 126 __raw_writel(tmp, KS8695_PCI_VA + KS8695_PBCD); 127 break; 128 } 129 130 return PCIBIOS_SUCCESSFUL; 131} 132 133static void ks8695_local_writeconfig(int where, u32 value) 134{ 135 ks8695_pci_setupconfig(0, 0, where); 136 __raw_writel(value, KS8695_PCI_VA + KS8695_PBCD); 137} 138 139static struct pci_ops ks8695_pci_ops = { 140 .read = ks8695_pci_readconfig, 141 .write = ks8695_pci_writeconfig, 142}; 143 144static struct pci_bus* __init ks8695_pci_scan_bus(int nr, struct pci_sys_data *sys) 145{ 146 return pci_scan_bus(sys->busnr, &ks8695_pci_ops, sys); 147} 148 149static struct resource pci_mem = { 150 .name = "PCI Memory space", 151 .start = KS8695_PCIMEM_PA, 152 .end = KS8695_PCIMEM_PA + (KS8695_PCIMEM_SIZE - 1), 153 .flags = IORESOURCE_MEM, 154}; 155 156static struct resource pci_io = { 157 .name = "PCI IO space", 158 .start = KS8695_PCIIO_PA, 159 .end = KS8695_PCIIO_PA + (KS8695_PCIIO_SIZE - 1), 160 .flags = IORESOURCE_IO, 161}; 162 163static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys) 164{ 165 if (nr > 0) 166 return 0; 167 168 request_resource(&iomem_resource, &pci_mem); 169 request_resource(&ioport_resource, &pci_io); 170 171 sys->resource[0] = &pci_io; 172 sys->resource[1] = &pci_mem; 173 sys->resource[2] = NULL; 174 175 /* Assign and enable processor bridge */ 176 ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA); 177 178 /* Enable bus-master & Memory Space access */ 179 ks8695_local_writeconfig(PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); 180 181 /* Set cache-line size & latency. */ 182 ks8695_local_writeconfig(PCI_CACHE_LINE_SIZE, (32 << 8) | (L1_CACHE_BYTES / sizeof(u32))); 183 184 /* Reserve PCI memory space for PCI-AHB resources */ 185 if (!request_mem_region(KS8695_PCIMEM_PA, SZ_64M, "PCI-AHB Bridge")) { 186 printk(KERN_ERR "Cannot allocate PCI-AHB Bridge memory.\n"); 187 return -EBUSY; 188 } 189 190 return 1; 191} 192 193static inline unsigned int size_mask(unsigned long size) 194{ 195 return (~size) + 1; 196} 197 198static int ks8695_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) 199{ 200 unsigned long pc = instruction_pointer(regs); 201 unsigned long instr = *(unsigned long *)pc; 202 unsigned long cmdstat; 203 204 cmdstat = __raw_readl(KS8695_PCI_VA + KS8695_CRCFCS); 205 206 printk(KERN_ERR "PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx [%s%s%s%s%s]\n", 207 addr, fsr, regs->ARM_pc, regs->ARM_lr, 208 cmdstat & (PCI_STATUS_SIG_TARGET_ABORT << 16) ? "GenTarget" : " ", 209 cmdstat & (PCI_STATUS_REC_TARGET_ABORT << 16) ? "RecvTarget" : " ", 210 cmdstat & (PCI_STATUS_REC_MASTER_ABORT << 16) ? "MasterAbort" : " ", 211 cmdstat & (PCI_STATUS_SIG_SYSTEM_ERROR << 16) ? "SysError" : " ", 212 cmdstat & (PCI_STATUS_DETECTED_PARITY << 16) ? "Parity" : " " 213 ); 214 215 __raw_writel(cmdstat, KS8695_PCI_VA + KS8695_CRCFCS); 216 217 /* 218 * If the instruction being executed was a read, 219 * make it look like it read all-ones. 220 */ 221 if ((instr & 0x0c100000) == 0x04100000) { 222 int reg = (instr >> 12) & 15; 223 unsigned long val; 224 225 if (instr & 0x00400000) 226 val = 255; 227 else 228 val = -1; 229 230 regs->uregs[reg] = val; 231 regs->ARM_pc += 4; 232 return 0; 233 } 234 235 if ((instr & 0x0e100090) == 0x00100090) { 236 int reg = (instr >> 12) & 15; 237 238 regs->uregs[reg] = -1; 239 regs->ARM_pc += 4; 240 return 0; 241 } 242 243 return 1; 244} 245 246static void __init ks8695_pci_preinit(void) 247{ 248 /* make software reset to avoid freeze if PCI bus was messed up */ 249 __raw_writel(0x80000000, KS8695_PCI_VA + KS8695_PBCS); 250 251 /* stage 1 initialization, subid, subdevice = 0x0001 */ 252 __raw_writel(0x00010001, KS8695_PCI_VA + KS8695_CRCSID); 253 254 /* stage 2 initialization */ 255 /* prefetch limits with 16 words, retry enable */ 256 __raw_writel(0x40000000, KS8695_PCI_VA + KS8695_PBCS); 257 258 /* configure memory mapping */ 259 __raw_writel(KS8695_PCIMEM_PA, KS8695_PCI_VA + KS8695_PMBA); 260 __raw_writel(size_mask(KS8695_PCIMEM_SIZE), KS8695_PCI_VA + KS8695_PMBAM); 261 __raw_writel(KS8695_PCIMEM_PA, KS8695_PCI_VA + KS8695_PMBAT); 262 __raw_writel(0, KS8695_PCI_VA + KS8695_PMBAC); 263 264 /* configure IO mapping */ 265 __raw_writel(KS8695_PCIIO_PA, KS8695_PCI_VA + KS8695_PIOBA); 266 __raw_writel(size_mask(KS8695_PCIIO_SIZE), KS8695_PCI_VA + KS8695_PIOBAM); 267 __raw_writel(KS8695_PCIIO_PA, KS8695_PCI_VA + KS8695_PIOBAT); 268 __raw_writel(0, KS8695_PCI_VA + KS8695_PIOBAC); 269 270 /* hook in fault handlers */ 271 hook_fault_code(8, ks8695_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); 272 hook_fault_code(10, ks8695_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); 273} 274 275static void ks8695_show_pciregs(void) 276{ 277 if (!pci_dbg) 278 return; 279 280 printk(KERN_INFO "PCI: CRCFID = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFID)); 281 printk(KERN_INFO "PCI: CRCFCS = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFCS)); 282 printk(KERN_INFO "PCI: CRCFRV = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFRV)); 283 printk(KERN_INFO "PCI: CRCFLT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFLT)); 284 printk(KERN_INFO "PCI: CRCBMA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCBMA)); 285 printk(KERN_INFO "PCI: CRCSID = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCSID)); 286 printk(KERN_INFO "PCI: CRCFIT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_CRCFIT)); 287 288 printk(KERN_INFO "PCI: PBM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PBM)); 289 printk(KERN_INFO "PCI: PBCS = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PBCS)); 290 291 printk(KERN_INFO "PCI: PMBA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBA)); 292 printk(KERN_INFO "PCI: PMBAC = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAC)); 293 printk(KERN_INFO "PCI: PMBAM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAM)); 294 printk(KERN_INFO "PCI: PMBAT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PMBAT)); 295 296 printk(KERN_INFO "PCI: PIOBA = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBA)); 297 printk(KERN_INFO "PCI: PIOBAC = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAC)); 298 printk(KERN_INFO "PCI: PIOBAM = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAM)); 299 printk(KERN_INFO "PCI: PIOBAT = %08x\n", __raw_readl(KS8695_PCI_VA + KS8695_PIOBAT)); 300} 301 302 303static struct hw_pci ks8695_pci __initdata = { 304 .nr_controllers = 1, 305 .preinit = ks8695_pci_preinit, 306 .setup = ks8695_pci_setup, 307 .scan = ks8695_pci_scan_bus, 308 .postinit = NULL, 309 .swizzle = pci_std_swizzle, 310 .map_irq = NULL, 311}; 312 313void __init ks8695_init_pci(struct ks8695_pci_cfg *cfg) 314{ 315 if (__raw_readl(KS8695_PCI_VA + KS8695_CRCFRV) & CFRV_GUEST) { 316 printk("PCI: KS8695 in guest mode, not initialising\n"); 317 return; 318 } 319 320 printk(KERN_INFO "PCI: Initialising\n"); 321 ks8695_show_pciregs(); 322 323 /* set Mode */ 324 __raw_writel(cfg->mode << 29, KS8695_PCI_VA + KS8695_PBM); 325 326 ks8695_pci.map_irq = cfg->map_irq; /* board-specific map_irq method */ 327 328 pci_common_init(&ks8695_pci); 329} 330