aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.com>2012-08-27 01:07:19 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-09-13 01:10:18 -0400
commitf1e70c2c535923de253eea2021376a936eb8d478 (patch)
tree74a55422cfd07ade3f711f8143272b47e6a577b8 /drivers
parent26fdaa7453db49de80cc216cb696233b23d0b9d1 (diff)
ata/ahci_platform: Add clock framework support
On many architectures, drivers are supposed to prepare/unprepare & enable/disable functional clock of device. This patch adds clock support for ahci_platform. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.h2
-rw-r--r--drivers/ata/ahci_platform.c57
2 files changed, 52 insertions, 7 deletions
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 6441cbecfa1d..9be471200a07 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -35,6 +35,7 @@
35#ifndef _AHCI_H 35#ifndef _AHCI_H
36#define _AHCI_H 36#define _AHCI_H
37 37
38#include <linux/clk.h>
38#include <linux/libata.h> 39#include <linux/libata.h>
39 40
40/* Enclosure Management Control */ 41/* Enclosure Management Control */
@@ -316,6 +317,7 @@ struct ahci_host_priv {
316 u32 em_loc; /* enclosure management location */ 317 u32 em_loc; /* enclosure management location */
317 u32 em_buf_sz; /* EM buffer size in byte */ 318 u32 em_buf_sz; /* EM buffer size in byte */
318 u32 em_msg_type; /* EM message type */ 319 u32 em_msg_type; /* EM message type */
320 struct clk *clk; /* Only for platforms supporting clk */
319}; 321};
320 322
321extern int ahci_ignore_sss; 323extern int ahci_ignore_sss;
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index dc187c746649..b1ae48054dc5 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -12,6 +12,7 @@
12 * any later version. 12 * any later version.
13 */ 13 */
14 14
15#include <linux/clk.h>
15#include <linux/kernel.h> 16#include <linux/kernel.h>
16#include <linux/gfp.h> 17#include <linux/gfp.h>
17#include <linux/module.h> 18#include <linux/module.h>
@@ -118,6 +119,17 @@ static int __init ahci_probe(struct platform_device *pdev)
118 return -ENOMEM; 119 return -ENOMEM;
119 } 120 }
120 121
122 hpriv->clk = clk_get(dev, NULL);
123 if (IS_ERR(hpriv->clk)) {
124 dev_err(dev, "can't get clock\n");
125 } else {
126 rc = clk_prepare_enable(hpriv->clk);
127 if (rc) {
128 dev_err(dev, "clock prepare enable failed");
129 goto free_clk;
130 }
131 }
132
121 /* 133 /*
122 * Some platforms might need to prepare for mmio region access, 134 * Some platforms might need to prepare for mmio region access,
123 * which could be done in the following init call. So, the mmio 135 * which could be done in the following init call. So, the mmio
@@ -127,7 +139,7 @@ static int __init ahci_probe(struct platform_device *pdev)
127 if (pdata && pdata->init) { 139 if (pdata && pdata->init) {
128 rc = pdata->init(dev, hpriv->mmio); 140 rc = pdata->init(dev, hpriv->mmio);
129 if (rc) 141 if (rc)
130 return rc; 142 goto disable_unprepare_clk;
131 } 143 }
132 144
133 ahci_save_initial_config(dev, hpriv, 145 ahci_save_initial_config(dev, hpriv,
@@ -153,7 +165,7 @@ static int __init ahci_probe(struct platform_device *pdev)
153 host = ata_host_alloc_pinfo(dev, ppi, n_ports); 165 host = ata_host_alloc_pinfo(dev, ppi, n_ports);
154 if (!host) { 166 if (!host) {
155 rc = -ENOMEM; 167 rc = -ENOMEM;
156 goto err0; 168 goto pdata_exit;
157 } 169 }
158 170
159 host->private_data = hpriv; 171 host->private_data = hpriv;
@@ -183,7 +195,7 @@ static int __init ahci_probe(struct platform_device *pdev)
183 195
184 rc = ahci_reset_controller(host); 196 rc = ahci_reset_controller(host);
185 if (rc) 197 if (rc)
186 goto err0; 198 goto pdata_exit;
187 199
188 ahci_init_controller(host); 200 ahci_init_controller(host);
189 ahci_print_info(host, "platform"); 201 ahci_print_info(host, "platform");
@@ -191,12 +203,18 @@ static int __init ahci_probe(struct platform_device *pdev)
191 rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED, 203 rc = ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
192 &ahci_platform_sht); 204 &ahci_platform_sht);
193 if (rc) 205 if (rc)
194 goto err0; 206 goto pdata_exit;
195 207
196 return 0; 208 return 0;
197err0: 209pdata_exit:
198 if (pdata && pdata->exit) 210 if (pdata && pdata->exit)
199 pdata->exit(dev); 211 pdata->exit(dev);
212disable_unprepare_clk:
213 if (!IS_ERR(hpriv->clk))
214 clk_disable_unprepare(hpriv->clk);
215free_clk:
216 if (!IS_ERR(hpriv->clk))
217 clk_put(hpriv->clk);
200 return rc; 218 return rc;
201} 219}
202 220
@@ -205,12 +223,18 @@ static int __devexit ahci_remove(struct platform_device *pdev)
205 struct device *dev = &pdev->dev; 223 struct device *dev = &pdev->dev;
206 struct ahci_platform_data *pdata = dev_get_platdata(dev); 224 struct ahci_platform_data *pdata = dev_get_platdata(dev);
207 struct ata_host *host = dev_get_drvdata(dev); 225 struct ata_host *host = dev_get_drvdata(dev);
226 struct ahci_host_priv *hpriv = host->private_data;
208 227
209 ata_host_detach(host); 228 ata_host_detach(host);
210 229
211 if (pdata && pdata->exit) 230 if (pdata && pdata->exit)
212 pdata->exit(dev); 231 pdata->exit(dev);
213 232
233 if (!IS_ERR(hpriv->clk)) {
234 clk_disable_unprepare(hpriv->clk);
235 clk_put(hpriv->clk);
236 }
237
214 return 0; 238 return 0;
215} 239}
216 240
@@ -245,6 +269,10 @@ static int ahci_suspend(struct device *dev)
245 269
246 if (pdata && pdata->suspend) 270 if (pdata && pdata->suspend)
247 return pdata->suspend(dev); 271 return pdata->suspend(dev);
272
273 if (!IS_ERR(hpriv->clk))
274 clk_disable_unprepare(hpriv->clk);
275
248 return 0; 276 return 0;
249} 277}
250 278
@@ -252,18 +280,27 @@ static int ahci_resume(struct device *dev)
252{ 280{
253 struct ahci_platform_data *pdata = dev_get_platdata(dev); 281 struct ahci_platform_data *pdata = dev_get_platdata(dev);
254 struct ata_host *host = dev_get_drvdata(dev); 282 struct ata_host *host = dev_get_drvdata(dev);
283 struct ahci_host_priv *hpriv = host->private_data;
255 int rc; 284 int rc;
256 285
286 if (!IS_ERR(hpriv->clk)) {
287 rc = clk_prepare_enable(hpriv->clk);
288 if (rc) {
289 dev_err(dev, "clock prepare enable failed");
290 return rc;
291 }
292 }
293
257 if (pdata && pdata->resume) { 294 if (pdata && pdata->resume) {
258 rc = pdata->resume(dev); 295 rc = pdata->resume(dev);
259 if (rc) 296 if (rc)
260 return rc; 297 goto disable_unprepare_clk;
261 } 298 }
262 299
263 if (dev->power.power_state.event == PM_EVENT_SUSPEND) { 300 if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
264 rc = ahci_reset_controller(host); 301 rc = ahci_reset_controller(host);
265 if (rc) 302 if (rc)
266 return rc; 303 goto disable_unprepare_clk;
267 304
268 ahci_init_controller(host); 305 ahci_init_controller(host);
269 } 306 }
@@ -271,6 +308,12 @@ static int ahci_resume(struct device *dev)
271 ata_host_resume(host); 308 ata_host_resume(host);
272 309
273 return 0; 310 return 0;
311
312disable_unprepare_clk:
313 if (!IS_ERR(hpriv->clk))
314 clk_disable_unprepare(hpriv->clk);
315
316 return rc;
274} 317}
275#endif 318#endif
276 319