aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-11-12 12:48:15 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-11-12 12:48:15 -0500
commitbca1c4eb9411533d613123618c0d127fae532595 (patch)
treed673342d82a88ac099bb71f38ec9015b335541a9
parent9a68c1b9580886a2ff07a42733adb7583ee3d9ac (diff)
[libata sata_mv] implement a bunch of errata workarounds
Based largely on the GPL'd Marvell vendor driver.
-rw-r--r--drivers/scsi/sata_mv.c268
1 files changed, 261 insertions, 7 deletions
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index 26e9d51e6caf..b1696e353dd4 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -50,6 +50,8 @@ enum {
50 MV_PCI_REG_BASE = 0, 50 MV_PCI_REG_BASE = 0,
51 MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ 51 MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */
52 MV_SATAHC0_REG_BASE = 0x20000, 52 MV_SATAHC0_REG_BASE = 0x20000,
53 MV_GPIO_PORT_CTL = 0x104f0,
54 MV_RESET_CFG = 0x180d8,
53 55
54 MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ, 56 MV_PCI_REG_SZ = MV_MAJOR_REG_AREA_SZ,
55 MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ, 57 MV_SATAHC_REG_SZ = MV_MAJOR_REG_AREA_SZ,
@@ -148,6 +150,11 @@ enum {
148 /* SATA registers */ 150 /* SATA registers */
149 SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */ 151 SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */
150 SATA_ACTIVE_OFS = 0x350, 152 SATA_ACTIVE_OFS = 0x350,
153 PHY_MODE4 = 0x314,
154 PHY_MODE2 = 0x330,
155 SATA_INTERFACE_CTL = 0x050,
156
157 MV_M2_PREAMP_MASK = 0x7e0,
151 158
152 /* Port registers */ 159 /* Port registers */
153 EDMA_CFG_OFS = 0, 160 EDMA_CFG_OFS = 0,
@@ -201,14 +208,26 @@ enum {
201 EDMA_DS = (1 << 1), 208 EDMA_DS = (1 << 1),
202 ATA_RST = (1 << 2), 209 ATA_RST = (1 << 2),
203 210
211 EDMA_ARB_CFG = 0x38,
212 EDMA_NO_SNOOP = (1 << 6),
213
204 /* Host private flags (hp_flags) */ 214 /* Host private flags (hp_flags) */
205 MV_HP_FLAG_MSI = (1 << 0), 215 MV_HP_FLAG_MSI = (1 << 0),
216 MV_HP_ERRATA_60X1A1 = (1 << 1),
217 MV_HP_ERRATA_60X1B0 = (1 << 2),
218 MV_HP_ERRATA_50XXB0 = (1 << 3),
219 MV_HP_ERRATA_50XXB1 = (1 << 4),
220 MV_HP_ERRATA_50XXB2 = (1 << 5),
221 MV_HP_50XX = (1 << 6),
206 222
207 /* Port private flags (pp_flags) */ 223 /* Port private flags (pp_flags) */
208 MV_PP_FLAG_EDMA_EN = (1 << 0), 224 MV_PP_FLAG_EDMA_EN = (1 << 0),
209 MV_PP_FLAG_EDMA_DS_ACT = (1 << 1), 225 MV_PP_FLAG_EDMA_DS_ACT = (1 << 1),
210}; 226};
211 227
228#define IS_50XX(hpriv) ((hpriv)->hp_flags & MV_HP_50XX)
229#define IS_60XX(hpriv) (((hpriv)->hp_flags & MV_HP_50XX) == 0)
230
212enum { 231enum {
213 /* Our DMA boundary is determined by an ePRD being unable to handle 232 /* Our DMA boundary is determined by an ePRD being unable to handle
214 * anything larger than 64KB 233 * anything larger than 64KB
@@ -256,8 +275,14 @@ struct mv_port_priv {
256 u32 pp_flags; 275 u32 pp_flags;
257}; 276};
258 277
278struct mv_port_signal {
279 u32 amps;
280 u32 pre;
281};
282
259struct mv_host_priv { 283struct mv_host_priv {
260 u32 hp_flags; 284 u32 hp_flags;
285 struct mv_port_signal signal[8];
261}; 286};
262 287
263static void mv_irq_clear(struct ata_port *ap); 288static void mv_irq_clear(struct ata_port *ap);
@@ -354,10 +379,12 @@ static struct ata_port_info mv_port_info[] = {
354}; 379};
355 380
356static const struct pci_device_id mv_pci_tbl[] = { 381static const struct pci_device_id mv_pci_tbl[] = {
382#if 0 /* unusably broken right now */
357 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x}, 383 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5040), 0, 0, chip_504x},
358 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x}, 384 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5041), 0, 0, chip_504x},
359 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_508x}, 385 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5080), 0, 0, chip_508x},
360 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x}, 386 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5081), 0, 0, chip_508x},
387#endif
361 388
362 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x}, 389 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6040), 0, 0, chip_604x},
363 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x}, 390 {PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x6041), 0, 0, chip_604x},
@@ -402,9 +429,9 @@ static inline void __iomem *mv_ap_base(struct ata_port *ap)
402 return mv_port_base(ap->host_set->mmio_base, ap->port_no); 429 return mv_port_base(ap->host_set->mmio_base, ap->port_no);
403} 430}
404 431
405static inline int mv_get_hc_count(unsigned long hp_flags) 432static inline int mv_get_hc_count(unsigned long host_flags)
406{ 433{
407 return ((hp_flags & MV_FLAG_DUAL_HC) ? 2 : 1); 434 return ((host_flags & MV_FLAG_DUAL_HC) ? 2 : 1);
408} 435}
409 436
410static void mv_irq_clear(struct ata_port *ap) 437static void mv_irq_clear(struct ata_port *ap)
@@ -694,6 +721,7 @@ static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev)
694static int mv_port_start(struct ata_port *ap) 721static int mv_port_start(struct ata_port *ap)
695{ 722{
696 struct device *dev = ap->host_set->dev; 723 struct device *dev = ap->host_set->dev;
724 struct mv_host_priv *hpriv = ap->host_set->private_data;
697 struct mv_port_priv *pp; 725 struct mv_port_priv *pp;
698 void __iomem *port_mmio = mv_ap_base(ap); 726 void __iomem *port_mmio = mv_ap_base(ap);
699 void *mem; 727 void *mem;
@@ -751,6 +779,15 @@ static int mv_port_start(struct ata_port *ap)
751 writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK, 779 writelfl(pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK,
752 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); 780 port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
753 781
782 if (hpriv->hp_flags & MV_HP_ERRATA_60X1A1) {
783 u32 new_tmp, tmp;
784
785 new_tmp = tmp = readl(port_mmio + EDMA_ARB_CFG);
786 new_tmp &= ~EDMA_NO_SNOOP;
787 if (new_tmp != tmp)
788 writel(new_tmp, port_mmio + EDMA_ARB_CFG);
789 }
790
754 pp->req_producer = pp->rsp_consumer = 0; 791 pp->req_producer = pp->rsp_consumer = 0;
755 792
756 /* Don't turn on EDMA here...do it before DMA commands only. Else 793 /* Don't turn on EDMA here...do it before DMA commands only. Else
@@ -1206,6 +1243,52 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
1206 return IRQ_RETVAL(handled); 1243 return IRQ_RETVAL(handled);
1207} 1244}
1208 1245
1246static void mv_phy_errata5(struct ata_port *ap)
1247{
1248 /* FIXME */
1249}
1250
1251static void mv_phy_errata6(struct ata_port *ap)
1252{
1253 struct mv_host_priv *hpriv = ap->host_set->private_data;
1254 u32 hp_flags = hpriv->hp_flags;
1255 void __iomem *port_mmio = mv_ap_base(ap);
1256 int fix_phy_mode4 =
1257 hp_flags & (MV_HP_ERRATA_60X1A1 | MV_HP_ERRATA_60X1B0);
1258 u32 m2;
1259
1260 if (fix_phy_mode4) {
1261 u32 tmp, m4;
1262
1263 m4 = readl(port_mmio + PHY_MODE4);
1264 tmp = readl(port_mmio + 0x310);
1265
1266 m4 = (m4 & ~(1 << 1)) | (1 << 0);
1267
1268 writel(m4, port_mmio + PHY_MODE4);
1269 writel(tmp, port_mmio + 0x310);
1270 }
1271
1272 /* Revert values of pre-emphasis and signal amps to the saved ones */
1273 m2 = readl(port_mmio + PHY_MODE2);
1274
1275 m2 &= ~MV_M2_PREAMP_MASK;
1276 m2 |= hpriv->signal[ap->port_no].amps;
1277 m2 |= hpriv->signal[ap->port_no].pre;
1278
1279 writel(m2, port_mmio + PHY_MODE2);
1280}
1281
1282static void mv_phy_errata(struct ata_port *ap)
1283{
1284 struct mv_host_priv *hpriv = ap->host_set->private_data;
1285
1286 if (IS_50XX(hpriv))
1287 mv_phy_errata5(ap);
1288 else
1289 mv_phy_errata6(ap);
1290}
1291
1209/** 1292/**
1210 * mv_phy_reset - Perform eDMA reset followed by COMRESET 1293 * mv_phy_reset - Perform eDMA reset followed by COMRESET
1211 * @ap: ATA channel to manipulate 1294 * @ap: ATA channel to manipulate
@@ -1220,6 +1303,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance,
1220static void mv_phy_reset(struct ata_port *ap) 1303static void mv_phy_reset(struct ata_port *ap)
1221{ 1304{
1222 struct mv_port_priv *pp = ap->private_data; 1305 struct mv_port_priv *pp = ap->private_data;
1306 struct mv_host_priv *hpriv = ap->host_set->private_data;
1223 void __iomem *port_mmio = mv_ap_base(ap); 1307 void __iomem *port_mmio = mv_ap_base(ap);
1224 struct ata_taskfile tf; 1308 struct ata_taskfile tf;
1225 struct ata_device *dev = &ap->device[0]; 1309 struct ata_device *dev = &ap->device[0];
@@ -1230,6 +1314,13 @@ static void mv_phy_reset(struct ata_port *ap)
1230 mv_stop_dma(ap); 1314 mv_stop_dma(ap);
1231 1315
1232 writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS); 1316 writelfl(ATA_RST, port_mmio + EDMA_CMD_OFS);
1317
1318 if (IS_60XX(hpriv)) {
1319 u32 ifctl = readl(port_mmio + SATA_INTERFACE_CTL);
1320 ifctl |= (1 << 12) | (1 << 7);
1321 writelfl(ifctl, port_mmio + SATA_INTERFACE_CTL);
1322 }
1323
1233 udelay(25); /* allow reset propagation */ 1324 udelay(25); /* allow reset propagation */
1234 1325
1235 /* Spec never mentions clearing the bit. Marvell's driver does 1326 /* Spec never mentions clearing the bit. Marvell's driver does
@@ -1237,6 +1328,8 @@ static void mv_phy_reset(struct ata_port *ap)
1237 */ 1328 */
1238 writelfl(0, port_mmio + EDMA_CMD_OFS); 1329 writelfl(0, port_mmio + EDMA_CMD_OFS);
1239 1330
1331 mv_phy_errata(ap);
1332
1240 DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x " 1333 DPRINTK("S-regs after ATA_RST: SStat 0x%08x SErr 0x%08x "
1241 "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS), 1334 "SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
1242 mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); 1335 mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
@@ -1283,7 +1376,7 @@ static void mv_phy_reset(struct ata_port *ap)
1283 1376
1284 pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; 1377 pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN;
1285 1378
1286 printk("EXIT\n"); 1379 VPRINTK("EXIT\n");
1287} 1380}
1288 1381
1289/** 1382/**
@@ -1380,8 +1473,152 @@ static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio)
1380 readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS)); 1473 readl(port_mmio + EDMA_ERR_IRQ_MASK_OFS));
1381} 1474}
1382 1475
1476static void mv_enable_leds5(struct mv_host_priv *hpriv, void __iomem *mmio)
1477{
1478 /* FIXME */
1479}
1480
1481static void mv_enable_leds6(struct mv_host_priv *hpriv, void __iomem *mmio)
1482{
1483 if (hpriv->hp_flags & MV_HP_ERRATA_60X1A1)
1484 writel(0x00020060, mmio + MV_GPIO_PORT_CTL);
1485
1486 else if (hpriv->hp_flags & MV_HP_ERRATA_60X1B0)
1487 writel(0x00000060, mmio + MV_GPIO_PORT_CTL);
1488}
1489
1490static void mv_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
1491{
1492 if (IS_50XX(hpriv))
1493 mv_enable_leds5(hpriv, mmio);
1494 else
1495 mv_enable_leds6(hpriv, mmio);
1496}
1497
1498static void mv_cfg_signal5(struct mv_host_priv *hpriv, int idx,
1499 void __iomem *mmio)
1500{
1501 /* FIXME */
1502}
1503
1504static void mv_cfg_signal6(struct mv_host_priv *hpriv, int idx,
1505 void __iomem *mmio)
1506{
1507 void __iomem *port_mmio;
1508 u32 tmp;
1509
1510 if (hpriv->hp_flags & MV_HP_ERRATA_60X1A1) {
1511 hpriv->signal[idx].amps = 0x5 << 8;
1512 hpriv->signal[idx].pre = 0x3 << 5;
1513 return;
1514 }
1515
1516 assert (hpriv->hp_flags & MV_HP_ERRATA_60X1B0);
1517
1518 tmp = readl(mmio + MV_RESET_CFG);
1519 if ((tmp & (1 << 0)) == 0) {
1520 hpriv->signal[idx].amps = 0x4 << 8;
1521 hpriv->signal[idx].pre = 0x1 << 5;
1522 return;
1523 }
1524
1525 port_mmio = mv_port_base(mmio, idx);
1526 tmp = readl(port_mmio + PHY_MODE2);
1527
1528 hpriv->signal[idx].amps = tmp & 0x700; /* bits 10:8 */
1529 hpriv->signal[idx].pre = tmp & 0xe0; /* bits 7:5 */
1530}
1531
1532static int mv_cfg_errata(struct pci_dev *pdev, struct mv_host_priv *hpriv,
1533 unsigned int board_idx)
1534{
1535 u8 rev_id;
1536 u32 hp_flags = hpriv->hp_flags;
1537
1538 pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
1539
1540 switch(board_idx) {
1541 case chip_504x:
1542 case chip_508x:
1543 hp_flags |= MV_HP_50XX;
1544
1545 if (pdev->device == 0x5080) {
1546 switch (rev_id) {
1547 case 0x0:
1548 dev_printk(KERN_WARNING, &pdev->dev,
1549 "Applying B0 workarounds to unknown rev 0\n");
1550 /* fall through */
1551 case 0x1:
1552 hp_flags |= MV_HP_ERRATA_50XXB0;
1553 break;
1554 case 0x2:
1555 hp_flags |= MV_HP_ERRATA_50XXB1;
1556 break;
1557 case 0x3:
1558 hp_flags |= MV_HP_ERRATA_50XXB2;
1559 break;
1560 default:
1561 dev_printk(KERN_WARNING, &pdev->dev,
1562 "Applying B2 workarounds to future rev\n");
1563 hp_flags |= MV_HP_ERRATA_50XXB2;
1564 break;
1565 }
1566 } else {
1567 switch (rev_id) {
1568 case 0x0:
1569 hp_flags |= MV_HP_ERRATA_50XXB0;
1570 break;
1571 case 0x1:
1572 dev_printk(KERN_WARNING, &pdev->dev,
1573 "Applying B1 workarounds to unknown rev 1\n");
1574 /* fall through */
1575 case 0x2:
1576 hp_flags |= MV_HP_ERRATA_50XXB1;
1577 break;
1578 default:
1579 dev_printk(KERN_WARNING, &pdev->dev,
1580 "Applying B2 workarounds to future rev\n");
1581 /* fall through */
1582 case 0x3:
1583 hp_flags |= MV_HP_ERRATA_50XXB2;
1584 break;
1585 }
1586 }
1587 break;
1588
1589 case chip_604x:
1590 case chip_608x:
1591 switch (rev_id) {
1592 case 0x0:
1593 dev_printk(KERN_WARNING, &pdev->dev,
1594 "Applying A1 workarounds to unknown rev 0\n");
1595 /* fall through */
1596 case 0x1:
1597 hp_flags |= MV_HP_ERRATA_60X1A1;
1598 break;
1599 default:
1600 dev_printk(KERN_WARNING, &pdev->dev,
1601 "Applying B0 workarounds to future rev\n");
1602 /* fall through */
1603 case 0x2:
1604 hp_flags |= MV_HP_ERRATA_60X1B0;
1605 break;
1606 }
1607 break;
1608
1609 default:
1610 printk(KERN_ERR DRV_NAME ": BUG: invalid board index %u\n", board_idx);
1611 return 1;
1612 }
1613
1614 hpriv->hp_flags = hp_flags;
1615
1616 return 0;
1617}
1618
1383/** 1619/**
1384 * mv_host_init - Perform some early initialization of the host. 1620 * mv_host_init - Perform some early initialization of the host.
1621 * @pdev: host PCI device
1385 * @probe_ent: early data struct representing the host 1622 * @probe_ent: early data struct representing the host
1386 * 1623 *
1387 * If possible, do an early global reset of the host. Then do 1624 * If possible, do an early global reset of the host. Then do
@@ -1390,11 +1627,28 @@ static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio)
1390 * LOCKING: 1627 * LOCKING:
1391 * Inherited from caller. 1628 * Inherited from caller.
1392 */ 1629 */
1393static int mv_host_init(struct ata_probe_ent *probe_ent) 1630static int mv_host_init(struct pci_dev *pdev, struct ata_probe_ent *probe_ent,
1631 unsigned int board_idx)
1394{ 1632{
1395 int rc = 0, n_hc, port, hc; 1633 int rc = 0, n_hc, port, hc;
1396 void __iomem *mmio = probe_ent->mmio_base; 1634 void __iomem *mmio = probe_ent->mmio_base;
1397 void __iomem *port_mmio; 1635 void __iomem *port_mmio;
1636 struct mv_host_priv *hpriv = probe_ent->private_data;
1637
1638 rc = mv_cfg_errata(pdev, hpriv, board_idx);
1639 if (rc)
1640 goto done;
1641
1642 n_hc = mv_get_hc_count(probe_ent->host_flags);
1643 probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
1644
1645 if (IS_50XX(hpriv)) {
1646 for (port = 0; port < probe_ent->n_ports; port++)
1647 mv_cfg_signal5(hpriv, port, mmio);
1648 } else {
1649 for (port = 0; port < probe_ent->n_ports; port++)
1650 mv_cfg_signal6(hpriv, port, mmio);
1651 }
1398 1652
1399 if ((MV_FLAG_GLBL_SFT_RST & probe_ent->host_flags) && 1653 if ((MV_FLAG_GLBL_SFT_RST & probe_ent->host_flags) &&
1400 mv_global_soft_reset(probe_ent->mmio_base)) { 1654 mv_global_soft_reset(probe_ent->mmio_base)) {
@@ -1402,8 +1656,7 @@ static int mv_host_init(struct ata_probe_ent *probe_ent)
1402 goto done; 1656 goto done;
1403 } 1657 }
1404 1658
1405 n_hc = mv_get_hc_count(probe_ent->host_flags); 1659 mv_enable_leds(hpriv, mmio);
1406 probe_ent->n_ports = MV_PORTS_PER_HC * n_hc;
1407 1660
1408 for (port = 0; port < probe_ent->n_ports; port++) { 1661 for (port = 0; port < probe_ent->n_ports; port++) {
1409 port_mmio = mv_port_base(mmio, port); 1662 port_mmio = mv_port_base(mmio, port);
@@ -1435,6 +1688,7 @@ static int mv_host_init(struct ata_probe_ent *probe_ent)
1435 readl(mmio + HC_MAIN_IRQ_MASK_OFS), 1688 readl(mmio + HC_MAIN_IRQ_MASK_OFS),
1436 readl(mmio + PCI_IRQ_CAUSE_OFS), 1689 readl(mmio + PCI_IRQ_CAUSE_OFS),
1437 readl(mmio + PCI_IRQ_MASK_OFS)); 1690 readl(mmio + PCI_IRQ_MASK_OFS));
1691
1438done: 1692done:
1439 return rc; 1693 return rc;
1440} 1694}
@@ -1540,7 +1794,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1540 probe_ent->private_data = hpriv; 1794 probe_ent->private_data = hpriv;
1541 1795
1542 /* initialize adapter */ 1796 /* initialize adapter */
1543 rc = mv_host_init(probe_ent); 1797 rc = mv_host_init(pdev, probe_ent, board_idx);
1544 if (rc) { 1798 if (rc) {
1545 goto err_out_hpriv; 1799 goto err_out_hpriv;
1546 } 1800 }