Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8550c163 authored by Alan Cox's avatar Alan Cox Committed by Jeff Garzik
Browse files

[PATCH] pata_sil680 suspend/resume



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: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent ad4a42d2
Loading
Loading
Loading
Loading
+55 −27
Original line number Diff line number Diff line
@@ -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
@@ -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 */
@@ -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);
@@ -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), },

@@ -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)