kernel: update 3.14 to 3.14.18
[openwrt/openwrt.git] / target / linux / ipq806x / patches / 0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch
1 From 04800db1047afbf6701379435bff1a6fa64215f7 Mon Sep 17 00:00:00 2001
2 From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
3 Date: Tue, 25 Mar 2014 19:51:39 +0100
4 Subject: [PATCH 124/182] ata: move library code from ahci_platform.c to
5 libahci_platform.c
6
7 Move AHCI platform library code from ahci_platform.c to
8 libahci_platform.c and fix dependencies for ahci_st,
9 ahci_imx and ahci_sunxi drivers.
10
11 Acked-by: Hans de Goede <hdegoede@redhat.com>
12 Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
13 Signed-off-by: Tejun Heo <tj@kernel.org>
14
15 Conflicts:
16 drivers/ata/Kconfig
17 drivers/ata/Makefile
18 ---
19 drivers/ata/Kconfig | 2 +-
20 drivers/ata/Makefile | 4 +-
21 drivers/ata/ahci_platform.c | 515 --------------------------------------
22 drivers/ata/libahci_platform.c | 541 ++++++++++++++++++++++++++++++++++++++++
23 4 files changed, 544 insertions(+), 518 deletions(-)
24 create mode 100644 drivers/ata/libahci_platform.c
25
26 --- a/drivers/ata/Kconfig
27 +++ b/drivers/ata/Kconfig
28 @@ -99,7 +99,7 @@ config SATA_AHCI_PLATFORM
29
30 config AHCI_IMX
31 tristate "Freescale i.MX AHCI SATA support"
32 - depends on SATA_AHCI_PLATFORM && MFD_SYSCON
33 + depends on MFD_SYSCON
34 help
35 This option enables support for the Freescale i.MX SoC's
36 onboard AHCI SATA.
37 --- a/drivers/ata/Makefile
38 +++ b/drivers/ata/Makefile
39 @@ -4,13 +4,13 @@ obj-$(CONFIG_ATA) += libata.o
40 # non-SFF interface
41 obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
42 obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
43 -obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
44 +obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
45 obj-$(CONFIG_SATA_FSL) += sata_fsl.o
46 obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
47 obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
48 obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
49 obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
50 -obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
51 +obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o
52
53 # SFF w/ custom DMA
54 obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
55 --- a/drivers/ata/ahci_platform.c
56 +++ b/drivers/ata/ahci_platform.c
57 @@ -12,28 +12,15 @@
58 * any later version.
59 */
60
61 -#include <linux/clk.h>
62 #include <linux/kernel.h>
63 -#include <linux/gfp.h>
64 #include <linux/module.h>
65 #include <linux/pm.h>
66 -#include <linux/interrupt.h>
67 #include <linux/device.h>
68 #include <linux/platform_device.h>
69 #include <linux/libata.h>
70 #include <linux/ahci_platform.h>
71 -#include <linux/phy/phy.h>
72 -#include <linux/pm_runtime.h>
73 #include "ahci.h"
74
75 -static void ahci_host_stop(struct ata_host *host);
76 -
77 -struct ata_port_operations ahci_platform_ops = {
78 - .inherits = &ahci_ops,
79 - .host_stop = ahci_host_stop,
80 -};
81 -EXPORT_SYMBOL_GPL(ahci_platform_ops);
82 -
83 static const struct ata_port_info ahci_port_info = {
84 .flags = AHCI_FLAG_COMMON,
85 .pio_mask = ATA_PIO4,
86 @@ -41,345 +28,6 @@ static const struct ata_port_info ahci_p
87 .port_ops = &ahci_platform_ops,
88 };
89
90 -static struct scsi_host_template ahci_platform_sht = {
91 - AHCI_SHT("ahci_platform"),
92 -};
93 -
94 -/**
95 - * ahci_platform_enable_clks - Enable platform clocks
96 - * @hpriv: host private area to store config values
97 - *
98 - * This function enables all the clks found in hpriv->clks, starting at
99 - * index 0. If any clk fails to enable it disables all the clks already
100 - * enabled in reverse order, and then returns an error.
101 - *
102 - * RETURNS:
103 - * 0 on success otherwise a negative error code
104 - */
105 -int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
106 -{
107 - int c, rc;
108 -
109 - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
110 - rc = clk_prepare_enable(hpriv->clks[c]);
111 - if (rc)
112 - goto disable_unprepare_clk;
113 - }
114 - return 0;
115 -
116 -disable_unprepare_clk:
117 - while (--c >= 0)
118 - clk_disable_unprepare(hpriv->clks[c]);
119 - return rc;
120 -}
121 -EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
122 -
123 -/**
124 - * ahci_platform_disable_clks - Disable platform clocks
125 - * @hpriv: host private area to store config values
126 - *
127 - * This function disables all the clks found in hpriv->clks, in reverse
128 - * order of ahci_platform_enable_clks (starting at the end of the array).
129 - */
130 -void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
131 -{
132 - int c;
133 -
134 - for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
135 - if (hpriv->clks[c])
136 - clk_disable_unprepare(hpriv->clks[c]);
137 -}
138 -EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
139 -
140 -/**
141 - * ahci_platform_enable_resources - Enable platform resources
142 - * @hpriv: host private area to store config values
143 - *
144 - * This function enables all ahci_platform managed resources in the
145 - * following order:
146 - * 1) Regulator
147 - * 2) Clocks (through ahci_platform_enable_clks)
148 - * 3) Phy
149 - *
150 - * If resource enabling fails at any point the previous enabled resources
151 - * are disabled in reverse order.
152 - *
153 - * RETURNS:
154 - * 0 on success otherwise a negative error code
155 - */
156 -int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
157 -{
158 - int rc;
159 -
160 - if (hpriv->target_pwr) {
161 - rc = regulator_enable(hpriv->target_pwr);
162 - if (rc)
163 - return rc;
164 - }
165 -
166 - rc = ahci_platform_enable_clks(hpriv);
167 - if (rc)
168 - goto disable_regulator;
169 -
170 - if (hpriv->phy) {
171 - rc = phy_init(hpriv->phy);
172 - if (rc)
173 - goto disable_clks;
174 -
175 - rc = phy_power_on(hpriv->phy);
176 - if (rc) {
177 - phy_exit(hpriv->phy);
178 - goto disable_clks;
179 - }
180 - }
181 -
182 - return 0;
183 -
184 -disable_clks:
185 - ahci_platform_disable_clks(hpriv);
186 -
187 -disable_regulator:
188 - if (hpriv->target_pwr)
189 - regulator_disable(hpriv->target_pwr);
190 - return rc;
191 -}
192 -EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
193 -
194 -/**
195 - * ahci_platform_disable_resources - Disable platform resources
196 - * @hpriv: host private area to store config values
197 - *
198 - * This function disables all ahci_platform managed resources in the
199 - * following order:
200 - * 1) Phy
201 - * 2) Clocks (through ahci_platform_disable_clks)
202 - * 3) Regulator
203 - */
204 -void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
205 -{
206 - if (hpriv->phy) {
207 - phy_power_off(hpriv->phy);
208 - phy_exit(hpriv->phy);
209 - }
210 -
211 - ahci_platform_disable_clks(hpriv);
212 -
213 - if (hpriv->target_pwr)
214 - regulator_disable(hpriv->target_pwr);
215 -}
216 -EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
217 -
218 -static void ahci_platform_put_resources(struct device *dev, void *res)
219 -{
220 - struct ahci_host_priv *hpriv = res;
221 - int c;
222 -
223 - if (hpriv->got_runtime_pm) {
224 - pm_runtime_put_sync(dev);
225 - pm_runtime_disable(dev);
226 - }
227 -
228 - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
229 - clk_put(hpriv->clks[c]);
230 -}
231 -
232 -/**
233 - * ahci_platform_get_resources - Get platform resources
234 - * @pdev: platform device to get resources for
235 - *
236 - * This function allocates an ahci_host_priv struct, and gets the following
237 - * resources, storing a reference to them inside the returned struct:
238 - *
239 - * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
240 - * 2) regulator for controlling the targets power (optional)
241 - * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
242 - * or for non devicetree enabled platforms a single clock
243 - * 4) phy (optional)
244 - *
245 - * RETURNS:
246 - * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
247 - */
248 -struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
249 -{
250 - struct device *dev = &pdev->dev;
251 - struct ahci_host_priv *hpriv;
252 - struct clk *clk;
253 - int i, rc = -ENOMEM;
254 -
255 - if (!devres_open_group(dev, NULL, GFP_KERNEL))
256 - return ERR_PTR(-ENOMEM);
257 -
258 - hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
259 - GFP_KERNEL);
260 - if (!hpriv)
261 - goto err_out;
262 -
263 - devres_add(dev, hpriv);
264 -
265 - hpriv->mmio = devm_ioremap_resource(dev,
266 - platform_get_resource(pdev, IORESOURCE_MEM, 0));
267 - if (IS_ERR(hpriv->mmio)) {
268 - dev_err(dev, "no mmio space\n");
269 - rc = PTR_ERR(hpriv->mmio);
270 - goto err_out;
271 - }
272 -
273 - hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
274 - if (IS_ERR(hpriv->target_pwr)) {
275 - rc = PTR_ERR(hpriv->target_pwr);
276 - if (rc == -EPROBE_DEFER)
277 - goto err_out;
278 - hpriv->target_pwr = NULL;
279 - }
280 -
281 - for (i = 0; i < AHCI_MAX_CLKS; i++) {
282 - /*
283 - * For now we must use clk_get(dev, NULL) for the first clock,
284 - * because some platforms (da850, spear13xx) are not yet
285 - * converted to use devicetree for clocks. For new platforms
286 - * this is equivalent to of_clk_get(dev->of_node, 0).
287 - */
288 - if (i == 0)
289 - clk = clk_get(dev, NULL);
290 - else
291 - clk = of_clk_get(dev->of_node, i);
292 -
293 - if (IS_ERR(clk)) {
294 - rc = PTR_ERR(clk);
295 - if (rc == -EPROBE_DEFER)
296 - goto err_out;
297 - break;
298 - }
299 - hpriv->clks[i] = clk;
300 - }
301 -
302 - hpriv->phy = devm_phy_get(dev, "sata-phy");
303 - if (IS_ERR(hpriv->phy)) {
304 - rc = PTR_ERR(hpriv->phy);
305 - switch (rc) {
306 - case -ENODEV:
307 - case -ENOSYS:
308 - /* continue normally */
309 - hpriv->phy = NULL;
310 - break;
311 -
312 - case -EPROBE_DEFER:
313 - goto err_out;
314 -
315 - default:
316 - dev_err(dev, "couldn't get sata-phy\n");
317 - goto err_out;
318 - }
319 - }
320 -
321 - pm_runtime_enable(dev);
322 - pm_runtime_get_sync(dev);
323 - hpriv->got_runtime_pm = true;
324 -
325 - devres_remove_group(dev, NULL);
326 - return hpriv;
327 -
328 -err_out:
329 - devres_release_group(dev, NULL);
330 - return ERR_PTR(rc);
331 -}
332 -EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
333 -
334 -/**
335 - * ahci_platform_init_host - Bring up an ahci-platform host
336 - * @pdev: platform device pointer for the host
337 - * @hpriv: ahci-host private data for the host
338 - * @pi_template: template for the ata_port_info to use
339 - * @force_port_map: param passed to ahci_save_initial_config
340 - * @mask_port_map: param passed to ahci_save_initial_config
341 - *
342 - * This function does all the usual steps needed to bring up an
343 - * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
344 - * must be initialized / enabled before calling this.
345 - *
346 - * RETURNS:
347 - * 0 on success otherwise a negative error code
348 - */
349 -int ahci_platform_init_host(struct platform_device *pdev,
350 - struct ahci_host_priv *hpriv,
351 - const struct ata_port_info *pi_template,
352 - unsigned int force_port_map,
353 - unsigned int mask_port_map)
354 -{
355 - struct device *dev = &pdev->dev;
356 - struct ata_port_info pi = *pi_template;
357 - const struct ata_port_info *ppi[] = { &pi, NULL };
358 - struct ata_host *host;
359 - int i, irq, n_ports, rc;
360 -
361 - irq = platform_get_irq(pdev, 0);
362 - if (irq <= 0) {
363 - dev_err(dev, "no irq\n");
364 - return -EINVAL;
365 - }
366 -
367 - /* prepare host */
368 - hpriv->flags |= (unsigned long)pi.private_data;
369 -
370 - ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
371 -
372 - if (hpriv->cap & HOST_CAP_NCQ)
373 - pi.flags |= ATA_FLAG_NCQ;
374 -
375 - if (hpriv->cap & HOST_CAP_PMP)
376 - pi.flags |= ATA_FLAG_PMP;
377 -
378 - ahci_set_em_messages(hpriv, &pi);
379 -
380 - /* CAP.NP sometimes indicate the index of the last enabled
381 - * port, at other times, that of the last possible port, so
382 - * determining the maximum port number requires looking at
383 - * both CAP.NP and port_map.
384 - */
385 - n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
386 -
387 - host = ata_host_alloc_pinfo(dev, ppi, n_ports);
388 - if (!host)
389 - return -ENOMEM;
390 -
391 - host->private_data = hpriv;
392 -
393 - if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
394 - host->flags |= ATA_HOST_PARALLEL_SCAN;
395 - else
396 - dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
397 -
398 - if (pi.flags & ATA_FLAG_EM)
399 - ahci_reset_em(host);
400 -
401 - for (i = 0; i < host->n_ports; i++) {
402 - struct ata_port *ap = host->ports[i];
403 -
404 - ata_port_desc(ap, "mmio %pR",
405 - platform_get_resource(pdev, IORESOURCE_MEM, 0));
406 - ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
407 -
408 - /* set enclosure management message type */
409 - if (ap->flags & ATA_FLAG_EM)
410 - ap->em_message_type = hpriv->em_msg_type;
411 -
412 - /* disabled/not-implemented port */
413 - if (!(hpriv->port_map & (1 << i)))
414 - ap->ops = &ata_dummy_port_ops;
415 - }
416 -
417 - rc = ahci_reset_controller(host);
418 - if (rc)
419 - return rc;
420 -
421 - ahci_init_controller(host);
422 - ahci_print_info(host, "platform");
423 -
424 - return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
425 - &ahci_platform_sht);
426 -}
427 -EXPORT_SYMBOL_GPL(ahci_platform_init_host);
428 -
429 static int ahci_probe(struct platform_device *pdev)
430 {
431 struct device *dev = &pdev->dev;
432 @@ -420,169 +68,6 @@ disable_resources:
433 return rc;
434 }
435
436 -static void ahci_host_stop(struct ata_host *host)
437 -{
438 - struct device *dev = host->dev;
439 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
440 - struct ahci_host_priv *hpriv = host->private_data;
441 -
442 - if (pdata && pdata->exit)
443 - pdata->exit(dev);
444 -
445 - ahci_platform_disable_resources(hpriv);
446 -}
447 -
448 -#ifdef CONFIG_PM_SLEEP
449 -/**
450 - * ahci_platform_suspend_host - Suspend an ahci-platform host
451 - * @dev: device pointer for the host
452 - *
453 - * This function does all the usual steps needed to suspend an
454 - * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
455 - * must be disabled after calling this.
456 - *
457 - * RETURNS:
458 - * 0 on success otherwise a negative error code
459 - */
460 -int ahci_platform_suspend_host(struct device *dev)
461 -{
462 - struct ata_host *host = dev_get_drvdata(dev);
463 - struct ahci_host_priv *hpriv = host->private_data;
464 - void __iomem *mmio = hpriv->mmio;
465 - u32 ctl;
466 -
467 - if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
468 - dev_err(dev, "firmware update required for suspend/resume\n");
469 - return -EIO;
470 - }
471 -
472 - /*
473 - * AHCI spec rev1.1 section 8.3.3:
474 - * Software must disable interrupts prior to requesting a
475 - * transition of the HBA to D3 state.
476 - */
477 - ctl = readl(mmio + HOST_CTL);
478 - ctl &= ~HOST_IRQ_EN;
479 - writel(ctl, mmio + HOST_CTL);
480 - readl(mmio + HOST_CTL); /* flush */
481 -
482 - return ata_host_suspend(host, PMSG_SUSPEND);
483 -}
484 -EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
485 -
486 -/**
487 - * ahci_platform_resume_host - Resume an ahci-platform host
488 - * @dev: device pointer for the host
489 - *
490 - * This function does all the usual steps needed to resume an ahci-platform
491 - * host, note any necessary resources (ie clks, phy, etc.) must be
492 - * initialized / enabled before calling this.
493 - *
494 - * RETURNS:
495 - * 0 on success otherwise a negative error code
496 - */
497 -int ahci_platform_resume_host(struct device *dev)
498 -{
499 - struct ata_host *host = dev_get_drvdata(dev);
500 - int rc;
501 -
502 - if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
503 - rc = ahci_reset_controller(host);
504 - if (rc)
505 - return rc;
506 -
507 - ahci_init_controller(host);
508 - }
509 -
510 - ata_host_resume(host);
511 -
512 - return 0;
513 -}
514 -EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
515 -
516 -/**
517 - * ahci_platform_suspend - Suspend an ahci-platform device
518 - * @dev: the platform device to suspend
519 - *
520 - * This function suspends the host associated with the device, followed by
521 - * disabling all the resources of the device.
522 - *
523 - * RETURNS:
524 - * 0 on success otherwise a negative error code
525 - */
526 -int ahci_platform_suspend(struct device *dev)
527 -{
528 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
529 - struct ata_host *host = dev_get_drvdata(dev);
530 - struct ahci_host_priv *hpriv = host->private_data;
531 - int rc;
532 -
533 - rc = ahci_platform_suspend_host(dev);
534 - if (rc)
535 - return rc;
536 -
537 - if (pdata && pdata->suspend) {
538 - rc = pdata->suspend(dev);
539 - if (rc)
540 - goto resume_host;
541 - }
542 -
543 - ahci_platform_disable_resources(hpriv);
544 -
545 - return 0;
546 -
547 -resume_host:
548 - ahci_platform_resume_host(dev);
549 - return rc;
550 -}
551 -EXPORT_SYMBOL_GPL(ahci_platform_suspend);
552 -
553 -/**
554 - * ahci_platform_resume - Resume an ahci-platform device
555 - * @dev: the platform device to resume
556 - *
557 - * This function enables all the resources of the device followed by
558 - * resuming the host associated with the device.
559 - *
560 - * RETURNS:
561 - * 0 on success otherwise a negative error code
562 - */
563 -int ahci_platform_resume(struct device *dev)
564 -{
565 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
566 - struct ata_host *host = dev_get_drvdata(dev);
567 - struct ahci_host_priv *hpriv = host->private_data;
568 - int rc;
569 -
570 - rc = ahci_platform_enable_resources(hpriv);
571 - if (rc)
572 - return rc;
573 -
574 - if (pdata && pdata->resume) {
575 - rc = pdata->resume(dev);
576 - if (rc)
577 - goto disable_resources;
578 - }
579 -
580 - rc = ahci_platform_resume_host(dev);
581 - if (rc)
582 - goto disable_resources;
583 -
584 - /* We resumed so update PM runtime state */
585 - pm_runtime_disable(dev);
586 - pm_runtime_set_active(dev);
587 - pm_runtime_enable(dev);
588 -
589 - return 0;
590 -
591 -disable_resources:
592 - ahci_platform_disable_resources(hpriv);
593 -
594 - return rc;
595 -}
596 -EXPORT_SYMBOL_GPL(ahci_platform_resume);
597 -#endif
598 -
599 static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
600 ahci_platform_resume);
601
602 --- /dev/null
603 +++ b/drivers/ata/libahci_platform.c
604 @@ -0,0 +1,541 @@
605 +/*
606 + * AHCI SATA platform library
607 + *
608 + * Copyright 2004-2005 Red Hat, Inc.
609 + * Jeff Garzik <jgarzik@pobox.com>
610 + * Copyright 2010 MontaVista Software, LLC.
611 + * Anton Vorontsov <avorontsov@ru.mvista.com>
612 + *
613 + * This program is free software; you can redistribute it and/or modify
614 + * it under the terms of the GNU General Public License as published by
615 + * the Free Software Foundation; either version 2, or (at your option)
616 + * any later version.
617 + */
618 +
619 +#include <linux/clk.h>
620 +#include <linux/kernel.h>
621 +#include <linux/gfp.h>
622 +#include <linux/module.h>
623 +#include <linux/pm.h>
624 +#include <linux/interrupt.h>
625 +#include <linux/device.h>
626 +#include <linux/platform_device.h>
627 +#include <linux/libata.h>
628 +#include <linux/ahci_platform.h>
629 +#include <linux/phy/phy.h>
630 +#include <linux/pm_runtime.h>
631 +#include "ahci.h"
632 +
633 +static void ahci_host_stop(struct ata_host *host);
634 +
635 +struct ata_port_operations ahci_platform_ops = {
636 + .inherits = &ahci_ops,
637 + .host_stop = ahci_host_stop,
638 +};
639 +EXPORT_SYMBOL_GPL(ahci_platform_ops);
640 +
641 +static struct scsi_host_template ahci_platform_sht = {
642 + AHCI_SHT("ahci_platform"),
643 +};
644 +
645 +/**
646 + * ahci_platform_enable_clks - Enable platform clocks
647 + * @hpriv: host private area to store config values
648 + *
649 + * This function enables all the clks found in hpriv->clks, starting at
650 + * index 0. If any clk fails to enable it disables all the clks already
651 + * enabled in reverse order, and then returns an error.
652 + *
653 + * RETURNS:
654 + * 0 on success otherwise a negative error code
655 + */
656 +int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
657 +{
658 + int c, rc;
659 +
660 + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
661 + rc = clk_prepare_enable(hpriv->clks[c]);
662 + if (rc)
663 + goto disable_unprepare_clk;
664 + }
665 + return 0;
666 +
667 +disable_unprepare_clk:
668 + while (--c >= 0)
669 + clk_disable_unprepare(hpriv->clks[c]);
670 + return rc;
671 +}
672 +EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
673 +
674 +/**
675 + * ahci_platform_disable_clks - Disable platform clocks
676 + * @hpriv: host private area to store config values
677 + *
678 + * This function disables all the clks found in hpriv->clks, in reverse
679 + * order of ahci_platform_enable_clks (starting at the end of the array).
680 + */
681 +void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
682 +{
683 + int c;
684 +
685 + for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
686 + if (hpriv->clks[c])
687 + clk_disable_unprepare(hpriv->clks[c]);
688 +}
689 +EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
690 +
691 +/**
692 + * ahci_platform_enable_resources - Enable platform resources
693 + * @hpriv: host private area to store config values
694 + *
695 + * This function enables all ahci_platform managed resources in the
696 + * following order:
697 + * 1) Regulator
698 + * 2) Clocks (through ahci_platform_enable_clks)
699 + * 3) Phy
700 + *
701 + * If resource enabling fails at any point the previous enabled resources
702 + * are disabled in reverse order.
703 + *
704 + * RETURNS:
705 + * 0 on success otherwise a negative error code
706 + */
707 +int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
708 +{
709 + int rc;
710 +
711 + if (hpriv->target_pwr) {
712 + rc = regulator_enable(hpriv->target_pwr);
713 + if (rc)
714 + return rc;
715 + }
716 +
717 + rc = ahci_platform_enable_clks(hpriv);
718 + if (rc)
719 + goto disable_regulator;
720 +
721 + if (hpriv->phy) {
722 + rc = phy_init(hpriv->phy);
723 + if (rc)
724 + goto disable_clks;
725 +
726 + rc = phy_power_on(hpriv->phy);
727 + if (rc) {
728 + phy_exit(hpriv->phy);
729 + goto disable_clks;
730 + }
731 + }
732 +
733 + return 0;
734 +
735 +disable_clks:
736 + ahci_platform_disable_clks(hpriv);
737 +
738 +disable_regulator:
739 + if (hpriv->target_pwr)
740 + regulator_disable(hpriv->target_pwr);
741 + return rc;
742 +}
743 +EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
744 +
745 +/**
746 + * ahci_platform_disable_resources - Disable platform resources
747 + * @hpriv: host private area to store config values
748 + *
749 + * This function disables all ahci_platform managed resources in the
750 + * following order:
751 + * 1) Phy
752 + * 2) Clocks (through ahci_platform_disable_clks)
753 + * 3) Regulator
754 + */
755 +void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
756 +{
757 + if (hpriv->phy) {
758 + phy_power_off(hpriv->phy);
759 + phy_exit(hpriv->phy);
760 + }
761 +
762 + ahci_platform_disable_clks(hpriv);
763 +
764 + if (hpriv->target_pwr)
765 + regulator_disable(hpriv->target_pwr);
766 +}
767 +EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
768 +
769 +static void ahci_platform_put_resources(struct device *dev, void *res)
770 +{
771 + struct ahci_host_priv *hpriv = res;
772 + int c;
773 +
774 + if (hpriv->got_runtime_pm) {
775 + pm_runtime_put_sync(dev);
776 + pm_runtime_disable(dev);
777 + }
778 +
779 + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
780 + clk_put(hpriv->clks[c]);
781 +}
782 +
783 +/**
784 + * ahci_platform_get_resources - Get platform resources
785 + * @pdev: platform device to get resources for
786 + *
787 + * This function allocates an ahci_host_priv struct, and gets the following
788 + * resources, storing a reference to them inside the returned struct:
789 + *
790 + * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
791 + * 2) regulator for controlling the targets power (optional)
792 + * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
793 + * or for non devicetree enabled platforms a single clock
794 + * 4) phy (optional)
795 + *
796 + * RETURNS:
797 + * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
798 + */
799 +struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
800 +{
801 + struct device *dev = &pdev->dev;
802 + struct ahci_host_priv *hpriv;
803 + struct clk *clk;
804 + int i, rc = -ENOMEM;
805 +
806 + if (!devres_open_group(dev, NULL, GFP_KERNEL))
807 + return ERR_PTR(-ENOMEM);
808 +
809 + hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
810 + GFP_KERNEL);
811 + if (!hpriv)
812 + goto err_out;
813 +
814 + devres_add(dev, hpriv);
815 +
816 + hpriv->mmio = devm_ioremap_resource(dev,
817 + platform_get_resource(pdev, IORESOURCE_MEM, 0));
818 + if (IS_ERR(hpriv->mmio)) {
819 + dev_err(dev, "no mmio space\n");
820 + rc = PTR_ERR(hpriv->mmio);
821 + goto err_out;
822 + }
823 +
824 + hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
825 + if (IS_ERR(hpriv->target_pwr)) {
826 + rc = PTR_ERR(hpriv->target_pwr);
827 + if (rc == -EPROBE_DEFER)
828 + goto err_out;
829 + hpriv->target_pwr = NULL;
830 + }
831 +
832 + for (i = 0; i < AHCI_MAX_CLKS; i++) {
833 + /*
834 + * For now we must use clk_get(dev, NULL) for the first clock,
835 + * because some platforms (da850, spear13xx) are not yet
836 + * converted to use devicetree for clocks. For new platforms
837 + * this is equivalent to of_clk_get(dev->of_node, 0).
838 + */
839 + if (i == 0)
840 + clk = clk_get(dev, NULL);
841 + else
842 + clk = of_clk_get(dev->of_node, i);
843 +
844 + if (IS_ERR(clk)) {
845 + rc = PTR_ERR(clk);
846 + if (rc == -EPROBE_DEFER)
847 + goto err_out;
848 + break;
849 + }
850 + hpriv->clks[i] = clk;
851 + }
852 +
853 + hpriv->phy = devm_phy_get(dev, "sata-phy");
854 + if (IS_ERR(hpriv->phy)) {
855 + rc = PTR_ERR(hpriv->phy);
856 + switch (rc) {
857 + case -ENODEV:
858 + case -ENOSYS:
859 + /* continue normally */
860 + hpriv->phy = NULL;
861 + break;
862 +
863 + case -EPROBE_DEFER:
864 + goto err_out;
865 +
866 + default:
867 + dev_err(dev, "couldn't get sata-phy\n");
868 + goto err_out;
869 + }
870 + }
871 +
872 + pm_runtime_enable(dev);
873 + pm_runtime_get_sync(dev);
874 + hpriv->got_runtime_pm = true;
875 +
876 + devres_remove_group(dev, NULL);
877 + return hpriv;
878 +
879 +err_out:
880 + devres_release_group(dev, NULL);
881 + return ERR_PTR(rc);
882 +}
883 +EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
884 +
885 +/**
886 + * ahci_platform_init_host - Bring up an ahci-platform host
887 + * @pdev: platform device pointer for the host
888 + * @hpriv: ahci-host private data for the host
889 + * @pi_template: template for the ata_port_info to use
890 + * @force_port_map: param passed to ahci_save_initial_config
891 + * @mask_port_map: param passed to ahci_save_initial_config
892 + *
893 + * This function does all the usual steps needed to bring up an
894 + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
895 + * must be initialized / enabled before calling this.
896 + *
897 + * RETURNS:
898 + * 0 on success otherwise a negative error code
899 + */
900 +int ahci_platform_init_host(struct platform_device *pdev,
901 + struct ahci_host_priv *hpriv,
902 + const struct ata_port_info *pi_template,
903 + unsigned int force_port_map,
904 + unsigned int mask_port_map)
905 +{
906 + struct device *dev = &pdev->dev;
907 + struct ata_port_info pi = *pi_template;
908 + const struct ata_port_info *ppi[] = { &pi, NULL };
909 + struct ata_host *host;
910 + int i, irq, n_ports, rc;
911 +
912 + irq = platform_get_irq(pdev, 0);
913 + if (irq <= 0) {
914 + dev_err(dev, "no irq\n");
915 + return -EINVAL;
916 + }
917 +
918 + /* prepare host */
919 + hpriv->flags |= (unsigned long)pi.private_data;
920 +
921 + ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
922 +
923 + if (hpriv->cap & HOST_CAP_NCQ)
924 + pi.flags |= ATA_FLAG_NCQ;
925 +
926 + if (hpriv->cap & HOST_CAP_PMP)
927 + pi.flags |= ATA_FLAG_PMP;
928 +
929 + ahci_set_em_messages(hpriv, &pi);
930 +
931 + /* CAP.NP sometimes indicate the index of the last enabled
932 + * port, at other times, that of the last possible port, so
933 + * determining the maximum port number requires looking at
934 + * both CAP.NP and port_map.
935 + */
936 + n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
937 +
938 + host = ata_host_alloc_pinfo(dev, ppi, n_ports);
939 + if (!host)
940 + return -ENOMEM;
941 +
942 + host->private_data = hpriv;
943 +
944 + if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
945 + host->flags |= ATA_HOST_PARALLEL_SCAN;
946 + else
947 + dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
948 +
949 + if (pi.flags & ATA_FLAG_EM)
950 + ahci_reset_em(host);
951 +
952 + for (i = 0; i < host->n_ports; i++) {
953 + struct ata_port *ap = host->ports[i];
954 +
955 + ata_port_desc(ap, "mmio %pR",
956 + platform_get_resource(pdev, IORESOURCE_MEM, 0));
957 + ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
958 +
959 + /* set enclosure management message type */
960 + if (ap->flags & ATA_FLAG_EM)
961 + ap->em_message_type = hpriv->em_msg_type;
962 +
963 + /* disabled/not-implemented port */
964 + if (!(hpriv->port_map & (1 << i)))
965 + ap->ops = &ata_dummy_port_ops;
966 + }
967 +
968 + rc = ahci_reset_controller(host);
969 + if (rc)
970 + return rc;
971 +
972 + ahci_init_controller(host);
973 + ahci_print_info(host, "platform");
974 +
975 + return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
976 + &ahci_platform_sht);
977 +}
978 +EXPORT_SYMBOL_GPL(ahci_platform_init_host);
979 +
980 +static void ahci_host_stop(struct ata_host *host)
981 +{
982 + struct device *dev = host->dev;
983 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
984 + struct ahci_host_priv *hpriv = host->private_data;
985 +
986 + if (pdata && pdata->exit)
987 + pdata->exit(dev);
988 +
989 + ahci_platform_disable_resources(hpriv);
990 +}
991 +
992 +#ifdef CONFIG_PM_SLEEP
993 +/**
994 + * ahci_platform_suspend_host - Suspend an ahci-platform host
995 + * @dev: device pointer for the host
996 + *
997 + * This function does all the usual steps needed to suspend an
998 + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
999 + * must be disabled after calling this.
1000 + *
1001 + * RETURNS:
1002 + * 0 on success otherwise a negative error code
1003 + */
1004 +int ahci_platform_suspend_host(struct device *dev)
1005 +{
1006 + struct ata_host *host = dev_get_drvdata(dev);
1007 + struct ahci_host_priv *hpriv = host->private_data;
1008 + void __iomem *mmio = hpriv->mmio;
1009 + u32 ctl;
1010 +
1011 + if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
1012 + dev_err(dev, "firmware update required for suspend/resume\n");
1013 + return -EIO;
1014 + }
1015 +
1016 + /*
1017 + * AHCI spec rev1.1 section 8.3.3:
1018 + * Software must disable interrupts prior to requesting a
1019 + * transition of the HBA to D3 state.
1020 + */
1021 + ctl = readl(mmio + HOST_CTL);
1022 + ctl &= ~HOST_IRQ_EN;
1023 + writel(ctl, mmio + HOST_CTL);
1024 + readl(mmio + HOST_CTL); /* flush */
1025 +
1026 + return ata_host_suspend(host, PMSG_SUSPEND);
1027 +}
1028 +EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
1029 +
1030 +/**
1031 + * ahci_platform_resume_host - Resume an ahci-platform host
1032 + * @dev: device pointer for the host
1033 + *
1034 + * This function does all the usual steps needed to resume an ahci-platform
1035 + * host, note any necessary resources (ie clks, phy, etc.) must be
1036 + * initialized / enabled before calling this.
1037 + *
1038 + * RETURNS:
1039 + * 0 on success otherwise a negative error code
1040 + */
1041 +int ahci_platform_resume_host(struct device *dev)
1042 +{
1043 + struct ata_host *host = dev_get_drvdata(dev);
1044 + int rc;
1045 +
1046 + if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
1047 + rc = ahci_reset_controller(host);
1048 + if (rc)
1049 + return rc;
1050 +
1051 + ahci_init_controller(host);
1052 + }
1053 +
1054 + ata_host_resume(host);
1055 +
1056 + return 0;
1057 +}
1058 +EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
1059 +
1060 +/**
1061 + * ahci_platform_suspend - Suspend an ahci-platform device
1062 + * @dev: the platform device to suspend
1063 + *
1064 + * This function suspends the host associated with the device, followed by
1065 + * disabling all the resources of the device.
1066 + *
1067 + * RETURNS:
1068 + * 0 on success otherwise a negative error code
1069 + */
1070 +int ahci_platform_suspend(struct device *dev)
1071 +{
1072 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
1073 + struct ata_host *host = dev_get_drvdata(dev);
1074 + struct ahci_host_priv *hpriv = host->private_data;
1075 + int rc;
1076 +
1077 + rc = ahci_platform_suspend_host(dev);
1078 + if (rc)
1079 + return rc;
1080 +
1081 + if (pdata && pdata->suspend) {
1082 + rc = pdata->suspend(dev);
1083 + if (rc)
1084 + goto resume_host;
1085 + }
1086 +
1087 + ahci_platform_disable_resources(hpriv);
1088 +
1089 + return 0;
1090 +
1091 +resume_host:
1092 + ahci_platform_resume_host(dev);
1093 + return rc;
1094 +}
1095 +EXPORT_SYMBOL_GPL(ahci_platform_suspend);
1096 +
1097 +/**
1098 + * ahci_platform_resume - Resume an ahci-platform device
1099 + * @dev: the platform device to resume
1100 + *
1101 + * This function enables all the resources of the device followed by
1102 + * resuming the host associated with the device.
1103 + *
1104 + * RETURNS:
1105 + * 0 on success otherwise a negative error code
1106 + */
1107 +int ahci_platform_resume(struct device *dev)
1108 +{
1109 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
1110 + struct ata_host *host = dev_get_drvdata(dev);
1111 + struct ahci_host_priv *hpriv = host->private_data;
1112 + int rc;
1113 +
1114 + rc = ahci_platform_enable_resources(hpriv);
1115 + if (rc)
1116 + return rc;
1117 +
1118 + if (pdata && pdata->resume) {
1119 + rc = pdata->resume(dev);
1120 + if (rc)
1121 + goto disable_resources;
1122 + }
1123 +
1124 + rc = ahci_platform_resume_host(dev);
1125 + if (rc)
1126 + goto disable_resources;
1127 +
1128 + /* We resumed so update PM runtime state */
1129 + pm_runtime_disable(dev);
1130 + pm_runtime_set_active(dev);
1131 + pm_runtime_enable(dev);
1132 +
1133 + return 0;
1134 +
1135 +disable_resources:
1136 + ahci_platform_disable_resources(hpriv);
1137 +
1138 + return rc;
1139 +}
1140 +EXPORT_SYMBOL_GPL(ahci_platform_resume);
1141 +#endif
1142 +
1143 +MODULE_DESCRIPTION("AHCI SATA platform library");
1144 +MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
1145 +MODULE_LICENSE("GPL");