From: Lee Jones <lee@kernel.org>
To: Christian Marangi <ansuelsmth@gmail.com>
Cc: Pavel Machek <pavel@ucw.cz>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Jacek Anaszewski <jacek.anaszewski@gmail.com>,
linux-leds@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v6 20/20] leds: leds-lp5569: Add support for Texas Instruments LP5569
Date: Thu, 20 Jun 2024 17:03:48 +0100 [thread overview]
Message-ID: <20240620160348.GO3029315@google.com> (raw)
In-Reply-To: <20240616215226.2112-21-ansuelsmth@gmail.com>
On Sun, 16 Jun 2024, Christian Marangi wrote:
> Add support for Texas Instruments LP5569 LED driver.
>
> Texas Instruments LP5569 is 9 channels chip with programmable engines.
>
> It almost a copy of LP5523 with fundamental changes to regs order and
> regs content.
>
> Has difference in how the clock is handled and doesn't support detecting
> clock time automatically, different handling for selftest and different
> scheme for the status regs.
>
> LED chip supports ENGINE and MUX to group LED and run precompiled code
> with magic values to run patterns. This is loaded via the sysfs entry
> and it's passed as a string of ASCII HEX char.
>
> One some devices using this LED Controller (a NBG7815 Router) it was
> found loading big precompiled pattern with up to 96 bytes of code. To
> have support for this "extended" scenario, hardcode each engine to
> support 4 pages of precompiled pattern (128 bytes of code) and 1 page
> for each MUX. This gives plenty of space for any kind precompiled
> pattern keeping simple logic for page handling of each engine and mux.
>
> Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
> ---
> drivers/leds/Kconfig | 16 +-
> drivers/leds/Makefile | 1 +
> drivers/leds/leds-lp5569.c | 542 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 556 insertions(+), 3 deletions(-)
> create mode 100644 drivers/leds/leds-lp5569.c
Pretty good, just a couple of tiny nits.
[...]
> +static ssize_t lp5569_led_short_test(struct lp55xx_led *led, char *buf)
> +{
> + struct lp55xx_chip *chip = led->chip;
> + struct lp55xx_platform_data *pdata = chip->pdata;
> + bool leds_fault[LP5569_MAX_LEDS];
> + struct lp55xx_led *led_tmp = led;
> + int i, ret, pos = 0;
> + u8 status;
> +
> + /* Set in STANDBY state */
> + ret = lp55xx_write(chip, LP5569_REG_ENABLE, 0);
> + if (ret)
> + goto exit;
> +
> + /* Wait 1ms for device to enter STANDBY state */
> + usleep_range(1000, 2000);
> +
> + /* Set Charge Pump to 1x */
> + ret = lp55xx_update_bits(chip, LP5569_REG_MISC,
> + FIELD_PREP(LP5569_CP_MODE_MASK, LP55XX_CP_BYPASS),
> + LP5569_CP_MODE_MASK);
> + if (ret)
> + goto exit;
> +
> + /* Enable LED and set to 100% brightness and current to 100% (25.5mA) */
> + for (i = 0; i < pdata->num_channels; i++) {
> + ret = lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr,
> + LED_FULL);
> + if (ret)
> + goto exit;
> +
> + ret = lp55xx_write(chip, LP5569_REG_LED_CURRENT_BASE + led_tmp->chan_nr,
> + LED_FULL);
> + if (ret)
> + goto exit;
> +
> + led_tmp++;
> + }
> +
> + /* Put Device in NORMAL state */
> + ret = lp55xx_write(chip, LP5569_REG_ENABLE, LP5569_ENABLE);
> + if (ret)
> + goto exit;
> +
> + /* Wait 500 us for device to enter NORMAL state */
> + usleep_range(500, 750);
> +
> + /* Enable LED Shorted Test */
> + ret = lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_OPEN_TEST,
> + LP5569_LED_SHORT_TEST);
> + if (ret)
> + goto exit;
> +
> + /* Wait 500 us for device to fill status regs */
> + usleep_range(500, 750);
> +
> + /* Parse status led fault 1 regs */
> + ret = lp55xx_read(chip, LP5569_REG_LED_FAULT1, &status);
> + if (ret < 0)
> + goto exit;
> +
> + for (i = 0; i < 8; i++)
> + leds_fault[i] = !!LEDn_STATUS_FAULT(i, status);
> +
> + /* Parse status led fault 2 regs */
> + ret = lp55xx_read(chip, LP5569_REG_LED_FAULT2, &status);
> + if (ret < 0)
> + goto exit;
> +
> + for (i = 0; i < 1; i++)
> + leds_fault[i + 8] = !!LEDn_STATUS_FAULT(i, status);
> +
> + /* Report LED fault */
> + led_tmp = led;
> + for (i = 0; i < pdata->num_channels; i++) {
> + if (leds_fault[led_tmp->chan_nr])
> + pos += sprintf(buf + pos, "LED %d SHORTED FAIL\n",
> + led_tmp->chan_nr);
> +
> + led_tmp++;
> + }
> +
> + ret = pos;
> +
> +exit:
> + /* Disable LED Shorted Test */
> + lp55xx_update_bits(chip, LP5569_REG_MISC2, LP5569_LED_SHORT_TEST,
> + 0);
Nit: This line break seems unnecessary.
> +
> + led_tmp = led;
> + for (i = 0; i < pdata->num_channels; i++) {
> + lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led_tmp->chan_nr,
> + 0);
Nit: This too.
> +
> + led_tmp++;
> + }
> +
> + return ret;
> +}
> +
> +static ssize_t lp5569_selftest(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev));
> + struct lp55xx_chip *chip = led->chip;
> + int i, pos = 0;
> +
> + mutex_lock(&chip->lock);
> +
> + /* Test LED Open */
> + pos = lp5569_led_open_test(led, buf);
> + if (pos < 0)
> + goto fail;
> +
> + /* Test LED Shorted */
> + pos = lp5569_led_short_test(led, buf);
> + if (pos < 0)
> + goto fail;
> +
> + for (i = 0; i < chip->pdata->num_channels; i++) {
> + /* Restore current */
> + lp55xx_write(chip, LP5569_REG_LED_CURRENT_BASE + led->chan_nr,
> + led->led_current);
> +
> + /* Restore brightness */
> + lp55xx_write(chip, LP5569_REG_LED_PWM_BASE + led->chan_nr,
> + led->brightness);
> + led++;
> + }
> +
> + if (pos == 0)
> + pos = sprintf(buf, "OK\n");
> + goto release_lock;
> +fail:
> + pos = sprintf(buf, "FAIL\n");
> +
> +release_lock:
> + mutex_unlock(&chip->lock);
> +
> + return pos;
> +}
> +
> +LP55XX_DEV_ATTR_ENGINE_MODE(1);
> +LP55XX_DEV_ATTR_ENGINE_MODE(2);
> +LP55XX_DEV_ATTR_ENGINE_MODE(3);
> +LP55XX_DEV_ATTR_ENGINE_LEDS(1);
> +LP55XX_DEV_ATTR_ENGINE_LEDS(2);
> +LP55XX_DEV_ATTR_ENGINE_LEDS(3);
> +LP55XX_DEV_ATTR_ENGINE_LOAD(1);
> +LP55XX_DEV_ATTR_ENGINE_LOAD(2);
> +LP55XX_DEV_ATTR_ENGINE_LOAD(3);
> +static LP55XX_DEV_ATTR_RO(selftest, lp5569_selftest);
> +LP55XX_DEV_ATTR_MASTER_FADER(1);
> +LP55XX_DEV_ATTR_MASTER_FADER(2);
> +LP55XX_DEV_ATTR_MASTER_FADER(3);
> +static LP55XX_DEV_ATTR_RW(master_fader_leds, lp55xx_show_master_fader_leds,
> + lp55xx_store_master_fader_leds);
> +
> +static struct attribute *lp5569_attributes[] = {
> + &dev_attr_engine1_mode.attr,
> + &dev_attr_engine2_mode.attr,
> + &dev_attr_engine3_mode.attr,
> + &dev_attr_engine1_load.attr,
> + &dev_attr_engine2_load.attr,
> + &dev_attr_engine3_load.attr,
> + &dev_attr_engine1_leds.attr,
> + &dev_attr_engine2_leds.attr,
> + &dev_attr_engine3_leds.attr,
> + &dev_attr_selftest.attr,
> + &dev_attr_master_fader1.attr,
> + &dev_attr_master_fader2.attr,
> + &dev_attr_master_fader3.attr,
> + &dev_attr_master_fader_leds.attr,
> + NULL,
> +};
> +
> +static const struct attribute_group lp5569_group = {
> + .attrs = lp5569_attributes,
> +};
> +
> +/* Chip specific configurations */
> +static struct lp55xx_device_config lp5569_cfg = {
> + .reg_op_mode = {
> + .addr = LP5569_REG_OP_MODE,
> + .shift = LP5569_MODE_ENG_SHIFT,
> + },
> + .reg_exec = {
> + .addr = LP5569_REG_EXEC_CTRL,
> + .shift = LP5569_EXEC_ENG_SHIFT,
> + },
> + .reset = {
> + .addr = LP5569_REG_RESET,
> + .val = LP5569_RESET,
> + },
> + .enable = {
> + .addr = LP5569_REG_ENABLE,
> + .val = LP5569_ENABLE,
> + },
> + .prog_mem_base = {
> + .addr = LP5569_REG_PROG_MEM,
> + },
> + .reg_led_pwm_base = {
> + .addr = LP5569_REG_LED_PWM_BASE,
> + },
> + .reg_led_current_base = {
> + .addr = LP5569_REG_LED_CURRENT_BASE,
> + },
> + .pages_per_engine = LP5569_PAGES_PER_ENGINE,
> + .max_channel = LP5569_MAX_LEDS,
> + .post_init_device = lp5569_post_init_device,
> + .brightness_fn = lp55xx_led_brightness,
> + .multicolor_brightness_fn = lp55xx_multicolor_brightness,
> + .set_led_current = lp55xx_set_led_current,
> + .firmware_cb = lp55xx_firmware_loaded_cb,
> + .run_engine = lp5569_run_engine,
> + .dev_attr_group = &lp5569_group,
> +};
> +
> +static const struct i2c_device_id lp5569_id[] = {
> + { "lp5569", .driver_data = (kernel_ulong_t)&lp5569_cfg, },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, lp5569_id);
> +
> +static const struct of_device_id of_lp5569_leds_match[] = {
> + { .compatible = "ti,lp5569", .data = &lp5569_cfg, },
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, of_lp5569_leds_match);
> +
> +static struct i2c_driver lp5569_driver = {
> + .driver = {
> + .name = "lp5569x",
> + .of_match_table = of_lp5569_leds_match,
> + },
> + .probe = lp55xx_probe,
> + .remove = lp55xx_remove,
> + .id_table = lp5569_id,
> +};
> +
> +module_i2c_driver(lp5569_driver);
> +
> +MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
> +MODULE_DESCRIPTION("LP5569 LED engine");
> +MODULE_LICENSE("GPL");
> --
> 2.43.0
>
--
Lee Jones [李琼斯]
next prev parent reply other threads:[~2024-06-20 16:03 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-16 21:51 [PATCH v6 00/20] leds: leds-lp55xx: overhaul driver Christian Marangi
2024-06-16 21:52 ` [PATCH v6 01/20] dt-bindings: leds-lp55xx: limit pwr-sel property to ti,lp8501 Christian Marangi
2024-06-16 21:52 ` [PATCH v6 02/20] dt-bindings: leds-lp55xx: Add new ti,lp5569 compatible Christian Marangi
2024-06-16 21:52 ` [PATCH v6 03/20] leds: leds-lp55xx: generalize stop_all_engine OP Christian Marangi
2024-06-16 21:52 ` [PATCH v6 04/20] leds: leds-lp55xx: generalize probe/remove functions Christian Marangi
2024-06-20 15:38 ` Lee Jones
2024-06-16 21:52 ` [PATCH v6 05/20] leds: leds-lp55xx: generalize load_engine function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 06/20] leds: leds-lp55xx: generalize load_engine_and_select_page function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 07/20] leds: leds-lp55xx: generalize run_engine function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 08/20] leds: leds-lp55xx: generalize update_program_memory function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 09/20] leds: leds-lp55xx: generalize firmware_loaded function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 10/20] leds: leds-lp55xx: generalize led_brightness function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 11/20] leds: leds-lp55xx: generalize multicolor_brightness function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 12/20] leds: leds-lp55xx: generalize set_led_current function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 13/20] leds: leds-lp55xx: generalize turn_off_channels function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 14/20] leds: leds-lp55xx: generalize stop_engine function Christian Marangi
2024-06-16 21:52 ` [PATCH v6 15/20] leds: leds-lp55xx: generalize sysfs engine_load and engine_mode Christian Marangi
2024-06-16 21:52 ` [PATCH v6 16/20] leds: leds-lp55xx: generalize sysfs engine_leds Christian Marangi
2024-06-16 21:52 ` [PATCH v6 17/20] leds: leds-lp55xx: generalize sysfs master_fader Christian Marangi
2024-06-16 21:52 ` [PATCH v6 18/20] leds: leds-lp55xx: support ENGINE program up to 128 bytes Christian Marangi
2024-06-16 21:52 ` [PATCH v6 19/20] leds: leds-lp55xx: drop deprecated defines Christian Marangi
2024-06-16 21:52 ` [PATCH v6 20/20] leds: leds-lp5569: Add support for Texas Instruments LP5569 Christian Marangi
2024-06-20 16:03 ` Lee Jones [this message]
2024-06-20 16:09 ` [PATCH v6 00/20] leds: leds-lp55xx: overhaul driver Lee Jones
2024-06-20 15:15 ` Christian Marangi
2024-06-20 16:57 ` Lee Jones
2024-06-20 16:49 ` Lee Jones
2024-06-20 15:57 ` Christian Marangi
2024-06-20 17:30 ` Lee Jones
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=20240620160348.GO3029315@google.com \
--to=lee@kernel.org \
--cc=ansuelsmth@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=jacek.anaszewski@gmail.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=pavel@ucw.cz \
--cc=robh@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).