2021-03-29 06:01:26

by Hermes Zhang

[permalink] [raw]
Subject: [PATCH v3] leds: leds-multi-gpio: Add multiple GPIOs LED driver

From: Hermes Zhang <[email protected]>

Introduce a new multiple GPIOs LED driver. This LED will made of
multiple GPIOs (up to 8) and will map different brightness to different
GPIOs states which defined in dts file.

Signed-off-by: Hermes Zhang <[email protected]>
---

Notes:
changes v3:
- Remove LEDS_SIMPLE menu
- Minro code style fix

changes v2:
- use max_brightness(2^gpio numbers) instead of LED_FULL
- malloc the priv in once
- move the code to simple folder

drivers/leds/Kconfig | 3 +
drivers/leds/Makefile | 3 +
drivers/leds/simple/Kconfig | 12 +++
drivers/leds/simple/Makefile | 3 +
drivers/leds/simple/leds-multi-gpio.c | 144 ++++++++++++++++++++++++++
5 files changed, 165 insertions(+)
create mode 100644 drivers/leds/simple/Kconfig
create mode 100644 drivers/leds/simple/Makefile
create mode 100644 drivers/leds/simple/leds-multi-gpio.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index b6742b4231bf..f95217b2fcf1 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -937,4 +937,7 @@ source "drivers/leds/trigger/Kconfig"
comment "LED Blink"
source "drivers/leds/blink/Kconfig"

+comment "LED Simple"
+source "drivers/leds/simple/Kconfig"
+
endif # NEW_LEDS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 2a698df9da57..22cba8dfd6a9 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -111,3 +111,6 @@ obj-$(CONFIG_LEDS_TRIGGERS) += trigger/

# LED Blink
obj-$(CONFIG_LEDS_BLINK) += blink/
+
+# LED Simple
+obj-$(CONFIG_LEDS_SIMPLE) += simple/
diff --git a/drivers/leds/simple/Kconfig b/drivers/leds/simple/Kconfig
new file mode 100644
index 000000000000..98540b6c8d7a
--- /dev/null
+++ b/drivers/leds/simple/Kconfig
@@ -0,0 +1,12 @@
+config LEDS_MULTI_GPIO
+ tristate "LED Support for multiple GPIOs LED"
+ depends on LEDS_CLASS
+ depends on GPIOLIB
+ depends on OF
+ help
+ This option enables support for a multiple GPIOs LED. Such LED is made
+ of multiple GPIOs and could change the brightness by setting different
+ states of the GPIOs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called leds-multi-gpio.
diff --git a/drivers/leds/simple/Makefile b/drivers/leds/simple/Makefile
new file mode 100644
index 000000000000..2ba655fdc175
--- /dev/null
+++ b/drivers/leds/simple/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_LEDS_MULTI_GPIO) += leds-multi-gpio.o
diff --git a/drivers/leds/simple/leds-multi-gpio.c b/drivers/leds/simple/leds-multi-gpio.c
new file mode 100644
index 000000000000..ede033354156
--- /dev/null
+++ b/drivers/leds/simple/leds-multi-gpio.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Axis Communications AB
+ */
+
+#include <linux/leds.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+
+#define MAX_GPIO_NUM 8
+
+struct multi_gpio_led_priv {
+ struct led_classdev cdev;
+
+ struct gpio_descs *gpios;
+
+ u16 nr_states;
+
+ u8 states[0];
+};
+
+
+static void multi_gpio_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct multi_gpio_led_priv *priv;
+ int idx;
+
+ DECLARE_BITMAP(values, MAX_GPIO_NUM);
+
+ priv = container_of(led_cdev, struct multi_gpio_led_priv, cdev);
+
+ idx = value > led_cdev->max_brightness ? led_cdev->max_brightness : value;
+
+ values[0] = priv->states[idx];
+
+ gpiod_set_array_value(priv->gpios->ndescs, priv->gpios->desc,
+ priv->gpios->info, values);
+}
+
+static int multi_gpio_led_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct multi_gpio_led_priv *priv = NULL;
+ int ret;
+ const char *state = NULL;
+ struct led_init_data init_data = {};
+ struct gpio_descs *gpios;
+ u16 nr_states;
+
+ gpios = devm_gpiod_get_array(dev, "led", GPIOD_OUT_LOW);
+ if (IS_ERR(gpios))
+ return PTR_ERR(gpios);
+
+ if (gpios->ndescs >= MAX_GPIO_NUM) {
+ dev_err(dev, "Too many GPIOs\n");
+ return -EINVAL;
+ }
+
+ ret = of_property_count_u8_elems(node, "led-states");
+ if (ret < 0)
+ return ret;
+
+ if (ret != (1 << gpios->ndescs)) {
+ dev_err(dev, "led-states number should equal to 2^led-gpios\n");
+ return -EINVAL;
+ }
+
+ nr_states = ret;
+
+ priv = devm_kzalloc(dev, sizeof(struct multi_gpio_led_priv) + nr_states,
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ret = of_property_read_u8_array(node, "led-states", priv->states, nr_states);
+ if (ret)
+ return ret;
+
+ priv->gpios = gpios;
+ priv->nr_states = nr_states;
+
+ priv->cdev.max_brightness = nr_states;
+ priv->cdev.default_trigger = of_get_property(node, "linux,default-trigger", NULL);
+ priv->cdev.brightness_set = multi_gpio_led_set;
+
+ init_data.fwnode = of_fwnode_handle(node);
+
+ ret = devm_led_classdev_register_ext(dev, &priv->cdev, &init_data);
+ if (ret < 0)
+ return ret;
+
+ of_property_read_string(node, "default-state", &state);
+ if (!strcmp(state, "on"))
+ multi_gpio_led_set(&priv->cdev, priv->cdev.max_brightness);
+ else
+ multi_gpio_led_set(&priv->cdev, 0);
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+}
+
+static void multi_gpio_led_shutdown(struct platform_device *pdev)
+{
+ struct multi_gpio_led_priv *priv = platform_get_drvdata(pdev);
+
+ multi_gpio_led_set(&priv->cdev, 0);
+}
+
+static int multi_gpio_led_remove(struct platform_device *pdev)
+{
+ multi_gpio_led_shutdown(pdev);
+
+ return 0;
+}
+
+static const struct of_device_id of_multi_gpio_led_match[] = {
+ { .compatible = "multi-gpio-led", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, of_multi_gpio_led_match);
+
+static struct platform_driver multi_gpio_led_driver = {
+ .probe = multi_gpio_led_probe,
+ .remove = multi_gpio_led_remove,
+ .shutdown = multi_gpio_led_shutdown,
+ .driver = {
+ .name = "multi-gpio-led",
+ .of_match_table = of_multi_gpio_led_match,
+ },
+};
+
+module_platform_driver(multi_gpio_led_driver);
+
+MODULE_AUTHOR("Hermes Zhang <[email protected]>");
+MODULE_DESCRIPTION("Multiple GPIOs LED driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:leds-multi-gpio");
--
2.20.1


2021-08-04 19:16:48

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v3] leds: leds-multi-gpio: Add multiple GPIOs LED driver

Hi!

> From: Hermes Zhang <[email protected]>
>
> Introduce a new multiple GPIOs LED driver. This LED will made of
> multiple GPIOs (up to 8) and will map different brightness to different
> GPIOs states which defined in dts file.
>
> Signed-off-by: Hermes Zhang <[email protected]>

Thank you, it looks simple and mostly ok.

Acked-by: Pavel Machek <[email protected]>

But it really needs to go in with devicetree documentation changes,
and they need to be acked by devicetree maintainers. If you have that,
please send it in series.

Best regards,
Pavel
--
http://www.livejournal.com/~pavelmachek


Attachments:
(No filename) (628.00 B)
signature.asc (188.00 B)
Digital signature
Download all attachments

2021-08-09 06:33:52

by Hermes Zhang

[permalink] [raw]
Subject: RE: [PATCH v3] leds: leds-multi-gpio: Add multiple GPIOs LED driver

Hi,

> -----Original Message-----
> From: Pavel Machek <[email protected]>
> Sent: 2021??8??4?? 23:52
> To: Hermes Zhang <[email protected]>
> Cc: Dan Murphy <[email protected]>; kernel <[email protected]>; Hermes
> Zhang <[email protected]>; [email protected]; linux-
> [email protected]
> Subject: Re: [PATCH v3] leds: leds-multi-gpio: Add multiple GPIOs LED driver
>
> Hi!
>
> > From: Hermes Zhang <[email protected]>
> >
> > Introduce a new multiple GPIOs LED driver. This LED will made of
> > multiple GPIOs (up to 8) and will map different brightness to
> > different GPIOs states which defined in dts file.
> >
> > Signed-off-by: Hermes Zhang <[email protected]>
>
> Thank you, it looks simple and mostly ok.
>
> Acked-by: Pavel Machek <[email protected]>
>
> But it really needs to go in with devicetree documentation changes, and they
> need to be acked by devicetree maintainers. If you have that, please send it
> in series.
>

Do you mean this one: https://lore.kernel.org/patchwork/patch/1402471/, it's already in series.

Best Regards,
Hermes

2021-08-18 07:06:02

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH v3] leds: leds-multi-gpio: Add multiple GPIOs LED driver

Hi!

> > > From: Hermes Zhang <[email protected]>
> > >
> > > Introduce a new multiple GPIOs LED driver. This LED will made of
> > > multiple GPIOs (up to 8) and will map different brightness to
> > > different GPIOs states which defined in dts file.
> > >
> > > Signed-off-by: Hermes Zhang <[email protected]>
> >
> > Thank you, it looks simple and mostly ok.
> >
> > Acked-by: Pavel Machek <[email protected]>
> >
> > But it really needs to go in with devicetree documentation changes, and they
> > need to be acked by devicetree maintainers. If you have that, please send it
> > in series.
> >
>
> Do you mean this one: https://lore.kernel.org/patchwork/patch/1402471/, it's already in series.

I don't see Rob Herring's ack there.

Best regards,
Pavel
--
http://www.livejournal.com/~pavelmachek


Attachments:
(No filename) (834.00 B)
signature.asc (188.00 B)
Digital signature
Download all attachments