Hi,
Some platforms (like TI) have complex DVFS configuration for CPU
devices, where multiple regulators are required to be configured to
change DVFS state of the device. This was explained well by Nishanth
earlier [1].
One of the major complaints around multiple regulators case was that the
DT isn't responsible in any way to represent the order in which multiple
supplies need to be programmed, before or after a frequency change. It
was considered in this patch and such information is left for the
platform specific OPP driver now, which can register its own
opp_set_rate() callback with the OPP core and the OPP core will then
call it during DVFS.
The patches are tested on Exynos5250 (Dual A15). I have hacked around DT
and code to pass values for multiple regulators and verified that they
are all properly read by the kernel (using debugfs interface).
Dave Gerlach has already tested [2] it on the real TI platforms and it
works well for him.
This is rebased over: linux-next branch in the PM tree.
V4->V5:
- Stephen boyd had some minor review comments and gave his Reviewed-by
tag for the rest. Only 2 patches don't have his RBY tag.
- Individual patches contain the version history from V4 to V5.
V3->V4:
- Separate out cpu-supply fix in the binding in a separate patch (Mark).
- Add more documentation to the binding to explain that the relation to
the supplies and the order of programming them is left for the
platform specific bindings and that every platform using multiple
regulators for their devices needs to provide a separate binding
document explaining their implementation (Mark).
- @Rob and Stephen: I have kept your Acks for the bindings as the
bindings only got a bit reworded (improved) since the time you guys
Acked them. Please let me know if you want more improvement in the
bindings now.
- V4 for 10/10 was sent earlier, which added a missing
rcu_read_unlock(). Nothing else changed in it.
- Added some missing Kernel documentation comments
V2->V3:
- The last patch is new
- Removed a debug leftover pr_info() message
- Renamed few names as s/set_rate/set_opp
- Removed a TODO comment (as it is done now with this series)
- created struct for min_uV and max_uV
- kerneldoc comments for structures in pm_opp.h
- s/const char */const char * const
- use kasprintf()
- Some more minor reformatting
- More Ack/RBY tags added
V1->V2:
- Ack from Rob for 1st patch
- Moved the supplies structure to pm_opp.h (Dave)
- Fixed an compilation warning.
--
viresh
[1] https://marc.info/?l=linux-pm&m=145684495832764&w=2
[2] https://marc.info/?l=linux-kernel&m=147924789305276&w=2
Viresh Kumar (10):
PM / OPP: Fix incorrect cpu-supply property in binding
PM / OPP: Reword binding supporting multiple regulators per device
PM / OPP: Don't use OPP structure outside of rcu protected section
PM / OPP: Manage supply's voltage/current in a separate structure
PM / OPP: Pass struct dev_pm_opp_supply to _set_opp_voltage()
PM / OPP: Add infrastructure to manage multiple regulators
PM / OPP: Separate out _generic_set_opp()
PM / OPP: Allow platform specific custom set_opp() callbacks
PM / OPP: Don't WARN on multiple calls to dev_pm_opp_set_regulators()
PM / OPP: Don't assume platform doesn't have regulators
Documentation/devicetree/bindings/opp/opp.txt | 27 +-
drivers/base/power/opp/core.c | 536 ++++++++++++++++++++------
drivers/base/power/opp/debugfs.c | 52 ++-
drivers/base/power/opp/of.c | 105 +++--
drivers/base/power/opp/opp.h | 22 +-
drivers/cpufreq/cpufreq-dt.c | 9 +-
include/linux/pm_opp.h | 69 +++-
7 files changed, 634 insertions(+), 186 deletions(-)
--
2.7.1.410.g6faf27b
Tree/Branch: next-20161129
Git describe: next-20161129
Commit: 4030ddad30 Add linux-next specific files for 20161129
Build Time: 84 min 40 sec
Passed: 10 / 10 (100.00 %)
Failed: 0 / 10 ( 0.00 %)
Errors: 0
Warnings: 2
Section Mismatches: 0
-------------------------------------------------------------------------------
defconfigs with issues (other than build errors):
1 warnings 0 mismatches : arm64-allmodconfig
1 warnings 0 mismatches : arm64-defconfig
-------------------------------------------------------------------------------
Warnings Summary: 2
1 ../include/linux/kern_levels.h:4:18: warning: format '%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Wformat=]
1 ../fs/btrfs/inode.c:1198:31: warning: 'cur_end' may be used uninitialized in this function [-Wmaybe-uninitialized]
===============================================================================
Detailed per-defconfig build reports below:
-------------------------------------------------------------------------------
arm64-allmodconfig : PASS, 0 errors, 1 warnings, 0 section mismatches
Warnings:
../include/linux/kern_levels.h:4:18: warning: format '%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Wformat=]
-------------------------------------------------------------------------------
arm64-defconfig : PASS, 0 errors, 1 warnings, 0 section mismatches
Warnings:
../fs/btrfs/inode.c:1198:31: warning: 'cur_end' may be used uninitialized in this function [-Wmaybe-uninitialized]
-------------------------------------------------------------------------------
Passed with no errors, warnings or mismatches:
arm64-allnoconfig
arm-multi_v5_defconfig
arm-multi_v7_defconfig
x86_64-defconfig
arm-allmodconfig
arm-allnoconfig
x86_64-allnoconfig
arm-multi_v4t_defconfig
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
Joonyoung Shim reported an interesting problem on his ARM octa-core
Odoroid-XU3 platform. During system suspend, dev_pm_opp_put_regulator()
was failing for a struct device for which dev_pm_opp_set_regulator() is
called earlier.
This happened because an earlier call to
dev_pm_opp_of_cpumask_remove_table() function (from cpufreq-dt.c file)
removed all the entries from opp_table->dev_list apart from the last CPU
device in the cpumask of CPUs sharing the OPP.
But both dev_pm_opp_set_regulator() and dev_pm_opp_put_regulator()
routines get CPU device for the first CPU in the cpumask. And so the OPP
core failed to find the OPP table for the struct device.
In order to fix that up properly, we need to revisit APIs like
dev_pm_opp_set_regulator() and make them talk in terms of cookies
provided by the OPP core. But such a solution will be hard to backport
to stable kernels.
This patch attempts to fix this problem (in a Hacky way) by specially
handling the first cpu in the mask. A FIXME is also added to make sure
that this Hack doesn't get unnoticed later on.
Cc: # v4.4+ <stable(a)vger.kernel.org>
Signed-off-by: Viresh Kumar <viresh.kumar(a)linaro.org>
---
V1->V2:
- A completely different approach, more of hack so that backport to
stable kernels can be done easily.
- A more comprehensive solution is required to fix the design flaws.
drivers/base/power/opp/cpu.c | 50 +++++++++++++++++++++++++++++++-------------
1 file changed, 35 insertions(+), 15 deletions(-)
diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c
index 8c3434bdb26d..5d1b0f98bcb0 100644
--- a/drivers/base/power/opp/cpu.c
+++ b/drivers/base/power/opp/cpu.c
@@ -118,26 +118,46 @@ void dev_pm_opp_free_cpufreq_table(struct device *dev,
EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
#endif /* CONFIG_CPU_FREQ */
+void _cpu_remove_table(unsigned int cpu, bool of)
+{
+ struct device *cpu_dev = get_cpu_device(cpu);
+
+ if (!cpu_dev) {
+ pr_err("%s: failed to get cpu%d device\n", __func__, cpu);
+ return;
+ }
+
+ if (of)
+ dev_pm_opp_of_remove_table(cpu_dev);
+ else
+ dev_pm_opp_remove_table(cpu_dev);
+}
+
void _dev_pm_opp_cpumask_remove_table(const struct cpumask *cpumask, bool of)
{
- struct device *cpu_dev;
- int cpu;
+ struct cpumask tmpmask;
+ int cpu, first_cpu;
WARN_ON(cpumask_empty(cpumask));
- for_each_cpu(cpu, cpumask) {
- cpu_dev = get_cpu_device(cpu);
- if (!cpu_dev) {
- pr_err("%s: failed to get cpu%d device\n", __func__,
- cpu);
- continue;
- }
-
- if (of)
- dev_pm_opp_of_remove_table(cpu_dev);
- else
- dev_pm_opp_remove_table(cpu_dev);
- }
+ /*
+ * The first cpu in the cpumask is important as that is used to create
+ * the opp-table initially and routines like dev_pm_opp_put_regulator()
+ * will expect the list-dev for the first CPU to be present while such
+ * routines are called, otherwise we will fail to find the opp-table for
+ * such devices.
+ *
+ * FIXME: Cleanup this mess and implement cookie based solutions instead
+ * of working on the device pointer.
+ */
+ first_cpu = cpumask_first(cpumask);
+ cpumask_copy(&tmpmask, cpumask);
+ cpumask_clear_cpu(first_cpu, &tmpmask);
+
+ for_each_cpu(cpu, &tmpmask)
+ _cpu_remove_table(cpu, of);
+
+ _cpu_remove_table(first_cpu, of);
}
/**
--
2.7.1.410.g6faf27b
Hi,
Some platforms (like TI) have complex DVFS configuration for CPU
devices, where multiple regulators are required to be configured to
change DVFS state of the device. This was explained well by Nishanth
earlier [1].
One of the major complaints around multiple regulators case was that the
DT isn't responsible in any way to represent the order in which multiple
supplies need to be programmed, before or after a frequency change. It
was considered in this patch and such information is left for the
platform specific OPP driver now, which can register its own
opp_set_rate() callback with the OPP core and the OPP core will then
call it during DVFS.
The patches are tested on Exynos5250 (Dual A15). I have hacked around DT
and code to pass values for multiple regulators and verified that they
are all properly read by the kernel (using debugfs interface).
Dave Gerlach has already tested [2] it on the real TI platforms and it
works well for him.
This is rebased over: linux-next branch in the PM tree.
V3->V4:
- Separate out cpu-supply fix in the binding in a separate patch (Mark).
- Add more documentation to the binding to explain that the relation to
the supplies and the order of programming them is left for the
platform specific bindings and that every platform using multiple
regulators for their devices needs to provide a separate binding
document explaining their implementation (Mark).
- @Rob and Stephen: I have kept your Acks for the bindings as the
bindings only got a bit reworded (improved) since the time you guys
Acked them. Please let me know if you want more improvement in the
bindings now.
- V4 for 10/10 was sent earlier, which added a missing
rcu_read_unlock(). Nothing else changed in it.
- Added some missing Kernel documentation comments
V2->V3:
- The last patch is new
- Removed a debug leftover pr_info() message
- Renamed few names as s/set_rate/set_opp
- Removed a TODO comment (as it is done now with this series)
- created struct for min_uV and max_uV
- kerneldoc comments for structures in pm_opp.h
- s/const char */const char * const
- use kasprintf()
- Some more minor reformatting
- More Ack/RBY tags added
V1->V2:
- Ack from Rob for 1st patch
- Moved the supplies structure to pm_opp.h (Dave)
- Fixed an compilation warning.
--
viresh
[1] https://marc.info/?l=linux-pm&m=145684495832764&w=2
[2] https://marc.info/?l=linux-kernel&m=147924789305276&w=2
Viresh Kumar (10):
PM / OPP: Fix incorrect cpu-supply property in binding
PM / OPP: Reword binding supporting multiple regulators per device
PM / OPP: Don't use OPP structure outside of rcu protected section
PM / OPP: Manage supply's voltage/current in a separate structure
PM / OPP: Pass struct dev_pm_opp_supply to _set_opp_voltage()
PM / OPP: Add infrastructure to manage multiple regulators
PM / OPP: Separate out _generic_opp_set_rate()
PM / OPP: Allow platform specific custom set_opp() callbacks
PM / OPP: Don't WARN on multiple calls to dev_pm_opp_set_regulators()
PM / OPP: Don't assume platform doesn't have regulators
Documentation/devicetree/bindings/opp/opp.txt | 27 +-
drivers/base/power/opp/core.c | 511 ++++++++++++++++++++------
drivers/base/power/opp/debugfs.c | 52 ++-
drivers/base/power/opp/of.c | 105 ++++--
drivers/base/power/opp/opp.h | 22 +-
drivers/cpufreq/cpufreq-dt.c | 9 +-
include/linux/pm_opp.h | 67 +++-
7 files changed, 612 insertions(+), 181 deletions(-)
--
2.7.1.410.g6faf27b
The following patches enable pwm and IIO Timer features for stm32 platforms.
Those two features are mixed into the registers of the same hardware block
(named timer) which lead to introduce a multifunctions driver on the top to
be able to share the registers.
In stm32 14 instances of timer hardware block exist, even if they all have
the same register mapping they could have a different number of pwm channels
and/or different triggers capabilities. To keep the code as simple as possible
we use compatible and platform_data to distinguish them.
The MFD (stm32-mfd-timer.c) takes care of clock, interrupt and register mapping
by using regmap. stm32_mfd_timer_dev structure is provided to its children to
share those information.
PWM driver is implemented into pwm-stm32.c. Depending of the instance we may
have up to 4 channels, sometime with complementary outputs or 32 bits counter
instead of 16 bits. Some hardware blocks may also have a break input function
which allows to stop pwm depending of a level, defined in devicetree, on an
external pin.
IIO timer driver (stm32-iio-timer.c and stm32-iio-timers.h) define a list of
hardware triggers usable by hardware blocks like ADC, DAC or other timers.
The matrix of possible connections between blocks is quite complex so we use
trigger names and is_stm32_iio_timer_trigger() function to be sure that
triggers are valid and configure the IPs.
Timer hardware blocks can configure (through "master_mode" IIO device attribute)
which internal signal (counter enable, reset, comparison block, etc...) is
used to generate the trigger.
By using "slave_mode" IIO device attribute timer can also configure on which
event (level, rising edge) of the block is enabled.
Since we can use trigger from one hardware to control an other block, we can
use a pwm to control an other one. The following example shows how to configure
pwm1 and pwm3 to make pwm3 generate pulse only when pwm1 pulse level is high.
/sys/bus/iio/devices # ls
iio:device0 iio:device1 trigger0 trigger1
configure timer1 to use pwm1 channel 0 as output trigger
/sys/bus/iio/devices # echo 4 > iio\:device0/master_mode
configure timer3 to enable only when input is high
/sys/bus/iio/devices # echo 5 > iio\:device1/slave_mode
/sys/bus/iio/devices # cat trigger0/name
tim1_trgo
configure timer2 to use timer1 trigger is input
/sys/bus/iio/devices # echo "tim1_trgo" > iio\:device1/trigger/current_trigger
configure pwm3 channel 0 to generate a signal with a period of 100ms and a
duty cycle of 50%
/sys/devices/platform/soc/40000400.mfdtimer3/pwm3/pwm/pwmchip4 # echo 0 > export
/sys/devices/platform/soc/40000400.mfdtimer3/pwm3/pwm/pwmchip4 # echo 100000000 > pwm0/period
/sys/devices/platform/soc/40000400.mfdtimer3/pwm3/pwm/pwmchip4 # echo 50000000 > pwm0/duty_cycle
/sys/devices/platform/soc/40000400.mfdtimer3/pwm3/pwm/pwmchip4 # echo 1 > pwm0/enable
here pwm3 channel 0, as expected, doesn't start because has to be triggered by
pwm1 channel 0
configure pwm1 channel 0 to generate a signal with a period of 1s and a
duty cycle of 50%
/sys/devices/platform/soc/40010000.mfdtimer1/pwm1/pwm/pwmchip0 # echo 0 > export
/sys/devices/platform/soc/40010000.mfdtimer1/pwm1/pwm/pwmchip0 # echo 1000000000 > pwm0/period
/sys/devices/platform/soc/40010000.mfdtimer1/pwm1/pwm/pwmchip0 # echo 500000000 > pwm0/duty_cycle
/sys/devices/platform/soc/40010000.mfdtimer1/pwm1/pwm/pwmchip0 # echo 1 > pwm0/enable
finally pwm1 starts and pwm3 only generates pulse when pwm1 signal is high
An other example to use a timer as source of clock for another device.
Here timer1 is used a source clock for pwm3:
/sys/bus/iio/devices # echo 100000 > trigger0/sampling_frequency
/sys/bus/iio/devices # echo tim1_trgo > iio\:device1/trigger/current_trigger
/sys/bus/iio/devices # echo 7 > iio\:device1/slave_mode
/sys/devices/platform/soc/40000400.mfdtimer3/pwm3/pwm/pwmchip4 # echo 0 > export
/sys/devices/platform/soc/40000400.mfdtimer3/pwm3/pwm/pwmchip4 # echo 1000000 > pwm0/period
/sys/devices/platform/soc/40000400.mfdtimer3/pwm3/pwm/pwmchip4 # echo 500000 > pwm0/duty_cycle
/sys/devices/platform/soc/40000400.mfdtimer3/pwm3/pwm/pwmchip4 # echo 1 > pwm0/enable
Benjamin Gaignard (7):
add binding for stm32 multifunctions timer driver
add MFD for stm32 timer IP
add pwm-stm32 DT bindings
add pwm driver for stm32 plaftorm
add bindings for stm32 IIO timer drivers
add STM32 IIO timer driver
add stm32 multi-functions timer driver in DT
.../bindings/iio/timer/stm32-iio-timer.txt | 33 +
.../devicetree/bindings/mfd/stm32-timer.txt | 53 ++
.../devicetree/bindings/pwm/pwm-stm32.txt | 43 ++
arch/arm/boot/dts/stm32f429.dtsi | 246 +++++++
arch/arm/boot/dts/stm32f469-disco.dts | 29 +
drivers/iio/Kconfig | 2 +-
drivers/iio/Makefile | 1 +
drivers/iio/timer/Kconfig | 15 +
drivers/iio/timer/Makefile | 1 +
drivers/iio/timer/stm32-iio-timer.c | 766 +++++++++++++++++++++
drivers/iio/trigger/Kconfig | 1 -
drivers/mfd/Kconfig | 10 +
drivers/mfd/Makefile | 2 +
drivers/mfd/stm32-mfd-timer.c | 236 +++++++
drivers/pwm/Kconfig | 8 +
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-stm32.c | 358 ++++++++++
include/linux/iio/timer/stm32-iio-timers.h | 25 +
include/linux/mfd/stm32-mfd-timer.h | 78 +++
19 files changed, 1906 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/iio/timer/stm32-iio-timer.txt
create mode 100644 Documentation/devicetree/bindings/mfd/stm32-timer.txt
create mode 100644 Documentation/devicetree/bindings/pwm/pwm-stm32.txt
create mode 100644 drivers/iio/timer/Kconfig
create mode 100644 drivers/iio/timer/Makefile
create mode 100644 drivers/iio/timer/stm32-iio-timer.c
create mode 100644 drivers/mfd/stm32-mfd-timer.c
create mode 100644 drivers/pwm/pwm-stm32.c
create mode 100644 include/linux/iio/timer/stm32-iio-timers.h
create mode 100644 include/linux/mfd/stm32-mfd-timer.h
--
1.9.1
Tree/Branch: next-20161128
Git describe: next-20161128
Commit: 02eb3c71e3 Add linux-next specific files for 20161128
Build Time: 72 min 19 sec
Passed: 8 / 10 ( 80.00 %)
Failed: 2 / 10 ( 20.00 %)
Errors: 0
Warnings: 3
Section Mismatches: 0
Failed defconfigs:
arm64-allmodconfig
arm-allmodconfig
Errors:
-------------------------------------------------------------------------------
defconfigs with issues (other than build errors):
2 warnings 0 mismatches : arm64-allmodconfig
1 warnings 0 mismatches : arm-allmodconfig
1 warnings 0 mismatches : arm64-defconfig
-------------------------------------------------------------------------------
Warnings Summary: 3
2 ../include/linux/device.h:1300:36: warning: 'rate' may be used uninitialized in this function [-Wmaybe-uninitialized]
1 ../include/linux/kern_levels.h:4:18: warning: format '%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Wformat=]
1 ../fs/btrfs/inode.c:1198:31: warning: 'cur_end' may be used uninitialized in this function [-Wmaybe-uninitialized]
===============================================================================
Detailed per-defconfig build reports below:
-------------------------------------------------------------------------------
arm64-allmodconfig : FAIL, 0 errors, 2 warnings, 0 section mismatches
Warnings:
../include/linux/kern_levels.h:4:18: warning: format '%d' expects argument of type 'int', but argument 2 has type 'long unsigned int' [-Wformat=]
../include/linux/device.h:1300:36: warning: 'rate' may be used uninitialized in this function [-Wmaybe-uninitialized]
-------------------------------------------------------------------------------
arm-allmodconfig : FAIL, 0 errors, 1 warnings, 0 section mismatches
Warnings:
../include/linux/device.h:1300:36: warning: 'rate' may be used uninitialized in this function [-Wmaybe-uninitialized]
-------------------------------------------------------------------------------
arm64-defconfig : PASS, 0 errors, 1 warnings, 0 section mismatches
Warnings:
../fs/btrfs/inode.c:1198:31: warning: 'cur_end' may be used uninitialized in this function [-Wmaybe-uninitialized]
-------------------------------------------------------------------------------
Passed with no errors, warnings or mismatches:
arm64-allnoconfig
arm-multi_v5_defconfig
arm-multi_v7_defconfig
x86_64-defconfig
arm-allnoconfig
x86_64-allnoconfig
arm-multi_v4t_defconfig