Skip to content

Commit

Permalink
[PATCH] pata_sil680 suspend/resume
Browse files Browse the repository at this point in the history
The SI680 can come back from s2ram with the clocks disabled (crash time)
or wrong (ugly as this can cause CRC errors, and in theory corruption).
On a resume we must put the clock back.

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Alan authored and Jeff Garzik committed Dec 2, 2006
1 parent ad4a42d commit 8550c16
Showing 1 changed file with 55 additions and 27 deletions.
82 changes: 55 additions & 27 deletions drivers/ata/pata_sil680.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#include <linux/libata.h>

#define DRV_NAME "pata_sil680"
#define DRV_VERSION "0.3.2"
#define DRV_VERSION "0.4.1"

/**
* sil680_selreg - return register base
Expand Down Expand Up @@ -263,32 +263,20 @@ static struct ata_port_operations sil680_port_ops = {
.host_stop = ata_host_stop
};

static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
/**
* sil680_init_chip - chip setup
* @pdev: PCI device
*
* Perform all the chip setup which must be done both when the device
* is powered up on boot and when we resume in case we resumed from RAM.
* Returns the final clock settings.
*/

static u8 sil680_init_chip(struct pci_dev *pdev)
{
static struct ata_port_info info = {
.sht = &sil680_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x7f,
.port_ops = &sil680_port_ops
};
static struct ata_port_info info_slow = {
.sht = &sil680_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x3f,
.port_ops = &sil680_port_ops
};
static struct ata_port_info *port_info[2] = {&info, &info};
static int printed_version;
u32 class_rev = 0;
u8 tmpbyte = 0;

if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");

pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
class_rev &= 0xff;
/* FIXME: double check */
Expand Down Expand Up @@ -323,8 +311,6 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
tmpbyte & 1, tmpbyte & 0x30);
if ((tmpbyte & 0x30) == 0)
port_info[0] = port_info[1] = &info_slow;

pci_write_config_byte(pdev, 0xA1, 0x72);
pci_write_config_word(pdev, 0xA2, 0x328A);
Expand All @@ -343,11 +329,51 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break;
/* This last case is _NOT_ ok */
case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n");
return -EIO;
}
return tmpbyte & 0x30;
}

static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
static struct ata_port_info info = {
.sht = &sil680_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x7f,
.port_ops = &sil680_port_ops
};
static struct ata_port_info info_slow = {
.sht = &sil680_sht,
.flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x3f,
.port_ops = &sil680_port_ops
};
static struct ata_port_info *port_info[2] = {&info, &info};
static int printed_version;

if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");

switch(sil680_init_chip(pdev))
{
case 0:
port_info[0] = port_info[1] = &info_slow;
break;
case 0x30:
return -ENODEV;
}
return ata_pci_init_one(pdev, port_info, 2);
}

static int sil680_reinit_one(struct pci_dev *pdev)
{
sil680_init_chip(pdev);
return ata_pci_device_resume(pdev);
}

static const struct pci_device_id sil680[] = {
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), },

Expand All @@ -358,7 +384,9 @@ static struct pci_driver sil680_pci_driver = {
.name = DRV_NAME,
.id_table = sil680,
.probe = sil680_init_one,
.remove = ata_pci_remove_one
.remove = ata_pci_remove_one,
.suspend = ata_pci_device_suspend,
.resume = sil680_reinit_one,
};

static int __init sil680_init(void)
Expand Down

0 comments on commit 8550c16

Please sign in to comment.