diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-11-12 12:48:15 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-12 12:48:15 -0500 |
commit | bca1c4eb9411533d613123618c0d127fae532595 (patch) | |
tree | d673342d82a88ac099bb71f38ec9015b335541a9 | |
parent | 9a68c1b9580886a2ff07a42733adb7583ee3d9ac (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.c | 268 |
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 | |||
212 | enum { | 231 | enum { |
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 | ||
278 | struct mv_port_signal { | ||
279 | u32 amps; | ||
280 | u32 pre; | ||
281 | }; | ||
282 | |||
259 | struct mv_host_priv { | 283 | struct mv_host_priv { |
260 | u32 hp_flags; | 284 | u32 hp_flags; |
285 | struct mv_port_signal signal[8]; | ||
261 | }; | 286 | }; |
262 | 287 | ||
263 | static void mv_irq_clear(struct ata_port *ap); | 288 | static void mv_irq_clear(struct ata_port *ap); |
@@ -354,10 +379,12 @@ static struct ata_port_info mv_port_info[] = { | |||
354 | }; | 379 | }; |
355 | 380 | ||
356 | static const struct pci_device_id mv_pci_tbl[] = { | 381 | static 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 | ||
405 | static inline int mv_get_hc_count(unsigned long hp_flags) | 432 | static 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 | ||
410 | static void mv_irq_clear(struct ata_port *ap) | 437 | static 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) | |||
694 | static int mv_port_start(struct ata_port *ap) | 721 | static 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 | ||
1246 | static void mv_phy_errata5(struct ata_port *ap) | ||
1247 | { | ||
1248 | /* FIXME */ | ||
1249 | } | ||
1250 | |||
1251 | static 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 | |||
1282 | static 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, | |||
1220 | static void mv_phy_reset(struct ata_port *ap) | 1303 | static 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 | ||
1476 | static void mv_enable_leds5(struct mv_host_priv *hpriv, void __iomem *mmio) | ||
1477 | { | ||
1478 | /* FIXME */ | ||
1479 | } | ||
1480 | |||
1481 | static 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 | |||
1490 | static 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 | |||
1498 | static void mv_cfg_signal5(struct mv_host_priv *hpriv, int idx, | ||
1499 | void __iomem *mmio) | ||
1500 | { | ||
1501 | /* FIXME */ | ||
1502 | } | ||
1503 | |||
1504 | static 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 | |||
1532 | static 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 | */ |
1393 | static int mv_host_init(struct ata_probe_ent *probe_ent) | 1630 | static 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 | |||
1438 | done: | 1692 | done: |
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 | } |