[PATCH] powerpc: trivial: modify comments to refer to new location of files
[deliverable/linux.git] / arch / ppc / syslib / mpc52xx_pci.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * PCI code for the Freescale MPC52xx embedded CPU.
3 *
4 *
5 * Maintainer : Sylvain Munaut <tnt@246tNt.com>
6 *
7 * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
8 *
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied.
12 */
13
14#include <linux/config.h>
15
16#include <asm/pci.h>
17
18#include <asm/mpc52xx.h>
19#include "mpc52xx_pci.h"
20
21#include <asm/delay.h>
fd582ec8 22#include <asm/machdep.h>
1da177e4
LT
23
24
db674ed4
SM
25/* This macro is defined to activate the workaround for the bug
26 435 of the MPC5200 (L25R). With it activated, we don't do any
27 32 bits configuration access during type-1 cycles */
28#define MPC5200_BUG_435_WORKAROUND
29
30
1da177e4
LT
31static int
32mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
33 int offset, int len, u32 *val)
34{
35 struct pci_controller *hose = bus->sysdata;
36 u32 value;
37
38 if (ppc_md.pci_exclude_device)
39 if (ppc_md.pci_exclude_device(bus->number, devfn))
40 return PCIBIOS_DEVICE_NOT_FOUND;
41
42 out_be32(hose->cfg_addr,
43 (1 << 31) |
44 ((bus->number - hose->bus_offset) << 16) |
45 (devfn << 8) |
46 (offset & 0xfc));
db674ed4
SM
47 mb();
48
49#ifdef MPC5200_BUG_435_WORKAROUND
50 if (bus->number != hose->bus_offset) {
51 switch (len) {
52 case 1:
53 value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
54 break;
55 case 2:
56 value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
57 break;
58
59 default:
60 value = in_le16((u16 __iomem *)hose->cfg_data) |
61 (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
62 break;
63 }
64 }
65 else
66#endif
67 {
68 value = in_le32(hose->cfg_data);
1da177e4 69
db674ed4
SM
70 if (len != 4) {
71 value >>= ((offset & 0x3) << 3);
72 value &= 0xffffffff >> (32 - (len << 3));
73 }
1da177e4
LT
74 }
75
76 *val = value;
77
78 out_be32(hose->cfg_addr, 0);
db674ed4 79 mb();
1da177e4
LT
80
81 return PCIBIOS_SUCCESSFUL;
82}
83
84static int
85mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
86 int offset, int len, u32 val)
87{
88 struct pci_controller *hose = bus->sysdata;
89 u32 value, mask;
90
91 if (ppc_md.pci_exclude_device)
92 if (ppc_md.pci_exclude_device(bus->number, devfn))
93 return PCIBIOS_DEVICE_NOT_FOUND;
94
95 out_be32(hose->cfg_addr,
96 (1 << 31) |
97 ((bus->number - hose->bus_offset) << 16) |
98 (devfn << 8) |
99 (offset & 0xfc));
db674ed4
SM
100 mb();
101
102#ifdef MPC5200_BUG_435_WORKAROUND
103 if (bus->number != hose->bus_offset) {
104 switch (len) {
105 case 1:
106 out_8(((u8 __iomem *)hose->cfg_data) +
107 (offset & 3), val);
108 break;
109 case 2:
110 out_le16(((u16 __iomem *)hose->cfg_data) +
111 ((offset>>1) & 1), val);
112 break;
113
114 default:
115 out_le16((u16 __iomem *)hose->cfg_data,
116 (u16)val);
117 out_le16(((u16 __iomem *)hose->cfg_data) + 1,
118 (u16)(val>>16));
119 break;
120 }
121 }
122 else
123#endif
124 {
125 if (len != 4) {
126 value = in_le32(hose->cfg_data);
1da177e4 127
db674ed4
SM
128 offset = (offset & 0x3) << 3;
129 mask = (0xffffffff >> (32 - (len << 3)));
130 mask <<= offset;
1da177e4 131
db674ed4
SM
132 value &= ~mask;
133 val = value | ((val << offset) & mask);
134 }
1da177e4 135
db674ed4 136 out_le32(hose->cfg_data, val);
1da177e4 137 }
db674ed4 138 mb();
1da177e4
LT
139
140 out_be32(hose->cfg_addr, 0);
db674ed4 141 mb();
1da177e4
LT
142
143 return PCIBIOS_SUCCESSFUL;
144}
145
146static struct pci_ops mpc52xx_pci_ops = {
147 .read = mpc52xx_pci_read_config,
148 .write = mpc52xx_pci_write_config
149};
150
151
152static void __init
153mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
154{
041cb624 155 u32 tmp;
1da177e4
LT
156
157 /* Setup control regs */
041cb624
SM
158 tmp = in_be32(&pci_regs->scr);
159 tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
160 out_be32(&pci_regs->scr, tmp);
1da177e4
LT
161
162 /* Setup windows */
163 out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
164 MPC52xx_PCI_MEM_START + MPC52xx_PCI_MEM_OFFSET,
165 MPC52xx_PCI_MEM_START,
166 MPC52xx_PCI_MEM_SIZE ));
167
168 out_be32(&pci_regs->iw1btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
169 MPC52xx_PCI_MMIO_START + MPC52xx_PCI_MEM_OFFSET,
170 MPC52xx_PCI_MMIO_START,
171 MPC52xx_PCI_MMIO_SIZE ));
172
173 out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
174 MPC52xx_PCI_IO_BASE,
175 MPC52xx_PCI_IO_START,
176 MPC52xx_PCI_IO_SIZE ));
177
178 out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(
179 ( MPC52xx_PCI_IWCR_ENABLE | /* iw0btar */
180 MPC52xx_PCI_IWCR_READ_MULTI |
181 MPC52xx_PCI_IWCR_MEM ),
182 ( MPC52xx_PCI_IWCR_ENABLE | /* iw1btar */
183 MPC52xx_PCI_IWCR_READ |
184 MPC52xx_PCI_IWCR_MEM ),
185 ( MPC52xx_PCI_IWCR_ENABLE | /* iw2btar */
186 MPC52xx_PCI_IWCR_IO )
187 ));
188
189
190 out_be32(&pci_regs->tbatr0,
191 MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
192 out_be32(&pci_regs->tbatr1,
193 MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
194
195 out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
196
197 /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
198 /* Not necessary and can be a bad thing if for example the bootloader
199 is displaying a splash screen or ... Just left here for
200 documentation purpose if anyone need it */
1da177e4 201 tmp = in_be32(&pci_regs->gscr);
041cb624 202#if 0
1da177e4
LT
203 out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
204 udelay(50);
1da177e4 205#endif
041cb624 206 out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
1da177e4
LT
207}
208
dbeb198d 209static void
1da177e4
LT
210mpc52xx_pci_fixup_resources(struct pci_dev *dev)
211{
212 int i;
213
214 /* We don't rely on boot loader for PCI and resets all
215 devices */
216 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
217 struct resource *res = &dev->resource[i];
218 if (res->end > res->start) { /* Only valid resources */
219 res->end -= res->start;
220 res->start = 0;
221 res->flags |= IORESOURCE_UNSET;
222 }
223 }
224
225 /* The PCI Host bridge of MPC52xx has a prefetch memory resource
226 fixed to 1Gb. Doesn't fit in the resource system so we remove it */
227 if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
228 (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200) ) {
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
399fe2bd 240 pci_assign_all_buses = 1;
1da177e4
LT
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
92a11f9e
AV
264 hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE);
265 isa_io_base = (unsigned long) hose->io_base_virt;
1da177e4
LT
266
267 hose->cfg_addr = &pci_regs->car;
92a11f9e 268 hose->cfg_data = hose->io_base_virt;
1da177e4
LT
269
270 /* Setup resources */
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}
This page took 0.091291 seconds and 5 git commands to generate.