522 lines
19 KiB
C

/*
* Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/tegra-soc.h>
#include <linux/tegra-dvfs.h>
#include <linux/clk/tegra124-dfll.h>
#include <linux/platform_data/tegra_thermal.h>
#include <linux/platform_data/tegra_emc.h>
#define KHZ 1000
#define MHZ 1000000
#define VDD_SAFE_STEP 100
static bool tegra_dvfs_cpu_disabled;
static bool tegra_dvfs_core_disabled;
static int cpu_millivolts[MAX_DVFS_FREQS];
static int cpu_dfll_millivolts[MAX_DVFS_FREQS];
static int vdd_core_therm_trips_table[MAX_THERMAL_LIMITS] = { 20, };
static int vdd_core_therm_floors_table[MAX_THERMAL_LIMITS] = { 900, };
static struct tegra_cooling_device core_vmin_cdev = {
.cdev_type = "core_cold",
};
static struct dvfs_rail tegra124_dvfs_rail_vdd_cpu = {
.reg_id = "vdd_cpu",
.max_millivolts = 1300,
.min_millivolts = 700,
.step = VDD_SAFE_STEP,
.jmp_to_zero = true,
.alignment = {
.step_uv = 10000, /* 10mV */
},
};
static struct dvfs_rail tegra124_dvfs_rail_vdd_core = {
.reg_id = "vdd_core",
.max_millivolts = 1400,
.min_millivolts = 800,
.step = VDD_SAFE_STEP,
.step_up = 1400,
.vmin_cdev = &core_vmin_cdev,
};
static struct dvfs_rail *tegra124_dvfs_rails[] = {
&tegra124_dvfs_rail_vdd_cpu,
&tegra124_dvfs_rail_vdd_core,
};
static struct dvfs cpu_dvfs = {
.clk_name = "cclk_g",
.millivolts = cpu_millivolts,
.dfll_millivolts = cpu_dfll_millivolts,
.auto_dvfs = true,
.dvfs_rail = &tegra124_dvfs_rail_vdd_cpu,
};
/* CPU DVFS tables */
static unsigned long cpu_max_freq[] = {
/* speedo_id 0 1 2 3 4 5 */
2014500, 2320500, 2116500, 2524500, 1811000, 2218500,
};
static struct cpu_dvfs cpu_fv_dvfs_table[] = {
{
.speedo_id = -1,
.process_id = -1,
.min_mv = 720,
.max_mv = 1260,
.fv_table = {
{204000, 800},
{306000, 800},
{408000, 800},
{510000, 800},
{612000, 800},
{714000, 800},
{816000, 820},
{918000, 840},
{1020000, 880},
{1122000, 900},
{1224000, 930},
{1326000, 960},
{1428000, 990},
{1530000, 1020},
{1632000, 1070},
{1734000, 1100},
{1836000, 1140},
{1938000, 1180},
{2014500, 1220},
{2116500, 1260},
{2218500, 1310},
{2320500, 1360},
{2422500, 1400},
{2524500, 1400},
},
},
};
/* Core DVFS tables */
static const int core_millivolts[MAX_DVFS_FREQS] = {
800, 850, 900, 950, 1000, 1050, 1100, 1150};
#define CORE_DVFS(_clk_name, _speedo_id, _process_id, _auto, _mult, _freqs...) \
{ \
.clk_name = _clk_name, \
.speedo_id = _speedo_id, \
.process_id = _process_id, \
.freqs = {_freqs}, \
.freqs_mult = _mult, \
.millivolts = core_millivolts, \
.auto_dvfs = _auto, \
.dvfs_rail = &tegra124_dvfs_rail_vdd_core, \
}
static struct dvfs core_dvfs_table[] = {
/* Core voltages (mV): 800, 850, 900, 950, 1000, 1050, 1100, 1150 */
/* Clock limits for internal blocks, PLLs */
CORE_DVFS("emc", -1, -1, 1, KHZ, 264000, 348000, 384000, 384000, 528000, 528000, 1200000, 1200000),
CORE_DVFS("cclk_lp", 0, 0, 1, KHZ, 312000, 528000, 660000, 804000, 912000, 1044000, 1044000, 1044000),
CORE_DVFS("cclk_lp", 0, 1, 1, KHZ, 312000, 564000, 696000, 828000, 960000, 1044000, 1044000, 1044000),
CORE_DVFS("cclk_lp", 1, -1, 1, KHZ, 312000, 564000, 696000, 828000, 960000, 1092000, 1092000, 1092000),
CORE_DVFS("sbus", 0, 0, 1, KHZ, 120000, 192000, 228000, 264000, 312000, 348000, 372000, 372000),
CORE_DVFS("sbus", 0, 1, 1, KHZ, 120000, 204000, 252000, 288000, 324000, 360000, 372000, 372000),
CORE_DVFS("sbus", 1, -1, 1, KHZ, 120000, 204000, 252000, 288000, 324000, 360000, 384000, 384000),
CORE_DVFS("vic03", 0, 0, 1, KHZ, 180000, 324000, 408000, 492000, 588000, 660000, 708000, 756000),
CORE_DVFS("vic03", 0, 1, 1, KHZ, 180000, 336000, 420000, 504000, 600000, 684000, 756000, 756000),
CORE_DVFS("vic03", 1, -1, 1, KHZ, 180000, 336000, 420000, 504000, 600000, 684000, 756000, 828000),
CORE_DVFS("tsec", 0, 0, 1, KHZ, 180000, 324000, 408000, 492000, 588000, 660000, 708000, 756000),
CORE_DVFS("tsec", 0, 1, 1, KHZ, 180000, 336000, 420000, 504000, 600000, 684000, 756000, 756000),
CORE_DVFS("tsec", 1, -1, 1, KHZ, 180000, 336000, 420000, 504000, 600000, 684000, 756000, 828000),
CORE_DVFS("msenc", 0, 0, 1, KHZ, 120000, 216000, 288000, 336000, 384000, 432000, 456000, 480000),
CORE_DVFS("msenc", 0, 1, 1, KHZ, 120000, 228000, 276000, 348000, 396000, 444000, 480000, 480000),
CORE_DVFS("msenc", 1, -1, 1, KHZ, 120000, 228000, 276000, 348000, 396000, 444000, 480000, 528000),
CORE_DVFS("se", 0, 0, 1, KHZ, 120000, 216000, 288000, 336000, 384000, 432000, 456000, 480000),
CORE_DVFS("se", 0, 1, 1, KHZ, 120000, 228000, 276000, 348000, 396000, 444000, 480000, 480000),
CORE_DVFS("se", 1, -1, 1, KHZ, 120000, 228000, 276000, 348000, 396000, 444000, 480000, 528000),
CORE_DVFS("vde", 0, 0, 1, KHZ, 120000, 216000, 288000, 336000, 384000, 432000, 456000, 480000),
CORE_DVFS("vde", 0, 1, 1, KHZ, 120000, 228000, 276000, 348000, 396000, 444000, 480000, 480000),
CORE_DVFS("vde", 1, -1, 1, KHZ, 120000, 228000, 276000, 348000, 396000, 444000, 480000, 528000),
CORE_DVFS("host1x", 0, 0, 1, KHZ, 108000, 156000, 204000, 240000, 348000, 372000, 408000, 408000),
CORE_DVFS("host1x", 0, 1, 1, KHZ, 108000, 156000, 204000, 252000, 348000, 384000, 408000, 408000),
CORE_DVFS("host1x", 1, -1, 1, KHZ, 108000, 156000, 204000, 252000, 348000, 384000, 444000, 444000),
CORE_DVFS("vi", 0, 0, 1, KHZ, 228000, 408000, 480000, 600000, 600000, 600000, 600000, 600000),
CORE_DVFS("vi", 0, 1, 1, KHZ, 228000, 420000, 480000, 600000, 600000, 600000, 600000, 600000),
CORE_DVFS("vi", 1, -1, 1, KHZ, 228000, 420000, 480000, 600000, 600000, 600000, 600000, 600000),
CORE_DVFS("isp", 0, 0, 1, KHZ, 228000, 408000, 480000, 600000, 600000, 600000, 600000, 600000),
CORE_DVFS("isp", 0, 1, 1, KHZ, 228000, 420000, 480000, 600000, 600000, 600000, 600000, 600000),
CORE_DVFS("isp", 1, -1, 1, KHZ, 228000, 420000, 480000, 600000, 600000, 600000, 600000, 600000),
CORE_DVFS("c2bus", 0, 0, 1, KHZ, 120000, 216000, 288000, 336000, 384000, 432000, 456000, 480000),
CORE_DVFS("c2bus", 0, 1, 1, KHZ, 120000, 228000, 276000, 348000, 396000, 444000, 480000, 480000),
CORE_DVFS("c2bus", 1, -1, 1, KHZ, 120000, 228000, 276000, 348000, 396000, 444000, 480000, 528000),
CORE_DVFS("c3bus", 0, 0, 1, KHZ, 180000, 324000, 408000, 492000, 588000, 660000, 708000, 756000),
CORE_DVFS("c3bus", 0, 1, 1, KHZ, 180000, 336000, 420000, 504000, 600000, 684000, 756000, 756000),
CORE_DVFS("c3bus", 1, -1, 1, KHZ, 180000, 336000, 420000, 504000, 600000, 684000, 756000, 828000),
CORE_DVFS("pll_m", -1, -1, 1, KHZ, 800000, 800000, 1066000, 1066000, 1066000, 1066000, 1200000, 1200000),
CORE_DVFS("pll_c", -1, -1, 1, KHZ, 800000, 800000, 1066000, 1066000, 1066000, 1066000, 1066000, 1066000),
CORE_DVFS("pll_c2", -1, -1, 1, KHZ, 800000, 800000, 1066000, 1066000, 1066000, 1066000, 1066000, 1066000),
CORE_DVFS("pll_c3", -1, -1, 1, KHZ, 800000, 800000, 1066000, 1066000, 1066000, 1066000, 1066000, 1066000),
/* Clock limits for I/O peripherals */
CORE_DVFS("sbc1", -1, -1, 1, KHZ, 33000, 33000, 33000, 33000, 33000, 33000, 51000, 51000),
CORE_DVFS("sbc2", -1, -1, 1, KHZ, 33000, 33000, 33000, 33000, 33000, 33000, 51000, 51000),
CORE_DVFS("sbc3", -1, -1, 1, KHZ, 33000, 33000, 33000, 33000, 33000, 33000, 51000, 51000),
CORE_DVFS("sbc4", -1, -1, 1, KHZ, 33000, 33000, 33000, 33000, 33000, 33000, 51000, 51000),
CORE_DVFS("sbc5", -1, -1, 1, KHZ, 33000, 33000, 33000, 33000, 33000, 33000, 51000, 51000),
CORE_DVFS("sbc6", -1, -1, 1, KHZ, 33000, 33000, 33000, 33000, 33000, 33000, 51000, 51000),
CORE_DVFS("sdmmc1", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 204000),
CORE_DVFS("sdmmc3", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 204000),
CORE_DVFS("sdmmc4", -1, -1, 1, KHZ, 1, 1, 82000, 82000, 136000, 136000, 136000, 204000),
CORE_DVFS("hdmi", -1, -1, 1, KHZ, 1, 148500, 148500, 297000, 297000, 297000, 297000, 297000),
CORE_DVFS("nor", -1, -1, 1, KHZ, 102000, 102000, 102000, 102000, 102000, 102000, 102000, 102000),
CORE_DVFS("pciex", -1, -1, 1, KHZ, 1, 250000, 250000, 500000, 500000, 500000, 500000, 500000),
CORE_DVFS("mselect", -1, -1, 1, KHZ, 102000, 102000, 204000, 204000, 204000, 204000, 408000, 408000),
CORE_DVFS("xusb_falcon_src", -1, -1, 1, KHZ, 1, 336000, 336000, 336000, 336000, 336000, 336000, 336000),
CORE_DVFS("xusb_host_src", -1, -1, 1, KHZ, 1, 112000, 112000, 112000, 112000, 112000, 112000, 112000),
CORE_DVFS("xusb_dev_src", -1, -1, 1, KHZ, 1, 58300, 58300, 58300, 112000, 112000, 112000, 112000),
CORE_DVFS("xusb_ss_src", -1, -1, 1, KHZ, 1, 120000, 120000, 120000, 120000, 120000, 120000, 120000),
CORE_DVFS("xusb_fs_src", -1, -1, 1, KHZ, 1, 48000, 48000, 48000, 48000, 48000, 48000, 48000),
CORE_DVFS("xusb_hs_src", -1, -1, 1, KHZ, 1, 60000, 60000, 60000, 60000, 60000, 60000, 60000),
CORE_DVFS("hda", -1, -1, 1, KHZ, 1, 108000, 108000, 108000, 108000, 108000, 108000, 108000),
CORE_DVFS("hda2codec_2x", -1, -1, 1, KHZ, 1, 48000, 48000, 48000, 48000, 48000, 48000, 48000),
CORE_DVFS("sor0", -1, -1, 1, KHZ, 162000, 270000, 540000, 540000, 540000, 540000, 540000, 540000),
/*
* The clock rate for the display controllers that determines the
* necessary core voltage depends on a divider that is internal
* to the display block. Disable auto-dvfs on the display clocks,
* and let the display driver call tegra_dvfs_set_rate manually
*/
CORE_DVFS("disp1", 0, 0, 0, KHZ, 148500, 241000, 297000, 297000, 297000, 474000, 474000, 474000),
CORE_DVFS("disp1", 0, 1, 0, KHZ, 148500, 241000, 297000, 297000, 474000, 474000, 474000, 474000),
CORE_DVFS("disp1", 1, -1, 0, KHZ, 148500, 241000, 297000, 297000, 474000, 474000, 474000, 533000),
CORE_DVFS("disp2", 0, 0, 0, KHZ, 148500, 241000, 297000, 297000, 297000, 474000, 474000, 474000),
CORE_DVFS("disp2", 0, 1, 0, KHZ, 148500, 241000, 297000, 297000, 474000, 474000, 474000, 474000),
CORE_DVFS("disp2", 1, -1, 0, KHZ, 148500, 241000, 297000, 297000, 474000, 474000, 474000, 533000),
};
int tegra_dvfs_disable_core_set(const char *arg, const struct kernel_param *kp)
{
int ret;
ret = param_set_bool(arg, kp);
if (ret)
return ret;
if (tegra_dvfs_core_disabled)
tegra_dvfs_rail_disable(&tegra124_dvfs_rail_vdd_core);
else
tegra_dvfs_rail_enable(&tegra124_dvfs_rail_vdd_core);
return 0;
}
int tegra_dvfs_disable_cpu_set(const char *arg, const struct kernel_param *kp)
{
int ret;
ret = param_set_bool(arg, kp);
if (ret)
return ret;
if (tegra_dvfs_cpu_disabled)
tegra_dvfs_rail_disable(&tegra124_dvfs_rail_vdd_cpu);
else
tegra_dvfs_rail_enable(&tegra124_dvfs_rail_vdd_cpu);
return 0;
}
int tegra_dvfs_disable_get(char *buffer, const struct kernel_param *kp)
{
return param_get_bool(buffer, kp);
}
static struct kernel_param_ops tegra_dvfs_disable_core_ops = {
.set = tegra_dvfs_disable_core_set,
.get = tegra_dvfs_disable_get,
};
static struct kernel_param_ops tegra_dvfs_disable_cpu_ops = {
.set = tegra_dvfs_disable_cpu_set,
.get = tegra_dvfs_disable_get,
};
module_param_cb(disable_core, &tegra_dvfs_disable_core_ops,
&tegra_dvfs_core_disabled, 0644);
module_param_cb(disable_cpu, &tegra_dvfs_disable_cpu_ops,
&tegra_dvfs_cpu_disabled, 0644);
static void init_dvfs_one(struct dvfs *d, int max_freq_index)
{
int ret;
struct clk *c = clk_get_sys(d->clk_name, d->clk_name);
if (IS_ERR(c)) {
pr_debug("tegra124_dvfs: no clock found for %s\n",
d->clk_name);
return;
}
d->max_millivolts = d->dvfs_rail->nominal_millivolts;
ret = tegra_setup_dvfs(c, d);
if (ret)
pr_err("tegra124_dvfs: failed to enable dvfs on %s\n",
__clk_get_name(c));
}
static bool match_dvfs_one(const char *name,
int dvfs_speedo_id, int dvfs_process_id,
int speedo_id, int process_id)
{
if ((dvfs_process_id != -1 && dvfs_process_id != process_id) ||
(dvfs_speedo_id != -1 && dvfs_speedo_id != speedo_id)) {
pr_debug("tegra124_dvfs: rejected %s speedo %d, process %d\n",
name, dvfs_speedo_id, dvfs_process_id);
return false;
}
return true;
}
static int round_voltage(int mv, struct rail_alignment *align, bool up)
{
if (align->step_uv) {
int uv = max(mv * 1000, align->offset_uv) - align->offset_uv;
uv = (uv + (up ? align->step_uv - 1 : 0)) / align->step_uv;
return (uv * align->step_uv + align->offset_uv) / 1000;
}
return mv;
}
static int set_cpu_dvfs_data(unsigned long max_freq,
struct cpu_dvfs *d, struct dvfs *cpu_dvfs, int *max_freq_index)
{
int i, mv, dfll_mv, min_dfll_mv, num_freqs;
unsigned long fmax_at_vmin = 0;
unsigned long fmin_use_dfll = 0;
unsigned long *freqs;
int *dfll_millivolts;
struct rail_alignment *align = &tegra124_dvfs_rail_vdd_cpu.alignment;
min_dfll_mv = d->min_mv;
min_dfll_mv = round_voltage(min_dfll_mv, align, true);
d->max_mv = round_voltage(d->max_mv, align, false);
BUG_ON(min_dfll_mv < tegra124_dvfs_rail_vdd_cpu.min_millivolts);
if (tegra124_dfll_get_fv_table(&num_freqs, &freqs, &dfll_millivolts))
return -EPROBE_DEFER;
for (i = 0; i < num_freqs; i++) {
if (freqs[i] != d->fv_table[i].freq * 1000) {
pr_err("Err: DFLL freq ladder does not match PLL's\n");
return -EINVAL;
}
if (d->fv_table[i].freq > max_freq)
break;
mv = d->fv_table[i].volt;
/*
* Check maximum frequency at minimum voltage for dfll source;
* round down unless all table entries are above Vmin, then use
* the 1st entry as is.
*/
dfll_mv = max(dfll_millivolts[i], min_dfll_mv);
if (dfll_mv > min_dfll_mv) {
if (!i)
fmax_at_vmin = freqs[i];
if (!fmax_at_vmin)
fmax_at_vmin = freqs[i - 1];
}
/* Clip maximum frequency at maximum voltage for pll source */
if ((mv > d->max_mv) && !i) {
pr_err("Err: volt of 1st entry is higher than Vmax\n");
return -EINVAL;
}
/* Minimum rate with pll source voltage above dfll Vmin */
if ((mv >= min_dfll_mv) && !fmin_use_dfll)
fmin_use_dfll = freqs[i];
/* fill in dvfs tables */
cpu_dvfs->freqs[i] = freqs[i];
cpu_millivolts[i] = mv;
cpu_dfll_millivolts[i] = min(dfll_mv, d->max_mv);
}
/*
* In the dfll operating range dfll voltage at any rate should be
* better (below) than pll voltage
*/
if (!fmin_use_dfll || (fmin_use_dfll > fmax_at_vmin))
fmin_use_dfll = fmax_at_vmin;
/* dvfs tables are successfully populated - fill in the rest */
cpu_dvfs->speedo_id = d->speedo_id;
cpu_dvfs->process_id = d->process_id;
cpu_dvfs->dvfs_rail->nominal_millivolts = min(d->max_mv,
max(cpu_millivolts[i - 1], cpu_dfll_millivolts[i - 1]));
*max_freq_index = i - 1;
cpu_dvfs->use_dfll_rate_min = fmin_use_dfll;
return 0;
}
static int get_core_nominal_mv_index(int speedo_id)
{
int i;
int mv = tegra124_get_core_speedo_mv();
if (mv < 0) {
pr_err("Can't get Tegra124 speedo mv\n");
return -EINVAL;
}
/* Round nominal level down to the nearest core scaling step */
for (i = 0; i < MAX_DVFS_FREQS; i++) {
if ((core_millivolts[i] == 0) || (mv < core_millivolts[i]))
break;
}
if (i == 0) {
pr_err("tegra124-dvfs: failed to get nominal idx at volt %d\n",
mv);
return -ENOSYS;
}
return i - 1;
}
static void adjust_emc_dvfs_table(struct dvfs *d)
{
unsigned long rate;
int i;
for (i = 0; i < ARRAY_SIZE(core_millivolts); i++) {
if (core_millivolts[i] == 0)
return;
rate = tegra124_predict_emc_rate(core_millivolts[i]);
if (rate < 0)
return;
d->freqs[i] = rate;
}
}
int tegra124_init_dvfs(void)
{
int cpu_speedo_id = tegra_get_cpu_speedo_id();
int cpu_process_id = tegra_get_cpu_process_id();
int soc_speedo_id = tegra_get_soc_speedo_id();
int core_process_id = tegra_get_core_process_id();
int i, ret;
int core_nominal_mv_index;
int cpu_max_freq_index = 0;
/*
* Find nominal voltages for core (1st) and cpu rails before rail
* init. Nominal voltage index in core scaling ladder can also be
* used to determine max dvfs frequencies for all core clocks. In
* case of error disable core scaling and set index to 0, so that
* core clocks would not exceed rates allowed at minimum voltage.
*/
core_nominal_mv_index = get_core_nominal_mv_index(soc_speedo_id);
if (core_nominal_mv_index < 0) {
tegra124_dvfs_rail_vdd_core.disabled = true;
tegra_dvfs_core_disabled = true;
core_nominal_mv_index = 0;
}
tegra124_dvfs_rail_vdd_core.nominal_millivolts =
core_millivolts[core_nominal_mv_index];
/*
* Setup cpu dvfs and dfll tables from cvb data, determine nominal
* voltage for cpu rail, and cpu maximum frequency. Note that entire
* frequency range is guaranteed only when dfll is used as cpu clock
* source. Reaching maximum frequency with pll as cpu clock source
* may not be possible within nominal voltage range (dvfs mechanism
* would automatically fail frequency request in this case, so that
* voltage limit is not violated). Error when cpu dvfs table can not
* be constructed must never happen.
*/
BUG_ON(cpu_speedo_id >= ARRAY_SIZE(cpu_max_freq));
for (ret = 0, i = 0; i < ARRAY_SIZE(cpu_fv_dvfs_table); i++) {
struct cpu_dvfs *d = &cpu_fv_dvfs_table[i];
unsigned long max_freq = cpu_max_freq[cpu_speedo_id];
if (match_dvfs_one("cpu dvfs", d->speedo_id, d->process_id,
cpu_speedo_id, cpu_process_id)) {
ret = set_cpu_dvfs_data(max_freq,
d, &cpu_dvfs, &cpu_max_freq_index);
if (ret)
goto out;
break;
}
}
BUG_ON(i == ARRAY_SIZE(cpu_fv_dvfs_table));
/* Init core thermal profile */
tegra_dvfs_rail_init_vmin_thermal_profile(vdd_core_therm_trips_table,
vdd_core_therm_floors_table, &tegra124_dvfs_rail_vdd_core);
/* Init rail structures and dependencies */
tegra_dvfs_init_rails(tegra124_dvfs_rails,
ARRAY_SIZE(tegra124_dvfs_rails));
/*
* Search core dvfs table for speedo/process matching entries and
* initialize dvfs-ed clocks
*/
for (i = 0; i < ARRAY_SIZE(core_dvfs_table); i++) {
struct dvfs *d = &core_dvfs_table[i];
if (!match_dvfs_one(d->clk_name, d->speedo_id,
d->process_id, soc_speedo_id, core_process_id))
continue;
init_dvfs_one(d, core_nominal_mv_index);
/*
* EMC dvfs is board dependent, the EMC scaling frequencies are
* determined by the Tegra BCT and the board specific EMC DFS
* table owned by EMC driver.
*/
if (!strcmp(d->clk_name, "emc") && tegra124_emc_is_ready())
adjust_emc_dvfs_table(d);
}
/*
* Initialize matching cpu dvfs entry already found when nominal
* voltage was determined
*/
init_dvfs_one(&cpu_dvfs, cpu_max_freq_index);
pr_info("tegra dvfs: VDD_CPU nominal %dmV, scaling %s\n",
tegra124_dvfs_rail_vdd_cpu.nominal_millivolts,
tegra_dvfs_cpu_disabled ? "disabled" : "enabled");
pr_info("tegra dvfs: VDD_CORE nominal %dmV, scaling %s\n",
tegra124_dvfs_rail_vdd_core.nominal_millivolts,
tegra_dvfs_core_disabled ? "disabled" : "enabled");
return 0;
out:
return ret;
}