Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[pandora-kernel.git] / drivers / ata / pata_bf54x.c
index 747549e..a32e3c4 100644 (file)
@@ -832,6 +832,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
 {
        unsigned short config = WDSIZE_16;
        struct scatterlist *sg;
+       unsigned int si;
 
        pr_debug("in atapi dma setup\n");
        /* Program the ATA_CTRL register with dir */
@@ -839,7 +840,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
                /* fill the ATAPI DMA controller */
                set_dma_config(CH_ATAPI_TX, config);
                set_dma_x_modify(CH_ATAPI_TX, 2);
-               ata_for_each_sg(sg, qc) {
+               for_each_sg(qc->sg, sg, qc->n_elem, si) {
                        set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg));
                        set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1);
                }
@@ -848,7 +849,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
                /* fill the ATAPI DMA controller */
                set_dma_config(CH_ATAPI_RX, config);
                set_dma_x_modify(CH_ATAPI_RX, 2);
-               ata_for_each_sg(sg, qc) {
+               for_each_sg(qc->sg, sg, qc->n_elem, si) {
                        set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg));
                        set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1);
                }
@@ -867,6 +868,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
        struct ata_port *ap = qc->ap;
        void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
        struct scatterlist *sg;
+       unsigned int si;
 
        pr_debug("in atapi dma start\n");
        if (!(ap->udma_mask || ap->mwdma_mask))
@@ -881,7 +883,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
                 * data cache is enabled. Otherwise, this loop
                 * is an empty loop and optimized out.
                 */
-               ata_for_each_sg(sg, qc) {
+               for_each_sg(qc->sg, sg, qc->n_elem, si) {
                        flush_dcache_range(sg_dma_address(sg),
                                sg_dma_address(sg) + sg_dma_len(sg));
                }
@@ -910,7 +912,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
        ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
 
                /* Set transfer length to buffer len */
-       ata_for_each_sg(sg, qc) {
+       for_each_sg(qc->sg, sg, qc->n_elem, si) {
                ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
        }
 
@@ -932,6 +934,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct scatterlist *sg;
+       unsigned int si;
 
        pr_debug("in atapi dma stop\n");
        if (!(ap->udma_mask || ap->mwdma_mask))
@@ -950,7 +953,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
                         * data cache is enabled. Otherwise, this loop
                         * is an empty loop and optimized out.
                         */
-                       ata_for_each_sg(sg, qc) {
+                       for_each_sg(qc->sg, sg, qc->n_elem, si) {
                                invalidate_dcache_range(
                                        sg_dma_address(sg),
                                        sg_dma_address(sg)
@@ -1092,14 +1095,15 @@ static unsigned int bfin_bus_softreset(struct ata_port *ap,
  *     Note: Original code is ata_std_softreset().
  */
 
-static int bfin_std_softreset(struct ata_port *ap, unsigned int *classes,
+static int bfin_std_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;
        unsigned int devmask = 0, err_mask;
        u8 err;
 
-       if (ata_port_offline(ap)) {
+       if (ata_link_offline(link)) {
                classes[0] = ATA_DEV_NONE;
                goto out;
        }
@@ -1122,9 +1126,11 @@ static int bfin_std_softreset(struct ata_port *ap, unsigned int *classes,
        }
 
        /* determine by signature whether we have ATA or ATAPI devices */
-       classes[0] = ata_dev_try_classify(ap, 0, &err);
+       classes[0] = ata_dev_try_classify(&ap->link.device[0],
+                               devmask & (1 << 0), &err);
        if (slave_possible && err != 0x81)
-               classes[1] = ata_dev_try_classify(ap, 1, &err);
+               classes[1] = ata_dev_try_classify(&ap->link.device[1],
+                                       devmask & (1 << 1), &err);
 
  out:
        return 0;
@@ -1142,13 +1148,13 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
        unsigned short int_status = ATAPI_GET_INT_STATUS(base);
 
        if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) {
-               host_stat = ATA_DMA_ACTIVE;
+               host_stat |= ATA_DMA_ACTIVE;
        }
        if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT)) {
-               host_stat = ATA_DMA_INTR;
+               host_stat |= ATA_DMA_INTR;
        }
        if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT)) {
-               host_stat = ATA_DMA_ERR;
+               host_stat |= ATA_DMA_ERR;
        }
 
        return host_stat;
@@ -1164,34 +1170,36 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
  *     Note: Original code is ata_data_xfer().
  */
 
-static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf,
-                          unsigned int buflen, int write_data)
+static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
+                                  unsigned int buflen, int rw)
 {
-       struct ata_port *ap = adev->ap;
-       unsigned int words = buflen >> 1;
-       unsigned short *buf16 = (u16 *) buf;
+       struct ata_port *ap = dev->link->ap;
        void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+       unsigned int words = buflen >> 1;
+       unsigned short *buf16 = (u16 *)buf;
 
        /* Transfer multiple of 2 bytes */
-       if (write_data) {
-               write_atapi_data(base, words, buf16);
-       } else {
+       if (rw == READ)
                read_atapi_data(base, words, buf16);
-       }
+       else
+               write_atapi_data(base, words, buf16);
 
        /* Transfer trailing 1 byte, if any. */
        if (unlikely(buflen & 0x01)) {
                unsigned short align_buf[1] = { 0 };
                unsigned char *trailing_buf = buf + buflen - 1;
 
-               if (write_data) {
-                       memcpy(align_buf, trailing_buf, 1);
-                       write_atapi_data(base, 1, align_buf);
-               } else {
+               if (rw == READ) {
                        read_atapi_data(base, 1, align_buf);
                        memcpy(trailing_buf, align_buf, 1);
+               } else {
+                       memcpy(align_buf, trailing_buf, 1);
+                       write_atapi_data(base, 1, align_buf);
                }
+               words++;
        }
+
+       return words << 1;
 }
 
 /**
@@ -1206,7 +1214,10 @@ static void bfin_irq_clear(struct ata_port *ap)
        void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
 
        pr_debug("in atapi irq clear\n");
-       ATAPI_SET_INT_STATUS(base, 0x1FF);
+
+       ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT
+               | MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT
+               | MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
 }
 
 /**
@@ -1233,33 +1244,6 @@ static unsigned char bfin_irq_on(struct ata_port *ap)
        return tmp;
 }
 
-/**
- *     bfin_irq_ack - Acknowledge a device interrupt.
- *     @ap: Port on which interrupts are enabled.
- *
- *     Note: Original code is ata_irq_ack().
- */
-
-static unsigned char bfin_irq_ack(struct ata_port *ap, unsigned int chk_drq)
-{
-       void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
-       unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
-       unsigned char status;
-
-       pr_debug("in atapi irq ack\n");
-       status = ata_busy_wait(ap, bits, 1000);
-       if (status & bits)
-               if (ata_msg_err(ap))
-                       dev_err(ap->dev, "abnormal status 0x%X\n", status);
-
-       /* get controller status; clear intr, err bits */
-       ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT
-               | MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT
-               | MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
-
-       return bfin_bmdma_status(ap);
-}
-
 /**
  *     bfin_bmdma_freeze - Freeze DMA controller port
  *     @ap: port to freeze
@@ -1308,8 +1292,9 @@ void bfin_bmdma_thaw(struct ata_port *ap)
  *     Note: Original code is ata_std_postreset().
  */
 
-static void bfin_std_postreset(struct ata_port *ap, unsigned int *classes)
+static void bfin_std_postreset(struct ata_link *link, unsigned int *classes)
 {
+       struct ata_port *ap = link->ap;
        void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
 
        /* re-enable interrupts */
@@ -1395,7 +1380,6 @@ static struct scsi_host_template bfin_sht = {
 };
 
 static const struct ata_port_operations bfin_pata_ops = {
-       .port_disable           = ata_port_disable,
        .set_piomode            = bfin_set_piomode,
        .set_dmamode            = bfin_set_dmamode,
 
@@ -1423,7 +1407,6 @@ static const struct ata_port_operations bfin_pata_ops = {
        .irq_handler            = ata_interrupt,
        .irq_clear              = bfin_irq_clear,
        .irq_on                 = bfin_irq_on,
-       .irq_ack                = bfin_irq_ack,
 
        .port_start             = bfin_port_start,
        .port_stop              = bfin_port_stop,
@@ -1437,11 +1420,7 @@ static struct ata_port_info bfin_port_info[] = {
                                | ATA_FLAG_NO_LEGACY,
                .pio_mask       = 0x1f, /* pio0-4 */
                .mwdma_mask     = 0,
-#ifdef CONFIG_PATA_BF54X_DMA
-               .udma_mask      = ATA_UDMA5,
-#else
                .udma_mask      = 0,
-#endif
                .port_ops       = &bfin_pata_ops,
        },
 };
@@ -1515,6 +1494,8 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
        int board_idx = 0;
        struct resource *res;
        struct ata_host *host;
+       unsigned int fsclk = get_sclk();
+       int udma_mode = 5;
        const struct ata_port_info *ppi[] =
                { &bfin_port_info[board_idx], NULL };
 
@@ -1533,6 +1514,12 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
        if (res == NULL)
                return -EINVAL;
 
+       while (bfin_port_info[board_idx].udma_mask > 0 &&
+                       udma_fsclk[udma_mode] > fsclk) {
+               udma_mode--;
+               bfin_port_info[board_idx].udma_mask >>= 1;
+       }
+
        /*
         * Now that that's out of the way, wire up the port..
         */
@@ -1607,9 +1594,25 @@ static struct platform_driver bfin_atapi_driver = {
        },
 };
 
+#define ATAPI_MODE_SIZE                10
+static char bfin_atapi_mode[ATAPI_MODE_SIZE];
+
 static int __init bfin_atapi_init(void)
 {
        pr_info("register bfin atapi driver\n");
+
+       switch(bfin_atapi_mode[0]) {
+       case 'p':
+       case 'P':
+               break;
+       case 'm':
+       case 'M':
+               bfin_port_info[0].mwdma_mask = ATA_MWDMA2;
+               break;
+       default:
+               bfin_port_info[0].udma_mask = ATA_UDMA5;
+       };
+
        return platform_driver_register(&bfin_atapi_driver);
 }
 
@@ -1620,6 +1623,13 @@ static void __exit bfin_atapi_exit(void)
 
 module_init(bfin_atapi_init);
 module_exit(bfin_atapi_exit);
+/*
+ * ATAPI mode:
+ * pio/PIO
+ * udma/UDMA (default)
+ * mwdma/MWDMA
+ */
+module_param_string(bfin_atapi_mode, bfin_atapi_mode, ATAPI_MODE_SIZE, 0);
 
 MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
 MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller");