diff options
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r-- | drivers/ata/ahci.c | 68 |
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 | ||
634 | static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) | 635 | static 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 | 652 | static int ahci_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) | |
652 | static 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)); | 664 | static 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 | ||
669 | static void ahci_start_engine(struct ata_port *ap) | 676 | static 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 |