All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] pata_sil680 suspend/resume
@ 2006-11-22 17:28 Alan
  2007-02-26 21:17 ` Guennadi Liakhovetski
  0 siblings, 1 reply; 13+ messages in thread
From: Alan @ 2006-11-22 17:28 UTC (permalink / raw)
  To: akpm, linux-kernel, jgarzik

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>

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.19-rc5-mm2/drivers/ata/pata_sil680.c linux-2.6.19-rc5-mm2/drivers/ata/pata_sil680.c
--- linux.vanilla-2.6.19-rc5-mm2/drivers/ata/pata_sil680.c	2006-11-15 13:26:00.000000000 +0000
+++ linux-2.6.19-rc5-mm2/drivers/ata/pata_sil680.c	2006-11-22 14:44:57.221814608 +0000
@@ -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
@@ -262,32 +262,20 @@
 	.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 */
@@ -322,8 +310,6 @@
 	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);
@@ -342,11 +328,51 @@
 		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), },
 
@@ -357,7 +383,9 @@
 	.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)


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2007-03-03  5:34 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-22 17:28 [PATCH] pata_sil680 suspend/resume Alan
2007-02-26 21:17 ` Guennadi Liakhovetski
2007-02-26 21:38   ` Guennadi Liakhovetski
2007-02-28 21:19   ` Guennadi Liakhovetski
2007-02-28 21:19     ` Guennadi Liakhovetski
2007-03-01 22:11     ` Guennadi Liakhovetski
2007-03-02  8:45       ` [PATCH 1/2 -stable] libata: add missing PM callbacks Tejun Heo
2007-03-02  8:46         ` [PATCH 2/2 -stable] libata: add missing CONFIG_PM in LLDs Tejun Heo
2007-03-03  0:18           ` Nigel Cunningham
2007-03-03  0:18             ` [linux-pm] " Nigel Cunningham
2007-03-03  3:20             ` Tejun Heo
2007-03-03  5:34               ` Nigel Cunningham
2007-03-02 22:42         ` [PATCH 1/2 -stable] libata: add missing PM callbacks Guennadi Liakhovetski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.