|
5 | 5 | #include <linux/kernel.h> |
6 | 6 | #include <linux/init.h> |
7 | 7 | #include <linux/acpi.h> |
| 8 | +#include <linux/delay.h> |
8 | 9 | #include <linux/types.h> |
9 | 10 | #include <linux/pci.h> |
10 | 11 | #include <linux/vgaarb.h> |
| 12 | +#include <linux/io-64-nonatomic-lo-hi.h> |
11 | 13 | #include <asm/cacheflush.h> |
12 | 14 | #include <asm/loongson.h> |
13 | 15 |
|
14 | 16 | #define PCI_DEVICE_ID_LOONGSON_HOST 0x7a00 |
15 | 17 | #define PCI_DEVICE_ID_LOONGSON_DC1 0x7a06 |
16 | 18 | #define PCI_DEVICE_ID_LOONGSON_DC2 0x7a36 |
17 | 19 | #define PCI_DEVICE_ID_LOONGSON_DC3 0x7a46 |
| 20 | +#define PCI_DEVICE_ID_LOONGSON_GPU1 0x7a15 |
| 21 | +#define PCI_DEVICE_ID_LOONGSON_GPU2 0x7a25 |
| 22 | +#define PCI_DEVICE_ID_LOONGSON_GPU3 0x7a35 |
18 | 23 |
|
19 | 24 | int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, |
20 | 25 | int reg, int len, u32 *val) |
@@ -99,3 +104,78 @@ static void pci_fixup_vgadev(struct pci_dev *pdev) |
99 | 104 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC1, pci_fixup_vgadev); |
100 | 105 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC2, pci_fixup_vgadev); |
101 | 106 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_DC3, pci_fixup_vgadev); |
| 107 | + |
| 108 | +#define CRTC_NUM_MAX 2 |
| 109 | +#define CRTC_OUTPUT_ENABLE 0x100 |
| 110 | + |
| 111 | +static void loongson_gpu_fixup_dma_hang(struct pci_dev *pdev, bool on) |
| 112 | +{ |
| 113 | + u32 i, val, count, crtc_offset, device; |
| 114 | + void __iomem *crtc_reg, *base, *regbase; |
| 115 | + static u32 crtc_status[CRTC_NUM_MAX] = { 0 }; |
| 116 | + |
| 117 | + base = pdev->bus->ops->map_bus(pdev->bus, pdev->devfn + 1, 0); |
| 118 | + device = readw(base + PCI_DEVICE_ID); |
| 119 | + |
| 120 | + regbase = ioremap(readq(base + PCI_BASE_ADDRESS_0) & ~0xffull, SZ_64K); |
| 121 | + if (!regbase) { |
| 122 | + pci_err(pdev, "Failed to ioremap()\n"); |
| 123 | + return; |
| 124 | + } |
| 125 | + |
| 126 | + switch (device) { |
| 127 | + case PCI_DEVICE_ID_LOONGSON_DC2: |
| 128 | + crtc_reg = regbase + 0x1240; |
| 129 | + crtc_offset = 0x10; |
| 130 | + break; |
| 131 | + case PCI_DEVICE_ID_LOONGSON_DC3: |
| 132 | + crtc_reg = regbase; |
| 133 | + crtc_offset = 0x400; |
| 134 | + break; |
| 135 | + } |
| 136 | + |
| 137 | + for (i = 0; i < CRTC_NUM_MAX; i++, crtc_reg += crtc_offset) { |
| 138 | + val = readl(crtc_reg); |
| 139 | + |
| 140 | + if (!on) |
| 141 | + crtc_status[i] = val; |
| 142 | + |
| 143 | + /* No need to fixup if the status is off at startup. */ |
| 144 | + if (!(crtc_status[i] & CRTC_OUTPUT_ENABLE)) |
| 145 | + continue; |
| 146 | + |
| 147 | + if (on) |
| 148 | + val |= CRTC_OUTPUT_ENABLE; |
| 149 | + else |
| 150 | + val &= ~CRTC_OUTPUT_ENABLE; |
| 151 | + |
| 152 | + mb(); |
| 153 | + writel(val, crtc_reg); |
| 154 | + |
| 155 | + for (count = 0; count < 40; count++) { |
| 156 | + val = readl(crtc_reg) & CRTC_OUTPUT_ENABLE; |
| 157 | + if ((on && val) || (!on && !val)) |
| 158 | + break; |
| 159 | + udelay(1000); |
| 160 | + } |
| 161 | + |
| 162 | + pci_info(pdev, "DMA hang fixup at reg[0x%lx]: 0x%x\n", |
| 163 | + (unsigned long)crtc_reg & 0xffff, readl(crtc_reg)); |
| 164 | + } |
| 165 | + |
| 166 | + iounmap(regbase); |
| 167 | +} |
| 168 | + |
| 169 | +static void pci_fixup_dma_hang_early(struct pci_dev *pdev) |
| 170 | +{ |
| 171 | + loongson_gpu_fixup_dma_hang(pdev, false); |
| 172 | +} |
| 173 | +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU2, pci_fixup_dma_hang_early); |
| 174 | +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU3, pci_fixup_dma_hang_early); |
| 175 | + |
| 176 | +static void pci_fixup_dma_hang_final(struct pci_dev *pdev) |
| 177 | +{ |
| 178 | + loongson_gpu_fixup_dma_hang(pdev, true); |
| 179 | +} |
| 180 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU2, pci_fixup_dma_hang_final); |
| 181 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LOONGSON, PCI_DEVICE_ID_LOONGSON_GPU3, pci_fixup_dma_hang_final); |
0 commit comments