Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  This file contains quirk handling code for PnP devices
0004  *  Some devices do not report all their resources, and need to have extra
0005  *  resources added. This is most easily accomplished at initialisation time
0006  *  when building up the resource structure for the first time.
0007  *
0008  *  Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
0009  *  Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
0010  *  Bjorn Helgaas <bjorn.helgaas@hp.com>
0011  *
0012  *  Heavily based on PCI quirks handling which is
0013  *
0014  *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
0015  */
0016 
0017 #include <linux/types.h>
0018 #include <linux/kernel.h>
0019 #include <linux/pci.h>
0020 #include <linux/string.h>
0021 #include <linux/slab.h>
0022 #include <linux/pnp.h>
0023 #include <linux/io.h>
0024 #include "base.h"
0025 
0026 static void quirk_awe32_add_ports(struct pnp_dev *dev,
0027                   struct pnp_option *option,
0028                   unsigned int offset)
0029 {
0030     struct pnp_option *new_option;
0031 
0032     new_option = kmalloc(sizeof(struct pnp_option), GFP_KERNEL);
0033     if (!new_option) {
0034         dev_err(&dev->dev, "couldn't add ioport region to option set "
0035             "%d\n", pnp_option_set(option));
0036         return;
0037     }
0038 
0039     *new_option = *option;
0040     new_option->u.port.min += offset;
0041     new_option->u.port.max += offset;
0042     list_add(&new_option->list, &option->list);
0043 
0044     dev_info(&dev->dev, "added ioport region %#llx-%#llx to set %d\n",
0045         (unsigned long long) new_option->u.port.min,
0046         (unsigned long long) new_option->u.port.max,
0047         pnp_option_set(option));
0048 }
0049 
0050 static void quirk_awe32_resources(struct pnp_dev *dev)
0051 {
0052     struct pnp_option *option;
0053     unsigned int set = ~0;
0054 
0055     /*
0056      * Add two extra ioport regions (at offset 0x400 and 0x800 from the
0057      * one given) to every dependent option set.
0058      */
0059     list_for_each_entry(option, &dev->options, list) {
0060         if (pnp_option_is_dependent(option) &&
0061             pnp_option_set(option) != set) {
0062             set = pnp_option_set(option);
0063             quirk_awe32_add_ports(dev, option, 0x800);
0064             quirk_awe32_add_ports(dev, option, 0x400);
0065         }
0066     }
0067 }
0068 
0069 static void quirk_cmi8330_resources(struct pnp_dev *dev)
0070 {
0071     struct pnp_option *option;
0072     struct pnp_irq *irq;
0073     struct pnp_dma *dma;
0074 
0075     list_for_each_entry(option, &dev->options, list) {
0076         if (!pnp_option_is_dependent(option))
0077             continue;
0078 
0079         if (option->type == IORESOURCE_IRQ) {
0080             irq = &option->u.irq;
0081             bitmap_zero(irq->map.bits, PNP_IRQ_NR);
0082             __set_bit(5, irq->map.bits);
0083             __set_bit(7, irq->map.bits);
0084             __set_bit(10, irq->map.bits);
0085             dev_info(&dev->dev, "set possible IRQs in "
0086                  "option set %d to 5, 7, 10\n",
0087                  pnp_option_set(option));
0088         } else if (option->type == IORESOURCE_DMA) {
0089             dma = &option->u.dma;
0090             if ((dma->flags & IORESOURCE_DMA_TYPE_MASK) ==
0091                         IORESOURCE_DMA_8BIT &&
0092                 dma->map != 0x0A) {
0093                 dev_info(&dev->dev, "changing possible "
0094                      "DMA channel mask in option set %d "
0095                      "from %#02x to 0x0A (1, 3)\n",
0096                      pnp_option_set(option), dma->map);
0097                 dma->map = 0x0A;
0098             }
0099         }
0100     }
0101 }
0102 
0103 static void quirk_sb16audio_resources(struct pnp_dev *dev)
0104 {
0105     struct pnp_option *option;
0106     unsigned int prev_option_flags = ~0, n = 0;
0107     struct pnp_port *port;
0108 
0109     /*
0110      * The default range on the OPL port for these devices is 0x388-0x388.
0111      * Here we increase that range so that two such cards can be
0112      * auto-configured.
0113      */
0114     list_for_each_entry(option, &dev->options, list) {
0115         if (prev_option_flags != option->flags) {
0116             prev_option_flags = option->flags;
0117             n = 0;
0118         }
0119 
0120         if (pnp_option_is_dependent(option) &&
0121             option->type == IORESOURCE_IO) {
0122             n++;
0123             port = &option->u.port;
0124             if (n == 3 && port->min == port->max) {
0125                 port->max += 0x70;
0126                 dev_info(&dev->dev, "increased option port "
0127                      "range from %#llx-%#llx to "
0128                      "%#llx-%#llx\n",
0129                      (unsigned long long) port->min,
0130                      (unsigned long long) port->min,
0131                      (unsigned long long) port->min,
0132                      (unsigned long long) port->max);
0133             }
0134         }
0135     }
0136 }
0137 
0138 static struct pnp_option *pnp_clone_dependent_set(struct pnp_dev *dev,
0139                           unsigned int set)
0140 {
0141     struct pnp_option *tail = NULL, *first_new_option = NULL;
0142     struct pnp_option *option, *new_option;
0143     unsigned int flags;
0144 
0145     list_for_each_entry(option, &dev->options, list) {
0146         if (pnp_option_is_dependent(option))
0147             tail = option;
0148     }
0149     if (!tail) {
0150         dev_err(&dev->dev, "no dependent option sets\n");
0151         return NULL;
0152     }
0153 
0154     flags = pnp_new_dependent_set(dev, PNP_RES_PRIORITY_FUNCTIONAL);
0155     list_for_each_entry(option, &dev->options, list) {
0156         if (pnp_option_is_dependent(option) &&
0157             pnp_option_set(option) == set) {
0158             new_option = kmalloc(sizeof(struct pnp_option),
0159                          GFP_KERNEL);
0160             if (!new_option) {
0161                 dev_err(&dev->dev, "couldn't clone dependent "
0162                     "set %d\n", set);
0163                 return NULL;
0164             }
0165 
0166             *new_option = *option;
0167             new_option->flags = flags;
0168             if (!first_new_option)
0169                 first_new_option = new_option;
0170 
0171             list_add(&new_option->list, &tail->list);
0172             tail = new_option;
0173         }
0174     }
0175 
0176     return first_new_option;
0177 }
0178 
0179 
0180 static void quirk_add_irq_optional_dependent_sets(struct pnp_dev *dev)
0181 {
0182     struct pnp_option *new_option;
0183     unsigned int num_sets, i, set;
0184     struct pnp_irq *irq;
0185 
0186     num_sets = dev->num_dependent_sets;
0187     for (i = 0; i < num_sets; i++) {
0188         new_option = pnp_clone_dependent_set(dev, i);
0189         if (!new_option)
0190             return;
0191 
0192         set = pnp_option_set(new_option);
0193         while (new_option && pnp_option_set(new_option) == set) {
0194             if (new_option->type == IORESOURCE_IRQ) {
0195                 irq = &new_option->u.irq;
0196                 irq->flags |= IORESOURCE_IRQ_OPTIONAL;
0197             }
0198             dbg_pnp_show_option(dev, new_option);
0199             new_option = list_entry(new_option->list.next,
0200                         struct pnp_option, list);
0201         }
0202 
0203         dev_info(&dev->dev, "added dependent option set %d (same as "
0204              "set %d except IRQ optional)\n", set, i);
0205     }
0206 }
0207 
0208 static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
0209 {
0210     struct pnp_option *option;
0211     struct pnp_irq *irq = NULL;
0212     unsigned int independent_irqs = 0;
0213 
0214     list_for_each_entry(option, &dev->options, list) {
0215         if (option->type == IORESOURCE_IRQ &&
0216             !pnp_option_is_dependent(option)) {
0217             independent_irqs++;
0218             irq = &option->u.irq;
0219         }
0220     }
0221 
0222     if (independent_irqs != 1)
0223         return;
0224 
0225     irq->flags |= IORESOURCE_IRQ_OPTIONAL;
0226     dev_info(&dev->dev, "made independent IRQ optional\n");
0227 }
0228 
0229 static void quirk_system_pci_resources(struct pnp_dev *dev)
0230 {
0231     struct pci_dev *pdev = NULL;
0232     struct resource *res;
0233     resource_size_t pnp_start, pnp_end, pci_start, pci_end;
0234     int i, j;
0235 
0236     /*
0237      * Some BIOSes have PNP motherboard devices with resources that
0238      * partially overlap PCI BARs.  The PNP system driver claims these
0239      * motherboard resources, which prevents the normal PCI driver from
0240      * requesting them later.
0241      *
0242      * This patch disables the PNP resources that conflict with PCI BARs
0243      * so they won't be claimed by the PNP system driver.
0244      */
0245     for_each_pci_dev(pdev) {
0246         for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
0247             unsigned long flags, type;
0248 
0249             flags = pci_resource_flags(pdev, i);
0250             type = flags & (IORESOURCE_IO | IORESOURCE_MEM);
0251             if (!type || pci_resource_len(pdev, i) == 0)
0252                 continue;
0253 
0254             if (flags & IORESOURCE_UNSET)
0255                 continue;
0256 
0257             pci_start = pci_resource_start(pdev, i);
0258             pci_end = pci_resource_end(pdev, i);
0259             for (j = 0;
0260                  (res = pnp_get_resource(dev, type, j)); j++) {
0261                 if (res->start == 0 && res->end == 0)
0262                     continue;
0263 
0264                 pnp_start = res->start;
0265                 pnp_end = res->end;
0266 
0267                 /*
0268                  * If the PNP region doesn't overlap the PCI
0269                  * region at all, there's no problem.
0270                  */
0271                 if (pnp_end < pci_start || pnp_start > pci_end)
0272                     continue;
0273 
0274                 /*
0275                  * If the PNP region completely encloses (or is
0276                  * at least as large as) the PCI region, that's
0277                  * also OK.  For example, this happens when the
0278                  * PNP device describes a bridge with PCI
0279                  * behind it.
0280                  */
0281                 if (pnp_start <= pci_start &&
0282                     pnp_end >= pci_end)
0283                     continue;
0284 
0285                 /*
0286                  * Otherwise, the PNP region overlaps *part* of
0287                  * the PCI region, and that might prevent a PCI
0288                  * driver from requesting its resources.
0289                  */
0290                 dev_warn(&dev->dev,
0291                      "disabling %pR because it overlaps "
0292                      "%s BAR %d %pR\n", res,
0293                      pci_name(pdev), i, &pdev->resource[i]);
0294                 res->flags |= IORESOURCE_DISABLED;
0295             }
0296         }
0297     }
0298 }
0299 
0300 #ifdef CONFIG_AMD_NB
0301 
0302 #include <asm/amd_nb.h>
0303 
0304 static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
0305 {
0306     resource_size_t start, end;
0307     struct pnp_resource *pnp_res;
0308     struct resource *res;
0309     struct resource mmconfig_res, *mmconfig;
0310 
0311     mmconfig = amd_get_mmconfig_range(&mmconfig_res);
0312     if (!mmconfig)
0313         return;
0314 
0315     list_for_each_entry(pnp_res, &dev->resources, list) {
0316         res = &pnp_res->res;
0317         if (res->end < mmconfig->start || res->start > mmconfig->end ||
0318             (res->start == mmconfig->start && res->end == mmconfig->end))
0319             continue;
0320 
0321         dev_info(&dev->dev, FW_BUG
0322              "%pR covers only part of AMD MMCONFIG area %pR; adding more reservations\n",
0323              res, mmconfig);
0324         if (mmconfig->start < res->start) {
0325             start = mmconfig->start;
0326             end = res->start - 1;
0327             pnp_add_mem_resource(dev, start, end, 0);
0328         }
0329         if (mmconfig->end > res->end) {
0330             start = res->end + 1;
0331             end = mmconfig->end;
0332             pnp_add_mem_resource(dev, start, end, 0);
0333         }
0334         break;
0335     }
0336 }
0337 #endif
0338 
0339 #ifdef CONFIG_PCI
0340 /* Device IDs of parts that have 32KB MCH space */
0341 static const unsigned int mch_quirk_devices[] = {
0342     0x0154, /* Ivy Bridge */
0343     0x0a04, /* Haswell-ULT */
0344     0x0c00, /* Haswell */
0345     0x1604, /* Broadwell */
0346 };
0347 
0348 static struct pci_dev *get_intel_host(void)
0349 {
0350     int i;
0351     struct pci_dev *host;
0352 
0353     for (i = 0; i < ARRAY_SIZE(mch_quirk_devices); i++) {
0354         host = pci_get_device(PCI_VENDOR_ID_INTEL, mch_quirk_devices[i],
0355                       NULL);
0356         if (host)
0357             return host;
0358     }
0359     return NULL;
0360 }
0361 
0362 static void quirk_intel_mch(struct pnp_dev *dev)
0363 {
0364     struct pci_dev *host;
0365     u32 addr_lo, addr_hi;
0366     struct pci_bus_region region;
0367     struct resource mch;
0368     struct pnp_resource *pnp_res;
0369     struct resource *res;
0370 
0371     host = get_intel_host();
0372     if (!host)
0373         return;
0374 
0375     /*
0376      * MCHBAR is not an architected PCI BAR, so MCH space is usually
0377      * reported as a PNP0C02 resource.  The MCH space was originally
0378      * 16KB, but is 32KB in newer parts.  Some BIOSes still report a
0379      * PNP0C02 resource that is only 16KB, which means the rest of the
0380      * MCH space is consumed but unreported.
0381      */
0382 
0383     /*
0384      * Read MCHBAR for Host Member Mapped Register Range Base
0385      * https://www-ssl.intel.com/content/www/us/en/processors/core/4th-gen-core-family-desktop-vol-2-datasheet
0386      * Sec 3.1.12.
0387      */
0388     pci_read_config_dword(host, 0x48, &addr_lo);
0389     region.start = addr_lo & ~0x7fff;
0390     pci_read_config_dword(host, 0x4c, &addr_hi);
0391     region.start |= (u64) addr_hi << 32;
0392     region.end = region.start + 32*1024 - 1;
0393 
0394     memset(&mch, 0, sizeof(mch));
0395     mch.flags = IORESOURCE_MEM;
0396     pcibios_bus_to_resource(host->bus, &mch, &region);
0397 
0398     list_for_each_entry(pnp_res, &dev->resources, list) {
0399         res = &pnp_res->res;
0400         if (res->end < mch.start || res->start > mch.end)
0401             continue;   /* no overlap */
0402         if (res->start == mch.start && res->end == mch.end)
0403             continue;   /* exact match */
0404 
0405         dev_info(&dev->dev, FW_BUG "PNP resource %pR covers only part of %s Intel MCH; extending to %pR\n",
0406              res, pci_name(host), &mch);
0407         res->start = mch.start;
0408         res->end = mch.end;
0409         break;
0410     }
0411 
0412     pci_dev_put(host);
0413 }
0414 #endif
0415 
0416 /*
0417  *  PnP Quirks
0418  *  Cards or devices that need some tweaking due to incomplete resource info
0419  */
0420 
0421 static struct pnp_fixup pnp_fixups[] = {
0422     /* Soundblaster awe io port quirk */
0423     {"CTL0021", quirk_awe32_resources},
0424     {"CTL0022", quirk_awe32_resources},
0425     {"CTL0023", quirk_awe32_resources},
0426     /* CMI 8330 interrupt and dma fix */
0427     {"@X@0001", quirk_cmi8330_resources},
0428     /* Soundblaster audio device io port range quirk */
0429     {"CTL0001", quirk_sb16audio_resources},
0430     {"CTL0031", quirk_sb16audio_resources},
0431     {"CTL0041", quirk_sb16audio_resources},
0432     {"CTL0042", quirk_sb16audio_resources},
0433     {"CTL0043", quirk_sb16audio_resources},
0434     {"CTL0044", quirk_sb16audio_resources},
0435     {"CTL0045", quirk_sb16audio_resources},
0436     /* Add IRQ-optional MPU options */
0437     {"ADS7151", quirk_ad1815_mpu_resources},
0438     {"ADS7181", quirk_add_irq_optional_dependent_sets},
0439     {"AZT0002", quirk_add_irq_optional_dependent_sets},
0440     /* PnP resources that might overlap PCI BARs */
0441     {"PNP0c01", quirk_system_pci_resources},
0442     {"PNP0c02", quirk_system_pci_resources},
0443 #ifdef CONFIG_AMD_NB
0444     {"PNP0c01", quirk_amd_mmconfig_area},
0445 #endif
0446 #ifdef CONFIG_PCI
0447     {"PNP0c02", quirk_intel_mch},
0448 #endif
0449     {""}
0450 };
0451 
0452 void pnp_fixup_device(struct pnp_dev *dev)
0453 {
0454     struct pnp_fixup *f;
0455 
0456     for (f = pnp_fixups; *f->id; f++) {
0457         if (!compare_pnp_id(dev->id, f->id))
0458             continue;
0459         pnp_dbg(&dev->dev, "%s: calling %pS\n", f->id,
0460             f->quirk_function);
0461         f->quirk_function(dev);
0462     }
0463 }