2 * Copyright 2002 Momentum Computer
3 * Author: Matthew Dharm <mdharm@momenco.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
11 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
13 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
14 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
16 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
17 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
18 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <linux/config.h>
26 #include <linux/types.h>
27 #include <linux/pci.h>
28 #include <linux/kernel.h>
29 #include <linux/slab.h>
30 #include <linux/version.h>
33 #include <asm/mv64340.h>
35 #include <linux/init.h>
40 * These functions and structures provide the BIOS scan and mapping of the PCI
44 #define MAX_PCI_DEVS 10
46 void mv64340_board_pcibios_fixup_bus(struct pci_bus* c);
48 /* Functions to implement "pci ops" */
49 static int marvell_pcibios_read_config_word(struct pci_dev *dev,
50 int offset, u16 * val);
51 static int marvell_pcibios_read_config_byte(struct pci_dev *dev,
52 int offset, u8 * val);
53 static int marvell_pcibios_read_config_dword(struct pci_dev *dev,
54 int offset, u32 * val);
55 static int marvell_pcibios_write_config_byte(struct pci_dev *dev,
57 static int marvell_pcibios_write_config_word(struct pci_dev *dev,
59 static int marvell_pcibios_write_config_dword(struct pci_dev *dev,
63 * General-purpose PCI functions.
70 * Check if the pci device that are trying to access does really exists
71 * on the evaluation board.
74 * bus - bus number (0 for PCI 0 ; 1 for PCI 1)
75 * dev - number of device on the specific pci bus
78 * 0 - if OK , 1 - if failure
80 static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev)
82 /* Accessing device 31 crashes the MV-64340. */
89 * marvell_pcibios_(read/write)_config_(dword/word/byte) -
91 * reads/write a dword/word/byte register from the configuration space
94 * Note that bus 0 and bus 1 are local, and we assume all other busses are
95 * bridged from bus 1. This is a safe assumption, since any other
96 * configuration will require major modifications to the CP7000G
100 * dev - device number
101 * offset - register offset in the configuration space
102 * val - value to be written / read
105 * PCIBIOS_SUCCESSFUL when operation was succesfull
106 * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous
107 * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned
110 static int marvell_pcibios_read_config_dword(struct pci_dev *device,
111 int offset, u32* val)
114 uint32_t address_reg, data_reg;
117 bus = device->bus->number;
118 dev = PCI_SLOT(device->devfn);
119 func = PCI_FUNC(device->devfn);
121 /* verify the range */
122 if (pci_range_ck(bus, dev))
123 return PCIBIOS_DEVICE_NOT_FOUND;
125 /* select the MV-64340 registers to communicate with the PCI bus */
127 address_reg = MV64340_PCI_0_CONFIG_ADDR;
128 data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
130 address_reg = MV64340_PCI_1_CONFIG_ADDR;
131 data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
134 address = (bus << 16) | (dev << 11) | (func << 8) |
135 (offset & 0xfc) | 0x80000000;
137 /* start the configuration cycle */
138 MV_WRITE(address_reg, address);
141 MV_READ(data_reg, val);
143 return PCIBIOS_SUCCESSFUL;
147 static int marvell_pcibios_read_config_word(struct pci_dev *device,
148 int offset, u16* val)
151 uint32_t address_reg, data_reg;
154 bus = device->bus->number;
155 dev = PCI_SLOT(device->devfn);
156 func = PCI_FUNC(device->devfn);
158 /* verify the range */
159 if (pci_range_ck(bus, dev))
160 return PCIBIOS_DEVICE_NOT_FOUND;
162 /* select the MV-64340 registers to communicate with the PCI bus */
164 address_reg = MV64340_PCI_0_CONFIG_ADDR;
165 data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
167 address_reg = MV64340_PCI_1_CONFIG_ADDR;
168 data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
171 address = (bus << 16) | (dev << 11) | (func << 8) |
172 (offset & 0xfc) | 0x80000000;
174 /* start the configuration cycle */
175 MV_WRITE(address_reg, address);
178 MV_READ_16(data_reg + (offset & 0x3), val);
180 return PCIBIOS_SUCCESSFUL;
183 static int marvell_pcibios_read_config_byte(struct pci_dev *device,
187 uint32_t address_reg, data_reg;
190 bus = device->bus->number;
191 dev = PCI_SLOT(device->devfn);
192 func = PCI_FUNC(device->devfn);
194 /* verify the range */
195 if (pci_range_ck(bus, dev))
196 return PCIBIOS_DEVICE_NOT_FOUND;
198 /* select the MV-64340 registers to communicate with the PCI bus */
200 address_reg = MV64340_PCI_0_CONFIG_ADDR;
201 data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
203 address_reg = MV64340_PCI_1_CONFIG_ADDR;
204 data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
207 address = (bus << 16) | (dev << 11) | (func << 8) |
208 (offset & 0xfc) | 0x80000000;
210 /* start the configuration cycle */
211 MV_WRITE(address_reg, address);
214 MV_READ_8(data_reg + (offset & 0x3), val);
216 return PCIBIOS_SUCCESSFUL;
219 static int marvell_pcibios_write_config_dword(struct pci_dev *device,
223 uint32_t address_reg, data_reg;
226 bus = device->bus->number;
227 dev = PCI_SLOT(device->devfn);
228 func = PCI_FUNC(device->devfn);
230 /* verify the range */
231 if (pci_range_ck(bus, dev))
232 return PCIBIOS_DEVICE_NOT_FOUND;
234 /* select the MV-64340 registers to communicate with the PCI bus */
236 address_reg = MV64340_PCI_0_CONFIG_ADDR;
237 data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
239 address_reg = MV64340_PCI_1_CONFIG_ADDR;
240 data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
243 address = (bus << 16) | (dev << 11) | (func << 8) |
244 (offset & 0xfc) | 0x80000000;
246 /* start the configuration cycle */
247 MV_WRITE(address_reg, address);
250 MV_WRITE(data_reg, val);
252 return PCIBIOS_SUCCESSFUL;
256 static int marvell_pcibios_write_config_word(struct pci_dev *device,
260 uint32_t address_reg, data_reg;
263 bus = device->bus->number;
264 dev = PCI_SLOT(device->devfn);
265 func = PCI_FUNC(device->devfn);
267 /* verify the range */
268 if (pci_range_ck(bus, dev))
269 return PCIBIOS_DEVICE_NOT_FOUND;
271 /* select the MV-64340 registers to communicate with the PCI bus */
273 address_reg = MV64340_PCI_0_CONFIG_ADDR;
274 data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
276 address_reg = MV64340_PCI_1_CONFIG_ADDR;
277 data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
280 address = (bus << 16) | (dev << 11) | (func << 8) |
281 (offset & 0xfc) | 0x80000000;
283 /* start the configuration cycle */
284 MV_WRITE(address_reg, address);
287 MV_WRITE_16(data_reg + (offset & 0x3), val);
289 return PCIBIOS_SUCCESSFUL;
292 static int marvell_pcibios_write_config_byte(struct pci_dev *device,
296 uint32_t address_reg, data_reg;
299 bus = device->bus->number;
300 dev = PCI_SLOT(device->devfn);
301 func = PCI_FUNC(device->devfn);
303 /* verify the range */
304 if (pci_range_ck(bus, dev))
305 return PCIBIOS_DEVICE_NOT_FOUND;
307 /* select the MV-64340 registers to communicate with the PCI bus */
309 address_reg = MV64340_PCI_0_CONFIG_ADDR;
310 data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG;
312 address_reg = MV64340_PCI_1_CONFIG_ADDR;
313 data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG;
316 address = (bus << 16) | (dev << 11) | (func << 8) |
317 (offset & 0xfc) | 0x80000000;
319 /* start the configuration cycle */
320 MV_WRITE(address_reg, address);
323 MV_WRITE_8(data_reg + (offset & 0x3), val);
325 return PCIBIOS_SUCCESSFUL;
328 struct pci_ops marvell_pci_ops = {
329 marvell_pcibios_read_config_byte,
330 marvell_pcibios_read_config_word,
331 marvell_pcibios_read_config_dword,
332 marvell_pcibios_write_config_byte,
333 marvell_pcibios_write_config_word,
334 marvell_pcibios_write_config_dword
337 struct pci_fixup pcibios_fixups[] = {
341 void __init pcibios_fixup_bus(struct pci_bus *c)
343 mv64340_board_pcibios_fixup_bus(c);
346 void __init pcibios_init(void)
348 /* Reset PCI I/O and PCI MEM values */
349 ioport_resource.start = 0xe0000000;
350 ioport_resource.end = 0xe0000000 + 0x20000000 - 1;
351 iomem_resource.start = 0xc0000000;
352 iomem_resource.end = 0xc0000000 + 0x20000000 - 1;
354 pci_scan_bus(0, &marvell_pci_ops, NULL);
355 pci_scan_bus(1, &marvell_pci_ops, NULL);
358 unsigned __init int pcibios_assign_all_busses(void)
363 #endif /* CONFIG_PCI */