Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (C) 2004, 2006  MIPS Technologies, Inc.  All rights reserved.
0004  *      Author: Maciej W. Rozycki <macro@mips.com>
0005  *  Copyright (C) 2018  Maciej W. Rozycki
0006  */
0007 
0008 #include <linux/dma-mapping.h>
0009 #include <linux/pci.h>
0010 
0011 /*
0012  * Set the BCM1250, etc. PCI host bridge's TRDY timeout
0013  * to the finite max.
0014  */
0015 static void quirk_sb1250_pci(struct pci_dev *dev)
0016 {
0017     pci_write_config_byte(dev, 0x40, 0xff);
0018 }
0019 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_PCI,
0020             quirk_sb1250_pci);
0021 
0022 /*
0023  * The BCM1250, etc. PCI host bridge does not support DAC on its 32-bit
0024  * bus, so we set the bus's DMA limit accordingly.  However the HT link
0025  * down the artificial PCI-HT bridge supports 40-bit addressing and the
0026  * SP1011 HT-PCI bridge downstream supports both DAC and a 64-bit bus
0027  * width, so we record the PCI-HT bridge's secondary and subordinate bus
0028  * numbers and do not set the limit for devices present in the inclusive
0029  * range of those.
0030  */
0031 struct sb1250_bus_dma_limit_exclude {
0032     bool set;
0033     unsigned char start;
0034     unsigned char end;
0035 };
0036 
0037 static int sb1250_bus_dma_limit(struct pci_dev *dev, void *data)
0038 {
0039     struct sb1250_bus_dma_limit_exclude *exclude = data;
0040     bool exclude_this;
0041     bool ht_bridge;
0042 
0043     exclude_this = exclude->set && (dev->bus->number >= exclude->start &&
0044                     dev->bus->number <= exclude->end);
0045     ht_bridge = !exclude->set && (dev->vendor == PCI_VENDOR_ID_SIBYTE &&
0046                       dev->device == PCI_DEVICE_ID_BCM1250_HT);
0047 
0048     if (exclude_this) {
0049         dev_dbg(&dev->dev, "not disabling DAC for device");
0050     } else if (ht_bridge) {
0051         exclude->start = dev->subordinate->number;
0052         exclude->end = pci_bus_max_busnr(dev->subordinate);
0053         exclude->set = true;
0054         dev_dbg(&dev->dev, "not disabling DAC for [bus %02x-%02x]",
0055             exclude->start, exclude->end);
0056     } else {
0057         dev_dbg(&dev->dev, "disabling DAC for device");
0058         dev->dev.bus_dma_limit = DMA_BIT_MASK(32);
0059     }
0060 
0061     return 0;
0062 }
0063 
0064 static void quirk_sb1250_pci_dac(struct pci_dev *dev)
0065 {
0066     struct sb1250_bus_dma_limit_exclude exclude = { .set = false };
0067 
0068     pci_walk_bus(dev->bus, sb1250_bus_dma_limit, &exclude);
0069 }
0070 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_PCI,
0071             quirk_sb1250_pci_dac);
0072 
0073 /*
0074  * The BCM1250, etc. PCI/HT bridge reports as a host bridge.
0075  */
0076 static void quirk_sb1250_ht(struct pci_dev *dev)
0077 {
0078     dev->class = PCI_CLASS_BRIDGE_PCI_NORMAL;
0079 }
0080 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT,
0081             quirk_sb1250_ht);
0082 
0083 /*
0084  * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max.
0085  */
0086 static void quirk_sp1011(struct pci_dev *dev)
0087 {
0088     pci_write_config_byte(dev, 0x64, 0xff);
0089 }
0090 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIPACKETS, PCI_DEVICE_ID_SP1011,
0091             quirk_sp1011);