aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c86
1 files changed, 66 insertions, 20 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c95015986c94..a47d309df2f2 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -122,6 +122,7 @@ enum {
122 HOST_VERSION = 0x10, /* AHCI spec. version compliancy */ 122 HOST_VERSION = 0x10, /* AHCI spec. version compliancy */
123 HOST_EM_LOC = 0x1c, /* Enclosure Management location */ 123 HOST_EM_LOC = 0x1c, /* Enclosure Management location */
124 HOST_EM_CTL = 0x20, /* Enclosure Management Control */ 124 HOST_EM_CTL = 0x20, /* Enclosure Management Control */
125 HOST_CAP2 = 0x24, /* host capabilities, extended */
125 126
126 /* HOST_CTL bits */ 127 /* HOST_CTL bits */
127 HOST_RESET = (1 << 0), /* reset controller; self-clear */ 128 HOST_RESET = (1 << 0), /* reset controller; self-clear */
@@ -129,16 +130,29 @@ enum {
129 HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ 130 HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
130 131
131 /* HOST_CAP bits */ 132 /* HOST_CAP bits */
133 HOST_CAP_SXS = (1 << 5), /* Supports External SATA */
132 HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */ 134 HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
133 HOST_CAP_SSC = (1 << 14), /* Slumber capable */ 135 HOST_CAP_CCC = (1 << 7), /* Command Completion Coalescing */
136 HOST_CAP_PART = (1 << 13), /* Partial state capable */
137 HOST_CAP_SSC = (1 << 14), /* Slumber state capable */
138 HOST_CAP_PIO_MULTI = (1 << 15), /* PIO multiple DRQ support */
139 HOST_CAP_FBS = (1 << 16), /* FIS-based switching support */
134 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */ 140 HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
141 HOST_CAP_ONLY = (1 << 18), /* Supports AHCI mode only */
135 HOST_CAP_CLO = (1 << 24), /* Command List Override support */ 142 HOST_CAP_CLO = (1 << 24), /* Command List Override support */
143 HOST_CAP_LED = (1 << 25), /* Supports activity LED */
136 HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */ 144 HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
137 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ 145 HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
146 HOST_CAP_MPS = (1 << 28), /* Mechanical presence switch */
138 HOST_CAP_SNTF = (1 << 29), /* SNotification register */ 147 HOST_CAP_SNTF = (1 << 29), /* SNotification register */
139 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ 148 HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
140 HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ 149 HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
141 150
151 /* HOST_CAP2 bits */
152 HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */
153 HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */
154 HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */
155
142 /* registers for each SATA port */ 156 /* registers for each SATA port */
143 PORT_LST_ADDR = 0x00, /* command list DMA addr */ 157 PORT_LST_ADDR = 0x00, /* command list DMA addr */
144 PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */ 158 PORT_LST_ADDR_HI = 0x04, /* command list DMA addr hi */
@@ -267,8 +281,10 @@ struct ahci_em_priv {
267struct ahci_host_priv { 281struct ahci_host_priv {
268 unsigned int flags; /* AHCI_HFLAG_* */ 282 unsigned int flags; /* AHCI_HFLAG_* */
269 u32 cap; /* cap to use */ 283 u32 cap; /* cap to use */
284 u32 cap2; /* cap2 to use */
270 u32 port_map; /* port map to use */ 285 u32 port_map; /* port map to use */
271 u32 saved_cap; /* saved initial cap */ 286 u32 saved_cap; /* saved initial cap */
287 u32 saved_cap2; /* saved initial cap2 */
272 u32 saved_port_map; /* saved initial port_map */ 288 u32 saved_port_map; /* saved initial port_map */
273 u32 em_loc; /* enclosure management location */ 289 u32 em_loc; /* enclosure management location */
274}; 290};
@@ -331,12 +347,15 @@ static void ahci_init_sw_activity(struct ata_link *link);
331 347
332static ssize_t ahci_show_host_caps(struct device *dev, 348static ssize_t ahci_show_host_caps(struct device *dev,
333 struct device_attribute *attr, char *buf); 349 struct device_attribute *attr, char *buf);
350static ssize_t ahci_show_host_cap2(struct device *dev,
351 struct device_attribute *attr, char *buf);
334static ssize_t ahci_show_host_version(struct device *dev, 352static ssize_t ahci_show_host_version(struct device *dev,
335 struct device_attribute *attr, char *buf); 353 struct device_attribute *attr, char *buf);
336static ssize_t ahci_show_port_cmd(struct device *dev, 354static ssize_t ahci_show_port_cmd(struct device *dev,
337 struct device_attribute *attr, char *buf); 355 struct device_attribute *attr, char *buf);
338 356
339DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL); 357DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
358DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
340DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL); 359DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
341DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL); 360DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
342 361
@@ -345,6 +364,7 @@ static struct device_attribute *ahci_shost_attrs[] = {
345 &dev_attr_em_message_type, 364 &dev_attr_em_message_type,
346 &dev_attr_em_message, 365 &dev_attr_em_message,
347 &dev_attr_ahci_host_caps, 366 &dev_attr_ahci_host_caps,
367 &dev_attr_ahci_host_cap2,
348 &dev_attr_ahci_host_version, 368 &dev_attr_ahci_host_version,
349 &dev_attr_ahci_port_cmd, 369 &dev_attr_ahci_port_cmd,
350 NULL 370 NULL
@@ -733,6 +753,16 @@ static ssize_t ahci_show_host_caps(struct device *dev,
733 return sprintf(buf, "%x\n", hpriv->cap); 753 return sprintf(buf, "%x\n", hpriv->cap);
734} 754}
735 755
756static ssize_t ahci_show_host_cap2(struct device *dev,
757 struct device_attribute *attr, char *buf)
758{
759 struct Scsi_Host *shost = class_to_shost(dev);
760 struct ata_port *ap = ata_shost_to_port(shost);
761 struct ahci_host_priv *hpriv = ap->host->private_data;
762
763 return sprintf(buf, "%x\n", hpriv->cap2);
764}
765
736static ssize_t ahci_show_host_version(struct device *dev, 766static ssize_t ahci_show_host_version(struct device *dev,
737 struct device_attribute *attr, char *buf) 767 struct device_attribute *attr, char *buf)
738{ 768{
@@ -772,7 +802,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
772 struct ahci_host_priv *hpriv) 802 struct ahci_host_priv *hpriv)
773{ 803{
774 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR]; 804 void __iomem *mmio = pcim_iomap_table(pdev)[AHCI_PCI_BAR];
775 u32 cap, port_map; 805 u32 cap, cap2, vers, port_map;
776 int i; 806 int i;
777 int mv; 807 int mv;
778 808
@@ -785,6 +815,14 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
785 hpriv->saved_cap = cap = readl(mmio + HOST_CAP); 815 hpriv->saved_cap = cap = readl(mmio + HOST_CAP);
786 hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL); 816 hpriv->saved_port_map = port_map = readl(mmio + HOST_PORTS_IMPL);
787 817
818 /* CAP2 register is only defined for AHCI 1.2 and later */
819 vers = readl(mmio + HOST_VERSION);
820 if ((vers >> 16) > 1 ||
821 ((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200))
822 hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2);
823 else
824 hpriv->saved_cap2 = cap2 = 0;
825
788 /* some chips have errata preventing 64bit use */ 826 /* some chips have errata preventing 64bit use */
789 if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) { 827 if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
790 dev_printk(KERN_INFO, &pdev->dev, 828 dev_printk(KERN_INFO, &pdev->dev,
@@ -870,6 +908,7 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
870 908
871 /* record values to use during operation */ 909 /* record values to use during operation */
872 hpriv->cap = cap; 910 hpriv->cap = cap;
911 hpriv->cap2 = cap2;
873 hpriv->port_map = port_map; 912 hpriv->port_map = port_map;
874} 913}
875 914
@@ -888,6 +927,8 @@ static void ahci_restore_initial_config(struct ata_host *host)
888 void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; 927 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
889 928
890 writel(hpriv->saved_cap, mmio + HOST_CAP); 929 writel(hpriv->saved_cap, mmio + HOST_CAP);
930 if (hpriv->saved_cap2)
931 writel(hpriv->saved_cap2, mmio + HOST_CAP2);
891 writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL); 932 writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
892 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ 933 (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
893} 934}
@@ -2535,13 +2576,14 @@ static void ahci_print_info(struct ata_host *host)
2535 struct ahci_host_priv *hpriv = host->private_data; 2576 struct ahci_host_priv *hpriv = host->private_data;
2536 struct pci_dev *pdev = to_pci_dev(host->dev); 2577 struct pci_dev *pdev = to_pci_dev(host->dev);
2537 void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; 2578 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
2538 u32 vers, cap, impl, speed; 2579 u32 vers, cap, cap2, impl, speed;
2539 const char *speed_s; 2580 const char *speed_s;
2540 u16 cc; 2581 u16 cc;
2541 const char *scc_s; 2582 const char *scc_s;
2542 2583
2543 vers = readl(mmio + HOST_VERSION); 2584 vers = readl(mmio + HOST_VERSION);
2544 cap = hpriv->cap; 2585 cap = hpriv->cap;
2586 cap2 = hpriv->cap2;
2545 impl = hpriv->port_map; 2587 impl = hpriv->port_map;
2546 2588
2547 speed = (cap >> 20) & 0xf; 2589 speed = (cap >> 20) & 0xf;
@@ -2584,25 +2626,29 @@ static void ahci_print_info(struct ata_host *host)
2584 "flags: " 2626 "flags: "
2585 "%s%s%s%s%s%s%s" 2627 "%s%s%s%s%s%s%s"
2586 "%s%s%s%s%s%s%s" 2628 "%s%s%s%s%s%s%s"
2587 "%s\n" 2629 "%s%s%s%s%s%s\n"
2588 , 2630 ,
2589 2631
2590 cap & (1 << 31) ? "64bit " : "", 2632 cap & HOST_CAP_64 ? "64bit " : "",
2591 cap & (1 << 30) ? "ncq " : "", 2633 cap & HOST_CAP_NCQ ? "ncq " : "",
2592 cap & (1 << 29) ? "sntf " : "", 2634 cap & HOST_CAP_SNTF ? "sntf " : "",
2593 cap & (1 << 28) ? "ilck " : "", 2635 cap & HOST_CAP_MPS ? "ilck " : "",
2594 cap & (1 << 27) ? "stag " : "", 2636 cap & HOST_CAP_SSS ? "stag " : "",
2595 cap & (1 << 26) ? "pm " : "", 2637 cap & HOST_CAP_ALPM ? "pm " : "",
2596 cap & (1 << 25) ? "led " : "", 2638 cap & HOST_CAP_LED ? "led " : "",
2597 2639 cap & HOST_CAP_CLO ? "clo " : "",
2598 cap & (1 << 24) ? "clo " : "", 2640 cap & HOST_CAP_ONLY ? "only " : "",
2599 cap & (1 << 19) ? "nz " : "", 2641 cap & HOST_CAP_PMP ? "pmp " : "",
2600 cap & (1 << 18) ? "only " : "", 2642 cap & HOST_CAP_FBS ? "fbs " : "",
2601 cap & (1 << 17) ? "pmp " : "", 2643 cap & HOST_CAP_PIO_MULTI ? "pio " : "",
2602 cap & (1 << 15) ? "pio " : "", 2644 cap & HOST_CAP_SSC ? "slum " : "",
2603 cap & (1 << 14) ? "slum " : "", 2645 cap & HOST_CAP_PART ? "part " : "",
2604 cap & (1 << 13) ? "part " : "", 2646 cap & HOST_CAP_CCC ? "ccc " : "",
2605 cap & (1 << 6) ? "ems ": "" 2647 cap & HOST_CAP_EMS ? "ems " : "",
2648 cap & HOST_CAP_SXS ? "sxs " : "",
2649 cap2 & HOST_CAP2_APST ? "apst " : "",
2650 cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
2651 cap2 & HOST_CAP2_BOH ? "boh " : ""
2606 ); 2652 );
2607} 2653}
2608 2654