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 sets something different. Signed-off-by: Denis Osterland-Heim <Denis.Osterland@xxxxxxxxx> --- drivers/leds/leds-pwm.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 5f69b6571595..fce7969e7918 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -18,11 +18,16 @@ #include <linux/pwm.h> #include <linux/slab.h> +#define LEDS_PWM_DEFSTATE_OFF 0 +#define LEDS_PWM_DEFSTATE_ON 1 +#define LEDS_PWM_DEFSTATE_KEEP 2 + struct led_pwm { const char *name; const char *default_trigger; unsigned int pwm_id __deprecated; u8 active_low; + u8 default_state; unsigned int max_brightness; unsigned int pwm_period_ns; }; @@ -72,7 +77,6 @@ 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; led_data->cdev.max_brightness = led->max_brightness; led_data->cdev.flags = LED_CORE_SUSPENDRESUME; @@ -92,13 +96,27 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, pwm_init_state(led_data->pwm, &led_data->pwmstate); + if (led->default_state == LEDS_PWM_DEFSTATE_ON) + led_data->cdev.brightness = led->max_brightness; + else if (led->default_state == LEDS_PWM_DEFSTATE_KEEP) { + uint64_t brightness; + + pwm_get_state(led_data->pwm, &led_data->pwmstate); + brightness = led->max_brightness; + brightness *= led_data->pwmstate.duty_cycle; + do_div(brightness, led_data->pwmstate.period); + led_data->cdev.brightness = (enum led_brightness)brightness; + } + if (!led_data->pwmstate.period) led_data->pwmstate.period = led->pwm_period_ns; 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_PWM_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); @@ -116,6 +134,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; @@ -133,6 +153,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_PWM_DEFSTATE_KEEP; + else if (!strcmp(state, "on")) + led.default_state = LEDS_PWM_DEFSTATE_ON; + else + led.default_state = LEDS_PWM_DEFSTATE_OFF; + } + ret = led_pwm_add(dev, priv, &led, fwnode); if (ret) { fwnode_handle_put(fwnode); -- 2.25.1 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/