aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorAlan <alan@lxorguk.ukuu.org.uk>2006-11-22 12:26:06 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-01 22:46:44 -0500
commit34d8dfb1e6b51dbd6eefcb449b531c7ee773664c (patch)
treeafc35f1f602340be69c6c66f10b0133a8624580f /drivers/ata
parentd39ca896fb9a25f80465d3e52872cf5c510762a8 (diff)
[PATCH] pata_ali: suspend/resume support
Various chipset functions must be reprogrammed on a resume from RAM, without this things like ATAPI DMA stop working on resume with some chipset variants. Split the chipset programming and init time method selection into two functions. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/pata_ali.c135
1 files changed, 84 insertions, 51 deletions
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
index e6d2b840e870..ae6d573574cd 100644
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -34,7 +34,7 @@
34#include <linux/dmi.h> 34#include <linux/dmi.h>
35 35
36#define DRV_NAME "pata_ali" 36#define DRV_NAME "pata_ali"
37#define DRV_VERSION "0.6.6" 37#define DRV_VERSION "0.7.1"
38 38
39/* 39/*
40 * Cable special cases 40 * Cable special cases
@@ -348,6 +348,8 @@ static struct scsi_host_template ali_sht = {
348 .slave_configure = ata_scsi_slave_config, 348 .slave_configure = ata_scsi_slave_config,
349 .slave_destroy = ata_scsi_slave_destroy, 349 .slave_destroy = ata_scsi_slave_destroy,
350 .bios_param = ata_std_bios_param, 350 .bios_param = ata_std_bios_param,
351 .resume = ata_scsi_device_resume,
352 .suspend = ata_scsi_device_suspend,
351}; 353};
352 354
353/* 355/*
@@ -497,6 +499,69 @@ static struct ata_port_operations ali_c5_port_ops = {
497 .host_stop = ata_host_stop 499 .host_stop = ata_host_stop
498}; 500};
499 501
502
503/**
504 * ali_init_chipset - chip setup function
505 * @pdev: PCI device of ATA controller
506 *
507 * Perform the setup on the device that must be done both at boot
508 * and at resume time.
509 */
510
511static void ali_init_chipset(struct pci_dev *pdev)
512{
513 u8 rev, tmp;
514 struct pci_dev *north, *isa_bridge;
515
516 pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
517
518 /*
519 * The chipset revision selects the driver operations and
520 * mode data.
521 */
522
523 if (rev >= 0x20 && rev < 0xC2) {
524 /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
525 pci_read_config_byte(pdev, 0x4B, &tmp);
526 /* Clear CD-ROM DMA write bit */
527 tmp &= 0x7F;
528 pci_write_config_byte(pdev, 0x4B, tmp);
529 } else if (rev >= 0xC2) {
530 /* Enable cable detection logic */
531 pci_read_config_byte(pdev, 0x4B, &tmp);
532 pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
533 }
534 north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0));
535 isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
536
537 if (north && north->vendor == PCI_VENDOR_ID_AL && isa_bridge) {
538 /* Configure the ALi bridge logic. For non ALi rely on BIOS.
539 Set the south bridge enable bit */
540 pci_read_config_byte(isa_bridge, 0x79, &tmp);
541 if (rev == 0xC2)
542 pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
543 else if (rev > 0xC2)
544 pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
545 }
546 if (rev >= 0x20) {
547 /*
548 * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
549 * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
550 * via 0x54/55.
551 */
552 pci_read_config_byte(pdev, 0x53, &tmp);
553 if (rev <= 0x20)
554 tmp &= ~0x02;
555 if (rev >= 0xc7)
556 tmp |= 0x03;
557 else
558 tmp |= 0x01; /* CD_ROM enable for DMA */
559 pci_write_config_byte(pdev, 0x53, tmp);
560 }
561 pci_dev_put(isa_bridge);
562 pci_dev_put(north);
563 ata_pci_clear_simplex(pdev);
564}
500/** 565/**
501 * ali_init_one - discovery callback 566 * ali_init_one - discovery callback
502 * @pdev: PCI device ID 567 * @pdev: PCI device ID
@@ -570,7 +635,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
570 635
571 static struct ata_port_info *port_info[2]; 636 static struct ata_port_info *port_info[2];
572 u8 rev, tmp; 637 u8 rev, tmp;
573 struct pci_dev *north, *isa_bridge; 638 struct pci_dev *isa_bridge;
574 639
575 pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); 640 pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
576 641
@@ -582,11 +647,6 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
582 if (rev < 0x20) { 647 if (rev < 0x20) {
583 port_info[0] = port_info[1] = &info_early; 648 port_info[0] = port_info[1] = &info_early;
584 } else if (rev < 0xC2) { 649 } else if (rev < 0xC2) {
585 /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
586 pci_read_config_byte(pdev, 0x4B, &tmp);
587 /* Clear CD-ROM DMA write bit */
588 tmp &= 0x7F;
589 pci_write_config_byte(pdev, 0x4B, tmp);
590 port_info[0] = port_info[1] = &info_20; 650 port_info[0] = port_info[1] = &info_20;
591 } else if (rev == 0xC2) { 651 } else if (rev == 0xC2) {
592 port_info[0] = port_info[1] = &info_c2; 652 port_info[0] = port_info[1] = &info_c2;
@@ -597,54 +657,25 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
597 } else 657 } else
598 port_info[0] = port_info[1] = &info_c5; 658 port_info[0] = port_info[1] = &info_c5;
599 659
600 if (rev >= 0xC2) { 660 ali_init_chipset(pdev);
601 /* Enable cable detection logic */ 661
602 pci_read_config_byte(pdev, 0x4B, &tmp);
603 pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
604 }
605
606 north = pci_get_slot(pdev->bus, PCI_DEVFN(0,0));
607 isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); 662 isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
608 663 if (isa_bridge && rev >= 0x20 && rev < 0xC2) {
609 if (north && north->vendor == PCI_VENDOR_ID_AL) { 664 /* Are we paired with a UDMA capable chip */
610 /* Configure the ALi bridge logic. For non ALi rely on BIOS. 665 pci_read_config_byte(isa_bridge, 0x5E, &tmp);
611 Set the south bridge enable bit */ 666 if ((tmp & 0x1E) == 0x12)
612 pci_read_config_byte(isa_bridge, 0x79, &tmp); 667 port_info[0] = port_info[1] = &info_20_udma;
613 if (rev == 0xC2) 668 pci_dev_put(isa_bridge);
614 pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
615 else if (rev > 0xC2)
616 pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
617 } 669 }
618
619 if (rev >= 0x20) {
620 if (rev < 0xC2) {
621 /* Are we paired with a UDMA capable chip */
622 pci_read_config_byte(isa_bridge, 0x5E, &tmp);
623 if ((tmp & 0x1E) == 0x12)
624 port_info[0] = port_info[1] = &info_20_udma;
625 }
626 /*
627 * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
628 * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
629 * via 0x54/55.
630 */
631 pci_read_config_byte(pdev, 0x53, &tmp);
632 if (rev <= 0x20)
633 tmp &= ~0x02;
634 if (rev >= 0xc7)
635 tmp |= 0x03;
636 else
637 tmp |= 0x01; /* CD_ROM enable for DMA */
638 pci_write_config_byte(pdev, 0x53, tmp);
639 }
640
641 pci_dev_put(isa_bridge);
642 pci_dev_put(north);
643
644 ata_pci_clear_simplex(pdev);
645 return ata_pci_init_one(pdev, port_info, 2); 670 return ata_pci_init_one(pdev, port_info, 2);
646} 671}
647 672
673static int ali_reinit_one(struct pci_dev *pdev)
674{
675 ali_init_chipset(pdev);
676 return ata_pci_device_resume(pdev);
677}
678
648static const struct pci_device_id ali[] = { 679static const struct pci_device_id ali[] = {
649 { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), }, 680 { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), },
650 { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), }, 681 { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), },
@@ -656,7 +687,9 @@ static struct pci_driver ali_pci_driver = {
656 .name = DRV_NAME, 687 .name = DRV_NAME,
657 .id_table = ali, 688 .id_table = ali,
658 .probe = ali_init_one, 689 .probe = ali_init_one,
659 .remove = ata_pci_remove_one 690 .remove = ata_pci_remove_one,
691 .suspend = ata_pci_device_suspend,
692 .resume = ali_reinit_one,
660}; 693};
661 694
662static int __init ali_init(void) 695static int __init ali_init(void)