Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b3e603a authored by Hans de Goede's avatar Hans de Goede Committed by Tejun Heo
Browse files

ahci-platform: Add support for an optional regulator for sata-target power



Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 156c5887
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ Required properties:
Optional properties:
- dma-coherent      : Present if dma operations are coherent
- clocks            : a list of phandle + clock specifier pairs
- target-supply     : regulator for SATA target power

Example:
        sata@ffe08000 {
+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@

#include <linux/clk.h>
#include <linux/libata.h>
#include <linux/regulator/consumer.h>

/* Enclosure Management Control */
#define EM_CTRL_MSG_TYPE              0x000f0000
@@ -323,6 +324,7 @@ struct ahci_host_priv {
	u32			em_buf_sz;	/* EM buffer size in byte */
	u32			em_msg_type;	/* EM message type */
	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
	struct regulator	*target_pwr;	/* Optional */
	void			*plat_data;	/* Other platform data */
	/*
	 * Optional ahci_start_engine override, if not set this gets set to the
+34 −2
Original line number Diff line number Diff line
@@ -185,6 +185,14 @@ static int ahci_probe(struct platform_device *pdev)
		return -ENOMEM;
	}

	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)
			return -EPROBE_DEFER;
		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,
@@ -206,9 +214,15 @@ static int ahci_probe(struct platform_device *pdev)
		hpriv->clks[i] = clk;
	}

	rc = ahci_enable_clks(dev, hpriv);
	if (hpriv->target_pwr) {
		rc = regulator_enable(hpriv->target_pwr);
		if (rc)
			goto free_clk;
	}

	rc = ahci_enable_clks(dev, hpriv);
	if (rc)
		goto disable_regulator;

	/*
	 * Some platforms might need to prepare for mmio region access,
@@ -291,6 +305,9 @@ static int ahci_probe(struct platform_device *pdev)
		pdata->exit(dev);
disable_unprepare_clk:
	ahci_disable_clks(hpriv);
disable_regulator:
	if (hpriv->target_pwr)
		regulator_disable(hpriv->target_pwr);
free_clk:
	ahci_put_clks(hpriv);
	return rc;
@@ -307,6 +324,9 @@ static void ahci_host_stop(struct ata_host *host)

	ahci_disable_clks(hpriv);
	ahci_put_clks(hpriv);

	if (hpriv->target_pwr)
		regulator_disable(hpriv->target_pwr);
}

#ifdef CONFIG_PM_SLEEP
@@ -343,6 +363,9 @@ static int ahci_suspend(struct device *dev)

	ahci_disable_clks(hpriv);

	if (hpriv->target_pwr)
		regulator_disable(hpriv->target_pwr);

	return 0;
}

@@ -353,9 +376,15 @@ static int ahci_resume(struct device *dev)
	struct ahci_host_priv *hpriv = host->private_data;
	int rc;

	rc = ahci_enable_clks(dev, hpriv);
	if (hpriv->target_pwr) {
		rc = regulator_enable(hpriv->target_pwr);
		if (rc)
			return rc;
	}

	rc = ahci_enable_clks(dev, hpriv);
	if (rc)
		goto disable_regulator;

	if (pdata && pdata->resume) {
		rc = pdata->resume(dev);
@@ -377,6 +406,9 @@ static int ahci_resume(struct device *dev)

disable_unprepare_clk:
	ahci_disable_clks(hpriv);
disable_regulator:
	if (hpriv->target_pwr)
		regulator_disable(hpriv->target_pwr);

	return rc;
}