1 /* 2 * Copyright (C) 2004, 2006 MIPS Technologies, Inc. All rights reserved. 3 * Author: Maciej W. Rozycki <macro@mips.com> 4 * Copyright (C) 2018 Maciej W. Rozycki 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #include <linux/dma-mapping.h> 13 #include <linux/pci.h> 14 15 /* 16 * Set the BCM1250, etc. PCI host bridge's TRDY timeout 17 * to the finite max. 18 */ 19 static void quirk_sb1250_pci(struct pci_dev *dev) 20 { 21 pci_write_config_byte(dev, 0x40, 0xff); 22 } 23 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_PCI, 24 quirk_sb1250_pci); 25 26 /* 27 * The BCM1250, etc. PCI host bridge does not support DAC on its 32-bit 28 * bus, so we set the bus's DMA mask accordingly. However the HT link 29 * down the artificial PCI-HT bridge supports 40-bit addressing and the 30 * SP1011 HT-PCI bridge downstream supports both DAC and a 64-bit bus 31 * width, so we record the PCI-HT bridge's secondary and subordinate bus 32 * numbers and do not set the mask for devices present in the inclusive 33 * range of those. 34 */ 35 struct sb1250_bus_dma_mask_exclude { 36 bool set; 37 unsigned char start; 38 unsigned char end; 39 }; 40 41 static int sb1250_bus_dma_mask(struct pci_dev *dev, void *data) 42 { 43 struct sb1250_bus_dma_mask_exclude *exclude = data; 44 bool exclude_this; 45 bool ht_bridge; 46 47 exclude_this = exclude->set && (dev->bus->number >= exclude->start && 48 dev->bus->number <= exclude->end); 49 ht_bridge = !exclude->set && (dev->vendor == PCI_VENDOR_ID_SIBYTE && 50 dev->device == PCI_DEVICE_ID_BCM1250_HT); 51 52 if (exclude_this) { 53 dev_dbg(&dev->dev, "not disabling DAC for device"); 54 } else if (ht_bridge) { 55 exclude->start = dev->subordinate->number; 56 exclude->end = pci_bus_max_busnr(dev->subordinate); 57 exclude->set = true; 58 dev_dbg(&dev->dev, "not disabling DAC for [bus %02x-%02x]", 59 exclude->start, exclude->end); 60 } else { 61 dev_dbg(&dev->dev, "disabling DAC for device"); 62 dev->dev.bus_dma_mask = DMA_BIT_MASK(32); 63 } 64 65 return 0; 66 } 67 68 static void quirk_sb1250_pci_dac(struct pci_dev *dev) 69 { 70 struct sb1250_bus_dma_mask_exclude exclude = { .set = false }; 71 72 pci_walk_bus(dev->bus, sb1250_bus_dma_mask, &exclude); 73 } 74 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_PCI, 75 quirk_sb1250_pci_dac); 76 77 /* 78 * The BCM1250, etc. PCI/HT bridge reports as a host bridge. 79 */ 80 static void quirk_sb1250_ht(struct pci_dev *dev) 81 { 82 dev->class = PCI_CLASS_BRIDGE_PCI << 8; 83 } 84 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT, 85 quirk_sb1250_ht); 86 87 /* 88 * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max. 89 */ 90 static void quirk_sp1011(struct pci_dev *dev) 91 { 92 pci_write_config_byte(dev, 0x64, 0xff); 93 } 94 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIPACKETS, PCI_DEVICE_ID_SP1011, 95 quirk_sp1011); 96