455 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * This file contains quirk handling code for PnP devices4 * Some devices do not report all their resources, and need to have extra5 * resources added. This is most easily accomplished at initialisation time6 * when building up the resource structure for the first time.7 *8 * Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>9 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.10 * Bjorn Helgaas <bjorn.helgaas@hp.com>11 *12 * Heavily based on PCI quirks handling which is13 *14 * Copyright (c) 1999 Martin Mares <mj@ucw.cz>15 */16 17#include <linux/types.h>18#include <linux/kernel.h>19#include <linux/pci.h>20#include <linux/string.h>21#include <linux/slab.h>22#include <linux/pnp.h>23#include <linux/io.h>24#include "base.h"25 26static void quirk_awe32_add_ports(struct pnp_dev *dev,27 struct pnp_option *option,28 unsigned int offset)29{30 struct pnp_option *new_option;31 32 new_option = kmalloc(sizeof(struct pnp_option), GFP_KERNEL);33 if (!new_option) {34 dev_err(&dev->dev, "couldn't add ioport region to option set "35 "%d\n", pnp_option_set(option));36 return;37 }38 39 *new_option = *option;40 new_option->u.port.min += offset;41 new_option->u.port.max += offset;42 list_add(&new_option->list, &option->list);43 44 dev_info(&dev->dev, "added ioport region %#llx-%#llx to set %d\n",45 (unsigned long long) new_option->u.port.min,46 (unsigned long long) new_option->u.port.max,47 pnp_option_set(option));48}49 50static void quirk_awe32_resources(struct pnp_dev *dev)51{52 struct pnp_option *option;53 unsigned int set = ~0;54 55 /*56 * Add two extra ioport regions (at offset 0x400 and 0x800 from the57 * one given) to every dependent option set.58 */59 list_for_each_entry(option, &dev->options, list) {60 if (pnp_option_is_dependent(option) &&61 pnp_option_set(option) != set) {62 set = pnp_option_set(option);63 quirk_awe32_add_ports(dev, option, 0x800);64 quirk_awe32_add_ports(dev, option, 0x400);65 }66 }67}68 69static void quirk_cmi8330_resources(struct pnp_dev *dev)70{71 struct pnp_option *option;72 struct pnp_irq *irq;73 struct pnp_dma *dma;74 75 list_for_each_entry(option, &dev->options, list) {76 if (!pnp_option_is_dependent(option))77 continue;78 79 if (option->type == IORESOURCE_IRQ) {80 irq = &option->u.irq;81 bitmap_zero(irq->map.bits, PNP_IRQ_NR);82 __set_bit(5, irq->map.bits);83 __set_bit(7, irq->map.bits);84 __set_bit(10, irq->map.bits);85 dev_info(&dev->dev, "set possible IRQs in "86 "option set %d to 5, 7, 10\n",87 pnp_option_set(option));88 } else if (option->type == IORESOURCE_DMA) {89 dma = &option->u.dma;90 if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) ==91 IORESOURCE_DMA_8BIT &&92 dma->map != 0x0A) {93 dev_info(&dev->dev, "changing possible "94 "DMA channel mask in option set %d "95 "from %#02x to 0x0A (1, 3)\n",96 pnp_option_set(option), dma->map);97 dma->map = 0x0A;98 }99 }100 }101}102 103static void quirk_sb16audio_resources(struct pnp_dev *dev)104{105 struct pnp_option *option;106 unsigned int prev_option_flags = ~0, n = 0;107 struct pnp_port *port;108 109 /*110 * The default range on the OPL port for these devices is 0x388-0x388.111 * Here we increase that range so that two such cards can be112 * auto-configured.113 */114 list_for_each_entry(option, &dev->options, list) {115 if (prev_option_flags != option->flags) {116 prev_option_flags = option->flags;117 n = 0;118 }119 120 if (pnp_option_is_dependent(option) &&121 option->type == IORESOURCE_IO) {122 n++;123 port = &option->u.port;124 if (n == 3 && port->min == port->max) {125 port->max += 0x70;126 dev_info(&dev->dev, "increased option port "127 "range from %#llx-%#llx to "128 "%#llx-%#llx\n",129 (unsigned long long) port->min,130 (unsigned long long) port->min,131 (unsigned long long) port->min,132 (unsigned long long) port->max);133 }134 }135 }136}137 138static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev,139 unsigned int set)140{141 struct pnp_option *tail = NULL, *first_new_option = NULL;142 struct pnp_option *option, *new_option;143 unsigned int flags;144 145 list_for_each_entry(option, &dev->options, list) {146 if (pnp_option_is_dependent(option))147 tail = option;148 }149 if (!tail) {150 dev_err(&dev->dev, "no dependent option sets\n");151 return NULL;152 }153 154 flags = pnp_new_dependent_set(dev, PNP_RES_PRIORITY_FUNCTIONAL);155 list_for_each_entry(option, &dev->options, list) {156 if (pnp_option_is_dependent(option) &&157 pnp_option_set(option) == set) {158 new_option = kmalloc(sizeof(struct pnp_option),159 GFP_KERNEL);160 if (!new_option) {161 dev_err(&dev->dev, "couldn't clone dependent "162 "set %d\n", set);163 return NULL;164 }165 166 *new_option = *option;167 new_option->flags = flags;168 if (!first_new_option)169 first_new_option = new_option;170 171 list_add(&new_option->list, &tail->list);172 tail = new_option;173 }174 }175 176 return first_new_option;177}178 179 180static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev)181{182 struct pnp_option *new_option;183 unsigned int num_sets, i, set;184 struct pnp_irq *irq;185 186 num_sets = dev->num_dependent_sets;187 for (i = 0; i < num_sets; i++) {188 new_option = pnp_clone_dependent_set(dev, i);189 if (!new_option)190 return;191 192 set = pnp_option_set(new_option);193 while (new_option && pnp_option_set(new_option) == set) {194 if (new_option->type == IORESOURCE_IRQ) {195 irq = &new_option->u.irq;196 irq->flags |= IORESOURCE_IRQ_OPTIONAL;197 }198 dbg_pnp_show_option(dev, new_option);199 new_option = list_entry(new_option->list.next,200 struct pnp_option, list);201 }202 203 dev_info(&dev->dev, "added dependent option set %d (same as "204 "set %d except IRQ optional)\n", set, i);205 }206}207 208static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)209{210 struct pnp_option *option;211 struct pnp_irq *irq = NULL;212 unsigned int independent_irqs = 0;213 214 list_for_each_entry(option, &dev->options, list) {215 if (option->type == IORESOURCE_IRQ &&216 !pnp_option_is_dependent(option)) {217 independent_irqs++;218 irq = &option->u.irq;219 }220 }221 222 if (independent_irqs != 1)223 return;224 225 irq->flags |= IORESOURCE_IRQ_OPTIONAL;226 dev_info(&dev->dev, "made independent IRQ optional\n");227}228 229static void quirk_system_pci_resources(struct pnp_dev *dev)230{231 struct pci_dev *pdev = NULL;232 struct resource *res, *r;233 int i, j;234 235 /*236 * Some BIOSes have PNP motherboard devices with resources that237 * partially overlap PCI BARs. The PNP system driver claims these238 * motherboard resources, which prevents the normal PCI driver from239 * requesting them later.240 *241 * This patch disables the PNP resources that conflict with PCI BARs242 * so they won't be claimed by the PNP system driver.243 */244 for_each_pci_dev(pdev) {245 pci_dev_for_each_resource(pdev, r, i) {246 unsigned long type = resource_type(r);247 248 if (!(type == IORESOURCE_IO || type == IORESOURCE_MEM) ||249 resource_size(r) == 0)250 continue;251 252 if (r->flags & IORESOURCE_UNSET)253 continue;254 255 for (j = 0;256 (res = pnp_get_resource(dev, type, j)); j++) {257 if (res->start == 0 && res->end == 0)258 continue;259 260 /*261 * If the PNP region doesn't overlap the PCI262 * region at all, there's no problem.263 */264 if (!resource_overlaps(res, r))265 continue;266 267 /*268 * If the PNP region completely encloses (or is269 * at least as large as) the PCI region, that's270 * also OK. For example, this happens when the271 * PNP device describes a bridge with PCI272 * behind it.273 */274 if (res->start <= r->start && res->end >= r->end)275 continue;276 277 /*278 * Otherwise, the PNP region overlaps *part* of279 * the PCI region, and that might prevent a PCI280 * driver from requesting its resources.281 */282 dev_warn(&dev->dev,283 "disabling %pR because it overlaps %s BAR %d %pR\n",284 res, pci_name(pdev), i, r);285 res->flags |= IORESOURCE_DISABLED;286 }287 }288 }289}290 291#ifdef CONFIG_AMD_NB292 293#include <asm/amd_nb.h>294 295static void quirk_amd_mmconfig_area(struct pnp_dev *dev)296{297 resource_size_t start, end;298 struct pnp_resource *pnp_res;299 struct resource *res;300 struct resource mmconfig_res, *mmconfig;301 302 mmconfig = amd_get_mmconfig_range(&mmconfig_res);303 if (!mmconfig)304 return;305 306 list_for_each_entry(pnp_res, &dev->resources, list) {307 res = &pnp_res->res;308 if (res->end < mmconfig->start || res->start > mmconfig->end ||309 (res->start == mmconfig->start && res->end == mmconfig->end))310 continue;311 312 dev_info(&dev->dev, FW_BUG313 "%pR covers only part of AMD MMCONFIG area %pR; adding more reservations\n",314 res, mmconfig);315 if (mmconfig->start < res->start) {316 start = mmconfig->start;317 end = res->start - 1;318 pnp_add_mem_resource(dev, start, end, 0);319 }320 if (mmconfig->end > res->end) {321 start = res->end + 1;322 end = mmconfig->end;323 pnp_add_mem_resource(dev, start, end, 0);324 }325 break;326 }327}328#endif329 330#ifdef CONFIG_PCI331/* Device IDs of parts that have 32KB MCH space */332static const unsigned int mch_quirk_devices[] = {333 0x0154, /* Ivy Bridge */334 0x0a04, /* Haswell-ULT */335 0x0c00, /* Haswell */336 0x1604, /* Broadwell */337};338 339static struct pci_dev *get_intel_host(void)340{341 int i;342 struct pci_dev *host;343 344 for (i = 0; i < ARRAY_SIZE(mch_quirk_devices); i++) {345 host = pci_get_device(PCI_VENDOR_ID_INTEL, mch_quirk_devices[i],346 NULL);347 if (host)348 return host;349 }350 return NULL;351}352 353static void quirk_intel_mch(struct pnp_dev *dev)354{355 struct pci_dev *host;356 u32 addr_lo, addr_hi;357 struct pci_bus_region region;358 struct resource mch;359 struct pnp_resource *pnp_res;360 struct resource *res;361 362 host = get_intel_host();363 if (!host)364 return;365 366 /*367 * MCHBAR is not an architected PCI BAR, so MCH space is usually368 * reported as a PNP0C02 resource. The MCH space was originally369 * 16KB, but is 32KB in newer parts. Some BIOSes still report a370 * PNP0C02 resource that is only 16KB, which means the rest of the371 * MCH space is consumed but unreported.372 */373 374 /*375 * Read MCHBAR for Host Member Mapped Register Range Base376 * https://www-ssl.intel.com/content/www/us/en/processors/core/4th-gen-core-family-desktop-vol-2-datasheet377 * Sec 3.1.12.378 */379 pci_read_config_dword(host, 0x48, &addr_lo);380 region.start = addr_lo & ~0x7fff;381 pci_read_config_dword(host, 0x4c, &addr_hi);382 region.start |= (u64) addr_hi << 32;383 region.end = region.start + 32*1024 - 1;384 385 memset(&mch, 0, sizeof(mch));386 mch.flags = IORESOURCE_MEM;387 pcibios_bus_to_resource(host->bus, &mch, ®ion);388 389 list_for_each_entry(pnp_res, &dev->resources, list) {390 res = &pnp_res->res;391 if (res->end < mch.start || res->start > mch.end)392 continue; /* no overlap */393 if (res->start == mch.start && res->end == mch.end)394 continue; /* exact match */395 396 dev_info(&dev->dev, FW_BUG "PNP resource %pR covers only part of %s Intel MCH; extending to %pR\n",397 res, pci_name(host), &mch);398 res->start = mch.start;399 res->end = mch.end;400 break;401 }402 403 pci_dev_put(host);404}405#endif406 407/*408 * PnP Quirks409 * Cards or devices that need some tweaking due to incomplete resource info410 */411 412static struct pnp_fixup pnp_fixups[] = {413 /* Soundblaster awe io port quirk */414 {"CTL0021", quirk_awe32_resources},415 {"CTL0022", quirk_awe32_resources},416 {"CTL0023", quirk_awe32_resources},417 /* CMI 8330 interrupt and dma fix */418 {"@X@0001", quirk_cmi8330_resources},419 /* Soundblaster audio device io port range quirk */420 {"CTL0001", quirk_sb16audio_resources},421 {"CTL0031", quirk_sb16audio_resources},422 {"CTL0041", quirk_sb16audio_resources},423 {"CTL0042", quirk_sb16audio_resources},424 {"CTL0043", quirk_sb16audio_resources},425 {"CTL0044", quirk_sb16audio_resources},426 {"CTL0045", quirk_sb16audio_resources},427 /* Add IRQ-optional MPU options */428 {"ADS7151", quirk_ad1815_mpu_resources},429 {"ADS7181", quirk_add_irq_optional_dependent_sets},430 {"AZT0002", quirk_add_irq_optional_dependent_sets},431 /* PnP resources that might overlap PCI BARs */432 {"PNP0c01", quirk_system_pci_resources},433 {"PNP0c02", quirk_system_pci_resources},434#ifdef CONFIG_AMD_NB435 {"PNP0c01", quirk_amd_mmconfig_area},436#endif437#ifdef CONFIG_PCI438 {"PNP0c02", quirk_intel_mch},439#endif440 {""}441};442 443void pnp_fixup_device(struct pnp_dev *dev)444{445 struct pnp_fixup *f;446 447 for (f = pnp_fixups; *f->id; f++) {448 if (!compare_pnp_id(dev->id, f->id))449 continue;450 pnp_dbg(&dev->dev, "%s: calling %pS\n", f->id,451 f->quirk_function);452 f->quirk_function(dev);453 }454}455