Loading arch/arm64/configs/kitakami_suzuran_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -649,3 +649,4 @@ CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y CONFIG_QMI_ENCDEC=y CONFIG_STRICT_MEMORY_RWX=y CONFIG_CPU_VOLTAGE_CONTROL=y drivers/clk/qcom/clock-cpu-8994.c +83 −0 Original line number Diff line number Diff line Loading @@ -1084,6 +1084,89 @@ static struct mux_clk cpu_debug_mux = { }, }; #ifdef CONFIG_CPU_VOLTAGE_CONTROL extern int cpr_regulator_get_corner_voltage(struct regulator *regulator, int corner); extern int cpr_regulator_set_corner_voltage(struct regulator *regulator, int corner, int volt); ssize_t cpu_clock_get_vdd(char *buf) { ssize_t count = 0; int i, uv; if (!buf) return 0; for (i = 1; i < a53_clk.c.num_fmax; i++) { uv = cpr_regulator_get_corner_voltage( a53_clk.c.vdd_class->regulator[0], a53_clk.c.vdd_class->vdd_uv[i]); if (uv < 0) return 0; count += sprintf(buf + count, "A53: %lumhz: %d mV\n", a53_clk.c.fmax[i] / 1000000, uv / 1000); } for (i = 1; i < a57_clk.c.num_fmax; i++) { uv = cpr_regulator_get_corner_voltage( a57_clk.c.vdd_class->regulator[0], a57_clk.c.vdd_class->vdd_uv[i]); if (uv < 0) return 0; count += sprintf(buf + count, "A57: %lumhz: %d mV\n", a57_clk.c.fmax[i] / 1000000, uv / 1000); } return count; } ssize_t cpu_clock_set_vdd(const char *buf, size_t count) { int i, mv, ret; char line[32]; if (!buf) return -EINVAL; for (i = 1; i < a53_clk.c.num_fmax; i++) { ret = sscanf(buf, "%d", &mv); if (ret != 1) return -EINVAL; ret = cpr_regulator_set_corner_voltage( a53_clk.c.vdd_class->regulator[0], a53_clk.c.vdd_class->vdd_uv[i], mv * 1000); if (ret < 0) return ret; ret = sscanf(buf, "%s", line); buf += strlen(line) + 1; } for (i = 1; i < a57_clk.c.num_fmax; i++) { ret = sscanf(buf, "%d", &mv); if (ret != 1) return -EINVAL; ret = cpr_regulator_set_corner_voltage( a57_clk.c.vdd_class->regulator[0], a57_clk.c.vdd_class->vdd_uv[i], mv * 1000); if (ret < 0) return ret; ret = sscanf(buf, "%s", line); buf += strlen(line) + 1; } return count; } #endif static struct clk *logical_cpu_to_clk(int cpu) { struct device_node *cpu_node = of_get_cpu_node(cpu, NULL); Loading drivers/cpufreq/cpufreq.c +23 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <linux/slab.h> #include <linux/syscore_ops.h> #include <linux/tick.h> #include <linux/pm_opp.h> #include <trace/events/power.h> /** Loading Loading @@ -633,6 +634,22 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); } #ifdef CONFIG_CPU_VOLTAGE_CONTROL extern ssize_t cpu_clock_get_vdd(char *buf); extern ssize_t cpu_clock_set_vdd(const char *buf, size_t count); static ssize_t show_UV_mV_table(struct cpufreq_policy *policy, char *buf) { return cpu_clock_get_vdd(buf); } static ssize_t store_UV_mV_table(struct cpufreq_policy *policy, const char *buf, size_t count) { return cpu_clock_set_vdd(buf, count); } #endif cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); cpufreq_freq_attr_ro(cpuinfo_min_freq); cpufreq_freq_attr_ro(cpuinfo_max_freq); Loading @@ -647,6 +664,9 @@ cpufreq_freq_attr_rw(scaling_min_freq); cpufreq_freq_attr_rw(scaling_max_freq); cpufreq_freq_attr_rw(scaling_governor); cpufreq_freq_attr_rw(scaling_setspeed); #ifdef CONFIG_CPU_VOLTAGE_CONTROL cpufreq_freq_attr_rw(UV_mV_table); #endif static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, Loading @@ -660,6 +680,9 @@ static struct attribute *default_attrs[] = { &scaling_driver.attr, &scaling_available_governors.attr, &scaling_setspeed.attr, #ifdef CONFIG_CPU_VOLTAGE_CONTROL &UV_mV_table.attr, #endif NULL }; Loading drivers/regulator/Kconfig +6 −0 Original line number Diff line number Diff line Loading @@ -629,5 +629,11 @@ config SOMC_LCD_OCP_ENABLED bool "enable SoMC LCD OCP function" help Select this to enable SoMC LCD Over current protection function. config CPU_VOLTAGE_CONTROL bool "Enable CPU voltage control" help Enable CPU voltage control for MSM8994. endif drivers/regulator/cpr-regulator.c +30 −0 Original line number Diff line number Diff line Loading @@ -1096,6 +1096,36 @@ static struct regulator_ops cpr_corner_ops = { .get_voltage = cpr_regulator_get_voltage, }; #ifdef CONFIG_CPU_VOLTAGE_CONTROL int cpr_regulator_get_corner_voltage(struct regulator *regulator, int corner) { struct cpr_regulator *cpr_vreg = regulator_get_drvdata(regulator); if (corner >= CPR_CORNER_MIN && corner <= cpr_vreg->num_corners) return cpr_vreg->last_volt[corner]; return -EINVAL; } int cpr_regulator_set_corner_voltage(struct regulator *regulator, int corner, int volt) { struct cpr_regulator *cpr_vreg = regulator_get_drvdata(regulator); if (corner >= CPR_CORNER_MIN && corner <= cpr_vreg->num_corners) { mutex_lock(&cpr_vreg->cpr_mutex); cpr_vreg->last_volt[corner] = volt; cpr_vreg->ceiling_volt[corner] = volt; cpr_vreg->floor_volt[corner] = volt - 200000; mutex_unlock(&cpr_vreg->cpr_mutex); return 0; } return -EINVAL; } #endif #ifdef CONFIG_PM static int cpr_suspend(struct cpr_regulator *cpr_vreg) { Loading Loading
arch/arm64/configs/kitakami_suzuran_defconfig +1 −0 Original line number Diff line number Diff line Loading @@ -649,3 +649,4 @@ CONFIG_CRYPTO_AES_ARM64_CE_BLK=y CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y CONFIG_QMI_ENCDEC=y CONFIG_STRICT_MEMORY_RWX=y CONFIG_CPU_VOLTAGE_CONTROL=y
drivers/clk/qcom/clock-cpu-8994.c +83 −0 Original line number Diff line number Diff line Loading @@ -1084,6 +1084,89 @@ static struct mux_clk cpu_debug_mux = { }, }; #ifdef CONFIG_CPU_VOLTAGE_CONTROL extern int cpr_regulator_get_corner_voltage(struct regulator *regulator, int corner); extern int cpr_regulator_set_corner_voltage(struct regulator *regulator, int corner, int volt); ssize_t cpu_clock_get_vdd(char *buf) { ssize_t count = 0; int i, uv; if (!buf) return 0; for (i = 1; i < a53_clk.c.num_fmax; i++) { uv = cpr_regulator_get_corner_voltage( a53_clk.c.vdd_class->regulator[0], a53_clk.c.vdd_class->vdd_uv[i]); if (uv < 0) return 0; count += sprintf(buf + count, "A53: %lumhz: %d mV\n", a53_clk.c.fmax[i] / 1000000, uv / 1000); } for (i = 1; i < a57_clk.c.num_fmax; i++) { uv = cpr_regulator_get_corner_voltage( a57_clk.c.vdd_class->regulator[0], a57_clk.c.vdd_class->vdd_uv[i]); if (uv < 0) return 0; count += sprintf(buf + count, "A57: %lumhz: %d mV\n", a57_clk.c.fmax[i] / 1000000, uv / 1000); } return count; } ssize_t cpu_clock_set_vdd(const char *buf, size_t count) { int i, mv, ret; char line[32]; if (!buf) return -EINVAL; for (i = 1; i < a53_clk.c.num_fmax; i++) { ret = sscanf(buf, "%d", &mv); if (ret != 1) return -EINVAL; ret = cpr_regulator_set_corner_voltage( a53_clk.c.vdd_class->regulator[0], a53_clk.c.vdd_class->vdd_uv[i], mv * 1000); if (ret < 0) return ret; ret = sscanf(buf, "%s", line); buf += strlen(line) + 1; } for (i = 1; i < a57_clk.c.num_fmax; i++) { ret = sscanf(buf, "%d", &mv); if (ret != 1) return -EINVAL; ret = cpr_regulator_set_corner_voltage( a57_clk.c.vdd_class->regulator[0], a57_clk.c.vdd_class->vdd_uv[i], mv * 1000); if (ret < 0) return ret; ret = sscanf(buf, "%s", line); buf += strlen(line) + 1; } return count; } #endif static struct clk *logical_cpu_to_clk(int cpu) { struct device_node *cpu_node = of_get_cpu_node(cpu, NULL); Loading
drivers/cpufreq/cpufreq.c +23 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include <linux/slab.h> #include <linux/syscore_ops.h> #include <linux/tick.h> #include <linux/pm_opp.h> #include <trace/events/power.h> /** Loading Loading @@ -633,6 +634,22 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); } #ifdef CONFIG_CPU_VOLTAGE_CONTROL extern ssize_t cpu_clock_get_vdd(char *buf); extern ssize_t cpu_clock_set_vdd(const char *buf, size_t count); static ssize_t show_UV_mV_table(struct cpufreq_policy *policy, char *buf) { return cpu_clock_get_vdd(buf); } static ssize_t store_UV_mV_table(struct cpufreq_policy *policy, const char *buf, size_t count) { return cpu_clock_set_vdd(buf, count); } #endif cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); cpufreq_freq_attr_ro(cpuinfo_min_freq); cpufreq_freq_attr_ro(cpuinfo_max_freq); Loading @@ -647,6 +664,9 @@ cpufreq_freq_attr_rw(scaling_min_freq); cpufreq_freq_attr_rw(scaling_max_freq); cpufreq_freq_attr_rw(scaling_governor); cpufreq_freq_attr_rw(scaling_setspeed); #ifdef CONFIG_CPU_VOLTAGE_CONTROL cpufreq_freq_attr_rw(UV_mV_table); #endif static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, Loading @@ -660,6 +680,9 @@ static struct attribute *default_attrs[] = { &scaling_driver.attr, &scaling_available_governors.attr, &scaling_setspeed.attr, #ifdef CONFIG_CPU_VOLTAGE_CONTROL &UV_mV_table.attr, #endif NULL }; Loading
drivers/regulator/Kconfig +6 −0 Original line number Diff line number Diff line Loading @@ -629,5 +629,11 @@ config SOMC_LCD_OCP_ENABLED bool "enable SoMC LCD OCP function" help Select this to enable SoMC LCD Over current protection function. config CPU_VOLTAGE_CONTROL bool "Enable CPU voltage control" help Enable CPU voltage control for MSM8994. endif
drivers/regulator/cpr-regulator.c +30 −0 Original line number Diff line number Diff line Loading @@ -1096,6 +1096,36 @@ static struct regulator_ops cpr_corner_ops = { .get_voltage = cpr_regulator_get_voltage, }; #ifdef CONFIG_CPU_VOLTAGE_CONTROL int cpr_regulator_get_corner_voltage(struct regulator *regulator, int corner) { struct cpr_regulator *cpr_vreg = regulator_get_drvdata(regulator); if (corner >= CPR_CORNER_MIN && corner <= cpr_vreg->num_corners) return cpr_vreg->last_volt[corner]; return -EINVAL; } int cpr_regulator_set_corner_voltage(struct regulator *regulator, int corner, int volt) { struct cpr_regulator *cpr_vreg = regulator_get_drvdata(regulator); if (corner >= CPR_CORNER_MIN && corner <= cpr_vreg->num_corners) { mutex_lock(&cpr_vreg->cpr_mutex); cpr_vreg->last_volt[corner] = volt; cpr_vreg->ceiling_volt[corner] = volt; cpr_vreg->floor_volt[corner] = volt - 200000; mutex_unlock(&cpr_vreg->cpr_mutex); return 0; } return -EINVAL; } #endif #ifdef CONFIG_PM static int cpr_suspend(struct cpr_regulator *cpr_vreg) { Loading