18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/arm/plat-iop/pci.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * PCI support for the Intel IOP32X and IOP33X processors 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: Rory Bolt <rorybolt@pacbell.net> 88c2ecf20Sopenharmony_ci * Copyright (C) 2002 Rory Bolt 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/pci.h> 138c2ecf20Sopenharmony_ci#include <linux/slab.h> 148c2ecf20Sopenharmony_ci#include <linux/mm.h> 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/ioport.h> 178c2ecf20Sopenharmony_ci#include <linux/io.h> 188c2ecf20Sopenharmony_ci#include <asm/irq.h> 198c2ecf20Sopenharmony_ci#include <asm/signal.h> 208c2ecf20Sopenharmony_ci#include <asm/mach/pci.h> 218c2ecf20Sopenharmony_ci#include "hardware.h" 228c2ecf20Sopenharmony_ci#include "iop3xx.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci// #define DEBUG 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#ifdef DEBUG 278c2ecf20Sopenharmony_ci#define DBG(x...) printk(x) 288c2ecf20Sopenharmony_ci#else 298c2ecf20Sopenharmony_ci#define DBG(x...) do { } while (0) 308c2ecf20Sopenharmony_ci#endif 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci * This routine builds either a type0 or type1 configuration command. If the 348c2ecf20Sopenharmony_ci * bus is on the 803xx then a type0 made, else a type1 is created. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_cistatic u32 iop3xx_cfg_address(struct pci_bus *bus, int devfn, int where) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct pci_sys_data *sys = bus->sysdata; 398c2ecf20Sopenharmony_ci u32 addr; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (sys->busnr == bus->number) 428c2ecf20Sopenharmony_ci addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11); 438c2ecf20Sopenharmony_ci else 448c2ecf20Sopenharmony_ci addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci addr |= PCI_FUNC(devfn) << 8 | (where & ~3); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci return addr; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* 528c2ecf20Sopenharmony_ci * This routine checks the status of the last configuration cycle. If an error 538c2ecf20Sopenharmony_ci * was detected it returns a 1, else it returns a 0. The errors being checked 548c2ecf20Sopenharmony_ci * are parity, master abort, target abort (master and target). These types of 558c2ecf20Sopenharmony_ci * errors occur during a config cycle where there is no device, like during 568c2ecf20Sopenharmony_ci * the discovery stage. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_cistatic int iop3xx_pci_status(void) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci unsigned int status; 618c2ecf20Sopenharmony_ci int ret = 0; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci /* 648c2ecf20Sopenharmony_ci * Check the status registers. 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_ci status = *IOP3XX_ATUSR; 678c2ecf20Sopenharmony_ci if (status & 0xf900) { 688c2ecf20Sopenharmony_ci DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status); 698c2ecf20Sopenharmony_ci *IOP3XX_ATUSR = status & 0xf900; 708c2ecf20Sopenharmony_ci ret = 1; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci status = *IOP3XX_ATUISR; 748c2ecf20Sopenharmony_ci if (status & 0x679f) { 758c2ecf20Sopenharmony_ci DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status); 768c2ecf20Sopenharmony_ci *IOP3XX_ATUISR = status & 0x679f; 778c2ecf20Sopenharmony_ci ret = 1; 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci return ret; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/* 848c2ecf20Sopenharmony_ci * Simply write the address register and read the configuration 858c2ecf20Sopenharmony_ci * data. Note that the 4 nops ensure that we are able to handle 868c2ecf20Sopenharmony_ci * a delayed abort (in theory.) 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_cistatic u32 iop3xx_read(unsigned long addr) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci u32 val; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci __asm__ __volatile__( 938c2ecf20Sopenharmony_ci "str %1, [%2]\n\t" 948c2ecf20Sopenharmony_ci "ldr %0, [%3]\n\t" 958c2ecf20Sopenharmony_ci "nop\n\t" 968c2ecf20Sopenharmony_ci "nop\n\t" 978c2ecf20Sopenharmony_ci "nop\n\t" 988c2ecf20Sopenharmony_ci "nop\n\t" 998c2ecf20Sopenharmony_ci : "=r" (val) 1008c2ecf20Sopenharmony_ci : "r" (addr), "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR)); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci return val; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci/* 1068c2ecf20Sopenharmony_ci * The read routines must check the error status of the last configuration 1078c2ecf20Sopenharmony_ci * cycle. If there was an error, the routine returns all hex f's. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_cistatic int 1108c2ecf20Sopenharmony_ciiop3xx_read_config(struct pci_bus *bus, unsigned int devfn, int where, 1118c2ecf20Sopenharmony_ci int size, u32 *value) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci unsigned long addr = iop3xx_cfg_address(bus, devfn, where); 1148c2ecf20Sopenharmony_ci u32 val = iop3xx_read(addr) >> ((where & 3) * 8); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (iop3xx_pci_status()) 1178c2ecf20Sopenharmony_ci val = 0xffffffff; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci *value = val; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int 1258c2ecf20Sopenharmony_ciiop3xx_write_config(struct pci_bus *bus, unsigned int devfn, int where, 1268c2ecf20Sopenharmony_ci int size, u32 value) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci unsigned long addr = iop3xx_cfg_address(bus, devfn, where); 1298c2ecf20Sopenharmony_ci u32 val; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (size != 4) { 1328c2ecf20Sopenharmony_ci val = iop3xx_read(addr); 1338c2ecf20Sopenharmony_ci if (iop3xx_pci_status()) 1348c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci where = (where & 3) * 8; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci if (size == 1) 1398c2ecf20Sopenharmony_ci val &= ~(0xff << where); 1408c2ecf20Sopenharmony_ci else 1418c2ecf20Sopenharmony_ci val &= ~(0xffff << where); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci *IOP3XX_OCCDR = val | value << where; 1448c2ecf20Sopenharmony_ci } else { 1458c2ecf20Sopenharmony_ci asm volatile( 1468c2ecf20Sopenharmony_ci "str %1, [%2]\n\t" 1478c2ecf20Sopenharmony_ci "str %0, [%3]\n\t" 1488c2ecf20Sopenharmony_ci "nop\n\t" 1498c2ecf20Sopenharmony_ci "nop\n\t" 1508c2ecf20Sopenharmony_ci "nop\n\t" 1518c2ecf20Sopenharmony_ci "nop\n\t" 1528c2ecf20Sopenharmony_ci : 1538c2ecf20Sopenharmony_ci : "r" (value), "r" (addr), 1548c2ecf20Sopenharmony_ci "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR)); 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistruct pci_ops iop3xx_ops = { 1618c2ecf20Sopenharmony_ci .read = iop3xx_read_config, 1628c2ecf20Sopenharmony_ci .write = iop3xx_write_config, 1638c2ecf20Sopenharmony_ci}; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* 1668c2ecf20Sopenharmony_ci * When a PCI device does not exist during config cycles, the 80200 gets a 1678c2ecf20Sopenharmony_ci * bus error instead of returning 0xffffffff. This handler simply returns. 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_cistatic int 1708c2ecf20Sopenharmony_ciiop3xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n", 1738c2ecf20Sopenharmony_ci addr, fsr, regs->ARM_pc, regs->ARM_lr); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* 1768c2ecf20Sopenharmony_ci * If it was an imprecise abort, then we need to correct the 1778c2ecf20Sopenharmony_ci * return address to be _after_ the instruction. 1788c2ecf20Sopenharmony_ci */ 1798c2ecf20Sopenharmony_ci if (fsr & (1 << 10)) 1808c2ecf20Sopenharmony_ci regs->ARM_pc += 4; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci return 0; 1838c2ecf20Sopenharmony_ci} 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ciint iop3xx_pci_setup(int nr, struct pci_sys_data *sys) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci struct resource *res; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci if (nr != 0) 1908c2ecf20Sopenharmony_ci return 0; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci res = kzalloc(sizeof(struct resource), GFP_KERNEL); 1938c2ecf20Sopenharmony_ci if (!res) 1948c2ecf20Sopenharmony_ci panic("PCI: unable to alloc resources"); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci res->start = IOP3XX_PCI_LOWER_MEM_PA; 1978c2ecf20Sopenharmony_ci res->end = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE - 1; 1988c2ecf20Sopenharmony_ci res->name = "IOP3XX PCI Memory Space"; 1998c2ecf20Sopenharmony_ci res->flags = IORESOURCE_MEM; 2008c2ecf20Sopenharmony_ci request_resource(&iomem_resource, res); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* 2038c2ecf20Sopenharmony_ci * Use whatever translation is already setup. 2048c2ecf20Sopenharmony_ci */ 2058c2ecf20Sopenharmony_ci sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci pci_add_resource_offset(&sys->resources, res, sys->mem_offset); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci pci_ioremap_io(0, IOP3XX_PCI_LOWER_IO_PA); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return 1; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_civoid __init iop3xx_atu_setup(void) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci /* BAR 0 ( Disabled ) */ 2178c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR0 = 0x0; 2188c2ecf20Sopenharmony_ci *IOP3XX_IABAR0 = 0x0; 2198c2ecf20Sopenharmony_ci *IOP3XX_IATVR0 = 0x0; 2208c2ecf20Sopenharmony_ci *IOP3XX_IALR0 = 0x0; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* BAR 1 ( Disabled ) */ 2238c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR1 = 0x0; 2248c2ecf20Sopenharmony_ci *IOP3XX_IABAR1 = 0x0; 2258c2ecf20Sopenharmony_ci *IOP3XX_IALR1 = 0x0; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* BAR 2 (1:1 mapping with Physical RAM) */ 2288c2ecf20Sopenharmony_ci /* Set limit and enable */ 2298c2ecf20Sopenharmony_ci *IOP3XX_IALR2 = ~((u32)IOP3XX_MAX_RAM_SIZE - 1) & ~0x1; 2308c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR2 = 0x0; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* Align the inbound bar with the base of memory */ 2338c2ecf20Sopenharmony_ci *IOP3XX_IABAR2 = PHYS_OFFSET | 2348c2ecf20Sopenharmony_ci PCI_BASE_ADDRESS_MEM_TYPE_64 | 2358c2ecf20Sopenharmony_ci PCI_BASE_ADDRESS_MEM_PREFETCH; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci *IOP3XX_IATVR2 = PHYS_OFFSET; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* Outbound window 0 */ 2408c2ecf20Sopenharmony_ci *IOP3XX_OMWTVR0 = IOP3XX_PCI_LOWER_MEM_BA; 2418c2ecf20Sopenharmony_ci *IOP3XX_OUMWTVR0 = 0; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* Outbound window 1 */ 2448c2ecf20Sopenharmony_ci *IOP3XX_OMWTVR1 = IOP3XX_PCI_LOWER_MEM_BA + 2458c2ecf20Sopenharmony_ci IOP3XX_PCI_MEM_WINDOW_SIZE / 2; 2468c2ecf20Sopenharmony_ci *IOP3XX_OUMWTVR1 = 0; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* BAR 3 ( Disabled ) */ 2498c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR3 = 0x0; 2508c2ecf20Sopenharmony_ci *IOP3XX_IABAR3 = 0x0; 2518c2ecf20Sopenharmony_ci *IOP3XX_IATVR3 = 0x0; 2528c2ecf20Sopenharmony_ci *IOP3XX_IALR3 = 0x0; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* Setup the I/O Bar 2558c2ecf20Sopenharmony_ci */ 2568c2ecf20Sopenharmony_ci *IOP3XX_OIOWTVR = IOP3XX_PCI_LOWER_IO_BA; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci /* Enable inbound and outbound cycles 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_ci *IOP3XX_ATUCMD |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | 2618c2ecf20Sopenharmony_ci PCI_COMMAND_PARITY | PCI_COMMAND_SERR; 2628c2ecf20Sopenharmony_ci *IOP3XX_ATUCR |= IOP3XX_ATUCR_OUT_EN; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_civoid __init iop3xx_atu_disable(void) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci *IOP3XX_ATUCMD = 0; 2688c2ecf20Sopenharmony_ci *IOP3XX_ATUCR = 0; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci /* wait for cycles to quiesce */ 2718c2ecf20Sopenharmony_ci while (*IOP3XX_PCSR & (IOP3XX_PCSR_OUT_Q_BUSY | 2728c2ecf20Sopenharmony_ci IOP3XX_PCSR_IN_Q_BUSY)) 2738c2ecf20Sopenharmony_ci cpu_relax(); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci /* BAR 0 ( Disabled ) */ 2768c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR0 = 0x0; 2778c2ecf20Sopenharmony_ci *IOP3XX_IABAR0 = 0x0; 2788c2ecf20Sopenharmony_ci *IOP3XX_IATVR0 = 0x0; 2798c2ecf20Sopenharmony_ci *IOP3XX_IALR0 = 0x0; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* BAR 1 ( Disabled ) */ 2828c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR1 = 0x0; 2838c2ecf20Sopenharmony_ci *IOP3XX_IABAR1 = 0x0; 2848c2ecf20Sopenharmony_ci *IOP3XX_IALR1 = 0x0; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* BAR 2 ( Disabled ) */ 2878c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR2 = 0x0; 2888c2ecf20Sopenharmony_ci *IOP3XX_IABAR2 = 0x0; 2898c2ecf20Sopenharmony_ci *IOP3XX_IATVR2 = 0x0; 2908c2ecf20Sopenharmony_ci *IOP3XX_IALR2 = 0x0; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* BAR 3 ( Disabled ) */ 2938c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR3 = 0x0; 2948c2ecf20Sopenharmony_ci *IOP3XX_IABAR3 = 0x0; 2958c2ecf20Sopenharmony_ci *IOP3XX_IATVR3 = 0x0; 2968c2ecf20Sopenharmony_ci *IOP3XX_IALR3 = 0x0; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* Clear the outbound windows */ 2998c2ecf20Sopenharmony_ci *IOP3XX_OIOWTVR = 0; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci /* Outbound window 0 */ 3028c2ecf20Sopenharmony_ci *IOP3XX_OMWTVR0 = 0; 3038c2ecf20Sopenharmony_ci *IOP3XX_OUMWTVR0 = 0; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* Outbound window 1 */ 3068c2ecf20Sopenharmony_ci *IOP3XX_OMWTVR1 = 0; 3078c2ecf20Sopenharmony_ci *IOP3XX_OUMWTVR1 = 0; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci/* Flag to determine whether the ATU is initialized and the PCI bus scanned */ 3118c2ecf20Sopenharmony_ciint init_atu; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ciint iop3xx_get_init_atu(void) { 3148c2ecf20Sopenharmony_ci /* check if default has been overridden */ 3158c2ecf20Sopenharmony_ci if (init_atu != IOP3XX_INIT_ATU_DEFAULT) 3168c2ecf20Sopenharmony_ci return init_atu; 3178c2ecf20Sopenharmony_ci else 3188c2ecf20Sopenharmony_ci return IOP3XX_INIT_ATU_DISABLE; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic void __init iop3xx_atu_debug(void) 3228c2ecf20Sopenharmony_ci{ 3238c2ecf20Sopenharmony_ci DBG("PCI: Intel IOP3xx PCI init.\n"); 3248c2ecf20Sopenharmony_ci DBG("PCI: Outbound memory window 0: PCI 0x%08x%08x\n", 3258c2ecf20Sopenharmony_ci *IOP3XX_OUMWTVR0, *IOP3XX_OMWTVR0); 3268c2ecf20Sopenharmony_ci DBG("PCI: Outbound memory window 1: PCI 0x%08x%08x\n", 3278c2ecf20Sopenharmony_ci *IOP3XX_OUMWTVR1, *IOP3XX_OMWTVR1); 3288c2ecf20Sopenharmony_ci DBG("PCI: Outbound IO window: PCI 0x%08x\n", 3298c2ecf20Sopenharmony_ci *IOP3XX_OIOWTVR); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci DBG("PCI: Inbound memory window 0: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", 3328c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR0, *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0); 3338c2ecf20Sopenharmony_ci DBG("PCI: Inbound memory window 1: PCI 0x%08x%08x 0x%08x\n", 3348c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR1, *IOP3XX_IABAR1, *IOP3XX_IALR1); 3358c2ecf20Sopenharmony_ci DBG("PCI: Inbound memory window 2: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", 3368c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR2, *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2); 3378c2ecf20Sopenharmony_ci DBG("PCI: Inbound memory window 3: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", 3388c2ecf20Sopenharmony_ci *IOP3XX_IAUBAR3, *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci DBG("PCI: Expansion ROM window: PCI 0x%08x%08x 0x%08x -> 0x%08x\n", 3418c2ecf20Sopenharmony_ci 0, *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD); 3448c2ecf20Sopenharmony_ci DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, 0, "imprecise external abort"); 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci/* for platforms that might be host-bus-adapters */ 3508c2ecf20Sopenharmony_civoid __init iop3xx_pci_preinit_cond(void) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) { 3538c2ecf20Sopenharmony_ci iop3xx_atu_disable(); 3548c2ecf20Sopenharmony_ci iop3xx_atu_setup(); 3558c2ecf20Sopenharmony_ci iop3xx_atu_debug(); 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_civoid __init iop3xx_pci_preinit(void) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci pcibios_min_mem = 0; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci iop3xx_atu_disable(); 3648c2ecf20Sopenharmony_ci iop3xx_atu_setup(); 3658c2ecf20Sopenharmony_ci iop3xx_atu_debug(); 3668c2ecf20Sopenharmony_ci} 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci/* allow init_atu to be user overridden */ 3698c2ecf20Sopenharmony_cistatic int __init iop3xx_init_atu_setup(char *str) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci init_atu = IOP3XX_INIT_ATU_DEFAULT; 3728c2ecf20Sopenharmony_ci if (str) { 3738c2ecf20Sopenharmony_ci while (*str != '\0') { 3748c2ecf20Sopenharmony_ci switch (*str) { 3758c2ecf20Sopenharmony_ci case 'y': 3768c2ecf20Sopenharmony_ci case 'Y': 3778c2ecf20Sopenharmony_ci init_atu = IOP3XX_INIT_ATU_ENABLE; 3788c2ecf20Sopenharmony_ci break; 3798c2ecf20Sopenharmony_ci case 'n': 3808c2ecf20Sopenharmony_ci case 'N': 3818c2ecf20Sopenharmony_ci init_atu = IOP3XX_INIT_ATU_DISABLE; 3828c2ecf20Sopenharmony_ci break; 3838c2ecf20Sopenharmony_ci case ',': 3848c2ecf20Sopenharmony_ci case '=': 3858c2ecf20Sopenharmony_ci break; 3868c2ecf20Sopenharmony_ci default: 3878c2ecf20Sopenharmony_ci printk(KERN_DEBUG "\"%s\" malformed at " 3888c2ecf20Sopenharmony_ci "character: \'%c\'", 3898c2ecf20Sopenharmony_ci __func__, 3908c2ecf20Sopenharmony_ci *str); 3918c2ecf20Sopenharmony_ci *(str + 1) = '\0'; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci str++; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci return 1; 3988c2ecf20Sopenharmony_ci} 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci__setup("iop3xx_init_atu", iop3xx_init_atu_setup); 4018c2ecf20Sopenharmony_ci 402