2 * arch/ppc/syslib/mpc52xx_pci.c
4 * PCI code for the Freescale MPC52xx embedded CPU.
7 * Maintainer : Sylvain Munaut <tnt@246tNt.com>
9 * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
11 * This file is licensed under the terms of the GNU General Public License
12 * version 2. This program is licensed "as is" without any warranty of any
13 * kind, whether express or implied.
16 #include <linux/config.h>
20 #include <asm/mpc52xx.h>
21 #include "mpc52xx_pci.h"
23 #include <asm/delay.h>
24 #include <asm/machdep.h>
27 /* This macro is defined to activate the workaround for the bug
28 435 of the MPC5200 (L25R). With it activated, we don't do any
29 32 bits configuration access during type-1 cycles */
30 #define MPC5200_BUG_435_WORKAROUND
34 mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
35 int offset, int len, u32 *val)
37 struct pci_controller *hose = bus->sysdata;
40 if (ppc_md.pci_exclude_device)
41 if (ppc_md.pci_exclude_device(bus->number, devfn))
42 return PCIBIOS_DEVICE_NOT_FOUND;
44 out_be32(hose->cfg_addr,
46 ((bus->number - hose->bus_offset) << 16) |
51 #ifdef MPC5200_BUG_435_WORKAROUND
52 if (bus->number != hose->bus_offset) {
55 value = in_8(((u8 __iomem *)hose->cfg_data) + (offset & 3));
58 value = in_le16(((u16 __iomem *)hose->cfg_data) + ((offset>>1) & 1));
62 value = in_le16((u16 __iomem *)hose->cfg_data) |
63 (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
70 value = in_le32(hose->cfg_data);
73 value >>= ((offset & 0x3) << 3);
74 value &= 0xffffffff >> (32 - (len << 3));
80 out_be32(hose->cfg_addr, 0);
83 return PCIBIOS_SUCCESSFUL;
87 mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
88 int offset, int len, u32 val)
90 struct pci_controller *hose = bus->sysdata;
93 if (ppc_md.pci_exclude_device)
94 if (ppc_md.pci_exclude_device(bus->number, devfn))
95 return PCIBIOS_DEVICE_NOT_FOUND;
97 out_be32(hose->cfg_addr,
99 ((bus->number - hose->bus_offset) << 16) |
104 #ifdef MPC5200_BUG_435_WORKAROUND
105 if (bus->number != hose->bus_offset) {
108 out_8(((u8 __iomem *)hose->cfg_data) +
112 out_le16(((u16 __iomem *)hose->cfg_data) +
113 ((offset>>1) & 1), val);
117 out_le16((u16 __iomem *)hose->cfg_data,
119 out_le16(((u16 __iomem *)hose->cfg_data) + 1,
128 value = in_le32(hose->cfg_data);
130 offset = (offset & 0x3) << 3;
131 mask = (0xffffffff >> (32 - (len << 3)));
135 val = value | ((val << offset) & mask);
138 out_le32(hose->cfg_data, val);
142 out_be32(hose->cfg_addr, 0);
145 return PCIBIOS_SUCCESSFUL;
148 static struct pci_ops mpc52xx_pci_ops = {
149 .read = mpc52xx_pci_read_config,
150 .write = mpc52xx_pci_write_config
155 mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs)
159 /* Setup control regs */
160 tmp = in_be32(&pci_regs->scr);
161 tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
162 out_be32(&pci_regs->scr, tmp);
165 out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
166 MPC52xx_PCI_MEM_START + MPC52xx_PCI_MEM_OFFSET,
167 MPC52xx_PCI_MEM_START,
168 MPC52xx_PCI_MEM_SIZE ));
170 out_be32(&pci_regs->iw1btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
171 MPC52xx_PCI_MMIO_START + MPC52xx_PCI_MEM_OFFSET,
172 MPC52xx_PCI_MMIO_START,
173 MPC52xx_PCI_MMIO_SIZE ));
175 out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION(
177 MPC52xx_PCI_IO_START,
178 MPC52xx_PCI_IO_SIZE ));
180 out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(
181 ( MPC52xx_PCI_IWCR_ENABLE | /* iw0btar */
182 MPC52xx_PCI_IWCR_READ_MULTI |
183 MPC52xx_PCI_IWCR_MEM ),
184 ( MPC52xx_PCI_IWCR_ENABLE | /* iw1btar */
185 MPC52xx_PCI_IWCR_READ |
186 MPC52xx_PCI_IWCR_MEM ),
187 ( MPC52xx_PCI_IWCR_ENABLE | /* iw2btar */
188 MPC52xx_PCI_IWCR_IO )
192 out_be32(&pci_regs->tbatr0,
193 MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
194 out_be32(&pci_regs->tbatr1,
195 MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
197 out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
199 /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
200 /* Not necessary and can be a bad thing if for example the bootloader
201 is displaying a splash screen or ... Just left here for
202 documentation purpose if anyone need it */
203 tmp = in_be32(&pci_regs->gscr);
205 out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
208 out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
212 mpc52xx_pci_fixup_resources(struct pci_dev *dev)
216 /* We don't rely on boot loader for PCI and resets all
218 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
219 struct resource *res = &dev->resource[i];
220 if (res->end > res->start) { /* Only valid resources */
221 res->end -= res->start;
223 res->flags |= IORESOURCE_UNSET;
227 /* The PCI Host bridge of MPC52xx has a prefetch memory resource
228 fixed to 1Gb. Doesn't fit in the resource system so we remove it */
229 if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
230 (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200) ) {
231 struct resource *res = &dev->resource[1];
232 res->start = res->end = res->flags = 0;
237 mpc52xx_find_bridges(void)
239 struct mpc52xx_pci __iomem *pci_regs;
240 struct pci_controller *hose;
242 pci_assign_all_buses = 1;
244 pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE);
248 hose = pcibios_alloc_controller();
254 ppc_md.pci_swizzle = common_swizzle;
255 ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
257 hose->first_busno = 0;
258 hose->last_busno = 0xff;
259 hose->bus_offset = 0;
260 hose->ops = &mpc52xx_pci_ops;
262 mpc52xx_pci_setup(pci_regs);
264 hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET;
266 hose->io_base_virt = ioremap(MPC52xx_PCI_IO_BASE, MPC52xx_PCI_IO_SIZE);
267 isa_io_base = (unsigned long) hose->io_base_virt;
269 hose->cfg_addr = &pci_regs->car;
270 hose->cfg_data = hose->io_base_virt;
272 /* Setup resources */
273 pci_init_resource(&hose->mem_resources[0],
274 MPC52xx_PCI_MEM_START,
275 MPC52xx_PCI_MEM_STOP,
276 IORESOURCE_MEM|IORESOURCE_PREFETCH,
277 "PCI prefetchable memory");
279 pci_init_resource(&hose->mem_resources[1],
280 MPC52xx_PCI_MMIO_START,
281 MPC52xx_PCI_MMIO_STOP,
285 pci_init_resource(&hose->io_resource,
286 MPC52xx_PCI_IO_START,