1c82ee6d3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2365cfa1eSAnton Vorontsov /*
3365cfa1eSAnton Vorontsov * libahci.c - Common AHCI SATA low-level routines
4365cfa1eSAnton Vorontsov *
58c3d3d4bSTejun Heo * Maintained by: Tejun Heo <tj@kernel.org>
6365cfa1eSAnton Vorontsov * Please ALWAYS copy linux-ide@vger.kernel.org
7365cfa1eSAnton Vorontsov * on emails.
8365cfa1eSAnton Vorontsov *
9365cfa1eSAnton Vorontsov * Copyright 2004-2005 Red Hat, Inc.
10365cfa1eSAnton Vorontsov *
11365cfa1eSAnton Vorontsov * libata documentation is available via 'make {ps|pdf}docs',
129bb9a39cSMauro Carvalho Chehab * as Documentation/driver-api/libata.rst
13365cfa1eSAnton Vorontsov *
14365cfa1eSAnton Vorontsov * AHCI hardware documentation:
15365cfa1eSAnton Vorontsov * http://www.intel.com/technology/serialata/pdf/rev1_0.pdf
16365cfa1eSAnton Vorontsov * http://www.intel.com/technology/serialata/pdf/rev1_1.pdf
17365cfa1eSAnton Vorontsov */
18365cfa1eSAnton Vorontsov
1918ee7c49SSerge Semin #include <linux/bitops.h>
20365cfa1eSAnton Vorontsov #include <linux/kernel.h>
21fbaf666bSTejun Heo #include <linux/gfp.h>
22365cfa1eSAnton Vorontsov #include <linux/module.h>
23fae2a637SJohn Garry #include <linux/nospec.h>
24365cfa1eSAnton Vorontsov #include <linux/blkdev.h>
25365cfa1eSAnton Vorontsov #include <linux/delay.h>
26365cfa1eSAnton Vorontsov #include <linux/interrupt.h>
27365cfa1eSAnton Vorontsov #include <linux/dma-mapping.h>
28365cfa1eSAnton Vorontsov #include <linux/device.h>
29365cfa1eSAnton Vorontsov #include <scsi/scsi_host.h>
30365cfa1eSAnton Vorontsov #include <scsi/scsi_cmnd.h>
31365cfa1eSAnton Vorontsov #include <linux/libata.h>
32d684a90dSDan Williams #include <linux/pci.h>
33365cfa1eSAnton Vorontsov #include "ahci.h"
3465fe1f0fSShane Huang #include "libata.h"
35365cfa1eSAnton Vorontsov
36365cfa1eSAnton Vorontsov static int ahci_skip_host_reset;
37365cfa1eSAnton Vorontsov int ahci_ignore_sss;
38365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_ignore_sss);
39365cfa1eSAnton Vorontsov
40365cfa1eSAnton Vorontsov module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444);
41365cfa1eSAnton Vorontsov MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)");
42365cfa1eSAnton Vorontsov
43365cfa1eSAnton Vorontsov module_param_named(ignore_sss, ahci_ignore_sss, int, 0444);
44365cfa1eSAnton Vorontsov MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)");
45365cfa1eSAnton Vorontsov
466b7ae954STejun Heo static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
476b7ae954STejun Heo unsigned hints);
48365cfa1eSAnton Vorontsov static ssize_t ahci_led_show(struct ata_port *ap, char *buf);
49365cfa1eSAnton Vorontsov static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
50365cfa1eSAnton Vorontsov size_t size);
51365cfa1eSAnton Vorontsov static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
52365cfa1eSAnton Vorontsov ssize_t size);
53365cfa1eSAnton Vorontsov
54365cfa1eSAnton Vorontsov
55365cfa1eSAnton Vorontsov
56365cfa1eSAnton Vorontsov static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
57365cfa1eSAnton Vorontsov static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
58931139afSDamien Le Moal static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
5993c4aa44SNiklas Cassel static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask);
60365cfa1eSAnton Vorontsov static int ahci_port_start(struct ata_port *ap);
61365cfa1eSAnton Vorontsov static void ahci_port_stop(struct ata_port *ap);
6295364f36SJiri Slaby static enum ata_completion_errors ahci_qc_prep(struct ata_queued_cmd *qc);
63365cfa1eSAnton Vorontsov static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc);
64365cfa1eSAnton Vorontsov static void ahci_freeze(struct ata_port *ap);
65365cfa1eSAnton Vorontsov static void ahci_thaw(struct ata_port *ap);
6665fe1f0fSShane Huang static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep);
67365cfa1eSAnton Vorontsov static void ahci_enable_fbs(struct ata_port *ap);
68365cfa1eSAnton Vorontsov static void ahci_disable_fbs(struct ata_port *ap);
69365cfa1eSAnton Vorontsov static void ahci_pmp_attach(struct ata_port *ap);
70365cfa1eSAnton Vorontsov static void ahci_pmp_detach(struct ata_port *ap);
71365cfa1eSAnton Vorontsov static int ahci_softreset(struct ata_link *link, unsigned int *class,
72365cfa1eSAnton Vorontsov unsigned long deadline);
73345347c5SYuan-Hsin Chen static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
74345347c5SYuan-Hsin Chen unsigned long deadline);
75365cfa1eSAnton Vorontsov static int ahci_hardreset(struct ata_link *link, unsigned int *class,
76365cfa1eSAnton Vorontsov unsigned long deadline);
77365cfa1eSAnton Vorontsov static void ahci_postreset(struct ata_link *link, unsigned int *class);
78365cfa1eSAnton Vorontsov static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
79365cfa1eSAnton Vorontsov static void ahci_dev_config(struct ata_device *dev);
80365cfa1eSAnton Vorontsov #ifdef CONFIG_PM
81365cfa1eSAnton Vorontsov static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg);
82365cfa1eSAnton Vorontsov #endif
83365cfa1eSAnton Vorontsov static ssize_t ahci_activity_show(struct ata_device *dev, char *buf);
84365cfa1eSAnton Vorontsov static ssize_t ahci_activity_store(struct ata_device *dev,
85365cfa1eSAnton Vorontsov enum sw_activity val);
86365cfa1eSAnton Vorontsov static void ahci_init_sw_activity(struct ata_link *link);
87365cfa1eSAnton Vorontsov
88365cfa1eSAnton Vorontsov static ssize_t ahci_show_host_caps(struct device *dev,
89365cfa1eSAnton Vorontsov struct device_attribute *attr, char *buf);
90365cfa1eSAnton Vorontsov static ssize_t ahci_show_host_cap2(struct device *dev,
91365cfa1eSAnton Vorontsov struct device_attribute *attr, char *buf);
92365cfa1eSAnton Vorontsov static ssize_t ahci_show_host_version(struct device *dev,
93365cfa1eSAnton Vorontsov struct device_attribute *attr, char *buf);
94365cfa1eSAnton Vorontsov static ssize_t ahci_show_port_cmd(struct device *dev,
95365cfa1eSAnton Vorontsov struct device_attribute *attr, char *buf);
96c0623166SHarry Zhang static ssize_t ahci_read_em_buffer(struct device *dev,
97c0623166SHarry Zhang struct device_attribute *attr, char *buf);
98c0623166SHarry Zhang static ssize_t ahci_store_em_buffer(struct device *dev,
99c0623166SHarry Zhang struct device_attribute *attr,
100c0623166SHarry Zhang const char *buf, size_t size);
1016e5fe5b1SHannes Reinecke static ssize_t ahci_show_em_supported(struct device *dev,
1026e5fe5b1SHannes Reinecke struct device_attribute *attr, char *buf);
103f070d671SSuman Tripathi static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance);
104365cfa1eSAnton Vorontsov
105365cfa1eSAnton Vorontsov static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
106365cfa1eSAnton Vorontsov static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
107365cfa1eSAnton Vorontsov static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
108365cfa1eSAnton Vorontsov static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
109c0623166SHarry Zhang static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
110c0623166SHarry Zhang ahci_read_em_buffer, ahci_store_em_buffer);
1116e5fe5b1SHannes Reinecke static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);
112365cfa1eSAnton Vorontsov
113c3f69c7fSBart Van Assche static struct attribute *ahci_shost_attrs[] = {
114c3f69c7fSBart Van Assche &dev_attr_link_power_management_policy.attr,
115c3f69c7fSBart Van Assche &dev_attr_em_message_type.attr,
116c3f69c7fSBart Van Assche &dev_attr_em_message.attr,
117c3f69c7fSBart Van Assche &dev_attr_ahci_host_caps.attr,
118c3f69c7fSBart Van Assche &dev_attr_ahci_host_cap2.attr,
119c3f69c7fSBart Van Assche &dev_attr_ahci_host_version.attr,
120c3f69c7fSBart Van Assche &dev_attr_ahci_port_cmd.attr,
121c3f69c7fSBart Van Assche &dev_attr_em_buffer.attr,
122c3f69c7fSBart Van Assche &dev_attr_em_message_supported.attr,
123365cfa1eSAnton Vorontsov NULL
124365cfa1eSAnton Vorontsov };
125365cfa1eSAnton Vorontsov
126c3f69c7fSBart Van Assche static const struct attribute_group ahci_shost_attr_group = {
127c3f69c7fSBart Van Assche .attrs = ahci_shost_attrs
128c3f69c7fSBart Van Assche };
129c3f69c7fSBart Van Assche
130c3f69c7fSBart Van Assche const struct attribute_group *ahci_shost_groups[] = {
131c3f69c7fSBart Van Assche &ahci_shost_attr_group,
132365cfa1eSAnton Vorontsov NULL
133365cfa1eSAnton Vorontsov };
134c3f69c7fSBart Van Assche EXPORT_SYMBOL_GPL(ahci_shost_groups);
135c3f69c7fSBart Van Assche
1361b87bda1SDamien Le Moal static struct attribute *ahci_sdev_attrs[] = {
137c3f69c7fSBart Van Assche &dev_attr_sw_activity.attr,
138c3f69c7fSBart Van Assche &dev_attr_unload_heads.attr,
139c3f69c7fSBart Van Assche &dev_attr_ncq_prio_supported.attr,
140c3f69c7fSBart Van Assche &dev_attr_ncq_prio_enable.attr,
141c3f69c7fSBart Van Assche NULL
142c3f69c7fSBart Van Assche };
143c3f69c7fSBart Van Assche
144c3f69c7fSBart Van Assche static const struct attribute_group ahci_sdev_attr_group = {
145c3f69c7fSBart Van Assche .attrs = ahci_sdev_attrs
146c3f69c7fSBart Van Assche };
147c3f69c7fSBart Van Assche
148c3f69c7fSBart Van Assche const struct attribute_group *ahci_sdev_groups[] = {
149c3f69c7fSBart Van Assche &ahci_sdev_attr_group,
150c3f69c7fSBart Van Assche NULL
151c3f69c7fSBart Van Assche };
152c3f69c7fSBart Van Assche EXPORT_SYMBOL_GPL(ahci_sdev_groups);
153365cfa1eSAnton Vorontsov
154365cfa1eSAnton Vorontsov struct ata_port_operations ahci_ops = {
155365cfa1eSAnton Vorontsov .inherits = &sata_pmp_port_ops,
156365cfa1eSAnton Vorontsov
157365cfa1eSAnton Vorontsov .qc_defer = ahci_pmp_qc_defer,
158365cfa1eSAnton Vorontsov .qc_prep = ahci_qc_prep,
159365cfa1eSAnton Vorontsov .qc_issue = ahci_qc_issue,
160365cfa1eSAnton Vorontsov .qc_fill_rtf = ahci_qc_fill_rtf,
16193c4aa44SNiklas Cassel .qc_ncq_fill_rtf = ahci_qc_ncq_fill_rtf,
162365cfa1eSAnton Vorontsov
163365cfa1eSAnton Vorontsov .freeze = ahci_freeze,
164365cfa1eSAnton Vorontsov .thaw = ahci_thaw,
165365cfa1eSAnton Vorontsov .softreset = ahci_softreset,
166365cfa1eSAnton Vorontsov .hardreset = ahci_hardreset,
167365cfa1eSAnton Vorontsov .postreset = ahci_postreset,
168365cfa1eSAnton Vorontsov .pmp_softreset = ahci_softreset,
169365cfa1eSAnton Vorontsov .error_handler = ahci_error_handler,
170365cfa1eSAnton Vorontsov .post_internal_cmd = ahci_post_internal_cmd,
171365cfa1eSAnton Vorontsov .dev_config = ahci_dev_config,
172365cfa1eSAnton Vorontsov
173365cfa1eSAnton Vorontsov .scr_read = ahci_scr_read,
174365cfa1eSAnton Vorontsov .scr_write = ahci_scr_write,
175365cfa1eSAnton Vorontsov .pmp_attach = ahci_pmp_attach,
176365cfa1eSAnton Vorontsov .pmp_detach = ahci_pmp_detach,
177365cfa1eSAnton Vorontsov
1786b7ae954STejun Heo .set_lpm = ahci_set_lpm,
179365cfa1eSAnton Vorontsov .em_show = ahci_led_show,
180365cfa1eSAnton Vorontsov .em_store = ahci_led_store,
181365cfa1eSAnton Vorontsov .sw_activity_show = ahci_activity_show,
182365cfa1eSAnton Vorontsov .sw_activity_store = ahci_activity_store,
183439d7a35SMark Langsdorf .transmit_led_message = ahci_transmit_led_message,
184365cfa1eSAnton Vorontsov #ifdef CONFIG_PM
185365cfa1eSAnton Vorontsov .port_suspend = ahci_port_suspend,
186365cfa1eSAnton Vorontsov .port_resume = ahci_port_resume,
187365cfa1eSAnton Vorontsov #endif
188365cfa1eSAnton Vorontsov .port_start = ahci_port_start,
189365cfa1eSAnton Vorontsov .port_stop = ahci_port_stop,
190365cfa1eSAnton Vorontsov };
191365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_ops);
192365cfa1eSAnton Vorontsov
193345347c5SYuan-Hsin Chen struct ata_port_operations ahci_pmp_retry_srst_ops = {
194345347c5SYuan-Hsin Chen .inherits = &ahci_ops,
195345347c5SYuan-Hsin Chen .softreset = ahci_pmp_retry_softreset,
196345347c5SYuan-Hsin Chen };
197345347c5SYuan-Hsin Chen EXPORT_SYMBOL_GPL(ahci_pmp_retry_srst_ops);
198345347c5SYuan-Hsin Chen
199ed08d40cSChuansheng Liu static bool ahci_em_messages __read_mostly = true;
200ed08d40cSChuansheng Liu module_param(ahci_em_messages, bool, 0444);
201365cfa1eSAnton Vorontsov /* add other LED protocol types when they become supported */
202365cfa1eSAnton Vorontsov MODULE_PARM_DESC(ahci_em_messages,
203008dbd61SHarry Zhang "AHCI Enclosure Management Message control (0 = off, 1 = on)");
204365cfa1eSAnton Vorontsov
205ed08d40cSChuansheng Liu /* device sleep idle timeout in ms */
206ed08d40cSChuansheng Liu static int devslp_idle_timeout __read_mostly = 1000;
20765fe1f0fSShane Huang module_param(devslp_idle_timeout, int, 0644);
20865fe1f0fSShane Huang MODULE_PARM_DESC(devslp_idle_timeout, "device sleep idle timeout");
20965fe1f0fSShane Huang
ahci_enable_ahci(void __iomem * mmio)210365cfa1eSAnton Vorontsov static void ahci_enable_ahci(void __iomem *mmio)
211365cfa1eSAnton Vorontsov {
212365cfa1eSAnton Vorontsov int i;
213365cfa1eSAnton Vorontsov u32 tmp;
214365cfa1eSAnton Vorontsov
215365cfa1eSAnton Vorontsov /* turn on AHCI_EN */
216365cfa1eSAnton Vorontsov tmp = readl(mmio + HOST_CTL);
217365cfa1eSAnton Vorontsov if (tmp & HOST_AHCI_EN)
218365cfa1eSAnton Vorontsov return;
219365cfa1eSAnton Vorontsov
220365cfa1eSAnton Vorontsov /* Some controllers need AHCI_EN to be written multiple times.
221365cfa1eSAnton Vorontsov * Try a few times before giving up.
222365cfa1eSAnton Vorontsov */
223365cfa1eSAnton Vorontsov for (i = 0; i < 5; i++) {
224365cfa1eSAnton Vorontsov tmp |= HOST_AHCI_EN;
225365cfa1eSAnton Vorontsov writel(tmp, mmio + HOST_CTL);
226365cfa1eSAnton Vorontsov tmp = readl(mmio + HOST_CTL); /* flush && sanity check */
227365cfa1eSAnton Vorontsov if (tmp & HOST_AHCI_EN)
228365cfa1eSAnton Vorontsov return;
229365cfa1eSAnton Vorontsov msleep(10);
230365cfa1eSAnton Vorontsov }
231365cfa1eSAnton Vorontsov
232365cfa1eSAnton Vorontsov WARN_ON(1);
233365cfa1eSAnton Vorontsov }
234365cfa1eSAnton Vorontsov
235bb03c640SMika Westerberg /**
236bb03c640SMika Westerberg * ahci_rpm_get_port - Make sure the port is powered on
237bb03c640SMika Westerberg * @ap: Port to power on
238bb03c640SMika Westerberg *
239bb03c640SMika Westerberg * Whenever there is need to access the AHCI host registers outside of
240bb03c640SMika Westerberg * normal execution paths, call this function to make sure the host is
241bb03c640SMika Westerberg * actually powered on.
242bb03c640SMika Westerberg */
ahci_rpm_get_port(struct ata_port * ap)243bb03c640SMika Westerberg static int ahci_rpm_get_port(struct ata_port *ap)
244bb03c640SMika Westerberg {
245bb03c640SMika Westerberg return pm_runtime_get_sync(ap->dev);
246bb03c640SMika Westerberg }
247bb03c640SMika Westerberg
248bb03c640SMika Westerberg /**
249bb03c640SMika Westerberg * ahci_rpm_put_port - Undoes ahci_rpm_get_port()
250bb03c640SMika Westerberg * @ap: Port to power down
251bb03c640SMika Westerberg *
252bb03c640SMika Westerberg * Undoes ahci_rpm_get_port() and possibly powers down the AHCI host
253bb03c640SMika Westerberg * if it has no more active users.
254bb03c640SMika Westerberg */
ahci_rpm_put_port(struct ata_port * ap)255bb03c640SMika Westerberg static void ahci_rpm_put_port(struct ata_port *ap)
256bb03c640SMika Westerberg {
257bb03c640SMika Westerberg pm_runtime_put(ap->dev);
258bb03c640SMika Westerberg }
259bb03c640SMika Westerberg
ahci_show_host_caps(struct device * dev,struct device_attribute * attr,char * buf)260365cfa1eSAnton Vorontsov static ssize_t ahci_show_host_caps(struct device *dev,
261365cfa1eSAnton Vorontsov struct device_attribute *attr, char *buf)
262365cfa1eSAnton Vorontsov {
263365cfa1eSAnton Vorontsov struct Scsi_Host *shost = class_to_shost(dev);
264365cfa1eSAnton Vorontsov struct ata_port *ap = ata_shost_to_port(shost);
265365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
266365cfa1eSAnton Vorontsov
267365cfa1eSAnton Vorontsov return sprintf(buf, "%x\n", hpriv->cap);
268365cfa1eSAnton Vorontsov }
269365cfa1eSAnton Vorontsov
ahci_show_host_cap2(struct device * dev,struct device_attribute * attr,char * buf)270365cfa1eSAnton Vorontsov static ssize_t ahci_show_host_cap2(struct device *dev,
271365cfa1eSAnton Vorontsov struct device_attribute *attr, char *buf)
272365cfa1eSAnton Vorontsov {
273365cfa1eSAnton Vorontsov struct Scsi_Host *shost = class_to_shost(dev);
274365cfa1eSAnton Vorontsov struct ata_port *ap = ata_shost_to_port(shost);
275365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
276365cfa1eSAnton Vorontsov
277365cfa1eSAnton Vorontsov return sprintf(buf, "%x\n", hpriv->cap2);
278365cfa1eSAnton Vorontsov }
279365cfa1eSAnton Vorontsov
ahci_show_host_version(struct device * dev,struct device_attribute * attr,char * buf)280365cfa1eSAnton Vorontsov static ssize_t ahci_show_host_version(struct device *dev,
281365cfa1eSAnton Vorontsov struct device_attribute *attr, char *buf)
282365cfa1eSAnton Vorontsov {
283365cfa1eSAnton Vorontsov struct Scsi_Host *shost = class_to_shost(dev);
284365cfa1eSAnton Vorontsov struct ata_port *ap = ata_shost_to_port(shost);
285365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
286365cfa1eSAnton Vorontsov
2878ea909cbSMika Westerberg return sprintf(buf, "%x\n", hpriv->version);
288365cfa1eSAnton Vorontsov }
289365cfa1eSAnton Vorontsov
ahci_show_port_cmd(struct device * dev,struct device_attribute * attr,char * buf)290365cfa1eSAnton Vorontsov static ssize_t ahci_show_port_cmd(struct device *dev,
291365cfa1eSAnton Vorontsov struct device_attribute *attr, char *buf)
292365cfa1eSAnton Vorontsov {
293365cfa1eSAnton Vorontsov struct Scsi_Host *shost = class_to_shost(dev);
294365cfa1eSAnton Vorontsov struct ata_port *ap = ata_shost_to_port(shost);
295365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
296bb03c640SMika Westerberg ssize_t ret;
297365cfa1eSAnton Vorontsov
298bb03c640SMika Westerberg ahci_rpm_get_port(ap);
299bb03c640SMika Westerberg ret = sprintf(buf, "%x\n", readl(port_mmio + PORT_CMD));
300bb03c640SMika Westerberg ahci_rpm_put_port(ap);
301bb03c640SMika Westerberg
302bb03c640SMika Westerberg return ret;
303365cfa1eSAnton Vorontsov }
304365cfa1eSAnton Vorontsov
ahci_read_em_buffer(struct device * dev,struct device_attribute * attr,char * buf)305c0623166SHarry Zhang static ssize_t ahci_read_em_buffer(struct device *dev,
306c0623166SHarry Zhang struct device_attribute *attr, char *buf)
307c0623166SHarry Zhang {
308c0623166SHarry Zhang struct Scsi_Host *shost = class_to_shost(dev);
309c0623166SHarry Zhang struct ata_port *ap = ata_shost_to_port(shost);
310c0623166SHarry Zhang struct ahci_host_priv *hpriv = ap->host->private_data;
311c0623166SHarry Zhang void __iomem *mmio = hpriv->mmio;
312c0623166SHarry Zhang void __iomem *em_mmio = mmio + hpriv->em_loc;
313c0623166SHarry Zhang u32 em_ctl, msg;
314c0623166SHarry Zhang unsigned long flags;
315c0623166SHarry Zhang size_t count;
316c0623166SHarry Zhang int i;
317c0623166SHarry Zhang
318bb03c640SMika Westerberg ahci_rpm_get_port(ap);
319c0623166SHarry Zhang spin_lock_irqsave(ap->lock, flags);
320c0623166SHarry Zhang
321c0623166SHarry Zhang em_ctl = readl(mmio + HOST_EM_CTL);
322c0623166SHarry Zhang if (!(ap->flags & ATA_FLAG_EM) || em_ctl & EM_CTL_XMT ||
323c0623166SHarry Zhang !(hpriv->em_msg_type & EM_MSG_TYPE_SGPIO)) {
324c0623166SHarry Zhang spin_unlock_irqrestore(ap->lock, flags);
325bb03c640SMika Westerberg ahci_rpm_put_port(ap);
326c0623166SHarry Zhang return -EINVAL;
327c0623166SHarry Zhang }
328c0623166SHarry Zhang
329c0623166SHarry Zhang if (!(em_ctl & EM_CTL_MR)) {
330c0623166SHarry Zhang spin_unlock_irqrestore(ap->lock, flags);
331bb03c640SMika Westerberg ahci_rpm_put_port(ap);
332c0623166SHarry Zhang return -EAGAIN;
333c0623166SHarry Zhang }
334c0623166SHarry Zhang
335c0623166SHarry Zhang if (!(em_ctl & EM_CTL_SMB))
336c0623166SHarry Zhang em_mmio += hpriv->em_buf_sz;
337c0623166SHarry Zhang
338c0623166SHarry Zhang count = hpriv->em_buf_sz;
339c0623166SHarry Zhang
340c0623166SHarry Zhang /* the count should not be larger than PAGE_SIZE */
341c0623166SHarry Zhang if (count > PAGE_SIZE) {
342c0623166SHarry Zhang if (printk_ratelimit())
343a9a79dfeSJoe Perches ata_port_warn(ap,
344c0623166SHarry Zhang "EM read buffer size too large: "
345c0623166SHarry Zhang "buffer size %u, page size %lu\n",
346c0623166SHarry Zhang hpriv->em_buf_sz, PAGE_SIZE);
347c0623166SHarry Zhang count = PAGE_SIZE;
348c0623166SHarry Zhang }
349c0623166SHarry Zhang
350c0623166SHarry Zhang for (i = 0; i < count; i += 4) {
351c0623166SHarry Zhang msg = readl(em_mmio + i);
352c0623166SHarry Zhang buf[i] = msg & 0xff;
353c0623166SHarry Zhang buf[i + 1] = (msg >> 8) & 0xff;
354c0623166SHarry Zhang buf[i + 2] = (msg >> 16) & 0xff;
355c0623166SHarry Zhang buf[i + 3] = (msg >> 24) & 0xff;
356c0623166SHarry Zhang }
357c0623166SHarry Zhang
358c0623166SHarry Zhang spin_unlock_irqrestore(ap->lock, flags);
359bb03c640SMika Westerberg ahci_rpm_put_port(ap);
360c0623166SHarry Zhang
361c0623166SHarry Zhang return i;
362c0623166SHarry Zhang }
363c0623166SHarry Zhang
ahci_store_em_buffer(struct device * dev,struct device_attribute * attr,const char * buf,size_t size)364c0623166SHarry Zhang static ssize_t ahci_store_em_buffer(struct device *dev,
365c0623166SHarry Zhang struct device_attribute *attr,
366c0623166SHarry Zhang const char *buf, size_t size)
367c0623166SHarry Zhang {
368c0623166SHarry Zhang struct Scsi_Host *shost = class_to_shost(dev);
369c0623166SHarry Zhang struct ata_port *ap = ata_shost_to_port(shost);
370c0623166SHarry Zhang struct ahci_host_priv *hpriv = ap->host->private_data;
371c0623166SHarry Zhang void __iomem *mmio = hpriv->mmio;
372c0623166SHarry Zhang void __iomem *em_mmio = mmio + hpriv->em_loc;
373f9ce889bSHarry Zhang const unsigned char *msg_buf = buf;
374c0623166SHarry Zhang u32 em_ctl, msg;
375c0623166SHarry Zhang unsigned long flags;
376c0623166SHarry Zhang int i;
377c0623166SHarry Zhang
378c0623166SHarry Zhang /* check size validity */
379c0623166SHarry Zhang if (!(ap->flags & ATA_FLAG_EM) ||
380c0623166SHarry Zhang !(hpriv->em_msg_type & EM_MSG_TYPE_SGPIO) ||
381c0623166SHarry Zhang size % 4 || size > hpriv->em_buf_sz)
382c0623166SHarry Zhang return -EINVAL;
383c0623166SHarry Zhang
384bb03c640SMika Westerberg ahci_rpm_get_port(ap);
385c0623166SHarry Zhang spin_lock_irqsave(ap->lock, flags);
386c0623166SHarry Zhang
387c0623166SHarry Zhang em_ctl = readl(mmio + HOST_EM_CTL);
388c0623166SHarry Zhang if (em_ctl & EM_CTL_TM) {
389c0623166SHarry Zhang spin_unlock_irqrestore(ap->lock, flags);
390bb03c640SMika Westerberg ahci_rpm_put_port(ap);
391c0623166SHarry Zhang return -EBUSY;
392c0623166SHarry Zhang }
393c0623166SHarry Zhang
394c0623166SHarry Zhang for (i = 0; i < size; i += 4) {
395f9ce889bSHarry Zhang msg = msg_buf[i] | msg_buf[i + 1] << 8 |
396f9ce889bSHarry Zhang msg_buf[i + 2] << 16 | msg_buf[i + 3] << 24;
397c0623166SHarry Zhang writel(msg, em_mmio + i);
398c0623166SHarry Zhang }
399c0623166SHarry Zhang
400c0623166SHarry Zhang writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
401c0623166SHarry Zhang
402c0623166SHarry Zhang spin_unlock_irqrestore(ap->lock, flags);
403bb03c640SMika Westerberg ahci_rpm_put_port(ap);
404c0623166SHarry Zhang
405c0623166SHarry Zhang return size;
406c0623166SHarry Zhang }
407c0623166SHarry Zhang
ahci_show_em_supported(struct device * dev,struct device_attribute * attr,char * buf)4086e5fe5b1SHannes Reinecke static ssize_t ahci_show_em_supported(struct device *dev,
4096e5fe5b1SHannes Reinecke struct device_attribute *attr, char *buf)
4106e5fe5b1SHannes Reinecke {
4116e5fe5b1SHannes Reinecke struct Scsi_Host *shost = class_to_shost(dev);
4126e5fe5b1SHannes Reinecke struct ata_port *ap = ata_shost_to_port(shost);
4136e5fe5b1SHannes Reinecke struct ahci_host_priv *hpriv = ap->host->private_data;
4146e5fe5b1SHannes Reinecke void __iomem *mmio = hpriv->mmio;
4156e5fe5b1SHannes Reinecke u32 em_ctl;
4166e5fe5b1SHannes Reinecke
417bb03c640SMika Westerberg ahci_rpm_get_port(ap);
4186e5fe5b1SHannes Reinecke em_ctl = readl(mmio + HOST_EM_CTL);
419bb03c640SMika Westerberg ahci_rpm_put_port(ap);
4206e5fe5b1SHannes Reinecke
4216e5fe5b1SHannes Reinecke return sprintf(buf, "%s%s%s%s\n",
4226e5fe5b1SHannes Reinecke em_ctl & EM_CTL_LED ? "led " : "",
4236e5fe5b1SHannes Reinecke em_ctl & EM_CTL_SAFTE ? "saf-te " : "",
4246e5fe5b1SHannes Reinecke em_ctl & EM_CTL_SES ? "ses-2 " : "",
4256e5fe5b1SHannes Reinecke em_ctl & EM_CTL_SGPIO ? "sgpio " : "");
4266e5fe5b1SHannes Reinecke }
4276e5fe5b1SHannes Reinecke
428365cfa1eSAnton Vorontsov /**
429365cfa1eSAnton Vorontsov * ahci_save_initial_config - Save and fixup initial config values
430365cfa1eSAnton Vorontsov * @dev: target AHCI device
431365cfa1eSAnton Vorontsov * @hpriv: host private area to store config values
432365cfa1eSAnton Vorontsov *
433365cfa1eSAnton Vorontsov * Some registers containing configuration info might be setup by
434365cfa1eSAnton Vorontsov * BIOS and might be cleared on reset. This function saves the
435365cfa1eSAnton Vorontsov * initial values of those registers into @hpriv such that they
436365cfa1eSAnton Vorontsov * can be restored after controller reset.
437365cfa1eSAnton Vorontsov *
438365cfa1eSAnton Vorontsov * If inconsistent, config values are fixed up by this function.
439365cfa1eSAnton Vorontsov *
440039ece38SHans de Goede * If it is not set already this function sets hpriv->start_engine to
441039ece38SHans de Goede * ahci_start_engine.
442039ece38SHans de Goede *
443365cfa1eSAnton Vorontsov * LOCKING:
444365cfa1eSAnton Vorontsov * None.
445365cfa1eSAnton Vorontsov */
ahci_save_initial_config(struct device * dev,struct ahci_host_priv * hpriv)446725c7b57SAntoine Ténart void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
447365cfa1eSAnton Vorontsov {
448365cfa1eSAnton Vorontsov void __iomem *mmio = hpriv->mmio;
44918ee7c49SSerge Semin void __iomem *port_mmio;
45018ee7c49SSerge Semin unsigned long port_map;
45118ee7c49SSerge Semin u32 cap, cap2, vers;
452365cfa1eSAnton Vorontsov int i;
453365cfa1eSAnton Vorontsov
454365cfa1eSAnton Vorontsov /* make sure AHCI mode is enabled before accessing CAP */
455365cfa1eSAnton Vorontsov ahci_enable_ahci(mmio);
456365cfa1eSAnton Vorontsov
45718ee7c49SSerge Semin /*
45818ee7c49SSerge Semin * Values prefixed with saved_ are written back to the HBA and ports
45918ee7c49SSerge Semin * registers after reset. Values without are used for driver operation.
460365cfa1eSAnton Vorontsov */
46118ee7c49SSerge Semin
46218ee7c49SSerge Semin /*
46318ee7c49SSerge Semin * Override HW-init HBA capability fields with the platform-specific
46418ee7c49SSerge Semin * values. The rest of the HBA capabilities are defined as Read-only
46518ee7c49SSerge Semin * and can't be modified in CSR anyway.
46618ee7c49SSerge Semin */
46718ee7c49SSerge Semin cap = readl(mmio + HOST_CAP);
46818ee7c49SSerge Semin if (hpriv->saved_cap)
46918ee7c49SSerge Semin cap = (cap & ~(HOST_CAP_SSS | HOST_CAP_MPS)) | hpriv->saved_cap;
47018ee7c49SSerge Semin hpriv->saved_cap = cap;
471365cfa1eSAnton Vorontsov
472365cfa1eSAnton Vorontsov /* CAP2 register is only defined for AHCI 1.2 and later */
473365cfa1eSAnton Vorontsov vers = readl(mmio + HOST_VERSION);
474365cfa1eSAnton Vorontsov if ((vers >> 16) > 1 ||
475365cfa1eSAnton Vorontsov ((vers >> 16) == 1 && (vers & 0xFFFF) >= 0x200))
476365cfa1eSAnton Vorontsov hpriv->saved_cap2 = cap2 = readl(mmio + HOST_CAP2);
477365cfa1eSAnton Vorontsov else
478365cfa1eSAnton Vorontsov hpriv->saved_cap2 = cap2 = 0;
479365cfa1eSAnton Vorontsov
480365cfa1eSAnton Vorontsov /* some chips have errata preventing 64bit use */
481365cfa1eSAnton Vorontsov if ((cap & HOST_CAP_64) && (hpriv->flags & AHCI_HFLAG_32BIT_ONLY)) {
482a44fec1fSJoe Perches dev_info(dev, "controller can't do 64bit DMA, forcing 32bit\n");
483365cfa1eSAnton Vorontsov cap &= ~HOST_CAP_64;
484365cfa1eSAnton Vorontsov }
485365cfa1eSAnton Vorontsov
486365cfa1eSAnton Vorontsov if ((cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_NO_NCQ)) {
487a44fec1fSJoe Perches dev_info(dev, "controller can't do NCQ, turning off CAP_NCQ\n");
488365cfa1eSAnton Vorontsov cap &= ~HOST_CAP_NCQ;
489365cfa1eSAnton Vorontsov }
490365cfa1eSAnton Vorontsov
491365cfa1eSAnton Vorontsov if (!(cap & HOST_CAP_NCQ) && (hpriv->flags & AHCI_HFLAG_YES_NCQ)) {
492a44fec1fSJoe Perches dev_info(dev, "controller can do NCQ, turning on CAP_NCQ\n");
493365cfa1eSAnton Vorontsov cap |= HOST_CAP_NCQ;
494365cfa1eSAnton Vorontsov }
495365cfa1eSAnton Vorontsov
496365cfa1eSAnton Vorontsov if ((cap & HOST_CAP_PMP) && (hpriv->flags & AHCI_HFLAG_NO_PMP)) {
497a44fec1fSJoe Perches dev_info(dev, "controller can't do PMP, turning off CAP_PMP\n");
498365cfa1eSAnton Vorontsov cap &= ~HOST_CAP_PMP;
499365cfa1eSAnton Vorontsov }
500365cfa1eSAnton Vorontsov
501365cfa1eSAnton Vorontsov if ((cap & HOST_CAP_SNTF) && (hpriv->flags & AHCI_HFLAG_NO_SNTF)) {
502a44fec1fSJoe Perches dev_info(dev,
503365cfa1eSAnton Vorontsov "controller can't do SNTF, turning off CAP_SNTF\n");
504365cfa1eSAnton Vorontsov cap &= ~HOST_CAP_SNTF;
505365cfa1eSAnton Vorontsov }
506365cfa1eSAnton Vorontsov
5070cf4a7d6SJacob Pan if ((cap2 & HOST_CAP2_SDS) && (hpriv->flags & AHCI_HFLAG_NO_DEVSLP)) {
5080cf4a7d6SJacob Pan dev_info(dev,
5090cf4a7d6SJacob Pan "controller can't do DEVSLP, turning off\n");
5100cf4a7d6SJacob Pan cap2 &= ~HOST_CAP2_SDS;
5110cf4a7d6SJacob Pan cap2 &= ~HOST_CAP2_SADM;
5120cf4a7d6SJacob Pan }
5130cf4a7d6SJacob Pan
5145f173107STejun Heo if (!(cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_YES_FBS)) {
515a44fec1fSJoe Perches dev_info(dev, "controller can do FBS, turning on CAP_FBS\n");
5165f173107STejun Heo cap |= HOST_CAP_FBS;
5175f173107STejun Heo }
5185f173107STejun Heo
519888d91a0SKefeng Wang if ((cap & HOST_CAP_FBS) && (hpriv->flags & AHCI_HFLAG_NO_FBS)) {
520888d91a0SKefeng Wang dev_info(dev, "controller can't do FBS, turning off CAP_FBS\n");
521888d91a0SKefeng Wang cap &= ~HOST_CAP_FBS;
522888d91a0SKefeng Wang }
523888d91a0SKefeng Wang
524ef0da1bfSDoug Berger if (!(cap & HOST_CAP_ALPM) && (hpriv->flags & AHCI_HFLAG_YES_ALPM)) {
525ef0da1bfSDoug Berger dev_info(dev, "controller can do ALPM, turning on CAP_ALPM\n");
526ef0da1bfSDoug Berger cap |= HOST_CAP_ALPM;
527ef0da1bfSDoug Berger }
528ef0da1bfSDoug Berger
529234e6d2cSXingui Yang if ((cap & HOST_CAP_SXS) && (hpriv->flags & AHCI_HFLAG_NO_SXS)) {
530234e6d2cSXingui Yang dev_info(dev, "controller does not support SXS, disabling CAP_SXS\n");
531234e6d2cSXingui Yang cap &= ~HOST_CAP_SXS;
532234e6d2cSXingui Yang }
533234e6d2cSXingui Yang
53488589772SSerge Semin /* Override the HBA ports mapping if the platform needs it */
53588589772SSerge Semin port_map = readl(mmio + HOST_PORTS_IMPL);
53688589772SSerge Semin if (hpriv->saved_port_map && port_map != hpriv->saved_port_map) {
53718ee7c49SSerge Semin dev_info(dev, "forcing port_map 0x%lx -> 0x%x\n",
53888589772SSerge Semin port_map, hpriv->saved_port_map);
53988589772SSerge Semin port_map = hpriv->saved_port_map;
54088589772SSerge Semin } else {
5412fd0f46cSSrinivas Kandagatla hpriv->saved_port_map = port_map;
542365cfa1eSAnton Vorontsov }
543365cfa1eSAnton Vorontsov
544725c7b57SAntoine Ténart if (hpriv->mask_port_map) {
54518ee7c49SSerge Semin dev_warn(dev, "masking port_map 0x%lx -> 0x%lx\n",
546365cfa1eSAnton Vorontsov port_map,
547725c7b57SAntoine Ténart port_map & hpriv->mask_port_map);
548725c7b57SAntoine Ténart port_map &= hpriv->mask_port_map;
549365cfa1eSAnton Vorontsov }
550365cfa1eSAnton Vorontsov
551365cfa1eSAnton Vorontsov /* cross check port_map and cap.n_ports */
552365cfa1eSAnton Vorontsov if (port_map) {
553365cfa1eSAnton Vorontsov int map_ports = 0;
554365cfa1eSAnton Vorontsov
555365cfa1eSAnton Vorontsov for (i = 0; i < AHCI_MAX_PORTS; i++)
556365cfa1eSAnton Vorontsov if (port_map & (1 << i))
557365cfa1eSAnton Vorontsov map_ports++;
558365cfa1eSAnton Vorontsov
559365cfa1eSAnton Vorontsov /* If PI has more ports than n_ports, whine, clear
560365cfa1eSAnton Vorontsov * port_map and let it be generated from n_ports.
561365cfa1eSAnton Vorontsov */
562365cfa1eSAnton Vorontsov if (map_ports > ahci_nr_ports(cap)) {
563a44fec1fSJoe Perches dev_warn(dev,
56418ee7c49SSerge Semin "implemented port map (0x%lx) contains more ports than nr_ports (%u), using nr_ports\n",
565365cfa1eSAnton Vorontsov port_map, ahci_nr_ports(cap));
566365cfa1eSAnton Vorontsov port_map = 0;
567365cfa1eSAnton Vorontsov }
568365cfa1eSAnton Vorontsov }
569365cfa1eSAnton Vorontsov
570566d1827STejun Heo /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
571566d1827STejun Heo if (!port_map && vers < 0x10300) {
572365cfa1eSAnton Vorontsov port_map = (1 << ahci_nr_ports(cap)) - 1;
57318ee7c49SSerge Semin dev_warn(dev, "forcing PORTS_IMPL to 0x%lx\n", port_map);
574365cfa1eSAnton Vorontsov
575365cfa1eSAnton Vorontsov /* write the fixed up value to the PI register */
576365cfa1eSAnton Vorontsov hpriv->saved_port_map = port_map;
577365cfa1eSAnton Vorontsov }
578365cfa1eSAnton Vorontsov
57918ee7c49SSerge Semin /*
58018ee7c49SSerge Semin * Preserve the ports capabilities defined by the platform. Note there
58118ee7c49SSerge Semin * is no need in storing the rest of the P#.CMD fields since they are
58218ee7c49SSerge Semin * volatile.
58318ee7c49SSerge Semin */
58418ee7c49SSerge Semin for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
58518ee7c49SSerge Semin if (hpriv->saved_port_cap[i])
58618ee7c49SSerge Semin continue;
58718ee7c49SSerge Semin
58818ee7c49SSerge Semin port_mmio = __ahci_port_base(hpriv, i);
58918ee7c49SSerge Semin hpriv->saved_port_cap[i] =
59018ee7c49SSerge Semin readl(port_mmio + PORT_CMD) & PORT_CMD_CAP;
59118ee7c49SSerge Semin }
59218ee7c49SSerge Semin
593365cfa1eSAnton Vorontsov /* record values to use during operation */
594365cfa1eSAnton Vorontsov hpriv->cap = cap;
595365cfa1eSAnton Vorontsov hpriv->cap2 = cap2;
596fad64dc0SSerge Semin hpriv->version = vers;
597365cfa1eSAnton Vorontsov hpriv->port_map = port_map;
598039ece38SHans de Goede
599039ece38SHans de Goede if (!hpriv->start_engine)
600039ece38SHans de Goede hpriv->start_engine = ahci_start_engine;
601f070d671SSuman Tripathi
602fa89f53bSEvan Wang if (!hpriv->stop_engine)
603fa89f53bSEvan Wang hpriv->stop_engine = ahci_stop_engine;
604fa89f53bSEvan Wang
605f070d671SSuman Tripathi if (!hpriv->irq_handler)
606d867b95fSSuman Tripathi hpriv->irq_handler = ahci_single_level_irq_intr;
607365cfa1eSAnton Vorontsov }
608365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_save_initial_config);
609365cfa1eSAnton Vorontsov
610365cfa1eSAnton Vorontsov /**
611365cfa1eSAnton Vorontsov * ahci_restore_initial_config - Restore initial config
612365cfa1eSAnton Vorontsov * @host: target ATA host
613365cfa1eSAnton Vorontsov *
614365cfa1eSAnton Vorontsov * Restore initial config stored by ahci_save_initial_config().
615365cfa1eSAnton Vorontsov *
616365cfa1eSAnton Vorontsov * LOCKING:
617365cfa1eSAnton Vorontsov * None.
618365cfa1eSAnton Vorontsov */
ahci_restore_initial_config(struct ata_host * host)619365cfa1eSAnton Vorontsov static void ahci_restore_initial_config(struct ata_host *host)
620365cfa1eSAnton Vorontsov {
621365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data;
62218ee7c49SSerge Semin unsigned long port_map = hpriv->port_map;
623365cfa1eSAnton Vorontsov void __iomem *mmio = hpriv->mmio;
62418ee7c49SSerge Semin void __iomem *port_mmio;
62518ee7c49SSerge Semin int i;
626365cfa1eSAnton Vorontsov
627365cfa1eSAnton Vorontsov writel(hpriv->saved_cap, mmio + HOST_CAP);
628365cfa1eSAnton Vorontsov if (hpriv->saved_cap2)
629365cfa1eSAnton Vorontsov writel(hpriv->saved_cap2, mmio + HOST_CAP2);
630365cfa1eSAnton Vorontsov writel(hpriv->saved_port_map, mmio + HOST_PORTS_IMPL);
631365cfa1eSAnton Vorontsov (void) readl(mmio + HOST_PORTS_IMPL); /* flush */
63218ee7c49SSerge Semin
63318ee7c49SSerge Semin for_each_set_bit(i, &port_map, AHCI_MAX_PORTS) {
63418ee7c49SSerge Semin port_mmio = __ahci_port_base(hpriv, i);
63518ee7c49SSerge Semin writel(hpriv->saved_port_cap[i], port_mmio + PORT_CMD);
63618ee7c49SSerge Semin }
637365cfa1eSAnton Vorontsov }
638365cfa1eSAnton Vorontsov
ahci_scr_offset(struct ata_port * ap,unsigned int sc_reg)639365cfa1eSAnton Vorontsov static unsigned ahci_scr_offset(struct ata_port *ap, unsigned int sc_reg)
640365cfa1eSAnton Vorontsov {
641365cfa1eSAnton Vorontsov static const int offset[] = {
642365cfa1eSAnton Vorontsov [SCR_STATUS] = PORT_SCR_STAT,
643365cfa1eSAnton Vorontsov [SCR_CONTROL] = PORT_SCR_CTL,
644365cfa1eSAnton Vorontsov [SCR_ERROR] = PORT_SCR_ERR,
645365cfa1eSAnton Vorontsov [SCR_ACTIVE] = PORT_SCR_ACT,
646365cfa1eSAnton Vorontsov [SCR_NOTIFICATION] = PORT_SCR_NTF,
647365cfa1eSAnton Vorontsov };
648365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
649365cfa1eSAnton Vorontsov
650365cfa1eSAnton Vorontsov if (sc_reg < ARRAY_SIZE(offset) &&
651365cfa1eSAnton Vorontsov (sc_reg != SCR_NOTIFICATION || (hpriv->cap & HOST_CAP_SNTF)))
652365cfa1eSAnton Vorontsov return offset[sc_reg];
653365cfa1eSAnton Vorontsov return 0;
654365cfa1eSAnton Vorontsov }
655365cfa1eSAnton Vorontsov
ahci_scr_read(struct ata_link * link,unsigned int sc_reg,u32 * val)656365cfa1eSAnton Vorontsov static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
657365cfa1eSAnton Vorontsov {
658365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(link->ap);
659365cfa1eSAnton Vorontsov int offset = ahci_scr_offset(link->ap, sc_reg);
660365cfa1eSAnton Vorontsov
661365cfa1eSAnton Vorontsov if (offset) {
662365cfa1eSAnton Vorontsov *val = readl(port_mmio + offset);
663365cfa1eSAnton Vorontsov return 0;
664365cfa1eSAnton Vorontsov }
665365cfa1eSAnton Vorontsov return -EINVAL;
666365cfa1eSAnton Vorontsov }
667365cfa1eSAnton Vorontsov
ahci_scr_write(struct ata_link * link,unsigned int sc_reg,u32 val)668365cfa1eSAnton Vorontsov static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
669365cfa1eSAnton Vorontsov {
670365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(link->ap);
671365cfa1eSAnton Vorontsov int offset = ahci_scr_offset(link->ap, sc_reg);
672365cfa1eSAnton Vorontsov
673365cfa1eSAnton Vorontsov if (offset) {
674365cfa1eSAnton Vorontsov writel(val, port_mmio + offset);
675365cfa1eSAnton Vorontsov return 0;
676365cfa1eSAnton Vorontsov }
677365cfa1eSAnton Vorontsov return -EINVAL;
678365cfa1eSAnton Vorontsov }
679365cfa1eSAnton Vorontsov
ahci_start_engine(struct ata_port * ap)680365cfa1eSAnton Vorontsov void ahci_start_engine(struct ata_port *ap)
681365cfa1eSAnton Vorontsov {
682365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
683365cfa1eSAnton Vorontsov u32 tmp;
684365cfa1eSAnton Vorontsov
685365cfa1eSAnton Vorontsov /* start DMA */
686365cfa1eSAnton Vorontsov tmp = readl(port_mmio + PORT_CMD);
687365cfa1eSAnton Vorontsov tmp |= PORT_CMD_START;
688365cfa1eSAnton Vorontsov writel(tmp, port_mmio + PORT_CMD);
689365cfa1eSAnton Vorontsov readl(port_mmio + PORT_CMD); /* flush */
690365cfa1eSAnton Vorontsov }
691365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_start_engine);
692365cfa1eSAnton Vorontsov
ahci_stop_engine(struct ata_port * ap)693365cfa1eSAnton Vorontsov int ahci_stop_engine(struct ata_port *ap)
694365cfa1eSAnton Vorontsov {
695365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
696fb329633SDanesh Petigara struct ahci_host_priv *hpriv = ap->host->private_data;
697365cfa1eSAnton Vorontsov u32 tmp;
698365cfa1eSAnton Vorontsov
699fb329633SDanesh Petigara /*
700fb329633SDanesh Petigara * On some controllers, stopping a port's DMA engine while the port
701fb329633SDanesh Petigara * is in ALPM state (partial or slumber) results in failures on
702fb329633SDanesh Petigara * subsequent DMA engine starts. For those controllers, put the
703fb329633SDanesh Petigara * port back in active state before stopping its DMA engine.
704fb329633SDanesh Petigara */
705fb329633SDanesh Petigara if ((hpriv->flags & AHCI_HFLAG_WAKE_BEFORE_STOP) &&
706fb329633SDanesh Petigara (ap->link.lpm_policy > ATA_LPM_MAX_POWER) &&
707fb329633SDanesh Petigara ahci_set_lpm(&ap->link, ATA_LPM_MAX_POWER, ATA_LPM_WAKE_ONLY)) {
708fb329633SDanesh Petigara dev_err(ap->host->dev, "Failed to wake up port before engine stop\n");
709fb329633SDanesh Petigara return -EIO;
710fb329633SDanesh Petigara }
711fb329633SDanesh Petigara
712365cfa1eSAnton Vorontsov tmp = readl(port_mmio + PORT_CMD);
713365cfa1eSAnton Vorontsov
714365cfa1eSAnton Vorontsov /* check if the HBA is idle */
715365cfa1eSAnton Vorontsov if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
716365cfa1eSAnton Vorontsov return 0;
717365cfa1eSAnton Vorontsov
7183b61e512SStefan Roese /*
7193b61e512SStefan Roese * Don't try to issue commands but return with ENODEV if the
7203b61e512SStefan Roese * AHCI controller not available anymore (e.g. due to PCIe hot
7213b61e512SStefan Roese * unplugging). Otherwise a 500ms delay for each port is added.
7223b61e512SStefan Roese */
7233b61e512SStefan Roese if (tmp == 0xffffffff) {
7243b61e512SStefan Roese dev_err(ap->host->dev, "AHCI controller unavailable!\n");
7253b61e512SStefan Roese return -ENODEV;
7263b61e512SStefan Roese }
7273b61e512SStefan Roese
728365cfa1eSAnton Vorontsov /* setting HBA to idle */
729365cfa1eSAnton Vorontsov tmp &= ~PORT_CMD_START;
730365cfa1eSAnton Vorontsov writel(tmp, port_mmio + PORT_CMD);
731365cfa1eSAnton Vorontsov
732365cfa1eSAnton Vorontsov /* wait for engine to stop. This could be as long as 500 msec */
73397750cebSTejun Heo tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
734365cfa1eSAnton Vorontsov PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
735365cfa1eSAnton Vorontsov if (tmp & PORT_CMD_LIST_ON)
736365cfa1eSAnton Vorontsov return -EIO;
737365cfa1eSAnton Vorontsov
738365cfa1eSAnton Vorontsov return 0;
739365cfa1eSAnton Vorontsov }
740365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_stop_engine);
741365cfa1eSAnton Vorontsov
ahci_start_fis_rx(struct ata_port * ap)74239e0ee99SSuman Tripathi void ahci_start_fis_rx(struct ata_port *ap)
743365cfa1eSAnton Vorontsov {
744365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
745365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
746365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
747365cfa1eSAnton Vorontsov u32 tmp;
748365cfa1eSAnton Vorontsov
749365cfa1eSAnton Vorontsov /* set FIS registers */
750365cfa1eSAnton Vorontsov if (hpriv->cap & HOST_CAP_64)
751365cfa1eSAnton Vorontsov writel((pp->cmd_slot_dma >> 16) >> 16,
752365cfa1eSAnton Vorontsov port_mmio + PORT_LST_ADDR_HI);
753365cfa1eSAnton Vorontsov writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR);
754365cfa1eSAnton Vorontsov
755365cfa1eSAnton Vorontsov if (hpriv->cap & HOST_CAP_64)
756365cfa1eSAnton Vorontsov writel((pp->rx_fis_dma >> 16) >> 16,
757365cfa1eSAnton Vorontsov port_mmio + PORT_FIS_ADDR_HI);
758365cfa1eSAnton Vorontsov writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR);
759365cfa1eSAnton Vorontsov
760365cfa1eSAnton Vorontsov /* enable FIS reception */
761365cfa1eSAnton Vorontsov tmp = readl(port_mmio + PORT_CMD);
762365cfa1eSAnton Vorontsov tmp |= PORT_CMD_FIS_RX;
763365cfa1eSAnton Vorontsov writel(tmp, port_mmio + PORT_CMD);
764365cfa1eSAnton Vorontsov
765365cfa1eSAnton Vorontsov /* flush */
766365cfa1eSAnton Vorontsov readl(port_mmio + PORT_CMD);
767365cfa1eSAnton Vorontsov }
76839e0ee99SSuman Tripathi EXPORT_SYMBOL_GPL(ahci_start_fis_rx);
769365cfa1eSAnton Vorontsov
ahci_stop_fis_rx(struct ata_port * ap)770365cfa1eSAnton Vorontsov static int ahci_stop_fis_rx(struct ata_port *ap)
771365cfa1eSAnton Vorontsov {
772365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
773365cfa1eSAnton Vorontsov u32 tmp;
774365cfa1eSAnton Vorontsov
775365cfa1eSAnton Vorontsov /* disable FIS reception */
776365cfa1eSAnton Vorontsov tmp = readl(port_mmio + PORT_CMD);
777365cfa1eSAnton Vorontsov tmp &= ~PORT_CMD_FIS_RX;
778365cfa1eSAnton Vorontsov writel(tmp, port_mmio + PORT_CMD);
779365cfa1eSAnton Vorontsov
780365cfa1eSAnton Vorontsov /* wait for completion, spec says 500ms, give it 1000 */
78197750cebSTejun Heo tmp = ata_wait_register(ap, port_mmio + PORT_CMD, PORT_CMD_FIS_ON,
782365cfa1eSAnton Vorontsov PORT_CMD_FIS_ON, 10, 1000);
783365cfa1eSAnton Vorontsov if (tmp & PORT_CMD_FIS_ON)
784365cfa1eSAnton Vorontsov return -EBUSY;
785365cfa1eSAnton Vorontsov
786365cfa1eSAnton Vorontsov return 0;
787365cfa1eSAnton Vorontsov }
788365cfa1eSAnton Vorontsov
ahci_power_up(struct ata_port * ap)789365cfa1eSAnton Vorontsov static void ahci_power_up(struct ata_port *ap)
790365cfa1eSAnton Vorontsov {
791365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
792365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
793365cfa1eSAnton Vorontsov u32 cmd;
794365cfa1eSAnton Vorontsov
795365cfa1eSAnton Vorontsov cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
796365cfa1eSAnton Vorontsov
797365cfa1eSAnton Vorontsov /* spin up device */
798365cfa1eSAnton Vorontsov if (hpriv->cap & HOST_CAP_SSS) {
799365cfa1eSAnton Vorontsov cmd |= PORT_CMD_SPIN_UP;
800365cfa1eSAnton Vorontsov writel(cmd, port_mmio + PORT_CMD);
801365cfa1eSAnton Vorontsov }
802365cfa1eSAnton Vorontsov
803365cfa1eSAnton Vorontsov /* wake up link */
804365cfa1eSAnton Vorontsov writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD);
805365cfa1eSAnton Vorontsov }
806365cfa1eSAnton Vorontsov
ahci_set_lpm(struct ata_link * link,enum ata_lpm_policy policy,unsigned int hints)8076b7ae954STejun Heo static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
8086b7ae954STejun Heo unsigned int hints)
809365cfa1eSAnton Vorontsov {
8106b7ae954STejun Heo struct ata_port *ap = link->ap;
811365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
812365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
813365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
814365cfa1eSAnton Vorontsov
8156b7ae954STejun Heo if (policy != ATA_LPM_MAX_POWER) {
816fb329633SDanesh Petigara /* wakeup flag only applies to the max power policy */
817fb329633SDanesh Petigara hints &= ~ATA_LPM_WAKE_ONLY;
818fb329633SDanesh Petigara
819365cfa1eSAnton Vorontsov /*
820365cfa1eSAnton Vorontsov * Disable interrupts on Phy Ready. This keeps us from
8216b7ae954STejun Heo * getting woken up due to spurious phy ready
8226b7ae954STejun Heo * interrupts.
823365cfa1eSAnton Vorontsov */
824365cfa1eSAnton Vorontsov pp->intr_mask &= ~PORT_IRQ_PHYRDY;
825365cfa1eSAnton Vorontsov writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
826365cfa1eSAnton Vorontsov
8276b7ae954STejun Heo sata_link_scr_lpm(link, policy, false);
8286b7ae954STejun Heo }
829365cfa1eSAnton Vorontsov
8306b7ae954STejun Heo if (hpriv->cap & HOST_CAP_ALPM) {
8316b7ae954STejun Heo u32 cmd = readl(port_mmio + PORT_CMD);
832365cfa1eSAnton Vorontsov
8336b7ae954STejun Heo if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
834fb329633SDanesh Petigara if (!(hints & ATA_LPM_WAKE_ONLY))
8356b7ae954STejun Heo cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
8366b7ae954STejun Heo cmd |= PORT_CMD_ICC_ACTIVE;
837365cfa1eSAnton Vorontsov
8386b7ae954STejun Heo writel(cmd, port_mmio + PORT_CMD);
8396b7ae954STejun Heo readl(port_mmio + PORT_CMD);
8406b7ae954STejun Heo
8416b7ae954STejun Heo /* wait 10ms to be sure we've come out of LPM state */
84297750cebSTejun Heo ata_msleep(ap, 10);
843fb329633SDanesh Petigara
844fb329633SDanesh Petigara if (hints & ATA_LPM_WAKE_ONLY)
845fb329633SDanesh Petigara return 0;
8466b7ae954STejun Heo } else {
847365cfa1eSAnton Vorontsov cmd |= PORT_CMD_ALPE;
8486b7ae954STejun Heo if (policy == ATA_LPM_MIN_POWER)
8496b7ae954STejun Heo cmd |= PORT_CMD_ASP;
850a5ec5a7bSSrinivas Pandruvada else if (policy == ATA_LPM_MIN_POWER_WITH_PARTIAL)
851a5ec5a7bSSrinivas Pandruvada cmd &= ~PORT_CMD_ASP;
852365cfa1eSAnton Vorontsov
853365cfa1eSAnton Vorontsov /* write out new cmd value */
854365cfa1eSAnton Vorontsov writel(cmd, port_mmio + PORT_CMD);
8556b7ae954STejun Heo }
8566b7ae954STejun Heo }
857365cfa1eSAnton Vorontsov
85865fe1f0fSShane Huang /* set aggressive device sleep */
85965fe1f0fSShane Huang if ((hpriv->cap2 & HOST_CAP2_SDS) &&
86065fe1f0fSShane Huang (hpriv->cap2 & HOST_CAP2_SADM) &&
86165fe1f0fSShane Huang (link->device->flags & ATA_DFLAG_DEVSLP)) {
862a5ec5a7bSSrinivas Pandruvada if (policy == ATA_LPM_MIN_POWER ||
863a5ec5a7bSSrinivas Pandruvada policy == ATA_LPM_MIN_POWER_WITH_PARTIAL)
86465fe1f0fSShane Huang ahci_set_aggressive_devslp(ap, true);
86565fe1f0fSShane Huang else
86665fe1f0fSShane Huang ahci_set_aggressive_devslp(ap, false);
86765fe1f0fSShane Huang }
86865fe1f0fSShane Huang
8696b7ae954STejun Heo if (policy == ATA_LPM_MAX_POWER) {
8706b7ae954STejun Heo sata_link_scr_lpm(link, policy, false);
8716b7ae954STejun Heo
8726b7ae954STejun Heo /* turn PHYRDY IRQ back on */
8736b7ae954STejun Heo pp->intr_mask |= PORT_IRQ_PHYRDY;
8746b7ae954STejun Heo writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
8756b7ae954STejun Heo }
8766b7ae954STejun Heo
877365cfa1eSAnton Vorontsov return 0;
878365cfa1eSAnton Vorontsov }
879365cfa1eSAnton Vorontsov
880365cfa1eSAnton Vorontsov #ifdef CONFIG_PM
ahci_power_down(struct ata_port * ap)881365cfa1eSAnton Vorontsov static void ahci_power_down(struct ata_port *ap)
882365cfa1eSAnton Vorontsov {
883365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
884365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
885365cfa1eSAnton Vorontsov u32 cmd, scontrol;
886365cfa1eSAnton Vorontsov
887365cfa1eSAnton Vorontsov if (!(hpriv->cap & HOST_CAP_SSS))
888365cfa1eSAnton Vorontsov return;
889365cfa1eSAnton Vorontsov
890365cfa1eSAnton Vorontsov /* put device into listen mode, first set PxSCTL.DET to 0 */
891365cfa1eSAnton Vorontsov scontrol = readl(port_mmio + PORT_SCR_CTL);
892365cfa1eSAnton Vorontsov scontrol &= ~0xf;
893365cfa1eSAnton Vorontsov writel(scontrol, port_mmio + PORT_SCR_CTL);
894365cfa1eSAnton Vorontsov
895365cfa1eSAnton Vorontsov /* then set PxCMD.SUD to 0 */
896365cfa1eSAnton Vorontsov cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK;
897365cfa1eSAnton Vorontsov cmd &= ~PORT_CMD_SPIN_UP;
898365cfa1eSAnton Vorontsov writel(cmd, port_mmio + PORT_CMD);
899365cfa1eSAnton Vorontsov }
900365cfa1eSAnton Vorontsov #endif
901365cfa1eSAnton Vorontsov
ahci_start_port(struct ata_port * ap)902365cfa1eSAnton Vorontsov static void ahci_start_port(struct ata_port *ap)
903365cfa1eSAnton Vorontsov {
90466583c9fSBrian Norris struct ahci_host_priv *hpriv = ap->host->private_data;
905365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
906365cfa1eSAnton Vorontsov struct ata_link *link;
907365cfa1eSAnton Vorontsov struct ahci_em_priv *emp;
908365cfa1eSAnton Vorontsov ssize_t rc;
909365cfa1eSAnton Vorontsov int i;
910365cfa1eSAnton Vorontsov
911365cfa1eSAnton Vorontsov /* enable FIS reception */
912365cfa1eSAnton Vorontsov ahci_start_fis_rx(ap);
913365cfa1eSAnton Vorontsov
91466583c9fSBrian Norris /* enable DMA */
91566583c9fSBrian Norris if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE))
916039ece38SHans de Goede hpriv->start_engine(ap);
91766583c9fSBrian Norris
918365cfa1eSAnton Vorontsov /* turn on LEDs */
919365cfa1eSAnton Vorontsov if (ap->flags & ATA_FLAG_EM) {
920365cfa1eSAnton Vorontsov ata_for_each_link(link, ap, EDGE) {
921365cfa1eSAnton Vorontsov emp = &pp->em_priv[link->pmp];
922365cfa1eSAnton Vorontsov
923365cfa1eSAnton Vorontsov /* EM Transmit bit maybe busy during init */
924365cfa1eSAnton Vorontsov for (i = 0; i < EM_MAX_RETRY; i++) {
925439d7a35SMark Langsdorf rc = ap->ops->transmit_led_message(ap,
926365cfa1eSAnton Vorontsov emp->led_state,
927365cfa1eSAnton Vorontsov 4);
928fa070ee6SLukasz Dorau /*
929fa070ee6SLukasz Dorau * If busy, give a breather but do not
930fa070ee6SLukasz Dorau * release EH ownership by using msleep()
931fa070ee6SLukasz Dorau * instead of ata_msleep(). EM Transmit
932fa070ee6SLukasz Dorau * bit is busy for the whole host and
933fa070ee6SLukasz Dorau * releasing ownership will cause other
934fa070ee6SLukasz Dorau * ports to fail the same way.
935fa070ee6SLukasz Dorau */
936365cfa1eSAnton Vorontsov if (rc == -EBUSY)
937fa070ee6SLukasz Dorau msleep(1);
938365cfa1eSAnton Vorontsov else
939365cfa1eSAnton Vorontsov break;
940365cfa1eSAnton Vorontsov }
941365cfa1eSAnton Vorontsov }
942365cfa1eSAnton Vorontsov }
943365cfa1eSAnton Vorontsov
944365cfa1eSAnton Vorontsov if (ap->flags & ATA_FLAG_SW_ACTIVITY)
945365cfa1eSAnton Vorontsov ata_for_each_link(link, ap, EDGE)
946365cfa1eSAnton Vorontsov ahci_init_sw_activity(link);
947365cfa1eSAnton Vorontsov
948365cfa1eSAnton Vorontsov }
949365cfa1eSAnton Vorontsov
ahci_deinit_port(struct ata_port * ap,const char ** emsg)950365cfa1eSAnton Vorontsov static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
951365cfa1eSAnton Vorontsov {
952365cfa1eSAnton Vorontsov int rc;
953fa89f53bSEvan Wang struct ahci_host_priv *hpriv = ap->host->private_data;
954365cfa1eSAnton Vorontsov
955365cfa1eSAnton Vorontsov /* disable DMA */
956fa89f53bSEvan Wang rc = hpriv->stop_engine(ap);
957365cfa1eSAnton Vorontsov if (rc) {
958365cfa1eSAnton Vorontsov *emsg = "failed to stop engine";
959365cfa1eSAnton Vorontsov return rc;
960365cfa1eSAnton Vorontsov }
961365cfa1eSAnton Vorontsov
962365cfa1eSAnton Vorontsov /* disable FIS reception */
963365cfa1eSAnton Vorontsov rc = ahci_stop_fis_rx(ap);
964365cfa1eSAnton Vorontsov if (rc) {
965365cfa1eSAnton Vorontsov *emsg = "failed stop FIS RX";
966365cfa1eSAnton Vorontsov return rc;
967365cfa1eSAnton Vorontsov }
968365cfa1eSAnton Vorontsov
969365cfa1eSAnton Vorontsov return 0;
970365cfa1eSAnton Vorontsov }
971365cfa1eSAnton Vorontsov
ahci_reset_controller(struct ata_host * host)972365cfa1eSAnton Vorontsov int ahci_reset_controller(struct ata_host *host)
973365cfa1eSAnton Vorontsov {
974365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data;
975365cfa1eSAnton Vorontsov void __iomem *mmio = hpriv->mmio;
976365cfa1eSAnton Vorontsov u32 tmp;
977365cfa1eSAnton Vorontsov
9789e936277SDamien Le Moal /*
9799e936277SDamien Le Moal * We must be in AHCI mode, before using anything AHCI-specific, such
9809e936277SDamien Le Moal * as HOST_RESET.
981365cfa1eSAnton Vorontsov */
982365cfa1eSAnton Vorontsov ahci_enable_ahci(mmio);
983365cfa1eSAnton Vorontsov
9849e936277SDamien Le Moal /* Global controller reset */
9859e936277SDamien Le Moal if (ahci_skip_host_reset) {
9869e936277SDamien Le Moal dev_info(host->dev, "Skipping global host reset\n");
9879e936277SDamien Le Moal return 0;
9889e936277SDamien Le Moal }
9899e936277SDamien Le Moal
990365cfa1eSAnton Vorontsov tmp = readl(mmio + HOST_CTL);
9919e936277SDamien Le Moal if (!(tmp & HOST_RESET)) {
992365cfa1eSAnton Vorontsov writel(tmp | HOST_RESET, mmio + HOST_CTL);
993365cfa1eSAnton Vorontsov readl(mmio + HOST_CTL); /* flush */
994365cfa1eSAnton Vorontsov }
995365cfa1eSAnton Vorontsov
996365cfa1eSAnton Vorontsov /*
9979e936277SDamien Le Moal * To perform host reset, OS should set HOST_RESET and poll until this
9989e936277SDamien Le Moal * bit is read to be "0". Reset must complete within 1 second, or the
9999e936277SDamien Le Moal * hardware should be considered fried.
1000365cfa1eSAnton Vorontsov */
100197750cebSTejun Heo tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
1002365cfa1eSAnton Vorontsov HOST_RESET, 10, 1000);
1003365cfa1eSAnton Vorontsov if (tmp & HOST_RESET) {
10049e936277SDamien Le Moal dev_err(host->dev, "Controller reset failed (0x%x)\n",
1005a44fec1fSJoe Perches tmp);
1006365cfa1eSAnton Vorontsov return -EIO;
1007365cfa1eSAnton Vorontsov }
1008365cfa1eSAnton Vorontsov
10099e936277SDamien Le Moal /* Turn on AHCI mode */
1010365cfa1eSAnton Vorontsov ahci_enable_ahci(mmio);
1011365cfa1eSAnton Vorontsov
10129e936277SDamien Le Moal /* Some registers might be cleared on reset. Restore initial values. */
10137fab72f8SDoug Berger if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
1014365cfa1eSAnton Vorontsov ahci_restore_initial_config(host);
1015365cfa1eSAnton Vorontsov
1016365cfa1eSAnton Vorontsov return 0;
1017365cfa1eSAnton Vorontsov }
1018365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_reset_controller);
1019365cfa1eSAnton Vorontsov
ahci_sw_activity(struct ata_link * link)1020365cfa1eSAnton Vorontsov static void ahci_sw_activity(struct ata_link *link)
1021365cfa1eSAnton Vorontsov {
1022365cfa1eSAnton Vorontsov struct ata_port *ap = link->ap;
1023365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1024365cfa1eSAnton Vorontsov struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1025365cfa1eSAnton Vorontsov
1026365cfa1eSAnton Vorontsov if (!(link->flags & ATA_LFLAG_SW_ACTIVITY))
1027365cfa1eSAnton Vorontsov return;
1028365cfa1eSAnton Vorontsov
1029365cfa1eSAnton Vorontsov emp->activity++;
1030365cfa1eSAnton Vorontsov if (!timer_pending(&emp->timer))
1031365cfa1eSAnton Vorontsov mod_timer(&emp->timer, jiffies + msecs_to_jiffies(10));
1032365cfa1eSAnton Vorontsov }
1033365cfa1eSAnton Vorontsov
ahci_sw_activity_blink(struct timer_list * t)10341843594cSKees Cook static void ahci_sw_activity_blink(struct timer_list *t)
1035365cfa1eSAnton Vorontsov {
10361843594cSKees Cook struct ahci_em_priv *emp = from_timer(emp, t, timer);
10371843594cSKees Cook struct ata_link *link = emp->link;
1038365cfa1eSAnton Vorontsov struct ata_port *ap = link->ap;
10391843594cSKees Cook
1040365cfa1eSAnton Vorontsov unsigned long led_message = emp->led_state;
1041365cfa1eSAnton Vorontsov u32 activity_led_state;
1042365cfa1eSAnton Vorontsov unsigned long flags;
1043365cfa1eSAnton Vorontsov
1044365cfa1eSAnton Vorontsov led_message &= EM_MSG_LED_VALUE;
1045365cfa1eSAnton Vorontsov led_message |= ap->port_no | (link->pmp << 8);
1046365cfa1eSAnton Vorontsov
1047365cfa1eSAnton Vorontsov /* check to see if we've had activity. If so,
1048365cfa1eSAnton Vorontsov * toggle state of LED and reset timer. If not,
1049365cfa1eSAnton Vorontsov * turn LED to desired idle state.
1050365cfa1eSAnton Vorontsov */
1051365cfa1eSAnton Vorontsov spin_lock_irqsave(ap->lock, flags);
1052365cfa1eSAnton Vorontsov if (emp->saved_activity != emp->activity) {
1053365cfa1eSAnton Vorontsov emp->saved_activity = emp->activity;
1054365cfa1eSAnton Vorontsov /* get the current LED state */
1055365cfa1eSAnton Vorontsov activity_led_state = led_message & EM_MSG_LED_VALUE_ON;
1056365cfa1eSAnton Vorontsov
1057365cfa1eSAnton Vorontsov if (activity_led_state)
1058365cfa1eSAnton Vorontsov activity_led_state = 0;
1059365cfa1eSAnton Vorontsov else
1060365cfa1eSAnton Vorontsov activity_led_state = 1;
1061365cfa1eSAnton Vorontsov
1062365cfa1eSAnton Vorontsov /* clear old state */
1063365cfa1eSAnton Vorontsov led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
1064365cfa1eSAnton Vorontsov
1065365cfa1eSAnton Vorontsov /* toggle state */
1066365cfa1eSAnton Vorontsov led_message |= (activity_led_state << 16);
1067365cfa1eSAnton Vorontsov mod_timer(&emp->timer, jiffies + msecs_to_jiffies(100));
1068365cfa1eSAnton Vorontsov } else {
1069365cfa1eSAnton Vorontsov /* switch to idle */
1070365cfa1eSAnton Vorontsov led_message &= ~EM_MSG_LED_VALUE_ACTIVITY;
1071365cfa1eSAnton Vorontsov if (emp->blink_policy == BLINK_OFF)
1072365cfa1eSAnton Vorontsov led_message |= (1 << 16);
1073365cfa1eSAnton Vorontsov }
1074365cfa1eSAnton Vorontsov spin_unlock_irqrestore(ap->lock, flags);
1075439d7a35SMark Langsdorf ap->ops->transmit_led_message(ap, led_message, 4);
1076365cfa1eSAnton Vorontsov }
1077365cfa1eSAnton Vorontsov
ahci_init_sw_activity(struct ata_link * link)1078365cfa1eSAnton Vorontsov static void ahci_init_sw_activity(struct ata_link *link)
1079365cfa1eSAnton Vorontsov {
1080365cfa1eSAnton Vorontsov struct ata_port *ap = link->ap;
1081365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1082365cfa1eSAnton Vorontsov struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1083365cfa1eSAnton Vorontsov
1084365cfa1eSAnton Vorontsov /* init activity stats, setup timer */
1085365cfa1eSAnton Vorontsov emp->saved_activity = emp->activity = 0;
10861843594cSKees Cook emp->link = link;
10871843594cSKees Cook timer_setup(&emp->timer, ahci_sw_activity_blink, 0);
1088365cfa1eSAnton Vorontsov
1089365cfa1eSAnton Vorontsov /* check our blink policy and set flag for link if it's enabled */
1090365cfa1eSAnton Vorontsov if (emp->blink_policy)
1091365cfa1eSAnton Vorontsov link->flags |= ATA_LFLAG_SW_ACTIVITY;
1092365cfa1eSAnton Vorontsov }
1093365cfa1eSAnton Vorontsov
ahci_reset_em(struct ata_host * host)1094365cfa1eSAnton Vorontsov int ahci_reset_em(struct ata_host *host)
1095365cfa1eSAnton Vorontsov {
1096365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data;
1097365cfa1eSAnton Vorontsov void __iomem *mmio = hpriv->mmio;
1098365cfa1eSAnton Vorontsov u32 em_ctl;
1099365cfa1eSAnton Vorontsov
1100365cfa1eSAnton Vorontsov em_ctl = readl(mmio + HOST_EM_CTL);
1101365cfa1eSAnton Vorontsov if ((em_ctl & EM_CTL_TM) || (em_ctl & EM_CTL_RST))
1102365cfa1eSAnton Vorontsov return -EINVAL;
1103365cfa1eSAnton Vorontsov
1104365cfa1eSAnton Vorontsov writel(em_ctl | EM_CTL_RST, mmio + HOST_EM_CTL);
1105365cfa1eSAnton Vorontsov return 0;
1106365cfa1eSAnton Vorontsov }
1107365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_reset_em);
1108365cfa1eSAnton Vorontsov
ahci_transmit_led_message(struct ata_port * ap,u32 state,ssize_t size)1109365cfa1eSAnton Vorontsov static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state,
1110365cfa1eSAnton Vorontsov ssize_t size)
1111365cfa1eSAnton Vorontsov {
1112365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
1113365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1114365cfa1eSAnton Vorontsov void __iomem *mmio = hpriv->mmio;
1115365cfa1eSAnton Vorontsov u32 em_ctl;
1116365cfa1eSAnton Vorontsov u32 message[] = {0, 0};
1117365cfa1eSAnton Vorontsov unsigned long flags;
1118365cfa1eSAnton Vorontsov int pmp;
1119365cfa1eSAnton Vorontsov struct ahci_em_priv *emp;
1120365cfa1eSAnton Vorontsov
1121365cfa1eSAnton Vorontsov /* get the slot number from the message */
1122365cfa1eSAnton Vorontsov pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
1123365cfa1eSAnton Vorontsov if (pmp < EM_MAX_SLOTS)
1124365cfa1eSAnton Vorontsov emp = &pp->em_priv[pmp];
1125365cfa1eSAnton Vorontsov else
1126365cfa1eSAnton Vorontsov return -EINVAL;
1127365cfa1eSAnton Vorontsov
1128bb03c640SMika Westerberg ahci_rpm_get_port(ap);
1129365cfa1eSAnton Vorontsov spin_lock_irqsave(ap->lock, flags);
1130365cfa1eSAnton Vorontsov
1131365cfa1eSAnton Vorontsov /*
1132365cfa1eSAnton Vorontsov * if we are still busy transmitting a previous message,
1133365cfa1eSAnton Vorontsov * do not allow
1134365cfa1eSAnton Vorontsov */
1135365cfa1eSAnton Vorontsov em_ctl = readl(mmio + HOST_EM_CTL);
1136365cfa1eSAnton Vorontsov if (em_ctl & EM_CTL_TM) {
1137365cfa1eSAnton Vorontsov spin_unlock_irqrestore(ap->lock, flags);
1138bb03c640SMika Westerberg ahci_rpm_put_port(ap);
1139365cfa1eSAnton Vorontsov return -EBUSY;
1140365cfa1eSAnton Vorontsov }
1141365cfa1eSAnton Vorontsov
1142008dbd61SHarry Zhang if (hpriv->em_msg_type & EM_MSG_TYPE_LED) {
1143365cfa1eSAnton Vorontsov /*
1144365cfa1eSAnton Vorontsov * create message header - this is all zero except for
1145365cfa1eSAnton Vorontsov * the message size, which is 4 bytes.
1146365cfa1eSAnton Vorontsov */
1147365cfa1eSAnton Vorontsov message[0] |= (4 << 8);
1148365cfa1eSAnton Vorontsov
1149365cfa1eSAnton Vorontsov /* ignore 0:4 of byte zero, fill in port info yourself */
1150365cfa1eSAnton Vorontsov message[1] = ((state & ~EM_MSG_LED_HBA_PORT) | ap->port_no);
1151365cfa1eSAnton Vorontsov
1152365cfa1eSAnton Vorontsov /* write message to EM_LOC */
1153365cfa1eSAnton Vorontsov writel(message[0], mmio + hpriv->em_loc);
1154365cfa1eSAnton Vorontsov writel(message[1], mmio + hpriv->em_loc+4);
1155365cfa1eSAnton Vorontsov
1156365cfa1eSAnton Vorontsov /*
1157365cfa1eSAnton Vorontsov * tell hardware to transmit the message
1158365cfa1eSAnton Vorontsov */
1159365cfa1eSAnton Vorontsov writel(em_ctl | EM_CTL_TM, mmio + HOST_EM_CTL);
1160008dbd61SHarry Zhang }
1161008dbd61SHarry Zhang
1162008dbd61SHarry Zhang /* save off new led state for port/slot */
1163008dbd61SHarry Zhang emp->led_state = state;
1164365cfa1eSAnton Vorontsov
1165365cfa1eSAnton Vorontsov spin_unlock_irqrestore(ap->lock, flags);
1166bb03c640SMika Westerberg ahci_rpm_put_port(ap);
1167bb03c640SMika Westerberg
1168365cfa1eSAnton Vorontsov return size;
1169365cfa1eSAnton Vorontsov }
1170365cfa1eSAnton Vorontsov
ahci_led_show(struct ata_port * ap,char * buf)1171365cfa1eSAnton Vorontsov static ssize_t ahci_led_show(struct ata_port *ap, char *buf)
1172365cfa1eSAnton Vorontsov {
1173365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1174365cfa1eSAnton Vorontsov struct ata_link *link;
1175365cfa1eSAnton Vorontsov struct ahci_em_priv *emp;
1176365cfa1eSAnton Vorontsov int rc = 0;
1177365cfa1eSAnton Vorontsov
1178365cfa1eSAnton Vorontsov ata_for_each_link(link, ap, EDGE) {
1179365cfa1eSAnton Vorontsov emp = &pp->em_priv[link->pmp];
1180365cfa1eSAnton Vorontsov rc += sprintf(buf, "%lx\n", emp->led_state);
1181365cfa1eSAnton Vorontsov }
1182365cfa1eSAnton Vorontsov return rc;
1183365cfa1eSAnton Vorontsov }
1184365cfa1eSAnton Vorontsov
ahci_led_store(struct ata_port * ap,const char * buf,size_t size)1185365cfa1eSAnton Vorontsov static ssize_t ahci_led_store(struct ata_port *ap, const char *buf,
1186365cfa1eSAnton Vorontsov size_t size)
1187365cfa1eSAnton Vorontsov {
1188b2a52b6aSDaeseok Youn unsigned int state;
1189365cfa1eSAnton Vorontsov int pmp;
1190365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1191365cfa1eSAnton Vorontsov struct ahci_em_priv *emp;
1192365cfa1eSAnton Vorontsov
1193b2a52b6aSDaeseok Youn if (kstrtouint(buf, 0, &state) < 0)
1194b2a52b6aSDaeseok Youn return -EINVAL;
1195365cfa1eSAnton Vorontsov
1196365cfa1eSAnton Vorontsov /* get the slot number from the message */
1197365cfa1eSAnton Vorontsov pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8;
1198fae2a637SJohn Garry if (pmp < EM_MAX_SLOTS) {
1199fae2a637SJohn Garry pmp = array_index_nospec(pmp, EM_MAX_SLOTS);
1200365cfa1eSAnton Vorontsov emp = &pp->em_priv[pmp];
1201fae2a637SJohn Garry } else {
1202365cfa1eSAnton Vorontsov return -EINVAL;
1203fae2a637SJohn Garry }
1204365cfa1eSAnton Vorontsov
1205365cfa1eSAnton Vorontsov /* mask off the activity bits if we are in sw_activity
1206365cfa1eSAnton Vorontsov * mode, user should turn off sw_activity before setting
1207365cfa1eSAnton Vorontsov * activity led through em_message
1208365cfa1eSAnton Vorontsov */
1209365cfa1eSAnton Vorontsov if (emp->blink_policy)
1210365cfa1eSAnton Vorontsov state &= ~EM_MSG_LED_VALUE_ACTIVITY;
1211365cfa1eSAnton Vorontsov
1212439d7a35SMark Langsdorf return ap->ops->transmit_led_message(ap, state, size);
1213365cfa1eSAnton Vorontsov }
1214365cfa1eSAnton Vorontsov
ahci_activity_store(struct ata_device * dev,enum sw_activity val)1215365cfa1eSAnton Vorontsov static ssize_t ahci_activity_store(struct ata_device *dev, enum sw_activity val)
1216365cfa1eSAnton Vorontsov {
1217365cfa1eSAnton Vorontsov struct ata_link *link = dev->link;
1218365cfa1eSAnton Vorontsov struct ata_port *ap = link->ap;
1219365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1220365cfa1eSAnton Vorontsov struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1221365cfa1eSAnton Vorontsov u32 port_led_state = emp->led_state;
1222365cfa1eSAnton Vorontsov
1223365cfa1eSAnton Vorontsov /* save the desired Activity LED behavior */
1224365cfa1eSAnton Vorontsov if (val == OFF) {
1225365cfa1eSAnton Vorontsov /* clear LFLAG */
1226365cfa1eSAnton Vorontsov link->flags &= ~(ATA_LFLAG_SW_ACTIVITY);
1227365cfa1eSAnton Vorontsov
1228365cfa1eSAnton Vorontsov /* set the LED to OFF */
1229365cfa1eSAnton Vorontsov port_led_state &= EM_MSG_LED_VALUE_OFF;
1230365cfa1eSAnton Vorontsov port_led_state |= (ap->port_no | (link->pmp << 8));
1231439d7a35SMark Langsdorf ap->ops->transmit_led_message(ap, port_led_state, 4);
1232365cfa1eSAnton Vorontsov } else {
1233365cfa1eSAnton Vorontsov link->flags |= ATA_LFLAG_SW_ACTIVITY;
1234365cfa1eSAnton Vorontsov if (val == BLINK_OFF) {
1235365cfa1eSAnton Vorontsov /* set LED to ON for idle */
1236365cfa1eSAnton Vorontsov port_led_state &= EM_MSG_LED_VALUE_OFF;
1237365cfa1eSAnton Vorontsov port_led_state |= (ap->port_no | (link->pmp << 8));
1238365cfa1eSAnton Vorontsov port_led_state |= EM_MSG_LED_VALUE_ON; /* check this */
1239439d7a35SMark Langsdorf ap->ops->transmit_led_message(ap, port_led_state, 4);
1240365cfa1eSAnton Vorontsov }
1241365cfa1eSAnton Vorontsov }
1242365cfa1eSAnton Vorontsov emp->blink_policy = val;
1243365cfa1eSAnton Vorontsov return 0;
1244365cfa1eSAnton Vorontsov }
1245365cfa1eSAnton Vorontsov
ahci_activity_show(struct ata_device * dev,char * buf)1246365cfa1eSAnton Vorontsov static ssize_t ahci_activity_show(struct ata_device *dev, char *buf)
1247365cfa1eSAnton Vorontsov {
1248365cfa1eSAnton Vorontsov struct ata_link *link = dev->link;
1249365cfa1eSAnton Vorontsov struct ata_port *ap = link->ap;
1250365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1251365cfa1eSAnton Vorontsov struct ahci_em_priv *emp = &pp->em_priv[link->pmp];
1252365cfa1eSAnton Vorontsov
1253365cfa1eSAnton Vorontsov /* display the saved value of activity behavior for this
1254365cfa1eSAnton Vorontsov * disk.
1255365cfa1eSAnton Vorontsov */
1256365cfa1eSAnton Vorontsov return sprintf(buf, "%d\n", emp->blink_policy);
1257365cfa1eSAnton Vorontsov }
1258365cfa1eSAnton Vorontsov
ahci_port_clear_pending_irq(struct ata_port * ap)1259737dd811SSzuying Chen static void ahci_port_clear_pending_irq(struct ata_port *ap)
1260737dd811SSzuying Chen {
1261737dd811SSzuying Chen struct ahci_host_priv *hpriv = ap->host->private_data;
1262737dd811SSzuying Chen void __iomem *port_mmio = ahci_port_base(ap);
1263737dd811SSzuying Chen u32 tmp;
1264737dd811SSzuying Chen
1265737dd811SSzuying Chen /* clear SError */
1266737dd811SSzuying Chen tmp = readl(port_mmio + PORT_SCR_ERR);
1267737dd811SSzuying Chen dev_dbg(ap->host->dev, "PORT_SCR_ERR 0x%x\n", tmp);
1268737dd811SSzuying Chen writel(tmp, port_mmio + PORT_SCR_ERR);
1269737dd811SSzuying Chen
1270737dd811SSzuying Chen /* clear port IRQ */
1271737dd811SSzuying Chen tmp = readl(port_mmio + PORT_IRQ_STAT);
1272737dd811SSzuying Chen dev_dbg(ap->host->dev, "PORT_IRQ_STAT 0x%x\n", tmp);
1273737dd811SSzuying Chen if (tmp)
1274737dd811SSzuying Chen writel(tmp, port_mmio + PORT_IRQ_STAT);
1275737dd811SSzuying Chen
1276737dd811SSzuying Chen writel(1 << ap->port_no, hpriv->mmio + HOST_IRQ_STAT);
1277737dd811SSzuying Chen }
1278737dd811SSzuying Chen
ahci_port_init(struct device * dev,struct ata_port * ap,int port_no,void __iomem * mmio,void __iomem * port_mmio)1279365cfa1eSAnton Vorontsov static void ahci_port_init(struct device *dev, struct ata_port *ap,
1280365cfa1eSAnton Vorontsov int port_no, void __iomem *mmio,
1281365cfa1eSAnton Vorontsov void __iomem *port_mmio)
1282365cfa1eSAnton Vorontsov {
12838a3e33cfSManuel Lauss struct ahci_host_priv *hpriv = ap->host->private_data;
1284365cfa1eSAnton Vorontsov const char *emsg = NULL;
1285365cfa1eSAnton Vorontsov int rc;
1286365cfa1eSAnton Vorontsov u32 tmp;
1287365cfa1eSAnton Vorontsov
1288365cfa1eSAnton Vorontsov /* make sure port is not active */
1289365cfa1eSAnton Vorontsov rc = ahci_deinit_port(ap, &emsg);
1290365cfa1eSAnton Vorontsov if (rc)
1291365cfa1eSAnton Vorontsov dev_warn(dev, "%s (%d)\n", emsg, rc);
1292365cfa1eSAnton Vorontsov
1293737dd811SSzuying Chen ahci_port_clear_pending_irq(ap);
12948a3e33cfSManuel Lauss
12958a3e33cfSManuel Lauss /* mark esata ports */
12968a3e33cfSManuel Lauss tmp = readl(port_mmio + PORT_CMD);
1297dc8b4afcSManuel Lauss if ((tmp & PORT_CMD_ESP) && (hpriv->cap & HOST_CAP_SXS))
12988a3e33cfSManuel Lauss ap->pflags |= ATA_PFLAG_EXTERNAL;
1299365cfa1eSAnton Vorontsov }
1300365cfa1eSAnton Vorontsov
ahci_init_controller(struct ata_host * host)1301365cfa1eSAnton Vorontsov void ahci_init_controller(struct ata_host *host)
1302365cfa1eSAnton Vorontsov {
1303365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data;
1304365cfa1eSAnton Vorontsov void __iomem *mmio = hpriv->mmio;
1305365cfa1eSAnton Vorontsov int i;
1306365cfa1eSAnton Vorontsov void __iomem *port_mmio;
1307365cfa1eSAnton Vorontsov u32 tmp;
1308365cfa1eSAnton Vorontsov
1309365cfa1eSAnton Vorontsov for (i = 0; i < host->n_ports; i++) {
1310365cfa1eSAnton Vorontsov struct ata_port *ap = host->ports[i];
1311365cfa1eSAnton Vorontsov
1312365cfa1eSAnton Vorontsov port_mmio = ahci_port_base(ap);
1313365cfa1eSAnton Vorontsov if (ata_port_is_dummy(ap))
1314365cfa1eSAnton Vorontsov continue;
1315365cfa1eSAnton Vorontsov
1316365cfa1eSAnton Vorontsov ahci_port_init(host->dev, ap, i, mmio, port_mmio);
1317365cfa1eSAnton Vorontsov }
1318365cfa1eSAnton Vorontsov
1319365cfa1eSAnton Vorontsov tmp = readl(mmio + HOST_CTL);
132093c77114SHannes Reinecke dev_dbg(host->dev, "HOST_CTL 0x%x\n", tmp);
1321365cfa1eSAnton Vorontsov writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
1322365cfa1eSAnton Vorontsov tmp = readl(mmio + HOST_CTL);
132393c77114SHannes Reinecke dev_dbg(host->dev, "HOST_CTL 0x%x\n", tmp);
1324365cfa1eSAnton Vorontsov }
1325365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_init_controller);
1326365cfa1eSAnton Vorontsov
ahci_dev_config(struct ata_device * dev)1327365cfa1eSAnton Vorontsov static void ahci_dev_config(struct ata_device *dev)
1328365cfa1eSAnton Vorontsov {
1329365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = dev->link->ap->host->private_data;
1330365cfa1eSAnton Vorontsov
1331365cfa1eSAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_SECT255) {
1332365cfa1eSAnton Vorontsov dev->max_sectors = 255;
1333a9a79dfeSJoe Perches ata_dev_info(dev,
1334365cfa1eSAnton Vorontsov "SB600 AHCI: limiting to 255 sectors per cmd\n");
1335365cfa1eSAnton Vorontsov }
1336365cfa1eSAnton Vorontsov }
1337365cfa1eSAnton Vorontsov
ahci_dev_classify(struct ata_port * ap)1338bbb4ab43SRob Herring unsigned int ahci_dev_classify(struct ata_port *ap)
1339365cfa1eSAnton Vorontsov {
1340365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
1341365cfa1eSAnton Vorontsov struct ata_taskfile tf;
1342365cfa1eSAnton Vorontsov u32 tmp;
1343365cfa1eSAnton Vorontsov
1344365cfa1eSAnton Vorontsov tmp = readl(port_mmio + PORT_SIG);
1345365cfa1eSAnton Vorontsov tf.lbah = (tmp >> 24) & 0xff;
1346365cfa1eSAnton Vorontsov tf.lbam = (tmp >> 16) & 0xff;
1347365cfa1eSAnton Vorontsov tf.lbal = (tmp >> 8) & 0xff;
1348365cfa1eSAnton Vorontsov tf.nsect = (tmp) & 0xff;
1349365cfa1eSAnton Vorontsov
13506c952a0dSHannes Reinecke return ata_port_classify(ap, &tf);
1351365cfa1eSAnton Vorontsov }
1352bbb4ab43SRob Herring EXPORT_SYMBOL_GPL(ahci_dev_classify);
1353365cfa1eSAnton Vorontsov
ahci_fill_cmd_slot(struct ahci_port_priv * pp,unsigned int tag,u32 opts)135402cdfcf0SDavid Milburn void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
1355365cfa1eSAnton Vorontsov u32 opts)
1356365cfa1eSAnton Vorontsov {
1357365cfa1eSAnton Vorontsov dma_addr_t cmd_tbl_dma;
1358365cfa1eSAnton Vorontsov
1359365cfa1eSAnton Vorontsov cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
1360365cfa1eSAnton Vorontsov
1361365cfa1eSAnton Vorontsov pp->cmd_slot[tag].opts = cpu_to_le32(opts);
1362365cfa1eSAnton Vorontsov pp->cmd_slot[tag].status = 0;
1363365cfa1eSAnton Vorontsov pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
1364365cfa1eSAnton Vorontsov pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
1365365cfa1eSAnton Vorontsov }
136602cdfcf0SDavid Milburn EXPORT_SYMBOL_GPL(ahci_fill_cmd_slot);
1367365cfa1eSAnton Vorontsov
ahci_kick_engine(struct ata_port * ap)1368365cfa1eSAnton Vorontsov int ahci_kick_engine(struct ata_port *ap)
1369365cfa1eSAnton Vorontsov {
1370365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
1371365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
1372365cfa1eSAnton Vorontsov u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1373365cfa1eSAnton Vorontsov u32 tmp;
1374365cfa1eSAnton Vorontsov int busy, rc;
1375365cfa1eSAnton Vorontsov
1376365cfa1eSAnton Vorontsov /* stop engine */
1377fa89f53bSEvan Wang rc = hpriv->stop_engine(ap);
1378365cfa1eSAnton Vorontsov if (rc)
1379365cfa1eSAnton Vorontsov goto out_restart;
1380365cfa1eSAnton Vorontsov
1381365cfa1eSAnton Vorontsov /* need to do CLO?
1382365cfa1eSAnton Vorontsov * always do CLO if PMP is attached (AHCI-1.3 9.2)
1383365cfa1eSAnton Vorontsov */
1384365cfa1eSAnton Vorontsov busy = status & (ATA_BUSY | ATA_DRQ);
1385365cfa1eSAnton Vorontsov if (!busy && !sata_pmp_attached(ap)) {
1386365cfa1eSAnton Vorontsov rc = 0;
1387365cfa1eSAnton Vorontsov goto out_restart;
1388365cfa1eSAnton Vorontsov }
1389365cfa1eSAnton Vorontsov
1390365cfa1eSAnton Vorontsov if (!(hpriv->cap & HOST_CAP_CLO)) {
1391365cfa1eSAnton Vorontsov rc = -EOPNOTSUPP;
1392365cfa1eSAnton Vorontsov goto out_restart;
1393365cfa1eSAnton Vorontsov }
1394365cfa1eSAnton Vorontsov
1395365cfa1eSAnton Vorontsov /* perform CLO */
1396365cfa1eSAnton Vorontsov tmp = readl(port_mmio + PORT_CMD);
1397365cfa1eSAnton Vorontsov tmp |= PORT_CMD_CLO;
1398365cfa1eSAnton Vorontsov writel(tmp, port_mmio + PORT_CMD);
1399365cfa1eSAnton Vorontsov
1400365cfa1eSAnton Vorontsov rc = 0;
140197750cebSTejun Heo tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
1402365cfa1eSAnton Vorontsov PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
1403365cfa1eSAnton Vorontsov if (tmp & PORT_CMD_CLO)
1404365cfa1eSAnton Vorontsov rc = -EIO;
1405365cfa1eSAnton Vorontsov
1406365cfa1eSAnton Vorontsov /* restart engine */
1407365cfa1eSAnton Vorontsov out_restart:
1408039ece38SHans de Goede hpriv->start_engine(ap);
1409365cfa1eSAnton Vorontsov return rc;
1410365cfa1eSAnton Vorontsov }
1411365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_kick_engine);
1412365cfa1eSAnton Vorontsov
ahci_exec_polled_cmd(struct ata_port * ap,int pmp,struct ata_taskfile * tf,int is_cmd,u16 flags,unsigned int timeout_msec)1413365cfa1eSAnton Vorontsov static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
1414365cfa1eSAnton Vorontsov struct ata_taskfile *tf, int is_cmd, u16 flags,
1415cc264364SSergey Shtylyov unsigned int timeout_msec)
1416365cfa1eSAnton Vorontsov {
1417365cfa1eSAnton Vorontsov const u32 cmd_fis_len = 5; /* five dwords */
1418365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1419365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
1420365cfa1eSAnton Vorontsov u8 *fis = pp->cmd_tbl;
1421365cfa1eSAnton Vorontsov u32 tmp;
1422365cfa1eSAnton Vorontsov
1423365cfa1eSAnton Vorontsov /* prep the command */
1424365cfa1eSAnton Vorontsov ata_tf_to_fis(tf, pmp, is_cmd, fis);
1425365cfa1eSAnton Vorontsov ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
1426365cfa1eSAnton Vorontsov
1427023113d2SXiangliang Yu /* set port value for softreset of Port Multiplier */
1428023113d2SXiangliang Yu if (pp->fbs_enabled && pp->fbs_last_dev != pmp) {
1429023113d2SXiangliang Yu tmp = readl(port_mmio + PORT_FBS);
1430023113d2SXiangliang Yu tmp &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC);
1431023113d2SXiangliang Yu tmp |= pmp << PORT_FBS_DEV_OFFSET;
1432023113d2SXiangliang Yu writel(tmp, port_mmio + PORT_FBS);
1433023113d2SXiangliang Yu pp->fbs_last_dev = pmp;
1434023113d2SXiangliang Yu }
1435023113d2SXiangliang Yu
1436365cfa1eSAnton Vorontsov /* issue & wait */
1437365cfa1eSAnton Vorontsov writel(1, port_mmio + PORT_CMD_ISSUE);
1438365cfa1eSAnton Vorontsov
1439365cfa1eSAnton Vorontsov if (timeout_msec) {
144097750cebSTejun Heo tmp = ata_wait_register(ap, port_mmio + PORT_CMD_ISSUE,
144197750cebSTejun Heo 0x1, 0x1, 1, timeout_msec);
1442365cfa1eSAnton Vorontsov if (tmp & 0x1) {
1443365cfa1eSAnton Vorontsov ahci_kick_engine(ap);
1444365cfa1eSAnton Vorontsov return -EBUSY;
1445365cfa1eSAnton Vorontsov }
1446365cfa1eSAnton Vorontsov } else
1447365cfa1eSAnton Vorontsov readl(port_mmio + PORT_CMD_ISSUE); /* flush */
1448365cfa1eSAnton Vorontsov
1449365cfa1eSAnton Vorontsov return 0;
1450365cfa1eSAnton Vorontsov }
1451365cfa1eSAnton Vorontsov
ahci_do_softreset(struct ata_link * link,unsigned int * class,int pmp,unsigned long deadline,int (* check_ready)(struct ata_link * link))1452365cfa1eSAnton Vorontsov int ahci_do_softreset(struct ata_link *link, unsigned int *class,
1453365cfa1eSAnton Vorontsov int pmp, unsigned long deadline,
1454365cfa1eSAnton Vorontsov int (*check_ready)(struct ata_link *link))
1455365cfa1eSAnton Vorontsov {
1456365cfa1eSAnton Vorontsov struct ata_port *ap = link->ap;
1457365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
145889dafa20Sxiangliang yu struct ahci_port_priv *pp = ap->private_data;
1459365cfa1eSAnton Vorontsov const char *reason = NULL;
1460cc264364SSergey Shtylyov unsigned long now;
1461cc264364SSergey Shtylyov unsigned int msecs;
1462365cfa1eSAnton Vorontsov struct ata_taskfile tf;
146389dafa20Sxiangliang yu bool fbs_disabled = false;
1464365cfa1eSAnton Vorontsov int rc;
1465365cfa1eSAnton Vorontsov
1466365cfa1eSAnton Vorontsov /* prepare for SRST (AHCI-1.1 10.4.1) */
1467365cfa1eSAnton Vorontsov rc = ahci_kick_engine(ap);
1468365cfa1eSAnton Vorontsov if (rc && rc != -EOPNOTSUPP)
1469a9a79dfeSJoe Perches ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc);
1470365cfa1eSAnton Vorontsov
147189dafa20Sxiangliang yu /*
147289dafa20Sxiangliang yu * According to AHCI-1.2 9.3.9: if FBS is enable, software shall
147389dafa20Sxiangliang yu * clear PxFBS.EN to '0' prior to issuing software reset to devices
147489dafa20Sxiangliang yu * that is attached to port multiplier.
147589dafa20Sxiangliang yu */
147689dafa20Sxiangliang yu if (!ata_is_host_link(link) && pp->fbs_enabled) {
147789dafa20Sxiangliang yu ahci_disable_fbs(ap);
147889dafa20Sxiangliang yu fbs_disabled = true;
147989dafa20Sxiangliang yu }
148089dafa20Sxiangliang yu
1481365cfa1eSAnton Vorontsov ata_tf_init(link->device, &tf);
1482365cfa1eSAnton Vorontsov
148308fc4756SMinwoo Im /* issue the first H2D Register FIS */
1484365cfa1eSAnton Vorontsov msecs = 0;
1485365cfa1eSAnton Vorontsov now = jiffies;
1486f1f5a807STejun Heo if (time_after(deadline, now))
1487365cfa1eSAnton Vorontsov msecs = jiffies_to_msecs(deadline - now);
1488365cfa1eSAnton Vorontsov
1489365cfa1eSAnton Vorontsov tf.ctl |= ATA_SRST;
1490365cfa1eSAnton Vorontsov if (ahci_exec_polled_cmd(ap, pmp, &tf, 0,
1491365cfa1eSAnton Vorontsov AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs)) {
1492365cfa1eSAnton Vorontsov rc = -EIO;
1493365cfa1eSAnton Vorontsov reason = "1st FIS failed";
1494365cfa1eSAnton Vorontsov goto fail;
1495365cfa1eSAnton Vorontsov }
1496365cfa1eSAnton Vorontsov
1497365cfa1eSAnton Vorontsov /* spec says at least 5us, but be generous and sleep for 1ms */
149897750cebSTejun Heo ata_msleep(ap, 1);
1499365cfa1eSAnton Vorontsov
150008fc4756SMinwoo Im /* issue the second H2D Register FIS */
1501365cfa1eSAnton Vorontsov tf.ctl &= ~ATA_SRST;
1502365cfa1eSAnton Vorontsov ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);
1503365cfa1eSAnton Vorontsov
1504365cfa1eSAnton Vorontsov /* wait for link to become ready */
1505365cfa1eSAnton Vorontsov rc = ata_wait_after_reset(link, deadline, check_ready);
1506365cfa1eSAnton Vorontsov if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) {
1507365cfa1eSAnton Vorontsov /*
1508365cfa1eSAnton Vorontsov * Workaround for cases where link online status can't
1509365cfa1eSAnton Vorontsov * be trusted. Treat device readiness timeout as link
1510365cfa1eSAnton Vorontsov * offline.
1511365cfa1eSAnton Vorontsov */
1512a9a79dfeSJoe Perches ata_link_info(link, "device not ready, treating as offline\n");
1513365cfa1eSAnton Vorontsov *class = ATA_DEV_NONE;
1514365cfa1eSAnton Vorontsov } else if (rc) {
1515365cfa1eSAnton Vorontsov /* link occupied, -ENODEV too is an error */
1516365cfa1eSAnton Vorontsov reason = "device not ready";
1517365cfa1eSAnton Vorontsov goto fail;
1518365cfa1eSAnton Vorontsov } else
1519365cfa1eSAnton Vorontsov *class = ahci_dev_classify(ap);
1520365cfa1eSAnton Vorontsov
152189dafa20Sxiangliang yu /* re-enable FBS if disabled before */
152289dafa20Sxiangliang yu if (fbs_disabled)
152389dafa20Sxiangliang yu ahci_enable_fbs(ap);
152489dafa20Sxiangliang yu
1525365cfa1eSAnton Vorontsov return 0;
1526365cfa1eSAnton Vorontsov
1527365cfa1eSAnton Vorontsov fail:
1528a9a79dfeSJoe Perches ata_link_err(link, "softreset failed (%s)\n", reason);
1529365cfa1eSAnton Vorontsov return rc;
1530365cfa1eSAnton Vorontsov }
1531365cfa1eSAnton Vorontsov
ahci_check_ready(struct ata_link * link)1532365cfa1eSAnton Vorontsov int ahci_check_ready(struct ata_link *link)
1533365cfa1eSAnton Vorontsov {
1534365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(link->ap);
1535365cfa1eSAnton Vorontsov u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1536365cfa1eSAnton Vorontsov
1537365cfa1eSAnton Vorontsov return ata_check_ready(status);
1538365cfa1eSAnton Vorontsov }
1539365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_check_ready);
1540365cfa1eSAnton Vorontsov
ahci_softreset(struct ata_link * link,unsigned int * class,unsigned long deadline)1541365cfa1eSAnton Vorontsov static int ahci_softreset(struct ata_link *link, unsigned int *class,
1542365cfa1eSAnton Vorontsov unsigned long deadline)
1543365cfa1eSAnton Vorontsov {
1544365cfa1eSAnton Vorontsov int pmp = sata_srst_pmp(link);
1545365cfa1eSAnton Vorontsov
1546365cfa1eSAnton Vorontsov return ahci_do_softreset(link, class, pmp, deadline, ahci_check_ready);
1547365cfa1eSAnton Vorontsov }
1548365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_do_softreset);
1549365cfa1eSAnton Vorontsov
ahci_bad_pmp_check_ready(struct ata_link * link)1550345347c5SYuan-Hsin Chen static int ahci_bad_pmp_check_ready(struct ata_link *link)
1551345347c5SYuan-Hsin Chen {
1552345347c5SYuan-Hsin Chen void __iomem *port_mmio = ahci_port_base(link->ap);
1553345347c5SYuan-Hsin Chen u8 status = readl(port_mmio + PORT_TFDATA) & 0xFF;
1554345347c5SYuan-Hsin Chen u32 irq_status = readl(port_mmio + PORT_IRQ_STAT);
1555345347c5SYuan-Hsin Chen
1556345347c5SYuan-Hsin Chen /*
1557345347c5SYuan-Hsin Chen * There is no need to check TFDATA if BAD PMP is found due to HW bug,
1558345347c5SYuan-Hsin Chen * which can save timeout delay.
1559345347c5SYuan-Hsin Chen */
1560345347c5SYuan-Hsin Chen if (irq_status & PORT_IRQ_BAD_PMP)
1561345347c5SYuan-Hsin Chen return -EIO;
1562345347c5SYuan-Hsin Chen
1563345347c5SYuan-Hsin Chen return ata_check_ready(status);
1564345347c5SYuan-Hsin Chen }
1565345347c5SYuan-Hsin Chen
ahci_pmp_retry_softreset(struct ata_link * link,unsigned int * class,unsigned long deadline)156635186d05SDaeseok Youn static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
1567345347c5SYuan-Hsin Chen unsigned long deadline)
1568345347c5SYuan-Hsin Chen {
1569345347c5SYuan-Hsin Chen struct ata_port *ap = link->ap;
1570345347c5SYuan-Hsin Chen void __iomem *port_mmio = ahci_port_base(ap);
1571345347c5SYuan-Hsin Chen int pmp = sata_srst_pmp(link);
1572345347c5SYuan-Hsin Chen int rc;
1573345347c5SYuan-Hsin Chen u32 irq_sts;
1574345347c5SYuan-Hsin Chen
1575345347c5SYuan-Hsin Chen rc = ahci_do_softreset(link, class, pmp, deadline,
1576345347c5SYuan-Hsin Chen ahci_bad_pmp_check_ready);
1577345347c5SYuan-Hsin Chen
1578345347c5SYuan-Hsin Chen /*
1579345347c5SYuan-Hsin Chen * Soft reset fails with IPMS set when PMP is enabled but
1580345347c5SYuan-Hsin Chen * SATA HDD/ODD is connected to SATA port, do soft reset
1581345347c5SYuan-Hsin Chen * again to port 0.
1582345347c5SYuan-Hsin Chen */
1583345347c5SYuan-Hsin Chen if (rc == -EIO) {
1584345347c5SYuan-Hsin Chen irq_sts = readl(port_mmio + PORT_IRQ_STAT);
1585345347c5SYuan-Hsin Chen if (irq_sts & PORT_IRQ_BAD_PMP) {
158639f80acbSWei Yongjun ata_link_warn(link,
1587345347c5SYuan-Hsin Chen "applying PMP SRST workaround "
1588345347c5SYuan-Hsin Chen "and retrying\n");
1589345347c5SYuan-Hsin Chen rc = ahci_do_softreset(link, class, 0, deadline,
1590345347c5SYuan-Hsin Chen ahci_check_ready);
1591345347c5SYuan-Hsin Chen }
1592345347c5SYuan-Hsin Chen }
1593345347c5SYuan-Hsin Chen
1594345347c5SYuan-Hsin Chen return rc;
1595345347c5SYuan-Hsin Chen }
1596345347c5SYuan-Hsin Chen
ahci_do_hardreset(struct ata_link * link,unsigned int * class,unsigned long deadline,bool * online)1597d436501eSBartosz Golaszewski int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
1598d436501eSBartosz Golaszewski unsigned long deadline, bool *online)
1599365cfa1eSAnton Vorontsov {
1600d14d41ccSSergey Shtylyov const unsigned int *timing = sata_ehc_deb_timing(&link->eh_context);
1601365cfa1eSAnton Vorontsov struct ata_port *ap = link->ap;
1602365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1603039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data;
1604365cfa1eSAnton Vorontsov u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
1605365cfa1eSAnton Vorontsov struct ata_taskfile tf;
1606365cfa1eSAnton Vorontsov int rc;
1607365cfa1eSAnton Vorontsov
1608fa89f53bSEvan Wang hpriv->stop_engine(ap);
1609365cfa1eSAnton Vorontsov
1610365cfa1eSAnton Vorontsov /* clear D2H reception area to properly wait for D2H FIS */
1611365cfa1eSAnton Vorontsov ata_tf_init(link->device, &tf);
1612efcef265SSergey Shtylyov tf.status = ATA_BUSY;
1613365cfa1eSAnton Vorontsov ata_tf_to_fis(&tf, 0, 0, d2h_fis);
1614365cfa1eSAnton Vorontsov
1615737dd811SSzuying Chen ahci_port_clear_pending_irq(ap);
1616737dd811SSzuying Chen
1617d436501eSBartosz Golaszewski rc = sata_link_hardreset(link, timing, deadline, online,
1618365cfa1eSAnton Vorontsov ahci_check_ready);
1619365cfa1eSAnton Vorontsov
1620039ece38SHans de Goede hpriv->start_engine(ap);
1621365cfa1eSAnton Vorontsov
1622d436501eSBartosz Golaszewski if (*online)
1623365cfa1eSAnton Vorontsov *class = ahci_dev_classify(ap);
1624365cfa1eSAnton Vorontsov
1625365cfa1eSAnton Vorontsov return rc;
1626365cfa1eSAnton Vorontsov }
1627d436501eSBartosz Golaszewski EXPORT_SYMBOL_GPL(ahci_do_hardreset);
1628d436501eSBartosz Golaszewski
ahci_hardreset(struct ata_link * link,unsigned int * class,unsigned long deadline)1629d436501eSBartosz Golaszewski static int ahci_hardreset(struct ata_link *link, unsigned int *class,
1630d436501eSBartosz Golaszewski unsigned long deadline)
1631d436501eSBartosz Golaszewski {
1632d436501eSBartosz Golaszewski bool online;
1633d436501eSBartosz Golaszewski
1634d436501eSBartosz Golaszewski return ahci_do_hardreset(link, class, deadline, &online);
1635d436501eSBartosz Golaszewski }
1636365cfa1eSAnton Vorontsov
ahci_postreset(struct ata_link * link,unsigned int * class)1637365cfa1eSAnton Vorontsov static void ahci_postreset(struct ata_link *link, unsigned int *class)
1638365cfa1eSAnton Vorontsov {
1639365cfa1eSAnton Vorontsov struct ata_port *ap = link->ap;
1640365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
1641365cfa1eSAnton Vorontsov u32 new_tmp, tmp;
1642365cfa1eSAnton Vorontsov
1643365cfa1eSAnton Vorontsov ata_std_postreset(link, class);
1644365cfa1eSAnton Vorontsov
1645365cfa1eSAnton Vorontsov /* Make sure port's ATAPI bit is set appropriately */
1646365cfa1eSAnton Vorontsov new_tmp = tmp = readl(port_mmio + PORT_CMD);
1647365cfa1eSAnton Vorontsov if (*class == ATA_DEV_ATAPI)
1648365cfa1eSAnton Vorontsov new_tmp |= PORT_CMD_ATAPI;
1649365cfa1eSAnton Vorontsov else
1650365cfa1eSAnton Vorontsov new_tmp &= ~PORT_CMD_ATAPI;
1651365cfa1eSAnton Vorontsov if (new_tmp != tmp) {
1652365cfa1eSAnton Vorontsov writel(new_tmp, port_mmio + PORT_CMD);
1653365cfa1eSAnton Vorontsov readl(port_mmio + PORT_CMD); /* flush */
1654365cfa1eSAnton Vorontsov }
1655365cfa1eSAnton Vorontsov }
1656365cfa1eSAnton Vorontsov
ahci_fill_sg(struct ata_queued_cmd * qc,void * cmd_tbl)1657365cfa1eSAnton Vorontsov static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
1658365cfa1eSAnton Vorontsov {
1659365cfa1eSAnton Vorontsov struct scatterlist *sg;
1660365cfa1eSAnton Vorontsov struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
1661365cfa1eSAnton Vorontsov unsigned int si;
1662365cfa1eSAnton Vorontsov
1663365cfa1eSAnton Vorontsov /*
1664365cfa1eSAnton Vorontsov * Next, the S/G list.
1665365cfa1eSAnton Vorontsov */
1666365cfa1eSAnton Vorontsov for_each_sg(qc->sg, sg, qc->n_elem, si) {
1667365cfa1eSAnton Vorontsov dma_addr_t addr = sg_dma_address(sg);
1668365cfa1eSAnton Vorontsov u32 sg_len = sg_dma_len(sg);
1669365cfa1eSAnton Vorontsov
1670365cfa1eSAnton Vorontsov ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
1671365cfa1eSAnton Vorontsov ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
1672365cfa1eSAnton Vorontsov ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
1673365cfa1eSAnton Vorontsov }
1674365cfa1eSAnton Vorontsov
1675365cfa1eSAnton Vorontsov return si;
1676365cfa1eSAnton Vorontsov }
1677365cfa1eSAnton Vorontsov
ahci_pmp_qc_defer(struct ata_queued_cmd * qc)1678365cfa1eSAnton Vorontsov static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc)
1679365cfa1eSAnton Vorontsov {
1680365cfa1eSAnton Vorontsov struct ata_port *ap = qc->ap;
1681365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1682365cfa1eSAnton Vorontsov
1683365cfa1eSAnton Vorontsov if (!sata_pmp_attached(ap) || pp->fbs_enabled)
1684365cfa1eSAnton Vorontsov return ata_std_qc_defer(qc);
1685365cfa1eSAnton Vorontsov else
1686365cfa1eSAnton Vorontsov return sata_pmp_qc_defer_cmd_switch(qc);
1687365cfa1eSAnton Vorontsov }
1688365cfa1eSAnton Vorontsov
ahci_qc_prep(struct ata_queued_cmd * qc)168995364f36SJiri Slaby static enum ata_completion_errors ahci_qc_prep(struct ata_queued_cmd *qc)
1690365cfa1eSAnton Vorontsov {
1691365cfa1eSAnton Vorontsov struct ata_port *ap = qc->ap;
1692365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1693365cfa1eSAnton Vorontsov int is_atapi = ata_is_atapi(qc->tf.protocol);
1694365cfa1eSAnton Vorontsov void *cmd_tbl;
1695365cfa1eSAnton Vorontsov u32 opts;
1696365cfa1eSAnton Vorontsov const u32 cmd_fis_len = 5; /* five dwords */
1697365cfa1eSAnton Vorontsov unsigned int n_elem;
1698365cfa1eSAnton Vorontsov
1699365cfa1eSAnton Vorontsov /*
1700365cfa1eSAnton Vorontsov * Fill in command table information. First, the header,
1701365cfa1eSAnton Vorontsov * a SATA Register - Host to Device command FIS.
1702365cfa1eSAnton Vorontsov */
17034e5b6260SJens Axboe cmd_tbl = pp->cmd_tbl + qc->hw_tag * AHCI_CMD_TBL_SZ;
1704365cfa1eSAnton Vorontsov
1705365cfa1eSAnton Vorontsov ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, cmd_tbl);
1706365cfa1eSAnton Vorontsov if (is_atapi) {
1707365cfa1eSAnton Vorontsov memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
1708365cfa1eSAnton Vorontsov memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
1709365cfa1eSAnton Vorontsov }
1710365cfa1eSAnton Vorontsov
1711365cfa1eSAnton Vorontsov n_elem = 0;
1712365cfa1eSAnton Vorontsov if (qc->flags & ATA_QCFLAG_DMAMAP)
1713365cfa1eSAnton Vorontsov n_elem = ahci_fill_sg(qc, cmd_tbl);
1714365cfa1eSAnton Vorontsov
1715365cfa1eSAnton Vorontsov /*
1716365cfa1eSAnton Vorontsov * Fill in command slot information.
1717365cfa1eSAnton Vorontsov */
1718365cfa1eSAnton Vorontsov opts = cmd_fis_len | n_elem << 16 | (qc->dev->link->pmp << 12);
1719365cfa1eSAnton Vorontsov if (qc->tf.flags & ATA_TFLAG_WRITE)
1720365cfa1eSAnton Vorontsov opts |= AHCI_CMD_WRITE;
1721365cfa1eSAnton Vorontsov if (is_atapi)
1722365cfa1eSAnton Vorontsov opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
1723365cfa1eSAnton Vorontsov
17244e5b6260SJens Axboe ahci_fill_cmd_slot(pp, qc->hw_tag, opts);
172595364f36SJiri Slaby
172695364f36SJiri Slaby return AC_ERR_OK;
1727365cfa1eSAnton Vorontsov }
1728365cfa1eSAnton Vorontsov
ahci_fbs_dec_intr(struct ata_port * ap)1729365cfa1eSAnton Vorontsov static void ahci_fbs_dec_intr(struct ata_port *ap)
1730365cfa1eSAnton Vorontsov {
1731365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1732365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
1733365cfa1eSAnton Vorontsov u32 fbs = readl(port_mmio + PORT_FBS);
1734365cfa1eSAnton Vorontsov int retries = 3;
1735365cfa1eSAnton Vorontsov
1736365cfa1eSAnton Vorontsov BUG_ON(!pp->fbs_enabled);
1737365cfa1eSAnton Vorontsov
1738365cfa1eSAnton Vorontsov /* time to wait for DEC is not specified by AHCI spec,
1739365cfa1eSAnton Vorontsov * add a retry loop for safety.
1740365cfa1eSAnton Vorontsov */
1741365cfa1eSAnton Vorontsov writel(fbs | PORT_FBS_DEC, port_mmio + PORT_FBS);
1742365cfa1eSAnton Vorontsov fbs = readl(port_mmio + PORT_FBS);
1743365cfa1eSAnton Vorontsov while ((fbs & PORT_FBS_DEC) && retries--) {
1744365cfa1eSAnton Vorontsov udelay(1);
1745365cfa1eSAnton Vorontsov fbs = readl(port_mmio + PORT_FBS);
1746365cfa1eSAnton Vorontsov }
1747365cfa1eSAnton Vorontsov
1748365cfa1eSAnton Vorontsov if (fbs & PORT_FBS_DEC)
1749a44fec1fSJoe Perches dev_err(ap->host->dev, "failed to clear device error\n");
1750365cfa1eSAnton Vorontsov }
1751365cfa1eSAnton Vorontsov
ahci_error_intr(struct ata_port * ap,u32 irq_stat)1752365cfa1eSAnton Vorontsov static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
1753365cfa1eSAnton Vorontsov {
1754365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
1755365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
1756365cfa1eSAnton Vorontsov struct ata_eh_info *host_ehi = &ap->link.eh_info;
1757365cfa1eSAnton Vorontsov struct ata_link *link = NULL;
1758365cfa1eSAnton Vorontsov struct ata_queued_cmd *active_qc;
1759365cfa1eSAnton Vorontsov struct ata_eh_info *active_ehi;
1760365cfa1eSAnton Vorontsov bool fbs_need_dec = false;
1761365cfa1eSAnton Vorontsov u32 serror;
1762365cfa1eSAnton Vorontsov
1763365cfa1eSAnton Vorontsov /* determine active link with error */
1764365cfa1eSAnton Vorontsov if (pp->fbs_enabled) {
1765365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
1766365cfa1eSAnton Vorontsov u32 fbs = readl(port_mmio + PORT_FBS);
1767365cfa1eSAnton Vorontsov int pmp = fbs >> PORT_FBS_DWE_OFFSET;
1768365cfa1eSAnton Vorontsov
1769912b9ac6SShane Huang if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links)) {
1770365cfa1eSAnton Vorontsov link = &ap->pmp_link[pmp];
1771365cfa1eSAnton Vorontsov fbs_need_dec = true;
1772365cfa1eSAnton Vorontsov }
1773365cfa1eSAnton Vorontsov
1774365cfa1eSAnton Vorontsov } else
1775365cfa1eSAnton Vorontsov ata_for_each_link(link, ap, EDGE)
1776365cfa1eSAnton Vorontsov if (ata_link_active(link))
1777365cfa1eSAnton Vorontsov break;
1778365cfa1eSAnton Vorontsov
1779365cfa1eSAnton Vorontsov if (!link)
1780365cfa1eSAnton Vorontsov link = &ap->link;
1781365cfa1eSAnton Vorontsov
1782365cfa1eSAnton Vorontsov active_qc = ata_qc_from_tag(ap, link->active_tag);
1783365cfa1eSAnton Vorontsov active_ehi = &link->eh_info;
1784365cfa1eSAnton Vorontsov
1785365cfa1eSAnton Vorontsov /* record irq stat */
1786365cfa1eSAnton Vorontsov ata_ehi_clear_desc(host_ehi);
1787365cfa1eSAnton Vorontsov ata_ehi_push_desc(host_ehi, "irq_stat 0x%08x", irq_stat);
1788365cfa1eSAnton Vorontsov
1789365cfa1eSAnton Vorontsov /* AHCI needs SError cleared; otherwise, it might lock up */
1790365cfa1eSAnton Vorontsov ahci_scr_read(&ap->link, SCR_ERROR, &serror);
1791365cfa1eSAnton Vorontsov ahci_scr_write(&ap->link, SCR_ERROR, serror);
1792365cfa1eSAnton Vorontsov host_ehi->serror |= serror;
1793365cfa1eSAnton Vorontsov
1794365cfa1eSAnton Vorontsov /* some controllers set IRQ_IF_ERR on device errors, ignore it */
1795365cfa1eSAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_IGN_IRQ_IF_ERR)
1796365cfa1eSAnton Vorontsov irq_stat &= ~PORT_IRQ_IF_ERR;
1797365cfa1eSAnton Vorontsov
1798365cfa1eSAnton Vorontsov if (irq_stat & PORT_IRQ_TF_ERR) {
1799365cfa1eSAnton Vorontsov /* If qc is active, charge it; otherwise, the active
1800365cfa1eSAnton Vorontsov * link. There's no active qc on NCQ errors. It will
1801365cfa1eSAnton Vorontsov * be determined by EH by reading log page 10h.
1802365cfa1eSAnton Vorontsov */
1803365cfa1eSAnton Vorontsov if (active_qc)
1804365cfa1eSAnton Vorontsov active_qc->err_mask |= AC_ERR_DEV;
1805365cfa1eSAnton Vorontsov else
1806365cfa1eSAnton Vorontsov active_ehi->err_mask |= AC_ERR_DEV;
1807365cfa1eSAnton Vorontsov
1808365cfa1eSAnton Vorontsov if (hpriv->flags & AHCI_HFLAG_IGN_SERR_INTERNAL)
1809365cfa1eSAnton Vorontsov host_ehi->serror &= ~SERR_INTERNAL;
1810365cfa1eSAnton Vorontsov }
1811365cfa1eSAnton Vorontsov
1812365cfa1eSAnton Vorontsov if (irq_stat & PORT_IRQ_UNK_FIS) {
1813d5185d65SJoe Perches u32 *unk = pp->rx_fis + RX_FIS_UNK;
1814365cfa1eSAnton Vorontsov
1815365cfa1eSAnton Vorontsov active_ehi->err_mask |= AC_ERR_HSM;
1816365cfa1eSAnton Vorontsov active_ehi->action |= ATA_EH_RESET;
1817365cfa1eSAnton Vorontsov ata_ehi_push_desc(active_ehi,
1818365cfa1eSAnton Vorontsov "unknown FIS %08x %08x %08x %08x" ,
1819365cfa1eSAnton Vorontsov unk[0], unk[1], unk[2], unk[3]);
1820365cfa1eSAnton Vorontsov }
1821365cfa1eSAnton Vorontsov
1822365cfa1eSAnton Vorontsov if (sata_pmp_attached(ap) && (irq_stat & PORT_IRQ_BAD_PMP)) {
1823365cfa1eSAnton Vorontsov active_ehi->err_mask |= AC_ERR_HSM;
1824365cfa1eSAnton Vorontsov active_ehi->action |= ATA_EH_RESET;
1825365cfa1eSAnton Vorontsov ata_ehi_push_desc(active_ehi, "incorrect PMP");
1826365cfa1eSAnton Vorontsov }
1827365cfa1eSAnton Vorontsov
1828365cfa1eSAnton Vorontsov if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
1829365cfa1eSAnton Vorontsov host_ehi->err_mask |= AC_ERR_HOST_BUS;
1830365cfa1eSAnton Vorontsov host_ehi->action |= ATA_EH_RESET;
1831365cfa1eSAnton Vorontsov ata_ehi_push_desc(host_ehi, "host bus error");
1832365cfa1eSAnton Vorontsov }
1833365cfa1eSAnton Vorontsov
1834365cfa1eSAnton Vorontsov if (irq_stat & PORT_IRQ_IF_ERR) {
1835365cfa1eSAnton Vorontsov if (fbs_need_dec)
1836365cfa1eSAnton Vorontsov active_ehi->err_mask |= AC_ERR_DEV;
1837365cfa1eSAnton Vorontsov else {
1838365cfa1eSAnton Vorontsov host_ehi->err_mask |= AC_ERR_ATA_BUS;
1839365cfa1eSAnton Vorontsov host_ehi->action |= ATA_EH_RESET;
1840365cfa1eSAnton Vorontsov }
1841365cfa1eSAnton Vorontsov
1842365cfa1eSAnton Vorontsov ata_ehi_push_desc(host_ehi, "interface fatal error");
1843365cfa1eSAnton Vorontsov }
1844365cfa1eSAnton Vorontsov
1845365cfa1eSAnton Vorontsov if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
1846365cfa1eSAnton Vorontsov ata_ehi_hotplugged(host_ehi);
1847365cfa1eSAnton Vorontsov ata_ehi_push_desc(host_ehi, "%s",
1848365cfa1eSAnton Vorontsov irq_stat & PORT_IRQ_CONNECT ?
1849365cfa1eSAnton Vorontsov "connection status changed" : "PHY RDY changed");
1850365cfa1eSAnton Vorontsov }
1851365cfa1eSAnton Vorontsov
1852365cfa1eSAnton Vorontsov /* okay, let's hand over to EH */
1853365cfa1eSAnton Vorontsov
1854365cfa1eSAnton Vorontsov if (irq_stat & PORT_IRQ_FREEZE)
1855365cfa1eSAnton Vorontsov ata_port_freeze(ap);
1856365cfa1eSAnton Vorontsov else if (fbs_need_dec) {
1857365cfa1eSAnton Vorontsov ata_link_abort(link);
1858365cfa1eSAnton Vorontsov ahci_fbs_dec_intr(ap);
1859365cfa1eSAnton Vorontsov } else
1860365cfa1eSAnton Vorontsov ata_port_abort(ap);
1861365cfa1eSAnton Vorontsov }
1862365cfa1eSAnton Vorontsov
ahci_qc_complete(struct ata_port * ap,void __iomem * port_mmio)18637affcdedSNiklas Cassel static void ahci_qc_complete(struct ata_port *ap, void __iomem *port_mmio)
1864365cfa1eSAnton Vorontsov {
1865365cfa1eSAnton Vorontsov struct ata_eh_info *ehi = &ap->link.eh_info;
1866365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
18675ca72c4fSAlexander Gordeev u32 qc_active = 0;
1868365cfa1eSAnton Vorontsov int rc;
1869365cfa1eSAnton Vorontsov
18707affcdedSNiklas Cassel /*
18717affcdedSNiklas Cassel * pp->active_link is not reliable once FBS is enabled, both
18727affcdedSNiklas Cassel * PORT_SCR_ACT and PORT_CMD_ISSUE should be checked because
18737affcdedSNiklas Cassel * NCQ and non-NCQ commands may be in flight at the same time.
18747affcdedSNiklas Cassel */
18757affcdedSNiklas Cassel if (pp->fbs_enabled) {
18767affcdedSNiklas Cassel if (ap->qc_active) {
18777affcdedSNiklas Cassel qc_active = readl(port_mmio + PORT_SCR_ACT);
18787affcdedSNiklas Cassel qc_active |= readl(port_mmio + PORT_CMD_ISSUE);
18797affcdedSNiklas Cassel }
18807affcdedSNiklas Cassel } else {
18817affcdedSNiklas Cassel /* pp->active_link is valid iff any command is in flight */
18827affcdedSNiklas Cassel if (ap->qc_active && pp->active_link->sactive)
18837affcdedSNiklas Cassel qc_active = readl(port_mmio + PORT_SCR_ACT);
18847affcdedSNiklas Cassel else
18857affcdedSNiklas Cassel qc_active = readl(port_mmio + PORT_CMD_ISSUE);
18867affcdedSNiklas Cassel }
18877affcdedSNiklas Cassel
18887affcdedSNiklas Cassel rc = ata_qc_complete_multiple(ap, qc_active);
18897affcdedSNiklas Cassel if (unlikely(rc < 0 && !(ap->pflags & ATA_PFLAG_RESETTING))) {
18907affcdedSNiklas Cassel ehi->err_mask |= AC_ERR_HSM;
18917affcdedSNiklas Cassel ehi->action |= ATA_EH_RESET;
18927affcdedSNiklas Cassel ata_port_freeze(ap);
18937affcdedSNiklas Cassel }
18947affcdedSNiklas Cassel }
18957affcdedSNiklas Cassel
ahci_handle_port_interrupt(struct ata_port * ap,void __iomem * port_mmio,u32 status)18967affcdedSNiklas Cassel static void ahci_handle_port_interrupt(struct ata_port *ap,
18977affcdedSNiklas Cassel void __iomem *port_mmio, u32 status)
18987affcdedSNiklas Cassel {
18997affcdedSNiklas Cassel struct ahci_port_priv *pp = ap->private_data;
19007affcdedSNiklas Cassel struct ahci_host_priv *hpriv = ap->host->private_data;
19017affcdedSNiklas Cassel
1902365cfa1eSAnton Vorontsov /* ignore BAD_PMP while resetting */
19037affcdedSNiklas Cassel if (unlikely(ap->pflags & ATA_PFLAG_RESETTING))
1904365cfa1eSAnton Vorontsov status &= ~PORT_IRQ_BAD_PMP;
1905365cfa1eSAnton Vorontsov
19068393b811SGabriele Mazzotta if (sata_lpm_ignore_phy_events(&ap->link)) {
1907365cfa1eSAnton Vorontsov status &= ~PORT_IRQ_PHYRDY;
19086b7ae954STejun Heo ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
1909365cfa1eSAnton Vorontsov }
1910365cfa1eSAnton Vorontsov
1911365cfa1eSAnton Vorontsov if (unlikely(status & PORT_IRQ_ERROR)) {
19127affcdedSNiklas Cassel /*
19137affcdedSNiklas Cassel * Before getting the error notification, we may have
19147affcdedSNiklas Cassel * received SDB FISes notifying successful completions.
19157affcdedSNiklas Cassel * Handle these first and then handle the error.
19167affcdedSNiklas Cassel */
19177affcdedSNiklas Cassel ahci_qc_complete(ap, port_mmio);
1918365cfa1eSAnton Vorontsov ahci_error_intr(ap, status);
1919365cfa1eSAnton Vorontsov return;
1920365cfa1eSAnton Vorontsov }
1921365cfa1eSAnton Vorontsov
1922365cfa1eSAnton Vorontsov if (status & PORT_IRQ_SDB_FIS) {
1923365cfa1eSAnton Vorontsov /* If SNotification is available, leave notification
1924365cfa1eSAnton Vorontsov * handling to sata_async_notification(). If not,
1925365cfa1eSAnton Vorontsov * emulate it by snooping SDB FIS RX area.
1926365cfa1eSAnton Vorontsov *
1927365cfa1eSAnton Vorontsov * Snooping FIS RX area is probably cheaper than
1928365cfa1eSAnton Vorontsov * poking SNotification but some constrollers which
1929365cfa1eSAnton Vorontsov * implement SNotification, ICH9 for example, don't
1930365cfa1eSAnton Vorontsov * store AN SDB FIS into receive area.
1931365cfa1eSAnton Vorontsov */
1932365cfa1eSAnton Vorontsov if (hpriv->cap & HOST_CAP_SNTF)
1933365cfa1eSAnton Vorontsov sata_async_notification(ap);
1934365cfa1eSAnton Vorontsov else {
1935365cfa1eSAnton Vorontsov /* If the 'N' bit in word 0 of the FIS is set,
1936365cfa1eSAnton Vorontsov * we just received asynchronous notification.
1937365cfa1eSAnton Vorontsov * Tell libata about it.
1938365cfa1eSAnton Vorontsov *
1939365cfa1eSAnton Vorontsov * Lack of SNotification should not appear in
1940365cfa1eSAnton Vorontsov * ahci 1.2, so the workaround is unnecessary
1941365cfa1eSAnton Vorontsov * when FBS is enabled.
1942365cfa1eSAnton Vorontsov */
1943365cfa1eSAnton Vorontsov if (pp->fbs_enabled)
1944365cfa1eSAnton Vorontsov WARN_ON_ONCE(1);
1945365cfa1eSAnton Vorontsov else {
1946365cfa1eSAnton Vorontsov const __le32 *f = pp->rx_fis + RX_FIS_SDB;
1947365cfa1eSAnton Vorontsov u32 f0 = le32_to_cpu(f[0]);
1948365cfa1eSAnton Vorontsov if (f0 & (1 << 15))
1949365cfa1eSAnton Vorontsov sata_async_notification(ap);
1950365cfa1eSAnton Vorontsov }
1951365cfa1eSAnton Vorontsov }
1952365cfa1eSAnton Vorontsov }
1953365cfa1eSAnton Vorontsov
19547affcdedSNiklas Cassel /* Handle completed commands */
19557affcdedSNiklas Cassel ahci_qc_complete(ap, port_mmio);
1956365cfa1eSAnton Vorontsov }
1957365cfa1eSAnton Vorontsov
ahci_port_intr(struct ata_port * ap)19587865f83fSTejun Heo static void ahci_port_intr(struct ata_port *ap)
19595ca72c4fSAlexander Gordeev {
19605ca72c4fSAlexander Gordeev void __iomem *port_mmio = ahci_port_base(ap);
19615ca72c4fSAlexander Gordeev u32 status;
19625ca72c4fSAlexander Gordeev
19635ca72c4fSAlexander Gordeev status = readl(port_mmio + PORT_IRQ_STAT);
19645ca72c4fSAlexander Gordeev writel(status, port_mmio + PORT_IRQ_STAT);
19655ca72c4fSAlexander Gordeev
19667865f83fSTejun Heo ahci_handle_port_interrupt(ap, port_mmio, status);
19675ca72c4fSAlexander Gordeev }
19685ca72c4fSAlexander Gordeev
ahci_multi_irqs_intr_hard(int irq,void * dev_instance)1969a6b7fb76SDan Williams static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance)
19705ca72c4fSAlexander Gordeev {
1971227dfb4dSAlexander Gordeev struct ata_port *ap = dev_instance;
19725ca72c4fSAlexander Gordeev void __iomem *port_mmio = ahci_port_base(ap);
19735ca72c4fSAlexander Gordeev u32 status;
19745ca72c4fSAlexander Gordeev
19755ca72c4fSAlexander Gordeev status = readl(port_mmio + PORT_IRQ_STAT);
19765ca72c4fSAlexander Gordeev writel(status, port_mmio + PORT_IRQ_STAT);
19775ca72c4fSAlexander Gordeev
1978a6b7fb76SDan Williams spin_lock(ap->lock);
1979a6b7fb76SDan Williams ahci_handle_port_interrupt(ap, port_mmio, status);
1980a6b7fb76SDan Williams spin_unlock(ap->lock);
19815ca72c4fSAlexander Gordeev
1982a6b7fb76SDan Williams return IRQ_HANDLED;
19835ca72c4fSAlexander Gordeev }
19845ca72c4fSAlexander Gordeev
ahci_handle_port_intr(struct ata_host * host,u32 irq_masked)1985f070d671SSuman Tripathi u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
1986365cfa1eSAnton Vorontsov {
1987365cfa1eSAnton Vorontsov unsigned int i, handled = 0;
198803e83cbdSTejun Heo
1989365cfa1eSAnton Vorontsov for (i = 0; i < host->n_ports; i++) {
1990365cfa1eSAnton Vorontsov struct ata_port *ap;
1991365cfa1eSAnton Vorontsov
1992365cfa1eSAnton Vorontsov if (!(irq_masked & (1 << i)))
1993365cfa1eSAnton Vorontsov continue;
1994365cfa1eSAnton Vorontsov
1995365cfa1eSAnton Vorontsov ap = host->ports[i];
1996365cfa1eSAnton Vorontsov if (ap) {
19977865f83fSTejun Heo ahci_port_intr(ap);
1998365cfa1eSAnton Vorontsov } else {
1999365cfa1eSAnton Vorontsov if (ata_ratelimit())
2000a44fec1fSJoe Perches dev_warn(host->dev,
2001365cfa1eSAnton Vorontsov "interrupt on disabled port %u\n", i);
2002365cfa1eSAnton Vorontsov }
2003365cfa1eSAnton Vorontsov
2004365cfa1eSAnton Vorontsov handled = 1;
2005365cfa1eSAnton Vorontsov }
2006365cfa1eSAnton Vorontsov
2007a129db89SSuman Tripathi return handled;
2008a129db89SSuman Tripathi }
2009f070d671SSuman Tripathi EXPORT_SYMBOL_GPL(ahci_handle_port_intr);
2010a129db89SSuman Tripathi
ahci_single_level_irq_intr(int irq,void * dev_instance)2011a129db89SSuman Tripathi static irqreturn_t ahci_single_level_irq_intr(int irq, void *dev_instance)
2012a129db89SSuman Tripathi {
2013a129db89SSuman Tripathi struct ata_host *host = dev_instance;
2014a129db89SSuman Tripathi struct ahci_host_priv *hpriv;
2015a129db89SSuman Tripathi unsigned int rc = 0;
2016a129db89SSuman Tripathi void __iomem *mmio;
2017a129db89SSuman Tripathi u32 irq_stat, irq_masked;
2018a129db89SSuman Tripathi
2019a129db89SSuman Tripathi hpriv = host->private_data;
2020a129db89SSuman Tripathi mmio = hpriv->mmio;
2021a129db89SSuman Tripathi
2022a129db89SSuman Tripathi /* sigh. 0xffffffff is a valid return from h/w */
2023a129db89SSuman Tripathi irq_stat = readl(mmio + HOST_IRQ_STAT);
2024a129db89SSuman Tripathi if (!irq_stat)
2025a129db89SSuman Tripathi return IRQ_NONE;
2026a129db89SSuman Tripathi
2027a129db89SSuman Tripathi irq_masked = irq_stat & hpriv->port_map;
2028a129db89SSuman Tripathi
2029a129db89SSuman Tripathi spin_lock(&host->lock);
2030a129db89SSuman Tripathi
2031a129db89SSuman Tripathi rc = ahci_handle_port_intr(host, irq_masked);
2032a129db89SSuman Tripathi
2033365cfa1eSAnton Vorontsov /* HOST_IRQ_STAT behaves as level triggered latch meaning that
2034365cfa1eSAnton Vorontsov * it should be cleared after all the port events are cleared;
2035365cfa1eSAnton Vorontsov * otherwise, it will raise a spurious interrupt after each
2036365cfa1eSAnton Vorontsov * valid one. Please read section 10.6.2 of ahci 1.1 for more
2037365cfa1eSAnton Vorontsov * information.
2038365cfa1eSAnton Vorontsov *
2039365cfa1eSAnton Vorontsov * Also, use the unmasked value to clear interrupt as spurious
2040365cfa1eSAnton Vorontsov * pending event on a dummy port might cause screaming IRQ.
2041365cfa1eSAnton Vorontsov */
2042365cfa1eSAnton Vorontsov writel(irq_stat, mmio + HOST_IRQ_STAT);
2043365cfa1eSAnton Vorontsov
204403e83cbdSTejun Heo spin_unlock(&host->lock);
204503e83cbdSTejun Heo
2046a129db89SSuman Tripathi return IRQ_RETVAL(rc);
2047365cfa1eSAnton Vorontsov }
2048365cfa1eSAnton Vorontsov
ahci_qc_issue(struct ata_queued_cmd * qc)204939e0ee99SSuman Tripathi unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
2050365cfa1eSAnton Vorontsov {
2051365cfa1eSAnton Vorontsov struct ata_port *ap = qc->ap;
2052365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
2053365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
2054365cfa1eSAnton Vorontsov
2055365cfa1eSAnton Vorontsov /* Keep track of the currently active link. It will be used
2056365cfa1eSAnton Vorontsov * in completion path to determine whether NCQ phase is in
2057365cfa1eSAnton Vorontsov * progress.
2058365cfa1eSAnton Vorontsov */
2059365cfa1eSAnton Vorontsov pp->active_link = qc->dev->link;
2060365cfa1eSAnton Vorontsov
2061179b310aSHannes Reinecke if (ata_is_ncq(qc->tf.protocol))
20624e5b6260SJens Axboe writel(1 << qc->hw_tag, port_mmio + PORT_SCR_ACT);
2063365cfa1eSAnton Vorontsov
2064365cfa1eSAnton Vorontsov if (pp->fbs_enabled && pp->fbs_last_dev != qc->dev->link->pmp) {
2065365cfa1eSAnton Vorontsov u32 fbs = readl(port_mmio + PORT_FBS);
2066365cfa1eSAnton Vorontsov fbs &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC);
2067365cfa1eSAnton Vorontsov fbs |= qc->dev->link->pmp << PORT_FBS_DEV_OFFSET;
2068365cfa1eSAnton Vorontsov writel(fbs, port_mmio + PORT_FBS);
2069365cfa1eSAnton Vorontsov pp->fbs_last_dev = qc->dev->link->pmp;
2070365cfa1eSAnton Vorontsov }
2071365cfa1eSAnton Vorontsov
20724e5b6260SJens Axboe writel(1 << qc->hw_tag, port_mmio + PORT_CMD_ISSUE);
2073365cfa1eSAnton Vorontsov
2074365cfa1eSAnton Vorontsov ahci_sw_activity(qc->dev->link);
2075365cfa1eSAnton Vorontsov
2076365cfa1eSAnton Vorontsov return 0;
2077365cfa1eSAnton Vorontsov }
207839e0ee99SSuman Tripathi EXPORT_SYMBOL_GPL(ahci_qc_issue);
2079365cfa1eSAnton Vorontsov
ahci_qc_fill_rtf(struct ata_queued_cmd * qc)2080931139afSDamien Le Moal static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
2081365cfa1eSAnton Vorontsov {
2082365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = qc->ap->private_data;
20836ad60195STejun Heo u8 *rx_fis = pp->rx_fis;
2084365cfa1eSAnton Vorontsov
2085365cfa1eSAnton Vorontsov if (pp->fbs_enabled)
20866ad60195STejun Heo rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
2087365cfa1eSAnton Vorontsov
20886ad60195STejun Heo /*
20896ad60195STejun Heo * After a successful execution of an ATA PIO data-in command,
20906ad60195STejun Heo * the device doesn't send D2H Reg FIS to update the TF and
20916ad60195STejun Heo * the host should take TF and E_Status from the preceding PIO
20926ad60195STejun Heo * Setup FIS.
20936ad60195STejun Heo */
20946ad60195STejun Heo if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE &&
209587629312SNiklas Cassel !(qc->flags & ATA_QCFLAG_EH)) {
20966ad60195STejun Heo ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
2097efcef265SSergey Shtylyov qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15];
209893c4aa44SNiklas Cassel return;
209993c4aa44SNiklas Cassel }
21004ba09d20SNiklas Cassel
21014ba09d20SNiklas Cassel /*
21024ba09d20SNiklas Cassel * For NCQ commands, we never get a D2H FIS, so reading the D2H Register
21034ba09d20SNiklas Cassel * FIS area of the Received FIS Structure (which contains a copy of the
21044ba09d20SNiklas Cassel * last D2H FIS received) will contain an outdated status code.
21054ba09d20SNiklas Cassel * For NCQ commands, we instead get a SDB FIS, so read the SDB FIS area
21064ba09d20SNiklas Cassel * instead. However, the SDB FIS does not contain the LBA, so we can't
21074ba09d20SNiklas Cassel * use the ata_tf_from_fis() helper.
21084ba09d20SNiklas Cassel */
210993c4aa44SNiklas Cassel if (ata_is_ncq(qc->tf.protocol)) {
21104ba09d20SNiklas Cassel const u8 *fis = rx_fis + RX_FIS_SDB;
21114ba09d20SNiklas Cassel
211293c4aa44SNiklas Cassel /*
211393c4aa44SNiklas Cassel * Successful NCQ commands have been filled already.
211493c4aa44SNiklas Cassel * A failed NCQ command will read the status here.
211593c4aa44SNiklas Cassel * (Note that a failed NCQ command will get a more specific
211693c4aa44SNiklas Cassel * error when reading the NCQ Command Error log.)
211793c4aa44SNiklas Cassel */
21184ba09d20SNiklas Cassel qc->result_tf.status = fis[2];
21194ba09d20SNiklas Cassel qc->result_tf.error = fis[3];
212093c4aa44SNiklas Cassel return;
212193c4aa44SNiklas Cassel }
212293c4aa44SNiklas Cassel
21236ad60195STejun Heo ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
212493c4aa44SNiklas Cassel }
212593c4aa44SNiklas Cassel
ahci_qc_ncq_fill_rtf(struct ata_port * ap,u64 done_mask)212693c4aa44SNiklas Cassel static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask)
212793c4aa44SNiklas Cassel {
212893c4aa44SNiklas Cassel struct ahci_port_priv *pp = ap->private_data;
212993c4aa44SNiklas Cassel const u8 *fis;
213093c4aa44SNiklas Cassel
213193c4aa44SNiklas Cassel /* No outstanding commands. */
213293c4aa44SNiklas Cassel if (!ap->qc_active)
213393c4aa44SNiklas Cassel return;
213493c4aa44SNiklas Cassel
213593c4aa44SNiklas Cassel /*
213693c4aa44SNiklas Cassel * FBS not enabled, so read status and error once, since they are shared
213793c4aa44SNiklas Cassel * for all QCs.
213893c4aa44SNiklas Cassel */
213993c4aa44SNiklas Cassel if (!pp->fbs_enabled) {
214093c4aa44SNiklas Cassel u8 status, error;
214193c4aa44SNiklas Cassel
214293c4aa44SNiklas Cassel /* No outstanding NCQ commands. */
214393c4aa44SNiklas Cassel if (!pp->active_link->sactive)
214493c4aa44SNiklas Cassel return;
214593c4aa44SNiklas Cassel
214693c4aa44SNiklas Cassel fis = pp->rx_fis + RX_FIS_SDB;
214793c4aa44SNiklas Cassel status = fis[2];
214893c4aa44SNiklas Cassel error = fis[3];
214993c4aa44SNiklas Cassel
215093c4aa44SNiklas Cassel while (done_mask) {
215193c4aa44SNiklas Cassel struct ata_queued_cmd *qc;
215293c4aa44SNiklas Cassel unsigned int tag = __ffs64(done_mask);
215393c4aa44SNiklas Cassel
215493c4aa44SNiklas Cassel qc = ata_qc_from_tag(ap, tag);
215593c4aa44SNiklas Cassel if (qc && ata_is_ncq(qc->tf.protocol)) {
215693c4aa44SNiklas Cassel qc->result_tf.status = status;
215793c4aa44SNiklas Cassel qc->result_tf.error = error;
2158*2364dc21SIgor Pylypiv qc->result_tf.flags = qc->tf.flags;
215993c4aa44SNiklas Cassel qc->flags |= ATA_QCFLAG_RTF_FILLED;
216093c4aa44SNiklas Cassel }
216193c4aa44SNiklas Cassel done_mask &= ~(1ULL << tag);
216293c4aa44SNiklas Cassel }
216393c4aa44SNiklas Cassel
216493c4aa44SNiklas Cassel return;
216593c4aa44SNiklas Cassel }
216693c4aa44SNiklas Cassel
216793c4aa44SNiklas Cassel /*
216893c4aa44SNiklas Cassel * FBS enabled, so read the status and error for each QC, since the QCs
216993c4aa44SNiklas Cassel * can belong to different PMP links. (Each PMP link has its own FIS
217093c4aa44SNiklas Cassel * Receive Area.)
217193c4aa44SNiklas Cassel */
217293c4aa44SNiklas Cassel while (done_mask) {
217393c4aa44SNiklas Cassel struct ata_queued_cmd *qc;
217493c4aa44SNiklas Cassel unsigned int tag = __ffs64(done_mask);
217593c4aa44SNiklas Cassel
217693c4aa44SNiklas Cassel qc = ata_qc_from_tag(ap, tag);
217793c4aa44SNiklas Cassel if (qc && ata_is_ncq(qc->tf.protocol)) {
217893c4aa44SNiklas Cassel fis = pp->rx_fis;
217993c4aa44SNiklas Cassel fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ;
218093c4aa44SNiklas Cassel fis += RX_FIS_SDB;
218193c4aa44SNiklas Cassel qc->result_tf.status = fis[2];
218293c4aa44SNiklas Cassel qc->result_tf.error = fis[3];
2183*2364dc21SIgor Pylypiv qc->result_tf.flags = qc->tf.flags;
218493c4aa44SNiklas Cassel qc->flags |= ATA_QCFLAG_RTF_FILLED;
218593c4aa44SNiklas Cassel }
218693c4aa44SNiklas Cassel done_mask &= ~(1ULL << tag);
218793c4aa44SNiklas Cassel }
2188365cfa1eSAnton Vorontsov }
2189365cfa1eSAnton Vorontsov
ahci_freeze(struct ata_port * ap)2190365cfa1eSAnton Vorontsov static void ahci_freeze(struct ata_port *ap)
2191365cfa1eSAnton Vorontsov {
2192365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
2193365cfa1eSAnton Vorontsov
2194365cfa1eSAnton Vorontsov /* turn IRQ off */
2195365cfa1eSAnton Vorontsov writel(0, port_mmio + PORT_IRQ_MASK);
2196365cfa1eSAnton Vorontsov }
2197365cfa1eSAnton Vorontsov
ahci_thaw(struct ata_port * ap)2198365cfa1eSAnton Vorontsov static void ahci_thaw(struct ata_port *ap)
2199365cfa1eSAnton Vorontsov {
2200365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
2201365cfa1eSAnton Vorontsov void __iomem *mmio = hpriv->mmio;
2202365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
2203365cfa1eSAnton Vorontsov u32 tmp;
2204365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
2205365cfa1eSAnton Vorontsov
2206365cfa1eSAnton Vorontsov /* clear IRQ */
2207365cfa1eSAnton Vorontsov tmp = readl(port_mmio + PORT_IRQ_STAT);
2208365cfa1eSAnton Vorontsov writel(tmp, port_mmio + PORT_IRQ_STAT);
2209365cfa1eSAnton Vorontsov writel(1 << ap->port_no, mmio + HOST_IRQ_STAT);
2210365cfa1eSAnton Vorontsov
2211365cfa1eSAnton Vorontsov /* turn IRQ back on */
2212365cfa1eSAnton Vorontsov writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
2213365cfa1eSAnton Vorontsov }
2214365cfa1eSAnton Vorontsov
ahci_error_handler(struct ata_port * ap)22158b789d89SRichard Zhu void ahci_error_handler(struct ata_port *ap)
2216365cfa1eSAnton Vorontsov {
2217039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data;
2218039ece38SHans de Goede
22194cb7c6f1SNiklas Cassel if (!ata_port_is_frozen(ap)) {
2220365cfa1eSAnton Vorontsov /* restart engine */
2221fa89f53bSEvan Wang hpriv->stop_engine(ap);
2222039ece38SHans de Goede hpriv->start_engine(ap);
2223365cfa1eSAnton Vorontsov }
2224365cfa1eSAnton Vorontsov
2225365cfa1eSAnton Vorontsov sata_pmp_error_handler(ap);
22260ee71952STejun Heo
22270ee71952STejun Heo if (!ata_dev_enabled(ap->link.device))
2228fa89f53bSEvan Wang hpriv->stop_engine(ap);
2229365cfa1eSAnton Vorontsov }
22308b789d89SRichard Zhu EXPORT_SYMBOL_GPL(ahci_error_handler);
2231365cfa1eSAnton Vorontsov
ahci_post_internal_cmd(struct ata_queued_cmd * qc)2232365cfa1eSAnton Vorontsov static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
2233365cfa1eSAnton Vorontsov {
2234365cfa1eSAnton Vorontsov struct ata_port *ap = qc->ap;
2235365cfa1eSAnton Vorontsov
2236365cfa1eSAnton Vorontsov /* make DMA engine forget about the failed command */
223787629312SNiklas Cassel if (qc->flags & ATA_QCFLAG_EH)
2238365cfa1eSAnton Vorontsov ahci_kick_engine(ap);
2239365cfa1eSAnton Vorontsov }
2240365cfa1eSAnton Vorontsov
ahci_set_aggressive_devslp(struct ata_port * ap,bool sleep)224165fe1f0fSShane Huang static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
224265fe1f0fSShane Huang {
2243039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data;
224465fe1f0fSShane Huang void __iomem *port_mmio = ahci_port_base(ap);
224565fe1f0fSShane Huang struct ata_device *dev = ap->link.device;
224611c29146SSrinivas Pandruvada u32 devslp, dm, dito, mdat, deto, dito_conf;
224765fe1f0fSShane Huang int rc;
224865fe1f0fSShane Huang unsigned int err_mask;
224965fe1f0fSShane Huang
225065fe1f0fSShane Huang devslp = readl(port_mmio + PORT_DEVSLP);
225165fe1f0fSShane Huang if (!(devslp & PORT_DEVSLP_DSP)) {
225295bbbe9aSGabriele Mazzotta dev_info(ap->host->dev, "port does not support device sleep\n");
225365fe1f0fSShane Huang return;
225465fe1f0fSShane Huang }
225565fe1f0fSShane Huang
225665fe1f0fSShane Huang /* disable device sleep */
225765fe1f0fSShane Huang if (!sleep) {
225865fe1f0fSShane Huang if (devslp & PORT_DEVSLP_ADSE) {
225965fe1f0fSShane Huang writel(devslp & ~PORT_DEVSLP_ADSE,
226065fe1f0fSShane Huang port_mmio + PORT_DEVSLP);
226165fe1f0fSShane Huang err_mask = ata_dev_set_feature(dev,
226265fe1f0fSShane Huang SETFEATURES_SATA_DISABLE,
226365fe1f0fSShane Huang SATA_DEVSLP);
226465fe1f0fSShane Huang if (err_mask && err_mask != AC_ERR_DEV)
226565fe1f0fSShane Huang ata_dev_warn(dev, "failed to disable DEVSLP\n");
226665fe1f0fSShane Huang }
226765fe1f0fSShane Huang return;
226865fe1f0fSShane Huang }
226965fe1f0fSShane Huang
227011c29146SSrinivas Pandruvada dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
227111c29146SSrinivas Pandruvada dito = devslp_idle_timeout / (dm + 1);
227211c29146SSrinivas Pandruvada if (dito > 0x3ff)
227311c29146SSrinivas Pandruvada dito = 0x3ff;
227411c29146SSrinivas Pandruvada
227511c29146SSrinivas Pandruvada dito_conf = (devslp >> PORT_DEVSLP_DITO_OFFSET) & 0x3FF;
227611c29146SSrinivas Pandruvada
227711c29146SSrinivas Pandruvada /* device sleep was already enabled and same dito */
227811c29146SSrinivas Pandruvada if ((devslp & PORT_DEVSLP_ADSE) && (dito_conf == dito))
227965fe1f0fSShane Huang return;
228065fe1f0fSShane Huang
228165fe1f0fSShane Huang /* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */
2282fa89f53bSEvan Wang rc = hpriv->stop_engine(ap);
228365fe1f0fSShane Huang if (rc)
228465fe1f0fSShane Huang return;
228565fe1f0fSShane Huang
228665fe1f0fSShane Huang /* Use the nominal value 10 ms if the read MDAT is zero,
228765fe1f0fSShane Huang * the nominal value of DETO is 20 ms.
228865fe1f0fSShane Huang */
2289803739d2SShane Huang if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
229065fe1f0fSShane Huang ATA_LOG_DEVSLP_VALID_MASK) {
2291803739d2SShane Huang mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
229265fe1f0fSShane Huang ATA_LOG_DEVSLP_MDAT_MASK;
229365fe1f0fSShane Huang if (!mdat)
229465fe1f0fSShane Huang mdat = 10;
2295803739d2SShane Huang deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
229665fe1f0fSShane Huang if (!deto)
229765fe1f0fSShane Huang deto = 20;
229865fe1f0fSShane Huang } else {
229965fe1f0fSShane Huang mdat = 10;
230065fe1f0fSShane Huang deto = 20;
230165fe1f0fSShane Huang }
230265fe1f0fSShane Huang
23032dbb3ec2SSrinivas Pandruvada /* Make dito, mdat, deto bits to 0s */
23042dbb3ec2SSrinivas Pandruvada devslp &= ~GENMASK_ULL(24, 2);
230565fe1f0fSShane Huang devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) |
230665fe1f0fSShane Huang (mdat << PORT_DEVSLP_MDAT_OFFSET) |
230765fe1f0fSShane Huang (deto << PORT_DEVSLP_DETO_OFFSET) |
230865fe1f0fSShane Huang PORT_DEVSLP_ADSE);
230965fe1f0fSShane Huang writel(devslp, port_mmio + PORT_DEVSLP);
231065fe1f0fSShane Huang
2311039ece38SHans de Goede hpriv->start_engine(ap);
231265fe1f0fSShane Huang
231365fe1f0fSShane Huang /* enable device sleep feature for the drive */
231465fe1f0fSShane Huang err_mask = ata_dev_set_feature(dev,
231565fe1f0fSShane Huang SETFEATURES_SATA_ENABLE,
231665fe1f0fSShane Huang SATA_DEVSLP);
231765fe1f0fSShane Huang if (err_mask && err_mask != AC_ERR_DEV)
231865fe1f0fSShane Huang ata_dev_warn(dev, "failed to enable DEVSLP\n");
231965fe1f0fSShane Huang }
232065fe1f0fSShane Huang
ahci_enable_fbs(struct ata_port * ap)2321365cfa1eSAnton Vorontsov static void ahci_enable_fbs(struct ata_port *ap)
2322365cfa1eSAnton Vorontsov {
2323039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data;
2324365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
2325365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
2326365cfa1eSAnton Vorontsov u32 fbs;
2327365cfa1eSAnton Vorontsov int rc;
2328365cfa1eSAnton Vorontsov
2329365cfa1eSAnton Vorontsov if (!pp->fbs_supported)
2330365cfa1eSAnton Vorontsov return;
2331365cfa1eSAnton Vorontsov
2332365cfa1eSAnton Vorontsov fbs = readl(port_mmio + PORT_FBS);
2333365cfa1eSAnton Vorontsov if (fbs & PORT_FBS_EN) {
2334365cfa1eSAnton Vorontsov pp->fbs_enabled = true;
2335365cfa1eSAnton Vorontsov pp->fbs_last_dev = -1; /* initialization */
2336365cfa1eSAnton Vorontsov return;
2337365cfa1eSAnton Vorontsov }
2338365cfa1eSAnton Vorontsov
2339fa89f53bSEvan Wang rc = hpriv->stop_engine(ap);
2340365cfa1eSAnton Vorontsov if (rc)
2341365cfa1eSAnton Vorontsov return;
2342365cfa1eSAnton Vorontsov
2343365cfa1eSAnton Vorontsov writel(fbs | PORT_FBS_EN, port_mmio + PORT_FBS);
2344365cfa1eSAnton Vorontsov fbs = readl(port_mmio + PORT_FBS);
2345365cfa1eSAnton Vorontsov if (fbs & PORT_FBS_EN) {
2346a44fec1fSJoe Perches dev_info(ap->host->dev, "FBS is enabled\n");
2347365cfa1eSAnton Vorontsov pp->fbs_enabled = true;
2348365cfa1eSAnton Vorontsov pp->fbs_last_dev = -1; /* initialization */
2349365cfa1eSAnton Vorontsov } else
2350a44fec1fSJoe Perches dev_err(ap->host->dev, "Failed to enable FBS\n");
2351365cfa1eSAnton Vorontsov
2352039ece38SHans de Goede hpriv->start_engine(ap);
2353365cfa1eSAnton Vorontsov }
2354365cfa1eSAnton Vorontsov
ahci_disable_fbs(struct ata_port * ap)2355365cfa1eSAnton Vorontsov static void ahci_disable_fbs(struct ata_port *ap)
2356365cfa1eSAnton Vorontsov {
2357039ece38SHans de Goede struct ahci_host_priv *hpriv = ap->host->private_data;
2358365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
2359365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
2360365cfa1eSAnton Vorontsov u32 fbs;
2361365cfa1eSAnton Vorontsov int rc;
2362365cfa1eSAnton Vorontsov
2363365cfa1eSAnton Vorontsov if (!pp->fbs_supported)
2364365cfa1eSAnton Vorontsov return;
2365365cfa1eSAnton Vorontsov
2366365cfa1eSAnton Vorontsov fbs = readl(port_mmio + PORT_FBS);
2367365cfa1eSAnton Vorontsov if ((fbs & PORT_FBS_EN) == 0) {
2368365cfa1eSAnton Vorontsov pp->fbs_enabled = false;
2369365cfa1eSAnton Vorontsov return;
2370365cfa1eSAnton Vorontsov }
2371365cfa1eSAnton Vorontsov
2372fa89f53bSEvan Wang rc = hpriv->stop_engine(ap);
2373365cfa1eSAnton Vorontsov if (rc)
2374365cfa1eSAnton Vorontsov return;
2375365cfa1eSAnton Vorontsov
2376365cfa1eSAnton Vorontsov writel(fbs & ~PORT_FBS_EN, port_mmio + PORT_FBS);
2377365cfa1eSAnton Vorontsov fbs = readl(port_mmio + PORT_FBS);
2378365cfa1eSAnton Vorontsov if (fbs & PORT_FBS_EN)
2379a44fec1fSJoe Perches dev_err(ap->host->dev, "Failed to disable FBS\n");
2380365cfa1eSAnton Vorontsov else {
2381a44fec1fSJoe Perches dev_info(ap->host->dev, "FBS is disabled\n");
2382365cfa1eSAnton Vorontsov pp->fbs_enabled = false;
2383365cfa1eSAnton Vorontsov }
2384365cfa1eSAnton Vorontsov
2385039ece38SHans de Goede hpriv->start_engine(ap);
2386365cfa1eSAnton Vorontsov }
2387365cfa1eSAnton Vorontsov
ahci_pmp_attach(struct ata_port * ap)2388365cfa1eSAnton Vorontsov static void ahci_pmp_attach(struct ata_port *ap)
2389365cfa1eSAnton Vorontsov {
2390365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
2391365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
2392365cfa1eSAnton Vorontsov u32 cmd;
2393365cfa1eSAnton Vorontsov
2394365cfa1eSAnton Vorontsov cmd = readl(port_mmio + PORT_CMD);
2395365cfa1eSAnton Vorontsov cmd |= PORT_CMD_PMP;
2396365cfa1eSAnton Vorontsov writel(cmd, port_mmio + PORT_CMD);
2397365cfa1eSAnton Vorontsov
2398365cfa1eSAnton Vorontsov ahci_enable_fbs(ap);
2399365cfa1eSAnton Vorontsov
2400365cfa1eSAnton Vorontsov pp->intr_mask |= PORT_IRQ_BAD_PMP;
24017b3a24c5SMaxime Bizon
24027b3a24c5SMaxime Bizon /*
24037b3a24c5SMaxime Bizon * We must not change the port interrupt mask register if the
24047b3a24c5SMaxime Bizon * port is marked frozen, the value in pp->intr_mask will be
24057b3a24c5SMaxime Bizon * restored later when the port is thawed.
24067b3a24c5SMaxime Bizon *
24077b3a24c5SMaxime Bizon * Note that during initialization, the port is marked as
24087b3a24c5SMaxime Bizon * frozen since the irq handler is not yet registered.
24097b3a24c5SMaxime Bizon */
24104cb7c6f1SNiklas Cassel if (!ata_port_is_frozen(ap))
2411365cfa1eSAnton Vorontsov writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
2412365cfa1eSAnton Vorontsov }
2413365cfa1eSAnton Vorontsov
ahci_pmp_detach(struct ata_port * ap)2414365cfa1eSAnton Vorontsov static void ahci_pmp_detach(struct ata_port *ap)
2415365cfa1eSAnton Vorontsov {
2416365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
2417365cfa1eSAnton Vorontsov struct ahci_port_priv *pp = ap->private_data;
2418365cfa1eSAnton Vorontsov u32 cmd;
2419365cfa1eSAnton Vorontsov
2420365cfa1eSAnton Vorontsov ahci_disable_fbs(ap);
2421365cfa1eSAnton Vorontsov
2422365cfa1eSAnton Vorontsov cmd = readl(port_mmio + PORT_CMD);
2423365cfa1eSAnton Vorontsov cmd &= ~PORT_CMD_PMP;
2424365cfa1eSAnton Vorontsov writel(cmd, port_mmio + PORT_CMD);
2425365cfa1eSAnton Vorontsov
2426365cfa1eSAnton Vorontsov pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
24277b3a24c5SMaxime Bizon
24287b3a24c5SMaxime Bizon /* see comment above in ahci_pmp_attach() */
24294cb7c6f1SNiklas Cassel if (!ata_port_is_frozen(ap))
2430365cfa1eSAnton Vorontsov writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
2431365cfa1eSAnton Vorontsov }
2432365cfa1eSAnton Vorontsov
ahci_port_resume(struct ata_port * ap)243302cdfcf0SDavid Milburn int ahci_port_resume(struct ata_port *ap)
2434365cfa1eSAnton Vorontsov {
2435bb03c640SMika Westerberg ahci_rpm_get_port(ap);
2436bb03c640SMika Westerberg
2437365cfa1eSAnton Vorontsov ahci_power_up(ap);
2438365cfa1eSAnton Vorontsov ahci_start_port(ap);
2439365cfa1eSAnton Vorontsov
2440365cfa1eSAnton Vorontsov if (sata_pmp_attached(ap))
2441365cfa1eSAnton Vorontsov ahci_pmp_attach(ap);
2442365cfa1eSAnton Vorontsov else
2443365cfa1eSAnton Vorontsov ahci_pmp_detach(ap);
2444365cfa1eSAnton Vorontsov
2445365cfa1eSAnton Vorontsov return 0;
2446365cfa1eSAnton Vorontsov }
244702cdfcf0SDavid Milburn EXPORT_SYMBOL_GPL(ahci_port_resume);
2448365cfa1eSAnton Vorontsov
2449365cfa1eSAnton Vorontsov #ifdef CONFIG_PM
ahci_handle_s2idle(struct ata_port * ap)24507c5f641aSMario Limonciello static void ahci_handle_s2idle(struct ata_port *ap)
24517c5f641aSMario Limonciello {
24527c5f641aSMario Limonciello void __iomem *port_mmio = ahci_port_base(ap);
24537c5f641aSMario Limonciello u32 devslp;
24547c5f641aSMario Limonciello
24557c5f641aSMario Limonciello if (pm_suspend_via_firmware())
24567c5f641aSMario Limonciello return;
24577c5f641aSMario Limonciello devslp = readl(port_mmio + PORT_DEVSLP);
24587c5f641aSMario Limonciello if ((devslp & PORT_DEVSLP_ADSE))
24597c5f641aSMario Limonciello ata_msleep(ap, devslp_idle_timeout);
24607c5f641aSMario Limonciello }
24617c5f641aSMario Limonciello
ahci_port_suspend(struct ata_port * ap,pm_message_t mesg)2462365cfa1eSAnton Vorontsov static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
2463365cfa1eSAnton Vorontsov {
2464365cfa1eSAnton Vorontsov const char *emsg = NULL;
2465365cfa1eSAnton Vorontsov int rc;
2466365cfa1eSAnton Vorontsov
2467365cfa1eSAnton Vorontsov rc = ahci_deinit_port(ap, &emsg);
2468365cfa1eSAnton Vorontsov if (rc == 0)
2469365cfa1eSAnton Vorontsov ahci_power_down(ap);
2470365cfa1eSAnton Vorontsov else {
2471a9a79dfeSJoe Perches ata_port_err(ap, "%s (%d)\n", emsg, rc);
24727faa33daSTejun Heo ata_port_freeze(ap);
2473365cfa1eSAnton Vorontsov }
2474365cfa1eSAnton Vorontsov
24757c5f641aSMario Limonciello if (acpi_storage_d3(ap->host->dev))
24767c5f641aSMario Limonciello ahci_handle_s2idle(ap);
24777c5f641aSMario Limonciello
2478bb03c640SMika Westerberg ahci_rpm_put_port(ap);
2479365cfa1eSAnton Vorontsov return rc;
2480365cfa1eSAnton Vorontsov }
2481365cfa1eSAnton Vorontsov #endif
2482365cfa1eSAnton Vorontsov
ahci_port_start(struct ata_port * ap)2483365cfa1eSAnton Vorontsov static int ahci_port_start(struct ata_port *ap)
2484365cfa1eSAnton Vorontsov {
2485365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = ap->host->private_data;
2486365cfa1eSAnton Vorontsov struct device *dev = ap->host->dev;
2487365cfa1eSAnton Vorontsov struct ahci_port_priv *pp;
2488365cfa1eSAnton Vorontsov void *mem;
2489365cfa1eSAnton Vorontsov dma_addr_t mem_dma;
2490365cfa1eSAnton Vorontsov size_t dma_sz, rx_fis_sz;
2491365cfa1eSAnton Vorontsov
2492365cfa1eSAnton Vorontsov pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
2493365cfa1eSAnton Vorontsov if (!pp)
2494365cfa1eSAnton Vorontsov return -ENOMEM;
2495365cfa1eSAnton Vorontsov
2496b29900e6SAlexander Gordeev if (ap->host->n_ports > 1) {
2497b29900e6SAlexander Gordeev pp->irq_desc = devm_kzalloc(dev, 8, GFP_KERNEL);
2498b29900e6SAlexander Gordeev if (!pp->irq_desc) {
2499b29900e6SAlexander Gordeev devm_kfree(dev, pp);
2500b29900e6SAlexander Gordeev return -ENOMEM;
2501b29900e6SAlexander Gordeev }
2502b29900e6SAlexander Gordeev snprintf(pp->irq_desc, 8,
2503b29900e6SAlexander Gordeev "%s%d", dev_driver_string(dev), ap->port_no);
2504b29900e6SAlexander Gordeev }
2505b29900e6SAlexander Gordeev
2506365cfa1eSAnton Vorontsov /* check FBS capability */
2507365cfa1eSAnton Vorontsov if ((hpriv->cap & HOST_CAP_FBS) && sata_pmp_supported(ap)) {
2508365cfa1eSAnton Vorontsov void __iomem *port_mmio = ahci_port_base(ap);
2509365cfa1eSAnton Vorontsov u32 cmd = readl(port_mmio + PORT_CMD);
2510365cfa1eSAnton Vorontsov if (cmd & PORT_CMD_FBSCP)
2511365cfa1eSAnton Vorontsov pp->fbs_supported = true;
25125f173107STejun Heo else if (hpriv->flags & AHCI_HFLAG_YES_FBS) {
2513a44fec1fSJoe Perches dev_info(dev, "port %d can do FBS, forcing FBSCP\n",
25145f173107STejun Heo ap->port_no);
25155f173107STejun Heo pp->fbs_supported = true;
25165f173107STejun Heo } else
2517a44fec1fSJoe Perches dev_warn(dev, "port %d is not capable of FBS\n",
25185f173107STejun Heo ap->port_no);
2519365cfa1eSAnton Vorontsov }
2520365cfa1eSAnton Vorontsov
2521365cfa1eSAnton Vorontsov if (pp->fbs_supported) {
2522365cfa1eSAnton Vorontsov dma_sz = AHCI_PORT_PRIV_FBS_DMA_SZ;
2523365cfa1eSAnton Vorontsov rx_fis_sz = AHCI_RX_FIS_SZ * 16;
2524365cfa1eSAnton Vorontsov } else {
2525365cfa1eSAnton Vorontsov dma_sz = AHCI_PORT_PRIV_DMA_SZ;
2526365cfa1eSAnton Vorontsov rx_fis_sz = AHCI_RX_FIS_SZ;
2527365cfa1eSAnton Vorontsov }
2528365cfa1eSAnton Vorontsov
2529365cfa1eSAnton Vorontsov mem = dmam_alloc_coherent(dev, dma_sz, &mem_dma, GFP_KERNEL);
2530365cfa1eSAnton Vorontsov if (!mem)
2531365cfa1eSAnton Vorontsov return -ENOMEM;
2532365cfa1eSAnton Vorontsov
2533365cfa1eSAnton Vorontsov /*
2534365cfa1eSAnton Vorontsov * First item in chunk of DMA memory: 32-slot command table,
2535365cfa1eSAnton Vorontsov * 32 bytes each in size
2536365cfa1eSAnton Vorontsov */
2537365cfa1eSAnton Vorontsov pp->cmd_slot = mem;
2538365cfa1eSAnton Vorontsov pp->cmd_slot_dma = mem_dma;
2539365cfa1eSAnton Vorontsov
2540365cfa1eSAnton Vorontsov mem += AHCI_CMD_SLOT_SZ;
2541365cfa1eSAnton Vorontsov mem_dma += AHCI_CMD_SLOT_SZ;
2542365cfa1eSAnton Vorontsov
2543365cfa1eSAnton Vorontsov /*
2544365cfa1eSAnton Vorontsov * Second item: Received-FIS area
2545365cfa1eSAnton Vorontsov */
2546365cfa1eSAnton Vorontsov pp->rx_fis = mem;
2547365cfa1eSAnton Vorontsov pp->rx_fis_dma = mem_dma;
2548365cfa1eSAnton Vorontsov
2549365cfa1eSAnton Vorontsov mem += rx_fis_sz;
2550365cfa1eSAnton Vorontsov mem_dma += rx_fis_sz;
2551365cfa1eSAnton Vorontsov
2552365cfa1eSAnton Vorontsov /*
2553365cfa1eSAnton Vorontsov * Third item: data area for storing a single command
2554365cfa1eSAnton Vorontsov * and its scatter-gather table
2555365cfa1eSAnton Vorontsov */
2556365cfa1eSAnton Vorontsov pp->cmd_tbl = mem;
2557365cfa1eSAnton Vorontsov pp->cmd_tbl_dma = mem_dma;
2558365cfa1eSAnton Vorontsov
2559365cfa1eSAnton Vorontsov /*
2560365cfa1eSAnton Vorontsov * Save off initial list of interrupts to be enabled.
2561365cfa1eSAnton Vorontsov * This could be changed later
2562365cfa1eSAnton Vorontsov */
2563365cfa1eSAnton Vorontsov pp->intr_mask = DEF_PORT_IRQ;
2564365cfa1eSAnton Vorontsov
25657865f83fSTejun Heo /*
25667865f83fSTejun Heo * Switch to per-port locking in case each port has its own MSI vector.
25677865f83fSTejun Heo */
25680b9e2988SChristoph Hellwig if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) {
25695ca72c4fSAlexander Gordeev spin_lock_init(&pp->lock);
25705ca72c4fSAlexander Gordeev ap->lock = &pp->lock;
25717865f83fSTejun Heo }
25725ca72c4fSAlexander Gordeev
2573365cfa1eSAnton Vorontsov ap->private_data = pp;
2574365cfa1eSAnton Vorontsov
2575365cfa1eSAnton Vorontsov /* engage engines, captain */
2576365cfa1eSAnton Vorontsov return ahci_port_resume(ap);
2577365cfa1eSAnton Vorontsov }
2578365cfa1eSAnton Vorontsov
ahci_port_stop(struct ata_port * ap)2579365cfa1eSAnton Vorontsov static void ahci_port_stop(struct ata_port *ap)
2580365cfa1eSAnton Vorontsov {
2581365cfa1eSAnton Vorontsov const char *emsg = NULL;
25820516900aSPang Raymond struct ahci_host_priv *hpriv = ap->host->private_data;
25830516900aSPang Raymond void __iomem *host_mmio = hpriv->mmio;
2584365cfa1eSAnton Vorontsov int rc;
2585365cfa1eSAnton Vorontsov
2586365cfa1eSAnton Vorontsov /* de-initialize port */
2587365cfa1eSAnton Vorontsov rc = ahci_deinit_port(ap, &emsg);
2588365cfa1eSAnton Vorontsov if (rc)
2589a9a79dfeSJoe Perches ata_port_warn(ap, "%s (%d)\n", emsg, rc);
25900516900aSPang Raymond
25910516900aSPang Raymond /*
25920516900aSPang Raymond * Clear GHC.IS to prevent stuck INTx after disabling MSI and
25930516900aSPang Raymond * re-enabling INTx.
25940516900aSPang Raymond */
25950516900aSPang Raymond writel(1 << ap->port_no, host_mmio + HOST_IRQ_STAT);
2596332c42a9SSamuel Morris
2597332c42a9SSamuel Morris ahci_rpm_put_port(ap);
2598365cfa1eSAnton Vorontsov }
2599365cfa1eSAnton Vorontsov
ahci_print_info(struct ata_host * host,const char * scc_s)2600365cfa1eSAnton Vorontsov void ahci_print_info(struct ata_host *host, const char *scc_s)
2601365cfa1eSAnton Vorontsov {
2602365cfa1eSAnton Vorontsov struct ahci_host_priv *hpriv = host->private_data;
2603365cfa1eSAnton Vorontsov u32 vers, cap, cap2, impl, speed;
2604365cfa1eSAnton Vorontsov const char *speed_s;
2605365cfa1eSAnton Vorontsov
26068ea909cbSMika Westerberg vers = hpriv->version;
2607365cfa1eSAnton Vorontsov cap = hpriv->cap;
2608365cfa1eSAnton Vorontsov cap2 = hpriv->cap2;
2609365cfa1eSAnton Vorontsov impl = hpriv->port_map;
2610365cfa1eSAnton Vorontsov
2611365cfa1eSAnton Vorontsov speed = (cap >> 20) & 0xf;
2612365cfa1eSAnton Vorontsov if (speed == 1)
2613365cfa1eSAnton Vorontsov speed_s = "1.5";
2614365cfa1eSAnton Vorontsov else if (speed == 2)
2615365cfa1eSAnton Vorontsov speed_s = "3";
2616365cfa1eSAnton Vorontsov else if (speed == 3)
2617365cfa1eSAnton Vorontsov speed_s = "6";
2618365cfa1eSAnton Vorontsov else
2619365cfa1eSAnton Vorontsov speed_s = "?";
2620365cfa1eSAnton Vorontsov
2621365cfa1eSAnton Vorontsov dev_info(host->dev,
2622365cfa1eSAnton Vorontsov "AHCI %02x%02x.%02x%02x "
2623365cfa1eSAnton Vorontsov "%u slots %u ports %s Gbps 0x%x impl %s mode\n"
2624365cfa1eSAnton Vorontsov ,
2625365cfa1eSAnton Vorontsov
2626365cfa1eSAnton Vorontsov (vers >> 24) & 0xff,
2627365cfa1eSAnton Vorontsov (vers >> 16) & 0xff,
2628365cfa1eSAnton Vorontsov (vers >> 8) & 0xff,
2629365cfa1eSAnton Vorontsov vers & 0xff,
2630365cfa1eSAnton Vorontsov
2631365cfa1eSAnton Vorontsov ((cap >> 8) & 0x1f) + 1,
2632365cfa1eSAnton Vorontsov (cap & 0x1f) + 1,
2633365cfa1eSAnton Vorontsov speed_s,
2634365cfa1eSAnton Vorontsov impl,
2635365cfa1eSAnton Vorontsov scc_s);
2636365cfa1eSAnton Vorontsov
2637365cfa1eSAnton Vorontsov dev_info(host->dev,
2638365cfa1eSAnton Vorontsov "flags: "
2639365cfa1eSAnton Vorontsov "%s%s%s%s%s%s%s"
2640365cfa1eSAnton Vorontsov "%s%s%s%s%s%s%s"
264165fe1f0fSShane Huang "%s%s%s%s%s%s%s"
264265fe1f0fSShane Huang "%s%s\n"
2643365cfa1eSAnton Vorontsov ,
2644365cfa1eSAnton Vorontsov
2645365cfa1eSAnton Vorontsov cap & HOST_CAP_64 ? "64bit " : "",
2646365cfa1eSAnton Vorontsov cap & HOST_CAP_NCQ ? "ncq " : "",
2647365cfa1eSAnton Vorontsov cap & HOST_CAP_SNTF ? "sntf " : "",
2648365cfa1eSAnton Vorontsov cap & HOST_CAP_MPS ? "ilck " : "",
2649365cfa1eSAnton Vorontsov cap & HOST_CAP_SSS ? "stag " : "",
2650365cfa1eSAnton Vorontsov cap & HOST_CAP_ALPM ? "pm " : "",
2651365cfa1eSAnton Vorontsov cap & HOST_CAP_LED ? "led " : "",
2652365cfa1eSAnton Vorontsov cap & HOST_CAP_CLO ? "clo " : "",
2653365cfa1eSAnton Vorontsov cap & HOST_CAP_ONLY ? "only " : "",
2654365cfa1eSAnton Vorontsov cap & HOST_CAP_PMP ? "pmp " : "",
2655365cfa1eSAnton Vorontsov cap & HOST_CAP_FBS ? "fbs " : "",
2656365cfa1eSAnton Vorontsov cap & HOST_CAP_PIO_MULTI ? "pio " : "",
2657365cfa1eSAnton Vorontsov cap & HOST_CAP_SSC ? "slum " : "",
2658365cfa1eSAnton Vorontsov cap & HOST_CAP_PART ? "part " : "",
2659365cfa1eSAnton Vorontsov cap & HOST_CAP_CCC ? "ccc " : "",
2660365cfa1eSAnton Vorontsov cap & HOST_CAP_EMS ? "ems " : "",
2661365cfa1eSAnton Vorontsov cap & HOST_CAP_SXS ? "sxs " : "",
266265fe1f0fSShane Huang cap2 & HOST_CAP2_DESO ? "deso " : "",
266365fe1f0fSShane Huang cap2 & HOST_CAP2_SADM ? "sadm " : "",
266465fe1f0fSShane Huang cap2 & HOST_CAP2_SDS ? "sds " : "",
2665365cfa1eSAnton Vorontsov cap2 & HOST_CAP2_APST ? "apst " : "",
2666365cfa1eSAnton Vorontsov cap2 & HOST_CAP2_NVMHCI ? "nvmp " : "",
2667365cfa1eSAnton Vorontsov cap2 & HOST_CAP2_BOH ? "boh " : ""
2668365cfa1eSAnton Vorontsov );
2669365cfa1eSAnton Vorontsov }
2670365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_print_info);
2671365cfa1eSAnton Vorontsov
ahci_set_em_messages(struct ahci_host_priv * hpriv,struct ata_port_info * pi)2672365cfa1eSAnton Vorontsov void ahci_set_em_messages(struct ahci_host_priv *hpriv,
2673365cfa1eSAnton Vorontsov struct ata_port_info *pi)
2674365cfa1eSAnton Vorontsov {
2675365cfa1eSAnton Vorontsov u8 messages;
2676365cfa1eSAnton Vorontsov void __iomem *mmio = hpriv->mmio;
2677365cfa1eSAnton Vorontsov u32 em_loc = readl(mmio + HOST_EM_LOC);
2678365cfa1eSAnton Vorontsov u32 em_ctl = readl(mmio + HOST_EM_CTL);
2679365cfa1eSAnton Vorontsov
2680365cfa1eSAnton Vorontsov if (!ahci_em_messages || !(hpriv->cap & HOST_CAP_EMS))
2681365cfa1eSAnton Vorontsov return;
2682365cfa1eSAnton Vorontsov
2683365cfa1eSAnton Vorontsov messages = (em_ctl & EM_CTRL_MSG_TYPE) >> 16;
2684365cfa1eSAnton Vorontsov
2685008dbd61SHarry Zhang if (messages) {
2686365cfa1eSAnton Vorontsov /* store em_loc */
2687365cfa1eSAnton Vorontsov hpriv->em_loc = ((em_loc >> 16) * 4);
2688c0623166SHarry Zhang hpriv->em_buf_sz = ((em_loc & 0xff) * 4);
2689008dbd61SHarry Zhang hpriv->em_msg_type = messages;
2690365cfa1eSAnton Vorontsov pi->flags |= ATA_FLAG_EM;
2691365cfa1eSAnton Vorontsov if (!(em_ctl & EM_CTL_ALHD))
2692365cfa1eSAnton Vorontsov pi->flags |= ATA_FLAG_SW_ACTIVITY;
2693365cfa1eSAnton Vorontsov }
2694365cfa1eSAnton Vorontsov }
2695365cfa1eSAnton Vorontsov EXPORT_SYMBOL_GPL(ahci_set_em_messages);
2696365cfa1eSAnton Vorontsov
ahci_host_activate_multi_irqs(struct ata_host * host,const struct scsi_host_template * sht)2697d684a90dSDan Williams static int ahci_host_activate_multi_irqs(struct ata_host *host,
269825df73d9SBart Van Assche const struct scsi_host_template *sht)
26991c62854fSAlexander Gordeev {
2700d684a90dSDan Williams struct ahci_host_priv *hpriv = host->private_data;
27011c62854fSAlexander Gordeev int i, rc;
27021c62854fSAlexander Gordeev
27031c62854fSAlexander Gordeev rc = ata_host_start(host);
27041c62854fSAlexander Gordeev if (rc)
27051c62854fSAlexander Gordeev return rc;
270621bfd1aaSRobert Richter /*
270721bfd1aaSRobert Richter * Requests IRQs according to AHCI-1.1 when multiple MSIs were
270821bfd1aaSRobert Richter * allocated. That is one MSI per port, starting from @irq.
270921bfd1aaSRobert Richter */
27101c62854fSAlexander Gordeev for (i = 0; i < host->n_ports; i++) {
27111c62854fSAlexander Gordeev struct ahci_port_priv *pp = host->ports[i]->private_data;
27120b9e2988SChristoph Hellwig int irq = hpriv->get_irq_vector(host, i);
27131c62854fSAlexander Gordeev
27141c62854fSAlexander Gordeev /* Do not receive interrupts sent by dummy ports */
27151c62854fSAlexander Gordeev if (!pp) {
27169b4b3f6aSChristoph Hellwig disable_irq(irq);
27171c62854fSAlexander Gordeev continue;
27181c62854fSAlexander Gordeev }
27191c62854fSAlexander Gordeev
2720a6b7fb76SDan Williams rc = devm_request_irq(host->dev, irq, ahci_multi_irqs_intr_hard,
2721a6b7fb76SDan Williams 0, pp->irq_desc, host->ports[i]);
2722a6b7fb76SDan Williams
27231c62854fSAlexander Gordeev if (rc)
27241c62854fSAlexander Gordeev return rc;
2725d684a90dSDan Williams ata_port_desc(host->ports[i], "irq %d", irq);
27260a142b26SDan Williams }
2727d684a90dSDan Williams
27280a142b26SDan Williams return ata_host_register(host, sht);
27291c62854fSAlexander Gordeev }
2730d1028e2fSAlexander Gordeev
2731d1028e2fSAlexander Gordeev /**
2732d1028e2fSAlexander Gordeev * ahci_host_activate - start AHCI host, request IRQs and register it
2733d1028e2fSAlexander Gordeev * @host: target ATA host
2734d1028e2fSAlexander Gordeev * @sht: scsi_host_template to use when registering the host
2735d1028e2fSAlexander Gordeev *
2736d1028e2fSAlexander Gordeev * LOCKING:
2737d1028e2fSAlexander Gordeev * Inherited from calling layer (may sleep).
2738d1028e2fSAlexander Gordeev *
2739d1028e2fSAlexander Gordeev * RETURNS:
2740d1028e2fSAlexander Gordeev * 0 on success, -errno otherwise.
2741d1028e2fSAlexander Gordeev */
ahci_host_activate(struct ata_host * host,const struct scsi_host_template * sht)274225df73d9SBart Van Assche int ahci_host_activate(struct ata_host *host, const struct scsi_host_template *sht)
2743d1028e2fSAlexander Gordeev {
2744d1028e2fSAlexander Gordeev struct ahci_host_priv *hpriv = host->private_data;
274521bfd1aaSRobert Richter int irq = hpriv->irq;
2746d1028e2fSAlexander Gordeev int rc;
2747d1028e2fSAlexander Gordeev
27480b9e2988SChristoph Hellwig if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) {
27493bac408aSJohn Garry if (hpriv->irq_handler &&
27503bac408aSJohn Garry hpriv->irq_handler != ahci_single_level_irq_intr)
2751d991c872SSander Eikelenboom dev_warn(host->dev,
2752d991c872SSander Eikelenboom "both AHCI_HFLAG_MULTI_MSI flag set and custom irq handler implemented\n");
27530b9e2988SChristoph Hellwig if (!hpriv->get_irq_vector) {
27540b9e2988SChristoph Hellwig dev_err(host->dev,
27550b9e2988SChristoph Hellwig "AHCI_HFLAG_MULTI_MSI requires ->get_irq_vector!\n");
27560b9e2988SChristoph Hellwig return -EIO;
27570b9e2988SChristoph Hellwig }
2758f070d671SSuman Tripathi
2759d684a90dSDan Williams rc = ahci_host_activate_multi_irqs(host, sht);
2760f070d671SSuman Tripathi } else {
2761f070d671SSuman Tripathi rc = ata_host_activate(host, irq, hpriv->irq_handler,
27625903b164SSuman Tripathi IRQF_SHARED, sht);
2763f070d671SSuman Tripathi }
2764f070d671SSuman Tripathi
2765f070d671SSuman Tripathi
2766d1028e2fSAlexander Gordeev return rc;
2767d1028e2fSAlexander Gordeev }
27681c62854fSAlexander Gordeev EXPORT_SYMBOL_GPL(ahci_host_activate);
27691c62854fSAlexander Gordeev
2770365cfa1eSAnton Vorontsov MODULE_AUTHOR("Jeff Garzik");
2771365cfa1eSAnton Vorontsov MODULE_DESCRIPTION("Common AHCI SATA low-level routines");
2772365cfa1eSAnton Vorontsov MODULE_LICENSE("GPL");
2773