| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2006 PA Semi, Inc |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 7 | 8 | * Maintained by: Olof Johansson <olof@lixom.net> |
|---|
| 8 | 9 | * |
|---|
| 9 | 10 | * Based on arch/powerpc/platforms/maple/pci.c |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 12 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 13 | | - * published by the Free Software Foundation. |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 16 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 18 | | - * GNU General Public License for more details. |
|---|
| 19 | | - * |
|---|
| 20 | | - * You should have received a copy of the GNU General Public License |
|---|
| 21 | | - * along with this program; if not, write to the Free Software |
|---|
| 22 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 23 | 11 | */ |
|---|
| 24 | 12 | |
|---|
| 25 | 13 | |
|---|
| .. | .. |
|---|
| 27 | 15 | #include <linux/pci.h> |
|---|
| 28 | 16 | |
|---|
| 29 | 17 | #include <asm/pci-bridge.h> |
|---|
| 18 | +#include <asm/isa-bridge.h> |
|---|
| 30 | 19 | #include <asm/machdep.h> |
|---|
| 31 | 20 | |
|---|
| 32 | 21 | #include <asm/ppc-pci.h> |
|---|
| .. | .. |
|---|
| 108 | 97 | return 1; |
|---|
| 109 | 98 | } |
|---|
| 110 | 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 | + |
|---|
| 105 | +static 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 | + |
|---|
| 150 | +static void sb600_set_flag(int bus) |
|---|
| 151 | +{ |
|---|
| 152 | +} |
|---|
| 153 | +#endif |
|---|
| 154 | + |
|---|
| 111 | 155 | static int pa_pxp_read_config(struct pci_bus *bus, unsigned int devfn, |
|---|
| 112 | 156 | int offset, int len, u32 *val) |
|---|
| 113 | 157 | { |
|---|
| .. | .. |
|---|
| 125 | 169 | return PCIBIOS_SUCCESSFUL; |
|---|
| 126 | 170 | |
|---|
| 127 | 171 | addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); |
|---|
| 172 | + |
|---|
| 173 | + sb600_set_flag(bus->number); |
|---|
| 128 | 174 | |
|---|
| 129 | 175 | /* |
|---|
| 130 | 176 | * Note: the caller has already checked that offset is |
|---|
| .. | .. |
|---|
| 159 | 205 | return PCIBIOS_BAD_REGISTER_NUMBER; |
|---|
| 160 | 206 | |
|---|
| 161 | 207 | addr = pa_pxp_cfg_addr(hose, bus->number, devfn, offset); |
|---|
| 208 | + |
|---|
| 209 | + sb600_set_flag(bus->number); |
|---|
| 162 | 210 | |
|---|
| 163 | 211 | /* |
|---|
| 164 | 212 | * Note: the caller has already checked that offset is |
|---|
| .. | .. |
|---|
| 210 | 258 | /* Interpret the "ranges" property */ |
|---|
| 211 | 259 | pci_process_bridge_OF_ranges(hose, dev, 1); |
|---|
| 212 | 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 | + |
|---|
| 213 | 267 | return 0; |
|---|
| 214 | 268 | } |
|---|
| 215 | 269 | |
|---|