aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/ahci.h2
-rw-r--r--drivers/ata/ahci_imx.c101
-rw-r--r--drivers/ata/ahci_platform.c3
-rw-r--r--drivers/ata/libahci.c4
4 files changed, 105 insertions, 5 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 11456371f29b..2289efdf8203 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -339,6 +339,7 @@ extern struct device_attribute *ahci_sdev_attrs[];
339 .sdev_attrs = ahci_sdev_attrs 339 .sdev_attrs = ahci_sdev_attrs
340 340
341extern struct ata_port_operations ahci_ops; 341extern struct ata_port_operations ahci_ops;
342extern struct ata_port_operations ahci_platform_ops;
342extern struct ata_port_operations ahci_pmp_retry_srst_ops; 343extern struct ata_port_operations ahci_pmp_retry_srst_ops;
343 344
344unsigned int ahci_dev_classify(struct ata_port *ap); 345unsigned int ahci_dev_classify(struct ata_port *ap);
@@ -368,6 +369,7 @@ irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance);
368irqreturn_t ahci_thread_fn(int irq, void *dev_instance); 369irqreturn_t ahci_thread_fn(int irq, void *dev_instance);
369void ahci_print_info(struct ata_host *host, const char *scc_s); 370void ahci_print_info(struct ata_host *host, const char *scc_s);
370int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis); 371int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis);
372void ahci_error_handler(struct ata_port *ap);
371 373
372static inline void __iomem *__ahci_port_base(struct ata_host *host, 374static inline void __iomem *__ahci_port_base(struct ata_host *host,
373 unsigned int port_no) 375 unsigned int port_no)
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 58debb0acc3a..ae2d73fe321e 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * copyright (c) 2013 Freescale Semiconductor, Inc.
2 * Freescale IMX AHCI SATA platform driver 3 * Freescale IMX AHCI SATA platform driver
3 * Copyright 2013 Freescale Semiconductor, Inc.
4 * 4 *
5 * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov 5 * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
6 * 6 *
@@ -25,10 +25,13 @@
25#include <linux/of_device.h> 25#include <linux/of_device.h>
26#include <linux/mfd/syscon.h> 26#include <linux/mfd/syscon.h>
27#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 27#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
28#include <linux/libata.h>
28#include "ahci.h" 29#include "ahci.h"
29 30
30enum { 31enum {
31 HOST_TIMER1MS = 0xe0, /* Timer 1-ms */ 32 PORT_PHY_CTL = 0x178, /* Port0 PHY Control */
33 PORT_PHY_CTL_PDDQ_LOC = 0x100000, /* PORT_PHY_CTL bits */
34 HOST_TIMER1MS = 0xe0, /* Timer 1-ms */
32}; 35};
33 36
34struct imx_ahci_priv { 37struct imx_ahci_priv {
@@ -36,6 +39,56 @@ struct imx_ahci_priv {
36 struct clk *sata_ref_clk; 39 struct clk *sata_ref_clk;
37 struct clk *ahb_clk; 40 struct clk *ahb_clk;
38 struct regmap *gpr; 41 struct regmap *gpr;
42 bool no_device;
43 bool first_time;
44};
45
46static int ahci_imx_hotplug;
47module_param_named(hotplug, ahci_imx_hotplug, int, 0644);
48MODULE_PARM_DESC(hotplug, "AHCI IMX hot-plug support (0=Don't support, 1=support)");
49
50static void ahci_imx_error_handler(struct ata_port *ap)
51{
52 u32 reg_val;
53 struct ata_device *dev;
54 struct ata_host *host = dev_get_drvdata(ap->dev);
55 struct ahci_host_priv *hpriv = host->private_data;
56 void __iomem *mmio = hpriv->mmio;
57 struct imx_ahci_priv *imxpriv = dev_get_drvdata(ap->dev->parent);
58
59 ahci_error_handler(ap);
60
61 if (!(imxpriv->first_time) || ahci_imx_hotplug)
62 return;
63
64 imxpriv->first_time = false;
65
66 ata_for_each_dev(dev, &ap->link, ENABLED)
67 return;
68 /*
69 * Disable link to save power. An imx ahci port can't be recovered
70 * without full reset once the pddq mode is enabled making it
71 * impossible to use as part of libata LPM.
72 */
73 reg_val = readl(mmio + PORT_PHY_CTL);
74 writel(reg_val | PORT_PHY_CTL_PDDQ_LOC, mmio + PORT_PHY_CTL);
75 regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
76 IMX6Q_GPR13_SATA_MPLL_CLK_EN,
77 !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
78 clk_disable_unprepare(imxpriv->sata_ref_clk);
79 imxpriv->no_device = true;
80}
81
82static struct ata_port_operations ahci_imx_ops = {
83 .inherits = &ahci_platform_ops,
84 .error_handler = ahci_imx_error_handler,
85};
86
87static const struct ata_port_info ahci_imx_port_info = {
88 .flags = AHCI_FLAG_COMMON,
89 .pio_mask = ATA_PIO4,
90 .udma_mask = ATA_UDMA6,
91 .port_ops = &ahci_imx_ops,
39}; 92};
40 93
41static int imx6q_sata_init(struct device *dev, void __iomem *mmio) 94static int imx6q_sata_init(struct device *dev, void __iomem *mmio)
@@ -117,9 +170,51 @@ static void imx6q_sata_exit(struct device *dev)
117 clk_disable_unprepare(imxpriv->sata_ref_clk); 170 clk_disable_unprepare(imxpriv->sata_ref_clk);
118} 171}
119 172
173static int imx_ahci_suspend(struct device *dev)
174{
175 struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
176
177 /*
178 * If no_device is set, The CLKs had been gated off in the
179 * initialization so don't do it again here.
180 */
181 if (!imxpriv->no_device) {
182 regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
183 IMX6Q_GPR13_SATA_MPLL_CLK_EN,
184 !IMX6Q_GPR13_SATA_MPLL_CLK_EN);
185 clk_disable_unprepare(imxpriv->sata_ref_clk);
186 }
187
188 return 0;
189}
190
191static int imx_ahci_resume(struct device *dev)
192{
193 struct imx_ahci_priv *imxpriv = dev_get_drvdata(dev->parent);
194 int ret;
195
196 if (!imxpriv->no_device) {
197 ret = clk_prepare_enable(imxpriv->sata_ref_clk);
198 if (ret < 0) {
199 dev_err(dev, "pre-enable sata_ref clock err:%d\n", ret);
200 return ret;
201 }
202
203 regmap_update_bits(imxpriv->gpr, IOMUXC_GPR13,
204 IMX6Q_GPR13_SATA_MPLL_CLK_EN,
205 IMX6Q_GPR13_SATA_MPLL_CLK_EN);
206 usleep_range(1000, 2000);
207 }
208
209 return 0;
210}
211
120static struct ahci_platform_data imx6q_sata_pdata = { 212static struct ahci_platform_data imx6q_sata_pdata = {
121 .init = imx6q_sata_init, 213 .init = imx6q_sata_init,
122 .exit = imx6q_sata_exit, 214 .exit = imx6q_sata_exit,
215 .ata_port_info = &ahci_imx_port_info,
216 .suspend = imx_ahci_suspend,
217 .resume = imx_ahci_resume,
123}; 218};
124 219
125static const struct of_device_id imx_ahci_of_match[] = { 220static const struct of_device_id imx_ahci_of_match[] = {
@@ -152,6 +247,8 @@ static int imx_ahci_probe(struct platform_device *pdev)
152 ahci_dev = &ahci_pdev->dev; 247 ahci_dev = &ahci_pdev->dev;
153 ahci_dev->parent = dev; 248 ahci_dev->parent = dev;
154 249
250 imxpriv->no_device = false;
251 imxpriv->first_time = true;
155 imxpriv->ahb_clk = devm_clk_get(dev, "ahb"); 252 imxpriv->ahb_clk = devm_clk_get(dev, "ahb");
156 if (IS_ERR(imxpriv->ahb_clk)) { 253 if (IS_ERR(imxpriv->ahb_clk)) {
157 dev_err(dev, "can't get ahb clock.\n"); 254 dev_err(dev, "can't get ahb clock.\n");
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 2daaee05cab1..7708ca71f14e 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -49,10 +49,11 @@ static struct platform_device_id ahci_devtype[] = {
49}; 49};
50MODULE_DEVICE_TABLE(platform, ahci_devtype); 50MODULE_DEVICE_TABLE(platform, ahci_devtype);
51 51
52static struct ata_port_operations ahci_platform_ops = { 52struct ata_port_operations ahci_platform_ops = {
53 .inherits = &ahci_ops, 53 .inherits = &ahci_ops,
54 .host_stop = ahci_host_stop, 54 .host_stop = ahci_host_stop,
55}; 55};
56EXPORT_SYMBOL_GPL(ahci_platform_ops);
56 57
57static struct ata_port_operations ahci_platform_retry_srst_ops = { 58static struct ata_port_operations ahci_platform_retry_srst_ops = {
58 .inherits = &ahci_pmp_retry_srst_ops, 59 .inherits = &ahci_pmp_retry_srst_ops,
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index b67086fde1f1..7e2a1b38093e 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -89,7 +89,6 @@ static int ahci_pmp_retry_softreset(struct ata_link *link, unsigned int *class,
89static int ahci_hardreset(struct ata_link *link, unsigned int *class, 89static int ahci_hardreset(struct ata_link *link, unsigned int *class,
90 unsigned long deadline); 90 unsigned long deadline);
91static void ahci_postreset(struct ata_link *link, unsigned int *class); 91static void ahci_postreset(struct ata_link *link, unsigned int *class);
92static void ahci_error_handler(struct ata_port *ap);
93static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); 92static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
94static void ahci_dev_config(struct ata_device *dev); 93static void ahci_dev_config(struct ata_device *dev);
95#ifdef CONFIG_PM 94#ifdef CONFIG_PM
@@ -1982,7 +1981,7 @@ static void ahci_thaw(struct ata_port *ap)
1982 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK); 1981 writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
1983} 1982}
1984 1983
1985static void ahci_error_handler(struct ata_port *ap) 1984void ahci_error_handler(struct ata_port *ap)
1986{ 1985{
1987 if (!(ap->pflags & ATA_PFLAG_FROZEN)) { 1986 if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
1988 /* restart engine */ 1987 /* restart engine */
@@ -1995,6 +1994,7 @@ static void ahci_error_handler(struct ata_port *ap)
1995 if (!ata_dev_enabled(ap->link.device)) 1994 if (!ata_dev_enabled(ap->link.device))
1996 ahci_stop_engine(ap); 1995 ahci_stop_engine(ap);
1997} 1996}
1997EXPORT_SYMBOL_GPL(ahci_error_handler);
1998 1998
1999static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) 1999static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
2000{ 2000{