aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan <alan@lxorguk.ukuu.org.uk>2006-11-22 12:28:41 -0500
committerJeff Garzik <jeff@garzik.org>2006-12-01 22:46:46 -0500
commit8550c1637ba7dd96a76353eb52d31088f9c2f5fe (patch)
tree86b56ff88f5b9f74df07922e4c601cde2e9cd481
parentad4a42d287546888349ad24d351673a59f429ee8 (diff)
[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: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/pata_sil680.c82
1 files changed, 55 insertions, 27 deletions
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c
index 11942fd03b55..5d3b42ec8e47 100644
--- a/drivers/ata/pata_sil680.c
+++ b/drivers/ata/pata_sil680.c
@@ -33,7 +33,7 @@
33#include <linux/libata.h> 33#include <linux/libata.h>
34 34
35#define DRV_NAME "pata_sil680" 35#define DRV_NAME "pata_sil680"
36#define DRV_VERSION "0.3.2" 36#define DRV_VERSION "0.4.1"
37 37
38/** 38/**
39 * sil680_selreg - return register base 39 * sil680_selreg - return register base
@@ -263,32 +263,20 @@ static struct ata_port_operations sil680_port_ops = {
263 .host_stop = ata_host_stop 263 .host_stop = ata_host_stop
264}; 264};
265 265
266static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id) 266/**
267 * sil680_init_chip - chip setup
268 * @pdev: PCI device
269 *
270 * Perform all the chip setup which must be done both when the device
271 * is powered up on boot and when we resume in case we resumed from RAM.
272 * Returns the final clock settings.
273 */
274
275static u8 sil680_init_chip(struct pci_dev *pdev)
267{ 276{
268 static struct ata_port_info info = {
269 .sht = &sil680_sht,
270 .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
271 .pio_mask = 0x1f,
272 .mwdma_mask = 0x07,
273 .udma_mask = 0x7f,
274 .port_ops = &sil680_port_ops
275 };
276 static struct ata_port_info info_slow = {
277 .sht = &sil680_sht,
278 .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
279 .pio_mask = 0x1f,
280 .mwdma_mask = 0x07,
281 .udma_mask = 0x3f,
282 .port_ops = &sil680_port_ops
283 };
284 static struct ata_port_info *port_info[2] = {&info, &info};
285 static int printed_version;
286 u32 class_rev = 0; 277 u32 class_rev = 0;
287 u8 tmpbyte = 0; 278 u8 tmpbyte = 0;
288 279
289 if (!printed_version++)
290 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
291
292 pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev); 280 pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
293 class_rev &= 0xff; 281 class_rev &= 0xff;
294 /* FIXME: double check */ 282 /* FIXME: double check */
@@ -323,8 +311,6 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
323 pci_read_config_byte(pdev, 0x8A, &tmpbyte); 311 pci_read_config_byte(pdev, 0x8A, &tmpbyte);
324 printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n", 312 printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
325 tmpbyte & 1, tmpbyte & 0x30); 313 tmpbyte & 1, tmpbyte & 0x30);
326 if ((tmpbyte & 0x30) == 0)
327 port_info[0] = port_info[1] = &info_slow;
328 314
329 pci_write_config_byte(pdev, 0xA1, 0x72); 315 pci_write_config_byte(pdev, 0xA1, 0x72);
330 pci_write_config_word(pdev, 0xA2, 0x328A); 316 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)
343 case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break; 329 case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break;
344 /* This last case is _NOT_ ok */ 330 /* This last case is _NOT_ ok */
345 case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n"); 331 case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n");
346 return -EIO; 332 }
333 return tmpbyte & 0x30;
334}
335
336static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
337{
338 static struct ata_port_info info = {
339 .sht = &sil680_sht,
340 .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
341 .pio_mask = 0x1f,
342 .mwdma_mask = 0x07,
343 .udma_mask = 0x7f,
344 .port_ops = &sil680_port_ops
345 };
346 static struct ata_port_info info_slow = {
347 .sht = &sil680_sht,
348 .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
349 .pio_mask = 0x1f,
350 .mwdma_mask = 0x07,
351 .udma_mask = 0x3f,
352 .port_ops = &sil680_port_ops
353 };
354 static struct ata_port_info *port_info[2] = {&info, &info};
355 static int printed_version;
356
357 if (!printed_version++)
358 dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
359
360 switch(sil680_init_chip(pdev))
361 {
362 case 0:
363 port_info[0] = port_info[1] = &info_slow;
364 break;
365 case 0x30:
366 return -ENODEV;
347 } 367 }
348 return ata_pci_init_one(pdev, port_info, 2); 368 return ata_pci_init_one(pdev, port_info, 2);
349} 369}
350 370
371static int sil680_reinit_one(struct pci_dev *pdev)
372{
373 sil680_init_chip(pdev);
374 return ata_pci_device_resume(pdev);
375}
376
351static const struct pci_device_id sil680[] = { 377static const struct pci_device_id sil680[] = {
352 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), }, 378 { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), },
353 379
@@ -358,7 +384,9 @@ static struct pci_driver sil680_pci_driver = {
358 .name = DRV_NAME, 384 .name = DRV_NAME,
359 .id_table = sil680, 385 .id_table = sil680,
360 .probe = sil680_init_one, 386 .probe = sil680_init_one,
361 .remove = ata_pci_remove_one 387 .remove = ata_pci_remove_one,
388 .suspend = ata_pci_device_suspend,
389 .resume = sil680_reinit_one,
362}; 390};
363 391
364static int __init sil680_init(void) 392static int __init sil680_init(void)