linux/arch/arm/mach-ixp2000/pci.c
<<
>>
Prefs
   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
 247