blob: 28bf2bad154141bfa6cd4dc36a1251266cd9797b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01002 * linux/drivers/ide/pci/hpt366.c Version 0.43 May 17, 2006
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
4 * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
5 * Portions Copyright (C) 2001 Sun Microsystems, Inc.
6 * Portions Copyright (C) 2003 Red Hat Inc
Sergei Shtylyov836c0062006-12-13 00:35:47 -08007 * Portions Copyright (C) 2005-2006 MontaVista Software, Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * Thanks to HighPoint Technologies for their assistance, and hardware.
10 * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his
11 * donation of an ABit BP6 mainboard, processor, and memory acellerated
12 * development and support.
13 *
Alan Coxb39b01f2005-06-27 15:24:27 -070014 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -080015 * HighPoint has its own drivers (open source except for the RAID part)
16 * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/.
17 * This may be useful to anyone wanting to work on this driver, however do not
18 * trust them too much since the code tends to become less and less meaningful
19 * as the time passes... :-/
Alan Coxb39b01f2005-06-27 15:24:27 -070020 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 * Note that final HPT370 support was done by force extraction of GPL.
22 *
23 * - add function for getting/setting power status of drive
24 * - the HPT370's state machine can get confused. reset it before each dma
25 * xfer to prevent that from happening.
26 * - reset state engine whenever we get an error.
27 * - check for busmaster state at end of dma.
28 * - use new highpoint timings.
29 * - detect bus speed using highpoint register.
30 * - use pll if we don't have a clock table. added a 66MHz table that's
31 * just 2x the 33MHz table.
32 * - removed turnaround. NOTE: we never want to switch between pll and
33 * pci clocks as the chip can glitch in those cases. the highpoint
34 * approved workaround slows everything down too much to be useful. in
35 * addition, we would have to serialize access to each chip.
36 * Adrian Sun <a.sun@sun.com>
37 *
38 * add drive timings for 66MHz PCI bus,
39 * fix ATA Cable signal detection, fix incorrect /proc info
40 * add /proc display for per-drive PIO/DMA/UDMA mode and
41 * per-channel ATA-33/66 Cable detect.
42 * Duncan Laurie <void@sun.com>
43 *
44 * fixup /proc output for multiple controllers
45 * Tim Hockin <thockin@sun.com>
46 *
47 * On hpt366:
48 * Reset the hpt366 on error, reset on dma
49 * Fix disabling Fast Interrupt hpt366.
50 * Mike Waychison <crlf@sun.com>
51 *
52 * Added support for 372N clocking and clock switching. The 372N needs
53 * different clocks on read/write. This requires overloading rw_disk and
54 * other deeply crazy things. Thanks to <http://www.hoerstreich.de> for
55 * keeping me sane.
56 * Alan Cox <alan@redhat.com>
57 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -080058 * - fix the clock turnaround code: it was writing to the wrong ports when
59 * called for the secondary channel, caching the current clock mode per-
60 * channel caused the cached register value to get out of sync with the
61 * actual one, the channels weren't serialized, the turnaround shouldn't
62 * be done on 66 MHz PCI bus
63 * - avoid calibrating PLL twice as the second time results in a wrong PCI
64 * frequency and thus in the wrong timings for the secondary channel
Sergei Shtylyove139b0b2007-02-07 18:17:37 +010065 * - disable UltraATA/133 for HPT372 and UltraATA/100 for HPT370 by default
66 * as the ATA clock being used does not allow for this speed anyway
Sergei Shtylyov836c0062006-12-13 00:35:47 -080067 * - add support for HPT302N and HPT371N clocking (the same as for HPT372N)
68 * - HPT371/N are single channel chips, so avoid touching the primary channel
69 * which exists only virtually (there's no pins for it)
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -080070 * - fix/remove bad/unused timing tables and use one set of tables for the whole
71 * HPT37x chip family; save space by introducing the separate transfer mode
72 * table in which the mode lookup is done
Sergei Shtylyov26c068d2006-12-13 00:35:52 -080073 * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives
74 * the wrong PCI frequency since DPLL has already been calibrated by BIOS
Sergei Shtylyov33b18a62006-12-13 00:35:50 -080075 * - fix the hotswap code: it caused RESET- to glitch when tristating the bus,
76 * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -080077 * - pass to init_chipset() handlers a copy of the IDE PCI device structure as
78 * they tamper with its fields
Sergei Shtylyove139b0b2007-02-07 18:17:37 +010079 * - optimize the rate masking/filtering and the drive list lookup code
Sergei Shtylyov836c0062006-12-13 00:35:47 -080080 * <source@mvista.com>
81 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 */
83
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085#include <linux/types.h>
86#include <linux/module.h>
87#include <linux/kernel.h>
88#include <linux/delay.h>
89#include <linux/timer.h>
90#include <linux/mm.h>
91#include <linux/ioport.h>
92#include <linux/blkdev.h>
93#include <linux/hdreg.h>
94
95#include <linux/interrupt.h>
96#include <linux/pci.h>
97#include <linux/init.h>
98#include <linux/ide.h>
99
100#include <asm/uaccess.h>
101#include <asm/io.h>
102#include <asm/irq.h>
103
104/* various tuning parameters */
105#define HPT_RESET_STATE_ENGINE
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800106#undef HPT_DELAY_INTERRUPT
107#define HPT_SERIALIZE_IO 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108
109static const char *quirk_drives[] = {
110 "QUANTUM FIREBALLlct08 08",
111 "QUANTUM FIREBALLP KA6.4",
112 "QUANTUM FIREBALLP LM20.4",
113 "QUANTUM FIREBALLP LM20.5",
114 NULL
115};
116
117static const char *bad_ata100_5[] = {
118 "IBM-DTLA-307075",
119 "IBM-DTLA-307060",
120 "IBM-DTLA-307045",
121 "IBM-DTLA-307030",
122 "IBM-DTLA-307020",
123 "IBM-DTLA-307015",
124 "IBM-DTLA-305040",
125 "IBM-DTLA-305030",
126 "IBM-DTLA-305020",
127 "IC35L010AVER07-0",
128 "IC35L020AVER07-0",
129 "IC35L030AVER07-0",
130 "IC35L040AVER07-0",
131 "IC35L060AVER07-0",
132 "WDC AC310200R",
133 NULL
134};
135
136static const char *bad_ata66_4[] = {
137 "IBM-DTLA-307075",
138 "IBM-DTLA-307060",
139 "IBM-DTLA-307045",
140 "IBM-DTLA-307030",
141 "IBM-DTLA-307020",
142 "IBM-DTLA-307015",
143 "IBM-DTLA-305040",
144 "IBM-DTLA-305030",
145 "IBM-DTLA-305020",
146 "IC35L010AVER07-0",
147 "IC35L020AVER07-0",
148 "IC35L030AVER07-0",
149 "IC35L040AVER07-0",
150 "IC35L060AVER07-0",
151 "WDC AC310200R",
152 NULL
153};
154
155static const char *bad_ata66_3[] = {
156 "WDC AC310200R",
157 NULL
158};
159
160static const char *bad_ata33[] = {
161 "Maxtor 92720U8", "Maxtor 92040U6", "Maxtor 91360U4", "Maxtor 91020U3", "Maxtor 90845U3", "Maxtor 90650U2",
162 "Maxtor 91360D8", "Maxtor 91190D7", "Maxtor 91020D6", "Maxtor 90845D5", "Maxtor 90680D4", "Maxtor 90510D3", "Maxtor 90340D2",
163 "Maxtor 91152D8", "Maxtor 91008D7", "Maxtor 90845D6", "Maxtor 90840D6", "Maxtor 90720D5", "Maxtor 90648D5", "Maxtor 90576D4",
164 "Maxtor 90510D4",
165 "Maxtor 90432D3", "Maxtor 90288D2", "Maxtor 90256D2",
166 "Maxtor 91000D8", "Maxtor 90910D8", "Maxtor 90875D7", "Maxtor 90840D7", "Maxtor 90750D6", "Maxtor 90625D5", "Maxtor 90500D4",
167 "Maxtor 91728D8", "Maxtor 91512D7", "Maxtor 91303D6", "Maxtor 91080D5", "Maxtor 90845D4", "Maxtor 90680D4", "Maxtor 90648D3", "Maxtor 90432D2",
168 NULL
169};
170
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800171static u8 xfer_speeds[] = {
172 XFER_UDMA_6,
173 XFER_UDMA_5,
174 XFER_UDMA_4,
175 XFER_UDMA_3,
176 XFER_UDMA_2,
177 XFER_UDMA_1,
178 XFER_UDMA_0,
179
180 XFER_MW_DMA_2,
181 XFER_MW_DMA_1,
182 XFER_MW_DMA_0,
183
184 XFER_PIO_4,
185 XFER_PIO_3,
186 XFER_PIO_2,
187 XFER_PIO_1,
188 XFER_PIO_0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189};
190
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800191/* Key for bus clock timings
192 * 36x 37x
193 * bits bits
194 * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA.
195 * cycles = value + 1
196 * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA.
197 * cycles = value + 1
198 * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file
199 * register access.
200 * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file
201 * register access.
202 * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer.
203 * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock.
204 * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and
205 * MW DMA xfer.
206 * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for
207 * task file register access.
208 * 28 28 UDMA enable.
209 * 29 29 DMA enable.
210 * 30 30 PIO MST enable. If set, the chip is in bus master mode during
211 * PIO xfer.
212 * 31 31 FIFO enable.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800215static u32 forty_base_hpt36x[] = {
216 /* XFER_UDMA_6 */ 0x900fd943,
217 /* XFER_UDMA_5 */ 0x900fd943,
218 /* XFER_UDMA_4 */ 0x900fd943,
219 /* XFER_UDMA_3 */ 0x900ad943,
220 /* XFER_UDMA_2 */ 0x900bd943,
221 /* XFER_UDMA_1 */ 0x9008d943,
222 /* XFER_UDMA_0 */ 0x9008d943,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800224 /* XFER_MW_DMA_2 */ 0xa008d943,
225 /* XFER_MW_DMA_1 */ 0xa010d955,
226 /* XFER_MW_DMA_0 */ 0xa010d9fc,
227
228 /* XFER_PIO_4 */ 0xc008d963,
229 /* XFER_PIO_3 */ 0xc010d974,
230 /* XFER_PIO_2 */ 0xc010d997,
231 /* XFER_PIO_1 */ 0xc010d9c7,
232 /* XFER_PIO_0 */ 0xc018d9d9
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233};
234
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800235static u32 thirty_three_base_hpt36x[] = {
236 /* XFER_UDMA_6 */ 0x90c9a731,
237 /* XFER_UDMA_5 */ 0x90c9a731,
238 /* XFER_UDMA_4 */ 0x90c9a731,
239 /* XFER_UDMA_3 */ 0x90cfa731,
240 /* XFER_UDMA_2 */ 0x90caa731,
241 /* XFER_UDMA_1 */ 0x90cba731,
242 /* XFER_UDMA_0 */ 0x90c8a731,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800244 /* XFER_MW_DMA_2 */ 0xa0c8a731,
245 /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */
246 /* XFER_MW_DMA_0 */ 0xa0c8a797,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800248 /* XFER_PIO_4 */ 0xc0c8a731,
249 /* XFER_PIO_3 */ 0xc0c8a742,
250 /* XFER_PIO_2 */ 0xc0d0a753,
251 /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */
252 /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253};
254
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800255static u32 twenty_five_base_hpt36x[] = {
256 /* XFER_UDMA_6 */ 0x90c98521,
257 /* XFER_UDMA_5 */ 0x90c98521,
258 /* XFER_UDMA_4 */ 0x90c98521,
259 /* XFER_UDMA_3 */ 0x90cf8521,
260 /* XFER_UDMA_2 */ 0x90cf8521,
261 /* XFER_UDMA_1 */ 0x90cb8521,
262 /* XFER_UDMA_0 */ 0x90cb8521,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800264 /* XFER_MW_DMA_2 */ 0xa0ca8521,
265 /* XFER_MW_DMA_1 */ 0xa0ca8532,
266 /* XFER_MW_DMA_0 */ 0xa0ca8575,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800268 /* XFER_PIO_4 */ 0xc0ca8521,
269 /* XFER_PIO_3 */ 0xc0ca8532,
270 /* XFER_PIO_2 */ 0xc0ca8542,
271 /* XFER_PIO_1 */ 0xc0d08572,
272 /* XFER_PIO_0 */ 0xc0d08585
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273};
274
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800275static u32 thirty_three_base_hpt37x[] = {
276 /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */
277 /* XFER_UDMA_5 */ 0x12446231,
278 /* XFER_UDMA_4 */ 0x12446231,
279 /* XFER_UDMA_3 */ 0x126c6231,
280 /* XFER_UDMA_2 */ 0x12486231,
281 /* XFER_UDMA_1 */ 0x124c6233,
282 /* XFER_UDMA_0 */ 0x12506297,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800284 /* XFER_MW_DMA_2 */ 0x22406c31,
285 /* XFER_MW_DMA_1 */ 0x22406c33,
286 /* XFER_MW_DMA_0 */ 0x22406c97,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800288 /* XFER_PIO_4 */ 0x06414e31,
289 /* XFER_PIO_3 */ 0x06414e42,
290 /* XFER_PIO_2 */ 0x06414e53,
291 /* XFER_PIO_1 */ 0x06814e93,
292 /* XFER_PIO_0 */ 0x06814ea7
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293};
294
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800295static u32 fifty_base_hpt37x[] = {
296 /* XFER_UDMA_6 */ 0x12848242,
297 /* XFER_UDMA_5 */ 0x12848242,
298 /* XFER_UDMA_4 */ 0x12ac8242,
299 /* XFER_UDMA_3 */ 0x128c8242,
300 /* XFER_UDMA_2 */ 0x120c8242,
301 /* XFER_UDMA_1 */ 0x12148254,
302 /* XFER_UDMA_0 */ 0x121882ea,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800304 /* XFER_MW_DMA_2 */ 0x22808242,
305 /* XFER_MW_DMA_1 */ 0x22808254,
306 /* XFER_MW_DMA_0 */ 0x228082ea,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800308 /* XFER_PIO_4 */ 0x0a81f442,
309 /* XFER_PIO_3 */ 0x0a81f443,
310 /* XFER_PIO_2 */ 0x0a81f454,
311 /* XFER_PIO_1 */ 0x0ac1f465,
312 /* XFER_PIO_0 */ 0x0ac1f48a
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313};
314
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800315static u32 sixty_six_base_hpt37x[] = {
316 /* XFER_UDMA_6 */ 0x1c869c62,
317 /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */
318 /* XFER_UDMA_4 */ 0x1c8a9c62,
319 /* XFER_UDMA_3 */ 0x1c8e9c62,
320 /* XFER_UDMA_2 */ 0x1c929c62,
321 /* XFER_UDMA_1 */ 0x1c9a9c62,
322 /* XFER_UDMA_0 */ 0x1c829c62,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800324 /* XFER_MW_DMA_2 */ 0x2c829c62,
325 /* XFER_MW_DMA_1 */ 0x2c829c66,
326 /* XFER_MW_DMA_0 */ 0x2c829d2e,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800328 /* XFER_PIO_4 */ 0x0c829c62,
329 /* XFER_PIO_3 */ 0x0c829c84,
330 /* XFER_PIO_2 */ 0x0c829ca6,
331 /* XFER_PIO_1 */ 0x0d029d26,
332 /* XFER_PIO_0 */ 0x0d029d5e
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333};
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335#define HPT366_DEBUG_DRIVE_INFO 0
336#define HPT374_ALLOW_ATA133_6 0
337#define HPT371_ALLOW_ATA133_6 0
338#define HPT302_ALLOW_ATA133_6 0
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800339#define HPT372_ALLOW_ATA133_6 0
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100340#define HPT370_ALLOW_ATA100_5 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341#define HPT366_ALLOW_ATA66_4 1
342#define HPT366_ALLOW_ATA66_3 1
343#define HPT366_MAX_DEVS 8
344
345#define F_LOW_PCI_33 0x23
346#define F_LOW_PCI_40 0x29
347#define F_LOW_PCI_50 0x2d
348#define F_LOW_PCI_66 0x42
349
Alan Coxb39b01f2005-06-27 15:24:27 -0700350/*
351 * Hold all the highpoint quirks and revision information in one
352 * place.
353 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Alan Coxb39b01f2005-06-27 15:24:27 -0700355struct hpt_info
356{
357 u8 max_mode; /* Speeds allowed */
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100358 u8 revision; /* Chipset revision */
359 u8 flags; /* Chipset properties */
Alan Coxb39b01f2005-06-27 15:24:27 -0700360#define PLL_MODE 1
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800361#define IS_3xxN 2
362#define PCI_66MHZ 4
Alan Coxb39b01f2005-06-27 15:24:27 -0700363 /* Speed table */
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800364 u32 *speed;
Alan Coxb39b01f2005-06-27 15:24:27 -0700365};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Alan Coxb39b01f2005-06-27 15:24:27 -0700367/*
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100368 * This wants fixing so that we do everything not by revision
Alan Coxb39b01f2005-06-27 15:24:27 -0700369 * (which breaks on the newest chips) but by creating an
370 * enumeration of chip variants and using that
371 */
372
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100373static __devinit u8 hpt_revision(struct pci_dev *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100375 u8 rev = 0;
376
377 pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 switch(dev->device) {
380 /* Remap new 372N onto 372 */
381 case PCI_DEVICE_ID_TTI_HPT372N:
Andrew Mortonf36702b2007-02-07 18:17:37 +0100382 rev = PCI_DEVICE_ID_TTI_HPT372;
383 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 case PCI_DEVICE_ID_TTI_HPT374:
Andrew Mortonf36702b2007-02-07 18:17:37 +0100385 rev = PCI_DEVICE_ID_TTI_HPT374;
386 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 case PCI_DEVICE_ID_TTI_HPT371:
Andrew Mortonf36702b2007-02-07 18:17:37 +0100388 rev = PCI_DEVICE_ID_TTI_HPT371;
389 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 case PCI_DEVICE_ID_TTI_HPT302:
Andrew Mortonf36702b2007-02-07 18:17:37 +0100391 rev = PCI_DEVICE_ID_TTI_HPT302;
392 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 case PCI_DEVICE_ID_TTI_HPT372:
Andrew Mortonf36702b2007-02-07 18:17:37 +0100394 rev = PCI_DEVICE_ID_TTI_HPT372;
395 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 default:
397 break;
398 }
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100399 return rev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400}
401
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100402static int check_in_drive_list(ide_drive_t *drive, const char **list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403{
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100404 struct hd_driveid *id = drive->id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100406 while (*list)
407 if (!strcmp(*list++,id->model))
408 return 1;
409 return 0;
410}
Alan Coxb39b01f2005-06-27 15:24:27 -0700411
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100412static u8 hpt3xx_ratemask(ide_drive_t *drive)
413{
414 struct hpt_info *info = ide_get_hwifdata(HWIF(drive));
415 u8 mode = info->max_mode;
416
Alan Coxb39b01f2005-06-27 15:24:27 -0700417 if (!eighty_ninty_three(drive) && mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 mode = min(mode, (u8)1);
419 return mode;
420}
421
422/*
423 * Note for the future; the SATA hpt37x we must set
424 * either PIO or UDMA modes 0,4,5
425 */
426
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100427static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428{
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100429 struct hpt_info *info = ide_get_hwifdata(HWIF(drive));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 u8 mode = hpt3xx_ratemask(drive);
431
432 if (drive->media != ide_disk)
433 return min(speed, (u8)XFER_PIO_4);
434
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100435 switch (mode) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 case 0x04:
437 speed = min(speed, (u8)XFER_UDMA_6);
438 break;
439 case 0x03:
440 speed = min(speed, (u8)XFER_UDMA_5);
Alan Coxb39b01f2005-06-27 15:24:27 -0700441 if (info->revision >= 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 break;
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100443 if (!check_in_drive_list(drive, bad_ata100_5))
444 goto check_bad_ata33;
445 /* fall thru */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 case 0x02:
Andrew Mortonf36702b2007-02-07 18:17:37 +0100447 speed = min_t(u8, speed, XFER_UDMA_4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 /*
449 * CHECK ME, Does this need to be set to 5 ??
450 */
Alan Coxb39b01f2005-06-27 15:24:27 -0700451 if (info->revision >= 3)
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100452 goto check_bad_ata33;
453 if (HPT366_ALLOW_ATA66_4 &&
454 !check_in_drive_list(drive, bad_ata66_4))
455 goto check_bad_ata33;
456
Andrew Mortonf36702b2007-02-07 18:17:37 +0100457 speed = min_t(u8, speed, XFER_UDMA_3);
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100458 if (HPT366_ALLOW_ATA66_3 &&
459 !check_in_drive_list(drive, bad_ata66_3))
460 goto check_bad_ata33;
461 /* fall thru */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 case 0x01:
Andrew Mortonf36702b2007-02-07 18:17:37 +0100463 speed = min_t(u8, speed, XFER_UDMA_2);
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100464
465 check_bad_ata33:
466 if (info->revision >= 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 break;
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100468 if (!check_in_drive_list(drive, bad_ata33))
469 break;
470 /* fall thru */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 case 0x00:
472 default:
Andrew Mortonf36702b2007-02-07 18:17:37 +0100473 speed = min_t(u8, speed, XFER_MW_DMA_2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 break;
475 }
476 return speed;
477}
478
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800479static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800481 int i;
482
483 /*
484 * Lookup the transfer mode table to get the index into
485 * the timing table.
486 *
487 * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used.
488 */
489 for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
490 if (xfer_speeds[i] == speed)
491 break;
492 return chipset_table[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493}
494
495static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed)
496{
Alan Coxb39b01f2005-06-27 15:24:27 -0700497 ide_hwif_t *hwif = drive->hwif;
498 struct pci_dev *dev = hwif->pci_dev;
499 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
Alan Coxb39b01f2005-06-27 15:24:27 -0700502 u8 regfast = (hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 u8 drive_fast = 0;
504 u32 reg1 = 0, reg2 = 0;
505
506 /*
507 * Disable the "fast interrupt" prediction.
508 */
509 pci_read_config_byte(dev, regfast, &drive_fast);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 if (drive_fast & 0x80)
511 pci_write_config_byte(dev, regfast, drive_fast & ~0x80);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Alan Coxb39b01f2005-06-27 15:24:27 -0700513 reg2 = pci_bus_clock_list(speed, info->speed);
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 /*
516 * Disable on-chip PIO FIFO/buffer
517 * (to avoid problems handling I/O errors later)
518 */
519 pci_read_config_dword(dev, regtime, &reg1);
520 if (speed >= XFER_MW_DMA_0) {
521 reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000);
522 } else {
523 reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000);
524 }
525 reg2 &= ~0x80000000;
526
527 pci_write_config_dword(dev, regtime, reg2);
528
529 return ide_config_drive_speed(drive, speed);
530}
531
532static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed)
533{
Alan Coxb39b01f2005-06-27 15:24:27 -0700534 ide_hwif_t *hwif = drive->hwif;
535 struct pci_dev *dev = hwif->pci_dev;
536 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700538 u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 u8 drive_pci = 0x40 + (drive->dn * 4);
540 u8 new_fast = 0, drive_fast = 0;
541 u32 list_conf = 0, drive_conf = 0;
542 u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
543
544 /*
545 * Disable the "fast interrupt" prediction.
546 * don't holdoff on interrupts. (== 0x01 despite what the docs say)
547 */
548 pci_read_config_byte(dev, regfast, &drive_fast);
549 new_fast = drive_fast;
550 if (new_fast & 0x02)
551 new_fast &= ~0x02;
552
553#ifdef HPT_DELAY_INTERRUPT
554 if (new_fast & 0x01)
555 new_fast &= ~0x01;
556#else
557 if ((new_fast & 0x01) == 0)
558 new_fast |= 0x01;
559#endif
560 if (new_fast != drive_fast)
561 pci_write_config_byte(dev, regfast, new_fast);
562
Alan Coxb39b01f2005-06-27 15:24:27 -0700563 list_conf = pci_bus_clock_list(speed, info->speed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
565 pci_read_config_dword(dev, drive_pci, &drive_conf);
566 list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
567
Alan Coxb39b01f2005-06-27 15:24:27 -0700568 if (speed < XFER_MW_DMA_0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 pci_write_config_dword(dev, drive_pci, list_conf);
571
572 return ide_config_drive_speed(drive, speed);
573}
574
575static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed)
576{
Alan Coxb39b01f2005-06-27 15:24:27 -0700577 ide_hwif_t *hwif = drive->hwif;
578 struct pci_dev *dev = hwif->pci_dev;
579 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 u8 speed = hpt3xx_ratefilter(drive, xferspeed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700581 u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4);
583 u32 list_conf = 0, drive_conf = 0;
584 u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000;
585
586 /*
587 * Disable the "fast interrupt" prediction.
588 * don't holdoff on interrupts. (== 0x01 despite what the docs say)
589 */
590 pci_read_config_byte(dev, regfast, &drive_fast);
591 drive_fast &= ~0x07;
592 pci_write_config_byte(dev, regfast, drive_fast);
Alan Coxb39b01f2005-06-27 15:24:27 -0700593
594 list_conf = pci_bus_clock_list(speed, info->speed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 pci_read_config_dword(dev, drive_pci, &drive_conf);
596 list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask);
597 if (speed < XFER_MW_DMA_0)
598 list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
599 pci_write_config_dword(dev, drive_pci, list_conf);
600
601 return ide_config_drive_speed(drive, speed);
602}
603
604static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed)
605{
Alan Coxb39b01f2005-06-27 15:24:27 -0700606 ide_hwif_t *hwif = drive->hwif;
607 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
Alan Coxb39b01f2005-06-27 15:24:27 -0700609 if (info->revision >= 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 return hpt372_tune_chipset(drive, speed); /* not a typo */
Alan Coxb39b01f2005-06-27 15:24:27 -0700611 else if (info->revision >= 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 return hpt372_tune_chipset(drive, speed);
Alan Coxb39b01f2005-06-27 15:24:27 -0700613 else if (info->revision >= 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 return hpt370_tune_chipset(drive, speed);
615 else /* hpt368: hpt_minimum_revision(dev, 2) */
616 return hpt36x_tune_chipset(drive, speed);
617}
618
619static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio)
620{
621 pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
622 (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio));
623}
624
625/*
626 * This allows the configuration of ide_pci chipset registers
627 * for cards that learn about the drive's UDMA, DMA, PIO capabilities
628 * after the drive is reported by the OS. Initially for designed for
629 * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc.
630 *
631 * check_in_drive_lists(drive, bad_ata66_4)
632 * check_in_drive_lists(drive, bad_ata66_3)
633 * check_in_drive_lists(drive, bad_ata33)
634 *
635 */
636static int config_chipset_for_dma (ide_drive_t *drive)
637{
638 u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive));
Alan Coxb39b01f2005-06-27 15:24:27 -0700639 ide_hwif_t *hwif = drive->hwif;
640 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
Alan Coxb39b01f2005-06-27 15:24:27 -0700642 if (!speed)
643 return 0;
644
645 /* If we don't have any timings we can't do a lot */
646 if (info->speed == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 return 0;
648
649 (void) hpt3xx_tune_chipset(drive, speed);
650 return ide_dma_enable(drive);
651}
652
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100653static int hpt3xx_quirkproc(ide_drive_t *drive)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654{
Sergei Shtylyove139b0b2007-02-07 18:17:37 +0100655 struct hd_driveid *id = drive->id;
656 const char **list = quirk_drives;
657
658 while (*list)
659 if (strstr(id->model, *list++))
660 return 1;
661 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662}
663
664static void hpt3xx_intrproc (ide_drive_t *drive)
665{
Alan Coxb39b01f2005-06-27 15:24:27 -0700666 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
668 if (drive->quirk_list)
669 return;
670 /* drives in the quirk_list may not like intr setups/cleanups */
671 hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);
672}
673
674static void hpt3xx_maskproc (ide_drive_t *drive, int mask)
675{
Alan Coxb39b01f2005-06-27 15:24:27 -0700676 ide_hwif_t *hwif = drive->hwif;
677 struct hpt_info *info = ide_get_hwifdata(hwif);
678 struct pci_dev *dev = hwif->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
680 if (drive->quirk_list) {
Alan Coxb39b01f2005-06-27 15:24:27 -0700681 if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 u8 reg5a = 0;
683 pci_read_config_byte(dev, 0x5a, &reg5a);
684 if (((reg5a & 0x10) >> 4) != mask)
685 pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10));
686 } else {
687 if (mask) {
Alan Coxb39b01f2005-06-27 15:24:27 -0700688 disable_irq(hwif->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 } else {
Alan Coxb39b01f2005-06-27 15:24:27 -0700690 enable_irq(hwif->irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 }
692 }
693 } else {
694 if (IDE_CONTROL_REG)
Alan Coxb39b01f2005-06-27 15:24:27 -0700695 hwif->OUTB(mask ? (drive->ctl | 2) :
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 (drive->ctl & ~2),
697 IDE_CONTROL_REG);
698 }
699}
700
701static int hpt366_config_drive_xfer_rate (ide_drive_t *drive)
702{
Alan Coxb39b01f2005-06-27 15:24:27 -0700703 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 struct hd_driveid *id = drive->id;
705
706 drive->init_speed = 0;
707
Alan Coxb39b01f2005-06-27 15:24:27 -0700708 if ((id->capability & 1) && drive->autodma) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710 if (ide_use_dma(drive)) {
711 if (config_chipset_for_dma(drive))
712 return hwif->ide_dma_on(drive);
713 }
714
715 goto fast_ata_pio;
716
717 } else if ((id->capability & 8) || (id->field_valid & 2)) {
718fast_ata_pio:
719 hpt3xx_tune_drive(drive, 5);
720 return hwif->ide_dma_off_quietly(drive);
721 }
722 /* IORDY not supported */
723 return 0;
724}
725
726/*
727 * This is specific to the HPT366 UDMA bios chipset
728 * by HighPoint|Triones Technologies, Inc.
729 */
730static int hpt366_ide_dma_lostirq (ide_drive_t *drive)
731{
732 struct pci_dev *dev = HWIF(drive)->pci_dev;
733 u8 reg50h = 0, reg52h = 0, reg5ah = 0;
734
735 pci_read_config_byte(dev, 0x50, &reg50h);
736 pci_read_config_byte(dev, 0x52, &reg52h);
737 pci_read_config_byte(dev, 0x5a, &reg5ah);
738 printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n",
739 drive->name, __FUNCTION__, reg50h, reg52h, reg5ah);
740 if (reg5ah & 0x10)
741 pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 return __ide_dma_lostirq(drive);
743}
744
745static void hpt370_clear_engine (ide_drive_t *drive)
746{
747 u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50;
748 pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37);
749 udelay(10);
750}
751
752static void hpt370_ide_dma_start(ide_drive_t *drive)
753{
754#ifdef HPT_RESET_STATE_ENGINE
755 hpt370_clear_engine(drive);
756#endif
757 ide_dma_start(drive);
758}
759
760static int hpt370_ide_dma_end (ide_drive_t *drive)
761{
762 ide_hwif_t *hwif = HWIF(drive);
763 u8 dma_stat = hwif->INB(hwif->dma_status);
764
765 if (dma_stat & 0x01) {
766 /* wait a little */
767 udelay(20);
768 dma_stat = hwif->INB(hwif->dma_status);
769 }
770 if ((dma_stat & 0x01) != 0)
771 /* fallthrough */
772 (void) HWIF(drive)->ide_dma_timeout(drive);
773
774 return __ide_dma_end(drive);
775}
776
777static void hpt370_lostirq_timeout (ide_drive_t *drive)
778{
779 ide_hwif_t *hwif = HWIF(drive);
780 u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52;
781 u8 dma_stat = 0, dma_cmd = 0;
782
783 pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo);
Alan Coxb39b01f2005-06-27 15:24:27 -0700784 printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 hpt370_clear_engine(drive);
786 /* get dma command mode */
787 dma_cmd = hwif->INB(hwif->dma_command);
788 /* stop dma */
789 hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command);
790 dma_stat = hwif->INB(hwif->dma_status);
791 /* clear errors */
792 hwif->OUTB(dma_stat | 0x6, hwif->dma_status);
793}
794
795static int hpt370_ide_dma_timeout (ide_drive_t *drive)
796{
797 hpt370_lostirq_timeout(drive);
798 hpt370_clear_engine(drive);
799 return __ide_dma_timeout(drive);
800}
801
802static int hpt370_ide_dma_lostirq (ide_drive_t *drive)
803{
804 hpt370_lostirq_timeout(drive);
805 hpt370_clear_engine(drive);
806 return __ide_dma_lostirq(drive);
807}
808
809/* returns 1 if DMA IRQ issued, 0 otherwise */
810static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
811{
812 ide_hwif_t *hwif = HWIF(drive);
813 u16 bfifo = 0;
814 u8 reginfo = hwif->channel ? 0x56 : 0x52;
815 u8 dma_stat;
816
817 pci_read_config_word(hwif->pci_dev, reginfo, &bfifo);
818 if (bfifo & 0x1FF) {
819// printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
820 return 0;
821 }
822
823 dma_stat = hwif->INB(hwif->dma_status);
824 /* return 1 if INTR asserted */
825 if ((dma_stat & 4) == 4)
826 return 1;
827
828 if (!drive->waiting_for_dma)
829 printk(KERN_WARNING "%s: (%s) called while not waiting\n",
830 drive->name, __FUNCTION__);
831 return 0;
832}
833
834static int hpt374_ide_dma_end (ide_drive_t *drive)
835{
836 struct pci_dev *dev = HWIF(drive)->pci_dev;
837 ide_hwif_t *hwif = HWIF(drive);
838 u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50;
839 u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01;
840
841 pci_read_config_byte(dev, 0x6a, &bwsr_stat);
842 pci_read_config_byte(dev, mscreg, &msc_stat);
843 if ((bwsr_stat & bwsr_mask) == bwsr_mask)
844 pci_write_config_byte(dev, mscreg, msc_stat|0x30);
845 return __ide_dma_end(drive);
846}
847
848/**
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800849 * hpt3xxn_set_clock - perform clock switching dance
850 * @hwif: hwif to switch
851 * @mode: clocking mode (0x21 for write, 0x23 otherwise)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800853 * Switch the DPLL clock on the HPT3xxN devices. This is a right mess.
854 * NOTE: avoid touching the disabled primary channel on HPT371N -- it
855 * doesn't physically exist anyway...
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800857
858static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859{
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800860 u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b);
861
862 if ((scr2 & 0x7f) == mode)
863 return;
864
865 /* MISC. control register 1 has the channel enable bit... */
866 mcr1 = hwif->INB(hwif->dma_master + 0x70);
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 /* Tristate the bus */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800869 if (mcr1 & 0x04)
870 hwif->OUTB(0x80, hwif->dma_master + 0x73);
871 hwif->OUTB(0x80, hwif->dma_master + 0x77);
872
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 /* Switch clock and reset channels */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800874 hwif->OUTB(mode, hwif->dma_master + 0x7b);
875 hwif->OUTB(0xc0, hwif->dma_master + 0x79);
876
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 /* Reset state machines */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800878 if (mcr1 & 0x04)
879 hwif->OUTB(0x37, hwif->dma_master + 0x70);
880 hwif->OUTB(0x37, hwif->dma_master + 0x74);
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 /* Complete reset */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800883 hwif->OUTB(0x00, hwif->dma_master + 0x79);
884
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 /* Reconnect channels to bus */
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800886 if (mcr1 & 0x04)
887 hwif->OUTB(0x00, hwif->dma_master + 0x73);
888 hwif->OUTB(0x00, hwif->dma_master + 0x77);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889}
890
891/**
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800892 * hpt3xxn_rw_disk - prepare for I/O
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 * @drive: drive for command
894 * @rq: block request structure
895 *
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800896 * This is called when a disk I/O is issued to HPT3xxN.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 * We need it because of the clock switching.
898 */
899
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800900static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901{
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800902 ide_hwif_t *hwif = HWIF(drive);
903 u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
Sergei Shtylyov836c0062006-12-13 00:35:47 -0800905 hpt3xxn_set_clock(hwif, wantclock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906}
907
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908/*
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800909 * Set/get power state for a drive.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 *
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800911 * When we turn the power back on, we need to re-initialize things.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 */
913#define TRISTATE_BIT 0x8000
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800914
915static int hpt3xx_busproc(ide_drive_t *drive, int state)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
Alan Coxb39b01f2005-06-27 15:24:27 -0700917 ide_hwif_t *hwif = drive->hwif;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 struct pci_dev *dev = hwif->pci_dev;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800919 u8 tristate, resetmask, bus_reg = 0;
920 u16 tri_reg = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
922 hwif->bus_state = state;
923
924 if (hwif->channel) {
925 /* secondary channel */
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800926 tristate = 0x56;
927 resetmask = 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 } else {
929 /* primary channel */
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800930 tristate = 0x52;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 resetmask = 0x40;
932 }
933
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800934 /* Grab the status. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 pci_read_config_word(dev, tristate, &tri_reg);
936 pci_read_config_byte(dev, 0x59, &bus_reg);
937
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800938 /*
939 * Set the state. We don't set it if we don't need to do so.
940 * Make sure that the drive knows that it has failed if it's off.
941 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 switch (state) {
943 case BUSSTATE_ON:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800944 if (!(bus_reg & resetmask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 return 0;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800946 hwif->drives[0].failures = hwif->drives[1].failures = 0;
947
948 pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask);
949 pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT);
950 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 case BUSSTATE_OFF:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800952 if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return 0;
954 tri_reg &= ~TRISTATE_BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 break;
956 case BUSSTATE_TRISTATE:
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800957 if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 return 0;
959 tri_reg |= TRISTATE_BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 break;
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800961 default:
962 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964
Sergei Shtylyov33b18a62006-12-13 00:35:50 -0800965 hwif->drives[0].failures = hwif->drives[0].max_failures + 1;
966 hwif->drives[1].failures = hwif->drives[1].max_failures + 1;
967
968 pci_write_config_word(dev, tristate, tri_reg);
969 pci_write_config_byte(dev, 0x59, bus_reg | resetmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 return 0;
971}
972
Alan Coxb39b01f2005-06-27 15:24:27 -0700973static void __devinit hpt366_clocking(ide_hwif_t *hwif)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974{
Alan Coxb39b01f2005-06-27 15:24:27 -0700975 u32 reg1 = 0;
976 struct hpt_info *info = ide_get_hwifdata(hwif);
977
978 pci_read_config_dword(hwif->pci_dev, 0x40, &reg1);
979
980 /* detect bus speed by looking at control reg timing: */
981 switch((reg1 >> 8) & 7) {
982 case 5:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800983 info->speed = forty_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -0700984 break;
985 case 9:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800986 info->speed = twenty_five_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -0700987 break;
988 case 7:
989 default:
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -0800990 info->speed = thirty_three_base_hpt36x;
Alan Coxb39b01f2005-06-27 15:24:27 -0700991 break;
992 }
993}
994
995static void __devinit hpt37x_clocking(ide_hwif_t *hwif)
996{
997 struct hpt_info *info = ide_get_hwifdata(hwif);
998 struct pci_dev *dev = hwif->pci_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 int adjust, i;
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001000 u16 freq = 0;
1001 u32 pll, temp = 0;
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001002 u8 reg5bh = 0, mcr1 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 /*
1005 * default to pci clock. make sure MA15/16 are set to output
Alan Coxb39b01f2005-06-27 15:24:27 -07001006 * to prevent drives having problems with 40-pin cables. Needed
1007 * for some drives such as IBM-DTLA which will not enter ready
1008 * state on reset when PDIAG is a input.
1009 *
1010 * ToDo: should we set 0x21 when using PLL mode ?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 */
1012 pci_write_config_byte(dev, 0x5b, 0x23);
1013
1014 /*
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001015 * We'll have to read f_CNT value in order to determine
1016 * the PCI clock frequency according to the following ratio:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 *
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001018 * f_CNT = Fpci * 192 / Fdpll
1019 *
1020 * First try reading the register in which the HighPoint BIOS
1021 * saves f_CNT value before reprogramming the DPLL from its
1022 * default setting (which differs for the various chips).
Sergei Shtylyovf13c1522006-12-13 00:35:53 -08001023 * NOTE: This register is only accessible via I/O space.
1024 *
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001025 * In case the signature check fails, we'll have to resort to
1026 * reading the f_CNT register itself in hopes that nobody has
1027 * touched the DPLL yet...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 */
Sergei Shtylyovf13c1522006-12-13 00:35:53 -08001029 temp = inl(pci_resource_start(dev, 4) + 0x90);
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001030 if ((temp & 0xFFFFF000) != 0xABCDE000) {
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001031 printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n");
1032
1033 /* Calculate the average value of f_CNT */
1034 for (temp = i = 0; i < 128; i++) {
1035 pci_read_config_word(dev, 0x78, &freq);
1036 temp += freq & 0x1ff;
1037 mdelay(1);
1038 }
1039 freq = temp / 128;
1040 } else
1041 freq = temp & 0x1ff;
1042
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 /*
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001044 * HPT3xxN chips use different PCI clock information.
1045 * Currently we always set up the PLL for them.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 */
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001047
1048 if (info->flags & IS_3xxN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 if(freq < 0x55)
1050 pll = F_LOW_PCI_33;
1051 else if(freq < 0x70)
1052 pll = F_LOW_PCI_40;
1053 else if(freq < 0x7F)
1054 pll = F_LOW_PCI_50;
1055 else
1056 pll = F_LOW_PCI_66;
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001057
1058 printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 }
1060 else
1061 {
1062 if(freq < 0x9C)
1063 pll = F_LOW_PCI_33;
1064 else if(freq < 0xb0)
1065 pll = F_LOW_PCI_40;
1066 else if(freq <0xc8)
1067 pll = F_LOW_PCI_50;
1068 else
1069 pll = F_LOW_PCI_66;
1070
1071 if (pll == F_LOW_PCI_33) {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001072 info->speed = thirty_three_base_hpt37x;
Alan Coxb39b01f2005-06-27 15:24:27 -07001073 printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 } else if (pll == F_LOW_PCI_40) {
1075 /* Unsupported */
1076 } else if (pll == F_LOW_PCI_50) {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001077 info->speed = fifty_base_hpt37x;
Alan Coxb39b01f2005-06-27 15:24:27 -07001078 printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 } else {
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001080 info->speed = sixty_six_base_hpt37x;
1081 printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 }
1083 }
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001084
1085 if (pll == F_LOW_PCI_66)
1086 info->flags |= PCI_66MHZ;
1087
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 /*
1089 * only try the pll if we don't have a table for the clock
1090 * speed that we're running at. NOTE: the internal PLL will
1091 * result in slow reads when using a 33MHz PCI clock. we also
1092 * don't like to use the PLL because it will cause glitches
1093 * on PRST/SRST when the HPT state engine gets reset.
Alan Coxb39b01f2005-06-27 15:24:27 -07001094 *
1095 * ToDo: Use 66MHz PLL when ATA133 devices are present on a
1096 * 372 device so we can get ATA133 support
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 */
Alan Coxb39b01f2005-06-27 15:24:27 -07001098 if (info->speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 goto init_hpt37X_done;
Alan Coxb39b01f2005-06-27 15:24:27 -07001100
1101 info->flags |= PLL_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102
1103 /*
Sergei Shtylyov26c068d2006-12-13 00:35:52 -08001104 * Adjust the PLL based upon the PCI clock, enable it, and
1105 * wait for stabilization...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 */
1107 adjust = 0;
1108 freq = (pll < F_LOW_PCI_50) ? 2 : 4;
1109 while (adjust++ < 6) {
1110 pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 |
1111 pll | 0x100);
1112
1113 /* wait for clock stabilization */
1114 for (i = 0; i < 0x50000; i++) {
1115 pci_read_config_byte(dev, 0x5b, &reg5bh);
1116 if (reg5bh & 0x80) {
1117 /* spin looking for the clock to destabilize */
1118 for (i = 0; i < 0x1000; ++i) {
1119 pci_read_config_byte(dev, 0x5b,
1120 &reg5bh);
1121 if ((reg5bh & 0x80) == 0)
1122 goto pll_recal;
1123 }
1124 pci_read_config_dword(dev, 0x5c, &pll);
1125 pci_write_config_dword(dev, 0x5c,
1126 pll & ~0x100);
1127 pci_write_config_byte(dev, 0x5b, 0x21);
Sergei Shtylyov471a0bd2006-12-13 00:35:49 -08001128
1129 info->speed = fifty_base_hpt37x;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 printk("HPT37X: using 50MHz internal PLL\n");
1131 goto init_hpt37X_done;
1132 }
1133 }
1134pll_recal:
1135 if (adjust & 1)
1136 pll -= (adjust >> 1);
1137 else
1138 pll += (adjust >> 1);
1139 }
1140
1141init_hpt37X_done:
Alan Coxb39b01f2005-06-27 15:24:27 -07001142 if (!info->speed)
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001143 printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n",
1144 (info->flags & IS_3xxN) ? "N" : "", pll, freq);
1145 /*
1146 * Reset the state engines.
1147 * NOTE: avoid accidentally enabling the primary channel on HPT371N.
1148 */
1149 pci_read_config_byte(dev, 0x50, &mcr1);
1150 if (mcr1 & 0x04)
1151 pci_write_config_byte(dev, 0x50, 0x37);
1152 pci_write_config_byte(dev, 0x54, 0x37);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 udelay(100);
Alan Coxb39b01f2005-06-27 15:24:27 -07001154}
1155
1156static int __devinit init_hpt37x(struct pci_dev *dev)
1157{
1158 u8 reg5ah;
1159
1160 pci_read_config_byte(dev, 0x5a, &reg5ah);
1161 /* interrupt force enable */
1162 pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 return 0;
1164}
1165
1166static int __devinit init_hpt366(struct pci_dev *dev)
1167{
1168 u32 reg1 = 0;
1169 u8 drive_fast = 0;
1170
1171 /*
1172 * Disable the "fast interrupt" prediction.
1173 */
1174 pci_read_config_byte(dev, 0x51, &drive_fast);
1175 if (drive_fast & 0x80)
1176 pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
1177 pci_read_config_dword(dev, 0x40, &reg1);
1178
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 return 0;
1180}
1181
1182static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name)
1183{
1184 int ret = 0;
Linus Torvalds9ec4ff42005-09-11 09:22:50 -07001185
1186 /*
1187 * FIXME: Not portable. Also, why do we enable the ROM in the first place?
1188 * We don't seem to be using it.
1189 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 if (dev->resource[PCI_ROM_RESOURCE].start)
Linus Torvalds9ec4ff42005-09-11 09:22:50 -07001191 pci_write_config_dword(dev, PCI_ROM_ADDRESS,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
1193
Alan Coxb39b01f2005-06-27 15:24:27 -07001194 pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
1195 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
1196 pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
1197 pci_write_config_byte(dev, PCI_MAX_LAT, 0x08);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
Alan Coxb39b01f2005-06-27 15:24:27 -07001199 if (hpt_revision(dev) >= 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 ret = init_hpt37x(dev);
Alan Coxb39b01f2005-06-27 15:24:27 -07001201 else
1202 ret = init_hpt366(dev);
1203
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 if (ret)
1205 return ret;
1206
1207 return dev->irq;
1208}
1209
1210static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
1211{
1212 struct pci_dev *dev = hwif->pci_dev;
Alan Coxb39b01f2005-06-27 15:24:27 -07001213 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02;
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001215 int serialize = HPT_SERIALIZE_IO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 hwif->tuneproc = &hpt3xx_tune_drive;
1218 hwif->speedproc = &hpt3xx_tune_chipset;
1219 hwif->quirkproc = &hpt3xx_quirkproc;
1220 hwif->intrproc = &hpt3xx_intrproc;
1221 hwif->maskproc = &hpt3xx_maskproc;
1222
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001223 /*
1224 * HPT3xxN chips have some complications:
1225 *
1226 * - on 33 MHz PCI we must clock switch
1227 * - on 66 MHz PCI we must NOT use the PCI clock
1228 */
1229 if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) {
1230 /*
1231 * Clock is shared between the channels,
1232 * so we'll have to serialize them... :-(
1233 */
1234 serialize = 1;
1235 hwif->rw_disk = &hpt3xxn_rw_disk;
1236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
1238 /*
1239 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
1240 * address lines to access an external eeprom. To read valid
1241 * cable detect state the pins must be enabled as inputs.
1242 */
Alan Coxb39b01f2005-06-27 15:24:27 -07001243 if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 /*
1245 * HPT374 PCI function 1
1246 * - set bit 15 of reg 0x52 to enable TCBLID as input
1247 * - set bit 15 of reg 0x56 to enable FCBLID as input
1248 */
1249 u16 mcr3, mcr6;
1250 pci_read_config_word(dev, 0x52, &mcr3);
1251 pci_read_config_word(dev, 0x56, &mcr6);
1252 pci_write_config_word(dev, 0x52, mcr3 | 0x8000);
1253 pci_write_config_word(dev, 0x56, mcr6 | 0x8000);
1254 /* now read cable id register */
1255 pci_read_config_byte(dev, 0x5a, &ata66);
1256 pci_write_config_word(dev, 0x52, mcr3);
1257 pci_write_config_word(dev, 0x56, mcr6);
Alan Coxb39b01f2005-06-27 15:24:27 -07001258 } else if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 /*
1260 * HPT370/372 and 374 pcifn 0
1261 * - clear bit 0 of 0x5b to enable P/SCBLID as inputs
1262 */
1263 u8 scr2;
1264 pci_read_config_byte(dev, 0x5b, &scr2);
1265 pci_write_config_byte(dev, 0x5b, scr2 & ~1);
1266 /* now read cable id register */
1267 pci_read_config_byte(dev, 0x5a, &ata66);
1268 pci_write_config_byte(dev, 0x5b, scr2);
1269 } else {
1270 pci_read_config_byte(dev, 0x5a, &ata66);
1271 }
1272
1273#ifdef DEBUG
1274 printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n",
1275 ata66, (ata66 & regmask) ? "33" : "66",
1276 PCI_FUNC(hwif->pci_dev->devfn));
1277#endif /* DEBUG */
1278
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001279 /* Serialize access to this device */
1280 if (serialize && hwif->mate)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 hwif->serialized = hwif->mate->serialized = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Sergei Shtylyov33b18a62006-12-13 00:35:50 -08001283 /*
1284 * Set up ioctl for power status.
1285 * NOTE: power affects both drives on each channel.
1286 */
1287 hwif->busproc = &hpt3xx_busproc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
1289 if (!hwif->dma_base) {
1290 hwif->drives[0].autotune = 1;
1291 hwif->drives[1].autotune = 1;
1292 return;
1293 }
1294
1295 hwif->ultra_mask = 0x7f;
1296 hwif->mwdma_mask = 0x07;
1297
1298 if (!(hwif->udma_four))
1299 hwif->udma_four = ((ata66 & regmask) ? 0 : 1);
1300 hwif->ide_dma_check = &hpt366_config_drive_xfer_rate;
1301
Alan Coxb39b01f2005-06-27 15:24:27 -07001302 if (info->revision >= 8) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
1304 hwif->ide_dma_end = &hpt374_ide_dma_end;
Alan Coxb39b01f2005-06-27 15:24:27 -07001305 } else if (info->revision >= 5) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq;
1307 hwif->ide_dma_end = &hpt374_ide_dma_end;
Alan Coxb39b01f2005-06-27 15:24:27 -07001308 } else if (info->revision >= 3) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 hwif->dma_start = &hpt370_ide_dma_start;
1310 hwif->ide_dma_end = &hpt370_ide_dma_end;
1311 hwif->ide_dma_timeout = &hpt370_ide_dma_timeout;
1312 hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq;
Alan Coxb39b01f2005-06-27 15:24:27 -07001313 } else if (info->revision >= 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
1315 else
1316 hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq;
1317
1318 if (!noautodma)
1319 hwif->autodma = 1;
1320 hwif->drives[0].autodma = hwif->autodma;
1321 hwif->drives[1].autodma = hwif->autodma;
1322}
1323
1324static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
1325{
Alan Coxb39b01f2005-06-27 15:24:27 -07001326 struct hpt_info *info = ide_get_hwifdata(hwif);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 u8 masterdma = 0, slavedma = 0;
1328 u8 dma_new = 0, dma_old = 0;
1329 u8 primary = hwif->channel ? 0x4b : 0x43;
1330 u8 secondary = hwif->channel ? 0x4f : 0x47;
1331 unsigned long flags;
1332
1333 if (!dmabase)
1334 return;
1335
Alan Coxb39b01f2005-06-27 15:24:27 -07001336 if(info->speed == NULL) {
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001337 printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 return;
1339 }
1340
1341 dma_old = hwif->INB(dmabase+2);
1342
1343 local_irq_save(flags);
1344
1345 dma_new = dma_old;
1346 pci_read_config_byte(hwif->pci_dev, primary, &masterdma);
1347 pci_read_config_byte(hwif->pci_dev, secondary, &slavedma);
1348
1349 if (masterdma & 0x30) dma_new |= 0x20;
1350 if (slavedma & 0x30) dma_new |= 0x40;
1351 if (dma_new != dma_old)
1352 hwif->OUTB(dma_new, dmabase+2);
1353
1354 local_irq_restore(flags);
1355
1356 ide_setup_dma(hwif, dmabase, 8);
1357}
1358
Alan Coxb39b01f2005-06-27 15:24:27 -07001359/*
1360 * We "borrow" this hook in order to set the data structures
1361 * up early enough before dma or init_hwif calls are made.
1362 */
1363
1364static void __devinit init_iops_hpt366(ide_hwif_t *hwif)
1365{
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001366 struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL);
1367 struct pci_dev *dev = hwif->pci_dev;
1368 u16 did = dev->device;
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001369 u8 mode, rid = 0;
Alan Coxb39b01f2005-06-27 15:24:27 -07001370
1371 if(info == NULL) {
1372 printk(KERN_WARNING "hpt366: out of memory.\n");
1373 return;
1374 }
Alan Coxb39b01f2005-06-27 15:24:27 -07001375 ide_set_hwifdata(hwif, info);
1376
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001377 /* Avoid doing the same thing twice. */
1378 if (hwif->channel && hwif->mate) {
1379 memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info));
1380 return;
Alan Coxb39b01f2005-06-27 15:24:27 -07001381 }
1382
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001383 pci_read_config_byte(dev, PCI_REVISION_ID, &rid);
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001384
1385 if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) ||
1386 ((did == PCI_DEVICE_ID_TTI_HPT372 ||
1387 did == PCI_DEVICE_ID_TTI_HPT302 ||
1388 did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) ||
1389 did == PCI_DEVICE_ID_TTI_HPT372N)
1390 info->flags |= IS_3xxN;
1391
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001392 rid = info->revision = hpt_revision(dev);
1393 if (rid >= 8) /* HPT374 */
1394 mode = HPT374_ALLOW_ATA133_6 ? 4 : 3;
1395 else if (rid >= 7) /* HPT371 and HPT371N */
1396 mode = HPT371_ALLOW_ATA133_6 ? 4 : 3;
1397 else if (rid >= 6) /* HPT302 and HPT302N */
1398 mode = HPT302_ALLOW_ATA133_6 ? 4 : 3;
1399 else if (rid >= 5) /* HPT372, HPT372A, and HPT372N */
1400 mode = HPT372_ALLOW_ATA133_6 ? 4 : 3;
1401 else if (rid >= 3) /* HPT370 and HPT370A */
1402 mode = HPT370_ALLOW_ATA100_5 ? 3 : 2;
1403 else /* HPT366 and HPT368 */
1404 mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1;
1405 info->max_mode = mode;
Alan Coxb39b01f2005-06-27 15:24:27 -07001406
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001407 if (rid >= 3)
Alan Coxb39b01f2005-06-27 15:24:27 -07001408 hpt37x_clocking(hwif);
1409 else
1410 hpt366_clocking(hwif);
1411}
1412
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d)
1414{
1415 struct pci_dev *findev = NULL;
1416
1417 if (PCI_FUNC(dev->devfn) & 1)
1418 return -ENODEV;
1419
1420 while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
1421 if ((findev->vendor == dev->vendor) &&
1422 (findev->device == dev->device) &&
1423 ((findev->devfn - dev->devfn) == 1) &&
1424 (PCI_FUNC(findev->devfn) & 1)) {
1425 if (findev->irq != dev->irq) {
1426 /* FIXME: we need a core pci_set_interrupt() */
1427 findev->irq = dev->irq;
1428 printk(KERN_WARNING "%s: pci-config space interrupt "
1429 "fixed.\n", d->name);
1430 }
1431 return ide_setup_pci_devices(dev, findev, d);
1432 }
1433 }
1434 return ide_setup_pci_device(dev, d);
1435}
1436
1437static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d)
1438{
1439 return ide_setup_pci_device(dev, d);
1440}
1441
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001442static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d)
1443{
1444 u8 mcr1 = 0;
1445
1446 /*
1447 * HPT371 chips physically have only one channel, the secondary one,
1448 * but the primary channel registers do exist! Go figure...
1449 * So, we manually disable the non-existing channel here
1450 * (if the BIOS hasn't done this already).
1451 */
1452 pci_read_config_byte(dev, 0x50, &mcr1);
1453 if (mcr1 & 0x04)
1454 pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04));
1455
1456 return ide_setup_pci_device(dev, d);
1457}
1458
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d)
1460{
1461 struct pci_dev *findev = NULL;
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001462 u8 rev = 0, pin1 = 0, pin2 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 char *chipset_names[] = {"HPT366", "HPT366", "HPT368",
1464 "HPT370", "HPT370A", "HPT372",
1465 "HPT372N" };
1466
1467 if (PCI_FUNC(dev->devfn) & 1)
1468 return -ENODEV;
1469
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001470 pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 if(dev->device == PCI_DEVICE_ID_TTI_HPT372N)
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001473 rev = 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001475 if(rev <= 6)
1476 d->name = chipset_names[rev];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Sergei Shtylyove139b0b2007-02-07 18:17:37 +01001478 switch(rev) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 case 6:
1480 case 5:
1481 case 4:
1482 case 3:
1483 goto init_single;
1484 default:
1485 break;
1486 }
1487
1488 d->channels = 1;
1489
1490 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
1491 while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) {
1492 if ((findev->vendor == dev->vendor) &&
1493 (findev->device == dev->device) &&
1494 ((findev->devfn - dev->devfn) == 1) &&
1495 (PCI_FUNC(findev->devfn) & 1)) {
1496 pci_read_config_byte(findev, PCI_INTERRUPT_PIN, &pin2);
1497 if ((pin1 != pin2) && (dev->irq == findev->irq)) {
1498 d->bootable = ON_BOARD;
1499 printk("%s: onboard version of chipset, "
1500 "pin1=%d pin2=%d\n", d->name,
1501 pin1, pin2);
1502 }
1503 return ide_setup_pci_devices(dev, findev, d);
1504 }
1505 }
1506init_single:
1507 return ide_setup_pci_device(dev, d);
1508}
1509
1510static ide_pci_device_t hpt366_chipsets[] __devinitdata = {
1511 { /* 0 */
1512 .name = "HPT366",
1513 .init_setup = init_setup_hpt366,
1514 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001515 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 .init_hwif = init_hwif_hpt366,
1517 .init_dma = init_dma_hpt366,
1518 .channels = 2,
1519 .autodma = AUTODMA,
1520 .bootable = OFF_BOARD,
1521 .extra = 240
1522 },{ /* 1 */
1523 .name = "HPT372A",
1524 .init_setup = init_setup_hpt37x,
1525 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001526 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 .init_hwif = init_hwif_hpt366,
1528 .init_dma = init_dma_hpt366,
1529 .channels = 2,
1530 .autodma = AUTODMA,
1531 .bootable = OFF_BOARD,
1532 },{ /* 2 */
1533 .name = "HPT302",
1534 .init_setup = init_setup_hpt37x,
1535 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001536 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 .init_hwif = init_hwif_hpt366,
1538 .init_dma = init_dma_hpt366,
1539 .channels = 2,
1540 .autodma = AUTODMA,
1541 .bootable = OFF_BOARD,
1542 },{ /* 3 */
1543 .name = "HPT371",
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001544 .init_setup = init_setup_hpt371,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001546 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 .init_hwif = init_hwif_hpt366,
1548 .init_dma = init_dma_hpt366,
1549 .channels = 2,
1550 .autodma = AUTODMA,
Sergei Shtylyov836c0062006-12-13 00:35:47 -08001551 .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 .bootable = OFF_BOARD,
1553 },{ /* 4 */
1554 .name = "HPT374",
1555 .init_setup = init_setup_hpt374,
1556 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001557 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 .init_hwif = init_hwif_hpt366,
1559 .init_dma = init_dma_hpt366,
1560 .channels = 2, /* 4 */
1561 .autodma = AUTODMA,
1562 .bootable = OFF_BOARD,
1563 },{ /* 5 */
1564 .name = "HPT372N",
1565 .init_setup = init_setup_hpt37x,
1566 .init_chipset = init_chipset_hpt366,
Alan Coxb39b01f2005-06-27 15:24:27 -07001567 .init_iops = init_iops_hpt366,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 .init_hwif = init_hwif_hpt366,
1569 .init_dma = init_dma_hpt366,
1570 .channels = 2, /* 4 */
1571 .autodma = AUTODMA,
1572 .bootable = OFF_BOARD,
1573 }
1574};
1575
1576/**
1577 * hpt366_init_one - called when an HPT366 is found
1578 * @dev: the hpt366 device
1579 * @id: the matching pci id
1580 *
1581 * Called when the PCI registration layer (or the IDE initialization)
1582 * finds a device matching our IDE device tables.
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001583 *
1584 * NOTE: since we'll have to modify some fields of the ide_pci_device_t
1585 * structure depending on the chip's revision, we'd better pass a local
1586 * copy down the call chain...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
1589{
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001590 ide_pci_device_t d = hpt366_chipsets[id->driver_data];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
Sergei Shtylyov73d1dd92006-12-13 00:35:51 -08001592 return d.init_setup(dev, &d);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593}
1594
1595static struct pci_device_id hpt366_pci_tbl[] = {
1596 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
1597 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
1598 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
1599 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
1600 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
1601 { PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372N, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
1602 { 0, },
1603};
1604MODULE_DEVICE_TABLE(pci, hpt366_pci_tbl);
1605
1606static struct pci_driver driver = {
1607 .name = "HPT366_IDE",
1608 .id_table = hpt366_pci_tbl,
1609 .probe = hpt366_init_one,
1610};
1611
Bartlomiej Zolnierkiewicz82ab1ee2007-01-27 13:46:56 +01001612static int __init hpt366_ide_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613{
1614 return ide_pci_register_driver(&driver);
1615}
1616
1617module_init(hpt366_ide_init);
1618
1619MODULE_AUTHOR("Andre Hedrick");
1620MODULE_DESCRIPTION("PCI driver module for Highpoint HPT366 IDE");
1621MODULE_LICENSE("GPL");