linux/arch/mips/pci/ops-bonito64.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 1999, 2000, 2004  MIPS Technologies, Inc.
   3 *      All rights reserved.
   4 *      Authors: Carsten Langgaard <carstenl@mips.com>
   5 *               Maciej W. Rozycki <macro@mips.com>
   6 *
   7 *  This program is free software; you can distribute it and/or modify it
   8 *  under the terms of the GNU General Public License (Version 2) as
   9 *  published by the Free Software Foundation.
  10 *
  11 *  This program is distributed in the hope it will be useful, but WITHOUT
  12 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14 *  for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License along
  17 *  with this program; if not, write to the Free Software Foundation, Inc.,
  18 *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  19 *
  20 * MIPS boards specific PCI support.
  21 */
  22#include <linux/types.h>
  23#include <linux/pci.h>
  24#include <linux/kernel.h>
  25#include <linux/init.h>
  26
  27#include <asm/mips-boards/bonito64.h>
  28
  29#define PCI_ACCESS_READ  0
  30#define PCI_ACCESS_WRITE 1
  31
  32#ifdef CONFIG_LEMOTE_FULONG
  33#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(BONITO_PCICFG_BASE | (offset))
  34#define ID_SEL_BEGIN 11
  35#else
  36#define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset))
  37#define ID_SEL_BEGIN 10
  38#endif
  39#define MAX_DEV_NUM (31 - ID_SEL_BEGIN)
  40
  41
  42static int bonito64_pcibios_config_access(unsigned char access_type,
  43                                      struct pci_bus *bus,
  44                                      unsigned int devfn, int where,
  45                                      u32 * data)
  46{
  47        u32 busnum = bus->number;
  48        u32 addr, type;
  49        u32 dummy;
  50        void *addrp;
  51        int device = PCI_SLOT(devfn);
  52        int function = PCI_FUNC(devfn);
  53        int reg = where & ~3;
  54
  55        if (busnum == 0) {
  56                /* Type 0 configuration for onboard PCI bus */
  57                if (device > MAX_DEV_NUM)
  58                        return -1;
  59
  60                addr = (1 << (device + ID_SEL_BEGIN)) | (function << 8) | reg;
  61                type = 0;
  62        } else {
  63                /* Type 1 configuration for offboard PCI bus */
  64                addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
  65                type = 0x10000;
  66        }
  67
  68        /* Clear aborts */
  69        BONITO_PCICMD |= BONITO_PCICMD_MABORT_CLR | BONITO_PCICMD_MTABORT_CLR;
  70
  71        BONITO_PCIMAP_CFG = (addr >> 16) | type;
  72
  73        /* Flush Bonito register block */
  74        dummy = BONITO_PCIMAP_CFG;
  75        mmiowb();
  76
  77        addrp = CFG_SPACE_REG(addr & 0xffff);
  78        if (access_type == PCI_ACCESS_WRITE) {
  79                writel(cpu_to_le32(*data), addrp);
  80#ifndef CONFIG_LEMOTE_FULONG
  81                /* Wait till done */
  82                while (BONITO_PCIMSTAT & 0xF);
  83#endif
  84        } else {
  85                *data = le32_to_cpu(readl(addrp));
  86        }
  87
  88        /* Detect Master/Target abort */
  89        if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR |
  90                             BONITO_PCICMD_MTABORT_CLR)) {
  91                /* Error occurred */
  92
  93                /* Clear bits */
  94                BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR |
  95                                  BONITO_PCICMD_MTABORT_CLR);
  96
  97                return -1;
  98        }
  99
 100        return 0;
 101
 102}
 103
 104
 105/*
 106 * We can't address 8 and 16 bit words directly.  Instead we have to
 107 * read/write a 32bit word and mask/modify the data we actually want.
 108 */
 109static int bonito64_pcibios_read(struct pci_bus *bus, unsigned int devfn,
 110                             int where, int size, u32 * val)
 111{
 112        u32 data = 0;
 113
 114        if ((size == 2) && (where & 1))
 115                return PCIBIOS_BAD_REGISTER_NUMBER;
 116        else if ((size == 4) && (where & 3))
 117                return PCIBIOS_BAD_REGISTER_NUMBER;
 118
 119        if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
 120                                       &data))
 121                return -1;
 122
 123        if (size == 1)
 124                *val = (data >> ((where & 3) << 3)) & 0xff;
 125        else if (size == 2)
 126                *val = (data >> ((where & 3) << 3)) & 0xffff;
 127        else
 128                *val = data;
 129
 130        return PCIBIOS_SUCCESSFUL;
 131}
 132
 133static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn,
 134                              int where, int size, u32 val)
 135{
 136        u32 data = 0;
 137
 138        if ((size == 2) && (where & 1))
 139                return PCIBIOS_BAD_REGISTER_NUMBER;
 140        else if ((size == 4) && (where & 3))
 141                return PCIBIOS_BAD_REGISTER_NUMBER;
 142
 143        if (size == 4)
 144                data = val;
 145        else {
 146                if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
 147                                               where, &data))
 148                        return -1;
 149
 150                if (size == 1)
 151                        data = (data & ~(0xff << ((where & 3) << 3))) |
 152                                (val << ((where & 3) << 3));
 153                else if (size == 2)
 154                        data = (data & ~(0xffff << ((where & 3) << 3))) |
 155                                (val << ((where & 3) << 3));
 156        }
 157
 158        if (bonito64_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
 159                                       &data))
 160                return -1;
 161
 162        return PCIBIOS_SUCCESSFUL;
 163}
 164
 165struct pci_ops bonito64_pci_ops = {
 166        .read = bonito64_pcibios_read,
 167        .write = bonito64_pcibios_write
 168};
 169