Re: [PATCH RFC/RFT 2/2] pinctrl-cygnus-gpio: convert to use gpiochip_add_with_ranges

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

 



++ Broadcom engineers working on Cygnus GPIO driver

We will discuss this change on the other email thread, i.e., [PATCH
RFC/RFT 0/2]...

On 10/11/2015 8:48 AM, Jonas Gorski wrote:
> Convert the driver to make use of passing ranges to gpiochip_add, and
> drop the custom implemtation of gpio_ranges.
> Since gpiochip_add_with_ranges also supports conditional setting of
> request/free based on the existence of ranges, and pinmux_is_supported
> held the same information, we can drop the custom request/free calbacks
> at the same time and just use the generic implementations if needed.
> 
> Signed-off-by: Jonas Gorski <jogo@xxxxxxxxxxx>
> ---
>  drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c | 126 +++++++-----------------------
>  1 file changed, 27 insertions(+), 99 deletions(-)
> 
> diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
> index 1ca7830..d24218f 100644
> --- a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
> +++ b/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
> @@ -75,8 +75,6 @@
>   * @lock: lock to protect access to I/O registers
>   * @gc: GPIO chip
>   * @num_banks: number of GPIO banks, each bank supports up to 32 GPIOs
> - * @pinmux_is_supported: flag to indicate this GPIO controller contains pins
> - * that can be individually muxed to GPIO
>   * @pctl: pointer to pinctrl_dev
>   * @pctldesc: pinctrl descriptor
>   */
> @@ -91,8 +89,6 @@ struct cygnus_gpio {
>  	struct gpio_chip gc;
>  	unsigned num_banks;
>  
> -	bool pinmux_is_supported;
> -
>  	struct pinctrl_dev *pctl;
>  	struct pinctrl_desc pctldesc;
>  };
> @@ -289,28 +285,6 @@ static struct irq_chip cygnus_gpio_irq_chip = {
>  /*
>   * Request the Cygnus IOMUX pinmux controller to mux individual pins to GPIO
>   */
> -static int cygnus_gpio_request(struct gpio_chip *gc, unsigned offset)
> -{
> -	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
> -	unsigned gpio = gc->base + offset;
> -
> -	/* not all Cygnus GPIO pins can be muxed individually */
> -	if (!chip->pinmux_is_supported)
> -		return 0;
> -
> -	return pinctrl_request_gpio(gpio);
> -}
> -
> -static void cygnus_gpio_free(struct gpio_chip *gc, unsigned offset)
> -{
> -	struct cygnus_gpio *chip = to_cygnus_gpio(gc);
> -	unsigned gpio = gc->base + offset;
> -
> -	if (!chip->pinmux_is_supported)
> -		return;
> -
> -	pinctrl_free_gpio(gpio);
> -}
>  
>  static int cygnus_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
>  {
> @@ -596,22 +570,12 @@ static const struct pinconf_ops cygnus_pconf_ops = {
>  	.pin_config_set = cygnus_pin_config_set,
>  };
>  
> -/*
> - * Map a GPIO in the local gpio_chip pin space to a pin in the Cygnus IOMUX
> - * pinctrl pin space
> - */
> -struct cygnus_gpio_pin_range {
> -	unsigned offset;
> -	unsigned pin_base;
> -	unsigned num_pins;
> -};
> -
> -#define CYGNUS_PINRANGE(o, p, n) { .offset = o, .pin_base = p, .num_pins = n }
> +#define CYGNUS_PINRANGE(o, p, n) { .base = o, .pin_base = p, .npins = n }
>  
>  /*
>   * Pin mapping table for mapping local GPIO pins to Cygnus IOMUX pinctrl pins
>   */
> -static const struct cygnus_gpio_pin_range cygnus_gpio_pintable[] = {
> +static const struct pinctrl_gpio_range cygnus_gpio_pintable[] = {
>  	CYGNUS_PINRANGE(0, 42, 1),
>  	CYGNUS_PINRANGE(1, 44, 3),
>  	CYGNUS_PINRANGE(4, 48, 1),
> @@ -666,58 +630,6 @@ static const struct cygnus_gpio_pin_range cygnus_gpio_pintable[] = {
>  };
>  
>  /*
> - * The Cygnus IOMUX controller mainly supports group based mux configuration,
> - * but certain pins can be muxed to GPIO individually. Only the ASIU GPIO
> - * controller can support this, so it's an optional configuration
> - *
> - * Return -ENODEV means no support and that's fine
> - */
> -static int cygnus_gpio_pinmux_add_range(struct cygnus_gpio *chip)
> -{
> -	struct device_node *node = chip->dev->of_node;
> -	struct device_node *pinmux_node;
> -	struct platform_device *pinmux_pdev;
> -	struct gpio_chip *gc = &chip->gc;
> -	int i, ret = 0;
> -
> -	/* parse DT to find the phandle to the pinmux controller */
> -	pinmux_node = of_parse_phandle(node, "pinmux", 0);
> -	if (!pinmux_node)
> -		return -ENODEV;
> -
> -	pinmux_pdev = of_find_device_by_node(pinmux_node);
> -	/* no longer need the pinmux node */
> -	of_node_put(pinmux_node);
> -	if (!pinmux_pdev) {
> -		dev_err(chip->dev, "failed to get pinmux device\n");
> -		return -EINVAL;
> -	}
> -
> -	/* now need to create the mapping between local GPIO and PINMUX pins */
> -	for (i = 0; i < ARRAY_SIZE(cygnus_gpio_pintable); i++) {
> -		ret = gpiochip_add_pin_range(gc, dev_name(&pinmux_pdev->dev),
> -					     cygnus_gpio_pintable[i].offset,
> -					     cygnus_gpio_pintable[i].pin_base,
> -					     cygnus_gpio_pintable[i].num_pins);
> -		if (ret) {
> -			dev_err(chip->dev, "unable to add GPIO pin range\n");
> -			goto err_put_device;
> -		}
> -	}
> -
> -	chip->pinmux_is_supported = true;
> -
> -	/* no need for pinmux_pdev device reference anymore */
> -	put_device(&pinmux_pdev->dev);
> -	return 0;
> -
> -err_put_device:
> -	put_device(&pinmux_pdev->dev);
> -	gpiochip_remove_pin_ranges(gc);
> -	return ret;
> -}
> -
> -/*
>   * Cygnus GPIO controller supports some PINCONF related configurations such as
>   * pull up, pull down, and drive strength, when the pin is configured to GPIO
>   *
> @@ -805,6 +717,10 @@ static int cygnus_gpio_probe(struct platform_device *pdev)
>  	int irq, ret;
>  	const struct of_device_id *match;
>  	const struct cygnus_gpio_data *gpio_data;
> +	struct device_node *pinmux_node;
> +	const char *pinctrl_name = NULL;
> +	const struct pinctrl_gpio_range *ranges = NULL;
> +	unsigned int nranges = 0;
>  
>  	match = of_match_device(cygnus_gpio_of_match, dev);
>  	if (!match)
> @@ -844,25 +760,37 @@ static int cygnus_gpio_probe(struct platform_device *pdev)
>  	gc->label = dev_name(dev);
>  	gc->dev = dev;
>  	gc->of_node = dev->of_node;
> -	gc->request = cygnus_gpio_request;
> -	gc->free = cygnus_gpio_free;
>  	gc->direction_input = cygnus_gpio_direction_input;
>  	gc->direction_output = cygnus_gpio_direction_output;
>  	gc->set = cygnus_gpio_set;
>  	gc->get = cygnus_gpio_get;
>  
> -	ret = gpiochip_add(gc);
> +	/* parse DT to find the phandle to the pinmux controller */
> +	pinmux_node = of_parse_phandle(dev->of_node, "pinmux", 0);
> +	if (pinmux_node) {
> +		struct platform_device *pinmux_pdev;
> +
> +		pinmux_pdev = of_find_device_by_node(pinmux_node);
> +		/* no longer need the pinmux node */
> +		of_node_put(pinmux_node);
> +		if (!pinmux_pdev) {
> +			dev_err(chip->dev, "failed to get pinmux device\n");
> +			return -EINVAL;
> +		}
> +
> +		pinctrl_name = dev_name(&pinmux_pdev->dev);
> +		ranges = cygnus_gpio_pintable;
> +		nranges = ARRAY_SIZE(cygnus_gpio_pintable);
> +
> +		put_device(&pinmux_pdev->dev);
> +	}
> +
> +	ret = gpiochip_add_with_ranges(gc, pinctrl_name, ranges, nranges);
>  	if (ret < 0) {
>  		dev_err(dev, "unable to add GPIO chip\n");
>  		return ret;
>  	}
>  
> -	ret = cygnus_gpio_pinmux_add_range(chip);
> -	if (ret && ret != -ENODEV) {
> -		dev_err(dev, "unable to add GPIO pin range\n");
> -		goto err_rm_gpiochip;
> -	}
> -
>  	ret = cygnus_gpio_register_pinconf(chip);
>  	if (ret) {
>  		dev_err(dev, "unable to register pinconf\n");
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux