1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * arch/arm/plat-iop/pci.c 4 * 5 * PCI support for the Intel IOP32X and IOP33X processors 6 * 7 * Author: Rory Bolt <rorybolt@pacbell.net> 8 * Copyright (C) 2002 Rory Bolt 9 */ 10 11#include <linux/kernel.h> 12#include <linux/pci.h> 13#include <linux/slab.h> 14#include <linux/mm.h> 15#include <linux/init.h> 16#include <linux/ioport.h> 17#include <linux/io.h> 18#include <asm/irq.h> 19#include <asm/signal.h> 20#include <asm/mach/pci.h> 21#include "hardware.h" 22#include "iop3xx.h" 23 24// #define DEBUG 25 26#ifdef DEBUG 27#define DBG(x...) printk(x) 28#else 29#define DBG(x...) do { } while (0) 30#endif 31 32/* 33 * This routine builds either a type0 or type1 configuration command. If the 34 * bus is on the 803xx then a type0 made, else a type1 is created. 35 */ 36static u32 iop3xx_cfg_address(struct pci_bus *bus, int devfn, int where) 37{ 38 struct pci_sys_data *sys = bus->sysdata; 39 u32 addr; 40 41 if (sys->busnr == bus->number) 42 addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11); 43 else 44 addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1; 45 46 addr |= PCI_FUNC(devfn) << 8 | (where & ~3); 47 48 return addr; 49} 50 51/* 52 * This routine checks the status of the last configuration cycle. If an error 53 * was detected it returns a 1, else it returns a 0. The errors being checked 54 * are parity, master abort, target abort (master and target). These types of 55 * errors occur during a config cycle where there is no device, like during 56 * the discovery stage. 57 */ 58static int iop3xx_pci_status(void) 59{ 60 unsigned int status; 61 int ret = 0; 62 63 /* 64 * Check the status registers. 65 */ 66 status = *IOP3XX_ATUSR; 67 if (status & 0xf900) { 68 DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status); 69 *IOP3XX_ATUSR = status & 0xf900; 70 ret = 1; 71 } 72 73 status = *IOP3XX_ATUISR; 74 if (status & 0x679f) { 75 DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status); 76 *IOP3XX_ATUISR = status & 0x679f; 77 ret = 1; 78 } 79 80 return ret; 81} 82 83/* 84 * Simply write the address register and read the configuration 85 * data. Note that the 4 nops ensure that we are able to handle 86 * a delayed abort (in theory.) 87 */ 88static u32 iop3xx_read(unsigned long addr) 89{ 90 u32 val; 91 92 __asm__ __volatile__( 93 "str %1, [%2]\n\t" 94 "ldr %0, [%3]\n\t" 95 "nop\n\t" 96 "nop\n\t" 97 "nop\n\t" 98 "nop\n\t" 99 : "=r" (val) 100 : "r" (addr), "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR)); 101 102 return val; 103} 104 105/* 106 * The read routines must check the error status of the last configuration 107 * cycle. If there was an error, the routine returns all hex f's. 108 */ 109static int 110iop3xx_read_config(struct pci_bus *bus, unsigned int devfn, int where, 111 int size, u32 *value) 112{ 113 unsigned long addr = iop3xx_cfg_address(bus, devfn, where); 114 u32 val = iop3xx_read(addr) >> ((where & 3) * 8); 115 116 if (iop3xx_pci_status()) 117 val = 0xffffffff; 118 119 *value = val; 120 121 return PCIBIOS_SUCCESSFUL; 122} 123 124static int 125iop3xx_write_config(struct pci_bus *bus, unsigned int devfn, int where, 126 int size, u32 value) 127{ 128 unsigned long addr = iop3xx_cfg_address(bus, devfn, where); 129 u32 val; 130 131 if (size != 4) { 132 val = iop3xx_read(addr); 133 if (iop3xx_pci_status()) 134 return PCIBIOS_SUCCESSFUL; 135 136 where = (where & 3) * 8; 137 138 if (size == 1) 139 val &= ~(0xff << where); 140 else 141 val &= ~(0xffff << where); 142 143 *IOP3XX_OCCDR = val | value << where; 144 } else { 145 asm volatile( 146 "str %1, [%2]\n\t" 147 "str %0, [%3]\n\t" 148 "nop\n\t" 149 "nop\n\t" 150 "nop\n\t" 151 "nop\n\t" 152 : 153 : "r" (value), "r" (addr), 154 "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR)); 155 } 156 157 return PCIBIOS_SUCCESSFUL; 158} 159 160struct pci_ops iop3xx_ops = { 161 .read = iop3xx_read_config, 162 .write = iop3xx_write_config, 163}; 164 165/* 166 * When a PCI device does not exist during config cycles, the 80200 gets a 167 * bus error instead of returning 0xffffffff. This handler simply returns. 168 */ 169static int 170iop3xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) 171{ 172 DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n", 173 addr, fsr, regs->ARM_pc, regs->ARM_lr); 174 175 /* 176 * If it was an imprecise abort, then we need to correct the 177 * return address to be _after_ the instruction. 178 */ 179 if (fsr & (1 << 10)) 180 regs->ARM_pc += 4; 181 182 return 0; 183} 184 185int iop3xx_pci_setup(int nr, struct pci_sys_data *sys) 186{ 187 struct resource *res; 188 189 if (nr != 0) 190 return 0; 191 192 res = kzalloc(sizeof(struct resource), GFP_KERNEL); 193 if (!res) 194 panic("PCI: unable to alloc resources"); 195 196 res->start = IOP3XX_PCI_LOWER_MEM_PA; 197 res->end = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE - 1; 198 res->name = "IOP3XX PCI Memory Space"; 199 res->flags = IORESOURCE_MEM; 200 request_resource(&iomem_resource, res); 201 202 /* 203 * Use whatever translation is already setup. 204 */ 205 sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0; 206 207 pci_add_resource_offset(&sys->resources, res, sys->mem_offset); 208 209 pci_ioremap_io(0, IOP3XX_PCI_LOWER_IO_PA); 210 211 return 1; 212} 213 214void __init iop3xx_atu_setup(void) 215{ 216 /* BAR 0 ( Disabled ) */ 217 *IOP3XX_IAUBAR0 = 0x0; 218 *IOP3XX_IABAR0 = 0x0; 219 *IOP3XX_IATVR0 = 0x0; 220 *IOP3XX_IALR0 = 0x0; 221 222 /* BAR 1 ( Disabled ) */ 223 *IOP3XX_IAUBAR1 = 0x0; 224 *IOP3XX_IABAR1 = 0x0; 225 *IOP3XX_IALR1 = 0x0; 226 227 /* BAR 2 (1:1 mapping with Physical RAM) */ 228 /* Set limit and enable */ 229 *IOP3XX_IALR2 = ~((u32)IOP3XX_MAX_RAM_SIZE - 1) & ~0x1; 230 *IOP3XX_IAUBAR2 = 0x0; 231 232 /* Align the inbound bar with the base of memory */ 233 *IOP3XX_IABAR2 = PHYS_OFFSET | 234 PCI_BASE_ADDRESS_MEM_TYPE_64 | 235 PCI_BASE_ADDRESS_MEM_PREFETCH; 236 237 *IOP3XX_IATVR2 = PHYS_OFFSET; 238 239 /* Outbound window 0 */ 240 *IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_BA; 241 *IOP3XX_OUMWTVR0 = 0; 242 243 /* Outbound window 1 */ 244 *IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_BA + 245 IOP3XX_PCI_MEM_WINDOW_SIZE / 2; 246 *IOP3XX_OUMWTVR1 = 0; 247 248 /* BAR 3 ( Disabled ) */ 249 *IOP3XX_IAUBAR3 = 0x0; 250 *IOP3XX_IABAR3 = 0x0; 251 *IOP3XX_IATVR3 = 0x0; 252 *IOP3XX_IALR3 = 0x0; 253 254 /* Setup the I/O Bar 255 */ 256 *IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_BA; 257 258 /* Enable inbound and outbound cycles 259 */ 260 *IOP3XX_ATUCMD |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | 261 PCI_COMMAND_PARITY | PCI_COMMAND_SERR; 262 *IOP3XX_ATUCR |= IOP3XX_ATUCR_OUT_EN; 263} 264 265void __init iop3xx_atu_disable(void) 266{ 267 *IOP3XX_ATUCMD = 0; 268 *IOP3XX_ATUCR = 0; 269 270 /* wait for cycles to quiesce */ 271 while (*IOP3XX_PCSR & (IOP3XX_PCSR_OUT_Q_BUSY | 272 IOP3XX_PCSR_IN_Q_BUSY)) 273 cpu_relax(); 274 275 /* BAR 0 ( Disabled ) */ 276 *IOP3XX_IAUBAR0 = 0x0; 277 *IOP3XX_IABAR0 = 0x0; 278 *IOP3XX_IATVR0 = 0x0; 279 *IOP3XX_IALR0 = 0x0; 280 281 /* BAR 1 ( Disabled ) */ 282 *IOP3XX_IAUBAR1 = 0x0; 283 *IOP3XX_IABAR1 = 0x0; 284 *IOP3XX_IALR1 = 0x0; 285 286 /* BAR 2 ( Disabled ) */ 287 *IOP3XX_IAUBAR2 = 0x0; 288 *IOP3XX_IABAR2 = 0x0; 289 *IOP3XX_IATVR2 = 0x0; 290 *IOP3XX_IALR2 = 0x0; 291 292 /* BAR 3 ( Disabled ) */ 293 *IOP3XX_IAUBAR3 = 0x0; 294 *IOP3XX_IABAR3 = 0x0; 295 *IOP3XX_IATVR3 = 0x0; 296 *IOP3XX_IALR3 = 0x0; 297 298 /* Clear the outbound windows */ 299 *IOP3XX_OIOWTVR = 0; 300 301 /* Outbound window 0 */ 302 *IOP3XX_OMWTVR0 = 0; 303 *IOP3XX_OUMWTVR0 = 0; 304 305 /* Outbound window 1 */ 306 *IOP3XX_OMWTVR1 = 0; 307 *IOP3XX_OUMWTVR1 = 0; 308} 309 310/* Flag to determine whether the ATU is initialized and the PCI bus scanned */ 311int init_atu; 312 313int iop3xx_get_init_atu(void) { 314 /* check if default has been overridden */ 315 if (init_atu != IOP3XX_INIT_ATU_DEFAULT) 316 return init_atu; 317 else 318 return IOP3XX_INIT_ATU_DISABLE; 319} 320 321static void __init iop3xx_atu_debug(void) 322{ 323 DBG("PCI: Intel IOP3xx PCI init.\n"); 324 DBG("PCI: Outbound memory window 0: PCI 0x%08x%08x\n", 325 *IOP3XX_OUMWTVR0, *IOP3XX_OMWTVR0); 326 DBG("PCI: Outbound memory window 1: PCI 0x%08x%08x\n", 327 *IOP3XX_OUMWTVR1, *IOP3XX_OMWTVR1); 328 DBG("PCI: Outbound IO window: PCI 0x%08x\n", 329 *IOP3XX_OIOWTVR); 330 331 DBG("PCI: Inbound memory window 0: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", 332 *IOP3XX_IAUBAR0, *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0); 333 DBG("PCI: Inbound memory window 1: PCI 0x%08x%08x 0x%08x\n", 334 *IOP3XX_IAUBAR1, *IOP3XX_IABAR1, *IOP3XX_IALR1); 335 DBG("PCI: Inbound memory window 2: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", 336 *IOP3XX_IAUBAR2, *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2); 337 DBG("PCI: Inbound memory window 3: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", 338 *IOP3XX_IAUBAR3, *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3); 339 340 DBG("PCI: Expansion ROM window: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", 341 0, *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR); 342 343 DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD); 344 DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR); 345 346 hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, 0, "imprecise external abort"); 347} 348 349/* for platforms that might be host-bus-adapters */ 350void __init iop3xx_pci_preinit_cond(void) 351{ 352 if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) { 353 iop3xx_atu_disable(); 354 iop3xx_atu_setup(); 355 iop3xx_atu_debug(); 356 } 357} 358 359void __init iop3xx_pci_preinit(void) 360{ 361 pcibios_min_mem = 0; 362 363 iop3xx_atu_disable(); 364 iop3xx_atu_setup(); 365 iop3xx_atu_debug(); 366} 367 368/* allow init_atu to be user overridden */ 369static int __init iop3xx_init_atu_setup(char *str) 370{ 371 init_atu = IOP3XX_INIT_ATU_DEFAULT; 372 if (str) { 373 while (*str != '\0') { 374 switch (*str) { 375 case 'y': 376 case 'Y': 377 init_atu = IOP3XX_INIT_ATU_ENABLE; 378 break; 379 case 'n': 380 case 'N': 381 init_atu = IOP3XX_INIT_ATU_DISABLE; 382 break; 383 case ',': 384 case '=': 385 break; 386 default: 387 printk(KERN_DEBUG "\"%s\" malformed at " 388 "character: \'%c\'", 389 __func__, 390 *str); 391 *(str + 1) = '\0'; 392 } 393 str++; 394 } 395 } 396 397 return 1; 398} 399 400__setup("iop3xx_init_atu", iop3xx_init_atu_setup); 401 402