diff options
Diffstat (limited to 'drivers/ide/sis5513.c')
-rw-r--r-- | drivers/ide/sis5513.c | 641 |
1 files changed, 641 insertions, 0 deletions
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c new file mode 100644 index 000000000000..ad32e18c5ba3 --- /dev/null +++ b/drivers/ide/sis5513.c | |||
@@ -0,0 +1,641 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> | ||
3 | * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer | ||
4 | * Copyright (C) 2003 Vojtech Pavlik <vojtech@suse.cz> | ||
5 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | ||
6 | * | ||
7 | * May be copied or modified under the terms of the GNU General Public License | ||
8 | * | ||
9 | * | ||
10 | * Thanks : | ||
11 | * | ||
12 | * SiS Taiwan : for direct support and hardware. | ||
13 | * Daniela Engert : for initial ATA100 advices and numerous others. | ||
14 | * John Fremlin, Manfred Spraul, Dave Morgan, Peter Kjellerstedt : | ||
15 | * for checking code correctness, providing patches. | ||
16 | * | ||
17 | * | ||
18 | * Original tests and design on the SiS620 chipset. | ||
19 | * ATA100 tests and design on the SiS735 chipset. | ||
20 | * ATA16/33 support from specs | ||
21 | * ATA133 support for SiS961/962 by L.C. Chang <lcchang@sis.com.tw> | ||
22 | * ATA133 961/962/963 fixes by Vojtech Pavlik <vojtech@suse.cz> | ||
23 | * | ||
24 | * Documentation: | ||
25 | * SiS chipset documentation available under NDA to companies only | ||
26 | * (not to individuals). | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * The original SiS5513 comes from a SiS5511/55112/5513 chipset. The original | ||
31 | * SiS5513 was also used in the SiS5596/5513 chipset. Thus if we see a SiS5511 | ||
32 | * or SiS5596, we can assume we see the first MWDMA-16 capable SiS5513 chip. | ||
33 | * | ||
34 | * Later SiS chipsets integrated the 5513 functionality into the NorthBridge, | ||
35 | * starting with SiS5571 and up to SiS745. The PCI ID didn't change, though. We | ||
36 | * can figure out that we have a more modern and more capable 5513 by looking | ||
37 | * for the respective NorthBridge IDs. | ||
38 | * | ||
39 | * Even later (96x family) SiS chipsets use the MuTIOL link and place the 5513 | ||
40 | * into the SouthBrige. Here we cannot rely on looking up the NorthBridge PCI | ||
41 | * ID, while the now ATA-133 capable 5513 still has the same PCI ID. | ||
42 | * Fortunately the 5513 can be 'unmasked' by fiddling with some config space | ||
43 | * bits, changing its device id to the true one - 5517 for 961 and 5518 for | ||
44 | * 962/963. | ||
45 | */ | ||
46 | |||
47 | #include <linux/types.h> | ||
48 | #include <linux/module.h> | ||
49 | #include <linux/kernel.h> | ||
50 | #include <linux/pci.h> | ||
51 | #include <linux/init.h> | ||
52 | #include <linux/ide.h> | ||
53 | |||
54 | #define DRV_NAME "sis5513" | ||
55 | |||
56 | /* registers layout and init values are chipset family dependant */ | ||
57 | |||
58 | #define ATA_16 0x01 | ||
59 | #define ATA_33 0x02 | ||
60 | #define ATA_66 0x03 | ||
61 | #define ATA_100a 0x04 /* SiS730/SiS550 is ATA100 with ATA66 layout */ | ||
62 | #define ATA_100 0x05 | ||
63 | #define ATA_133a 0x06 /* SiS961b with 133 support */ | ||
64 | #define ATA_133 0x07 /* SiS962/963 */ | ||
65 | |||
66 | static u8 chipset_family; | ||
67 | |||
68 | /* | ||
69 | * Devices supported | ||
70 | */ | ||
71 | static const struct { | ||
72 | const char *name; | ||
73 | u16 host_id; | ||
74 | u8 chipset_family; | ||
75 | u8 flags; | ||
76 | } SiSHostChipInfo[] = { | ||
77 | { "SiS968", PCI_DEVICE_ID_SI_968, ATA_133 }, | ||
78 | { "SiS966", PCI_DEVICE_ID_SI_966, ATA_133 }, | ||
79 | { "SiS965", PCI_DEVICE_ID_SI_965, ATA_133 }, | ||
80 | { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100 }, | ||
81 | { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100 }, | ||
82 | { "SiS733", PCI_DEVICE_ID_SI_733, ATA_100 }, | ||
83 | { "SiS635", PCI_DEVICE_ID_SI_635, ATA_100 }, | ||
84 | { "SiS633", PCI_DEVICE_ID_SI_633, ATA_100 }, | ||
85 | |||
86 | { "SiS730", PCI_DEVICE_ID_SI_730, ATA_100a }, | ||
87 | { "SiS550", PCI_DEVICE_ID_SI_550, ATA_100a }, | ||
88 | |||
89 | { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66 }, | ||
90 | { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66 }, | ||
91 | { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66 }, | ||
92 | { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66 }, | ||
93 | { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66 }, | ||
94 | |||
95 | { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33 }, | ||
96 | { "SiS5598", PCI_DEVICE_ID_SI_5598, ATA_33 }, | ||
97 | { "SiS5597", PCI_DEVICE_ID_SI_5597, ATA_33 }, | ||
98 | { "SiS5591/2", PCI_DEVICE_ID_SI_5591, ATA_33 }, | ||
99 | { "SiS5582", PCI_DEVICE_ID_SI_5582, ATA_33 }, | ||
100 | { "SiS5581", PCI_DEVICE_ID_SI_5581, ATA_33 }, | ||
101 | |||
102 | { "SiS5596", PCI_DEVICE_ID_SI_5596, ATA_16 }, | ||
103 | { "SiS5571", PCI_DEVICE_ID_SI_5571, ATA_16 }, | ||
104 | { "SiS5517", PCI_DEVICE_ID_SI_5517, ATA_16 }, | ||
105 | { "SiS551x", PCI_DEVICE_ID_SI_5511, ATA_16 }, | ||
106 | }; | ||
107 | |||
108 | /* Cycle time bits and values vary across chip dma capabilities | ||
109 | These three arrays hold the register layout and the values to set. | ||
110 | Indexed by chipset_family and (dma_mode - XFER_UDMA_0) */ | ||
111 | |||
112 | /* {0, ATA_16, ATA_33, ATA_66, ATA_100a, ATA_100, ATA_133} */ | ||
113 | static u8 cycle_time_offset[] = { 0, 0, 5, 4, 4, 0, 0 }; | ||
114 | static u8 cycle_time_range[] = { 0, 0, 2, 3, 3, 4, 4 }; | ||
115 | static u8 cycle_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { | ||
116 | { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ | ||
117 | { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ | ||
118 | { 3, 2, 1, 0, 0, 0, 0 }, /* ATA_33 */ | ||
119 | { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_66 */ | ||
120 | { 7, 5, 3, 2, 1, 0, 0 }, /* ATA_100a (730 specific), | ||
121 | different cycle_time range and offset */ | ||
122 | { 11, 7, 5, 4, 2, 1, 0 }, /* ATA_100 */ | ||
123 | { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133a (earliest 691 southbridges) */ | ||
124 | { 15, 10, 7, 5, 3, 2, 1 }, /* ATA_133 */ | ||
125 | }; | ||
126 | /* CRC Valid Setup Time vary across IDE clock setting 33/66/100/133 | ||
127 | See SiS962 data sheet for more detail */ | ||
128 | static u8 cvs_time_value[][XFER_UDMA_6 - XFER_UDMA_0 + 1] = { | ||
129 | { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ | ||
130 | { 0, 0, 0, 0, 0, 0, 0 }, /* no UDMA */ | ||
131 | { 2, 1, 1, 0, 0, 0, 0 }, | ||
132 | { 4, 3, 2, 1, 0, 0, 0 }, | ||
133 | { 4, 3, 2, 1, 0, 0, 0 }, | ||
134 | { 6, 4, 3, 1, 1, 1, 0 }, | ||
135 | { 9, 6, 4, 2, 2, 2, 2 }, | ||
136 | { 9, 6, 4, 2, 2, 2, 2 }, | ||
137 | }; | ||
138 | /* Initialize time, Active time, Recovery time vary across | ||
139 | IDE clock settings. These 3 arrays hold the register value | ||
140 | for PIO0/1/2/3/4 and DMA0/1/2 mode in order */ | ||
141 | static u8 ini_time_value[][8] = { | ||
142 | { 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
143 | { 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
144 | { 2, 1, 0, 0, 0, 1, 0, 0 }, | ||
145 | { 4, 3, 1, 1, 1, 3, 1, 1 }, | ||
146 | { 4, 3, 1, 1, 1, 3, 1, 1 }, | ||
147 | { 6, 4, 2, 2, 2, 4, 2, 2 }, | ||
148 | { 9, 6, 3, 3, 3, 6, 3, 3 }, | ||
149 | { 9, 6, 3, 3, 3, 6, 3, 3 }, | ||
150 | }; | ||
151 | static u8 act_time_value[][8] = { | ||
152 | { 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
153 | { 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
154 | { 9, 9, 9, 2, 2, 7, 2, 2 }, | ||
155 | { 19, 19, 19, 5, 4, 14, 5, 4 }, | ||
156 | { 19, 19, 19, 5, 4, 14, 5, 4 }, | ||
157 | { 28, 28, 28, 7, 6, 21, 7, 6 }, | ||
158 | { 38, 38, 38, 10, 9, 28, 10, 9 }, | ||
159 | { 38, 38, 38, 10, 9, 28, 10, 9 }, | ||
160 | }; | ||
161 | static u8 rco_time_value[][8] = { | ||
162 | { 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
163 | { 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
164 | { 9, 2, 0, 2, 0, 7, 1, 1 }, | ||
165 | { 19, 5, 1, 5, 2, 16, 3, 2 }, | ||
166 | { 19, 5, 1, 5, 2, 16, 3, 2 }, | ||
167 | { 30, 9, 3, 9, 4, 25, 6, 4 }, | ||
168 | { 40, 12, 4, 12, 5, 34, 12, 5 }, | ||
169 | { 40, 12, 4, 12, 5, 34, 12, 5 }, | ||
170 | }; | ||
171 | |||
172 | /* | ||
173 | * Printing configuration | ||
174 | */ | ||
175 | /* Used for chipset type printing at boot time */ | ||
176 | static char *chipset_capability[] = { | ||
177 | "ATA", "ATA 16", | ||
178 | "ATA 33", "ATA 66", | ||
179 | "ATA 100 (1st gen)", "ATA 100 (2nd gen)", | ||
180 | "ATA 133 (1st gen)", "ATA 133 (2nd gen)" | ||
181 | }; | ||
182 | |||
183 | /* | ||
184 | * Configuration functions | ||
185 | */ | ||
186 | |||
187 | static u8 sis_ata133_get_base(ide_drive_t *drive) | ||
188 | { | ||
189 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
190 | u32 reg54 = 0; | ||
191 | |||
192 | pci_read_config_dword(dev, 0x54, ®54); | ||
193 | |||
194 | return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4; | ||
195 | } | ||
196 | |||
197 | static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode) | ||
198 | { | ||
199 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
200 | u16 t1 = 0; | ||
201 | u8 drive_pci = 0x40 + drive->dn * 2; | ||
202 | |||
203 | const u16 pio_timings[] = { 0x000, 0x607, 0x404, 0x303, 0x301 }; | ||
204 | const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 }; | ||
205 | |||
206 | pci_read_config_word(dev, drive_pci, &t1); | ||
207 | |||
208 | /* clear active/recovery timings */ | ||
209 | t1 &= ~0x070f; | ||
210 | if (mode >= XFER_MW_DMA_0) { | ||
211 | if (chipset_family > ATA_16) | ||
212 | t1 &= ~0x8000; /* disable UDMA */ | ||
213 | t1 |= mwdma_timings[mode - XFER_MW_DMA_0]; | ||
214 | } else | ||
215 | t1 |= pio_timings[mode - XFER_PIO_0]; | ||
216 | |||
217 | pci_write_config_word(dev, drive_pci, t1); | ||
218 | } | ||
219 | |||
220 | static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode) | ||
221 | { | ||
222 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
223 | u8 t1, drive_pci = 0x40 + drive->dn * 2; | ||
224 | |||
225 | /* timing bits: 7:4 active 3:0 recovery */ | ||
226 | const u8 pio_timings[] = { 0x00, 0x67, 0x44, 0x33, 0x31 }; | ||
227 | const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 }; | ||
228 | |||
229 | if (mode >= XFER_MW_DMA_0) { | ||
230 | u8 t2 = 0; | ||
231 | |||
232 | pci_read_config_byte(dev, drive_pci, &t2); | ||
233 | t2 &= ~0x80; /* disable UDMA */ | ||
234 | pci_write_config_byte(dev, drive_pci, t2); | ||
235 | |||
236 | t1 = mwdma_timings[mode - XFER_MW_DMA_0]; | ||
237 | } else | ||
238 | t1 = pio_timings[mode - XFER_PIO_0]; | ||
239 | |||
240 | pci_write_config_byte(dev, drive_pci + 1, t1); | ||
241 | } | ||
242 | |||
243 | static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode) | ||
244 | { | ||
245 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
246 | u32 t1 = 0; | ||
247 | u8 drive_pci = sis_ata133_get_base(drive), clk, idx; | ||
248 | |||
249 | pci_read_config_dword(dev, drive_pci, &t1); | ||
250 | |||
251 | t1 &= 0xc0c00fff; | ||
252 | clk = (t1 & 0x08) ? ATA_133 : ATA_100; | ||
253 | if (mode >= XFER_MW_DMA_0) { | ||
254 | t1 &= ~0x04; /* disable UDMA */ | ||
255 | idx = mode - XFER_MW_DMA_0 + 5; | ||
256 | } else | ||
257 | idx = mode - XFER_PIO_0; | ||
258 | t1 |= ini_time_value[clk][idx] << 12; | ||
259 | t1 |= act_time_value[clk][idx] << 16; | ||
260 | t1 |= rco_time_value[clk][idx] << 24; | ||
261 | |||
262 | pci_write_config_dword(dev, drive_pci, t1); | ||
263 | } | ||
264 | |||
265 | static void sis_program_timings(ide_drive_t *drive, const u8 mode) | ||
266 | { | ||
267 | if (chipset_family < ATA_100) /* ATA_16/33/66/100a */ | ||
268 | sis_ata16_program_timings(drive, mode); | ||
269 | else if (chipset_family < ATA_133) /* ATA_100/133a */ | ||
270 | sis_ata100_program_timings(drive, mode); | ||
271 | else /* ATA_133 */ | ||
272 | sis_ata133_program_timings(drive, mode); | ||
273 | } | ||
274 | |||
275 | static void config_drive_art_rwp(ide_drive_t *drive) | ||
276 | { | ||
277 | ide_hwif_t *hwif = HWIF(drive); | ||
278 | struct pci_dev *dev = to_pci_dev(hwif->dev); | ||
279 | u8 reg4bh = 0; | ||
280 | u8 rw_prefetch = 0; | ||
281 | |||
282 | pci_read_config_byte(dev, 0x4b, ®4bh); | ||
283 | |||
284 | if (drive->media == ide_disk) | ||
285 | rw_prefetch = 0x11 << drive->dn; | ||
286 | |||
287 | if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch) | ||
288 | pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); | ||
289 | } | ||
290 | |||
291 | static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) | ||
292 | { | ||
293 | config_drive_art_rwp(drive); | ||
294 | sis_program_timings(drive, XFER_PIO_0 + pio); | ||
295 | } | ||
296 | |||
297 | static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode) | ||
298 | { | ||
299 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
300 | u32 regdw = 0; | ||
301 | u8 drive_pci = sis_ata133_get_base(drive), clk, idx; | ||
302 | |||
303 | pci_read_config_dword(dev, drive_pci, ®dw); | ||
304 | |||
305 | regdw |= 0x04; | ||
306 | regdw &= 0xfffff00f; | ||
307 | /* check if ATA133 enable */ | ||
308 | clk = (regdw & 0x08) ? ATA_133 : ATA_100; | ||
309 | idx = mode - XFER_UDMA_0; | ||
310 | regdw |= cycle_time_value[clk][idx] << 4; | ||
311 | regdw |= cvs_time_value[clk][idx] << 8; | ||
312 | |||
313 | pci_write_config_dword(dev, drive_pci, regdw); | ||
314 | } | ||
315 | |||
316 | static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode) | ||
317 | { | ||
318 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
319 | u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family; | ||
320 | |||
321 | pci_read_config_byte(dev, drive_pci + 1, ®); | ||
322 | |||
323 | /* force the UDMA bit on if we want to use UDMA */ | ||
324 | reg |= 0x80; | ||
325 | /* clean reg cycle time bits */ | ||
326 | reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]); | ||
327 | /* set reg cycle time bits */ | ||
328 | reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i]; | ||
329 | |||
330 | pci_write_config_byte(dev, drive_pci + 1, reg); | ||
331 | } | ||
332 | |||
333 | static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode) | ||
334 | { | ||
335 | if (chipset_family >= ATA_133) /* ATA_133 */ | ||
336 | sis_ata133_program_udma_timings(drive, mode); | ||
337 | else /* ATA_33/66/100a/100/133a */ | ||
338 | sis_ata33_program_udma_timings(drive, mode); | ||
339 | } | ||
340 | |||
341 | static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) | ||
342 | { | ||
343 | if (speed >= XFER_UDMA_0) | ||
344 | sis_program_udma_timings(drive, speed); | ||
345 | else | ||
346 | sis_program_timings(drive, speed); | ||
347 | } | ||
348 | |||
349 | static u8 sis_ata133_udma_filter(ide_drive_t *drive) | ||
350 | { | ||
351 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | ||
352 | u32 regdw = 0; | ||
353 | u8 drive_pci = sis_ata133_get_base(drive); | ||
354 | |||
355 | pci_read_config_dword(dev, drive_pci, ®dw); | ||
356 | |||
357 | /* if ATA133 disable, we should not set speed above UDMA5 */ | ||
358 | return (regdw & 0x08) ? ATA_UDMA6 : ATA_UDMA5; | ||
359 | } | ||
360 | |||
361 | static int __devinit sis_find_family(struct pci_dev *dev) | ||
362 | { | ||
363 | struct pci_dev *host; | ||
364 | int i = 0; | ||
365 | |||
366 | chipset_family = 0; | ||
367 | |||
368 | for (i = 0; i < ARRAY_SIZE(SiSHostChipInfo) && !chipset_family; i++) { | ||
369 | |||
370 | host = pci_get_device(PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL); | ||
371 | |||
372 | if (!host) | ||
373 | continue; | ||
374 | |||
375 | chipset_family = SiSHostChipInfo[i].chipset_family; | ||
376 | |||
377 | /* Special case for SiS630 : 630S/ET is ATA_100a */ | ||
378 | if (SiSHostChipInfo[i].host_id == PCI_DEVICE_ID_SI_630) { | ||
379 | if (host->revision >= 0x30) | ||
380 | chipset_family = ATA_100a; | ||
381 | } | ||
382 | pci_dev_put(host); | ||
383 | |||
384 | printk(KERN_INFO DRV_NAME " %s: %s %s controller\n", | ||
385 | pci_name(dev), SiSHostChipInfo[i].name, | ||
386 | chipset_capability[chipset_family]); | ||
387 | } | ||
388 | |||
389 | if (!chipset_family) { /* Belongs to pci-quirks */ | ||
390 | |||
391 | u32 idemisc; | ||
392 | u16 trueid; | ||
393 | |||
394 | /* Disable ID masking and register remapping */ | ||
395 | pci_read_config_dword(dev, 0x54, &idemisc); | ||
396 | pci_write_config_dword(dev, 0x54, (idemisc & 0x7fffffff)); | ||
397 | pci_read_config_word(dev, PCI_DEVICE_ID, &trueid); | ||
398 | pci_write_config_dword(dev, 0x54, idemisc); | ||
399 | |||
400 | if (trueid == 0x5518) { | ||
401 | printk(KERN_INFO DRV_NAME " %s: SiS 962/963 MuTIOL IDE UDMA133 controller\n", | ||
402 | pci_name(dev)); | ||
403 | chipset_family = ATA_133; | ||
404 | |||
405 | /* Check for 5513 compability mapping | ||
406 | * We must use this, else the port enabled code will fail, | ||
407 | * as it expects the enablebits at 0x4a. | ||
408 | */ | ||
409 | if ((idemisc & 0x40000000) == 0) { | ||
410 | pci_write_config_dword(dev, 0x54, idemisc | 0x40000000); | ||
411 | printk(KERN_INFO DRV_NAME " %s: Switching to 5513 register mapping\n", | ||
412 | pci_name(dev)); | ||
413 | } | ||
414 | } | ||
415 | } | ||
416 | |||
417 | if (!chipset_family) { /* Belongs to pci-quirks */ | ||
418 | |||
419 | struct pci_dev *lpc_bridge; | ||
420 | u16 trueid; | ||
421 | u8 prefctl; | ||
422 | u8 idecfg; | ||
423 | |||
424 | pci_read_config_byte(dev, 0x4a, &idecfg); | ||
425 | pci_write_config_byte(dev, 0x4a, idecfg | 0x10); | ||
426 | pci_read_config_word(dev, PCI_DEVICE_ID, &trueid); | ||
427 | pci_write_config_byte(dev, 0x4a, idecfg); | ||
428 | |||
429 | if (trueid == 0x5517) { /* SiS 961/961B */ | ||
430 | |||
431 | lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */ | ||
432 | pci_read_config_byte(dev, 0x49, &prefctl); | ||
433 | pci_dev_put(lpc_bridge); | ||
434 | |||
435 | if (lpc_bridge->revision == 0x10 && (prefctl & 0x80)) { | ||
436 | printk(KERN_INFO DRV_NAME " %s: SiS 961B MuTIOL IDE UDMA133 controller\n", | ||
437 | pci_name(dev)); | ||
438 | chipset_family = ATA_133a; | ||
439 | } else { | ||
440 | printk(KERN_INFO DRV_NAME " %s: SiS 961 MuTIOL IDE UDMA100 controller\n", | ||
441 | pci_name(dev)); | ||
442 | chipset_family = ATA_100; | ||
443 | } | ||
444 | } | ||
445 | } | ||
446 | |||
447 | return chipset_family; | ||
448 | } | ||
449 | |||
450 | static unsigned int init_chipset_sis5513(struct pci_dev *dev) | ||
451 | { | ||
452 | /* Make general config ops here | ||
453 | 1/ tell IDE channels to operate in Compatibility mode only | ||
454 | 2/ tell old chips to allow per drive IDE timings */ | ||
455 | |||
456 | u8 reg; | ||
457 | u16 regw; | ||
458 | |||
459 | switch (chipset_family) { | ||
460 | case ATA_133: | ||
461 | /* SiS962 operation mode */ | ||
462 | pci_read_config_word(dev, 0x50, ®w); | ||
463 | if (regw & 0x08) | ||
464 | pci_write_config_word(dev, 0x50, regw&0xfff7); | ||
465 | pci_read_config_word(dev, 0x52, ®w); | ||
466 | if (regw & 0x08) | ||
467 | pci_write_config_word(dev, 0x52, regw&0xfff7); | ||
468 | break; | ||
469 | case ATA_133a: | ||
470 | case ATA_100: | ||
471 | /* Fixup latency */ | ||
472 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); | ||
473 | /* Set compatibility bit */ | ||
474 | pci_read_config_byte(dev, 0x49, ®); | ||
475 | if (!(reg & 0x01)) | ||
476 | pci_write_config_byte(dev, 0x49, reg|0x01); | ||
477 | break; | ||
478 | case ATA_100a: | ||
479 | case ATA_66: | ||
480 | /* Fixup latency */ | ||
481 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); | ||
482 | |||
483 | /* On ATA_66 chips the bit was elsewhere */ | ||
484 | pci_read_config_byte(dev, 0x52, ®); | ||
485 | if (!(reg & 0x04)) | ||
486 | pci_write_config_byte(dev, 0x52, reg|0x04); | ||
487 | break; | ||
488 | case ATA_33: | ||
489 | /* On ATA_33 we didn't have a single bit to set */ | ||
490 | pci_read_config_byte(dev, 0x09, ®); | ||
491 | if ((reg & 0x0f) != 0x00) | ||
492 | pci_write_config_byte(dev, 0x09, reg&0xf0); | ||
493 | case ATA_16: | ||
494 | /* force per drive recovery and active timings | ||
495 | needed on ATA_33 and below chips */ | ||
496 | pci_read_config_byte(dev, 0x52, ®); | ||
497 | if (!(reg & 0x08)) | ||
498 | pci_write_config_byte(dev, 0x52, reg|0x08); | ||
499 | break; | ||
500 | } | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | struct sis_laptop { | ||
506 | u16 device; | ||
507 | u16 subvendor; | ||
508 | u16 subdevice; | ||
509 | }; | ||
510 | |||
511 | static const struct sis_laptop sis_laptop[] = { | ||
512 | /* devid, subvendor, subdev */ | ||
513 | { 0x5513, 0x1043, 0x1107 }, /* ASUS A6K */ | ||
514 | { 0x5513, 0x1734, 0x105f }, /* FSC Amilo A1630 */ | ||
515 | { 0x5513, 0x1071, 0x8640 }, /* EasyNote K5305 */ | ||
516 | /* end marker */ | ||
517 | { 0, } | ||
518 | }; | ||
519 | |||
520 | static u8 sis_cable_detect(ide_hwif_t *hwif) | ||
521 | { | ||
522 | struct pci_dev *pdev = to_pci_dev(hwif->dev); | ||
523 | const struct sis_laptop *lap = &sis_laptop[0]; | ||
524 | u8 ata66 = 0; | ||
525 | |||
526 | while (lap->device) { | ||
527 | if (lap->device == pdev->device && | ||
528 | lap->subvendor == pdev->subsystem_vendor && | ||
529 | lap->subdevice == pdev->subsystem_device) | ||
530 | return ATA_CBL_PATA40_SHORT; | ||
531 | lap++; | ||
532 | } | ||
533 | |||
534 | if (chipset_family >= ATA_133) { | ||
535 | u16 regw = 0; | ||
536 | u16 reg_addr = hwif->channel ? 0x52: 0x50; | ||
537 | pci_read_config_word(pdev, reg_addr, ®w); | ||
538 | ata66 = (regw & 0x8000) ? 0 : 1; | ||
539 | } else if (chipset_family >= ATA_66) { | ||
540 | u8 reg48h = 0; | ||
541 | u8 mask = hwif->channel ? 0x20 : 0x10; | ||
542 | pci_read_config_byte(pdev, 0x48, ®48h); | ||
543 | ata66 = (reg48h & mask) ? 0 : 1; | ||
544 | } | ||
545 | |||
546 | return ata66 ? ATA_CBL_PATA80 : ATA_CBL_PATA40; | ||
547 | } | ||
548 | |||
549 | static const struct ide_port_ops sis_port_ops = { | ||
550 | .set_pio_mode = sis_set_pio_mode, | ||
551 | .set_dma_mode = sis_set_dma_mode, | ||
552 | .cable_detect = sis_cable_detect, | ||
553 | }; | ||
554 | |||
555 | static const struct ide_port_ops sis_ata133_port_ops = { | ||
556 | .set_pio_mode = sis_set_pio_mode, | ||
557 | .set_dma_mode = sis_set_dma_mode, | ||
558 | .udma_filter = sis_ata133_udma_filter, | ||
559 | .cable_detect = sis_cable_detect, | ||
560 | }; | ||
561 | |||
562 | static const struct ide_port_info sis5513_chipset __devinitdata = { | ||
563 | .name = DRV_NAME, | ||
564 | .init_chipset = init_chipset_sis5513, | ||
565 | .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} }, | ||
566 | .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA, | ||
567 | .pio_mask = ATA_PIO4, | ||
568 | .mwdma_mask = ATA_MWDMA2, | ||
569 | }; | ||
570 | |||
571 | static int __devinit sis5513_init_one(struct pci_dev *dev, const struct pci_device_id *id) | ||
572 | { | ||
573 | struct ide_port_info d = sis5513_chipset; | ||
574 | u8 udma_rates[] = { 0x00, 0x00, 0x07, 0x1f, 0x3f, 0x3f, 0x7f, 0x7f }; | ||
575 | int rc; | ||
576 | |||
577 | rc = pci_enable_device(dev); | ||
578 | if (rc) | ||
579 | return rc; | ||
580 | |||
581 | if (sis_find_family(dev) == 0) | ||
582 | return -ENOTSUPP; | ||
583 | |||
584 | if (chipset_family >= ATA_133) | ||
585 | d.port_ops = &sis_ata133_port_ops; | ||
586 | else | ||
587 | d.port_ops = &sis_port_ops; | ||
588 | |||
589 | d.udma_mask = udma_rates[chipset_family]; | ||
590 | |||
591 | return ide_pci_init_one(dev, &d, NULL); | ||
592 | } | ||
593 | |||
594 | static void __devexit sis5513_remove(struct pci_dev *dev) | ||
595 | { | ||
596 | ide_pci_remove(dev); | ||
597 | pci_disable_device(dev); | ||
598 | } | ||
599 | |||
600 | static const struct pci_device_id sis5513_pci_tbl[] = { | ||
601 | { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5513), 0 }, | ||
602 | { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_5518), 0 }, | ||
603 | { PCI_VDEVICE(SI, PCI_DEVICE_ID_SI_1180), 0 }, | ||
604 | { 0, }, | ||
605 | }; | ||
606 | MODULE_DEVICE_TABLE(pci, sis5513_pci_tbl); | ||
607 | |||
608 | static struct pci_driver sis5513_pci_driver = { | ||
609 | .name = "SIS_IDE", | ||
610 | .id_table = sis5513_pci_tbl, | ||
611 | .probe = sis5513_init_one, | ||
612 | .remove = __devexit_p(sis5513_remove), | ||
613 | .suspend = ide_pci_suspend, | ||
614 | .resume = ide_pci_resume, | ||
615 | }; | ||
616 | |||
617 | static int __init sis5513_ide_init(void) | ||
618 | { | ||
619 | return ide_pci_register_driver(&sis5513_pci_driver); | ||
620 | } | ||
621 | |||
622 | static void __exit sis5513_ide_exit(void) | ||
623 | { | ||
624 | pci_unregister_driver(&sis5513_pci_driver); | ||
625 | } | ||
626 | |||
627 | module_init(sis5513_ide_init); | ||
628 | module_exit(sis5513_ide_exit); | ||
629 | |||
630 | MODULE_AUTHOR("Lionel Bouton, L C Chang, Andre Hedrick, Vojtech Pavlik"); | ||
631 | MODULE_DESCRIPTION("PCI driver module for SIS IDE"); | ||
632 | MODULE_LICENSE("GPL"); | ||
633 | |||
634 | /* | ||
635 | * TODO: | ||
636 | * - CLEANUP | ||
637 | * - More checks in the config registers (force values instead of | ||
638 | * relying on the BIOS setting them correctly). | ||
639 | * - Further optimisations ? | ||
640 | * . for example ATA66+ regs 0x48 & 0x4A | ||
641 | */ | ||