Age | Commit message (Collapse) | Author | Files | Lines |
|
According to the datasheet the update bit must be set if the on-time-div
or the base-unit changes.
Now that we properly order device resume on Cherry Trail so that the GFX0
_PS0 method no longer exits with an error, we end up with a sequence of
events where we are writing the same values twice in a row.
First the _PS0 method restores the duty cycle of 0% the GPU driver set
on suspend and then the GPU driver first updates just the enabled bit in
the pwm_state from 0 to 1, causing us to write the same values again,
before restoring the pre-suspend duty-cycle in a separate pwm_apply call.
When writing the update bit the second time, without changing any of
the values the update bit clears immediately / instantly, instead of
staying 1 for a while as usual. After this the next setting of the update
bit seems to be ignored, causing the restoring of the pre-suspend
duty-cycle to not get applied. This makes the backlight come up with
a 0% dutycycle after suspend/resume.
Any further brightness changes after this do work.
This commit moves the setting of the update bit into pwm_lpss_prepare()
and only sets the bit if we have actually changed any of the values.
This avoids the setting of the update bit the second time we configure
the PWM to 0% dutycycle, this fixes the backlight coming up with 0%
duty-cycle after a suspend/resume.
Signed-off-by: Hans de Goede <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Add a get_state callback so that the initial state correctly reflects
the actual hardware state.
Cc: Andy Shevchenko <[email protected]>
Acked-by: Jani Nikula <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
Signed-off-by: Hans de Goede <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
For each pwm output which gets enabled through pwm_lpss_apply(), we do a
pm_runtime_get_sync().
This commit adds pm_runtime_put() calls to pwm_lpss_remove() to balance
these when the driver gets removed with some of the outputs still enabled.
Fixes: f080be27d7d9 ("pwm: lpss: Add support for runtime PM")
Acked-by: Andy Shevchenko <[email protected]>
Signed-off-by: Hans de Goede <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Move struct pwm_lpss_chip definition from pwm-lpss.c to pwm-lpss.h,
so that the pci/platform drivers can access the info member
(struct pwm_lpss_boardinfo *).
This is a preparation patch for adding platform specific quirks, which
the drivers need access to, to pwm_lpss_boardinfo.
Reviewed-by: Andy Shevchenko <[email protected]>
Signed-off-by: Hans de Goede <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
On some devices the contents of the ctrl register get lost over a
suspend/resume and the PWM comes back up disabled after the resume.
This is seen on some Bay Trail devices with the PWM in ACPI enumerated
mode, so it shows up as a platform device instead of a PCI device.
If we still think it is enabled and then try to change the duty-cycle
after this, we end up with a "PWM_SW_UPDATE was not cleared" error and
the PWM is stuck in that state from then on.
This commit adds suspend and resume pm callbacks to the pwm-lpss-platform
code, which save/restore the ctrl register over a suspend/resume, fixing
this.
Note that:
1) There is no need to do this over a runtime suspend, since we
only runtime suspend when disabled and then we properly set the enable
bit and reprogram the timings when we re-enable the PWM.
2) This may be happening on more systems then we realize, but has been
covered up sofar by a bug in the acpi-lpss.c code which was save/restoring
the regular device registers instead of the lpss private registers due to
lpss_device_desc.prv_offset not being set. This is fixed by a later patch
in this series.
Cc: [email protected]
Signed-off-by: Hans de Goede <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
At least on cherrytrail, the update bit will never go low when the
enabled bit is not set.
This causes the backlight on my cube iwork8 air tablet to never turn on
again after being turned off because in the pwm_lpss_apply enable path
pwm_lpss_update will fail causing an error exit and the enable-bit to
never get set. Any following pwm_lpss_apply calls will fail the
pwm_lpss_is_updating check.
Since the docs say that the update bit should be set before the
enable-bit, split pwm_lpss_update into setting the update-bit and
pwm_lpss_wait_for_update, and move the pwm_lpss_wait_for_update call
in the enable path to after setting the enable-bit.
Fixes: 10d56a4 ("pwm: lpss: Avoid reconfiguring while UPDATE bit...")
Cc: Ilkka Koskinen <[email protected]>
Signed-off-by: Hans de Goede <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
Tested-by: Hans de Goede <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
The PWM LPSS probe drivers just pass a pointer to the exported board
info structures to pwm_lpss_probe() based on device PCI or ACPI ID.
In order to remove the knowledge of specific devices from library part of
the driver and reduce noise in exported namespace just duplicate the
board info structures and stop exporting them.
Signed-off-by: Andy Shevchenko <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
PWM Configuration register has SW_UPDATE bit that is set when a new
configuration is written to the register. The bit is automatically
cleared at the start of the next output cycle by the IP block.
If one writes a new configuration to the register while it still has
the bit enabled, PWM may freeze. That is, while one can still write
to the register, it won't have an effect. Thus, we try to sleep long
enough that the bit gets cleared and make sure the bit is not
enabled while we update the configuration.
Reviewed-by: Mika Westerberg <[email protected]>
Tested-by: Richard Griffiths <[email protected]>
Signed-off-by: Ilkka Koskinen <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Instead of doing things separately, which is not so reliable on some platforms,
switch the driver to use new atomic API, i.e. ->apply() callback.
The change has been tested on Intel platforms such as Broxton, BayTrail, and
Merrifield.
Reviewed-by: Mika Westerberg <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
A duty cycle is represented by values [0..<period>] which reflects [0%..100%].
0% of the duty cycle means always off (logical "0") on output. Allow this in
the driver.
Reviewed-by: Mika Westerberg <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
The resolution of base_unit is derived from base_unit_bits and thus must be
equal to (2^base_unit_bits - 1). Otherwise frequency and therefore base_unit
might potentially overflow.
Prevent the above by substracting 1 in all cases where base_unit_bits or
derivative is used.
Reviewed-by: Mika Westerberg <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
There is no need to check each time if the clk_rate defined or not when we call
pwm_lpss_config(). Move the check to ->probe() instead.
Signed-off-by: Andy Shevchenko <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
If duty_ns is large enough multiplying it by 255 overflows and results
wrong duty cycle value being programmed. For example with 10ms duty when
period is 20ms (50%) we get
255 * 10000000 / 20000000 = -87
because 255 * 10000000 overlows int. Whereas correct value should be
255 * 10000000 / 20000000 = 127
Fix this by using unsigned long long as type for on_time_div and changing
integer literals to use proper type annotation.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
The base_unit calculation applies an offset of 0x2 which adds
significant error for lower frequencies and doesn't appear to be
warranted - rounding the division result gives a correct value.
Also, the upper limit check for base_unit is off-by-one; the upper
nibble of base_unit is invalid if >=128 according to the Table 88
in the Z8000 Processor Series Datasheet Volume 1 (Rev. 2).
Verified on UP Board (Cherry Trail) and Minnowboard Max (Bay Trail).
Signed-off-by: Dan O'Donovan <[email protected]>
Acked-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Setting of PWM_SW_UPDATE is bit different in Intel Broxton compared to the
previous generation SoCs. Previously it was OK to set the bit many times
(from userspace via sysfs for example) before the PWM is actually enabled.
Starting from Intel Broxton it seems that we must set PWM_SW_UPDATE only
once before the PWM is enabled. Otherwise it is possible that the PWM does
not start properly.
Change the sequence of how PWM_SW_UPDATE is programmed so that we only set
it in pwm_lpss_config() when the PWM is already enabled. The initial
setting of PWM_SW_UPDATE will be done when PWM gets enabled. This should
make the driver work with the previous generation Intel SoCs and Broxton.
Add also small delay after the bit is set to let the hardware propagate it
properly.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
For Broxton PWM controller, base unit is defined as 8-bit integer
and 14-bit fraction, so need to update base unit setting to output
wave with right frequency.
Signed-off-by: Qipeng Zha <[email protected]>
Acked-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
The LPSS PWM driver calls pwm_lpss_disable() when the PWM device is
released (for example unexported from sysfs). This in turn calls
pm_runtime_put() which makes runtime PM count to be unbalanced if the
device has not been enabled at this point.
This is easy to reproduce:
# cd /sys/class/pwm/pwmchip0
# echo 0 > export
# echo 0 > unexport
The count is unbalanced and prevents the PWM device from being powered on
next time.
Fix this by removing ->free() callback. There are no resources to be
released anyway.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
To be able to save some power when PWM is not in use, add support for
runtime PM for this driver. This also allows the platform to transition to
low power S0ix states when the system is idle.
Signed-off-by: Huiquan Zhong <[email protected]>
Signed-off-by: Qipeng Zha <[email protected]>
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Intel Broxton has similar PWM than Intel Braswell but instead of one it has
four PWMs included in one PCI/ACPI device. This patch adds support for all
the four PWMs and changes the PCI part of the driver to use
'pwm_lpss_bxt_info' instead.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
New Intel SoCs such as Broxton will have four PWMs per PCI (or ACPI)
device. Each PWM has 1k of register space allocated from the parent device.
Add support for this.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Use c99 initializers for structures.
A simplified version of the semantic match that finds this problem is as
follows: (http://coccinelle.lip6.fr/)
// <smpl>
@decl@
identifier i1,fld;
type T;
field list[n] fs;
@@
struct i1 {
fs
T fld;
...};
@bad@
identifier decl.i1,i2;
expression e;
initializer list[decl.n] is;
@@
struct i1 i2 = { is,
+ .fld = e
- e
,...};
// </smpl>
Signed-off-by: Julia Lawall <[email protected]>
[thierry.reding: rebased and applied same fix for Braswell]
Signed-off-by: Thierry Reding <[email protected]>
|
|
An x86 build seems to pull in the linux/io.h include indirectly. On
PowerPC that doesn't happen and the build breaks due to the readl() and
writel() functions not being declared. Fix this by explicitly including
linux/io.h.
Reported-by: Stephen Rothwell <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
The driver consists of core, PCI, and platform parts. It would be better
to split them into separate files.
The platform driver is now called pwm-lpss-platform. Thus, previously
set CONFIG_PWM_LPSS=m is not enough to build it. But we are on the safe
side since it seems no one from outside Intel is using it for now.
While here, move to use macros module_pci_driver() and
module_platform_driver().
Signed-off-by: Andy Shevchenko <[email protected]>
Reviewed-by: Mika Westerberg <[email protected]>
Acked-by: Alan Cox <[email protected]>
[thierry.reding: change select to depends on PWM_LPSS, cleanup]
Signed-off-by: Thierry Reding <[email protected]>
|
|
This is pretty much the same as Baytrail PWM. Only difference is that the
input clock runs on different frequency.
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Unlike other Intel LPSS devices, the PWM does not have the
clock dividers or the gate. All we get from the clock is the
rate. Since PCI case uses the driver data to get the rate,
we can drop the clk and use the same data also in case of
ACPI. The frequency is the same.
Signed-off-by: Heikki Krogerus <[email protected]>
Reviewed-by: Mika Westerberg <[email protected]>
Reviewed-by: Chew, Chiau Ee <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Fixes the following warnings reported by the 0-DAY kernel build testing
backend:
drivers/pwm/pwm-lpss.c: In function 'pwm_lpss_probe_pci':
>> drivers/pwm/pwm-lpss.c:192:2: warning: passing argument 3 of 'pwm_lpss_probe' discards 'const' qualifier from pointer target type [enabled by default]
lpwm = pwm_lpss_probe(&pdev->dev, &pdev->resource[0], info);
^
drivers/pwm/pwm-lpss.c:130:30: note: expected 'struct pwm_lpss_boardinfo *' but argument is of type 'const struct pwm_lpss_boardinfo *'
static struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev,
^
>> drivers/pwm/pwm-lpss.c:143:28: sparse: incorrect type in return expression (different address spaces)
drivers/pwm/pwm-lpss.c:143:28: expected struct pwm_lpss_chip *
drivers/pwm/pwm-lpss.c:143:28: got void [noderef] <asn:2>*regs
>> drivers/pwm/pwm-lpss.c:192:63: sparse: incorrect type in argument 3 (different modifiers)
drivers/pwm/pwm-lpss.c:192:63: expected struct pwm_lpss_boardinfo *info
drivers/pwm/pwm-lpss.c:192:63: got struct pwm_lpss_boardinfo const *[assigned] info
drivers/pwm/pwm-lpss.c: In function 'pwm_lpss_probe_pci':
drivers/pwm/pwm-lpss.c:192:2: warning: passing argument 3 of 'pwm_lpss_probe' discards 'const' qualifier from pointer target type [enabled by default]
lpwm = pwm_lpss_probe(&pdev->dev, &pdev->resource[0], info);
^
drivers/pwm/pwm-lpss.c:130:30: note: expected 'struct pwm_lpss_boardinfo *' but argument is of type 'const struct pwm_lpss_boardinfo *'
static struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev,
^
Reported-by: kbuild test robot <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Not all systems enumerate the PWM devices via ACPI. They can also be
exposed via the PCI interface.
Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Chew, Chiau Ee <[email protected]>
Reviewed-by: Mika Westerberg <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|
|
Add support for Intel Low Power I/O subsystem PWM controllers found on
Intel BayTrail SoC.
Signed-off-by: Mika Westerberg <[email protected]>
Signed-off-by: Chew, Kean Ho <[email protected]>
Signed-off-by: Chang, Rebecca Swee Fun <[email protected]>
Signed-off-by: Chew, Chiau Ee <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
|