Commit b503ce39 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Jeff Garzik

[libata] Fix flush of Device Control register to device

Also add some ServerWorks-specific tweaks.
parent 2cb1b24d
......@@ -133,7 +133,11 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
outb(tf->ctl, ioaddr->ctl_addr);
if (tf->ctl != ap->last_ctl) {
outb(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
outb(tf->hob_feature, ioaddr->error_addr);
......@@ -187,7 +191,11 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
writeb(tf->ctl, ap->ioaddr.ctl_addr);
if (tf->ctl != ap->last_ctl) {
writeb(tf->ctl, ap->ioaddr.ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
writeb(tf->hob_feature, (void *) ioaddr->error_addr);
......@@ -1281,9 +1289,9 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
/* software reset. causes dev0 to be selected */
if (ap->flags & ATA_FLAG_MMIO) {
writeb(ap->ctl, ioaddr->ctl_addr);
udelay(10); /* FIXME: flush */
udelay(20); /* FIXME: flush */
writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
udelay(10); /* FIXME: flush */
udelay(20); /* FIXME: flush */
writeb(ap->ctl, ioaddr->ctl_addr);
} else {
outb(ap->ctl, ioaddr->ctl_addr);
......@@ -2755,6 +2763,7 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
ap->cbl = ATA_CBL_NONE;
ap->device[0].flags = ATA_DFLAG_MASTER;
ap->active_tag = ATA_TAG_POISON;
ap->last_ctl = 0xFF;
/* ata_engine init */
ap->eng.flags = 0;
......
......@@ -69,8 +69,11 @@ static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
struct ata_ioports *ioaddr = &ap->ioaddr;
unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
writeb(tf->ctl, ioaddr->ctl_addr);
if (tf->ctl != ap->last_ctl) {
writeb(tf->ctl, ioaddr->ctl_addr);
ap->last_ctl = tf->ctl;
ata_wait_idle(ap);
}
if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->error_addr);
writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr);
......@@ -311,13 +314,24 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
rc = -ENODEV;
goto err_out_unmap;
}
/* Clear a magic bit in SCR1 according to Darwin, those help
* some funky seagate drives (though so far, those were already
* set by the firmware on the machines I had access to
*/
writel(readl(mmio_base + 0x80) & ~0x00040000, mmio_base + 0x80);
/* Clear SATA error & interrupts we don't use */
writel(0xffffffff, mmio_base + 0x44);
writel(0x0, mmio_base + 0x88);
probe_ent->sht = &k2_sata_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
probe_ent->port_ops = &k2_sata_ops;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->mmio_base = mmio_base;
/*
......
......@@ -310,6 +310,7 @@ struct ata_port {
struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */
u8 ctl; /* cache of ATA control register */
u8 last_ctl; /* Cache last written value */
unsigned int bus_state;
unsigned int port_state;
unsigned int pio_mask;
......@@ -522,12 +523,12 @@ static inline u8 ata_irq_on(struct ata_port *ap)
struct ata_ioports *ioaddr = &ap->ioaddr;
ap->ctl &= ~ATA_NIEN;
ap->last_ctl = ap->ctl;
if (ap->flags & ATA_FLAG_MMIO)
writeb(ap->ctl, ioaddr->ctl_addr);
else
outb(ap->ctl, ioaddr->ctl_addr);
return ata_wait_idle(ap);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment