Message ID | 20230417094035.998965-1-Naresh.Solanki@9elements.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp1996334vqo; Mon, 17 Apr 2023 02:48:51 -0700 (PDT) X-Google-Smtp-Source: AKy350bhZLzofMboypbfeAKMMzU/Ud2+Joj5FUc7jAgVnUcy8sdhm6lI92gpW+NfdY4x1LgvK+JC X-Received: by 2002:a17:90a:a607:b0:247:8029:fb2e with SMTP id c7-20020a17090aa60700b002478029fb2emr4445209pjq.46.1681724931422; Mon, 17 Apr 2023 02:48:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1681724931; cv=none; d=google.com; s=arc-20160816; b=V2GSEa0cKtvkkhWrX0XDBlckZCgO6Dwt0RJecWflOeH3BBQEFeK2/wzsr2ryKEdrT4 5aqxeglsL0v1ZQhiFvkSP8V1pSl9zNbKF82IdlXo8qPp6a0AjaeDdmYtG+b3r1WCfl/O 8rel2IKc4KhoeaBYHGrDaSFjVLNsrurOr95Z7POSIgPFBnSPusHZDEmhILqMyXwbRsnf 6dfrtJ0V5SLTyuLoF1Ciqx6JvpSJGpQggZQg1/jLlXs0gRkKv6R8ATsEJgKSRu9jGBox T/u6gq/yBaoXB6la2+kSAfoVhhZoljCB2bNT7whJagDi8XvV1eQzhYeZav86lK/BHrbZ U6kQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from:dkim-signature; bh=tll4GHwBgwWI+CvDMCVg7zGiU4JG66Dh6Fj+kV8ccKQ=; b=v+dRkYUQMNXaFJ75YEdv+LIfigKGHgnm+AzHdy/ClFzagVvktNmXFfcgpWvYvYZi1l YwffHB/okEyj/QYSTeg+en0RrYZs1RHR6esndaG9Iq/VhgzFrHOhSfpg5vUBEYem5iLZ yT3XwTjMXBECxXAlaCD2IJ0txW5EFW2pi5R9V1qMRrudgwwYA91XpHr9WSmZtjJ/Qsmr AaPhQ0VP8JbweIXY1+JbtUY2s0BSb7y85ilBzB1pJgG2gAbKXcwwaNDdjennYjz0n3vz Na1WZlTAYCtI1PeJTSk6GWawBxSBB8xCEFP1Az3Brnf2n8QclhE4X01Hz5KroGzHOr/C LtCQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@9elements.com header.s=google header.b=Xp2DcHrB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=9elements.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id nl5-20020a17090b384500b0023af4ee47dasi263563pjb.65.2023.04.17.02.48.31; Mon, 17 Apr 2023 02:48:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@9elements.com header.s=google header.b=Xp2DcHrB; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=9elements.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230332AbjDQJmc (ORCPT <rfc822;leviz.kernel.dev@gmail.com> + 99 others); Mon, 17 Apr 2023 05:42:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42792 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230436AbjDQJmS (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 17 Apr 2023 05:42:18 -0400 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 64C9BCE for <linux-kernel@vger.kernel.org>; Mon, 17 Apr 2023 02:41:16 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id ffacd0b85a97d-2efbab2dfbeso1327603f8f.1 for <linux-kernel@vger.kernel.org>; Mon, 17 Apr 2023 02:41:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=9elements.com; s=google; t=1681724440; x=1684316440; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=tll4GHwBgwWI+CvDMCVg7zGiU4JG66Dh6Fj+kV8ccKQ=; b=Xp2DcHrB8X6Irn+LtLMvce62pvJ+3px8Dc2zuempDPTU6S89mlcOuk8ezAGTnAVCVB prpEoKR9GUI4vkzbcCjqIPAGl6hkMcWlqavnaQlnVoSrMVcQNLM2jfLBEDRjpugzjzKp xpQCTgxPsOwkEJgwKmJVDTZ8ukVZUL8YlG3CWsxPEIv3uuGFu8Onoi0AfPCvt0HvELEc NHgVDn5AJV9SCCKn2EX8LTNPxQBnf8ArkUSF7K+rcCuBqeyupNp3tIYoFsKS5KRvhSS0 bx+8XEDC9RW6yXiSUMDg+shGyKQqftHhwYC8cEh5U0yxIAPbKH6Kx8M4tct31AvAXG9G V0WA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681724440; x=1684316440; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=tll4GHwBgwWI+CvDMCVg7zGiU4JG66Dh6Fj+kV8ccKQ=; b=PAjGZd0rlZaGgTdexfYvoPF/QhQLdOIa3G7/RLO48DALM3tg9H93MSdF6neiZJSVVW kPYaM7jxU8dcUrtUGOh6z0/9iyy3No/vuqhKNW5M6FDFFh+my9VfTf4AzPw6pqWzvEck ocS/WdQHt6EhKtLSDT1g7IcytXoDEUyZnTiyM8yvakQNKQKPxxNyP+A64Z/LQoTg4XFx 3BCyK/C7dV8zmdxgFAPvligbrCXFQERo41En6BSDFZlNdkKIsDe+3hoyDLYQTilw2EHz goq1iSCWu7HcsDm+bGGwtaK+6n75lrfKD4IwDR2grt6WKw2zQq4IqwG3PotSAJA4S+sB M5wg== X-Gm-Message-State: AAQBX9eYLEkBzdrNvyV+xA1kHm6gmr8sC5su/gu6VZxaheoUQ998ITIr hqujHbQAGThh3kzAJ7FM4EK8WLAaBL7wUKLRqPvsAA== X-Received: by 2002:a5d:4a05:0:b0:2f4:30ee:310b with SMTP id m5-20020a5d4a05000000b002f430ee310bmr5360032wrq.26.1681724440447; Mon, 17 Apr 2023 02:40:40 -0700 (PDT) Received: from stroh80.sec.9e.network (ip-078-094-000-051.um19.pools.vodafone-ip.de. [78.94.0.51]) by smtp.gmail.com with ESMTPSA id e16-20020a5d4e90000000b002f2782978d8sm10013226wru.20.2023.04.17.02.40.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Apr 2023 02:40:40 -0700 (PDT) From: Naresh Solanki <naresh.solanki@9elements.com> X-Google-Original-From: Naresh Solanki <Naresh.Solanki@9elements.com> To: Pavel Machek <pavel@ucw.cz>, Lee Jones <lee@kernel.org> Cc: Patrick Rudolph <patrick.rudolph@9elements.com>, Naresh Solanki <Naresh.Solanki@9elements.com>, linux-kernel@vger.kernel.org, linux-leds@vger.kernel.org Subject: [PATCH v5] leds: max597x: Add support for max597x Date: Mon, 17 Apr 2023 11:40:34 +0200 Message-Id: <20230417094035.998965-1-Naresh.Solanki@9elements.com> X-Mailer: git-send-email 2.39.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1763416401473799814?= X-GMAIL-MSGID: =?utf-8?q?1763416401473799814?= |
Series |
[v5] leds: max597x: Add support for max597x
|
|
Commit Message
Naresh Solanki
April 17, 2023, 9:40 a.m. UTC
From: Patrick Rudolph <patrick.rudolph@9elements.com> max597x is hot swap controller with indicator LED support. This driver uses DT property to configure led during boot time & also provide the LED control in sysfs. DTS example: i2c { #address-cells = <1>; #size-cells = <0>; regulator@3a { compatible = "maxim,max5978"; reg = <0x3a>; vss1-supply = <&p3v3>; regulators { sw0_ref_0: sw0 { shunt-resistor-micro-ohms = <12000>; }; }; leds { #address-cells = <1>; #size-cells = <0>; led@0 { reg = <0>; label = "ssd0:green"; default-state = "on"; }; led@1 { reg = <1>; label = "ssd1:green"; default-state = "on"; }; }; }; }; Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> ... Changes in V5: - Update commit message - Fix comments - Add necessary new line Changes in V4: - Remove unwanted preinitialise - Remove unneeded line breaks - Fix variable name to avoid confusion - Update module description to mention LED driver. Changes in V3: - Remove of_node_put as its handled by for loop - Print error if an LED fails to register. - Update driver name in Kconfig description - Remove unneeded variable assignment - Use devm_led_classdev_register to reget led Changes in V2: - Fix regmap update - Remove devm_kfree - Remove default-state - Add example dts in commit message - Fix whitespace in Kconfig - Fix comment --- drivers/leds/Kconfig | 11 ++++ drivers/leds/Makefile | 1 + drivers/leds/leds-max597x.c | 115 ++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 drivers/leds/leds-max597x.c base-commit: 9d8d0d98885abba451d7ffc4885236d14ead3c9a
Comments
On Mon, 17 Apr 2023, Naresh Solanki wrote: > From: Patrick Rudolph <patrick.rudolph@9elements.com> > > max597x is hot swap controller with indicator LED support. > This driver uses DT property to configure led during boot time & > also provide the LED control in sysfs. > > DTS example: > i2c { > #address-cells = <1>; > #size-cells = <0>; > regulator@3a { > compatible = "maxim,max5978"; > reg = <0x3a>; > vss1-supply = <&p3v3>; > > regulators { > sw0_ref_0: sw0 { > shunt-resistor-micro-ohms = <12000>; > }; > }; > > leds { > #address-cells = <1>; > #size-cells = <0>; > led@0 { > reg = <0>; > label = "ssd0:green"; > default-state = "on"; > }; > led@1 { > reg = <1>; > label = "ssd1:green"; > default-state = "on"; > }; > }; > }; > }; Where is the DT binding document for this? > Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> > Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> > ... > Changes in V5: > - Update commit message > - Fix comments > - Add necessary new line > Changes in V4: > - Remove unwanted preinitialise > - Remove unneeded line breaks > - Fix variable name to avoid confusion > - Update module description to mention LED driver. > Changes in V3: > - Remove of_node_put as its handled by for loop > - Print error if an LED fails to register. > - Update driver name in Kconfig description > - Remove unneeded variable assignment > - Use devm_led_classdev_register to reget led > Changes in V2: > - Fix regmap update > - Remove devm_kfree > - Remove default-state > - Add example dts in commit message > - Fix whitespace in Kconfig > - Fix comment > --- > drivers/leds/Kconfig | 11 ++++ > drivers/leds/Makefile | 1 + > drivers/leds/leds-max597x.c | 115 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 127 insertions(+) > create mode 100644 drivers/leds/leds-max597x.c > > diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig > index 9dbce09eabac..60004cb8c257 100644 > --- a/drivers/leds/Kconfig > +++ b/drivers/leds/Kconfig > @@ -590,6 +590,17 @@ config LEDS_ADP5520 > To compile this driver as a module, choose M here: the module will > be called leds-adp5520. > > +config LEDS_MAX597X > + tristate "LED Support for Maxim 597x" > + depends on LEDS_CLASS > + depends on MFD_MAX597X > + help > + This option enables support for the Maxim MAX5970 & MAX5978 smart > + switch indication LEDs via the I2C bus. > + > + To compile this driver as a module, choose M here: the module will > + be called leds-max597x. > + > config LEDS_MC13783 > tristate "LED Support for MC13XXX PMIC" > depends on LEDS_CLASS > diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile > index d30395d11fd8..da1192e40268 100644 > --- a/drivers/leds/Makefile > +++ b/drivers/leds/Makefile > @@ -53,6 +53,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o > obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o > obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o > obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o > +obj-$(CONFIG_LEDS_MAX597X) += leds-max597x.o > obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o > obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o > obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o > diff --git a/drivers/leds/leds-max597x.c b/drivers/leds/leds-max597x.c > new file mode 100644 > index 000000000000..edbd43018822 > --- /dev/null > +++ b/drivers/leds/leds-max597x.c > @@ -0,0 +1,115 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * Device driver for leds in MAX5970 and MAX5978 IC "MAX5970 and MAX5978 IC LED support" > + * Copyright (c) 2022 9elements GmbH > + * > + * Author: Patrick Rudolph <patrick.rudolph@9elements.com> > + */ > + > +#include <linux/leds.h> > +#include <linux/mfd/max597x.h> > +#include <linux/of.h> > +#include <linux/platform_device.h> > +#include <linux/regmap.h> > + > +#define ldev_to_maxled(c) container_of(c, struct max597x_led, cdev) > + > +struct max597x_led { > + struct regmap *regmap; > + struct led_classdev cdev; > + unsigned int index; > +}; > + > +static int max597x_led_set_brightness(struct led_classdev *cdev, > + enum led_brightness brightness) > +{ > + struct max597x_led *ddata = ldev_to_maxled(cdev); > + int ret, val; > + > + if (!ddata->regmap) > + return -ENODEV; > + > + /* Set/clear corresponding bit for given led index */ > + val = !brightness ? BIT(ddata->index) : 0; > + > + ret = regmap_update_bits(ddata->regmap, MAX5970_REG_LED_FLASH, BIT(ddata->index), val); > + if (ret < 0) > + dev_err(cdev->dev, "failed to set brightness %d", ret); > + > + return ret; > +} > + > +static int max597x_setup_led(struct device *dev, struct regmap *regmap, struct device_node *nc, > + u32 reg) > +{ > + struct max597x_led *ddata; > + int ret; > + > + ddata = devm_kzalloc(dev, sizeof(struct max597x_led), GFP_KERNEL); > + if (!ddata) > + return -ENOMEM; > + > + if (of_property_read_string(nc, "label", &ddata->cdev.name)) > + ddata->cdev.name = nc->name; > + > + ddata->cdev.max_brightness = 1; > + ddata->cdev.brightness_set_blocking = max597x_led_set_brightness; > + ddata->cdev.default_trigger = "none"; > + ddata->index = reg; > + ddata->regmap = regmap; > + > + ret = devm_led_classdev_register(dev, &ddata->cdev); > + if (ret) > + dev_err(dev, "Error initializing LED %s", ddata->cdev.name); > + > + return ret; > +} > + > +static int max597x_led_probe(struct platform_device *pdev) > +{ > + struct device_node *np = dev_of_node(pdev->dev.parent); My previous question about having its own compatible string was ignored. > + struct regmap *regmap; > + struct device_node *led_node; > + struct device_node *child; > + int ret = 0; > + > + regmap = dev_get_regmap(pdev->dev.parent, NULL); > + if (!regmap) > + return -EPROBE_DEFER; > + > + led_node = of_get_child_by_name(np, "leds"); > + if (!led_node) > + return -ENODEV; > + > + for_each_available_child_of_node(led_node, child) { > + u32 reg; > + > + if (of_property_read_u32(child, "reg", ®)) > + continue; > + > + if (reg >= MAX597X_NUM_LEDS) { > + dev_err(&pdev->dev, "invalid LED (%u >= %d)\n", reg, > + MAX597X_NUM_LEDS); > + continue; > + } > + > + ret = max597x_setup_led(&pdev->dev, regmap, child, reg); > + if (ret < 0) > + dev_err(&pdev->dev, "Failed to initialize LED %u\n", reg); You've ignored my previous review. > + } > + > + return ret; > +} > + > +static struct platform_driver max597x_led_driver = { > + .driver = { > + .name = "max597x-led", > + }, > + .probe = max597x_led_probe, > +}; > + > +module_platform_driver(max597x_led_driver); > +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); > +MODULE_DESCRIPTION("MAX5970_hot-swap controller LED driver"); > +MODULE_LICENSE("GPL"); > > base-commit: 9d8d0d98885abba451d7ffc4885236d14ead3c9a > -- > 2.39.1 >
Hi Lee, On 20-04-2023 05:20 pm, Lee Jones wrote: > On Mon, 17 Apr 2023, Naresh Solanki wrote: > >> From: Patrick Rudolph <patrick.rudolph@9elements.com> >> >> max597x is hot swap controller with indicator LED support. >> This driver uses DT property to configure led during boot time & >> also provide the LED control in sysfs. >> >> DTS example: >> i2c { >> #address-cells = <1>; >> #size-cells = <0>; >> regulator@3a { >> compatible = "maxim,max5978"; >> reg = <0x3a>; >> vss1-supply = <&p3v3>; >> >> regulators { >> sw0_ref_0: sw0 { >> shunt-resistor-micro-ohms = <12000>; >> }; >> }; >> >> leds { >> #address-cells = <1>; >> #size-cells = <0>; >> led@0 { >> reg = <0>; >> label = "ssd0:green"; >> default-state = "on"; >> }; >> led@1 { >> reg = <1>; >> label = "ssd1:green"; >> default-state = "on"; >> }; >> }; >> }; >> }; > > Where is the DT binding document for this? > >> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> >> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> >> ... >> Changes in V5: >> - Update commit message >> - Fix comments >> - Add necessary new line >> Changes in V4: >> - Remove unwanted preinitialise >> - Remove unneeded line breaks >> - Fix variable name to avoid confusion >> - Update module description to mention LED driver. >> Changes in V3: >> - Remove of_node_put as its handled by for loop >> - Print error if an LED fails to register. >> - Update driver name in Kconfig description >> - Remove unneeded variable assignment >> - Use devm_led_classdev_register to reget led >> Changes in V2: >> - Fix regmap update >> - Remove devm_kfree >> - Remove default-state >> - Add example dts in commit message >> - Fix whitespace in Kconfig >> - Fix comment >> --- >> drivers/leds/Kconfig | 11 ++++ >> drivers/leds/Makefile | 1 + >> drivers/leds/leds-max597x.c | 115 ++++++++++++++++++++++++++++++++++++ >> 3 files changed, 127 insertions(+) >> create mode 100644 drivers/leds/leds-max597x.c >> >> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig >> index 9dbce09eabac..60004cb8c257 100644 >> --- a/drivers/leds/Kconfig >> +++ b/drivers/leds/Kconfig >> @@ -590,6 +590,17 @@ config LEDS_ADP5520 >> To compile this driver as a module, choose M here: the module will >> be called leds-adp5520. >> >> +config LEDS_MAX597X >> + tristate "LED Support for Maxim 597x" >> + depends on LEDS_CLASS >> + depends on MFD_MAX597X >> + help >> + This option enables support for the Maxim MAX5970 & MAX5978 smart >> + switch indication LEDs via the I2C bus. >> + >> + To compile this driver as a module, choose M here: the module will >> + be called leds-max597x. >> + >> config LEDS_MC13783 >> tristate "LED Support for MC13XXX PMIC" >> depends on LEDS_CLASS >> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile >> index d30395d11fd8..da1192e40268 100644 >> --- a/drivers/leds/Makefile >> +++ b/drivers/leds/Makefile >> @@ -53,6 +53,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o >> obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o >> obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o >> obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o >> +obj-$(CONFIG_LEDS_MAX597X) += leds-max597x.o >> obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o >> obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o >> obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o >> diff --git a/drivers/leds/leds-max597x.c b/drivers/leds/leds-max597x.c >> new file mode 100644 >> index 000000000000..edbd43018822 >> --- /dev/null >> +++ b/drivers/leds/leds-max597x.c >> @@ -0,0 +1,115 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * Device driver for leds in MAX5970 and MAX5978 IC > > "MAX5970 and MAX5978 IC LED support" > >> + * Copyright (c) 2022 9elements GmbH >> + * >> + * Author: Patrick Rudolph <patrick.rudolph@9elements.com> >> + */ >> + >> +#include <linux/leds.h> >> +#include <linux/mfd/max597x.h> >> +#include <linux/of.h> >> +#include <linux/platform_device.h> >> +#include <linux/regmap.h> >> + >> +#define ldev_to_maxled(c) container_of(c, struct max597x_led, cdev) >> + >> +struct max597x_led { >> + struct regmap *regmap; >> + struct led_classdev cdev; >> + unsigned int index; >> +}; >> + >> +static int max597x_led_set_brightness(struct led_classdev *cdev, >> + enum led_brightness brightness) >> +{ >> + struct max597x_led *ddata = ldev_to_maxled(cdev); >> + int ret, val; >> + >> + if (!ddata->regmap) >> + return -ENODEV; >> + >> + /* Set/clear corresponding bit for given led index */ >> + val = !brightness ? BIT(ddata->index) : 0; >> + >> + ret = regmap_update_bits(ddata->regmap, MAX5970_REG_LED_FLASH, BIT(ddata->index), val); >> + if (ret < 0) >> + dev_err(cdev->dev, "failed to set brightness %d", ret); >> + >> + return ret; >> +} >> + >> +static int max597x_setup_led(struct device *dev, struct regmap *regmap, struct device_node *nc, >> + u32 reg) >> +{ >> + struct max597x_led *ddata; >> + int ret; >> + >> + ddata = devm_kzalloc(dev, sizeof(struct max597x_led), GFP_KERNEL); >> + if (!ddata) >> + return -ENOMEM; >> + >> + if (of_property_read_string(nc, "label", &ddata->cdev.name)) >> + ddata->cdev.name = nc->name; >> + >> + ddata->cdev.max_brightness = 1; >> + ddata->cdev.brightness_set_blocking = max597x_led_set_brightness; >> + ddata->cdev.default_trigger = "none"; >> + ddata->index = reg; >> + ddata->regmap = regmap; >> + >> + ret = devm_led_classdev_register(dev, &ddata->cdev); >> + if (ret) >> + dev_err(dev, "Error initializing LED %s", ddata->cdev.name); >> + >> + return ret; >> +} >> + >> +static int max597x_led_probe(struct platform_device *pdev) >> +{ >> + struct device_node *np = dev_of_node(pdev->dev.parent); > > My previous question about having its own compatible string was ignored. As previously stated, the MFD driver for max597x already has a compatible string that serves its purpose, so I opted not to include a separate compatible string for the leaf driver. Prior to implementing this approach, I reviewed other implementations within the MFD driver, such as the sy7636 which uses the similar approach in leaf driver. > >> + struct regmap *regmap; >> + struct device_node *led_node; >> + struct device_node *child; >> + int ret = 0; >> + >> + regmap = dev_get_regmap(pdev->dev.parent, NULL); >> + if (!regmap) >> + return -EPROBE_DEFER; >> + >> + led_node = of_get_child_by_name(np, "leds"); >> + if (!led_node) >> + return -ENODEV; >> + >> + for_each_available_child_of_node(led_node, child) { >> + u32 reg; >> + >> + if (of_property_read_u32(child, "reg", ®)) >> + continue; >> + >> + if (reg >= MAX597X_NUM_LEDS) { >> + dev_err(&pdev->dev, "invalid LED (%u >= %d)\n", reg, >> + MAX597X_NUM_LEDS); >> + continue; >> + } >> + >> + ret = max597x_setup_led(&pdev->dev, regmap, child, reg); >> + if (ret < 0) >> + dev_err(&pdev->dev, "Failed to initialize LED %u\n", reg); > > You've ignored my previous review. I would like to clarify that I did not intend to overlook your previous review comment. Rather, I have taken it into consideration and evaluated it in the context of the current approach, which is derived from the code in other LED drivers. To eliminate any potential confusion, it may be best to adopt a consistent approach that all LED drivers should adhere to in similar circumstances. > >> + } >> + >> + return ret; >> +} >> + >> +static struct platform_driver max597x_led_driver = { >> + .driver = { >> + .name = "max597x-led", >> + }, >> + .probe = max597x_led_probe, >> +}; >> + >> +module_platform_driver(max597x_led_driver); >> +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); >> +MODULE_DESCRIPTION("MAX5970_hot-swap controller LED driver"); >> +MODULE_LICENSE("GPL"); >> >> base-commit: 9d8d0d98885abba451d7ffc4885236d14ead3c9a >> -- >> 2.39.1 >> > Regards, Naresh
On Thu, 20 Apr 2023, Naresh Solanki wrote: > Hi Lee, > > On 20-04-2023 05:20 pm, Lee Jones wrote: > > On Mon, 17 Apr 2023, Naresh Solanki wrote: > > > > > From: Patrick Rudolph <patrick.rudolph@9elements.com> > > > > > > max597x is hot swap controller with indicator LED support. > > > This driver uses DT property to configure led during boot time & > > > also provide the LED control in sysfs. > > > > > > DTS example: > > > i2c { > > > #address-cells = <1>; > > > #size-cells = <0>; > > > regulator@3a { > > > compatible = "maxim,max5978"; > > > reg = <0x3a>; > > > vss1-supply = <&p3v3>; > > > > > > regulators { > > > sw0_ref_0: sw0 { > > > shunt-resistor-micro-ohms = <12000>; > > > }; > > > }; > > > > > > leds { > > > #address-cells = <1>; > > > #size-cells = <0>; > > > led@0 { > > > reg = <0>; > > > label = "ssd0:green"; > > > default-state = "on"; > > > }; > > > led@1 { > > > reg = <1>; > > > label = "ssd1:green"; > > > default-state = "on"; > > > }; > > > }; > > > }; > > > }; > > > > Where is the DT binding document for this? ? <--------------------------------------------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > > Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> > > > Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> > > > ... > > > Changes in V5: > > > - Update commit message > > > - Fix comments > > > - Add necessary new line > > > Changes in V4: > > > - Remove unwanted preinitialise > > > - Remove unneeded line breaks > > > - Fix variable name to avoid confusion > > > - Update module description to mention LED driver. > > > Changes in V3: > > > - Remove of_node_put as its handled by for loop > > > - Print error if an LED fails to register. > > > - Update driver name in Kconfig description > > > - Remove unneeded variable assignment > > > - Use devm_led_classdev_register to reget led > > > Changes in V2: > > > - Fix regmap update > > > - Remove devm_kfree > > > - Remove default-state > > > - Add example dts in commit message > > > - Fix whitespace in Kconfig > > > - Fix comment > > > --- > > > drivers/leds/Kconfig | 11 ++++ > > > drivers/leds/Makefile | 1 + > > > drivers/leds/leds-max597x.c | 115 ++++++++++++++++++++++++++++++++++++ > > > 3 files changed, 127 insertions(+) > > > create mode 100644 drivers/leds/leds-max597x.c > > > > > > diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig > > > index 9dbce09eabac..60004cb8c257 100644 > > > --- a/drivers/leds/Kconfig > > > +++ b/drivers/leds/Kconfig > > > @@ -590,6 +590,17 @@ config LEDS_ADP5520 > > > To compile this driver as a module, choose M here: the module will > > > be called leds-adp5520. > > > +config LEDS_MAX597X > > > + tristate "LED Support for Maxim 597x" > > > + depends on LEDS_CLASS > > > + depends on MFD_MAX597X > > > + help > > > + This option enables support for the Maxim MAX5970 & MAX5978 smart > > > + switch indication LEDs via the I2C bus. > > > + > > > + To compile this driver as a module, choose M here: the module will > > > + be called leds-max597x. > > > + > > > config LEDS_MC13783 > > > tristate "LED Support for MC13XXX PMIC" > > > depends on LEDS_CLASS > > > diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile > > > index d30395d11fd8..da1192e40268 100644 > > > --- a/drivers/leds/Makefile > > > +++ b/drivers/leds/Makefile > > > @@ -53,6 +53,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o > > > obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o > > > obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o > > > obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o > > > +obj-$(CONFIG_LEDS_MAX597X) += leds-max597x.o > > > obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o > > > obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o > > > obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o > > > diff --git a/drivers/leds/leds-max597x.c b/drivers/leds/leds-max597x.c > > > new file mode 100644 > > > index 000000000000..edbd43018822 > > > --- /dev/null > > > +++ b/drivers/leds/leds-max597x.c > > > @@ -0,0 +1,115 @@ > > > +// SPDX-License-Identifier: GPL-2.0 > > > +/* > > > + * Device driver for leds in MAX5970 and MAX5978 IC > > > > "MAX5970 and MAX5978 IC LED support" > > > > > + * Copyright (c) 2022 9elements GmbH > > > + * > > > + * Author: Patrick Rudolph <patrick.rudolph@9elements.com> > > > + */ > > > + > > > +#include <linux/leds.h> > > > +#include <linux/mfd/max597x.h> > > > +#include <linux/of.h> > > > +#include <linux/platform_device.h> > > > +#include <linux/regmap.h> > > > + > > > +#define ldev_to_maxled(c) container_of(c, struct max597x_led, cdev) > > > + > > > +struct max597x_led { > > > + struct regmap *regmap; > > > + struct led_classdev cdev; > > > + unsigned int index; > > > +}; > > > + > > > +static int max597x_led_set_brightness(struct led_classdev *cdev, > > > + enum led_brightness brightness) > > > +{ > > > + struct max597x_led *ddata = ldev_to_maxled(cdev); > > > + int ret, val; > > > + > > > + if (!ddata->regmap) > > > + return -ENODEV; > > > + > > > + /* Set/clear corresponding bit for given led index */ > > > + val = !brightness ? BIT(ddata->index) : 0; > > > + > > > + ret = regmap_update_bits(ddata->regmap, MAX5970_REG_LED_FLASH, BIT(ddata->index), val); > > > + if (ret < 0) > > > + dev_err(cdev->dev, "failed to set brightness %d", ret); > > > + > > > + return ret; > > > +} > > > + > > > +static int max597x_setup_led(struct device *dev, struct regmap *regmap, struct device_node *nc, > > > + u32 reg) > > > +{ > > > + struct max597x_led *ddata; > > > + int ret; > > > + > > > + ddata = devm_kzalloc(dev, sizeof(struct max597x_led), GFP_KERNEL); > > > + if (!ddata) > > > + return -ENOMEM; > > > + > > > + if (of_property_read_string(nc, "label", &ddata->cdev.name)) > > > + ddata->cdev.name = nc->name; > > > + > > > + ddata->cdev.max_brightness = 1; > > > + ddata->cdev.brightness_set_blocking = max597x_led_set_brightness; > > > + ddata->cdev.default_trigger = "none"; > > > + ddata->index = reg; > > > + ddata->regmap = regmap; > > > + > > > + ret = devm_led_classdev_register(dev, &ddata->cdev); > > > + if (ret) > > > + dev_err(dev, "Error initializing LED %s", ddata->cdev.name); > > > + > > > + return ret; > > > +} > > > + > > > +static int max597x_led_probe(struct platform_device *pdev) > > > +{ > > > + struct device_node *np = dev_of_node(pdev->dev.parent); > > > > My previous question about having its own compatible string was ignored. > As previously stated, the MFD driver for max597x already has a compatible > string that serves its purpose, so I opted not to include a separate > compatible string for the leaf driver. > Prior to implementing this approach, I reviewed other implementations within > the MFD driver, such as the sy7636 which uses the similar approach in leaf > driver. I'm not saying it's never been done. However, most of the time leaf/child devices have their own compatible string and node. > > > + struct regmap *regmap; > > > + struct device_node *led_node; > > > + struct device_node *child; > > > + int ret = 0; > > > + > > > + regmap = dev_get_regmap(pdev->dev.parent, NULL); > > > + if (!regmap) > > > + return -EPROBE_DEFER; Will other child devices have be using the parent's regmap too? > > > + led_node = of_get_child_by_name(np, "leds"); > > > + if (!led_node) > > > + return -ENODEV; It's odd for a device to be referring to itself as the "child". > > > + for_each_available_child_of_node(led_node, child) { > > > + u32 reg; > > > + > > > + if (of_property_read_u32(child, "reg", ®)) > > > + continue; > > > + > > > + if (reg >= MAX597X_NUM_LEDS) { > > > + dev_err(&pdev->dev, "invalid LED (%u >= %d)\n", reg, > > > + MAX597X_NUM_LEDS); > > > + continue; > > > + } > > > + > > > + ret = max597x_setup_led(&pdev->dev, regmap, child, reg); > > > + if (ret < 0) > > > + dev_err(&pdev->dev, "Failed to initialize LED %u\n", reg); > > > > You've ignored my previous review. > I would like to clarify that I did not intend to overlook your previous > review comment. Rather, I have taken it into consideration and evaluated it > in the context of the current approach, which is derived from the code in > other LED drivers. > To eliminate any potential confusion, it may be best to adopt a consistent > approach that all LED drivers should adhere to in similar circumstances. I agree. That's start with this one. You should not error and continue. If you encounter an error, please unwind what you have done before and return the error. > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static struct platform_driver max597x_led_driver = { > > > + .driver = { > > > + .name = "max597x-led", > > > + }, > > > + .probe = max597x_led_probe, > > > +}; > > > + > > > +module_platform_driver(max597x_led_driver); > > > +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); > > > +MODULE_DESCRIPTION("MAX5970_hot-swap controller LED driver"); > > > +MODULE_LICENSE("GPL"); > > > > > > base-commit: 9d8d0d98885abba451d7ffc4885236d14ead3c9a > > > -- > > > 2.39.1 > > > > > > Regards, > Naresh
Hi Lee, On 20-04-2023 07:24 pm, Lee Jones wrote: > On Thu, 20 Apr 2023, Naresh Solanki wrote: > >> Hi Lee, >> >> On 20-04-2023 05:20 pm, Lee Jones wrote: >>> On Mon, 17 Apr 2023, Naresh Solanki wrote: >>> >>>> From: Patrick Rudolph <patrick.rudolph@9elements.com> >>>> >>>> max597x is hot swap controller with indicator LED support. >>>> This driver uses DT property to configure led during boot time & >>>> also provide the LED control in sysfs. >>>> >>>> DTS example: >>>> i2c { >>>> #address-cells = <1>; >>>> #size-cells = <0>; >>>> regulator@3a { >>>> compatible = "maxim,max5978"; >>>> reg = <0x3a>; >>>> vss1-supply = <&p3v3>; >>>> >>>> regulators { >>>> sw0_ref_0: sw0 { >>>> shunt-resistor-micro-ohms = <12000>; >>>> }; >>>> }; >>>> >>>> leds { >>>> #address-cells = <1>; >>>> #size-cells = <0>; >>>> led@0 { >>>> reg = <0>; >>>> label = "ssd0:green"; >>>> default-state = "on"; >>>> }; >>>> led@1 { >>>> reg = <1>; >>>> label = "ssd1:green"; >>>> default-state = "on"; >>>> }; >>>> }; >>>> }; >>>> }; >>> >>> Where is the DT binding document for this? https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git/tree/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml?h=for-mfd-next > > > ? <--------------------------------------------------------------------------- > > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > >>>> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> >>>> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> >>>> ... >>>> Changes in V5: >>>> - Update commit message >>>> - Fix comments >>>> - Add necessary new line >>>> Changes in V4: >>>> - Remove unwanted preinitialise >>>> - Remove unneeded line breaks >>>> - Fix variable name to avoid confusion >>>> - Update module description to mention LED driver. >>>> Changes in V3: >>>> - Remove of_node_put as its handled by for loop >>>> - Print error if an LED fails to register. >>>> - Update driver name in Kconfig description >>>> - Remove unneeded variable assignment >>>> - Use devm_led_classdev_register to reget led >>>> Changes in V2: >>>> - Fix regmap update >>>> - Remove devm_kfree >>>> - Remove default-state >>>> - Add example dts in commit message >>>> - Fix whitespace in Kconfig >>>> - Fix comment >>>> --- >>>> drivers/leds/Kconfig | 11 ++++ >>>> drivers/leds/Makefile | 1 + >>>> drivers/leds/leds-max597x.c | 115 ++++++++++++++++++++++++++++++++++++ >>>> 3 files changed, 127 insertions(+) >>>> create mode 100644 drivers/leds/leds-max597x.c >>>> >>>> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig >>>> index 9dbce09eabac..60004cb8c257 100644 >>>> --- a/drivers/leds/Kconfig >>>> +++ b/drivers/leds/Kconfig >>>> @@ -590,6 +590,17 @@ config LEDS_ADP5520 >>>> To compile this driver as a module, choose M here: the module will >>>> be called leds-adp5520. >>>> +config LEDS_MAX597X >>>> + tristate "LED Support for Maxim 597x" >>>> + depends on LEDS_CLASS >>>> + depends on MFD_MAX597X >>>> + help >>>> + This option enables support for the Maxim MAX5970 & MAX5978 smart >>>> + switch indication LEDs via the I2C bus. >>>> + >>>> + To compile this driver as a module, choose M here: the module will >>>> + be called leds-max597x. >>>> + >>>> config LEDS_MC13783 >>>> tristate "LED Support for MC13XXX PMIC" >>>> depends on LEDS_CLASS >>>> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile >>>> index d30395d11fd8..da1192e40268 100644 >>>> --- a/drivers/leds/Makefile >>>> +++ b/drivers/leds/Makefile >>>> @@ -53,6 +53,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o >>>> obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o >>>> obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o >>>> obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o >>>> +obj-$(CONFIG_LEDS_MAX597X) += leds-max597x.o >>>> obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o >>>> obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o >>>> obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o >>>> diff --git a/drivers/leds/leds-max597x.c b/drivers/leds/leds-max597x.c >>>> new file mode 100644 >>>> index 000000000000..edbd43018822 >>>> --- /dev/null >>>> +++ b/drivers/leds/leds-max597x.c >>>> @@ -0,0 +1,115 @@ >>>> +// SPDX-License-Identifier: GPL-2.0 >>>> +/* >>>> + * Device driver for leds in MAX5970 and MAX5978 IC >>> >>> "MAX5970 and MAX5978 IC LED support" >>> >>>> + * Copyright (c) 2022 9elements GmbH >>>> + * >>>> + * Author: Patrick Rudolph <patrick.rudolph@9elements.com> >>>> + */ >>>> + >>>> +#include <linux/leds.h> >>>> +#include <linux/mfd/max597x.h> >>>> +#include <linux/of.h> >>>> +#include <linux/platform_device.h> >>>> +#include <linux/regmap.h> >>>> + >>>> +#define ldev_to_maxled(c) container_of(c, struct max597x_led, cdev) >>>> + >>>> +struct max597x_led { >>>> + struct regmap *regmap; >>>> + struct led_classdev cdev; >>>> + unsigned int index; >>>> +}; >>>> + >>>> +static int max597x_led_set_brightness(struct led_classdev *cdev, >>>> + enum led_brightness brightness) >>>> +{ >>>> + struct max597x_led *ddata = ldev_to_maxled(cdev); >>>> + int ret, val; >>>> + >>>> + if (!ddata->regmap) >>>> + return -ENODEV; >>>> + >>>> + /* Set/clear corresponding bit for given led index */ >>>> + val = !brightness ? BIT(ddata->index) : 0; >>>> + >>>> + ret = regmap_update_bits(ddata->regmap, MAX5970_REG_LED_FLASH, BIT(ddata->index), val); >>>> + if (ret < 0) >>>> + dev_err(cdev->dev, "failed to set brightness %d", ret); >>>> + >>>> + return ret; >>>> +} >>>> + >>>> +static int max597x_setup_led(struct device *dev, struct regmap *regmap, struct device_node *nc, >>>> + u32 reg) >>>> +{ >>>> + struct max597x_led *ddata; >>>> + int ret; >>>> + >>>> + ddata = devm_kzalloc(dev, sizeof(struct max597x_led), GFP_KERNEL); >>>> + if (!ddata) >>>> + return -ENOMEM; >>>> + >>>> + if (of_property_read_string(nc, "label", &ddata->cdev.name)) >>>> + ddata->cdev.name = nc->name; >>>> + >>>> + ddata->cdev.max_brightness = 1; >>>> + ddata->cdev.brightness_set_blocking = max597x_led_set_brightness; >>>> + ddata->cdev.default_trigger = "none"; >>>> + ddata->index = reg; >>>> + ddata->regmap = regmap; >>>> + >>>> + ret = devm_led_classdev_register(dev, &ddata->cdev); >>>> + if (ret) >>>> + dev_err(dev, "Error initializing LED %s", ddata->cdev.name); >>>> + >>>> + return ret; >>>> +} >>>> + >>>> +static int max597x_led_probe(struct platform_device *pdev) >>>> +{ >>>> + struct device_node *np = dev_of_node(pdev->dev.parent); >>> >>> My previous question about having its own compatible string was ignored. >> As previously stated, the MFD driver for max597x already has a compatible >> string that serves its purpose, so I opted not to include a separate >> compatible string for the leaf driver. >> Prior to implementing this approach, I reviewed other implementations within >> the MFD driver, such as the sy7636 which uses the similar approach in leaf >> driver. > > I'm not saying it's never been done. However, most of the time > leaf/child devices have their own compatible string and node. True. > >>>> + struct regmap *regmap; >>>> + struct device_node *led_node; >>>> + struct device_node *child; >>>> + int ret = 0; >>>> + >>>> + regmap = dev_get_regmap(pdev->dev.parent, NULL); >>>> + if (!regmap) >>>> + return -EPROBE_DEFER; > > Will other child devices have be using the parent's regmap too? Yes > >>>> + led_node = of_get_child_by_name(np, "leds"); >>>> + if (!led_node) >>>> + return -ENODEV; > > It's odd for a device to be referring to itself as the "child". As this is leaf driver, LED specific info is present in "leds" node in DT. > >>>> + for_each_available_child_of_node(led_node, child) { >>>> + u32 reg; >>>> + >>>> + if (of_property_read_u32(child, "reg", ®)) >>>> + continue; >>>> + >>>> + if (reg >= MAX597X_NUM_LEDS) { >>>> + dev_err(&pdev->dev, "invalid LED (%u >= %d)\n", reg, >>>> + MAX597X_NUM_LEDS); >>>> + continue; >>>> + } >>>> + >>>> + ret = max597x_setup_led(&pdev->dev, regmap, child, reg); >>>> + if (ret < 0) >>>> + dev_err(&pdev->dev, "Failed to initialize LED %u\n", reg); >>> >>> You've ignored my previous review. >> I would like to clarify that I did not intend to overlook your previous >> review comment. Rather, I have taken it into consideration and evaluated it >> in the context of the current approach, which is derived from the code in >> other LED drivers. >> To eliminate any potential confusion, it may be best to adopt a consistent >> approach that all LED drivers should adhere to in similar circumstances. > > I agree. That's start with this one. > > You should not error and continue. If you encounter an error, please > unwind what you have done before and return the error. Ack. > >>>> + } >>>> + >>>> + return ret; >>>> +} >>>> + >>>> +static struct platform_driver max597x_led_driver = { >>>> + .driver = { >>>> + .name = "max597x-led", >>>> + }, >>>> + .probe = max597x_led_probe, >>>> +}; >>>> + >>>> +module_platform_driver(max597x_led_driver); >>>> +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); >>>> +MODULE_DESCRIPTION("MAX5970_hot-swap controller LED driver"); >>>> +MODULE_LICENSE("GPL"); >>>> >>>> base-commit: 9d8d0d98885abba451d7ffc4885236d14ead3c9a >>>> -- >>>> 2.39.1 >>>> >>> >> Regards, >> Naresh > Regards, Naresh
On Thu, 20 Apr 2023, Naresh Solanki wrote: > Hi Lee, > > On 20-04-2023 07:24 pm, Lee Jones wrote: > > On Thu, 20 Apr 2023, Naresh Solanki wrote: > > > > > Hi Lee, > > > > > > On 20-04-2023 05:20 pm, Lee Jones wrote: > > > > On Mon, 17 Apr 2023, Naresh Solanki wrote: > > > > > > > > > From: Patrick Rudolph <patrick.rudolph@9elements.com> > > > > > > > > > > max597x is hot swap controller with indicator LED support. > > > > > This driver uses DT property to configure led during boot time & > > > > > also provide the LED control in sysfs. > > > > > > > > > > DTS example: > > > > > i2c { > > > > > #address-cells = <1>; > > > > > #size-cells = <0>; > > > > > regulator@3a { > > > > > compatible = "maxim,max5978"; > > > > > reg = <0x3a>; > > > > > vss1-supply = <&p3v3>; > > > > > > > > > > regulators { > > > > > sw0_ref_0: sw0 { > > > > > shunt-resistor-micro-ohms = <12000>; > > > > > }; > > > > > }; > > > > > > > > > > leds { > > > > > #address-cells = <1>; > > > > > #size-cells = <0>; > > > > > led@0 { > > > > > reg = <0>; > > > > > label = "ssd0:green"; > > > > > default-state = "on"; > > > > > }; > > > > > led@1 { > > > > > reg = <1>; > > > > > label = "ssd1:green"; > > > > > default-state = "on"; > > > > > }; > > > > > }; > > > > > }; > > > > > }; > > > > > > > > Where is the DT binding document for this? > https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git/tree/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml?h=for-mfd-next You need to update it. It is different to the one you supplied here. > > > > > Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> > > > > > Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> > > > > > ... > > > > > Changes in V5: > > > > > - Update commit message > > > > > - Fix comments > > > > > - Add necessary new line > > > > > Changes in V4: > > > > > - Remove unwanted preinitialise > > > > > - Remove unneeded line breaks > > > > > - Fix variable name to avoid confusion > > > > > - Update module description to mention LED driver. > > > > > Changes in V3: > > > > > - Remove of_node_put as its handled by for loop > > > > > - Print error if an LED fails to register. > > > > > - Update driver name in Kconfig description > > > > > - Remove unneeded variable assignment > > > > > - Use devm_led_classdev_register to reget led > > > > > Changes in V2: > > > > > - Fix regmap update > > > > > - Remove devm_kfree > > > > > - Remove default-state > > > > > - Add example dts in commit message > > > > > - Fix whitespace in Kconfig > > > > > - Fix comment > > > > > --- > > > > > drivers/leds/Kconfig | 11 ++++ > > > > > drivers/leds/Makefile | 1 + > > > > > drivers/leds/leds-max597x.c | 115 ++++++++++++++++++++++++++++++++++++ > > > > > 3 files changed, 127 insertions(+) > > > > > create mode 100644 drivers/leds/leds-max597x.c [...] > > > > + led_node = of_get_child_by_name(np, "leds"); > > > > > + if (!led_node) > > > > > + return -ENODEV; > > > > It's odd for a device to be referring to itself as the "child". > As this is leaf driver, LED specific info is present in "leds" node in DT. I'm aware of the architecture. If you give the LEDs driver it's own compatible you don't need to keep doing this self->parent->child level-jumping craziness to obtain resources.
Hi, On 21-04-2023 12:49 pm, Lee Jones wrote: > On Thu, 20 Apr 2023, Naresh Solanki wrote: > >> Hi Lee, >> >> On 20-04-2023 07:24 pm, Lee Jones wrote: >>> On Thu, 20 Apr 2023, Naresh Solanki wrote: >>> >>>> Hi Lee, >>>> >>>> On 20-04-2023 05:20 pm, Lee Jones wrote: >>>>> On Mon, 17 Apr 2023, Naresh Solanki wrote: >>>>> >>>>>> From: Patrick Rudolph <patrick.rudolph@9elements.com> >>>>>> >>>>>> max597x is hot swap controller with indicator LED support. >>>>>> This driver uses DT property to configure led during boot time & >>>>>> also provide the LED control in sysfs. >>>>>> >>>>>> DTS example: >>>>>> i2c { >>>>>> #address-cells = <1>; >>>>>> #size-cells = <0>; >>>>>> regulator@3a { >>>>>> compatible = "maxim,max5978"; >>>>>> reg = <0x3a>; >>>>>> vss1-supply = <&p3v3>; >>>>>> >>>>>> regulators { >>>>>> sw0_ref_0: sw0 { >>>>>> shunt-resistor-micro-ohms = <12000>; >>>>>> }; >>>>>> }; >>>>>> >>>>>> leds { >>>>>> #address-cells = <1>; >>>>>> #size-cells = <0>; >>>>>> led@0 { >>>>>> reg = <0>; >>>>>> label = "ssd0:green"; >>>>>> default-state = "on"; >>>>>> }; >>>>>> led@1 { >>>>>> reg = <1>; >>>>>> label = "ssd1:green"; >>>>>> default-state = "on"; >>>>>> }; >>>>>> }; >>>>>> }; >>>>>> }; >>>>> >>>>> Where is the DT binding document for this? >> https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git/tree/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml?h=for-mfd-next > > You need to update it. It is different to the one you supplied here. Ack. > >>>>>> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> >>>>>> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> >>>>>> ... >>>>>> Changes in V5: >>>>>> - Update commit message >>>>>> - Fix comments >>>>>> - Add necessary new line >>>>>> Changes in V4: >>>>>> - Remove unwanted preinitialise >>>>>> - Remove unneeded line breaks >>>>>> - Fix variable name to avoid confusion >>>>>> - Update module description to mention LED driver. >>>>>> Changes in V3: >>>>>> - Remove of_node_put as its handled by for loop >>>>>> - Print error if an LED fails to register. >>>>>> - Update driver name in Kconfig description >>>>>> - Remove unneeded variable assignment >>>>>> - Use devm_led_classdev_register to reget led >>>>>> Changes in V2: >>>>>> - Fix regmap update >>>>>> - Remove devm_kfree >>>>>> - Remove default-state >>>>>> - Add example dts in commit message >>>>>> - Fix whitespace in Kconfig >>>>>> - Fix comment >>>>>> --- >>>>>> drivers/leds/Kconfig | 11 ++++ >>>>>> drivers/leds/Makefile | 1 + >>>>>> drivers/leds/leds-max597x.c | 115 ++++++++++++++++++++++++++++++++++++ >>>>>> 3 files changed, 127 insertions(+) >>>>>> create mode 100644 drivers/leds/leds-max597x.c > > [...] > >>>>> + led_node = of_get_child_by_name(np, "leds"); >>>>>> + if (!led_node) >>>>>> + return -ENODEV; >>> >>> It's odd for a device to be referring to itself as the "child". >> As this is leaf driver, LED specific info is present in "leds" node in DT. > > I'm aware of the architecture. > > If you give the LEDs driver it's own compatible you don't need to keep > doing this self->parent->child level-jumping craziness to obtain > resources. From my understanding, it is preferable to have only one compatible per chip(in this case MFD driver), and the leaf driver can leverage it unless it is not serving the purpose/breaks something. I think this is acceptable as long as it doesn't creates any issue/breaks anything. > Regards, Naresh
Hi Lee, On 24-04-2023 03:10 pm, Naresh Solanki wrote: > Hi, > > On 21-04-2023 12:49 pm, Lee Jones wrote: >> On Thu, 20 Apr 2023, Naresh Solanki wrote: >> >>> Hi Lee, >>> >>> On 20-04-2023 07:24 pm, Lee Jones wrote: >>>> On Thu, 20 Apr 2023, Naresh Solanki wrote: >>>> >>>>> Hi Lee, >>>>> >>>>> On 20-04-2023 05:20 pm, Lee Jones wrote: >>>>>> On Mon, 17 Apr 2023, Naresh Solanki wrote: >>>>>> >>>>>>> From: Patrick Rudolph <patrick.rudolph@9elements.com> >>>>>>> >>>>>>> max597x is hot swap controller with indicator LED support. >>>>>>> This driver uses DT property to configure led during boot time & >>>>>>> also provide the LED control in sysfs. >>>>>>> >>>>>>> DTS example: >>>>>>> i2c { >>>>>>> #address-cells = <1>; >>>>>>> #size-cells = <0>; >>>>>>> regulator@3a { >>>>>>> compatible = "maxim,max5978"; >>>>>>> reg = <0x3a>; >>>>>>> vss1-supply = <&p3v3>; >>>>>>> >>>>>>> regulators { >>>>>>> sw0_ref_0: sw0 { >>>>>>> shunt-resistor-micro-ohms = <12000>; >>>>>>> }; >>>>>>> }; >>>>>>> >>>>>>> leds { >>>>>>> #address-cells = <1>; >>>>>>> #size-cells = <0>; >>>>>>> led@0 { >>>>>>> reg = <0>; >>>>>>> label = "ssd0:green"; >>>>>>> default-state = "on"; >>>>>>> }; >>>>>>> led@1 { >>>>>>> reg = <1>; >>>>>>> label = "ssd1:green"; >>>>>>> default-state = "on"; >>>>>>> }; >>>>>>> }; >>>>>>> }; >>>>>>> }; >>>>>> >>>>>> Where is the DT binding document for this? >>> https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git/tree/Documentation/devicetree/bindings/mfd/maxim,max5970.yaml?h=for-mfd-next >> >> You need to update it. It is different to the one you supplied here. > Ack. >> >>>>>>> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com> >>>>>>> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com> >>>>>>> ... >>>>>>> Changes in V5: >>>>>>> - Update commit message >>>>>>> - Fix comments >>>>>>> - Add necessary new line >>>>>>> Changes in V4: >>>>>>> - Remove unwanted preinitialise >>>>>>> - Remove unneeded line breaks >>>>>>> - Fix variable name to avoid confusion >>>>>>> - Update module description to mention LED driver. >>>>>>> Changes in V3: >>>>>>> - Remove of_node_put as its handled by for loop >>>>>>> - Print error if an LED fails to register. >>>>>>> - Update driver name in Kconfig description >>>>>>> - Remove unneeded variable assignment >>>>>>> - Use devm_led_classdev_register to reget led >>>>>>> Changes in V2: >>>>>>> - Fix regmap update >>>>>>> - Remove devm_kfree >>>>>>> - Remove default-state >>>>>>> - Add example dts in commit message >>>>>>> - Fix whitespace in Kconfig >>>>>>> - Fix comment >>>>>>> --- >>>>>>> drivers/leds/Kconfig | 11 ++++ >>>>>>> drivers/leds/Makefile | 1 + >>>>>>> drivers/leds/leds-max597x.c | 115 >>>>>>> ++++++++++++++++++++++++++++++++++++ >>>>>>> 3 files changed, 127 insertions(+) >>>>>>> create mode 100644 drivers/leds/leds-max597x.c >> >> [...] >> >>>>>> + led_node = of_get_child_by_name(np, "leds"); >>>>>>> + if (!led_node) >>>>>>> + return -ENODEV; >>>> >>>> It's odd for a device to be referring to itself as the "child". >>> As this is leaf driver, LED specific info is present in "leds" node >>> in DT. >> >> I'm aware of the architecture. >> >> If you give the LEDs driver it's own compatible you don't need to keep >> doing this self->parent->child level-jumping craziness to obtain >> resources. > From my understanding, it is preferable to have only one compatible per > chip(in this case MFD driver), and the leaf driver can leverage it > unless it is not serving the purpose/breaks something. > I think this is acceptable as long as it doesn't creates any > issue/breaks anything. I just wanted to kindly follow up and check if we are aligned with the approach. And kindly let me know if you have any concerns regarding this. Thank you very much for your time and I look forward to hearing back from you soon :) >> > > > Regards, > Naresh
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9dbce09eabac..60004cb8c257 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -590,6 +590,17 @@ config LEDS_ADP5520 To compile this driver as a module, choose M here: the module will be called leds-adp5520. +config LEDS_MAX597X + tristate "LED Support for Maxim 597x" + depends on LEDS_CLASS + depends on MFD_MAX597X + help + This option enables support for the Maxim MAX5970 & MAX5978 smart + switch indication LEDs via the I2C bus. + + To compile this driver as a module, choose M here: the module will + be called leds-max597x. + config LEDS_MC13783 tristate "LED Support for MC13XXX PMIC" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index d30395d11fd8..da1192e40268 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_LEDS_LP8501) += leds-lp8501.o obj-$(CONFIG_LEDS_LP8788) += leds-lp8788.o obj-$(CONFIG_LEDS_LP8860) += leds-lp8860.o obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o +obj-$(CONFIG_LEDS_MAX597X) += leds-max597x.o obj-$(CONFIG_LEDS_MAX77650) += leds-max77650.o obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o diff --git a/drivers/leds/leds-max597x.c b/drivers/leds/leds-max597x.c new file mode 100644 index 000000000000..edbd43018822 --- /dev/null +++ b/drivers/leds/leds-max597x.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Device driver for leds in MAX5970 and MAX5978 IC + * + * Copyright (c) 2022 9elements GmbH + * + * Author: Patrick Rudolph <patrick.rudolph@9elements.com> + */ + +#include <linux/leds.h> +#include <linux/mfd/max597x.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#define ldev_to_maxled(c) container_of(c, struct max597x_led, cdev) + +struct max597x_led { + struct regmap *regmap; + struct led_classdev cdev; + unsigned int index; +}; + +static int max597x_led_set_brightness(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct max597x_led *ddata = ldev_to_maxled(cdev); + int ret, val; + + if (!ddata->regmap) + return -ENODEV; + + /* Set/clear corresponding bit for given led index */ + val = !brightness ? BIT(ddata->index) : 0; + + ret = regmap_update_bits(ddata->regmap, MAX5970_REG_LED_FLASH, BIT(ddata->index), val); + if (ret < 0) + dev_err(cdev->dev, "failed to set brightness %d", ret); + + return ret; +} + +static int max597x_setup_led(struct device *dev, struct regmap *regmap, struct device_node *nc, + u32 reg) +{ + struct max597x_led *ddata; + int ret; + + ddata = devm_kzalloc(dev, sizeof(struct max597x_led), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + if (of_property_read_string(nc, "label", &ddata->cdev.name)) + ddata->cdev.name = nc->name; + + ddata->cdev.max_brightness = 1; + ddata->cdev.brightness_set_blocking = max597x_led_set_brightness; + ddata->cdev.default_trigger = "none"; + ddata->index = reg; + ddata->regmap = regmap; + + ret = devm_led_classdev_register(dev, &ddata->cdev); + if (ret) + dev_err(dev, "Error initializing LED %s", ddata->cdev.name); + + return ret; +} + +static int max597x_led_probe(struct platform_device *pdev) +{ + struct device_node *np = dev_of_node(pdev->dev.parent); + struct regmap *regmap; + struct device_node *led_node; + struct device_node *child; + int ret = 0; + + regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!regmap) + return -EPROBE_DEFER; + + led_node = of_get_child_by_name(np, "leds"); + if (!led_node) + return -ENODEV; + + for_each_available_child_of_node(led_node, child) { + u32 reg; + + if (of_property_read_u32(child, "reg", ®)) + continue; + + if (reg >= MAX597X_NUM_LEDS) { + dev_err(&pdev->dev, "invalid LED (%u >= %d)\n", reg, + MAX597X_NUM_LEDS); + continue; + } + + ret = max597x_setup_led(&pdev->dev, regmap, child, reg); + if (ret < 0) + dev_err(&pdev->dev, "Failed to initialize LED %u\n", reg); + } + + return ret; +} + +static struct platform_driver max597x_led_driver = { + .driver = { + .name = "max597x-led", + }, + .probe = max597x_led_probe, +}; + +module_platform_driver(max597x_led_driver); +MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>"); +MODULE_DESCRIPTION("MAX5970_hot-swap controller LED driver"); +MODULE_LICENSE("GPL");