kernel: update 3.14 to 3.14.18
[openwrt/openwrt.git] / target / linux / sunxi / patches-3.14 / 192-ahci-platform-changes.patch
1 From a52ae09871d171d6771b4bef2d4c56dd435e740f Mon Sep 17 00:00:00 2001
2 From: Roger Quadros <rogerq@ti.com>
3 Date: Mon, 20 Jan 2014 16:32:33 +0200
4 Subject: [PATCH] ata: ahci_platform: Add DT compatible for Synopsis DWC AHCI
5 controller
6
7 Add compatible string "snps,dwc-ahci", which should be used
8 for Synopsis Designware SATA cores. e.g. on TI OMAP5 and DRA7 platforms.
9
10 Signed-off-by: Roger Quadros <rogerq@ti.com>
11 Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
12 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
13 ---
14 drivers/ata/ahci_platform.c | 1 +
15 1 file changed, 1 insertion(+)
16
17 --- a/drivers/ata/ahci_platform.c
18 +++ b/drivers/ata/ahci_platform.c
19 @@ -23,6 +23,8 @@
20 #include <linux/platform_device.h>
21 #include <linux/libata.h>
22 #include <linux/ahci_platform.h>
23 +#include <linux/phy/phy.h>
24 +#include <linux/pm_runtime.h>
25 #include "ahci.h"
26
27 static void ahci_host_stop(struct ata_host *host);
28 @@ -147,6 +149,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_
29 * the following order:
30 * 1) Regulator
31 * 2) Clocks (through ahci_platform_enable_clks)
32 + * 3) Phy
33 *
34 * If resource enabling fails at any point the previous enabled
35 * resources are disabled in reverse order.
36 @@ -171,8 +174,23 @@ int ahci_platform_enable_resources(struc
37 if (rc)
38 goto disable_regulator;
39
40 + if (hpriv->phy) {
41 + rc = phy_init(hpriv->phy);
42 + if (rc)
43 + goto disable_clks;
44 +
45 + rc = phy_power_on(hpriv->phy);
46 + if (rc) {
47 + phy_exit(hpriv->phy);
48 + goto disable_clks;
49 + }
50 + }
51 +
52 return 0;
53
54 +disable_clks:
55 + ahci_platform_disable_clks(hpriv);
56 +
57 disable_regulator:
58 if (hpriv->target_pwr)
59 regulator_disable(hpriv->target_pwr);
60 @@ -186,14 +204,20 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_r
61 *
62 * This function disables all ahci_platform managed resources in
63 * the following order:
64 - * 1) Clocks (through ahci_platform_disable_clks)
65 - * 2) Regulator
66 + * 1) Phy
67 + * 2) Clocks (through ahci_platform_disable_clks)
68 + * 3) Regulator
69 *
70 * LOCKING:
71 * None.
72 */
73 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
74 {
75 + if (hpriv->phy) {
76 + phy_power_off(hpriv->phy);
77 + phy_exit(hpriv->phy);
78 + }
79 +
80 ahci_platform_disable_clks(hpriv);
81
82 if (hpriv->target_pwr)
83 @@ -206,6 +230,11 @@ static void ahci_platform_put_resources(
84 struct ahci_host_priv *hpriv = res;
85 int c;
86
87 + if (hpriv->got_runtime_pm) {
88 + pm_runtime_put_sync(dev);
89 + pm_runtime_disable(dev);
90 + }
91 +
92 for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
93 clk_put(hpriv->clks[c]);
94 }
95 @@ -222,6 +251,7 @@ static void ahci_platform_put_resources(
96 * 2) regulator for controlling the targets power (optional)
97 * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
98 * or for non devicetree enabled platforms a single clock
99 + * 4) phy (optional)
100 *
101 * LOCKING:
102 * None.
103 @@ -283,6 +313,29 @@ struct ahci_host_priv *ahci_platform_get
104 hpriv->clks[i] = clk;
105 }
106
107 + hpriv->phy = devm_phy_get(dev, "sata-phy");
108 + if (IS_ERR(hpriv->phy)) {
109 + rc = PTR_ERR(hpriv->phy);
110 + switch (rc) {
111 + case -ENODEV:
112 + case -ENOSYS:
113 + /* continue normally */
114 + hpriv->phy = NULL;
115 + break;
116 +
117 + case -EPROBE_DEFER:
118 + goto err_out;
119 +
120 + default:
121 + dev_err(dev, "couldn't get sata-phy\n");
122 + goto err_out;
123 + }
124 + }
125 +
126 + pm_runtime_enable(dev);
127 + pm_runtime_get_sync(dev);
128 + hpriv->got_runtime_pm = true;
129 +
130 devres_remove_group(dev, NULL);
131 return hpriv;
132
133 @@ -592,6 +645,11 @@ int ahci_platform_resume(struct device *
134 if (rc)
135 goto disable_resources;
136
137 + /* We resumed so update PM runtime state */
138 + pm_runtime_disable(dev);
139 + pm_runtime_set_active(dev);
140 + pm_runtime_enable(dev);
141 +
142 return 0;
143
144 disable_resources:
145 @@ -609,6 +667,7 @@ static const struct of_device_id ahci_of
146 { .compatible = "snps,spear-ahci", },
147 { .compatible = "snps,exynos5440-ahci", },
148 { .compatible = "ibm,476gtr-ahci", },
149 + { .compatible = "snps,dwc-ahci", },
150 {},
151 };
152 MODULE_DEVICE_TABLE(of, ahci_of_match);
153 --- a/drivers/ata/ahci.h
154 +++ b/drivers/ata/ahci.h
155 @@ -37,6 +37,7 @@
156
157 #include <linux/clk.h>
158 #include <linux/libata.h>
159 +#include <linux/phy/phy.h>
160 #include <linux/regulator/consumer.h>
161
162 /* Enclosure Management Control */
163 @@ -324,8 +325,10 @@ struct ahci_host_priv {
164 u32 em_loc; /* enclosure management location */
165 u32 em_buf_sz; /* EM buffer size in byte */
166 u32 em_msg_type; /* EM message type */
167 + bool got_runtime_pm; /* Did we do pm_runtime_get? */
168 struct clk *clks[AHCI_MAX_CLKS]; /* Optional */
169 struct regulator *target_pwr; /* Optional */
170 + struct phy *phy; /* If platform uses phy */
171 void *plat_data; /* Other platform data */
172 /*
173 * Optional ahci_start_engine override, if not set this gets set to the
174 --- a/drivers/ata/ahci_sunxi.c
175 +++ b/drivers/ata/ahci_sunxi.c
176 @@ -90,7 +90,7 @@ static int ahci_sunxi_phy_init(struct de
177
178 /* This magic is from the original code */
179 writel(0, reg_base + AHCI_RWCR);
180 - mdelay(5);
181 + msleep(5);
182
183 sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
184 sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
185 @@ -105,7 +105,7 @@ static int ahci_sunxi_phy_init(struct de
186 (0x7 << 20), (0x3 << 20));
187 sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
188 (0x1f << 5), (0x19 << 5));
189 - mdelay(5);
190 + msleep(5);
191
192 sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
193
194 @@ -137,7 +137,7 @@ static int ahci_sunxi_phy_init(struct de
195 udelay(1);
196 } while (1);
197
198 - mdelay(15);
199 + msleep(15);
200
201 writel(0x7, reg_base + AHCI_RWCR);
202