1/* 2 * arch/arm/mach-ixp2000/pci.c 3 * 4 * PCI routines for IXDP2400/IXDP2800 boards 5 * 6 * Original Author: Naeem Afzal <naeem.m.afzal@intel.com> 7 * Maintained by: Deepak Saxena <dsaxena@plexity.net> 8 * 9 * Copyright 2002 Intel Corp. 10 * Copyright (C) 2003-2004 MontaVista Software, Inc. 11 * 12 * This program is free software; you can redistribute it and/or modify it 13 * under the terms of the GNU General Public License as published by the 14 * Free Software Foundation; either version 2 of the License, or (at your 15 * option) any later version. 16 */ 17 18#include <linux/sched.h> 19#include <linux/kernel.h> 20#include <linux/pci.h> 21#include <linux/interrupt.h> 22#include <linux/mm.h> 23#include <linux/init.h> 24#include <linux/ioport.h> 25#include <linux/delay.h> 26#include <linux/io.h> 27 28#include <asm/irq.h> 29#include <asm/system.h> 30#include <mach/hardware.h> 31 32#include <asm/mach/pci.h> 33 34static volatile int pci_master_aborts = 0; 35 36static int clear_master_aborts(void); 37 38u32 * 39ixp2000_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where) 40{ 41 u32 *paddress; 42 43 if (PCI_SLOT(devfn) > 7) 44 return 0; 45 46 /* Must be dword aligned */ 47 where &= ~3; 48 49 /* 50 * For top bus, generate type 0, else type 1 51 */ 52 if (!bus_nr) { 53 /* only bits[23:16] are used for IDSEL */ 54 paddress = (u32 *) (IXP2000_PCI_CFG0_VIRT_BASE 55 | (1 << (PCI_SLOT(devfn) + 16)) 56 | (PCI_FUNC(devfn) << 8) | where); 57 } else { 58 paddress = (u32 *) (IXP2000_PCI_CFG1_VIRT_BASE 59 | (bus_nr << 16) 60 | (PCI_SLOT(devfn) << 11) 61 | (PCI_FUNC(devfn) << 8) | where); 62 } 63 64 return paddress; 65} 66 67/* 68 * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes. 69 * 0 and 3 are not valid indexes... 70 */ 71static u32 bytemask[] = { 72 /*0*/ 0, 73 /*1*/ 0xff, 74 /*2*/ 0xffff, 75 /*3*/ 0, 76 /*4*/ 0xffffffff, 77}; 78 79 80int ixp2000_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, 81 int size, u32 *value) 82{ 83 u32 n; 84 u32 *addr; 85 86 n = where % 4; 87 88 addr = ixp2000_pci_config_addr(bus->number, devfn, where); 89 if (!addr) 90 return PCIBIOS_DEVICE_NOT_FOUND; 91 92 pci_master_aborts = 0; 93 *value = (*addr >> (8*n)) & bytemask[size]; 94 if (pci_master_aborts) { 95 pci_master_aborts = 0; 96 *value = 0xffffffff; 97 return PCIBIOS_DEVICE_NOT_FOUND; 98 } 99 100 return PCIBIOS_SUCCESSFUL; 101} 102 103/* 104 * We don't do error checks by calling clear_master_aborts() b/c the 105 * assumption is that the caller did a read first to make sure a device 106 * exists. 107 */ 108int ixp2000_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, 109 int size, u32 value) 110{ 111 u32 mask; 112 u32 *addr; 113 u32 temp; 114 115 mask = ~(bytemask[size] << ((where % 0x4) * 8)); 116 addr = ixp2000_pci_config_addr(bus->number, devfn, where); 117 if (!addr) 118 return PCIBIOS_DEVICE_NOT_FOUND; 119 temp = (u32) (value) << ((where % 0x4) * 8); 120 *addr = (*addr & mask) | temp; 121 122 clear_master_aborts(); 123 124 return PCIBIOS_SUCCESSFUL; 125} 126 127 128static struct pci_ops ixp2000_pci_ops = { 129 .read = ixp2000_pci_read_config, 130 .write = ixp2000_pci_write_config 131}; 132 133struct pci_bus *ixp2000_pci_scan_bus(int nr, struct pci_sys_data *sysdata) 134{ 135 return pci_scan_bus(sysdata->busnr, &ixp2000_pci_ops, sysdata); 136} 137 138 139int ixp2000_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) 140{ 141 142 volatile u32 temp; 143 unsigned long flags; 144 145 pci_master_aborts = 1; 146 147 local_irq_save(flags); 148 temp = *(IXP2000_PCI_CONTROL); 149 if (temp & ((1 << 8) | (1 << 5))) { 150 ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp); 151 } 152 153 temp = *(IXP2000_PCI_CMDSTAT); 154 if (temp & (1 << 29)) { 155 while (temp & (1 << 29)) { 156 ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp); 157 temp = *(IXP2000_PCI_CMDSTAT); 158 } 159 } 160 local_irq_restore(flags); 161 162 /* 163 * If it was an imprecise abort, then we need to correct the 164 * return address to be _after_ the instruction. 165 */ 166 if (fsr & (1 << 10)) 167 regs->ARM_pc += 4; 168 169 return 0; 170} 171 172int 173clear_master_aborts(void) 174{ 175 volatile u32 temp; 176 unsigned long flags; 177 178 local_irq_save(flags); 179 temp = *(IXP2000_PCI_CONTROL); 180 if (temp & ((1 << 8) | (1 << 5))) { 181 ixp2000_reg_wrb(IXP2000_PCI_CONTROL, temp); 182 } 183 184 temp = *(IXP2000_PCI_CMDSTAT); 185 if (temp & (1 << 29)) { 186 while (temp & (1 << 29)) { 187 ixp2000_reg_write(IXP2000_PCI_CMDSTAT, temp); 188 temp = *(IXP2000_PCI_CMDSTAT); 189 } 190 } 191 local_irq_restore(flags); 192 193 return 0; 194} 195 196void __init 197ixp2000_pci_preinit(void) 198{ 199#ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO 200 /* 201 * Configure the PCI unit to properly byteswap I/O transactions, 202 * and verify that it worked. 203 */ 204 ixp2000_reg_write(IXP2000_PCI_CONTROL, 205 (*IXP2000_PCI_CONTROL | PCI_CONTROL_IEE)); 206 207 if ((*IXP2000_PCI_CONTROL & PCI_CONTROL_IEE) == 0) 208 panic("IXP2000: PCI I/O is broken on this ixp model, and " 209 "the needed workaround has not been configured in"); 210#endif 211 212 hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS, 0, 213 "PCI config cycle to non-existent device"); 214} 215 216 217/* 218 * IXP2000 systems often have large resource requirements, so we just 219 * use our own resource space. 220 */ 221static struct resource ixp2000_pci_mem_space = { 222 .start = 0xe0000000, 223 .end = 0xffffffff, 224 .flags = IORESOURCE_MEM, 225 .name = "PCI Mem Space" 226}; 227 228static struct resource ixp2000_pci_io_space = { 229 .start = 0x00010000, 230 .end = 0x0001ffff, 231 .flags = IORESOURCE_IO, 232 .name = "PCI I/O Space" 233}; 234 235int ixp2000_pci_setup(int nr, struct pci_sys_data *sys) 236{ 237 if (nr >= 1) 238 return 0; 239 240 sys->resource[0] = &ixp2000_pci_io_space; 241 sys->resource[1] = &ixp2000_pci_mem_space; 242 sys->resource[2] = NULL; 243 244 return 1; 245} 246