diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2008-04-19 16:17:34 (GMT) |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2008-04-19 16:17:34 (GMT) |
commit | cf816ecb533ab96b883dfdc0db174598b5b5c4d2 (patch) | |
tree | 1b7705db288ae2917105e624b01fdf81e0882bf1 /drivers/ata/pata_scc.c | |
parent | adf6d34e460387ee3e8f1e1875d52bff51212c7d (diff) | |
parent | 15f7d677ccff6f0f5de8a1ee43a792567e9f9de9 (diff) | |
download | linux-fsl-qoriq-cf816ecb533ab96b883dfdc0db174598b5b5c4d2.tar.xz |
Merge branch 'merge-fixes' into devel
Diffstat (limited to 'drivers/ata/pata_scc.c')
-rw-r--r-- | drivers/ata/pata_scc.c | 257 |
1 files changed, 118 insertions, 139 deletions
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 6c016de..e965b25 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -266,7 +266,7 @@ unsigned long scc_mode_filter(struct ata_device *adev, unsigned long mask) printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME); mask &= ~(0xE0 << ATA_SHIFT_UDMA); } - return ata_pci_default_filter(adev, mask); + return ata_bmdma_mode_filter(adev, mask); } /** @@ -274,7 +274,7 @@ unsigned long scc_mode_filter(struct ata_device *adev, unsigned long mask) * @ap: Port to which output is sent * @tf: ATA taskfile register set * - * Note: Original code is ata_tf_load(). + * Note: Original code is ata_sff_tf_load(). */ static void scc_tf_load (struct ata_port *ap, const struct ata_taskfile *tf) @@ -341,7 +341,7 @@ static u8 scc_check_status (struct ata_port *ap) * @ap: Port from which input is read * @tf: ATA taskfile register set for storing input * - * Note: Original code is ata_tf_read(). + * Note: Original code is ata_sff_tf_read(). */ static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf) @@ -373,7 +373,7 @@ static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf) * @ap: port to which command is being issued * @tf: ATA taskfile register set * - * Note: Original code is ata_exec_command(). + * Note: Original code is ata_sff_exec_command(). */ static void scc_exec_command (struct ata_port *ap, @@ -382,7 +382,7 @@ static void scc_exec_command (struct ata_port *ap, DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command); out_be32(ap->ioaddr.command_addr, tf->command); - ata_pause(ap); + ata_sff_pause(ap); } /** @@ -396,14 +396,14 @@ static u8 scc_check_altstatus (struct ata_port *ap) } /** - * scc_std_dev_select - Select device 0/1 on ATA bus + * scc_dev_select - Select device 0/1 on ATA bus * @ap: ATA channel to manipulate * @device: ATA device (numbered from zero) to select * - * Note: Original code is ata_std_dev_select(). + * Note: Original code is ata_sff_dev_select(). */ -static void scc_std_dev_select (struct ata_port *ap, unsigned int device) +static void scc_dev_select (struct ata_port *ap, unsigned int device) { u8 tmp; @@ -413,7 +413,7 @@ static void scc_std_dev_select (struct ata_port *ap, unsigned int device) tmp = ATA_DEVICE_OBS | ATA_DEV1; out_be32(ap->ioaddr.device_addr, tmp); - ata_pause(ap); + ata_sff_pause(ap); } /** @@ -441,7 +441,7 @@ static void scc_bmdma_setup (struct ata_queued_cmd *qc) out_be32(mmio + SCC_DMA_CMD, dmactl); /* issue r/w command */ - ap->ops->exec_command(ap, &qc->tf); + ap->ops->sff_exec_command(ap, &qc->tf); } /** @@ -476,7 +476,7 @@ static unsigned int scc_devchk (struct ata_port *ap, struct ata_ioports *ioaddr = &ap->ioaddr; u8 nsect, lbal; - ap->ops->dev_select(ap, device); + ap->ops->sff_dev_select(ap, device); out_be32(ioaddr->nsect_addr, 0x55); out_be32(ioaddr->lbal_addr, 0xaa); @@ -497,57 +497,78 @@ static unsigned int scc_devchk (struct ata_port *ap, } /** - * scc_bus_post_reset - PATA device post reset + * scc_wait_after_reset - wait for devices to become ready after reset * - * Note: Original code is ata_bus_post_reset(). + * Note: Original code is ata_sff_wait_after_reset */ -static int scc_bus_post_reset(struct ata_port *ap, unsigned int devmask, - unsigned long deadline) +int scc_wait_after_reset(struct ata_link *link, unsigned int devmask, + unsigned long deadline) { + struct ata_port *ap = link->ap; struct ata_ioports *ioaddr = &ap->ioaddr; unsigned int dev0 = devmask & (1 << 0); unsigned int dev1 = devmask & (1 << 1); - int rc; - - /* if device 0 was found in ata_devchk, wait for its - * BSY bit to clear + int rc, ret = 0; + + /* Spec mandates ">= 2ms" before checking status. We wait + * 150ms, because that was the magic delay used for ATAPI + * devices in Hale Landis's ATADRVR, for the period of time + * between when the ATA command register is written, and then + * status is checked. Because waiting for "a while" before + * checking status is fine, post SRST, we perform this magic + * delay here as well. + * + * Old drivers/ide uses the 2mS rule and then waits for ready. */ - if (dev0) { - rc = ata_wait_ready(ap, deadline); - if (rc && rc != -ENODEV) - return rc; - } + msleep(150); - /* if device 1 was found in ata_devchk, wait for - * register access, then wait for BSY to clear + /* always check readiness of the master device */ + rc = ata_sff_wait_ready(link, deadline); + /* -ENODEV means the odd clown forgot the D7 pulldown resistor + * and TF status is 0xff, bail out on it too. */ - while (dev1) { - u8 nsect, lbal; + if (rc) + return rc; - ap->ops->dev_select(ap, 1); - nsect = in_be32(ioaddr->nsect_addr); - lbal = in_be32(ioaddr->lbal_addr); - if ((nsect == 1) && (lbal == 1)) - break; - if (time_after(jiffies, deadline)) - return -EBUSY; - msleep(50); /* give drive a breather */ - } + /* if device 1 was found in ata_devchk, wait for register + * access briefly, then wait for BSY to clear. + */ if (dev1) { - rc = ata_wait_ready(ap, deadline); - if (rc && rc != -ENODEV) - return rc; + int i; + + ap->ops->sff_dev_select(ap, 1); + + /* Wait for register access. Some ATAPI devices fail + * to set nsect/lbal after reset, so don't waste too + * much time on it. We're gonna wait for !BSY anyway. + */ + for (i = 0; i < 2; i++) { + u8 nsect, lbal; + + nsect = in_be32(ioaddr->nsect_addr); + lbal = in_be32(ioaddr->lbal_addr); + if ((nsect == 1) && (lbal == 1)) + break; + msleep(50); /* give drive a breather */ + } + + rc = ata_sff_wait_ready(link, deadline); + if (rc) { + if (rc != -ENODEV) + return rc; + ret = rc; + } } /* is all this really necessary? */ - ap->ops->dev_select(ap, 0); + ap->ops->sff_dev_select(ap, 0); if (dev1) - ap->ops->dev_select(ap, 1); + ap->ops->sff_dev_select(ap, 1); if (dev0) - ap->ops->dev_select(ap, 0); + ap->ops->sff_dev_select(ap, 0); - return 0; + return ret; } /** @@ -570,32 +591,22 @@ static unsigned int scc_bus_softreset(struct ata_port *ap, unsigned int devmask, udelay(20); out_be32(ioaddr->ctl_addr, ap->ctl); - /* wait a while before checking status */ - ata_wait_after_reset(ap, deadline); - - /* Before we perform post reset processing we want to see if - * the bus shows 0xFF because the odd clown forgets the D7 - * pulldown resistor. - */ - if (scc_check_status(ap) == 0xFF) - return 0; - - scc_bus_post_reset(ap, devmask, deadline); + scc_wait_after_reset(&ap->link, devmask, deadline); return 0; } /** - * scc_std_softreset - reset host port via ATA SRST + * scc_softreset - reset host port via ATA SRST * @ap: port to reset * @classes: resulting classes of attached devices * @deadline: deadline jiffies for the operation * - * Note: Original code is ata_std_softreset(). + * Note: Original code is ata_sff_softreset(). */ -static int scc_std_softreset(struct ata_link *link, unsigned int *classes, - unsigned long deadline) +static int scc_softreset(struct ata_link *link, unsigned int *classes, + unsigned long deadline) { struct ata_port *ap = link->ap; unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; @@ -604,11 +615,6 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes, DPRINTK("ENTER\n"); - if (ata_link_offline(link)) { - classes[0] = ATA_DEV_NONE; - goto out; - } - /* determine if device 0/1 are present */ if (scc_devchk(ap, 0)) devmask |= (1 << 0); @@ -616,7 +622,7 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes, devmask |= (1 << 1); /* select device 0 again */ - ap->ops->dev_select(ap, 0); + ap->ops->sff_dev_select(ap, 0); /* issue bus reset */ DPRINTK("about to softreset, devmask=%x\n", devmask); @@ -628,13 +634,12 @@ static int scc_std_softreset(struct ata_link *link, unsigned int *classes, } /* determine by signature whether we have ATA or ATAPI devices */ - classes[0] = ata_dev_try_classify(&ap->link.device[0], + classes[0] = ata_sff_dev_classify(&ap->link.device[0], devmask & (1 << 0), &err); if (slave_possible && err != 0x81) - classes[1] = ata_dev_try_classify(&ap->link.device[1], + classes[1] = ata_sff_dev_classify(&ap->link.device[1], devmask & (1 << 1), &err); - out: DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]); return 0; } @@ -695,7 +700,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc) printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME); out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT); /* TBD: SW reset */ - scc_std_softreset(&ap->link, &classes, deadline); + scc_softreset(&ap->link, &classes, deadline); continue; } @@ -721,7 +726,7 @@ static void scc_bmdma_stop (struct ata_queued_cmd *qc) in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START); /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ - ata_altstatus(ap); /* dummy read */ + ata_sff_altstatus(ap); /* dummy read */ } /** @@ -742,7 +747,7 @@ static u8 scc_bmdma_status (struct ata_port *ap) return host_stat; /* errata A252,A308 workaround: Step4 */ - if ((ata_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ)) + if ((ata_sff_altstatus(ap) & ATA_ERR) && (int_status & INTSTS_INTRQ)) return (host_stat | ATA_DMA_INTR); /* errata A308 workaround Step5 */ @@ -773,7 +778,7 @@ static u8 scc_bmdma_status (struct ata_port *ap) * @buflen: buffer length * @rw: read/write * - * Note: Original code is ata_data_xfer(). + * Note: Original code is ata_sff_data_xfer(). */ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf, @@ -782,28 +787,28 @@ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf, struct ata_port *ap = dev->link->ap; unsigned int words = buflen >> 1; unsigned int i; - u16 *buf16 = (u16 *) buf; + __le16 *buf16 = (__le16 *) buf; void __iomem *mmio = ap->ioaddr.data_addr; /* Transfer multiple of 2 bytes */ if (rw == READ) for (i = 0; i < words; i++) - buf16[i] = le16_to_cpu(in_be32(mmio)); + buf16[i] = cpu_to_le16(in_be32(mmio)); else for (i = 0; i < words; i++) - out_be32(mmio, cpu_to_le16(buf16[i])); + out_be32(mmio, le16_to_cpu(buf16[i])); /* Transfer trailing 1 byte, if any. */ if (unlikely(buflen & 0x01)) { - u16 align_buf[1] = { 0 }; + __le16 align_buf[1] = { 0 }; unsigned char *trailing_buf = buf + buflen - 1; if (rw == READ) { - align_buf[0] = le16_to_cpu(in_be32(mmio)); + align_buf[0] = cpu_to_le16(in_be32(mmio)); memcpy(trailing_buf, align_buf, 1); } else { memcpy(align_buf, trailing_buf, 1); - out_be32(mmio, cpu_to_le16(align_buf[0])); + out_be32(mmio, le16_to_cpu(align_buf[0])); } words++; } @@ -815,7 +820,7 @@ static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf, * scc_irq_on - Enable interrupts on a port. * @ap: Port on which interrupts are enabled. * - * Note: Original code is ata_irq_on(). + * Note: Original code is ata_sff_irq_on(). */ static u8 scc_irq_on (struct ata_port *ap) @@ -829,19 +834,19 @@ static u8 scc_irq_on (struct ata_port *ap) out_be32(ioaddr->ctl_addr, ap->ctl); tmp = ata_wait_idle(ap); - ap->ops->irq_clear(ap); + ap->ops->sff_irq_clear(ap); return tmp; } /** - * scc_bmdma_freeze - Freeze BMDMA controller port + * scc_freeze - Freeze BMDMA controller port * @ap: port to freeze * - * Note: Original code is ata_bmdma_freeze(). + * Note: Original code is ata_sff_freeze(). */ -static void scc_bmdma_freeze (struct ata_port *ap) +static void scc_freeze (struct ata_port *ap) { struct ata_ioports *ioaddr = &ap->ioaddr; @@ -854,9 +859,9 @@ static void scc_bmdma_freeze (struct ata_port *ap) * ATA_NIEN manipulation. Also, many controllers fail to mask * previously pending IRQ on ATA_NIEN assertion. Clear it. */ - ata_chk_status(ap); + ap->ops->sff_check_status(ap); - ap->ops->irq_clear(ap); + ap->ops->sff_irq_clear(ap); } /** @@ -868,18 +873,18 @@ static void scc_bmdma_freeze (struct ata_port *ap) static int scc_pata_prereset(struct ata_link *link, unsigned long deadline) { link->ap->cbl = ATA_CBL_PATA80; - return ata_std_prereset(link, deadline); + return ata_sff_prereset(link, deadline); } /** - * scc_std_postreset - standard postreset callback + * scc_postreset - standard postreset callback * @ap: the target ata_port * @classes: classes of attached devices * - * Note: Original code is ata_std_postreset(). + * Note: Original code is ata_sff_postreset(). */ -static void scc_std_postreset(struct ata_link *link, unsigned int *classes) +static void scc_postreset(struct ata_link *link, unsigned int *classes) { struct ata_port *ap = link->ap; @@ -887,9 +892,9 @@ static void scc_std_postreset(struct ata_link *link, unsigned int *classes) /* is double-select really necessary? */ if (classes[0] != ATA_DEV_NONE) - ap->ops->dev_select(ap, 1); + ap->ops->sff_dev_select(ap, 1); if (classes[1] != ATA_DEV_NONE) - ap->ops->dev_select(ap, 0); + ap->ops->sff_dev_select(ap, 0); /* bail out if no device is present */ if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) { @@ -905,24 +910,13 @@ static void scc_std_postreset(struct ata_link *link, unsigned int *classes) } /** - * scc_error_handler - Stock error handler for BMDMA controller - * @ap: port to handle error for - */ - -static void scc_error_handler (struct ata_port *ap) -{ - ata_bmdma_drive_eh(ap, scc_pata_prereset, scc_std_softreset, NULL, - scc_std_postreset); -} - -/** - * scc_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt. + * scc_irq_clear - Clear PCI IDE BMDMA interrupt. * @ap: Port associated with this ATA transaction. * - * Note: Original code is ata_bmdma_irq_clear(). + * Note: Original code is ata_sff_irq_clear(). */ -static void scc_bmdma_irq_clear (struct ata_port *ap) +static void scc_irq_clear (struct ata_port *ap) { void __iomem *mmio = ap->ioaddr.bmdma_addr; @@ -968,52 +962,37 @@ static void scc_port_stop (struct ata_port *ap) } static struct scsi_host_template scc_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .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, + ATA_BMDMA_SHT(DRV_NAME), }; -static const struct ata_port_operations scc_pata_ops = { +static struct ata_port_operations scc_pata_ops = { + .inherits = &ata_bmdma_port_ops, + .set_piomode = scc_set_piomode, .set_dmamode = scc_set_dmamode, .mode_filter = scc_mode_filter, - .tf_load = scc_tf_load, - .tf_read = scc_tf_read, - .exec_command = scc_exec_command, - .check_status = scc_check_status, - .check_altstatus = scc_check_altstatus, - .dev_select = scc_std_dev_select, + .sff_tf_load = scc_tf_load, + .sff_tf_read = scc_tf_read, + .sff_exec_command = scc_exec_command, + .sff_check_status = scc_check_status, + .sff_check_altstatus = scc_check_altstatus, + .sff_dev_select = scc_dev_select, .bmdma_setup = scc_bmdma_setup, .bmdma_start = scc_bmdma_start, .bmdma_stop = scc_bmdma_stop, .bmdma_status = scc_bmdma_status, - .data_xfer = scc_data_xfer, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - - .freeze = scc_bmdma_freeze, - .thaw = ata_bmdma_thaw, + .sff_data_xfer = scc_data_xfer, - .error_handler = scc_error_handler, + .freeze = scc_freeze, + .prereset = scc_pata_prereset, + .softreset = scc_softreset, + .postreset = scc_postreset, .post_internal_cmd = scc_bmdma_stop, - .irq_clear = scc_bmdma_irq_clear, - .irq_on = scc_irq_on, + .sff_irq_clear = scc_irq_clear, + .sff_irq_on = scc_irq_on, .port_start = scc_port_start, .port_stop = scc_port_stop, @@ -1166,8 +1145,8 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return rc; - return ata_host_activate(host, pdev->irq, ata_interrupt, IRQF_SHARED, - &scc_sht); + return ata_host_activate(host, pdev->irq, ata_sff_interrupt, + IRQF_SHARED, &scc_sht); } static struct pci_driver scc_pci_driver = { |