diff options
Diffstat (limited to 'drivers/ata/pata_sil680.c')
-rw-r--r-- | drivers/ata/pata_sil680.c | 84 |
1 files changed, 56 insertions, 28 deletions
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 4a2b72b4be8..32cf0bfa892 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -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 @@ -218,13 +218,13 @@ static struct scsi_host_template sil680_sht = { .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, - .max_sectors = ATA_MAX_SECTORS, .cmd_per_lun = ATA_SHT_CMD_PER_LUN, .emulated = ATA_SHT_EMULATED, .use_clustering = ATA_SHT_USE_CLUSTERING, .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; @@ -262,32 +262,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 */ @@ -322,8 +310,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); @@ -342,11 +328,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), }, @@ -357,7 +383,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) |