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/init.h>
  30#include <linux/io.h>
  31#include <linux/pci.h>
  32#include <linux/types.h>
  33
  34#include <asm/cpu.h>
  35#include <asm/mach-rc32434/rc32434.h>
  36#include <asm/mach-rc32434/pci.h>
  37
  38#define PCI_ACCESS_READ  0
  39#define PCI_ACCESS_WRITE 1
  40
  41
  42#define PCI_CFG_SET(bus, slot, func, off) \
  43        (rc32434_pci->pcicfga = (0x80000000 | \
  44                                ((bus) << 16) | ((slot)<<11) | \
  45                                ((func)<<8) | (off)))
  46
  47static inline int config_access(unsigned char access_type,
  48                                struct pci_bus *bus, unsigned int devfn,
  49                                unsigned char where, u32 *data)
  50{
  51        unsigned int slot = PCI_SLOT(devfn);
  52        u8 func = PCI_FUNC(devfn);
  53
  54        /* Setup address */
  55        PCI_CFG_SET(bus->number, slot, func, where);
  56        rc32434_sync();
  57
  58        if (access_type == PCI_ACCESS_WRITE)
  59                rc32434_pci->pcicfgd = *data;
  60        else
  61                *data = rc32434_pci->pcicfgd;
  62
  63        rc32434_sync();
  64
  65        return 0;
  66}
  67
  68
  69/*
  70 * We can't address 8 and 16 bit words directly.  Instead we have to
  71 * read/write a 32bit word and mask/modify the data we actually want.
  72 */
  73static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
  74                            int where, u8 *val)
  75{
  76        u32 data;
  77        int ret;
  78
  79        ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
  80        *val = (data >> ((where & 3) << 3)) & 0xff;
  81        return ret;
  82}
  83
  84static int read_config_word(struct pci_bus *bus, unsigned int devfn,
  85                            int where, u16 *val)
  86{
  87        u32 data;
  88        int ret;
  89
  90        ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
  91        *val = (data >> ((where & 3) << 3)) & 0xffff;
  92        return ret;
  93}
  94
  95static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
  96                             int where, u32 *val)
  97{
  98        int ret;
  99        int delay = 1;
 100
 101        /*
 102         * Don't scan too far, else there will be errors with plugged in
 103         * daughterboard (rb564).
 104         */
 105        if (bus->number == 0 && PCI_SLOT(devfn) > 21)
 106                return 0;
 107
 108retry:
 109        ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
 110
 111        /*
 112         * Certain devices react delayed at device scan time, this
 113         * gives them time to settle
 114         */
 115        if (where == PCI_VENDOR_ID) {
 116                if (ret == 0xffffffff || ret == 0x00000000 ||
 117                    ret == 0x0000ffff || ret == 0xffff0000) {
 118                        if (delay > 4)
 119                                return 0;
 120                        delay *= 2;
 121                        msleep(delay);
 122                        goto retry;
 123                }
 124        }
 125
 126        return ret;
 127}
 128
 129static int
 130write_config_byte(struct pci_bus *bus, unsigned int devfn, int where,
 131                  u8 val)
 132{
 133        u32 data = 0;
 134
 135        if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
 136                return -1;
 137
 138        data = (data & ~(0xff << ((where & 3) << 3))) |
 139            (val << ((where & 3) << 3));
 140
 141        if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
 142                return -1;
 143
 144        return PCIBIOS_SUCCESSFUL;
 145}
 146
 147
 148static int
 149write_config_word(struct pci_bus *bus, unsigned int devfn, int where,
 150                  u16 val)
 151{
 152        u32 data = 0;
 153
 154        if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
 155                return -1;
 156
 157        data = (data & ~(0xffff << ((where & 3) << 3))) |
 158            (val << ((where & 3) << 3));
 159
 160        if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
 161                return -1;
 162
 163
 164        return PCIBIOS_SUCCESSFUL;
 165}
 166
 167
 168static int
 169write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
 170                   u32 val)
 171{
 172        if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
 173                return -1;
 174
 175        return PCIBIOS_SUCCESSFUL;
 176}
 177
 178static int pci_config_read(struct pci_bus *bus, unsigned int devfn,
 179                           int where, int size, u32 *val)
 180{
 181        switch (size) {
 182        case 1:
 183                return read_config_byte(bus, devfn, where, (u8 *) val);
 184        case 2:
 185                return read_config_word(bus, devfn, where, (u16 *) val);
 186        default:
 187                return read_config_dword(bus, devfn, where, val);
 188        }
 189}
 190
 191static int pci_config_write(struct pci_bus *bus, unsigned int devfn,
 192                            int where, int size, u32 val)
 193{
 194        switch (size) {
 195        case 1:
 196                return write_config_byte(bus, devfn, where, (u8) val);
 197        case 2:
 198                return write_config_word(bus, devfn, where, (u16) val);
 199        default:
 200                return write_config_dword(bus, devfn, where, val);
 201        }
 202}
 203
 204struct pci_ops rc32434_pci_ops = {
 205        .read = pci_config_read,
 206        .write = pci_config_write,
 207};
 208