1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2004 ICT CAS |
4 | * Author: Li xiaoyu, ICT CAS |
5 | * lixy@ict.ac.cn |
6 | * |
7 | * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology |
8 | * Author: Fuxin Zhang, zhangfx@lemote.com |
9 | */ |
10 | #include <linux/init.h> |
11 | #include <linux/pci.h> |
12 | |
13 | #include <loongson.h> |
14 | |
15 | /* South bridge slot number is set by the pci probe process */ |
16 | static u8 sb_slot = 5; |
17 | |
18 | int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
19 | { |
20 | int irq = 0; |
21 | |
22 | if (slot == sb_slot) { |
23 | switch (PCI_FUNC(dev->devfn)) { |
24 | case 2: |
25 | irq = 10; |
26 | break; |
27 | case 3: |
28 | irq = 11; |
29 | break; |
30 | case 5: |
31 | irq = 9; |
32 | break; |
33 | } |
34 | } else { |
35 | irq = LOONGSON_IRQ_BASE + 25 + pin; |
36 | } |
37 | return irq; |
38 | |
39 | } |
40 | |
41 | /* Do platform specific device initialization at pci_enable_device() time */ |
42 | int pcibios_plat_dev_init(struct pci_dev *dev) |
43 | { |
44 | return 0; |
45 | } |
46 | |
47 | static void loongson2e_nec_fixup(struct pci_dev *pdev) |
48 | { |
49 | unsigned int val; |
50 | |
51 | /* Configures port 1, 2, 3, 4 to be validate*/ |
52 | pci_read_config_dword(dev: pdev, where: 0xe0, val: &val); |
53 | pci_write_config_dword(dev: pdev, where: 0xe0, val: (val & ~7) | 0x4); |
54 | |
55 | /* System clock is 48-MHz Oscillator. */ |
56 | pci_write_config_dword(dev: pdev, where: 0xe4, val: 1 << 5); |
57 | } |
58 | |
59 | static void loongson2e_686b_func0_fixup(struct pci_dev *pdev) |
60 | { |
61 | unsigned char c; |
62 | |
63 | sb_slot = PCI_SLOT(pdev->devfn); |
64 | |
65 | printk(KERN_INFO "via686b fix: ISA bridge\n" ); |
66 | |
67 | /* Enable I/O Recovery time */ |
68 | pci_write_config_byte(dev: pdev, where: 0x40, val: 0x08); |
69 | |
70 | /* Enable ISA refresh */ |
71 | pci_write_config_byte(dev: pdev, where: 0x41, val: 0x01); |
72 | |
73 | /* disable ISA line buffer */ |
74 | pci_write_config_byte(dev: pdev, where: 0x45, val: 0x00); |
75 | |
76 | /* Gate INTR, and flush line buffer */ |
77 | pci_write_config_byte(dev: pdev, where: 0x46, val: 0xe0); |
78 | |
79 | /* Disable PCI Delay Transaction, Enable EISA ports 4D0/4D1. */ |
80 | /* pci_write_config_byte(pdev, 0x47, 0x20); */ |
81 | |
82 | /* |
83 | * enable PCI Delay Transaction, Enable EISA ports 4D0/4D1. |
84 | * enable time-out timer |
85 | */ |
86 | pci_write_config_byte(dev: pdev, where: 0x47, val: 0xe6); |
87 | |
88 | /* |
89 | * enable level trigger on pci irqs: 9,10,11,13 |
90 | * important! without this PCI interrupts won't work |
91 | */ |
92 | outb(value: 0x2e, port: 0x4d1); |
93 | |
94 | /* 512 K PCI Decode */ |
95 | pci_write_config_byte(dev: pdev, where: 0x48, val: 0x01); |
96 | |
97 | /* Wait for PGNT before grant to ISA Master/DMA */ |
98 | pci_write_config_byte(dev: pdev, where: 0x4a, val: 0x84); |
99 | |
100 | /* |
101 | * Plug'n'Play |
102 | * |
103 | * Parallel DRQ 3, Floppy DRQ 2 (default) |
104 | */ |
105 | pci_write_config_byte(dev: pdev, where: 0x50, val: 0x0e); |
106 | |
107 | /* |
108 | * IRQ Routing for Floppy and Parallel port |
109 | * |
110 | * IRQ 6 for floppy, IRQ 7 for parallel port |
111 | */ |
112 | pci_write_config_byte(dev: pdev, where: 0x51, val: 0x76); |
113 | |
114 | /* IRQ Routing for serial ports (take IRQ 3 and 4) */ |
115 | pci_write_config_byte(dev: pdev, where: 0x52, val: 0x34); |
116 | |
117 | /* All IRQ's level triggered. */ |
118 | pci_write_config_byte(dev: pdev, where: 0x54, val: 0x00); |
119 | |
120 | /* route PIRQA-D irq */ |
121 | pci_write_config_byte(dev: pdev, where: 0x55, val: 0x90); /* bit 7-4, PIRQA */ |
122 | pci_write_config_byte(dev: pdev, where: 0x56, val: 0xba); /* bit 7-4, PIRQC; */ |
123 | /* 3-0, PIRQB */ |
124 | pci_write_config_byte(dev: pdev, where: 0x57, val: 0xd0); /* bit 7-4, PIRQD */ |
125 | |
126 | /* enable function 5/6, audio/modem */ |
127 | pci_read_config_byte(dev: pdev, where: 0x85, val: &c); |
128 | c &= ~(0x3 << 2); |
129 | pci_write_config_byte(dev: pdev, where: 0x85, val: c); |
130 | |
131 | printk(KERN_INFO"via686b fix: ISA bridge done\n" ); |
132 | } |
133 | |
134 | static void loongson2e_686b_func1_fixup(struct pci_dev *pdev) |
135 | { |
136 | printk(KERN_INFO"via686b fix: IDE\n" ); |
137 | |
138 | /* Modify IDE controller setup */ |
139 | pci_write_config_byte(dev: pdev, PCI_LATENCY_TIMER, val: 48); |
140 | pci_write_config_byte(dev: pdev, PCI_COMMAND, |
141 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | |
142 | PCI_COMMAND_MASTER); |
143 | pci_write_config_byte(dev: pdev, where: 0x40, val: 0x0b); |
144 | /* legacy mode */ |
145 | pci_write_config_byte(dev: pdev, where: 0x42, val: 0x09); |
146 | |
147 | #if 1/* play safe, otherwise we may see notebook's usb keyboard lockup */ |
148 | /* disable read prefetch/write post buffers */ |
149 | pci_write_config_byte(dev: pdev, where: 0x41, val: 0x02); |
150 | |
151 | /* use 3/4 as fifo thresh hold */ |
152 | pci_write_config_byte(dev: pdev, where: 0x43, val: 0x0a); |
153 | pci_write_config_byte(dev: pdev, where: 0x44, val: 0x00); |
154 | |
155 | pci_write_config_byte(dev: pdev, where: 0x45, val: 0x00); |
156 | #else |
157 | pci_write_config_byte(pdev, 0x41, 0xc2); |
158 | pci_write_config_byte(pdev, 0x43, 0x35); |
159 | pci_write_config_byte(pdev, 0x44, 0x1c); |
160 | |
161 | pci_write_config_byte(pdev, 0x45, 0x10); |
162 | #endif |
163 | |
164 | printk(KERN_INFO"via686b fix: IDE done\n" ); |
165 | } |
166 | |
167 | static void loongson2e_686b_func2_fixup(struct pci_dev *pdev) |
168 | { |
169 | /* irq routing */ |
170 | pci_write_config_byte(dev: pdev, PCI_INTERRUPT_LINE, val: 10); |
171 | } |
172 | |
173 | static void loongson2e_686b_func3_fixup(struct pci_dev *pdev) |
174 | { |
175 | /* irq routing */ |
176 | pci_write_config_byte(dev: pdev, PCI_INTERRUPT_LINE, val: 11); |
177 | } |
178 | |
179 | static void loongson2e_686b_func5_fixup(struct pci_dev *pdev) |
180 | { |
181 | unsigned int val; |
182 | unsigned char c; |
183 | |
184 | /* enable IO */ |
185 | pci_write_config_byte(dev: pdev, PCI_COMMAND, |
186 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | |
187 | PCI_COMMAND_MASTER); |
188 | pci_read_config_dword(dev: pdev, where: 0x4, val: &val); |
189 | pci_write_config_dword(dev: pdev, where: 0x4, val: val | 1); |
190 | |
191 | /* route ac97 IRQ */ |
192 | pci_write_config_byte(dev: pdev, where: 0x3c, val: 9); |
193 | |
194 | pci_read_config_byte(dev: pdev, where: 0x8, val: &c); |
195 | |
196 | /* link control: enable link & SGD PCM output */ |
197 | pci_write_config_byte(dev: pdev, where: 0x41, val: 0xcc); |
198 | |
199 | /* disable game port, FM, midi, sb, enable write to reg2c-2f */ |
200 | pci_write_config_byte(dev: pdev, where: 0x42, val: 0x20); |
201 | |
202 | /* we are using Avance logic codec */ |
203 | pci_write_config_word(dev: pdev, where: 0x2c, val: 0x1005); |
204 | pci_write_config_word(dev: pdev, where: 0x2e, val: 0x4710); |
205 | pci_read_config_dword(dev: pdev, where: 0x2c, val: &val); |
206 | |
207 | pci_write_config_byte(dev: pdev, where: 0x42, val: 0x0); |
208 | } |
209 | |
210 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, |
211 | loongson2e_686b_func0_fixup); |
212 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, |
213 | loongson2e_686b_func1_fixup); |
214 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, |
215 | loongson2e_686b_func2_fixup); |
216 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, |
217 | loongson2e_686b_func3_fixup); |
218 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, |
219 | loongson2e_686b_func5_fixup); |
220 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, |
221 | loongson2e_nec_fixup); |
222 | |