From: Martin Botka <martin.botka1@gmail.com>
To: unlisted-recipients:; (no To-header on input)
Cc: "Fenglin Wu" <fenglinw@codeaurora.org>,
"Konrad Dybcio" <konradybcio@gmail.com>,
"Martin Botka" <martin.botka1@gmail.com>,
"Jacek Anaszewski" <jacek.anaszewski@gmail.com>,
"Pavel Machek" <pavel@ucw.cz>, "Dan Murphy" <dmurphy@ti.com>,
"Rob Herring" <robh+dt@kernel.org>,
"Thierry Reding" <thierry.reding@gmail.com>,
"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
"Lee Jones" <lee.jones@linaro.org>,
linux-leds@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-pwm@vger.kernel.org
Subject: [PATCH RFC 2/6] pwm: core: Add option to config PWM duty/period with u64 data length
Date: Fri, 24 Jul 2020 23:36:52 +0200 [thread overview]
Message-ID: <20200724213659.273599-3-martin.botka1@gmail.com> (raw)
In-Reply-To: <20200724213659.273599-1-martin.botka1@gmail.com>
From: Fenglin Wu <fenglinw@codeaurora.org>
Currently, PWM core driver provides interfaces for configuring PWM
period and duty length in nanoseconds with an integer data type, so
the max period can be only set to ~2.147 seconds. Add interfaces which
can set PWM period and duty with u64 data type to remove this
limitation.
Signed-off-by: Fenglin Wu <fenglinw@codeaurora.org>
[konradybcio@gmail.com: Fast-forward from kernel 4.14 to 5.8]
Signed-off-by: Konrad Dybcio <konradybcio@gmail.com>
Signed-off-by: Martin Botka <martin.botka1@gmail.com>
---
drivers/pwm/core.c | 30 +++++++++++------
drivers/pwm/sysfs.c | 6 ++--
include/linux/pwm.h | 79 +++++++++++++++++++++++++++++++++++++++++----
3 files changed, 95 insertions(+), 20 deletions(-)
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index f3aa44106962..82411e3ccbbb 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -511,12 +511,12 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
last->period > s2.period &&
last->period <= state->period)
dev_warn(chip->dev,
- ".apply didn't pick the best available period (requested: %u, applied: %u, possible: %u)\n",
+ ".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n",
state->period, s2.period, last->period);
if (state->enabled && state->period < s2.period)
dev_warn(chip->dev,
- ".apply is supposed to round down period (requested: %u, applied: %u)\n",
+ ".apply is supposed to round down period (requested: %llu, applied: %llu)\n",
state->period, s2.period);
if (state->enabled &&
@@ -525,14 +525,14 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
last->duty_cycle > s2.duty_cycle &&
last->duty_cycle <= state->duty_cycle)
dev_warn(chip->dev,
- ".apply didn't pick the best available duty cycle (requested: %u/%u, applied: %u/%u, possible: %u/%u)\n",
+ ".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n",
state->duty_cycle, state->period,
s2.duty_cycle, s2.period,
last->duty_cycle, last->period);
if (state->enabled && state->duty_cycle < s2.duty_cycle)
dev_warn(chip->dev,
- ".apply is supposed to round down duty_cycle (requested: %u/%u, applied: %u/%u)\n",
+ ".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n",
state->duty_cycle, state->period,
s2.duty_cycle, s2.period);
@@ -559,7 +559,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
(s1.enabled && s1.period != last->period) ||
(s1.enabled && s1.duty_cycle != last->duty_cycle)) {
dev_err(chip->dev,
- ".apply is not idempotent (ena=%d pol=%d %u/%u) -> (ena=%d pol=%d %u/%u)\n",
+ ".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n",
s1.enabled, s1.polarity, s1.duty_cycle, s1.period,
last->enabled, last->polarity, last->duty_cycle,
last->period);
@@ -655,9 +655,19 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
if (state->period != pwm->state.period ||
state->duty_cycle != pwm->state.duty_cycle) {
- err = chip->ops->config(pwm->chip, pwm,
- state->duty_cycle,
- state->period);
+ if (pwm->chip->ops->config_extend) {
+ err = pwm->chip->ops->config_extend(pwm->chip,
+ pwm, state->duty_cycle,
+ state->period);
+ } else {
+ if (state->period > UINT_MAX)
+ pr_warn("period %llu duty_cycle %llu will be truncated\n",
+ state->period,
+ state->duty_cycle);
+ err = pwm->chip->ops->config(pwm->chip, pwm,
+ state->duty_cycle,
+ state->period);
+ }
if (err)
return err;
@@ -1310,8 +1320,8 @@ static void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s)
if (state.enabled)
seq_puts(s, " enabled");
- seq_printf(s, " period: %u ns", state.period);
- seq_printf(s, " duty: %u ns", state.duty_cycle);
+ seq_printf(s, " period: %llu ns", state.period);
+ seq_printf(s, " duty: %llu ns", state.duty_cycle);
seq_printf(s, " polarity: %s",
state.polarity ? "inverse" : "normal");
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 4ee1e81db0bc..f9d7ebfb48f4 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -42,7 +42,7 @@ static ssize_t period_show(struct device *child,
pwm_get_state(pwm, &state);
- return sprintf(buf, "%u\n", state.period);
+ return sprintf(buf, "%llu\n", state.period);
}
static ssize_t period_store(struct device *child,
@@ -77,7 +77,7 @@ static ssize_t duty_cycle_show(struct device *child,
pwm_get_state(pwm, &state);
- return sprintf(buf, "%u\n", state.duty_cycle);
+ return sprintf(buf, "%llu\n", state.duty_cycle);
}
static ssize_t duty_cycle_store(struct device *child,
@@ -212,7 +212,7 @@ static ssize_t capture_show(struct device *child,
if (ret)
return ret;
- return sprintf(buf, "%u %u\n", result.period, result.duty_cycle);
+ return sprintf(buf, "%llu %llu\n", result.period, result.duty_cycle);
}
static ssize_t output_type_show(struct device *child,
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 10a102efadc4..ab235007287f 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -39,7 +39,7 @@ enum pwm_polarity {
* current PWM hardware state.
*/
struct pwm_args {
- unsigned int period;
+ u64 period;
enum pwm_polarity polarity;
};
@@ -66,9 +66,9 @@ enum pwm_output_type {
* @cycles_per_duty: number of PWM period cycles an entry stays at
*/
struct pwm_output_pattern {
- unsigned int *duty_pattern;
+ u64 *duty_pattern;
unsigned int num_entries;
- unsigned int cycles_per_duty;
+ u64 cycles_per_duty;
};
/*
@@ -79,8 +79,8 @@ struct pwm_output_pattern {
* @enabled: PWM enabled status
*/
struct pwm_state {
- unsigned int period;
- unsigned int duty_cycle;
+ u64 period;
+ u64 duty_cycle;
enum pwm_polarity polarity;
enum pwm_output_type output_type;
struct pwm_output_pattern *output_pattern;
@@ -138,12 +138,30 @@ static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period)
pwm->state.period = period;
}
+static inline void pwm_set_period_extend(struct pwm_device *pwm, u64 period)
+{
+ if (pwm)
+ pwm->state.period = period;
+}
+
static inline unsigned int pwm_get_period(const struct pwm_device *pwm)
{
struct pwm_state state;
pwm_get_state(pwm, &state);
+ if (state.period > UINT_MAX)
+ pr_warn("PWM period %llu is truncated\n", state.period);
+
+ return (unsigned int)state.period;
+}
+
+static inline u64 pwm_get_period_extend(const struct pwm_device *pwm)
+{
+ struct pwm_state state;
+
+ pwm_get_state(pwm, &state);
+
return state.period;
}
@@ -153,12 +171,30 @@ static inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty)
pwm->state.duty_cycle = duty;
}
+static inline void pwm_set_duty_cycle_extend(struct pwm_device *pwm, u64 duty)
+{
+ if (pwm)
+ pwm->state.duty_cycle = duty;
+}
+
static inline unsigned int pwm_get_duty_cycle(const struct pwm_device *pwm)
{
struct pwm_state state;
pwm_get_state(pwm, &state);
+ if (state.duty_cycle > UINT_MAX)
+ pr_warn("PWM duty cycle %llu is truncated\n", state.duty_cycle);
+
+ return (unsigned int)state.duty_cycle;
+}
+
+static inline u64 pwm_get_duty_cycle_extend(const struct pwm_device *pwm)
+{
+ struct pwm_state state;
+
+ pwm_get_state(pwm, &state);
+
return state.duty_cycle;
}
@@ -296,6 +332,8 @@ pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle,
* registered.
* @owner: helps prevent removal of modules exporting active PWMs
* @config: configure duty cycles and period length for this PWM
+ * @config_extend: configure duty cycles and period length for this
+ * PWM with u64 data type
* @set_polarity: configure the polarity of this PWM
* @enable: enable PWM output toggling
* @disable: disable PWM output toggling
@@ -317,6 +355,8 @@ struct pwm_ops {
/* Only used by legacy drivers */
int (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns);
+ int (*config_extend)(struct pwm_chip *chip, struct pwm_device *pwm,
+ u64 duty_ns, u64 period_ns);
int (*set_polarity)(struct pwm_chip *chip, struct pwm_device *pwm,
enum pwm_polarity polarity);
int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm);
@@ -362,8 +402,8 @@ struct pwm_chip {
* @duty_cycle: duty cycle of the PWM signal (in nanoseconds)
*/
struct pwm_capture {
- unsigned int period;
- unsigned int duty_cycle;
+ u64 period;
+ u64 duty_cycle;
};
#if IS_ENABLED(CONFIG_PWM)
@@ -415,6 +455,31 @@ static inline int pwm_config(struct pwm_device *pwm, int duty_ns,
return pwm_apply_state(pwm, &state);
}
+/*
+ * pwm_config_extend() - change PWM period and duty length with u64 data type
+ * @pwm: PWM device
+ * @duty_ns: "on" time (in nanoseconds)
+ * @period_ns: duration (in nanoseconds) of one cycle
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+static inline int pwm_config_extend(struct pwm_device *pwm, u64 duty_ns,
+ u64 period_ns)
+{
+ struct pwm_state state;
+
+ if (!pwm)
+ return -EINVAL;
+
+ pwm_get_state(pwm, &state);
+ if (state.duty_cycle == duty_ns && state.period == period_ns)
+ return 0;
+
+ state.duty_cycle = duty_ns;
+ state.period = period_ns;
+ return pwm_apply_state(pwm, &state);
+}
+
/**
* pwm_enable() - start a PWM output toggling
* @pwm: PWM device
--
2.27.0
next prev parent reply other threads:[~2020-07-24 21:37 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-24 21:36 [PATCH RFC 0/6] Add QCOM pwm-lpg and tri-led drivers Martin Botka
2020-07-24 21:36 ` [PATCH RCC 1/6] pwm: Add different PWM output types support Martin Botka
2020-07-27 20:10 ` Uwe Kleine-König
2020-07-27 20:56 ` Martin Botka
2020-07-28 7:52 ` Uwe Kleine-König
2020-07-27 21:46 ` Guru Das Srinagesh
2020-07-24 21:36 ` Martin Botka [this message]
2020-07-25 14:55 ` [PATCH RFC 2/6] pwm: core: Add option to config PWM duty/period with u64 data length Martin Botka
2020-07-25 15:24 ` Pavel Machek
2020-07-25 15:30 ` Martin Botka
2020-07-26 9:04 ` Andy Shevchenko
2020-07-26 9:12 ` Martin Botka
2020-07-27 7:29 ` Martin Botka
2020-07-27 7:32 ` Martin Botka
2020-07-27 7:52 ` Uwe Kleine-König
2020-07-27 7:58 ` Martin Botka
2020-07-27 8:34 ` Uwe Kleine-König
2020-07-24 21:36 ` [PATCH RFC 3/6] pwm: pwm-qti-lpg: Add PWM driver for QTI LPG module Martin Botka
2020-07-27 20:09 ` Uwe Kleine-König
2020-07-27 21:16 ` Martin Botka
2020-07-28 7:08 ` Uwe Kleine-König
2020-07-24 21:36 ` [PATCH RFC 4/6] leds: leds-qti-tri-led: Add LED driver for QTI TRI_LED module Martin Botka
2020-07-26 17:25 ` Martin Botka
2020-07-24 21:36 ` [PATCH RFC 5/6] Documentation: Add binding for qti-tri-led Martin Botka
2020-07-24 21:36 ` [PATCH RFC 6/6] Documentation: Add binding for pwm-qti-lpg Martin Botka
2020-07-24 22:05 ` [PATCH RFC 0/6] Add QCOM pwm-lpg and tri-led drivers Pavel Machek
2020-07-24 22:26 ` Martin Botka
2020-07-24 22:32 ` Pavel Machek
2020-07-24 22:48 ` Martin Botka
[not found] ` <CADQ2G_HbysJbiQKSRmA6HDRfjPYPiDjbZfeuUjM1mNV-BBBC-A@mail.gmail.com>
2020-07-24 22:31 ` Pavel Machek
2020-07-24 22:46 ` Martin Botka
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200724213659.273599-3-martin.botka1@gmail.com \
--to=martin.botka1@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=dmurphy@ti.com \
--cc=fenglinw@codeaurora.org \
--cc=jacek.anaszewski@gmail.com \
--cc=konradybcio@gmail.com \
--cc=lee.jones@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=linux-pwm@vger.kernel.org \
--cc=pavel@ucw.cz \
--cc=robh+dt@kernel.org \
--cc=thierry.reding@gmail.com \
--cc=u.kleine-koenig@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).