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