Skip to content

Commit

Permalink
Merge tag 'pwm/for-6.2-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:
 "Various changes across the board, mostly improvements and cleanups"

* tag 'pwm/for-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm: (42 commits)
  pwm: pca9685: Convert to i2c's .probe_new()
  pwm: sun4i: Propagate errors in .get_state() to the caller
  pwm: Handle .get_state() failures
  pwm: sprd: Propagate errors in .get_state() to the caller
  pwm: rockchip: Propagate errors in .get_state() to the caller
  pwm: mtk-disp: Propagate errors in .get_state() to the caller
  pwm: imx27: Propagate errors in .get_state() to the caller
  pwm: cros-ec: Propagate errors in .get_state() to the caller
  pwm: crc: Propagate errors in .get_state() to the caller
  leds: qcom-lpg: Propagate errors in .get_state() to the caller
  drm/bridge: ti-sn65dsi86: Propagate errors in .get_state() to the caller
  pwm/tracing: Also record trace events for failed API calls
  pwm: Make .get_state() callback return an error code
  pwm: pxa: Enable for MMP platform
  pwm: pxa: Add reference manual link and limitations
  pwm: pxa: Use abrupt shutdown mode
  pwm: pxa: Remove clk enable/disable from pxa_pwm_config
  pwm: pxa: Set duty cycle to 0 when disabling PWM
  pwm: pxa: Remove pxa_pwm_enable/disable
  pwm: mediatek: Add support for MT7986
  ...
  • Loading branch information
Linus Torvalds committed Dec 21, 2022
2 parents 9cf5b50 + 8fa22f4 commit 7a693ea
Show file tree
Hide file tree
Showing 42 changed files with 299 additions and 229 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ properties:
- renesas,pwm-r8a77980 # R-Car V3H
- renesas,pwm-r8a77990 # R-Car E3
- renesas,pwm-r8a77995 # R-Car D3
- renesas,pwm-r8a779g0 # R-Car V4H
- const: renesas,pwm-rcar

reg:
Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ properties:
- renesas,tpu-r8a77970 # R-Car V3M
- renesas,tpu-r8a77980 # R-Car V3H
- renesas,tpu-r8a779a0 # R-Car V3U
- renesas,tpu-r8a779g0 # R-Car V4H
- const: renesas,tpu

reg:
Expand Down
9 changes: 6 additions & 3 deletions drivers/gpio/gpio-mvebu.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,9 +657,10 @@ static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
spin_unlock_irqrestore(&mvpwm->lock, flags);
}

static void mvebu_pwm_get_state(struct pwm_chip *chip,
struct pwm_device *pwm,
struct pwm_state *state) {
static int mvebu_pwm_get_state(struct pwm_chip *chip,
struct pwm_device *pwm,
struct pwm_state *state)
{

struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
Expand Down Expand Up @@ -693,6 +694,8 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
state->enabled = false;

spin_unlock_irqrestore(&mvpwm->lock, flags);

return 0;
}

static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
Expand Down
14 changes: 8 additions & 6 deletions drivers/gpu/drm/bridge/ti-sn65dsi86.c
Original file line number Diff line number Diff line change
Expand Up @@ -1500,8 +1500,8 @@ static int ti_sn_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}

static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
static int ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct ti_sn65dsi86 *pdata = pwm_chip_to_ti_sn_bridge(chip);
unsigned int pwm_en_inv;
Expand All @@ -1512,19 +1512,19 @@ static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,

ret = regmap_read(pdata->regmap, SN_PWM_EN_INV_REG, &pwm_en_inv);
if (ret)
return;
return ret;

ret = ti_sn65dsi86_read_u16(pdata, SN_BACKLIGHT_SCALE_REG, &scale);
if (ret)
return;
return ret;

ret = ti_sn65dsi86_read_u16(pdata, SN_BACKLIGHT_REG, &backlight);
if (ret)
return;
return ret;

ret = regmap_read(pdata->regmap, SN_PWM_PRE_DIV_REG, &pre_div);
if (ret)
return;
return ret;

state->enabled = FIELD_GET(SN_PWM_EN_MASK, pwm_en_inv);
if (FIELD_GET(SN_PWM_INV_MASK, pwm_en_inv))
Expand All @@ -1539,6 +1539,8 @@ static void ti_sn_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,

if (state->duty_cycle > state->period)
state->duty_cycle = state->period;

return 0;
}

static const struct pwm_ops ti_sn_pwm_ops = {
Expand Down
14 changes: 8 additions & 6 deletions drivers/leds/rgb/leds-qcom-lpg.c
Original file line number Diff line number Diff line change
Expand Up @@ -972,8 +972,8 @@ static int lpg_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return ret;
}

static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
static int lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct lpg *lpg = container_of(chip, struct lpg, pwm);
struct lpg_channel *chan = &lpg->channels[pwm->hwpwm];
Expand All @@ -986,20 +986,20 @@ static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,

ret = regmap_read(lpg->map, chan->base + LPG_SIZE_CLK_REG, &val);
if (ret)
return;
return ret;

refclk = lpg_clk_rates[val & PWM_CLK_SELECT_MASK];
if (refclk) {
ret = regmap_read(lpg->map, chan->base + LPG_PREDIV_CLK_REG, &val);
if (ret)
return;
return ret;

pre_div = lpg_pre_divs[FIELD_GET(PWM_FREQ_PRE_DIV_MASK, val)];
m = FIELD_GET(PWM_FREQ_EXP_MASK, val);

ret = regmap_bulk_read(lpg->map, chan->base + PWM_VALUE_REG, &pwm_value, sizeof(pwm_value));
if (ret)
return;
return ret;

state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * LPG_RESOLUTION * pre_div * (1 << m), refclk);
state->duty_cycle = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * pwm_value * pre_div * (1 << m), refclk);
Expand All @@ -1010,13 +1010,15 @@ static void lpg_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,

ret = regmap_read(lpg->map, chan->base + PWM_ENABLE_CONTROL_REG, &val);
if (ret)
return;
return ret;

state->enabled = FIELD_GET(LPG_ENABLE_CONTROL_OUTPUT, val);
state->polarity = PWM_POLARITY_NORMAL;

if (state->duty_cycle > state->period)
state->duty_cycle = state->period;

return 0;
}

static const struct pwm_ops lpg_pwm_ops = {
Expand Down
6 changes: 3 additions & 3 deletions drivers/pwm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ config PWM_IQS620A

config PWM_JZ4740
tristate "Ingenic JZ47xx PWM support"
depends on MIPS || COMPILE_TEST
depends on COMMON_CLK
depends on MACH_INGENIC || COMPILE_TEST
depends on COMMON_CLK && OF
select MFD_SYSCON
help
Generic PWM framework driver for Ingenic JZ47xx based
Expand Down Expand Up @@ -434,7 +434,7 @@ config PWM_PCA9685

config PWM_PXA
tristate "PXA PWM support"
depends on ARCH_PXA || COMPILE_TEST
depends on ARCH_PXA || ARCH_MMP || COMPILE_TEST
depends on HAS_IOMEM
help
Generic PWM framework driver for PXA.
Expand Down
68 changes: 38 additions & 30 deletions drivers/pwm/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@

static DEFINE_MUTEX(pwm_lookup_lock);
static LIST_HEAD(pwm_lookup_list);

/* protects access to pwm_chips, allocated_pwms, and pwm_tree */
static DEFINE_MUTEX(pwm_lock);

static LIST_HEAD(pwm_chips);
static DECLARE_BITMAP(allocated_pwms, MAX_PWMS);
static RADIX_TREE(pwm_tree, GFP_KERNEL);
Expand All @@ -37,6 +40,7 @@ static struct pwm_device *pwm_to_device(unsigned int pwm)
return radix_tree_lookup(&pwm_tree, pwm);
}

/* Called with pwm_lock held */
static int alloc_pwms(unsigned int count)
{
unsigned int start;
Expand All @@ -47,9 +51,12 @@ static int alloc_pwms(unsigned int count)
if (start + count > MAX_PWMS)
return -ENOSPC;

bitmap_set(allocated_pwms, start, count);

return start;
}

/* Called with pwm_lock held */
static void free_pwms(struct pwm_chip *chip)
{
unsigned int i;
Expand Down Expand Up @@ -108,8 +115,13 @@ static int pwm_device_request(struct pwm_device *pwm, const char *label)
}

if (pwm->chip->ops->get_state) {
pwm->chip->ops->get_state(pwm->chip, pwm, &pwm->state);
trace_pwm_get(pwm, &pwm->state);
struct pwm_state state;

err = pwm->chip->ops->get_state(pwm->chip, pwm, &state);
trace_pwm_get(pwm, &state, err);

if (!err)
pwm->state = state;

if (IS_ENABLED(CONFIG_PWM_DEBUG))
pwm->last = pwm->state;
Expand Down Expand Up @@ -267,20 +279,21 @@ int pwmchip_add(struct pwm_chip *chip)
if (!pwm_ops_check(chip))
return -EINVAL;

chip->pwms = kcalloc(chip->npwm, sizeof(*pwm), GFP_KERNEL);
if (!chip->pwms)
return -ENOMEM;

mutex_lock(&pwm_lock);

ret = alloc_pwms(chip->npwm);
if (ret < 0)
goto out;
if (ret < 0) {
mutex_unlock(&pwm_lock);
kfree(chip->pwms);
return ret;
}

chip->base = ret;

chip->pwms = kcalloc(chip->npwm, sizeof(*pwm), GFP_KERNEL);
if (!chip->pwms) {
ret = -ENOMEM;
goto out;
}

for (i = 0; i < chip->npwm; i++) {
pwm = &chip->pwms[i];

Expand All @@ -291,23 +304,16 @@ int pwmchip_add(struct pwm_chip *chip)
radix_tree_insert(&pwm_tree, pwm->pwm, pwm);
}

bitmap_set(allocated_pwms, chip->base, chip->npwm);

INIT_LIST_HEAD(&chip->list);
list_add(&chip->list, &pwm_chips);

ret = 0;
mutex_unlock(&pwm_lock);

if (IS_ENABLED(CONFIG_OF))
of_pwmchip_add(chip);

out:
mutex_unlock(&pwm_lock);

if (!ret)
pwmchip_sysfs_export(chip);
pwmchip_sysfs_export(chip);

return ret;
return 0;
}
EXPORT_SYMBOL_GPL(pwmchip_add);

Expand Down Expand Up @@ -457,8 +463,11 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,
* checks.
*/

chip->ops->get_state(chip, pwm, &s1);
trace_pwm_get(pwm, &s1);
err = chip->ops->get_state(chip, pwm, &s1);
trace_pwm_get(pwm, &s1, err);
if (err)
/* If that failed there isn't much to debug */
return;

/*
* The lowlevel driver either ignored .polarity (which is a bug) or as
Expand Down Expand Up @@ -514,16 +523,17 @@ static void pwm_apply_state_debug(struct pwm_device *pwm,

/* reapply the state that the driver reported being configured. */
err = chip->ops->apply(chip, pwm, &s1);
trace_pwm_apply(pwm, &s1, err);
if (err) {
*last = s1;
dev_err(chip->dev, "failed to reapply current setting\n");
return;
}

trace_pwm_apply(pwm, &s1);

chip->ops->get_state(chip, pwm, last);
trace_pwm_get(pwm, last);
err = chip->ops->get_state(chip, pwm, last);
trace_pwm_get(pwm, last, err);
if (err)
return;

/* reapplication of the current state should give an exact match */
if (s1.enabled != last->enabled ||
Expand Down Expand Up @@ -571,11 +581,10 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state)
return 0;

err = chip->ops->apply(chip, pwm, state);
trace_pwm_apply(pwm, state, err);
if (err)
return err;

trace_pwm_apply(pwm, state);

pwm->state = *state;

/*
Expand Down Expand Up @@ -1179,8 +1188,7 @@ DEFINE_SEQ_ATTRIBUTE(pwm_debugfs);

static int __init pwm_debugfs_init(void)
{
debugfs_create_file("pwm", S_IFREG | 0444, NULL, NULL,
&pwm_debugfs_fops);
debugfs_create_file("pwm", 0444, NULL, NULL, &pwm_debugfs_fops);

return 0;
}
Expand Down
6 changes: 4 additions & 2 deletions drivers/pwm/pwm-atmel.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
return 0;
}

static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
static int atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
u32 sr, cmr;
Expand Down Expand Up @@ -396,6 +396,8 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
state->polarity = PWM_POLARITY_INVERSED;
else
state->polarity = PWM_POLARITY_NORMAL;

return 0;
}

static const struct pwm_ops atmel_pwm_ops = {
Expand Down
8 changes: 5 additions & 3 deletions drivers/pwm/pwm-bcm-iproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ static void iproc_pwmc_disable(struct iproc_pwmc *ip, unsigned int channel)
ndelay(400);
}

static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
static int iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct iproc_pwmc *ip = to_iproc_pwmc(chip);
u64 tmp, multi, rate;
Expand All @@ -91,7 +91,7 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
if (rate == 0) {
state->period = 0;
state->duty_cycle = 0;
return;
return 0;
}

value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
Expand All @@ -107,6 +107,8 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
tmp = (value & IPROC_PWM_PERIOD_MAX) * multi;
state->duty_cycle = div64_u64(tmp, rate);

return 0;
}

static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
Expand Down
Loading

0 comments on commit 7a693ea

Please sign in to comment.