From: Boris Brezillon <hidden> Date: 2016-03-30 20:04:38
Hello,
This series adds support for atomic PWM update, or IOW, the capability
to update all the parameters of a PWM device (enabled/disabled, period,
duty and polarity) in one go.
It also adds support for initial PWM state retrieval (or hardware readout),
which should allow smooth handover between the bootloader and Linux. For
example, critical PWM users (like critical regulators controlled by a PWM)
can query the current PWM state, and adapt the PWM config without having
to disable/enable the PWM, or abruptly change the period/dutycyle/polarity
config.
Thierry, I hope this version meets your expectations, if that's not the
case, could you let me know quickly so I can adjust the implementation
accordingly (I'd really like to get most of those changes in 4.7).
Best Regards,
Boris
Changes since v4:
- introduce pwm_args to expose per-board/platform config
- deprecate non-atomic APIs
- implement non-atomic functions as wrappers around atomic ones
- patch all PWM users to use the atomic API
- rename the ->reset_state() hook into ->get_state()
- drop most acks
- rework PWM config in the pwm-regulator driver
- patch sun4i and sti PWM drivers to support HW readout
Changes since v3:
- rebased on pwm/for-next after pulling 4.4-rc1
- replace direct access to pwm fields by pwm_get/set_xxx() helpers, thus
fixing some build errors
- split changes to allow each maintainer to review/ack or take the
modification through its subsystem
Changes since v2:
- rebased on top of 4.3-rc2
- reintroduced pwm-regulator patches
Changes since v1:
- dropped applied patches
- squashed Heiko's fixes into the rockchip driver changes
- made a few cosmetic changes
- added kerneldoc comments
- added Heiko's patch to display more information in debugfs
- dropped pwm-regulator patches (should be submitted separately)
*** BLURB HERE ***
Boris Brezillon (45):
pwm: rcar: make use of pwm_is_enabled()
backlight: pwm_bl: remove useless call to pwm_set_period()
backlight: lm3630a_bl: stop messing with the pwm->period field
pwm: get rid of pwm->lock
pwm: introduce the pwm_args concept
pwm: use pwm_get/set_xxx() helpers where appropriate
clk: pwm: use pwm_get_args() where appropriate
hwmon: pwm-fan: use pwm_get_args() where appropriate
misc: max77693-haptic: use pwm_get_args() where appropriate
leds: pwm: use pwm_get_args() where appropriate
regulator: pwm: use pwm_get_args() where appropriate
fbdev: ssd1307fb: use pwm_get_args() where appropriate
backlight: pwm_bl: use pwm_get_args() where appropriate
pwm: keep PWM state in sync with hardware state
pwm: introduce the pwm_state concept
pwm: move the enabled/disabled info into pwm_state
pwm: add the PWM initial state retrieval infra
pwm: add the core infrastructure to allow atomic update
pwm: switch to the atomic API
pwm: rockchip: add initial state retrieval
pwm: rockchip: avoid glitches on already running PWMs
pwm: rockchip: add support for atomic update
pwm: sti: add support for initial state retrieval
pwm: sti: avoid glitches on already running PWMs
pwm: sun4i: implement hardware readout
regulator: pwm: adjust PWM config at probe time
regulator: pwm: swith to the atomic PWM API
regulator: pwm: properly initialize the ->state field
regulator: pwm: retrieve correct voltage
pwm: update documentation
pwm: deprecate pwm_config(), pwm_enable() and pwm_disable()
pwm: replace pwm_disable() by pwm_apply_state()
clk: pwm: switch to the atomic API
hwmon: pwm-fan: switch to the atomic API
input: misc: max77693: switch to the atomic API
input: misc: max8997: switch to the atomic PWM API
input: misc: pwm-beeper: switch to the atomic PWM API
leds: pwm: switch to the atomic PWM API
backlight: lm3630a: switch to the atomic PWM API
backlight: lp855x: switch to the atomic PWM API
backlight: lp8788: switch to the atomic PWM API
backlight: pwm_bl: switch to the atomic PWM API
video: ssd1307fb: switch to the atomic PWM API
drm: i915: switch to the atomic PWM API
ARM: s3c24xx: rx1950: switch to the atomic PWM API
Heiko Stübner (1):
pwm: add information about polarity, duty cycle and period to debugfs
Documentation/pwm.txt | 27 +++-
arch/arm/mach-s3c24xx/mach-rx1950.c | 17 +-
drivers/clk/clk-pwm.c | 36 ++++-
drivers/gpu/drm/i915/intel_panel.c | 39 +++--
drivers/hwmon/pwm-fan.c | 88 ++++++----
drivers/input/misc/max77693-haptic.c | 28 +++-
drivers/input/misc/max8997_haptic.c | 23 ++-
drivers/input/misc/pwm-beeper.c | 46 ++++--
drivers/leds/leds-pwm.c | 15 +-
drivers/pwm/core.c | 186 ++++++++++-----------
drivers/pwm/pwm-clps711x.c | 2 +-
drivers/pwm/pwm-crc.c | 2 +-
drivers/pwm/pwm-lpc18xx-sct.c | 9 +-
drivers/pwm/pwm-lpc32xx.c | 9 +-
drivers/pwm/pwm-omap-dmtimer.c | 2 +-
drivers/pwm/pwm-pxa.c | 2 +-
drivers/pwm/pwm-rcar.c | 2 +-
drivers/pwm/pwm-rockchip.c | 156 +++++++++++++++---
drivers/pwm/pwm-spear.c | 9 +-
drivers/pwm/pwm-sti.c | 67 +++++++-
drivers/pwm/pwm-sun4i.c | 73 ++++++---
drivers/pwm/sysfs.c | 98 ++++++++---
drivers/regulator/pwm-regulator.c | 151 ++++++++++++++---
drivers/video/backlight/lm3630a_bl.c | 15 +-
drivers/video/backlight/lp855x_bl.c | 15 +-
drivers/video/backlight/lp8788_bl.c | 17 +-
drivers/video/backlight/pwm_bl.c | 51 +++---
drivers/video/fbdev/ssd1307fb.c | 28 +++-
include/linux/pwm.h | 303 ++++++++++++++++++++++++++---------
29 files changed, 1096 insertions(+), 420 deletions(-)
--
2.5.0
From: Boris Brezillon <hidden> Date: 2016-03-30 20:04:35
Commit 5c31252c4a86 ("pwm: Add the pwm_is_enabled() helper") introduced a
new function to test whether a PWM device is enabled or not without
manipulating PWM internal fields.
Hiding this is necessary if we want to smoothly move to the atomic PWM
config approach without impacting PWM drivers.
Fix this driver to use pwm_is_enabled() instead of directly accessing the
->flags field.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/pwm-rcar.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
@@ -157,7 +157,7 @@ static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,returndiv;/* Let the core driver set pwm->period if disabled and duty_ns = 0 */-if(!test_bit(PWMF_ENABLED,&pwm->flags)&&!duty_ns)+if(!pwm_is_enabled(pwm)&&!duty_ns)return0;rcar_pwm_update(rp,RCAR_PWMCR_SYNC,RCAR_PWMCR_SYNC,RCAR_PWMCR);
From: Boris Brezillon <hidden> Date: 2016-03-30 20:04:42
The PWM period will be set when calling pwm_config. Remove this useless
call to pwm_set_period(), which might mess up with the internal PWM state.
Signed-off-by: Boris Brezillon <redacted>
Acked-by: Lee Jones <redacted>
---
drivers/video/backlight/pwm_bl.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:04:47
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/clk/clk-pwm.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
@@ -71,22 +72,23 @@ static int clk_pwm_probe(struct platform_device *pdev)if(IS_ERR(pwm))returnPTR_ERR(pwm);-if(!pwm->period){+pwm_get_args(pwm,&pargs);+if(!pargs.period){dev_err(&pdev->dev,"invalid PWM period\n");return-EINVAL;}if(of_property_read_u32(node,"clock-frequency",&clk_pwm->fixed_rate))-clk_pwm->fixed_rate=NSEC_PER_SEC/pwm->period;+clk_pwm->fixed_rate=NSEC_PER_SEC/pargs.period;-if(pwm->period!=NSEC_PER_SEC/clk_pwm->fixed_rate&&-pwm->period!=DIV_ROUND_UP(NSEC_PER_SEC,clk_pwm->fixed_rate)){+if(pargs.period!=NSEC_PER_SEC/clk_pwm->fixed_rate&&+pargs.period!=DIV_ROUND_UP(NSEC_PER_SEC,clk_pwm->fixed_rate)){dev_err(&pdev->dev,"clock-frequency does not match PWM period\n");return-EINVAL;}-ret=pwm_config(pwm,(pwm->period+1)>>1,pwm->period);+ret=pwm_config(pwm,(pargs.period+1)>>1,pargs.period);if(ret<0)returnret;
From: Boris Brezillon <hidden> Date: 2016-03-30 20:04:51
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/hwmon/pwm-fan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
@@ -214,6 +217,7 @@ static int pwm_fan_of_get_cooling_data(struct device *dev,staticintpwm_fan_probe(structplatform_device*pdev){structthermal_cooling_device*cdev;+structpwm_argspargs={};structpwm_fan_ctx*ctx;structdevice*hwmon;intduty_cycle;
@@ -234,10 +238,11 @@ static int pwm_fan_probe(struct platform_device *pdev)platform_set_drvdata(pdev,ctx);/* Set duty cycle to maximum allowed */-duty_cycle=ctx->pwm->period-1;+pwm_get_args(ctx->pwm,&pargs);+duty_cycle=pargs.period-1;ctx->pwm_value=MAX_PWM;-ret=pwm_config(ctx->pwm,duty_cycle,ctx->pwm->period);+ret=pwm_config(ctx->pwm,duty_cycle,pargs.period);if(ret){dev_err(&pdev->dev,"Failed to configure PWM\n");returnret;
@@ -303,14 +308,16 @@ static int pwm_fan_suspend(struct device *dev)staticintpwm_fan_resume(structdevice*dev){structpwm_fan_ctx*ctx=dev_get_drvdata(dev);+structpwm_argspargs={};unsignedlongduty;intret;if(ctx->pwm_value=0)return0;-duty=DIV_ROUND_UP(ctx->pwm_value*(ctx->pwm->period-1),MAX_PWM);-ret=pwm_config(ctx->pwm,duty,ctx->pwm->period);+pwm_get_args(ctx->pwm,&pargs);+duty=DIV_ROUND_UP(ctx->pwm_value*(pargs.period-1),MAX_PWM);+ret=pwm_config(ctx->pwm,duty,pargs.period);if(ret)returnret;returnpwm_enable(ctx->pwm);
From: Boris Brezillon <hidden> Date: 2016-03-30 20:04:57
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/video/fbdev/ssd1307fb.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:00
Before the introduction of pwm_args, the core and some drivers were
resetting the PWM period and polarity states to the reference values
(those provided through the DT, a PWM lookup table or hardcoded in the
driver).
Now that all PWM users are correctly using pwm_args to configure their
PWM device, we can safely remove some pwm_set_period/polarity() calls.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/core.c | 5 -----
drivers/pwm/pwm-clps711x.c | 1 -
drivers/pwm/pwm-pxa.c | 1 -
3 files changed, 7 deletions(-)
@@ -61,7 +61,6 @@ static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)/* Store constant period value */pwm->args.period=DIV_ROUND_CLOSEST(NSEC_PER_SEC,freq);-pwm_set_period(pwm,pwm->args.period);return0;}
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:05
Add a ->get_state() function to the pwm_ops struct to let PWM drivers
initialize the PWM state attached to a PWM device.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/core.c | 3 +++
include/linux/pwm.h | 5 +++++
2 files changed, 8 insertions(+)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:12
From: Heiko Stübner <heiko@sntech.de>
The pwm-states make it possible to also output the polarity, duty cycle
and period information in the debugfs pwm summary-outout.
This makes it easier to gather overview information about pwms without
needing to walk through the sysfs attributes of every pwm.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/core.c | 5 +++++
1 file changed, 5 insertions(+)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:23
The current logic will disable the PWM clk even if the PWM was left
enabled by the bootloader (because it's controlling a critical device
like a regulator for example).
Keep the PWM clk enabled if the PWM is enabled to avoid any glitches.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/pwm-rockchip.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
@@ -302,6 +302,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev){conststructof_device_id*id;structrockchip_pwm_chip*pc;+structpwm_statepstate;structresource*r;intret;
@@ -322,7 +323,7 @@ static int rockchip_pwm_probe(struct platform_device *pdev)if(IS_ERR(pc->clk))returnPTR_ERR(pc->clk);-ret=clk_prepare(pc->clk);+ret=clk_prepare_enable(pc->clk);if(ret)returnret;
@@ -345,12 +346,33 @@ static int rockchip_pwm_probe(struct platform_device *pdev)dev_err(&pdev->dev,"pwmchip_add() failed: %d\n",ret);}+/* Keep the PWM clk enabled if the PWM appears to be up and running. */+pwm_get_state(pc->chip.pwms,&pstate);+if(!pstate.enabled)+clk_disable(pc->clk);+returnret;}staticintrockchip_pwm_remove(structplatform_device*pdev){structrockchip_pwm_chip*pc=platform_get_drvdata(pdev);+structpwm_statepstate;++/*+*DisablethePWMclkbeforeunpreparingitifthePWMdeviceisstill+*running.ThisshouldonlyhappenwhenthelastPWMuserleftit+*enabled,orwhennobodyrequestedaPWMthatwaspreviouslyenabled+*bythebootloader.+*+*FIXME:MaybethecoreshoulddisableallPWMdevicesin+*pwmchip_remove().Inthiscasewe'donlyhavetocall+*clk_unprepare()afterpwmchip_remove().+*+*/+pwm_get_state(pc->chip.pwms,&pstate);+if(pstate.enabled)+clk_disable(pc->clk);clk_unprepare(pc->clk);
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:37
The current logic will disable the PWM clk even if a PWM was left
enabled by the bootloader (because it's controlling a critical device
like a regulator for example).
Keep the PWM clk enabled if at least one PWM is enabled to avoid any
glitches.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/pwm-sti.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:42
Implement ->get_state() instead of only initializing the polarity in
the probe function.
This implementation also takes care of keeping the PWM clk enabled if at
least one of the PWM exported by the PWM chip is already enabled, which
should prevent glitches.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/pwm-sun4i.c | 74 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 55 insertions(+), 19 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:46
The continuous PWM voltage regulator is caching the voltage value in
the ->volt_uV field. While most of the time this value should reflect the
real voltage, sometime it can be sightly different if the PWM device
rounded the set_duty_cycle request.
Moreover, this value is not valid until someone has modified the regulator
output.
Remove the ->volt_uV field and always rely on the PWM state to calculate
the regulator output.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/regulator/pwm-regulator.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
@@ -35,9 +35,6 @@ struct pwm_regulator_data {structregulator_opsops;intstate;--/* Continuous voltage */-intvolt_uV;};structpwm_voltages{
@@ -167,11 +164,27 @@ static int pwm_voltage_to_duty_cycle_percentage(struct regulator_dev *rdev, intreturn((req_uV*100)-(min_uV*100))/diff;}+staticintpwm_duty_cycle_percentage_to_voltage(structregulator_dev*rdev,+intdutycycle)+{+intmin_uV=rdev->constraints->min_uV;+intmax_uV=rdev->constraints->max_uV;+intdiff=max_uV-min_uV;++returnmin_uV+((diff*dutycycle)/100);+}+staticintpwm_regulator_get_voltage(structregulator_dev*rdev){structpwm_regulator_data*drvdata=rdev_get_drvdata(rdev);+structpwm_statepstate;+u64dutycycle;-returndrvdata->volt_uV;+pwm_get_state(drvdata->pwm,&pstate);+dutycycle=pstate.duty_cycle*100;+do_div(dutycycle,pstate.period);++returnpwm_duty_cycle_percentage_to_voltage(rdev,dutycycle);}staticintpwm_regulator_set_voltage(structregulator_dev*rdev,
@@ -196,8 +209,6 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev,returnret;}-drvdata->volt_uV=min_uV;-/* Delay required by PWM regulator to settle to the new voltage */usleep_range(ramp_delay,ramp_delay+1000);
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:51
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/hwmon/pwm-fan.c | 81 ++++++++++++++++++++++++++++---------------------
1 file changed, 46 insertions(+), 35 deletions(-)
@@ -50,19 +50,17 @@ static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)if(ctx->pwm_value=pwm)gotoexit_set_pwm_err;-duty=DIV_ROUND_UP(pwm*(pargs.period-1),MAX_PWM);-ret=pwm_config(ctx->pwm,duty,pargs.period);-if(ret)-gotoexit_set_pwm_err;-+pwm_get_state(ctx->pwm,&pstate);+pstate.period=pargs.period;+pstate.duty_cycle=DIV_ROUND_UP(pwm*(pargs.period-1),MAX_PWM);if(pwm=0)-pwm_disable(ctx->pwm);+pstate.enabled=false;+else+pstate.enabled=true;-if(ctx->pwm_value=0){-ret=pwm_enable(ctx->pwm);-if(ret)-gotoexit_set_pwm_err;-}+ret=pwm_apply_state(ctx->pwm,&pstate);+if(ret)+gotoexit_set_pwm_err;ctx->pwm_value=pwm;exit_set_pwm_err:
@@ -217,10 +215,10 @@ static int pwm_fan_of_get_cooling_data(struct device *dev,staticintpwm_fan_probe(structplatform_device*pdev){structthermal_cooling_device*cdev;+structpwm_statepstate;structpwm_argspargs={};structpwm_fan_ctx*ctx;structdevice*hwmon;-intduty_cycle;intret;ctx=devm_kzalloc(&pdev->dev,sizeof(*ctx),GFP_KERNEL);
@@ -239,27 +237,25 @@ static int pwm_fan_probe(struct platform_device *pdev)/* Set duty cycle to maximum allowed */pwm_get_args(ctx->pwm,&pargs);-duty_cycle=pargs.period-1;+pwm_get_state(ctx->pwm,&pstate);++pstate.period=pargs.period;+pstate.duty_cycle=pargs.period-1;+pstate.enabled=true;ctx->pwm_value=MAX_PWM;-ret=pwm_config(ctx->pwm,duty_cycle,pargs.period);+ret=pwm_apply_state(ctx->pwm,&pstate);if(ret){dev_err(&pdev->dev,"Failed to configure PWM\n");returnret;}-/* Enbale PWM output */-ret=pwm_enable(ctx->pwm);-if(ret){-dev_err(&pdev->dev,"Failed to enable PWM\n");-returnret;-}-hwmon=devm_hwmon_device_register_with_groups(&pdev->dev,"pwmfan",ctx,pwm_fan_groups);if(IS_ERR(hwmon)){dev_err(&pdev->dev,"Failed to register hwmon device\n");-pwm_disable(ctx->pwm);+pstate.enabled=false;+pwm_apply_state(ctx->pwm,&pstate);returnPTR_ERR(hwmon);}
@@ -275,7 +271,8 @@ static int pwm_fan_probe(struct platform_device *pdev)if(IS_ERR(cdev)){dev_err(&pdev->dev,"Failed to register pwm-fan as cooling device");-pwm_disable(ctx->pwm);+pstate.enabled=false;+pwm_apply_state(ctx->pwm,&pstate);returnPTR_ERR(cdev);}ctx->cdev=cdev;
@@ -290,8 +287,14 @@ static int pwm_fan_remove(struct platform_device *pdev)structpwm_fan_ctx*ctx=platform_get_drvdata(pdev);thermal_cooling_device_unregister(ctx->cdev);-if(ctx->pwm_value)-pwm_disable(ctx->pwm);+if(ctx->pwm_value){+structpwm_statepstate;++pwm_get_state(ctx->pwm,&pstate);+pstate.enabled=false;+pwm_apply_state(ctx->pwm,&pstate);+}+return0;}
@@ -300,27 +303,35 @@ static int pwm_fan_suspend(struct device *dev){structpwm_fan_ctx*ctx=dev_get_drvdata(dev);-if(ctx->pwm_value)-pwm_disable(ctx->pwm);+if(ctx->pwm_value){+structpwm_statepstate;++pwm_get_state(ctx->pwm,&pstate);+pstate.enabled=false;+pwm_apply_state(ctx->pwm,&pstate);+}+return0;}staticintpwm_fan_resume(structdevice*dev){structpwm_fan_ctx*ctx=dev_get_drvdata(dev);+structpwm_statepstate;structpwm_argspargs={};-unsignedlongduty;-intret;if(ctx->pwm_value=0)return0;pwm_get_args(ctx->pwm,&pargs);-duty=DIV_ROUND_UP(ctx->pwm_value*(pargs.period-1),MAX_PWM);-ret=pwm_config(ctx->pwm,duty,pargs.period);-if(ret)-returnret;-returnpwm_enable(ctx->pwm);+pwm_get_state(ctx->pwm,&pstate);++pstate.period=pargs.period;+pstate.duty_cycle=DIV_ROUND_UP(ctx->pwm_value*(pargs.period-1),+MAX_PWM);+pstate.enabled=true;++returnpwm_apply_state(ctx->pwm,&pstate);}#endif
From: Boris Brezillon <hidden> Date: 2016-03-30 20:05:56
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/input/misc/max77693-haptic.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:06:01
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/video/backlight/lm3630a_bl.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
@@ -162,14 +162,16 @@ static int lm3630a_intr_config(struct lm3630a_chip *pchip)staticvoidlm3630a_pwm_ctrl(structlm3630a_chip*pchip,intbr,intbr_max){-unsignedintperiod=pchip->pdata->pwm_period;-unsignedintduty=br*period/br_max;+structpwm_statepstate;-pwm_config(pchip->pwmd,duty,period);-if(duty)-pwm_enable(pchip->pwmd);+pwm_get_state(pchip->pwmd,&pstate);+pstate.period=pchip->pdata->pwm_period;+pstate.duty_cycle=br*pstate.period/br_max;+if(pstate.duty_cycle)+pstate.enabled=true;else-pwm_disable(pchip->pwmd);+pstate.enabled=false;+pwm_apply_state(pchip->pwmd,&pstate);}/* update and get brightness */
From: Boris Brezillon <hidden> Date: 2016-03-30 20:06:05
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/video/backlight/lp855x_bl.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
@@ -235,8 +235,7 @@ err:staticvoidlp855x_pwm_ctrl(structlp855x*lp,intbr,intmax_br){-unsignedintperiod=lp->pdata->period_ns;-unsignedintduty=br*period/max_br;+structpwm_statepstate;structpwm_device*pwm;/* request pwm device with the consumer name */
@@ -248,11 +247,15 @@ static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br)lp->pwm=pwm;}-pwm_config(lp->pwm,duty,period);-if(duty)-pwm_enable(lp->pwm);+pwm_get_state(lp->pwm,&pstate);+pstate.period=lp->pdata->period_ns;+pstate.duty_cycle=br*pstate.period/max_br;+if(pstate.duty_cycle)+pstate.enabled=true;else-pwm_disable(lp->pwm);+pstate.enabled=false;++pwm_apply_state(lp->pwm,&pstate);}staticintlp855x_bl_update_status(structbacklight_device*bl)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:06:12
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/video/backlight/lp8788_bl.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
@@ -124,16 +124,13 @@ static int lp8788_backlight_configure(struct lp8788_bl *bl)staticvoidlp8788_pwm_ctrl(structlp8788_bl*bl,intbr,intmax_br){-unsignedintperiod;-unsignedintduty;structdevice*dev;+structpwm_statepstate;structpwm_device*pwm;if(!bl->pdata)return;-period=bl->pdata->period_ns;-duty=br*period/max_br;dev=bl->lp->dev;/* request PWM device with the consumer name */
@@ -147,11 +144,15 @@ static void lp8788_pwm_ctrl(struct lp8788_bl *bl, int br, int max_br)bl->pwm=pwm;}-pwm_config(bl->pwm,duty,period);-if(duty)-pwm_enable(bl->pwm);+pwm_get_state(bl->pwm,&pstate);+pstate.period=bl->pdata->period_ns;+pstate.duty_cycle=br*pstate.period/max_br;+if(pstate.duty_cycle)+pstate.enabled=true;else-pwm_disable(bl->pwm);+pstate.enabled=false;++pwm_apply_state(bl->pwm,&pstate);}staticintlp8788_bl_update_status(structbacklight_device*bl_dev)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:06:21
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/video/fbdev/ssd1307fb.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
@@ -289,6 +289,8 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)structpwm_argspargs={};if(par->device_info->need_pwm){+structpwm_statepstate;+par->pwm=pwm_get(&par->client->dev,NULL);if(IS_ERR(par->pwm)){dev_err(&par->client->dev,"Could not get PWM from device tree!\n");
@@ -296,10 +298,14 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)}pwm_get_args(par->pwm,&pargs);+pwm_get_state(par->pwm,&pstate);par->pwm_period=pargs.period;+/* Enable the PWM */-pwm_config(par->pwm,par->pwm_period/2,par->pwm_period);-pwm_enable(par->pwm);+pstate.period=pargs.period;+pstate.duty_cycle=pstate.period/2;+pstate.enabled=true;+pwm_apply_state(par->pwm,&pstate);dev_dbg(&par->client->dev,"Using PWM%d with a %dns period.\n",par->pwm->pwm,par->pwm_period);
@@ -685,8 +691,12 @@ static int ssd1307fb_probe(struct i2c_client *client,bl_init_error:unregister_framebuffer(info);panel_init_error:-if(par->device_info->need_pwm){-pwm_disable(par->pwm);+if(par->device_info->need_pwm&&par->pwm){+structpwm_statepstate;++pwm_get_state(par->pwm,&pstate);+pstate.enabled=false;+pwm_apply_state(par->pwm,&pstate);pwm_put(par->pwm);};reset_oled_error:
@@ -707,7 +717,11 @@ static int ssd1307fb_remove(struct i2c_client *client)unregister_framebuffer(info);if(par->device_info->need_pwm){-pwm_disable(par->pwm);+structpwm_statepstate;++pwm_get_state(par->pwm,&pstate);+pstate.enabled=false;+pwm_apply_state(par->pwm,&pstate);pwm_put(par->pwm);};fb_deferred_io_cleanup(info);
From: Boris Brezillon <hidden> Date: 2016-03-30 20:06:27
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/gpu/drm/i915/intel_panel.c | 39 +++++++++++++++++++++++++-------------
1 file changed, 26 insertions(+), 13 deletions(-)
@@ -1630,6 +1640,7 @@ static int pwm_setup_backlight(struct intel_connector *connector,{structdrm_device*dev=connector->base.dev;structintel_panel*panel=&connector->panel;+structpwm_statepstate;intretval;/* Get the PWM chip for backlight control */
@@ -1640,8 +1651,10 @@ static int pwm_setup_backlight(struct intel_connector *connector,return-ENODEV;}-retval=pwm_config(panel->backlight.pwm,CRC_PMIC_PWM_PERIOD_NS,-CRC_PMIC_PWM_PERIOD_NS);+pwm_get_state(panel->backlight.pwm,&pstate);+pstate.period=CRC_PMIC_PWM_PERIOD_NS;+pstate.duty_cycle=CRC_PMIC_PWM_PERIOD_NS;+retval=pwm_apply_state(panel->backlight.pwm,&pstate);if(retval<0){DRM_ERROR("Failed to configure the pwm chip\n");pwm_put(panel->backlight.pwm);
From: Boris Brezillon <hidden> Date: 2016-03-30 20:07:25
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/video/backlight/pwm_bl.c | 43 ++++++++++++++++++++++------------------
1 file changed, 24 insertions(+), 19 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:08:31
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/leds/leds-pwm.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:08:33
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/input/misc/pwm-beeper.c | 46 +++++++++++++++++++++++++++--------------
1 file changed, 31 insertions(+), 15 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:09:43
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/input/misc/max8997_haptic.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:10:11
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/clk/clk-pwm.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:10:52
Prefix those function as deprecated to encourage all existing users to
switch to pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
include/linux/pwm.h | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
@@ -42,9 +42,23 @@ variants of these functions, devm_pwm_get() and devm_pwm_put(), also exist. After being requested, a PWM has to be configured using:-int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);+int pwm_apply_state(struct pwm_device *pwm, struct pwm_state *pstate);-To start/stop toggling the PWM output use pwm_enable()/pwm_disable().+This API controls both the PWM period/duty_cycle config and the+enable/disable state.++The legacy pwm_config(), pwm_enable() and pwm_disable() are now deprecated,+and should be replaced by pwm_apply_state() calls.++The PWM user API also allows one to query the PWM state with pwm_get_state().++In addition to the PWM state, the PWM API also exposes PWM arguments, which+are the reference PWM config one should use on this PWM.+PWM arguments are usually platform-specific and allows the PWM user to only+care about dutycycle relatively to the full period (like, duty = 50% of the+period). struct pwm_args contains 2 fields (period and polarity) and should+be used to set the initial PWM config (usually done in the probe function+of the PWM user). PWM arguments are retrieved with pwm_get_args(). Using PWMs with the sysfs interface -----------------------------------
@@ -105,6 +119,15 @@ goes low for the remainder of the period. Conversely, a signal with inversed polarity starts low for the duration of the duty cycle and goes high for the remainder of the period.+Drivers are encouraged to implement ->apply() instead of the legacy+->enable(), ->disable() and ->config() methods. Doing that should provide+atomicity in the PWM config workflow, which is required when the PWM controls+a critical device (like a regulator).++The implementation of ->get_state() (a method used to retrieve initial PWM+state) is also encouraged for the same reason: letting the PWM user know+about the current PWM state would allow him to avoid glitches.+ Locking -------
From: Boris Brezillon <hidden> Date: 2016-03-30 20:11:57
The ->state field is currently initialized to 0, thus referencing the
voltage selector at index 0, which might not reflect the current voltage
value.
If possible, retrieve the current voltage selector from the PWM state, else
return -EINVAL.
Signed-off-by: Boris Brezillon <redacted>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Mark Brown <broonie@kernel.org>
---
drivers/regulator/pwm-regulator.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:12:25
pwm_config/enable/disable() have been deprecated in favor of
pwm_apply_state().
Replace all those calls with the equivalent pwm_get/apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/regulator/pwm-regulator.c | 54 ++++++++++++++++++++++++---------------
1 file changed, 34 insertions(+), 20 deletions(-)
@@ -59,16 +59,18 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,unsignedselector){structpwm_regulator_data*drvdata=rdev_get_drvdata(rdev);-structpwm_argspargs={};-intdutycycle;+structpwm_statepstate={};+u64dutycycle;intret;-pwm_get_args(drvdata->pwm,&pargs);+pwm_get_state(drvdata->pwm,&pstate);-dutycycle=(pargs.period*-drvdata->duty_cycle_table[selector].dutycycle)/100;+dutycycle=drvdata->duty_cycle_table[selector].dutycycle;+dutycycle*=pstate.period;+do_div(dutycycle,100);+pstate.duty_cycle=dutycycle;-ret=pwm_config(drvdata->pwm,dutycycle,pargs.period);+ret=pwm_apply_state(drvdata->pwm,&pstate);if(ret){dev_err(&rdev->dev,"Failed to configure PWM\n");returnret;
@@ -93,24 +95,39 @@ static int pwm_regulator_list_voltage(struct regulator_dev *rdev,staticintpwm_regulator_enable(structregulator_dev*dev){structpwm_regulator_data*drvdata=rdev_get_drvdata(dev);+structpwm_statepstate={};++pwm_get_state(drvdata->pwm,&pstate);+if(pstate.enabled)+return0;++pstate.enabled=true;-returnpwm_enable(drvdata->pwm);+returnpwm_apply_state(drvdata->pwm,&pstate);}staticintpwm_regulator_disable(structregulator_dev*dev){structpwm_regulator_data*drvdata=rdev_get_drvdata(dev);+structpwm_statepstate={};-pwm_disable(drvdata->pwm);+pwm_get_state(drvdata->pwm,&pstate);+if(!pstate.enabled)+return0;-return0;+pstate.enabled=false;++returnpwm_apply_state(drvdata->pwm,&pstate);}staticintpwm_regulator_is_enabled(structregulator_dev*dev){structpwm_regulator_data*drvdata=rdev_get_drvdata(dev);+structpwm_statepstate={};-returnpwm_is_enabled(drvdata->pwm);+pwm_get_state(drvdata->pwm,&pstate);++returnpstate.enabled;}/**
@@ -138,25 +155,22 @@ static int pwm_regulator_set_voltage(struct regulator_dev *rdev,{structpwm_regulator_data*drvdata=rdev_get_drvdata(rdev);unsignedintramp_delay=rdev->constraints->ramp_delay;-structpwm_argspargs={};-intduty_cycle;+structpwm_statepstate={};+u64duty_cycle;intret;-pwm_get_args(drvdata->pwm,&pargs);+pwm_get_state(drvdata->pwm,&pstate);duty_cycle=pwm_voltage_to_duty_cycle_percentage(rdev,min_uV);+duty_cycle*=pstate.period;+do_div(duty_cycle,100);+pstate.duty_cycle=duty_cycle;-ret=pwm_config(drvdata->pwm,(pargs.period/100)*duty_cycle,-pargs.period);+ret=pwm_apply_state(drvdata->pwm,&pstate);if(ret){dev_err(&rdev->dev,"Failed to configure PWM\n");returnret;}-ret=pwm_enable(drvdata->pwm);-if(ret){-dev_err(&rdev->dev,"Failed to enable PWM\n");-returnret;-}drvdata->volt_uV=min_uV;/* Delay required by PWM regulator to settle to the new voltage */
From: Boris Brezillon <hidden> Date: 2016-03-30 20:13:06
The PWM attached to a PWM regulator device might have been previously
configured by the bootloader.
Make sure the bootloader and linux config are in sync, and adjust the PWM
config if that's not the case.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/regulator/pwm-regulator.c | 50 +++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:13:36
Implement ->get_state() to provide support for initial state retrieval.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/pwm-sti.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
@@ -238,6 +238,46 @@ static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)mutex_unlock(&pc->sti_pwm_lock);}+staticvoidsti_pwm_get_state(structpwm_chip*chip,+structpwm_device*pwm,+structpwm_state*pstate)+{+structsti_pwm_chip*pc=to_sti_pwmchip(chip);+unsignedintregval,prescaler;+u64timens;+intret;++/* The clock has to be enabled to access PWM registers */+ret=clk_enable(pc->clk);+if(ret){+dev_err(chip->dev,"Failed to enable PWM clk");+return;+}++regmap_field_read(pc->prescale_high,®val);+prescaler=regval<<4;+regmap_field_read(pc->prescale_low,®val);+prescaler|=regval;++timens=(u64)(prescaler+1)*NSEC_PER_SEC*+(pc->cdata->max_pwm_cnt+1);+do_div(timens,pc->clk_rate);++pstate->period=timens;++regmap_read(pc->regmap,STI_DS_REG(pwm->hwpwm),®val);+timens=(u64)(regval+1)*pstate->period;+do_div(timens,pc->cdata->max_pwm_cnt+1);+pstate->duty_cycle=timens;++regmap_field_read(pc->pwm_en,®val);+pstate->enabled=regval;++pstate->polarity=PWM_POLARITY_NORMAL;++clk_disable(pc->clk);+}+staticvoidsti_pwm_free(structpwm_chip*chip,structpwm_device*pwm){structsti_pwm_chip*pc=to_sti_pwmchip(chip);
From: Boris Brezillon <hidden> Date: 2016-03-30 20:13:41
Implement the ->apply() function to add support for atomic update.
Signed-off-by: Boris Brezillon <redacted>
Tested-by: Heiko Stuebner <heiko@sntech.de>
---
drivers/pwm/pwm-rockchip.c | 63 ++++++++++++++++++++++++++++------------------
1 file changed, 39 insertions(+), 24 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:13:59
Some PWM drivers are calling the deprecated pwm_disable() function in
their pwm->free() or pdev->remove() function. Replace those calls by
the pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/pwm-lpc18xx-sct.c | 7 +++++--
drivers/pwm/pwm-lpc32xx.c | 9 +++++++--
drivers/pwm/pwm-spear.c | 9 +++++++--
drivers/pwm/pwm-sti.c | 9 +++++++--
4 files changed, 26 insertions(+), 8 deletions(-)
@@ -233,8 +233,13 @@ static int spear_pwm_remove(struct platform_device *pdev)structspear_pwm_chip*pc=platform_get_drvdata(pdev);inti;-for(i=0;i<NUM_PWM;i++)-pwm_disable(&pc->chip.pwms[i]);+for(i=0;i<NUM_PWM;i++){+structpwm_statepstate;++pwm_get_state(&pc->chip.pwms[i],&pstate);+pstate.enabled=false;+pwm_apply_state(&pc->chip.pwms[i],&pstate);+}/* clk was prepared in probe, hence unprepare it here */clk_unprepare(pc->clk);
From: Boris Brezillon <hidden> Date: 2016-03-30 20:16:05
Add an ->apply() method to the pwm_ops struct to allow PWM drivers to
implement atomic update.
This method will be preferred over the ->enable(), ->disable() and
->config() methods if available.
Add the pwm_apply_state() function to the PWM user API.
Note that the pwm_apply_state() does not guarantee the atomicity of the
update operation, it all depends on the availability and implementation
of the ->apply() method.
pwm_enable/disable/set_polarity/config() are now implemented as wrappers
around the pwm_apply_state() function.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/core.c | 155 ++++++++++++++++++---------------------
include/linux/pwm.h | 207 +++++++++++++++++++++++++++++++++++++---------------
2 files changed, 220 insertions(+), 142 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:16:37
Prepare the transition to PWM atomic update by moving the enabled/disabled
state into the pwm_state struct. This way we can easily update the whole
PWM state by copying the new state in the ->state field.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/core.c | 13 +++++++++----
include/linux/pwm.h | 11 ++++++++---
2 files changed, 17 insertions(+), 7 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:16:57
The PWM state, represented by its period, duty_cycle and polarity,
is currently directly stored in the PWM device.
Declare a pwm_state structure embedding those field so that we can later
use this struct to atomically update all the PWM parameters at once.
All pwm_get_xxx() helpers are now implemented as wrappers around
pwm_get_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/core.c | 8 ++++----
include/linux/pwm.h | 54 +++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 46 insertions(+), 16 deletions(-)
@@ -268,7 +268,7 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip,pwm->chip=chip;pwm->pwm=chip->base+i;pwm->hwpwm=i;-pwm->polarity=polarity;+pwm->state.polarity=polarity;radix_tree_insert(&pwm_tree,pwm->pwm,pwm);}
@@ -446,8 +446,8 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)if(err)returnerr;-pwm->duty_cycle=duty_ns;-pwm->period=period_ns;+pwm->state.duty_cycle=duty_ns;+pwm->state.period=period_ns;return0;}
From: Boris Brezillon <hidden> Date: 2016-03-30 20:17:32
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/video/backlight/pwm_bl.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:17:52
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/regulator/pwm-regulator.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:18:23
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/leds/leds-pwm.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:18:56
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/input/misc/max77693-haptic.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:19:02
+Doug (sorry, I forgot to add you in to the recipient list)
On Wed, 30 Mar 2016 22:03:23 +0200
Boris Brezillon [off-list ref] wrote:
Hello,
This series adds support for atomic PWM update, or IOW, the capability
to update all the parameters of a PWM device (enabled/disabled, period,
duty and polarity) in one go.
It also adds support for initial PWM state retrieval (or hardware readout),
which should allow smooth handover between the bootloader and Linux. For
example, critical PWM users (like critical regulators controlled by a PWM)
can query the current PWM state, and adapt the PWM config without having
to disable/enable the PWM, or abruptly change the period/dutycyle/polarity
config.
Thierry, I hope this version meets your expectations, if that's not the
case, could you let me know quickly so I can adjust the implementation
accordingly (I'd really like to get most of those changes in 4.7).
Oh, I forgot to mention that I'm not necessarily expecting all those
patches to be taken in one go. We only need patches 1 to 31 for the
problem exposed by Doug. Patch 32 is deprecating the non-atomic APIs and
patches 33 to 46 are switching all PWM users to the atomic APIs to avoid
compilation warnings.
It's up to you to decide which you'd like to take.
Best Regards,
Boris
Changes since v4:
- introduce pwm_args to expose per-board/platform config
- deprecate non-atomic APIs
- implement non-atomic functions as wrappers around atomic ones
- patch all PWM users to use the atomic API
- rename the ->reset_state() hook into ->get_state()
- drop most acks
- rework PWM config in the pwm-regulator driver
- patch sun4i and sti PWM drivers to support HW readout
Changes since v3:
- rebased on pwm/for-next after pulling 4.4-rc1
- replace direct access to pwm fields by pwm_get/set_xxx() helpers, thus
fixing some build errors
- split changes to allow each maintainer to review/ack or take the
modification through its subsystem
Changes since v2:
- rebased on top of 4.3-rc2
- reintroduced pwm-regulator patches
Changes since v1:
- dropped applied patches
- squashed Heiko's fixes into the rockchip driver changes
- made a few cosmetic changes
- added kerneldoc comments
- added Heiko's patch to display more information in debugfs
- dropped pwm-regulator patches (should be submitted separately)
*** BLURB HERE ***
Boris Brezillon (45):
pwm: rcar: make use of pwm_is_enabled()
backlight: pwm_bl: remove useless call to pwm_set_period()
backlight: lm3630a_bl: stop messing with the pwm->period field
pwm: get rid of pwm->lock
pwm: introduce the pwm_args concept
pwm: use pwm_get/set_xxx() helpers where appropriate
clk: pwm: use pwm_get_args() where appropriate
hwmon: pwm-fan: use pwm_get_args() where appropriate
misc: max77693-haptic: use pwm_get_args() where appropriate
leds: pwm: use pwm_get_args() where appropriate
regulator: pwm: use pwm_get_args() where appropriate
fbdev: ssd1307fb: use pwm_get_args() where appropriate
backlight: pwm_bl: use pwm_get_args() where appropriate
pwm: keep PWM state in sync with hardware state
pwm: introduce the pwm_state concept
pwm: move the enabled/disabled info into pwm_state
pwm: add the PWM initial state retrieval infra
pwm: add the core infrastructure to allow atomic update
pwm: switch to the atomic API
pwm: rockchip: add initial state retrieval
pwm: rockchip: avoid glitches on already running PWMs
pwm: rockchip: add support for atomic update
pwm: sti: add support for initial state retrieval
pwm: sti: avoid glitches on already running PWMs
pwm: sun4i: implement hardware readout
regulator: pwm: adjust PWM config at probe time
regulator: pwm: swith to the atomic PWM API
regulator: pwm: properly initialize the ->state field
regulator: pwm: retrieve correct voltage
pwm: update documentation
pwm: deprecate pwm_config(), pwm_enable() and pwm_disable()
pwm: replace pwm_disable() by pwm_apply_state()
clk: pwm: switch to the atomic API
hwmon: pwm-fan: switch to the atomic API
input: misc: max77693: switch to the atomic API
input: misc: max8997: switch to the atomic PWM API
input: misc: pwm-beeper: switch to the atomic PWM API
leds: pwm: switch to the atomic PWM API
backlight: lm3630a: switch to the atomic PWM API
backlight: lp855x: switch to the atomic PWM API
backlight: lp8788: switch to the atomic PWM API
backlight: pwm_bl: switch to the atomic PWM API
video: ssd1307fb: switch to the atomic PWM API
drm: i915: switch to the atomic PWM API
ARM: s3c24xx: rx1950: switch to the atomic PWM API
Heiko Stübner (1):
pwm: add information about polarity, duty cycle and period to debugfs
Documentation/pwm.txt | 27 +++-
arch/arm/mach-s3c24xx/mach-rx1950.c | 17 +-
drivers/clk/clk-pwm.c | 36 ++++-
drivers/gpu/drm/i915/intel_panel.c | 39 +++--
drivers/hwmon/pwm-fan.c | 88 ++++++----
drivers/input/misc/max77693-haptic.c | 28 +++-
drivers/input/misc/max8997_haptic.c | 23 ++-
drivers/input/misc/pwm-beeper.c | 46 ++++--
drivers/leds/leds-pwm.c | 15 +-
drivers/pwm/core.c | 186 ++++++++++-----------
drivers/pwm/pwm-clps711x.c | 2 +-
drivers/pwm/pwm-crc.c | 2 +-
drivers/pwm/pwm-lpc18xx-sct.c | 9 +-
drivers/pwm/pwm-lpc32xx.c | 9 +-
drivers/pwm/pwm-omap-dmtimer.c | 2 +-
drivers/pwm/pwm-pxa.c | 2 +-
drivers/pwm/pwm-rcar.c | 2 +-
drivers/pwm/pwm-rockchip.c | 156 +++++++++++++++---
drivers/pwm/pwm-spear.c | 9 +-
drivers/pwm/pwm-sti.c | 67 +++++++-
drivers/pwm/pwm-sun4i.c | 73 ++++++---
drivers/pwm/sysfs.c | 98 ++++++++---
drivers/regulator/pwm-regulator.c | 151 ++++++++++++++---
drivers/video/backlight/lm3630a_bl.c | 15 +-
drivers/video/backlight/lp855x_bl.c | 15 +-
drivers/video/backlight/lp8788_bl.c | 17 +-
drivers/video/backlight/pwm_bl.c | 51 +++---
drivers/video/fbdev/ssd1307fb.c | 28 +++-
include/linux/pwm.h | 303 ++++++++++++++++++++++++++---------
29 files changed, 1096 insertions(+), 420 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:20:05
Currently the PWM core mixes the current PWM state with the per-platform
reference config (specified through the PWM lookup table, DT definition or
directly hardcoded in PWM drivers).
Create a pwm_args struct to store this reference config, so that PWM users
can differentiate the current config from the reference one.
Patch all places where pwm->args should be initialized. We keep the
pwm_set_polarity/period() calls until all PWM users are patched to
use pwm_args instead of pwm_get_period/polarity().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/core.c | 13 +++++++++----
drivers/pwm/pwm-clps711x.c | 3 ++-
drivers/pwm/pwm-pxa.c | 1 +
include/linux/pwm.h | 26 ++++++++++++++++++++++++++
4 files changed, 38 insertions(+), 5 deletions(-)
@@ -60,7 +60,8 @@ static int clps711x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)return-EINVAL;/* Store constant period value */-pwm_set_period(pwm,DIV_ROUND_CLOSEST(NSEC_PER_SEC,freq));+pwm->args.period=DIV_ROUND_CLOSEST(NSEC_PER_SEC,freq);+pwm_set_period(pwm,pwm->args.period);return0;}
From: Boris Brezillon <hidden> Date: 2016-03-30 20:20:40
PWM devices are not protected against concurrent accesses. The lock in
pwm_device might let PWM users think it is, but it's actually only
protecting the enabled state.
Removing this lock should be fine as long as all PWM users are aware that
accesses to the PWM device have to be serialized, which seems to be the
case for all of them except the sysfs interface.
Patch the sysfs code by adding a lock to the pwm_export struct and making
sure it's taken for all accesses to the exported PWM device.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/pwm/core.c | 19 ++++--------------
drivers/pwm/sysfs.c | 57 ++++++++++++++++++++++++++++++++++++++++++-----------
include/linux/pwm.h | 2 --
3 files changed, 50 insertions(+), 28 deletions(-)
From: Boris Brezillon <hidden> Date: 2016-03-30 20:21:10
pwm->period field is not supposed to be changed by PWM users. The only
ones authorized to change it are the PWM core and PWM drivers.
Signed-off-by: Boris Brezillon <redacted>
---
drivers/video/backlight/lm3630a_bl.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
From: Mark Brown <broonie@kernel.org> Date: 2016-03-30 21:24:11
On Wed, Mar 30, 2016 at 10:03:50PM +0200, Boris Brezillon wrote:
The PWM attached to a PWM regulator device might have been previously
configured by the bootloader.
Make sure the bootloader and linux config are in sync, and adjust the PWM
config if that's not the case.
From: Mark Brown <broonie@kernel.org> Date: 2016-03-30 21:25:31
On Wed, Mar 30, 2016 at 10:03:53PM +0200, Boris Brezillon wrote:
The continuous PWM voltage regulator is caching the voltage value in
the ->volt_uV field. While most of the time this value should reflect the
real voltage, sometime it can be sightly different if the PWM device
rounded the set_duty_cycle request.
Moreover, this value is not valid until someone has modified the regulator
output.
+ * device. Those arguments are usually retrieved from the PWM lookup table or
+ * DT definition.
+ * This should not be confused with the PWM state: PWM args not representing
s/not representing/don't represent/ ?
+ * the current PWM state, but the configuration the PWM user plan to use
s/plan/plans/
+ * on this PWM device.
+ */
+struct pwm_args {
+ unsigned int period;
+ enum pwm_polarity polarity;
+};
+
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
From: Stephen Boyd <hidden> Date: 2016-03-30 21:58:15
On 03/30, Boris Brezillon wrote:
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
Acked-by: Stephen Boyd <redacted>
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
This doesn't seem atomic anymore if we're checking the state and
then not calling apply_state if it's already enabled. But I
assume this doesn't matter because we "own" the pwm here?
Otherwise I would think this would be unconditional apply state
and duplicates would be ignored in the pwm framework.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
On Wed, Mar 30, 2016 at 10:03:31PM +0200, Boris Brezillon wrote:
quoted hunk
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/hwmon/pwm-fan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
Hi Boris,
I guess I am missing some context; sorry for that. Unfortunately,
I did not easily find an explanation, so please bear with me.
Two questions: Why do we need a local copy of struct pwm_args instead
of a pointer to it ? If it can change while being used, isn't it
inconsistent anyway ?
Also, assuming the local copy is necessary, why initialize pargs ?
After all, pwm_get_args() just overwrites it.
Thanks,
Guenter
quoted hunk
unsigned long duty;
int ret = 0;
+ pwm_get_args(ctx->pwm, &pargs);
+
mutex_lock(&ctx->lock);
if (ctx->pwm_value = pwm)
goto exit_set_pwm_err;
- duty = DIV_ROUND_UP(pwm * (ctx->pwm->period - 1), MAX_PWM);
- ret = pwm_config(ctx->pwm, duty, ctx->pwm->period);
+ duty = DIV_ROUND_UP(pwm * (pargs.period - 1), MAX_PWM);
+ ret = pwm_config(ctx->pwm, duty, pargs.period);
if (ret)
goto exit_set_pwm_err;
This doesn't seem atomic anymore if we're checking the state and
then not calling apply_state if it's already enabled. But I
assume this doesn't matter because we "own" the pwm here?
Yep. Actually it's not atomic in term of concurrency (maybe the
'atomic' word is not appropriate here). Atomicity is here referring to
the fact that we're now providing all the PWM parameters in the same
request instead of splitting it in pwm_config() + pwm_enable/disable()
calls.
Concurrent accesses still have to be controlled by the PWM user (which
is already the case for this driver, thanks to the locking
infrastructure in the CCF).
Otherwise I would think this would be unconditional apply state
and duplicates would be ignored in the pwm framework.
Yep, I'll remove the if (pstate.enabled) branch.
Thanks for your review.
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
From: Boris Brezillon <hidden> Date: 2016-03-31 07:07:19
Hi Guenter,
On Wed, 30 Mar 2016 15:52:44 -0700
Guenter Roeck [off-list ref] wrote:
On Wed, Mar 30, 2016 at 10:03:31PM +0200, Boris Brezillon wrote:
quoted
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/hwmon/pwm-fan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
Hi Boris,
I guess I am missing some context; sorry for that. Unfortunately,
I did not easily find an explanation, so please bear with me.
Two questions: Why do we need a local copy of struct pwm_args instead
of a pointer to it ? If it can change while being used, isn't it
inconsistent anyway ?
It cannot change after pwm_get() is called. For the reason behind
prototype: I just followed the Thierry's proposal, but I'm perfectly
fine returning a const struct pwm_args pointer intead of passing
pwm_args as a parameter.
Thierry, what's your opinion?
Also, assuming the local copy is necessary, why initialize pargs ?
After all, pwm_get_args() just overwrites it.
It's a leftover from a previous version where pwm_get_args was
implemented this way:
static inline void pwm_get_args(pwm, args)
{
if (pwm)
*args = pwm->args
}
and this implementation was generating a lot of 'uninitialized
variable' warnings.
I just decided to drop the 'if (pwm)' test, because, IMO, this
should be checked way before calling pwm_get_args() is called.
Anyway, apparently I forgot to modify a few patches after this
modification.
Thanks for the review.
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
+ * device. Those arguments are usually retrieved from the PWM lookup table or
+ * DT definition.
+ * This should not be confused with the PWM state: PWM args not representing
s/not representing/don't represent/ ?
quoted
+ * the current PWM state, but the configuration the PWM user plan to use
s/plan/plans/
quoted
+ * on this PWM device.
+ */
+struct pwm_args {
+ unsigned int period;
+ enum pwm_polarity polarity;
+};
+
Will fix these errors.
Thanks,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
From: Jacek Anaszewski <hidden> Date: 2016-03-31 07:13:38
Hi Boris,
On 03/30/2016 10:03 PM, Boris Brezillon wrote:
quoted hunk
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/leds/leds-pwm.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
+ * device. Those arguments are usually retrieved from the PWM lookup table or
+ * DT definition.
+ * This should not be confused with the PWM state: PWM args not representing
s/not representing/don't represent/ ?
Yes, I meant "are not representing", but "don't represent" is fine.
quoted
+ * the current PWM state, but the configuration the PWM user plan to use
s/plan/plans/
quoted
+ * on this PWM device.
+ */
+struct pwm_args {
+ unsigned int period;
+ enum pwm_polarity polarity;
+};
+
On 30/03/2016 at 22:03:49 +0200, Boris Brezillon wrote :
Implement ->get_state() instead of only initializing the polarity in
the probe function.
This implementation also takes care of keeping the PWM clk enabled if at
least one of the PWM exported by the PWM chip is already enabled, which
should prevent glitches.
Signed-off-by: Boris Brezillon <redacted>
Hi Boris,
On Wed, Mar 30, 2016 at 10:03:55PM +0200, Boris Brezillon wrote:
Prefix those function as deprecated to encourage all existing users to
switch to pwm_apply_state().
Why not keep at least some of them as wrappers where we do not need to
chnage several parameters at once? It is much easier to have a driver
do:
error = pwm_enable(pwm);
if (error)
...
rather than declaring the state variable, fectch it, adjust and then
apply.
Hi Boris,
On Wed, Mar 30, 2016 at 10:03:59PM +0200, Boris Brezillon wrote:
quoted hunk
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/input/misc/max77693-haptic.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
This does not make sense with regard to the atomic API. If you look in
max77693_haptic_play_work(), right after calling
max77693_haptic_set_duty_cycle() we either try to enable or disable the
pwm. When switching to this new API we should combine both actions.
quoted hunk
if (error) {
dev_err(haptic->dev, "failed to configure pwm: %d\n", error);
return error;
As I mentioned I'd rather we did not deprecate pwm_enable() and
pwm_disable() (and maybe others), as it forces us to add unnecessary
boilerplate code to the drivers.
quoted hunk
if (error) {
dev_err(haptic->dev,
"failed to enable haptic pwm device: %d\n", error);
From: Boris Brezillon <hidden> Date: 2016-03-31 18:55:04
Hi Dmitry,
On Thu, 31 Mar 2016 10:38:58 -0700
Dmitry Torokhov [off-list ref] wrote:
Hi Boris,
On Wed, Mar 30, 2016 at 10:03:55PM +0200, Boris Brezillon wrote:
quoted
Prefix those function as deprecated to encourage all existing users to
switch to pwm_apply_state().
Why not keep at least some of them as wrappers where we do not need to
chnage several parameters at once? It is much easier to have a driver
do:
error = pwm_enable(pwm);
if (error)
...
rather than declaring the state variable, fectch it, adjust and then
apply.
True. Actually deprecating the non-atomic API was not my primary goal.
Thierry would you mind if we keep both APIs around?
From: Boris Brezillon <hidden> Date: 2016-03-31 18:57:26
On Thu, 31 Mar 2016 10:48:01 -0700
Dmitry Torokhov [off-list ref] wrote:
Hi Boris,
On Wed, Mar 30, 2016 at 10:03:59PM +0200, Boris Brezillon wrote:
quoted
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/input/misc/max77693-haptic.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
This does not make sense with regard to the atomic API. If you look in
max77693_haptic_play_work(), right after calling
max77693_haptic_set_duty_cycle() we either try to enable or disable the
pwm. When switching to this new API we should combine both actions.
True. I'll address that, unless Thierry is fine keeping the non-atomic
API, in which case I'll just drop patches 32 to 46.
quoted
if (error) {
dev_err(haptic->dev, "failed to configure pwm: %d\n", error);
return error;
As I mentioned I'd rather we did not deprecate pwm_enable() and
pwm_disable() (and maybe others), as it forces us to add unnecessary
boilerplate code to the drivers.
quoted
if (error) {
dev_err(haptic->dev,
"failed to enable haptic pwm device: %d\n", error);
Hi Boris,
From: Boris Brezillon [mailto:boris.brezillon@free-electrons.com]
Sent: Wednesday, March 30, 2016 10:04 PM
Subject: [PATCH v5 35/46] hwmon: pwm-fan: switch to the atomic API
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
Acked-by: Kamil Debski <redacted>
Best wishes,
--
Kamil Debski
Samsung R&D Institute Poland
Hi Boris,
From: Boris Brezillon [mailto:boris.brezillon@free-electrons.com]
Sent: Wednesday, March 30, 2016 10:04 PM
Subject: [PATCH v5 08/46] hwmon: pwm-fan: use pwm_get_args() where
appropriate
The PWM framework has clarified the concept of reference PWM config (the
platform dependent config retrieved from the DT or the PWM lookup table)
and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support hardware
readout and expose real PWM state even when the PWM has just been
requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
Acked-by: Kamil Debski <redacted>
Best wishes,
--
Kamil Debski
Samsung R&D Institute Poland
On Thu, Mar 31, 2016 at 09:07:09AM +0200, Boris Brezillon wrote:
Hi Guenter,
On Wed, 30 Mar 2016 15:52:44 -0700
Guenter Roeck [off-list ref] wrote:
quoted
On Wed, Mar 30, 2016 at 10:03:31PM +0200, Boris Brezillon wrote:
quoted
The PWM framework has clarified the concept of reference PWM config
(the platform dependent config retrieved from the DT or the PWM
lookup table) and real PWM state.
Use pwm_get_args() when the PWM user wants to retrieve this reference
config and not the current state.
This is part of the rework allowing the PWM framework to support
hardware readout and expose real PWM state even when the PWM has
just been requested (before the user calls pwm_config/enable/disable()).
Signed-off-by: Boris Brezillon <redacted>
---
drivers/hwmon/pwm-fan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
Hi Boris,
I guess I am missing some context; sorry for that. Unfortunately,
I did not easily find an explanation, so please bear with me.
Two questions: Why do we need a local copy of struct pwm_args instead
of a pointer to it ? If it can change while being used, isn't it
inconsistent anyway ?
It cannot change after pwm_get() is called. For the reason behind
prototype: I just followed the Thierry's proposal, but I'm perfectly
fine returning a const struct pwm_args pointer intead of passing
pwm_args as a parameter.
Thierry, what's your opinion?
I do prefer the current variant because it is more consistent with the
new atomic API, even if not strictly necessary because of the immutable
data.
quoted
Also, assuming the local copy is necessary, why initialize pargs ?
After all, pwm_get_args() just overwrites it.
It's a leftover from a previous version where pwm_get_args was
implemented this way:
static inline void pwm_get_args(pwm, args)
{
if (pwm)
*args = pwm->args
}
and this implementation was generating a lot of 'uninitialized
variable' warnings.
I just decided to drop the 'if (pwm)' test, because, IMO, this
should be checked way before calling pwm_get_args() is called.
On Thu, Mar 31, 2016 at 08:54:54PM +0200, Boris Brezillon wrote:
Hi Dmitry,
On Thu, 31 Mar 2016 10:38:58 -0700
Dmitry Torokhov [off-list ref] wrote:
quoted
Hi Boris,
On Wed, Mar 30, 2016 at 10:03:55PM +0200, Boris Brezillon wrote:
quoted
Prefix those function as deprecated to encourage all existing users to
switch to pwm_apply_state().
Why not keep at least some of them as wrappers where we do not need to
chnage several parameters at once? It is much easier to have a driver
do:
error = pwm_enable(pwm);
if (error)
...
rather than declaring the state variable, fectch it, adjust and then
apply.
True. Actually deprecating the non-atomic API was not my primary goal.
Thierry would you mind if we keep both APIs around?
I'm fine with keeping these around, though purely as shortcuts. If users
need to modify two parameters at once (e.g. duty cycle and enable) then
they should be converted to use the atomic API, otherwise there'd be
little point in introduce it.
Thierry
This doesn't seem atomic anymore if we're checking the state and
then not calling apply_state if it's already enabled. But I
assume this doesn't matter because we "own" the pwm here?
Yep. Actually it's not atomic in term of concurrency (maybe the
'atomic' word is not appropriate here). Atomicity is here referring to
the fact that we're now providing all the PWM parameters in the same
request instead of splitting it in pwm_config() + pwm_enable/disable()
calls.
It's usually not possible to do really atomic updates with PWM hardware.
The idea is merely that we should be able to submit one request and the
framework (and drivers) will be responsible for making sure it is
applied as a whole or not at all. With the legacy API it is possible for
users to set the duty cycle and period, but then fail to enable/disable
the PWM.
pwm_apply_state() reporting success should indicate that the hardware
state is now what software wanted it to be. That kind of implies that
the application is serialized.
This doesn't imply that hardware state won't change between a call to
pwm_get_state() and pwm_apply_state(), though technically this is what
will usually happen because PWM devices are exclusively used by a single
user. Users are responsible for synchronizing accesses within their own
code.
Concurrent accesses still have to be controlled by the PWM user (which
is already the case for this driver, thanks to the locking
infrastructure in the CCF).
quoted
Otherwise I would think this would be unconditional apply state
and duplicates would be ignored in the pwm framework.
Yep, I'll remove the if (pstate.enabled) branch.
Yes, it should be the PWM framework's job to check for changes in state
and discard no-ops.
Thierry
On Thu, Mar 31, 2016 at 08:57:18PM +0200, Boris Brezillon wrote:
On Thu, 31 Mar 2016 10:48:01 -0700
Dmitry Torokhov [off-list ref] wrote:
quoted
Hi Boris,
On Wed, Mar 30, 2016 at 10:03:59PM +0200, Boris Brezillon wrote:
quoted
pwm_config/enable/disable() have been deprecated and should be replaced
by pwm_apply_state().
Signed-off-by: Boris Brezillon <redacted>
---
drivers/input/misc/max77693-haptic.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
This does not make sense with regard to the atomic API. If you look in
max77693_haptic_play_work(), right after calling
max77693_haptic_set_duty_cycle() we either try to enable or disable the
pwm. When switching to this new API we should combine both actions.
True. I'll address that, unless Thierry is fine keeping the non-atomic
API, in which case I'll just drop patches 32 to 46.
I'm fine with keeping the pwm_enable(), pwm_disable() and pwm_config()
APIs, but they should only be used as shortcuts. Where possible the new
atomic API should be used to combine multiple operations into one.
Thierry
From: Boris Brezillon <hidden> Date: 2016-04-07 21:54:49
Hi Mark,
On Wed, 30 Mar 2016 14:24:10 -0700
Mark Brown [off-list ref] wrote:
On Wed, Mar 30, 2016 at 10:03:53PM +0200, Boris Brezillon wrote:
quoted
The continuous PWM voltage regulator is caching the voltage value in
the ->volt_uV field. While most of the time this value should reflect the
real voltage, sometime it can be sightly different if the PWM device
rounded the set_duty_cycle request.
Moreover, this value is not valid until someone has modified the regulator
output.
Acked-by: Mark Brown <broonie@kernel.org>
Actually this patch introduces a bug (reported by Stephen):
"
I applied your patch series [PATCH v5 00/46] pwm: add support for
atomic update and found a null pointer dereference when probing a
pwm-regulator at boot. See the below stack trace:
[ 4.282374] [<ffffffc000399088>] pwm_regulator_get_voltage+0x78/0xa0
[ 4.289344] [<ffffffc000390740>] regulator_attr_is_visible+0x7c/0x264
[ 4.296408] [<ffffffc0001f75a0>] internal_create_group+0x14c/0x280
[ 4.303184] [<ffffffc0001f76e8>] sysfs_create_group+0x14/0x1c
[ 4.309483] [<ffffffc0001f77c8>] sysfs_create_groups+0x30/0x78
[ 4.315881] [<ffffffc00043631c>] device_add+0x224/0x4d8
[ 4.321609] [<ffffffc0004365ec>] device_register+0x1c/0x28
[ 4.327623] [<ffffffc0003952a4>] regulator_register+0x2e4/0xc14
[ 4.334112] [<ffffffc000396844>] devm_regulator_register+0x54/0x94
[ 4.340887] [<ffffffc000399328>] pwm_regulator_probe+0x278/0x2b8
[ 4.347473] [<ffffffc000439fe4>] platform_drv_probe+0x58/0xa4
[ 4.353772] [<ffffffc0004387a8>] driver_probe_device+0x114/0x2ac
[ 4.360358] [<ffffffc0004389a4>] __driver_attach+0x64/0x90
[ 4.366371] [<ffffffc000436f50>] bus_for_each_dev+0x74/0x90
[ 4.372478] [<ffffffc000438bd4>] driver_attach+0x20/0x28
[ 4.378299] [<ffffffc00043778c>] bus_add_driver+0xe8/0x1e0
[ 4.384312] [<ffffffc00043959c>] driver_register+0x98/0xe4
[ 4.390326] [<ffffffc00043aa04>] __platform_driver_register+0x48/0x50
[ 4.397388] [<ffffffc000cb2710>] pwm_regulator_driver_init+0x18/0x20
[ 4.404356] [<ffffffc000c8ca7c>] do_one_initcall+0xf8/0x180
[ 4.410466] [<ffffffc000c8cc58>] kernel_init_freeable+0x154/0x1f4
[ 4.417148] [<ffffffc000929cf4>] kernel_init+0x10/0xf8
[ 4.422782] [<ffffffc000084450>] ret_from_fork+0x10/0x40
It looks like the root cause is that regulator_attr_is_visible will
try to get the voltage, but at this point in regulator_register,
rdev->constraints is still null. So
pwm_duty_cycle_percentage_to_voltage will dereference a null
rdev->constraints pointer.
"
The problem is that we need to know the min and max voltage constraints
to calculate the current voltage. ->get_voltage() is called when the
sysfs attributes are created (part of device registration), and
set_machine_constraints() is called after device_register(), thus
leading to the NULL pointer dereference.
Is there any reason for calling set_machine_constraints() after
device_register() in regulator_register()?
Best Regards,
Boris
From: Boris Brezillon <hidden> Date: 2016-04-11 22:43:08
Hi Thierry,
On Wed, 30 Mar 2016 22:03:23 +0200
Boris Brezillon [off-list ref] wrote:
Hello,
This series adds support for atomic PWM update, or IOW, the capability
to update all the parameters of a PWM device (enabled/disabled, period,
duty and polarity) in one go.
It also adds support for initial PWM state retrieval (or hardware readout),
which should allow smooth handover between the bootloader and Linux. For
example, critical PWM users (like critical regulators controlled by a PWM)
can query the current PWM state, and adapt the PWM config without having
to disable/enable the PWM, or abruptly change the period/dutycyle/polarity
config.
Thierry, I hope this version meets your expectations, if that's not the
case, could you let me know quickly so I can adjust the implementation
accordingly (I'd really like to get most of those changes in 4.7).
Still haven't had a clear feedback from your side on this series (you
commented on a few details, but nothing on the general approach). Could
you please have at a quick look at it, and let me know if I should
adjust the implementation?
Note that I plan to send a new version addressing comments made by
other maintainers/developers by the end of the week. In the meantime,
could you have a look at the first set of patches (patch 1 to 4 are
completely independent), and apply them if you're happy with it.
As you can see, I now have a lot of patches. This helps in showing the
big picture, but also annoys people when I send this 50+ patchset. So,
if you don't mind, I'd like to drop the changes touching PWM user
drivers (to make them use the atomic API) until we get the other parts
applied.
Thanks,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
From: Boris Brezillon <hidden> Date: 2016-04-12 08:37:31
Hi Mark,
On Tue, 12 Apr 2016 05:42:03 +0100
Mark Brown [off-list ref] wrote:
On Thu, Apr 07, 2016 at 11:54:31PM +0200, Boris Brezillon wrote:
quoted
Is there any reason for calling set_machine_constraints() after
device_register() in regulator_register()?
I'm not sure there's a strong one, we don't really use the class device
for anything, but without doing a full audit I couldn't guarantee that.
At first glance I don't see any problem (even the rdev_err/info/...()
functions do not use dev_err/info/...()). The patch will be part of v6
(unless you want me to send it independently).
Thanks,
Boris
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com