aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/sata_mv.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 47184567248..8a751054c8a 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -251,6 +251,11 @@ enum {
251 HC_IRQ_COAL_IO_THRESHOLD_OFS = 0x000c, 251 HC_IRQ_COAL_IO_THRESHOLD_OFS = 0x000c,
252 HC_IRQ_COAL_TIME_THRESHOLD_OFS = 0x0010, 252 HC_IRQ_COAL_TIME_THRESHOLD_OFS = 0x0010,
253 253
254 SOC_LED_CTRL_OFS = 0x2c,
255 SOC_LED_CTRL_BLINK = (1 << 0), /* Active LED blink */
256 SOC_LED_CTRL_ACT_PRESENCE = (1 << 2), /* Multiplex dev presence */
257 /* with dev activity LED */
258
254 /* Shadow block registers */ 259 /* Shadow block registers */
255 SHD_BLK_OFS = 0x100, 260 SHD_BLK_OFS = 0x100,
256 SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */ 261 SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */
@@ -411,6 +416,7 @@ enum {
411 MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ 416 MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */
412 MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */ 417 MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */
413 MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */ 418 MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */
419 MV_HP_QUIRK_LED_BLINK_EN = (1 << 12), /* is led blinking enabled? */
414 420
415 /* Port private flags (pp_flags) */ 421 /* Port private flags (pp_flags) */
416 MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ 422 MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
@@ -1404,6 +1410,61 @@ static void mv_bmdma_enable_iie(struct ata_port *ap, int enable_bmdma)
1404 mv_write_cached_reg(mv_ap_base(ap) + EDMA_UNKNOWN_RSVD_OFS, old, new); 1410 mv_write_cached_reg(mv_ap_base(ap) + EDMA_UNKNOWN_RSVD_OFS, old, new);
1405} 1411}
1406 1412
1413/*
1414 * SOC chips have an issue whereby the HDD LEDs don't always blink
1415 * during I/O when NCQ is enabled. Enabling a special "LED blink" mode
1416 * of the SOC takes care of it, generating a steady blink rate when
1417 * any drive on the chip is active.
1418 *
1419 * Unfortunately, the blink mode is a global hardware setting for the SOC,
1420 * so we must use it whenever at least one port on the SOC has NCQ enabled.
1421 *
1422 * We turn "LED blink" off when NCQ is not in use anywhere, because the normal
1423 * LED operation works then, and provides better (more accurate) feedback.
1424 *
1425 * Note that this code assumes that an SOC never has more than one HC onboard.
1426 */
1427static void mv_soc_led_blink_enable(struct ata_port *ap)
1428{
1429 struct ata_host *host = ap->host;
1430 struct mv_host_priv *hpriv = host->private_data;
1431 void __iomem *hc_mmio;
1432 u32 led_ctrl;
1433
1434 if (hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN)
1435 return;
1436 hpriv->hp_flags |= MV_HP_QUIRK_LED_BLINK_EN;
1437 hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no);
1438 led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS);
1439 writel(led_ctrl | SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS);
1440}
1441
1442static void mv_soc_led_blink_disable(struct ata_port *ap)
1443{
1444 struct ata_host *host = ap->host;
1445 struct mv_host_priv *hpriv = host->private_data;
1446 void __iomem *hc_mmio;
1447 u32 led_ctrl;
1448 unsigned int port;
1449
1450 if (!(hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN))
1451 return;
1452
1453 /* disable led-blink only if no ports are using NCQ */
1454 for (port = 0; port < hpriv->n_ports; port++) {
1455 struct ata_port *this_ap = host->ports[port];
1456 struct mv_port_priv *pp = this_ap->private_data;
1457
1458 if (pp->pp_flags & MV_PP_FLAG_NCQ_EN)
1459 return;
1460 }
1461
1462 hpriv->hp_flags &= ~MV_HP_QUIRK_LED_BLINK_EN;
1463 hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no);
1464 led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS);
1465 writel(led_ctrl & ~SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS);
1466}
1467
1407static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) 1468static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma)
1408{ 1469{
1409 u32 cfg; 1470 u32 cfg;
@@ -1451,6 +1512,13 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma)
1451 if (hpriv->hp_flags & MV_HP_CUT_THROUGH) 1512 if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
1452 cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ 1513 cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
1453 mv_bmdma_enable_iie(ap, !want_edma); 1514 mv_bmdma_enable_iie(ap, !want_edma);
1515
1516 if (IS_SOC(hpriv)) {
1517 if (want_ncq)
1518 mv_soc_led_blink_enable(ap);
1519 else
1520 mv_soc_led_blink_disable(ap);
1521 }
1454 } 1522 }
1455 1523
1456 if (want_ncq) { 1524 if (want_ncq) {