[PATCH] led: Add a 74273 led driver

Ahmad Fatoum a.fatoum at pengutronix.de
Wed Jul 14 02:35:57 PDT 2021


Hello Jürgen,

On 14.07.21 11:14, Juergen Borleis wrote:
> From: Sascha Hauer <s.hauer at pengutronix.de>
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> Signed-off-by: Juergen Borleis <jbe at pengutronix.de>
> ---
>  drivers/led/Kconfig          |   2 +
>  drivers/led/Makefile         |   1 +
>  drivers/led/led-74273-gpio.c | 176 +++++++++++++++++++++++++++++++++++
>  3 files changed, 179 insertions(+)
>  create mode 100644 drivers/led/led-74273-gpio.c
> 
> diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig
> index 2a5920a..876aa31 100644
> --- a/drivers/led/Kconfig
> +++ b/drivers/led/Kconfig
> @@ -39,5 +39,7 @@ config LED_PCA955X
>  	  LED driver chips accessed via the I2C bus.  Supported
>  	  devices include PCA9550, PCA9551, PCA9552, and PCA9553.
>  
> +config LED_74273_GPIO
> +	bool "Support for LEDs connected through a 74273"

I talked this over with Sascha before:
https://lore.barebox.org/barebox/0f039d89-2b64-ae91-a0c3-30c10c461c34@pengutronix.de/

The 74273 is rather an output-only GPIO controller, so a LED driver isn't the correct
abstraction.

I implemented a GPIO driver for this before (see above link), but Sascha's opinion
is that this should at least have an upstream binding first.

Cheers,
Ahmad

>  
>  endif
> diff --git a/drivers/led/Makefile b/drivers/led/Makefile
> index 35693a7..5732f27 100644
> --- a/drivers/led/Makefile
> +++ b/drivers/led/Makefile
> @@ -1,5 +1,6 @@
>  obj-$(CONFIG_LED) += core.o
>  obj-$(CONFIG_LED_GPIO) += led-gpio.o
>  obj-$(CONFIG_LED_PWM) += led-pwm.o
> +obj-$(CONFIG_LED_74273_GPIO) += led-74273-gpio.o
>  obj-$(CONFIG_LED_TRIGGERS) += led-triggers.o
>  obj-$(CONFIG_LED_PCA955X) += led-pca955x.o
> diff --git a/drivers/led/led-74273-gpio.c b/drivers/led/led-74273-gpio.c
> new file mode 100644
> index 0000000..1d62e32
> --- /dev/null
> +++ b/drivers/led/led-74273-gpio.c
> @@ -0,0 +1,176 @@
> +/*
> + * Copyright (c) 2017 Sascha Hauer, Pengutronix
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; version 2.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#include <common.h>
> +#include <init.h>
> +#include <led.h>
> +#include <malloc.h>
> +#include <gpio.h>
> +#include <of_gpio.h>
> +
> +struct sn74273;
> +
> +struct sn74273_led {
> +	struct led led;
> +	struct sn74273 *sn74273;
> +	int port;
> +	int pin;
> +};
> +
> +struct sn74273 {
> +	struct sn74273_led *leds;
> +	int *clk_gpios;
> +	int *data_gpios;
> +	u8 *shadow;
> +	int n_ports;
> +	int n_pins;
> +	int n_leds;
> +};
> +
> +static void sn74273_led_set(struct led *led, unsigned int brightness)
> +{
> +	struct sn74273_led *sled = container_of(led, struct sn74273_led, led);
> +	struct sn74273 *sn74273 = sled->sn74273;
> +	int i, j;
> +	u8 val;
> +
> +	val = sn74273->shadow[sled->port];
> +	if (brightness)
> +		val |= 1 << sled->pin;
> +	else
> +		val &= ~(1 << sled->pin);
> +	sn74273->shadow[sled->port] = val;
> +
> +	for (i = 0; i < sn74273->n_ports; i++) {
> +		for (j = 0; j < sn74273->n_pins; j++) {
> +			gpio_set_active(sn74273->data_gpios[j],
> +				sn74273->shadow[i] & (1 << j));
> +		}
> +
> +		gpio_set_active(sn74273->clk_gpios[i], 1);
> +		gpio_set_active(sn74273->clk_gpios[i], 0);
> +	}
> +}
> +
> +static int sn74273_led_probe(struct device_d *dev)
> +{
> +	struct device_node *np = dev->device_node;
> +	struct sn74273 *sn74273;
> +	int i, ret;
> +	enum of_gpio_flags flags;
> +
> +	sn74273 = xzalloc(sizeof(*sn74273));
> +
> +	sn74273->n_ports = of_gpio_named_count(np, "clk-gpios");
> +	if (sn74273->n_ports < 0) {
> +		dev_err(dev, "invalid or missing clk-gpios");
> +		ret = -EINVAL;
> +		goto err_gpio;
> +	}
> +
> +	sn74273->n_pins = of_gpio_named_count(np, "data-gpios");
> +	if (sn74273->n_pins < 0) {
> +		dev_err(dev, "invalid or missing data-gpios");
> +		ret = -EINVAL;
> +		goto err_gpio;
> +	}
> +
> +	sn74273->n_leds = sn74273->n_ports * sn74273->n_pins;
> +
> +	sn74273->clk_gpios = xzalloc(sizeof(int) * sn74273->n_ports);
> +	sn74273->data_gpios = xzalloc(sizeof(int) * sn74273->n_pins);
> +
> +	for (i = 0; i < sn74273->n_ports; i++) {
> +		sn74273->clk_gpios[i] = of_get_named_gpio_flags(np, "clk-gpios",
> +								i, &flags);
> +		ret = gpio_request_one(sn74273->clk_gpios[i],
> +				 flags & OF_GPIO_ACTIVE_LOW ? GPIOF_ACTIVE_LOW : 0,
> +				 dev_name(dev));
> +		if (ret) {
> +			dev_err(dev, "Cannot request gpio %d: %s\n", sn74273->clk_gpios[i],
> +				strerror(-ret));
> +			goto err_gpio;
> +		}
> +
> +		gpio_direction_output(sn74273->clk_gpios[i], 0);
> +	}
> +
> +	for (i = 0; i < sn74273->n_pins; i++) {
> +		sn74273->data_gpios[i] = of_get_named_gpio_flags(np, "data-gpios",
> +								 i, &flags);
> +		ret = gpio_request_one(sn74273->data_gpios[i],
> +				 flags & OF_GPIO_ACTIVE_LOW ? GPIOF_ACTIVE_LOW : 0,
> +				 dev_name(dev));
> +		if (ret) {
> +			dev_err(dev, "Cannot request gpio %d: %s\n", sn74273->data_gpios[i],
> +				strerror(-ret));
> +			goto err_gpio;
> +		}
> +
> +		gpio_direction_output(sn74273->data_gpios[i], 0);
> +	}
> +
> +	sn74273->shadow = xzalloc(sizeof(u8) * sn74273->n_ports);
> +	sn74273->leds = xzalloc(sizeof(*sn74273->leds) * sn74273->n_leds);
> +
> +	for (i = 0; i < sn74273->n_leds; i++) {
> +		struct sn74273_led *led = &sn74273->leds[i];
> +		const char *name;
> +
> +		led->port = i / sn74273->n_pins;
> +		led->pin = i % sn74273->n_pins;
> +
> +		ret = of_property_read_string_index(np, "labels", i, &name);
> +		if (ret)
> +			led->led.name = basprintf("%s-%d", dev_name(dev), i);
> +		else
> +			led->led.name = xstrdup(name);
> +
> +		led->led.set = sn74273_led_set;
> +		led->led.max_value = 1;
> +		led->sn74273 = sn74273;
> +
> +		ret = led_register(&led->led);
> +		if (ret) {
> +			dev_err(dev, "Failed to register led %d\n", i);
> +			goto err_register;
> +		}
> +	}
> +
> +	return 0;
> +
> +err_register:
> +	for (i = i - 1; i >= 0; i--) {
> +		struct sn74273_led *led = &sn74273->leds[i];
> +
> +		led_unregister(&led->led);
> +	}
> +
> +err_gpio:
> +	return ret;
> +}
> +
> +static const struct of_device_id of_sn74273_gpio_leds_match[] = {
> +	{
> +		.compatible = "74273-gpio-leds",
> +	}, {
> +	},
> +};
> +
> +static struct driver_d sn74273_led_driver = {
> +	.name		= "74273-gpio-leds",
> +	.of_compatible	= of_sn74273_gpio_leds_match,
> +	.probe		= sn74273_led_probe,
> +};
> +
> +device_platform_driver(sn74273_led_driver);
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



More information about the barebox mailing list