17517de348663b08a808aff44b5300e817157a568Manuel Lauss/*
27517de348663b08a808aff44b5300e817157a568Manuel Lauss * Alchemy PCI host mode support.
37517de348663b08a808aff44b5300e817157a568Manuel Lauss *
47517de348663b08a808aff44b5300e817157a568Manuel Lauss * Copyright 2001-2003, 2007-2008 MontaVista Software Inc.
57517de348663b08a808aff44b5300e817157a568Manuel Lauss * Author: MontaVista Software, Inc. <source@mvista.com>
67517de348663b08a808aff44b5300e817157a568Manuel Lauss *
77517de348663b08a808aff44b5300e817157a568Manuel Lauss * Support for all devices (greater than 16) added by David Gathright.
87517de348663b08a808aff44b5300e817157a568Manuel Lauss */
97517de348663b08a808aff44b5300e817157a568Manuel Lauss
1071ca86937513f44151454cb6aa8a66e9ed86275aRalf Baechle#include <linux/export.h>
117517de348663b08a808aff44b5300e817157a568Manuel Lauss#include <linux/types.h>
127517de348663b08a808aff44b5300e817157a568Manuel Lauss#include <linux/pci.h>
137517de348663b08a808aff44b5300e817157a568Manuel Lauss#include <linux/platform_device.h>
147517de348663b08a808aff44b5300e817157a568Manuel Lauss#include <linux/kernel.h>
157517de348663b08a808aff44b5300e817157a568Manuel Lauss#include <linux/init.h>
16864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss#include <linux/syscore_ops.h>
177517de348663b08a808aff44b5300e817157a568Manuel Lauss#include <linux/vmalloc.h>
187517de348663b08a808aff44b5300e817157a568Manuel Lauss
197517de348663b08a808aff44b5300e817157a568Manuel Lauss#include <asm/mach-au1x00/au1000.h>
203d18c98367eac23555ea4887c4f570423474eeafRalf Baechle#include <asm/tlbmisc.h>
217517de348663b08a808aff44b5300e817157a568Manuel Lauss
227517de348663b08a808aff44b5300e817157a568Manuel Lauss#ifdef CONFIG_DEBUG_PCI
237517de348663b08a808aff44b5300e817157a568Manuel Lauss#define DBG(x...) printk(KERN_DEBUG x)
247517de348663b08a808aff44b5300e817157a568Manuel Lauss#else
257517de348663b08a808aff44b5300e817157a568Manuel Lauss#define DBG(x...) do {} while (0)
267517de348663b08a808aff44b5300e817157a568Manuel Lauss#endif
277517de348663b08a808aff44b5300e817157a568Manuel Lauss
287517de348663b08a808aff44b5300e817157a568Manuel Lauss#define PCI_ACCESS_READ		0
297517de348663b08a808aff44b5300e817157a568Manuel Lauss#define PCI_ACCESS_WRITE	1
307517de348663b08a808aff44b5300e817157a568Manuel Lauss
317517de348663b08a808aff44b5300e817157a568Manuel Laussstruct alchemy_pci_context {
327517de348663b08a808aff44b5300e817157a568Manuel Lauss	struct pci_controller alchemy_pci_ctrl;	/* leave as first member! */
337517de348663b08a808aff44b5300e817157a568Manuel Lauss	void __iomem *regs;			/* ctrl base */
347517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* tools for wired entry for config space access */
357517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned long last_elo0;
367517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned long last_elo1;
377517de348663b08a808aff44b5300e817157a568Manuel Lauss	int wired_entry;
387517de348663b08a808aff44b5300e817157a568Manuel Lauss	struct vm_struct *pci_cfg_vm;
397517de348663b08a808aff44b5300e817157a568Manuel Lauss
407517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned long pm[12];
417517de348663b08a808aff44b5300e817157a568Manuel Lauss
427517de348663b08a808aff44b5300e817157a568Manuel Lauss	int (*board_map_irq)(const struct pci_dev *d, u8 slot, u8 pin);
437517de348663b08a808aff44b5300e817157a568Manuel Lauss	int (*board_pci_idsel)(unsigned int devsel, int assert);
447517de348663b08a808aff44b5300e817157a568Manuel Lauss};
457517de348663b08a808aff44b5300e817157a568Manuel Lauss
46864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss/* for syscore_ops. There's only one PCI controller on Alchemy chips, so this
47864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss * should suffice for now.
48864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss */
49864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Laussstatic struct alchemy_pci_context *__alchemy_pci_ctx;
50864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
51864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
527517de348663b08a808aff44b5300e817157a568Manuel Lauss/* IO/MEM resources for PCI. Keep the memres in sync with __fixup_bigphys_addr
537517de348663b08a808aff44b5300e817157a568Manuel Lauss * in arch/mips/alchemy/common/setup.c
547517de348663b08a808aff44b5300e817157a568Manuel Lauss */
557517de348663b08a808aff44b5300e817157a568Manuel Laussstatic struct resource alchemy_pci_def_memres = {
567517de348663b08a808aff44b5300e817157a568Manuel Lauss	.start	= ALCHEMY_PCI_MEMWIN_START,
577517de348663b08a808aff44b5300e817157a568Manuel Lauss	.end	= ALCHEMY_PCI_MEMWIN_END,
587517de348663b08a808aff44b5300e817157a568Manuel Lauss	.name	= "PCI memory space",
597517de348663b08a808aff44b5300e817157a568Manuel Lauss	.flags	= IORESOURCE_MEM
607517de348663b08a808aff44b5300e817157a568Manuel Lauss};
617517de348663b08a808aff44b5300e817157a568Manuel Lauss
627517de348663b08a808aff44b5300e817157a568Manuel Laussstatic struct resource alchemy_pci_def_iores = {
637517de348663b08a808aff44b5300e817157a568Manuel Lauss	.start	= ALCHEMY_PCI_IOWIN_START,
647517de348663b08a808aff44b5300e817157a568Manuel Lauss	.end	= ALCHEMY_PCI_IOWIN_END,
657517de348663b08a808aff44b5300e817157a568Manuel Lauss	.name	= "PCI IO space",
667517de348663b08a808aff44b5300e817157a568Manuel Lauss	.flags	= IORESOURCE_IO
677517de348663b08a808aff44b5300e817157a568Manuel Lauss};
687517de348663b08a808aff44b5300e817157a568Manuel Lauss
697517de348663b08a808aff44b5300e817157a568Manuel Laussstatic void mod_wired_entry(int entry, unsigned long entrylo0,
707517de348663b08a808aff44b5300e817157a568Manuel Lauss		unsigned long entrylo1, unsigned long entryhi,
717517de348663b08a808aff44b5300e817157a568Manuel Lauss		unsigned long pagemask)
727517de348663b08a808aff44b5300e817157a568Manuel Lauss{
737517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned long old_pagemask;
747517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned long old_ctx;
757517de348663b08a808aff44b5300e817157a568Manuel Lauss
767517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Save old context and create impossible VPN2 value */
777517de348663b08a808aff44b5300e817157a568Manuel Lauss	old_ctx = read_c0_entryhi() & 0xff;
787517de348663b08a808aff44b5300e817157a568Manuel Lauss	old_pagemask = read_c0_pagemask();
797517de348663b08a808aff44b5300e817157a568Manuel Lauss	write_c0_index(entry);
807517de348663b08a808aff44b5300e817157a568Manuel Lauss	write_c0_pagemask(pagemask);
817517de348663b08a808aff44b5300e817157a568Manuel Lauss	write_c0_entryhi(entryhi);
827517de348663b08a808aff44b5300e817157a568Manuel Lauss	write_c0_entrylo0(entrylo0);
837517de348663b08a808aff44b5300e817157a568Manuel Lauss	write_c0_entrylo1(entrylo1);
847517de348663b08a808aff44b5300e817157a568Manuel Lauss	tlb_write_indexed();
857517de348663b08a808aff44b5300e817157a568Manuel Lauss	write_c0_entryhi(old_ctx);
867517de348663b08a808aff44b5300e817157a568Manuel Lauss	write_c0_pagemask(old_pagemask);
877517de348663b08a808aff44b5300e817157a568Manuel Lauss}
887517de348663b08a808aff44b5300e817157a568Manuel Lauss
897517de348663b08a808aff44b5300e817157a568Manuel Laussstatic void alchemy_pci_wired_entry(struct alchemy_pci_context *ctx)
907517de348663b08a808aff44b5300e817157a568Manuel Lauss{
917517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx->wired_entry = read_c0_wired();
927517de348663b08a808aff44b5300e817157a568Manuel Lauss	add_wired_entry(0, 0, (unsigned long)ctx->pci_cfg_vm->addr, PM_4K);
937517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx->last_elo0 = ctx->last_elo1 = ~0;
947517de348663b08a808aff44b5300e817157a568Manuel Lauss}
957517de348663b08a808aff44b5300e817157a568Manuel Lauss
967517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int config_access(unsigned char access_type, struct pci_bus *bus,
977517de348663b08a808aff44b5300e817157a568Manuel Lauss			 unsigned int dev_fn, unsigned char where, u32 *data)
987517de348663b08a808aff44b5300e817157a568Manuel Lauss{
997517de348663b08a808aff44b5300e817157a568Manuel Lauss	struct alchemy_pci_context *ctx = bus->sysdata;
1007517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned int device = PCI_SLOT(dev_fn);
1017517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned int function = PCI_FUNC(dev_fn);
1027517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned long offset, status, cfg_base, flags, entryLo0, entryLo1, r;
1037517de348663b08a808aff44b5300e817157a568Manuel Lauss	int error = PCIBIOS_SUCCESSFUL;
1047517de348663b08a808aff44b5300e817157a568Manuel Lauss
1057517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (device > 19) {
1067517de348663b08a808aff44b5300e817157a568Manuel Lauss		*data = 0xffffffff;
1077517de348663b08a808aff44b5300e817157a568Manuel Lauss		return -1;
1087517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
1097517de348663b08a808aff44b5300e817157a568Manuel Lauss
1107517de348663b08a808aff44b5300e817157a568Manuel Lauss	local_irq_save(flags);
1117517de348663b08a808aff44b5300e817157a568Manuel Lauss	r = __raw_readl(ctx->regs + PCI_REG_STATCMD) & 0x0000ffff;
1127517de348663b08a808aff44b5300e817157a568Manuel Lauss	r |= PCI_STATCMD_STATUS(0x2000);
1137517de348663b08a808aff44b5300e817157a568Manuel Lauss	__raw_writel(r, ctx->regs + PCI_REG_STATCMD);
1147517de348663b08a808aff44b5300e817157a568Manuel Lauss	wmb();
1157517de348663b08a808aff44b5300e817157a568Manuel Lauss
1167517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Allow board vendors to implement their own off-chip IDSEL.
1177517de348663b08a808aff44b5300e817157a568Manuel Lauss	 * If it doesn't succeed, may as well bail out at this point.
1187517de348663b08a808aff44b5300e817157a568Manuel Lauss	 */
1197517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (ctx->board_pci_idsel(device, 1) == 0) {
1207517de348663b08a808aff44b5300e817157a568Manuel Lauss		*data = 0xffffffff;
1217517de348663b08a808aff44b5300e817157a568Manuel Lauss		local_irq_restore(flags);
1227517de348663b08a808aff44b5300e817157a568Manuel Lauss		return -1;
1237517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
1247517de348663b08a808aff44b5300e817157a568Manuel Lauss
1257517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Setup the config window */
1267517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (bus->number == 0)
1277517de348663b08a808aff44b5300e817157a568Manuel Lauss		cfg_base = (1 << device) << 11;
1287517de348663b08a808aff44b5300e817157a568Manuel Lauss	else
1297517de348663b08a808aff44b5300e817157a568Manuel Lauss		cfg_base = 0x80000000 | (bus->number << 16) | (device << 11);
1307517de348663b08a808aff44b5300e817157a568Manuel Lauss
1317517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Setup the lower bits of the 36-bit address */
1327517de348663b08a808aff44b5300e817157a568Manuel Lauss	offset = (function << 8) | (where & ~0x3);
1337517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Pick up any address that falls below the page mask */
1347517de348663b08a808aff44b5300e817157a568Manuel Lauss	offset |= cfg_base & ~PAGE_MASK;
1357517de348663b08a808aff44b5300e817157a568Manuel Lauss
1367517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Page boundary */
1377517de348663b08a808aff44b5300e817157a568Manuel Lauss	cfg_base = cfg_base & PAGE_MASK;
1387517de348663b08a808aff44b5300e817157a568Manuel Lauss
1397517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* To improve performance, if the current device is the same as
1407517de348663b08a808aff44b5300e817157a568Manuel Lauss	 * the last device accessed, we don't touch the TLB.
1417517de348663b08a808aff44b5300e817157a568Manuel Lauss	 */
1427517de348663b08a808aff44b5300e817157a568Manuel Lauss	entryLo0 = (6 << 26) | (cfg_base >> 6) | (2 << 3) | 7;
1437517de348663b08a808aff44b5300e817157a568Manuel Lauss	entryLo1 = (6 << 26) | (cfg_base >> 6) | (0x1000 >> 6) | (2 << 3) | 7;
1447517de348663b08a808aff44b5300e817157a568Manuel Lauss	if ((entryLo0 != ctx->last_elo0) || (entryLo1 != ctx->last_elo1)) {
1457517de348663b08a808aff44b5300e817157a568Manuel Lauss		mod_wired_entry(ctx->wired_entry, entryLo0, entryLo1,
1467517de348663b08a808aff44b5300e817157a568Manuel Lauss				(unsigned long)ctx->pci_cfg_vm->addr, PM_4K);
1477517de348663b08a808aff44b5300e817157a568Manuel Lauss		ctx->last_elo0 = entryLo0;
1487517de348663b08a808aff44b5300e817157a568Manuel Lauss		ctx->last_elo1 = entryLo1;
1497517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
1507517de348663b08a808aff44b5300e817157a568Manuel Lauss
1517517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (access_type == PCI_ACCESS_WRITE)
1527517de348663b08a808aff44b5300e817157a568Manuel Lauss		__raw_writel(*data, ctx->pci_cfg_vm->addr + offset);
1537517de348663b08a808aff44b5300e817157a568Manuel Lauss	else
1547517de348663b08a808aff44b5300e817157a568Manuel Lauss		*data = __raw_readl(ctx->pci_cfg_vm->addr + offset);
1557517de348663b08a808aff44b5300e817157a568Manuel Lauss	wmb();
1567517de348663b08a808aff44b5300e817157a568Manuel Lauss
1577517de348663b08a808aff44b5300e817157a568Manuel Lauss	DBG("alchemy-pci: cfg access %d bus %u dev %u at %x dat %x conf %lx\n",
1587517de348663b08a808aff44b5300e817157a568Manuel Lauss	    access_type, bus->number, device, where, *data, offset);
1597517de348663b08a808aff44b5300e817157a568Manuel Lauss
1607517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* check for errors, master abort */
1617517de348663b08a808aff44b5300e817157a568Manuel Lauss	status = __raw_readl(ctx->regs + PCI_REG_STATCMD);
1627517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (status & (1 << 29)) {
1637517de348663b08a808aff44b5300e817157a568Manuel Lauss		*data = 0xffffffff;
1647517de348663b08a808aff44b5300e817157a568Manuel Lauss		error = -1;
1657517de348663b08a808aff44b5300e817157a568Manuel Lauss		DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d",
1667517de348663b08a808aff44b5300e817157a568Manuel Lauss		    access_type, bus->number, device);
1677517de348663b08a808aff44b5300e817157a568Manuel Lauss	} else if ((status >> 28) & 0xf) {
1687517de348663b08a808aff44b5300e817157a568Manuel Lauss		DBG("alchemy-pci: PCI ERR detected: dev %d, status %lx\n",
1697517de348663b08a808aff44b5300e817157a568Manuel Lauss		    device, (status >> 28) & 0xf);
1707517de348663b08a808aff44b5300e817157a568Manuel Lauss
1717517de348663b08a808aff44b5300e817157a568Manuel Lauss		/* clear errors */
1727517de348663b08a808aff44b5300e817157a568Manuel Lauss		__raw_writel(status & 0xf000ffff, ctx->regs + PCI_REG_STATCMD);
1737517de348663b08a808aff44b5300e817157a568Manuel Lauss
1747517de348663b08a808aff44b5300e817157a568Manuel Lauss		*data = 0xffffffff;
1757517de348663b08a808aff44b5300e817157a568Manuel Lauss		error = -1;
1767517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
1777517de348663b08a808aff44b5300e817157a568Manuel Lauss
1787517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Take away the IDSEL. */
1797517de348663b08a808aff44b5300e817157a568Manuel Lauss	(void)ctx->board_pci_idsel(device, 0);
1807517de348663b08a808aff44b5300e817157a568Manuel Lauss
1817517de348663b08a808aff44b5300e817157a568Manuel Lauss	local_irq_restore(flags);
1827517de348663b08a808aff44b5300e817157a568Manuel Lauss	return error;
1837517de348663b08a808aff44b5300e817157a568Manuel Lauss}
1847517de348663b08a808aff44b5300e817157a568Manuel Lauss
1857517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int read_config_byte(struct pci_bus *bus, unsigned int devfn,
1867517de348663b08a808aff44b5300e817157a568Manuel Lauss			    int where,	u8 *val)
1877517de348663b08a808aff44b5300e817157a568Manuel Lauss{
1887517de348663b08a808aff44b5300e817157a568Manuel Lauss	u32 data;
1897517de348663b08a808aff44b5300e817157a568Manuel Lauss	int ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
1907517de348663b08a808aff44b5300e817157a568Manuel Lauss
1917517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (where & 1)
1927517de348663b08a808aff44b5300e817157a568Manuel Lauss		data >>= 8;
1937517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (where & 2)
1947517de348663b08a808aff44b5300e817157a568Manuel Lauss		data >>= 16;
1957517de348663b08a808aff44b5300e817157a568Manuel Lauss	*val = data & 0xff;
1967517de348663b08a808aff44b5300e817157a568Manuel Lauss	return ret;
1977517de348663b08a808aff44b5300e817157a568Manuel Lauss}
1987517de348663b08a808aff44b5300e817157a568Manuel Lauss
1997517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int read_config_word(struct pci_bus *bus, unsigned int devfn,
2007517de348663b08a808aff44b5300e817157a568Manuel Lauss			    int where, u16 *val)
2017517de348663b08a808aff44b5300e817157a568Manuel Lauss{
2027517de348663b08a808aff44b5300e817157a568Manuel Lauss	u32 data;
2037517de348663b08a808aff44b5300e817157a568Manuel Lauss	int ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
2047517de348663b08a808aff44b5300e817157a568Manuel Lauss
2057517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (where & 2)
2067517de348663b08a808aff44b5300e817157a568Manuel Lauss		data >>= 16;
2077517de348663b08a808aff44b5300e817157a568Manuel Lauss	*val = data & 0xffff;
2087517de348663b08a808aff44b5300e817157a568Manuel Lauss	return ret;
2097517de348663b08a808aff44b5300e817157a568Manuel Lauss}
2107517de348663b08a808aff44b5300e817157a568Manuel Lauss
2117517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int read_config_dword(struct pci_bus *bus, unsigned int devfn,
2127517de348663b08a808aff44b5300e817157a568Manuel Lauss			     int where, u32 *val)
2137517de348663b08a808aff44b5300e817157a568Manuel Lauss{
2147517de348663b08a808aff44b5300e817157a568Manuel Lauss	return config_access(PCI_ACCESS_READ, bus, devfn, where, val);
2157517de348663b08a808aff44b5300e817157a568Manuel Lauss}
2167517de348663b08a808aff44b5300e817157a568Manuel Lauss
2177517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int write_config_byte(struct pci_bus *bus, unsigned int devfn,
2187517de348663b08a808aff44b5300e817157a568Manuel Lauss			     int where, u8 val)
2197517de348663b08a808aff44b5300e817157a568Manuel Lauss{
2207517de348663b08a808aff44b5300e817157a568Manuel Lauss	u32 data = 0;
2217517de348663b08a808aff44b5300e817157a568Manuel Lauss
2227517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
2237517de348663b08a808aff44b5300e817157a568Manuel Lauss		return -1;
2247517de348663b08a808aff44b5300e817157a568Manuel Lauss
2257517de348663b08a808aff44b5300e817157a568Manuel Lauss	data = (data & ~(0xff << ((where & 3) << 3))) |
2267517de348663b08a808aff44b5300e817157a568Manuel Lauss	       (val << ((where & 3) << 3));
2277517de348663b08a808aff44b5300e817157a568Manuel Lauss
2287517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
2297517de348663b08a808aff44b5300e817157a568Manuel Lauss		return -1;
2307517de348663b08a808aff44b5300e817157a568Manuel Lauss
2317517de348663b08a808aff44b5300e817157a568Manuel Lauss	return PCIBIOS_SUCCESSFUL;
2327517de348663b08a808aff44b5300e817157a568Manuel Lauss}
2337517de348663b08a808aff44b5300e817157a568Manuel Lauss
2347517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int write_config_word(struct pci_bus *bus, unsigned int devfn,
2357517de348663b08a808aff44b5300e817157a568Manuel Lauss			     int where, u16 val)
2367517de348663b08a808aff44b5300e817157a568Manuel Lauss{
2377517de348663b08a808aff44b5300e817157a568Manuel Lauss	u32 data = 0;
2387517de348663b08a808aff44b5300e817157a568Manuel Lauss
2397517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
2407517de348663b08a808aff44b5300e817157a568Manuel Lauss		return -1;
2417517de348663b08a808aff44b5300e817157a568Manuel Lauss
2427517de348663b08a808aff44b5300e817157a568Manuel Lauss	data = (data & ~(0xffff << ((where & 3) << 3))) |
2437517de348663b08a808aff44b5300e817157a568Manuel Lauss	       (val << ((where & 3) << 3));
2447517de348663b08a808aff44b5300e817157a568Manuel Lauss
2457517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
2467517de348663b08a808aff44b5300e817157a568Manuel Lauss		return -1;
2477517de348663b08a808aff44b5300e817157a568Manuel Lauss
2487517de348663b08a808aff44b5300e817157a568Manuel Lauss	return PCIBIOS_SUCCESSFUL;
2497517de348663b08a808aff44b5300e817157a568Manuel Lauss}
2507517de348663b08a808aff44b5300e817157a568Manuel Lauss
2517517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int write_config_dword(struct pci_bus *bus, unsigned int devfn,
2527517de348663b08a808aff44b5300e817157a568Manuel Lauss			      int where, u32 val)
2537517de348663b08a808aff44b5300e817157a568Manuel Lauss{
2547517de348663b08a808aff44b5300e817157a568Manuel Lauss	return config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val);
2557517de348663b08a808aff44b5300e817157a568Manuel Lauss}
2567517de348663b08a808aff44b5300e817157a568Manuel Lauss
2577517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int alchemy_pci_read(struct pci_bus *bus, unsigned int devfn,
2587517de348663b08a808aff44b5300e817157a568Manuel Lauss		       int where, int size, u32 *val)
2597517de348663b08a808aff44b5300e817157a568Manuel Lauss{
2607517de348663b08a808aff44b5300e817157a568Manuel Lauss	switch (size) {
2617517de348663b08a808aff44b5300e817157a568Manuel Lauss	case 1: {
2627517de348663b08a808aff44b5300e817157a568Manuel Lauss			u8 _val;
2637517de348663b08a808aff44b5300e817157a568Manuel Lauss			int rc = read_config_byte(bus, devfn, where, &_val);
2647517de348663b08a808aff44b5300e817157a568Manuel Lauss
2657517de348663b08a808aff44b5300e817157a568Manuel Lauss			*val = _val;
2667517de348663b08a808aff44b5300e817157a568Manuel Lauss			return rc;
2677517de348663b08a808aff44b5300e817157a568Manuel Lauss		}
2687517de348663b08a808aff44b5300e817157a568Manuel Lauss	case 2: {
2697517de348663b08a808aff44b5300e817157a568Manuel Lauss			u16 _val;
2707517de348663b08a808aff44b5300e817157a568Manuel Lauss			int rc = read_config_word(bus, devfn, where, &_val);
2717517de348663b08a808aff44b5300e817157a568Manuel Lauss
2727517de348663b08a808aff44b5300e817157a568Manuel Lauss			*val = _val;
2737517de348663b08a808aff44b5300e817157a568Manuel Lauss			return rc;
2747517de348663b08a808aff44b5300e817157a568Manuel Lauss		}
2757517de348663b08a808aff44b5300e817157a568Manuel Lauss	default:
2767517de348663b08a808aff44b5300e817157a568Manuel Lauss		return read_config_dword(bus, devfn, where, val);
2777517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
2787517de348663b08a808aff44b5300e817157a568Manuel Lauss}
2797517de348663b08a808aff44b5300e817157a568Manuel Lauss
2807517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int alchemy_pci_write(struct pci_bus *bus, unsigned int devfn,
2817517de348663b08a808aff44b5300e817157a568Manuel Lauss			     int where, int size, u32 val)
2827517de348663b08a808aff44b5300e817157a568Manuel Lauss{
2837517de348663b08a808aff44b5300e817157a568Manuel Lauss	switch (size) {
2847517de348663b08a808aff44b5300e817157a568Manuel Lauss	case 1:
2857517de348663b08a808aff44b5300e817157a568Manuel Lauss		return write_config_byte(bus, devfn, where, (u8) val);
2867517de348663b08a808aff44b5300e817157a568Manuel Lauss	case 2:
2877517de348663b08a808aff44b5300e817157a568Manuel Lauss		return write_config_word(bus, devfn, where, (u16) val);
2887517de348663b08a808aff44b5300e817157a568Manuel Lauss	default:
2897517de348663b08a808aff44b5300e817157a568Manuel Lauss		return write_config_dword(bus, devfn, where, val);
2907517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
2917517de348663b08a808aff44b5300e817157a568Manuel Lauss}
2927517de348663b08a808aff44b5300e817157a568Manuel Lauss
2937517de348663b08a808aff44b5300e817157a568Manuel Laussstatic struct pci_ops alchemy_pci_ops = {
2947517de348663b08a808aff44b5300e817157a568Manuel Lauss	.read	= alchemy_pci_read,
2957517de348663b08a808aff44b5300e817157a568Manuel Lauss	.write	= alchemy_pci_write,
2967517de348663b08a808aff44b5300e817157a568Manuel Lauss};
2977517de348663b08a808aff44b5300e817157a568Manuel Lauss
2987517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int alchemy_pci_def_idsel(unsigned int devsel, int assert)
2997517de348663b08a808aff44b5300e817157a568Manuel Lauss{
3007517de348663b08a808aff44b5300e817157a568Manuel Lauss	return 1;	/* success */
3017517de348663b08a808aff44b5300e817157a568Manuel Lauss}
3027517de348663b08a808aff44b5300e817157a568Manuel Lauss
303864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss/* save PCI controller register contents. */
304864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Laussstatic int alchemy_pci_suspend(void)
305864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss{
306864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
307864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	if (!ctx)
308864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss		return 0;
309864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
310864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[0]  = __raw_readl(ctx->regs + PCI_REG_CMEM);
311864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[1]  = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009ffff;
312864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[2]  = __raw_readl(ctx->regs + PCI_REG_B2BMASK_CCH);
313864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[3]  = __raw_readl(ctx->regs + PCI_REG_B2BBASE0_VID);
314864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[4]  = __raw_readl(ctx->regs + PCI_REG_B2BBASE1_SID);
315864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[5]  = __raw_readl(ctx->regs + PCI_REG_MWMASK_DEV);
316864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[6]  = __raw_readl(ctx->regs + PCI_REG_MWBASE_REV_CCL);
317864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[7]  = __raw_readl(ctx->regs + PCI_REG_ID);
318864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[8]  = __raw_readl(ctx->regs + PCI_REG_CLASSREV);
319864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[9]  = __raw_readl(ctx->regs + PCI_REG_PARAM);
320864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[10] = __raw_readl(ctx->regs + PCI_REG_MBAR);
321864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->pm[11] = __raw_readl(ctx->regs + PCI_REG_TIMEOUT);
322864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
323864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	return 0;
324864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss}
325864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
326864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Laussstatic void alchemy_pci_resume(void)
327864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss{
328864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
329864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	if (!ctx)
330864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss		return;
331864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
332864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[0],  ctx->regs + PCI_REG_CMEM);
333864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[2],  ctx->regs + PCI_REG_B2BMASK_CCH);
334864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[3],  ctx->regs + PCI_REG_B2BBASE0_VID);
335864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[4],  ctx->regs + PCI_REG_B2BBASE1_SID);
336864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[5],  ctx->regs + PCI_REG_MWMASK_DEV);
337864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[6],  ctx->regs + PCI_REG_MWBASE_REV_CCL);
338864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[7],  ctx->regs + PCI_REG_ID);
339864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[8],  ctx->regs + PCI_REG_CLASSREV);
340864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[9],  ctx->regs + PCI_REG_PARAM);
341864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[10], ctx->regs + PCI_REG_MBAR);
342864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[11], ctx->regs + PCI_REG_TIMEOUT);
343864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	wmb();
344864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__raw_writel(ctx->pm[1],  ctx->regs + PCI_REG_CONFIG);
345864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	wmb();
346864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
347864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	/* YAMON on all db1xxx boards wipes the TLB and writes zero to C0_wired
348864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	 * on resume, making it necessary to recreate it as soon as possible.
349864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	 */
350864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->wired_entry = 8191;	/* impossibly high value */
351864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	alchemy_pci_wired_entry(ctx);	/* install it */
352864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss}
353864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
354864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Laussstatic struct syscore_ops alchemy_pci_pmops = {
355864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	.suspend	= alchemy_pci_suspend,
356864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	.resume		= alchemy_pci_resume,
357864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss};
358864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss
3597517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int __devinit alchemy_pci_probe(struct platform_device *pdev)
3607517de348663b08a808aff44b5300e817157a568Manuel Lauss{
3617517de348663b08a808aff44b5300e817157a568Manuel Lauss	struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
3627517de348663b08a808aff44b5300e817157a568Manuel Lauss	struct alchemy_pci_context *ctx;
3637517de348663b08a808aff44b5300e817157a568Manuel Lauss	void __iomem *virt_io;
3647517de348663b08a808aff44b5300e817157a568Manuel Lauss	unsigned long val;
3657517de348663b08a808aff44b5300e817157a568Manuel Lauss	struct resource *r;
3667517de348663b08a808aff44b5300e817157a568Manuel Lauss	int ret;
3677517de348663b08a808aff44b5300e817157a568Manuel Lauss
3687517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* need at least PCI IRQ mapping table */
3697517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (!pd) {
3707517de348663b08a808aff44b5300e817157a568Manuel Lauss		dev_err(&pdev->dev, "need platform data for PCI setup\n");
3717517de348663b08a808aff44b5300e817157a568Manuel Lauss		ret = -ENODEV;
3727517de348663b08a808aff44b5300e817157a568Manuel Lauss		goto out;
3737517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
3747517de348663b08a808aff44b5300e817157a568Manuel Lauss
3757517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
3767517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (!ctx) {
3777517de348663b08a808aff44b5300e817157a568Manuel Lauss		dev_err(&pdev->dev, "no memory for pcictl context\n");
3787517de348663b08a808aff44b5300e817157a568Manuel Lauss		ret = -ENOMEM;
3797517de348663b08a808aff44b5300e817157a568Manuel Lauss		goto out;
3807517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
3817517de348663b08a808aff44b5300e817157a568Manuel Lauss
3827517de348663b08a808aff44b5300e817157a568Manuel Lauss	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3837517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (!r) {
3847517de348663b08a808aff44b5300e817157a568Manuel Lauss		dev_err(&pdev->dev, "no  pcictl ctrl regs resource\n");
3857517de348663b08a808aff44b5300e817157a568Manuel Lauss		ret = -ENODEV;
3867517de348663b08a808aff44b5300e817157a568Manuel Lauss		goto out1;
3877517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
3887517de348663b08a808aff44b5300e817157a568Manuel Lauss
3897517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (!request_mem_region(r->start, resource_size(r), pdev->name)) {
3907517de348663b08a808aff44b5300e817157a568Manuel Lauss		dev_err(&pdev->dev, "cannot claim pci regs\n");
3917517de348663b08a808aff44b5300e817157a568Manuel Lauss		ret = -ENODEV;
3927517de348663b08a808aff44b5300e817157a568Manuel Lauss		goto out1;
3937517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
3947517de348663b08a808aff44b5300e817157a568Manuel Lauss
3957517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx->regs = ioremap_nocache(r->start, resource_size(r));
3967517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (!ctx->regs) {
3977517de348663b08a808aff44b5300e817157a568Manuel Lauss		dev_err(&pdev->dev, "cannot map pci regs\n");
3987517de348663b08a808aff44b5300e817157a568Manuel Lauss		ret = -ENODEV;
3997517de348663b08a808aff44b5300e817157a568Manuel Lauss		goto out2;
4007517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
4017517de348663b08a808aff44b5300e817157a568Manuel Lauss
4027517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* map parts of the PCI IO area */
4037517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* REVISIT: if this changes with a newer variant (doubt it) make this
4047517de348663b08a808aff44b5300e817157a568Manuel Lauss	 * a platform resource.
4057517de348663b08a808aff44b5300e817157a568Manuel Lauss	 */
4067517de348663b08a808aff44b5300e817157a568Manuel Lauss	virt_io = ioremap(AU1500_PCI_IO_PHYS_ADDR, 0x00100000);
4077517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (!virt_io) {
4087517de348663b08a808aff44b5300e817157a568Manuel Lauss		dev_err(&pdev->dev, "cannot remap pci io space\n");
4097517de348663b08a808aff44b5300e817157a568Manuel Lauss		ret = -ENODEV;
4107517de348663b08a808aff44b5300e817157a568Manuel Lauss		goto out3;
4117517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
4127517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx->alchemy_pci_ctrl.io_map_base = (unsigned long)virt_io;
4137517de348663b08a808aff44b5300e817157a568Manuel Lauss
4147517de348663b08a808aff44b5300e817157a568Manuel Lauss#ifdef CONFIG_DMA_NONCOHERENT
4157517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Au1500 revisions older than AD have borked coherent PCI */
4167517de348663b08a808aff44b5300e817157a568Manuel Lauss	if ((alchemy_get_cputype() == ALCHEMY_CPU_AU1500) &&
4177517de348663b08a808aff44b5300e817157a568Manuel Lauss	    (read_c0_prid() < 0x01030202)) {
4187517de348663b08a808aff44b5300e817157a568Manuel Lauss		val = __raw_readl(ctx->regs + PCI_REG_CONFIG);
4197517de348663b08a808aff44b5300e817157a568Manuel Lauss		val |= PCI_CONFIG_NC;
4207517de348663b08a808aff44b5300e817157a568Manuel Lauss		__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
4217517de348663b08a808aff44b5300e817157a568Manuel Lauss		wmb();
4227517de348663b08a808aff44b5300e817157a568Manuel Lauss		dev_info(&pdev->dev, "non-coherent PCI on Au1500 AA/AB/AC\n");
4237517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
4247517de348663b08a808aff44b5300e817157a568Manuel Lauss#endif
4257517de348663b08a808aff44b5300e817157a568Manuel Lauss
4267517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (pd->board_map_irq)
4277517de348663b08a808aff44b5300e817157a568Manuel Lauss		ctx->board_map_irq = pd->board_map_irq;
4287517de348663b08a808aff44b5300e817157a568Manuel Lauss
4297517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (pd->board_pci_idsel)
4307517de348663b08a808aff44b5300e817157a568Manuel Lauss		ctx->board_pci_idsel = pd->board_pci_idsel;
4317517de348663b08a808aff44b5300e817157a568Manuel Lauss	else
4327517de348663b08a808aff44b5300e817157a568Manuel Lauss		ctx->board_pci_idsel = alchemy_pci_def_idsel;
4337517de348663b08a808aff44b5300e817157a568Manuel Lauss
4347517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* fill in relevant pci_controller members */
4357517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx->alchemy_pci_ctrl.pci_ops = &alchemy_pci_ops;
4367517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx->alchemy_pci_ctrl.mem_resource = &alchemy_pci_def_memres;
4377517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx->alchemy_pci_ctrl.io_resource = &alchemy_pci_def_iores;
4387517de348663b08a808aff44b5300e817157a568Manuel Lauss
4397517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* we can't ioremap the entire pci config space because it's too large,
4407517de348663b08a808aff44b5300e817157a568Manuel Lauss	 * nor can we dynamically ioremap it because some drivers use the
4417517de348663b08a808aff44b5300e817157a568Manuel Lauss	 * PCI config routines from within atomic contex and that becomes a
4427517de348663b08a808aff44b5300e817157a568Manuel Lauss	 * problem in get_vm_area().  Instead we use one wired TLB entry to
4437517de348663b08a808aff44b5300e817157a568Manuel Lauss	 * handle all config accesses for all busses.
4447517de348663b08a808aff44b5300e817157a568Manuel Lauss	 */
4457517de348663b08a808aff44b5300e817157a568Manuel Lauss	ctx->pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
4467517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (!ctx->pci_cfg_vm) {
4477517de348663b08a808aff44b5300e817157a568Manuel Lauss		dev_err(&pdev->dev, "unable to get vm area\n");
4487517de348663b08a808aff44b5300e817157a568Manuel Lauss		ret = -ENOMEM;
4497517de348663b08a808aff44b5300e817157a568Manuel Lauss		goto out4;
4507517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
451864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	ctx->wired_entry = 8191;	/* impossibly high value */
452864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	alchemy_pci_wired_entry(ctx);	/* install it */
4537517de348663b08a808aff44b5300e817157a568Manuel Lauss
4547517de348663b08a808aff44b5300e817157a568Manuel Lauss	set_io_port_base((unsigned long)ctx->alchemy_pci_ctrl.io_map_base);
4557517de348663b08a808aff44b5300e817157a568Manuel Lauss
4567517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* board may want to modify bits in the config register, do it now */
4577517de348663b08a808aff44b5300e817157a568Manuel Lauss	val = __raw_readl(ctx->regs + PCI_REG_CONFIG);
4587517de348663b08a808aff44b5300e817157a568Manuel Lauss	val &= ~pd->pci_cfg_clr;
4597517de348663b08a808aff44b5300e817157a568Manuel Lauss	val |= pd->pci_cfg_set;
4607517de348663b08a808aff44b5300e817157a568Manuel Lauss	val &= ~PCI_CONFIG_PD;		/* clear disable bit */
4617517de348663b08a808aff44b5300e817157a568Manuel Lauss	__raw_writel(val, ctx->regs + PCI_REG_CONFIG);
4627517de348663b08a808aff44b5300e817157a568Manuel Lauss	wmb();
4637517de348663b08a808aff44b5300e817157a568Manuel Lauss
464864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	__alchemy_pci_ctx = ctx;
4657517de348663b08a808aff44b5300e817157a568Manuel Lauss	platform_set_drvdata(pdev, ctx);
466864c6c22e9a5742b0f43c983b6c405d52817bacdManuel Lauss	register_syscore_ops(&alchemy_pci_pmops);
4677517de348663b08a808aff44b5300e817157a568Manuel Lauss	register_pci_controller(&ctx->alchemy_pci_ctrl);
4687517de348663b08a808aff44b5300e817157a568Manuel Lauss
4697517de348663b08a808aff44b5300e817157a568Manuel Lauss	return 0;
4707517de348663b08a808aff44b5300e817157a568Manuel Lauss
4717517de348663b08a808aff44b5300e817157a568Manuel Laussout4:
4727517de348663b08a808aff44b5300e817157a568Manuel Lauss	iounmap(virt_io);
4737517de348663b08a808aff44b5300e817157a568Manuel Laussout3:
4747517de348663b08a808aff44b5300e817157a568Manuel Lauss	iounmap(ctx->regs);
4757517de348663b08a808aff44b5300e817157a568Manuel Laussout2:
4767517de348663b08a808aff44b5300e817157a568Manuel Lauss	release_mem_region(r->start, resource_size(r));
4777517de348663b08a808aff44b5300e817157a568Manuel Laussout1:
4787517de348663b08a808aff44b5300e817157a568Manuel Lauss	kfree(ctx);
4797517de348663b08a808aff44b5300e817157a568Manuel Laussout:
4807517de348663b08a808aff44b5300e817157a568Manuel Lauss	return ret;
4817517de348663b08a808aff44b5300e817157a568Manuel Lauss}
4827517de348663b08a808aff44b5300e817157a568Manuel Lauss
4837517de348663b08a808aff44b5300e817157a568Manuel Laussstatic struct platform_driver alchemy_pcictl_driver = {
4847517de348663b08a808aff44b5300e817157a568Manuel Lauss	.probe		= alchemy_pci_probe,
4857517de348663b08a808aff44b5300e817157a568Manuel Lauss	.driver	= {
4867517de348663b08a808aff44b5300e817157a568Manuel Lauss		.name	= "alchemy-pci",
4877517de348663b08a808aff44b5300e817157a568Manuel Lauss		.owner	= THIS_MODULE,
4887517de348663b08a808aff44b5300e817157a568Manuel Lauss	},
4897517de348663b08a808aff44b5300e817157a568Manuel Lauss};
4907517de348663b08a808aff44b5300e817157a568Manuel Lauss
4917517de348663b08a808aff44b5300e817157a568Manuel Laussstatic int __init alchemy_pci_init(void)
4927517de348663b08a808aff44b5300e817157a568Manuel Lauss{
4937517de348663b08a808aff44b5300e817157a568Manuel Lauss	/* Au1500/Au1550 have PCI */
4947517de348663b08a808aff44b5300e817157a568Manuel Lauss	switch (alchemy_get_cputype()) {
4957517de348663b08a808aff44b5300e817157a568Manuel Lauss	case ALCHEMY_CPU_AU1500:
4967517de348663b08a808aff44b5300e817157a568Manuel Lauss	case ALCHEMY_CPU_AU1550:
4977517de348663b08a808aff44b5300e817157a568Manuel Lauss		return platform_driver_register(&alchemy_pcictl_driver);
4987517de348663b08a808aff44b5300e817157a568Manuel Lauss	}
4997517de348663b08a808aff44b5300e817157a568Manuel Lauss	return 0;
5007517de348663b08a808aff44b5300e817157a568Manuel Lauss}
5017517de348663b08a808aff44b5300e817157a568Manuel Laussarch_initcall(alchemy_pci_init);
5027517de348663b08a808aff44b5300e817157a568Manuel Lauss
5037517de348663b08a808aff44b5300e817157a568Manuel Lauss
5047517de348663b08a808aff44b5300e817157a568Manuel Laussint __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
5057517de348663b08a808aff44b5300e817157a568Manuel Lauss{
5067517de348663b08a808aff44b5300e817157a568Manuel Lauss	struct alchemy_pci_context *ctx = dev->sysdata;
5077517de348663b08a808aff44b5300e817157a568Manuel Lauss	if (ctx && ctx->board_map_irq)
5087517de348663b08a808aff44b5300e817157a568Manuel Lauss		return ctx->board_map_irq(dev, slot, pin);
5097517de348663b08a808aff44b5300e817157a568Manuel Lauss	return -1;
5107517de348663b08a808aff44b5300e817157a568Manuel Lauss}
5117517de348663b08a808aff44b5300e817157a568Manuel Lauss
5127517de348663b08a808aff44b5300e817157a568Manuel Laussint pcibios_plat_dev_init(struct pci_dev *dev)
5137517de348663b08a808aff44b5300e817157a568Manuel Lauss{
5147517de348663b08a808aff44b5300e817157a568Manuel Lauss	return 0;
5157517de348663b08a808aff44b5300e817157a568Manuel Lauss}
516