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