ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / mips / pci / ops-mv64340.c
1 /*
2  * Copyright 2002 Momentum Computer
3  * Author: Matthew Dharm <mdharm@momenco.com>
4  *
5  * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
6  *
7  *  This program is free software; you can redistribute  it and/or modify it
8  *  under  the terms of  the GNU General  Public License as published by the
9  *  Free Software Foundation;  either version 2 of the  License, or (at your
10  *  option) any later version.
11  *
12  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
13  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
14  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
15  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
16  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
17  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
18  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
20  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
21  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  *
23  *  You should have received a copy of the  GNU General Public License along
24  *  with this program; if not, write  to the Free Software Foundation, Inc.,
25  *  675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27 #include <linux/types.h>
28 #include <linux/pci.h>
29 #include <linux/kernel.h>
30 #include <asm/mv64340.h>
31
32 /*
33  * galileo_pcibios_(read/write)_config_(dword/word/byte) -
34  *
35  * reads/write a dword/word/byte register from the configuration space
36  * of a device.
37  *
38  * Note that bus 0 and bus 1 are local, and we assume all other busses are
39  * bridged from bus 1.  This is a safe assumption, since any other
40  * configuration will require major modifications to the CP7000G
41  *
42  * Inputs :
43  * bus - bus number
44  * dev - device number
45  * offset - register offset in the configuration space
46  * val - value to be written / read
47  *
48  * Outputs :
49  * PCIBIOS_SUCCESSFUL when operation was succesfull
50  * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous
51  * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned
52  */
53
54 static int mv64340_read_config(struct pci_bus *bus, unsigned int devfn, int reg,
55         int size, u32 * val, u32 address_reg, u32 data_reg)
56 {
57         u32 address;
58
59         /* Accessing device 31 crashes the MV-64340. */
60         if (PCI_SLOT(devfn) > 5)
61                 return PCIBIOS_DEVICE_NOT_FOUND;
62
63         address = (bus->number << 16) | (devfn << 8) |
64                   (reg & 0xfc) | 0x80000000;
65
66         /* start the configuration cycle */
67         MV_WRITE(address_reg, address);
68
69         switch (size) {
70         case 1:
71                 *val = MV_READ_8(data_reg + (reg & 0x3));
72                 break;
73
74         case 2:
75                 *val = MV_READ_16(data_reg + (reg & 0x3));
76                 break;
77
78         case 4:
79                 *val = MV_READ(data_reg);
80                 break;
81         }
82
83         return PCIBIOS_SUCCESSFUL;
84 }
85
86 static int mv64340_write_config(struct pci_bus *bus, unsigned int devfn,
87         int reg, int size, u32 val, u32 address_reg, u32 data_reg)
88 {
89         u32 address;
90
91         /* Accessing device 31 crashes the MV-64340. */
92         if (PCI_SLOT(devfn) > 5)
93                 return PCIBIOS_DEVICE_NOT_FOUND;
94
95         address = (bus->number << 16) | (devfn << 8) |
96                   (reg & 0xfc) | 0x80000000;
97
98         /* start the configuration cycle */
99         MV_WRITE(address_reg, address);
100
101         switch (size) {
102         case 1:
103                 /* write the data */
104                 MV_WRITE_8(data_reg + (reg & 0x3), val);
105                 break;
106
107         case 2:
108                 /* write the data */
109                 MV_WRITE_16(data_reg + (reg & 0x3), val);
110                 break;
111
112         case 4:
113                 /* write the data */
114                 MV_WRITE(data_reg, val);
115                 break;
116         }
117
118         return PCIBIOS_SUCCESSFUL;
119 }
120
121 #define BUILD_PCI_OPS(host)                                             \
122                                                                         \
123 static int mv64340_bus ## host ## _read_config(struct pci_bus *bus,     \
124         unsigned int devfn, int reg, int size, u32 * val)               \
125 {                                                                       \
126         return mv64340_read_config(bus, devfn, reg, size, val,          \
127                    MV64340_PCI_ ## host ## _CONFIG_ADDR,                \
128                    MV64340_PCI_ ## host ## _CONFIG_DATA_VIRTUAL_REG);   \
129 }                                                                       \
130                                                                         \
131 static int mv64340_bus ## host ## _write_config(struct pci_bus *bus,    \
132         unsigned int devfn, int reg, int size, u32 val)                 \
133 {                                                                       \
134         return mv64340_write_config(bus, devfn, reg, size, val,         \
135                    MV64340_PCI_ ## host ## _CONFIG_ADDR,                \
136                    MV64340_PCI_ ## host ## _CONFIG_DATA_VIRTUAL_REG);   \
137 }                                                                       \
138                                                                         \
139 struct pci_ops mv64340_bus ## host ## _pci_ops = {                      \
140         .read   = mv64340_bus ## host ## _read_config,                  \
141         .write  = mv64340_bus ## host ## _write_config                  \
142 };
143
144 BUILD_PCI_OPS(0)
145 BUILD_PCI_OPS(1)