364 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2015, 2016 Cavium, Inc.4 */5 6#include <linux/kernel.h>7#include <linux/init.h>8#include <linux/ioport.h>9#include <linux/of_pci.h>10#include <linux/of.h>11#include <linux/pci-ecam.h>12#include <linux/platform_device.h>13 14#if defined(CONFIG_PCI_HOST_THUNDER_ECAM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))15 16static void set_val(u32 v, int where, int size, u32 *val)17{18 int shift = (where & 3) * 8;19 20 pr_debug("set_val %04x: %08x\n", (unsigned int)(where & ~3), v);21 v >>= shift;22 if (size == 1)23 v &= 0xff;24 else if (size == 2)25 v &= 0xffff;26 *val = v;27}28 29static int handle_ea_bar(u32 e0, int bar, struct pci_bus *bus,30 unsigned int devfn, int where, int size, u32 *val)31{32 void __iomem *addr;33 u32 v;34 35 /* Entries are 16-byte aligned; bits[2,3] select word in entry */36 int where_a = where & 0xc;37 38 if (where_a == 0) {39 set_val(e0, where, size, val);40 return PCIBIOS_SUCCESSFUL;41 }42 if (where_a == 0x4) {43 addr = bus->ops->map_bus(bus, devfn, bar); /* BAR 0 */44 if (!addr)45 return PCIBIOS_DEVICE_NOT_FOUND;46 47 v = readl(addr);48 v &= ~0xf;49 v |= 2; /* EA entry-1. Base-L */50 set_val(v, where, size, val);51 return PCIBIOS_SUCCESSFUL;52 }53 if (where_a == 0x8) {54 u32 barl_orig;55 u32 barl_rb;56 57 addr = bus->ops->map_bus(bus, devfn, bar); /* BAR 0 */58 if (!addr)59 return PCIBIOS_DEVICE_NOT_FOUND;60 61 barl_orig = readl(addr + 0);62 writel(0xffffffff, addr + 0);63 barl_rb = readl(addr + 0);64 writel(barl_orig, addr + 0);65 /* zeros in unsettable bits */66 v = ~barl_rb & ~3;67 v |= 0xc; /* EA entry-2. Offset-L */68 set_val(v, where, size, val);69 return PCIBIOS_SUCCESSFUL;70 }71 if (where_a == 0xc) {72 addr = bus->ops->map_bus(bus, devfn, bar + 4); /* BAR 1 */73 if (!addr)74 return PCIBIOS_DEVICE_NOT_FOUND;75 76 v = readl(addr); /* EA entry-3. Base-H */77 set_val(v, where, size, val);78 return PCIBIOS_SUCCESSFUL;79 }80 return PCIBIOS_DEVICE_NOT_FOUND;81}82 83static int thunder_ecam_p2_config_read(struct pci_bus *bus, unsigned int devfn,84 int where, int size, u32 *val)85{86 struct pci_config_window *cfg = bus->sysdata;87 int where_a = where & ~3;88 void __iomem *addr;89 u32 node_bits;90 u32 v;91 92 /* EA Base[63:32] may be missing some bits ... */93 switch (where_a) {94 case 0xa8:95 case 0xbc:96 case 0xd0:97 case 0xe4:98 break;99 default:100 return pci_generic_config_read(bus, devfn, where, size, val);101 }102 103 addr = bus->ops->map_bus(bus, devfn, where_a);104 if (!addr)105 return PCIBIOS_DEVICE_NOT_FOUND;106 107 v = readl(addr);108 109 /*110 * Bit 44 of the 64-bit Base must match the same bit in111 * the config space access window. Since we are working with112 * the high-order 32 bits, shift everything down by 32 bits.113 */114 node_bits = upper_32_bits(cfg->res.start) & (1 << 12);115 116 v |= node_bits;117 set_val(v, where, size, val);118 119 return PCIBIOS_SUCCESSFUL;120}121 122static int thunder_ecam_config_read(struct pci_bus *bus, unsigned int devfn,123 int where, int size, u32 *val)124{125 u32 v;126 u32 vendor_device;127 u32 class_rev;128 void __iomem *addr;129 int cfg_type;130 int where_a = where & ~3;131 132 addr = bus->ops->map_bus(bus, devfn, 0xc);133 if (!addr)134 return PCIBIOS_DEVICE_NOT_FOUND;135 136 v = readl(addr);137 138 /* Check for non type-00 header */139 cfg_type = (v >> 16) & 0x7f;140 141 addr = bus->ops->map_bus(bus, devfn, 8);142 if (!addr)143 return PCIBIOS_DEVICE_NOT_FOUND;144 145 class_rev = readl(addr);146 if (class_rev == 0xffffffff)147 goto no_emulation;148 149 if ((class_rev & 0xff) >= 8) {150 /* Pass-2 handling */151 if (cfg_type)152 goto no_emulation;153 return thunder_ecam_p2_config_read(bus, devfn, where,154 size, val);155 }156 157 /*158 * All BARs have fixed addresses specified by the EA159 * capability; they must return zero on read.160 */161 if (cfg_type == 0 &&162 ((where >= 0x10 && where < 0x2c) ||163 (where >= 0x1a4 && where < 0x1bc))) {164 /* BAR or SR-IOV BAR */165 *val = 0;166 return PCIBIOS_SUCCESSFUL;167 }168 169 addr = bus->ops->map_bus(bus, devfn, 0);170 if (!addr)171 return PCIBIOS_DEVICE_NOT_FOUND;172 173 vendor_device = readl(addr);174 if (vendor_device == 0xffffffff)175 goto no_emulation;176 177 pr_debug("%04x:%04x - Fix pass#: %08x, where: %03x, devfn: %03x\n",178 vendor_device & 0xffff, vendor_device >> 16, class_rev,179 (unsigned int)where, devfn);180 181 /* Check for non type-00 header */182 if (cfg_type == 0) {183 bool has_msix;184 bool is_nic = (vendor_device == 0xa01e177d);185 bool is_tns = (vendor_device == 0xa01f177d);186 187 addr = bus->ops->map_bus(bus, devfn, 0x70);188 if (!addr)189 return PCIBIOS_DEVICE_NOT_FOUND;190 191 /* E_CAP */192 v = readl(addr);193 has_msix = (v & 0xff00) != 0;194 195 if (!has_msix && where_a == 0x70) {196 v |= 0xbc00; /* next capability is EA at 0xbc */197 set_val(v, where, size, val);198 return PCIBIOS_SUCCESSFUL;199 }200 if (where_a == 0xb0) {201 addr = bus->ops->map_bus(bus, devfn, where_a);202 if (!addr)203 return PCIBIOS_DEVICE_NOT_FOUND;204 205 v = readl(addr);206 if (v & 0xff00)207 pr_err("Bad MSIX cap header: %08x\n", v);208 v |= 0xbc00; /* next capability is EA at 0xbc */209 set_val(v, where, size, val);210 return PCIBIOS_SUCCESSFUL;211 }212 if (where_a == 0xbc) {213 if (is_nic)214 v = 0x40014; /* EA last in chain, 4 entries */215 else if (is_tns)216 v = 0x30014; /* EA last in chain, 3 entries */217 else if (has_msix)218 v = 0x20014; /* EA last in chain, 2 entries */219 else220 v = 0x10014; /* EA last in chain, 1 entry */221 set_val(v, where, size, val);222 return PCIBIOS_SUCCESSFUL;223 }224 if (where_a >= 0xc0 && where_a < 0xd0)225 /* EA entry-0. PP=0, BAR0 Size:3 */226 return handle_ea_bar(0x80ff0003,227 0x10, bus, devfn, where,228 size, val);229 if (where_a >= 0xd0 && where_a < 0xe0 && has_msix)230 /* EA entry-1. PP=0, BAR4 Size:3 */231 return handle_ea_bar(0x80ff0043,232 0x20, bus, devfn, where,233 size, val);234 if (where_a >= 0xe0 && where_a < 0xf0 && is_tns)235 /* EA entry-2. PP=0, BAR2, Size:3 */236 return handle_ea_bar(0x80ff0023,237 0x18, bus, devfn, where,238 size, val);239 if (where_a >= 0xe0 && where_a < 0xf0 && is_nic)240 /* EA entry-2. PP=4, VF_BAR0 (9), Size:3 */241 return handle_ea_bar(0x80ff0493,242 0x1a4, bus, devfn, where,243 size, val);244 if (where_a >= 0xf0 && where_a < 0x100 && is_nic)245 /* EA entry-3. PP=4, VF_BAR4 (d), Size:3 */246 return handle_ea_bar(0x80ff04d3,247 0x1b4, bus, devfn, where,248 size, val);249 } else if (cfg_type == 1) {250 bool is_rsl_bridge = devfn == 0x08;251 bool is_rad_bridge = devfn == 0xa0;252 bool is_zip_bridge = devfn == 0xa8;253 bool is_dfa_bridge = devfn == 0xb0;254 bool is_nic_bridge = devfn == 0x10;255 256 if (where_a == 0x70) {257 addr = bus->ops->map_bus(bus, devfn, where_a);258 if (!addr)259 return PCIBIOS_DEVICE_NOT_FOUND;260 261 v = readl(addr);262 if (v & 0xff00)263 pr_err("Bad PCIe cap header: %08x\n", v);264 v |= 0xbc00; /* next capability is EA at 0xbc */265 set_val(v, where, size, val);266 return PCIBIOS_SUCCESSFUL;267 }268 if (where_a == 0xbc) {269 if (is_nic_bridge)270 v = 0x10014; /* EA last in chain, 1 entry */271 else272 v = 0x00014; /* EA last in chain, no entries */273 set_val(v, where, size, val);274 return PCIBIOS_SUCCESSFUL;275 }276 if (where_a == 0xc0) {277 if (is_rsl_bridge || is_nic_bridge)278 v = 0x0101; /* subordinate:secondary = 1:1 */279 else if (is_rad_bridge)280 v = 0x0202; /* subordinate:secondary = 2:2 */281 else if (is_zip_bridge)282 v = 0x0303; /* subordinate:secondary = 3:3 */283 else if (is_dfa_bridge)284 v = 0x0404; /* subordinate:secondary = 4:4 */285 set_val(v, where, size, val);286 return PCIBIOS_SUCCESSFUL;287 }288 if (where_a == 0xc4 && is_nic_bridge) {289 /* Enabled, not-Write, SP=ff, PP=05, BEI=6, ES=4 */290 v = 0x80ff0564;291 set_val(v, where, size, val);292 return PCIBIOS_SUCCESSFUL;293 }294 if (where_a == 0xc8 && is_nic_bridge) {295 v = 0x00000002; /* Base-L 64-bit */296 set_val(v, where, size, val);297 return PCIBIOS_SUCCESSFUL;298 }299 if (where_a == 0xcc && is_nic_bridge) {300 v = 0xfffffffe; /* MaxOffset-L 64-bit */301 set_val(v, where, size, val);302 return PCIBIOS_SUCCESSFUL;303 }304 if (where_a == 0xd0 && is_nic_bridge) {305 v = 0x00008430; /* NIC Base-H */306 set_val(v, where, size, val);307 return PCIBIOS_SUCCESSFUL;308 }309 if (where_a == 0xd4 && is_nic_bridge) {310 v = 0x0000000f; /* MaxOffset-H */311 set_val(v, where, size, val);312 return PCIBIOS_SUCCESSFUL;313 }314 }315no_emulation:316 return pci_generic_config_read(bus, devfn, where, size, val);317}318 319static int thunder_ecam_config_write(struct pci_bus *bus, unsigned int devfn,320 int where, int size, u32 val)321{322 /*323 * All BARs have fixed addresses; ignore BAR writes so they324 * don't get corrupted.325 */326 if ((where >= 0x10 && where < 0x2c) ||327 (where >= 0x1a4 && where < 0x1bc))328 /* BAR or SR-IOV BAR */329 return PCIBIOS_SUCCESSFUL;330 331 return pci_generic_config_write(bus, devfn, where, size, val);332}333 334const struct pci_ecam_ops pci_thunder_ecam_ops = {335 .pci_ops = {336 .map_bus = pci_ecam_map_bus,337 .read = thunder_ecam_config_read,338 .write = thunder_ecam_config_write,339 }340};341 342#ifdef CONFIG_PCI_HOST_THUNDER_ECAM343 344static const struct of_device_id thunder_ecam_of_match[] = {345 {346 .compatible = "cavium,pci-host-thunder-ecam",347 .data = &pci_thunder_ecam_ops,348 },349 { },350};351 352static struct platform_driver thunder_ecam_driver = {353 .driver = {354 .name = KBUILD_MODNAME,355 .of_match_table = thunder_ecam_of_match,356 .suppress_bind_attrs = true,357 },358 .probe = pci_host_common_probe,359};360builtin_platform_driver(thunder_ecam_driver);361 362#endif363#endif364