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
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.
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>
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
26 diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
27 index 868429a..dc950f3 100644
28 --- a/drivers/ata/Kconfig
29 +++ b/drivers/ata/Kconfig
30 @@ -99,7 +99,7 @@ config SATA_AHCI_PLATFORM
33 tristate "Freescale i.MX AHCI SATA support"
34 - depends on SATA_AHCI_PLATFORM && MFD_SYSCON
35 + depends on MFD_SYSCON
37 This option enables support for the Freescale i.MX SoC's
39 diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
40 index 46518c6..366b743 100644
41 --- a/drivers/ata/Makefile
42 +++ b/drivers/ata/Makefile
43 @@ -4,13 +4,13 @@ obj-$(CONFIG_ATA) += libata.o
45 obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
46 obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
47 -obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
48 +obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
49 obj-$(CONFIG_SATA_FSL) += sata_fsl.o
50 obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
51 obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
52 obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
53 obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
54 -obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
55 +obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o
58 obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
59 diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
60 index 7bd6adf..ef67e79 100644
61 --- a/drivers/ata/ahci_platform.c
62 +++ b/drivers/ata/ahci_platform.c
67 -#include <linux/clk.h>
68 #include <linux/kernel.h>
69 -#include <linux/gfp.h>
70 #include <linux/module.h>
72 -#include <linux/interrupt.h>
73 #include <linux/device.h>
74 #include <linux/platform_device.h>
75 #include <linux/libata.h>
76 #include <linux/ahci_platform.h>
77 -#include <linux/phy/phy.h>
78 -#include <linux/pm_runtime.h>
81 -static void ahci_host_stop(struct ata_host *host);
83 -struct ata_port_operations ahci_platform_ops = {
84 - .inherits = &ahci_ops,
85 - .host_stop = ahci_host_stop,
87 -EXPORT_SYMBOL_GPL(ahci_platform_ops);
89 static const struct ata_port_info ahci_port_info = {
90 .flags = AHCI_FLAG_COMMON,
92 @@ -41,345 +28,6 @@ static const struct ata_port_info ahci_port_info = {
93 .port_ops = &ahci_platform_ops,
96 -static struct scsi_host_template ahci_platform_sht = {
97 - AHCI_SHT("ahci_platform"),
101 - * ahci_platform_enable_clks - Enable platform clocks
102 - * @hpriv: host private area to store config values
104 - * This function enables all the clks found in hpriv->clks, starting at
105 - * index 0. If any clk fails to enable it disables all the clks already
106 - * enabled in reverse order, and then returns an error.
109 - * 0 on success otherwise a negative error code
111 -int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
115 - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
116 - rc = clk_prepare_enable(hpriv->clks[c]);
118 - goto disable_unprepare_clk;
122 -disable_unprepare_clk:
124 - clk_disable_unprepare(hpriv->clks[c]);
127 -EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
130 - * ahci_platform_disable_clks - Disable platform clocks
131 - * @hpriv: host private area to store config values
133 - * This function disables all the clks found in hpriv->clks, in reverse
134 - * order of ahci_platform_enable_clks (starting at the end of the array).
136 -void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
140 - for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
141 - if (hpriv->clks[c])
142 - clk_disable_unprepare(hpriv->clks[c]);
144 -EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
147 - * ahci_platform_enable_resources - Enable platform resources
148 - * @hpriv: host private area to store config values
150 - * This function enables all ahci_platform managed resources in the
153 - * 2) Clocks (through ahci_platform_enable_clks)
156 - * If resource enabling fails at any point the previous enabled resources
157 - * are disabled in reverse order.
160 - * 0 on success otherwise a negative error code
162 -int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
166 - if (hpriv->target_pwr) {
167 - rc = regulator_enable(hpriv->target_pwr);
172 - rc = ahci_platform_enable_clks(hpriv);
174 - goto disable_regulator;
177 - rc = phy_init(hpriv->phy);
181 - rc = phy_power_on(hpriv->phy);
183 - phy_exit(hpriv->phy);
191 - ahci_platform_disable_clks(hpriv);
194 - if (hpriv->target_pwr)
195 - regulator_disable(hpriv->target_pwr);
198 -EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
201 - * ahci_platform_disable_resources - Disable platform resources
202 - * @hpriv: host private area to store config values
204 - * This function disables all ahci_platform managed resources in the
207 - * 2) Clocks (through ahci_platform_disable_clks)
210 -void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
213 - phy_power_off(hpriv->phy);
214 - phy_exit(hpriv->phy);
217 - ahci_platform_disable_clks(hpriv);
219 - if (hpriv->target_pwr)
220 - regulator_disable(hpriv->target_pwr);
222 -EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
224 -static void ahci_platform_put_resources(struct device *dev, void *res)
226 - struct ahci_host_priv *hpriv = res;
229 - if (hpriv->got_runtime_pm) {
230 - pm_runtime_put_sync(dev);
231 - pm_runtime_disable(dev);
234 - for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
235 - clk_put(hpriv->clks[c]);
239 - * ahci_platform_get_resources - Get platform resources
240 - * @pdev: platform device to get resources for
242 - * This function allocates an ahci_host_priv struct, and gets the following
243 - * resources, storing a reference to them inside the returned struct:
245 - * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
246 - * 2) regulator for controlling the targets power (optional)
247 - * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
248 - * or for non devicetree enabled platforms a single clock
249 - * 4) phy (optional)
252 - * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
254 -struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
256 - struct device *dev = &pdev->dev;
257 - struct ahci_host_priv *hpriv;
259 - int i, rc = -ENOMEM;
261 - if (!devres_open_group(dev, NULL, GFP_KERNEL))
262 - return ERR_PTR(-ENOMEM);
264 - hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
269 - devres_add(dev, hpriv);
271 - hpriv->mmio = devm_ioremap_resource(dev,
272 - platform_get_resource(pdev, IORESOURCE_MEM, 0));
273 - if (IS_ERR(hpriv->mmio)) {
274 - dev_err(dev, "no mmio space\n");
275 - rc = PTR_ERR(hpriv->mmio);
279 - hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
280 - if (IS_ERR(hpriv->target_pwr)) {
281 - rc = PTR_ERR(hpriv->target_pwr);
282 - if (rc == -EPROBE_DEFER)
284 - hpriv->target_pwr = NULL;
287 - for (i = 0; i < AHCI_MAX_CLKS; i++) {
289 - * For now we must use clk_get(dev, NULL) for the first clock,
290 - * because some platforms (da850, spear13xx) are not yet
291 - * converted to use devicetree for clocks. For new platforms
292 - * this is equivalent to of_clk_get(dev->of_node, 0).
295 - clk = clk_get(dev, NULL);
297 - clk = of_clk_get(dev->of_node, i);
301 - if (rc == -EPROBE_DEFER)
305 - hpriv->clks[i] = clk;
308 - hpriv->phy = devm_phy_get(dev, "sata-phy");
309 - if (IS_ERR(hpriv->phy)) {
310 - rc = PTR_ERR(hpriv->phy);
314 - /* continue normally */
318 - case -EPROBE_DEFER:
322 - dev_err(dev, "couldn't get sata-phy\n");
327 - pm_runtime_enable(dev);
328 - pm_runtime_get_sync(dev);
329 - hpriv->got_runtime_pm = true;
331 - devres_remove_group(dev, NULL);
335 - devres_release_group(dev, NULL);
336 - return ERR_PTR(rc);
338 -EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
341 - * ahci_platform_init_host - Bring up an ahci-platform host
342 - * @pdev: platform device pointer for the host
343 - * @hpriv: ahci-host private data for the host
344 - * @pi_template: template for the ata_port_info to use
345 - * @force_port_map: param passed to ahci_save_initial_config
346 - * @mask_port_map: param passed to ahci_save_initial_config
348 - * This function does all the usual steps needed to bring up an
349 - * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
350 - * must be initialized / enabled before calling this.
353 - * 0 on success otherwise a negative error code
355 -int ahci_platform_init_host(struct platform_device *pdev,
356 - struct ahci_host_priv *hpriv,
357 - const struct ata_port_info *pi_template,
358 - unsigned int force_port_map,
359 - unsigned int mask_port_map)
361 - struct device *dev = &pdev->dev;
362 - struct ata_port_info pi = *pi_template;
363 - const struct ata_port_info *ppi[] = { &pi, NULL };
364 - struct ata_host *host;
365 - int i, irq, n_ports, rc;
367 - irq = platform_get_irq(pdev, 0);
369 - dev_err(dev, "no irq\n");
374 - hpriv->flags |= (unsigned long)pi.private_data;
376 - ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
378 - if (hpriv->cap & HOST_CAP_NCQ)
379 - pi.flags |= ATA_FLAG_NCQ;
381 - if (hpriv->cap & HOST_CAP_PMP)
382 - pi.flags |= ATA_FLAG_PMP;
384 - ahci_set_em_messages(hpriv, &pi);
386 - /* CAP.NP sometimes indicate the index of the last enabled
387 - * port, at other times, that of the last possible port, so
388 - * determining the maximum port number requires looking at
389 - * both CAP.NP and port_map.
391 - n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
393 - host = ata_host_alloc_pinfo(dev, ppi, n_ports);
397 - host->private_data = hpriv;
399 - if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
400 - host->flags |= ATA_HOST_PARALLEL_SCAN;
402 - dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
404 - if (pi.flags & ATA_FLAG_EM)
405 - ahci_reset_em(host);
407 - for (i = 0; i < host->n_ports; i++) {
408 - struct ata_port *ap = host->ports[i];
410 - ata_port_desc(ap, "mmio %pR",
411 - platform_get_resource(pdev, IORESOURCE_MEM, 0));
412 - ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
414 - /* set enclosure management message type */
415 - if (ap->flags & ATA_FLAG_EM)
416 - ap->em_message_type = hpriv->em_msg_type;
418 - /* disabled/not-implemented port */
419 - if (!(hpriv->port_map & (1 << i)))
420 - ap->ops = &ata_dummy_port_ops;
423 - rc = ahci_reset_controller(host);
427 - ahci_init_controller(host);
428 - ahci_print_info(host, "platform");
430 - return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
431 - &ahci_platform_sht);
433 -EXPORT_SYMBOL_GPL(ahci_platform_init_host);
435 static int ahci_probe(struct platform_device *pdev)
437 struct device *dev = &pdev->dev;
438 @@ -420,169 +68,6 @@ disable_resources:
442 -static void ahci_host_stop(struct ata_host *host)
444 - struct device *dev = host->dev;
445 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
446 - struct ahci_host_priv *hpriv = host->private_data;
448 - if (pdata && pdata->exit)
451 - ahci_platform_disable_resources(hpriv);
454 -#ifdef CONFIG_PM_SLEEP
456 - * ahci_platform_suspend_host - Suspend an ahci-platform host
457 - * @dev: device pointer for the host
459 - * This function does all the usual steps needed to suspend an
460 - * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
461 - * must be disabled after calling this.
464 - * 0 on success otherwise a negative error code
466 -int ahci_platform_suspend_host(struct device *dev)
468 - struct ata_host *host = dev_get_drvdata(dev);
469 - struct ahci_host_priv *hpriv = host->private_data;
470 - void __iomem *mmio = hpriv->mmio;
473 - if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
474 - dev_err(dev, "firmware update required for suspend/resume\n");
479 - * AHCI spec rev1.1 section 8.3.3:
480 - * Software must disable interrupts prior to requesting a
481 - * transition of the HBA to D3 state.
483 - ctl = readl(mmio + HOST_CTL);
484 - ctl &= ~HOST_IRQ_EN;
485 - writel(ctl, mmio + HOST_CTL);
486 - readl(mmio + HOST_CTL); /* flush */
488 - return ata_host_suspend(host, PMSG_SUSPEND);
490 -EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
493 - * ahci_platform_resume_host - Resume an ahci-platform host
494 - * @dev: device pointer for the host
496 - * This function does all the usual steps needed to resume an ahci-platform
497 - * host, note any necessary resources (ie clks, phy, etc.) must be
498 - * initialized / enabled before calling this.
501 - * 0 on success otherwise a negative error code
503 -int ahci_platform_resume_host(struct device *dev)
505 - struct ata_host *host = dev_get_drvdata(dev);
508 - if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
509 - rc = ahci_reset_controller(host);
513 - ahci_init_controller(host);
516 - ata_host_resume(host);
520 -EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
523 - * ahci_platform_suspend - Suspend an ahci-platform device
524 - * @dev: the platform device to suspend
526 - * This function suspends the host associated with the device, followed by
527 - * disabling all the resources of the device.
530 - * 0 on success otherwise a negative error code
532 -int ahci_platform_suspend(struct device *dev)
534 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
535 - struct ata_host *host = dev_get_drvdata(dev);
536 - struct ahci_host_priv *hpriv = host->private_data;
539 - rc = ahci_platform_suspend_host(dev);
543 - if (pdata && pdata->suspend) {
544 - rc = pdata->suspend(dev);
549 - ahci_platform_disable_resources(hpriv);
554 - ahci_platform_resume_host(dev);
557 -EXPORT_SYMBOL_GPL(ahci_platform_suspend);
560 - * ahci_platform_resume - Resume an ahci-platform device
561 - * @dev: the platform device to resume
563 - * This function enables all the resources of the device followed by
564 - * resuming the host associated with the device.
567 - * 0 on success otherwise a negative error code
569 -int ahci_platform_resume(struct device *dev)
571 - struct ahci_platform_data *pdata = dev_get_platdata(dev);
572 - struct ata_host *host = dev_get_drvdata(dev);
573 - struct ahci_host_priv *hpriv = host->private_data;
576 - rc = ahci_platform_enable_resources(hpriv);
580 - if (pdata && pdata->resume) {
581 - rc = pdata->resume(dev);
583 - goto disable_resources;
586 - rc = ahci_platform_resume_host(dev);
588 - goto disable_resources;
590 - /* We resumed so update PM runtime state */
591 - pm_runtime_disable(dev);
592 - pm_runtime_set_active(dev);
593 - pm_runtime_enable(dev);
598 - ahci_platform_disable_resources(hpriv);
602 -EXPORT_SYMBOL_GPL(ahci_platform_resume);
605 static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
606 ahci_platform_resume);
608 diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
610 index 0000000..7cb3a85
612 +++ b/drivers/ata/libahci_platform.c
615 + * AHCI SATA platform library
617 + * Copyright 2004-2005 Red Hat, Inc.
618 + * Jeff Garzik <jgarzik@pobox.com>
619 + * Copyright 2010 MontaVista Software, LLC.
620 + * Anton Vorontsov <avorontsov@ru.mvista.com>
622 + * This program is free software; you can redistribute it and/or modify
623 + * it under the terms of the GNU General Public License as published by
624 + * the Free Software Foundation; either version 2, or (at your option)
625 + * any later version.
628 +#include <linux/clk.h>
629 +#include <linux/kernel.h>
630 +#include <linux/gfp.h>
631 +#include <linux/module.h>
632 +#include <linux/pm.h>
633 +#include <linux/interrupt.h>
634 +#include <linux/device.h>
635 +#include <linux/platform_device.h>
636 +#include <linux/libata.h>
637 +#include <linux/ahci_platform.h>
638 +#include <linux/phy/phy.h>
639 +#include <linux/pm_runtime.h>
642 +static void ahci_host_stop(struct ata_host *host);
644 +struct ata_port_operations ahci_platform_ops = {
645 + .inherits = &ahci_ops,
646 + .host_stop = ahci_host_stop,
648 +EXPORT_SYMBOL_GPL(ahci_platform_ops);
650 +static struct scsi_host_template ahci_platform_sht = {
651 + AHCI_SHT("ahci_platform"),
655 + * ahci_platform_enable_clks - Enable platform clocks
656 + * @hpriv: host private area to store config values
658 + * This function enables all the clks found in hpriv->clks, starting at
659 + * index 0. If any clk fails to enable it disables all the clks already
660 + * enabled in reverse order, and then returns an error.
663 + * 0 on success otherwise a negative error code
665 +int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
669 + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
670 + rc = clk_prepare_enable(hpriv->clks[c]);
672 + goto disable_unprepare_clk;
676 +disable_unprepare_clk:
678 + clk_disable_unprepare(hpriv->clks[c]);
681 +EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
684 + * ahci_platform_disable_clks - Disable platform clocks
685 + * @hpriv: host private area to store config values
687 + * This function disables all the clks found in hpriv->clks, in reverse
688 + * order of ahci_platform_enable_clks (starting at the end of the array).
690 +void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
694 + for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
695 + if (hpriv->clks[c])
696 + clk_disable_unprepare(hpriv->clks[c]);
698 +EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
701 + * ahci_platform_enable_resources - Enable platform resources
702 + * @hpriv: host private area to store config values
704 + * This function enables all ahci_platform managed resources in the
707 + * 2) Clocks (through ahci_platform_enable_clks)
710 + * If resource enabling fails at any point the previous enabled resources
711 + * are disabled in reverse order.
714 + * 0 on success otherwise a negative error code
716 +int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
720 + if (hpriv->target_pwr) {
721 + rc = regulator_enable(hpriv->target_pwr);
726 + rc = ahci_platform_enable_clks(hpriv);
728 + goto disable_regulator;
731 + rc = phy_init(hpriv->phy);
735 + rc = phy_power_on(hpriv->phy);
737 + phy_exit(hpriv->phy);
745 + ahci_platform_disable_clks(hpriv);
748 + if (hpriv->target_pwr)
749 + regulator_disable(hpriv->target_pwr);
752 +EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
755 + * ahci_platform_disable_resources - Disable platform resources
756 + * @hpriv: host private area to store config values
758 + * This function disables all ahci_platform managed resources in the
761 + * 2) Clocks (through ahci_platform_disable_clks)
764 +void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
767 + phy_power_off(hpriv->phy);
768 + phy_exit(hpriv->phy);
771 + ahci_platform_disable_clks(hpriv);
773 + if (hpriv->target_pwr)
774 + regulator_disable(hpriv->target_pwr);
776 +EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
778 +static void ahci_platform_put_resources(struct device *dev, void *res)
780 + struct ahci_host_priv *hpriv = res;
783 + if (hpriv->got_runtime_pm) {
784 + pm_runtime_put_sync(dev);
785 + pm_runtime_disable(dev);
788 + for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
789 + clk_put(hpriv->clks[c]);
793 + * ahci_platform_get_resources - Get platform resources
794 + * @pdev: platform device to get resources for
796 + * This function allocates an ahci_host_priv struct, and gets the following
797 + * resources, storing a reference to them inside the returned struct:
799 + * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
800 + * 2) regulator for controlling the targets power (optional)
801 + * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
802 + * or for non devicetree enabled platforms a single clock
803 + * 4) phy (optional)
806 + * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
808 +struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
810 + struct device *dev = &pdev->dev;
811 + struct ahci_host_priv *hpriv;
813 + int i, rc = -ENOMEM;
815 + if (!devres_open_group(dev, NULL, GFP_KERNEL))
816 + return ERR_PTR(-ENOMEM);
818 + hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
823 + devres_add(dev, hpriv);
825 + hpriv->mmio = devm_ioremap_resource(dev,
826 + platform_get_resource(pdev, IORESOURCE_MEM, 0));
827 + if (IS_ERR(hpriv->mmio)) {
828 + dev_err(dev, "no mmio space\n");
829 + rc = PTR_ERR(hpriv->mmio);
833 + hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
834 + if (IS_ERR(hpriv->target_pwr)) {
835 + rc = PTR_ERR(hpriv->target_pwr);
836 + if (rc == -EPROBE_DEFER)
838 + hpriv->target_pwr = NULL;
841 + for (i = 0; i < AHCI_MAX_CLKS; i++) {
843 + * For now we must use clk_get(dev, NULL) for the first clock,
844 + * because some platforms (da850, spear13xx) are not yet
845 + * converted to use devicetree for clocks. For new platforms
846 + * this is equivalent to of_clk_get(dev->of_node, 0).
849 + clk = clk_get(dev, NULL);
851 + clk = of_clk_get(dev->of_node, i);
855 + if (rc == -EPROBE_DEFER)
859 + hpriv->clks[i] = clk;
862 + hpriv->phy = devm_phy_get(dev, "sata-phy");
863 + if (IS_ERR(hpriv->phy)) {
864 + rc = PTR_ERR(hpriv->phy);
868 + /* continue normally */
872 + case -EPROBE_DEFER:
876 + dev_err(dev, "couldn't get sata-phy\n");
881 + pm_runtime_enable(dev);
882 + pm_runtime_get_sync(dev);
883 + hpriv->got_runtime_pm = true;
885 + devres_remove_group(dev, NULL);
889 + devres_release_group(dev, NULL);
890 + return ERR_PTR(rc);
892 +EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
895 + * ahci_platform_init_host - Bring up an ahci-platform host
896 + * @pdev: platform device pointer for the host
897 + * @hpriv: ahci-host private data for the host
898 + * @pi_template: template for the ata_port_info to use
899 + * @force_port_map: param passed to ahci_save_initial_config
900 + * @mask_port_map: param passed to ahci_save_initial_config
902 + * This function does all the usual steps needed to bring up an
903 + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
904 + * must be initialized / enabled before calling this.
907 + * 0 on success otherwise a negative error code
909 +int ahci_platform_init_host(struct platform_device *pdev,
910 + struct ahci_host_priv *hpriv,
911 + const struct ata_port_info *pi_template,
912 + unsigned int force_port_map,
913 + unsigned int mask_port_map)
915 + struct device *dev = &pdev->dev;
916 + struct ata_port_info pi = *pi_template;
917 + const struct ata_port_info *ppi[] = { &pi, NULL };
918 + struct ata_host *host;
919 + int i, irq, n_ports, rc;
921 + irq = platform_get_irq(pdev, 0);
923 + dev_err(dev, "no irq\n");
928 + hpriv->flags |= (unsigned long)pi.private_data;
930 + ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
932 + if (hpriv->cap & HOST_CAP_NCQ)
933 + pi.flags |= ATA_FLAG_NCQ;
935 + if (hpriv->cap & HOST_CAP_PMP)
936 + pi.flags |= ATA_FLAG_PMP;
938 + ahci_set_em_messages(hpriv, &pi);
940 + /* CAP.NP sometimes indicate the index of the last enabled
941 + * port, at other times, that of the last possible port, so
942 + * determining the maximum port number requires looking at
943 + * both CAP.NP and port_map.
945 + n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
947 + host = ata_host_alloc_pinfo(dev, ppi, n_ports);
951 + host->private_data = hpriv;
953 + if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
954 + host->flags |= ATA_HOST_PARALLEL_SCAN;
956 + dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
958 + if (pi.flags & ATA_FLAG_EM)
959 + ahci_reset_em(host);
961 + for (i = 0; i < host->n_ports; i++) {
962 + struct ata_port *ap = host->ports[i];
964 + ata_port_desc(ap, "mmio %pR",
965 + platform_get_resource(pdev, IORESOURCE_MEM, 0));
966 + ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
968 + /* set enclosure management message type */
969 + if (ap->flags & ATA_FLAG_EM)
970 + ap->em_message_type = hpriv->em_msg_type;
972 + /* disabled/not-implemented port */
973 + if (!(hpriv->port_map & (1 << i)))
974 + ap->ops = &ata_dummy_port_ops;
977 + rc = ahci_reset_controller(host);
981 + ahci_init_controller(host);
982 + ahci_print_info(host, "platform");
984 + return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
985 + &ahci_platform_sht);
987 +EXPORT_SYMBOL_GPL(ahci_platform_init_host);
989 +static void ahci_host_stop(struct ata_host *host)
991 + struct device *dev = host->dev;
992 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
993 + struct ahci_host_priv *hpriv = host->private_data;
995 + if (pdata && pdata->exit)
998 + ahci_platform_disable_resources(hpriv);
1001 +#ifdef CONFIG_PM_SLEEP
1003 + * ahci_platform_suspend_host - Suspend an ahci-platform host
1004 + * @dev: device pointer for the host
1006 + * This function does all the usual steps needed to suspend an
1007 + * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
1008 + * must be disabled after calling this.
1011 + * 0 on success otherwise a negative error code
1013 +int ahci_platform_suspend_host(struct device *dev)
1015 + struct ata_host *host = dev_get_drvdata(dev);
1016 + struct ahci_host_priv *hpriv = host->private_data;
1017 + void __iomem *mmio = hpriv->mmio;
1020 + if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
1021 + dev_err(dev, "firmware update required for suspend/resume\n");
1026 + * AHCI spec rev1.1 section 8.3.3:
1027 + * Software must disable interrupts prior to requesting a
1028 + * transition of the HBA to D3 state.
1030 + ctl = readl(mmio + HOST_CTL);
1031 + ctl &= ~HOST_IRQ_EN;
1032 + writel(ctl, mmio + HOST_CTL);
1033 + readl(mmio + HOST_CTL); /* flush */
1035 + return ata_host_suspend(host, PMSG_SUSPEND);
1037 +EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
1040 + * ahci_platform_resume_host - Resume an ahci-platform host
1041 + * @dev: device pointer for the host
1043 + * This function does all the usual steps needed to resume an ahci-platform
1044 + * host, note any necessary resources (ie clks, phy, etc.) must be
1045 + * initialized / enabled before calling this.
1048 + * 0 on success otherwise a negative error code
1050 +int ahci_platform_resume_host(struct device *dev)
1052 + struct ata_host *host = dev_get_drvdata(dev);
1055 + if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
1056 + rc = ahci_reset_controller(host);
1060 + ahci_init_controller(host);
1063 + ata_host_resume(host);
1067 +EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
1070 + * ahci_platform_suspend - Suspend an ahci-platform device
1071 + * @dev: the platform device to suspend
1073 + * This function suspends the host associated with the device, followed by
1074 + * disabling all the resources of the device.
1077 + * 0 on success otherwise a negative error code
1079 +int ahci_platform_suspend(struct device *dev)
1081 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
1082 + struct ata_host *host = dev_get_drvdata(dev);
1083 + struct ahci_host_priv *hpriv = host->private_data;
1086 + rc = ahci_platform_suspend_host(dev);
1090 + if (pdata && pdata->suspend) {
1091 + rc = pdata->suspend(dev);
1096 + ahci_platform_disable_resources(hpriv);
1101 + ahci_platform_resume_host(dev);
1104 +EXPORT_SYMBOL_GPL(ahci_platform_suspend);
1107 + * ahci_platform_resume - Resume an ahci-platform device
1108 + * @dev: the platform device to resume
1110 + * This function enables all the resources of the device followed by
1111 + * resuming the host associated with the device.
1114 + * 0 on success otherwise a negative error code
1116 +int ahci_platform_resume(struct device *dev)
1118 + struct ahci_platform_data *pdata = dev_get_platdata(dev);
1119 + struct ata_host *host = dev_get_drvdata(dev);
1120 + struct ahci_host_priv *hpriv = host->private_data;
1123 + rc = ahci_platform_enable_resources(hpriv);
1127 + if (pdata && pdata->resume) {
1128 + rc = pdata->resume(dev);
1130 + goto disable_resources;
1133 + rc = ahci_platform_resume_host(dev);
1135 + goto disable_resources;
1137 + /* We resumed so update PM runtime state */
1138 + pm_runtime_disable(dev);
1139 + pm_runtime_set_active(dev);
1140 + pm_runtime_enable(dev);
1145 + ahci_platform_disable_resources(hpriv);
1149 +EXPORT_SYMBOL_GPL(ahci_platform_resume);
1152 +MODULE_DESCRIPTION("AHCI SATA platform library");
1153 +MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
1154 +MODULE_LICENSE("GPL");