Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[ARM] 3820/1: iop3xx: factor out shared pci code

Merge the iop32x PCI code and iop33x PCI code into plat-iop/pci.c.

Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Lennert Buytenhek and committed by
Russell King
0cb015f9 e25d64f1

+312 -1
+1 -1
arch/arm/plat-iop/Makefile
··· 2 2 # Makefile for the linux kernel. 3 3 # 4 4 5 - obj-y := i2c.o setup.o 5 + obj-y := i2c.o pci.o setup.o 6 6 obj-m := 7 7 obj-n := 8 8 obj- :=
+247
arch/arm/plat-iop/pci.c
··· 1 + /* 2 + * arch/arm/plat-iop/pci.c 3 + * 4 + * PCI support for the Intel IOP32X and IOP33X processors 5 + * 6 + * Author: Rory Bolt <rorybolt@pacbell.net> 7 + * Copyright (C) 2002 Rory Bolt 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 version 2 as 11 + * published by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/pci.h> 16 + #include <linux/slab.h> 17 + #include <linux/mm.h> 18 + #include <linux/init.h> 19 + #include <linux/ioport.h> 20 + #include <asm/io.h> 21 + #include <asm/irq.h> 22 + #include <asm/system.h> 23 + #include <asm/hardware.h> 24 + #include <asm/mach/pci.h> 25 + #include <asm/hardware/iop3xx.h> 26 + 27 + // #define DEBUG 28 + 29 + #ifdef DEBUG 30 + #define DBG(x...) printk(x) 31 + #else 32 + #define DBG(x...) do { } while (0) 33 + #endif 34 + 35 + /* 36 + * This routine builds either a type0 or type1 configuration command. If the 37 + * bus is on the 803xx then a type0 made, else a type1 is created. 38 + */ 39 + static u32 iop3xx_cfg_address(struct pci_bus *bus, int devfn, int where) 40 + { 41 + struct pci_sys_data *sys = bus->sysdata; 42 + u32 addr; 43 + 44 + if (sys->busnr == bus->number) 45 + addr = 1 << (PCI_SLOT(devfn) + 16) | (PCI_SLOT(devfn) << 11); 46 + else 47 + addr = bus->number << 16 | PCI_SLOT(devfn) << 11 | 1; 48 + 49 + addr |= PCI_FUNC(devfn) << 8 | (where & ~3); 50 + 51 + return addr; 52 + } 53 + 54 + /* 55 + * This routine checks the status of the last configuration cycle. If an error 56 + * was detected it returns a 1, else it returns a 0. The errors being checked 57 + * are parity, master abort, target abort (master and target). These types of 58 + * errors occure during a config cycle where there is no device, like during 59 + * the discovery stage. 60 + */ 61 + static int iop3xx_pci_status(void) 62 + { 63 + unsigned int status; 64 + int ret = 0; 65 + 66 + /* 67 + * Check the status registers. 68 + */ 69 + status = *IOP3XX_ATUSR; 70 + if (status & 0xf900) { 71 + DBG("\t\t\tPCI: P0 - status = 0x%08x\n", status); 72 + *IOP3XX_ATUSR = status & 0xf900; 73 + ret = 1; 74 + } 75 + 76 + status = *IOP3XX_ATUISR; 77 + if (status & 0x679f) { 78 + DBG("\t\t\tPCI: P1 - status = 0x%08x\n", status); 79 + *IOP3XX_ATUISR = status & 0x679f; 80 + ret = 1; 81 + } 82 + 83 + return ret; 84 + } 85 + 86 + /* 87 + * Simply write the address register and read the configuration 88 + * data. Note that the 4 nop's ensure that we are able to handle 89 + * a delayed abort (in theory.) 90 + */ 91 + static inline u32 iop3xx_read(unsigned long addr) 92 + { 93 + u32 val; 94 + 95 + __asm__ __volatile__( 96 + "str %1, [%2]\n\t" 97 + "ldr %0, [%3]\n\t" 98 + "nop\n\t" 99 + "nop\n\t" 100 + "nop\n\t" 101 + "nop\n\t" 102 + : "=r" (val) 103 + : "r" (addr), "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR)); 104 + 105 + return val; 106 + } 107 + 108 + /* 109 + * The read routines must check the error status of the last configuration 110 + * cycle. If there was an error, the routine returns all hex f's. 111 + */ 112 + static int 113 + iop3xx_read_config(struct pci_bus *bus, unsigned int devfn, int where, 114 + int size, u32 *value) 115 + { 116 + unsigned long addr = iop3xx_cfg_address(bus, devfn, where); 117 + u32 val = iop3xx_read(addr) >> ((where & 3) * 8); 118 + 119 + if (iop3xx_pci_status()) 120 + val = 0xffffffff; 121 + 122 + *value = val; 123 + 124 + return PCIBIOS_SUCCESSFUL; 125 + } 126 + 127 + static int 128 + iop3xx_write_config(struct pci_bus *bus, unsigned int devfn, int where, 129 + int size, u32 value) 130 + { 131 + unsigned long addr = iop3xx_cfg_address(bus, devfn, where); 132 + u32 val; 133 + 134 + if (size != 4) { 135 + val = iop3xx_read(addr); 136 + if (iop3xx_pci_status()) 137 + return PCIBIOS_SUCCESSFUL; 138 + 139 + where = (where & 3) * 8; 140 + 141 + if (size == 1) 142 + val &= ~(0xff << where); 143 + else 144 + val &= ~(0xffff << where); 145 + 146 + *IOP3XX_OCCDR = val | value << where; 147 + } else { 148 + asm volatile( 149 + "str %1, [%2]\n\t" 150 + "str %0, [%3]\n\t" 151 + "nop\n\t" 152 + "nop\n\t" 153 + "nop\n\t" 154 + "nop\n\t" 155 + : 156 + : "r" (value), "r" (addr), 157 + "r" (IOP3XX_OCCAR), "r" (IOP3XX_OCCDR)); 158 + } 159 + 160 + return PCIBIOS_SUCCESSFUL; 161 + } 162 + 163 + static struct pci_ops iop3xx_ops = { 164 + .read = iop3xx_read_config, 165 + .write = iop3xx_write_config, 166 + }; 167 + 168 + /* 169 + * When a PCI device does not exist during config cycles, the 80200 gets a 170 + * bus error instead of returning 0xffffffff. This handler simply returns. 171 + */ 172 + static int 173 + iop3xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) 174 + { 175 + DBG("PCI abort: address = 0x%08lx fsr = 0x%03x PC = 0x%08lx LR = 0x%08lx\n", 176 + addr, fsr, regs->ARM_pc, regs->ARM_lr); 177 + 178 + /* 179 + * If it was an imprecise abort, then we need to correct the 180 + * return address to be _after_ the instruction. 181 + */ 182 + if (fsr & (1 << 10)) 183 + regs->ARM_pc += 4; 184 + 185 + return 0; 186 + } 187 + 188 + int iop3xx_pci_setup(int nr, struct pci_sys_data *sys) 189 + { 190 + struct resource *res; 191 + 192 + if (nr != 0) 193 + return 0; 194 + 195 + res = kzalloc(2 * sizeof(struct resource), GFP_KERNEL); 196 + if (!res) 197 + panic("PCI: unable to alloc resources"); 198 + 199 + res[0].start = IOP3XX_PCI_LOWER_IO_VA; 200 + res[0].end = IOP3XX_PCI_LOWER_IO_VA + IOP3XX_PCI_IO_WINDOW_SIZE - 1; 201 + res[0].name = "IOP3XX PCI I/O Space"; 202 + res[0].flags = IORESOURCE_IO; 203 + request_resource(&ioport_resource, &res[0]); 204 + 205 + res[1].start = IOP3XX_PCI_LOWER_MEM_PA; 206 + res[1].end = IOP3XX_PCI_LOWER_MEM_PA + IOP3XX_PCI_MEM_WINDOW_SIZE - 1; 207 + res[1].name = "IOP3XX PCI Memory Space"; 208 + res[1].flags = IORESOURCE_MEM; 209 + request_resource(&iomem_resource, &res[1]); 210 + 211 + sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - IOP3XX_PCI_LOWER_MEM_BA; 212 + sys->io_offset = IOP3XX_PCI_LOWER_IO_VA - IOP3XX_PCI_LOWER_IO_BA; 213 + 214 + sys->resource[0] = &res[0]; 215 + sys->resource[1] = &res[1]; 216 + sys->resource[2] = NULL; 217 + 218 + return 1; 219 + } 220 + 221 + struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *sys) 222 + { 223 + return pci_scan_bus(sys->busnr, &iop3xx_ops, sys); 224 + } 225 + 226 + void iop3xx_pci_preinit(void) 227 + { 228 + DBG("PCI: Intel 803xx PCI init code.\n"); 229 + DBG("ATU: IOP3XX_ATUCMD=0x%04x\n", *IOP3XX_ATUCMD); 230 + DBG("ATU: IOP3XX_OMWTVR0=0x%04x, IOP3XX_OIOWTVR=0x%04x\n", 231 + *IOP3XX_OMWTVR0, 232 + *IOP3XX_OIOWTVR); 233 + DBG("ATU: IOP3XX_ATUCR=0x%08x\n", *IOP3XX_ATUCR); 234 + DBG("ATU: IOP3XX_IABAR0=0x%08x IOP3XX_IALR0=0x%08x IOP3XX_IATVR0=%08x\n", 235 + *IOP3XX_IABAR0, *IOP3XX_IALR0, *IOP3XX_IATVR0); 236 + DBG("ATU: IOP3XX_OMWTVR0=0x%08x\n", *IOP3XX_OMWTVR0); 237 + DBG("ATU: IOP3XX_IABAR1=0x%08x IOP3XX_IALR1=0x%08x\n", 238 + *IOP3XX_IABAR1, *IOP3XX_IALR1); 239 + DBG("ATU: IOP3XX_ERBAR=0x%08x IOP3XX_ERLR=0x%08x IOP3XX_ERTVR=%08x\n", 240 + *IOP3XX_ERBAR, *IOP3XX_ERLR, *IOP3XX_ERTVR); 241 + DBG("ATU: IOP3XX_IABAR2=0x%08x IOP3XX_IALR2=0x%08x IOP3XX_IATVR2=%08x\n", 242 + *IOP3XX_IABAR2, *IOP3XX_IALR2, *IOP3XX_IATVR2); 243 + DBG("ATU: IOP3XX_IABAR3=0x%08x IOP3XX_IALR3=0x%08x IOP3XX_IATVR3=%08x\n", 244 + *IOP3XX_IABAR3, *IOP3XX_IALR3, *IOP3XX_IATVR3); 245 + 246 + hook_fault_code(16+6, iop3xx_pci_abort, SIGBUS, "imprecise external abort"); 247 + }
+60
include/asm-arm/hardware/iop3xx.h
··· 23 23 #define IOP3XX_PERIPHERAL_SIZE 0x00002000 24 24 #define IOP3XX_REG_ADDR(reg) (IOP3XX_PERIPHERAL_VIRT_BASE + (reg)) 25 25 26 + /* Address Translation Unit */ 27 + #define IOP3XX_ATUVID (volatile u16 *)IOP3XX_REG_ADDR(0x0100) 28 + #define IOP3XX_ATUDID (volatile u16 *)IOP3XX_REG_ADDR(0x0102) 29 + #define IOP3XX_ATUCMD (volatile u16 *)IOP3XX_REG_ADDR(0x0104) 30 + #define IOP3XX_ATUSR (volatile u16 *)IOP3XX_REG_ADDR(0x0106) 31 + #define IOP3XX_ATURID (volatile u8 *)IOP3XX_REG_ADDR(0x0108) 32 + #define IOP3XX_ATUCCR (volatile u32 *)IOP3XX_REG_ADDR(0x0109) 33 + #define IOP3XX_ATUCLSR (volatile u8 *)IOP3XX_REG_ADDR(0x010c) 34 + #define IOP3XX_ATULT (volatile u8 *)IOP3XX_REG_ADDR(0x010d) 35 + #define IOP3XX_ATUHTR (volatile u8 *)IOP3XX_REG_ADDR(0x010e) 36 + #define IOP3XX_ATUBIST (volatile u8 *)IOP3XX_REG_ADDR(0x010f) 37 + #define IOP3XX_IABAR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0110) 38 + #define IOP3XX_IAUBAR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0114) 39 + #define IOP3XX_IABAR1 (volatile u32 *)IOP3XX_REG_ADDR(0x0118) 40 + #define IOP3XX_IAUBAR1 (volatile u32 *)IOP3XX_REG_ADDR(0x011c) 41 + #define IOP3XX_IABAR2 (volatile u32 *)IOP3XX_REG_ADDR(0x0120) 42 + #define IOP3XX_IAUBAR2 (volatile u32 *)IOP3XX_REG_ADDR(0x0124) 43 + #define IOP3XX_ASVIR (volatile u16 *)IOP3XX_REG_ADDR(0x012c) 44 + #define IOP3XX_ASIR (volatile u16 *)IOP3XX_REG_ADDR(0x012e) 45 + #define IOP3XX_ERBAR (volatile u32 *)IOP3XX_REG_ADDR(0x0130) 46 + #define IOP3XX_ATUILR (volatile u8 *)IOP3XX_REG_ADDR(0x013c) 47 + #define IOP3XX_ATUIPR (volatile u8 *)IOP3XX_REG_ADDR(0x013d) 48 + #define IOP3XX_ATUMGNT (volatile u8 *)IOP3XX_REG_ADDR(0x013e) 49 + #define IOP3XX_ATUMLAT (volatile u8 *)IOP3XX_REG_ADDR(0x013f) 50 + #define IOP3XX_IALR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0140) 51 + #define IOP3XX_IATVR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0144) 52 + #define IOP3XX_ERLR (volatile u32 *)IOP3XX_REG_ADDR(0x0148) 53 + #define IOP3XX_ERTVR (volatile u32 *)IOP3XX_REG_ADDR(0x014c) 54 + #define IOP3XX_IALR1 (volatile u32 *)IOP3XX_REG_ADDR(0x0150) 55 + #define IOP3XX_IALR2 (volatile u32 *)IOP3XX_REG_ADDR(0x0154) 56 + #define IOP3XX_IATVR2 (volatile u32 *)IOP3XX_REG_ADDR(0x0158) 57 + #define IOP3XX_OIOWTVR (volatile u32 *)IOP3XX_REG_ADDR(0x015c) 58 + #define IOP3XX_OMWTVR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0160) 59 + #define IOP3XX_OUMWTVR0 (volatile u32 *)IOP3XX_REG_ADDR(0x0164) 60 + #define IOP3XX_OMWTVR1 (volatile u32 *)IOP3XX_REG_ADDR(0x0168) 61 + #define IOP3XX_OUMWTVR1 (volatile u32 *)IOP3XX_REG_ADDR(0x016c) 62 + #define IOP3XX_OUDWTVR (volatile u32 *)IOP3XX_REG_ADDR(0x0178) 63 + #define IOP3XX_ATUCR (volatile u32 *)IOP3XX_REG_ADDR(0x0180) 64 + #define IOP3XX_PCSR (volatile u32 *)IOP3XX_REG_ADDR(0x0184) 65 + #define IOP3XX_ATUISR (volatile u32 *)IOP3XX_REG_ADDR(0x0188) 66 + #define IOP3XX_ATUIMR (volatile u32 *)IOP3XX_REG_ADDR(0x018c) 67 + #define IOP3XX_IABAR3 (volatile u32 *)IOP3XX_REG_ADDR(0x0190) 68 + #define IOP3XX_IAUBAR3 (volatile u32 *)IOP3XX_REG_ADDR(0x0194) 69 + #define IOP3XX_IALR3 (volatile u32 *)IOP3XX_REG_ADDR(0x0198) 70 + #define IOP3XX_IATVR3 (volatile u32 *)IOP3XX_REG_ADDR(0x019c) 71 + #define IOP3XX_OCCAR (volatile u32 *)IOP3XX_REG_ADDR(0x01a4) 72 + #define IOP3XX_OCCDR (volatile u32 *)IOP3XX_REG_ADDR(0x01ac) 73 + #define IOP3XX_PDSCR (volatile u32 *)IOP3XX_REG_ADDR(0x01bc) 74 + #define IOP3XX_PMCAPID (volatile u8 *)IOP3XX_REG_ADDR(0x01c0) 75 + #define IOP3XX_PMNEXT (volatile u8 *)IOP3XX_REG_ADDR(0x01c1) 76 + #define IOP3XX_APMCR (volatile u16 *)IOP3XX_REG_ADDR(0x01c2) 77 + #define IOP3XX_APMCSR (volatile u16 *)IOP3XX_REG_ADDR(0x01c4) 78 + #define IOP3XX_PCIXCAPID (volatile u8 *)IOP3XX_REG_ADDR(0x01e0) 79 + #define IOP3XX_PCIXNEXT (volatile u8 *)IOP3XX_REG_ADDR(0x01e1) 80 + #define IOP3XX_PCIXCMD (volatile u16 *)IOP3XX_REG_ADDR(0x01e2) 81 + #define IOP3XX_PCIXSR (volatile u32 *)IOP3XX_REG_ADDR(0x01e4) 82 + #define IOP3XX_PCIIRSR (volatile u32 *)IOP3XX_REG_ADDR(0x01ec) 83 + 26 84 /* I2C bus interface unit */ 27 85 #define IOP3XX_ICR0 (volatile u32 *)IOP3XX_REG_ADDR(0x1680) 28 86 #define IOP3XX_ISR0 (volatile u32 *)IOP3XX_REG_ADDR(0x1684) ··· 99 41 */ 100 42 #define IOP3XX_PCI_MEM_WINDOW_SIZE 0x04000000 101 43 #define IOP3XX_PCI_LOWER_MEM_PA 0x80000000 44 + #define IOP3XX_PCI_LOWER_MEM_BA (*IOP3XX_OMWTVR0) 102 45 103 46 #define IOP3XX_PCI_IO_WINDOW_SIZE 0x00010000 104 47 #define IOP3XX_PCI_LOWER_IO_PA 0x90000000 105 48 #define IOP3XX_PCI_LOWER_IO_VA 0xfe000000 49 + #define IOP3XX_PCI_LOWER_IO_BA (*IOP3XX_OIOWTVR) 106 50 107 51 108 52 #ifndef __ASSEMBLY__
+4
include/asm-arm/mach/pci.h
··· 52 52 /* 53 53 * PCI controllers 54 54 */ 55 + extern int iop3xx_pci_setup(int nr, struct pci_sys_data *); 56 + extern struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *); 57 + extern void iop3xx_pci_preinit(void); 58 + 55 59 extern int iop321_setup(int nr, struct pci_sys_data *); 56 60 extern struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *); 57 61 extern void iop321_init(void);