]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ata/sata_mv.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[linux-2.6-omap-h63xx.git] / drivers / ata / sata_mv.c
index 969a76987781b47f524c0622520c2216d8e8923f..28092bc50146a04bf0298f48166550c8efa4320b 100644 (file)
@@ -72,7 +72,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_mv"
-#define DRV_VERSION    "1.22"
+#define DRV_VERSION    "1.24"
 
 enum {
        /* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -224,6 +224,11 @@ enum {
 
        PHY_MODE3               = 0x310,
        PHY_MODE4               = 0x314,
+       PHY_MODE4_CFG_MASK      = 0x00000003,   /* phy internal config field */
+       PHY_MODE4_CFG_VALUE     = 0x00000001,   /* phy internal config field */
+       PHY_MODE4_RSVD_ZEROS    = 0x5de3fffa,   /* Gen2e always write zeros */
+       PHY_MODE4_RSVD_ONES     = 0x00000005,   /* Gen2e always write ones */
+
        PHY_MODE2               = 0x330,
        SATA_IFCTL_OFS          = 0x344,
        SATA_TESTCTL_OFS        = 0x348,
@@ -1317,6 +1322,9 @@ static int mv_port_start(struct ata_port *ap)
                goto out_port_free_dma_mem;
        memset(pp->crpb, 0, MV_CRPB_Q_SZ);
 
+       /* 6041/6081 Rev. "C0" (and newer) are okay with async notify */
+       if (hpriv->hp_flags & MV_HP_ERRATA_60X1C0)
+               ap->flags |= ATA_FLAG_AN;
        /*
         * For GEN_I, there's no NCQ, so we only allocate a single sg_tbl.
         * For later hardware, we need one unique sg_tbl per NCQ tag.
@@ -1587,6 +1595,24 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
 
        if ((qc->tf.protocol != ATA_PROT_DMA) &&
            (qc->tf.protocol != ATA_PROT_NCQ)) {
+               static int limit_warnings = 10;
+               /*
+                * Errata SATA#16, SATA#24: warn if multiple DRQs expected.
+                *
+                * Someday, we might implement special polling workarounds
+                * for these, but it all seems rather unnecessary since we
+                * normally use only DMA for commands which transfer more
+                * than a single block of data.
+                *
+                * Much of the time, this could just work regardless.
+                * So for now, just log the incident, and allow the attempt.
+                */
+               if (limit_warnings && (qc->nbytes / qc->sect_size) > 1) {
+                       --limit_warnings;
+                       ata_link_printk(qc->dev->link, KERN_WARNING, DRV_NAME
+                                       ": attempting PIO w/multiple DRQ: "
+                                       "this may fail due to h/w errata\n");
+               }
                /*
                 * We're about to send a non-EDMA capable command to the
                 * port.  Turn off EDMA so there won't be problems accessing
@@ -2557,22 +2583,30 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
         */
        m3 = readl(port_mmio + PHY_MODE3);
        m3 = (m3 & 0x1f) | (0x5555601 << 5);
-       writel(m3, port_mmio + PHY_MODE3);
-
-       if (fix_phy_mode4) {
-               u32 m4;
 
-               m4 = readl(port_mmio + PHY_MODE4);
+       /* Guideline 88F5182 (GL# SATA-S11) */
+       if (IS_SOC(hpriv))
+               m3 &= ~0x1c;
 
-               /* workaround for errata FEr SATA#10 (part 1) */
-               m4 = (m4 & ~(1 << 1)) | (1 << 0);
-
-               /* enforce bit restrictions on GenIIe devices */
+       if (fix_phy_mode4) {
+               u32 m4 = readl(port_mmio + PHY_MODE4);
+               /*
+                * Enforce reserved-bit restrictions on GenIIe devices only.
+                * For earlier chipsets, force only the internal config field
+                *  (workaround for errata FEr SATA#10 part 1).
+                */
                if (IS_GEN_IIE(hpriv))
-                       m4 = (m4 & ~0x5DE3FFFC) | (1 << 2);
-
+                       m4 = (m4 & ~PHY_MODE4_RSVD_ZEROS) | PHY_MODE4_RSVD_ONES;
+               else
+                       m4 = (m4 & ~PHY_MODE4_CFG_MASK) | PHY_MODE4_CFG_VALUE;
                writel(m4, port_mmio + PHY_MODE4);
        }
+       /*
+        * Workaround for 60x1-B2 errata SATA#13:
+        * Any write to PHY_MODE4 (above) may corrupt PHY_MODE3,
+        * so we must always rewrite PHY_MODE3 after PHY_MODE4.
+        */
+       writel(m3, port_mmio + PHY_MODE3);
 
        /* Revert values of pre-emphasis and signal amps to the saved ones */
        m2 = readl(port_mmio + PHY_MODE2);