diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2011-10-13 06:59:35 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2011-10-14 13:32:54 -0400 |
commit | 067f8c7b490edc8cc947666516f2c6833b676a2e (patch) | |
tree | dec01f0519c6c12a907cb5efdb33d05344e8edcc | |
parent | 81452182be1a95567da3718773dfcb45b42a579c (diff) |
pata_artop: add Power Management support
Fixes IDE -> libata regression.
There shouldn't be any problems with it as corresponding IDE's host
driver (aec62xx) has been supporting PCI Power Management since
Oct 10 2008 (commit feb22b7f "ide: add proper PCI PM support (v2)")
and IDE PM since Jun 14 2003 (patch v2.5.73 "ide: Power Management").
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r-- | drivers/ata/pata_artop.c | 81 |
1 files changed, 54 insertions, 27 deletions
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index ef2bec0d4479..4b8b22efc00b 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * pata_artop.c - ARTOP ATA controller driver | 2 | * pata_artop.c - ARTOP ATA controller driver |
3 | * | 3 | * |
4 | * (C) 2006 Red Hat | 4 | * (C) 2006 Red Hat |
5 | * (C) 2007 Bartlomiej Zolnierkiewicz | 5 | * (C) 2007,2011 Bartlomiej Zolnierkiewicz |
6 | * | 6 | * |
7 | * Based in part on drivers/ide/pci/aec62xx.c | 7 | * Based in part on drivers/ide/pci/aec62xx.c |
8 | * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> | 8 | * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> |
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/ata.h> | 28 | #include <linux/ata.h> |
29 | 29 | ||
30 | #define DRV_NAME "pata_artop" | 30 | #define DRV_NAME "pata_artop" |
31 | #define DRV_VERSION "0.4.5" | 31 | #define DRV_VERSION "0.4.6" |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * The ARTOP has 33 Mhz and "over clocked" timing tables. Until we | 34 | * The ARTOP has 33 Mhz and "over clocked" timing tables. Until we |
@@ -313,6 +313,33 @@ static struct ata_port_operations artop6260_ops = { | |||
313 | .prereset = artop62x0_pre_reset, | 313 | .prereset = artop62x0_pre_reset, |
314 | }; | 314 | }; |
315 | 315 | ||
316 | static void atp8xx_fixup(struct pci_dev *pdev) | ||
317 | { | ||
318 | if (pdev->device == 0x0005) | ||
319 | /* BIOS may have left us in UDMA, clear it before libata probe */ | ||
320 | pci_write_config_byte(pdev, 0x54, 0); | ||
321 | else if (pdev->device == 0x0008 || pdev->device == 0x0009) { | ||
322 | u8 reg; | ||
323 | |||
324 | /* Mac systems come up with some registers not set as we | ||
325 | will need them */ | ||
326 | |||
327 | /* Clear reset & test bits */ | ||
328 | pci_read_config_byte(pdev, 0x49, ®); | ||
329 | pci_write_config_byte(pdev, 0x49, reg & ~0x30); | ||
330 | |||
331 | /* PCI latency must be > 0x80 for burst mode, tweak it | ||
332 | * if required. | ||
333 | */ | ||
334 | pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®); | ||
335 | if (reg <= 0x80) | ||
336 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90); | ||
337 | |||
338 | /* Enable IRQ output and burst mode */ | ||
339 | pci_read_config_byte(pdev, 0x4a, ®); | ||
340 | pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80); | ||
341 | } | ||
342 | } | ||
316 | 343 | ||
317 | /** | 344 | /** |
318 | * artop_init_one - Register ARTOP ATA PCI device with kernel services | 345 | * artop_init_one - Register ARTOP ATA PCI device with kernel services |
@@ -367,42 +394,22 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) | |||
367 | if (rc) | 394 | if (rc) |
368 | return rc; | 395 | return rc; |
369 | 396 | ||
370 | if (id->driver_data == 0) { /* 6210 variant */ | 397 | if (id->driver_data == 0) /* 6210 variant */ |
371 | ppi[0] = &info_6210; | 398 | ppi[0] = &info_6210; |
372 | /* BIOS may have left us in UDMA, clear it before libata probe */ | ||
373 | pci_write_config_byte(pdev, 0x54, 0); | ||
374 | } | ||
375 | else if (id->driver_data == 1) /* 6260 */ | 399 | else if (id->driver_data == 1) /* 6260 */ |
376 | ppi[0] = &info_626x; | 400 | ppi[0] = &info_626x; |
377 | else if (id->driver_data == 2) { /* 6280 or 6280 + fast */ | 401 | else if (id->driver_data == 2) { /* 6280 or 6280 + fast */ |
378 | unsigned long io = pci_resource_start(pdev, 4); | 402 | unsigned long io = pci_resource_start(pdev, 4); |
379 | u8 reg; | ||
380 | 403 | ||
381 | ppi[0] = &info_628x; | 404 | ppi[0] = &info_628x; |
382 | if (inb(io) & 0x10) | 405 | if (inb(io) & 0x10) |
383 | ppi[0] = &info_628x_fast; | 406 | ppi[0] = &info_628x_fast; |
384 | /* Mac systems come up with some registers not set as we | ||
385 | will need them */ | ||
386 | |||
387 | /* Clear reset & test bits */ | ||
388 | pci_read_config_byte(pdev, 0x49, ®); | ||
389 | pci_write_config_byte(pdev, 0x49, reg & ~ 0x30); | ||
390 | |||
391 | /* PCI latency must be > 0x80 for burst mode, tweak it | ||
392 | * if required. | ||
393 | */ | ||
394 | pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®); | ||
395 | if (reg <= 0x80) | ||
396 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90); | ||
397 | |||
398 | /* Enable IRQ output and burst mode */ | ||
399 | pci_read_config_byte(pdev, 0x4a, ®); | ||
400 | pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80); | ||
401 | |||
402 | } | 407 | } |
403 | 408 | ||
404 | BUG_ON(ppi[0] == NULL); | 409 | BUG_ON(ppi[0] == NULL); |
405 | 410 | ||
411 | atp8xx_fixup(pdev); | ||
412 | |||
406 | return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0); | 413 | return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0); |
407 | } | 414 | } |
408 | 415 | ||
@@ -416,11 +423,32 @@ static const struct pci_device_id artop_pci_tbl[] = { | |||
416 | { } /* terminate list */ | 423 | { } /* terminate list */ |
417 | }; | 424 | }; |
418 | 425 | ||
426 | #ifdef CONFIG_PM | ||
427 | static int atp8xx_reinit_one(struct pci_dev *pdev) | ||
428 | { | ||
429 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | ||
430 | int rc; | ||
431 | |||
432 | rc = ata_pci_device_do_resume(pdev); | ||
433 | if (rc) | ||
434 | return rc; | ||
435 | |||
436 | atp8xx_fixup(pdev); | ||
437 | |||
438 | ata_host_resume(host); | ||
439 | return 0; | ||
440 | } | ||
441 | #endif | ||
442 | |||
419 | static struct pci_driver artop_pci_driver = { | 443 | static struct pci_driver artop_pci_driver = { |
420 | .name = DRV_NAME, | 444 | .name = DRV_NAME, |
421 | .id_table = artop_pci_tbl, | 445 | .id_table = artop_pci_tbl, |
422 | .probe = artop_init_one, | 446 | .probe = artop_init_one, |
423 | .remove = ata_pci_remove_one, | 447 | .remove = ata_pci_remove_one, |
448 | #ifdef CONFIG_PM | ||
449 | .suspend = ata_pci_device_suspend, | ||
450 | .resume = atp8xx_reinit_one, | ||
451 | #endif | ||
424 | }; | 452 | }; |
425 | 453 | ||
426 | static int __init artop_init(void) | 454 | static int __init artop_init(void) |
@@ -436,9 +464,8 @@ static void __exit artop_exit(void) | |||
436 | module_init(artop_init); | 464 | module_init(artop_init); |
437 | module_exit(artop_exit); | 465 | module_exit(artop_exit); |
438 | 466 | ||
439 | MODULE_AUTHOR("Alan Cox"); | 467 | MODULE_AUTHOR("Alan Cox, Bartlomiej Zolnierkiewicz"); |
440 | MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA"); | 468 | MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA"); |
441 | MODULE_LICENSE("GPL"); | 469 | MODULE_LICENSE("GPL"); |
442 | MODULE_DEVICE_TABLE(pci, artop_pci_tbl); | 470 | MODULE_DEVICE_TABLE(pci, artop_pci_tbl); |
443 | MODULE_VERSION(DRV_VERSION); | 471 | MODULE_VERSION(DRV_VERSION); |
444 | |||