linux/arch/powerpc/platforms/pasemi/pci.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2006 PA Semi, Inc
   4 *
   5 * Authors: Kip Walker, PA Semi
   6 *          Olof Johansson, PA Semi
   7 *
   8 * Maintained by: Olof Johansson <olof@lixom.net>
   9 *
  10 * Based on arch/powerpc/platforms/maple/pci.c
  11 */
  12
  13
  14#include <linux/kernel.h>
  15#include <linux/pci.h>
  16
  17#include <asm/pci-bridge.h>
  18#include <asm/isa-bridge.h>
  19#include <asm/machdep.h>
  20
  21#include <asm/ppc-pci.h>
  22
  23#include "pasemi.h"
  24
  25#define PA_PXP_CFA(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off))
  26
  27static inline int pa_pxp_offset_valid(u8 bus, u8 devfn, int offset)
  28{
  29        /* Device 0 Function 0 is special: It's config space spans function 1 as
  30         * well, so allow larger offset. It's really a two-function device but the
  31         * second function does not probe.
  32         */
  33        if (bus == 0 && devfn == 0)
  34                return offset < 8192;
  35        else
  36                return offset < 4096;
  37}
  38
  39static void volatile __iomem *pa_pxp_cfg_addr(struct pci_controller *hose,
  40                                       u8 bus, u8 devfn, int offset)
  41{
  42        return hose->cfg_data + PA_PXP_CFA(bus, devfn, offset);
  43}
  44
  45static inline int is_root_port(int busno, int devfn)
  46{
  47        return ((busno == 0) && (PCI_FUNC(devfn) < 4) &&
  48                 ((PCI_SLOT(devfn) == 16) || (PCI_SLOT(devfn) == 17)));
  49}
  50
  51static inline int is_5945_reg(int reg)
  52{
  53        return (((reg >= 0x18) && (reg < 0x34)) ||
  54                ((reg >= 0x158) && (reg < 0x178)));
  55}
  56
  57static int workaround_5945(struct pci_bus *bus, unsigned int devfn,
  58                           int offset, int len, u32 *val)
  59{
  60        struct pci_controller *hose;
  61        void volatile __iomem *addr, *dummy;
  62        int byte;
  63        u32 tmp;
  64
  65        if (!is_root_port(bus->number, devfn) || !is_5945_reg(offset))
  66                return 0;
  67
  68        hose = pci_bus_to_host(bus);
  69
  70        addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset & ~0x3);
  71        byte = offset & 0x3;
  72
  73        /* Workaround bug 5945: write 0 to a dummy register before reading,
  74         * and write back what we read. We must read/write the full 32-bit
  75         * contents so we need to shift and mask by hand.
  76         */
  77        dummy = pa_pxp_cfg_addr(hose, bus->number, devfn, 0x10);
  78        out_le32(dummy, 0);
  79        tmp = in_le32(addr);
  80        out_le32(addr, tmp);
  81
  82        switch (len) {
  83        case 1:
  84                *val = (tmp >> (8*byte)) & 0xff;
  85                break;
  86        case 2:
  87                if (byte == 0)
  88                        *val = tmp & 0xffff;
  89                else
  90                        *val = (tmp >> 16) & 0xffff;
  91                break;
  92        default:
  93                *val = tmp;
  94                break;
  95        }
  96
  97        return 1;
  98}
  99
 100#ifdef CONFIG_PPC_PASEMI_NEMO
 101#define PXP_ERR_CFG_REG 0x4
 102#define PXP_IGNORE_PCIE_ERRORS  0x800
 103#define SB600_BUS 5
 104
 105static void sb600_set_flag(int bus)
 106{
 107        static void __iomem *iob_mapbase = NULL;
 108        struct resource res;
 109        struct device_node *dn;
 110        int err;
 111
 112        if (iob_mapbase == NULL) {
 113                dn = of_find_compatible_node(NULL, "isa", "pasemi,1682m-iob");
 114                if (!dn) {
 115                        pr_crit("NEMO SB600 missing iob node\n");
 116                        return;
 117                }
 118
 119                err = of_address_to_resource(dn, 0, &res);
 120                of_node_put(dn);
 121
 122                if (err) {
 123                        pr_crit("NEMO SB600 missing resource\n");
 124                        return;
 125                }
 126
 127                pr_info("NEMO SB600 IOB base %08llx\n",res.start);
 128
 129                iob_mapbase = ioremap(res.start + 0x100, 0x94);
 130        }
 131
 132        if (iob_mapbase != NULL) {
 133                if (bus == SB600_BUS) {
 134                        /*
 135                         * This is the SB600's bus, tell the PCI-e root port
 136                         * to allow non-zero devices to enumerate.
 137                         */
 138                        out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) | PXP_IGNORE_PCIE_ERRORS);
 139                } else {
 140                        /*
 141                         * Only scan device 0 on other busses
 142                         */
 143                        out_le32(iob_mapbase + PXP_ERR_CFG_REG, in_le32(iob_mapbase + PXP_ERR_CFG_REG) & ~PXP_IGNORE_PCIE_ERRORS);
 144                }
 145        }
 146}
 147
 148#else
 149
 150static void sb600_set_flag(int bus)
 151{
 152}
 153#endif
 154
 155static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn,
 156                              int offset, int len, u32 *val)
 157{
 158        struct pci_controller *hose;
 159        void volatile __iomem *addr;
 160
 161        hose = pci_bus_to_host(bus);
 162        if (!hose)
 163                return PCIBIOS_DEVICE_NOT_FOUND;
 164
 165        if (!pa_pxp_offset_valid(bus->number, devfn, offset))
 166                return PCIBIOS_BAD_REGISTER_NUMBER;
 167
 168        if (workaround_5945(bus, devfn, offset, len, val))
 169                return PCIBIOS_SUCCESSFUL;
 170
 171        addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
 172
 173        sb600_set_flag(bus->number);
 174
 175        /*
 176         * Note: the caller has already checked that offset is
 177         * suitably aligned and that len is 1, 2 or 4.
 178         */
 179        switch (len) {
 180        case 1:
 181                *val = in_8(addr);
 182                break;
 183        case 2:
 184                *val = in_le16(addr);
 185                break;
 186        default:
 187                *val = in_le32(addr);
 188                break;
 189        }
 190
 191        return PCIBIOS_SUCCESSFUL;
 192}
 193
 194static int pa_pxp_write_config(struct pci_bus *bus, unsigned int devfn,
 195                               int offset, int len, u32 val)
 196{
 197        struct pci_controller *hose;
 198        void volatile __iomem *addr;
 199
 200        hose = pci_bus_to_host(bus);
 201        if (!hose)
 202                return PCIBIOS_DEVICE_NOT_FOUND;
 203
 204        if (!pa_pxp_offset_valid(bus->number, devfn, offset))
 205                return PCIBIOS_BAD_REGISTER_NUMBER;
 206
 207        addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset);
 208
 209        sb600_set_flag(bus->number);
 210
 211        /*
 212         * Note: the caller has already checked that offset is
 213         * suitably aligned and that len is 1, 2 or 4.
 214         */
 215        switch (len) {
 216        case 1:
 217                out_8(addr, val);
 218                break;
 219        case 2:
 220                out_le16(addr, val);
 221                break;
 222        default:
 223                out_le32(addr, val);
 224                break;
 225        }
 226        return PCIBIOS_SUCCESSFUL;
 227}
 228
 229static struct pci_ops pa_pxp_ops = {
 230        .read = pa_pxp_read_config,
 231        .write = pa_pxp_write_config,
 232};
 233
 234static void __init setup_pa_pxp(struct pci_controller *hose)
 235{
 236        hose->ops = &pa_pxp_ops;
 237        hose->cfg_data = ioremap(0xe0000000, 0x10000000);
 238}
 239
 240static int __init pas_add_bridge(struct device_node *dev)
 241{
 242        struct pci_controller *hose;
 243
 244        pr_debug("Adding PCI host bridge %pOF\n", dev);
 245
 246        hose = pcibios_alloc_controller(dev);
 247        if (!hose)
 248                return -ENOMEM;
 249
 250        hose->first_busno = 0;
 251        hose->last_busno = 0xff;
 252        hose->controller_ops = pasemi_pci_controller_ops;
 253
 254        setup_pa_pxp(hose);
 255
 256        pr_info("Found PA-PXP PCI host bridge.\n");
 257
 258        /* Interpret the "ranges" property */
 259        pci_process_bridge_OF_ranges(hose, dev, 1);
 260
 261        /*
 262         * Scan for an isa bridge. This is needed to find the SB600 on the nemo
 263         * and does nothing on machines without one.
 264         */
 265        isa_bridge_find_early(hose);
 266
 267        return 0;
 268}
 269
 270void __init pas_pci_init(void)
 271{
 272        struct device_node *np, *root;
 273        int res;
 274
 275        root = of_find_node_by_path("/");
 276        if (!root) {
 277                pr_crit("pas_pci_init: can't find root of device tree\n");
 278                return;
 279        }
 280
 281        pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS);
 282
 283        np = of_find_compatible_node(root, NULL, "pasemi,rootbus");
 284        if (np) {
 285                res = pas_add_bridge(np);
 286                of_node_put(np);
 287        }
 288}
 289
 290void __iomem *pasemi_pci_getcfgaddr(struct pci_dev *dev, int offset)
 291{
 292        struct pci_controller *hose;
 293
 294        hose = pci_bus_to_host(dev->bus);
 295
 296        return (void __iomem *)pa_pxp_cfg_addr(hose, dev->bus->number, dev->devfn, offset);
 297}
 298
 299struct pci_controller_ops pasemi_pci_controller_ops;
 300