Received: by 2002:ab2:7855:0:b0:1f9:5764:f03e with SMTP id m21csp583784lqp; Wed, 22 May 2024 13:06:14 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCU0RWcENUnVp3lQBpdqXve8VZs+P8Uz28HncPchP63x3ppG2A7iiwB01Ij2BnmQAT3TLdLuOFCa2Un2wMzQt5jM9Q5QmH9xHTOSNRq7Rw== X-Google-Smtp-Source: AGHT+IFmY2d5sZz1RPLQ345LeFiCDwdGtDciSXLpMADXUoB120h+keErQPnF8WUa0uWhwXDWcYAr X-Received: by 2002:a05:6402:11c6:b0:578:34f8:cc04 with SMTP id 4fb4d7f45d1cf-57834f8cc0amr2875178a12.4.1716408374393; Wed, 22 May 2024 13:06:14 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1716408374; cv=pass; d=google.com; s=arc-20160816; b=ABuNTiIxRcPbnwVKKcVz/74VG0kn376xVYqcewgu+a2HkGEyvZOj6CBJIRxfubClip odlGfvd6FPzIZUBYi7gUEYmt4WLO/O+BrDp/YzKIBNkKBrDkEo+ux7u/jNncP9fl98mh MtSKUEwwneR/Rm4tgQgS1oVRCzvN9ToGeES1PLo1pMXHFkKprpo9E0m78BnNXB7Wh55J 23bq0VvazOFcsJ5+0B7aTkc2vsly58SFwWrs/bXEv4nEEEDDFYJIZ55TvbFLwLTUwxTO U3UT53+765EiMiNwHruEiwWWabL6h+vaUDFnNFTgOwESp1WPg5OzxgQ3jBfHhCggM4Df 7GWQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:date:message-id:dkim-signature; bh=Dd7GrKK6qrVpweRGgoT/fw8t7w7OjlAlF8Ebyefp99A=; fh=1U/K3QKgwHBQs4ja0jEBeHMQJ8Nq8NJ7U1a0UlJA2N4=; b=uAOCdpe9X3KP6hNNCLN6O1fudxJBz5BozEjRKGS6XIX0a0n1EkRM7P1yoiWHotTCl2 CygaaxD9ZEhFfyJ36tzsk/cpq8FgA2erwBuRrsb3J+7ZFwMiSdbhzE2FfRylsTrQ7tHb ZE5LoVR0kbrlWsE63E8lV7Zc154VHx40zywf0bAx/6eShsxaNwckq7QTo+m/3u4kZtgU 4kWvLZp6z9J00Xt2XO4GWGSsHMFF40Xcd3KwFGUKkGgKm3KPPKLY7Qq19oPBljplGFEX XORTAyHVBMoojyJfNvmKNmuXbyHsdCCaZvO6d/HF5/l280cpfnnFVMvRTJ71aKYSgOKi 30GQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@baylibre-com.20230601.gappssmtp.com header.s=20230601 header.b=HkZa7hGc; arc=pass (i=1 spf=pass spfdomain=baylibre.com dkim=pass dkdomain=baylibre-com.20230601.gappssmtp.com); spf=pass (google.com: domain of linux-kernel+bounces-186688-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-186688-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id 4fb4d7f45d1cf-574f9fdddd6si8965987a12.71.2024.05.22.13.06.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 May 2024 13:06:14 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-186688-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20230601.gappssmtp.com header.s=20230601 header.b=HkZa7hGc; arc=pass (i=1 spf=pass spfdomain=baylibre.com dkim=pass dkdomain=baylibre-com.20230601.gappssmtp.com); spf=pass (google.com: domain of linux-kernel+bounces-186688-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-186688-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id EC0D21F2210E for ; Wed, 22 May 2024 20:06:13 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7EADE145B3B; Wed, 22 May 2024 20:06:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="HkZa7hGc" Received: from mail-qk1-f180.google.com (mail-qk1-f180.google.com [209.85.222.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 111CD78C9D for ; Wed, 22 May 2024 20:06:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.180 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716408367; cv=none; b=qYK+VM+cB18GXL/xcImZOPQKzZb00X14Lj5fDVgYb0cIN7kBTThJi3sNTVc1pwxNf4hzDqJOJGvFbND1YA8EZzEY/b4dgr2GfmwVrQkzHzhtU3m+YyugadAzXqQHX9M2gG1gs9UyYgCHXrAYR0y/KgaDaMVjLAAn4QbNK6CPMUU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716408367; c=relaxed/simple; bh=zkCJWYYFlcj5D3tT+xTyw8Pg3kAf4fTMTuu0pKc9aJE=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=qlkWOnIzLKafYWcMdf+ozy+MI0UoMOyDZkNKdbCzXHPlAb22seGnIk9mRA/3NtI73RIG5x5wirqE6vItXgh40ym92eteqgrd+kaCBgo2OYpm98FcO2OZ8ICCcCRotUyA1axTAZEaXV/ZHEXo0GiZU7P8ZGFj59Ar4/5s5bCJSdY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=HkZa7hGc; arc=none smtp.client-ip=209.85.222.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Received: by mail-qk1-f180.google.com with SMTP id af79cd13be357-792b8c9046bso137944685a.3 for ; Wed, 22 May 2024 13:06:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1716408363; x=1717013163; darn=vger.kernel.org; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=Dd7GrKK6qrVpweRGgoT/fw8t7w7OjlAlF8Ebyefp99A=; b=HkZa7hGc7qW3wUC3MJ5LHI8JbKnnBNPZWfpqPPWlXrRSMRteOK/e2iFFSuW0eaPaj7 9pkMOy37mKY3F1GdyyQz3W85TwMv+X7SjC235fw9J9f6WIPeHGRe7oSUUxg9HJ3ZAq8M ppgI8BsQRVSmDkfMwYj6Ij2IBYK8AYQCytmxIGdN1FPAT9syBc57wv5AgFE3Si+ePINg hR5PQxy6FWXG7RHPqFPwLu12l4UsiUVc+pD1UZqgDtSpXrlcnxP7H3HpvM5g1k8hCAzK EPBr5DJB+ZNIjGUGAIi9EuFqg6AF4KUAshv7DfwP1v+7Iv5RWgR6EMydVHcLbrOQfSev xDcg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1716408363; x=1717013163; h=content-transfer-encoding:in-reply-to:from:content-language :references:cc:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Dd7GrKK6qrVpweRGgoT/fw8t7w7OjlAlF8Ebyefp99A=; b=rF5tu8YERIjdzHm66Wfx5QY26Ez/A75nG71ydDb3U/EgWM1DtbzX/+TUXyZ6E8e1oW hZsMXF/yxiuGTZAQk4v0HjVP4Tr9tGzIfFPuW8A4sPHPWk3YjirBaCgQbBOgndeDxLqT s8xSLh1TBlSLtxlj3KAOwPHIhSABNsrLSP5UCM3k8vlqHIwfHE4323wQ1s64/I9ZnjWn rGUjq3kFJj06BIj9k2jEpFRwrs6p0xdZkjAJ9I/gkWYyERdfmhm0iud1KsQ5PD235Y0Z +OxTsBzsLXZ1ed8oCUu+lVEXQMhm4q+2KqmY608PKgQehgSbjJTLALqm2Sx+UFKX4XbS QWUQ== X-Forwarded-Encrypted: i=1; AJvYcCU6HunyzY6OQK9kXPe8T91iaCnqUnfLREu1XM9d6ILO4OTK9odekyYmIgkXaZLQLIRzRdiXKlVa4/73YEG9AQ/2W4mvud10grSmEG1l X-Gm-Message-State: AOJu0YxKnSnyaPYgxO3G2TsLJ5TCmt9WFglQUN0MMBqz48ZL1iIt+v4R Nb+Rhq488Sj/jHwIwpjDppIwIdQxjUxjXPkzJUzmhF6K7C/Y2d2kbBuDxTvjmQk= X-Received: by 2002:a05:620a:20cb:b0:794:7969:5d66 with SMTP id af79cd13be357-794994b20d4mr274602485a.55.1716408362773; Wed, 22 May 2024 13:06:02 -0700 (PDT) Received: from [192.168.40.12] (d24-150-219-207.home.cgocable.net. [24.150.219.207]) by smtp.gmail.com with ESMTPSA id af79cd13be357-792bf275229sm1428443185a.18.2024.05.22.13.06.01 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 22 May 2024 13:06:02 -0700 (PDT) Message-ID: <8cd080ef-e1f3-4752-8f92-d61c5fd321b5@baylibre.com> Date: Wed, 22 May 2024 16:06:00 -0400 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 1/2 v3] pwm: add duty offset support To: =?UTF-8?Q?Uwe_Kleine-K=C3=B6nig?= Cc: linux-pwm@vger.kernel.org, linux-kernel@vger.kernel.org, michael.hennerich@analog.com, nuno.sa@analog.com, dlechner@baylibre.com References: <20240521194916.1897909-1-tgamblin@baylibre.com> <20240521194916.1897909-2-tgamblin@baylibre.com> <73y7ovftjv35gw3sjeu3jisg7feplhyebmcnldqvszuofqnn7q@eh4lyicuhfmq> Content-Language: en-US From: Trevor Gamblin In-Reply-To: <73y7ovftjv35gw3sjeu3jisg7feplhyebmcnldqvszuofqnn7q@eh4lyicuhfmq> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 2024-05-22 11:53 a.m., Uwe Kleine-König wrote: > Hello Trevor, > > On Tue, May 21, 2024 at 03:49:15PM -0400, Trevor Gamblin wrote: >> Some PWM chips support a "phase" or "duty_offset" feature. This patch >> continues adding support for configuring this property in the PWM >> subsystem. >> >> Functions duty_offset_show(), duty_offset_store(), and >> pwm_get_duty_offset() are added to match what exists for duty_cycle. >> >> Add a check to disallow applying a state with both inversed polarity and >> a nonzero duty_offset. >> >> Also add duty_offset to TP_printk in include/trace/events/pwm.h so that >> it is reported with other properties when using the event tracing pipe >> for debug. >> >> Signed-off-by: Trevor Gamblin >> --- >> v3 changes: >> * rebased on top of latest pwm/for-next >> * removed changes related to cdev to match current pwm tree >> * fixed minor whitespace issue caught by checkpatch >> >> v2 changes: >> * Address feedback for driver in v1: >> * Remove line setting supports_offset flag in pwm_chip, since that has >> been removed from the struct in core.c. >> >> --- >> drivers/pwm/core.c | 79 +++++++++++++++++++++++++++++++++++--- >> include/linux/pwm.h | 15 ++++++++ >> include/trace/events/pwm.h | 6 ++- >> 3 files changed, 93 insertions(+), 7 deletions(-) >> >> diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c >> index 18574857641e..2ebfc7f3de8a 100644 >> --- a/drivers/pwm/core.c >> +++ b/drivers/pwm/core.c >> @@ -62,6 +62,7 @@ static void pwm_apply_debug(struct pwm_device *pwm, >> */ >> if (s1.enabled && s1.polarity != state->polarity) { >> s2.polarity = state->polarity; >> + s2.duty_offset = s1.duty_cycle; > s/duty_cycle/duty_offset/ Thanks for the catch. > >> s2.duty_cycle = s1.period - s1.duty_cycle; >> s2.period = s1.period; >> s2.enabled = s1.enabled; >> @@ -103,6 +104,23 @@ static void pwm_apply_debug(struct pwm_device *pwm, >> state->duty_cycle, state->period, >> s2.duty_cycle, s2.period); >> >> + if (state->enabled && >> + last->polarity == state->polarity && >> + last->period == s2.period && >> + last->duty_offset > s2.duty_offset && >> + last->duty_offset <= state->duty_offset) >> + dev_warn(pwmchip_parent(chip), >> + ".apply didn't pick the best available duty offset (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n", >> + state->duty_offset, state->period, > Does it make sense to emit $duty_offset/$period here? Establishing a > consistent way to write this would be nice. Something like: > > $duty_cycle/$period [+$duty_offset] > > maybe? I like that. I'll clean it up. > >> + s2.duty_offset, s2.period, >> + last->duty_offset, last->period); >> + >> + if (state->enabled && state->duty_offset < s2.duty_offset) >> + dev_warn(pwmchip_parent(chip), >> + ".apply is supposed to round down duty_offset (requested: %llu/%llu, applied: %llu/%llu)\n", >> + state->duty_offset, state->period, >> + s2.duty_offset, s2.period); >> + >> if (!state->enabled && s2.enabled && s2.duty_cycle > 0) >> dev_warn(pwmchip_parent(chip), >> "requested disabled, but yielded enabled with duty > 0\n"); >> @@ -126,12 +144,13 @@ static void pwm_apply_debug(struct pwm_device *pwm, >> if (s1.enabled != last->enabled || >> s1.polarity != last->polarity || >> (s1.enabled && s1.period != last->period) || >> + (s1.enabled && s1.duty_offset != last->duty_offset) || >> (s1.enabled && s1.duty_cycle != last->duty_cycle)) { >> dev_err(pwmchip_parent(chip), >> - ".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n", >> + ".apply is not idempotent (ena=%d pol=%d %llu/%llu/%llu) -> (ena=%d pol=%d %llu/%llu/%llu)\n", >> s1.enabled, s1.polarity, s1.duty_cycle, s1.period, >> - last->enabled, last->polarity, last->duty_cycle, >> - last->period); >> + s1.duty_offset, last->enabled, last->polarity, >> + last->duty_cycle, last->period, last->duty_offset); >> } >> } >> >> @@ -146,13 +165,24 @@ static int __pwm_apply(struct pwm_device *pwm, const struct pwm_state *state) >> int err; >> >> if (!pwm || !state || !state->period || >> - state->duty_cycle > state->period) >> + state->duty_cycle > state->period || >> + state->duty_offset > state->period) >> return -EINVAL; >> >> chip = pwm->chip; >> >> + /* >> + * There is no need to set duty_offset with inverse polarity, >> + * since signals with duty_offset values greater than 0.5 * >> + * period can equivalently be represented by an inverted signal >> + * without offset. > This isn't exact. The equation is: > > state_with_offset.period = inverted_state.period > state_with_offset.duty_cycle = inverted_state.period - inverted_state.duty_cycle > state_with_offset.duty_offset = inverted_state.duty_cycle > > And with duty_offset you can express more wave-forms than with > inversion. Thanks for the clarification, I'll change this too. > >> + */ >> + if (state->polarity == PWM_POLARITY_INVERSED && state->duty_offset) >> + return -EINVAL; >> + >> if (state->period == pwm->state.period && >> state->duty_cycle == pwm->state.duty_cycle && >> + state->duty_offset == pwm->state.duty_offset && >> state->polarity == pwm->state.polarity && >> state->enabled == pwm->state.enabled && >> state->usage_power == pwm->state.usage_power) > While I like the added expressiveness of having .duty_offset, I think we > shouldn't let the low-level drivers face both .duty_offset and > .polarity. > > I suggest to add a new callback similar to .apply that gets passed a > variant of pwm_state that only has > > u64 period > u64 duty_cycle > u64 duty_offset > > period = 0 then signals disable. Implementers are then supposed to first > round down period to a possible period (> 0), then duty_cycle to a > possible duty_cycle for the picked period and then duty_offset to a > possible duty_offset with the picked period and duty_cycle. > > Then there is a single code location that handles the translation > between state with polarity and state with duty_offset in the core, > instead of case switching in each lowlevel driver. And I wouldn't > add .duty_offset to the sysfs interface, to lure people into using the > character device support which has several advantages over the sysfs > API. (One reasonable justification is that we cannot remove polarity > there, and we also cannot report polarity = normal + some duty_offset > without possibly breaking assumptions in sysfs users.) Makes sense. On a related note, will your pwm/chardev branch be merged soon? > > What is missing in my plan is a nice name for the new struct pwm_state > and the .apply() (and matching .get_state()) callback. Maybe pwm_nstate, > .apply_nstate() and .get_nstate()? n for "new", which however won't age > nicely. Maybe it also makes sense to add a .round_nstate() in the same > go. We'd have to touch all drivers anyhow and implementing a rounding > callback (that has similar semantics to clk_round_rate() for clocks, > i.e. it reports what would be configured for a given (n)state) isn't > much more work. With rounding in place we could also request that > .apply_nstate() only succeeds if rounding down decrements the values by > less than 1, which gives still more control. (The more lax variant can > then be implemented by first passing an nstate to .round_nstate and then > .apply_nstate that one.) Instead of "new", what about something like "raw", "base", "signal", or "waveform"? I think those (even abbreviated) might make it more clear what the purpose of the new struct is. "wstate" seems to be fairly unique to me - a quick grep caught other uses of the string only in: - tools/testing/selftests/net/mptcp/mptcp_connect.c - arch/sparc/include/asm/hibernate.h - arch/sparc/kernel/asm-offsets.c Thanks again for the feedback. I'll spend some time thinking about this and aim to come back with a v4 soon. Trevor > > Best regards > Uwe >