Re: [PATCH v2] leds: pwm: add support for default-state device property

From: Denis Osterland-Heim
Date: Tue Mar 10 2020 - 11:19:21 EST


Hi,

should be
In-Reply-To: <20200309082218.13263-1-Denis.Osterland@xxxxxxxxx>
instead of
Reply-To: <20200309082218.13263-1-Denis.Osterland@xxxxxxxxx>

Sorry

Am Dienstag, den 10.03.2020, 13:47 +0100 schrieb Denis Osterland-Heim:
> This patch adds support for "default-state" devicetree property, which
> allows to defer pwm init to first use of led.
>
> This allows to configure the PWM early in bootloader to let the LED
> blink until an application in Linux userspace set something different.
>
> Signed-off-by: Denis Osterland-Heim <Denis.Osterland@xxxxxxxxx>
> ---
> v1->v2:
> - use default-state = "keep", as suggested by Jacek Anaszewski
> - calc initial brightness with PWM state from device
>
> .../devicetree/bindings/leds/leds-pwm.txt | 2 ++
> drivers/leds/leds-pwm.c | 33 +++++++++++++++++--
> include/linux/leds_pwm.h | 1 +
> 3 files changed, 33 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/leds/leds-pwm.txt b/Documentation/devicetree/bindings/leds/leds-pwm.txt
> index 6c6583c35f2f..d0f489680594 100644
> --- a/Documentation/devicetree/bindings/leds/leds-pwm.txt
> +++ b/Documentation/devicetree/bindings/leds/leds-pwm.txt
> @@ -19,6 +19,8 @@ LED sub-node properties:
> see Documentation/devicetree/bindings/leds/common.txt
> - linux,default-trigger : (optional)
> see Documentation/devicetree/bindings/leds/common.txt
> +- default-state : (optional)
> + see Documentation/devicetree/bindings/leds/common.yaml
>
> Example:
>
> diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
> index 8b6965a563e9..92726c2e43ba 100644
> --- a/drivers/leds/leds-pwm.c
> +++ b/drivers/leds/leds-pwm.c
> @@ -75,7 +75,8 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
> led_data->active_low = led->active_low;
> led_data->cdev.name = led->name;
> led_data->cdev.default_trigger = led->default_trigger;
> - led_data->cdev.brightness = LED_OFF;
> + ret = led->default_state == LEDS_GPIO_DEFSTATE_ON;
> + led_data->cdev.brightness = ret ? led->max_brightness : LED_OFF;
> led_data->cdev.max_brightness = led->max_brightness;
> led_data->cdev.flags = LED_CORE_SUSPENDRESUME;
>
> @@ -97,7 +98,8 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
> * FIXME: pwm_apply_args() should be removed when switching to the
> * atomic PWM API.
> */
> - pwm_apply_args(led_data->pwm);
> + if (led->default_state != LEDS_GPIO_DEFSTATE_KEEP)
> + pwm_apply_args(led_data->pwm);
>
> pwm_get_args(led_data->pwm, &pargs);
>
> @@ -105,10 +107,23 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
> if (!led_data->period && (led->pwm_period_ns > 0))
> led_data->period = led->pwm_period_ns;
>
> + if (led->default_state == LEDS_GPIO_DEFSTATE_KEEP) {
> + uint64_t brightness;
> + struct pwm_device *pwm = led_data->pwm;
> + struct pwm_state state;
> +
> + pwm->chip->ops->get_state(pwm->chip, pwm, &state);
> + brightness = led->max_brightness * state.duty_cycle;
> + do_div(brightness, state.period);
> + led_data->cdev.brightness = (enum led_brightness)brightness;
> + }
> +
> ret = devm_led_classdev_register(dev, &led_data->cdev);
> if (ret == 0) {
> priv->num_leds++;
> - led_pwm_set(&led_data->cdev, led_data->cdev.brightness);
> + if (led->default_state != LEDS_GPIO_DEFSTATE_KEEP)
> + led_pwm_set(&led_data->cdev,
> + led_data->cdev.brightness);
> } else {
> dev_err(dev, "failed to register PWM led for %s: %d\n",
> led->name, ret);
> @@ -126,6 +141,8 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
> memset(&led, 0, sizeof(led));
>
> device_for_each_child_node(dev, fwnode) {
> + const char *state = NULL;
> +
> ret = fwnode_property_read_string(fwnode, "label", &led.name);
> if (ret && is_of_node(fwnode))
> led.name = to_of_node(fwnode)->name;
> @@ -143,6 +160,16 @@ static int led_pwm_create_fwnode(struct device *dev, struct led_pwm_priv *priv)
> fwnode_property_read_u32(fwnode, "max-brightness",
> &led.max_brightness);
>
> + if (!fwnode_property_read_string(fwnode, "default-state",
> + &state)) {
> + if (!strcmp(state, "keep"))
> + led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
> + else if (!strcmp(state, "on"))
> + led.default_state = LEDS_GPIO_DEFSTATE_ON;
> + else
> + led.default_state = LEDS_GPIO_DEFSTATE_OFF;
> + }
> +
> ret = led_pwm_add(dev, priv, &led, fwnode);
> if (ret) {
> fwnode_handle_put(fwnode);
> diff --git a/include/linux/leds_pwm.h b/include/linux/leds_pwm.h
> index 93d101d28943..c9ef9012913d 100644
> --- a/include/linux/leds_pwm.h
> +++ b/include/linux/leds_pwm.h
> @@ -10,6 +10,7 @@ struct led_pwm {
> const char *default_trigger;
> unsigned pwm_id __deprecated;
> u8 active_low;
> + u8 default_state;
> unsigned max_brightness;
> unsigned pwm_period_ns;
> };


Diehl Connectivity Solutions GmbH
GeschÃftsfÃhrung: Horst Leonberger
Sitz der Gesellschaft: NÃrnberg - Registergericht: Amtsgericht
NÃrnberg: HRB 32315
___________________________________________________________________________________________________

Der Inhalt der vorstehenden E-Mail ist nicht rechtlich bindend. Diese E-Mail enthaelt vertrauliche und/oder rechtlich geschuetzte Informationen.
Informieren Sie uns bitte, wenn Sie diese E-Mail faelschlicherweise erhalten haben. Bitte loeschen Sie in diesem Fall die Nachricht.
Jede unerlaubte Form der Reproduktion, Bekanntgabe, Aenderung, Verteilung und/oder Publikation dieser E-Mail ist strengstens untersagt.
- Informationen zum Datenschutz, insbesondere zu Ihren Rechten, erhalten Sie unter https://www.diehl.com/group/de/transparenz-und-informationspflichten/

The contents of the above mentioned e-mail is not legally binding. This e-mail contains confidential and/or legally protected information. Please inform us if you have received this e-mail by
mistake and delete it in such a case. Each unauthorized reproduction, disclosure, alteration, distribution and/or publication of this e-mail is strictly prohibited.
- For general information on data protection and your respective rights please visit https://www.diehl.com/group/en/transparency-and-information-obligations/