linux/arch/arm/mach-ixp23xx/pci.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-ixp23xx/pci.c
   3 *
   4 * PCI routines for IXP23XX based systems
   5 *
   6 * Copyright (c) 2005 MontaVista Software, Inc.
   7 *
   8 * based on original code:
   9 *
  10 * Author: Naeem Afzal <naeem.m.afzal@intel.com>
  11 * Copyright 2002-2005 Intel Corp.
  12 *
  13 * This program is free software; you can redistribute it and/or modify it
  14 * under the terms of the GNU General Public License as published by the
  15 * Free Software Foundation; either version 2 of the License, or (at your
  16 * option) any later version.
  17 */
  18
  19#include <linux/sched.h>
  20#include <linux/kernel.h>
  21#include <linux/pci.h>
  22#include <linux/interrupt.h>
  23#include <linux/mm.h>
  24#include <linux/init.h>
  25#include <linux/ioport.h>
  26#include <linux/slab.h>
  27#include <linux/delay.h>
  28#include <linux/io.h>
  29
  30#include <asm/irq.h>
  31#include <asm/sizes.h>
  32#include <asm/system.h>
  33#include <asm/mach/pci.h>
  34#include <mach/hardware.h>
  35
  36extern int (*external_fault) (unsigned long, struct pt_regs *);
  37
  38static volatile int pci_master_aborts = 0;
  39
  40#ifdef DEBUG
  41#define DBG(x...)       printk(x)
  42#else
  43#define DBG(x...)
  44#endif
  45
  46int clear_master_aborts(void);
  47
  48static u32
  49*ixp23xx_pci_config_addr(unsigned int bus_nr, unsigned int devfn, int where)
  50{
  51        u32 *paddress;
  52
  53        /*
  54         * Must be dword aligned
  55         */
  56        where &= ~3;
  57
  58        /*
  59         * For top bus, generate type 0, else type 1
  60         */
  61        if (!bus_nr) {
  62                if (PCI_SLOT(devfn) >= 8)
  63                        return 0;
  64
  65                paddress = (u32 *) (IXP23XX_PCI_CFG0_VIRT
  66                                    | (1 << (PCI_SLOT(devfn) + 16))
  67                                    | (PCI_FUNC(devfn) << 8) | where);
  68        } else {
  69                paddress = (u32 *) (IXP23XX_PCI_CFG1_VIRT
  70                                    | (bus_nr << 16)
  71                                    | (PCI_SLOT(devfn) << 11)
  72                                    | (PCI_FUNC(devfn) << 8) | where);
  73        }
  74
  75        return paddress;
  76}
  77
  78/*
  79 * Mask table, bits to mask for quantity of size 1, 2 or 4 bytes.
  80 * 0 and 3 are not valid indexes...
  81 */
  82static u32 bytemask[] = {
  83        /*0*/   0,
  84        /*1*/   0xff,
  85        /*2*/   0xffff,
  86        /*3*/   0,
  87        /*4*/   0xffffffff,
  88};
  89
  90static int ixp23xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
  91                                int where, int size, u32 *value)
  92{
  93        u32 n;
  94        u32 *addr;
  95
  96        n = where % 4;
  97
  98        DBG("In config_read(%d) %d from dev %d:%d:%d\n", size, where,
  99                bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
 100
 101        addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
 102        if (!addr)
 103                return PCIBIOS_DEVICE_NOT_FOUND;
 104
 105        pci_master_aborts = 0;
 106        *value = (*addr >> (8*n)) & bytemask[size];
 107        if (pci_master_aborts) {
 108                        pci_master_aborts = 0;
 109                        *value = 0xffffffff;
 110                        return PCIBIOS_DEVICE_NOT_FOUND;
 111                }
 112
 113        return PCIBIOS_SUCCESSFUL;
 114}
 115
 116/*
 117 * We don't do error checking on the address for writes.
 118 * It's assumed that the user checked for the device existing first
 119 * by doing a read first.
 120 */
 121static int ixp23xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
 122                                        int where, int size, u32 value)
 123{
 124        u32 mask;
 125        u32 *addr;
 126        u32 temp;
 127
 128        mask = ~(bytemask[size] << ((where % 0x4) * 8));
 129        addr = ixp23xx_pci_config_addr(bus->number, devfn, where);
 130        if (!addr)
 131                return PCIBIOS_DEVICE_NOT_FOUND;
 132        temp = (u32) (value) << ((where % 0x4) * 8);
 133        *addr = (*addr & mask) | temp;
 134
 135        clear_master_aborts();
 136
 137        return PCIBIOS_SUCCESSFUL;
 138}
 139
 140struct pci_ops ixp23xx_pci_ops = {
 141        .read   = ixp23xx_pci_read_config,
 142        .write  = ixp23xx_pci_write_config,
 143};
 144
 145struct pci_bus *ixp23xx_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
 146{
 147        return pci_scan_bus(sysdata->busnr, &ixp23xx_pci_ops, sysdata);
 148}
 149
 150int ixp23xx_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 151{
 152        volatile unsigned long temp;
 153        unsigned long flags;
 154
 155        pci_master_aborts = 1;
 156
 157        local_irq_save(flags);
 158        temp = *IXP23XX_PCI_CONTROL;
 159
 160        /*
 161         * master abort and cmd tgt err
 162         */
 163        if (temp & ((1 << 8) | (1 << 5)))
 164                *IXP23XX_PCI_CONTROL = temp;
 165
 166        temp = *IXP23XX_PCI_CMDSTAT;
 167
 168        if (temp & (1 << 29))
 169                *IXP23XX_PCI_CMDSTAT = temp;
 170        local_irq_restore(flags);
 171
 172        /*
 173         * If it was an imprecise abort, then we need to correct the
 174         * return address to be _after_ the instruction.
 175         */
 176        if (fsr & (1 << 10))
 177                regs->ARM_pc += 4;
 178
 179        return 0;
 180}
 181
 182int clear_master_aborts(void)
 183{
 184        volatile u32 temp;
 185
 186        temp = *IXP23XX_PCI_CONTROL;
 187
 188        /*
 189         * master abort and cmd tgt err
 190         */
 191        if (temp & ((1 << 8) | (1 << 5)))
 192                *IXP23XX_PCI_CONTROL = temp;
 193
 194        temp = *IXP23XX_PCI_CMDSTAT;
 195
 196        if (temp & (1 << 29))
 197                *IXP23XX_PCI_CMDSTAT = temp;
 198
 199        return 0;
 200}
 201
 202static void __init ixp23xx_pci_common_init(void)
 203{
 204#ifdef __ARMEB__
 205        *IXP23XX_PCI_CONTROL |= 0x20000;        /* set I/O swapping */
 206#endif
 207        /*
 208         * ADDR_31 needs to be clear for PCI memory access to CPP memory
 209         */
 210        *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_ADDR_31;
 211        *IXP23XX_CPP2XSI_CURR_XFER_REG3 |= IXP23XX_CPP2XSI_PSH_OFF;
 212
 213        /*
 214         * Select correct memory for PCI inbound transactions
 215         */
 216        if (ixp23xx_cpp_boot()) {
 217                *IXP23XX_PCI_CPP_ADDR_BITS &= ~(1 << 1);
 218        } else {
 219                *IXP23XX_PCI_CPP_ADDR_BITS |= (1 << 1);
 220
 221                /*
 222                 * Enable coherency on A2 silicon.
 223                 */
 224                if (arch_is_coherent())
 225                        *IXP23XX_CPP2XSI_CURR_XFER_REG3 &= ~IXP23XX_CPP2XSI_COH_OFF;
 226        }
 227}
 228
 229void __init ixp23xx_pci_preinit(void)
 230{
 231        ixp23xx_pci_common_init();
 232
 233        hook_fault_code(16+6, ixp23xx_pci_abort_handler, SIGBUS,
 234                        "PCI config cycle to non-existent device");
 235
 236        *IXP23XX_PCI_ADDR_EXT = 0x0000e000;
 237}
 238
 239/*
 240 * Prevent PCI layer from seeing the inbound host-bridge resources
 241 */
 242static void __devinit pci_fixup_ixp23xx(struct pci_dev *dev)
 243{
 244        int i;
 245
 246        dev->class &= 0xff;
 247        dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
 248        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
 249                dev->resource[i].start = 0;
 250                dev->resource[i].end   = 0;
 251                dev->resource[i].flags = 0;
 252        }
 253}
 254DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9002, pci_fixup_ixp23xx);
 255
 256/*
 257 * IXP2300 systems often have large resource requirements, so we just
 258 * use our own resource space.
 259 */
 260static struct resource ixp23xx_pci_mem_space = {
 261        .start  = IXP23XX_PCI_MEM_START,
 262        .end    = IXP23XX_PCI_MEM_START + IXP23XX_PCI_MEM_SIZE - 1,
 263        .flags  = IORESOURCE_MEM,
 264        .name   = "PCI Mem Space"
 265};
 266
 267static struct resource ixp23xx_pci_io_space = {
 268        .start  = 0x00000100,
 269        .end    = 0x01ffffff,
 270        .flags  = IORESOURCE_IO,
 271        .name   = "PCI I/O Space"
 272};
 273
 274int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
 275{
 276        if (nr >= 1)
 277                return 0;
 278
 279        sys->resource[0] = &ixp23xx_pci_io_space;
 280        sys->resource[1] = &ixp23xx_pci_mem_space;
 281        sys->resource[2] = NULL;
 282
 283        return 1;
 284}
 285
 286void __init ixp23xx_pci_slave_init(void)
 287{
 288        ixp23xx_pci_common_init();
 289}
 290