1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <asm/pci.h>
16
17#include <asm/mpc52xx.h>
18#include "mpc52xx_pci.h"
19
20#include <asm/delay.h>
21#include <asm/machdep.h>
22
23
24
25
26
27#define MPC5200_BUG_435_WORKAROUND
28
29
30static int
31mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
32 int offset, int len, u32 *val)
33{
34 struct pci_controller *hose = bus->sysdata;
35 u32 value;
36
37 if (ppc_md.pci_exclude_device)
38 if (ppc_md.pci_exclude_device(bus->number, devfn))
39 return PCIBIOS_DEVICE_NOT_FOUND;
40
41 out_be32(hose->cfg_addr,
42 (1 << 31) |
43 ((bus->number - hose->bus_offset) << 16) |
44 (devfn << 8) |
45 (offset & 0xfc));
46 mb();
47
48#ifdef MPC5200_BUG_435_WORKAROUND
49 if (bus->number != hose->bus_offset) {
50 switch (len) {
51 case 1:
52 value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
53 break;
54 case 2:
55 value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
56 break;
57
58 default:
59 value = in_le16((u16 __iomem *)hose->cfg_data) |
60 (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
61 break;
62 }
63 }
64 else
65#endif
66 {
67 value = in_le32(hose->cfg_data);
68
69 if (len != 4) {
70 value >>= ((offset & 0x3) << 3);
71 value &= 0xffffffff >> (32 - (len << 3));
72 }
73 }
74
75 *val = value;
76
77 out_be32(hose->cfg_addr, 0);
78 mb();
79
80 return PCIBIOS_SUCCESSFUL;
81}
82
83static int
84mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
85 int offset, int len, u32 val)
86{
87 struct pci_controller *hose = bus->sysdata;
88 u32 value, mask;
89
90 if (ppc_md.pci_exclude_device)
91 if (ppc_md.pci_exclude_device(bus->number, devfn))
92 return PCIBIOS_DEVICE_NOT_FOUND;
93
94 out_be32(hose->cfg_addr,
95 (1 << 31) |
96 ((bus->number - hose->bus_offset) << 16) |
97 (devfn << 8) |
98 (offset & 0xfc));
99 mb();
100
101#ifdef MPC5200_BUG_435_WORKAROUND
102 if (bus->number != hose->bus_offset) {
103 switch (len) {
104 case 1:
105 out_8(((u8 __iomem *)hose->cfg_data) +
106 (offset & 3), val);
107 break;
108 case 2:
109 out_le16(((u16 __iomem *)hose->cfg_data) +
110 ((offset>>1) & 1), val);
111 break;
112
113 default:
114 out_le16((u16 __iomem *)hose->cfg_data,
115 (u16)val);
116 out_le16(((u16 __iomem *)hose->cfg_data) + 1,
117 (u16)(val>>16));
118 break;
119 }
120 }
121 else
122#endif
123 {
124 if (len != 4) {
125 value = in_le32(hose->cfg_data);
126
127 offset = (offset & 0x3) << 3;
128 mask = (0xffffffff >> (32 - (len << 3)));
129 mask <<= offset;
130
131 value &= ~mask;
132 val = value | ((val << offset) & mask);
133 }
134
135 out_le32(hose->cfg_data, val);
136 }
137 mb();
138
139 out_be32(hose->cfg_addr, 0);
140 mb();
141
142 return PCIBIOS_SUCCESSFUL;
143}
144
145static struct pci_ops mpc52xx_pci_ops = {
146 .read = mpc52xx_pci_read_config,
147 .write = mpc52xx_pci_write_config
148};
149
150
151static void __init
152mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
153{
154 u32 tmp;
155
156
157 tmp = in_be32(&pci_regs->scr);
158 tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
159 out_be32(&pci_regs->scr, tmp);
160
161
162 out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
163 MPC52xx_PCI_MEM_START + MPC52xx_PCI_MEM_OFFSET,
164 MPC52xx_PCI_MEM_START,
165 MPC52xx_PCI_MEM_SIZE ));
166
167 out_be32(&pci_regs->iw1btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
168 MPC52xx_PCI_MMIO_START + MPC52xx_PCI_MEM_OFFSET,
169 MPC52xx_PCI_MMIO_START,
170 MPC52xx_PCI_MMIO_SIZE ));
171
172 out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
173 MPC52xx_PCI_IO_BASE,
174 MPC52xx_PCI_IO_START,
175 MPC52xx_PCI_IO_SIZE ));
176
177 out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(
178 ( MPC52xx_PCI_IWCR_ENABLE |
179 MPC52xx_PCI_IWCR_READ_MULTI |
180 MPC52xx_PCI_IWCR_MEM ),
181 ( MPC52xx_PCI_IWCR_ENABLE |
182 MPC52xx_PCI_IWCR_READ |
183 MPC52xx_PCI_IWCR_MEM ),
184 ( MPC52xx_PCI_IWCR_ENABLE |
185 MPC52xx_PCI_IWCR_IO )
186 ));
187
188
189 out_be32(&pci_regs->tbatr0,
190 MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
191 out_be32(&pci_regs->tbatr1,
192 MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
193
194 out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
195
196
197
198
199
200 tmp = in_be32(&pci_regs->gscr);
201#if 0
202 out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
203 udelay(50);
204#endif
205 out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
206}
207
208static void
209mpc52xx_pci_fixup_resources(struct pci_dev *dev)
210{
211 int i;
212
213
214
215 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
216 struct resource *res = &dev->resource[i];
217 if (res->end > res->start) {
218 res->end -= res->start;
219 res->start = 0;
220 res->flags |= IORESOURCE_UNSET;
221 }
222 }
223
224
225
226 if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
227 ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
228 || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
229 struct resource *res = &dev->resource[1];
230 res->start = res->end = res->flags = 0;
231 }
232}
233
234void __init
235mpc52xx_find_bridges(void)
236{
237 struct mpc52xx_pci __iomem *pci_regs;
238 struct pci_controller *hose;
239
240 pci_assign_all_buses = 1;
241
242 pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
243 if (!pci_regs)
244 return;
245
246 hose = pcibios_alloc_controller();
247 if (!hose) {
248 iounmap(pci_regs);
249 return;
250 }
251
252 ppc_md.pci_swizzle = common_swizzle;
253 ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
254
255 hose->first_busno = 0;
256 hose->last_busno = 0xff;
257 hose->bus_offset = 0;
258 hose->ops = &mpc52xx_pci_ops;
259
260 mpc52xx_pci_setup(pci_regs);
261
262 hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
263
264 hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE);
265 isa_io_base = (unsigned long) hose->io_base_virt;
266
267 hose->cfg_addr = &pci_regs->car;
268 hose->cfg_data = hose->io_base_virt;
269
270
271 pci_init_resource(&hose->mem_resources[0],
272 MPC52xx_PCI_MEM_START,
273 MPC52xx_PCI_MEM_STOP,
274 IORESOURCE_MEM|IORESOURCE_PREFETCH,
275 "PCI prefetchable memory");
276
277 pci_init_resource(&hose->mem_resources[1],
278 MPC52xx_PCI_MMIO_START,
279 MPC52xx_PCI_MMIO_STOP,
280 IORESOURCE_MEM,
281 "PCI memory");
282
283 pci_init_resource(&hose->io_resource,
284 MPC52xx_PCI_IO_START,
285 MPC52xx_PCI_IO_STOP,
286 IORESOURCE_IO,
287 "PCI I/O");
288
289}
290