diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-11-12 22:14:02 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-12 22:14:02 -0500 |
commit | 522479fb98c6667f081e75f87e298e413c0b1db8 (patch) | |
tree | 2a2b52371dd840e054374f23ae607e4476db0ac0 /drivers/scsi/sata_mv.c | |
parent | 47c2b677daeed9c79ecb7167c211ff36876ea611 (diff) |
[libata sata_mv] hardware initialization work
Implement flash reset and PCI reset on 50xx and 60xx.
Implement LED enable on 50xx.
Diffstat (limited to 'drivers/scsi/sata_mv.c')
-rw-r--r-- | drivers/scsi/sata_mv.c | 117 |
1 files changed, 105 insertions, 12 deletions
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 4ca4b35d0022..180baa532068 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -50,6 +50,7 @@ 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_FLASH_CTL = 0x1046c, | ||
53 | MV_GPIO_PORT_CTL = 0x104f0, | 54 | MV_GPIO_PORT_CTL = 0x104f0, |
54 | MV_RESET_CFG = 0x180d8, | 55 | MV_RESET_CFG = 0x180d8, |
55 | 56 | ||
@@ -87,12 +88,6 @@ enum { | |||
87 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO), | 88 | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO), |
88 | MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, | 89 | MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, |
89 | 90 | ||
90 | chip_504x = 0, | ||
91 | chip_508x = 1, | ||
92 | chip_5080 = 2, | ||
93 | chip_604x = 3, | ||
94 | chip_608x = 4, | ||
95 | |||
96 | CRQB_FLAG_READ = (1 << 0), | 91 | CRQB_FLAG_READ = (1 << 0), |
97 | CRQB_TAG_SHIFT = 1, | 92 | CRQB_TAG_SHIFT = 1, |
98 | CRQB_CMD_ADDR_SHIFT = 8, | 93 | CRQB_CMD_ADDR_SHIFT = 8, |
@@ -112,8 +107,19 @@ enum { | |||
112 | PCI_MASTER_EMPTY = (1 << 3), | 107 | PCI_MASTER_EMPTY = (1 << 3), |
113 | GLOB_SFT_RST = (1 << 4), | 108 | GLOB_SFT_RST = (1 << 4), |
114 | 109 | ||
115 | PCI_IRQ_CAUSE_OFS = 0x1d58, | 110 | MV_PCI_MODE = 0xd00, |
116 | PCI_IRQ_MASK_OFS = 0x1d5c, | 111 | MV_PCI_EXP_ROM_BAR_CTL = 0xd2c, |
112 | MV_PCI_DISC_TIMER = 0xd04, | ||
113 | MV_PCI_MSI_TRIGGER = 0xc38, | ||
114 | MV_PCI_SERR_MASK = 0xc28, | ||
115 | MV_PCI_XBAR_TMOUT = 0x1d04, | ||
116 | MV_PCI_ERR_LOW_ADDRESS = 0x1d40, | ||
117 | MV_PCI_ERR_HIGH_ADDRESS = 0x1d44, | ||
118 | MV_PCI_ERR_ATTRIBUTE = 0x1d48, | ||
119 | MV_PCI_ERR_COMMAND = 0x1d50, | ||
120 | |||
121 | PCI_IRQ_CAUSE_OFS = 0x1d58, | ||
122 | PCI_IRQ_MASK_OFS = 0x1d5c, | ||
117 | PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ | 123 | PCI_UNMASK_ALL_IRQS = 0x7fffff, /* bits 22-0 */ |
118 | 124 | ||
119 | HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, | 125 | HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, |
@@ -236,6 +242,14 @@ enum { | |||
236 | EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U, | 242 | EDMA_RSP_Q_BASE_LO_MASK = 0xffffff00U, |
237 | }; | 243 | }; |
238 | 244 | ||
245 | enum chip_type { | ||
246 | chip_504x, | ||
247 | chip_508x, | ||
248 | chip_5080, | ||
249 | chip_604x, | ||
250 | chip_608x, | ||
251 | }; | ||
252 | |||
239 | /* Command ReQuest Block: 32B */ | 253 | /* Command ReQuest Block: 32B */ |
240 | struct mv_crqb { | 254 | struct mv_crqb { |
241 | u32 sg_addr; | 255 | u32 sg_addr; |
@@ -284,6 +298,8 @@ struct mv_hw_ops { | |||
284 | void (*read_preamp)(struct mv_host_priv *hpriv, int idx, | 298 | void (*read_preamp)(struct mv_host_priv *hpriv, int idx, |
285 | void __iomem *mmio); | 299 | void __iomem *mmio); |
286 | int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio); | 300 | int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio); |
301 | void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
302 | void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio); | ||
287 | }; | 303 | }; |
288 | 304 | ||
289 | struct mv_host_priv { | 305 | struct mv_host_priv { |
@@ -311,12 +327,16 @@ static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); | |||
311 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, | 327 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, |
312 | void __iomem *mmio); | 328 | void __iomem *mmio); |
313 | static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio); | 329 | static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio); |
330 | static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
331 | static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio); | ||
314 | 332 | ||
315 | static void mv6_phy_errata(struct ata_port *ap); | 333 | static void mv6_phy_errata(struct ata_port *ap); |
316 | static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); | 334 | static void mv6_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio); |
317 | static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, | 335 | static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, |
318 | void __iomem *mmio); | 336 | void __iomem *mmio); |
319 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio); | 337 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio); |
338 | static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); | ||
339 | static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio); | ||
320 | 340 | ||
321 | static struct scsi_host_template mv_sht = { | 341 | static struct scsi_host_template mv_sht = { |
322 | .module = THIS_MODULE, | 342 | .module = THIS_MODULE, |
@@ -433,6 +453,8 @@ static const struct mv_hw_ops mv5xxx_ops = { | |||
433 | .enable_leds = mv5_enable_leds, | 453 | .enable_leds = mv5_enable_leds, |
434 | .read_preamp = mv5_read_preamp, | 454 | .read_preamp = mv5_read_preamp, |
435 | .reset_hc = mv5_reset_hc, | 455 | .reset_hc = mv5_reset_hc, |
456 | .reset_flash = mv5_reset_flash, | ||
457 | .reset_bus = mv5_reset_bus, | ||
436 | }; | 458 | }; |
437 | 459 | ||
438 | static const struct mv_hw_ops mv6xxx_ops = { | 460 | static const struct mv_hw_ops mv6xxx_ops = { |
@@ -440,6 +462,8 @@ static const struct mv_hw_ops mv6xxx_ops = { | |||
440 | .enable_leds = mv6_enable_leds, | 462 | .enable_leds = mv6_enable_leds, |
441 | .read_preamp = mv6_read_preamp, | 463 | .read_preamp = mv6_read_preamp, |
442 | .reset_hc = mv6_reset_hc, | 464 | .reset_hc = mv6_reset_hc, |
465 | .reset_flash = mv6_reset_flash, | ||
466 | .reset_bus = mv_reset_pci_bus, | ||
443 | }; | 467 | }; |
444 | 468 | ||
445 | /* | 469 | /* |
@@ -655,9 +679,45 @@ static void mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) | |||
655 | } | 679 | } |
656 | } | 680 | } |
657 | 681 | ||
682 | #undef ZERO | ||
683 | #define ZERO(reg) writel(0, mmio + (reg)) | ||
684 | static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio) | ||
685 | { | ||
686 | u32 tmp; | ||
687 | |||
688 | tmp = readl(mmio + MV_PCI_MODE); | ||
689 | tmp &= 0xff00ffff; | ||
690 | writel(tmp, mmio + MV_PCI_MODE); | ||
691 | |||
692 | ZERO(MV_PCI_DISC_TIMER); | ||
693 | ZERO(MV_PCI_MSI_TRIGGER); | ||
694 | writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); | ||
695 | ZERO(HC_MAIN_IRQ_MASK_OFS); | ||
696 | ZERO(MV_PCI_SERR_MASK); | ||
697 | ZERO(PCI_IRQ_CAUSE_OFS); | ||
698 | ZERO(PCI_IRQ_MASK_OFS); | ||
699 | ZERO(MV_PCI_ERR_LOW_ADDRESS); | ||
700 | ZERO(MV_PCI_ERR_HIGH_ADDRESS); | ||
701 | ZERO(MV_PCI_ERR_ATTRIBUTE); | ||
702 | ZERO(MV_PCI_ERR_COMMAND); | ||
703 | } | ||
704 | #undef ZERO | ||
705 | |||
706 | static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) | ||
707 | { | ||
708 | u32 tmp; | ||
709 | |||
710 | mv5_reset_flash(hpriv, mmio); | ||
711 | |||
712 | tmp = readl(mmio + MV_GPIO_PORT_CTL); | ||
713 | tmp &= 0x3; | ||
714 | tmp |= (1 << 5) | (1 << 6); | ||
715 | writel(tmp, mmio + MV_GPIO_PORT_CTL); | ||
716 | } | ||
717 | |||
658 | /** | 718 | /** |
659 | * mv_global_soft_reset - Perform the 6xxx global soft reset | 719 | * mv6_reset_hc - Perform the 6xxx global soft reset |
660 | * @mmio_base: base address of the HBA | 720 | * @mmio: base address of the HBA |
661 | * | 721 | * |
662 | * This routine only applies to 6xxx parts. | 722 | * This routine only applies to 6xxx parts. |
663 | * | 723 | * |
@@ -1273,6 +1333,29 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, | |||
1273 | return IRQ_RETVAL(handled); | 1333 | return IRQ_RETVAL(handled); |
1274 | } | 1334 | } |
1275 | 1335 | ||
1336 | static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio) | ||
1337 | { | ||
1338 | u8 rev_id; | ||
1339 | int early_5080; | ||
1340 | |||
1341 | pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); | ||
1342 | |||
1343 | early_5080 = (pdev->device == 0x5080) && (rev_id == 0); | ||
1344 | |||
1345 | if (!early_5080) { | ||
1346 | u32 tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); | ||
1347 | tmp |= (1 << 0); | ||
1348 | writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); | ||
1349 | } | ||
1350 | |||
1351 | mv_reset_pci_bus(pdev, mmio); | ||
1352 | } | ||
1353 | |||
1354 | static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio) | ||
1355 | { | ||
1356 | writel(0x0fcfffff, mmio + MV_FLASH_CTL); | ||
1357 | } | ||
1358 | |||
1276 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, | 1359 | static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, |
1277 | void __iomem *mmio) | 1360 | void __iomem *mmio) |
1278 | { | 1361 | { |
@@ -1281,7 +1364,15 @@ static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx, | |||
1281 | 1364 | ||
1282 | static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) | 1365 | static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio) |
1283 | { | 1366 | { |
1284 | /* FIXME */ | 1367 | u32 tmp; |
1368 | |||
1369 | writel(0, mmio + MV_GPIO_PORT_CTL); | ||
1370 | |||
1371 | /* FIXME: handle MV_HP_ERRATA_50XXB2 errata */ | ||
1372 | |||
1373 | tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL); | ||
1374 | tmp |= ~(1 << 0); | ||
1375 | writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL); | ||
1285 | } | 1376 | } |
1286 | 1377 | ||
1287 | static void mv5_phy_errata(struct ata_port *ap) | 1378 | static void mv5_phy_errata(struct ata_port *ap) |
@@ -1564,7 +1655,7 @@ static void mv_port_init(struct ata_ioports *port, void __iomem *port_mmio) | |||
1564 | } | 1655 | } |
1565 | 1656 | ||
1566 | static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv, | 1657 | static int mv_chip_id(struct pci_dev *pdev, struct mv_host_priv *hpriv, |
1567 | unsigned int board_idx) | 1658 | unsigned int board_idx) |
1568 | { | 1659 | { |
1569 | u8 rev_id; | 1660 | u8 rev_id; |
1570 | u32 hp_flags = hpriv->hp_flags; | 1661 | u32 hp_flags = hpriv->hp_flags; |
@@ -1676,6 +1767,8 @@ static int mv_init_host(struct pci_dev *pdev, struct ata_probe_ent *probe_ent, | |||
1676 | if (rc) | 1767 | if (rc) |
1677 | goto done; | 1768 | goto done; |
1678 | 1769 | ||
1770 | hpriv->ops->reset_flash(hpriv, mmio); | ||
1771 | hpriv->ops->reset_bus(pdev, mmio); | ||
1679 | hpriv->ops->enable_leds(hpriv, mmio); | 1772 | hpriv->ops->enable_leds(hpriv, mmio); |
1680 | 1773 | ||
1681 | for (port = 0; port < probe_ent->n_ports; port++) { | 1774 | for (port = 0; port < probe_ent->n_ports; port++) { |