145051539SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21e76875eSOlof Johansson /* 31e76875eSOlof Johansson * Copyright (C) 2006 PA Semi, Inc 41e76875eSOlof Johansson * 51e76875eSOlof Johansson * Authors: Kip Walker, PA Semi 61e76875eSOlof Johansson * Olof Johansson, PA Semi 71e76875eSOlof Johansson * 81e76875eSOlof Johansson * Maintained by: Olof Johansson <olof@lixom.net> 91e76875eSOlof Johansson * 101e76875eSOlof Johansson * Based on arch/powerpc/platforms/maple/pci.c 111e76875eSOlof Johansson */ 121e76875eSOlof Johansson 131e76875eSOlof Johansson 141e76875eSOlof Johansson #include <linux/kernel.h> 15*e6f6390aSChristophe Leroy #include <linux/of_address.h> 161e76875eSOlof Johansson #include <linux/pci.h> 171e76875eSOlof Johansson 181e76875eSOlof Johansson #include <asm/pci-bridge.h> 1951f4cc20SDarren Stevens #include <asm/isa-bridge.h> 201e76875eSOlof Johansson #include <asm/machdep.h> 211e76875eSOlof Johansson 221e76875eSOlof Johansson #include <asm/ppc-pci.h> 231e76875eSOlof Johansson 24d28a0d94SDaniel Axtens #include "pasemi.h" 25d28a0d94SDaniel Axtens 261e76875eSOlof Johansson #define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off)) 271e76875eSOlof Johansson 28df7e70a2SOlof Johansson static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset) 29df7e70a2SOlof Johansson { 30df7e70a2SOlof Johansson /* Device 0 Function 0 is special: It's config space spans function 1 as 31df7e70a2SOlof Johansson * well, so allow larger offset. It's really a two-function device but the 32df7e70a2SOlof Johansson * second function does not probe. 33df7e70a2SOlof Johansson */ 34df7e70a2SOlof Johansson if (bus == 0 && devfn == 0) 35df7e70a2SOlof Johansson return offset < 8192; 36df7e70a2SOlof Johansson else 37df7e70a2SOlof Johansson return offset < 4096; 38df7e70a2SOlof Johansson } 391e76875eSOlof Johansson 407c84ace9SAl Viro static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose, 411e76875eSOlof Johansson u8 bus, u8 devfn, int offset) 421e76875eSOlof Johansson { 437c84ace9SAl Viro return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset); 441e76875eSOlof Johansson } 451e76875eSOlof Johansson 464d442331SOlof Johansson static inline int is_root_port(int busno, int devfn) 474d442331SOlof Johansson { 484d442331SOlof Johansson return ((busno == 0) && (PCI_FUNC(devfn) < 4) && 494d442331SOlof Johansson ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17))); 504d442331SOlof Johansson } 514d442331SOlof Johansson 524d442331SOlof Johansson static inline int is_5945_reg(int reg) 534d442331SOlof Johansson { 544d442331SOlof Johansson return (((reg >= 0x18) && (reg < 0x34)) || 554d442331SOlof Johansson ((reg >= 0x158) && (reg < 0x178))); 564d442331SOlof Johansson } 574d442331SOlof Johansson 584d442331SOlof Johansson static int workaround_5945(struct pci_bus *bus, unsigned int devfn, 594d442331SOlof Johansson int offset, int len, u32 *val) 604d442331SOlof Johansson { 614d442331SOlof Johansson struct pci_controller *hose; 624d442331SOlof Johansson void volatile __iomem *addr, *dummy; 634d442331SOlof Johansson int byte; 644d442331SOlof Johansson u32 tmp; 654d442331SOlof Johansson 664d442331SOlof Johansson if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset)) 674d442331SOlof Johansson return 0; 684d442331SOlof Johansson 694d442331SOlof Johansson hose = pci_bus_to_host(bus); 704d442331SOlof Johansson 714d442331SOlof Johansson addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3); 724d442331SOlof Johansson byte = offset & 0x3; 734d442331SOlof Johansson 744d442331SOlof Johansson /* Workaround bug 5945: write 0 to a dummy register before reading, 754d442331SOlof Johansson * and write back what we read. We must read/write the full 32-bit 764d442331SOlof Johansson * contents so we need to shift and mask by hand. 774d442331SOlof Johansson */ 784d442331SOlof Johansson dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10); 794d442331SOlof Johansson out_le32(dummy, 0); 804d442331SOlof Johansson tmp = in_le32(addr); 814d442331SOlof Johansson out_le32(addr, tmp); 824d442331SOlof Johansson 834d442331SOlof Johansson switch (len) { 844d442331SOlof Johansson case 1: 854d442331SOlof Johansson *val = (tmp >> (8*byte)) & 0xff; 864d442331SOlof Johansson break; 874d442331SOlof Johansson case 2: 884d442331SOlof Johansson if (byte == 0) 894d442331SOlof Johansson *val = tmp & 0xffff; 904d442331SOlof Johansson else 914d442331SOlof Johansson *val = (tmp >> 16) & 0xffff; 924d442331SOlof Johansson break; 934d442331SOlof Johansson default: 944d442331SOlof Johansson *val = tmp; 954d442331SOlof Johansson break; 964d442331SOlof Johansson } 974d442331SOlof Johansson 984d442331SOlof Johansson return 1; 994d442331SOlof Johansson } 1004d442331SOlof Johansson 10168f211a4SDarren Stevens #ifdef CONFIG_PPC_PASEMI_NEMO 10268f211a4SDarren Stevens #define PXP_ERR_CFG_REG 0x4 10368f211a4SDarren Stevens #define PXP_IGNORE_PCIE_ERRORS 0x800 10468f211a4SDarren Stevens #define SB600_BUS 5 10568f211a4SDarren Stevens 10668f211a4SDarren Stevens static void sb600_set_flag(int bus) 10768f211a4SDarren Stevens { 10868f211a4SDarren Stevens static void __iomem *iob_mapbase = NULL; 10968f211a4SDarren Stevens struct resource res; 11068f211a4SDarren Stevens struct device_node *dn; 11168f211a4SDarren Stevens int err; 11268f211a4SDarren Stevens 11368f211a4SDarren Stevens if (iob_mapbase == NULL) { 11468f211a4SDarren Stevens dn = of_find_compatible_node(NULL, "isa", "pasemi,1682m-iob"); 11568f211a4SDarren Stevens if (!dn) { 11668f211a4SDarren Stevens pr_crit("NEMO SB600 missing iob node\n"); 11768f211a4SDarren Stevens return; 11868f211a4SDarren Stevens } 11968f211a4SDarren Stevens 12068f211a4SDarren Stevens err = of_address_to_resource(dn, 0, &res); 12168f211a4SDarren Stevens of_node_put(dn); 12268f211a4SDarren Stevens 12368f211a4SDarren Stevens if (err) { 12468f211a4SDarren Stevens pr_crit("NEMO SB600 missing resource\n"); 12568f211a4SDarren Stevens return; 12668f211a4SDarren Stevens } 12768f211a4SDarren Stevens 12868f211a4SDarren Stevens pr_info("NEMO SB600 IOB base %08llx\n",res.start); 12968f211a4SDarren Stevens 13068f211a4SDarren Stevens iob_mapbase = ioremap(res.start + 0x100, 0x94); 13168f211a4SDarren Stevens } 13268f211a4SDarren Stevens 13368f211a4SDarren Stevens if (iob_mapbase != NULL) { 13468f211a4SDarren Stevens if (bus == SB600_BUS) { 13568f211a4SDarren Stevens /* 13668f211a4SDarren Stevens * This is the SB600's bus, tell the PCI-e root port 13768f211a4SDarren Stevens * to allow non-zero devices to enumerate. 13868f211a4SDarren Stevens */ 13968f211a4SDarren Stevens out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) | PXP_IGNORE_PCIE_ERRORS); 14068f211a4SDarren Stevens } else { 14168f211a4SDarren Stevens /* 14268f211a4SDarren Stevens * Only scan device 0 on other busses 14368f211a4SDarren Stevens */ 14468f211a4SDarren Stevens out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) & ~PXP_IGNORE_PCIE_ERRORS); 14568f211a4SDarren Stevens } 14668f211a4SDarren Stevens } 14768f211a4SDarren Stevens } 14868f211a4SDarren Stevens 14968f211a4SDarren Stevens #else 15068f211a4SDarren Stevens 15168f211a4SDarren Stevens static void sb600_set_flag(int bus) 15268f211a4SDarren Stevens { 15368f211a4SDarren Stevens } 15468f211a4SDarren Stevens #endif 15568f211a4SDarren Stevens 1561e76875eSOlof Johansson static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, 1571e76875eSOlof Johansson int offset, int len, u32 *val) 1581e76875eSOlof Johansson { 1591e76875eSOlof Johansson struct pci_controller *hose; 1607c84ace9SAl Viro void volatile __iomem *addr; 1611e76875eSOlof Johansson 1621e76875eSOlof Johansson hose = pci_bus_to_host(bus); 1631e76875eSOlof Johansson if (!hose) 1641e76875eSOlof Johansson return PCIBIOS_DEVICE_NOT_FOUND; 1651e76875eSOlof Johansson 166df7e70a2SOlof Johansson if (!pa_pxp_offset_valid(bus->number, devfn, offset)) 1671e76875eSOlof Johansson return PCIBIOS_BAD_REGISTER_NUMBER; 1681e76875eSOlof Johansson 1694d442331SOlof Johansson if (workaround_5945(bus, devfn, offset, len, val)) 1704d442331SOlof Johansson return PCIBIOS_SUCCESSFUL; 1714d442331SOlof Johansson 1721e76875eSOlof Johansson addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); 1731e76875eSOlof Johansson 17451f4cc20SDarren Stevens sb600_set_flag(bus->number); 17551f4cc20SDarren Stevens 1761e76875eSOlof Johansson /* 1771e76875eSOlof Johansson * Note: the caller has already checked that offset is 1781e76875eSOlof Johansson * suitably aligned and that len is 1, 2 or 4. 1791e76875eSOlof Johansson */ 1801e76875eSOlof Johansson switch (len) { 1811e76875eSOlof Johansson case 1: 1827c84ace9SAl Viro *val = in_8(addr); 1831e76875eSOlof Johansson break; 1841e76875eSOlof Johansson case 2: 1857c84ace9SAl Viro *val = in_le16(addr); 1861e76875eSOlof Johansson break; 1871e76875eSOlof Johansson default: 1887c84ace9SAl Viro *val = in_le32(addr); 1891e76875eSOlof Johansson break; 1901e76875eSOlof Johansson } 1911e76875eSOlof Johansson 1921e76875eSOlof Johansson return PCIBIOS_SUCCESSFUL; 1931e76875eSOlof Johansson } 1941e76875eSOlof Johansson 1951e76875eSOlof Johansson static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn, 1961e76875eSOlof Johansson int offset, int len, u32 val) 1971e76875eSOlof Johansson { 1981e76875eSOlof Johansson struct pci_controller *hose; 1997c84ace9SAl Viro void volatile __iomem *addr; 2001e76875eSOlof Johansson 2011e76875eSOlof Johansson hose = pci_bus_to_host(bus); 2021e76875eSOlof Johansson if (!hose) 2031e76875eSOlof Johansson return PCIBIOS_DEVICE_NOT_FOUND; 2041e76875eSOlof Johansson 205df7e70a2SOlof Johansson if (!pa_pxp_offset_valid(bus->number, devfn, offset)) 2061e76875eSOlof Johansson return PCIBIOS_BAD_REGISTER_NUMBER; 2071e76875eSOlof Johansson 2081e76875eSOlof Johansson addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); 2091e76875eSOlof Johansson 21051f4cc20SDarren Stevens sb600_set_flag(bus->number); 21151f4cc20SDarren Stevens 2121e76875eSOlof Johansson /* 2131e76875eSOlof Johansson * Note: the caller has already checked that offset is 2141e76875eSOlof Johansson * suitably aligned and that len is 1, 2 or 4. 2151e76875eSOlof Johansson */ 2161e76875eSOlof Johansson switch (len) { 2171e76875eSOlof Johansson case 1: 2187c84ace9SAl Viro out_8(addr, val); 2191e76875eSOlof Johansson break; 2201e76875eSOlof Johansson case 2: 2217c84ace9SAl Viro out_le16(addr, val); 2221e76875eSOlof Johansson break; 2231e76875eSOlof Johansson default: 2247c84ace9SAl Viro out_le32(addr, val); 2251e76875eSOlof Johansson break; 2261e76875eSOlof Johansson } 2271e76875eSOlof Johansson return PCIBIOS_SUCCESSFUL; 2281e76875eSOlof Johansson } 2291e76875eSOlof Johansson 2301e76875eSOlof Johansson static struct pci_ops pa_pxp_ops = { 2311bb8c621SNathan Lynch .read = pa_pxp_read_config, 2321bb8c621SNathan Lynch .write = pa_pxp_write_config, 2331e76875eSOlof Johansson }; 2341e76875eSOlof Johansson 2351e76875eSOlof Johansson static void __init setup_pa_pxp(struct pci_controller *hose) 2361e76875eSOlof Johansson { 2371e76875eSOlof Johansson hose->ops = &pa_pxp_ops; 2381e76875eSOlof Johansson hose->cfg_data = ioremap(0xe0000000, 0x10000000); 2391e76875eSOlof Johansson } 2401e76875eSOlof Johansson 24109b55f76SArnd Bergmann static int __init pas_add_bridge(struct device_node *dev) 2421e76875eSOlof Johansson { 2431e76875eSOlof Johansson struct pci_controller *hose; 2441e76875eSOlof Johansson 245b7c670d6SRob Herring pr_debug("Adding PCI host bridge %pOF\n", dev); 2461e76875eSOlof Johansson 2471e76875eSOlof Johansson hose = pcibios_alloc_controller(dev); 2481e76875eSOlof Johansson if (!hose) 2491e76875eSOlof Johansson return -ENOMEM; 2501e76875eSOlof Johansson 2511e76875eSOlof Johansson hose->first_busno = 0; 2521e76875eSOlof Johansson hose->last_busno = 0xff; 253d28a0d94SDaniel Axtens hose->controller_ops = pasemi_pci_controller_ops; 2541e76875eSOlof Johansson 2551e76875eSOlof Johansson setup_pa_pxp(hose); 2561e76875eSOlof Johansson 257e13606d7SDarren Stevens pr_info("Found PA-PXP PCI host bridge.\n"); 2581e76875eSOlof Johansson 2591e76875eSOlof Johansson /* Interpret the "ranges" property */ 2601e76875eSOlof Johansson pci_process_bridge_OF_ranges(hose, dev, 1); 2611e76875eSOlof Johansson 26251f4cc20SDarren Stevens /* 26351f4cc20SDarren Stevens * Scan for an isa bridge. This is needed to find the SB600 on the nemo 26451f4cc20SDarren Stevens * and does nothing on machines without one. 26551f4cc20SDarren Stevens */ 26651f4cc20SDarren Stevens isa_bridge_find_early(hose); 26751f4cc20SDarren Stevens 2681e76875eSOlof Johansson return 0; 2691e76875eSOlof Johansson } 2701e76875eSOlof Johansson 2711e76875eSOlof Johansson void __init pas_pci_init(void) 2721e76875eSOlof Johansson { 2731e76875eSOlof Johansson struct device_node *np, *root; 274250a9350SDarren Stevens int res; 2751e76875eSOlof Johansson 2761e76875eSOlof Johansson root = of_find_node_by_path("/"); 2771e76875eSOlof Johansson if (!root) { 278e13606d7SDarren Stevens pr_crit("pas_pci_init: can't find root of device tree\n"); 2791e76875eSOlof Johansson return; 2801e76875eSOlof Johansson } 2811e76875eSOlof Johansson 282eff06ef0SOlof Johansson pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS); 283eff06ef0SOlof Johansson 284250a9350SDarren Stevens np = of_find_compatible_node(root, NULL, "pasemi,rootbus"); 285250a9350SDarren Stevens if (np) { 286250a9350SDarren Stevens res = pas_add_bridge(np); 287250a9350SDarren Stevens of_node_put(np); 288250a9350SDarren Stevens } 2891e76875eSOlof Johansson } 29068c8404cSOlof Johansson 291e37e06afSNick Child void __iomem *__init pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset) 29268c8404cSOlof Johansson { 29368c8404cSOlof Johansson struct pci_controller *hose; 29468c8404cSOlof Johansson 2954d442331SOlof Johansson hose = pci_bus_to_host(dev->bus); 29668c8404cSOlof Johansson 2974d442331SOlof Johansson return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset); 29868c8404cSOlof Johansson } 299d28a0d94SDaniel Axtens 300d28a0d94SDaniel Axtens struct pci_controller_ops pasemi_pci_controller_ops; 301