MUSB: Add sanity check for maximum number of endpoints
[safe/jmp/linux-2.6] / drivers / ata / sata_mv.c
index fb81f0c..2b24ae5 100644 (file)
@@ -72,7 +72,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME       "sata_mv"
-#define DRV_VERSION    "1.21"
+#define DRV_VERSION    "1.24"
 
 enum {
        /* BAR's are enumerated in terms of pci_resource_start() terms */
@@ -122,8 +122,6 @@ enum {
        /* Host Flags */
        MV_FLAG_DUAL_HC         = (1 << 30),  /* two SATA Host Controllers */
        MV_FLAG_IRQ_COALESCE    = (1 << 29),  /* IRQ coalescing capability */
-       /* SoC integrated controllers, no PCI interface */
-       MV_FLAG_SOC             = (1 << 28),
 
        MV_COMMON_FLAGS         = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
                                  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
@@ -226,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,
@@ -356,12 +359,12 @@ enum {
        MV_HP_ERRATA_50XXB2     = (1 << 2),
        MV_HP_ERRATA_60X1B2     = (1 << 3),
        MV_HP_ERRATA_60X1C0     = (1 << 4),
-       MV_HP_ERRATA_XX42A0     = (1 << 5),
        MV_HP_GEN_I             = (1 << 6),     /* Generation I: 50xx */
        MV_HP_GEN_II            = (1 << 7),     /* Generation II: 60xx */
        MV_HP_GEN_IIE           = (1 << 8),     /* Generation IIE: 6042/7042 */
        MV_HP_PCIE              = (1 << 9),     /* PCIe bus/regs: 7042 */
        MV_HP_CUT_THROUGH       = (1 << 10),    /* can use EDMA cut-through */
+       MV_HP_FLAG_SOC          = (1 << 11),    /* SystemOnChip, no PCI */
 
        /* Port private flags (pp_flags) */
        MV_PP_FLAG_EDMA_EN      = (1 << 0),     /* is EDMA engine enabled? */
@@ -374,7 +377,7 @@ enum {
 #define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
 #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
 #define IS_PCIE(hpriv) ((hpriv)->hp_flags & MV_HP_PCIE)
-#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
+#define IS_SOC(hpriv) ((hpriv)->hp_flags & MV_HP_FLAG_SOC)
 
 #define WINDOW_CTRL(i)         (0x20030 + ((i) << 4))
 #define WINDOW_BASE(i)         (0x20034 + ((i) << 4))
@@ -490,10 +493,10 @@ struct mv_hw_ops {
        void (*reset_bus)(struct ata_host *host, void __iomem *mmio);
 };
 
-static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
-static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
-static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val);
-static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val);
+static int mv_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val);
+static int mv_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val);
+static int mv5_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val);
+static int mv5_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val);
 static int mv_port_start(struct ata_port *ap);
 static void mv_port_stop(struct ata_port *ap);
 static int mv_qc_defer(struct ata_queued_cmd *qc);
@@ -652,7 +655,7 @@ static const struct ata_port_info mv_port_info[] = {
                .port_ops       = &mv_iie_ops,
        },
        {  /* chip_soc */
-               .flags          = MV_GENIIE_FLAGS | MV_FLAG_SOC,
+               .flags          = MV_GENIIE_FLAGS,
                .pio_mask       = 0x1f, /* pio0-4 */
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &mv_iie_ops,
@@ -664,7 +667,8 @@ static const struct pci_device_id mv_pci_tbl[] = {
        { PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
        { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
        { PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
-       /* RocketRAID 1740/174x have different identifiers */
+       /* RocketRAID 1720/174x have different identifiers */
+       { PCI_VDEVICE(TTI, 0x1720), chip_6042 },
        { PCI_VDEVICE(TTI, 0x1740), chip_508x },
        { PCI_VDEVICE(TTI, 0x1742), chip_508x },
 
@@ -812,12 +816,7 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
        writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
        writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
                 port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
-
-       if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
-               writelfl((pp->crqb_dma & 0xffffffff) | index,
-                        port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
-       else
-               writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
+       writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
 
        /*
         * initialize response queue
@@ -827,13 +826,7 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
 
        WARN_ON(pp->crpb_dma & 0xff);
        writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
-
-       if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
-               writelfl((pp->crpb_dma & 0xffffffff) | index,
-                        port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
-       else
-               writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
-
+       writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
        writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
                 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
 }
@@ -1077,23 +1070,23 @@ static unsigned int mv_scr_offset(unsigned int sc_reg_in)
        return ofs;
 }
 
-static int mv_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
+static int mv_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val)
 {
        unsigned int ofs = mv_scr_offset(sc_reg_in);
 
        if (ofs != 0xffffffffU) {
-               *val = readl(mv_ap_base(ap) + ofs);
+               *val = readl(mv_ap_base(link->ap) + ofs);
                return 0;
        } else
                return -EINVAL;
 }
 
-static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+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(ap) + ofs);
+               writelfl(val, mv_ap_base(link->ap) + ofs);
                return 0;
        } else
                return -EINVAL;
@@ -1142,30 +1135,16 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
        if (ap->nr_active_links == 0)
                return 0;
 
-       if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
-               /*
-                * The port is operating in host queuing mode (EDMA).
-                * It can accomodate a new qc if the qc protocol
-                * is compatible with the current host queue mode.
-                */
-               if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) {
-                       /*
-                        * The host queue (EDMA) is in NCQ mode.
-                        * If the new qc is also an NCQ command,
-                        * then allow the new qc.
-                        */
-                       if (qc->tf.protocol == ATA_PROT_NCQ)
-                               return 0;
-               } else {
-                       /*
-                        * The host queue (EDMA) is in non-NCQ, DMA mode.
-                        * If the new qc is also a non-NCQ, DMA command,
-                        * then allow the new qc.
-                        */
-                       if (qc->tf.protocol == ATA_PROT_DMA)
-                               return 0;
-               }
-       }
+       /*
+        * The port is operating in host queuing mode (EDMA) with NCQ
+        * enabled, allow multiple NCQ commands.  EDMA also allows
+        * queueing multiple DMA commands but libata core currently
+        * doesn't allow it.
+        */
+       if ((pp->pp_flags & MV_PP_FLAG_EDMA_EN) &&
+           (pp->pp_flags & MV_PP_FLAG_NCQ_EN) && ata_is_ncq(qc->tf.protocol))
+               return 0;
+
        return ATA_DEFER_PORT;
 }
 
@@ -1254,7 +1233,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
 
                cfg |= (1 << 23);       /* do not mask PM field in rx'd FIS */
                cfg |= (1 << 22);       /* enab 4-entry host queue cache */
-               if (HAS_PCI(ap->host))
+               if (!IS_SOC(hpriv))
                        cfg |= (1 << 18);       /* enab early completion */
                if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
                        cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
@@ -1330,6 +1309,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.
@@ -1600,6 +1582,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 > 0 && (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
@@ -2225,7 +2225,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
         * a bogus register value which can indicate HW removal or PCI fault.
         */
        if (pending_irqs && main_irq_cause != 0xffffffffU) {
-               if (unlikely((pending_irqs & PCI_ERR) && HAS_PCI(host)))
+               if (unlikely((pending_irqs & PCI_ERR) && !IS_SOC(hpriv)))
                        handled = mv_pci_error(host, hpriv->base);
                else
                        handled = mv_host_intr(host, pending_irqs);
@@ -2251,11 +2251,11 @@ static unsigned int mv5_scr_offset(unsigned int sc_reg_in)
        return ofs;
 }
 
-static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
+static int mv5_scr_read(struct ata_link *link, unsigned int sc_reg_in, u32 *val)
 {
-       struct mv_host_priv *hpriv = ap->host->private_data;
+       struct mv_host_priv *hpriv = link->ap->host->private_data;
        void __iomem *mmio = hpriv->base;
-       void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
+       void __iomem *addr = mv5_phy_base(mmio, link->ap->port_no);
        unsigned int ofs = mv5_scr_offset(sc_reg_in);
 
        if (ofs != 0xffffffffU) {
@@ -2265,11 +2265,11 @@ static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val)
                return -EINVAL;
 }
 
-static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+static int mv5_scr_write(struct ata_link *link, unsigned int sc_reg_in, u32 val)
 {
-       struct mv_host_priv *hpriv = ap->host->private_data;
+       struct mv_host_priv *hpriv = link->ap->host->private_data;
        void __iomem *mmio = hpriv->base;
-       void __iomem *addr = mv5_phy_base(mmio, ap->port_no);
+       void __iomem *addr = mv5_phy_base(mmio, link->ap->port_no);
        unsigned int ofs = mv5_scr_offset(sc_reg_in);
 
        if (ofs != 0xffffffffU) {
@@ -2547,7 +2547,7 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
                hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
        int fix_phy_mode4 =
                hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
-       u32 m2, tmp;
+       u32 m2, m3;
 
        if (fix_phy_mode2) {
                m2 = readl(port_mmio + PHY_MODE2);
@@ -2564,28 +2564,36 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
                udelay(200);
        }
 
-       /* who knows what this magic does */
-       tmp = readl(port_mmio + PHY_MODE3);
-       tmp &= ~0x7F800000;
-       tmp |= 0x2A800000;
-       writel(tmp, port_mmio + PHY_MODE3);
-
-       if (fix_phy_mode4) {
-               u32 m4;
-
-               m4 = readl(port_mmio + PHY_MODE4);
-
-               if (hp_flags & MV_HP_ERRATA_60X1B2)
-                       tmp = readl(port_mmio + PHY_MODE3);
+       /*
+        * Gen-II/IIe PHY_MODE3 errata RM#2:
+        * Achieves better receiver noise performance than the h/w default:
+        */
+       m3 = readl(port_mmio + PHY_MODE3);
+       m3 = (m3 & 0x1f) | (0x5555601 << 5);
 
-               /* workaround for errata FEr SATA#10 (part 1) */
-               m4 = (m4 & ~(1 << 1)) | (1 << 0);
+       /* Guideline 88F5182 (GL# SATA-S11) */
+       if (IS_SOC(hpriv))
+               m3 &= ~0x1c;
 
+       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 & ~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);
-
-               if (hp_flags & MV_HP_ERRATA_60X1B2)
-                       writel(tmp, port_mmio + PHY_MODE3);
        }
+       /*
+        * 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);
@@ -2876,7 +2884,7 @@ static unsigned int mv_in_pcix_mode(struct ata_host *host)
        void __iomem *mmio = hpriv->base;
        u32 reg;
 
-       if (!HAS_PCI(host) || !IS_PCIE(hpriv))
+       if (IS_SOC(hpriv) || !IS_PCIE(hpriv))
                return 0;       /* not PCI-X capable */
        reg = readl(mmio + MV_PCI_MODE_OFS);
        if ((reg & MV_PCI_MODE_MASK) == 0)
@@ -3003,10 +3011,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
                        hp_flags |= MV_HP_CUT_THROUGH;
 
                switch (pdev->revision) {
-               case 0x0:
-                       hp_flags |= MV_HP_ERRATA_XX42A0;
-                       break;
-               case 0x1:
+               case 0x2: /* Rev.B0: the first/only public release */
                        hp_flags |= MV_HP_ERRATA_60X1C0;
                        break;
                default:
@@ -3018,7 +3023,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
                break;
        case chip_soc:
                hpriv->ops = &mv_soc_ops;
-               hp_flags |= MV_HP_ERRATA_60X1C0;
+               hp_flags |= MV_HP_FLAG_SOC | MV_HP_GEN_IIE |
+                       MV_HP_ERRATA_60X1C0;
                break;
 
        default:
@@ -3062,12 +3068,12 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
        if (rc)
                goto done;
 
-       if (HAS_PCI(host)) {
-               hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
-               hpriv->main_irq_mask_addr  = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
-       } else {
+       if (IS_SOC(hpriv)) {
                hpriv->main_irq_cause_addr = mmio + SOC_HC_MAIN_IRQ_CAUSE_OFS;
                hpriv->main_irq_mask_addr  = mmio + SOC_HC_MAIN_IRQ_MASK_OFS;
+       } else {
+               hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
+               hpriv->main_irq_mask_addr  = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
        }
 
        /* global interrupt mask: 0 == mask everything */
@@ -3093,7 +3099,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
                mv_port_init(&ap->ioaddr, port_mmio);
 
 #ifdef CONFIG_PCI
-               if (HAS_PCI(host)) {
+               if (!IS_SOC(hpriv)) {
                        unsigned int offset = port_mmio - mmio;
                        ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
                        ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
@@ -3113,7 +3119,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
                writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
        }
 
-       if (HAS_PCI(host)) {
+       if (!IS_SOC(hpriv)) {
                /* Clear any currently outstanding host interrupt conditions */
                writelfl(0, mmio + hpriv->irq_cause_ofs);