A small prescaler is beneficial, as this improves the resolution of the
duty_cycle configuration. However if the prescaler is too small, the
maximal possible period becomes considerably smaller than the requested
value.
One situation where this goes wrong is the following: With a parent
clock rate of 208877930 Hz and max_arr = 0xffff = 65535, a request for
period = 941243 ns currently results in PSC = 1. The value for ARR is
then calculated to
ARR = 941243 * 208877930 / (1000000000 * 2) - 1 = 98301
This value is bigger than 65535 however and so doesn't fit into the
respective register field. In this particular case the PWM was
configured for a period of 313733.4806027616 ns (with ARR = 98301 &
0xffff). Even if ARR was configured to its maximal value, only period =
627495.6861167669 ns would be achievable.
Fix the calculation accordingly and adapt the comment to match the new
algorithm.
With the calculation fixed the above case results in PSC = 2 and so an
actual period of 941229.1667195285 ns.
Fixes: 8002fbeef1 ("pwm: stm32: Calculate prescaler with a division instead of a loop")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Link: https://lore.kernel.org/r/b4d96b79917617434a540df45f20cb5de4142f88.1718979150.git.u.kleine-koenig@baylibre.com
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
The driver doesn't use the driver_data member of struct i2c_device_id,
so don't explicitly initialize this member.
This prepares putting driver_data in an anonymous union which requires
either no initialization or named designators. But it's also a nice
cleanup on its own.
While add it, also remove the trailing commas after the sentinel entry.
Link: https://lore.kernel.org/r/20240508130618.2148631-2-u.kleine-koenig@pengutronix.de
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Introduce a new compatible support in the Amlogic PWM driver.
The PWM HW is actually the same for all SoCs supported so far. A specific
compatible is needed only because the clock sources of the PWMs are
hard-coded in the driver.
It is better to have the clock source described in DT but this changes the
bindings so a new compatible must be introduced.
When all supported platform have migrated to the new compatible, support
for the legacy ones may be removed from the driver.
The addition of this new compatible makes the old ones obsolete, as
described in the DT documentation.
Adding a callback to setup the clock will also make it easier to add
support for the new PWM HW found in a1, s4, c3 and t7 SoC families.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Link: https://lore.kernel.org/r/20240221151154.26452-6-jbrunet@baylibre.com
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
While mathematically it's ok to calculate the number of cyles for the
duty cycle as:
duty_cycles = period_cycles * duty_ns / period_ns
this doesn't always give the right result when doing integer math. This
is best demonstrated using an example: With the input clock running at
208877930 Hz a request for duty_cycle = 383 ns and period = 49996 ns
results in
period_cycles = clkrate * period_ns / NSEC_PER_SEC = 10443.06098828
Now calculating duty_cycles with the above formula gives:
duty_cycles = 10443.06098828 * 383 / 49996 = 80.00024719
However with period_cycle truncated to an integer results in:
duty_cycles = 10443 * 383 / 49996 = 79.99977998239859
So while a value of (a little more than) 80 would be the right result,
only 79 is used here. The problem here is that 14443 is a rounded result
that should better not be used to do further math. So to fix that use
the exact formular similar to how period_cycles is calculated.
Link: https://lore.kernel.org/r/7628ecd8a7538aa5a7397f0fc4199a077168e8a6.1710711976.git.u.kleine-koenig@pengutronix.de
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
It's required to not free the memory underlying a requested PWM
while a consumer still has a reference to it. While currently a pwm_chip
doesn't live long enough in all cases, linking the struct pwm to the
pwm_chip results in the right lifetime as soon as the pwmchip is living
long enough. This happens with the following commits.
Note this is a breaking change for all pwm drivers that don't use
pwmchip_alloc().
Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org> # for struct_size() and __counted_by()
Link: https://lore.kernel.org/r/7e9e958841f049026c0023b309cc9deecf0ab61d.1710670958.git.u.kleine-koenig@pengutronix.de
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
With the upcoming restructuring having all in a single file simplifies
things a bit. The relevant and somewhat visible changes are:
- Some dropped prototypes from include/linux/pwm.h that were only
necessary that core.c has a declaration of the symbols defined in
sysfs.c. The respective functions are static now.
- The pwm class now also exists if CONFIG_SYSFS isn't enabled. Having
CONFIG_SYSFS is not very relevant today, but even without it the
class and device stuff still provides lifetime tracking.
- Both files had an initcall, these are merged into a single one now.
Instead of a big #ifdef block for CONFIG_DEBUG_FS, a single
if (IS_ENABLED(CONFIG_DEBUG_FS)) is used now. This increases compile
coverage a bit and is a tad nicer on the eyes.
Link: https://lore.kernel.org/r/9e2d39a5280d7dda5bfc6682a8aef510148635b2.1710670958.git.u.kleine-koenig@pengutronix.de
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
The code handling the sysfs API uses "child" and "parent" to refer to
the devices corresponding to a struct pwm or a struct pwm_chip
respectively.
Other parts of the pwm core use "parent" to refer to the parent device of
a struct pwm_chip.
So rename "child" to "pwm_dev" and "parent" to "pwmchip_dev" which
better explains the semantic. Also two functions are changed to match
the new names:
child_to_pwm_export() -> pwmexport_from_dev()
child_to_pwm_device() -> pwm_from_dev()
(which have the additional advantage to start with "pwm" which gives the
right scope). Additionally introduce a wrapper for dev_get_drvdata() to
convert a pwmchip_dev to the respective pwm_chip.
Link: https://lore.kernel.org/r/9cc05aceeae2f06ecb850bccb15ba821e768c183.1710670958.git.u.kleine-koenig@pengutronix.de
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Instead of of_clk_get_by_name() use devm_clk_get_prepared() which has
several advantages:
- Combines getting the clock and a call to clk_prepare(). The latter
can be dropped from sti_pwm_probe() accordingly.
- Cares for calling clk_put() which is missing in both probe's error
path and the remove function.
- Cares for calling clk_unprepare() which can be dropped from the error
paths and the remove function. (Note that not all error path got this
right.)
With additionally using devm_pwmchip_add() instead of pwmchip_add() the
remove callback can be dropped completely. With it the last user of
platform_get_drvdata() goes away and so platform_set_drvdata() can be
dropped from the probe function, too.
Fixes: 378fe115d1 ("pwm: sti: Add new driver for ST's PWM IP")
Link: https://lore.kernel.org/r/81f0e1d173652f435afda6719adaed1922fe059a.1710068192.git.u.kleine-koenig@pengutronix.de
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
With 16 channel pwm support, we're registering two instances of pwm_chip
with 8 channels each. We need to update PM functions to use both instances
of pwm_chip during power state transitions.
Introduce struct dwc_pwm_drvdata and use it as driver_data, which will
maintain both instances of pwm_chip along with dwc_pwm_info and allow us
to use them inside suspend/resume handles.
Fixes: ebf2c89eb9 ("pwm: dwc: Add 16 channel support for Intel Elkhart Lake")
Signed-off-by: Raag Jadav <raag.jadav@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20240415074051.14681-1-raag.jadav@intel.com
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
22e8e19 has introduced a regression in the imgchip->pwm_clk lookup, whereas
the clock name has also been renamed to "imgchip". This causes the driver
failing to load:
[ 0.546905] img-pwm 18101300.pwm: failed to get imgchip clock
[ 0.553418] img-pwm: probe of 18101300.pwm failed with error -2
Fix this lookup by reverting the clock name back to "pwm".
Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
Link: https://lore.kernel.org/r/20240320083602.81592-1-wigyori@uid0.hu
Fixes: 22e8e19a46 ("pwm: img: Rename variable pointing to driver private data")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
The following commit abf6569d64 ("pwm: imx-tpm: Make use of
devm_pwmchip_alloc() function") introduced an issue that accessing
registers without clock which results in the following boot crash
on MX7ULP platform. Fixed it by enabling clock properly.
Unhandled fault: external abort on non-linefetch (0x1008) at 0xf0978004
[f0978004] *pgd=64009811, *pte=40250653, *ppte=40250453
Internal error: : 1008 [#1] SMP ARM
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.8.0-rc6-next-20240301 #18
Hardware name: Freescale i.MX7ULP (Device Tree)
PC is at pwm_imx_tpm_probe+0x1c/0xd8
LR is at __devm_ioremap_resource+0xf8/0x1dc
pc : [<c0629e58>] lr : [<c0562d4c>] psr: 80000053
sp : f0825e10 ip : 00000000 fp : 00000000
r10: c148f8c0 r9 : c41fc338 r8 : c164b000
r7 : 00000000 r6 : c406b400 r5 : c406b410 r4 : f0978000
r3 : 00000005 r2 : 00000000 r1 : a0000053 r0 : f0978000
Flags: Nzcv IRQs on FIQs off Mode SVC_32 ISA ARM Segment none
Control: 10c5387d Table: 6000406a DAC: 00000051
...
Call trace:
pwm_imx_tpm_probe from platform_probe+0x58/0xb0
platform_probe from really_probe+0xc4/0x2e0
really_probe from __driver_probe_device+0x84/0x19c
__driver_probe_device from driver_probe_device+0x2c/0x104
driver_probe_device from __driver_attach+0x90/0x170
__driver_attach from bus_for_each_dev+0x7c/0xd0
bus_for_each_dev from bus_add_driver+0xc4/0x1cc
bus_add_driver from driver_register+0x7c/0x114
driver_register from do_one_initcall+0x58/0x270
do_one_initcall from kernel_init_freeable+0x170/0x218
kernel_init_freeable from kernel_init+0x14/0x140
kernel_init from ret_from_fork+0x14/0x20
Fixes: abf6569d64 ("pwm: imx-tpm: Make use of devm_pwmchip_alloc() function")
Signed-off-by: Dong Aisheng <aisheng.dong@nxp.com>
Link: https://lore.kernel.org/r/20240304102929.893542-1-aisheng.dong@nxp.com
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>