From fbdb31e061b67941342fc5afa714488f75174632 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Thu, 31 May 2018 19:08:12 +0100 Subject: [PATCH 1/3] bcm2835: cpufreq: add CPU frequency control driver Signed-off-by: Peter Robinson --- arch/arm/boot/dts/bcm2835-rpi.dtsi | 7 ++ arch/arm/boot/dts/bcm2837.dtsi | 33 +++++++ drivers/clk/bcm/Kconfig | 8 ++ drivers/clk/bcm/Makefile | 1 + drivers/clk/bcm/clk-raspberrypi.c | 138 +++++++++++++++++++++++++++++ 5 files changed, 187 insertions(+) create mode 100644 drivers/clk/bcm/clk-raspberrypi.c diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi index 29f970f864dc..6d0f43957af4 100644 --- a/arch/arm/boot/dts/bcm2835-rpi.dtsi +++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi @@ -35,6 +35,13 @@ reg = <0x7e00b840 0x3c>; interrupts = <0 2>; }; + + arm_clk: arm_clk { + compatible = "raspberrypi,bcm2835-cpu"; + clocks = <&clocks BCM2835_CLOCK_VPU>; + #clock-cells = <0>; + clock-output-names = "arm"; + }; }; }; diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi index beb6c502dadc..9cfc553a3633 100644 --- a/arch/arm/boot/dts/bcm2837.dtsi +++ b/arch/arm/boot/dts/bcm2837.dtsi @@ -44,6 +44,9 @@ reg = <0>; enable-method = "spin-table"; cpu-release-addr = <0x0 0x000000d8>; + clocks = <&arm_clk>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; }; cpu1: cpu@1 { @@ -52,6 +55,9 @@ reg = <1>; enable-method = "spin-table"; cpu-release-addr = <0x0 0x000000e0>; + clocks = <&arm_clk>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; }; cpu2: cpu@2 { @@ -60,6 +66,9 @@ reg = <2>; enable-method = "spin-table"; cpu-release-addr = <0x0 0x000000e8>; + clocks = <&arm_clk>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; }; cpu3: cpu@3 { @@ -68,6 +77,30 @@ reg = <3>; enable-method = "spin-table"; cpu-release-addr = <0x0 0x000000f0>; + clocks = <&arm_clk>; + clock-names = "cpu"; + operating-points-v2 = <&cpu0_opp_table>; + }; + }; + + cpu0_opp_table: opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + + opp@600000000 { + opp-hz = /bits/ 64 <600000000>; + clock-latency-ns = <355000>; + opp-suspend; + }; + + opp@900000000 { + opp-hz = /bits/ 64 <900000000>; + clock-latency-ns = <355000>; + }; + + opp@1200000000 { + opp-hz = /bits/ 64 <1200000000>; + clock-latency-ns = <355000>; }; }; }; diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig index 4c4bd85f707c..e40bd19da22b 100644 --- a/drivers/clk/bcm/Kconfig +++ b/drivers/clk/bcm/Kconfig @@ -63,3 +63,11 @@ config CLK_BCM_SR default ARCH_BCM_IPROC help Enable common clock framework support for the Broadcom Stingray SoC + +config CLK_RASPBERRYPI_CPU + bool "Raspberry Pi CPU clock driver" + depends on ARCH_BCM2835 || (COMPILE_TEST && OF) + depends on RASPBERRYPI_FIRMWARE=y + help + This enables support for the RPi CPU clock which can be adjusted + via the RPi firmware. diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile index 002661d39128..a028b0a90b6e 100644 --- a/drivers/clk/bcm/Makefile +++ b/drivers/clk/bcm/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-a obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835-aux.o obj-$(CONFIG_ARCH_BCM_53573) += clk-bcm53573-ilp.o +obj-$(CONFIG_CLK_RASPBERRYPI_CPU) += clk-raspberrypi.o obj-$(CONFIG_CLK_BCM_CYGNUS) += clk-cygnus.o obj-$(CONFIG_CLK_BCM_HR2) += clk-hr2.o obj-$(CONFIG_CLK_BCM_NSP) += clk-nsp.o diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c new file mode 100644 index 000000000000..046efc822a59 --- /dev/null +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Raspberry Pi CPU clock driver + * + * Copyright (C) 2018 Stefan Wahren + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define VCMSG_ID_ARM_CLOCK 0x000000003 /* Clock/Voltage ID's */ + +struct rpi_cpu_clkgen { + struct clk_hw hw; + struct rpi_firmware *fw; +}; + +/* tag part of the message */ +struct prop { + u32 id; /* the ID of the clock/voltage to get or set */ + u32 val; /* the value (e.g. rate (in Hz)) to set */ +} __packed; + +static int rpi_cpu_clock_property(struct rpi_firmware *fw, u32 tag, u32 *val) +{ + int ret; + struct prop msg = { + .id = VCMSG_ID_ARM_CLOCK, + .val = *val, + }; + + ret = rpi_firmware_property(fw, tag, &msg, sizeof(msg)); + if (ret) + return ret; + + *val = msg.val; + + return 0; +} + +static unsigned long rpi_cpu_get_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct rpi_cpu_clkgen *cpu = container_of(hw, struct rpi_cpu_clkgen, hw); + u32 rate = 0; + + rpi_cpu_clock_property(cpu->fw, RPI_FIRMWARE_GET_CLOCK_RATE, &rate); + + return rate; +} + +static long rpi_cpu_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + return rate; +} + +static int rpi_cpu_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct rpi_cpu_clkgen *cpu = container_of(hw, struct rpi_cpu_clkgen, hw); + u32 new_rate = rate; + + return rpi_cpu_clock_property(cpu->fw, RPI_FIRMWARE_SET_CLOCK_RATE, + &new_rate); +} + +static const struct clk_ops rpi_cpu_ops = { + .recalc_rate = rpi_cpu_get_rate, + .round_rate = rpi_cpu_round_rate, + .set_rate = rpi_cpu_set_rate, +}; + +static int rpi_cpu_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *fw_node; + struct rpi_cpu_clkgen *cpu; + struct clk_init_data *init; + int ret; + + cpu = devm_kzalloc(dev, sizeof(*cpu), GFP_KERNEL); + if (!cpu) + return -ENOMEM; + + init = devm_kzalloc(dev, sizeof(*init), GFP_KERNEL); + if (!init) + return -ENOMEM; + + fw_node = of_find_compatible_node(NULL, NULL, + "raspberrypi,bcm2835-firmware"); + if (!fw_node) { + dev_err(dev, "Missing firmware node\n"); + return -ENOENT; + } + + cpu->fw = rpi_firmware_get(fw_node); + of_node_put(fw_node); + if (!cpu->fw) + return -EPROBE_DEFER; + + init->name = dev->of_node->name; + init->ops = &rpi_cpu_ops; + + cpu->hw.init = init; + ret = devm_clk_hw_register(dev, &cpu->hw); + if (ret) + return ret; + + return of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, + &cpu->hw); +} + +static const struct of_device_id rpi_cpu_of_match[] = { + { .compatible = "raspberrypi,bcm2835-cpu", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rpi_cpu_of_match); + +static struct platform_driver rpi_cpu_driver = { + .driver = { + .name = "raspberrypi-cpu", + .of_match_table = rpi_cpu_of_match, + }, + .probe = rpi_cpu_probe, +}; +builtin_platform_driver(rpi_cpu_driver); + +MODULE_AUTHOR("Stefan Wahren "); +MODULE_DESCRIPTION("Raspberry Pi CPU clock driver"); +MODULE_LICENSE("GPL v2"); -- 2.20.1 From 0681db63db37cf9015ef9b667c237c3974de04e6 Mon Sep 17 00:00:00 2001 From: Peter Robinson Date: Mon, 4 Jun 2018 09:14:10 +0100 Subject: [PATCH 2/3] add 1.4 ghz OPP for the 3B+ Signed-off-by: Peter Robinson --- arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts index 42bb09044cc7..3333c080696c 100644 --- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts +++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts @@ -106,3 +106,10 @@ pinctrl-0 = <&uart1_gpio14>; status = "okay"; }; + +&cpu0_opp_table { + opp@1400000000 { + opp-hz = /bits/ 64 <1400000000>; + clock-latency-ns = <355000>; + }; +}; -- 2.20.1 From 65f821f03ac635f28c8c79c5e436b398194521f2 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Wed, 26 Sep 2018 21:13:22 +0200 Subject: [PATCH 3/3] ARM: bcm2837: Use CPU0 as cooling device Signed-off-by: Stefan Wahren --- arch/arm/boot/dts/bcm2837.dtsi | 25 +++++++++++++++++++++++++ arch/arm/boot/dts/bcm283x.dtsi | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi index 9cfc553a3633..1590d94b618e 100644 --- a/arch/arm/boot/dts/bcm2837.dtsi +++ b/arch/arm/boot/dts/bcm2837.dtsi @@ -1,4 +1,5 @@ #include "bcm283x.dtsi" +#include / { compatible = "brcm,bcm2837"; @@ -47,6 +48,7 @@ clocks = <&arm_clk>; clock-names = "cpu"; operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; }; cpu1: cpu@1 { @@ -58,6 +60,7 @@ clocks = <&arm_clk>; clock-names = "cpu"; operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; }; cpu2: cpu@2 { @@ -69,6 +72,7 @@ clocks = <&arm_clk>; clock-names = "cpu"; operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; }; cpu3: cpu@3 { @@ -80,6 +84,7 @@ clocks = <&arm_clk>; clock-names = "cpu"; operating-points-v2 = <&cpu0_opp_table>; + #cooling-cells = <2>; }; }; @@ -117,6 +122,26 @@ &cpu_thermal { coefficients = <(-538) 412000>; + + trips { + cpu_alert0: cpu-alert0 { + temperature = <70000>; + hysteresis = <0>; + type = "passive"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_alert0>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + + map1 { + trip = <&cpu_crit>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; }; /* enable thermal sensor with the correct compatible property set */ diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi index 31b29646b14c..2def0684d198 100644 --- a/arch/arm/boot/dts/bcm283x.dtsi +++ b/arch/arm/boot/dts/bcm283x.dtsi @@ -38,7 +38,7 @@ thermal-sensors = <&thermal>; trips { - cpu-crit { + cpu_crit: cpu-crit { temperature = <80000>; hysteresis = <0>; type = "critical"; -- 2.20.1