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