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/types.h>
26 #include <linux/pci.h>
27 #include <linux/kernel.h>
28 #include <linux/slab.h>
29 #include <linux/version.h>
32 #include <asm/mv64340.h>
34 #include <linux/init.h>
37 * These functions and structures provide the BIOS scan and mapping of the PCI
41 #define MAX_PCI_DEVS 10
43 void mv64340_board_pcibios_fixup_bus(struct pci_bus
*c
);
45 /* Functions to implement "pci ops" */
46 static int marvell_pcibios_read_config_word(struct pci_dev
*dev
,
47 int offset
, u16
* val
);
48 static int marvell_pcibios_read_config_byte(struct pci_dev
*dev
,
49 int offset
, u8
* val
);
50 static int marvell_pcibios_read_config_dword(struct pci_dev
*dev
,
51 int offset
, u32
* val
);
52 static int marvell_pcibios_write_config_byte(struct pci_dev
*dev
,
54 static int marvell_pcibios_write_config_word(struct pci_dev
*dev
,
56 static int marvell_pcibios_write_config_dword(struct pci_dev
*dev
,
58 static void marvell_pcibios_set_master(struct pci_dev
*dev
);
61 * General-purpose PCI functions.
68 * Check if the pci device that are trying to access does really exists
69 * on the evaluation board.
72 * bus - bus number (0 for PCI 0 ; 1 for PCI 1)
73 * dev - number of device on the specific pci bus
76 * 0 - if OK , 1 - if failure
78 static __inline__
int pci_range_ck(unsigned char bus
, unsigned char dev
)
80 /* Accessing device 31 crashes the MV-64340. */
87 * marvell_pcibios_(read/write)_config_(dword/word/byte) -
89 * reads/write a dword/word/byte register from the configuration space
92 * Note that bus 0 and bus 1 are local, and we assume all other busses are
93 * bridged from bus 1. This is a safe assumption, since any other
94 * configuration will require major modifications to the CP7000G
99 * offset - register offset in the configuration space
100 * val - value to be written / read
103 * PCIBIOS_SUCCESSFUL when operation was succesfull
104 * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous
105 * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned
108 static int marvell_pcibios_read_config_dword(struct pci_dev
*device
,
109 int offset
, u32
* val
)
112 uint32_t address_reg
, data_reg
;
115 bus
= device
->bus
->number
;
116 dev
= PCI_SLOT(device
->devfn
);
117 func
= PCI_FUNC(device
->devfn
);
119 /* verify the range */
120 if (pci_range_ck(bus
, dev
))
121 return PCIBIOS_DEVICE_NOT_FOUND
;
123 /* select the MV-64340 registers to communicate with the PCI bus */
125 address_reg
= MV64340_PCI_0_CONFIG_ADDR
;
126 data_reg
= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
;
128 address_reg
= MV64340_PCI_1_CONFIG_ADDR
;
129 data_reg
= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
;
132 address
= (bus
<< 16) | (dev
<< 11) | (func
<< 8) |
133 (offset
& 0xfc) | 0x80000000;
135 /* start the configuration cycle */
136 MV_WRITE(address_reg
, address
);
139 MV_READ(data_reg
, val
);
141 return PCIBIOS_SUCCESSFUL
;
145 static int marvell_pcibios_read_config_word(struct pci_dev
*device
,
146 int offset
, u16
* val
)
149 uint32_t address_reg
, data_reg
;
152 bus
= device
->bus
->number
;
153 dev
= PCI_SLOT(device
->devfn
);
154 func
= PCI_FUNC(device
->devfn
);
156 /* verify the range */
157 if (pci_range_ck(bus
, dev
))
158 return PCIBIOS_DEVICE_NOT_FOUND
;
160 /* select the MV-64340 registers to communicate with the PCI bus */
162 address_reg
= MV64340_PCI_0_CONFIG_ADDR
;
163 data_reg
= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
;
165 address_reg
= MV64340_PCI_1_CONFIG_ADDR
;
166 data_reg
= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
;
169 address
= (bus
<< 16) | (dev
<< 11) | (func
<< 8) |
170 (offset
& 0xfc) | 0x80000000;
172 /* start the configuration cycle */
173 MV_WRITE(address_reg
, address
);
176 MV_READ_16(data_reg
+ (offset
& 0x3), val
);
178 return PCIBIOS_SUCCESSFUL
;
181 static int marvell_pcibios_read_config_byte(struct pci_dev
*device
,
182 int offset
, u8
* val
)
185 uint32_t address_reg
, data_reg
;
188 bus
= device
->bus
->number
;
189 dev
= PCI_SLOT(device
->devfn
);
190 func
= PCI_FUNC(device
->devfn
);
192 /* verify the range */
193 if (pci_range_ck(bus
, dev
))
194 return PCIBIOS_DEVICE_NOT_FOUND
;
196 /* select the MV-64340 registers to communicate with the PCI bus */
198 address_reg
= MV64340_PCI_0_CONFIG_ADDR
;
199 data_reg
= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
;
201 address_reg
= MV64340_PCI_1_CONFIG_ADDR
;
202 data_reg
= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
;
205 address
= (bus
<< 16) | (dev
<< 11) | (func
<< 8) |
206 (offset
& 0xfc) | 0x80000000;
208 /* start the configuration cycle */
209 MV_WRITE(address_reg
, address
);
212 MV_READ_8(data_reg
+ (offset
& 0x3), val
);
214 return PCIBIOS_SUCCESSFUL
;
217 static int marvell_pcibios_write_config_dword(struct pci_dev
*device
,
221 uint32_t address_reg
, data_reg
;
224 bus
= device
->bus
->number
;
225 dev
= PCI_SLOT(device
->devfn
);
226 func
= PCI_FUNC(device
->devfn
);
228 /* verify the range */
229 if (pci_range_ck(bus
, dev
))
230 return PCIBIOS_DEVICE_NOT_FOUND
;
232 /* select the MV-64340 registers to communicate with the PCI bus */
234 address_reg
= MV64340_PCI_0_CONFIG_ADDR
;
235 data_reg
= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
;
237 address_reg
= MV64340_PCI_1_CONFIG_ADDR
;
238 data_reg
= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
;
241 address
= (bus
<< 16) | (dev
<< 11) | (func
<< 8) |
242 (offset
& 0xfc) | 0x80000000;
244 /* start the configuration cycle */
245 MV_WRITE(address_reg
, address
);
248 MV_WRITE(data_reg
, val
);
250 return PCIBIOS_SUCCESSFUL
;
254 static int marvell_pcibios_write_config_word(struct pci_dev
*device
,
258 uint32_t address_reg
, data_reg
;
261 bus
= device
->bus
->number
;
262 dev
= PCI_SLOT(device
->devfn
);
263 func
= PCI_FUNC(device
->devfn
);
265 /* verify the range */
266 if (pci_range_ck(bus
, dev
))
267 return PCIBIOS_DEVICE_NOT_FOUND
;
269 /* select the MV-64340 registers to communicate with the PCI bus */
271 address_reg
= MV64340_PCI_0_CONFIG_ADDR
;
272 data_reg
= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
;
274 address_reg
= MV64340_PCI_1_CONFIG_ADDR
;
275 data_reg
= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
;
278 address
= (bus
<< 16) | (dev
<< 11) | (func
<< 8) |
279 (offset
& 0xfc) | 0x80000000;
281 /* start the configuration cycle */
282 MV_WRITE(address_reg
, address
);
285 MV_WRITE_16(data_reg
+ (offset
& 0x3), val
);
287 return PCIBIOS_SUCCESSFUL
;
290 static int marvell_pcibios_write_config_byte(struct pci_dev
*device
,
294 uint32_t address_reg
, data_reg
;
297 bus
= device
->bus
->number
;
298 dev
= PCI_SLOT(device
->devfn
);
299 func
= PCI_FUNC(device
->devfn
);
301 /* verify the range */
302 if (pci_range_ck(bus
, dev
))
303 return PCIBIOS_DEVICE_NOT_FOUND
;
305 /* select the MV-64340 registers to communicate with the PCI bus */
307 address_reg
= MV64340_PCI_0_CONFIG_ADDR
;
308 data_reg
= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG
;
310 address_reg
= MV64340_PCI_1_CONFIG_ADDR
;
311 data_reg
= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG
;
314 address
= (bus
<< 16) | (dev
<< 11) | (func
<< 8) |
315 (offset
& 0xfc) | 0x80000000;
317 /* start the configuration cycle */
318 MV_WRITE(address_reg
, address
);
321 MV_WRITE_8(data_reg
+ (offset
& 0x3), val
);
323 return PCIBIOS_SUCCESSFUL
;
326 static void marvell_pcibios_set_master(struct pci_dev
*dev
)
330 marvell_pcibios_read_config_word(dev
, PCI_COMMAND
, &cmd
);
331 cmd
|= PCI_COMMAND_MASTER
;
332 marvell_pcibios_write_config_word(dev
, PCI_COMMAND
, cmd
);
335 /* Externally-expected functions. Do not change function names */
337 int pcibios_enable_resources(struct pci_dev
*dev
)
344 marvell_pcibios_read_config_word(dev
, PCI_COMMAND
, &cmd
);
346 for (idx
= 0; idx
< 6; idx
++) {
347 r
= &dev
->resource
[idx
];
348 if (!r
->start
&& r
->end
) {
350 "PCI: Device %s not available because of "
351 "resource collisions\n", dev
->slot_name
);
354 if (r
->flags
& IORESOURCE_IO
)
355 cmd
|= PCI_COMMAND_IO
;
356 if (r
->flags
& IORESOURCE_MEM
)
357 cmd
|= PCI_COMMAND_MEMORY
;
359 if (cmd
!= old_cmd
) {
360 marvell_pcibios_write_config_word(dev
, PCI_COMMAND
, cmd
);
364 * Let's fix up the latency timer and cache line size here. Cache
365 * line size = 32 bytes / sizeof dword (4) = 8.
366 * Latency timer must be > 8. 32 is random but appears to work.
368 marvell_pcibios_read_config_byte(dev
, PCI_CACHE_LINE_SIZE
, &tmp1
);
371 "PCI setting cache line size to 8 from " "%d\n",
373 marvell_pcibios_write_config_byte(dev
, PCI_CACHE_LINE_SIZE
,
376 marvell_pcibios_read_config_byte(dev
, PCI_LATENCY_TIMER
, &tmp1
);
379 "PCI setting latency timer to 32 from %d\n", tmp1
);
380 marvell_pcibios_write_config_byte(dev
, PCI_LATENCY_TIMER
,
387 int pcibios_enable_device(struct pci_dev
*dev
, int mask
)
389 return pcibios_enable_resources(dev
);
392 void pcibios_align_resource(void *data
, struct resource
*res
,
395 struct pci_dev
*dev
= data
;
397 if (res
->flags
& IORESOURCE_IO
) {
398 unsigned long start
= res
->start
;
400 /* We need to avoid collisions with `mirrored' VGA ports
401 and other strange ISA hardware, so we always want the
402 addresses kilobyte aligned. */
404 printk(KERN_ERR
"PCI: I/O Region %s/%d too large"
405 " (%ld bytes)\n", dev
->slot_name
,
406 dev
->resource
- res
, size
);
409 start
= (start
+ 1024 - 1) & ~(1024 - 1);
414 struct pci_ops marvell_pci_ops
= {
415 marvell_pcibios_read_config_byte
,
416 marvell_pcibios_read_config_word
,
417 marvell_pcibios_read_config_dword
,
418 marvell_pcibios_write_config_byte
,
419 marvell_pcibios_write_config_word
,
420 marvell_pcibios_write_config_dword
423 struct pci_fixup pcibios_fixups
[] = {
427 void __init
pcibios_fixup_bus(struct pci_bus
*c
)
429 mv64340_board_pcibios_fixup_bus(c
);
432 void __init
pcibios_init(void)
434 /* Reset PCI I/O and PCI MEM values */
435 ioport_resource
.start
= 0xe0000000;
436 ioport_resource
.end
= 0xe0000000 + 0x20000000 - 1;
437 iomem_resource
.start
= 0xc0000000;
438 iomem_resource
.end
= 0xc0000000 + 0x20000000 - 1;
440 pci_scan_bus(0, &marvell_pci_ops
, NULL
);
441 pci_scan_bus(1, &marvell_pci_ops
, NULL
);
445 * for parsing "pci=" kernel boot arguments.
447 char *pcibios_setup(char *str
)
449 printk(KERN_INFO
"rr: pcibios_setup\n");
450 /* Nothing to do for now. */
455 unsigned __init
int pcibios_assign_all_busses(void)