All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lukas Timmermann <linux@timmermann.space>
To: lee@kernel.org, pavel@kernel.org
Cc: linux-leds@vger.kernel.org, linux-kernel@vger.kernel.org,
	Lukas Timmermann <lukas@timmermann.space>
Subject: [PATCH 1/2] leds: as3668: Driver for the ams Osram 4-channel i2c LED driver
Date: Fri, 30 May 2025 20:42:21 +0200	[thread overview]
Message-ID: <20250530184219.78085-5-linux@timmermann.space> (raw)
In-Reply-To: <20250530184219.78085-3-linux@timmermann.space>

From: Lukas Timmermann <lukas@timmermann.space>

Document Osram as3668 LED driver devicetree
bindings.

---
 drivers/leds/Kconfig       |  10 +++
 drivers/leds/Makefile      |   1 +
 drivers/leds/leds-as3668.c | 178 +++++++++++++++++++++++++++++++++++++
 3 files changed, 189 insertions(+)
 create mode 100644 drivers/leds/leds-as3668.c

diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index a104cbb0a001..56477c170f0a 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -100,6 +100,16 @@ config LEDS_ARIEL
 
 	  Say Y to if your machine is a Dell Wyse 3020 thin client.
 
+config LEDS_AS3668
+	tristate "LED support for AMS AS3668"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+		This option enables support for the AMS AS3668 LED controller.
+
+		To compile this driver as a module, choose M here: the module
+		will be called leds-as3668.
+
 config LEDS_AW200XX
 	tristate "LED support for Awinic AW20036/AW20054/AW20072/AW20108"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 2f170d69dcbf..983811384fec 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_LEDS_ADP5520)		+= leds-adp5520.o
 obj-$(CONFIG_LEDS_AN30259A)		+= leds-an30259a.o
 obj-$(CONFIG_LEDS_APU)			+= leds-apu.o
 obj-$(CONFIG_LEDS_ARIEL)		+= leds-ariel.o
+obj-$(CONFIG_LEDS_AS3668)		+= leds-as3668.o
 obj-$(CONFIG_LEDS_AW200XX)		+= leds-aw200xx.o
 obj-$(CONFIG_LEDS_AW2013)		+= leds-aw2013.o
 obj-$(CONFIG_LEDS_BCM6328)		+= leds-bcm6328.o
diff --git a/drivers/leds/leds-as3668.c b/drivers/leds/leds-as3668.c
new file mode 100644
index 000000000000..f9448c12d170
--- /dev/null
+++ b/drivers/leds/leds-as3668.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  Osram AMS AS3668 LED Driver IC
+ *
+ *  Copyright (C) 2025 Lukas Timmermann <linux@timmermann.space>
+ */
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/uleds.h>
+
+#define AS3668_MAX_LEDS 4
+
+/* Chip Registers */
+#define AS3668_CHIP_ID1 0x3e
+#define AS3668_CHIP_ID2 0x3f
+
+#define AS3668_CHIP_ID2_SERIAL_MASK GENMASK(7, 4)
+#define AS3668_CHIP_ID2_REV_MASK GENMASK(3, 0)
+
+#define AS3668_CURRX_CONTROL 0x01
+#define AS3668_CURR1 0x02
+#define AS3668_CURR2 0x03
+#define AS3668_CURR3 0x04
+#define AS3668_CURR4 0x05
+
+/* Constants */
+#define AS3668_CHIP_IDENT 0xa5
+#define AS3668_CHIP_REV1 0x01
+
+struct as3668_led {
+	struct led_classdev cdev;
+	struct as3668 *chip;
+	struct fwnode_handle *fwnode;
+
+	int num;
+};
+
+struct as3668 {
+	struct i2c_client *client;
+	struct as3668_led leds[AS3668_MAX_LEDS];
+};
+
+static int as3668_read_value(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int as3668_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static enum led_brightness as3668_brightness_get(struct led_classdev *cdev)
+{
+	struct as3668_led *led = container_of(cdev, struct as3668_led, cdev);
+
+	return as3668_read_value(led->chip->client, AS3668_CURR1 + led->num);
+}
+
+static void as3668_brightness_set(struct led_classdev *cdev, enum led_brightness brightness)
+{
+	struct as3668_led *led = container_of(cdev, struct as3668_led, cdev);
+
+	as3668_write_value(led->chip->client, AS3668_CURR1 + led->num, brightness);
+}
+
+static int as3668_dt_init(struct as3668 *as3668)
+{
+	struct device *dev = &as3668->client->dev;
+	struct as3668_led *led;
+	struct led_init_data init_data = {};
+	int err;
+	int i = 0;
+
+	for_each_available_child_of_node_scoped(dev_of_node(dev), child) {
+		of_property_read_u8(child, "reg", &i);
+
+		if (i < 0 || i > AS3668_MAX_LEDS)
+			return dev_err_probe(dev, -EOPNOTSUPP, "Unsupported led reg %d\n", i);
+
+		led = &as3668->leds[i];
+		led->fwnode = of_fwnode_handle(child);
+
+		led->num = i;
+		led->chip = as3668;
+
+		led->cdev.max_brightness = U8_MAX;
+		led->cdev.brightness_get = as3668_brightness_get;
+		led->cdev.brightness_set = as3668_brightness_set;
+
+		init_data.fwnode = led->fwnode;
+		init_data.default_label = ":";
+
+		err = devm_led_classdev_register_ext(dev, &led->cdev, &init_data);
+		if (err)
+			return dev_err_probe(dev, err, "Failed to register %d LED\n", i);
+	}
+
+	return 0;
+}
+
+static int as3668_probe(struct i2c_client *client)
+{
+	u8 chip_id1, chip_id2, chip_serial, chip_rev;
+	struct as3668 *as3668;
+
+	/* Check for sensible i2c address */
+	if (client->addr != 0x42)
+		return dev_err_probe(&client->dev, -EFAULT, "Unexpected address for as3668 device\n");
+
+	/* Read identifier from chip */
+	chip_id1 = as3668_read_value(client, AS3668_CHIP_ID1);
+
+	if (chip_id1 != AS3668_CHIP_IDENT)
+		return dev_err_probe(&client->dev, -ENODEV, "Chip reported wrong id: 0x%tx\n", chip_id1);
+
+	/* Check the revision*/
+	chip_id2 = as3668_read_value(client, AS3668_CHIP_ID2);
+	chip_serial = FIELD_GET(AS3668_CHIP_ID2_SERIAL_MASK, chip_id2);
+	chip_rev = FIELD_GET(AS3668_CHIP_ID2_REV_MASK, chip_id2);
+
+	if (chip_rev != AS3668_CHIP_REV1)
+		dev_warn(&client->dev, "Unexpected chip revision\n");
+
+	/* Print out information about the chip */
+	dev_dbg(&client->dev, "chip_id: 0x%tx | chip_id2: 0x%tx | chip_serial: 0x%tx | chip_rev: 0x%tx\n", chip_id1, chip_id2, chip_serial, chip_rev);
+
+	as3668 = devm_kzalloc(&client->dev, struct_size(as3668, leds, 4), GFP_KERNEL);
+	as3668->client = client;
+
+	as3668_dt_init(as3668);
+
+	/* Initialize the chip */
+	as3668_write_value(client, AS3668_CURRX_CONTROL, 0x55);
+	as3668_write_value(client, AS3668_CURR1, 0x00);
+	as3668_write_value(client, AS3668_CURR2, 0x00);
+	as3668_write_value(client, AS3668_CURR3, 0x00);
+	as3668_write_value(client, AS3668_CURR4, 0x00);
+
+	return 0;
+}
+
+static void as3668_remove(struct i2c_client *client)
+{
+	as3668_write_value(client, AS3668_CURRX_CONTROL, 0x0);
+}
+
+static const struct i2c_device_id as3668_idtable[] = {
+	{"as3668"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, as3668_idtable);
+
+static const struct of_device_id as3668_match_table[] = {
+	{.compatible = "ams,as3668"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, as3668_match_table);
+
+static struct i2c_driver as3668_driver = {
+	.driver = {
+		.name           = "leds_as3668",
+		.of_match_table = as3668_match_table,
+	},
+	.probe          = as3668_probe,
+	.remove         = as3668_remove,
+	.id_table       = as3668_idtable,
+};
+
+module_i2c_driver(as3668_driver);
+
+MODULE_AUTHOR("Lukas Timmermann <linux@timmermann.space>");
+MODULE_DESCRIPTION("AS3668 LED driver");
+MODULE_LICENSE("GPL");
-- 
2.49.0


  reply	other threads:[~2025-05-30 18:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-30 18:42 [PATCH 0/2] Support for Osram as3668 LED driver Lukas Timmermann
2025-05-30 18:42 ` Lukas Timmermann [this message]
2025-05-30 18:42 ` [PATCH 2/2] dt-bindings: leds: Add new as3668 support Lukas Timmermann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250530184219.78085-5-linux@timmermann.space \
    --to=linux@timmermann.space \
    --cc=lee@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=lukas@timmermann.space \
    --cc=pavel@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.