From patchwork Tue Mar 10 12:47:03 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: 1252161 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=devicetree-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=diehl.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=diehl.com header.i=@diehl.com header.a=rsa-sha256 header.s=default header.b=HI4fouM3; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48cGJt2x6kzB41F for ; Wed, 11 Mar 2020 00:34:06 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728631AbgCJNeA (ORCPT ); Tue, 10 Mar 2020 09:34:00 -0400 Received: from enterprise01.smtp.diehl.com ([193.201.238.219]:55608 "EHLO enterprise01.smtp.diehl.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727560AbgCJMrK (ORCPT ); Tue, 10 Mar 2020 08:47:10 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=diehl.com; i=@diehl.com; q=dns/txt; s=default; t=1583844429; x=1615380429; h=from:to:cc:subject:date:message-id:reply-to: content-transfer-encoding:mime-version; bh=vJMUNeqDMsTha7ppeHbqyximHbM6DIWnSoKrK5grZ1I=; b=HI4fouM3osPsipuSsDRORHWMBkCeo5sru6keNAtqcJm2+IplX2APbBn4 ETbQXy8igc6H6q52eh0c5Q34ByM/N2/PlafESucJWCfI0d4w7vYm6Y6o2 GoktJzCgv/plND2Nak/xQGp7GMUdUXT/CADJTf4sg/8FRfB8WPgdVygCg Fp0eOXO7j9t9dBySwEs2cvc5RscGnzfaAUexsUvA3fX5ryFKWDMNgLvYz F1xuVm3Jrhn8oMiWym49xznpd/ovrvS5Z/rG3qFnNHSaX2V9+tFUwp7ra 4B/gbYBLQlqAgcmLgXhhvRGbwsnLPSGgx+qu/1F+WzFoU7EVEFNglbqxd w==; IronPort-SDR: HJKi4lh+OgEVnpq5+7C8qWg2DW7WiNTN9D7ZiCg5AttouSI2wgSKdTlbxC7drEZyQaa1l7rfCD /FSbIuI8n7Sw== 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 v2] leds: pwm: add support for default-state device property Thread-Topic: [PATCH v2] leds: pwm: add support for default-state device property Thread-Index: AQHV9tn/0ZJlTn83ZkK/QE6qVZtMDw== Date: Tue, 10 Mar 2020 12:47:03 +0000 Message-ID: <20200310123126.4709-1-Denis.Osterland@diehl.com> Reply-To: "20200309082218.13263-1-Denis.Osterland@diehl.com" <20200309082218.13263-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: byQFdw3ukCM+zy1/poiPc/AZUMLuadj5bOamS2OKQu8jauJJNj7A4I2WQ4sGAD2T Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@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 set something different. Signed-off-by: Denis Osterland-Heim --- 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; };