Received: by 2002:a05:6a10:17d3:0:0:0:0 with SMTP id hz19csp726115pxb; Thu, 15 Apr 2021 05:16:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJybbh7y/1y6k59HVKGWMq231h7oe47Qiu7QwsEohpXA7Net8ju5pbQsklTiwk1yLrlsTIV2 X-Received: by 2002:a63:ad42:: with SMTP id y2mr1347306pgo.187.1618488969251; Thu, 15 Apr 2021 05:16:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1618488969; cv=none; d=google.com; s=arc-20160816; b=jtXMNHBqSZRiWZvMiPkkZUL7G6C0Go1MnPA/JI7knFMlrYr7Anwrbo6zQ+qZ5NKEUn ANLm/mcKY9PgxRw82UQ0e99KZ9Qw/VuJd+XsiSqE63AftxRrzIqz8NR3/9YKtdwJzlyR mX9MOGB6vZwWmvxSDJ2d7nUcO1r3y8uVF/Wzhj5msNCIhA3Hi1dogoT3OnqI3Jqyvp5d 3TUWiWzi2RqvFFXghwVfHueteaeJfWoVv+62MgxPyuFaKjZtdrJWN1y7Grx09B6RFLR+ EATDZhJPYxArAqyvhETlZx/vkR7hz6nMQ/HiPkdxuPhxu0TRQ4wf0F9oiuatc6mTTTOO Xm1Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=06ZRhpbZxpxadONy0rq3gW+vmEz9TQ24K/L4VxJp+H4=; b=Zd2NTy50JieVo6SwnR9EgPmX/Fp/vDVtXFnccztd3Fkr4wY6pVwIG8Cn1wrWWpfS0x iIMCh+kPfRYORUZB3nDnz3Ru8qYyCpAQkY1NSNJf6MTMg7eB1sdhxJQETC/xFAx+2IYy sgP94nH9EdUSD8+FN7Gs7PA8e7Ov5ZFju16i4rUe8uFIQLJNkGx89Y4B4osCWdbCltfY bRnwMYUzl1tmKFUvFzrzo7RZ5zrNix/4VB+5yPKbGRfs0LVXOrcOUCl0JHb+roDBU3AZ fvOO0TmMwlmUlZH391qUrrxkqN+qkWawNTUoeYE9GzNvODzQApZfqAPmWq/c9k9UmgCY rJbQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@pqgruber.com header.s=mail header.b=qaALg2Q1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=NONE dis=NONE) header.from=pqgruber.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id l64si1173765pge.326.2021.04.15.05.15.56; Thu, 15 Apr 2021 05:16:09 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@pqgruber.com header.s=mail header.b=qaALg2Q1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=NONE dis=NONE) header.from=pqgruber.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232756AbhDOMPo (ORCPT + 99 others); Thu, 15 Apr 2021 08:15:44 -0400 Received: from mail.pqgruber.com ([52.59.78.55]:34760 "EHLO mail.pqgruber.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231590AbhDOMPl (ORCPT ); Thu, 15 Apr 2021 08:15:41 -0400 Received: from workstation.tuxnet (213-47-165-233.cable.dynamic.surfer.at [213.47.165.233]) by mail.pqgruber.com (Postfix) with ESMTPSA id A46EDC725D8; Thu, 15 Apr 2021 14:15:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pqgruber.com; s=mail; t=1618488916; bh=06ZRhpbZxpxadONy0rq3gW+vmEz9TQ24K/L4VxJp+H4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qaALg2Q1xoIuc8ukGjU9iwMA4OVX01EGXckf1uyZ4frUa6uAwkHgVu4IBDjuZOmFV Dq/TfmycpYnu0rxwQ9v7frA1Ayncve67HMfHoNiy6FRllB3+fhwqpNCwO6VwJzGFOG hO3kI2mlmULtTnL7wRXFDoukIs72oKjFzBFxWL4s= From: Clemens Gruber To: linux-pwm@vger.kernel.org Cc: Thierry Reding , Sven Van Asbroeck , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Clemens Gruber Subject: [PATCH v9 2/8] pwm: pca9685: Support hardware readout Date: Thu, 15 Apr 2021 14:14:49 +0200 Message-Id: <20210415121455.39536-2-clemens.gruber@pqgruber.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210415121455.39536-1-clemens.gruber@pqgruber.com> References: <20210415121455.39536-1-clemens.gruber@pqgruber.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement .get_state to read-out the current hardware state. The hardware readout may return slightly different values than those that were set in apply due to the limited range of possible prescale and counter register values. Also note that although the datasheet mentions 200 Hz as default frequency when using the internal 25 MHz oscillator, the calculated period from the default prescaler register setting of 30 is 5079040ns. Signed-off-by: Clemens Gruber --- Changes since v8: - As we left the math in apply as-is, use DIV_ROUND_DOWN in get_state Changes since v7: - Always return enabled=true for channels except "all LEDs" channel - Use DIV_ROUND_UP in .get_state Changes since v6: - Added a comment regarding the division (Suggested by Uwe) - Rebased drivers/pwm/pwm-pca9685.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index ea19d72e5c34..aa48c45bd294 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -331,6 +331,41 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return 0; } +static void pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, + struct pwm_state *state) +{ + struct pca9685 *pca = to_pca(chip); + unsigned long long duty; + unsigned int val = 0; + + /* Calculate (chip-wide) period from prescale value */ + regmap_read(pca->regmap, PCA9685_PRESCALE, &val); + /* + * PCA9685_OSC_CLOCK_MHZ is 25, i.e. an integer divider of 1000. + * The following calculation is therefore only a multiplication + * and we are not losing precision. + */ + state->period = (PCA9685_COUNTER_RANGE * 1000 / PCA9685_OSC_CLOCK_MHZ) * + (val + 1); + + /* The (per-channel) polarity is fixed */ + state->polarity = PWM_POLARITY_NORMAL; + + if (pwm->hwpwm >= PCA9685_MAXCHAN) { + /* + * The "all LEDs" channel does not support HW readout + * Return 0 and disabled for backwards compatibility + */ + state->duty_cycle = 0; + state->enabled = false; + return; + } + + state->enabled = true; + duty = pca9685_pwm_get_duty(pca, pwm->hwpwm); + state->duty_cycle = DIV_ROUND_DOWN_ULL(duty * state->period, PCA9685_COUNTER_RANGE); +} + static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { struct pca9685 *pca = to_pca(chip); @@ -353,6 +388,7 @@ static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) static const struct pwm_ops pca9685_pwm_ops = { .apply = pca9685_pwm_apply, + .get_state = pca9685_pwm_get_state, .request = pca9685_pwm_request, .free = pca9685_pwm_free, .owner = THIS_MODULE, -- 2.31.1