sata_mv: simplify freeze/thaw bit-shift calculations
[safe/jmp/linux-2.6] / drivers / ata / sata_fsl.c
index e3bf954..fddd346 100644 (file)
@@ -35,7 +35,6 @@ enum {
        SATA_FSL_HOST_FLAGS     = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
                                ATA_FLAG_NCQ),
-       SATA_FSL_HOST_LFLAGS    = ATA_LFLAG_SKIP_D2H_BSY,
 
        SATA_FSL_MAX_CMDS       = SATA_FSL_QUEUE_DEPTH,
        SATA_FSL_CMD_HDR_SIZE   = 16,   /* 4 DWORDS */
@@ -245,17 +244,6 @@ struct sata_fsl_port_priv {
        dma_addr_t cmdslot_paddr;
        struct command_desc *cmdentry;
        dma_addr_t cmdentry_paddr;
-
-       /*
-        * SATA FSL controller has a Status FIS which should contain the
-        * received D2H FIS & taskfile registers. This SFIS is present in
-        * the command descriptor, and to have a ready reference to it,
-        * we are caching it here, quite similar to what is done in H/W on
-        * AHCI compliant devices by copying taskfile fields to a 32-bit
-        * register.
-        */
-
-       struct ata_taskfile tf;
 };
 
 /*
@@ -269,7 +257,7 @@ struct sata_fsl_host_priv {
 };
 
 static inline unsigned int sata_fsl_tag(unsigned int tag,
-                                       void __iomem * hcr_base)
+                                       void __iomem *hcr_base)
 {
        /* We let libATA core do actual (queue) tag allocation */
 
@@ -308,7 +296,7 @@ static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp,
        pp->cmdslot[tag].prde_fis_len =
            cpu_to_le32((num_prde << 16) | (fis_len << 2));
        pp->cmdslot[tag].ttl = cpu_to_le32(data_xfer_len & ~0x03);
-       pp->cmdslot[tag].desc_info = cpu_to_le32((desc_info | (tag & 0x1F)));
+       pp->cmdslot[tag].desc_info = cpu_to_le32(desc_info | (tag & 0x1F));
 
        VPRINTK("cda=0x%x, prde_fis_len=0x%x, ttl=0x%x, di=0x%x\n",
                pp->cmdslot[tag].cda,
@@ -318,7 +306,7 @@ static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp,
 }
 
 static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
-                                    u32 * ttl, dma_addr_t cmd_desc_paddr)
+                                    u32 *ttl, dma_addr_t cmd_desc_paddr)
 {
        struct scatterlist *sg;
        unsigned int num_prde = 0;
@@ -333,13 +321,14 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
        struct prde *prd_ptr_to_indirect_ext = NULL;
        unsigned indirect_ext_segment_sz = 0;
        dma_addr_t indirect_ext_segment_paddr;
+       unsigned int si;
 
-       VPRINTK("SATA FSL : cd = 0x%x, prd = 0x%x\n", cmd_desc, prd);
+       VPRINTK("SATA FSL : cd = 0x%p, prd = 0x%p\n", cmd_desc, prd);
 
        indirect_ext_segment_paddr = cmd_desc_paddr +
            SATA_FSL_CMD_DESC_OFFSET_TO_PRDT + SATA_FSL_MAX_PRD_DIRECT * 16;
 
-       ata_for_each_sg(sg, qc) {
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
                dma_addr_t sg_addr = sg_dma_address(sg);
                u32 sg_len = sg_dma_len(sg);
 
@@ -354,8 +343,8 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
                        ata_port_printk(qc->ap, KERN_ERR,
                                        "s/g len unaligned : 0x%x\n", sg_len);
 
-               if ((num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1)) &&
-                   (qc->n_iter + 1 != qc->n_elem)) {
+               if (num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1) &&
+                   sg_next(sg) != NULL) {
                        VPRINTK("setting indirect prde\n");
                        prd_ptr_to_indirect_ext = prd;
                        prd->dba = cpu_to_le32(indirect_ext_segment_paddr);
@@ -406,7 +395,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
        cd = (struct command_desc *)pp->cmdentry + tag;
        cd_paddr = pp->cmdentry_paddr + tag * SATA_FSL_CMD_DESC_SIZE;
 
-       ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) & cd->cfis);
+       ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) &cd->cfis);
 
        VPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x\n",
                cd->cfis[0], cd->cfis[1], cd->cfis[2]);
@@ -417,7 +406,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
        }
 
        /* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */
-       if (is_atapi_taskfile(&qc->tf)) {
+       if (ata_is_atapi(qc->tf.protocol)) {
                desc_info |= ATAPI_CMD;
                memset((void *)&cd->acmd, 0, 32);
                memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len);
@@ -458,11 +447,26 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
        VPRINTK("CE=0x%x, DE=0x%x, CC=0x%x, CmdStat = 0x%x\n",
                ioread32(CE + hcr_base),
                ioread32(DE + hcr_base),
-               ioread32(CC + hcr_base), ioread32(COMMANDSTAT + csr_base));
+               ioread32(CC + hcr_base),
+               ioread32(COMMANDSTAT + host_priv->csr_base));
 
        return 0;
 }
 
+static bool sata_fsl_qc_fill_rtf(struct ata_queued_cmd *qc)
+{
+       struct sata_fsl_port_priv *pp = qc->ap->private_data;
+       struct sata_fsl_host_priv *host_priv = qc->ap->host->private_data;
+       void __iomem *hcr_base = host_priv->hcr_base;
+       unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
+       struct command_desc *cd;
+
+       cd = pp->cmdentry + tag;
+
+       ata_tf_from_fis(cd->sfis, &qc->result_tf);
+       return true;
+}
+
 static int sata_fsl_scr_write(struct ata_port *ap, unsigned int sc_reg_in,
                               u32 val)
 {
@@ -521,7 +525,8 @@ static void sata_fsl_freeze(struct ata_port *ap)
                ioread32(CQ + hcr_base),
                ioread32(CA + hcr_base),
                ioread32(CE + hcr_base), ioread32(DE + hcr_base));
-       VPRINTK("CmdStat = 0x%x\n", ioread32(csr_base + COMMANDSTAT));
+       VPRINTK("CmdStat = 0x%x\n",
+               ioread32(host_priv->csr_base + COMMANDSTAT));
 
        /* disable interrupts on the controller/port */
        temp = ioread32(hcr_base + HCONTROL);
@@ -553,40 +558,6 @@ static void sata_fsl_thaw(struct ata_port *ap)
                ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
 }
 
-/*
- * NOTE : 1st D2H FIS from device does not update sfis in command descriptor.
- */
-static inline void sata_fsl_cache_taskfile_from_d2h_fis(struct ata_queued_cmd
-                                                       *qc,
-                                                       struct ata_port *ap)
-{
-       struct sata_fsl_port_priv *pp = ap->private_data;
-       u8 fis[6 * 4];
-       struct sata_fsl_host_priv *host_priv = ap->host->private_data;
-       void __iomem *hcr_base = host_priv->hcr_base;
-       unsigned int tag = sata_fsl_tag(qc->tag, hcr_base);
-       struct command_desc *cd;
-
-       cd = pp->cmdentry + tag;
-
-       memcpy(fis, &cd->sfis, 6 * 4);  /* should we use memcpy_from_io() */
-       ata_tf_from_fis(fis, &pp->tf);
-}
-
-static u8 sata_fsl_check_status(struct ata_port *ap)
-{
-       struct sata_fsl_port_priv *pp = ap->private_data;
-
-       return pp->tf.command;
-}
-
-static void sata_fsl_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
-       struct sata_fsl_port_priv *pp = ap->private_data;
-
-       *tf = pp->tf;
-}
-
 static int sata_fsl_port_start(struct ata_port *ap)
 {
        struct device *dev = ap->host->dev;
@@ -602,21 +573,9 @@ static int sata_fsl_port_start(struct ata_port *ap)
        if (!pp)
                return -ENOMEM;
 
-       /*
-        * allocate per command dma alignment pad buffer, which is used
-        * internally by libATA to ensure that all transfers ending on
-        * unaligned boundaries are padded, to align on Dword boundaries
-        */
-       retval = ata_pad_alloc(ap, dev);
-       if (retval) {
-               kfree(pp);
-               return retval;
-       }
-
        mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
                                 GFP_KERNEL);
        if (!mem) {
-               ata_pad_free(ap, dev);
                kfree(pp);
                return -ENOMEM;
        }
@@ -654,6 +613,7 @@ static int sata_fsl_port_start(struct ata_port *ap)
        VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
        VPRINTK("CHBA  = 0x%x\n", ioread32(hcr_base + CHBA));
 
+#ifdef CONFIG_MPC8315_DS
        /*
         * Workaround for 8315DS board 3gbps link-up issue,
         * currently limit SATA port to GEN1 speed
@@ -666,6 +626,7 @@ static int sata_fsl_port_start(struct ata_port *ap)
        sata_fsl_scr_read(ap, SCR_CONTROL, &temp);
        dev_printk(KERN_WARNING, dev, "scr_control, speed limited to %x\n",
                        temp);
+#endif
 
        return 0;
 }
@@ -693,7 +654,6 @@ static void sata_fsl_port_stop(struct ata_port *ap)
        dma_free_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ,
                          pp->cmdslot, pp->cmdslot_paddr);
 
-       ata_pad_free(ap, dev);
        kfree(pp);
 }
 
@@ -718,6 +678,15 @@ static unsigned int sata_fsl_dev_classify(struct ata_port *ap)
        return ata_dev_classify(&tf);
 }
 
+static int sata_fsl_prereset(struct ata_linke *link, unsigned long deadline)
+{
+       /* FIXME: Never skip softreset, sata_fsl_softreset() is
+        * combination of soft and hard resets.  sata_fsl_softreset()
+        * needs to be splitted into soft and hard resets.
+        */
+       return 0;
+}
+
 static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
                              unsigned long deadline)
 {
@@ -730,10 +699,6 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
        u8 *cfis;
        u32 Serror;
        int i = 0;
-       struct ata_queued_cmd qc;
-       u8 *buf;
-       dma_addr_t dma_address;
-       struct scatterlist *sg;
        unsigned long start_jiffies;
 
        DPRINTK("in xx_softreset\n");
@@ -833,13 +798,10 @@ try_offline_again:
         * reached here, we can send a command to the target device
         */
 
-       if (link->sactive)
-               goto skip_srst_do_ncq_error_handling;
-
        DPRINTK("Sending SRST/device reset\n");
 
        ata_tf_init(link->device, &tf);
-       cfis = (u8 *) & pp->cmdentry->cfis;
+       cfis = (u8 *) &pp->cmdentry->cfis;
 
        /* device reset/SRST is a control register update FIS, uses tag0 */
        sata_fsl_setup_cmd_hdr_entry(pp, 0,
@@ -903,69 +865,6 @@ try_offline_again:
         * command bit of the CCreg
         */
        iowrite32(0x01, CC + hcr_base); /* We know it will be cmd#0 always */
-       goto check_device_signature;
-
-skip_srst_do_ncq_error_handling:
-
-       VPRINTK("Sending read log ext(10h) command\n");
-
-       memset(&qc, 0, sizeof(struct ata_queued_cmd));
-       ata_tf_init(link->device, &tf);
-
-       tf.command = ATA_CMD_READ_LOG_EXT;
-       tf.lbal = ATA_LOG_SATA_NCQ;
-       tf.nsect = 1;
-       tf.hob_nsect = 0;
-       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
-       tf.protocol = ATA_PROT_PIO;
-
-       qc.tag = ATA_TAG_INTERNAL;
-       qc.scsicmd = NULL;
-       qc.ap = ap;
-       qc.dev = link->device;
-
-       qc.tf = tf;
-       qc.flags |= ATA_QCFLAG_RESULT_TF;
-       qc.dma_dir = DMA_FROM_DEVICE;
-
-       buf = ap->sector_buf;
-       ata_sg_init_one(&qc, buf, 1 * ATA_SECT_SIZE);
-
-       /*
-        * Need to DMA-map the memory buffer associated with the command
-        */
-
-       sg = qc.__sg;
-       dma_address = dma_map_single(ap->dev, qc.buf_virt,
-                                    sg->length, DMA_FROM_DEVICE);
-
-       sg_dma_address(sg) = dma_address;
-       sg_dma_len(sg) = sg->length;
-
-       VPRINTK("EH, addr = 0x%x, len = 0x%x\n", dma_address, sg->length);
-
-       sata_fsl_qc_prep(&qc);
-       sata_fsl_qc_issue(&qc);
-
-       temp = ata_wait_register(CQ + hcr_base, 0x1, 0x1, 1, 5000);
-       if (temp & 0x1) {
-               VPRINTK("READ_LOG_EXT_10H issue failed\n");
-
-               VPRINTK("READ_LOG@5000,CQ=0x%x,CA=0x%x,CC=0x%x\n",
-                       ioread32(CQ + hcr_base),
-                       ioread32(CA + hcr_base), ioread32(CC + hcr_base));
-
-               sata_fsl_scr_read(ap, SCR_ERROR, &Serror);
-
-               VPRINTK("HStatus = 0x%x\n", ioread32(hcr_base + HSTATUS));
-               VPRINTK("HControl = 0x%x\n", ioread32(hcr_base + HCONTROL));
-               VPRINTK("Serror = 0x%x\n", Serror);
-               goto err;
-       }
-
-       iowrite32(0x01, CC + hcr_base); /* We know it will be cmd#0 always */
-
-      check_device_signature:
 
        DPRINTK("SATA FSL : Now checking device signature\n");
 
@@ -993,28 +892,6 @@ err:
        return -EIO;
 }
 
-static int sata_fsl_hardreset(struct ata_port *ap, unsigned int *class,
-                             unsigned long deadline)
-{
-       int retval;
-
-       retval = sata_std_hardreset(ap, class, deadline);
-
-       DPRINTK("SATA FSL : in xx_hardreset, retval = 0x%d\n", retval);
-
-       return retval;
-}
-
-static void sata_fsl_error_handler(struct ata_port *ap)
-{
-
-       DPRINTK("in xx_error_handler\n");
-
-       /* perform recovery */
-       ata_do_eh(ap, ata_std_prereset, sata_fsl_softreset, sata_fsl_hardreset,
-                 ata_std_postreset);
-}
-
 static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
 {
        if (qc->flags & ATA_QCFLAG_FAILED)
@@ -1026,11 +903,6 @@ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
        }
 }
 
-static void sata_fsl_irq_clear(struct ata_port *ap)
-{
-       /* unused */
-}
-
 static void sata_fsl_error_intr(struct ata_port *ap)
 {
        struct ata_link *link = &ap->link;
@@ -1088,7 +960,7 @@ static void sata_fsl_error_intr(struct ata_port *ap)
        /* handle fatal errors */
        if (hstatus & FATAL_ERROR_DECODE) {
                err_mask |= AC_ERR_ATA_BUS;
-               action |= ATA_EH_SOFTRESET;
+               action |= ATA_EH_RESET;
                /* how will fatal error interrupts be completed ?? */
                freeze = 1;
        }
@@ -1105,10 +977,9 @@ static void sata_fsl_error_intr(struct ata_port *ap)
        /* record error info */
        qc = ata_qc_from_tag(ap, link->active_tag);
 
-       if (qc) {
-               sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
+       if (qc)
                qc->err_mask |= err_mask;
-       else
+       else
                ehi->err_mask |= err_mask;
 
        ehi->action |= action;
@@ -1121,14 +992,6 @@ static void sata_fsl_error_intr(struct ata_port *ap)
                ata_port_abort(ap);
 }
 
-static void sata_fsl_qc_complete(struct ata_queued_cmd *qc)
-{
-       if (qc->flags & ATA_QCFLAG_RESULT_TF) {
-               DPRINTK("xx_qc_complete called\n");
-               sata_fsl_cache_taskfile_from_d2h_fis(qc, qc->ap);
-       }
-}
-
 static void sata_fsl_host_intr(struct ata_port *ap)
 {
        struct ata_link *link = &ap->link;
@@ -1169,10 +1032,8 @@ static void sata_fsl_host_intr(struct ata_port *ap)
                for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
                        if (qc_active & (1 << i)) {
                                qc = ata_qc_from_tag(ap, i);
-                               if (qc) {
-                                       sata_fsl_qc_complete(qc);
+                               if (qc)
                                        ata_qc_complete(qc);
-                               }
                                DPRINTK
                                    ("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
                                     i, ioread32(hcr_base + CC),
@@ -1188,10 +1049,8 @@ static void sata_fsl_host_intr(struct ata_port *ap)
                DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n",
                        link->active_tag, ioread32(hcr_base + CC));
 
-               if (qc) {
-                       sata_fsl_qc_complete(qc);
+               if (qc)
                        ata_qc_complete(qc);
-               }
        } else {
                /* Spurious Interrupt!! */
                DPRINTK("spurious interrupt!!, CC = 0x%x\n",
@@ -1289,45 +1148,26 @@ static int sata_fsl_init_controller(struct ata_host *host)
  * scsi mid-layer and libata interface structures
  */
 static struct scsi_host_template sata_fsl_sht = {
-       .module = THIS_MODULE,
-       .name = "sata_fsl",
-       .ioctl = ata_scsi_ioctl,
-       .queuecommand = ata_scsi_queuecmd,
-       .change_queue_depth = ata_scsi_change_queue_depth,
+       ATA_NCQ_SHT("sata_fsl"),
        .can_queue = SATA_FSL_QUEUE_DEPTH,
-       .this_id = ATA_SHT_THIS_ID,
        .sg_tablesize = SATA_FSL_MAX_PRD_USABLE,
-       .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
-       .emulated = ATA_SHT_EMULATED,
-       .use_clustering = ATA_SHT_USE_CLUSTERING,
-       .proc_name = "sata_fsl",
        .dma_boundary = ATA_DMA_BOUNDARY,
-       .slave_configure = ata_scsi_slave_config,
-       .slave_destroy = ata_scsi_slave_destroy,
-       .bios_param = ata_std_bios_param,
-#ifdef CONFIG_PM
-       .suspend = ata_scsi_device_suspend,
-       .resume = ata_scsi_device_resume,
-#endif
 };
 
 static const struct ata_port_operations sata_fsl_ops = {
-       .check_status = sata_fsl_check_status,
-       .check_altstatus = sata_fsl_check_status,
-       .dev_select = ata_noop_dev_select,
-
-       .tf_read = sata_fsl_tf_read,
+       .inherits = &sata_port_ops,
 
        .qc_prep = sata_fsl_qc_prep,
        .qc_issue = sata_fsl_qc_issue,
-       .irq_clear = sata_fsl_irq_clear,
+       .qc_fill_rtf = sata_fsl_qc_fill_rtf,
 
        .scr_read = sata_fsl_scr_read,
        .scr_write = sata_fsl_scr_write,
 
        .freeze = sata_fsl_freeze,
        .thaw = sata_fsl_thaw,
-       .error_handler = sata_fsl_error_handler,
+       .prereset = sata_fsl_prereset,
+       .softreset = sata_fsl_softreset,
        .post_internal_cmd = sata_fsl_post_internal_cmd,
 
        .port_start = sata_fsl_port_start,
@@ -1337,7 +1177,6 @@ static const struct ata_port_operations sata_fsl_ops = {
 static const struct ata_port_info sata_fsl_port_info[] = {
        {
         .flags = SATA_FSL_HOST_FLAGS,
-        .link_flags = SATA_FSL_HOST_LFLAGS,
         .pio_mask = 0x1f,      /* pio 0-4 */
         .udma_mask = 0x7f,     /* udma 0-6 */
         .port_ops = &sata_fsl_ops,
@@ -1352,7 +1191,6 @@ static int sata_fsl_probe(struct of_device *ofdev,
        void __iomem *ssr_base = NULL;
        void __iomem *csr_base = NULL;
        struct sata_fsl_host_priv *host_priv = NULL;
-       struct resource *r;
        int irq;
        struct ata_host *host;
 
@@ -1362,8 +1200,6 @@ static int sata_fsl_probe(struct of_device *ofdev,
        dev_printk(KERN_INFO, &ofdev->dev,
                   "Sata FSL Platform/CSB Driver init\n");
 
-       r = kmalloc(sizeof(struct resource), GFP_KERNEL);
-
        hcr_base = of_iomap(ofdev->node, 0);
        if (!hcr_base)
                goto error_exit_with_cleanup;
@@ -1396,11 +1232,6 @@ static int sata_fsl_probe(struct of_device *ofdev,
        /* host->iomap is not used currently */
        host->private_data = host_priv;
 
-       /* setup port(s) */
-
-       host->ports[0]->ioaddr.cmd_addr = host_priv->hcr_base;
-       host->ports[0]->ioaddr.scr_addr = host_priv->ssr_base;
-
        /* initialize host controller */
        sata_fsl_init_controller(host);
 
@@ -1444,10 +1275,7 @@ static int sata_fsl_remove(struct of_device *ofdev)
 
 static struct of_device_id fsl_sata_match[] = {
        {
-               .compatible = "fsl,mpc8315-sata",
-       },
-       {
-               .compatible = "fsl,mpc8379-sata",
+               .compatible = "fsl,pq-sata",
        },
        {},
 };