summaryrefslogtreecommitdiff
path: root/target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch')
-rw-r--r--target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch1145
1 files changed, 0 insertions, 1145 deletions
diff --git a/target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch b/target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch
deleted file mode 100644
index eca606b..0000000
--- a/target/linux/ipq806x/patches/0124-ata-move-library-code-from-ahci_platform.c-to-libahc.patch
+++ /dev/null
@@ -1,1145 +0,0 @@
-From 04800db1047afbf6701379435bff1a6fa64215f7 Mon Sep 17 00:00:00 2001
-From: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-Date: Tue, 25 Mar 2014 19:51:39 +0100
-Subject: [PATCH 124/182] ata: move library code from ahci_platform.c to
- libahci_platform.c
-
-Move AHCI platform library code from ahci_platform.c to
-libahci_platform.c and fix dependencies for ahci_st,
-ahci_imx and ahci_sunxi drivers.
-
-Acked-by: Hans de Goede <hdegoede@redhat.com>
-Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-Signed-off-by: Tejun Heo <tj@kernel.org>
-
-Conflicts:
- drivers/ata/Kconfig
- drivers/ata/Makefile
----
- drivers/ata/Kconfig | 2 +-
- drivers/ata/Makefile | 4 +-
- drivers/ata/ahci_platform.c | 515 --------------------------------------
- drivers/ata/libahci_platform.c | 541 ++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 544 insertions(+), 518 deletions(-)
- create mode 100644 drivers/ata/libahci_platform.c
-
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -115,7 +115,7 @@ config SATA_AHCI_PLATFORM
-
- config AHCI_IMX
- tristate "Freescale i.MX AHCI SATA support"
-- depends on SATA_AHCI_PLATFORM && MFD_SYSCON
-+ depends on MFD_SYSCON
- help
- This option enables support for the Freescale i.MX SoC's
- onboard AHCI SATA.
---- a/drivers/ata/Makefile
-+++ b/drivers/ata/Makefile
-@@ -4,13 +4,13 @@ obj-$(CONFIG_ATA) += libata.o
- # non-SFF interface
- obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o
- obj-$(CONFIG_SATA_ACARD_AHCI) += acard-ahci.o libahci.o
--obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o
-+obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o libahci_platform.o
- obj-$(CONFIG_SATA_FSL) += sata_fsl.o
- obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o
- obj-$(CONFIG_SATA_SIL24) += sata_sil24.o
- obj-$(CONFIG_SATA_DWC) += sata_dwc_460ex.o
- obj-$(CONFIG_SATA_HIGHBANK) += sata_highbank.o libahci.o
--obj-$(CONFIG_AHCI_IMX) += ahci_imx.o
-+obj-$(CONFIG_AHCI_IMX) += ahci_imx.o libahci.o libahci_platform.o
-
- # SFF w/ custom DMA
- obj-$(CONFIG_PDC_ADMA) += pdc_adma.o
---- a/drivers/ata/ahci_platform.c
-+++ b/drivers/ata/ahci_platform.c
-@@ -12,28 +12,15 @@
- * any later version.
- */
-
--#include <linux/clk.h>
- #include <linux/kernel.h>
--#include <linux/gfp.h>
- #include <linux/module.h>
- #include <linux/pm.h>
--#include <linux/interrupt.h>
- #include <linux/device.h>
- #include <linux/platform_device.h>
- #include <linux/libata.h>
- #include <linux/ahci_platform.h>
--#include <linux/phy/phy.h>
--#include <linux/pm_runtime.h>
- #include "ahci.h"
-
--static void ahci_host_stop(struct ata_host *host);
--
--struct ata_port_operations ahci_platform_ops = {
-- .inherits = &ahci_ops,
-- .host_stop = ahci_host_stop,
--};
--EXPORT_SYMBOL_GPL(ahci_platform_ops);
--
- static const struct ata_port_info ahci_port_info = {
- .flags = AHCI_FLAG_COMMON,
- .pio_mask = ATA_PIO4,
-@@ -41,345 +28,6 @@ static const struct ata_port_info ahci_p
- .port_ops = &ahci_platform_ops,
- };
-
--static struct scsi_host_template ahci_platform_sht = {
-- AHCI_SHT("ahci_platform"),
--};
--
--/**
-- * ahci_platform_enable_clks - Enable platform clocks
-- * @hpriv: host private area to store config values
-- *
-- * This function enables all the clks found in hpriv->clks, starting at
-- * index 0. If any clk fails to enable it disables all the clks already
-- * enabled in reverse order, and then returns an error.
-- *
-- * RETURNS:
-- * 0 on success otherwise a negative error code
-- */
--int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
--{
-- int c, rc;
--
-- for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
-- rc = clk_prepare_enable(hpriv->clks[c]);
-- if (rc)
-- goto disable_unprepare_clk;
-- }
-- return 0;
--
--disable_unprepare_clk:
-- while (--c >= 0)
-- clk_disable_unprepare(hpriv->clks[c]);
-- return rc;
--}
--EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
--
--/**
-- * ahci_platform_disable_clks - Disable platform clocks
-- * @hpriv: host private area to store config values
-- *
-- * This function disables all the clks found in hpriv->clks, in reverse
-- * order of ahci_platform_enable_clks (starting at the end of the array).
-- */
--void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
--{
-- int c;
--
-- for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
-- if (hpriv->clks[c])
-- clk_disable_unprepare(hpriv->clks[c]);
--}
--EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
--
--/**
-- * ahci_platform_enable_resources - Enable platform resources
-- * @hpriv: host private area to store config values
-- *
-- * This function enables all ahci_platform managed resources in the
-- * following order:
-- * 1) Regulator
-- * 2) Clocks (through ahci_platform_enable_clks)
-- * 3) Phy
-- *
-- * If resource enabling fails at any point the previous enabled resources
-- * are disabled in reverse order.
-- *
-- * RETURNS:
-- * 0 on success otherwise a negative error code
-- */
--int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
--{
-- int rc;
--
-- if (hpriv->target_pwr) {
-- rc = regulator_enable(hpriv->target_pwr);
-- if (rc)
-- return rc;
-- }
--
-- rc = ahci_platform_enable_clks(hpriv);
-- if (rc)
-- goto disable_regulator;
--
-- if (hpriv->phy) {
-- rc = phy_init(hpriv->phy);
-- if (rc)
-- goto disable_clks;
--
-- rc = phy_power_on(hpriv->phy);
-- if (rc) {
-- phy_exit(hpriv->phy);
-- goto disable_clks;
-- }
-- }
--
-- return 0;
--
--disable_clks:
-- ahci_platform_disable_clks(hpriv);
--
--disable_regulator:
-- if (hpriv->target_pwr)
-- regulator_disable(hpriv->target_pwr);
-- return rc;
--}
--EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
--
--/**
-- * ahci_platform_disable_resources - Disable platform resources
-- * @hpriv: host private area to store config values
-- *
-- * This function disables all ahci_platform managed resources in the
-- * following order:
-- * 1) Phy
-- * 2) Clocks (through ahci_platform_disable_clks)
-- * 3) Regulator
-- */
--void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
--{
-- if (hpriv->phy) {
-- phy_power_off(hpriv->phy);
-- phy_exit(hpriv->phy);
-- }
--
-- ahci_platform_disable_clks(hpriv);
--
-- if (hpriv->target_pwr)
-- regulator_disable(hpriv->target_pwr);
--}
--EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
--
--static void ahci_platform_put_resources(struct device *dev, void *res)
--{
-- struct ahci_host_priv *hpriv = res;
-- int c;
--
-- if (hpriv->got_runtime_pm) {
-- pm_runtime_put_sync(dev);
-- pm_runtime_disable(dev);
-- }
--
-- for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
-- clk_put(hpriv->clks[c]);
--}
--
--/**
-- * ahci_platform_get_resources - Get platform resources
-- * @pdev: platform device to get resources for
-- *
-- * This function allocates an ahci_host_priv struct, and gets the following
-- * resources, storing a reference to them inside the returned struct:
-- *
-- * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
-- * 2) regulator for controlling the targets power (optional)
-- * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
-- * or for non devicetree enabled platforms a single clock
-- * 4) phy (optional)
-- *
-- * RETURNS:
-- * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
-- */
--struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
--{
-- struct device *dev = &pdev->dev;
-- struct ahci_host_priv *hpriv;
-- struct clk *clk;
-- int i, rc = -ENOMEM;
--
-- if (!devres_open_group(dev, NULL, GFP_KERNEL))
-- return ERR_PTR(-ENOMEM);
--
-- hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
-- GFP_KERNEL);
-- if (!hpriv)
-- goto err_out;
--
-- devres_add(dev, hpriv);
--
-- hpriv->mmio = devm_ioremap_resource(dev,
-- platform_get_resource(pdev, IORESOURCE_MEM, 0));
-- if (IS_ERR(hpriv->mmio)) {
-- dev_err(dev, "no mmio space\n");
-- rc = PTR_ERR(hpriv->mmio);
-- goto err_out;
-- }
--
-- hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
-- if (IS_ERR(hpriv->target_pwr)) {
-- rc = PTR_ERR(hpriv->target_pwr);
-- if (rc == -EPROBE_DEFER)
-- goto err_out;
-- hpriv->target_pwr = NULL;
-- }
--
-- for (i = 0; i < AHCI_MAX_CLKS; i++) {
-- /*
-- * For now we must use clk_get(dev, NULL) for the first clock,
-- * because some platforms (da850, spear13xx) are not yet
-- * converted to use devicetree for clocks. For new platforms
-- * this is equivalent to of_clk_get(dev->of_node, 0).
-- */
-- if (i == 0)
-- clk = clk_get(dev, NULL);
-- else
-- clk = of_clk_get(dev->of_node, i);
--
-- if (IS_ERR(clk)) {
-- rc = PTR_ERR(clk);
-- if (rc == -EPROBE_DEFER)
-- goto err_out;
-- break;
-- }
-- hpriv->clks[i] = clk;
-- }
--
-- hpriv->phy = devm_phy_get(dev, "sata-phy");
-- if (IS_ERR(hpriv->phy)) {
-- rc = PTR_ERR(hpriv->phy);
-- switch (rc) {
-- case -ENODEV:
-- case -ENOSYS:
-- /* continue normally */
-- hpriv->phy = NULL;
-- break;
--
-- case -EPROBE_DEFER:
-- goto err_out;
--
-- default:
-- dev_err(dev, "couldn't get sata-phy\n");
-- goto err_out;
-- }
-- }
--
-- pm_runtime_enable(dev);
-- pm_runtime_get_sync(dev);
-- hpriv->got_runtime_pm = true;
--
-- devres_remove_group(dev, NULL);
-- return hpriv;
--
--err_out:
-- devres_release_group(dev, NULL);
-- return ERR_PTR(rc);
--}
--EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
--
--/**
-- * ahci_platform_init_host - Bring up an ahci-platform host
-- * @pdev: platform device pointer for the host
-- * @hpriv: ahci-host private data for the host
-- * @pi_template: template for the ata_port_info to use
-- * @force_port_map: param passed to ahci_save_initial_config
-- * @mask_port_map: param passed to ahci_save_initial_config
-- *
-- * This function does all the usual steps needed to bring up an
-- * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
-- * must be initialized / enabled before calling this.
-- *
-- * RETURNS:
-- * 0 on success otherwise a negative error code
-- */
--int ahci_platform_init_host(struct platform_device *pdev,
-- struct ahci_host_priv *hpriv,
-- const struct ata_port_info *pi_template,
-- unsigned int force_port_map,
-- unsigned int mask_port_map)
--{
-- struct device *dev = &pdev->dev;
-- struct ata_port_info pi = *pi_template;
-- const struct ata_port_info *ppi[] = { &pi, NULL };
-- struct ata_host *host;
-- int i, irq, n_ports, rc;
--
-- irq = platform_get_irq(pdev, 0);
-- if (irq <= 0) {
-- dev_err(dev, "no irq\n");
-- return -EINVAL;
-- }
--
-- /* prepare host */
-- hpriv->flags |= (unsigned long)pi.private_data;
--
-- ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
--
-- if (hpriv->cap & HOST_CAP_NCQ)
-- pi.flags |= ATA_FLAG_NCQ;
--
-- if (hpriv->cap & HOST_CAP_PMP)
-- pi.flags |= ATA_FLAG_PMP;
--
-- ahci_set_em_messages(hpriv, &pi);
--
-- /* CAP.NP sometimes indicate the index of the last enabled
-- * port, at other times, that of the last possible port, so
-- * determining the maximum port number requires looking at
-- * both CAP.NP and port_map.
-- */
-- n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
--
-- host = ata_host_alloc_pinfo(dev, ppi, n_ports);
-- if (!host)
-- return -ENOMEM;
--
-- host->private_data = hpriv;
--
-- if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
-- host->flags |= ATA_HOST_PARALLEL_SCAN;
-- else
-- dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
--
-- if (pi.flags & ATA_FLAG_EM)
-- ahci_reset_em(host);
--
-- for (i = 0; i < host->n_ports; i++) {
-- struct ata_port *ap = host->ports[i];
--
-- ata_port_desc(ap, "mmio %pR",
-- platform_get_resource(pdev, IORESOURCE_MEM, 0));
-- ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
--
-- /* set enclosure management message type */
-- if (ap->flags & ATA_FLAG_EM)
-- ap->em_message_type = hpriv->em_msg_type;
--
-- /* disabled/not-implemented port */
-- if (!(hpriv->port_map & (1 << i)))
-- ap->ops = &ata_dummy_port_ops;
-- }
--
-- rc = ahci_reset_controller(host);
-- if (rc)
-- return rc;
--
-- ahci_init_controller(host);
-- ahci_print_info(host, "platform");
--
-- return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
-- &ahci_platform_sht);
--}
--EXPORT_SYMBOL_GPL(ahci_platform_init_host);
--
- static int ahci_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
-@@ -420,169 +68,6 @@ disable_resources:
- return rc;
- }
-
--static void ahci_host_stop(struct ata_host *host)
--{
-- struct device *dev = host->dev;
-- struct ahci_platform_data *pdata = dev_get_platdata(dev);
-- struct ahci_host_priv *hpriv = host->private_data;
--
-- if (pdata && pdata->exit)
-- pdata->exit(dev);
--
-- ahci_platform_disable_resources(hpriv);
--}
--
--#ifdef CONFIG_PM_SLEEP
--/**
-- * ahci_platform_suspend_host - Suspend an ahci-platform host
-- * @dev: device pointer for the host
-- *
-- * This function does all the usual steps needed to suspend an
-- * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
-- * must be disabled after calling this.
-- *
-- * RETURNS:
-- * 0 on success otherwise a negative error code
-- */
--int ahci_platform_suspend_host(struct device *dev)
--{
-- struct ata_host *host = dev_get_drvdata(dev);
-- struct ahci_host_priv *hpriv = host->private_data;
-- void __iomem *mmio = hpriv->mmio;
-- u32 ctl;
--
-- if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
-- dev_err(dev, "firmware update required for suspend/resume\n");
-- return -EIO;
-- }
--
-- /*
-- * AHCI spec rev1.1 section 8.3.3:
-- * Software must disable interrupts prior to requesting a
-- * transition of the HBA to D3 state.
-- */
-- ctl = readl(mmio + HOST_CTL);
-- ctl &= ~HOST_IRQ_EN;
-- writel(ctl, mmio + HOST_CTL);
-- readl(mmio + HOST_CTL); /* flush */
--
-- return ata_host_suspend(host, PMSG_SUSPEND);
--}
--EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
--
--/**
-- * ahci_platform_resume_host - Resume an ahci-platform host
-- * @dev: device pointer for the host
-- *
-- * This function does all the usual steps needed to resume an ahci-platform
-- * host, note any necessary resources (ie clks, phy, etc.) must be
-- * initialized / enabled before calling this.
-- *
-- * RETURNS:
-- * 0 on success otherwise a negative error code
-- */
--int ahci_platform_resume_host(struct device *dev)
--{
-- struct ata_host *host = dev_get_drvdata(dev);
-- int rc;
--
-- if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
-- rc = ahci_reset_controller(host);
-- if (rc)
-- return rc;
--
-- ahci_init_controller(host);
-- }
--
-- ata_host_resume(host);
--
-- return 0;
--}
--EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
--
--/**
-- * ahci_platform_suspend - Suspend an ahci-platform device
-- * @dev: the platform device to suspend
-- *
-- * This function suspends the host associated with the device, followed by
-- * disabling all the resources of the device.
-- *
-- * RETURNS:
-- * 0 on success otherwise a negative error code
-- */
--int ahci_platform_suspend(struct device *dev)
--{
-- struct ahci_platform_data *pdata = dev_get_platdata(dev);
-- struct ata_host *host = dev_get_drvdata(dev);
-- struct ahci_host_priv *hpriv = host->private_data;
-- int rc;
--
-- rc = ahci_platform_suspend_host(dev);
-- if (rc)
-- return rc;
--
-- if (pdata && pdata->suspend) {
-- rc = pdata->suspend(dev);
-- if (rc)
-- goto resume_host;
-- }
--
-- ahci_platform_disable_resources(hpriv);
--
-- return 0;
--
--resume_host:
-- ahci_platform_resume_host(dev);
-- return rc;
--}
--EXPORT_SYMBOL_GPL(ahci_platform_suspend);
--
--/**
-- * ahci_platform_resume - Resume an ahci-platform device
-- * @dev: the platform device to resume
-- *
-- * This function enables all the resources of the device followed by
-- * resuming the host associated with the device.
-- *
-- * RETURNS:
-- * 0 on success otherwise a negative error code
-- */
--int ahci_platform_resume(struct device *dev)
--{
-- struct ahci_platform_data *pdata = dev_get_platdata(dev);
-- struct ata_host *host = dev_get_drvdata(dev);
-- struct ahci_host_priv *hpriv = host->private_data;
-- int rc;
--
-- rc = ahci_platform_enable_resources(hpriv);
-- if (rc)
-- return rc;
--
-- if (pdata && pdata->resume) {
-- rc = pdata->resume(dev);
-- if (rc)
-- goto disable_resources;
-- }
--
-- rc = ahci_platform_resume_host(dev);
-- if (rc)
-- goto disable_resources;
--
-- /* We resumed so update PM runtime state */
-- pm_runtime_disable(dev);
-- pm_runtime_set_active(dev);
-- pm_runtime_enable(dev);
--
-- return 0;
--
--disable_resources:
-- ahci_platform_disable_resources(hpriv);
--
-- return rc;
--}
--EXPORT_SYMBOL_GPL(ahci_platform_resume);
--#endif
--
- static SIMPLE_DEV_PM_OPS(ahci_pm_ops, ahci_platform_suspend,
- ahci_platform_resume);
-
---- /dev/null
-+++ b/drivers/ata/libahci_platform.c
-@@ -0,0 +1,541 @@
-+/*
-+ * AHCI SATA platform library
-+ *
-+ * Copyright 2004-2005 Red Hat, Inc.
-+ * Jeff Garzik <jgarzik@pobox.com>
-+ * Copyright 2010 MontaVista Software, LLC.
-+ * Anton Vorontsov <avorontsov@ru.mvista.com>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2, or (at your option)
-+ * any later version.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/kernel.h>
-+#include <linux/gfp.h>
-+#include <linux/module.h>
-+#include <linux/pm.h>
-+#include <linux/interrupt.h>
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
-+#include <linux/libata.h>
-+#include <linux/ahci_platform.h>
-+#include <linux/phy/phy.h>
-+#include <linux/pm_runtime.h>
-+#include "ahci.h"
-+
-+static void ahci_host_stop(struct ata_host *host);
-+
-+struct ata_port_operations ahci_platform_ops = {
-+ .inherits = &ahci_ops,
-+ .host_stop = ahci_host_stop,
-+};
-+EXPORT_SYMBOL_GPL(ahci_platform_ops);
-+
-+static struct scsi_host_template ahci_platform_sht = {
-+ AHCI_SHT("ahci_platform"),
-+};
-+
-+/**
-+ * ahci_platform_enable_clks - Enable platform clocks
-+ * @hpriv: host private area to store config values
-+ *
-+ * This function enables all the clks found in hpriv->clks, starting at
-+ * index 0. If any clk fails to enable it disables all the clks already
-+ * enabled in reverse order, and then returns an error.
-+ *
-+ * RETURNS:
-+ * 0 on success otherwise a negative error code
-+ */
-+int ahci_platform_enable_clks(struct ahci_host_priv *hpriv)
-+{
-+ int c, rc;
-+
-+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++) {
-+ rc = clk_prepare_enable(hpriv->clks[c]);
-+ if (rc)
-+ goto disable_unprepare_clk;
-+ }
-+ return 0;
-+
-+disable_unprepare_clk:
-+ while (--c >= 0)
-+ clk_disable_unprepare(hpriv->clks[c]);
-+ return rc;
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_enable_clks);
-+
-+/**
-+ * ahci_platform_disable_clks - Disable platform clocks
-+ * @hpriv: host private area to store config values
-+ *
-+ * This function disables all the clks found in hpriv->clks, in reverse
-+ * order of ahci_platform_enable_clks (starting at the end of the array).
-+ */
-+void ahci_platform_disable_clks(struct ahci_host_priv *hpriv)
-+{
-+ int c;
-+
-+ for (c = AHCI_MAX_CLKS - 1; c >= 0; c--)
-+ if (hpriv->clks[c])
-+ clk_disable_unprepare(hpriv->clks[c]);
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_disable_clks);
-+
-+/**
-+ * ahci_platform_enable_resources - Enable platform resources
-+ * @hpriv: host private area to store config values
-+ *
-+ * This function enables all ahci_platform managed resources in the
-+ * following order:
-+ * 1) Regulator
-+ * 2) Clocks (through ahci_platform_enable_clks)
-+ * 3) Phy
-+ *
-+ * If resource enabling fails at any point the previous enabled resources
-+ * are disabled in reverse order.
-+ *
-+ * RETURNS:
-+ * 0 on success otherwise a negative error code
-+ */
-+int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
-+{
-+ int rc;
-+
-+ if (hpriv->target_pwr) {
-+ rc = regulator_enable(hpriv->target_pwr);
-+ if (rc)
-+ return rc;
-+ }
-+
-+ rc = ahci_platform_enable_clks(hpriv);
-+ if (rc)
-+ goto disable_regulator;
-+
-+ if (hpriv->phy) {
-+ rc = phy_init(hpriv->phy);
-+ if (rc)
-+ goto disable_clks;
-+
-+ rc = phy_power_on(hpriv->phy);
-+ if (rc) {
-+ phy_exit(hpriv->phy);
-+ goto disable_clks;
-+ }
-+ }
-+
-+ return 0;
-+
-+disable_clks:
-+ ahci_platform_disable_clks(hpriv);
-+
-+disable_regulator:
-+ if (hpriv->target_pwr)
-+ regulator_disable(hpriv->target_pwr);
-+ return rc;
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
-+
-+/**
-+ * ahci_platform_disable_resources - Disable platform resources
-+ * @hpriv: host private area to store config values
-+ *
-+ * This function disables all ahci_platform managed resources in the
-+ * following order:
-+ * 1) Phy
-+ * 2) Clocks (through ahci_platform_disable_clks)
-+ * 3) Regulator
-+ */
-+void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
-+{
-+ if (hpriv->phy) {
-+ phy_power_off(hpriv->phy);
-+ phy_exit(hpriv->phy);
-+ }
-+
-+ ahci_platform_disable_clks(hpriv);
-+
-+ if (hpriv->target_pwr)
-+ regulator_disable(hpriv->target_pwr);
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_disable_resources);
-+
-+static void ahci_platform_put_resources(struct device *dev, void *res)
-+{
-+ struct ahci_host_priv *hpriv = res;
-+ int c;
-+
-+ if (hpriv->got_runtime_pm) {
-+ pm_runtime_put_sync(dev);
-+ pm_runtime_disable(dev);
-+ }
-+
-+ for (c = 0; c < AHCI_MAX_CLKS && hpriv->clks[c]; c++)
-+ clk_put(hpriv->clks[c]);
-+}
-+
-+/**
-+ * ahci_platform_get_resources - Get platform resources
-+ * @pdev: platform device to get resources for
-+ *
-+ * This function allocates an ahci_host_priv struct, and gets the following
-+ * resources, storing a reference to them inside the returned struct:
-+ *
-+ * 1) mmio registers (IORESOURCE_MEM 0, mandatory)
-+ * 2) regulator for controlling the targets power (optional)
-+ * 3) 0 - AHCI_MAX_CLKS clocks, as specified in the devs devicetree node,
-+ * or for non devicetree enabled platforms a single clock
-+ * 4) phy (optional)
-+ *
-+ * RETURNS:
-+ * The allocated ahci_host_priv on success, otherwise an ERR_PTR value
-+ */
-+struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct ahci_host_priv *hpriv;
-+ struct clk *clk;
-+ int i, rc = -ENOMEM;
-+
-+ if (!devres_open_group(dev, NULL, GFP_KERNEL))
-+ return ERR_PTR(-ENOMEM);
-+
-+ hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv),
-+ GFP_KERNEL);
-+ if (!hpriv)
-+ goto err_out;
-+
-+ devres_add(dev, hpriv);
-+
-+ hpriv->mmio = devm_ioremap_resource(dev,
-+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
-+ if (IS_ERR(hpriv->mmio)) {
-+ dev_err(dev, "no mmio space\n");
-+ rc = PTR_ERR(hpriv->mmio);
-+ goto err_out;
-+ }
-+
-+ hpriv->target_pwr = devm_regulator_get_optional(dev, "target");
-+ if (IS_ERR(hpriv->target_pwr)) {
-+ rc = PTR_ERR(hpriv->target_pwr);
-+ if (rc == -EPROBE_DEFER)
-+ goto err_out;
-+ hpriv->target_pwr = NULL;
-+ }
-+
-+ for (i = 0; i < AHCI_MAX_CLKS; i++) {
-+ /*
-+ * For now we must use clk_get(dev, NULL) for the first clock,
-+ * because some platforms (da850, spear13xx) are not yet
-+ * converted to use devicetree for clocks. For new platforms
-+ * this is equivalent to of_clk_get(dev->of_node, 0).
-+ */
-+ if (i == 0)
-+ clk = clk_get(dev, NULL);
-+ else
-+ clk = of_clk_get(dev->of_node, i);
-+
-+ if (IS_ERR(clk)) {
-+ rc = PTR_ERR(clk);
-+ if (rc == -EPROBE_DEFER)
-+ goto err_out;
-+ break;
-+ }
-+ hpriv->clks[i] = clk;
-+ }
-+
-+ hpriv->phy = devm_phy_get(dev, "sata-phy");
-+ if (IS_ERR(hpriv->phy)) {
-+ rc = PTR_ERR(hpriv->phy);
-+ switch (rc) {
-+ case -ENODEV:
-+ case -ENOSYS:
-+ /* continue normally */
-+ hpriv->phy = NULL;
-+ break;
-+
-+ case -EPROBE_DEFER:
-+ goto err_out;
-+
-+ default:
-+ dev_err(dev, "couldn't get sata-phy\n");
-+ goto err_out;
-+ }
-+ }
-+
-+ pm_runtime_enable(dev);
-+ pm_runtime_get_sync(dev);
-+ hpriv->got_runtime_pm = true;
-+
-+ devres_remove_group(dev, NULL);
-+ return hpriv;
-+
-+err_out:
-+ devres_release_group(dev, NULL);
-+ return ERR_PTR(rc);
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_get_resources);
-+
-+/**
-+ * ahci_platform_init_host - Bring up an ahci-platform host
-+ * @pdev: platform device pointer for the host
-+ * @hpriv: ahci-host private data for the host
-+ * @pi_template: template for the ata_port_info to use
-+ * @force_port_map: param passed to ahci_save_initial_config
-+ * @mask_port_map: param passed to ahci_save_initial_config
-+ *
-+ * This function does all the usual steps needed to bring up an
-+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
-+ * must be initialized / enabled before calling this.
-+ *
-+ * RETURNS:
-+ * 0 on success otherwise a negative error code
-+ */
-+int ahci_platform_init_host(struct platform_device *pdev,
-+ struct ahci_host_priv *hpriv,
-+ const struct ata_port_info *pi_template,
-+ unsigned int force_port_map,
-+ unsigned int mask_port_map)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct ata_port_info pi = *pi_template;
-+ const struct ata_port_info *ppi[] = { &pi, NULL };
-+ struct ata_host *host;
-+ int i, irq, n_ports, rc;
-+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq <= 0) {
-+ dev_err(dev, "no irq\n");
-+ return -EINVAL;
-+ }
-+
-+ /* prepare host */
-+ hpriv->flags |= (unsigned long)pi.private_data;
-+
-+ ahci_save_initial_config(dev, hpriv, force_port_map, mask_port_map);
-+
-+ if (hpriv->cap & HOST_CAP_NCQ)
-+ pi.flags |= ATA_FLAG_NCQ;
-+
-+ if (hpriv->cap & HOST_CAP_PMP)
-+ pi.flags |= ATA_FLAG_PMP;
-+
-+ ahci_set_em_messages(hpriv, &pi);
-+
-+ /* CAP.NP sometimes indicate the index of the last enabled
-+ * port, at other times, that of the last possible port, so
-+ * determining the maximum port number requires looking at
-+ * both CAP.NP and port_map.
-+ */
-+ n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map));
-+
-+ host = ata_host_alloc_pinfo(dev, ppi, n_ports);
-+ if (!host)
-+ return -ENOMEM;
-+
-+ host->private_data = hpriv;
-+
-+ if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
-+ host->flags |= ATA_HOST_PARALLEL_SCAN;
-+ else
-+ dev_info(dev, "SSS flag set, parallel bus scan disabled\n");
-+
-+ if (pi.flags & ATA_FLAG_EM)
-+ ahci_reset_em(host);
-+
-+ for (i = 0; i < host->n_ports; i++) {
-+ struct ata_port *ap = host->ports[i];
-+
-+ ata_port_desc(ap, "mmio %pR",
-+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
-+ ata_port_desc(ap, "port 0x%x", 0x100 + ap->port_no * 0x80);
-+
-+ /* set enclosure management message type */
-+ if (ap->flags & ATA_FLAG_EM)
-+ ap->em_message_type = hpriv->em_msg_type;
-+
-+ /* disabled/not-implemented port */
-+ if (!(hpriv->port_map & (1 << i)))
-+ ap->ops = &ata_dummy_port_ops;
-+ }
-+
-+ rc = ahci_reset_controller(host);
-+ if (rc)
-+ return rc;
-+
-+ ahci_init_controller(host);
-+ ahci_print_info(host, "platform");
-+
-+ return ata_host_activate(host, irq, ahci_interrupt, IRQF_SHARED,
-+ &ahci_platform_sht);
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_init_host);
-+
-+static void ahci_host_stop(struct ata_host *host)
-+{
-+ struct device *dev = host->dev;
-+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
-+ struct ahci_host_priv *hpriv = host->private_data;
-+
-+ if (pdata && pdata->exit)
-+ pdata->exit(dev);
-+
-+ ahci_platform_disable_resources(hpriv);
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+/**
-+ * ahci_platform_suspend_host - Suspend an ahci-platform host
-+ * @dev: device pointer for the host
-+ *
-+ * This function does all the usual steps needed to suspend an
-+ * ahci-platform host, note any necessary resources (ie clks, phy, etc.)
-+ * must be disabled after calling this.
-+ *
-+ * RETURNS:
-+ * 0 on success otherwise a negative error code
-+ */
-+int ahci_platform_suspend_host(struct device *dev)
-+{
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ struct ahci_host_priv *hpriv = host->private_data;
-+ void __iomem *mmio = hpriv->mmio;
-+ u32 ctl;
-+
-+ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
-+ dev_err(dev, "firmware update required for suspend/resume\n");
-+ return -EIO;
-+ }
-+
-+ /*
-+ * AHCI spec rev1.1 section 8.3.3:
-+ * Software must disable interrupts prior to requesting a
-+ * transition of the HBA to D3 state.
-+ */
-+ ctl = readl(mmio + HOST_CTL);
-+ ctl &= ~HOST_IRQ_EN;
-+ writel(ctl, mmio + HOST_CTL);
-+ readl(mmio + HOST_CTL); /* flush */
-+
-+ return ata_host_suspend(host, PMSG_SUSPEND);
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
-+
-+/**
-+ * ahci_platform_resume_host - Resume an ahci-platform host
-+ * @dev: device pointer for the host
-+ *
-+ * This function does all the usual steps needed to resume an ahci-platform
-+ * host, note any necessary resources (ie clks, phy, etc.) must be
-+ * initialized / enabled before calling this.
-+ *
-+ * RETURNS:
-+ * 0 on success otherwise a negative error code
-+ */
-+int ahci_platform_resume_host(struct device *dev)
-+{
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ int rc;
-+
-+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
-+ rc = ahci_reset_controller(host);
-+ if (rc)
-+ return rc;
-+
-+ ahci_init_controller(host);
-+ }
-+
-+ ata_host_resume(host);
-+
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_resume_host);
-+
-+/**
-+ * ahci_platform_suspend - Suspend an ahci-platform device
-+ * @dev: the platform device to suspend
-+ *
-+ * This function suspends the host associated with the device, followed by
-+ * disabling all the resources of the device.
-+ *
-+ * RETURNS:
-+ * 0 on success otherwise a negative error code
-+ */
-+int ahci_platform_suspend(struct device *dev)
-+{
-+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ struct ahci_host_priv *hpriv = host->private_data;
-+ int rc;
-+
-+ rc = ahci_platform_suspend_host(dev);
-+ if (rc)
-+ return rc;
-+
-+ if (pdata && pdata->suspend) {
-+ rc = pdata->suspend(dev);
-+ if (rc)
-+ goto resume_host;
-+ }
-+
-+ ahci_platform_disable_resources(hpriv);
-+
-+ return 0;
-+
-+resume_host:
-+ ahci_platform_resume_host(dev);
-+ return rc;
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_suspend);
-+
-+/**
-+ * ahci_platform_resume - Resume an ahci-platform device
-+ * @dev: the platform device to resume
-+ *
-+ * This function enables all the resources of the device followed by
-+ * resuming the host associated with the device.
-+ *
-+ * RETURNS:
-+ * 0 on success otherwise a negative error code
-+ */
-+int ahci_platform_resume(struct device *dev)
-+{
-+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
-+ struct ata_host *host = dev_get_drvdata(dev);
-+ struct ahci_host_priv *hpriv = host->private_data;
-+ int rc;
-+
-+ rc = ahci_platform_enable_resources(hpriv);
-+ if (rc)
-+ return rc;
-+
-+ if (pdata && pdata->resume) {
-+ rc = pdata->resume(dev);
-+ if (rc)
-+ goto disable_resources;
-+ }
-+
-+ rc = ahci_platform_resume_host(dev);
-+ if (rc)
-+ goto disable_resources;
-+
-+ /* We resumed so update PM runtime state */
-+ pm_runtime_disable(dev);
-+ pm_runtime_set_active(dev);
-+ pm_runtime_enable(dev);
-+
-+ return 0;
-+
-+disable_resources:
-+ ahci_platform_disable_resources(hpriv);
-+
-+ return rc;
-+}
-+EXPORT_SYMBOL_GPL(ahci_platform_resume);
-+#endif
-+
-+MODULE_DESCRIPTION("AHCI SATA platform library");
-+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
-+MODULE_LICENSE("GPL");