The PWMs are expected to be functional until pwmchip_remove() is called.
So disable the clks only afterwards.
Fixes: 9e37a53eb0 ("pwm: sifive: Add a driver for SiFive SoC PWM")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
.apply() assumes the clk to be for a given PWM iff the PWM is enabled.
So make sure this is the case when .probe() completes. And in .remove()
disable the according number of times.
This fixes a clk enable/disable imbalance, if some PWMs are already running
at probe time.
Fixes: 9e37a53eb0 (pwm: sifive: Add a driver for SiFive SoC PWM)
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
The clk is necessary for both register access and (enabled) operation of
the PWM. Instead of
clk_enable()
update_hw()
if pwm_got_enabled():
clk_enable()
elif pwm_got_disabled():
clk_disable()
clk_disable()
which is some cases only calls clk_enable() to immediately afterwards
call clk_disable again, do:
if (!prev_state.enabled)
clk_enable()
# clk enabled exactly once
update_hw()
if (!next_state.enabled)
clk_disable()
which is much easier.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
For the period check and the initial calculations of register values there
is no hardware access needed. So delay enabling the clk a bit to simplify
the code flow a bit.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
The lock is only to serialize access and update to user_count and
approx_period between different PWMs served by the same pwm_chip.
So the lock needs only to be taken during the check if the (chip global)
period can and/or needs to be changed.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
There is only a single caller of pwm_sifive_enable() which only enables
or disables the clk. Put this implementation directly into
pwm_sifive_apply() which allows further simplification in the next
change.
There is no change in behaviour.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Instead of explicitly using PWM_SIFIVE_PWMCMP0 + pwm->hwpwm *
PWM_SIFIVE_SIZE_PWMCMP for each access to one of the PWMCMP registers,
introduce a macro that takes the hwpwm id as parameter.
For the register definition using a plain 4 instead of the cpp constant
PWM_SIFIVE_SIZE_PWMCMP is easier to read, so define the offset macro
without the constant. The latter can then be dropped as there are no
users left.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Tested-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Use if and else instead of if(A) and if (!A).
Signed-off-by: Wan Jiabing <wanjiabing@vivo.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
pwmchip_remove() returns always 0. Don't use the value to make it
possible to eventually change the function to return void. Also the
driver core ignores the return value of pwm_sifive_remove().
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
With the previous commit there is no need for the lowlevel driver any
more to specify it it uses two or three cells. So simplify accordingly.
The only non-trival change affects the pwm-rockchip driver: It used to only
support three cells if the hardware supports polarity. Now the default
number depends on the device tree which has to match hardware anyhow
(and if it doesn't the error is just a bit delayed as a PWM handle with
an inverted setting is catched when pwm_apply_state() is called).
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Since commit 5e5da1e9fb ("pwm: ab8500: Explicitly allocate pwm chip
base dynamically") all drivers use dynamic ID allocation explicitly. New
drivers are supposed to do the same, so remove support for driver
specified base IDs and drop all assignments in the low-level drivers.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Common pattern of handling deferred probe can be simplified with
dev_err_probe(). Less code and also it prints the error value.
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Since the PWM framework is switching struct pwm_args.period's datatype
to u64, prepare for this transition by using DIV64_U64_ROUND_CLOSEST to
handle a 64-bit divisor.
Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org>
Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
It is surprising for a PWM consumer when the variable holding the
requested state is modified by pwm_apply_state(). Consider for example a
driver doing:
#define PERIOD 5000000
#define DUTY_LITTLE 10
...
struct pwm_state state = {
.period = PERIOD,
.duty_cycle = DUTY_LITTLE,
.polarity = PWM_POLARITY_NORMAL,
.enabled = true,
};
pwm_apply_state(mypwm, &state);
...
state.duty_cycle = PERIOD / 2;
pwm_apply_state(mypwm, &state);
For sure the second call to pwm_apply_state() should still have
state.period = PERIOD and not something the hardware driver chose for a
reason that doesn't necessarily apply to the second call.
So declare the state argument as a pointer to a const type and adapt all
drivers' .apply callbacks.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>