| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
| Bartlomiej Zolnierkiewicz | 95ba8c1 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 2 |  * linux/drivers/ide/pci/alim15x3.c		Version 0.25	Jun 9 2007 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3 |  * | 
 | 4 |  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer | 
 | 5 |  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer | 
 | 6 |  *  Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer | 
 | 7 |  * | 
 | 8 |  *  Copyright (C) 1998-2000 Andre Hedrick (andre@linux-ide.org) | 
 | 9 |  *  May be copied or modified under the terms of the GNU General Public License | 
 | 10 |  *  Copyright (C) 2002 Alan Cox <alan@redhat.com> | 
 | 11 |  *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw> | 
| Sergei Shtylyov | 21b8247 | 2007-03-03 17:48:52 +0100 | [diff] [blame] | 12 |  *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com> | 
| Bartlomiej Zolnierkiewicz | 95ba8c1 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 13 |  *  Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 14 |  * | 
 | 15 |  *  (U)DMA capable version of ali 1533/1543(C), 1535(D) | 
 | 16 |  * | 
 | 17 |  ********************************************************************** | 
 | 18 |  *  9/7/99 --Parts from the above author are included and need to be | 
 | 19 |  *  converted into standard interface, once I finish the thought. | 
 | 20 |  * | 
 | 21 |  *  Recent changes | 
 | 22 |  *	Don't use LBA48 mode on ALi <= 0xC4 | 
 | 23 |  *	Don't poke 0x79 with a non ALi northbridge | 
 | 24 |  *	Don't flip undefined bits on newer chipsets (fix Fujitsu laptop hang) | 
 | 25 |  *	Allow UDMA6 on revisions > 0xC4 | 
 | 26 |  * | 
 | 27 |  *  Documentation | 
 | 28 |  *	Chipset documentation available under NDA only | 
 | 29 |  * | 
 | 30 |  */ | 
 | 31 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 32 | #include <linux/module.h> | 
 | 33 | #include <linux/types.h> | 
 | 34 | #include <linux/kernel.h> | 
 | 35 | #include <linux/pci.h> | 
 | 36 | #include <linux/delay.h> | 
 | 37 | #include <linux/hdreg.h> | 
 | 38 | #include <linux/ide.h> | 
 | 39 | #include <linux/init.h> | 
| Bartlomiej Zolnierkiewicz | 95ba8c1 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 40 | #include <linux/dmi.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 41 |  | 
 | 42 | #include <asm/io.h> | 
 | 43 |  | 
 | 44 | #define DISPLAY_ALI_TIMINGS | 
 | 45 |  | 
 | 46 | /* | 
 | 47 |  *	ALi devices are not plug in. Otherwise these static values would | 
 | 48 |  *	need to go. They ought to go away anyway | 
 | 49 |  */ | 
 | 50 |   | 
 | 51 | static u8 m5229_revision; | 
 | 52 | static u8 chip_is_1543c_e; | 
 | 53 | static struct pci_dev *isa_dev; | 
 | 54 |  | 
| Bartlomiej Zolnierkiewicz | ecfd80e | 2007-05-10 00:01:09 +0200 | [diff] [blame] | 55 | #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 56 | #include <linux/stat.h> | 
 | 57 | #include <linux/proc_fs.h> | 
 | 58 |  | 
 | 59 | static u8 ali_proc = 0; | 
 | 60 |  | 
 | 61 | static struct pci_dev *bmide_dev; | 
 | 62 |  | 
 | 63 | static char *fifo[4] = { | 
 | 64 | 	"FIFO Off", | 
 | 65 | 	"FIFO On ", | 
 | 66 | 	"DMA mode", | 
 | 67 | 	"PIO mode" }; | 
 | 68 |  | 
 | 69 | static char *udmaT[8] = { | 
 | 70 | 	"1.5T", | 
 | 71 | 	"  2T", | 
 | 72 | 	"2.5T", | 
 | 73 | 	"  3T", | 
 | 74 | 	"3.5T", | 
 | 75 | 	"  4T", | 
 | 76 | 	"  6T", | 
 | 77 | 	"  8T" | 
 | 78 | }; | 
 | 79 |  | 
 | 80 | static char *channel_status[8] = { | 
 | 81 | 	"OK            ", | 
 | 82 | 	"busy          ", | 
 | 83 | 	"DRQ           ", | 
 | 84 | 	"DRQ busy      ", | 
 | 85 | 	"error         ", | 
 | 86 | 	"error busy    ", | 
 | 87 | 	"error DRQ     ", | 
 | 88 | 	"error DRQ busy" | 
 | 89 | }; | 
 | 90 |  | 
 | 91 | /** | 
 | 92 |  *	ali_get_info		-	generate proc file for ALi IDE | 
 | 93 |  *	@buffer: buffer to fill | 
 | 94 |  *	@addr: address of user start in buffer | 
 | 95 |  *	@offset: offset into 'file' | 
 | 96 |  *	@count: buffer count | 
 | 97 |  * | 
 | 98 |  *	Walks the Ali devices and outputs summary data on the tuning and | 
 | 99 |  *	anything else that will help with debugging | 
 | 100 |  */ | 
 | 101 |   | 
 | 102 | static int ali_get_info (char *buffer, char **addr, off_t offset, int count) | 
 | 103 | { | 
 | 104 | 	unsigned long bibma; | 
 | 105 | 	u8 reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1, c0, c1, rev, tmp; | 
 | 106 | 	char *q, *p = buffer; | 
 | 107 |  | 
 | 108 | 	/* fetch rev. */ | 
 | 109 | 	pci_read_config_byte(bmide_dev, 0x08, &rev); | 
 | 110 | 	if (rev >= 0xc1)	/* M1543C or newer */ | 
 | 111 | 		udmaT[7] = " ???"; | 
 | 112 | 	else | 
 | 113 | 		fifo[3]  = "   ???  "; | 
 | 114 |  | 
 | 115 | 	/* first fetch bibma: */ | 
 | 116 | 	 | 
 | 117 | 	bibma = pci_resource_start(bmide_dev, 4); | 
 | 118 |  | 
 | 119 | 	/* | 
 | 120 | 	 * at that point bibma+0x2 et bibma+0xa are byte | 
 | 121 | 	 * registers to investigate: | 
 | 122 | 	 */ | 
 | 123 | 	c0 = inb(bibma + 0x02); | 
 | 124 | 	c1 = inb(bibma + 0x0a); | 
 | 125 |  | 
 | 126 | 	p += sprintf(p, | 
 | 127 | 		"\n                                Ali M15x3 Chipset.\n"); | 
 | 128 | 	p += sprintf(p, | 
 | 129 | 		"                                ------------------\n"); | 
 | 130 | 	pci_read_config_byte(bmide_dev, 0x78, ®53h); | 
 | 131 | 	p += sprintf(p, "PCI Clock: %d.\n", reg53h); | 
 | 132 |  | 
 | 133 | 	pci_read_config_byte(bmide_dev, 0x53, ®53h); | 
 | 134 | 	p += sprintf(p, | 
 | 135 | 		"CD_ROM FIFO:%s, CD_ROM DMA:%s\n", | 
 | 136 | 		(reg53h & 0x02) ? "Yes" : "No ", | 
 | 137 | 		(reg53h & 0x01) ? "Yes" : "No " ); | 
 | 138 | 	pci_read_config_byte(bmide_dev, 0x74, ®53h); | 
 | 139 | 	p += sprintf(p, | 
 | 140 | 		"FIFO Status: contains %d Words, runs%s%s\n\n", | 
 | 141 | 		(reg53h & 0x3f), | 
 | 142 | 		(reg53h & 0x40) ? " OVERWR" : "", | 
 | 143 | 		(reg53h & 0x80) ? " OVERRD." : "." ); | 
 | 144 |  | 
 | 145 | 	p += sprintf(p, | 
 | 146 | 		"-------------------primary channel" | 
 | 147 | 		"-------------------secondary channel" | 
 | 148 | 		"---------\n\n"); | 
 | 149 |  | 
 | 150 | 	pci_read_config_byte(bmide_dev, 0x09, ®53h); | 
 | 151 | 	p += sprintf(p, | 
 | 152 | 		"channel status:       %s" | 
 | 153 | 		"                               %s\n", | 
 | 154 | 		(reg53h & 0x20) ? "On " : "Off", | 
 | 155 | 		(reg53h & 0x10) ? "On " : "Off" ); | 
 | 156 |  | 
 | 157 | 	p += sprintf(p, | 
 | 158 | 		"both channels togth:  %s" | 
 | 159 | 		"                               %s\n", | 
 | 160 | 		(c0&0x80) ? "No " : "Yes", | 
 | 161 | 		(c1&0x80) ? "No " : "Yes" ); | 
 | 162 |  | 
 | 163 | 	pci_read_config_byte(bmide_dev, 0x76, ®53h); | 
 | 164 | 	p += sprintf(p, | 
 | 165 | 		"Channel state:        %s                    %s\n", | 
 | 166 | 		channel_status[reg53h & 0x07], | 
 | 167 | 		channel_status[(reg53h & 0x70) >> 4] ); | 
 | 168 |  | 
 | 169 | 	pci_read_config_byte(bmide_dev, 0x58, ®5xh); | 
 | 170 | 	pci_read_config_byte(bmide_dev, 0x5c, ®5yh); | 
 | 171 | 	p += sprintf(p, | 
 | 172 | 		"Add. Setup Timing:    %dT" | 
 | 173 | 		"                                %dT\n", | 
 | 174 | 		(reg5xh & 0x07) ? (reg5xh & 0x07) : 8, | 
 | 175 | 		(reg5yh & 0x07) ? (reg5yh & 0x07) : 8 ); | 
 | 176 |  | 
 | 177 | 	pci_read_config_byte(bmide_dev, 0x59, ®5xh); | 
 | 178 | 	pci_read_config_byte(bmide_dev, 0x5d, ®5yh); | 
 | 179 | 	p += sprintf(p, | 
 | 180 | 		"Command Act. Count:   %dT" | 
 | 181 | 		"                                %dT\n" | 
 | 182 | 		"Command Rec. Count:   %dT" | 
 | 183 | 		"                               %dT\n\n", | 
 | 184 | 		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, | 
 | 185 | 		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,  | 
 | 186 | 		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, | 
 | 187 | 		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 ); | 
 | 188 |  | 
 | 189 | 	p += sprintf(p, | 
 | 190 | 		"----------------drive0-----------drive1" | 
 | 191 | 		"------------drive0-----------drive1------\n\n"); | 
 | 192 | 	p += sprintf(p, | 
 | 193 | 		"DMA enabled:      %s              %s" | 
 | 194 | 		"               %s              %s\n", | 
 | 195 | 		(c0&0x20) ? "Yes" : "No ", | 
 | 196 | 		(c0&0x40) ? "Yes" : "No ", | 
 | 197 | 		(c1&0x20) ? "Yes" : "No ", | 
 | 198 | 		(c1&0x40) ? "Yes" : "No " ); | 
 | 199 |  | 
 | 200 | 	pci_read_config_byte(bmide_dev, 0x54, ®5xh); | 
 | 201 | 	pci_read_config_byte(bmide_dev, 0x55, ®5yh); | 
 | 202 | 	q = "FIFO threshold:   %2d Words         %2d Words" | 
 | 203 | 		"          %2d Words         %2d Words\n"; | 
 | 204 | 	if (rev < 0xc1) { | 
 | 205 | 		if ((rev == 0x20) && | 
 | 206 | 		    (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) { | 
 | 207 | 			p += sprintf(p, q, 8, 8, 8, 8); | 
 | 208 | 		} else { | 
 | 209 | 			p += sprintf(p, q, | 
 | 210 | 				(reg5xh & 0x03) + 12, | 
 | 211 | 				((reg5xh & 0x30)>>4) + 12, | 
 | 212 | 				(reg5yh & 0x03) + 12, | 
 | 213 | 				((reg5yh & 0x30)>>4) + 12 ); | 
 | 214 | 		} | 
 | 215 | 	} else { | 
 | 216 | 		int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4; | 
 | 217 | 		int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4; | 
 | 218 | 		int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4; | 
 | 219 | 		int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4; | 
 | 220 | 		p += sprintf(p, q, t1, t2, t3, t4); | 
 | 221 | 	} | 
 | 222 |  | 
 | 223 | #if 0 | 
 | 224 | 	p += sprintf(p,  | 
 | 225 | 		"FIFO threshold:   %2d Words         %2d Words" | 
 | 226 | 		"          %2d Words         %2d Words\n", | 
 | 227 | 		(reg5xh & 0x03) + 12, | 
 | 228 | 		((reg5xh & 0x30)>>4) + 12, | 
 | 229 | 		(reg5yh & 0x03) + 12, | 
 | 230 | 		((reg5yh & 0x30)>>4) + 12 ); | 
 | 231 | #endif | 
 | 232 |  | 
 | 233 | 	p += sprintf(p, | 
 | 234 | 		"FIFO mode:        %s         %s          %s         %s\n", | 
 | 235 | 		fifo[((reg5xh & 0x0c) >> 2)], | 
 | 236 | 		fifo[((reg5xh & 0xc0) >> 6)], | 
 | 237 | 		fifo[((reg5yh & 0x0c) >> 2)], | 
 | 238 | 		fifo[((reg5yh & 0xc0) >> 6)] ); | 
 | 239 |  | 
 | 240 | 	pci_read_config_byte(bmide_dev, 0x5a, ®5xh); | 
 | 241 | 	pci_read_config_byte(bmide_dev, 0x5b, ®5xh1); | 
 | 242 | 	pci_read_config_byte(bmide_dev, 0x5e, ®5yh); | 
 | 243 | 	pci_read_config_byte(bmide_dev, 0x5f, ®5yh1); | 
 | 244 |  | 
 | 245 | 	p += sprintf(p,/* | 
 | 246 | 		"------------------drive0-----------drive1" | 
 | 247 | 		"------------drive0-----------drive1------\n")*/ | 
 | 248 | 		"Dt RW act. Cnt    %2dT              %2dT" | 
 | 249 | 		"               %2dT              %2dT\n" | 
 | 250 | 		"Dt RW rec. Cnt    %2dT              %2dT" | 
 | 251 | 		"               %2dT              %2dT\n\n", | 
 | 252 | 		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8, | 
 | 253 | 		(reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8, | 
 | 254 | 		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, | 
 | 255 | 		(reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8, | 
 | 256 | 		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16, | 
 | 257 | 		(reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16, | 
 | 258 | 		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16, | 
 | 259 | 		(reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 ); | 
 | 260 |  | 
 | 261 | 	p += sprintf(p, | 
 | 262 | 		"-----------------------------------UDMA Timings" | 
 | 263 | 		"--------------------------------\n\n"); | 
 | 264 |  | 
 | 265 | 	pci_read_config_byte(bmide_dev, 0x56, ®5xh); | 
 | 266 | 	pci_read_config_byte(bmide_dev, 0x57, ®5yh); | 
 | 267 | 	p += sprintf(p, | 
 | 268 | 		"UDMA:             %s               %s" | 
 | 269 | 		"                %s               %s\n" | 
 | 270 | 		"UDMA timings:     %s             %s" | 
 | 271 | 		"              %s             %s\n\n", | 
 | 272 | 		(reg5xh & 0x08) ? "OK" : "No", | 
 | 273 | 		(reg5xh & 0x80) ? "OK" : "No", | 
 | 274 | 		(reg5yh & 0x08) ? "OK" : "No", | 
 | 275 | 		(reg5yh & 0x80) ? "OK" : "No", | 
 | 276 | 		udmaT[(reg5xh & 0x07)], | 
 | 277 | 		udmaT[(reg5xh & 0x70) >> 4], | 
 | 278 | 		udmaT[reg5yh & 0x07], | 
 | 279 | 		udmaT[(reg5yh & 0x70) >> 4] ); | 
 | 280 |  | 
 | 281 | 	return p-buffer; /* => must be less than 4k! */ | 
 | 282 | } | 
| Bartlomiej Zolnierkiewicz | ecfd80e | 2007-05-10 00:01:09 +0200 | [diff] [blame] | 283 | #endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 284 |  | 
 | 285 | /** | 
| Sergei Shtylyov | 21b8247 | 2007-03-03 17:48:52 +0100 | [diff] [blame] | 286 |  *	ali15x3_tune_pio	-	set up chipset for PIO mode | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 287 |  *	@drive: drive to tune | 
| Sergei Shtylyov | 21b8247 | 2007-03-03 17:48:52 +0100 | [diff] [blame] | 288 |  *	@pio: desired mode | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 289 |  * | 
| Sergei Shtylyov | 21b8247 | 2007-03-03 17:48:52 +0100 | [diff] [blame] | 290 |  *	Select the best PIO mode for the drive in question. | 
 | 291 |  *	Then program the controller for this mode. | 
 | 292 |  * | 
 | 293 |  *	Returns the PIO mode programmed. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 294 |  */ | 
 | 295 |   | 
| Sergei Shtylyov | 21b8247 | 2007-03-03 17:48:52 +0100 | [diff] [blame] | 296 | static u8 ali15x3_tune_pio (ide_drive_t *drive, u8 pio) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 297 | { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 298 | 	ide_hwif_t *hwif = HWIF(drive); | 
 | 299 | 	struct pci_dev *dev = hwif->pci_dev; | 
 | 300 | 	int s_time, a_time, c_time; | 
 | 301 | 	u8 s_clc, a_clc, r_clc; | 
 | 302 | 	unsigned long flags; | 
 | 303 | 	int bus_speed = system_bus_clock(); | 
 | 304 | 	int port = hwif->channel ? 0x5c : 0x58; | 
 | 305 | 	int portFIFO = hwif->channel ? 0x55 : 0x54; | 
 | 306 | 	u8 cd_dma_fifo = 0; | 
 | 307 | 	int unit = drive->select.b.unit & 1; | 
 | 308 |  | 
| Bartlomiej Zolnierkiewicz | 2134758 | 2007-07-20 01:11:58 +0200 | [diff] [blame] | 309 | 	pio = ide_get_best_pio_mode(drive, pio, 5); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 310 | 	s_time = ide_pio_timings[pio].setup_time; | 
 | 311 | 	a_time = ide_pio_timings[pio].active_time; | 
 | 312 | 	if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) | 
 | 313 | 		s_clc = 0; | 
 | 314 | 	if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) | 
 | 315 | 		a_clc = 0; | 
 | 316 | 	c_time = ide_pio_timings[pio].cycle_time; | 
 | 317 |  | 
 | 318 | #if 0 | 
 | 319 | 	if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) | 
 | 320 | 		r_clc = 0; | 
 | 321 | #endif | 
 | 322 |  | 
 | 323 | 	if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { | 
 | 324 | 		r_clc = 1; | 
 | 325 | 	} else { | 
 | 326 | 		if (r_clc >= 16) | 
 | 327 | 			r_clc = 0; | 
 | 328 | 	} | 
 | 329 | 	local_irq_save(flags); | 
 | 330 | 	 | 
 | 331 | 	/*  | 
 | 332 | 	 * PIO mode => ATA FIFO on, ATAPI FIFO off | 
 | 333 | 	 */ | 
 | 334 | 	pci_read_config_byte(dev, portFIFO, &cd_dma_fifo); | 
 | 335 | 	if (drive->media==ide_disk) { | 
 | 336 | 		if (unit) { | 
 | 337 | 			pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0x0F) | 0x50); | 
 | 338 | 		} else { | 
 | 339 | 			pci_write_config_byte(dev, portFIFO, (cd_dma_fifo & 0xF0) | 0x05); | 
 | 340 | 		} | 
 | 341 | 	} else { | 
 | 342 | 		if (unit) { | 
 | 343 | 			pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0x0F); | 
 | 344 | 		} else { | 
 | 345 | 			pci_write_config_byte(dev, portFIFO, cd_dma_fifo & 0xF0); | 
 | 346 | 		} | 
 | 347 | 	} | 
 | 348 | 	 | 
 | 349 | 	pci_write_config_byte(dev, port, s_clc); | 
 | 350 | 	pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); | 
 | 351 | 	local_irq_restore(flags); | 
 | 352 |  | 
 | 353 | 	/* | 
 | 354 | 	 * setup   active  rec | 
 | 355 | 	 * { 70,   165,    365 },   PIO Mode 0 | 
 | 356 | 	 * { 50,   125,    208 },   PIO Mode 1 | 
 | 357 | 	 * { 30,   100,    110 },   PIO Mode 2 | 
 | 358 | 	 * { 30,   80,     70  },   PIO Mode 3 with IORDY | 
 | 359 | 	 * { 25,   70,     25  },   PIO Mode 4 with IORDY  ns | 
 | 360 | 	 * { 20,   50,     30  }    PIO Mode 5 with IORDY (nonstandard) | 
 | 361 | 	 */ | 
 | 362 |  | 
| Sergei Shtylyov | 21b8247 | 2007-03-03 17:48:52 +0100 | [diff] [blame] | 363 | 	return pio; | 
 | 364 | } | 
 | 365 |  | 
 | 366 | /** | 
 | 367 |  *	ali15x3_tune_drive	-	set up drive for PIO mode | 
 | 368 |  *	@drive: drive to tune | 
 | 369 |  *	@pio: desired mode | 
 | 370 |  * | 
 | 371 |  *	Program the controller with the best PIO timing for the given drive. | 
 | 372 |  *	Then set up the drive itself. | 
 | 373 |  */ | 
 | 374 |  | 
 | 375 | static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio) | 
 | 376 | { | 
 | 377 | 	pio = ali15x3_tune_pio(drive, pio); | 
 | 378 | 	(void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 379 | } | 
 | 380 |  | 
 | 381 | /** | 
| Bartlomiej Zolnierkiewicz | 2d5eaa6 | 2007-05-10 00:01:08 +0200 | [diff] [blame] | 382 |  *	ali_udma_filter		-	compute UDMA mask | 
 | 383 |  *	@drive: IDE device | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 384 |  * | 
| Bartlomiej Zolnierkiewicz | 2d5eaa6 | 2007-05-10 00:01:08 +0200 | [diff] [blame] | 385 |  *	Return available UDMA modes. | 
 | 386 |  * | 
 | 387 |  *	The actual rules for the ALi are: | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 388 |  *		No UDMA on revisions <= 0x20 | 
 | 389 |  *		Disk only for revisions < 0xC2 | 
 | 390 |  *		Not WDC drives for revisions < 0xC2 | 
 | 391 |  * | 
 | 392 |  *	FIXME: WDC ifdef needs to die | 
 | 393 |  */ | 
| Bartlomiej Zolnierkiewicz | 2d5eaa6 | 2007-05-10 00:01:08 +0200 | [diff] [blame] | 394 |  | 
 | 395 | static u8 ali_udma_filter(ide_drive_t *drive) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 396 | { | 
| Bartlomiej Zolnierkiewicz | 2d5eaa6 | 2007-05-10 00:01:08 +0200 | [diff] [blame] | 397 | 	if (m5229_revision > 0x20 && m5229_revision < 0xC2) { | 
 | 398 | 		if (drive->media != ide_disk) | 
 | 399 | 			return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 400 | #ifndef CONFIG_WDC_ALI15X3 | 
| Bartlomiej Zolnierkiewicz | 2d5eaa6 | 2007-05-10 00:01:08 +0200 | [diff] [blame] | 401 | 		if (chip_is_1543c_e && strstr(drive->id->model, "WDC ")) | 
 | 402 | 			return 0; | 
 | 403 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 404 | 	} | 
 | 405 |  | 
| Bartlomiej Zolnierkiewicz | 2d5eaa6 | 2007-05-10 00:01:08 +0200 | [diff] [blame] | 406 | 	return drive->hwif->ultra_mask; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 407 | } | 
 | 408 |  | 
 | 409 | /** | 
| Sergei Shtylyov | 21b8247 | 2007-03-03 17:48:52 +0100 | [diff] [blame] | 410 |  *	ali15x3_tune_chipset	-	set up chipset/drive for new speed | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 411 |  *	@drive: drive to configure for | 
 | 412 |  *	@xferspeed: desired speed | 
 | 413 |  * | 
 | 414 |  *	Configure the hardware for the desired IDE transfer mode. | 
 | 415 |  *	We also do the needed drive configuration through helpers | 
 | 416 |  */ | 
 | 417 |   | 
 | 418 | static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) | 
 | 419 | { | 
 | 420 | 	ide_hwif_t *hwif	= HWIF(drive); | 
 | 421 | 	struct pci_dev *dev	= hwif->pci_dev; | 
| Bartlomiej Zolnierkiewicz | 2d5eaa6 | 2007-05-10 00:01:08 +0200 | [diff] [blame] | 422 | 	u8 speed		= ide_rate_filter(drive, xferspeed); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 423 | 	u8 speed1		= speed; | 
 | 424 | 	u8 unit			= (drive->select.b.unit & 0x01); | 
 | 425 | 	u8 tmpbyte		= 0x00; | 
 | 426 | 	int m5229_udma		= (hwif->channel) ? 0x57 : 0x56; | 
 | 427 |  | 
 | 428 | 	if (speed == XFER_UDMA_6) | 
 | 429 | 		speed1 = 0x47; | 
 | 430 |  | 
 | 431 | 	if (speed < XFER_UDMA_0) { | 
 | 432 | 		u8 ultra_enable	= (unit) ? 0x7f : 0xf7; | 
 | 433 | 		/* | 
 | 434 | 		 * clear "ultra enable" bit | 
 | 435 | 		 */ | 
 | 436 | 		pci_read_config_byte(dev, m5229_udma, &tmpbyte); | 
 | 437 | 		tmpbyte &= ultra_enable; | 
 | 438 | 		pci_write_config_byte(dev, m5229_udma, tmpbyte); | 
 | 439 |  | 
 | 440 | 		if (speed < XFER_SW_DMA_0) | 
| Sergei Shtylyov | 21b8247 | 2007-03-03 17:48:52 +0100 | [diff] [blame] | 441 | 			(void) ali15x3_tune_pio(drive, speed - XFER_PIO_0); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 442 | 	} else { | 
 | 443 | 		pci_read_config_byte(dev, m5229_udma, &tmpbyte); | 
 | 444 | 		tmpbyte &= (0x0f << ((1-unit) << 2)); | 
 | 445 | 		/* | 
 | 446 | 		 * enable ultra dma and set timing | 
 | 447 | 		 */ | 
 | 448 | 		tmpbyte |= ((0x08 | ((4-speed1)&0x07)) << (unit << 2)); | 
 | 449 | 		pci_write_config_byte(dev, m5229_udma, tmpbyte); | 
 | 450 | 		if (speed >= XFER_UDMA_3) { | 
 | 451 | 			pci_read_config_byte(dev, 0x4b, &tmpbyte); | 
 | 452 | 			tmpbyte |= 1; | 
 | 453 | 			pci_write_config_byte(dev, 0x4b, tmpbyte); | 
 | 454 | 		} | 
 | 455 | 	} | 
 | 456 | 	return (ide_config_drive_speed(drive, speed)); | 
 | 457 | } | 
 | 458 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 459 | /** | 
 | 460 |  *	ali15x3_config_drive_for_dma	-	configure for DMA | 
 | 461 |  *	@drive: drive to configure | 
 | 462 |  * | 
 | 463 |  *	Configure a drive for DMA operation. If DMA is not possible we | 
 | 464 |  *	drop the drive into PIO mode instead. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 465 |  */ | 
| Bartlomiej Zolnierkiewicz | 3608b5d | 2007-02-17 02:40:26 +0100 | [diff] [blame] | 466 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 467 | static int ali15x3_config_drive_for_dma(ide_drive_t *drive) | 
 | 468 | { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 469 | 	drive->init_speed = 0; | 
 | 470 |  | 
| Bartlomiej Zolnierkiewicz | 38ff8a7 | 2007-05-16 00:51:43 +0200 | [diff] [blame] | 471 | 	if (ide_tune_dma(drive)) | 
 | 472 | 		return 0; | 
| Bartlomiej Zolnierkiewicz | 3608b5d | 2007-02-17 02:40:26 +0100 | [diff] [blame] | 473 |  | 
| Bartlomiej Zolnierkiewicz | 38ff8a7 | 2007-05-16 00:51:43 +0200 | [diff] [blame] | 474 | 	ali15x3_tune_drive(drive, 255); | 
 | 475 |  | 
 | 476 | 	return -1; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 477 | } | 
 | 478 |  | 
 | 479 | /** | 
 | 480 |  *	ali15x3_dma_setup	-	begin a DMA phase | 
 | 481 |  *	@drive:	target device | 
 | 482 |  * | 
 | 483 |  *	Returns 1 if the DMA cannot be performed, zero on success. | 
 | 484 |  */ | 
 | 485 |  | 
 | 486 | static int ali15x3_dma_setup(ide_drive_t *drive) | 
 | 487 | { | 
 | 488 | 	if (m5229_revision < 0xC2 && drive->media != ide_disk) { | 
 | 489 | 		if (rq_data_dir(drive->hwif->hwgroup->rq)) | 
 | 490 | 			return 1;	/* try PIO instead of DMA */ | 
 | 491 | 	} | 
 | 492 | 	return ide_dma_setup(drive); | 
 | 493 | } | 
 | 494 |  | 
 | 495 | /** | 
 | 496 |  *	init_chipset_ali15x3	-	Initialise an ALi IDE controller | 
 | 497 |  *	@dev: PCI device | 
 | 498 |  *	@name: Name of the controller | 
 | 499 |  * | 
 | 500 |  *	This function initializes the ALI IDE controller and where  | 
 | 501 |  *	appropriate also sets up the 1533 southbridge. | 
 | 502 |  */ | 
 | 503 |    | 
| Herbert Xu | c2f1258 | 2005-07-03 16:06:13 +0200 | [diff] [blame] | 504 | static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const char *name) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 505 | { | 
 | 506 | 	unsigned long flags; | 
 | 507 | 	u8 tmpbyte; | 
| Alan Cox | b148900 | 2006-12-08 02:39:58 -0800 | [diff] [blame] | 508 | 	struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 509 |  | 
| Auke Kok | 44c1013 | 2007-06-08 15:46:36 -0700 | [diff] [blame] | 510 | 	m5229_revision = dev->revision; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 511 |  | 
| Alan Cox | b148900 | 2006-12-08 02:39:58 -0800 | [diff] [blame] | 512 | 	isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 513 |  | 
| Bartlomiej Zolnierkiewicz | ecfd80e | 2007-05-10 00:01:09 +0200 | [diff] [blame] | 514 | #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 515 | 	if (!ali_proc) { | 
 | 516 | 		ali_proc = 1; | 
 | 517 | 		bmide_dev = dev; | 
 | 518 | 		ide_pci_create_host_proc("ali", ali_get_info); | 
 | 519 | 	} | 
| Bartlomiej Zolnierkiewicz | ecfd80e | 2007-05-10 00:01:09 +0200 | [diff] [blame] | 520 | #endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 521 |  | 
 | 522 | 	local_irq_save(flags); | 
 | 523 |  | 
 | 524 | 	if (m5229_revision < 0xC2) { | 
 | 525 | 		/* | 
 | 526 | 		 * revision 0x20 (1543-E, 1543-F) | 
 | 527 | 		 * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) | 
 | 528 | 		 * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 | 
 | 529 | 		 */ | 
 | 530 | 		pci_read_config_byte(dev, 0x4b, &tmpbyte); | 
 | 531 | 		/* | 
 | 532 | 		 * clear bit 7 | 
 | 533 | 		 */ | 
 | 534 | 		pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); | 
| Alan Cox | b148900 | 2006-12-08 02:39:58 -0800 | [diff] [blame] | 535 | 		goto out; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 536 | 	} | 
 | 537 |  | 
 | 538 | 	/* | 
 | 539 | 	 * 1543C-B?, 1535, 1535D, 1553 | 
 | 540 | 	 * Note 1: not all "motherboard" support this detection | 
 | 541 | 	 * Note 2: if no udma 66 device, the detection may "error". | 
 | 542 | 	 *         but in this case, we will not set the device to | 
 | 543 | 	 *         ultra 66, the detection result is not important | 
 | 544 | 	 */ | 
 | 545 |  | 
 | 546 | 	/* | 
 | 547 | 	 * enable "Cable Detection", m5229, 0x4b, bit3 | 
 | 548 | 	 */ | 
 | 549 | 	pci_read_config_byte(dev, 0x4b, &tmpbyte); | 
 | 550 | 	pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); | 
 | 551 |  | 
 | 552 | 	/* | 
 | 553 | 	 * We should only tune the 1533 enable if we are using an ALi | 
 | 554 | 	 * North bridge. We might have no north found on some zany | 
 | 555 | 	 * box without a device at 0:0.0. The ALi bridge will be at | 
 | 556 | 	 * 0:0.0 so if we didn't find one we know what is cooking. | 
 | 557 | 	 */ | 
| Alan Cox | b148900 | 2006-12-08 02:39:58 -0800 | [diff] [blame] | 558 | 	if (north && north->vendor != PCI_VENDOR_ID_AL) | 
 | 559 | 		goto out; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 560 |  | 
 | 561 | 	if (m5229_revision < 0xC5 && isa_dev) | 
 | 562 | 	{	 | 
 | 563 | 		/* | 
 | 564 | 		 * set south-bridge's enable bit, m1533, 0x79 | 
 | 565 | 		 */ | 
 | 566 |  | 
 | 567 | 		pci_read_config_byte(isa_dev, 0x79, &tmpbyte); | 
 | 568 | 		if (m5229_revision == 0xC2) { | 
 | 569 | 			/* | 
 | 570 | 			 * 1543C-B0 (m1533, 0x79, bit 2) | 
 | 571 | 			 */ | 
 | 572 | 			pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); | 
 | 573 | 		} else if (m5229_revision >= 0xC3) { | 
 | 574 | 			/* | 
 | 575 | 			 * 1553/1535 (m1533, 0x79, bit 1) | 
 | 576 | 			 */ | 
 | 577 | 			pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); | 
 | 578 | 		} | 
 | 579 | 	} | 
| Alan Cox | b148900 | 2006-12-08 02:39:58 -0800 | [diff] [blame] | 580 | out: | 
 | 581 | 	pci_dev_put(north); | 
 | 582 | 	pci_dev_put(isa_dev); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 583 | 	local_irq_restore(flags); | 
 | 584 | 	return 0; | 
 | 585 | } | 
 | 586 |  | 
| Bartlomiej Zolnierkiewicz | 95ba8c1 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 587 | /* | 
 | 588 |  *	Cable special cases | 
 | 589 |  */ | 
 | 590 |  | 
 | 591 | static struct dmi_system_id cable_dmi_table[] = { | 
 | 592 | 	{ | 
 | 593 | 		.ident = "HP Pavilion N5430", | 
 | 594 | 		.matches = { | 
 | 595 | 			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), | 
 | 596 | 			DMI_MATCH(DMI_BOARD_NAME, "OmniBook N32N-736"), | 
 | 597 | 		}, | 
 | 598 | 	}, | 
 | 599 | 	{ } | 
 | 600 | }; | 
 | 601 |  | 
 | 602 | static int ali_cable_override(struct pci_dev *pdev) | 
 | 603 | { | 
 | 604 | 	/* Fujitsu P2000 */ | 
 | 605 | 	if (pdev->subsystem_vendor == 0x10CF && | 
 | 606 | 	    pdev->subsystem_device == 0x10AF) | 
 | 607 | 		return 1; | 
 | 608 |  | 
 | 609 | 	/* Systems by DMI */ | 
 | 610 | 	if (dmi_check_system(cable_dmi_table)) | 
 | 611 | 		return 1; | 
 | 612 |  | 
 | 613 | 	return 0; | 
 | 614 | } | 
 | 615 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 616 | /** | 
 | 617 |  *	ata66_ali15x3	-	check for UDMA 66 support | 
 | 618 |  *	@hwif: IDE interface | 
 | 619 |  * | 
 | 620 |  *	This checks if the controller and the cable are capable | 
 | 621 |  *	of UDMA66 transfers. It doesn't check the drives. | 
 | 622 |  *	But see note 2 below! | 
 | 623 |  * | 
 | 624 |  *	FIXME: frobs bits that are not defined on newer ALi devicea | 
 | 625 |  */ | 
 | 626 |  | 
| Bartlomiej Zolnierkiewicz | 49521f9 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 627 | static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 628 | { | 
 | 629 | 	struct pci_dev *dev	= hwif->pci_dev; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 630 | 	unsigned long flags; | 
| Bartlomiej Zolnierkiewicz | 95ba8c1 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 631 | 	u8 cbl = ATA_CBL_PATA40, tmpbyte; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 632 |  | 
 | 633 | 	local_irq_save(flags); | 
 | 634 |  | 
 | 635 | 	if (m5229_revision >= 0xC2) { | 
 | 636 | 		/* | 
| Bartlomiej Zolnierkiewicz | 95ba8c1 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 637 | 		 * m5229 80-pin cable detection (from Host View) | 
 | 638 | 		 * | 
 | 639 | 		 * 0x4a bit0 is 0 => primary channel has 80-pin | 
 | 640 | 		 * 0x4a bit1 is 0 => secondary channel has 80-pin | 
 | 641 | 		 * | 
 | 642 | 		 * Certain laptops use short but suitable cables | 
 | 643 | 		 * and don't implement the detect logic. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 644 | 		 */ | 
| Bartlomiej Zolnierkiewicz | 95ba8c1 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 645 | 		if (ali_cable_override(dev)) | 
 | 646 | 			cbl = ATA_CBL_PATA40_SHORT; | 
 | 647 | 		else { | 
 | 648 | 			pci_read_config_byte(dev, 0x4a, &tmpbyte); | 
 | 649 | 			if ((tmpbyte & (1 << hwif->channel)) == 0) | 
 | 650 | 				cbl = ATA_CBL_PATA80; | 
 | 651 | 		} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 652 | 	} else { | 
 | 653 | 		/* | 
 | 654 | 		 * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 | 
 | 655 | 		 */ | 
 | 656 | 		pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); | 
 | 657 | 		chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; | 
 | 658 | 	} | 
 | 659 |  | 
 | 660 | 	/* | 
 | 661 | 	 * CD_ROM DMA on (m5229, 0x53, bit0) | 
 | 662 | 	 *      Enable this bit even if we want to use PIO | 
 | 663 | 	 * PIO FIFO off (m5229, 0x53, bit1) | 
 | 664 | 	 *      The hardware will use 0x54h and 0x55h to control PIO FIFO | 
 | 665 | 	 *	(Not on later devices it seems) | 
 | 666 | 	 * | 
 | 667 | 	 *	0x53 changes meaning on later revs - we must no touch | 
 | 668 | 	 *	bit 1 on them. Need to check if 0x20 is the right break | 
 | 669 | 	 */ | 
 | 670 | 	  | 
 | 671 | 	pci_read_config_byte(dev, 0x53, &tmpbyte); | 
 | 672 | 	 | 
 | 673 | 	if(m5229_revision <= 0x20) | 
 | 674 | 		tmpbyte = (tmpbyte & (~0x02)) | 0x01; | 
| Michael De Backer | e11db06 | 2006-09-12 20:35:53 -0700 | [diff] [blame] | 675 | 	else if (m5229_revision == 0xc7 || m5229_revision == 0xc8) | 
| KAI.HSU | 0d8a95e | 2006-04-18 22:22:08 -0700 | [diff] [blame] | 676 | 		tmpbyte |= 0x03; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 677 | 	else | 
 | 678 | 		tmpbyte |= 0x01; | 
 | 679 |  | 
 | 680 | 	pci_write_config_byte(dev, 0x53, tmpbyte); | 
 | 681 |  | 
 | 682 | 	local_irq_restore(flags); | 
 | 683 |  | 
| Bartlomiej Zolnierkiewicz | 95ba8c1 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 684 | 	return cbl; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 685 | } | 
 | 686 |  | 
 | 687 | /** | 
 | 688 |  *	init_hwif_common_ali15x3	-	Set up ALI IDE hardware | 
 | 689 |  *	@hwif: IDE interface | 
 | 690 |  * | 
 | 691 |  *	Initialize the IDE structure side of the ALi 15x3 driver. | 
 | 692 |  */ | 
 | 693 |   | 
| Herbert Xu | c2f1258 | 2005-07-03 16:06:13 +0200 | [diff] [blame] | 694 | static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 695 | { | 
 | 696 | 	hwif->autodma = 0; | 
 | 697 | 	hwif->tuneproc = &ali15x3_tune_drive; | 
 | 698 | 	hwif->speedproc = &ali15x3_tune_chipset; | 
| Bartlomiej Zolnierkiewicz | 2d5eaa6 | 2007-05-10 00:01:08 +0200 | [diff] [blame] | 699 | 	hwif->udma_filter = &ali_udma_filter; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 700 |  | 
 | 701 | 	/* don't use LBA48 DMA on ALi devices before rev 0xC5 */ | 
 | 702 | 	hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0; | 
 | 703 |  | 
 | 704 | 	if (!hwif->dma_base) { | 
 | 705 | 		hwif->drives[0].autotune = 1; | 
 | 706 | 		hwif->drives[1].autotune = 1; | 
 | 707 | 		return; | 
 | 708 | 	} | 
 | 709 |  | 
| Bartlomiej Zolnierkiewicz | 38ff8a7 | 2007-05-16 00:51:43 +0200 | [diff] [blame] | 710 | 	if (m5229_revision > 0x20) | 
 | 711 | 		hwif->atapi_dma = 1; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 712 |  | 
| Bartlomiej Zolnierkiewicz | 1813720 | 2007-05-10 00:01:07 +0200 | [diff] [blame] | 713 | 	if (m5229_revision <= 0x20) | 
 | 714 | 		hwif->ultra_mask = 0x00; /* no udma */ | 
 | 715 | 	else if (m5229_revision < 0xC2) | 
 | 716 | 		hwif->ultra_mask = 0x07; /* udma0-2 */ | 
 | 717 | 	else if (m5229_revision == 0xC2 || m5229_revision == 0xC3) | 
 | 718 | 		hwif->ultra_mask = 0x1f; /* udma0-4 */ | 
 | 719 | 	else if (m5229_revision == 0xC4) | 
 | 720 | 		hwif->ultra_mask = 0x3f; /* udma0-5 */ | 
 | 721 | 	else | 
 | 722 | 		hwif->ultra_mask = 0x7f; /* udma0-6 */ | 
 | 723 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 724 | 	hwif->mwdma_mask = 0x07; | 
 | 725 | 	hwif->swdma_mask = 0x07; | 
 | 726 |  | 
 | 727 |         if (m5229_revision >= 0x20) { | 
 | 728 |                 /* | 
 | 729 |                  * M1543C or newer for DMAing | 
 | 730 |                  */ | 
 | 731 |                 hwif->ide_dma_check = &ali15x3_config_drive_for_dma; | 
 | 732 | 		hwif->dma_setup = &ali15x3_dma_setup; | 
 | 733 | 		if (!noautodma) | 
 | 734 | 			hwif->autodma = 1; | 
| Bartlomiej Zolnierkiewicz | 49521f9 | 2007-07-09 23:17:58 +0200 | [diff] [blame] | 735 |  | 
 | 736 | 		if (hwif->cbl != ATA_CBL_PATA40_SHORT) | 
 | 737 | 			hwif->cbl = ata66_ali15x3(hwif); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 738 | 	} | 
 | 739 | 	hwif->drives[0].autodma = hwif->autodma; | 
 | 740 | 	hwif->drives[1].autodma = hwif->autodma; | 
 | 741 | } | 
 | 742 |  | 
 | 743 | /** | 
 | 744 |  *	init_hwif_ali15x3	-	Initialize the ALI IDE x86 stuff | 
 | 745 |  *	@hwif: interface to configure | 
 | 746 |  * | 
 | 747 |  *	Obtain the IRQ tables for an ALi based IDE solution on the PC | 
 | 748 |  *	class platforms. This part of the code isn't applicable to the | 
 | 749 |  *	Sparc systems | 
 | 750 |  */ | 
 | 751 |  | 
| Herbert Xu | c2f1258 | 2005-07-03 16:06:13 +0200 | [diff] [blame] | 752 | static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 753 | { | 
 | 754 | 	u8 ideic, inmir; | 
 | 755 | 	s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6, | 
 | 756 | 				      1, 11, 0, 12, 0, 14, 0, 15 }; | 
 | 757 | 	int irq = -1; | 
 | 758 |  | 
 | 759 | 	if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229) | 
 | 760 | 		hwif->irq = hwif->channel ? 15 : 14; | 
 | 761 |  | 
 | 762 | 	if (isa_dev) { | 
 | 763 | 		/* | 
 | 764 | 		 * read IDE interface control | 
 | 765 | 		 */ | 
 | 766 | 		pci_read_config_byte(isa_dev, 0x58, &ideic); | 
 | 767 |  | 
 | 768 | 		/* bit0, bit1 */ | 
 | 769 | 		ideic = ideic & 0x03; | 
 | 770 |  | 
 | 771 | 		/* get IRQ for IDE Controller */ | 
 | 772 | 		if ((hwif->channel && ideic == 0x03) || | 
 | 773 | 		    (!hwif->channel && !ideic)) { | 
 | 774 | 			/* | 
 | 775 | 			 * get SIRQ1 routing table | 
 | 776 | 			 */ | 
 | 777 | 			pci_read_config_byte(isa_dev, 0x44, &inmir); | 
 | 778 | 			inmir = inmir & 0x0f; | 
 | 779 | 			irq = irq_routing_table[inmir]; | 
 | 780 | 		} else if (hwif->channel && !(ideic & 0x01)) { | 
 | 781 | 			/* | 
 | 782 | 			 * get SIRQ2 routing table | 
 | 783 | 			 */ | 
 | 784 | 			pci_read_config_byte(isa_dev, 0x75, &inmir); | 
 | 785 | 			inmir = inmir & 0x0f; | 
 | 786 | 			irq = irq_routing_table[inmir]; | 
 | 787 | 		} | 
 | 788 | 		if(irq >= 0) | 
 | 789 | 			hwif->irq = irq; | 
 | 790 | 	} | 
 | 791 |  | 
 | 792 | 	init_hwif_common_ali15x3(hwif); | 
 | 793 | } | 
 | 794 |  | 
 | 795 | /** | 
 | 796 |  *	init_dma_ali15x3	-	set up DMA on ALi15x3 | 
 | 797 |  *	@hwif: IDE interface | 
 | 798 |  *	@dmabase: DMA interface base PCI address | 
 | 799 |  * | 
 | 800 |  *	Set up the DMA functionality on the ALi 15x3. For the ALi | 
 | 801 |  *	controllers this is generic so we can let the generic code do | 
 | 802 |  *	the actual work. | 
 | 803 |  */ | 
 | 804 |  | 
| Herbert Xu | c2f1258 | 2005-07-03 16:06:13 +0200 | [diff] [blame] | 805 | static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 806 | { | 
 | 807 | 	if (m5229_revision < 0x20) | 
 | 808 | 		return; | 
| Bartlomiej Zolnierkiewicz | 0ecdca2 | 2007-02-17 02:40:25 +0100 | [diff] [blame] | 809 | 	if (!hwif->channel) | 
 | 810 | 		outb(inb(dmabase + 2) & 0x60, dmabase + 2); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 811 | 	ide_setup_dma(hwif, dmabase, 8); | 
 | 812 | } | 
 | 813 |  | 
 | 814 | static ide_pci_device_t ali15x3_chipset __devinitdata = { | 
 | 815 | 	.name		= "ALI15X3", | 
 | 816 | 	.init_chipset	= init_chipset_ali15x3, | 
 | 817 | 	.init_hwif	= init_hwif_ali15x3, | 
 | 818 | 	.init_dma	= init_dma_ali15x3, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 819 | 	.autodma	= AUTODMA, | 
 | 820 | 	.bootable	= ON_BOARD, | 
| Bartlomiej Zolnierkiewicz | 4099d14 | 2007-07-20 01:11:59 +0200 | [diff] [blame] | 821 | 	.pio_mask	= ATA_PIO5, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 822 | }; | 
 | 823 |  | 
 | 824 | /** | 
 | 825 |  *	alim15x3_init_one	-	set up an ALi15x3 IDE controller | 
 | 826 |  *	@dev: PCI device to set up | 
 | 827 |  * | 
 | 828 |  *	Perform the actual set up for an ALi15x3 that has been found by the | 
 | 829 |  *	hot plug layer. | 
 | 830 |  */ | 
 | 831 |   | 
 | 832 | static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) | 
 | 833 | { | 
| Hanna Linder | cc3f7ca | 2005-11-18 22:19:15 +0100 | [diff] [blame] | 834 | 	static struct pci_device_id ati_rs100[] = { | 
 | 835 | 		{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100) }, | 
 | 836 | 		{ }, | 
 | 837 | 	}; | 
 | 838 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 839 | 	ide_pci_device_t *d = &ali15x3_chipset; | 
 | 840 |  | 
| Hanna Linder | cc3f7ca | 2005-11-18 22:19:15 +0100 | [diff] [blame] | 841 | 	if (pci_dev_present(ati_rs100)) | 
| Alexey Dobriyan | 2fefef1 | 2005-11-18 22:22:21 +0100 | [diff] [blame] | 842 | 		printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 843 |  | 
 | 844 | #if defined(CONFIG_SPARC64) | 
 | 845 | 	d->init_hwif = init_hwif_common_ali15x3; | 
 | 846 | #endif /* CONFIG_SPARC64 */ | 
 | 847 | 	return ide_setup_pci_device(dev, d); | 
 | 848 | } | 
 | 849 |  | 
 | 850 |  | 
 | 851 | static struct pci_device_id alim15x3_pci_tbl[] = { | 
 | 852 | 	{ PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 
 | 853 | 	{ PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 
 | 854 | 	{ 0, }, | 
 | 855 | }; | 
 | 856 | MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl); | 
 | 857 |  | 
 | 858 | static struct pci_driver driver = { | 
 | 859 | 	.name		= "ALI15x3_IDE", | 
 | 860 | 	.id_table	= alim15x3_pci_tbl, | 
 | 861 | 	.probe		= alim15x3_init_one, | 
 | 862 | }; | 
 | 863 |  | 
| Bartlomiej Zolnierkiewicz | 82ab1ee | 2007-01-27 13:46:56 +0100 | [diff] [blame] | 864 | static int __init ali15x3_ide_init(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 865 | { | 
 | 866 | 	return ide_pci_register_driver(&driver); | 
 | 867 | } | 
 | 868 |  | 
 | 869 | module_init(ali15x3_ide_init); | 
 | 870 |  | 
 | 871 | MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox"); | 
 | 872 | MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE"); | 
 | 873 | MODULE_LICENSE("GPL"); |