diff options
| -rw-r--r-- | drivers/ide/pci/it821x.c | 126 |
1 files changed, 58 insertions, 68 deletions
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index a132767f7d90..4e1254813ee0 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c | |||
| @@ -1,8 +1,9 @@ | |||
| 1 | 1 | ||
| 2 | /* | 2 | /* |
| 3 | * linux/drivers/ide/pci/it821x.c Version 0.09 December 2004 | 3 | * linux/drivers/ide/pci/it821x.c Version 0.10 Mar 10 2007 |
| 4 | * | 4 | * |
| 5 | * Copyright (C) 2004 Red Hat <alan@redhat.com> | 5 | * Copyright (C) 2004 Red Hat <alan@redhat.com> |
| 6 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | ||
| 6 | * | 7 | * |
| 7 | * May be copied or modified under the terms of the GNU General Public License | 8 | * May be copied or modified under the terms of the GNU General Public License |
| 8 | * Based in part on the ITE vendor provided SCSI driver. | 9 | * Based in part on the ITE vendor provided SCSI driver. |
| @@ -104,6 +105,7 @@ static int it8212_noraid; | |||
| 104 | /** | 105 | /** |
| 105 | * it821x_program - program the PIO/MWDMA registers | 106 | * it821x_program - program the PIO/MWDMA registers |
| 106 | * @drive: drive to tune | 107 | * @drive: drive to tune |
| 108 | * @timing: timing info | ||
| 107 | * | 109 | * |
| 108 | * Program the PIO/MWDMA timing for this channel according to the | 110 | * Program the PIO/MWDMA timing for this channel according to the |
| 109 | * current clock. | 111 | * current clock. |
| @@ -127,6 +129,7 @@ static void it821x_program(ide_drive_t *drive, u16 timing) | |||
| 127 | /** | 129 | /** |
| 128 | * it821x_program_udma - program the UDMA registers | 130 | * it821x_program_udma - program the UDMA registers |
| 129 | * @drive: drive to tune | 131 | * @drive: drive to tune |
| 132 | * @timing: timing info | ||
| 130 | * | 133 | * |
| 131 | * Program the UDMA timing for this drive according to the | 134 | * Program the UDMA timing for this drive according to the |
| 132 | * current clock. | 135 | * current clock. |
| @@ -153,10 +156,9 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing) | |||
| 153 | } | 156 | } |
| 154 | } | 157 | } |
| 155 | 158 | ||
| 156 | |||
| 157 | /** | 159 | /** |
| 158 | * it821x_clock_strategy | 160 | * it821x_clock_strategy |
| 159 | * @hwif: hardware interface | 161 | * @drive: drive to set up |
| 160 | * | 162 | * |
| 161 | * Select between the 50 and 66Mhz base clocks to get the best | 163 | * Select between the 50 and 66Mhz base clocks to get the best |
| 162 | * results for this interface. | 164 | * results for this interface. |
| @@ -182,8 +184,11 @@ static void it821x_clock_strategy(ide_drive_t *drive) | |||
| 182 | altclock = itdev->want[0][1]; | 184 | altclock = itdev->want[0][1]; |
| 183 | } | 185 | } |
| 184 | 186 | ||
| 185 | /* Master doesn't care does the slave ? */ | 187 | /* |
| 186 | if(clock == ATA_ANY) | 188 | * if both clocks can be used for the mode with the higher priority |
| 189 | * use the clock needed by the mode with the lower priority | ||
| 190 | */ | ||
| 191 | if (clock == ATA_ANY) | ||
| 187 | clock = altclock; | 192 | clock = altclock; |
| 188 | 193 | ||
| 189 | /* Nobody cares - keep the same clock */ | 194 | /* Nobody cares - keep the same clock */ |
| @@ -240,37 +245,56 @@ static u8 it821x_ratemask (ide_drive_t *drive) | |||
| 240 | } | 245 | } |
| 241 | 246 | ||
| 242 | /** | 247 | /** |
| 243 | * it821x_tuneproc - tune a drive | 248 | * it821x_tunepio - tune a drive |
| 244 | * @drive: drive to tune | 249 | * @drive: drive to tune |
| 245 | * @mode_wanted: the target operating mode | 250 | * @pio: the desired PIO mode |
| 246 | * | ||
| 247 | * Load the timing settings for this device mode into the | ||
| 248 | * controller. By the time we are called the mode has been | ||
| 249 | * modified as neccessary to handle the absence of seperate | ||
| 250 | * master/slave timers for MWDMA/PIO. | ||
| 251 | * | 251 | * |
| 252 | * This code is only used in pass through mode. | 252 | * Try to tune the drive/host to the desired PIO mode taking into |
| 253 | * the consideration the maximum PIO mode supported by the other | ||
| 254 | * device on the cable. | ||
| 253 | */ | 255 | */ |
| 254 | 256 | ||
| 255 | static void it821x_tuneproc (ide_drive_t *drive, byte mode_wanted) | 257 | static int it821x_tunepio(ide_drive_t *drive, u8 set_pio) |
| 256 | { | 258 | { |
| 257 | ide_hwif_t *hwif = drive->hwif; | 259 | ide_hwif_t *hwif = drive->hwif; |
| 258 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | 260 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); |
| 259 | int unit = drive->select.b.unit; | 261 | int unit = drive->select.b.unit; |
| 262 | ide_drive_t *pair = &hwif->drives[1 - unit]; | ||
| 260 | 263 | ||
| 261 | /* Spec says 89 ref driver uses 88 */ | 264 | /* Spec says 89 ref driver uses 88 */ |
| 262 | static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; | 265 | static u16 pio[] = { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 }; |
| 263 | static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; | 266 | static u8 pio_want[] = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY }; |
| 264 | 267 | ||
| 265 | if(itdev->smart) | 268 | /* |
| 266 | return; | 269 | * Compute the best PIO mode we can for a given device. We must |
| 270 | * pick a speed that does not cause problems with the other device | ||
| 271 | * on the cable. | ||
| 272 | */ | ||
| 273 | if (pair) { | ||
| 274 | u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL); | ||
| 275 | /* trim PIO to the slowest of the master/slave */ | ||
| 276 | if (pair_pio < set_pio) | ||
| 277 | set_pio = pair_pio; | ||
| 278 | } | ||
| 279 | |||
| 280 | if (itdev->smart) | ||
| 281 | goto set_drive_speed; | ||
| 267 | 282 | ||
| 268 | /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ | 283 | /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ |
| 269 | itdev->want[unit][1] = pio_want[mode_wanted]; | 284 | itdev->want[unit][1] = pio_want[set_pio]; |
| 270 | itdev->want[unit][0] = 1; /* PIO is lowest priority */ | 285 | itdev->want[unit][0] = 1; /* PIO is lowest priority */ |
| 271 | itdev->pio[unit] = pio[mode_wanted]; | 286 | itdev->pio[unit] = pio[set_pio]; |
| 272 | it821x_clock_strategy(drive); | 287 | it821x_clock_strategy(drive); |
| 273 | it821x_program(drive, itdev->pio[unit]); | 288 | it821x_program(drive, itdev->pio[unit]); |
| 289 | |||
| 290 | set_drive_speed: | ||
| 291 | return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio); | ||
| 292 | } | ||
| 293 | |||
| 294 | static void it821x_tuneproc(ide_drive_t *drive, u8 pio) | ||
| 295 | { | ||
| 296 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | ||
| 297 | (void)it821x_tunepio(drive, pio); | ||
| 274 | } | 298 | } |
| 275 | 299 | ||
| 276 | /** | 300 | /** |
| @@ -354,40 +378,6 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted) | |||
| 354 | } | 378 | } |
| 355 | 379 | ||
| 356 | /** | 380 | /** |
| 357 | * config_it821x_chipset_for_pio - set drive timings | ||
| 358 | * @drive: drive to tune | ||
| 359 | * @speed we want | ||
| 360 | * | ||
| 361 | * Compute the best pio mode we can for a given device. We must | ||
| 362 | * pick a speed that does not cause problems with the other device | ||
| 363 | * on the cable. | ||
| 364 | */ | ||
| 365 | |||
| 366 | static void config_it821x_chipset_for_pio (ide_drive_t *drive, byte set_speed) | ||
| 367 | { | ||
| 368 | u8 unit = drive->select.b.unit; | ||
| 369 | ide_hwif_t *hwif = drive->hwif; | ||
| 370 | ide_drive_t *pair = &hwif->drives[1-unit]; | ||
| 371 | u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 255, 5, NULL); | ||
| 372 | u8 pair_pio; | ||
| 373 | |||
| 374 | /* We have to deal with this mess in pairs */ | ||
| 375 | if(pair != NULL) { | ||
| 376 | pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL); | ||
| 377 | /* Trim PIO to the slowest of the master/slave */ | ||
| 378 | if(pair_pio < set_pio) | ||
| 379 | set_pio = pair_pio; | ||
| 380 | } | ||
| 381 | it821x_tuneproc(drive, set_pio); | ||
| 382 | speed = XFER_PIO_0 + set_pio; | ||
| 383 | /* XXX - We trim to the lowest of the pair so the other drive | ||
| 384 | will always be fine at this point until we do hotplug passthru */ | ||
| 385 | |||
| 386 | if (set_speed) | ||
| 387 | (void) ide_config_drive_speed(drive, speed); | ||
| 388 | } | ||
| 389 | |||
| 390 | /** | ||
| 391 | * it821x_dma_read - DMA hook | 381 | * it821x_dma_read - DMA hook |
| 392 | * @drive: drive for DMA | 382 | * @drive: drive for DMA |
| 393 | * | 383 | * |
| @@ -450,15 +440,17 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) | |||
| 450 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); | 440 | struct it821x_dev *itdev = ide_get_hwifdata(hwif); |
| 451 | u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed); | 441 | u8 speed = ide_rate_filter(it821x_ratemask(drive), xferspeed); |
| 452 | 442 | ||
| 453 | if(!itdev->smart) { | 443 | switch (speed) { |
| 454 | switch(speed) { | 444 | case XFER_PIO_4: |
| 455 | case XFER_PIO_4: | 445 | case XFER_PIO_3: |
| 456 | case XFER_PIO_3: | 446 | case XFER_PIO_2: |
| 457 | case XFER_PIO_2: | 447 | case XFER_PIO_1: |
| 458 | case XFER_PIO_1: | 448 | case XFER_PIO_0: |
| 459 | case XFER_PIO_0: | 449 | return it821x_tunepio(drive, speed - XFER_PIO_0); |
| 460 | it821x_tuneproc(drive, (speed - XFER_PIO_0)); | 450 | } |
| 461 | break; | 451 | |
| 452 | if (itdev->smart == 0) { | ||
| 453 | switch (speed) { | ||
| 462 | /* MWDMA tuning is really hard because our MWDMA and PIO | 454 | /* MWDMA tuning is really hard because our MWDMA and PIO |
| 463 | timings are kept in the same place. We can switch in the | 455 | timings are kept in the same place. We can switch in the |
| 464 | host dma on/off callbacks */ | 456 | host dma on/off callbacks */ |
| @@ -498,14 +490,12 @@ static int config_chipset_for_dma (ide_drive_t *drive) | |||
| 498 | { | 490 | { |
| 499 | u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); | 491 | u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); |
| 500 | 492 | ||
| 501 | if (speed) { | 493 | if (speed == 0) |
| 502 | config_it821x_chipset_for_pio(drive, 0); | 494 | return 0; |
| 503 | it821x_tune_chipset(drive, speed); | ||
| 504 | 495 | ||
| 505 | return ide_dma_enable(drive); | 496 | it821x_tune_chipset(drive, speed); |
| 506 | } | ||
| 507 | 497 | ||
| 508 | return 0; | 498 | return ide_dma_enable(drive); |
| 509 | } | 499 | } |
| 510 | 500 | ||
| 511 | /** | 501 | /** |
| @@ -523,7 +513,7 @@ static int it821x_config_drive_for_dma (ide_drive_t *drive) | |||
| 523 | if (ide_use_dma(drive) && config_chipset_for_dma(drive)) | 513 | if (ide_use_dma(drive) && config_chipset_for_dma(drive)) |
| 524 | return 0; | 514 | return 0; |
| 525 | 515 | ||
| 526 | config_it821x_chipset_for_pio(drive, 1); | 516 | it821x_tuneproc(drive, 255); |
| 527 | 517 | ||
| 528 | return -1; | 518 | return -1; |
| 529 | } | 519 | } |
