pwm: Changes for v5.9-rc1

The majority of this batch is conversion of the PWM period and duty
 cycle to 64-bit unsigned integers, which is required so that some types
 of hardware can generate the full range of signals that they're capable
 of. The remainder is mostly minor fixes and cleanups.
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEEiOrDCAFJzPfAjcif3SOs138+s6EFAl82iq0ZHHRoaWVycnku
 cmVkaW5nQGdtYWlsLmNvbQAKCRDdI6zXfz6zoTXSD/9h6v8w/9oC9xDxEO+6vTF3
 XNMWBO3PxzjNpI02bxYVMckb8J6AsDFwB+fsMnRvHooFXqi+/5iQvxyt6b8rTIRA
 ThOEd+PJnX9l8P9I/k/5RbdiYA51GtJomDc1f85yCs6UaMnTMRj9+S3E7rWPW+LZ
 azKegtqQloJxMM8w+MBS3+3w1c4h80tfHphU4DbNDCTS0Pq2rXK2B0BJq+oFWXS+
 GpTut7jzbQBpVm5+pF/3YwjQ1ODoHL+LJYtjdYdFk0HJtddsGIzR8xFAci//maZj
 NtbE6tFFSz97z18QCvHBNDySV3/qVIy+Pr2g141yv0uhjvJ3zms4uveD3wmxFSbZ
 0LWaGdCRUbffI1g5uCWjSEspWo+oEY3A6LQ2RVpmNL44T/rvgZuYKbJmFSnM3qr5
 DzB0gx5ZlagXGO9W1u4aif+VBfJdF7JUGWazbyZ1O36bSPF83T7db8Shok10Yx+J
 DsmWaxDMxVE8DFNUOaoDHXUq8L8gW8OFKeBttO3zUwCCxpIn9qunwDiFqvlkQHgI
 xVqC5Yp1oMqq5enYlLGLqnCahYuUXgBW91uyEpeB4hzZMhU2CTgei0bzHdu5xDE4
 5ZDks2EZ7CibJJ2EKwWgIF8iVkpepdXj0Wpy7HT6FStR2/kauT58h36bLzhjbh54
 GtD3Z5TDtV8lrabOfmk6pA==
 =v6MG
 -----END PGP SIGNATURE-----

Merge tag 'pwm/for-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm

Pull pwm updates from Thierry Reding:
 "The majority of this batch is conversion of the PWM period and duty
  cycle to 64-bit unsigned integers, which is required so that some
  types of hardware can generate the full range of signals that they're
  capable of.

  The remainder is mostly minor fixes and cleanups"

* tag 'pwm/for-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm:
  pwm: bcm-iproc: handle clk_get_rate() return
  pwm: Replace HTTP links with HTTPS ones
  pwm: omap-dmtimer: Repair pwm_omap_dmtimer_chip's broken kerneldoc header
  pwm: mediatek: Provide missing kerneldoc description for 'soc' arg
  pwm: bcm-kona: Remove impossible comparison when validating duty cycle
  pwm: bcm-iproc: Remove impossible comparison when validating duty cycle
  pwm: iqs620a: Use lowercase hexadecimal literals for consistency
  pwm: Convert period and duty cycle to u64
  clk: pwm: Use 64-bit division function
  backlight: pwm_bl: Use 64-bit division function
  pwm: sun4i: Use nsecs_to_jiffies to avoid a division
  pwm: sifive: Use 64-bit division macro
  pwm: iqs620a: Use 64-bit division
  pwm: imx27: Use 64-bit division macro
  pwm: imx-tpm: Use 64-bit division macro
  pwm: clps711x: Use 64-bit division macro
  hwmon: pwm-fan: Use 64-bit division macro
  drm/i915: Use 64-bit division macro
This commit is contained in:
Linus Torvalds 2020-08-14 16:00:09 -07:00
commit fded091988
21 changed files with 56 additions and 44 deletions

View File

@ -89,7 +89,12 @@ static int clk_pwm_probe(struct platform_device *pdev)
}
if (of_property_read_u32(node, "clock-frequency", &clk_pwm->fixed_rate))
clk_pwm->fixed_rate = NSEC_PER_SEC / pargs.period;
clk_pwm->fixed_rate = div64_u64(NSEC_PER_SEC, pargs.period);
if (!clk_pwm->fixed_rate) {
dev_err(&pdev->dev, "fixed_rate cannot be zero\n");
return -EINVAL;
}
if (pargs.period != NSEC_PER_SEC / clk_pwm->fixed_rate &&
pargs.period != DIV_ROUND_UP(NSEC_PER_SEC, clk_pwm->fixed_rate)) {

View File

@ -1929,7 +1929,7 @@ static int pwm_setup_backlight(struct intel_connector *connector,
return retval;
}
level = DIV_ROUND_UP(pwm_get_duty_cycle(panel->backlight.pwm) * 100,
level = DIV_ROUND_UP_ULL(pwm_get_duty_cycle(panel->backlight.pwm) * 100,
CRC_PMIC_PWM_PERIOD_NS);
panel->backlight.level =
intel_panel_compute_brightness(connector, level);

View File

@ -447,7 +447,7 @@ static int pwm_fan_resume(struct device *dev)
return 0;
pwm_get_args(ctx->pwm, &pargs);
duty = DIV_ROUND_UP(ctx->pwm_value * (pargs.period - 1), MAX_PWM);
duty = DIV_ROUND_UP_ULL(ctx->pwm_value * (pargs.period - 1), MAX_PWM);
ret = pwm_config(ctx->pwm, duty, pargs.period);
if (ret)
return ret;

View File

@ -510,12 +510,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 &&
@ -524,14 +524,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);
@ -558,7 +558,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);
@ -1284,8 +1284,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");

View File

@ -85,8 +85,6 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
u64 tmp, multi, rate;
u32 value, prescale;
rate = clk_get_rate(ip->clk);
value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
if (value & BIT(IPROC_PWM_CTRL_EN_SHIFT(pwm->hwpwm)))
@ -99,6 +97,13 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
else
state->polarity = PWM_POLARITY_INVERSED;
rate = clk_get_rate(ip->clk);
if (rate == 0) {
state->period = 0;
state->duty_cycle = 0;
return;
}
value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
prescale = value >> IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
prescale &= IPROC_PWM_PRESCALE_MAX;
@ -143,8 +148,7 @@ static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
value = rate * state->duty_cycle;
duty = div64_u64(value, div);
if (period < IPROC_PWM_PERIOD_MIN ||
duty < IPROC_PWM_DUTY_CYCLE_MIN)
if (period < IPROC_PWM_PERIOD_MIN)
return -EINVAL;
if (period <= IPROC_PWM_PERIOD_MAX &&

View File

@ -138,7 +138,7 @@ static int kona_pwmc_config(struct pwm_chip *chip, struct pwm_device *pwm,
dc = div64_u64(val, div);
/* If duty_ns or period_ns are not achievable then return */
if (pc < PERIOD_COUNT_MIN || dc < DUTY_CYCLE_HIGH_MIN)
if (pc < PERIOD_COUNT_MIN)
return -EINVAL;
/* If pc and dc are in bounds, the calculation is done */

View File

@ -43,7 +43,7 @@ static void clps711x_pwm_update_val(struct clps711x_chip *priv, u32 n, u32 v)
static unsigned int clps711x_get_duty(struct pwm_device *pwm, unsigned int v)
{
/* Duty cycle 0..15 max */
return DIV_ROUND_CLOSEST(v * 0xf, pwm->args.period);
return DIV64_U64_ROUND_CLOSEST(v * 0xf, pwm->args.period);
}
static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)

View File

@ -124,7 +124,7 @@ static int pwm_imx_tpm_round_state(struct pwm_chip *chip,
real_state->duty_cycle = state->duty_cycle;
tmp = (u64)p->mod * real_state->duty_cycle;
p->val = DIV_ROUND_CLOSEST_ULL(tmp, real_state->period);
p->val = DIV64_U64_ROUND_CLOSEST(tmp, real_state->period);
real_state->polarity = state->polarity;
real_state->enabled = state->enabled;

View File

@ -202,7 +202,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
sr = readl(imx->mmio_base + MX3_PWMSR);
fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr);
if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
period_ms = DIV_ROUND_UP(pwm_get_period(pwm),
period_ms = DIV_ROUND_UP_ULL(pwm_get_period(pwm),
NSEC_PER_MSEC);
msleep(period_ms);

View File

@ -25,10 +25,10 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#define IQS620_PWR_SETTINGS 0xD2
#define IQS620_PWR_SETTINGS 0xd2
#define IQS620_PWR_SETTINGS_PWM_OUT BIT(7)
#define IQS620_PWM_DUTY_CYCLE 0xD8
#define IQS620_PWM_DUTY_CYCLE 0xd8
#define IQS620_PWM_PERIOD_NS 1000000
@ -46,7 +46,8 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
{
struct iqs620_pwm_private *iqs620_pwm;
struct iqs62x_core *iqs62x;
int duty_scale, ret;
u64 duty_scale;
int ret;
if (state->polarity != PWM_POLARITY_NORMAL)
return -ENOTSUPP;
@ -69,7 +70,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* For lower duty cycles (e.g. 0), the PWM output is simply disabled to
* allow an external pull-down resistor to hold the GPIO3/LTX pin low.
*/
duty_scale = state->duty_cycle * 256 / IQS620_PWM_PERIOD_NS;
duty_scale = div_u64(state->duty_cycle * 256, IQS620_PWM_PERIOD_NS);
mutex_lock(&iqs620_pwm->lock);
@ -81,7 +82,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
}
if (duty_scale) {
u8 duty_val = min(duty_scale - 1, 0xFF);
u8 duty_val = min_t(u64, duty_scale - 1, 0xff);
ret = regmap_write(iqs62x->regmap, IQS620_PWM_DUTY_CYCLE,
duty_val);
@ -93,7 +94,7 @@ static int iqs620_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
if (state->enabled && duty_scale) {
ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS,
IQS620_PWR_SETTINGS_PWM_OUT, 0xFF);
IQS620_PWR_SETTINGS_PWM_OUT, 0xff);
if (ret)
goto err_mutex;
}
@ -159,7 +160,7 @@ static int iqs620_pwm_notifier(struct notifier_block *notifier,
ret = regmap_update_bits(iqs62x->regmap, IQS620_PWR_SETTINGS,
IQS620_PWR_SETTINGS_PWM_OUT,
iqs620_pwm->out_en ? 0xFF : 0);
iqs620_pwm->out_en ? 0xff : 0);
err_mutex:
mutex_unlock(&iqs620_pwm->lock);

View File

@ -46,6 +46,7 @@ struct pwm_mediatek_of_data {
* @clk_main: the clock used by PWM core
* @clk_pwms: the clock used by each PWM channel
* @clk_freq: the fix clock frequency of legacy MIPS SoC
* @soc: pointer to chip's platform data
*/
struct pwm_mediatek_chip {
struct pwm_chip chip;

View File

@ -14,7 +14,7 @@
* with a timer counter that goes up. When it overflows it gets
* reloaded with the load value and the pwm output goes up.
* When counter matches with match register, the output goes down.
* Reference Manual: http://www.ti.com/lit/ug/spruh73q/spruh73q.pdf
* Reference Manual: https://www.ti.com/lit/ug/spruh73q/spruh73q.pdf
*
* Limitations:
* - When PWM is stopped, timer counter gets stopped immediately. This
@ -58,7 +58,7 @@
* @mutex: Mutex to protect pwm apply state
* @dm_timer: Pointer to omap dm timer.
* @pdata: Pointer to omap dm timer ops.
* dm_timer_pdev: Pointer to omap dm timer platform device
* @dm_timer_pdev: Pointer to omap dm timer platform device
*/
struct pwm_omap_dmtimer_chip {
struct pwm_chip chip;

View File

@ -181,7 +181,7 @@ static int pwm_sifive_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* consecutively
*/
num = (u64)duty_cycle * (1U << PWM_SIFIVE_CMPWIDTH);
frac = DIV_ROUND_CLOSEST_ULL(num, state->period);
frac = DIV64_U64_ROUND_CLOSEST(num, state->period);
/* The hardware cannot generate a 100% duty cycle */
frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1);

View File

@ -61,7 +61,7 @@ static int stm32_pwm_lp_apply(struct pwm_chip *chip, struct pwm_device *pwm,
do_div(div, NSEC_PER_SEC);
if (!div) {
/* Clock is too slow to achieve requested period. */
dev_dbg(priv->chip.dev, "Can't reach %u ns\n", state->period);
dev_dbg(priv->chip.dev, "Can't reach %llu ns\n", state->period);
return -EINVAL;
}

View File

@ -285,7 +285,7 @@ static int sun4i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
val = (duty & PWM_DTY_MASK) | PWM_PRD(period);
sun4i_pwm_writel(sun4i_pwm, val, PWM_CH_PRD(pwm->hwpwm));
sun4i_pwm->next_period[pwm->hwpwm] = jiffies +
usecs_to_jiffies(cstate.period / 1000 + 1);
nsecs_to_jiffies(cstate.period + 1000);
if (state->polarity != PWM_POLARITY_NORMAL)
ctrl &= ~BIT_CH(PWM_ACT_STATE, pwm->hwpwm);

View File

@ -2,7 +2,7 @@
/*
* ECAP PWM driver
*
* Copyright (C) 2012 Texas Instruments, Inc. - http://www.ti.com/
* Copyright (C) 2012 Texas Instruments, Inc. - https://www.ti.com/
*/
#include <linux/module.h>

View File

@ -2,7 +2,7 @@
/*
* EHRPWM PWM driver
*
* Copyright (C) 2012 Texas Instruments, Inc. - http://www.ti.com/
* Copyright (C) 2012 Texas Instruments, Inc. - https://www.ti.com/
*/
#include <linux/module.h>

View File

@ -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,
@ -52,10 +52,10 @@ static ssize_t period_store(struct device *child,
struct pwm_export *export = child_to_pwm_export(child);
struct pwm_device *pwm = export->pwm;
struct pwm_state state;
unsigned int val;
u64 val;
int ret;
ret = kstrtouint(buf, 0, &val);
ret = kstrtou64(buf, 0, &val);
if (ret)
return ret;
@ -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,

View File

@ -601,7 +601,8 @@ static int pwm_backlight_probe(struct platform_device *pdev)
pb->scale = data->max_brightness;
}
pb->lth_brightness = data->lth_brightness * (state.period / pb->scale);
pb->lth_brightness = data->lth_brightness * (div_u64(state.period,
pb->scale));
props.type = BACKLIGHT_RAW;
props.max_brightness = data->max_brightness;

View File

@ -312,7 +312,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
/* Enable the PWM */
pwm_enable(par->pwm);
dev_dbg(&par->client->dev, "Using PWM%d with a %dns period.\n",
dev_dbg(&par->client->dev, "Using PWM%d with a %lluns period.\n",
par->pwm->pwm, pwm_get_period(par->pwm));
}

View File

@ -39,7 +39,7 @@ enum pwm_polarity {
* current PWM hardware state.
*/
struct pwm_args {
unsigned int period;
u64 period;
enum pwm_polarity polarity;
};
@ -56,8 +56,8 @@ enum {
* @enabled: PWM enabled status
*/
struct pwm_state {
unsigned int period;
unsigned int duty_cycle;
u64 period;
u64 duty_cycle;
enum pwm_polarity polarity;
bool enabled;
};
@ -107,13 +107,13 @@ static inline bool pwm_is_enabled(const struct pwm_device *pwm)
return state.enabled;
}
static inline void pwm_set_period(struct pwm_device *pwm, unsigned int period)
static inline void pwm_set_period(struct pwm_device *pwm, u64 period)
{
if (pwm)
pwm->state.period = period;
}
static inline unsigned int pwm_get_period(const struct pwm_device *pwm)
static inline u64 pwm_get_period(const struct pwm_device *pwm)
{
struct pwm_state state;
@ -128,7 +128,7 @@ static inline void pwm_set_duty_cycle(struct pwm_device *pwm, unsigned int duty)
pwm->state.duty_cycle = duty;
}
static inline unsigned int pwm_get_duty_cycle(const struct pwm_device *pwm)
static inline u64 pwm_get_duty_cycle(const struct pwm_device *pwm)
{
struct pwm_state state;