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

Commit 1e4abb47 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mmc: sdhci: Add support for pinctrl interface"

parents 7181e87d f07319f6
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -91,6 +91,11 @@ In the following, <supply> can be vdd (flash core voltage) or vdd-io (I/O voltag
	- qcom,msm-bus,num-paths
	- qcom,msm-bus,vectors-KBps

	- Refer to "Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt"
	  for following optional properties:
		- pinctrl-names
		- pinctrl-0, pinctrl-1,.. pinctrl-n

Example:

	aliases {
@@ -115,6 +120,11 @@ Example:
		qcom,vdd-io-voltage-level = <1800000 2950000>;
		qcom,vdd-io-current-level = <6 22000>;

		pinctrl-names = "active", "sleep";
		pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>;
		pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_on &sdc1_data_on>;


                qcom,bus-width = <4>;
		qcom,nonremovable;
		qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
@@ -148,6 +158,11 @@ Example:
		vdd-supply = <&pm8941_l21>;
		vdd-io-supply = <&pm8941_l13>;

		pinctrl-names = "active", "sleep";
		pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
		pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_on &sdc2_data_on>;


                qcom,bus-width = <4>;
		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000>;

+90 −7
Original line number Diff line number Diff line
@@ -38,9 +38,10 @@
#include <linux/mmc/slot-gpio.h>
#include <linux/dma-mapping.h>
#include <linux/irqchip/msm-mpm-irq.h>
#include <linux/iopoll.h>
#include <linux/pinctrl/consumer.h>
#include <mach/gpio.h>
#include <mach/msm_bus.h>
#include <linux/iopoll.h>

#include "sdhci-pltfm.h"

@@ -289,11 +290,16 @@ struct sdhci_msm_pin_data {
	 * = 0 if controller has dedicated MSM pads
	 */
	u8 is_gpio;
	bool cfg_sts;
	struct sdhci_msm_gpio_data *gpio_data;
	struct sdhci_msm_pad_data *pad_data;
};

struct sdhci_pinctrl_data {
	struct pinctrl          *pctrl;
	struct pinctrl_state    *pins_active;
	struct pinctrl_state    *pins_sleep;
};

struct sdhci_msm_bus_voting_data {
	struct msm_bus_scale_pdata *bus_pdata;
	unsigned int *bw_vecs;
@@ -310,7 +316,9 @@ struct sdhci_msm_pltfm_data {
	unsigned long mmc_bus_width;
	struct sdhci_msm_slot_reg_data *vreg_data;
	bool nonremovable;
	bool pin_cfg_sts;
	struct sdhci_msm_pin_data *pin_data;
	struct sdhci_pinctrl_data *pctrl_data;
	u32 cpu_dma_latency_us;
	int status_gpio; /* card detection GPIO that is configured as IRQ */
	struct sdhci_msm_bus_voting_data *voting_data;
@@ -1098,19 +1106,44 @@ static int sdhci_msm_setup_pad(struct sdhci_msm_pltfm_data *pdata, bool enable)
	return 0;
}

static int sdhci_msm_setup_pinctrl(struct sdhci_msm_pltfm_data *pdata,
		bool enable)
{
	int ret = 0;

	if (enable)
		ret = pinctrl_select_state(pdata->pctrl_data->pctrl,
			pdata->pctrl_data->pins_active);
	else
		ret = pinctrl_select_state(pdata->pctrl_data->pctrl,
			pdata->pctrl_data->pins_sleep);

	if (ret < 0)
		pr_err("%s state for pinctrl failed with %d\n",
			enable ? "Enabling" : "Disabling", ret);

	return ret;
}

static int sdhci_msm_setup_pins(struct sdhci_msm_pltfm_data *pdata, bool enable)
{
	int ret = 0;

	if (!pdata->pin_data || (pdata->pin_data->cfg_sts == enable))
	if  (pdata->pin_cfg_sts == enable) {
		return 0;
	} else if (pdata->pctrl_data) {
		ret = sdhci_msm_setup_pinctrl(pdata, enable);
		goto out;
	} else if (!pdata->pin_data) {
		return 0;
	}
	if (pdata->pin_data->is_gpio)
		ret = sdhci_msm_setup_gpio(pdata, enable);
	else
		ret = sdhci_msm_setup_pad(pdata, enable);

out:
	if (!ret)
		pdata->pin_data->cfg_sts = enable;
		pdata->pin_cfg_sts = enable;

	return ret;
}
@@ -1372,6 +1405,46 @@ out:
	return ret;
}

static int sdhci_msm_parse_pinctrl_info(struct device *dev,
		struct sdhci_msm_pltfm_data *pdata)
{
	struct sdhci_pinctrl_data *pctrl_data;
	struct pinctrl *pctrl;
	int ret = 0;

	/* Try to obtain pinctrl handle */
	pctrl = devm_pinctrl_get(dev);
	if (IS_ERR(pctrl)) {
		ret = PTR_ERR(pctrl);
		goto out;
	}
	pctrl_data = devm_kzalloc(dev, sizeof(*pctrl_data), GFP_KERNEL);
	if (!pctrl_data) {
		dev_err(dev, "No memory for sdhci_pinctrl_data\n");
		ret = -ENOMEM;
		goto out;
	}
	pctrl_data->pctrl = pctrl;
	/* Look-up and keep the states handy to be used later */
	pctrl_data->pins_active = pinctrl_lookup_state(
			pctrl_data->pctrl, "active");
	if (IS_ERR(pctrl_data->pins_active)) {
		ret = PTR_ERR(pctrl_data->pins_active);
		dev_err(dev, "Could not get active pinstates, err:%d\n", ret);
		goto out;
	}
	pctrl_data->pins_sleep = pinctrl_lookup_state(
			pctrl_data->pctrl, "sleep");
	if (IS_ERR(pctrl_data->pins_sleep)) {
		ret = PTR_ERR(pctrl_data->pins_sleep);
		dev_err(dev, "Could not get sleep pinstates, err:%d\n", ret);
		goto out;
	}
	pdata->pctrl_data = pctrl_data;
out:
	return ret;
}

#define GPIO_NAME_MAX_LEN 32
static int sdhci_msm_dt_parse_gpio_info(struct device *dev,
		struct sdhci_msm_pltfm_data *pdata)
@@ -1380,6 +1453,16 @@ static int sdhci_msm_dt_parse_gpio_info(struct device *dev,
	struct sdhci_msm_pin_data *pin_data;
	struct device_node *np = dev->of_node;

	ret = sdhci_msm_parse_pinctrl_info(dev, pdata);
	if (!ret) {
		goto out;
	} else if (ret == -EPROBE_DEFER) {
		dev_err(dev, "Pinctrl framework not registered, err:%d\n", ret);
		goto out;
	} else {
		dev_err(dev, "Parsing Pinctrl failed with %d, falling back on GPIO lib\n",
			ret);
	}
	pin_data = devm_kzalloc(dev, sizeof(*pin_data), GFP_KERNEL);
	if (!pin_data) {
		dev_err(dev, "No memory for pin_data\n");
@@ -3359,7 +3442,7 @@ static int sdhci_msm_remove(struct platform_device *pdev)

	sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, false);

	if (pdata->pin_data)
	sdhci_msm_setup_pins(pdata, true);
	sdhci_msm_setup_pins(pdata, false);

	if (msm_host->msm_bus_vote.client_handle) {