Linux-2.6.12-rc2
[safe/jmp/linux-2.6] / arch / mips / pci / ops-gt64120.c
1 /*
2  * Carsten Langgaard, carstenl@mips.com
3  * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
4  *
5  *  This program is free software; you can distribute it and/or modify it
6  *  under the terms of the GNU General Public License (Version 2) as
7  *  published by the Free Software Foundation.
8  *
9  *  This program is distributed in the hope it will be useful, but WITHOUT
10  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  *  for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17  */
18 #include <linux/types.h>
19 #include <linux/pci.h>
20 #include <linux/kernel.h>
21
22 #include <asm/gt64120.h>
23
24 #define PCI_ACCESS_READ  0
25 #define PCI_ACCESS_WRITE 1
26
27 /*
28  *  PCI configuration cycle AD bus definition
29  */
30 /* Type 0 */
31 #define PCI_CFG_TYPE0_REG_SHF           0
32 #define PCI_CFG_TYPE0_FUNC_SHF          8
33
34 /* Type 1 */
35 #define PCI_CFG_TYPE1_REG_SHF           0
36 #define PCI_CFG_TYPE1_FUNC_SHF          8
37 #define PCI_CFG_TYPE1_DEV_SHF           11
38 #define PCI_CFG_TYPE1_BUS_SHF           16
39
40 static int gt64120_pcibios_config_access(unsigned char access_type,
41         struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
42 {
43         unsigned char busnum = bus->number;
44         u32 intr;
45
46         if ((busnum == 0) && (PCI_SLOT(devfn) == 0))
47                 /* Galileo itself is devfn 0, don't move it around */
48                 return -1;
49
50         if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0)))
51                 return -1;      /* Because of a bug in the galileo (for slot 31). */
52
53         /* Clear cause register bits */
54         GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
55                                      GT_INTRCAUSE_TARABORT0_BIT));
56
57         /* Setup address */
58         GT_WRITE(GT_PCI0_CFGADDR_OFS,
59                  (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) |
60                  (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
61                  ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
62                  GT_PCI0_CFGADDR_CONFIGEN_BIT);
63
64         if (access_type == PCI_ACCESS_WRITE) {
65                 if (busnum == 0 && PCI_SLOT(devfn) == 0) {
66                         /*
67                          * The Galileo system controller is acting
68                          * differently than other devices.
69                          */
70                         GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
71                 } else
72                         __GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
73         } else {
74                 if (busnum == 0 && PCI_SLOT(devfn) == 0) {
75                         /*
76                          * The Galileo system controller is acting
77                          * differently than other devices.
78                          */
79                         *data = GT_READ(GT_PCI0_CFGDATA_OFS);
80                 } else
81                         *data = __GT_READ(GT_PCI0_CFGDATA_OFS);
82         }
83
84         /* Check for master or target abort */
85         intr = GT_READ(GT_INTRCAUSE_OFS);
86
87         if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
88                 /* Error occurred */
89
90                 /* Clear bits */
91                 GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
92                                              GT_INTRCAUSE_TARABORT0_BIT));
93
94                 return -1;
95         }
96
97         return 0;
98 }
99
100
101 /*
102  * We can't address 8 and 16 bit words directly.  Instead we have to
103  * read/write a 32bit word and mask/modify the data we actually want.
104  */
105 static int gt64120_pcibios_read(struct pci_bus *bus, unsigned int devfn,
106                                 int where, int size, u32 * val)
107 {
108         u32 data = 0;
109
110         if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
111                                           &data))
112                 return PCIBIOS_DEVICE_NOT_FOUND;
113
114         if (size == 1)
115                 *val = (data >> ((where & 3) << 3)) & 0xff;
116         else if (size == 2)
117                 *val = (data >> ((where & 3) << 3)) & 0xffff;
118         else
119                 *val = data;
120
121         return PCIBIOS_SUCCESSFUL;
122 }
123
124 static int gt64120_pcibios_write(struct pci_bus *bus, unsigned int devfn,
125                               int where, int size, u32 val)
126 {
127         u32 data = 0;
128
129         if (size == 4)
130                 data = val;
131         else {
132                 if (gt64120_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
133                                                   where, &data))
134                         return PCIBIOS_DEVICE_NOT_FOUND;
135
136                 if (size == 1)
137                         data = (data & ~(0xff << ((where & 3) << 3))) |
138                                 (val << ((where & 3) << 3));
139                 else if (size == 2)
140                         data = (data & ~(0xffff << ((where & 3) << 3))) |
141                                 (val << ((where & 3) << 3));
142         }
143
144         if (gt64120_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
145                                        &data))
146                 return PCIBIOS_DEVICE_NOT_FOUND;
147
148         return PCIBIOS_SUCCESSFUL;
149 }
150
151 struct pci_ops gt64120_pci_ops = {
152         .read = gt64120_pcibios_read,
153         .write = gt64120_pcibios_write
154 };