Original kernel 2.4.37.5
[tomato.git] / release / src / linux / linux / arch / mips / ddb5xxx / ddb5074 / pci_ops.c
blob7a46ef0973798c3a5f1c8265fa63e251e2e644a9
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.
18 #include <linux/config.h>
19 #include <linux/pci.h>
20 #include <linux/kernel.h>
21 #include <linux/types.h>
23 #include <asm/addrspace.h>
24 #include <asm/debug.h>
26 #include <asm/ddb5xxx/ddb5xxx.h>
29 * config_swap structure records what set of pdar/pmr are used
30 * to access pci config space. It also provides a place hold the
31 * original values for future restoring.
33 struct pci_config_swap {
34 u32 pdar;
35 u32 pmr;
36 u32 config_base;
37 u32 config_size;
38 u32 pdar_backup;
39 u32 pmr_backup;
43 * On DDB5476, we have one set of swap registers
45 struct pci_config_swap ext_pci_swap = {
46 DDB_PCIW0,
47 DDB_PCIINIT0,
48 DDB_PCI_CONFIG_BASE,
49 DDB_PCI_CONFIG_SIZE
53 * access config space
55 static inline u32 ddb_access_config_base(struct pci_config_swap *swap,
56 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 (slot_num == 5)
65 slot_num = 14;
67 /* minimum pdar (window) size is 2MB */
68 db_assert(swap->config_size >= (2 << 20));
70 db_assert(slot_num < (1 << 5));
71 db_assert(bus < (1 << 8));
73 /* backup registers */
74 swap->pdar_backup = ddb_in32(swap->pdar);
75 swap->pmr_backup = ddb_in32(swap->pmr);
77 /* set the pdar (pci window) register */
78 ddb_set_pdar(swap->pdar,
79 swap->config_base,
80 swap->config_size,
81 32, /* 32 bit wide */
82 0, /* not on local memory bus */
83 0); /* not visible from PCI bus (N/A) */
86 * calcuate the absolute pci config addr;
87 * according to the spec, we start scanning from adr:11 (0x800)
89 if (bus == 0) {
90 /* type 0 config */
91 pci_addr = 0x00040000 << slot_num;
92 } else {
93 /* type 1 config */
94 pci_addr = 0x00040000 << slot_num;
95 panic("ddb_access_config_base: we don't support type 1 config Yet");
99 * if pci_addr is less than pci config window size, we set
100 * pciinit_offset to 0 and adjust the virt_address.
101 * Otherwise we will try to adjust pciinit_offset.
103 if (pci_addr < swap->config_size) {
104 virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
105 pciinit_offset = 0;
106 } else {
107 db_assert( (pci_addr & (swap->config_size - 1)) == 0);
108 virt_addr = KSEG1ADDR(swap->config_base);
109 pciinit_offset = pci_addr;
112 /* set the pmr register */
113 option = DDB_PCI_ACCESS_32;
114 if (bus != 0) option |= DDB_PCI_CFGTYPE1;
115 ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
117 return virt_addr;
120 static inline void ddb_close_config_base(struct pci_config_swap *swap)
122 ddb_out32(swap->pdar, swap->pdar_backup);
123 ddb_out32(swap->pmr, swap->pmr_backup);
126 static int read_config_dword(struct pci_config_swap *swap,
127 struct pci_dev *dev,
128 u32 where,
129 u32 *val)
131 u32 bus, slot_num, func_num;
132 u32 base;
134 db_assert((where & 3) == 0);
135 db_assert(where < (1 << 8));
137 /* check if the bus is top-level */
138 if (dev->bus->parent != NULL) {
139 bus = dev->bus->number;
140 db_assert(bus != 0);
141 } else {
142 bus = 0;
145 slot_num = PCI_SLOT(dev->devfn);
146 func_num = PCI_FUNC(dev->devfn);
147 base = ddb_access_config_base(swap, bus, slot_num);
148 *val = *(volatile u32*) (base + (func_num << 8) + where);
149 ddb_close_config_base(swap);
150 return PCIBIOS_SUCCESSFUL;
153 static int read_config_word(struct pci_config_swap *swap,
154 struct pci_dev *dev,
155 u32 where,
156 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) result >>= 16;
165 *val = result & 0xffff;
166 return status;
169 static int read_config_byte(struct pci_config_swap *swap,
170 struct pci_dev *dev,
171 u32 where,
172 u8 *val)
174 int status;
175 u32 result;
177 status = read_config_dword(swap, dev, where & ~3, &result);
178 if (where & 1) result >>= 8;
179 if (where & 2) result >>= 16;
180 *val = result & 0xff;
181 return status;
184 static int write_config_dword(struct pci_config_swap *swap,
185 struct pci_dev *dev,
186 u32 where,
187 u32 val)
189 u32 bus, slot_num, func_num;
190 u32 base;
192 db_assert((where & 3) == 0);
193 db_assert(where < (1 << 8));
195 /* check if the bus is top-level */
196 if (dev->bus->parent != NULL) {
197 bus = dev->bus->number;
198 db_assert(bus != 0);
199 } else {
200 bus = 0;
203 slot_num = PCI_SLOT(dev->devfn);
204 func_num = PCI_FUNC(dev->devfn);
205 base = ddb_access_config_base(swap, bus, slot_num);
206 *(volatile u32*) (base + (func_num << 8) + where) = val;
207 ddb_close_config_base(swap);
208 return PCIBIOS_SUCCESSFUL;
211 static int write_config_word(struct pci_config_swap *swap,
212 struct pci_dev *dev,
213 u32 where,
214 u16 val)
216 int status, shift=0;
217 u32 result;
219 db_assert((where & 1) == 0);
221 status = read_config_dword(swap, dev, where & ~3, &result);
222 if (status != PCIBIOS_SUCCESSFUL) return status;
224 if (where & 2)
225 shift += 16;
226 result &= ~(0xffff << shift);
227 result |= val << shift;
228 return write_config_dword(swap, dev, where & ~3, result);
231 static int write_config_byte(struct pci_config_swap *swap,
232 struct pci_dev *dev,
233 u32 where,
234 u8 val)
236 int status, shift=0;
237 u32 result;
239 status = read_config_dword(swap, dev, where & ~3, &result);
240 if (status != PCIBIOS_SUCCESSFUL) return status;
242 if (where & 2)
243 shift += 16;
244 if (where & 1)
245 shift += 8;
246 result &= ~(0xff << shift);
247 result |= val << shift;
248 return write_config_dword(swap, dev, where & ~3, result);
251 #define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
252 static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
254 return rw##_config_##unitname(pciswap, \
255 dev, \
256 where, \
257 val); \
260 MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
261 MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
262 MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
264 MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
265 MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
266 MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
268 struct pci_ops ddb5476_ext_pci_ops ={
269 extpci_read_config_byte,
270 extpci_read_config_word,
271 extpci_read_config_dword,
272 extpci_write_config_byte,
273 extpci_write_config_word,
274 extpci_write_config_dword