2 * PCI code for the Freescale MPC52xx embedded CPU.
5 * Maintainer : Sylvain Munaut <tnt@246tNt.com>
7 * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
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.
17 #include <asm/mpc52xx.h>
18 #include "mpc52xx_pci.h"
20 #include <asm/delay.h>
21 #include <asm/machdep.h>
24 /* This macro is defined to activate the workaround for the bug
25 435 of the MPC5200 (L25R). With it activated, we don't do any
26 32 bits configuration access during type-1 cycles */
27 #define MPC5200_BUG_435_WORKAROUND
31 mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
32 int offset, int len, u32 *val)
34 struct pci_controller *hose = bus->sysdata;
37 if (ppc_md.pci_exclude_device)
38 if (ppc_md.pci_exclude_device(bus->number, devfn))
39 return PCIBIOS_DEVICE_NOT_FOUND;
41 out_be32(hose->cfg_addr,
43 ((bus->number - hose->bus_offset) << 16) |
48 #ifdef MPC5200_BUG_435_WORKAROUND
49 if (bus->number != hose->bus_offset) {
52 value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
55 value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
59 value = in_le16((u16 __iomem *)hose->cfg_data) |
60 (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
67 value = in_le32(hose->cfg_data);
70 value >>= ((offset & 0x3) << 3);
71 value &= 0xffffffff >> (32 - (len << 3));
77 out_be32(hose->cfg_addr, 0);
80 return PCIBIOS_SUCCESSFUL;
84 mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
85 int offset, int len, u32 val)
87 struct pci_controller *hose = bus->sysdata;
90 if (ppc_md.pci_exclude_device)
91 if (ppc_md.pci_exclude_device(bus->number, devfn))
92 return PCIBIOS_DEVICE_NOT_FOUND;
94 out_be32(hose->cfg_addr,
96 ((bus->number - hose->bus_offset) << 16) |
101 #ifdef MPC5200_BUG_435_WORKAROUND
102 if (bus->number != hose->bus_offset) {
105 out_8(((u8 __iomem *)hose->cfg_data) +
109 out_le16(((u16 __iomem *)hose->cfg_data) +
110 ((offset>>1) & 1), val);
114 out_le16((u16 __iomem *)hose->cfg_data,
116 out_le16(((u16 __iomem *)hose->cfg_data) + 1,
125 value = in_le32(hose->cfg_data);
127 offset = (offset & 0x3) << 3;
128 mask = (0xffffffff >> (32 - (len << 3)));
132 val = value | ((val << offset) & mask);
135 out_le32(hose->cfg_data, val);
139 out_be32(hose->cfg_addr, 0);
142 return PCIBIOS_SUCCESSFUL;
145 static struct pci_ops mpc52xx_pci_ops = {
146 .read = mpc52xx_pci_read_config,
147 .write = mpc52xx_pci_write_config
152 mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
156 /* Setup control regs */
157 tmp = in_be32(&pci_regs->scr);
158 tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
159 out_be32(&pci_regs->scr, tmp);
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 ));
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 ));
172 out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
174 MPC52xx_PCI_IO_START,
175 MPC52xx_PCI_IO_SIZE ));
177 out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(
178 ( MPC52xx_PCI_IWCR_ENABLE | /* iw0btar */
179 MPC52xx_PCI_IWCR_READ_MULTI |
180 MPC52xx_PCI_IWCR_MEM ),
181 ( MPC52xx_PCI_IWCR_ENABLE | /* iw1btar */
182 MPC52xx_PCI_IWCR_READ |
183 MPC52xx_PCI_IWCR_MEM ),
184 ( MPC52xx_PCI_IWCR_ENABLE | /* iw2btar */
185 MPC52xx_PCI_IWCR_IO )
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 );
194 out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
196 /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
197 /* Not necessary and can be a bad thing if for example the bootloader
198 is displaying a splash screen or ... Just left here for
199 documentation purpose if anyone need it */
200 tmp = in_be32(&pci_regs->gscr);
202 out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
205 out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
209 mpc52xx_pci_fixup_resources(struct pci_dev *dev)
213 /* We don't rely on boot loader for PCI and resets all
215 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
216 struct resource *res = &dev->resource[i];
217 if (res->end > res->start) { /* Only valid resources */
218 res->end -= res->start;
220 res->flags |= IORESOURCE_UNSET;
224 /* The PCI Host bridge of MPC52xx has a prefetch memory resource
225 fixed to 1Gb. Doesn't fit in the resource system so we remove it */
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;
235 mpc52xx_find_bridges(void)
237 struct mpc52xx_pci __iomem *pci_regs;
238 struct pci_controller *hose;
240 pci_assign_all_buses = 1;
242 pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
246 hose = pcibios_alloc_controller();
252 ppc_md.pci_swizzle = common_swizzle;
253 ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
255 hose->first_busno = 0;
256 hose->last_busno = 0xff;
257 hose->bus_offset = 0;
258 hose->ops = &mpc52xx_pci_ops;
260 mpc52xx_pci_setup(pci_regs);
262 hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
264 hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE);
265 isa_io_base = (unsigned long) hose->io_base_virt;
267 hose->cfg_addr = &pci_regs->car;
268 hose->cfg_data = hose->io_base_virt;
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");
277 pci_init_resource(&hose->mem_resources[1],
278 MPC52xx_PCI_MMIO_START,
279 MPC52xx_PCI_MMIO_STOP,
283 pci_init_resource(&hose->io_resource,
284 MPC52xx_PCI_IO_START,