au1000: revert 43626 due to syntax errors
[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");