[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