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.
14 #include <linux/config.h>
18 #include <asm/mpc52xx.h>
19 #include "mpc52xx_pci.h"
21 #include <asm/delay.h>
22 #include <asm/machdep.h>
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
32 mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
33 int offset, int len, u32 *val)
35 struct pci_controller *hose = bus->sysdata;
38 if (ppc_md.pci_exclude_device)
39 if (ppc_md.pci_exclude_device(bus->number, devfn))
40 return PCIBIOS_DEVICE_NOT_FOUND;
42 out_be32(hose->cfg_addr,
44 ((bus->number - hose->bus_offset) << 16) |
49 #ifdef MPC5200_BUG_435_WORKAROUND
50 if (bus->number != hose->bus_offset) {
53 value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
56 value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
60 value = in_le16((u16 __iomem *)hose->cfg_data) |
61 (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
68 value = in_le32(hose->cfg_data);
71 value >>= ((offset & 0x3) << 3);
72 value &= 0xffffffff >> (32 - (len << 3));
78 out_be32(hose->cfg_addr, 0);
81 return PCIBIOS_SUCCESSFUL;
85 mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
86 int offset, int len, u32 val)
88 struct pci_controller *hose = bus->sysdata;
91 if (ppc_md.pci_exclude_device)
92 if (ppc_md.pci_exclude_device(bus->number, devfn))
93 return PCIBIOS_DEVICE_NOT_FOUND;
95 out_be32(hose->cfg_addr,
97 ((bus->number - hose->bus_offset) << 16) |
102 #ifdef MPC5200_BUG_435_WORKAROUND
103 if (bus->number != hose->bus_offset) {
106 out_8(((u8 __iomem *)hose->cfg_data) +
110 out_le16(((u16 __iomem *)hose->cfg_data) +
111 ((offset>>1) & 1), val);
115 out_le16((u16 __iomem *)hose->cfg_data,
117 out_le16(((u16 __iomem *)hose->cfg_data) + 1,
126 value = in_le32(hose->cfg_data);
128 offset = (offset & 0x3) << 3;
129 mask = (0xffffffff >> (32 - (len << 3)));
133 val = value | ((val << offset) & mask);
136 out_le32(hose->cfg_data, val);
140 out_be32(hose->cfg_addr, 0);
143 return PCIBIOS_SUCCESSFUL;
146 static struct pci_ops mpc52xx_pci_ops = {
147 .read = mpc52xx_pci_read_config,
148 .write = mpc52xx_pci_write_config
153 mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
157 /* Setup control regs */
158 tmp = in_be32(&pci_regs->scr);
159 tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
160 out_be32(&pci_regs->scr, tmp);
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 ));
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 ));
173 out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
175 MPC52xx_PCI_IO_START,
176 MPC52xx_PCI_IO_SIZE ));
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 )
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 );
195 out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
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 */
201 tmp = in_be32(&pci_regs->gscr);
203 out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
206 out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
210 mpc52xx_pci_fixup_resources(struct pci_dev *dev)
214 /* We don't rely on boot loader for PCI and resets all
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;
221 res->flags |= IORESOURCE_UNSET;
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 || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
230 struct resource *res = &dev->resource[1];
231 res->start = res->end = res->flags = 0;
236 mpc52xx_find_bridges(void)
238 struct mpc52xx_pci __iomem *pci_regs;
239 struct pci_controller *hose;
241 pci_assign_all_buses = 1;
243 pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
247 hose = pcibios_alloc_controller();
253 ppc_md.pci_swizzle = common_swizzle;
254 ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
256 hose->first_busno = 0;
257 hose->last_busno = 0xff;
258 hose->bus_offset = 0;
259 hose->ops = &mpc52xx_pci_ops;
261 mpc52xx_pci_setup(pci_regs);
263 hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
265 hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE);
266 isa_io_base = (unsigned long) hose->io_base_virt;
268 hose->cfg_addr = &pci_regs->car;
269 hose->cfg_data = hose->io_base_virt;
271 /* Setup resources */
272 pci_init_resource(&hose->mem_resources[0],
273 MPC52xx_PCI_MEM_START,
274 MPC52xx_PCI_MEM_STOP,
275 IORESOURCE_MEM|IORESOURCE_PREFETCH,
276 "PCI prefetchable memory");
278 pci_init_resource(&hose->mem_resources[1],
279 MPC52xx_PCI_MMIO_START,
280 MPC52xx_PCI_MMIO_STOP,
284 pci_init_resource(&hose->io_resource,
285 MPC52xx_PCI_IO_START,