diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-gpio.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-gpio.c | 212 | 
1 files changed, 104 insertions, 108 deletions
| diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 0ef8fcc6ac3a..d80ea6ce91bb 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -14,27 +14,17 @@  #include <linux/module.h>  #include <linux/slab.h>  #include <linux/platform_device.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/of.h> -#include <linux/of_gpio.h>  struct i2c_gpio_private_data { +	struct gpio_desc *sda; +	struct gpio_desc *scl;  	struct i2c_adapter adap;  	struct i2c_algo_bit_data bit_data;  	struct i2c_gpio_platform_data pdata;  }; -/* Toggle SDA by changing the direction of the pin */ -static void i2c_gpio_setsda_dir(void *data, int state) -{ -	struct i2c_gpio_platform_data *pdata = data; - -	if (state) -		gpio_direction_input(pdata->sda_pin); -	else -		gpio_direction_output(pdata->sda_pin, 0); -} -  /*   * Toggle SDA by changing the output value of the pin. This is only   * valid for pins configured as open drain (i.e. setting the value @@ -42,20 +32,9 @@ static void i2c_gpio_setsda_dir(void *data, int state)   */  static void i2c_gpio_setsda_val(void *data, int state)  { -	struct i2c_gpio_platform_data *pdata = data; - -	gpio_set_value(pdata->sda_pin, state); -} - -/* Toggle SCL by changing the direction of the pin. */ -static void i2c_gpio_setscl_dir(void *data, int state) -{ -	struct i2c_gpio_platform_data *pdata = data; +	struct i2c_gpio_private_data *priv = data; -	if (state) -		gpio_direction_input(pdata->scl_pin); -	else -		gpio_direction_output(pdata->scl_pin, 0); +	gpiod_set_value(priv->sda, state);  }  /* @@ -66,44 +45,23 @@ static void i2c_gpio_setscl_dir(void *data, int state)   */  static void i2c_gpio_setscl_val(void *data, int state)  { -	struct i2c_gpio_platform_data *pdata = data; +	struct i2c_gpio_private_data *priv = data; -	gpio_set_value(pdata->scl_pin, state); +	gpiod_set_value(priv->scl, state);  }  static int i2c_gpio_getsda(void *data)  { -	struct i2c_gpio_platform_data *pdata = data; +	struct i2c_gpio_private_data *priv = data; -	return gpio_get_value(pdata->sda_pin); +	return gpiod_get_value(priv->sda);  }  static int i2c_gpio_getscl(void *data)  { -	struct i2c_gpio_platform_data *pdata = data; - -	return gpio_get_value(pdata->scl_pin); -} - -static int of_i2c_gpio_get_pins(struct device_node *np, -				unsigned int *sda_pin, unsigned int *scl_pin) -{ -	if (of_gpio_count(np) < 2) -		return -ENODEV; - -	*sda_pin = of_get_gpio(np, 0); -	*scl_pin = of_get_gpio(np, 1); - -	if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER) -		return -EPROBE_DEFER; - -	if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) { -		pr_err("%pOF: invalid GPIO pins, sda=%d/scl=%d\n", -		       np, *sda_pin, *scl_pin); -		return -ENODEV; -	} +	struct i2c_gpio_private_data *priv = data; -	return 0; +	return gpiod_get_value(priv->scl);  }  static void of_i2c_gpio_get_props(struct device_node *np, @@ -124,72 +82,105 @@ static void of_i2c_gpio_get_props(struct device_node *np,  		of_property_read_bool(np, "i2c-gpio,scl-output-only");  } +static struct gpio_desc *i2c_gpio_get_desc(struct device *dev, +					   const char *con_id, +					   unsigned int index, +					   enum gpiod_flags gflags) +{ +	struct gpio_desc *retdesc; +	int ret; + +	retdesc = devm_gpiod_get(dev, con_id, gflags); +	if (!IS_ERR(retdesc)) { +		dev_dbg(dev, "got GPIO from name %s\n", con_id); +		return retdesc; +	} + +	retdesc = devm_gpiod_get_index(dev, NULL, index, gflags); +	if (!IS_ERR(retdesc)) { +		dev_dbg(dev, "got GPIO from index %u\n", index); +		return retdesc; +	} + +	ret = PTR_ERR(retdesc); + +	/* FIXME: hack in the old code, is this really necessary? */ +	if (ret == -EINVAL) +		retdesc = ERR_PTR(-EPROBE_DEFER); + +	/* This happens if the GPIO driver is not yet probed, let's defer */ +	if (ret == -ENOENT) +		retdesc = ERR_PTR(-EPROBE_DEFER); + +	if (ret != -EPROBE_DEFER) +		dev_err(dev, "error trying to get descriptor: %d\n", ret); + +	return retdesc; +} +  static int i2c_gpio_probe(struct platform_device *pdev)  {  	struct i2c_gpio_private_data *priv;  	struct i2c_gpio_platform_data *pdata;  	struct i2c_algo_bit_data *bit_data;  	struct i2c_adapter *adap; -	unsigned int sda_pin, scl_pin; +	struct device *dev = &pdev->dev; +	struct device_node *np = dev->of_node; +	enum gpiod_flags gflags;  	int ret; -	/* First get the GPIO pins; if it fails, we'll defer the probe. */ -	if (pdev->dev.of_node) { -		ret = of_i2c_gpio_get_pins(pdev->dev.of_node, -					   &sda_pin, &scl_pin); -		if (ret) -			return ret; -	} else { -		if (!dev_get_platdata(&pdev->dev)) -			return -ENXIO; -		pdata = dev_get_platdata(&pdev->dev); -		sda_pin = pdata->sda_pin; -		scl_pin = pdata->scl_pin; -	} - -	ret = devm_gpio_request(&pdev->dev, sda_pin, "sda"); -	if (ret) { -		if (ret == -EINVAL) -			ret = -EPROBE_DEFER;	/* Try again later */ -		return ret; -	} -	ret = devm_gpio_request(&pdev->dev, scl_pin, "scl"); -	if (ret) { -		if (ret == -EINVAL) -			ret = -EPROBE_DEFER;	/* Try again later */ -		return ret; -	} - -	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);  	if (!priv)  		return -ENOMEM; +  	adap = &priv->adap;  	bit_data = &priv->bit_data;  	pdata = &priv->pdata; -	if (pdev->dev.of_node) { -		pdata->sda_pin = sda_pin; -		pdata->scl_pin = scl_pin; -		of_i2c_gpio_get_props(pdev->dev.of_node, pdata); +	if (np) { +		of_i2c_gpio_get_props(np, pdata);  	} else { -		memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata)); +		/* +		 * If all platform data settings are zero it is OK +		 * to not provide any platform data from the board. +		 */ +		if (dev_get_platdata(dev)) +			memcpy(pdata, dev_get_platdata(dev), sizeof(*pdata));  	} -	if (pdata->sda_is_open_drain) { -		gpio_direction_output(pdata->sda_pin, 1); -		bit_data->setsda = i2c_gpio_setsda_val; -	} else { -		gpio_direction_input(pdata->sda_pin); -		bit_data->setsda = i2c_gpio_setsda_dir; -	} +	/* +	 * First get the GPIO pins; if it fails, we'll defer the probe. +	 * If the SDA line is marked from platform data or device tree as +	 * "open drain" it means something outside of our control is making +	 * this line being handled as open drain, and we should just handle +	 * it as any other output. Else we enforce open drain as this is +	 * required for an I2C bus. +	 */ +	if (pdata->sda_is_open_drain) +		gflags = GPIOD_OUT_HIGH; +	else +		gflags = GPIOD_OUT_HIGH_OPEN_DRAIN; +	priv->sda = i2c_gpio_get_desc(dev, "sda", 0, gflags); +	if (IS_ERR(priv->sda)) +		return PTR_ERR(priv->sda); + +	/* +	 * If the SCL line is marked from platform data or device tree as +	 * "open drain" it means something outside of our control is making +	 * this line being handled as open drain, and we should just handle +	 * it as any other output. Else we enforce open drain as this is +	 * required for an I2C bus. +	 */ +	if (pdata->scl_is_open_drain) +		gflags = GPIOD_OUT_LOW; +	else +		gflags = GPIOD_OUT_LOW_OPEN_DRAIN; +	priv->scl = i2c_gpio_get_desc(dev, "scl", 1, gflags); +	if (IS_ERR(priv->scl)) +		return PTR_ERR(priv->scl); -	if (pdata->scl_is_open_drain || pdata->scl_is_output_only) { -		gpio_direction_output(pdata->scl_pin, 1); -		bit_data->setscl = i2c_gpio_setscl_val; -	} else { -		gpio_direction_input(pdata->scl_pin); -		bit_data->setscl = i2c_gpio_setscl_dir; -	} +	bit_data->setsda = i2c_gpio_setsda_val; +	bit_data->setscl = i2c_gpio_setscl_val;  	if (!pdata->scl_is_output_only)  		bit_data->getscl = i2c_gpio_getscl; @@ -207,18 +198,18 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	else  		bit_data->timeout = HZ / 10;		/* 100 ms */ -	bit_data->data = pdata; +	bit_data->data = priv;  	adap->owner = THIS_MODULE; -	if (pdev->dev.of_node) -		strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); +	if (np) +		strlcpy(adap->name, dev_name(dev), sizeof(adap->name));  	else  		snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);  	adap->algo_data = bit_data;  	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; -	adap->dev.parent = &pdev->dev; -	adap->dev.of_node = pdev->dev.of_node; +	adap->dev.parent = dev; +	adap->dev.of_node = np;  	adap->nr = pdev->id;  	ret = i2c_bit_add_numbered_bus(adap); @@ -227,8 +218,13 @@ static int i2c_gpio_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, priv); -	dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", -		 pdata->sda_pin, pdata->scl_pin, +	/* +	 * FIXME: using global GPIO numbers is not helpful. If/when we +	 * get accessors to get the actual name of the GPIO line, +	 * from the descriptor, then provide that instead. +	 */ +	dev_info(dev, "using lines %u (SDA) and %u (SCL%s)\n", +		 desc_to_gpio(priv->sda), desc_to_gpio(priv->scl),  		 pdata->scl_is_output_only  		 ? ", no clock stretching" : ""); |