.. | .. |
---|
| 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 | |
---|