Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2006 PA Semi, Inc
0004  *
0005  * Authors: Kip Walker, PA Semi
0006  *      Olof Johansson, PA Semi
0007  *
0008  * Maintained by: Olof Johansson <olof@lixom.net>
0009  *
0010  * Based on arch/powerpc/platforms/maple/pci.c
0011  */
0012 
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/of_address.h>
0016 #include <linux/pci.h>
0017 
0018 #include <asm/pci-bridge.h>
0019 #include <asm/isa-bridge.h>
0020 #include <asm/machdep.h>
0021 
0022 #include <asm/ppc-pci.h>
0023 
0024 #include "pasemi.h"
0025 
0026 #define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off))
0027 
0028 static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset)
0029 {
0030     /* Device 0 Function 0 is special: It's config space spans function 1 as
0031      * well, so allow larger offset. It's really a two-function device but the
0032      * second function does not probe.
0033      */
0034     if (bus == 0 && devfn == 0)
0035         return offset < 8192;
0036     else
0037         return offset < 4096;
0038 }
0039 
0040 static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose,
0041                        u8 bus, u8 devfn, int offset)
0042 {
0043     return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset);
0044 }
0045 
0046 static inline int is_root_port(int busno, int devfn)
0047 {
0048     return ((busno == 0) && (PCI_FUNC(devfn) < 4) &&
0049          ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17)));
0050 }
0051 
0052 static inline int is_5945_reg(int reg)
0053 {
0054     return (((reg >= 0x18) && (reg < 0x34)) ||
0055         ((reg >= 0x158) && (reg < 0x178)));
0056 }
0057 
0058 static int workaround_5945(struct pci_bus *bus, unsigned int devfn,
0059                int offset, int len, u32 *val)
0060 {
0061     struct pci_controller *hose;
0062     void volatile __iomem *addr, *dummy;
0063     int byte;
0064     u32 tmp;
0065 
0066     if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset))
0067         return 0;
0068 
0069     hose = pci_bus_to_host(bus);
0070 
0071     addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3);
0072     byte = offset & 0x3;
0073 
0074     /* Workaround bug 5945: write 0 to a dummy register before reading,
0075      * and write back what we read. We must read/write the full 32-bit
0076      * contents so we need to shift and mask by hand.
0077      */
0078     dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10);
0079     out_le32(dummy, 0);
0080     tmp = in_le32(addr);
0081     out_le32(addr, tmp);
0082 
0083     switch (len) {
0084     case 1:
0085         *val = (tmp >> (8*byte)) & 0xff;
0086         break;
0087     case 2:
0088         if (byte == 0)
0089             *val = tmp & 0xffff;
0090         else
0091             *val = (tmp >> 16) & 0xffff;
0092         break;
0093     default:
0094         *val = tmp;
0095         break;
0096     }
0097 
0098     return 1;
0099 }
0100 
0101 #ifdef CONFIG_PPC_PASEMI_NEMO
0102 #define PXP_ERR_CFG_REG 0x4
0103 #define PXP_IGNORE_PCIE_ERRORS  0x800
0104 #define SB600_BUS 5
0105 
0106 static void sb600_set_flag(int bus)
0107 {
0108     static void __iomem *iob_mapbase = NULL;
0109     struct resource res;
0110     struct device_node *dn;
0111     int err;
0112 
0113     if (iob_mapbase == NULL) {
0114         dn = of_find_compatible_node(NULL, "isa", "pasemi,1682m-iob");
0115         if (!dn) {
0116             pr_crit("NEMO SB600 missing iob node\n");
0117             return;
0118         }
0119 
0120         err = of_address_to_resource(dn, 0, &res);
0121         of_node_put(dn);
0122 
0123         if (err) {
0124             pr_crit("NEMO SB600 missing resource\n");
0125             return;
0126         }
0127 
0128         pr_info("NEMO SB600 IOB base %08llx\n",res.start);
0129 
0130         iob_mapbase = ioremap(res.start + 0x100, 0x94);
0131     }
0132 
0133     if (iob_mapbase != NULL) {
0134         if (bus == SB600_BUS) {
0135             /*
0136              * This is the SB600's bus, tell the PCI-e root port
0137              * to allow non-zero devices to enumerate.
0138              */
0139             out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) | PXP_IGNORE_PCIE_ERRORS);
0140         } else {
0141             /*
0142              * Only scan device 0 on other busses
0143              */
0144             out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) & ~PXP_IGNORE_PCIE_ERRORS);
0145         }
0146     }
0147 }
0148 
0149 #else
0150 
0151 static void sb600_set_flag(int bus)
0152 {
0153 }
0154 #endif
0155 
0156 static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
0157                   int offset, int len, u32 *val)
0158 {
0159     struct pci_controller *hose;
0160     void volatile __iomem *addr;
0161 
0162     hose = pci_bus_to_host(bus);
0163     if (!hose)
0164         return PCIBIOS_DEVICE_NOT_FOUND;
0165 
0166     if (!pa_pxp_offset_valid(bus->number, devfn, offset))
0167         return PCIBIOS_BAD_REGISTER_NUMBER;
0168 
0169     if (workaround_5945(bus, devfn, offset, len, val))
0170         return PCIBIOS_SUCCESSFUL;
0171 
0172     addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
0173 
0174     sb600_set_flag(bus->number);
0175 
0176     /*
0177      * Note: the caller has already checked that offset is
0178      * suitably aligned and that len is 1, 2 or 4.
0179      */
0180     switch (len) {
0181     case 1:
0182         *val = in_8(addr);
0183         break;
0184     case 2:
0185         *val = in_le16(addr);
0186         break;
0187     default:
0188         *val = in_le32(addr);
0189         break;
0190     }
0191 
0192     return PCIBIOS_SUCCESSFUL;
0193 }
0194 
0195 static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn,
0196                    int offset, int len, u32 val)
0197 {
0198     struct pci_controller *hose;
0199     void volatile __iomem *addr;
0200 
0201     hose = pci_bus_to_host(bus);
0202     if (!hose)
0203         return PCIBIOS_DEVICE_NOT_FOUND;
0204 
0205     if (!pa_pxp_offset_valid(bus->number, devfn, offset))
0206         return PCIBIOS_BAD_REGISTER_NUMBER;
0207 
0208     addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
0209 
0210     sb600_set_flag(bus->number);
0211 
0212     /*
0213      * Note: the caller has already checked that offset is
0214      * suitably aligned and that len is 1, 2 or 4.
0215      */
0216     switch (len) {
0217     case 1:
0218         out_8(addr, val);
0219         break;
0220     case 2:
0221         out_le16(addr, val);
0222         break;
0223     default:
0224         out_le32(addr, val);
0225         break;
0226     }
0227     return PCIBIOS_SUCCESSFUL;
0228 }
0229 
0230 static struct pci_ops pa_pxp_ops = {
0231     .read = pa_pxp_read_config,
0232     .write = pa_pxp_write_config,
0233 };
0234 
0235 static void __init setup_pa_pxp(struct pci_controller *hose)
0236 {
0237     hose->ops = &pa_pxp_ops;
0238     hose->cfg_data = ioremap(0xe0000000, 0x10000000);
0239 }
0240 
0241 static int __init pas_add_bridge(struct device_node *dev)
0242 {
0243     struct pci_controller *hose;
0244 
0245     pr_debug("Adding PCI host bridge %pOF\n", dev);
0246 
0247     hose = pcibios_alloc_controller(dev);
0248     if (!hose)
0249         return -ENOMEM;
0250 
0251     hose->first_busno = 0;
0252     hose->last_busno = 0xff;
0253     hose->controller_ops = pasemi_pci_controller_ops;
0254 
0255     setup_pa_pxp(hose);
0256 
0257     pr_info("Found PA-PXP PCI host bridge.\n");
0258 
0259     /* Interpret the "ranges" property */
0260     pci_process_bridge_OF_ranges(hose, dev, 1);
0261 
0262     /*
0263      * Scan for an isa bridge. This is needed to find the SB600 on the nemo
0264      * and does nothing on machines without one.
0265      */
0266     isa_bridge_find_early(hose);
0267 
0268     return 0;
0269 }
0270 
0271 void __init pas_pci_init(void)
0272 {
0273     struct device_node *np, *root;
0274     int res;
0275 
0276     root = of_find_node_by_path("/");
0277     if (!root) {
0278         pr_crit("pas_pci_init: can't find root of device tree\n");
0279         return;
0280     }
0281 
0282     pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS);
0283 
0284     np = of_find_compatible_node(root, NULL, "pasemi,rootbus");
0285     if (np) {
0286         res = pas_add_bridge(np);
0287         of_node_put(np);
0288     }
0289 }
0290 
0291 void __iomem *__init pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset)
0292 {
0293     struct pci_controller *hose;
0294 
0295     hose = pci_bus_to_host(dev->bus);
0296 
0297     return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset);
0298 }
0299 
0300 struct pci_controller_ops pasemi_pci_controller_ops;