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

Commit 266d1fe0 authored by Mao Li's avatar Mao Li Committed by Gerrit - the friendly Code Review server
Browse files

input: ft5x06_ts: add support for pinctrl framework



Migrate the Focaltech driver to use pinctrl framework for GPIO
configuration so that driver is compatible with targets that
use and targets that don't use pinctrl framework.

  This patch is propagated from 3.10 kernel
    commit: df621a0bebd6801f7fb9c76762cc9ac5f76e41e0
    input: ft5x06_ts: add support for pinctrl framework

Change-Id: I84fc2a6d30f831b4b054780b107ce105614855ea
Signed-off-by: default avatarMao Li <maol@codeaurora.org>
parent dba19fc8
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -27,6 +27,22 @@ Required properties:
 - focaltech,group-id	: group id of this device
 - focaltech,hard-reset-delay-ms : hard reset delay in ms
 - focaltech,soft-reset-delay-ms : soft reset delay in ms
 - focaltech,fw-delay-aa-ms : specify the delay in ms after programming 0xaa
				register for firmware upgrade
 - focaltech,fw-delay-55-ms : specify the delay in ms after programming 0x55
				register for firmware upgrade
 - focaltech,fw-upgrade-id1 : specify the upgrade id1 for firmware upgrade
 - focaltech,fw-upgrade-id2 : specify the upgrade id2 for firmware upgrade
 - focaltech,fw-delay-readid-ms : specify the read id delay in ms for firmware upgrade
 - focaltech,fw-delay-era-flsh-ms : specify the erase flash delay in ms for firmware upgrade
 - pinctrl-names : This should be defined if a target uses pinctrl framework.
			See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
			Specify the names of the configs that pinctrl can install in driver.
			Following are the pinctrl configs that can be installed:
			"pmx_ts_active" : Active configuration of pins, this should specify active
			config defined in pin groups of interrupt and reset gpio.
			"pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep
			config defined in pin groups of interrupt and reset gpio.

Optional properties:

@@ -57,6 +73,9 @@ Example:
			interrupts = <1 0x2>;
			vdd-supply = <&pm8110_l19>;
			vcc_i2c-supply = <&pm8110_l14>;
			pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
			pinctrl-0 = <&ts_int_active &ts_reset_active>;
			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
			focaltech,name = "ft6x06";
			focaltech,family-id = <0x06>;
			focaltech,reset-gpio = <&msmgpio 0 0x00>;
+102 −0
Original line number Diff line number Diff line
@@ -221,6 +221,9 @@ struct ft5x06_ts_data {
#elif defined(CONFIG_HAS_EARLYSUSPEND)
	struct early_suspend early_suspend;
#endif
	struct pinctrl *ts_pinctrl;
	struct pinctrl_state *gpio_state_active;
	struct pinctrl_state *gpio_state_suspend;
};

static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
@@ -509,6 +512,71 @@ pwr_deinit:
	return 0;
}

static int ft5x06_ts_pinctrl_init(struct ft5x06_ts_data *ft5x06_data)
{
	int retval;

	/* Get pinctrl if target uses pinctrl */
	ft5x06_data->ts_pinctrl = devm_pinctrl_get(&(ft5x06_data->client->dev));
	if (IS_ERR_OR_NULL(ft5x06_data->ts_pinctrl)) {
		dev_dbg(&ft5x06_data->client->dev,
			"Target does not use pinctrl\n");
		retval = PTR_ERR(ft5x06_data->ts_pinctrl);
		ft5x06_data->ts_pinctrl = NULL;
		return retval;
	}

	ft5x06_data->gpio_state_active
		= pinctrl_lookup_state(ft5x06_data->ts_pinctrl,
			"pmx_ts_active");
	if (IS_ERR_OR_NULL(ft5x06_data->gpio_state_active)) {
		dev_dbg(&ft5x06_data->client->dev,
			"Can not get ts default pinstate\n");
		retval = PTR_ERR(ft5x06_data->gpio_state_active);
		ft5x06_data->ts_pinctrl = NULL;
		return retval;
	}

	ft5x06_data->gpio_state_suspend
		= pinctrl_lookup_state(ft5x06_data->ts_pinctrl,
			"pmx_ts_suspend");
	if (IS_ERR_OR_NULL(ft5x06_data->gpio_state_suspend)) {
		dev_err(&ft5x06_data->client->dev,
			"Can not get ts sleep pinstate\n");
		retval = PTR_ERR(ft5x06_data->gpio_state_suspend);
		ft5x06_data->ts_pinctrl = NULL;
		return retval;
	}

	return 0;
}

static int ft5x06_ts_pinctrl_select(struct ft5x06_ts_data *ft5x06_data,
						bool on)
{
	struct pinctrl_state *pins_state;
	int ret;

	pins_state = on ? ft5x06_data->gpio_state_active
		: ft5x06_data->gpio_state_suspend;
	if (!IS_ERR_OR_NULL(pins_state)) {
		ret = pinctrl_select_state(ft5x06_data->ts_pinctrl, pins_state);
		if (ret) {
			dev_err(&ft5x06_data->client->dev,
				"can not set %s pins\n",
				on ? "pmx_ts_active" : "pmx_ts_suspend");
			return ret;
		}
	} else {
		dev_err(&ft5x06_data->client->dev,
			"not a valid '%s' pinstate\n",
				on ? "pmx_ts_active" : "pmx_ts_suspend");
	}

	return 0;
}


#ifdef CONFIG_PM
static int ft5x06_ts_suspend(struct device *dev)
{
@@ -525,6 +593,11 @@ static int ft5x06_ts_suspend(struct device *dev)
		dev_info(dev, "Already in suspend state\n");
		return 0;
	}
	if (data->ts_pinctrl) {
		err = ft5x06_ts_pinctrl_select(data, false);
		if (err < 0)
			dev_err(dev, "Cannot get idle pinctrl state\n");
	}

	disable_irq(data->client->irq);

@@ -593,6 +666,11 @@ static int ft5x06_ts_resume(struct device *dev)
			return err;
		}
	}
	if (data->ts_pinctrl) {
		err = ft5x06_ts_pinctrl_select(data, true);
		if (err < 0)
			dev_err(dev, "Cannot get default pinctrl state\n");
	}

	if (gpio_is_valid(data->pdata->reset_gpio)) {
		gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
@@ -1540,6 +1618,13 @@ static int ft5x06_ts_probe(struct i2c_client *client,
		}
	}

	err = ft5x06_ts_pinctrl_init(data);
	if (!err && data->ts_pinctrl) {
		err = ft5x06_ts_pinctrl_select(data, true);
		if (err < 0)
			goto pwr_off;
	}

	if (gpio_is_valid(pdata->irq_gpio)) {
		err = gpio_request(pdata->irq_gpio, "ft5x06_irq_gpio");
		if (err) {
@@ -1717,9 +1802,19 @@ irq_free:
free_reset_gpio:
	if (gpio_is_valid(pdata->reset_gpio))
		gpio_free(pdata->reset_gpio);
	if (data->ts_pinctrl) {
		err = ft5x06_ts_pinctrl_select(data, false);
		if (err < 0)
			pr_err("Cannot get idle pinctrl state\n");
	}
free_irq_gpio:
	if (gpio_is_valid(pdata->irq_gpio))
		gpio_free(pdata->irq_gpio);
	if (data->ts_pinctrl) {
		err = ft5x06_ts_pinctrl_select(data, false);
		if (err < 0)
			pr_err("Cannot get idle pinctrl state\n");
	}
pwr_off:
	if (pdata->power_on)
		pdata->power_on(false);
@@ -1741,6 +1836,7 @@ free_inputdev:
static int ft5x06_ts_remove(struct i2c_client *client)
{
	struct ft5x06_ts_data *data = i2c_get_clientdata(client);
	int retval;

	debugfs_remove_recursive(data->dir);
	device_remove_file(&client->dev, &dev_attr_force_update_fw);
@@ -1761,6 +1857,12 @@ static int ft5x06_ts_remove(struct i2c_client *client)
	if (gpio_is_valid(data->pdata->irq_gpio))
		gpio_free(data->pdata->irq_gpio);

	if (data->ts_pinctrl) {
		retval = ft5x06_ts_pinctrl_select(data, false);
		if (retval < 0)
			pr_err("Cannot get idle pinctrl state\n");
	}

	if (data->pdata->power_on)
		data->pdata->power_on(false);
	else