aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/pci/pci-ocelot-c.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/pci/pci-ocelot-c.c')
-rw-r--r--arch/mips/pci/pci-ocelot-c.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c
new file mode 100644
index 000000000000..1d84d36e034d
--- /dev/null
+++ b/arch/mips/pci/pci-ocelot-c.c
@@ -0,0 +1,143 @@
1/*
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 *
6 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
7 */
8
9#include <linux/types.h>
10#include <linux/pci.h>
11#include <asm/mv64340.h>
12
13#include <linux/init.h>
14
15/*
16 * We assume the address ranges have already been setup appropriately by
17 * the firmware. PMON in case of the Ocelot C does that.
18 */
19static struct resource mv_pci_io_mem0_resource = {
20 .name = "MV64340 PCI0 IO MEM",
21 .flags = IORESOURCE_IO
22};
23
24static struct resource mv_pci_mem0_resource = {
25 .name = "MV64340 PCI0 MEM",
26 .flags = IORESOURCE_MEM
27};
28
29static struct mv_pci_controller mv_bus0_controller = {
30 .pcic = {
31 .pci_ops = &mv_pci_ops,
32 .mem_resource = &mv_pci_mem0_resource,
33 .io_resource = &mv_pci_io_mem0_resource,
34 },
35 .config_addr = MV64340_PCI_0_CONFIG_ADDR,
36 .config_vreg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
37};
38
39static uint32_t mv_io_base, mv_io_size;
40
41static void mv64340_pci0_init(void)
42{
43 uint32_t mem0_base, mem0_size;
44 uint32_t io_base, io_size;
45
46 io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
47 io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
48 mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
49 mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
50
51 mv_pci_io_mem0_resource.start = 0;
52 mv_pci_io_mem0_resource.end = io_size - 1;
53 mv_pci_mem0_resource.start = mem0_base;
54 mv_pci_mem0_resource.end = mem0_base + mem0_size - 1;
55 mv_bus0_controller.pcic.mem_offset = mem0_base;
56 mv_bus0_controller.pcic.io_offset = 0;
57
58 ioport_resource.end = io_size - 1;
59
60 register_pci_controller(&mv_bus0_controller.pcic);
61
62 mv_io_base = io_base;
63 mv_io_size = io_size;
64}
65
66static struct resource mv_pci_io_mem1_resource = {
67 .name = "MV64340 PCI1 IO MEM",
68 .flags = IORESOURCE_IO
69};
70
71static struct resource mv_pci_mem1_resource = {
72 .name = "MV64340 PCI1 MEM",
73 .flags = IORESOURCE_MEM
74};
75
76static struct mv_pci_controller mv_bus1_controller = {
77 .pcic = {
78 .pci_ops = &mv_pci_ops,
79 .mem_resource = &mv_pci_mem1_resource,
80 .io_resource = &mv_pci_io_mem1_resource,
81 },
82 .config_addr = MV64340_PCI_1_CONFIG_ADDR,
83 .config_vreg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
84};
85
86static __init void mv64340_pci1_init(void)
87{
88 uint32_t mem0_base, mem0_size;
89 uint32_t io_base, io_size;
90
91 io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
92 io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
93 mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
94 mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
95
96 /*
97 * Here we assume the I/O window of second bus to be contiguous with
98 * the first. A gap is no problem but would waste address space for
99 * remapping the port space.
100 */
101 mv_pci_io_mem1_resource.start = mv_io_size;
102 mv_pci_io_mem1_resource.end = mv_io_size + io_size - 1;
103 mv_pci_mem1_resource.start = mem0_base;
104 mv_pci_mem1_resource.end = mem0_base + mem0_size - 1;
105 mv_bus1_controller.pcic.mem_offset = mem0_base;
106 mv_bus1_controller.pcic.io_offset = 0;
107
108 ioport_resource.end = io_base + io_size -mv_io_base - 1;
109
110 register_pci_controller(&mv_bus1_controller.pcic);
111
112 mv_io_size = io_base + io_size - mv_io_base;
113}
114
115static __init int __init ocelot_c_pci_init(void)
116{
117 unsigned long io_v_base;
118 uint32_t enable;
119
120 enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
121
122 /*
123 * We require at least one enabled I/O or PCI memory window or we
124 * will ignore this PCI bus. We ignore PCI windows 1, 2 and 3.
125 */
126 if (enable & (0x01 << 9) || enable & (0x01 << 10))
127 mv64340_pci0_init();
128
129 if (enable & (0x01 << 14) || enable & (0x01 << 15))
130 mv64340_pci1_init();
131
132 if (mv_io_size) {
133 io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
134 if (!io_v_base)
135 panic("Could not ioremap I/O port range");
136
137 set_io_port_base(io_v_base);
138 }
139
140 return 0;
141}
142
143arch_initcall(ocelot_c_pci_init);