Re: [PATCH v2 1/5] leds: Add Intel Cherry Trail Whiskey Cove PMIC LED driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 24 Apr 2023, Hans de Goede wrote:

> Hi Lee,
> 
> On 4/24/23 16:15, Lee Jones wrote:
> > On Thu, 20 Apr 2023, Hans de Goede wrote:
> > 
> >> From: Yauhen Kharuzhy <jekhor@xxxxxxxxx>
> >>
> >> Add support for LEDs connected to the Intel Cherry Trail Whiskey Cove
> >> PMIC. Charger and general-purpose LEDs are supported. Hardware blinking
> >> is implemented, breathing is not.
> >>
> >> This driver was tested with Lenovo Yoga Book notebook.
> >>
> >> Changes by Hans de Goede (in response to review of v2):
> >> - Since the PMIC is connected to the battery any changes we make to
> >>   the LED settings are permanent, even surviving reboot / poweroff.
> >>   Save LED1 register settings on probe() and if auto-/hw-control was
> >>   enabled on probe() restore the settings on remove() and shutdown().
> >> - Delay switching LED1 to software control mode to first brightness write.
> >> - Use dynamically allocated drvdata instead of a global drvdata variable.
> >> - Ensure the LED is on when activating blinking.
> >> - Fix CHT_WC_LED_EFF_BREATHING val ((3 << 1) rather then BIT(3)).
> >>
> >> Link: https://lore.kernel.org/r/20190212205901.13037-2-jekhor@xxxxxxxxx
> >> Signed-off-by: Yauhen Kharuzhy <jekhor@xxxxxxxxx>
> >> Co-developed-by: Hans de Goede <hdegoede@xxxxxxxxxx>
> >> Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
> >> ---
> >> Changes in v2:
> >> - Update comment about YB1 kernel source usage for register info
> >> - Replace "cht-wc::" LED name prefix with "platform::"
> >> - Add leds-cht-wcove to list of drivers using "platform::charging" in
> >>   Documentation/leds/well-known-leds.txt
> >> - Bail from cht_wc_leds_brightness_set() on first error
> >> - Make default blink 1Hz, like sw-blink default blink
> >> ---
> >>  Documentation/leds/well-known-leds.txt |   2 +-
> >>  drivers/leds/Kconfig                   |  11 +
> >>  drivers/leds/Makefile                  |   1 +
> >>  drivers/leds/leds-cht-wcove.c          | 373 +++++++++++++++++++++++++
> >>  4 files changed, 386 insertions(+), 1 deletion(-)
> >>  create mode 100644 drivers/leds/leds-cht-wcove.c
> > 
> > Generally nice.  Couple of small nits.
> > 
> >> diff --git a/Documentation/leds/well-known-leds.txt b/Documentation/leds/well-known-leds.txt
> >> index 2160382c86be..7640debee6c0 100644
> >> --- a/Documentation/leds/well-known-leds.txt
> >> +++ b/Documentation/leds/well-known-leds.txt
> >> @@ -65,7 +65,7 @@ Phones usually have multi-color status LED.
> >>  
> >>  * Power management
> >>  
> >> -Good: "platform:*:charging" (allwinner sun50i)
> >> +Good: "platform:*:charging" (allwinner sun50i, leds-cht-wcove)
> >>  
> >>  * Screen
> >>  
> >> diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
> >> index 9dbce09eabac..90835716f14a 100644
> >> --- a/drivers/leds/Kconfig
> >> +++ b/drivers/leds/Kconfig
> >> @@ -122,6 +122,17 @@ config LEDS_BCM6358
> >>  	  This option enables support for LEDs connected to the BCM6358
> >>  	  LED HW controller accessed via MMIO registers.
> >>  
> >> +config LEDS_CHT_WCOVE
> >> +	tristate "LED support for Intel Cherry Trail Whiskey Cove PMIC"
> >> +	depends on LEDS_CLASS
> >> +	depends on INTEL_SOC_PMIC_CHTWC
> >> +	help
> >> +	  This option enables support for charger and general purpose LEDs
> >> +	  connected to the Intel Cherrytrail Whiskey Cove PMIC.
> >> +
> >> +	  To compile this driver as a module, choose M here: the module
> >> +	  will be called leds-cht-wcove.
> >> +
> >>  config LEDS_CPCAP
> >>  	tristate "LED Support for Motorola CPCAP"
> >>  	depends on LEDS_CLASS
> >> diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
> >> index d30395d11fd8..78b5b69f9c54 100644
> >> --- a/drivers/leds/Makefile
> >> +++ b/drivers/leds/Makefile
> >> @@ -19,6 +19,7 @@ obj-$(CONFIG_LEDS_BCM6328)		+= leds-bcm6328.o
> >>  obj-$(CONFIG_LEDS_BCM6358)		+= leds-bcm6358.o
> >>  obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
> >>  obj-$(CONFIG_LEDS_BLINKM)		+= leds-blinkm.o
> >> +obj-$(CONFIG_LEDS_CHT_WCOVE)		+= leds-cht-wcove.o
> >>  obj-$(CONFIG_LEDS_CLEVO_MAIL)		+= leds-clevo-mail.o
> >>  obj-$(CONFIG_LEDS_COBALT_QUBE)		+= leds-cobalt-qube.o
> >>  obj-$(CONFIG_LEDS_COBALT_RAQ)		+= leds-cobalt-raq.o
> >> diff --git a/drivers/leds/leds-cht-wcove.c b/drivers/leds/leds-cht-wcove.c
> >> new file mode 100644
> >> index 000000000000..908965e25552
> >> --- /dev/null
> >> +++ b/drivers/leds/leds-cht-wcove.c
> >> @@ -0,0 +1,373 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Driver for LEDs connected to the Intel Cherry Trail Whiskey Cove PMIC
> >> + *
> >> + * Copyright 2019 Yauhen Kharuzhy <jekhor@xxxxxxxxx>
> >> + * Copyright 2023 Hans de Goede <hansg@xxxxxxxxxx>
> >> + *
> >> + * Register info comes from the Lenovo Yoga Book Android kernel sources:
> >> + * YB1_source_code/kernel/cht/drivers/misc/charger_gp_led.c.
> > 
> > How does one browse to this?
> 
> There is a tarbal with kernel sources available for download from
> the support page for the Android version of the Yoga Book (yb1-x90f / yb1-x90l).
> 
> This is the file path within that tarbal. I add a deep-link
> to the tarbal here, but I'm afraid that will not be a stable link.
> 
> Or I guess I could omit the filename too? I added the filename because
> even if you have the tarbal the file is still sort of non trivial to find.

That's not the issue I have with it.

How about:

  <tarball>/YB1_source_code/kernel/cht/drivers/misc/charger_gp_led.c

Or:

  file:///YB1_source_code/kernel/cht/drivers/misc/charger_gp_led.c

[...]

> >> +enum led_brightness cht_wc_leds_brightness_get(struct led_classdev *cdev)
> >> +{
> >> +	struct cht_wc_led *led = container_of(cdev, struct cht_wc_led, cdev);
> >> +	unsigned int val;
> >> +	int ret;
> >> +
> >> +	mutex_lock(&led->mutex);
> >> +
> >> +	ret = regmap_read(led->regmap, led->regs->ctrl, &val);
> >> +	if (ret < 0) {
> >> +		dev_err(cdev->dev, "Failed to read LED CTRL reg: %d\n", ret);
> >> +		ret = LED_OFF;
> > 
> > 
> > include/linux/leds.h:
> > 
> > /* This is obsolete/useless. We now support variable maximum brightness. */
> > enum led_brightness {
> >    LED_OFF         = 0,
> >    LED_ON          = 1,
> >    LED_HALF        = 127,
> >    LED_FULL        = 255,
> > };
> 
> I know but LED_OFF is still somewhat useful, it makes it
> clear that wat is being returned is a brightness value
> where as "ret = 0" reads like returning success.
> 
> With that said if you prefer 0/1 over LED_OFF / LED_ON
> I'm happy to replace them all ?

This is probably for Pavel to answer.

Ideally it'll either be:

 "still useful and thus not deprecated"

Or:

 "deprecated and therefore must not be used"

I'm less happy with a deprecated but still okay to use limbo-land.

[...]

> >> +static void cht_wc_led_restore_regs(struct cht_wc_led *led,
> >> +				    const struct cht_wc_led_saved_regs *saved_regs)
> >> +{
> >> +	regmap_write(led->regmap, led->regs->ctrl, saved_regs->ctrl);
> >> +	regmap_write(led->regmap, led->regs->fsm, saved_regs->fsm);
> >> +	regmap_write(led->regmap, led->regs->pwm, saved_regs->pwm);
> >> +}
> >> +
> >> +static int cht_wc_leds_probe(struct platform_device *pdev)
> >> +{
> >> +	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
> > 
> > platform_*()
> 
> This is getting the parent's driver data so platform_get_drvdata()
> can not be used here.

Fair point.

> >> +	struct cht_wc_leds *leds;
> >> +	int ret;
> >> +	int i;
> >> +
> >> +	leds = devm_kzalloc(&pdev->dev, sizeof(*leds), GFP_KERNEL);
> >> +	if (!leds)
> >> +		return -ENOMEM;
> >> +
> >> +	/*
> >> +	 * LED1 might be in hw-controlled mode when this driver gets loaded; and
> >> +	 * since the PMIC is always powered by the battery any changes made are
> >> +	 * permanent. Save LED1 regs to restore them on remove() or shutdown().
> >> +	 */
> >> +	leds->leds[0].regs = &cht_wc_led_regs[0];
> >> +	leds->leds[0].regmap = pmic->regmap;
> >> +	ret = cht_wc_led_save_regs(&leds->leds[0], &leds->led1_initial_regs);
> >> +	if (ret < 0)
> >> +		return ret;
> >> +
> >> +	for (i = 0; i < CHT_WC_LED_COUNT; i++) {
> >> +		struct cht_wc_led *led = &leds->leds[i];
> >> +
> >> +		led->regs = &cht_wc_led_regs[i];
> >> +		led->regmap = pmic->regmap;
> >> +		mutex_init(&led->mutex);
> >> +		led->cdev.name = cht_wc_leds_names[i];
> >> +		led->cdev.brightness_set_blocking = cht_wc_leds_brightness_set;
> >> +		led->cdev.brightness_get = cht_wc_leds_brightness_get;
> >> +		led->cdev.blink_set = cht_wc_leds_blink_set;
> >> +		led->cdev.max_brightness = 255;
> >> +
> >> +		ret = led_classdev_register(&pdev->dev, &led->cdev);
> >> +		if (ret < 0)
> >> +			return ret;
> >> +	}
> >> +
> >> +	platform_set_drvdata(pdev, leds);
> >> +	return 0;
> >> +}
> >> +
> >> +static void cht_wc_leds_remove(struct platform_device *pdev)
> >> +{
> >> +	struct cht_wc_leds *leds = platform_get_drvdata(pdev);
> >> +	int i;
> >> +
> >> +	for (i = 0; i < CHT_WC_LED_COUNT; i++)
> >> +		led_classdev_unregister(&leds->leds[i].cdev);
> >> +
> >> +	/* Restore LED1 regs if hw-control was active, else leave LED1 off. */
> > 
> > Either use full-stops, or don't.  Please be consistent.
> 
> I added the full-stop here because there is a ',' in the comment, I'll drop it.

Please apply this review comment widely, not just for this one line.

[...]

> >> +static struct platform_driver cht_wc_leds_driver = {
> >> +	.probe = cht_wc_leds_probe,
> >> +	.remove_new = cht_wc_leds_remove,
> > 
> > This is new to me.  What does remove_new do?
> > 
> > Just returns void?
> 
> Yes all the platform_device remove callbacks are being moved over to this which
> indeed returns void.

Thanks.

-- 
Lee Jones [李琼斯]



[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux