[PATCH] pata_via suspend/resume support
authorAlan <alan@lxorguk.ukuu.org.uk>
Mon, 27 Nov 2006 16:19:36 +0000 (16:19 +0000)
committerJeff Garzik <jeff@garzik.org>
Sat, 2 Dec 2006 03:46:58 +0000 (22:46 -0500)
The major VIA issues were handled by the quirks update for resume quirks.
The ATA driver also has to do some work however when resuming from RAM.
Certain chips need the FIFO reconfiguring, and the 66MHz clock setup
updating.

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/ata/pata_via.c

index c5f1616..489bd57 100644 (file)
@@ -60,7 +60,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_via"
-#define DRV_VERSION "0.1.14"
+#define DRV_VERSION "0.2.0"
 
 /*
  *     The following comes directly from Vojtech Pavlik's ide/pci/via82cxxx
@@ -297,6 +297,8 @@ static struct scsi_host_template via_sht = {
        .slave_configure        = ata_scsi_slave_config,
        .slave_destroy          = ata_scsi_slave_destroy,
        .bios_param             = ata_std_bios_param,
+       .resume                 = ata_scsi_device_resume,
+       .suspend                = ata_scsi_device_suspend,
 };
 
 static struct ata_port_operations via_port_ops = {
@@ -370,8 +372,42 @@ static struct ata_port_operations via_port_ops_noirq = {
 };
 
 /**
+ *     via_config_fifo         -       set up the FIFO
+ *     @pdev: PCI device
+ *     @flags: configuration flags
+ *
+ *     Set the FIFO properties for this device if neccessary. Used both on
+ *     set up and on and the resume path
+ */
+
+static void via_config_fifo(struct pci_dev *pdev, unsigned int flags)
+{
+       u8 enable;
+       
+       /* 0x40 low bits indicate enabled channels */
+       pci_read_config_byte(pdev, 0x40 , &enable);
+       enable &= 3;
+       
+       if (flags & VIA_SET_FIFO) {
+               u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20};
+               u8 fifo;
+
+               pci_read_config_byte(pdev, 0x43, &fifo);
+
+               /* Clear PREQ# until DDACK# for errata */
+               if (flags & VIA_BAD_PREQ)
+                       fifo &= 0x7F;
+               else
+                       fifo &= 0x9f;
+               /* Turn on FIFO for enabled channels */
+               fifo |= fifo_setting[enable];
+               pci_write_config_byte(pdev, 0x43, fifo);
+       }
+}
+
+/**
  *     via_init_one            -       discovery callback
- *     @pdev: PCI device ID
+ *     @pdev: PCI device
  *     @id: PCI table info
  *
  *     A VIA IDE interface has been discovered. Figure out what revision
@@ -471,21 +507,8 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
        /* Initialise the FIFO for the enabled channels. */
-       if (config->flags & VIA_SET_FIFO) {
-               u8 fifo_setting[4] = {0x00, 0x60, 0x00, 0x20};
-               u8 fifo;
-
-               pci_read_config_byte(pdev, 0x43, &fifo);
-
-               /* Clear PREQ# until DDACK# for errata */
-               if (config->flags & VIA_BAD_PREQ)
-                       fifo &= 0x7F;
-               else
-                       fifo &= 0x9f;
-               /* Turn on FIFO for enabled channels */
-               fifo |= fifo_setting[enable];
-               pci_write_config_byte(pdev, 0x43, fifo);
-       }
+       via_config_fifo(pdev, config->flags);
+       
        /* Clock set up */
        switch(config->flags & VIA_UDMA) {
                case VIA_UDMA_NONE:
@@ -529,6 +552,39 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        return ata_pci_init_one(pdev, port_info, 2);
 }
 
+/**
+ *     via_reinit_one          -       reinit after resume
+ *     @pdev; PCI device
+ *
+ *     Called when the VIA PATA device is resumed. We must then
+ *     reconfigure the fifo and other setup we may have altered. In
+ *     addition the kernel needs to have the resume methods on PCI
+ *     quirk supported.
+ */
+
+static int via_reinit_one(struct pci_dev *pdev)
+{
+       u32 timing;
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       const struct via_isa_bridge *config = host->private_data;
+       
+       via_config_fifo(pdev, config->flags);
+
+       if ((config->flags & VIA_UDMA) == VIA_UDMA_66) {
+               /* The 66 MHz devices require we enable the clock */
+               pci_read_config_dword(pdev, 0x50, &timing);
+               timing |= 0x80008;
+               pci_write_config_dword(pdev, 0x50, timing);
+       }
+       if (config->flags & VIA_BAD_CLK66) {
+               /* Disable the 66MHz clock on problem devices */
+               pci_read_config_dword(pdev, 0x50, &timing);
+               timing &= ~0x80008;
+               pci_write_config_dword(pdev, 0x50, timing);
+       }
+       return ata_pci_device_resume(pdev);     
+}
+
 static const struct pci_device_id via[] = {
        { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C576_1), },
        { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C586_1), },
@@ -542,7 +598,9 @@ static struct pci_driver via_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = via,
        .probe          = via_init_one,
-       .remove         = ata_pci_remove_one
+       .remove         = ata_pci_remove_one,
+       .suspend        = ata_pci_device_suspend,
+       .resume         = via_reinit_one,
 };
 
 static int __init via_init(void)