diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 | 
| commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
| tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/syslib/mpc52xx_pci.c | |
| download | olio-linux-3.10-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.xz olio-linux-3.10-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.zip  | |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/ppc/syslib/mpc52xx_pci.c')
| -rw-r--r-- | arch/ppc/syslib/mpc52xx_pci.c | 235 | 
1 files changed, 235 insertions, 0 deletions
diff --git a/arch/ppc/syslib/mpc52xx_pci.c b/arch/ppc/syslib/mpc52xx_pci.c new file mode 100644 index 00000000000..c723efd954a --- /dev/null +++ b/arch/ppc/syslib/mpc52xx_pci.c @@ -0,0 +1,235 @@ +/* + * arch/ppc/syslib/mpc52xx_pci.c + * + * PCI code for the Freescale MPC52xx embedded CPU. + * + * + * Maintainer : Sylvain Munaut <tnt@246tNt.com> + * + * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/config.h> + +#include <asm/pci.h> + +#include <asm/mpc52xx.h> +#include "mpc52xx_pci.h" + +#include <asm/delay.h> + + +static int +mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, +				int offset, int len, u32 *val) +{ +	struct pci_controller *hose = bus->sysdata; +	u32 value; + +	if (ppc_md.pci_exclude_device) +		if (ppc_md.pci_exclude_device(bus->number, devfn)) +			return PCIBIOS_DEVICE_NOT_FOUND; + +	out_be32(hose->cfg_addr, +		(1 << 31) | +		((bus->number - hose->bus_offset) << 16) | +		(devfn << 8) | +		(offset & 0xfc)); + +	value = in_le32(hose->cfg_data); + +	if (len != 4) { +		value >>= ((offset & 0x3) << 3); +		value &= 0xffffffff >> (32 - (len << 3)); +	} + +	*val = value; + +	out_be32(hose->cfg_addr, 0); + +	return PCIBIOS_SUCCESSFUL; +} + +static int +mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, +				int offset, int len, u32 val) +{ +	struct pci_controller *hose = bus->sysdata; +	u32 value, mask; + +	if (ppc_md.pci_exclude_device) +		if (ppc_md.pci_exclude_device(bus->number, devfn)) +			return PCIBIOS_DEVICE_NOT_FOUND; + +	out_be32(hose->cfg_addr, +		(1 << 31) | +		((bus->number - hose->bus_offset) << 16) | +		(devfn << 8) | +		(offset & 0xfc)); + +	if (len != 4) { +		value = in_le32(hose->cfg_data); + +		offset = (offset & 0x3) << 3; +		mask = (0xffffffff >> (32 - (len << 3))); +		mask <<= offset; + +		value &= ~mask; +		val = value | ((val << offset) & mask); +	} + +	out_le32(hose->cfg_data, val); + +	out_be32(hose->cfg_addr, 0); + +	return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops mpc52xx_pci_ops = { +	.read  = mpc52xx_pci_read_config, +	.write = mpc52xx_pci_write_config +}; + + +static void __init +mpc52xx_pci_setup(struct mpc52xx_pci __iomem *pci_regs) +{ + +	/* Setup control regs */ +		/* Nothing to do afaik */ + +	/* Setup windows */ +	out_be32(&pci_regs->iw0btar, MPC52xx_PCI_IWBTAR_TRANSLATION( +		MPC52xx_PCI_MEM_START + MPC52xx_PCI_MEM_OFFSET, +		MPC52xx_PCI_MEM_START, +		MPC52xx_PCI_MEM_SIZE )); + +	out_be32(&pci_regs->iw1btar, MPC52xx_PCI_IWBTAR_TRANSLATION( +		MPC52xx_PCI_MMIO_START + MPC52xx_PCI_MEM_OFFSET, +		MPC52xx_PCI_MMIO_START, +		MPC52xx_PCI_MMIO_SIZE )); + +	out_be32(&pci_regs->iw2btar, MPC52xx_PCI_IWBTAR_TRANSLATION( +		MPC52xx_PCI_IO_BASE, +		MPC52xx_PCI_IO_START, +		MPC52xx_PCI_IO_SIZE )); + +	out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK( +		( MPC52xx_PCI_IWCR_ENABLE |		/* iw0btar */ +		  MPC52xx_PCI_IWCR_READ_MULTI | +		  MPC52xx_PCI_IWCR_MEM ), +		( MPC52xx_PCI_IWCR_ENABLE |		/* iw1btar */ +		  MPC52xx_PCI_IWCR_READ | +		  MPC52xx_PCI_IWCR_MEM ), +		( MPC52xx_PCI_IWCR_ENABLE |		/* iw2btar */ +		  MPC52xx_PCI_IWCR_IO ) +	)); + + +	out_be32(&pci_regs->tbatr0, +		MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO ); +	out_be32(&pci_regs->tbatr1, +		MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM ); + +	out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD); + +	/* Reset the exteral bus ( internal PCI controller is NOT resetted ) */ +	/* Not necessary and can be a bad thing if for example the bootloader +	   is displaying a splash screen or ... Just left here for +	   documentation purpose if anyone need it */ +#if 0 +	u32 tmp; +	tmp = in_be32(&pci_regs->gscr); +	out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR); +	udelay(50); +	out_be32(&pci_regs->gscr, tmp); +#endif +} + +static void __init +mpc52xx_pci_fixup_resources(struct pci_dev *dev) +{ +	int i; + +	/* We don't rely on boot loader for PCI and resets all +	   devices */ +	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { +		struct resource *res = &dev->resource[i]; +		if (res->end > res->start) {	/* Only valid resources */ +			res->end -= res->start; +			res->start = 0; +			res->flags |= IORESOURCE_UNSET; +		} +	} + +	/* The PCI Host bridge of MPC52xx has a prefetch memory resource +	   fixed to 1Gb. Doesn't fit in the resource system so we remove it */ +	if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) && +	     (dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200) ) { +		struct resource *res = &dev->resource[1]; +		res->start = res->end = res->flags = 0; +	} +} + +void __init +mpc52xx_find_bridges(void) +{ +	struct mpc52xx_pci __iomem *pci_regs; +	struct pci_controller *hose; + +	pci_assign_all_busses = 1; + +	pci_regs = ioremap(MPC52xx_PA(MPC52xx_PCI_OFFSET), MPC52xx_PCI_SIZE); +	if (!pci_regs) +		return; + +	hose = pcibios_alloc_controller(); +	if (!hose) { +		iounmap(pci_regs); +		return; +	} + +	ppc_md.pci_swizzle = common_swizzle; +	ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources; + +	hose->first_busno = 0; +	hose->last_busno = 0xff; +	hose->bus_offset = 0; +	hose->ops = &mpc52xx_pci_ops; + +	mpc52xx_pci_setup(pci_regs); + +	hose->pci_mem_offset = MPC52xx_PCI_MEM_OFFSET; + +	isa_io_base = +		(unsigned long) ioremap(MPC52xx_PCI_IO_BASE, +					MPC52xx_PCI_IO_SIZE); +	hose->io_base_virt = (void *) isa_io_base; + +	hose->cfg_addr = &pci_regs->car; +	hose->cfg_data = (void __iomem *) isa_io_base; + +	/* Setup resources */ +	pci_init_resource(&hose->mem_resources[0], +			MPC52xx_PCI_MEM_START, +			MPC52xx_PCI_MEM_STOP, +			IORESOURCE_MEM|IORESOURCE_PREFETCH, +			"PCI prefetchable memory"); + +	pci_init_resource(&hose->mem_resources[1], +			MPC52xx_PCI_MMIO_START, +			MPC52xx_PCI_MMIO_STOP, +			IORESOURCE_MEM, +			"PCI memory"); + +	pci_init_resource(&hose->io_resource, +			MPC52xx_PCI_IO_START, +			MPC52xx_PCI_IO_STOP, +			IORESOURCE_IO, +			"PCI I/O"); + +}  |