[PATCH] led: Add a 74273 led driver
Juergen Borleis
jbe at pengutronix.de
Wed Jul 14 02:14:23 PDT 2021
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"
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);
--
2.20.1
More information about the barebox
mailing list