diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-10-16 16:29:52 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-10-16 16:29:52 -0400 |
commit | c77a89cd98d99819f23a4a08e5e17ee1f13f6e4d (patch) | |
tree | 7b79c1189547cde4adc5457745a9034690e9245b /drivers/ide/pci/sis5513.c | |
parent | a29ec3b2192247f93b10940119079196cf1dfc5c (diff) |
sis5513: DMA setup fixes
* Add sis_ata133_get_base() helper function for obtaining the address of
the drive control registers on chipset_family == ATA_133 chipsets.
* Add three helper functions for programming PIO/MWDMA timings:
- sis_ata16_program_timings() (for ATA_16/33/66/100a chipset families)
- sis_ata100_program_timings() (for ATA_100/133a chipset families)
- sis_ata133_program_timings() (for ATA_133 chipset family)
MWDMA timings are taken from datasheets and they match ATA spec.
* Add generic helper function sis_program_timings() and use it in
->set_pio_mode and ->set_dma_mode methods (previously the driver
depended on BIOS to program the correct MWDMA timings).
* Remove redundant !chipset_family check from init_hwif_sis5513()
(init_chipset_sis5513() guarantees that we will never get here if
chipset_family cannot be determined).
* SWDMA seems to be unsupported by SiS chipsets (no info about SWDMA in
datasheets and for SWDMA0 mode timing requirements are impossible to
fulfill) so remove ->swdma_mask from init_hwif_sis5513() and handling
of SWDMA modes from sis_set_dma_mode().
* Enable DMA support for chipset_family == ATA_16.
* Bump driver version.
Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/pci/sis5513.c')
-rw-r--r-- | drivers/ide/pci/sis5513.c | 214 |
1 files changed, 106 insertions, 108 deletions
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index b375ee53d66d..db8d96bd5a64 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/ide/pci/sis5513.c Version 0.27 Jul 14, 2007 | 2 | * linux/drivers/ide/pci/sis5513.c Version 0.28 Aug 1, 2007 |
3 | * | 3 | * |
4 | * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> | 4 | * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> |
5 | * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer | 5 | * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer |
@@ -433,6 +433,95 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) | |||
433 | /* | 433 | /* |
434 | * Configuration functions | 434 | * Configuration functions |
435 | */ | 435 | */ |
436 | |||
437 | static u8 sis_ata133_get_base(ide_drive_t *drive) | ||
438 | { | ||
439 | struct pci_dev *dev = drive->hwif->pci_dev; | ||
440 | u32 reg54 = 0; | ||
441 | |||
442 | pci_read_config_dword(dev, 0x54, ®54); | ||
443 | |||
444 | return ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4; | ||
445 | } | ||
446 | |||
447 | static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode) | ||
448 | { | ||
449 | struct pci_dev *dev = drive->hwif->pci_dev; | ||
450 | u16 t1 = 0; | ||
451 | u8 drive_pci = 0x40 + drive->dn * 2; | ||
452 | |||
453 | const u16 pio_timings[] = { 0x000, 0x607, 0x404, 0x303, 0x301 }; | ||
454 | const u16 mwdma_timings[] = { 0x008, 0x302, 0x301 }; | ||
455 | |||
456 | pci_read_config_word(dev, drive_pci, &t1); | ||
457 | |||
458 | /* clear active/recovery timings */ | ||
459 | t1 &= ~0x070f; | ||
460 | if (mode >= XFER_MW_DMA_0) { | ||
461 | if (chipset_family > ATA_16) | ||
462 | t1 &= ~0x8000; /* disable UDMA */ | ||
463 | t1 |= mwdma_timings[mode - XFER_MW_DMA_0]; | ||
464 | } else | ||
465 | t1 |= pio_timings[mode - XFER_PIO_0]; | ||
466 | |||
467 | pci_write_config_word(dev, drive_pci, t1); | ||
468 | } | ||
469 | |||
470 | static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode) | ||
471 | { | ||
472 | struct pci_dev *dev = drive->hwif->pci_dev; | ||
473 | u8 t1, drive_pci = 0x40 + drive->dn * 2; | ||
474 | |||
475 | /* timing bits: 7:4 active 3:0 recovery */ | ||
476 | const u8 pio_timings[] = { 0x00, 0x67, 0x44, 0x33, 0x31 }; | ||
477 | const u8 mwdma_timings[] = { 0x08, 0x32, 0x31 }; | ||
478 | |||
479 | if (mode >= XFER_MW_DMA_0) { | ||
480 | u8 t2 = 0; | ||
481 | |||
482 | pci_read_config_byte(dev, drive_pci, &t2); | ||
483 | t2 &= ~0x80; /* disable UDMA */ | ||
484 | pci_write_config_byte(dev, drive_pci, t2); | ||
485 | |||
486 | t1 = mwdma_timings[mode - XFER_MW_DMA_0]; | ||
487 | } else | ||
488 | t1 = pio_timings[mode - XFER_PIO_0]; | ||
489 | |||
490 | pci_write_config_byte(dev, drive_pci + 1, t1); | ||
491 | } | ||
492 | |||
493 | static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode) | ||
494 | { | ||
495 | struct pci_dev *dev = drive->hwif->pci_dev; | ||
496 | u32 t1 = 0; | ||
497 | u8 drive_pci = sis_ata133_get_base(drive), clk, idx; | ||
498 | |||
499 | pci_read_config_dword(dev, drive_pci, &t1); | ||
500 | |||
501 | t1 &= 0xc0c00fff; | ||
502 | clk = (t1 & 0x08) ? ATA_133 : ATA_100; | ||
503 | if (mode >= XFER_MW_DMA_0) { | ||
504 | t1 &= ~0x04; /* disable UDMA */ | ||
505 | idx = mode - XFER_MW_DMA_0 + 5; | ||
506 | } | ||
507 | idx = mode - XFER_PIO_0; | ||
508 | t1 |= ini_time_value[clk][idx] << 12; | ||
509 | t1 |= act_time_value[clk][idx] << 16; | ||
510 | t1 |= rco_time_value[clk][idx] << 24; | ||
511 | |||
512 | pci_write_config_dword(dev, drive_pci, t1); | ||
513 | } | ||
514 | |||
515 | static void sis_program_timings(ide_drive_t *drive, const u8 mode) | ||
516 | { | ||
517 | if (chipset_family < ATA_100) /* ATA_16/33/66/100a */ | ||
518 | sis_ata16_program_timings(drive, mode); | ||
519 | else if (chipset_family < ATA_133) /* ATA_100/133a */ | ||
520 | sis_ata100_program_timings(drive, mode); | ||
521 | else /* ATA_133 */ | ||
522 | sis_ata133_program_timings(drive, mode); | ||
523 | } | ||
524 | |||
436 | /* Enables per-drive prefetch and postwrite */ | 525 | /* Enables per-drive prefetch and postwrite */ |
437 | static void config_drive_art_rwp (ide_drive_t *drive) | 526 | static void config_drive_art_rwp (ide_drive_t *drive) |
438 | { | 527 | { |
@@ -450,105 +539,16 @@ static void config_drive_art_rwp (ide_drive_t *drive) | |||
450 | pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); | 539 | pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); |
451 | } | 540 | } |
452 | 541 | ||
453 | /* Set per-drive active and recovery time */ | ||
454 | static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) | 542 | static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) |
455 | { | 543 | { |
456 | ide_hwif_t *hwif = HWIF(drive); | ||
457 | struct pci_dev *dev = hwif->pci_dev; | ||
458 | |||
459 | u8 drive_pci, test1, test2; | ||
460 | |||
461 | config_drive_art_rwp(drive); | 544 | config_drive_art_rwp(drive); |
462 | 545 | sis_program_timings(drive, XFER_PIO_0 + pio); | |
463 | /* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */ | ||
464 | drive_pci = 0x40; | ||
465 | /* In SiS962 case drives sit at (0x40 or 0x70) + 8*drive->dn) */ | ||
466 | if (chipset_family >= ATA_133) { | ||
467 | u32 reg54h; | ||
468 | pci_read_config_dword(dev, 0x54, ®54h); | ||
469 | if (reg54h & 0x40000000) drive_pci = 0x70; | ||
470 | drive_pci += ((drive->dn)*0x4); | ||
471 | } else { | ||
472 | drive_pci += ((drive->dn)*0x2); | ||
473 | } | ||
474 | |||
475 | /* register layout changed with newer ATA100 chips */ | ||
476 | if (chipset_family < ATA_100) { | ||
477 | pci_read_config_byte(dev, drive_pci, &test1); | ||
478 | pci_read_config_byte(dev, drive_pci+1, &test2); | ||
479 | |||
480 | /* Clear active and recovery timings */ | ||
481 | test1 &= ~0x0F; | ||
482 | test2 &= ~0x07; | ||
483 | |||
484 | switch(pio) { | ||
485 | case 4: test1 |= 0x01; test2 |= 0x03; break; | ||
486 | case 3: test1 |= 0x03; test2 |= 0x03; break; | ||
487 | case 2: test1 |= 0x04; test2 |= 0x04; break; | ||
488 | case 1: test1 |= 0x07; test2 |= 0x06; break; | ||
489 | case 0: /* PIO0: register setting == X000 */ | ||
490 | default: break; | ||
491 | } | ||
492 | pci_write_config_byte(dev, drive_pci, test1); | ||
493 | pci_write_config_byte(dev, drive_pci+1, test2); | ||
494 | } else if (chipset_family < ATA_133) { | ||
495 | switch(pio) { /* active recovery | ||
496 | v v */ | ||
497 | case 4: test1 = 0x30|0x01; break; | ||
498 | case 3: test1 = 0x30|0x03; break; | ||
499 | case 2: test1 = 0x40|0x04; break; | ||
500 | case 1: test1 = 0x60|0x07; break; | ||
501 | case 0: test1 = 0x00; break; | ||
502 | default: break; | ||
503 | } | ||
504 | pci_write_config_byte(dev, drive_pci, test1); | ||
505 | } else { /* ATA_133 */ | ||
506 | u32 test3; | ||
507 | pci_read_config_dword(dev, drive_pci, &test3); | ||
508 | test3 &= 0xc0c00fff; | ||
509 | if (test3 & 0x08) { | ||
510 | test3 |= ini_time_value[ATA_133][pio] << 12; | ||
511 | test3 |= act_time_value[ATA_133][pio] << 16; | ||
512 | test3 |= rco_time_value[ATA_133][pio] << 24; | ||
513 | } else { | ||
514 | test3 |= ini_time_value[ATA_100][pio] << 12; | ||
515 | test3 |= act_time_value[ATA_100][pio] << 16; | ||
516 | test3 |= rco_time_value[ATA_100][pio] << 24; | ||
517 | } | ||
518 | pci_write_config_dword(dev, drive_pci, test3); | ||
519 | } | ||
520 | } | 546 | } |
521 | 547 | ||
522 | static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) | 548 | static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) |
523 | { | 549 | { |
524 | ide_hwif_t *hwif = HWIF(drive); | 550 | ide_hwif_t *hwif = HWIF(drive); |
525 | struct pci_dev *dev = hwif->pci_dev; | 551 | struct pci_dev *dev = hwif->pci_dev; |
526 | u32 regdw; | ||
527 | u8 drive_pci, reg; | ||
528 | |||
529 | /* See sis_set_pio_mode() for drive PCI config registers */ | ||
530 | drive_pci = 0x40; | ||
531 | if (chipset_family >= ATA_133) { | ||
532 | u32 reg54h; | ||
533 | pci_read_config_dword(dev, 0x54, ®54h); | ||
534 | if (reg54h & 0x40000000) drive_pci = 0x70; | ||
535 | drive_pci += ((drive->dn)*0x4); | ||
536 | pci_read_config_dword(dev, (unsigned long)drive_pci, ®dw); | ||
537 | /* Disable UDMA bit for non UDMA modes on UDMA chips */ | ||
538 | if (speed < XFER_UDMA_0) { | ||
539 | regdw &= 0xfffffffb; | ||
540 | pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); | ||
541 | } | ||
542 | |||
543 | } else { | ||
544 | drive_pci += ((drive->dn)*0x2); | ||
545 | pci_read_config_byte(dev, drive_pci+1, ®); | ||
546 | /* Disable UDMA bit for non UDMA modes on UDMA chips */ | ||
547 | if ((speed < XFER_UDMA_0) && (chipset_family > ATA_16)) { | ||
548 | reg &= 0x7F; | ||
549 | pci_write_config_byte(dev, drive_pci+1, reg); | ||
550 | } | ||
551 | } | ||
552 | 552 | ||
553 | /* Config chip for mode */ | 553 | /* Config chip for mode */ |
554 | switch(speed) { | 554 | switch(speed) { |
@@ -560,6 +560,10 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) | |||
560 | case XFER_UDMA_1: | 560 | case XFER_UDMA_1: |
561 | case XFER_UDMA_0: | 561 | case XFER_UDMA_0: |
562 | if (chipset_family >= ATA_133) { | 562 | if (chipset_family >= ATA_133) { |
563 | u32 regdw = 0; | ||
564 | u8 drive_pci = sis_ata133_get_base(drive); | ||
565 | |||
566 | pci_read_config_dword(dev, drive_pci, ®dw); | ||
563 | regdw |= 0x04; | 567 | regdw |= 0x04; |
564 | regdw &= 0xfffff00f; | 568 | regdw &= 0xfffff00f; |
565 | /* check if ATA133 enable */ | 569 | /* check if ATA133 enable */ |
@@ -572,6 +576,9 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) | |||
572 | } | 576 | } |
573 | pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); | 577 | pci_write_config_dword(dev, (unsigned long)drive_pci, regdw); |
574 | } else { | 578 | } else { |
579 | u8 drive_pci = 0x40 + drive->dn * 2, reg = 0; | ||
580 | |||
581 | pci_read_config_byte(dev, drive_pci+1, ®); | ||
575 | /* Force the UDMA bit on if we want to use UDMA */ | 582 | /* Force the UDMA bit on if we want to use UDMA */ |
576 | reg |= 0x80; | 583 | reg |= 0x80; |
577 | /* clean reg cycle time bits */ | 584 | /* clean reg cycle time bits */ |
@@ -586,9 +593,7 @@ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed) | |||
586 | case XFER_MW_DMA_2: | 593 | case XFER_MW_DMA_2: |
587 | case XFER_MW_DMA_1: | 594 | case XFER_MW_DMA_1: |
588 | case XFER_MW_DMA_0: | 595 | case XFER_MW_DMA_0: |
589 | case XFER_SW_DMA_2: | 596 | sis_program_timings(drive, speed); |
590 | case XFER_SW_DMA_1: | ||
591 | case XFER_SW_DMA_0: | ||
592 | break; | 597 | break; |
593 | default: | 598 | default: |
594 | BUG(); | 599 | BUG(); |
@@ -617,11 +622,9 @@ static int sis5513_config_xfer_rate(ide_drive_t *drive) | |||
617 | static u8 sis5513_ata133_udma_filter(ide_drive_t *drive) | 622 | static u8 sis5513_ata133_udma_filter(ide_drive_t *drive) |
618 | { | 623 | { |
619 | struct pci_dev *dev = drive->hwif->pci_dev; | 624 | struct pci_dev *dev = drive->hwif->pci_dev; |
620 | int drive_pci; | 625 | u32 regdw = 0; |
621 | u32 reg54 = 0, regdw = 0; | 626 | u8 drive_pci = sis_ata133_get_base(drive); |
622 | 627 | ||
623 | pci_read_config_dword(dev, 0x54, ®54); | ||
624 | drive_pci = ((reg54 & 0x40000000) ? 0x70 : 0x40) + drive->dn * 4; | ||
625 | pci_read_config_dword(dev, drive_pci, ®dw); | 628 | pci_read_config_dword(dev, drive_pci, ®dw); |
626 | 629 | ||
627 | /* if ATA133 disable, we should not set speed above UDMA5 */ | 630 | /* if ATA133 disable, we should not set speed above UDMA5 */ |
@@ -848,22 +851,17 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) | |||
848 | 851 | ||
849 | hwif->ultra_mask = udma_rates[chipset_family]; | 852 | hwif->ultra_mask = udma_rates[chipset_family]; |
850 | hwif->mwdma_mask = 0x07; | 853 | hwif->mwdma_mask = 0x07; |
851 | hwif->swdma_mask = 0x07; | ||
852 | |||
853 | if (!chipset_family) | ||
854 | return; | ||
855 | 854 | ||
856 | if (hwif->cbl != ATA_CBL_PATA40_SHORT) | 855 | if (hwif->cbl != ATA_CBL_PATA40_SHORT) |
857 | hwif->cbl = ata66_sis5513(hwif); | 856 | hwif->cbl = ata66_sis5513(hwif); |
858 | 857 | ||
859 | if (chipset_family > ATA_16) { | 858 | hwif->ide_dma_check = &sis5513_config_xfer_rate; |
860 | hwif->ide_dma_check = &sis5513_config_xfer_rate; | 859 | |
861 | if (!noautodma) | 860 | if (!noautodma) |
862 | hwif->autodma = 1; | 861 | hwif->autodma = 1; |
863 | } | 862 | |
864 | hwif->drives[0].autodma = hwif->autodma; | 863 | hwif->drives[0].autodma = hwif->autodma; |
865 | hwif->drives[1].autodma = hwif->autodma; | 864 | hwif->drives[1].autodma = hwif->autodma; |
866 | return; | ||
867 | } | 865 | } |
868 | 866 | ||
869 | static ide_pci_device_t sis5513_chipset __devinitdata = { | 867 | static ide_pci_device_t sis5513_chipset __devinitdata = { |