aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c68
1 files changed, 37 insertions, 31 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 9475e5619af1..de8bffbf4bd3 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -99,6 +99,7 @@ enum {
99 HOST_CAP_SSC = (1 << 14), /* Slumber capable */ 99 HOST_CAP_SSC = (1 << 14), /* Slumber capable */
100 HOST_CAP_CLO = (1 << 24), /* Command List Override support */ 100 HOST_CAP_CLO = (1 << 24), /* Command List Override support */
101 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ 101 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
102 HOST_CAP_SNTF = (1 << 29), /* SNotification register */
102 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ 103 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
103 HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ 104 HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
104 105
@@ -113,11 +114,11 @@ enum {
113 PORT_TFDATA = 0x20, /* taskfile data */ 114 PORT_TFDATA = 0x20, /* taskfile data */
114 PORT_SIG = 0x24, /* device TF signature */ 115 PORT_SIG = 0x24, /* device TF signature */
115 PORT_CMD_ISSUE = 0x38, /* command issue */ 116 PORT_CMD_ISSUE = 0x38, /* command issue */
116 PORT_SCR = 0x28, /* SATA phy register block */
117 PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */ 117 PORT_SCR_STAT = 0x28, /* SATA phy register: SStatus */
118 PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */ 118 PORT_SCR_CTL = 0x2c, /* SATA phy register: SControl */
119 PORT_SCR_ERR = 0x30, /* SATA phy register: SError */ 119 PORT_SCR_ERR = 0x30, /* SATA phy register: SError */
120 PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */ 120 PORT_SCR_ACT = 0x34, /* SATA phy register: SActive */
121 PORT_SCR_NTF = 0x3c, /* SATA phy register: SNotification */
121 122
122 /* PORT_IRQ_{STAT,MASK} bits */ 123 /* PORT_IRQ_{STAT,MASK} bits */
123 PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */ 124 PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
@@ -631,39 +632,45 @@ static void ahci_restore_initial_config(struct ata_host *host)
631 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ 632 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
632} 633}
633 634
634static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) 635static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
635{ 636{
636 unsigned int sc_reg; 637 static const int offset[] = {
637 638 [SCR_STATUS] = PORT_SCR_STAT,
638 switch (sc_reg_in) { 639 [SCR_CONTROL] = PORT_SCR_CTL,
639 case SCR_STATUS: sc_reg = 0; break; 640 [SCR_ERROR] = PORT_SCR_ERR,
640 case SCR_CONTROL: sc_reg = 1; break; 641 [SCR_ACTIVE] = PORT_SCR_ACT,
641 case SCR_ERROR: sc_reg = 2; break; 642 [SCR_NOTIFICATION] = PORT_SCR_NTF,
642 case SCR_ACTIVE: sc_reg = 3; break; 643 };
643 default: 644 struct ahci_host_priv *hpriv = ap->host->private_data;
644 return -EINVAL;
645 }
646 645
647 *val = readl(ap->ioaddr.scr_addr + (sc_reg * 4)); 646 if (sc_reg < ARRAY_SIZE(offset) &&
647 (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
648 return offset[sc_reg];
648 return 0; 649 return 0;
649} 650}
650 651
651 652static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
652static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
653{ 653{
654 unsigned int sc_reg; 654 void __iomem *port_mmio = ahci_port_base(ap);
655 655 int offset = ahci_scr_offset(ap, sc_reg);
656 switch (sc_reg_in) { 656
657 case SCR_STATUS: sc_reg = 0; break; 657 if (offset) {
658 case SCR_CONTROL: sc_reg = 1; break; 658 *val = readl(port_mmio + offset);
659 case SCR_ERROR: sc_reg = 2; break; 659 return 0;
660 case SCR_ACTIVE: sc_reg = 3; break;
661 default:
662 return -EINVAL;
663 } 660 }
661 return -EINVAL;
662}
664 663
665 writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); 664static int ahci_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
666 return 0; 665{
666 void __iomem *port_mmio = ahci_port_base(ap);
667 int offset = ahci_scr_offset(ap, sc_reg);
668
669 if (offset) {
670 writel(val, port_mmio + offset);
671 return 0;
672 }
673 return -EINVAL;
667} 674}
668 675
669static void ahci_start_engine(struct ata_port *ap) 676static void ahci_start_engine(struct ata_port *ap)
@@ -1768,12 +1775,13 @@ static void ahci_print_info(struct ata_host *host)
1768 1775
1769 dev_printk(KERN_INFO, &pdev->dev, 1776 dev_printk(KERN_INFO, &pdev->dev,
1770 "flags: " 1777 "flags: "
1771 "%s%s%s%s%s%s" 1778 "%s%s%s%s%s%s%s"
1772 "%s%s%s%s%s%s%s\n" 1779 "%s%s%s%s%s%s%s\n"
1773 , 1780 ,
1774 1781
1775 cap & (1 << 31) ? "64bit " : "", 1782 cap & (1 << 31) ? "64bit " : "",
1776 cap & (1 << 30) ? "ncq " : "", 1783 cap & (1 << 30) ? "ncq " : "",
1784 cap & (1 << 29) ? "sntf " : "",
1777 cap & (1 << 28) ? "ilck " : "", 1785 cap & (1 << 28) ? "ilck " : "",
1778 cap & (1 << 27) ? "stag " : "", 1786 cap & (1 << 27) ? "stag " : "",
1779 cap & (1 << 26) ? "pm " : "", 1787 cap & (1 << 26) ? "pm " : "",
@@ -1842,10 +1850,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1842 void __iomem *port_mmio = ahci_port_base(ap); 1850 void __iomem *port_mmio = ahci_port_base(ap);
1843 1851
1844 /* standard SATA port setup */ 1852 /* standard SATA port setup */
1845 if (hpriv->port_map & (1 << i)) { 1853 if (hpriv->port_map & (1 << i))
1846 ap->ioaddr.cmd_addr = port_mmio; 1854 ap->ioaddr.cmd_addr = port_mmio;
1847 ap->ioaddr.scr_addr = port_mmio + PORT_SCR;
1848 }
1849 1855
1850 /* disabled/not-implemented port */ 1856 /* disabled/not-implemented port */
1851 else 1857 else