* [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx
@ 2017-12-01 11:25 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, linux-pm-u79uwXL29TY76Z2rM5mHXA
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
Thomas Petazzoni,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Antoine Tenart, Miquèl Raynal, Nadav Haklai, Victor Gu,
Marcin Wojtas, Wilson Ding, Hua Jing, Neta Zur Hershkovits,
Evan Wang
Hi,
This series adds the CPU Frequency support on Armada 37xx using
DVFS. It is based on the initial work of Evan Wang and Victor Gu.
DVFS control is done by a set of registers from the North Bridge Power
Management block. The binding for this block is documented in patch 1.
While adding a new cpufreq driver I found that the Kconfig and
Makefile were no more in order, so it is fixed by patch 2 and 3.
The 4th patch is just about updating the MAINTAINERS file with the new
driver.
The next patch is the real purpose of the series. The main goal of
this driver is to setup the CPU load level in the hardware to
associate them to CPU frequencies and register a standard cpufreq
driver. Note that the hardware also capable of doing AVS (Adaptive
Voltage Scaling), by associating a voltage on each level beside the
CPU frequency. However, this support is not yet ready, so it is not
part of this series.
Finally, the last patch is for arm-soc the arm-soc subsystem through
mvebu and update the device tree to support the CPU frequency scaling.
An update on the CPU clock driver is needed in order to take into
account the DVFS setting. It's the purpose of an other series already
sent, but is no dependencies between the series (for building or at
runtime).
Thanks,
Gregory
Gregory CLEMENT (6):
dt-bindings: marvell: Add documentation for the North Bridge PM on
Armada 37xx
cpufreq: ARM: sort the Kconfig menu
cpufreq: sort the drivers in ARM part
MAINTAINERS: add new entries for Armada 37xx cpufreq driver
cpufreq: Add DVFS support for Armada 37xx
arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support
.../bindings/arm/marvell/armada-37xx.txt | 19 ++
MAINTAINERS | 1 +
arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +
drivers/cpufreq/Kconfig.arm | 89 ++++----
drivers/cpufreq/Makefile | 9 +-
drivers/cpufreq/armada-37xx-cpufreq.c | 241 +++++++++++++++++++++
7 files changed, 322 insertions(+), 45 deletions(-)
create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
--
2.15.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx
@ 2017-12-01 11:25 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This series adds the CPU Frequency support on Armada 37xx using
DVFS. It is based on the initial work of Evan Wang and Victor Gu.
DVFS control is done by a set of registers from the North Bridge Power
Management block. The binding for this block is documented in patch 1.
While adding a new cpufreq driver I found that the Kconfig and
Makefile were no more in order, so it is fixed by patch 2 and 3.
The 4th patch is just about updating the MAINTAINERS file with the new
driver.
The next patch is the real purpose of the series. The main goal of
this driver is to setup the CPU load level in the hardware to
associate them to CPU frequencies and register a standard cpufreq
driver. Note that the hardware also capable of doing AVS (Adaptive
Voltage Scaling), by associating a voltage on each level beside the
CPU frequency. However, this support is not yet ready, so it is not
part of this series.
Finally, the last patch is for arm-soc the arm-soc subsystem through
mvebu and update the device tree to support the CPU frequency scaling.
An update on the CPU clock driver is needed in order to take into
account the DVFS setting. It's the purpose of an other series already
sent, but is no dependencies between the series (for building or at
runtime).
Thanks,
Gregory
Gregory CLEMENT (6):
dt-bindings: marvell: Add documentation for the North Bridge PM on
Armada 37xx
cpufreq: ARM: sort the Kconfig menu
cpufreq: sort the drivers in ARM part
MAINTAINERS: add new entries for Armada 37xx cpufreq driver
cpufreq: Add DVFS support for Armada 37xx
arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support
.../bindings/arm/marvell/armada-37xx.txt | 19 ++
MAINTAINERS | 1 +
arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +
drivers/cpufreq/Kconfig.arm | 89 ++++----
drivers/cpufreq/Makefile | 9 +-
drivers/cpufreq/armada-37xx-cpufreq.c | 241 +++++++++++++++++++++
7 files changed, 322 insertions(+), 45 deletions(-)
create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
--
2.15.0
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/6] dt-bindings: marvell: Add documentation for the North Bridge PM on Armada 37xx
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-01 11:25 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, linux-pm
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
Extend the documentation of the Armada 37xx SoC with the the North
Bridge Power Management component.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
.../devicetree/bindings/arm/marvell/armada-37xx.txt | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
index 51336e5fc761..7ad9830d9177 100644
--- a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
+++ b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
@@ -14,3 +14,22 @@ following property before the previous one:
Example:
compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
+
+
+Power management
+----------------
+
+For power management (particularly DVFS and AVS), the North Bridge
+Power Management component is needed:
+
+Required properties:
+- compatible : should contain "marvell,armada-3700-nb-pm", "syscon";
+- reg : the register start and length for the North Bridge
+ Power Management
+
+Example:
+
+nb_pm: nb_pm@14000 {
+ compatible = "marvell,armada-3700-nb-pm", "syscon";
+ reg = <0x14000 0x60>;
+}
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 1/6] dt-bindings: marvell: Add documentation for the North Bridge PM on Armada 37xx
@ 2017-12-01 11:25 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: linux-arm-kernel
Extend the documentation of the Armada 37xx SoC with the the North
Bridge Power Management component.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
.../devicetree/bindings/arm/marvell/armada-37xx.txt | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
index 51336e5fc761..7ad9830d9177 100644
--- a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
+++ b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
@@ -14,3 +14,22 @@ following property before the previous one:
Example:
compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
+
+
+Power management
+----------------
+
+For power management (particularly DVFS and AVS), the North Bridge
+Power Management component is needed:
+
+Required properties:
+- compatible : should contain "marvell,armada-3700-nb-pm", "syscon";
+- reg : the register start and length for the North Bridge
+ Power Management
+
+Example:
+
+nb_pm: nb_pm at 14000 {
+ compatible = "marvell,armada-3700-nb-pm", "syscon";
+ reg = <0x14000 0x60>;
+}
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 2/6] cpufreq: ARM: sort the Kconfig menu
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-01 11:25 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, linux-pm
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
Group all the related big LITTLE configuration together and sort the
other entries in alphabetic order.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/cpufreq/Kconfig.arm | 82 ++++++++++++++++++++++-----------------------
1 file changed, 41 insertions(+), 41 deletions(-)
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index bdce4488ded1..17625115c67f 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -2,6 +2,23 @@
# ARM CPU Frequency scaling drivers
#
+config ACPI_CPPC_CPUFREQ
+ tristate "CPUFreq driver based on the ACPI CPPC spec"
+ depends on ACPI_PROCESSOR
+ select ACPI_CPPC_LIB
+ default n
+ help
+ This adds a CPUFreq driver which uses CPPC methods
+ as described in the ACPIv5.1 spec. CPPC stands for
+ Collaborative Processor Performance Controls. It
+ is based on an abstract continuous scale of CPU
+ performance values which allows the remote power
+ processor to flexibly optimize for power and
+ performance. CPPC relies on power management firmware
+ support for its operation.
+
+ If in doubt, say N.
+
# big LITTLE core layer and glue drivers
config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver"
@@ -12,6 +29,30 @@ config ARM_BIG_LITTLE_CPUFREQ
help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
+config ARM_DT_BL_CPUFREQ
+ tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver"
+ depends on ARM_BIG_LITTLE_CPUFREQ && OF
+ help
+ This enables probing via DT for Generic CPUfreq driver for ARM
+ big.LITTLE platform. This gets frequency tables from DT.
+
+config ARM_VEXPRESS_SPC_CPUFREQ
+ tristate "Versatile Express SPC based CPUfreq driver"
+ depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
+ help
+ This add the CPUfreq driver support for Versatile Express
+ big.LITTLE platforms using SPC for power management.
+
+config ARM_SCPI_CPUFREQ
+ tristate "SCPI based CPUfreq driver"
+ depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
+ help
+ This adds the CPUfreq driver support for ARM big.LITTLE platforms
+ using SCPI protocol for CPU power management.
+
+ This driver uses SCPI Message Protocol driver to interact with the
+ firmware providing the CPU DVFS functionality.
+
config ARM_BRCMSTB_AVS_CPUFREQ
tristate "Broadcom STB AVS CPUfreq driver"
depends on ARCH_BRCMSTB || COMPILE_TEST
@@ -33,20 +74,6 @@ config ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
If in doubt, say N.
-config ARM_DT_BL_CPUFREQ
- tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver"
- depends on ARM_BIG_LITTLE_CPUFREQ && OF
- help
- This enables probing via DT for Generic CPUfreq driver for ARM
- big.LITTLE platform. This gets frequency tables from DT.
-
-config ARM_VEXPRESS_SPC_CPUFREQ
- tristate "Versatile Express SPC based CPUfreq driver"
- depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
- help
- This add the CPUfreq driver support for Versatile Express
- big.LITTLE platforms using SPC for power management.
-
config ARM_EXYNOS5440_CPUFREQ
tristate "SAMSUNG EXYNOS5440"
depends on SOC_EXYNOS5440
@@ -205,16 +232,6 @@ config ARM_SA1100_CPUFREQ
config ARM_SA1110_CPUFREQ
bool
-config ARM_SCPI_CPUFREQ
- tristate "SCPI based CPUfreq driver"
- depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
- help
- This adds the CPUfreq driver support for ARM big.LITTLE platforms
- using SCPI protocol for CPU power management.
-
- This driver uses SCPI Message Protocol driver to interact with the
- firmware providing the CPU DVFS functionality.
-
config ARM_SPEAR_CPUFREQ
bool "SPEAr CPUFreq support"
depends on PLAT_SPEAR
@@ -275,20 +292,3 @@ config ARM_PXA2xx_CPUFREQ
This add the CPUFreq driver support for Intel PXA2xx SOCs.
If in doubt, say N.
-
-config ACPI_CPPC_CPUFREQ
- tristate "CPUFreq driver based on the ACPI CPPC spec"
- depends on ACPI_PROCESSOR
- select ACPI_CPPC_LIB
- default n
- help
- This adds a CPUFreq driver which uses CPPC methods
- as described in the ACPIv5.1 spec. CPPC stands for
- Collaborative Processor Performance Controls. It
- is based on an abstract continuous scale of CPU
- performance values which allows the remote power
- processor to flexibly optimize for power and
- performance. CPPC relies on power management firmware
- support for its operation.
-
- If in doubt, say N.
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 2/6] cpufreq: ARM: sort the Kconfig menu
@ 2017-12-01 11:25 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: linux-arm-kernel
Group all the related big LITTLE configuration together and sort the
other entries in alphabetic order.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/cpufreq/Kconfig.arm | 82 ++++++++++++++++++++++-----------------------
1 file changed, 41 insertions(+), 41 deletions(-)
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index bdce4488ded1..17625115c67f 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -2,6 +2,23 @@
# ARM CPU Frequency scaling drivers
#
+config ACPI_CPPC_CPUFREQ
+ tristate "CPUFreq driver based on the ACPI CPPC spec"
+ depends on ACPI_PROCESSOR
+ select ACPI_CPPC_LIB
+ default n
+ help
+ This adds a CPUFreq driver which uses CPPC methods
+ as described in the ACPIv5.1 spec. CPPC stands for
+ Collaborative Processor Performance Controls. It
+ is based on an abstract continuous scale of CPU
+ performance values which allows the remote power
+ processor to flexibly optimize for power and
+ performance. CPPC relies on power management firmware
+ support for its operation.
+
+ If in doubt, say N.
+
# big LITTLE core layer and glue drivers
config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver"
@@ -12,6 +29,30 @@ config ARM_BIG_LITTLE_CPUFREQ
help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
+config ARM_DT_BL_CPUFREQ
+ tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver"
+ depends on ARM_BIG_LITTLE_CPUFREQ && OF
+ help
+ This enables probing via DT for Generic CPUfreq driver for ARM
+ big.LITTLE platform. This gets frequency tables from DT.
+
+config ARM_VEXPRESS_SPC_CPUFREQ
+ tristate "Versatile Express SPC based CPUfreq driver"
+ depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
+ help
+ This add the CPUfreq driver support for Versatile Express
+ big.LITTLE platforms using SPC for power management.
+
+config ARM_SCPI_CPUFREQ
+ tristate "SCPI based CPUfreq driver"
+ depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
+ help
+ This adds the CPUfreq driver support for ARM big.LITTLE platforms
+ using SCPI protocol for CPU power management.
+
+ This driver uses SCPI Message Protocol driver to interact with the
+ firmware providing the CPU DVFS functionality.
+
config ARM_BRCMSTB_AVS_CPUFREQ
tristate "Broadcom STB AVS CPUfreq driver"
depends on ARCH_BRCMSTB || COMPILE_TEST
@@ -33,20 +74,6 @@ config ARM_BRCMSTB_AVS_CPUFREQ_DEBUG
If in doubt, say N.
-config ARM_DT_BL_CPUFREQ
- tristate "Generic probing via DT for ARM big LITTLE CPUfreq driver"
- depends on ARM_BIG_LITTLE_CPUFREQ && OF
- help
- This enables probing via DT for Generic CPUfreq driver for ARM
- big.LITTLE platform. This gets frequency tables from DT.
-
-config ARM_VEXPRESS_SPC_CPUFREQ
- tristate "Versatile Express SPC based CPUfreq driver"
- depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
- help
- This add the CPUfreq driver support for Versatile Express
- big.LITTLE platforms using SPC for power management.
-
config ARM_EXYNOS5440_CPUFREQ
tristate "SAMSUNG EXYNOS5440"
depends on SOC_EXYNOS5440
@@ -205,16 +232,6 @@ config ARM_SA1100_CPUFREQ
config ARM_SA1110_CPUFREQ
bool
-config ARM_SCPI_CPUFREQ
- tristate "SCPI based CPUfreq driver"
- depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
- help
- This adds the CPUfreq driver support for ARM big.LITTLE platforms
- using SCPI protocol for CPU power management.
-
- This driver uses SCPI Message Protocol driver to interact with the
- firmware providing the CPU DVFS functionality.
-
config ARM_SPEAR_CPUFREQ
bool "SPEAr CPUFreq support"
depends on PLAT_SPEAR
@@ -275,20 +292,3 @@ config ARM_PXA2xx_CPUFREQ
This add the CPUFreq driver support for Intel PXA2xx SOCs.
If in doubt, say N.
-
-config ACPI_CPPC_CPUFREQ
- tristate "CPUFreq driver based on the ACPI CPPC spec"
- depends on ACPI_PROCESSOR
- select ACPI_CPPC_LIB
- default n
- help
- This adds a CPUFreq driver which uses CPPC methods
- as described in the ACPIv5.1 spec. CPPC stands for
- Collaborative Processor Performance Controls. It
- is based on an abstract continuous scale of CPU
- performance values which allows the remote power
- processor to flexibly optimize for power and
- performance. CPPC relies on power management firmware
- support for its operation.
-
- If in doubt, say N.
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 3/6] cpufreq: sort the drivers in ARM part
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-01 11:25 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, linux-pm
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
Keep the driver files alphabetically sorted.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/cpufreq/Makefile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 812f9e0d01a3..d762e76887e7 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -53,22 +53,24 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
+obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
obj-$(CONFIG_ARM_MEDIATEK_CPUFREQ) += mediatek-cpufreq.o
+obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o
obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o
obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
-obj-$(CONFIG_ARM_S3C24XX_CPUFREQ) += s3c24xx-cpufreq.o
-obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o
obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o
obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o
obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o
obj-$(CONFIG_ARM_S3C2440_CPUFREQ) += s3c2440-cpufreq.o
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
+obj-$(CONFIG_ARM_S3C24XX_CPUFREQ) += s3c24xx-cpufreq.o
+obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
@@ -81,8 +83,6 @@ obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += tegra186-cpufreq.o
obj-$(CONFIG_ARM_TI_CPUFREQ) += ti-cpufreq.o
obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
-obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
-obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o
##################################################################################
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 3/6] cpufreq: sort the drivers in ARM part
@ 2017-12-01 11:25 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: linux-arm-kernel
Keep the driver files alphabetically sorted.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/cpufreq/Makefile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 812f9e0d01a3..d762e76887e7 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -53,22 +53,24 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
+obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
obj-$(CONFIG_ARM_MEDIATEK_CPUFREQ) += mediatek-cpufreq.o
+obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o
obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
obj-$(CONFIG_ARM_PXA2xx_CPUFREQ) += pxa2xx-cpufreq.o
obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
-obj-$(CONFIG_ARM_S3C24XX_CPUFREQ) += s3c24xx-cpufreq.o
-obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o
obj-$(CONFIG_ARM_S3C2410_CPUFREQ) += s3c2410-cpufreq.o
obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o
obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o
obj-$(CONFIG_ARM_S3C2440_CPUFREQ) += s3c2440-cpufreq.o
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
+obj-$(CONFIG_ARM_S3C24XX_CPUFREQ) += s3c24xx-cpufreq.o
+obj-$(CONFIG_ARM_S3C24XX_CPUFREQ_DEBUGFS) += s3c24xx-cpufreq-debugfs.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
@@ -81,8 +83,6 @@ obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += tegra186-cpufreq.o
obj-$(CONFIG_ARM_TI_CPUFREQ) += ti-cpufreq.o
obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
-obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
-obj-$(CONFIG_MACH_MVEBU_V7) += mvebu-cpufreq.o
##################################################################################
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 4/6] MAINTAINERS: add new entries for Armada 37xx cpufreq driver
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-01 11:25 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, linux-pm-u79uwXL29TY76Z2rM5mHXA
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Rob Herring, devicetree-u79uwXL29TY76Z2rM5mHXA,
Thomas Petazzoni,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Antoine Tenart, Miquèl Raynal, Nadav Haklai, Victor Gu,
Marcin Wojtas, Wilson Ding, Hua Jing, Neta Zur Hershkovits,
Evan Wang
This new driver belongs to the mvebu family, update the MAINTAINER file
to document it.
Signed-off-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index aa71ab52fd76..98dcee849481 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1582,6 +1582,7 @@ F: arch/arm/boot/dts/kirkwood*
F: arch/arm/configs/mvebu_*_defconfig
F: arch/arm/mach-mvebu/
F: arch/arm64/boot/dts/marvell/armada*
+F: drivers/cpufreq/armada-37xx-cpufreq.c
F: drivers/cpufreq/mvebu-cpufreq.c
F: drivers/irqchip/irq-armada-370-xp.c
F: drivers/irqchip/irq-mvebu-*
--
2.15.0
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 4/6] MAINTAINERS: add new entries for Armada 37xx cpufreq driver
@ 2017-12-01 11:25 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: linux-arm-kernel
This new driver belongs to the mvebu family, update the MAINTAINER file
to document it.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index aa71ab52fd76..98dcee849481 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1582,6 +1582,7 @@ F: arch/arm/boot/dts/kirkwood*
F: arch/arm/configs/mvebu_*_defconfig
F: arch/arm/mach-mvebu/
F: arch/arm64/boot/dts/marvell/armada*
+F: drivers/cpufreq/armada-37xx-cpufreq.c
F: drivers/cpufreq/mvebu-cpufreq.c
F: drivers/irqchip/irq-armada-370-xp.c
F: drivers/irqchip/irq-mvebu-*
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 5/6] cpufreq: Add DVFS support for Armada 37xx
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-01 11:25 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, linux-pm
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
This patch adds DVFS support for the Armada 37xx SoCs
There are up to four CPU frequency loads for Armada 37xx controlled by
the hardware.
This driver associates the CPU load level to a frequency, then the
hardware will switch while selecting a load level.
The hardware also can associate a voltage for each level (AVS support)
but it is not yet supported
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/cpufreq/Kconfig.arm | 7 +
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
3 files changed, 249 insertions(+)
create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 17625115c67f..3018ff0d068f 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -19,6 +19,13 @@ config ACPI_CPPC_CPUFREQ
If in doubt, say N.
+config ARM_ARMADA_37XX_CPUFREQ
+ tristate "Armada 37xx CPUFreq support"
+ depends on ARCH_MVEBU
+ help
+ This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
+ The Armada 37xx PMU supports 4 frequency and VDD levels.
+
# big LITTLE core layer and glue drivers
config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver"
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index d762e76887e7..e07715ce8844 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
# LITTLE drivers, so that it is probed last.
obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
+obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
new file mode 100644
index 000000000000..40c9a744cc6e
--- /dev/null
+++ b/drivers/cpufreq/armada-37xx-cpufreq.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CPU frequency scaling support for Armada 37xx platform.
+ *
+ * Copyright (C) 2017 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/* Power management in North Bridge register set */
+#define ARMADA_37XX_NB_L0L1 0x18
+#define ARMADA_37XX_NB_L2L3 0x1C
+#define ARMADA_37XX_NB_TBG_DIV_OFF 13
+#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
+#define ARMADA_37XX_NB_CLK_SEL_OFF 11
+#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
+#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
+#define ARMADA_37XX_NB_TBG_SEL_OFF 9
+#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
+#define ARMADA_37XX_NB_VDD_SEL_OFF 6
+#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
+#define ARMADA_37XX_NB_CONFIG_SHIFT 16
+#define ARMADA_37XX_NB_DYN_MOD 0x24
+#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
+#define ARMADA_37XX_NB_TBG_EN BIT(28)
+#define ARMADA_37XX_NB_DIV_EN BIT(29)
+#define ARMADA_37XX_NB_VDD_EN BIT(30)
+#define ARMADA_37XX_NB_DFS_EN BIT(31)
+#define ARMADA_37XX_NB_CPU_LOAD 0x30
+#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
+#define ARMADA_37XX_DVFS_LOAD_0 0
+#define ARMADA_37XX_DVFS_LOAD_1 1
+#define ARMADA_37XX_DVFS_LOAD_2 2
+#define ARMADA_37XX_DVFS_LOAD_3 3
+
+/*
+ * On Armada 37xx the Power management manages 4 level of CPU load,
+ * each level can be associated with a CPU clock source, a CPU
+ * divider, a VDD level, etc...
+ */
+#define LOAD_LEVEL_NR 4
+
+struct armada_37xx_dvfs {
+ u32 cpu_freq_max;
+ u8 divider[LOAD_LEVEL_NR];
+};
+
+static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
+ {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
+ {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
+ {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
+ {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
+};
+
+static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
+ if (freq == armada_37xx_dvfs[i].cpu_freq_max)
+ return &armada_37xx_dvfs[i];
+ }
+
+ pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
+ return NULL;
+}
+
+/*
+ * Setup the four level managed by the hardware. Once the four level
+ * will be configured then the DVFS will be enabled.
+ */
+static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
+ struct clk *clk, u8 *divider)
+{
+ int load_level;
+ struct clk *parent;
+
+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
+ unsigned int reg, mask, val, offset = 0;
+
+ if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
+ reg = ARMADA_37XX_NB_L0L1;
+ else
+ reg = ARMADA_37XX_NB_L2L3;
+
+ if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
+ load_level == ARMADA_37XX_DVFS_LOAD_2)
+ offset += ARMADA_37XX_NB_CONFIG_SHIFT;
+
+ /* Set cpu clock source, for all the level we use TBG */
+ val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
+ mask = (ARMADA_37XX_NB_CLK_SEL_MASK
+ << ARMADA_37XX_NB_CLK_SEL_OFF);
+
+ /*
+ * Set cpu divider based on the pre-computed array in
+ * order to have balanced step.
+ */
+ val |= divider[load_level] << ARMADA_37XX_NB_TBG_DIV_OFF;
+ mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
+ << ARMADA_37XX_NB_TBG_DIV_OFF);
+
+ /* Set VDD divider which is actually the load level. */
+ val |= load_level << ARMADA_37XX_NB_VDD_SEL_OFF;
+ mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
+ << ARMADA_37XX_NB_VDD_SEL_OFF);
+
+ val <<= offset;
+ mask <<= offset;
+
+ regmap_update_bits(base, reg, mask, val);
+ }
+
+ /*
+ * Set cpu clock source, for all the level we keep the same
+ * clock source that the one already configured. For this one
+ * we need to use the clock framework
+ */
+ parent = clk_get_parent(clk);
+ clk_set_parent(clk, parent);
+}
+
+static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
+{
+ unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
+ mask = ARMADA_37XX_NB_DFS_EN;
+
+ regmap_update_bits(base, reg, mask, 0);
+}
+
+static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
+{
+ unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
+ mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
+
+ /* Start with the highest load (0) */
+ val = ARMADA_37XX_DVFS_LOAD_0;
+ regmap_update_bits(base, reg, mask, val);
+
+ /* Now enable DVFS for the CPUs */
+ reg = ARMADA_37XX_NB_DYN_MOD;
+ mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
+ ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
+ ARMADA_37XX_NB_DFS_EN;
+
+ regmap_update_bits(base, reg, mask, mask);
+}
+
+static int __init armada37xx_cpufreq_driver_init(void)
+{
+ struct armada_37xx_dvfs *dvfs;
+ struct platform_device *pdev;
+ unsigned int cur_frequency;
+ struct regmap *nb_pm_base;
+ struct device *cpu_dev;
+ int load_level, ret;
+ struct clk *clk;
+
+ nb_pm_base =
+ syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
+
+ if (IS_ERR(nb_pm_base))
+ return -ENODEV;
+
+ /* Before doing any configuration on the DVFS first, disable it */
+ armada37xx_cpufreq_disable_dvfs(nb_pm_base);
+
+ /*
+ * On CPU 0 register the operating points supported (which are
+ * the nominal CPU frequency and full integer divisions of
+ * it).
+ */
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev) {
+ dev_err(cpu_dev, "Cannot get CPU\n");
+ return -ENODEV;
+ }
+
+ clk = clk_get(cpu_dev, 0);
+ if (IS_ERR(clk)) {
+ dev_err(cpu_dev, "Cannot get clock for CPU0\n");
+ return PTR_ERR(clk);
+ }
+
+ /* Get nominal (current) CPU frequency */
+ cur_frequency = clk_get_rate(clk);
+ if (!cur_frequency) {
+ dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
+ return -EINVAL;
+ }
+
+ dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
+ if (!dvfs)
+ return -EINVAL;
+
+ armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
+
+ /*
+ * In case of a failure of dev_pm_opp_add(), we don't bother
+ * with cleaning up the registered OPP (there's no function to
+ * do so), and simply cancel the registration of the cpufreq
+ * device.
+ */
+ for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
+ load_level++) {
+ unsigned long freq = dvfs->divider[load_level];
+
+ ret = dev_pm_opp_add(cpu_dev, freq, 0);
+ if (ret)
+ return ret;
+ }
+
+ /* Now that everything is setup, enable the DVFS at hardware level */
+ armada37xx_cpufreq_enable_dvfs(nb_pm_base);
+
+ pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+
+ return PTR_ERR_OR_ZERO(pdev);
+}
+/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
+late_initcall(armada37xx_cpufreq_driver_init);
+
+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
+MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
+MODULE_LICENSE("GPL");
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 5/6] cpufreq: Add DVFS support for Armada 37xx
@ 2017-12-01 11:25 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds DVFS support for the Armada 37xx SoCs
There are up to four CPU frequency loads for Armada 37xx controlled by
the hardware.
This driver associates the CPU load level to a frequency, then the
hardware will switch while selecting a load level.
The hardware also can associate a voltage for each level (AVS support)
but it is not yet supported
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
drivers/cpufreq/Kconfig.arm | 7 +
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
3 files changed, 249 insertions(+)
create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 17625115c67f..3018ff0d068f 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -19,6 +19,13 @@ config ACPI_CPPC_CPUFREQ
If in doubt, say N.
+config ARM_ARMADA_37XX_CPUFREQ
+ tristate "Armada 37xx CPUFreq support"
+ depends on ARCH_MVEBU
+ help
+ This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
+ The Armada 37xx PMU supports 4 frequency and VDD levels.
+
# big LITTLE core layer and glue drivers
config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver"
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index d762e76887e7..e07715ce8844 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
# LITTLE drivers, so that it is probed last.
obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
+obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
new file mode 100644
index 000000000000..40c9a744cc6e
--- /dev/null
+++ b/drivers/cpufreq/armada-37xx-cpufreq.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CPU frequency scaling support for Armada 37xx platform.
+ *
+ * Copyright (C) 2017 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+/* Power management in North Bridge register set */
+#define ARMADA_37XX_NB_L0L1 0x18
+#define ARMADA_37XX_NB_L2L3 0x1C
+#define ARMADA_37XX_NB_TBG_DIV_OFF 13
+#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
+#define ARMADA_37XX_NB_CLK_SEL_OFF 11
+#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
+#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
+#define ARMADA_37XX_NB_TBG_SEL_OFF 9
+#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
+#define ARMADA_37XX_NB_VDD_SEL_OFF 6
+#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
+#define ARMADA_37XX_NB_CONFIG_SHIFT 16
+#define ARMADA_37XX_NB_DYN_MOD 0x24
+#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
+#define ARMADA_37XX_NB_TBG_EN BIT(28)
+#define ARMADA_37XX_NB_DIV_EN BIT(29)
+#define ARMADA_37XX_NB_VDD_EN BIT(30)
+#define ARMADA_37XX_NB_DFS_EN BIT(31)
+#define ARMADA_37XX_NB_CPU_LOAD 0x30
+#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
+#define ARMADA_37XX_DVFS_LOAD_0 0
+#define ARMADA_37XX_DVFS_LOAD_1 1
+#define ARMADA_37XX_DVFS_LOAD_2 2
+#define ARMADA_37XX_DVFS_LOAD_3 3
+
+/*
+ * On Armada 37xx the Power management manages 4 level of CPU load,
+ * each level can be associated with a CPU clock source, a CPU
+ * divider, a VDD level, etc...
+ */
+#define LOAD_LEVEL_NR 4
+
+struct armada_37xx_dvfs {
+ u32 cpu_freq_max;
+ u8 divider[LOAD_LEVEL_NR];
+};
+
+static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
+ {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
+ {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
+ {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
+ {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
+};
+
+static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
+ if (freq == armada_37xx_dvfs[i].cpu_freq_max)
+ return &armada_37xx_dvfs[i];
+ }
+
+ pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
+ return NULL;
+}
+
+/*
+ * Setup the four level managed by the hardware. Once the four level
+ * will be configured then the DVFS will be enabled.
+ */
+static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
+ struct clk *clk, u8 *divider)
+{
+ int load_level;
+ struct clk *parent;
+
+ for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
+ unsigned int reg, mask, val, offset = 0;
+
+ if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
+ reg = ARMADA_37XX_NB_L0L1;
+ else
+ reg = ARMADA_37XX_NB_L2L3;
+
+ if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
+ load_level == ARMADA_37XX_DVFS_LOAD_2)
+ offset += ARMADA_37XX_NB_CONFIG_SHIFT;
+
+ /* Set cpu clock source, for all the level we use TBG */
+ val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
+ mask = (ARMADA_37XX_NB_CLK_SEL_MASK
+ << ARMADA_37XX_NB_CLK_SEL_OFF);
+
+ /*
+ * Set cpu divider based on the pre-computed array in
+ * order to have balanced step.
+ */
+ val |= divider[load_level] << ARMADA_37XX_NB_TBG_DIV_OFF;
+ mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
+ << ARMADA_37XX_NB_TBG_DIV_OFF);
+
+ /* Set VDD divider which is actually the load level. */
+ val |= load_level << ARMADA_37XX_NB_VDD_SEL_OFF;
+ mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
+ << ARMADA_37XX_NB_VDD_SEL_OFF);
+
+ val <<= offset;
+ mask <<= offset;
+
+ regmap_update_bits(base, reg, mask, val);
+ }
+
+ /*
+ * Set cpu clock source, for all the level we keep the same
+ * clock source that the one already configured. For this one
+ * we need to use the clock framework
+ */
+ parent = clk_get_parent(clk);
+ clk_set_parent(clk, parent);
+}
+
+static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
+{
+ unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
+ mask = ARMADA_37XX_NB_DFS_EN;
+
+ regmap_update_bits(base, reg, mask, 0);
+}
+
+static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
+{
+ unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
+ mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
+
+ /* Start with the highest load (0) */
+ val = ARMADA_37XX_DVFS_LOAD_0;
+ regmap_update_bits(base, reg, mask, val);
+
+ /* Now enable DVFS for the CPUs */
+ reg = ARMADA_37XX_NB_DYN_MOD;
+ mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
+ ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
+ ARMADA_37XX_NB_DFS_EN;
+
+ regmap_update_bits(base, reg, mask, mask);
+}
+
+static int __init armada37xx_cpufreq_driver_init(void)
+{
+ struct armada_37xx_dvfs *dvfs;
+ struct platform_device *pdev;
+ unsigned int cur_frequency;
+ struct regmap *nb_pm_base;
+ struct device *cpu_dev;
+ int load_level, ret;
+ struct clk *clk;
+
+ nb_pm_base =
+ syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
+
+ if (IS_ERR(nb_pm_base))
+ return -ENODEV;
+
+ /* Before doing any configuration on the DVFS first, disable it */
+ armada37xx_cpufreq_disable_dvfs(nb_pm_base);
+
+ /*
+ * On CPU 0 register the operating points supported (which are
+ * the nominal CPU frequency and full integer divisions of
+ * it).
+ */
+ cpu_dev = get_cpu_device(0);
+ if (!cpu_dev) {
+ dev_err(cpu_dev, "Cannot get CPU\n");
+ return -ENODEV;
+ }
+
+ clk = clk_get(cpu_dev, 0);
+ if (IS_ERR(clk)) {
+ dev_err(cpu_dev, "Cannot get clock for CPU0\n");
+ return PTR_ERR(clk);
+ }
+
+ /* Get nominal (current) CPU frequency */
+ cur_frequency = clk_get_rate(clk);
+ if (!cur_frequency) {
+ dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
+ return -EINVAL;
+ }
+
+ dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
+ if (!dvfs)
+ return -EINVAL;
+
+ armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
+
+ /*
+ * In case of a failure of dev_pm_opp_add(), we don't bother
+ * with cleaning up the registered OPP (there's no function to
+ * do so), and simply cancel the registration of the cpufreq
+ * device.
+ */
+ for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
+ load_level++) {
+ unsigned long freq = dvfs->divider[load_level];
+
+ ret = dev_pm_opp_add(cpu_dev, freq, 0);
+ if (ret)
+ return ret;
+ }
+
+ /* Now that everything is setup, enable the DVFS at hardware level */
+ armada37xx_cpufreq_enable_dvfs(nb_pm_base);
+
+ pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+
+ return PTR_ERR_OR_ZERO(pdev);
+}
+/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
+late_initcall(armada37xx_cpufreq_driver_init);
+
+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
+MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
+MODULE_LICENSE("GPL");
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 6/6] arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-01 11:25 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: Rafael J. Wysocki, Viresh Kumar, linux-pm
Cc: Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
Gregory CLEMENT, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
In order to be able to use cpu freq, we need to associate a clock to each
CPU and to expose the power management registers.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/marvell/armada-372x.dtsi b/arch/arm64/boot/dts/marvell/armada-372x.dtsi
index 59d7557d3b1b..2554e0baea6b 100644
--- a/arch/arm64/boot/dts/marvell/armada-372x.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-372x.dtsi
@@ -56,6 +56,7 @@
device_type = "cpu";
compatible = "arm,cortex-a53","arm,armv8";
reg = <0x1>;
+ clocks = <&nb_periph_clk 16>;
enable-method = "psci";
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index 90c26d616a54..6e51ed54d75c 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -65,6 +65,7 @@
device_type = "cpu";
compatible = "arm,cortex-a53", "arm,armv8";
reg = <0>;
+ clocks = <&nb_periph_clk 16>;
enable-method = "psci";
};
};
@@ -234,6 +235,12 @@
};
};
+ nb_pm: nb_pm@14000 {
+ compatible = "marvell,armada-3700-nb-pm",
+ "syscon";
+ reg = <0x14000 0x60>;
+ };
+
pinctrl_sb: pinctrl@18800 {
compatible = "marvell,armada3710-sb-pinctrl",
"syscon", "simple-mfd";
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 6/6] arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support
@ 2017-12-01 11:25 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-01 11:25 UTC (permalink / raw)
To: linux-arm-kernel
In order to be able to use cpu freq, we need to associate a clock to each
CPU and to expose the power management registers.
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/marvell/armada-372x.dtsi b/arch/arm64/boot/dts/marvell/armada-372x.dtsi
index 59d7557d3b1b..2554e0baea6b 100644
--- a/arch/arm64/boot/dts/marvell/armada-372x.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-372x.dtsi
@@ -56,6 +56,7 @@
device_type = "cpu";
compatible = "arm,cortex-a53","arm,armv8";
reg = <0x1>;
+ clocks = <&nb_periph_clk 16>;
enable-method = "psci";
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index 90c26d616a54..6e51ed54d75c 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -65,6 +65,7 @@
device_type = "cpu";
compatible = "arm,cortex-a53", "arm,armv8";
reg = <0>;
+ clocks = <&nb_periph_clk 16>;
enable-method = "psci";
};
};
@@ -234,6 +235,12 @@
};
};
+ nb_pm: nb_pm at 14000 {
+ compatible = "marvell,armada-3700-nb-pm",
+ "syscon";
+ reg = <0x14000 0x60>;
+ };
+
pinctrl_sb: pinctrl at 18800 {
compatible = "marvell,armada3710-sb-pinctrl",
"syscon", "simple-mfd";
--
2.15.0
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx
2017-12-01 11:25 ` Gregory CLEMENT
` (6 preceding siblings ...)
(?)
@ 2017-12-03 12:23 ` Andre Heider
2017-12-06 11:50 ` Gregory CLEMENT
-1 siblings, 1 reply; 35+ messages in thread
From: Andre Heider @ 2017-12-03 12:23 UTC (permalink / raw)
To: linux-arm-kernel
Hi Gregory,
I applied this and the dvfs patch set ([PATCH 0/3] Add DVFS support on
CPU clock for Armada 37xx) on top of 4.14.3 and gave it a try on
espressobin.
Upon modprobe I get:
[ 66.231652] freq_table: Duplicate freq-table entries: 0
[ 66.236967] cpu cpu0: cpufreq_init: invalid frequency table: -22
[ 66.243534] freq_table: Duplicate freq-table entries: 0
[ 66.248575] cpu cpu1: cpufreq_init: invalid frequency table: -22
Is this supposed to work already? Do I miss something?
Oh, and on that scenario it's not possible to rmmod the driver again, EBUSY.
Thanks,
Andre
On 01/12/17 12:25, Gregory CLEMENT <gregory.clement@free-electrons.com>
wrote:
> Hi,
>
> This series adds the CPU Frequency support on Armada 37xx using
> DVFS. It is based on the initial work of Evan Wang and Victor Gu.
>
> DVFS control is done by a set of registers from the North Bridge Power
> Management block. The binding for this block is documented in patch 1.
>
> While adding a new cpufreq driver I found that the Kconfig and
> Makefile were no more in order, so it is fixed by patch 2 and 3.
>
> The 4th patch is just about updating the MAINTAINERS file with the new
> driver.
>
> The next patch is the real purpose of the series. The main goal of
> this driver is to setup the CPU load level in the hardware to
> associate them to CPU frequencies and register a standard cpufreq
> driver. Note that the hardware also capable of doing AVS (Adaptive
> Voltage Scaling), by associating a voltage on each level beside the
> CPU frequency. However, this support is not yet ready, so it is not
> part of this series.
>
> Finally, the last patch is for arm-soc the arm-soc subsystem through
> mvebu and update the device tree to support the CPU frequency scaling.
>
> An update on the CPU clock driver is needed in order to take into
> account the DVFS setting. It's the purpose of an other series already
> sent, but is no dependencies between the series (for building or at
> runtime).
>
> Thanks,
>
> Gregory
>
> Gregory CLEMENT (6):
> dt-bindings: marvell: Add documentation for the North Bridge PM on
> Armada 37xx
> cpufreq: ARM: sort the Kconfig menu
> cpufreq: sort the drivers in ARM part
> MAINTAINERS: add new entries for Armada 37xx cpufreq driver
> cpufreq: Add DVFS support for Armada 37xx
> arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support
>
> .../bindings/arm/marvell/armada-37xx.txt | 19 ++
> MAINTAINERS | 1 +
> arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
> arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +
> drivers/cpufreq/Kconfig.arm | 89 ++++----
> drivers/cpufreq/Makefile | 9 +-
> drivers/cpufreq/armada-37xx-cpufreq.c | 241 +++++++++++++++++++++
> 7 files changed, 322 insertions(+), 45 deletions(-)
> create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/6] cpufreq: ARM: sort the Kconfig menu
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-04 8:41 ` Viresh Kumar
-1 siblings, 0 replies; 35+ messages in thread
From: Viresh Kumar @ 2017-12-04 8:41 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, linux-pm, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
On 01-12-17, 12:25, Gregory CLEMENT wrote:
> +config ARM_VEXPRESS_SPC_CPUFREQ
> + tristate "Versatile Express SPC based CPUfreq driver"
> + depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
> + help
> + This add the CPUfreq driver support for Versatile Express
> + big.LITTLE platforms using SPC for power management.
> +
> +config ARM_SCPI_CPUFREQ
The order of above two must be reversed ?
--
viresh
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 2/6] cpufreq: ARM: sort the Kconfig menu
@ 2017-12-04 8:41 ` Viresh Kumar
0 siblings, 0 replies; 35+ messages in thread
From: Viresh Kumar @ 2017-12-04 8:41 UTC (permalink / raw)
To: linux-arm-kernel
On 01-12-17, 12:25, Gregory CLEMENT wrote:
> +config ARM_VEXPRESS_SPC_CPUFREQ
> + tristate "Versatile Express SPC based CPUfreq driver"
> + depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
> + help
> + This add the CPUfreq driver support for Versatile Express
> + big.LITTLE platforms using SPC for power management.
> +
> +config ARM_SCPI_CPUFREQ
The order of above two must be reversed ?
--
viresh
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 3/6] cpufreq: sort the drivers in ARM part
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-04 9:18 ` Viresh Kumar
-1 siblings, 0 replies; 35+ messages in thread
From: Viresh Kumar @ 2017-12-04 9:18 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, linux-pm, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
On 01-12-17, 12:25, Gregory CLEMENT wrote:
> Keep the driver files alphabetically sorted.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/cpufreq/Makefile | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index 812f9e0d01a3..d762e76887e7 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -53,22 +53,24 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
> obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
>
> obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
> +obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
Shouldn't we add them in ascending order of the whole config name and not just
CPPC_CPUFREQ ?
--
viresh
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 3/6] cpufreq: sort the drivers in ARM part
@ 2017-12-04 9:18 ` Viresh Kumar
0 siblings, 0 replies; 35+ messages in thread
From: Viresh Kumar @ 2017-12-04 9:18 UTC (permalink / raw)
To: linux-arm-kernel
On 01-12-17, 12:25, Gregory CLEMENT wrote:
> Keep the driver files alphabetically sorted.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/cpufreq/Makefile | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index 812f9e0d01a3..d762e76887e7 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -53,22 +53,24 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
> obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
>
> obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
> +obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
Shouldn't we add them in ascending order of the whole config name and not just
CPPC_CPUFREQ ?
--
viresh
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 1/6] dt-bindings: marvell: Add documentation for the North Bridge PM on Armada 37xx
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-04 21:47 ` Rob Herring
-1 siblings, 0 replies; 35+ messages in thread
From: Rob Herring @ 2017-12-04 21:47 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, Viresh Kumar, linux-pm, Jason Cooper,
Andrew Lunn, Sebastian Hesselbarth, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
On Fri, Dec 01, 2017 at 12:25:03PM +0100, Gregory CLEMENT wrote:
> Extend the documentation of the Armada 37xx SoC with the the North
> Bridge Power Management component.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> .../devicetree/bindings/arm/marvell/armada-37xx.txt | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
> index 51336e5fc761..7ad9830d9177 100644
> --- a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
> +++ b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
> @@ -14,3 +14,22 @@ following property before the previous one:
> Example:
>
> compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
> +
> +
> +Power management
> +----------------
> +
> +For power management (particularly DVFS and AVS), the North Bridge
> +Power Management component is needed:
> +
> +Required properties:
> +- compatible : should contain "marvell,armada-3700-nb-pm", "syscon";
> +- reg : the register start and length for the North Bridge
> + Power Management
> +
> +Example:
> +
> +nb_pm: nb_pm@14000 {
Don't use underscore in node or property names. "syscon" is a better
choice here.
> + compatible = "marvell,armada-3700-nb-pm", "syscon";
> + reg = <0x14000 0x60>;
> +}
> --
> 2.15.0
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/6] dt-bindings: marvell: Add documentation for the North Bridge PM on Armada 37xx
@ 2017-12-04 21:47 ` Rob Herring
0 siblings, 0 replies; 35+ messages in thread
From: Rob Herring @ 2017-12-04 21:47 UTC (permalink / raw)
To: linux-arm-kernel
On Fri, Dec 01, 2017 at 12:25:03PM +0100, Gregory CLEMENT wrote:
> Extend the documentation of the Armada 37xx SoC with the the North
> Bridge Power Management component.
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> .../devicetree/bindings/arm/marvell/armada-37xx.txt | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
> index 51336e5fc761..7ad9830d9177 100644
> --- a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
> +++ b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
> @@ -14,3 +14,22 @@ following property before the previous one:
> Example:
>
> compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
> +
> +
> +Power management
> +----------------
> +
> +For power management (particularly DVFS and AVS), the North Bridge
> +Power Management component is needed:
> +
> +Required properties:
> +- compatible : should contain "marvell,armada-3700-nb-pm", "syscon";
> +- reg : the register start and length for the North Bridge
> + Power Management
> +
> +Example:
> +
> +nb_pm: nb_pm at 14000 {
Don't use underscore in node or property names. "syscon" is a better
choice here.
> + compatible = "marvell,armada-3700-nb-pm", "syscon";
> + reg = <0x14000 0x60>;
> +}
> --
> 2.15.0
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 5/6] cpufreq: Add DVFS support for Armada 37xx
2017-12-01 11:25 ` Gregory CLEMENT
@ 2017-12-05 5:54 ` Viresh Kumar
-1 siblings, 0 replies; 35+ messages in thread
From: Viresh Kumar @ 2017-12-05 5:54 UTC (permalink / raw)
To: Gregory CLEMENT
Cc: Rafael J. Wysocki, linux-pm, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
On 01-12-17, 12:25, Gregory CLEMENT wrote:
> This patch adds DVFS support for the Armada 37xx SoCs
>
> There are up to four CPU frequency loads for Armada 37xx controlled by
> the hardware.
>
> This driver associates the CPU load level to a frequency, then the
> hardware will switch while selecting a load level.
>
> The hardware also can associate a voltage for each level (AVS support)
> but it is not yet supported
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/cpufreq/Kconfig.arm | 7 +
> drivers/cpufreq/Makefile | 1 +
> drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
> 3 files changed, 249 insertions(+)
> create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
>
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index 17625115c67f..3018ff0d068f 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -19,6 +19,13 @@ config ACPI_CPPC_CPUFREQ
>
> If in doubt, say N.
>
> +config ARM_ARMADA_37XX_CPUFREQ
> + tristate "Armada 37xx CPUFreq support"
> + depends on ARCH_MVEBU
> + help
> + This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
> + The Armada 37xx PMU supports 4 frequency and VDD levels.
> +
> # big LITTLE core layer and glue drivers
> config ARM_BIG_LITTLE_CPUFREQ
> tristate "Generic ARM big LITTLE CPUfreq driver"
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index d762e76887e7..e07715ce8844 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
> # LITTLE drivers, so that it is probed last.
> obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
>
> +obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
> obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
> obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
> obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
> diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
> new file mode 100644
> index 000000000000..40c9a744cc6e
> --- /dev/null
> +++ b/drivers/cpufreq/armada-37xx-cpufreq.c
> @@ -0,0 +1,241 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * CPU frequency scaling support for Armada 37xx platform.
> + *
> + * Copyright (C) 2017 Marvell
> + *
> + * Gregory CLEMENT <gregory.clement@free-electrons.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/cpu.h>
> +#include <linux/cpufreq.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_opp.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +
> +/* Power management in North Bridge register set */
> +#define ARMADA_37XX_NB_L0L1 0x18
> +#define ARMADA_37XX_NB_L2L3 0x1C
> +#define ARMADA_37XX_NB_TBG_DIV_OFF 13
> +#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
> +#define ARMADA_37XX_NB_CLK_SEL_OFF 11
> +#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
> +#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
> +#define ARMADA_37XX_NB_TBG_SEL_OFF 9
> +#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
> +#define ARMADA_37XX_NB_VDD_SEL_OFF 6
> +#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
> +#define ARMADA_37XX_NB_CONFIG_SHIFT 16
Looks like you have added tabs after #define as well? Perhaps a space
is good enough there.
> +#define ARMADA_37XX_NB_DYN_MOD 0x24
> +#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
> +#define ARMADA_37XX_NB_TBG_EN BIT(28)
> +#define ARMADA_37XX_NB_DIV_EN BIT(29)
> +#define ARMADA_37XX_NB_VDD_EN BIT(30)
> +#define ARMADA_37XX_NB_DFS_EN BIT(31)
> +#define ARMADA_37XX_NB_CPU_LOAD 0x30
> +#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
> +#define ARMADA_37XX_DVFS_LOAD_0 0
> +#define ARMADA_37XX_DVFS_LOAD_1 1
> +#define ARMADA_37XX_DVFS_LOAD_2 2
> +#define ARMADA_37XX_DVFS_LOAD_3 3
> +
> +/*
> + * On Armada 37xx the Power management manages 4 level of CPU load,
> + * each level can be associated with a CPU clock source, a CPU
> + * divider, a VDD level, etc...
> + */
> +#define LOAD_LEVEL_NR 4
> +
> +struct armada_37xx_dvfs {
> + u32 cpu_freq_max;
> + u8 divider[LOAD_LEVEL_NR];
> +};
> +
> +static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
> + {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
> + {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
> + {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
> + {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
> +};
> +
> +static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
> + if (freq == armada_37xx_dvfs[i].cpu_freq_max)
> + return &armada_37xx_dvfs[i];
> + }
> +
> + pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
> + return NULL;
> +}
> +
> +/*
> + * Setup the four level managed by the hardware. Once the four level
> + * will be configured then the DVFS will be enabled.
> + */
> +static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
> + struct clk *clk, u8 *divider)
> +{
> + int load_level;
> + struct clk *parent;
> +
> + for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
> + unsigned int reg, mask, val, offset = 0;
> +
> + if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
> + reg = ARMADA_37XX_NB_L0L1;
> + else
> + reg = ARMADA_37XX_NB_L2L3;
> +
> + if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
> + load_level == ARMADA_37XX_DVFS_LOAD_2)
> + offset += ARMADA_37XX_NB_CONFIG_SHIFT;
> +
> + /* Set cpu clock source, for all the level we use TBG */
> + val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
> + mask = (ARMADA_37XX_NB_CLK_SEL_MASK
> + << ARMADA_37XX_NB_CLK_SEL_OFF);
> +
> + /*
> + * Set cpu divider based on the pre-computed array in
> + * order to have balanced step.
> + */
> + val |= divider[load_level] << ARMADA_37XX_NB_TBG_DIV_OFF;
> + mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
> + << ARMADA_37XX_NB_TBG_DIV_OFF);
> +
> + /* Set VDD divider which is actually the load level. */
> + val |= load_level << ARMADA_37XX_NB_VDD_SEL_OFF;
> + mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
> + << ARMADA_37XX_NB_VDD_SEL_OFF);
> +
> + val <<= offset;
> + mask <<= offset;
> +
> + regmap_update_bits(base, reg, mask, val);
> + }
> +
> + /*
> + * Set cpu clock source, for all the level we keep the same
> + * clock source that the one already configured. For this one
> + * we need to use the clock framework
> + */
> + parent = clk_get_parent(clk);
> + clk_set_parent(clk, parent);
> +}
> +
> +static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
> +{
> + unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
> + mask = ARMADA_37XX_NB_DFS_EN;
> +
> + regmap_update_bits(base, reg, mask, 0);
> +}
> +
> +static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
> +{
> + unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
> + mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
> +
> + /* Start with the highest load (0) */
> + val = ARMADA_37XX_DVFS_LOAD_0;
> + regmap_update_bits(base, reg, mask, val);
> +
> + /* Now enable DVFS for the CPUs */
> + reg = ARMADA_37XX_NB_DYN_MOD;
> + mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
> + ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
> + ARMADA_37XX_NB_DFS_EN;
> +
> + regmap_update_bits(base, reg, mask, mask);
> +}
> +
> +static int __init armada37xx_cpufreq_driver_init(void)
> +{
> + struct armada_37xx_dvfs *dvfs;
> + struct platform_device *pdev;
> + unsigned int cur_frequency;
> + struct regmap *nb_pm_base;
> + struct device *cpu_dev;
> + int load_level, ret;
> + struct clk *clk;
> +
> + nb_pm_base =
> + syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
> +
> + if (IS_ERR(nb_pm_base))
> + return -ENODEV;
> +
> + /* Before doing any configuration on the DVFS first, disable it */
> + armada37xx_cpufreq_disable_dvfs(nb_pm_base);
> +
> + /*
> + * On CPU 0 register the operating points supported (which are
> + * the nominal CPU frequency and full integer divisions of
> + * it).
> + */
> + cpu_dev = get_cpu_device(0);
> + if (!cpu_dev) {
> + dev_err(cpu_dev, "Cannot get CPU\n");
> + return -ENODEV;
> + }
> +
> + clk = clk_get(cpu_dev, 0);
> + if (IS_ERR(clk)) {
> + dev_err(cpu_dev, "Cannot get clock for CPU0\n");
> + return PTR_ERR(clk);
> + }
> +
> + /* Get nominal (current) CPU frequency */
> + cur_frequency = clk_get_rate(clk);
> + if (!cur_frequency) {
> + dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
> + return -EINVAL;
> + }
> +
> + dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
> + if (!dvfs)
> + return -EINVAL;
> +
> + armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
> +
> + /*
> + * In case of a failure of dev_pm_opp_add(), we don't bother
> + * with cleaning up the registered OPP (there's no function to
> + * do so),
What do you mean by the comment within ()? We do have
dev_pm_opp_remove() helper.
> and simply cancel the registration of the cpufreq
> + * device.
> + */
> + for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
> + load_level++) {
> + unsigned long freq = dvfs->divider[load_level];
> +
> + ret = dev_pm_opp_add(cpu_dev, freq, 0);
> + if (ret)
> + return ret;
> + }
> +
> + /* Now that everything is setup, enable the DVFS at hardware level */
> + armada37xx_cpufreq_enable_dvfs(nb_pm_base);
> +
> + pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
> +
> + return PTR_ERR_OR_ZERO(pdev);
> +}
> +/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
> +late_initcall(armada37xx_cpufreq_driver_init);
> +
> +MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
> +MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
> +MODULE_LICENSE("GPL");
> --
> 2.15.0
--
viresh
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 5/6] cpufreq: Add DVFS support for Armada 37xx
@ 2017-12-05 5:54 ` Viresh Kumar
0 siblings, 0 replies; 35+ messages in thread
From: Viresh Kumar @ 2017-12-05 5:54 UTC (permalink / raw)
To: linux-arm-kernel
On 01-12-17, 12:25, Gregory CLEMENT wrote:
> This patch adds DVFS support for the Armada 37xx SoCs
>
> There are up to four CPU frequency loads for Armada 37xx controlled by
> the hardware.
>
> This driver associates the CPU load level to a frequency, then the
> hardware will switch while selecting a load level.
>
> The hardware also can associate a voltage for each level (AVS support)
> but it is not yet supported
>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
> ---
> drivers/cpufreq/Kconfig.arm | 7 +
> drivers/cpufreq/Makefile | 1 +
> drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
> 3 files changed, 249 insertions(+)
> create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
>
> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
> index 17625115c67f..3018ff0d068f 100644
> --- a/drivers/cpufreq/Kconfig.arm
> +++ b/drivers/cpufreq/Kconfig.arm
> @@ -19,6 +19,13 @@ config ACPI_CPPC_CPUFREQ
>
> If in doubt, say N.
>
> +config ARM_ARMADA_37XX_CPUFREQ
> + tristate "Armada 37xx CPUFreq support"
> + depends on ARCH_MVEBU
> + help
> + This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
> + The Armada 37xx PMU supports 4 frequency and VDD levels.
> +
> # big LITTLE core layer and glue drivers
> config ARM_BIG_LITTLE_CPUFREQ
> tristate "Generic ARM big LITTLE CPUfreq driver"
> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
> index d762e76887e7..e07715ce8844 100644
> --- a/drivers/cpufreq/Makefile
> +++ b/drivers/cpufreq/Makefile
> @@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
> # LITTLE drivers, so that it is probed last.
> obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
>
> +obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
> obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
> obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
> obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
> diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
> new file mode 100644
> index 000000000000..40c9a744cc6e
> --- /dev/null
> +++ b/drivers/cpufreq/armada-37xx-cpufreq.c
> @@ -0,0 +1,241 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * CPU frequency scaling support for Armada 37xx platform.
> + *
> + * Copyright (C) 2017 Marvell
> + *
> + * Gregory CLEMENT <gregory.clement@free-electrons.com>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/cpu.h>
> +#include <linux/cpufreq.h>
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_device.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_opp.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +
> +/* Power management in North Bridge register set */
> +#define ARMADA_37XX_NB_L0L1 0x18
> +#define ARMADA_37XX_NB_L2L3 0x1C
> +#define ARMADA_37XX_NB_TBG_DIV_OFF 13
> +#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
> +#define ARMADA_37XX_NB_CLK_SEL_OFF 11
> +#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
> +#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
> +#define ARMADA_37XX_NB_TBG_SEL_OFF 9
> +#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
> +#define ARMADA_37XX_NB_VDD_SEL_OFF 6
> +#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
> +#define ARMADA_37XX_NB_CONFIG_SHIFT 16
Looks like you have added tabs after #define as well? Perhaps a space
is good enough there.
> +#define ARMADA_37XX_NB_DYN_MOD 0x24
> +#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
> +#define ARMADA_37XX_NB_TBG_EN BIT(28)
> +#define ARMADA_37XX_NB_DIV_EN BIT(29)
> +#define ARMADA_37XX_NB_VDD_EN BIT(30)
> +#define ARMADA_37XX_NB_DFS_EN BIT(31)
> +#define ARMADA_37XX_NB_CPU_LOAD 0x30
> +#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
> +#define ARMADA_37XX_DVFS_LOAD_0 0
> +#define ARMADA_37XX_DVFS_LOAD_1 1
> +#define ARMADA_37XX_DVFS_LOAD_2 2
> +#define ARMADA_37XX_DVFS_LOAD_3 3
> +
> +/*
> + * On Armada 37xx the Power management manages 4 level of CPU load,
> + * each level can be associated with a CPU clock source, a CPU
> + * divider, a VDD level, etc...
> + */
> +#define LOAD_LEVEL_NR 4
> +
> +struct armada_37xx_dvfs {
> + u32 cpu_freq_max;
> + u8 divider[LOAD_LEVEL_NR];
> +};
> +
> +static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
> + {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
> + {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
> + {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
> + {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
> +};
> +
> +static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
> + if (freq == armada_37xx_dvfs[i].cpu_freq_max)
> + return &armada_37xx_dvfs[i];
> + }
> +
> + pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
> + return NULL;
> +}
> +
> +/*
> + * Setup the four level managed by the hardware. Once the four level
> + * will be configured then the DVFS will be enabled.
> + */
> +static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
> + struct clk *clk, u8 *divider)
> +{
> + int load_level;
> + struct clk *parent;
> +
> + for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
> + unsigned int reg, mask, val, offset = 0;
> +
> + if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
> + reg = ARMADA_37XX_NB_L0L1;
> + else
> + reg = ARMADA_37XX_NB_L2L3;
> +
> + if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
> + load_level == ARMADA_37XX_DVFS_LOAD_2)
> + offset += ARMADA_37XX_NB_CONFIG_SHIFT;
> +
> + /* Set cpu clock source, for all the level we use TBG */
> + val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
> + mask = (ARMADA_37XX_NB_CLK_SEL_MASK
> + << ARMADA_37XX_NB_CLK_SEL_OFF);
> +
> + /*
> + * Set cpu divider based on the pre-computed array in
> + * order to have balanced step.
> + */
> + val |= divider[load_level] << ARMADA_37XX_NB_TBG_DIV_OFF;
> + mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
> + << ARMADA_37XX_NB_TBG_DIV_OFF);
> +
> + /* Set VDD divider which is actually the load level. */
> + val |= load_level << ARMADA_37XX_NB_VDD_SEL_OFF;
> + mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
> + << ARMADA_37XX_NB_VDD_SEL_OFF);
> +
> + val <<= offset;
> + mask <<= offset;
> +
> + regmap_update_bits(base, reg, mask, val);
> + }
> +
> + /*
> + * Set cpu clock source, for all the level we keep the same
> + * clock source that the one already configured. For this one
> + * we need to use the clock framework
> + */
> + parent = clk_get_parent(clk);
> + clk_set_parent(clk, parent);
> +}
> +
> +static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
> +{
> + unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
> + mask = ARMADA_37XX_NB_DFS_EN;
> +
> + regmap_update_bits(base, reg, mask, 0);
> +}
> +
> +static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
> +{
> + unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
> + mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
> +
> + /* Start with the highest load (0) */
> + val = ARMADA_37XX_DVFS_LOAD_0;
> + regmap_update_bits(base, reg, mask, val);
> +
> + /* Now enable DVFS for the CPUs */
> + reg = ARMADA_37XX_NB_DYN_MOD;
> + mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
> + ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
> + ARMADA_37XX_NB_DFS_EN;
> +
> + regmap_update_bits(base, reg, mask, mask);
> +}
> +
> +static int __init armada37xx_cpufreq_driver_init(void)
> +{
> + struct armada_37xx_dvfs *dvfs;
> + struct platform_device *pdev;
> + unsigned int cur_frequency;
> + struct regmap *nb_pm_base;
> + struct device *cpu_dev;
> + int load_level, ret;
> + struct clk *clk;
> +
> + nb_pm_base =
> + syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
> +
> + if (IS_ERR(nb_pm_base))
> + return -ENODEV;
> +
> + /* Before doing any configuration on the DVFS first, disable it */
> + armada37xx_cpufreq_disable_dvfs(nb_pm_base);
> +
> + /*
> + * On CPU 0 register the operating points supported (which are
> + * the nominal CPU frequency and full integer divisions of
> + * it).
> + */
> + cpu_dev = get_cpu_device(0);
> + if (!cpu_dev) {
> + dev_err(cpu_dev, "Cannot get CPU\n");
> + return -ENODEV;
> + }
> +
> + clk = clk_get(cpu_dev, 0);
> + if (IS_ERR(clk)) {
> + dev_err(cpu_dev, "Cannot get clock for CPU0\n");
> + return PTR_ERR(clk);
> + }
> +
> + /* Get nominal (current) CPU frequency */
> + cur_frequency = clk_get_rate(clk);
> + if (!cur_frequency) {
> + dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
> + return -EINVAL;
> + }
> +
> + dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
> + if (!dvfs)
> + return -EINVAL;
> +
> + armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
> +
> + /*
> + * In case of a failure of dev_pm_opp_add(), we don't bother
> + * with cleaning up the registered OPP (there's no function to
> + * do so),
What do you mean by the comment within ()? We do have
dev_pm_opp_remove() helper.
> and simply cancel the registration of the cpufreq
> + * device.
> + */
> + for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
> + load_level++) {
> + unsigned long freq = dvfs->divider[load_level];
> +
> + ret = dev_pm_opp_add(cpu_dev, freq, 0);
> + if (ret)
> + return ret;
> + }
> +
> + /* Now that everything is setup, enable the DVFS at hardware level */
> + armada37xx_cpufreq_enable_dvfs(nb_pm_base);
> +
> + pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
> +
> + return PTR_ERR_OR_ZERO(pdev);
> +}
> +/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
> +late_initcall(armada37xx_cpufreq_driver_init);
> +
> +MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
> +MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
> +MODULE_LICENSE("GPL");
> --
> 2.15.0
--
viresh
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx
2017-12-03 12:23 ` [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx Andre Heider
@ 2017-12-06 11:50 ` Gregory CLEMENT
2017-12-06 14:08 ` Andre Heider
0 siblings, 1 reply; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 11:50 UTC (permalink / raw)
To: linux-arm-kernel
Hi Andre,
On dim., d?c. 03 2017, Andre Heider <a.heider@gmail.com> wrote:
> Hi Gregory,
>
> I applied this and the dvfs patch set ([PATCH 0/3] Add DVFS support on
> CPU clock for Armada 37xx) on top of 4.14.3 and gave it a try on
> espressobin.
Thanks for testing.
>
> Upon modprobe I get:
> [ 66.231652] freq_table: Duplicate freq-table entries: 0
> [ 66.236967] cpu cpu0: cpufreq_init: invalid frequency table: -22
> [ 66.243534] freq_table: Duplicate freq-table entries: 0
> [ 66.248575] cpu cpu1: cpufreq_init: invalid frequency table: -22
>
> Is this supposed to work already? Do I miss something?
I did a last rebase before sending the series to remove the avs part not
working yet. And during this rebase I introduced an bug.
I will send a v2 soon if you are intersected by testing it right now,
here it is the fix:
iff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
index 40c9a744cc6e..96c2600009b5 100644
--- a/drivers/cpufreq/armada-37xx-cpufreq.c
+++ b/drivers/cpufreq/armada-37xx-cpufreq.c
@@ -219,7 +219,8 @@ static int __init armada37xx_cpufreq_driver_init(void)
*/
for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
load_level++) {
- unsigned long freq = dvfs->divider[load_level];
+ unsigned long freq = cur_frequency /
+ dvfs->divider[load_level];
ret = dev_pm_opp_add(cpu_dev, freq, 0);
if (ret)
Gregory
>
> Oh, and on that scenario it's not possible to rmmod the driver again, EBUSY.
>
> Thanks,
> Andre
>
> On 01/12/17 12:25, Gregory CLEMENT
> <gregory.clement@free-electrons.com> wrote:
>> Hi,
>>
>> This series adds the CPU Frequency support on Armada 37xx using
>> DVFS. It is based on the initial work of Evan Wang and Victor Gu.
>>
>> DVFS control is done by a set of registers from the North Bridge Power
>> Management block. The binding for this block is documented in patch 1.
>>
>> While adding a new cpufreq driver I found that the Kconfig and
>> Makefile were no more in order, so it is fixed by patch 2 and 3.
>>
>> The 4th patch is just about updating the MAINTAINERS file with the new
>> driver.
>>
>> The next patch is the real purpose of the series. The main goal of
>> this driver is to setup the CPU load level in the hardware to
>> associate them to CPU frequencies and register a standard cpufreq
>> driver. Note that the hardware also capable of doing AVS (Adaptive
>> Voltage Scaling), by associating a voltage on each level beside the
>> CPU frequency. However, this support is not yet ready, so it is not
>> part of this series.
>>
>> Finally, the last patch is for arm-soc the arm-soc subsystem through
>> mvebu and update the device tree to support the CPU frequency scaling.
>>
>> An update on the CPU clock driver is needed in order to take into
>> account the DVFS setting. It's the purpose of an other series already
>> sent, but is no dependencies between the series (for building or at
>> runtime).
>>
>> Thanks,
>>
>> Gregory
>>
>> Gregory CLEMENT (6):
>> dt-bindings: marvell: Add documentation for the North Bridge PM on
>> Armada 37xx
>> cpufreq: ARM: sort the Kconfig menu
>> cpufreq: sort the drivers in ARM part
>> MAINTAINERS: add new entries for Armada 37xx cpufreq driver
>> cpufreq: Add DVFS support for Armada 37xx
>> arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support
>>
>> .../bindings/arm/marvell/armada-37xx.txt | 19 ++
>> MAINTAINERS | 1 +
>> arch/arm64/boot/dts/marvell/armada-372x.dtsi | 1 +
>> arch/arm64/boot/dts/marvell/armada-37xx.dtsi | 7 +
>> drivers/cpufreq/Kconfig.arm | 89 ++++----
>> drivers/cpufreq/Makefile | 9 +-
>> drivers/cpufreq/armada-37xx-cpufreq.c | 241 +++++++++++++++++++++
>> 7 files changed, 322 insertions(+), 45 deletions(-)
>> create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
>>
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH 1/6] dt-bindings: marvell: Add documentation for the North Bridge PM on Armada 37xx
2017-12-04 21:47 ` Rob Herring
@ 2017-12-06 11:51 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 11:51 UTC (permalink / raw)
To: Rob Herring
Cc: Rafael J. Wysocki, Viresh Kumar, linux-pm-u79uwXL29TY76Z2rM5mHXA,
Jason Cooper, Andrew Lunn, Sebastian Hesselbarth,
devicetree-u79uwXL29TY76Z2rM5mHXA, Thomas Petazzoni,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
Antoine Tenart, Miquèl Raynal, Nadav Haklai, Victor Gu,
Marcin Wojtas, Wilson Ding, Hua Jing, Neta Zur Hershkovits,
Evan Wang
Hi Rob,
On lun., déc. 04 2017, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Fri, Dec 01, 2017 at 12:25:03PM +0100, Gregory CLEMENT wrote:
>> Extend the documentation of the Armada 37xx SoC with the the North
>> Bridge Power Management component.
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>> ---
>> .../devicetree/bindings/arm/marvell/armada-37xx.txt | 19 +++++++++++++++++++
>> 1 file changed, 19 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
>> index 51336e5fc761..7ad9830d9177 100644
>> --- a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
>> +++ b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
>> @@ -14,3 +14,22 @@ following property before the previous one:
>> Example:
>>
>> compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
>> +
>> +
>> +Power management
>> +----------------
>> +
>> +For power management (particularly DVFS and AVS), the North Bridge
>> +Power Management component is needed:
>> +
>> +Required properties:
>> +- compatible : should contain "marvell,armada-3700-nb-pm", "syscon";
>> +- reg : the register start and length for the North Bridge
>> + Power Management
>> +
>> +Example:
>> +
>> +nb_pm: nb_pm@14000 {
>
> Don't use underscore in node or property names. "syscon" is a better
> choice here.
OK I will change this.
Thanks,
Gregory
>
>> + compatible = "marvell,armada-3700-nb-pm", "syscon";
>> + reg = <0x14000 0x60>;
>> +}
>> --
>> 2.15.0
>>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 1/6] dt-bindings: marvell: Add documentation for the North Bridge PM on Armada 37xx
@ 2017-12-06 11:51 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 11:51 UTC (permalink / raw)
To: linux-arm-kernel
Hi Rob,
On lun., d?c. 04 2017, Rob Herring <robh@kernel.org> wrote:
> On Fri, Dec 01, 2017 at 12:25:03PM +0100, Gregory CLEMENT wrote:
>> Extend the documentation of the Armada 37xx SoC with the the North
>> Bridge Power Management component.
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>> ---
>> .../devicetree/bindings/arm/marvell/armada-37xx.txt | 19 +++++++++++++++++++
>> 1 file changed, 19 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
>> index 51336e5fc761..7ad9830d9177 100644
>> --- a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
>> +++ b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
>> @@ -14,3 +14,22 @@ following property before the previous one:
>> Example:
>>
>> compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
>> +
>> +
>> +Power management
>> +----------------
>> +
>> +For power management (particularly DVFS and AVS), the North Bridge
>> +Power Management component is needed:
>> +
>> +Required properties:
>> +- compatible : should contain "marvell,armada-3700-nb-pm", "syscon";
>> +- reg : the register start and length for the North Bridge
>> + Power Management
>> +
>> +Example:
>> +
>> +nb_pm: nb_pm at 14000 {
>
> Don't use underscore in node or property names. "syscon" is a better
> choice here.
OK I will change this.
Thanks,
Gregory
>
>> + compatible = "marvell,armada-3700-nb-pm", "syscon";
>> + reg = <0x14000 0x60>;
>> +}
>> --
>> 2.15.0
>>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 2/6] cpufreq: ARM: sort the Kconfig menu
2017-12-04 8:41 ` Viresh Kumar
@ 2017-12-06 11:52 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 11:52 UTC (permalink / raw)
To: Viresh Kumar
Cc: Thomas Petazzoni, Andrew Lunn, Jason Cooper, linux-pm,
Antoine Tenart, Rafael J. Wysocki, Evan Wang, Nadav Haklai,
devicetree, Rob Herring, Neta Zur Hershkovits,
Miquèl Raynal, Victor Gu, Hua Jing, Marcin Wojtas,
Wilson Ding, linux-arm-kernel, Sebastian Hesselbarth
Hi Viresh,
On lun., déc. 04 2017, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 01-12-17, 12:25, Gregory CLEMENT wrote:
>> +config ARM_VEXPRESS_SPC_CPUFREQ
>> + tristate "Versatile Express SPC based CPUfreq driver"
>> + depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
>> + help
>> + This add the CPUfreq driver support for Versatile Express
>> + big.LITTLE platforms using SPC for power management.
>> +
>> +config ARM_SCPI_CPUFREQ
>
> The order of above two must be reversed ?
Right, I will fix it.
Thanks,
Gregory
>
> --
> viresh
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 2/6] cpufreq: ARM: sort the Kconfig menu
@ 2017-12-06 11:52 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 11:52 UTC (permalink / raw)
To: linux-arm-kernel
Hi Viresh,
On lun., d?c. 04 2017, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 01-12-17, 12:25, Gregory CLEMENT wrote:
>> +config ARM_VEXPRESS_SPC_CPUFREQ
>> + tristate "Versatile Express SPC based CPUfreq driver"
>> + depends on ARM_BIG_LITTLE_CPUFREQ && ARCH_VEXPRESS_SPC
>> + help
>> + This add the CPUfreq driver support for Versatile Express
>> + big.LITTLE platforms using SPC for power management.
>> +
>> +config ARM_SCPI_CPUFREQ
>
> The order of above two must be reversed ?
Right, I will fix it.
Thanks,
Gregory
>
> --
> viresh
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 3/6] cpufreq: sort the drivers in ARM part
2017-12-04 9:18 ` Viresh Kumar
@ 2017-12-06 12:09 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 12:09 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael J. Wysocki, linux-pm, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
Hi Viresh,
On lun., déc. 04 2017, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 01-12-17, 12:25, Gregory CLEMENT wrote:
>> Keep the driver files alphabetically sorted.
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>> ---
>> drivers/cpufreq/Makefile | 8 ++++----
>> 1 file changed, 4 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index 812f9e0d01a3..d762e76887e7 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -53,22 +53,24 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
>> obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
>>
>> obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
>> +obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
>
> Shouldn't we add them in ascending order of the whole config name and not just
> CPPC_CPUFREQ ?
Here it is the object name that are sorted not the CONFIG_ name. So
cppc_cpufreq comes after brcmstb-avs-cpufreq.
Thanks,
Gregory
>
> --
> viresh
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 3/6] cpufreq: sort the drivers in ARM part
@ 2017-12-06 12:09 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 12:09 UTC (permalink / raw)
To: linux-arm-kernel
Hi Viresh,
On lun., d?c. 04 2017, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 01-12-17, 12:25, Gregory CLEMENT wrote:
>> Keep the driver files alphabetically sorted.
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>> ---
>> drivers/cpufreq/Makefile | 8 ++++----
>> 1 file changed, 4 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index 812f9e0d01a3..d762e76887e7 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -53,22 +53,24 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
>> obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
>>
>> obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
>> +obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
>
> Shouldn't we add them in ascending order of the whole config name and not just
> CPPC_CPUFREQ ?
Here it is the object name that are sorted not the CONFIG_ name. So
cppc_cpufreq comes after brcmstb-avs-cpufreq.
Thanks,
Gregory
>
> --
> viresh
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH 5/6] cpufreq: Add DVFS support for Armada 37xx
2017-12-05 5:54 ` Viresh Kumar
@ 2017-12-06 12:24 ` Gregory CLEMENT
-1 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 12:24 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael J. Wysocki, linux-pm, Jason Cooper, Andrew Lunn,
Sebastian Hesselbarth, Rob Herring, devicetree, Thomas Petazzoni,
linux-arm-kernel, Antoine Tenart, Miquèl Raynal,
Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
Neta Zur Hershkovits, Evan Wang
Hi Viresh,
On mar., déc. 05 2017, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 01-12-17, 12:25, Gregory CLEMENT wrote:
>> This patch adds DVFS support for the Armada 37xx SoCs
>>
>> There are up to four CPU frequency loads for Armada 37xx controlled by
>> the hardware.
>>
>> This driver associates the CPU load level to a frequency, then the
>> hardware will switch while selecting a load level.
>>
>> The hardware also can associate a voltage for each level (AVS support)
>> but it is not yet supported
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>> ---
>> drivers/cpufreq/Kconfig.arm | 7 +
>> drivers/cpufreq/Makefile | 1 +
>> drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
>> 3 files changed, 249 insertions(+)
>> create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index 17625115c67f..3018ff0d068f 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -19,6 +19,13 @@ config ACPI_CPPC_CPUFREQ
>>
>> If in doubt, say N.
>>
>> +config ARM_ARMADA_37XX_CPUFREQ
>> + tristate "Armada 37xx CPUFreq support"
>> + depends on ARCH_MVEBU
>> + help
>> + This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
>> + The Armada 37xx PMU supports 4 frequency and VDD levels.
>> +
>> # big LITTLE core layer and glue drivers
>> config ARM_BIG_LITTLE_CPUFREQ
>> tristate "Generic ARM big LITTLE CPUfreq driver"
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index d762e76887e7..e07715ce8844 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
>> # LITTLE drivers, so that it is probed last.
>> obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
>>
>> +obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
>> obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
>> obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
>> obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
>> diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
>> new file mode 100644
>> index 000000000000..40c9a744cc6e
>> --- /dev/null
>> +++ b/drivers/cpufreq/armada-37xx-cpufreq.c
>> @@ -0,0 +1,241 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * CPU frequency scaling support for Armada 37xx platform.
>> + *
>> + * Copyright (C) 2017 Marvell
>> + *
>> + * Gregory CLEMENT <gregory.clement@free-electrons.com>
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/cpu.h>
>> +#include <linux/cpufreq.h>
>> +#include <linux/err.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/module.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pm_opp.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +
>> +/* Power management in North Bridge register set */
>> +#define ARMADA_37XX_NB_L0L1 0x18
>> +#define ARMADA_37XX_NB_L2L3 0x1C
>> +#define ARMADA_37XX_NB_TBG_DIV_OFF 13
>> +#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
>> +#define ARMADA_37XX_NB_CLK_SEL_OFF 11
>> +#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
>> +#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
>> +#define ARMADA_37XX_NB_TBG_SEL_OFF 9
>> +#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
>> +#define ARMADA_37XX_NB_VDD_SEL_OFF 6
>> +#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
>> +#define ARMADA_37XX_NB_CONFIG_SHIFT 16
>
> Looks like you have added tabs after #define as well? Perhaps a space
> is good enough there.
OK
>
>> +#define ARMADA_37XX_NB_DYN_MOD 0x24
>> +#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
>> +#define ARMADA_37XX_NB_TBG_EN BIT(28)
>> +#define ARMADA_37XX_NB_DIV_EN BIT(29)
>> +#define ARMADA_37XX_NB_VDD_EN BIT(30)
>> +#define ARMADA_37XX_NB_DFS_EN BIT(31)
>> +#define ARMADA_37XX_NB_CPU_LOAD 0x30
>> +#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
>> +#define ARMADA_37XX_DVFS_LOAD_0 0
>> +#define ARMADA_37XX_DVFS_LOAD_1 1
>> +#define ARMADA_37XX_DVFS_LOAD_2 2
>> +#define ARMADA_37XX_DVFS_LOAD_3 3
>> +
>> +/*
>> + * On Armada 37xx the Power management manages 4 level of CPU load,
>> + * each level can be associated with a CPU clock source, a CPU
>> + * divider, a VDD level, etc...
>> + */
>> +#define LOAD_LEVEL_NR 4
>> +
>> +struct armada_37xx_dvfs {
>> + u32 cpu_freq_max;
>> + u8 divider[LOAD_LEVEL_NR];
>> +};
>> +
>> +static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
>> + {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
>> + {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
>> + {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
>> + {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
>> +};
>> +
>> +static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
>> + if (freq == armada_37xx_dvfs[i].cpu_freq_max)
>> + return &armada_37xx_dvfs[i];
>> + }
>> +
>> + pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
>> + return NULL;
>> +}
>> +
>> +/*
>> + * Setup the four level managed by the hardware. Once the four level
>> + * will be configured then the DVFS will be enabled.
>> + */
>> +static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
>> + struct clk *clk, u8 *divider)
>> +{
>> + int load_level;
>> + struct clk *parent;
>> +
>> + for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
>> + unsigned int reg, mask, val, offset = 0;
>> +
>> + if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
>> + reg = ARMADA_37XX_NB_L0L1;
>> + else
>> + reg = ARMADA_37XX_NB_L2L3;
>> +
>> + if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
>> + load_level == ARMADA_37XX_DVFS_LOAD_2)
>> + offset += ARMADA_37XX_NB_CONFIG_SHIFT;
>> +
>> + /* Set cpu clock source, for all the level we use TBG */
>> + val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
>> + mask = (ARMADA_37XX_NB_CLK_SEL_MASK
>> + << ARMADA_37XX_NB_CLK_SEL_OFF);
>> +
>> + /*
>> + * Set cpu divider based on the pre-computed array in
>> + * order to have balanced step.
>> + */
>> + val |= divider[load_level] << ARMADA_37XX_NB_TBG_DIV_OFF;
>> + mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
>> + << ARMADA_37XX_NB_TBG_DIV_OFF);
>> +
>> + /* Set VDD divider which is actually the load level. */
>> + val |= load_level << ARMADA_37XX_NB_VDD_SEL_OFF;
>> + mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
>> + << ARMADA_37XX_NB_VDD_SEL_OFF);
>> +
>> + val <<= offset;
>> + mask <<= offset;
>> +
>> + regmap_update_bits(base, reg, mask, val);
>> + }
>> +
>> + /*
>> + * Set cpu clock source, for all the level we keep the same
>> + * clock source that the one already configured. For this one
>> + * we need to use the clock framework
>> + */
>> + parent = clk_get_parent(clk);
>> + clk_set_parent(clk, parent);
>> +}
>> +
>> +static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
>> +{
>> + unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
>> + mask = ARMADA_37XX_NB_DFS_EN;
>> +
>> + regmap_update_bits(base, reg, mask, 0);
>> +}
>> +
>> +static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
>> +{
>> + unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
>> + mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
>> +
>> + /* Start with the highest load (0) */
>> + val = ARMADA_37XX_DVFS_LOAD_0;
>> + regmap_update_bits(base, reg, mask, val);
>> +
>> + /* Now enable DVFS for the CPUs */
>> + reg = ARMADA_37XX_NB_DYN_MOD;
>> + mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
>> + ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
>> + ARMADA_37XX_NB_DFS_EN;
>> +
>> + regmap_update_bits(base, reg, mask, mask);
>> +}
>> +
>> +static int __init armada37xx_cpufreq_driver_init(void)
>> +{
>> + struct armada_37xx_dvfs *dvfs;
>> + struct platform_device *pdev;
>> + unsigned int cur_frequency;
>> + struct regmap *nb_pm_base;
>> + struct device *cpu_dev;
>> + int load_level, ret;
>> + struct clk *clk;
>> +
>> + nb_pm_base =
>> + syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
>> +
>> + if (IS_ERR(nb_pm_base))
>> + return -ENODEV;
>> +
>> + /* Before doing any configuration on the DVFS first, disable it */
>> + armada37xx_cpufreq_disable_dvfs(nb_pm_base);
>> +
>> + /*
>> + * On CPU 0 register the operating points supported (which are
>> + * the nominal CPU frequency and full integer divisions of
>> + * it).
>> + */
>> + cpu_dev = get_cpu_device(0);
>> + if (!cpu_dev) {
>> + dev_err(cpu_dev, "Cannot get CPU\n");
>> + return -ENODEV;
>> + }
>> +
>> + clk = clk_get(cpu_dev, 0);
>> + if (IS_ERR(clk)) {
>> + dev_err(cpu_dev, "Cannot get clock for CPU0\n");
>> + return PTR_ERR(clk);
>> + }
>> +
>> + /* Get nominal (current) CPU frequency */
>> + cur_frequency = clk_get_rate(clk);
>> + if (!cur_frequency) {
>> + dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
>> + return -EINVAL;
>> + }
>> +
>> + dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
>> + if (!dvfs)
>> + return -EINVAL;
>> +
>> + armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
>> +
>> + /*
>> + * In case of a failure of dev_pm_opp_add(), we don't bother
>> + * with cleaning up the registered OPP (there's no function to
>> + * do so),
>
> What do you mean by the comment within ()? We do have
> dev_pm_opp_remove() helper.
Actually it was a copy and paste from an other driver, I didn't check it
this was still true.
So the original comment was added in July 2014 and the
dev_pm_opp_remove() helpers was added few months later
in Nov 2014.
I will fix it and also in the other driver mvebu-cpufreq.c.
Thanks,
Gregory
>
>> and simply cancel the registration of the cpufreq
>> + * device.
>> + */
>> + for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
>> + load_level++) {
>> + unsigned long freq = dvfs->divider[load_level];
>> +
>> + ret = dev_pm_opp_add(cpu_dev, freq, 0);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + /* Now that everything is setup, enable the DVFS at hardware level */
>> + armada37xx_cpufreq_enable_dvfs(nb_pm_base);
>> +
>> + pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
>> +
>> + return PTR_ERR_OR_ZERO(pdev);
>> +}
>> +/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
>> +late_initcall(armada37xx_cpufreq_driver_init);
>> +
>> +MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
>> +MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
>> +MODULE_LICENSE("GPL");
>> --
>> 2.15.0
>
> --
> viresh
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 5/6] cpufreq: Add DVFS support for Armada 37xx
@ 2017-12-06 12:24 ` Gregory CLEMENT
0 siblings, 0 replies; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-06 12:24 UTC (permalink / raw)
To: linux-arm-kernel
Hi Viresh,
On mar., d?c. 05 2017, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> On 01-12-17, 12:25, Gregory CLEMENT wrote:
>> This patch adds DVFS support for the Armada 37xx SoCs
>>
>> There are up to four CPU frequency loads for Armada 37xx controlled by
>> the hardware.
>>
>> This driver associates the CPU load level to a frequency, then the
>> hardware will switch while selecting a load level.
>>
>> The hardware also can associate a voltage for each level (AVS support)
>> but it is not yet supported
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>> ---
>> drivers/cpufreq/Kconfig.arm | 7 +
>> drivers/cpufreq/Makefile | 1 +
>> drivers/cpufreq/armada-37xx-cpufreq.c | 241 ++++++++++++++++++++++++++++++++++
>> 3 files changed, 249 insertions(+)
>> create mode 100644 drivers/cpufreq/armada-37xx-cpufreq.c
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index 17625115c67f..3018ff0d068f 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -19,6 +19,13 @@ config ACPI_CPPC_CPUFREQ
>>
>> If in doubt, say N.
>>
>> +config ARM_ARMADA_37XX_CPUFREQ
>> + tristate "Armada 37xx CPUFreq support"
>> + depends on ARCH_MVEBU
>> + help
>> + This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
>> + The Armada 37xx PMU supports 4 frequency and VDD levels.
>> +
>> # big LITTLE core layer and glue drivers
>> config ARM_BIG_LITTLE_CPUFREQ
>> tristate "Generic ARM big LITTLE CPUfreq driver"
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index d762e76887e7..e07715ce8844 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -52,6 +52,7 @@ obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o
>> # LITTLE drivers, so that it is probed last.
>> obj-$(CONFIG_ARM_DT_BL_CPUFREQ) += arm_big_little_dt.o
>>
>> +obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
>> obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
>> obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
>> obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
>> diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
>> new file mode 100644
>> index 000000000000..40c9a744cc6e
>> --- /dev/null
>> +++ b/drivers/cpufreq/armada-37xx-cpufreq.c
>> @@ -0,0 +1,241 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * CPU frequency scaling support for Armada 37xx platform.
>> + *
>> + * Copyright (C) 2017 Marvell
>> + *
>> + * Gregory CLEMENT <gregory.clement@free-electrons.com>
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/cpu.h>
>> +#include <linux/cpufreq.h>
>> +#include <linux/err.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/mfd/syscon.h>
>> +#include <linux/module.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/pm_opp.h>
>> +#include <linux/regmap.h>
>> +#include <linux/slab.h>
>> +
>> +/* Power management in North Bridge register set */
>> +#define ARMADA_37XX_NB_L0L1 0x18
>> +#define ARMADA_37XX_NB_L2L3 0x1C
>> +#define ARMADA_37XX_NB_TBG_DIV_OFF 13
>> +#define ARMADA_37XX_NB_TBG_DIV_MASK 0x7
>> +#define ARMADA_37XX_NB_CLK_SEL_OFF 11
>> +#define ARMADA_37XX_NB_CLK_SEL_MASK 0x1
>> +#define ARMADA_37XX_NB_CLK_SEL_TBG 0x1
>> +#define ARMADA_37XX_NB_TBG_SEL_OFF 9
>> +#define ARMADA_37XX_NB_TBG_SEL_MASK 0x3
>> +#define ARMADA_37XX_NB_VDD_SEL_OFF 6
>> +#define ARMADA_37XX_NB_VDD_SEL_MASK 0x3
>> +#define ARMADA_37XX_NB_CONFIG_SHIFT 16
>
> Looks like you have added tabs after #define as well? Perhaps a space
> is good enough there.
OK
>
>> +#define ARMADA_37XX_NB_DYN_MOD 0x24
>> +#define ARMADA_37XX_NB_CLK_SEL_EN BIT(26)
>> +#define ARMADA_37XX_NB_TBG_EN BIT(28)
>> +#define ARMADA_37XX_NB_DIV_EN BIT(29)
>> +#define ARMADA_37XX_NB_VDD_EN BIT(30)
>> +#define ARMADA_37XX_NB_DFS_EN BIT(31)
>> +#define ARMADA_37XX_NB_CPU_LOAD 0x30
>> +#define ARMADA_37XX_NB_CPU_LOAD_MASK 0x3
>> +#define ARMADA_37XX_DVFS_LOAD_0 0
>> +#define ARMADA_37XX_DVFS_LOAD_1 1
>> +#define ARMADA_37XX_DVFS_LOAD_2 2
>> +#define ARMADA_37XX_DVFS_LOAD_3 3
>> +
>> +/*
>> + * On Armada 37xx the Power management manages 4 level of CPU load,
>> + * each level can be associated with a CPU clock source, a CPU
>> + * divider, a VDD level, etc...
>> + */
>> +#define LOAD_LEVEL_NR 4
>> +
>> +struct armada_37xx_dvfs {
>> + u32 cpu_freq_max;
>> + u8 divider[LOAD_LEVEL_NR];
>> +};
>> +
>> +static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
>> + {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
>> + {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
>> + {.cpu_freq_max = 800*1000*1000, .divider = {1, 2, 3, 4} },
>> + {.cpu_freq_max = 600*1000*1000, .divider = {2, 4, 5, 6} },
>> +};
>> +
>> +static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
>> + if (freq == armada_37xx_dvfs[i].cpu_freq_max)
>> + return &armada_37xx_dvfs[i];
>> + }
>> +
>> + pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
>> + return NULL;
>> +}
>> +
>> +/*
>> + * Setup the four level managed by the hardware. Once the four level
>> + * will be configured then the DVFS will be enabled.
>> + */
>> +static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
>> + struct clk *clk, u8 *divider)
>> +{
>> + int load_level;
>> + struct clk *parent;
>> +
>> + for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
>> + unsigned int reg, mask, val, offset = 0;
>> +
>> + if (load_level <= ARMADA_37XX_DVFS_LOAD_1)
>> + reg = ARMADA_37XX_NB_L0L1;
>> + else
>> + reg = ARMADA_37XX_NB_L2L3;
>> +
>> + if (load_level == ARMADA_37XX_DVFS_LOAD_0 ||
>> + load_level == ARMADA_37XX_DVFS_LOAD_2)
>> + offset += ARMADA_37XX_NB_CONFIG_SHIFT;
>> +
>> + /* Set cpu clock source, for all the level we use TBG */
>> + val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
>> + mask = (ARMADA_37XX_NB_CLK_SEL_MASK
>> + << ARMADA_37XX_NB_CLK_SEL_OFF);
>> +
>> + /*
>> + * Set cpu divider based on the pre-computed array in
>> + * order to have balanced step.
>> + */
>> + val |= divider[load_level] << ARMADA_37XX_NB_TBG_DIV_OFF;
>> + mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
>> + << ARMADA_37XX_NB_TBG_DIV_OFF);
>> +
>> + /* Set VDD divider which is actually the load level. */
>> + val |= load_level << ARMADA_37XX_NB_VDD_SEL_OFF;
>> + mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
>> + << ARMADA_37XX_NB_VDD_SEL_OFF);
>> +
>> + val <<= offset;
>> + mask <<= offset;
>> +
>> + regmap_update_bits(base, reg, mask, val);
>> + }
>> +
>> + /*
>> + * Set cpu clock source, for all the level we keep the same
>> + * clock source that the one already configured. For this one
>> + * we need to use the clock framework
>> + */
>> + parent = clk_get_parent(clk);
>> + clk_set_parent(clk, parent);
>> +}
>> +
>> +static void __init armada37xx_cpufreq_disable_dvfs(struct regmap *base)
>> +{
>> + unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
>> + mask = ARMADA_37XX_NB_DFS_EN;
>> +
>> + regmap_update_bits(base, reg, mask, 0);
>> +}
>> +
>> +static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
>> +{
>> + unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
>> + mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
>> +
>> + /* Start with the highest load (0) */
>> + val = ARMADA_37XX_DVFS_LOAD_0;
>> + regmap_update_bits(base, reg, mask, val);
>> +
>> + /* Now enable DVFS for the CPUs */
>> + reg = ARMADA_37XX_NB_DYN_MOD;
>> + mask = ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
>> + ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
>> + ARMADA_37XX_NB_DFS_EN;
>> +
>> + regmap_update_bits(base, reg, mask, mask);
>> +}
>> +
>> +static int __init armada37xx_cpufreq_driver_init(void)
>> +{
>> + struct armada_37xx_dvfs *dvfs;
>> + struct platform_device *pdev;
>> + unsigned int cur_frequency;
>> + struct regmap *nb_pm_base;
>> + struct device *cpu_dev;
>> + int load_level, ret;
>> + struct clk *clk;
>> +
>> + nb_pm_base =
>> + syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
>> +
>> + if (IS_ERR(nb_pm_base))
>> + return -ENODEV;
>> +
>> + /* Before doing any configuration on the DVFS first, disable it */
>> + armada37xx_cpufreq_disable_dvfs(nb_pm_base);
>> +
>> + /*
>> + * On CPU 0 register the operating points supported (which are
>> + * the nominal CPU frequency and full integer divisions of
>> + * it).
>> + */
>> + cpu_dev = get_cpu_device(0);
>> + if (!cpu_dev) {
>> + dev_err(cpu_dev, "Cannot get CPU\n");
>> + return -ENODEV;
>> + }
>> +
>> + clk = clk_get(cpu_dev, 0);
>> + if (IS_ERR(clk)) {
>> + dev_err(cpu_dev, "Cannot get clock for CPU0\n");
>> + return PTR_ERR(clk);
>> + }
>> +
>> + /* Get nominal (current) CPU frequency */
>> + cur_frequency = clk_get_rate(clk);
>> + if (!cur_frequency) {
>> + dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
>> + return -EINVAL;
>> + }
>> +
>> + dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
>> + if (!dvfs)
>> + return -EINVAL;
>> +
>> + armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
>> +
>> + /*
>> + * In case of a failure of dev_pm_opp_add(), we don't bother
>> + * with cleaning up the registered OPP (there's no function to
>> + * do so),
>
> What do you mean by the comment within ()? We do have
> dev_pm_opp_remove() helper.
Actually it was a copy and paste from an other driver, I didn't check it
this was still true.
So the original comment was added in July 2014 and the
dev_pm_opp_remove() helpers was added few months later
in Nov 2014.
I will fix it and also in the other driver mvebu-cpufreq.c.
Thanks,
Gregory
>
>> and simply cancel the registration of the cpufreq
>> + * device.
>> + */
>> + for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
>> + load_level++) {
>> + unsigned long freq = dvfs->divider[load_level];
>> +
>> + ret = dev_pm_opp_add(cpu_dev, freq, 0);
>> + if (ret)
>> + return ret;
>> + }
>> +
>> + /* Now that everything is setup, enable the DVFS at hardware level */
>> + armada37xx_cpufreq_enable_dvfs(nb_pm_base);
>> +
>> + pdev = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
>> +
>> + return PTR_ERR_OR_ZERO(pdev);
>> +}
>> +/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
>> +late_initcall(armada37xx_cpufreq_driver_init);
>> +
>> +MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
>> +MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
>> +MODULE_LICENSE("GPL");
>> --
>> 2.15.0
>
> --
> viresh
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx
2017-12-06 11:50 ` Gregory CLEMENT
@ 2017-12-06 14:08 ` Andre Heider
2017-12-18 17:03 ` Gregory CLEMENT
0 siblings, 1 reply; 35+ messages in thread
From: Andre Heider @ 2017-12-06 14:08 UTC (permalink / raw)
To: linux-arm-kernel
On 06/12/17 12:50, Gregory CLEMENT wrote:
> I did a last rebase before sending the series to remove the avs part not
> working yet. And during this rebase I introduced an bug.
>
> I will send a v2 soon if you are intersected by testing it right now,
> here it is the fix:
>
> iff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
> index 40c9a744cc6e..96c2600009b5 100644
> --- a/drivers/cpufreq/armada-37xx-cpufreq.c
> +++ b/drivers/cpufreq/armada-37xx-cpufreq.c
> @@ -219,7 +219,8 @@ static int __init armada37xx_cpufreq_driver_init(void)
> */
> for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
> load_level++) {
> - unsigned long freq = dvfs->divider[load_level];
> + unsigned long freq = cur_frequency /
> + dvfs->divider[load_level];
>
> ret = dev_pm_opp_add(cpu_dev, freq, 0);
> if (ret)
Much better, that seems to work so far, thanks!
My espressobin now gets these frequencies: 200 MHz, 250 MHz, 500 MHz and
1000 MHz.
With the schedutil governor and `watch -n 0.2 cpufreq-info -f -m` it
jumps over all of those depending on the load, nice:
Tested-by: Andre Heider <a.heider@gmail.com>
The measured power usage doesn't drop though, I guess that requires the
AVS part you mentioned? Looking forward to it ;)
On a related note: Do you know if power usage can be lowered by
disabling eth phys? Is that possible on mainline?
Regards,
Andre
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx
2017-12-06 14:08 ` Andre Heider
@ 2017-12-18 17:03 ` Gregory CLEMENT
2017-12-21 7:45 ` Andre Heider
0 siblings, 1 reply; 35+ messages in thread
From: Gregory CLEMENT @ 2017-12-18 17:03 UTC (permalink / raw)
To: linux-arm-kernel
Hi Andre,
On mer., d?c. 06 2017, Andre Heider <a.heider@gmail.com> wrote:
> On 06/12/17 12:50, Gregory CLEMENT wrote:
>> I did a last rebase before sending the series to remove the avs part not
>> working yet. And during this rebase I introduced an bug.
>>
>> I will send a v2 soon if you are intersected by testing it right now,
>> here it is the fix:
>>
>> iff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
>> index 40c9a744cc6e..96c2600009b5 100644
>> --- a/drivers/cpufreq/armada-37xx-cpufreq.c
>> +++ b/drivers/cpufreq/armada-37xx-cpufreq.c
>> @@ -219,7 +219,8 @@ static int __init armada37xx_cpufreq_driver_init(void)
>> */
>> for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
>> load_level++) {
>> - unsigned long freq = dvfs->divider[load_level];
>> + unsigned long freq = cur_frequency /
>> + dvfs->divider[load_level];
>> ret = dev_pm_opp_add(cpu_dev, freq, 0);
>> if (ret)
>
> Much better, that seems to work so far, thanks!
>
> My espressobin now gets these frequencies: 200 MHz, 250 MHz, 500 MHz
> and 1000 MHz.
>
> With the schedutil governor and `watch -n 0.2 cpufreq-info -f -m` it
> jumps over all of those depending on the load, nice:
>
> Tested-by: Andre Heider <a.heider@gmail.com>
>
> The measured power usage doesn't drop though, I guess that requires
> the AVS part you mentioned? Looking forward to it ;)
Well I did some measurement and i saw some drop, according to my notes:
@ 250MHz: 222mA at 12V => 2.66W
@ 1000MHz: 238mA at 12CV => 2.87W
Not something huge, but only the CPUs which are concerned so it's not so
bad.
>
> On a related note: Do you know if power usage can be lowered by
> disabling eth phys? Is that possible on mainline?
For the test I have done just by removing an Ethernet cable we save a
lot of power, so it helps. I'm sure it is doable on mainline, but maybe
currently, there is something still missing.
Gregory
>
> Regards,
> Andre
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx
2017-12-18 17:03 ` Gregory CLEMENT
@ 2017-12-21 7:45 ` Andre Heider
0 siblings, 0 replies; 35+ messages in thread
From: Andre Heider @ 2017-12-21 7:45 UTC (permalink / raw)
To: linux-arm-kernel
On 18/12/17 18:03, Gregory CLEMENT wrote:
> Hi Andre,
>
> On mer., d?c. 06 2017, Andre Heider <a.heider@gmail.com> wrote:
>
>> On 06/12/17 12:50, Gregory CLEMENT wrote:
>>> I did a last rebase before sending the series to remove the avs part not
>>> working yet. And during this rebase I introduced an bug.
>>>
>>> I will send a v2 soon if you are intersected by testing it right now,
>>> here it is the fix:
>>>
>>> iff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
>>> index 40c9a744cc6e..96c2600009b5 100644
>>> --- a/drivers/cpufreq/armada-37xx-cpufreq.c
>>> +++ b/drivers/cpufreq/armada-37xx-cpufreq.c
>>> @@ -219,7 +219,8 @@ static int __init armada37xx_cpufreq_driver_init(void)
>>> */
>>> for (load_level = ARMADA_37XX_DVFS_LOAD_0; load_level < LOAD_LEVEL_NR;
>>> load_level++) {
>>> - unsigned long freq = dvfs->divider[load_level];
>>> + unsigned long freq = cur_frequency /
>>> + dvfs->divider[load_level];
>>> ret = dev_pm_opp_add(cpu_dev, freq, 0);
>>> if (ret)
>>
>> Much better, that seems to work so far, thanks!
>>
>> My espressobin now gets these frequencies: 200 MHz, 250 MHz, 500 MHz
>> and 1000 MHz.
>>
>> With the schedutil governor and `watch -n 0.2 cpufreq-info -f -m` it
>> jumps over all of those depending on the load, nice:
>>
>> Tested-by: Andre Heider <a.heider@gmail.com>
>>
>> The measured power usage doesn't drop though, I guess that requires
>> the AVS part you mentioned? Looking forward to it ;)
>
> Well I did some measurement and i saw some drop, according to my notes:
>
> @ 250MHz: 222mA at 12V => 2.66W
> @ 1000MHz: 238mA at 12CV => 2.87W
>
> Not something huge, but only the CPUs which are concerned so it's not so
> bad.
Oh, okay, my cheap equipment isn't capable to measure a difference of
just 0.2w... Guess I was hoping for more ;)
>> On a related note: Do you know if power usage can be lowered by
>> disabling eth phys? Is that possible on mainline?
>
> For the test I have done just by removing an Ethernet cable we save a
> lot of power, so it helps. I'm sure it is doable on mainline, but maybe
> currently, there is something still missing.
Promising, was that with a downstream kernel?
Thanks,
Andre
^ permalink raw reply [flat|nested] 35+ messages in thread
end of thread, other threads:[~2017-12-21 7:45 UTC | newest]
Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-01 11:25 [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx Gregory CLEMENT
2017-12-01 11:25 ` Gregory CLEMENT
2017-12-01 11:25 ` [PATCH 1/6] dt-bindings: marvell: Add documentation for the North Bridge PM " Gregory CLEMENT
2017-12-01 11:25 ` Gregory CLEMENT
2017-12-04 21:47 ` Rob Herring
2017-12-04 21:47 ` Rob Herring
2017-12-06 11:51 ` Gregory CLEMENT
2017-12-06 11:51 ` Gregory CLEMENT
2017-12-01 11:25 ` [PATCH 2/6] cpufreq: ARM: sort the Kconfig menu Gregory CLEMENT
2017-12-01 11:25 ` Gregory CLEMENT
2017-12-04 8:41 ` Viresh Kumar
2017-12-04 8:41 ` Viresh Kumar
2017-12-06 11:52 ` Gregory CLEMENT
2017-12-06 11:52 ` Gregory CLEMENT
2017-12-01 11:25 ` [PATCH 3/6] cpufreq: sort the drivers in ARM part Gregory CLEMENT
2017-12-01 11:25 ` Gregory CLEMENT
2017-12-04 9:18 ` Viresh Kumar
2017-12-04 9:18 ` Viresh Kumar
2017-12-06 12:09 ` Gregory CLEMENT
2017-12-06 12:09 ` Gregory CLEMENT
[not found] ` <20171201112508.14121-1-gregory.clement-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
2017-12-01 11:25 ` [PATCH 4/6] MAINTAINERS: add new entries for Armada 37xx cpufreq driver Gregory CLEMENT
2017-12-01 11:25 ` Gregory CLEMENT
2017-12-01 11:25 ` [PATCH 5/6] cpufreq: Add DVFS support for Armada 37xx Gregory CLEMENT
2017-12-01 11:25 ` Gregory CLEMENT
2017-12-05 5:54 ` Viresh Kumar
2017-12-05 5:54 ` Viresh Kumar
2017-12-06 12:24 ` Gregory CLEMENT
2017-12-06 12:24 ` Gregory CLEMENT
2017-12-01 11:25 ` [PATCH 6/6] arm64: dts: marvell: armada-37xx: add nodes allowing cpufreq support Gregory CLEMENT
2017-12-01 11:25 ` Gregory CLEMENT
2017-12-03 12:23 ` [PATCH 0/6] Add CPU Frequency scaling support on Armada 37xx Andre Heider
2017-12-06 11:50 ` Gregory CLEMENT
2017-12-06 14:08 ` Andre Heider
2017-12-18 17:03 ` Gregory CLEMENT
2017-12-21 7:45 ` Andre Heider
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.