blob: 027759f7c904ac38d304d3a471b3982eaff89d37 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
Ralf Baechle3367fd52006-03-08 14:22:27 +00006 * Copyright (C) 2004, 06 by Ralf Baechle (ralf@linux-mips.org)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 */
8
9#include <linux/types.h>
10#include <linux/pci.h>
Ralf Baechle3367fd52006-03-08 14:22:27 +000011#include <linux/mv643xx.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012
13#include <linux/init.h>
14
Ralf Baechle3367fd52006-03-08 14:22:27 +000015#include <asm/marvell.h>
16
Linus Torvalds1da177e2005-04-16 15:20:36 -070017/*
18 * We assume the address ranges have already been setup appropriately by
19 * the firmware. PMON in case of the Ocelot C does that.
20 */
21static struct resource mv_pci_io_mem0_resource = {
22 .name = "MV64340 PCI0 IO MEM",
23 .flags = IORESOURCE_IO
24};
25
26static struct resource mv_pci_mem0_resource = {
27 .name = "MV64340 PCI0 MEM",
28 .flags = IORESOURCE_MEM
29};
30
31static struct mv_pci_controller mv_bus0_controller = {
32 .pcic = {
33 .pci_ops = &mv_pci_ops,
34 .mem_resource = &mv_pci_mem0_resource,
35 .io_resource = &mv_pci_io_mem0_resource,
36 },
37 .config_addr = MV64340_PCI_0_CONFIG_ADDR,
38 .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
39};
40
41static uint32_t mv_io_base, mv_io_size;
42
43static void mv64340_pci0_init(void)
44{
45 uint32_t mem0_base, mem0_size;
46 uint32_t io_base, io_size;
47
48 io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
49 io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
50 mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
51 mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
52
53 mv_pci_io_mem0_resource.start = 0;
54 mv_pci_io_mem0_resource.end = io_size - 1;
55 mv_pci_mem0_resource.start = mem0_base;
56 mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
57 mv_bus0_controller.pcic.mem_offset = mem0_base;
58 mv_bus0_controller.pcic.io_offset = 0;
59
60 ioport_resource.end = io_size - 1;
61
62 register_pci_controller(&mv_bus0_controller.pcic);
63
64 mv_io_base = io_base;
65 mv_io_size = io_size;
66}
67
68static struct resource mv_pci_io_mem1_resource = {
69 .name = "MV64340 PCI1 IO MEM",
70 .flags = IORESOURCE_IO
71};
72
73static struct resource mv_pci_mem1_resource = {
74 .name = "MV64340 PCI1 MEM",
75 .flags = IORESOURCE_MEM
76};
77
78static struct mv_pci_controller mv_bus1_controller = {
79 .pcic = {
80 .pci_ops = &mv_pci_ops,
81 .mem_resource = &mv_pci_mem1_resource,
82 .io_resource = &mv_pci_io_mem1_resource,
83 },
84 .config_addr = MV64340_PCI_1_CONFIG_ADDR,
85 .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
86};
87
88static __init void mv64340_pci1_init(void)
89{
90 uint32_t mem0_base, mem0_size;
91 uint32_t io_base, io_size;
92
93 io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
94 io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
95 mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
96 mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
97
98 /*
99 * Here we assume the I/O window of second bus to be contiguous with
100 * the first. A gap is no problem but would waste address space for
101 * remapping the port space.
102 */
103 mv_pci_io_mem1_resource.start = mv_io_size;
104 mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
105 mv_pci_mem1_resource.start = mem0_base;
106 mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
107 mv_bus1_controller.pcic.mem_offset = mem0_base;
108 mv_bus1_controller.pcic.io_offset = 0;
109
110 ioport_resource.end = io_base + io_size -mv_io_base - 1;
111
112 register_pci_controller(&mv_bus1_controller.pcic);
113
114 mv_io_size = io_base + io_size - mv_io_base;
115}
116
117static __init int __init ocelot_c_pci_init(void)
118{
119 unsigned long io_v_base;
120 uint32_t enable;
121
122 enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
123
124 /*
125 * We require at least one enabled I/O or PCI memory window or we
126 * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
127 */
128 if (enable & (0x01 << 9) || enable & (0x01 << 10))
129 mv64340_pci0_init();
130
131 if (enable & (0x01 << 14) || enable & (0x01 << 15))
132 mv64340_pci1_init();
133
134 if (mv_io_size) {
135 io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
136 if (!io_v_base)
137 panic("Could not ioremap I/O port range");
138
139 set_io_port_base(io_v_base);
140 }
141
142 return 0;
143}
144
145arch_initcall(ocelot_c_pci_init);