From 2a780f9beb260cf811071d4073b20d1288cdd072 Mon Sep 17 00:00:00 2001 From: Jianxin Pan Date: Wed, 15 Feb 2017 14:26:11 +0800 Subject: [PATCH] cpufreq: enable scpi cpufreq PD#138714: add scpi_cpufreq Change-Id: Iaf90f7573657593f21200fed48209a2758fa189a Signed-off-by: Jianxin Pan --- MAINTAINERS | 4 + arch/arm64/boot/dts/amlogic/mesongxl.dtsi | 25 +- arch/arm64/boot/dts/amlogic/mesongxm.dtsi | 28 +- arch/arm64/configs/meson64_defconfig | 2 + drivers/amlogic/clk/Kconfig | 10 + drivers/amlogic/clk/Makefile | 1 + drivers/amlogic/clk/clk-scpi.c | 314 ++++++++++++++++++++++ drivers/cpufreq/Kconfig.arm | 2 +- drivers/cpufreq/arm_big_little.c | 27 +- drivers/cpufreq/scpi-cpufreq.c | 17 +- 10 files changed, 419 insertions(+), 11 deletions(-) create mode 100644 drivers/amlogic/clk/clk-scpi.c diff --git a/MAINTAINERS b/MAINTAINERS index b30db2e92531..76071f46598d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13481,3 +13481,7 @@ F: include/linux/amlogic/usb-gxbbtv.h F: include/linux/amlogic/usb-gxl.h F: include/linux/amlogic/usb-gxbb.h F: include/linux/amlogic/usbtype.h + +AMLOGIC scpi cpufreq +M: jianxin.pan +F: drivers/amlogic/clk/clk-scpi.c diff --git a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi index d81e02d00916..466c172416f5 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxl.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxl.dtsi @@ -45,6 +45,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; + clocks = <&scpi_dvfs 0>; + clock-names = "cpu-cluster.0"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -53,6 +55,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x1>; enable-method = "psci"; + clocks = <&scpi_dvfs 0>; + clock-names = "cpu-cluster.0"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU2:cpu@2 { @@ -60,6 +64,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x2>; enable-method = "psci"; + clocks = <&scpi_dvfs 0>; + clock-names = "cpu-cluster.0"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -68,6 +74,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x3>; enable-method = "psci"; + clocks = <&scpi_dvfs 0>; + clock-names = "cpu-cluster.0"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -174,13 +182,25 @@ compatible = "amlogic, meson_mhu"; reg = <0x0 0xc883c400 0x0 0x4c>, /* MHU registers */ <0x0 0xc8013000 0x0 0x800>; /* Payload area */ - interrupts = <0 209 8>, /* low priority interrupt */ - <0 210 8>; /* high priority interrupt */ + interrupts = <0 209 1>, /* low priority interrupt */ + <0 210 1>; /* high priority interrupt */ #mbox-cells = <1>; mbox-names = "cpu_to_scp_low", "cpu_to_scp_high"; mboxes = <&mailbox 0 &mailbox 1>; }; + scpi_clocks { + compatible = "arm, scpi-clks"; + + scpi_dvfs: scpi_clocks@0 { + compatible = "arm, scpi-clk-indexed"; + #clock-cells = <1>; + clock-indices = <0>; + clock-output-names = "vcpu"; + }; + + }; + xtal: xtal-clk { compatible = "fixed-clock"; clock-frequency = <24000000>; @@ -358,7 +378,6 @@ "jtag_clk_0", "jtag_tms_0"; function = "jtag"; - bias-pull-down; }; }; diff --git a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi index f5bfdcaaec7f..8c5b5f094c32 100644 --- a/arch/arm64/boot/dts/amlogic/mesongxm.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesongxm.dtsi @@ -60,6 +60,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x0>; enable-method = "psci"; + clocks = <&scpi_dvfs 0>; + clock-names = "cpu-cluster.0"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -68,6 +70,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x1>; enable-method = "psci"; + clocks = <&scpi_dvfs 0>; + clock-names = "cpu-cluster.0"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU2:cpu@2 { @@ -75,6 +79,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x2>; enable-method = "psci"; + clocks = <&scpi_dvfs 0>; + clock-names = "cpu-cluster.0"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -83,6 +89,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x3>; enable-method = "psci"; + clocks = <&scpi_dvfs 0>; + clock-names = "cpu-cluster.0"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -91,6 +99,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x100>; enable-method = "psci"; + clocks = <&scpi_dvfs 1>; + clock-names = "cpu-cluster.1"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -99,6 +109,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x101>; enable-method = "psci"; + clocks = <&scpi_dvfs 1>; + clock-names = "cpu-cluster.1"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; CPU6:cpu@102 { @@ -106,6 +118,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x102>; enable-method = "psci"; + clocks = <&scpi_dvfs 1>; + clock-names = "cpu-cluster.1"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -114,6 +128,8 @@ compatible = "arm,cortex-a53","arm,armv8"; reg = <0x0 0x103>; enable-method = "psci"; + clocks = <&scpi_dvfs 1>; + clock-names = "cpu-cluster.1"; cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; }; @@ -226,6 +242,17 @@ mboxes = <&mailbox 0 &mailbox 1>; }; + scpi_clocks { + compatible = "arm, scpi-clks"; + + scpi_dvfs: scpi_clocks@0 { + compatible = "arm, scpi-clk-indexed"; + #clock-cells = <1>; + clock-indices = <0 1>; + clock-output-names = "vbig", "vlittle"; + }; + + }; xtal: xtal-clk { compatible = "fixed-clock"; clock-frequency = <24000000>; @@ -403,7 +430,6 @@ "jtag_clk_0", "jtag_tms_0"; function = "jtag"; - bias-pull-down; }; }; diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 00b0073f707f..e43cdd6a3db0 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -31,6 +31,7 @@ CONFIG_COMPAT=y CONFIG_CPU_IDLE=y CONFIG_CPU_FREQ=y CONFIG_ARM_BIG_LITTLE_CPUFREQ=y +CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_PACKET_DIAG=y @@ -173,6 +174,7 @@ CONFIG_AMLOGIC_REG_ACCESS=y CONFIG_AMLOGIC_TIMER=y CONFIG_AMLOGIC_BC_TIMER=y CONFIG_AMLOGIC_CLK=y +CONFIG_AMLOGIC_COMMON_CLK_SCPI=y CONFIG_AMLOGIC_CRYPTO=y CONFIG_AMLOGIC_INPUT=y CONFIG_AMLOGIC_INPUT_KEYBOARD=y diff --git a/drivers/amlogic/clk/Kconfig b/drivers/amlogic/clk/Kconfig index 0e123f69f5dc..8d0d1dff11f9 100644 --- a/drivers/amlogic/clk/Kconfig +++ b/drivers/amlogic/clk/Kconfig @@ -13,3 +13,13 @@ config AMLOGIC_RESET default AMLOGIC_CLK help This enables the reset driver for Amlogic Meson SoCs. + +config AMLOGIC_COMMON_CLK_SCPI + tristate "Clock driver controlled via SCPI interface" + depends on ARM_SCPI_PROTOCOL || COMPILE_TEST + ---help--- + This driver provides support for clocks that are controlled + by firmware that implements the SCPI interface. + + This driver uses SCPI Message Protocol to interact with the + firmware providing all the clock controls. \ No newline at end of file diff --git a/drivers/amlogic/clk/Makefile b/drivers/amlogic/clk/Makefile index f1272dcd32cd..e0660a1b6479 100644 --- a/drivers/amlogic/clk/Makefile +++ b/drivers/amlogic/clk/Makefile @@ -2,6 +2,7 @@ # Makefile for Meson specific clk # +obj-$(CONFIG_AMLOGIC_COMMON_CLK_SCPI) += clk-scpi.o obj-$(CONFIG_AMLOGIC_RESET) += rstc.o obj-$(CONFIG_AMLOGIC_CLK) += clk-pll.o clk-cpu.o clk-mpll.o \ diff --git a/drivers/amlogic/clk/clk-scpi.c b/drivers/amlogic/clk/clk-scpi.c new file mode 100644 index 000000000000..33294d51b373 --- /dev/null +++ b/drivers/amlogic/clk/clk-scpi.c @@ -0,0 +1,314 @@ +/* + * drivers/amlogic/clk/clk-scpi.c + * + * Copyright (C) 2017 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +struct scpi_clk { + u32 id; + const char *name; + struct clk_hw hw; + struct scpi_dvfs_info *opps; + unsigned long rate_min; + unsigned long rate_max; +}; + +static struct platform_device *cpufreq_dev; +#define to_scpi_clk(clk) container_of(clk, struct scpi_clk, hw) + +static unsigned long scpi_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + + return scpi_clk_get_val(clk->id); +} + +static long scpi_clk_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + + if (clk->rate_min && rate < clk->rate_min) + rate = clk->rate_min; + if (clk->rate_max && rate > clk->rate_max) + rate = clk->rate_max; + + return rate; +} + +static int scpi_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + + return scpi_clk_set_val(clk->id, rate); +} + +static const struct clk_ops scpi_clk_ops = { + .recalc_rate = scpi_clk_recalc_rate, + .round_rate = scpi_clk_round_rate, + .set_rate = scpi_clk_set_rate, +}; + +/* find closest match to given frequency in OPP table */ +static int __scpi_dvfs_round_rate(struct scpi_clk *clk, unsigned long rate) +{ + int idx, max_opp = clk->opps->count; + struct scpi_opp_entry *opp = clk->opps->opp; + u32 fmin = 0, fmax = ~0, ftmp; + + for (idx = 0; idx < max_opp; idx++, opp++) { + ftmp = opp->freq_hz; + if (ftmp >= (u32)rate) { + if (ftmp <= fmax) + fmax = ftmp; + } else { + if (ftmp >= fmin) + fmin = ftmp; + } + } + if (fmax != ~0) + return fmax; + else + return fmin; +} + +static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + int idx = scpi_dvfs_get_idx(clk->id); + struct scpi_opp_entry *opp = clk->opps->opp; + + if (idx < 0) + return 0; + else + return opp[idx].freq_hz; +} + +static long scpi_dvfs_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + + return __scpi_dvfs_round_rate(clk, rate); +} + +static int __scpi_find_dvfs_index(struct scpi_clk *clk, unsigned long rate) +{ + int idx, max_opp = clk->opps->count; + struct scpi_opp_entry *opp = clk->opps->opp; + + for (idx = 0; idx < max_opp; idx++, opp++) + if (opp->freq_hz == (u32)rate) + break; + return (idx == max_opp) ? -EINVAL : idx; +} + +static int scpi_dvfs_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct scpi_clk *clk = to_scpi_clk(hw); + int ret = __scpi_find_dvfs_index(clk, rate); + + if (ret < 0) + return ret; + else + return scpi_dvfs_set_idx(clk->id, (u8)ret); +} + +static const struct clk_ops scpi_dvfs_ops = { + .recalc_rate = scpi_dvfs_recalc_rate, + .round_rate = scpi_dvfs_round_rate, + .set_rate = scpi_dvfs_set_rate, +}; + +static struct clk * +scpi_dvfs_ops_init(struct device *dev, struct device_node *np, + struct scpi_clk *sclk) +{ + struct clk_init_data init; + struct scpi_dvfs_info *opps; + + init.name = sclk->name; + init.flags = 0; + init.num_parents = 0; + init.ops = &scpi_dvfs_ops; + sclk->hw.init = &init; + + opps = scpi_dvfs_get_opps(sclk->id); + if (IS_ERR(opps)) + return (struct clk *)opps; + + sclk->opps = opps; + + return devm_clk_register(dev, &sclk->hw); +} + +static struct clk * +scpi_clk_ops_init(struct device *dev, struct device_node *np, + struct scpi_clk *sclk) +{ + struct clk_init_data init; + u32 range[2]; + int ret; + + init.name = sclk->name; + init.flags = 0; + init.num_parents = 0; + init.ops = &scpi_clk_ops; + sclk->hw.init = &init; + + ret = of_property_read_u32_array(np, "frequency-range", range, + ARRAY_SIZE(range)); + if (ret) + return ERR_PTR(ret); + sclk->rate_min = range[0]; + sclk->rate_max = range[1]; + + return devm_clk_register(dev, &sclk->hw); +} + +static int scpi_clk_setup(struct device *dev, struct device_node *np, + const void *data) +{ + struct clk * (*setup_ops)(struct device *, struct device_node *, + struct scpi_clk *) = data; + struct clk_onecell_data *clk_data; + struct clk **clks; + size_t count; + int idx; + + count = of_property_count_strings(np, "clock-output-names"); + if (count < 0) { + dev_err(dev, "%s: invalid clock output count\n", np->name); + return -EINVAL; + } + + clk_data = devm_kmalloc(dev, sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clks = devm_kmalloc(dev, count * sizeof(*clks), GFP_KERNEL); + if (!clks) + return -ENOMEM; + + for (idx = 0; idx < count; idx++) { + struct scpi_clk *sclk; + u32 val; + + sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL); + if (!sclk) + return -ENOMEM; + + if (of_property_read_string_index(np, "clock-output-names", + idx, &sclk->name)) { + dev_err(dev, "invalid clock name @ %s\n", np->name); + return -EINVAL; + } + + if (of_property_read_u32_index(np, "clock-indices", + idx, &val)) { + dev_err(dev, "invalid clock index @ %s\n", np->name); + return -EINVAL; + } + + sclk->id = val; + + clks[idx] = setup_ops(dev, np, sclk); + if (IS_ERR(clks[idx])) { + dev_err(dev, "failed to register clock '%s'\n", + sclk->name); + return PTR_ERR(clks[idx]); + } + + dev_dbg(dev, "Registered clock '%s'\n", sclk->name); + } + + clk_data->clks = clks; + clk_data->clk_num = count; + of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); + + return 0; +} + +static const struct of_device_id clk_match[] = { + { .compatible = "arm, scpi-clk-indexed", .data = scpi_dvfs_ops_init, }, + { .compatible = "arm, scpi-clk-range", .data = &scpi_clk_ops_init, }, + {} +}; + +static int scpi_clk_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node, *child; + const struct of_device_id *match; + int ret; + + for_each_child_of_node(np, child) { + match = of_match_node(clk_match, child); + if (!match) + continue; + ret = scpi_clk_setup(dev, child, match->data); + if (ret) + return ret; + } + /* Add the virtual cpufreq device */ + cpufreq_dev = platform_device_register_simple("scpi-cpufreq", + -1, NULL, 0); + if (!cpufreq_dev) + pr_warn("unable to register cpufreq device"); + + return 0; +} + +static const struct of_device_id scpi_clk_ids[] = { + { .compatible = "arm, scpi-clks", }, + {} +}; + +static struct platform_driver scpi_clk_driver = { + .driver = { + .name = "aml_scpi_clocks", + .of_match_table = scpi_clk_ids, + }, + .probe = scpi_clk_probe, +}; + +static int __init scpi_clk_init(void) +{ + return platform_driver_register(&scpi_clk_driver); +} +postcore_initcall(scpi_clk_init); + +static void __exit scpi_clk_exit(void) +{ + platform_driver_unregister(&scpi_clk_driver); +} +module_exit(scpi_clk_exit); + +MODULE_AUTHOR("Sudeep Holla "); +MODULE_DESCRIPTION("ARM SCPI clock driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index d89b8afe23b6..b2c75301f238 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -195,7 +195,7 @@ config ARM_SA1110_CPUFREQ config ARM_SCPI_CPUFREQ tristate "SCPI based CPUfreq driver" - depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI + depends on ARM_BIG_LITTLE_CPUFREQ && ARM_SCPI_PROTOCOL && (COMMON_CLK_SCPI || AMLOGIC_COMMON_CLK_SCPI) help This adds the CPUfreq driver support for ARM big.LITTLE platforms using SCPI protocol for CPU power management. diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 418042201e6d..2ccceacef1a5 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -134,7 +134,14 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate) int ret; bool bLs = is_bL_switching_enabled(); +#ifdef CONFIG_AMLOGIC_COMMON_CLK_SCPI + /* MARK: cluster0 and cluster share the same scpi lock, + * and don't send scpi command at the same time + */ + mutex_lock(&cluster_lock[0]); +#else mutex_lock(&cluster_lock[new_cluster]); +#endif if (bLs) { prev_rate = per_cpu(cpu_last_req_freq, cpu); @@ -172,12 +179,20 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate) per_cpu(physical_cluster, cpu) = old_cluster; } +#ifdef CONFIG_AMLOGIC_COMMON_CLK_SCPI + mutex_unlock(&cluster_lock[0]); +#else mutex_unlock(&cluster_lock[new_cluster]); +#endif return ret; } +#ifdef CONFIG_AMLOGIC_COMMON_CLK_SCPI + mutex_unlock(&cluster_lock[0]); +#else mutex_unlock(&cluster_lock[new_cluster]); +#endif /* Recalc freq for old cluster when switching clusters */ if (old_cluster != new_cluster) { @@ -187,7 +202,11 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate) /* Switch cluster */ bL_switch_request(cpu, new_cluster); - mutex_lock(&cluster_lock[old_cluster]); +#ifdef CONFIG_AMLOGIC_COMMON_CLK_SCPI + mutex_lock(&cluster_lock[0]); +#else + mutex_lock(&cluster_lock[new_cluster]); +#endif /* Set freq of old cluster if there are cpus left on it */ new_rate = find_cluster_maxfreq(old_cluster); @@ -201,7 +220,11 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate) pr_err("%s: clk_set_rate failed: %d, old cluster: %d\n", __func__, ret, old_cluster); } - mutex_unlock(&cluster_lock[old_cluster]); +#ifdef CONFIG_AMLOGIC_COMMON_CLK_SCPI + mutex_unlock(&cluster_lock[0]); +#else + mutex_unlock(&cluster_lock[new_cluster]); +#endif } return 0; diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index ea7a4e1b68c2..39206d14ba52 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -29,6 +29,7 @@ #include "arm_big_little.h" static struct scpi_ops *scpi_ops; +struct scpi_dvfs_info *scpi_dvfs_get_opps(u8 domain); static struct scpi_dvfs_info *scpi_get_dvfs_info(struct device *cpu_dev) { @@ -36,7 +37,12 @@ static struct scpi_dvfs_info *scpi_get_dvfs_info(struct device *cpu_dev) if (domain < 0) return ERR_PTR(-EINVAL); - return scpi_ops->dvfs_get_info(domain); + + /* TODO: Use API from 3.14 temporary. + * When 4.4 arm_mhu and arm_scpi is ported, + * tihs will be replaced by: return scpi_ops->dvfs_get_info(domain); + */ + return scpi_dvfs_get_opps(domain); } static int scpi_get_transition_latency(struct device *cpu_dev) @@ -88,9 +94,12 @@ static struct cpufreq_arm_bL_ops scpi_cpufreq_ops = { static int scpi_cpufreq_probe(struct platform_device *pdev) { - scpi_ops = get_scpi_ops(); - if (!scpi_ops) - return -EIO; + /* TODO: TODO: Use API from 3.14 temporary. + * When 4.4 arm_mhu and arm_scpi is ported, these lines should be added: + * scpi_ops = get_scpi_ops(); + * if (!scpi_ops) + * return -EIO; + */ return bL_cpufreq_register(&scpi_cpufreq_ops); }