diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2011-10-13 14:59:35 +0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2011-10-14 21:32:54 +0400 |
commit | 067f8c7b490edc8cc947666516f2c6833b676a2e (patch) | |
tree | dec01f0519c6c12a907cb5efdb33d05344e8edcc /drivers/ata | |
parent | 81452182be1a95567da3718773dfcb45b42a579c (diff) | |
download | linux-067f8c7b490edc8cc947666516f2c6833b676a2e.tar.xz |
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>
Diffstat (limited to 'drivers/ata')
-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 @@ * pata_artop.c - ARTOP ATA controller driver * * (C) 2006 Red Hat - * (C) 2007 Bartlomiej Zolnierkiewicz + * (C) 2007,2011 Bartlomiej Zolnierkiewicz * * Based in part on drivers/ide/pci/aec62xx.c * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> @@ -28,7 +28,7 @@ #include <linux/ata.h> #define DRV_NAME "pata_artop" -#define DRV_VERSION "0.4.5" +#define DRV_VERSION "0.4.6" /* * The ARTOP has 33 Mhz and "over clocked" timing tables. Until we @@ -313,6 +313,33 @@ static struct ata_port_operations artop6260_ops = { .prereset = artop62x0_pre_reset, }; +static void atp8xx_fixup(struct pci_dev *pdev) +{ + if (pdev->device == 0x0005) + /* BIOS may have left us in UDMA, clear it before libata probe */ + pci_write_config_byte(pdev, 0x54, 0); + else if (pdev->device == 0x0008 || pdev->device == 0x0009) { + u8 reg; + + /* Mac systems come up with some registers not set as we + will need them */ + + /* Clear reset & test bits */ + pci_read_config_byte(pdev, 0x49, ®); + pci_write_config_byte(pdev, 0x49, reg & ~0x30); + + /* PCI latency must be > 0x80 for burst mode, tweak it + * if required. + */ + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®); + if (reg <= 0x80) + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90); + + /* Enable IRQ output and burst mode */ + pci_read_config_byte(pdev, 0x4a, ®); + pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80); + } +} /** * 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) if (rc) return rc; - if (id->driver_data == 0) { /* 6210 variant */ + if (id->driver_data == 0) /* 6210 variant */ ppi[0] = &info_6210; - /* BIOS may have left us in UDMA, clear it before libata probe */ - pci_write_config_byte(pdev, 0x54, 0); - } else if (id->driver_data == 1) /* 6260 */ ppi[0] = &info_626x; else if (id->driver_data == 2) { /* 6280 or 6280 + fast */ unsigned long io = pci_resource_start(pdev, 4); - u8 reg; ppi[0] = &info_628x; if (inb(io) & 0x10) ppi[0] = &info_628x_fast; - /* Mac systems come up with some registers not set as we - will need them */ - - /* Clear reset & test bits */ - pci_read_config_byte(pdev, 0x49, ®); - pci_write_config_byte(pdev, 0x49, reg & ~ 0x30); - - /* PCI latency must be > 0x80 for burst mode, tweak it - * if required. - */ - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, ®); - if (reg <= 0x80) - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x90); - - /* Enable IRQ output and burst mode */ - pci_read_config_byte(pdev, 0x4a, ®); - pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80); - } BUG_ON(ppi[0] == NULL); + atp8xx_fixup(pdev); + return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0); } @@ -416,11 +423,32 @@ static const struct pci_device_id artop_pci_tbl[] = { { } /* terminate list */ }; +#ifdef CONFIG_PM +static int atp8xx_reinit_one(struct pci_dev *pdev) +{ + struct ata_host *host = dev_get_drvdata(&pdev->dev); + int rc; + + rc = ata_pci_device_do_resume(pdev); + if (rc) + return rc; + + atp8xx_fixup(pdev); + + ata_host_resume(host); + return 0; +} +#endif + static struct pci_driver artop_pci_driver = { .name = DRV_NAME, .id_table = artop_pci_tbl, .probe = artop_init_one, .remove = ata_pci_remove_one, +#ifdef CONFIG_PM + .suspend = ata_pci_device_suspend, + .resume = atp8xx_reinit_one, +#endif }; static int __init artop_init(void) @@ -436,9 +464,8 @@ static void __exit artop_exit(void) module_init(artop_init); module_exit(artop_exit); -MODULE_AUTHOR("Alan Cox"); +MODULE_AUTHOR("Alan Cox, Bartlomiej Zolnierkiewicz"); MODULE_DESCRIPTION("SCSI low-level driver for ARTOP PATA"); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, artop_pci_tbl); MODULE_VERSION(DRV_VERSION); - |