]> pilppa.com Git - linux-2.6-omap-h63xx.git/commitdiff
sata_mv: workaround errata SATA#26
authorMark Lord <liml@rtr.ca>
Mon, 6 Apr 2009 19:24:57 +0000 (15:24 -0400)
committerJeff Garzik <jgarzik@redhat.com>
Tue, 7 Apr 2009 00:13:50 +0000 (20:13 -0400)
Workaround for errata SATA#26.

Prevents accidently putting a drive to sleep when attempting COMRESET,
by ORing 0xf000 with the values written to SCR_CONTROL.

Signed-off-by: Mark Lord <mlord@pobox.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/ata/sata_mv.c

index b0c929d362341d6e921385c700c1621445e2d55d..d689fb9ceb969cd7a5951fb832ba87108ef0e4bf 100644 (file)
@@ -1296,7 +1296,25 @@ static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)
        unsigned int ofs = mv_scr_offset(sc_reg_in);
 
        if (ofs != 0xffffffffU) {
-               writelfl(val, mv_ap_base(link->ap) + ofs);
+               void __iomem *addr = mv_ap_base(link->ap) + ofs;
+               if (sc_reg_in == SCR_CONTROL) {
+                       /*
+                        * Workaround for 88SX60x1 FEr SATA#26:
+                        *
+                        * COMRESETs have to take care not to accidently
+                        * put the drive to sleep when writing SCR_CONTROL.
+                        * Setting bits 12..15 prevents this problem.
+                        *
+                        * So if we see an outbound COMMRESET, set those bits.
+                        * Ditto for the followup write that clears the reset.
+                        *
+                        * The proprietary driver does this for
+                        * all chip versions, and so do we.
+                        */
+                       if ((val & 0xf) == 1 || (readl(addr) & 0xf) == 1)
+                               val |= 0xf000;
+               }
+               writelfl(val, addr);
                return 0;
        } else
                return -EINVAL;