From patchwork Mon Mar 16 12:53:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis OSTERLAND-HEIM X-Patchwork-Id: 209141 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.1 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_2 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4BC22C0044D for ; Mon, 16 Mar 2020 12:54:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2537720719 for ; Mon, 16 Mar 2020 12:54:16 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=diehl.com header.i=@diehl.com header.b="OnmS4CBr" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731075AbgCPMyF (ORCPT ); Mon, 16 Mar 2020 08:54:05 -0400 Received: from enterprise01.smtp.diehl.com ([193.201.238.219]:15522 "EHLO enterprise01.smtp.diehl.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731023AbgCPMyE (ORCPT ); Mon, 16 Mar 2020 08:54:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=diehl.com; i=@diehl.com; q=dns/txt; s=default; t=1584363243; x=1615899243; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=ER2QqLcezibDMSXGEObfIVVmWurWCCq2yGT0KmuLoQ0=; b=OnmS4CBrLk9Ua2vXBRBJmnt3lAkWq3DWJbrjtv/Y+oJpJh+qWgw5j1MI Sz27jFNcs6YdkSrdhhKoa/JU0bYDPvy2yqFde0gPq0Eu6hvG295opQtHb yY0OX1nxhzIZKDGjHr34mBYsFiEcY/I+ZykEyD76Llbd5jPSErj+ECmtd suVdkwYi80y/kQQlt9ra8pXihEV2lx5tteJrGuwj4AK7EHhFigZjQrfGV 9x8XjhaxJ/IdiqoKOvwlOU4HbUPmSFVZRbEEA+OjkO7kg+5zGJBji8jN4 aSXMcTPQn+eMWUF5B5RgDmKYlZWDQNkG3Kqp4v8bHQk5LzXaQwmMWHszS g==; IronPort-SDR: NiPyy0izlDW5CsecNNrAyuLfm5QQKAlYX6OuB5Y4F0oSILp78ExVKpsVGHhExBJHxOOibUkyRw GcWvSuZL2Mdg== From: Denis Osterland-Heim To: "dmurphy@ti.com" , "pavel@ucw.cz" , "mark.rutland@arm.com" , "jacek.anaszewski@gmail.com" , "robh+dt@kernel.org" CC: "linux-kernel@vger.kernel.org" , "Denis Osterland-Heim" , "linux-leds@vger.kernel.org" , "devicetree@vger.kernel.org" Subject: [PATCH v3 2/3] leds: pwm: add support for default-state device property Thread-Topic: [PATCH v3 2/3] leds: pwm: add support for default-state device property Thread-Index: AQHV+5H21uxgWjW9wEe6B/TzHpI38w== Date: Mon, 16 Mar 2020 12:53:59 +0000 Message-ID: <20200316124851.6303-3-Denis.Osterland@diehl.com> References: <20200316124851.6303-1-Denis.Osterland@diehl.com> In-Reply-To: <20200316124851.6303-1-Denis.Osterland@diehl.com> Accept-Language: de-DE, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: Evolution 3.28.5-0ubuntu0.18.04.1 x-ms-exchange-messagesentrepresentingtype: 1 MIME-Version: 1.0 X-TrailerSkip: 1 X-GBS-PROC: 415AWy8o668fDtCxszluz0usJCarfP6B29so9zGpOBCP3VvdIGTGcW31xNRj+VSU Sender: linux-leds-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org 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 --- 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 #include +#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);