Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp427554pxf; Wed, 7 Apr 2021 03:04:46 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw1Q8J5rNgmsg2hdz7D6/CSfuX84QlT3165O90nWUE2DRZXLfgvs644b7iWRGX3d9bV8Dp6 X-Received: by 2002:a17:906:4c91:: with SMTP id q17mr2864387eju.0.1617789886047; Wed, 07 Apr 2021 03:04:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617789886; cv=none; d=google.com; s=arc-20160816; b=YXTSabS8Nw1/G14czxeF9IdHXvVCQDow0i5qrRCiyjAKDfb19gT0Y1SU6QyQJ9lhQa v+Js4EQgFxRNpSW8KlxuxdfPe4PSp4VaHquLBNz0KKWZbiuRafGOg7W5Ysfb/DMN0u/t rs12sHLbPO6EuoMfTRnkn/kSrSH1Dt3S4B8FXR5DZ720shsocf092UsqmNBzKSNmSdEt +oUjaOWuiSdAMFxypKWmPAWBbhkHpvig7tMIGnO/6rrp4zYErMOA/Jpfgx16hm637Bzf Smm5nQBBZVd4VcKGm3lw45x/wRYu7/eidEuwIKN2mWKJ43wu6LEMCoxDYtMc6taesvZP OYgg== 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=TF4X370n3fRovCG7RRBaZoUbB28YXxXjdTqhvmgeoVc=; b=BBxqDH9Z8HLMWmxpEAeuUPjmYmQyNTqX8lAHifo5irlOFc9Zopm+I95xOnYX0452+G sKxf8X/tdq28iQH7ZNCKfDL4ulzGwBbyxmsjrrLL1ElEf7pI2OfIGpQhvB43LQaRoUHP +Etp+9KRpqkBCQsoywhIX8ysosHC8LsxGZJmoULsobIem+sq1QkF8qCbhrKQ7bR4rd2J 4gCi+FMZgn+sMBXeXPyspO292g0SFMMvxthls/5Yq/9GQObYLxHk9xKuws60lOOKezEi RgliFBEPwX3gT87xTwU/ACM8yo1l9y6K3RlnTaT1tyq/Ubcdimhk0NKNL3+Is6Lex1Lt 4u1w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@pqgruber.com header.s=mail header.b=DSoEtnmK; 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 t4si18213473ejs.517.2021.04.07.03.04.16; Wed, 07 Apr 2021 03:04:46 -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=DSoEtnmK; 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 S1346544AbhDFQnj (ORCPT + 99 others); Tue, 6 Apr 2021 12:43:39 -0400 Received: from mail.pqgruber.com ([52.59.78.55]:56080 "EHLO mail.pqgruber.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346542AbhDFQng (ORCPT ); Tue, 6 Apr 2021 12:43:36 -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 C9C95C6B19D; Tue, 6 Apr 2021 18:43:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pqgruber.com; s=mail; t=1617727407; bh=TF4X370n3fRovCG7RRBaZoUbB28YXxXjdTqhvmgeoVc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DSoEtnmKA/4KfOfLhMZBTiQQVp4eHN7wKnWRyHItI0TMkytB6Gi7axeXRRwJ7T3Cz cXiRg1wVRgWnM7JUbVHNenspttXy6jWHuS6OXgeUnJenme+D4ytxCvkbP1LJ2Kl61W zbFshIBS6Gql9scSYeWr9wlfuluTlkODxnryPCKM= 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 v7 2/8] pwm: pca9685: Support hardware readout Date: Tue, 6 Apr 2021 18:41:34 +0200 Message-Id: <20210406164140.81423-2-clemens.gruber@pqgruber.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210406164140.81423-1-clemens.gruber@pqgruber.com> References: <20210406164140.81423-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 Implements .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 v6: - Added a comment regarding the division (Suggested by Uwe) - Rebased drivers/pwm/pwm-pca9685.c | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/pwm/pwm-pca9685.c b/drivers/pwm/pwm-pca9685.c index 5a2ce97e71fd..d4474c5ff96f 100644 --- a/drivers/pwm/pwm-pca9685.c +++ b/drivers/pwm/pwm-pca9685.c @@ -333,6 +333,51 @@ 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; + } + + duty = pca9685_pwm_get_duty(pca, pwm->hwpwm); + + state->enabled = !!duty; + if (!state->enabled) { + state->duty_cycle = 0; + return; + } else if (duty == PCA9685_COUNTER_RANGE) { + state->duty_cycle = state->period; + return; + } + + duty *= state->period; + state->duty_cycle = duty / PCA9685_COUNTER_RANGE; +} + static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { struct pca9685 *pca = to_pca(chip); @@ -355,6 +400,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