|
61 | 61 | SATA_CHAN_ENAB = 0x40, /* SATA channel enable */
|
62 | 62 | SATA_INT_GATE = 0x41, /* SATA interrupt gating */
|
63 | 63 | SATA_NATIVE_MODE = 0x42, /* Native mode enable */
|
| 64 | + SVIA_MISC_3 = 0x46, /* Miscellaneous Control III */ |
64 | 65 | PATA_UDMA_TIMING = 0xB3, /* PATA timing for DMA/ cable detect */
|
65 | 66 | PATA_PIO_TIMING = 0xAB, /* PATA timing register */
|
66 | 67 |
|
|
71 | 72 | NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
|
72 | 73 |
|
73 | 74 | SATA_EXT_PHY = (1 << 6), /* 0==use PATA, 1==ext phy */
|
| 75 | + |
| 76 | + SATA_HOTPLUG = (1 << 5), /* enable IRQ on hotplug */ |
74 | 77 | };
|
75 | 78 |
|
76 | 79 | struct svia_priv {
|
@@ -553,6 +556,37 @@ static void svia_wd_fix(struct pci_dev *pdev)
|
553 | 556 | pci_write_config_byte(pdev, 0x52, tmp8 | BIT(2));
|
554 | 557 | }
|
555 | 558 |
|
| 559 | +static irqreturn_t vt6421_interrupt(int irq, void *dev_instance) |
| 560 | +{ |
| 561 | + struct ata_host *host = dev_instance; |
| 562 | + irqreturn_t rc = ata_bmdma_interrupt(irq, dev_instance); |
| 563 | + |
| 564 | + /* if the IRQ was not handled, it might be a hotplug IRQ */ |
| 565 | + if (rc != IRQ_HANDLED) { |
| 566 | + u32 serror; |
| 567 | + unsigned long flags; |
| 568 | + |
| 569 | + spin_lock_irqsave(&host->lock, flags); |
| 570 | + /* check for hotplug on port 0 */ |
| 571 | + svia_scr_read(&host->ports[0]->link, SCR_ERROR, &serror); |
| 572 | + if (serror & SERR_PHYRDY_CHG) { |
| 573 | + ata_ehi_hotplugged(&host->ports[0]->link.eh_info); |
| 574 | + ata_port_freeze(host->ports[0]); |
| 575 | + rc = IRQ_HANDLED; |
| 576 | + } |
| 577 | + /* check for hotplug on port 1 */ |
| 578 | + svia_scr_read(&host->ports[1]->link, SCR_ERROR, &serror); |
| 579 | + if (serror & SERR_PHYRDY_CHG) { |
| 580 | + ata_ehi_hotplugged(&host->ports[1]->link.eh_info); |
| 581 | + ata_port_freeze(host->ports[1]); |
| 582 | + rc = IRQ_HANDLED; |
| 583 | + } |
| 584 | + spin_unlock_irqrestore(&host->lock, flags); |
| 585 | + } |
| 586 | + |
| 587 | + return rc; |
| 588 | +} |
| 589 | + |
556 | 590 | static void vt6421_error_handler(struct ata_port *ap)
|
557 | 591 | {
|
558 | 592 | struct svia_priv *hpriv = ap->host->private_data;
|
@@ -610,6 +644,16 @@ static void svia_configure(struct pci_dev *pdev, int board_id,
|
610 | 644 | pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
|
611 | 645 | }
|
612 | 646 |
|
| 647 | + /* enable IRQ on hotplug */ |
| 648 | + pci_read_config_byte(pdev, SVIA_MISC_3, &tmp8); |
| 649 | + if ((tmp8 & SATA_HOTPLUG) != SATA_HOTPLUG) { |
| 650 | + dev_dbg(&pdev->dev, |
| 651 | + "enabling SATA hotplug (0x%x)\n", |
| 652 | + (int) tmp8); |
| 653 | + tmp8 |= SATA_HOTPLUG; |
| 654 | + pci_write_config_byte(pdev, SVIA_MISC_3, tmp8); |
| 655 | + } |
| 656 | + |
613 | 657 | /*
|
614 | 658 | * vt6420/1 has problems talking to some drives. The following
|
615 | 659 | * is the fix from Joseph Chan <JosephChan@via.com.tw>.
|
@@ -698,8 +742,12 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
698 | 742 | svia_configure(pdev, board_id, hpriv);
|
699 | 743 |
|
700 | 744 | pci_set_master(pdev);
|
701 |
| - return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
702 |
| - IRQF_SHARED, &svia_sht); |
| 745 | + if (board_id == vt6421) |
| 746 | + return ata_host_activate(host, pdev->irq, vt6421_interrupt, |
| 747 | + IRQF_SHARED, &svia_sht); |
| 748 | + else |
| 749 | + return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
| 750 | + IRQF_SHARED, &svia_sht); |
703 | 751 | }
|
704 | 752 |
|
705 | 753 | #ifdef CONFIG_PM_SLEEP
|
|
0 commit comments