Add basic 2.6.24 support for rb532, korina napi code has to be adapted to work
[openwrt.git] / target / linux / rb532 / files-2.6.24 / arch / mips / pci / ops-rc32434.c
1 /**************************************************************************
2  *
3  *  BRIEF MODULE DESCRIPTION
4  *     pci_ops for IDT EB434 board
5  *
6  *  Copyright 2004 IDT Inc. (rischelp@idt.com)
7  *  Copyright 2006 Felix Fietkau <nbd@openwrt.org>
8  *         
9  *  This program is free software; you can redistribute  it and/or modify it
10  *  under  the terms of  the GNU General  Public License as published by the
11  *  Free Software Foundation;  either version 2 of the  License, or (at your
12  *  option) any later version.
13  *
14  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
15  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
16  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
17  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
18  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
20  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
22  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *  You should have received a copy of the  GNU General Public License along
26  *  with this program; if not, write  to the Free Software Foundation, Inc.,
27  *  675 Mass Ave, Cambridge, MA 02139, USA.
28  *
29  *
30  **************************************************************************
31  * May 2004 rkt, neb
32  *
33  * Initial Release
34  *
35  * 
36  *
37  **************************************************************************
38  */
39
40 #include <linux/autoconf.h>
41 #include <linux/init.h>
42 #include <linux/pci.h>
43 #include <linux/types.h>
44 #include <linux/delay.h>
45
46 #include <asm/cpu.h>
47 #include <asm/io.h>
48
49 #include <asm/rc32434/rc32434.h>
50 #include <asm/rc32434/pci.h> 
51
52 #define PCI_ACCESS_READ  0
53 #define PCI_ACCESS_WRITE 1
54
55
56 #define PCI_CFG_SET(bus,slot,func,off) \
57         (rc32434_pci->pcicfga = (0x80000000 | \
58                                 ((bus) << 16) | ((slot)<<11) | \
59                                 ((func)<<8) | (off)))
60
61 static inline int config_access(unsigned char access_type, struct pci_bus *bus,
62                          unsigned int devfn, unsigned char where,
63                          u32 * data)
64
65         unsigned int slot = PCI_SLOT(devfn);
66         u8 func = PCI_FUNC(devfn);
67         
68         /* Setup address */
69         PCI_CFG_SET(bus->number, slot, func, where);
70         rc32434_sync();
71         
72         if (access_type == PCI_ACCESS_WRITE)
73                 rc32434_pci->pcicfgd = *data;
74         else
75                 *data = rc32434_pci->pcicfgd;
76         
77         rc32434_sync();
78         
79         return 0;
80 }
81
82
83 /*
84  * We can't address 8 and 16 bit words directly.  Instead we have to
85  * read/write a 32bit word and mask/modify the data we actually want.
86  */
87 static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
88                             int where, u8 * val)
89 {
90         u32 data;
91         int ret;
92         
93         ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
94         *val = (data >> ((where & 3) << 3)) & 0xff;
95         return ret;
96 }
97
98 static int read_config_word(struct pci_bus *bus, unsigned int devfn,
99                             int where, u16 * val)
100 {
101         u32 data;
102         int ret;
103         
104         ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
105         *val = (data >> ((where & 3) << 3)) & 0xffff;
106         return ret;
107 }
108
109 static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
110                              int where, u32 * val)
111 {
112         int ret;
113         int delay = 1;
114
115         if (bus->number == 0 && PCI_SLOT(devfn) > 21)
116                 return 0;
117
118 retry:
119         ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
120         
121         /* PCI scan: check for invalid values, device may not have
122          * finished initializing */
123
124         if (where == PCI_VENDOR_ID) {
125                 if (ret == 0xffffffff || ret == 0x00000000 ||
126                         ret == 0x0000ffff || ret == 0xffff0000) {
127
128                         if (delay > 4)
129                                 return 0;
130
131                         delay *= 2;
132                         msleep(delay);
133                         goto retry;
134                 }
135         }
136         
137         return ret;
138 }
139
140 static int
141 write_config_byte(struct pci_bus *bus, unsigned int devfn, int where,
142                   u8 val)
143 {
144         u32 data = 0;
145         
146         if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
147                 return -1;
148         
149         data = (data & ~(0xff << ((where & 3) << 3))) |
150                 (val << ((where & 3) << 3));
151         
152         if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
153                 return -1;
154         
155         return PCIBIOS_SUCCESSFUL;
156 }
157
158
159 static int
160 write_config_word(struct pci_bus *bus, unsigned int devfn, int where,
161                   u16 val)
162 {
163         u32 data = 0;
164         
165         if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
166                 return -1;
167         
168         data = (data & ~(0xffff << ((where & 3) << 3))) |
169                 (val << ((where & 3) << 3));
170         
171         if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
172                 return -1;
173         
174         
175         return PCIBIOS_SUCCESSFUL;
176 }
177
178
179 static int 
180 write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
181                    u32 val)
182 {
183         if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
184                 return -1;
185         
186         return PCIBIOS_SUCCESSFUL;
187 }
188
189 static int pci_config_read(struct pci_bus *bus, unsigned int devfn,
190                            int where, int size, u32 * val)
191 {
192         switch (size) {
193         case 1: 
194                 return read_config_byte(bus, devfn, where, (u8 *) val);
195         case 2: 
196                 return read_config_word(bus, devfn, where, (u16 *) val);
197         default:
198                 return read_config_dword(bus, devfn, where, val);
199         }
200 }
201
202 static int pci_config_write(struct pci_bus *bus, unsigned int devfn,
203                             int where, int size, u32 val)
204 {
205         switch (size) {
206         case 1: 
207                 return write_config_byte(bus, devfn, where, (u8) val);
208         case 2: 
209                 return write_config_word(bus, devfn, where, (u16) val);
210         default:
211                 return write_config_dword(bus, devfn, where, val);
212         }
213 }
214
215 struct pci_ops rc32434_pci_ops = {
216         .read =  pci_config_read,
217         .write = pci_config_write,
218 };