Feed the mess through indent.
[linux-2.6/linux-mips.git] / arch / mips / pci / ops-ddb5074.c
blobbfb773833ba1ae04dd52da43624117e0b30c7486
1 /*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
5 * arch/mips/ddb5xxx/ddb5476/pci_ops.c
6 * Define the pci_ops for DB5477.
8 * Much of the code is derived from the original DDB5074 port by
9 * Geert Uytterhoeven <geert@sonycom.com>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
17 #include <linux/config.h>
18 #include <linux/pci.h>
19 #include <linux/kernel.h>
20 #include <linux/types.h>
22 #include <asm/addrspace.h>
23 #include <asm/debug.h>
25 #include <asm/ddb5xxx/ddb5xxx.h>
28 * config_swap structure records what set of pdar/pmr are used
29 * to access pci config space. It also provides a place hold the
30 * original values for future restoring.
32 struct pci_config_swap {
33 u32 pdar;
34 u32 pmr;
35 u32 config_base;
36 u32 config_size;
37 u32 pdar_backup;
38 u32 pmr_backup;
42 * On DDB5476, we have one set of swap registers
44 struct pci_config_swap ext_pci_swap = {
45 DDB_PCIW0,
46 DDB_PCIINIT0,
47 DDB_PCI_CONFIG_BASE,
48 DDB_PCI_CONFIG_SIZE
51 static int pci_config_workaround = 1;
54 * access config space
56 static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */
57 u32 slot_num)
59 u32 pci_addr = 0;
60 u32 pciinit_offset = 0;
61 u32 virt_addr = swap->config_base;
62 u32 option;
64 if (pci_config_workaround) {
65 if (slot_num == 5)
66 slot_num = 14;
67 } else {
68 if (slot_num == 5)
69 return DDB_BASE + DDB_PCI_BASE;
72 /* minimum pdar (window) size is 2MB */
73 db_assert(swap->config_size >= (2 << 20));
75 db_assert(slot_num < (1 << 5));
76 db_assert(bus < (1 << 8));
78 /* backup registers */
79 swap->pdar_backup = ddb_in32(swap->pdar);
80 swap->pmr_backup = ddb_in32(swap->pmr);
82 /* set the pdar (pci window) register */
83 ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */
84 0, /* not on local memory bus */
85 0); /* not visible from PCI bus (N/A) */
88 * calcuate the absolute pci config addr;
89 * according to the spec, we start scanning from adr:11 (0x800)
91 if (bus == 0) {
92 /* type 0 config */
93 pci_addr = 0x00040000 << slot_num;
94 } else {
95 /* type 1 config */
96 pci_addr = 0x00040000 << slot_num;
97 panic
98 ("ddb_access_config_base: we don't support type 1 config Yet");
102 * if pci_addr is less than pci config window size, we set
103 * pciinit_offset to 0 and adjust the virt_address.
104 * Otherwise we will try to adjust pciinit_offset.
106 if (pci_addr < swap->config_size) {
107 virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
108 pciinit_offset = 0;
109 } else {
110 db_assert((pci_addr & (swap->config_size - 1)) == 0);
111 virt_addr = KSEG1ADDR(swap->config_base);
112 pciinit_offset = pci_addr;
115 /* set the pmr register */
116 option = DDB_PCI_ACCESS_32;
117 if (bus != 0)
118 option |= DDB_PCI_CFGTYPE1;
119 ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
121 return virt_addr;
124 static inline void ddb_close_config_base(struct pci_config_swap *swap)
126 ddb_out32(swap->pdar, swap->pdar_backup);
127 ddb_out32(swap->pmr, swap->pmr_backup);
130 static int read_config_dword(struct pci_config_swap *swap,
131 struct pci_dev *dev, u32 where, u32 * val)
133 u32 bus, slot_num, func_num;
134 u32 base;
136 db_assert((where & 3) == 0);
137 db_assert(where < (1 << 8));
139 /* check if the bus is top-level */
140 if (dev->bus->parent != NULL) {
141 bus = dev->bus->number;
142 db_assert(bus != 0);
143 } else {
144 bus = 0;
147 slot_num = PCI_SLOT(dev->devfn);
148 func_num = PCI_FUNC(dev->devfn);
149 base = ddb_access_config_base(swap, bus, slot_num);
150 *val = *(volatile u32 *) (base + (func_num << 8) + where);
151 ddb_close_config_base(swap);
152 return PCIBIOS_SUCCESSFUL;
155 static int read_config_word(struct pci_config_swap *swap,
156 struct pci_dev *dev, u32 where, u16 * val)
158 int status;
159 u32 result;
161 db_assert((where & 1) == 0);
163 status = read_config_dword(swap, dev, where & ~3, &result);
164 if (where & 2)
165 result >>= 16;
166 *val = result & 0xffff;
167 return status;
170 static int read_config_byte(struct pci_config_swap *swap,
171 struct pci_dev *dev, u32 where, u8 * val)
173 int status;
174 u32 result;
176 status = read_config_dword(swap, dev, where & ~3, &result);
177 if (where & 1)
178 result >>= 8;
179 if (where & 2)
180 result >>= 16;
181 *val = result & 0xff;
182 return status;
185 static int write_config_dword(struct pci_config_swap *swap,
186 struct pci_dev *dev, u32 where, u32 val)
188 u32 bus, slot_num, func_num;
189 u32 base;
191 db_assert((where & 3) == 0);
192 db_assert(where < (1 << 8));
194 /* check if the bus is top-level */
195 if (dev->bus->parent != NULL) {
196 bus = dev->bus->number;
197 db_assert(bus != 0);
198 } else {
199 bus = 0;
202 slot_num = PCI_SLOT(dev->devfn);
203 func_num = PCI_FUNC(dev->devfn);
204 base = ddb_access_config_base(swap, bus, slot_num);
205 *(volatile u32 *) (base + (func_num << 8) + where) = val;
206 ddb_close_config_base(swap);
207 return PCIBIOS_SUCCESSFUL;
210 static int write_config_word(struct pci_config_swap *swap,
211 struct pci_dev *dev, u32 where, u16 val)
213 int status, shift = 0;
214 u32 result;
216 db_assert((where & 1) == 0);
218 status = read_config_dword(swap, dev, where & ~3, &result);
219 if (status != PCIBIOS_SUCCESSFUL)
220 return status;
222 if (where & 2)
223 shift += 16;
224 result &= ~(0xffff << shift);
225 result |= val << shift;
226 return write_config_dword(swap, dev, where & ~3, result);
229 static int write_config_byte(struct pci_config_swap *swap,
230 struct pci_dev *dev, u32 where, u8 val)
232 int status, shift = 0;
233 u32 result;
235 status = read_config_dword(swap, dev, where & ~3, &result);
236 if (status != PCIBIOS_SUCCESSFUL)
237 return status;
239 if (where & 2)
240 shift += 16;
241 if (where & 1)
242 shift += 8;
243 result &= ~(0xff << shift);
244 result |= val << shift;
245 return write_config_dword(swap, dev, where & ~3, result);
248 #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
249 static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
251 return rw##_config_##unitname(pciswap, \
252 dev, \
253 where, \
254 val); \
257 MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
258 MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
259 MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
261 MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
262 MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
263 MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
265 struct pci_ops ddb5476_ext_pci_ops = {
266 extpci_read_config_byte,
267 extpci_read_config_word,
268 extpci_read_config_dword,
269 extpci_write_config_byte,
270 extpci_write_config_word,
271 extpci_write_config_dword
275 #if defined(CONFIG_RUNTIME_DEBUG)
276 void jsun_scan_pci_bus(void)
278 struct pci_bus bus;
279 struct pci_dev dev;
280 unsigned int devfn;
281 int j;
283 pci_config_workaround = 0;
285 bus.parent = NULL; /* we scan the top level only */
286 dev.bus = &bus;
287 dev.sysdata = NULL;
289 /* scan ext pci bus and io pci bus */
290 for (j = 0; j < 1; j++) {
291 printk(KERN_INFO "scan ddb5476 external PCI bus:\n");
292 bus.ops = &ddb5476_ext_pci_ops;
294 for (devfn = 0; devfn < 0x100; devfn += 8) {
295 u32 temp;
296 u16 temp16;
297 u8 temp8;
298 int i;
300 dev.devfn = devfn;
301 db_verify(pci_read_config_dword(&dev, 0, &temp),
302 == PCIBIOS_SUCCESSFUL);
303 if (temp == 0xffffffff)
304 continue;
306 printk(KERN_INFO "slot %d: (addr %d) \n",
307 devfn / 8, 11 + devfn / 8);
309 /* verify read word and byte */
310 db_verify(pci_read_config_word(&dev, 2, &temp16),
311 == PCIBIOS_SUCCESSFUL);
312 db_assert(temp16 == (temp >> 16));
313 db_verify(pci_read_config_byte(&dev, 3, &temp8),
314 == PCIBIOS_SUCCESSFUL);
315 db_assert(temp8 == (temp >> 24));
316 db_verify(pci_read_config_byte(&dev, 1, &temp8),
317 == PCIBIOS_SUCCESSFUL);
318 db_assert(temp8 == ((temp >> 8) & 0xff));
320 for (i = 0; i < 16; i++) {
321 if ((i % 4) == 0)
322 printk(KERN_INFO);
323 db_verify(pci_read_config_dword
324 (&dev, i * 4, &temp),
325 == PCIBIOS_SUCCESSFUL);
326 printk("\t%08X", temp);
327 if ((i % 4) == 3)
328 printk("\n");
333 pci_config_workaround = 1;
335 #endif