linux/arch/mips/pci/ops-vr41xx.c
<<
>>
Prefs
   1/*
   2 *  ops-vr41xx.c, PCI configuration routines for the PCIU of NEC VR4100 series.
   3 *
   4 *  Copyright (C) 2001-2003 MontaVista Software Inc.
   5 *    Author: Yoichi Yuasa <source@mvista.com>
   6 *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@linux-mips.org>
   7 *
   8 *  This program is free software; you can redistribute it and/or modify
   9 *  it under the terms of the GNU General Public License as published by
  10 *  the Free Software Foundation; either version 2 of the License, or
  11 *  (at your option) any later version.
  12 *
  13 *  This program is distributed in the hope that it will be useful,
  14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *  GNU General Public License for more details.
  17 *
  18 *  You should have received a copy of the GNU General Public License
  19 *  along with this program; if not, write to the Free Software
  20 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 */
  22/*
  23 * Changes:
  24 *  MontaVista Software Inc. <source@mvista.com>
  25 *  - New creation, NEC VR4122 and VR4131 are supported.
  26 */
  27#include <linux/pci.h>
  28#include <linux/types.h>
  29
  30#include <asm/io.h>
  31
  32#define PCICONFDREG     (void __iomem *)KSEG1ADDR(0x0f000c14)
  33#define PCICONFAREG     (void __iomem *)KSEG1ADDR(0x0f000c18)
  34
  35static inline int set_pci_configuration_address(unsigned char number,
  36                                                unsigned int devfn, int where)
  37{
  38        if (number == 0) {
  39                /*
  40                 * Type 0 configuration
  41                 */
  42                if (PCI_SLOT(devfn) < 11 || where > 0xff)
  43                        return -EINVAL;
  44
  45                writel((1U << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) |
  46                       (where & 0xfc), PCICONFAREG);
  47        } else {
  48                /*
  49                 * Type 1 configuration
  50                 */
  51                if (where > 0xff)
  52                        return -EINVAL;
  53
  54                writel(((uint32_t)number << 16) | ((devfn & 0xff) << 8) |
  55                       (where & 0xfc) | 1U, PCICONFAREG);
  56        }
  57
  58        return 0;
  59}
  60
  61static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
  62                           int size, uint32_t *val)
  63{
  64        uint32_t data;
  65
  66        *val = 0xffffffffU;
  67        if (set_pci_configuration_address(bus->number, devfn, where) < 0)
  68                return PCIBIOS_DEVICE_NOT_FOUND;
  69
  70        data = readl(PCICONFDREG);
  71
  72        switch (size) {
  73        case 1:
  74                *val = (data >> ((where & 3) << 3)) & 0xffU;
  75                break;
  76        case 2:
  77                *val = (data >> ((where & 2) << 3)) & 0xffffU;
  78                break;
  79        case 4:
  80                *val = data;
  81                break;
  82        default:
  83                return PCIBIOS_FUNC_NOT_SUPPORTED;
  84        }
  85
  86        return PCIBIOS_SUCCESSFUL;
  87}
  88
  89static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
  90                            int size, uint32_t val)
  91{
  92        uint32_t data;
  93        int shift;
  94
  95        if (set_pci_configuration_address(bus->number, devfn, where) < 0)
  96                return PCIBIOS_DEVICE_NOT_FOUND;
  97
  98        data = readl(PCICONFDREG);
  99
 100        switch (size) {
 101        case 1:
 102                shift = (where & 3) << 3;
 103                data &= ~(0xffU << shift);
 104                data |= ((val & 0xffU) << shift);
 105                break;
 106        case 2:
 107                shift = (where & 2) << 3;
 108                data &= ~(0xffffU << shift);
 109                data |= ((val & 0xffffU) << shift);
 110                break;
 111        case 4:
 112                data = val;
 113                break;
 114        default:
 115                return PCIBIOS_FUNC_NOT_SUPPORTED;
 116        }
 117
 118        writel(data, PCICONFDREG);
 119
 120        return PCIBIOS_SUCCESSFUL;
 121}
 122
 123struct pci_ops vr41xx_pci_ops = {
 124        .read   = pci_config_read,
 125        .write  = pci_config_write,
 126};
 127