Skip to content

Commit

Permalink
Merge tag 'pwm/for-5.9-rc1' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/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
  • Loading branch information
torvalds committed Aug 14, 2020
2 parents 87bd8c2 + 6ced5ff commit fded091
Show file tree
Hide file tree
Showing 21 changed files with 56 additions and 44 deletions.
7 changes: 6 additions & 1 deletion drivers/clk/clk-pwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/display/intel_panel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/hwmon/pwm-fan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
14 changes: 7 additions & 7 deletions drivers/pwm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand All @@ -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);

Expand All @@ -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);
Expand Down Expand Up @@ -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");

Expand Down
12 changes: 8 additions & 4 deletions drivers/pwm/pwm-bcm-iproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand All @@ -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;
Expand Down Expand Up @@ -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 &&
Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-bcm-kona.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-clps711x.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-imx-tpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-imx27.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
15 changes: 8 additions & 7 deletions drivers/pwm/pwm-iqs620a.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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;
Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions drivers/pwm/pwm-mediatek.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions drivers/pwm/pwm-omap-dmtimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-sifive.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-stm32-lp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-sun4i.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-tiecap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion drivers/pwm/pwm-tiehrpwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
8 changes: 4 additions & 4 deletions drivers/pwm/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;

Expand All @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion drivers/video/backlight/pwm_bl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/video/fbdev/ssd1307fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down
12 changes: 6 additions & 6 deletions include/linux/pwm.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ enum pwm_polarity {
* current PWM hardware state.
*/
struct pwm_args {
unsigned int period;
u64 period;
enum pwm_polarity polarity;
};

Expand All @@ -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;
};
Expand Down Expand Up @@ -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;

Expand All @@ -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;

Expand Down

0 comments on commit fded091

Please sign in to comment.