|
@@ -33,7 +33,7 @@
|
|
#include <linux/libata.h>
|
|
#include <linux/libata.h>
|
|
|
|
|
|
#define DRV_NAME "pata_sil680"
|
|
#define DRV_NAME "pata_sil680"
|
|
-#define DRV_VERSION "0.3.2"
|
|
|
|
|
|
+#define DRV_VERSION "0.4.1"
|
|
|
|
|
|
/**
|
|
/**
|
|
* sil680_selreg - return register base
|
|
* sil680_selreg - return register base
|
|
@@ -263,32 +263,20 @@ static struct ata_port_operations sil680_port_ops = {
|
|
.host_stop = ata_host_stop
|
|
.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;
|
|
u32 class_rev = 0;
|
|
u8 tmpbyte = 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);
|
|
pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class_rev);
|
|
class_rev &= 0xff;
|
|
class_rev &= 0xff;
|
|
/* FIXME: double check */
|
|
/* FIXME: double check */
|
|
@@ -323,8 +311,6 @@ static int sil680_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
|
|
pci_read_config_byte(pdev, 0x8A, &tmpbyte);
|
|
printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
|
|
printk(KERN_INFO "sil680: BA5_EN = %d clock = %02X\n",
|
|
tmpbyte & 1, tmpbyte & 0x30);
|
|
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_byte(pdev, 0xA1, 0x72);
|
|
pci_write_config_word(pdev, 0xA2, 0x328A);
|
|
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)
|
|
case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break;
|
|
case 0x20: printk(KERN_INFO "sil680: Using PCI clock.\n");break;
|
|
/* This last case is _NOT_ ok */
|
|
/* This last case is _NOT_ ok */
|
|
case 0x30: printk(KERN_ERR "sil680: Clock disabled ?\n");
|
|
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);
|
|
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[] = {
|
|
static const struct pci_device_id sil680[] = {
|
|
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), },
|
|
{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), },
|
|
|
|
|
|
@@ -358,7 +384,9 @@ static struct pci_driver sil680_pci_driver = {
|
|
.name = DRV_NAME,
|
|
.name = DRV_NAME,
|
|
.id_table = sil680,
|
|
.id_table = sil680,
|
|
.probe = sil680_init_one,
|
|
.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)
|
|
static int __init sil680_init(void)
|