11e76875eSOlof Johansson /* 21e76875eSOlof Johansson * Copyright (C) 2006 PA Semi, Inc 31e76875eSOlof Johansson * 41e76875eSOlof Johansson * Authors: Kip Walker, PA Semi 51e76875eSOlof Johansson * Olof Johansson, PA Semi 61e76875eSOlof Johansson * 71e76875eSOlof Johansson * Maintained by: Olof Johansson <olof@lixom.net> 81e76875eSOlof Johansson * 91e76875eSOlof Johansson * Based on arch/powerpc/platforms/maple/pci.c 101e76875eSOlof Johansson * 111e76875eSOlof Johansson * This program is free software; you can redistribute it and/or modify 121e76875eSOlof Johansson * it under the terms of the GNU General Public License version 2 as 131e76875eSOlof Johansson * published by the Free Software Foundation. 141e76875eSOlof Johansson * 151e76875eSOlof Johansson * This program is distributed in the hope that it will be useful, 161e76875eSOlof Johansson * but WITHOUT ANY WARRANTY; without even the implied warranty of 171e76875eSOlof Johansson * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 181e76875eSOlof Johansson * GNU General Public License for more details. 191e76875eSOlof Johansson * 201e76875eSOlof Johansson * You should have received a copy of the GNU General Public License 211e76875eSOlof Johansson * along with this program; if not, write to the Free Software 221e76875eSOlof Johansson * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 231e76875eSOlof Johansson */ 241e76875eSOlof Johansson 251e76875eSOlof Johansson 261e76875eSOlof Johansson #include <linux/kernel.h> 271e76875eSOlof Johansson #include <linux/pci.h> 281e76875eSOlof Johansson 291e76875eSOlof Johansson #include <asm/pci-bridge.h> 301e76875eSOlof Johansson #include <asm/machdep.h> 311e76875eSOlof Johansson 321e76875eSOlof Johansson #include <asm/ppc-pci.h> 331e76875eSOlof Johansson 341e76875eSOlof Johansson #define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off)) 351e76875eSOlof Johansson 36df7e70a2SOlof Johansson static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset) 37df7e70a2SOlof Johansson { 38df7e70a2SOlof Johansson /* Device 0 Function 0 is special: It's config space spans function 1 as 39df7e70a2SOlof Johansson * well, so allow larger offset. It's really a two-function device but the 40df7e70a2SOlof Johansson * second function does not probe. 41df7e70a2SOlof Johansson */ 42df7e70a2SOlof Johansson if (bus == 0 && devfn == 0) 43df7e70a2SOlof Johansson return offset < 8192; 44df7e70a2SOlof Johansson else 45df7e70a2SOlof Johansson return offset < 4096; 46df7e70a2SOlof Johansson } 471e76875eSOlof Johansson 487c84ace9SAl Viro static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose, 491e76875eSOlof Johansson u8 bus, u8 devfn, int offset) 501e76875eSOlof Johansson { 517c84ace9SAl Viro return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset); 521e76875eSOlof Johansson } 531e76875eSOlof Johansson 54*4d442331SOlof Johansson static inline int is_root_port(int busno, int devfn) 55*4d442331SOlof Johansson { 56*4d442331SOlof Johansson return ((busno == 0) && (PCI_FUNC(devfn) < 4) && 57*4d442331SOlof Johansson ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17))); 58*4d442331SOlof Johansson } 59*4d442331SOlof Johansson 60*4d442331SOlof Johansson static inline int is_5945_reg(int reg) 61*4d442331SOlof Johansson { 62*4d442331SOlof Johansson return (((reg >= 0x18) && (reg < 0x34)) || 63*4d442331SOlof Johansson ((reg >= 0x158) && (reg < 0x178))); 64*4d442331SOlof Johansson } 65*4d442331SOlof Johansson 66*4d442331SOlof Johansson static int workaround_5945(struct pci_bus *bus, unsigned int devfn, 67*4d442331SOlof Johansson int offset, int len, u32 *val) 68*4d442331SOlof Johansson { 69*4d442331SOlof Johansson struct pci_controller *hose; 70*4d442331SOlof Johansson void volatile __iomem *addr, *dummy; 71*4d442331SOlof Johansson int byte; 72*4d442331SOlof Johansson u32 tmp; 73*4d442331SOlof Johansson 74*4d442331SOlof Johansson if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset)) 75*4d442331SOlof Johansson return 0; 76*4d442331SOlof Johansson 77*4d442331SOlof Johansson hose = pci_bus_to_host(bus); 78*4d442331SOlof Johansson 79*4d442331SOlof Johansson addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3); 80*4d442331SOlof Johansson byte = offset & 0x3; 81*4d442331SOlof Johansson 82*4d442331SOlof Johansson /* Workaround bug 5945: write 0 to a dummy register before reading, 83*4d442331SOlof Johansson * and write back what we read. We must read/write the full 32-bit 84*4d442331SOlof Johansson * contents so we need to shift and mask by hand. 85*4d442331SOlof Johansson */ 86*4d442331SOlof Johansson dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10); 87*4d442331SOlof Johansson out_le32(dummy, 0); 88*4d442331SOlof Johansson tmp = in_le32(addr); 89*4d442331SOlof Johansson out_le32(addr, tmp); 90*4d442331SOlof Johansson 91*4d442331SOlof Johansson switch (len) { 92*4d442331SOlof Johansson case 1: 93*4d442331SOlof Johansson *val = (tmp >> (8*byte)) & 0xff; 94*4d442331SOlof Johansson break; 95*4d442331SOlof Johansson case 2: 96*4d442331SOlof Johansson if (byte == 0) 97*4d442331SOlof Johansson *val = tmp & 0xffff; 98*4d442331SOlof Johansson else 99*4d442331SOlof Johansson *val = (tmp >> 16) & 0xffff; 100*4d442331SOlof Johansson break; 101*4d442331SOlof Johansson default: 102*4d442331SOlof Johansson *val = tmp; 103*4d442331SOlof Johansson break; 104*4d442331SOlof Johansson } 105*4d442331SOlof Johansson 106*4d442331SOlof Johansson return 1; 107*4d442331SOlof Johansson } 108*4d442331SOlof Johansson 1091e76875eSOlof Johansson static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, 1101e76875eSOlof Johansson int offset, int len, u32 *val) 1111e76875eSOlof Johansson { 1121e76875eSOlof Johansson struct pci_controller *hose; 1137c84ace9SAl Viro void volatile __iomem *addr; 1141e76875eSOlof Johansson 1151e76875eSOlof Johansson hose = pci_bus_to_host(bus); 1161e76875eSOlof Johansson if (!hose) 1171e76875eSOlof Johansson return PCIBIOS_DEVICE_NOT_FOUND; 1181e76875eSOlof Johansson 119df7e70a2SOlof Johansson if (!pa_pxp_offset_valid(bus->number, devfn, offset)) 1201e76875eSOlof Johansson return PCIBIOS_BAD_REGISTER_NUMBER; 1211e76875eSOlof Johansson 122*4d442331SOlof Johansson if (workaround_5945(bus, devfn, offset, len, val)) 123*4d442331SOlof Johansson return PCIBIOS_SUCCESSFUL; 124*4d442331SOlof Johansson 1251e76875eSOlof Johansson addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); 1261e76875eSOlof Johansson 1271e76875eSOlof Johansson /* 1281e76875eSOlof Johansson * Note: the caller has already checked that offset is 1291e76875eSOlof Johansson * suitably aligned and that len is 1, 2 or 4. 1301e76875eSOlof Johansson */ 1311e76875eSOlof Johansson switch (len) { 1321e76875eSOlof Johansson case 1: 1337c84ace9SAl Viro *val = in_8(addr); 1341e76875eSOlof Johansson break; 1351e76875eSOlof Johansson case 2: 1367c84ace9SAl Viro *val = in_le16(addr); 1371e76875eSOlof Johansson break; 1381e76875eSOlof Johansson default: 1397c84ace9SAl Viro *val = in_le32(addr); 1401e76875eSOlof Johansson break; 1411e76875eSOlof Johansson } 1421e76875eSOlof Johansson 1431e76875eSOlof Johansson return PCIBIOS_SUCCESSFUL; 1441e76875eSOlof Johansson } 1451e76875eSOlof Johansson 1461e76875eSOlof Johansson static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn, 1471e76875eSOlof Johansson int offset, int len, u32 val) 1481e76875eSOlof Johansson { 1491e76875eSOlof Johansson struct pci_controller *hose; 1507c84ace9SAl Viro void volatile __iomem *addr; 1511e76875eSOlof Johansson 1521e76875eSOlof Johansson hose = pci_bus_to_host(bus); 1531e76875eSOlof Johansson if (!hose) 1541e76875eSOlof Johansson return PCIBIOS_DEVICE_NOT_FOUND; 1551e76875eSOlof Johansson 156df7e70a2SOlof Johansson if (!pa_pxp_offset_valid(bus->number, devfn, offset)) 1571e76875eSOlof Johansson return PCIBIOS_BAD_REGISTER_NUMBER; 1581e76875eSOlof Johansson 1591e76875eSOlof Johansson addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); 1601e76875eSOlof Johansson 1611e76875eSOlof Johansson /* 1621e76875eSOlof Johansson * Note: the caller has already checked that offset is 1631e76875eSOlof Johansson * suitably aligned and that len is 1, 2 or 4. 1641e76875eSOlof Johansson */ 1651e76875eSOlof Johansson switch (len) { 1661e76875eSOlof Johansson case 1: 1677c84ace9SAl Viro out_8(addr, val); 1681e76875eSOlof Johansson break; 1691e76875eSOlof Johansson case 2: 1707c84ace9SAl Viro out_le16(addr, val); 1711e76875eSOlof Johansson break; 1721e76875eSOlof Johansson default: 1737c84ace9SAl Viro out_le32(addr, val); 1741e76875eSOlof Johansson break; 1751e76875eSOlof Johansson } 1761e76875eSOlof Johansson return PCIBIOS_SUCCESSFUL; 1771e76875eSOlof Johansson } 1781e76875eSOlof Johansson 1791e76875eSOlof Johansson static struct pci_ops pa_pxp_ops = { 1801bb8c621SNathan Lynch .read = pa_pxp_read_config, 1811bb8c621SNathan Lynch .write = pa_pxp_write_config, 1821e76875eSOlof Johansson }; 1831e76875eSOlof Johansson 1841e76875eSOlof Johansson static void __init setup_pa_pxp(struct pci_controller *hose) 1851e76875eSOlof Johansson { 1861e76875eSOlof Johansson hose->ops = &pa_pxp_ops; 1871e76875eSOlof Johansson hose->cfg_data = ioremap(0xe0000000, 0x10000000); 1881e76875eSOlof Johansson } 1891e76875eSOlof Johansson 19009b55f76SArnd Bergmann static int __init pas_add_bridge(struct device_node *dev) 1911e76875eSOlof Johansson { 1921e76875eSOlof Johansson struct pci_controller *hose; 1931e76875eSOlof Johansson 1941e76875eSOlof Johansson pr_debug("Adding PCI host bridge %s\n", dev->full_name); 1951e76875eSOlof Johansson 1961e76875eSOlof Johansson hose = pcibios_alloc_controller(dev); 1971e76875eSOlof Johansson if (!hose) 1981e76875eSOlof Johansson return -ENOMEM; 1991e76875eSOlof Johansson 2001e76875eSOlof Johansson hose->first_busno = 0; 2011e76875eSOlof Johansson hose->last_busno = 0xff; 2021e76875eSOlof Johansson 2031e76875eSOlof Johansson setup_pa_pxp(hose); 2041e76875eSOlof Johansson 2051e76875eSOlof Johansson printk(KERN_INFO "Found PA-PXP PCI host bridge.\n"); 2061e76875eSOlof Johansson 2071e76875eSOlof Johansson /* Interpret the "ranges" property */ 2081e76875eSOlof Johansson pci_process_bridge_OF_ranges(hose, dev, 1); 2091e76875eSOlof Johansson 2101e76875eSOlof Johansson return 0; 2111e76875eSOlof Johansson } 2121e76875eSOlof Johansson 2131e76875eSOlof Johansson void __init pas_pci_init(void) 2141e76875eSOlof Johansson { 2151e76875eSOlof Johansson struct device_node *np, *root; 2161e76875eSOlof Johansson 2171e76875eSOlof Johansson root = of_find_node_by_path("/"); 2181e76875eSOlof Johansson if (!root) { 2191e76875eSOlof Johansson printk(KERN_CRIT "pas_pci_init: can't find root " 2201e76875eSOlof Johansson "of device tree\n"); 2211e76875eSOlof Johansson return; 2221e76875eSOlof Johansson } 2231e76875eSOlof Johansson 2241e76875eSOlof Johansson for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) 22509b55f76SArnd Bergmann if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np)) 2261e76875eSOlof Johansson of_node_get(np); 2271e76875eSOlof Johansson 2281e76875eSOlof Johansson of_node_put(root); 2291e76875eSOlof Johansson 2301e76875eSOlof Johansson /* Setup the linkage between OF nodes and PHBs */ 2311e76875eSOlof Johansson pci_devs_phb_init(); 2321e76875eSOlof Johansson 2331e76875eSOlof Johansson /* Use the common resource allocation mechanism */ 2341e76875eSOlof Johansson pci_probe_only = 1; 2351e76875eSOlof Johansson } 23668c8404cSOlof Johansson 23768c8404cSOlof Johansson void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset) 23868c8404cSOlof Johansson { 23968c8404cSOlof Johansson struct pci_controller *hose; 24068c8404cSOlof Johansson 241*4d442331SOlof Johansson hose = pci_bus_to_host(dev->bus); 24268c8404cSOlof Johansson 243*4d442331SOlof Johansson return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset); 24468c8404cSOlof Johansson } 245