Re: [PATCH v2] i2c: mux: arb-gpio: Rewrite to use GPIO descriptors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Linus,

On 2019-06-01 18:59, Linus Walleij wrote:
> Instead of complex code picking GPIOs out of the device tree
> and keeping track of polarity for each GPIO line, use descriptors
> and pull polarity handling into the gpiolib.
>
> We look for "our-claim" and "their-claim" since the gpiolib
> code will try e.g. "our-claim-gpios" and "our-claim-gpio" in
> turn to locate these GPIO lines from the device tree.
>
> Cc: Krzysztof Kozlowski <krzk@xxxxxxxxxx>
> Cc: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
> Cc: Doug Anderson <dianders@xxxxxxxxxxxx>
> Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx>

Samsung Snow Chromebook works fine with linux-next 20190603 and this patch.

Tested-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>

> ---
> ChangeLog v1->v2:
> - Print some errors if we fail to obtain GPIOs.
> - Switch to devm_gpiod_get_index() and !IS_ERR() on the result
>    to check for an unsupported multimaster set-up.
> - Especially handle if the second master returns -EPROBE_DEFER
>    even in the case of the optional GPIO that we explicitly bail
>    out on if found, as it may be a sign that the GPIO controllers
>    are not yet up.
> ---
>   drivers/i2c/muxes/i2c-arb-gpio-challenge.c | 79 ++++++++--------------
>   1 file changed, 27 insertions(+), 52 deletions(-)
>
> diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> index 812b8cff265f..a664f637bc3d 100644
> --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c
> @@ -15,12 +15,11 @@
>    */
>   
>   #include <linux/delay.h>
> -#include <linux/gpio.h>
> +#include <linux/gpio/consumer.h>
>   #include <linux/kernel.h>
>   #include <linux/i2c.h>
>   #include <linux/i2c-mux.h>
>   #include <linux/module.h>
> -#include <linux/of_gpio.h>
>   #include <linux/platform_device.h>
>   #include <linux/slab.h>
>   
> @@ -28,22 +27,16 @@
>   /**
>    * struct i2c_arbitrator_data - Driver data for I2C arbitrator
>    *
> - * @our_gpio: GPIO we'll use to claim.
> - * @our_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
> - *   this then consider it released.
> - * @their_gpio: GPIO that the other side will use to claim.
> - * @their_gpio_release: 0 if active high; 1 if active low; AKA if the GPIO ==
> - *   this then consider it released.
> + * @our_gpio: GPIO descriptor we'll use to claim.
> + * @their_gpio: GPIO descriptor that the other side will use to claim.
>    * @slew_delay_us: microseconds to wait for a GPIO to go high.
>    * @wait_retry_us: we'll attempt another claim after this many microseconds.
>    * @wait_free_us: we'll give up after this many microseconds.
>    */
>   
>   struct i2c_arbitrator_data {
> -	int our_gpio;
> -	int our_gpio_release;
> -	int their_gpio;
> -	int their_gpio_release;
> +	struct gpio_desc *our_gpio;
> +	struct gpio_desc *their_gpio;
>   	unsigned int slew_delay_us;
>   	unsigned int wait_retry_us;
>   	unsigned int wait_free_us;
> @@ -64,15 +57,15 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
>   	stop_time = jiffies + usecs_to_jiffies(arb->wait_free_us) + 1;
>   	do {
>   		/* Indicate that we want to claim the bus */
> -		gpio_set_value(arb->our_gpio, !arb->our_gpio_release);
> +		gpiod_set_value(arb->our_gpio, 1);
>   		udelay(arb->slew_delay_us);
>   
>   		/* Wait for the other master to release it */
>   		stop_retry = jiffies + usecs_to_jiffies(arb->wait_retry_us) + 1;
>   		while (time_before(jiffies, stop_retry)) {
> -			int gpio_val = !!gpio_get_value(arb->their_gpio);
> +			int gpio_val = gpiod_get_value(arb->their_gpio);
>   
> -			if (gpio_val == arb->their_gpio_release) {
> +			if (!gpio_val) {
>   				/* We got it, so return */
>   				return 0;
>   			}
> @@ -81,13 +74,13 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
>   		}
>   
>   		/* It didn't release, so give up, wait, and try again */
> -		gpio_set_value(arb->our_gpio, arb->our_gpio_release);
> +		gpiod_set_value(arb->our_gpio, 0);
>   
>   		usleep_range(arb->wait_retry_us, arb->wait_retry_us * 2);
>   	} while (time_before(jiffies, stop_time));
>   
>   	/* Give up, release our claim */
> -	gpio_set_value(arb->our_gpio, arb->our_gpio_release);
> +	gpiod_set_value(arb->our_gpio, 0);
>   	udelay(arb->slew_delay_us);
>   	dev_err(muxc->dev, "Could not claim bus, timeout\n");
>   	return -EBUSY;
> @@ -103,7 +96,7 @@ static int i2c_arbitrator_deselect(struct i2c_mux_core *muxc, u32 chan)
>   	const struct i2c_arbitrator_data *arb = i2c_mux_priv(muxc);
>   
>   	/* Release the bus and wait for the other master to notice */
> -	gpio_set_value(arb->our_gpio, arb->our_gpio_release);
> +	gpiod_set_value(arb->our_gpio, 0);
>   	udelay(arb->slew_delay_us);
>   
>   	return 0;
> @@ -116,8 +109,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
>   	struct device_node *parent_np;
>   	struct i2c_mux_core *muxc;
>   	struct i2c_arbitrator_data *arb;
> -	enum of_gpio_flags gpio_flags;
> -	unsigned long out_init;
> +	struct gpio_desc *dummy;
>   	int ret;
>   
>   	/* We only support probing from device tree; no platform_data */
> @@ -138,45 +130,28 @@ static int i2c_arbitrator_probe(struct platform_device *pdev)
>   
>   	platform_set_drvdata(pdev, muxc);
>   
> -	/* Request GPIOs */
> -	ret = of_get_named_gpio_flags(np, "our-claim-gpio", 0, &gpio_flags);
> -	if (!gpio_is_valid(ret)) {
> -		if (ret != -EPROBE_DEFER)
> -			dev_err(dev, "Error getting our-claim-gpio\n");
> -		return ret;
> -	}
> -	arb->our_gpio = ret;
> -	arb->our_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW);
> -	out_init = (gpio_flags & OF_GPIO_ACTIVE_LOW) ?
> -		GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
> -	ret = devm_gpio_request_one(dev, arb->our_gpio, out_init,
> -				    "our-claim-gpio");
> -	if (ret) {
> -		if (ret != -EPROBE_DEFER)
> -			dev_err(dev, "Error requesting our-claim-gpio\n");
> -		return ret;
> +	/* Request GPIOs, our GPIO as unclaimed to begin with */
> +	arb->our_gpio = devm_gpiod_get(dev, "our-claim", GPIOD_OUT_LOW);
> +	if (IS_ERR(arb->our_gpio)) {
> +		dev_err(dev, "could not get \"our-claim\" GPIO (%ld)\n",
> +			PTR_ERR(arb->our_gpio));
> +		return PTR_ERR(arb->our_gpio);
>   	}
>   
> -	ret = of_get_named_gpio_flags(np, "their-claim-gpios", 0, &gpio_flags);
> -	if (!gpio_is_valid(ret)) {
> -		if (ret != -EPROBE_DEFER)
> -			dev_err(dev, "Error getting their-claim-gpio\n");
> -		return ret;
> -	}
> -	arb->their_gpio = ret;
> -	arb->their_gpio_release = !!(gpio_flags & OF_GPIO_ACTIVE_LOW);
> -	ret = devm_gpio_request_one(dev, arb->their_gpio, GPIOF_IN,
> -				    "their-claim-gpio");
> -	if (ret) {
> -		if (ret != -EPROBE_DEFER)
> -			dev_err(dev, "Error requesting their-claim-gpio\n");
> -		return ret;
> +	arb->their_gpio = devm_gpiod_get(dev, "their-claim", GPIOD_IN);
> +	if (IS_ERR(arb->their_gpio)) {
> +		dev_err(dev, "could not get \"their-claim\" GPIO (%ld)\n",
> +			PTR_ERR(arb->their_gpio));
> +		return PTR_ERR(arb->their_gpio);
>   	}
>   
>   	/* At the moment we only support a single two master (us + 1 other) */
> -	if (gpio_is_valid(of_get_named_gpio(np, "their-claim-gpios", 1))) {
> +	dummy = devm_gpiod_get_index(dev, "their-claim", 1, GPIOD_IN);
> +	if (!IS_ERR(dummy)) {
>   		dev_err(dev, "Only one other master is supported\n");
>   		return -EINVAL;
> +	} else if (PTR_ERR(dummy) == -EPROBE_DEFER) {
> +		return -EPROBE_DEFER;
>   	}
>   
>   	/* Arbitration parameters */

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland




[Index of Archives]     [Linux GPIO]     [Linux SPI]     [Linux Hardward Monitoring]     [LM Sensors]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux