linux/arch/mips/pci/ops-rc32434.c
<<
>>
Prefs
   1/*
   2 *  BRIEF MODULE DESCRIPTION
   3 *     pci_ops for IDT EB434 board
   4 *
   5 *  Copyright 2004 IDT Inc. (rischelp@idt.com)
   6 *  Copyright 2006 Felix Fietkau <nbd@openwrt.org>
   7 *
   8 *  This program is free software; you can redistribute  it and/or modify it
   9 *  under  the terms of  the GNU General  Public License as published by the
  10 *  Free Software Foundation;  either version 2 of the  License, or (at your
  11 *  option) any later version.
  12 *
  13 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  14 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  15 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  16 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  17 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  18 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  19 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  21 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  22 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23 *
  24 *  You should have received a copy of the  GNU General Public License along
  25 *  with this program; if not, write  to the Free Software Foundation, Inc.,
  26 *  675 Mass Ave, Cambridge, MA 02139, USA.
  27 */
  28#include <linux/delay.h>
  29#include <linux/io.h>
  30#include <linux/pci.h>
  31#include <linux/types.h>
  32
  33#include <asm/cpu.h>
  34#include <asm/mach-rc32434/rc32434.h>
  35#include <asm/mach-rc32434/pci.h>
  36
  37#define PCI_ACCESS_READ  0
  38#define PCI_ACCESS_WRITE 1
  39
  40
  41#define PCI_CFG_SET(bus, slot, func, off) \
  42        (rc32434_pci->pcicfga = (0x80000000 | \
  43                                ((bus) << 16) | ((slot)<<11) | \
  44                                ((func)<<8) | (off)))
  45
  46static inline int config_access(unsigned char access_type,
  47                                struct pci_bus *bus, unsigned int devfn,
  48                                unsigned char where, u32 *data)
  49{
  50        unsigned int slot = PCI_SLOT(devfn);
  51        u8 func = PCI_FUNC(devfn);
  52
  53        /* Setup address */
  54        PCI_CFG_SET(bus->number, slot, func, where);
  55        rc32434_sync();
  56
  57        if (access_type == PCI_ACCESS_WRITE)
  58                rc32434_pci->pcicfgd = *data;
  59        else
  60                *data = rc32434_pci->pcicfgd;
  61
  62        rc32434_sync();
  63
  64        return 0;
  65}
  66
  67
  68/*
  69 * We can't address 8 and 16 bit words directly.  Instead we have to
  70 * read/write a 32bit word and mask/modify the data we actually want.
  71 */
  72static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
  73                            int where, u8 *val)
  74{
  75        u32 data;
  76        int ret;
  77
  78        ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
  79        *val = (data >> ((where & 3) << 3)) & 0xff;
  80        return ret;
  81}
  82
  83static int read_config_word(struct pci_bus *bus, unsigned int devfn,
  84                            int where, u16 *val)
  85{
  86        u32 data;
  87        int ret;
  88
  89        ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
  90        *val = (data >> ((where & 3) << 3)) & 0xffff;
  91        return ret;
  92}
  93
  94static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
  95                             int where, u32 *val)
  96{
  97        int ret;
  98        int delay = 1;
  99
 100        /*
 101         * Don't scan too far, else there will be errors with plugged in
 102         * daughterboard (rb564).
 103         */
 104        if (bus->number == 0 && PCI_SLOT(devfn) > 21)
 105                return 0;
 106
 107retry:
 108        ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
 109
 110        /*
 111         * Certain devices react delayed at device scan time, this
 112         * gives them time to settle
 113         */
 114        if (where == PCI_VENDOR_ID) {
 115                if (ret == 0xffffffff || ret == 0x00000000 ||
 116                    ret == 0x0000ffff || ret == 0xffff0000) {
 117                        if (delay > 4)
 118                                return 0;
 119                        delay *= 2;
 120                        msleep(delay);
 121                        goto retry;
 122                }
 123        }
 124
 125        return ret;
 126}
 127
 128static int
 129write_config_byte(struct pci_bus *bus, unsigned int devfn, int where,
 130                  u8 val)
 131{
 132        u32 data = 0;
 133
 134        if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
 135                return -1;
 136
 137        data = (data & ~(0xff << ((where & 3) << 3))) |
 138            (val << ((where & 3) << 3));
 139
 140        if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
 141                return -1;
 142
 143        return PCIBIOS_SUCCESSFUL;
 144}
 145
 146
 147static int
 148write_config_word(struct pci_bus *bus, unsigned int devfn, int where,
 149                  u16 val)
 150{
 151        u32 data = 0;
 152
 153        if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
 154                return -1;
 155
 156        data = (data & ~(0xffff << ((where & 3) << 3))) |
 157            (val << ((where & 3) << 3));
 158
 159        if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
 160                return -1;
 161
 162
 163        return PCIBIOS_SUCCESSFUL;
 164}
 165
 166
 167static int
 168write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
 169                   u32 val)
 170{
 171        if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
 172                return -1;
 173
 174        return PCIBIOS_SUCCESSFUL;
 175}
 176
 177static int pci_config_read(struct pci_bus *bus, unsigned int devfn,
 178                           int where, int size, u32 *val)
 179{
 180        switch (size) {
 181        case 1:
 182                return read_config_byte(bus, devfn, where, (u8 *) val);
 183        case 2:
 184                return read_config_word(bus, devfn, where, (u16 *) val);
 185        default:
 186                return read_config_dword(bus, devfn, where, val);
 187        }
 188}
 189
 190static int pci_config_write(struct pci_bus *bus, unsigned int devfn,
 191                            int where, int size, u32 val)
 192{
 193        switch (size) {
 194        case 1:
 195                return write_config_byte(bus, devfn, where, (u8) val);
 196        case 2:
 197                return write_config_word(bus, devfn, where, (u16) val);
 198        default:
 199                return write_config_dword(bus, devfn, where, val);
 200        }
 201}
 202
 203struct pci_ops rc32434_pci_ops = {
 204        .read = pci_config_read,
 205        .write = pci_config_write,
 206};
 207