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