summaryrefslogtreecommitdiffstats
path: root/drivers/clk/tegra/clk-tegra114.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 11:54:50 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 11:54:50 -0700
commit92295f632cefbdf15d46e9ac5f0fc3cfade35259 (patch)
tree5b3820d4ed135ccbef540781d99a46137959bbb6 /drivers/clk/tegra/clk-tegra114.c
parent750b2d7b93f2ba19f4f238cc641bda22fe07c155 (diff)
parent45e3ec3784aec0d194740b75b547bfabca448ff3 (diff)
Merge tag 'clk-for-linus-3.11' of git://git.linaro.org/people/mturquette/linux
Pull clock framework updates from Mike Turquette: "The common clock framework changes for 3.11 include new clock drivers across several different platforms and architectures, fixes to existing drivers, a MAINTAINERS file fix and improvements to the basic clock types that allow them to be of use to more platforms than before. Only a few fixes to the core framework are included with most all of the changes landing in the various clock drivers themselves." * tag 'clk-for-linus-3.11' of git://git.linaro.org/people/mturquette/linux: (55 commits) clk: tegra: fix ifdef for tegra_periph_reset_assert inline clk: tegra: provide tegra_periph_reset_assert alternative clk: exynos4: Fix clock aliases for cpufreq related clocks clk: samsung: Add MUX_FA macro to pass flag and alias clk: add support for Rockchip gate clocks clk: vexpress: Make the clock drivers directly available for arm64 clk: vexpress: Use full node name to identify individual clocks clk: tegra: T114: add DFLL DVCO reset control clk: tegra: T114: add DFLL source clocks clk: tegra: T114: add FCPU clock shaper programming, needed by the DFLL clk: gate: add CLK_GATE_HIWORD_MASK clk: divider: add CLK_DIVIDER_HIWORD_MASK flag clk: mux: add CLK_MUX_HIWORD_MASK clk: Always notify whole subtree when reparenting MAINTAINERS: make drivers/clk entry match subdirs clk: honor CLK_GET_RATE_NOCACHE in clk_set_rate clk: use clk_get_rate() for debugfs clk: tegra: Use override bits when needed clk: tegra: override bits for Tegra30 PLLM clk: tegra: override bits for Tegra114 PLLM ...
Diffstat (limited to 'drivers/clk/tegra/clk-tegra114.c')
-rw-r--r--drivers/clk/tegra/clk-tegra114.c270
1 files changed, 263 insertions, 7 deletions
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 40d939d091b..b6015cb4fc0 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include <linux/clk/tegra.h>
#include "clk.h"
@@ -28,6 +29,7 @@
#define RST_DEVICES_L 0x004
#define RST_DEVICES_H 0x008
#define RST_DEVICES_U 0x00C
+#define RST_DFLL_DVCO 0x2F4
#define RST_DEVICES_V 0x358
#define RST_DEVICES_W 0x35C
#define RST_DEVICES_X 0x28C
@@ -41,8 +43,36 @@
#define RST_DEVICES_CLR_V 0x434
#define RST_DEVICES_SET_W 0x438
#define RST_DEVICES_CLR_W 0x43c
+#define CPU_FINETRIM_SELECT 0x4d4 /* override default prop dlys */
+#define CPU_FINETRIM_DR 0x4d8 /* rise->rise prop dly A */
+#define CPU_FINETRIM_R 0x4e4 /* rise->rise prop dly inc A */
#define RST_DEVICES_NUM 5
+/* RST_DFLL_DVCO bitfields */
+#define DVFS_DFLL_RESET_SHIFT 0
+
+/* CPU_FINETRIM_SELECT and CPU_FINETRIM_DR bitfields */
+#define CPU_FINETRIM_1_FCPU_1 BIT(0) /* fcpu0 */
+#define CPU_FINETRIM_1_FCPU_2 BIT(1) /* fcpu1 */
+#define CPU_FINETRIM_1_FCPU_3 BIT(2) /* fcpu2 */
+#define CPU_FINETRIM_1_FCPU_4 BIT(3) /* fcpu3 */
+#define CPU_FINETRIM_1_FCPU_5 BIT(4) /* fl2 */
+#define CPU_FINETRIM_1_FCPU_6 BIT(5) /* ftop */
+
+/* CPU_FINETRIM_R bitfields */
+#define CPU_FINETRIM_R_FCPU_1_SHIFT 0 /* fcpu0 */
+#define CPU_FINETRIM_R_FCPU_1_MASK (0x3 << CPU_FINETRIM_R_FCPU_1_SHIFT)
+#define CPU_FINETRIM_R_FCPU_2_SHIFT 2 /* fcpu1 */
+#define CPU_FINETRIM_R_FCPU_2_MASK (0x3 << CPU_FINETRIM_R_FCPU_2_SHIFT)
+#define CPU_FINETRIM_R_FCPU_3_SHIFT 4 /* fcpu2 */
+#define CPU_FINETRIM_R_FCPU_3_MASK (0x3 << CPU_FINETRIM_R_FCPU_3_SHIFT)
+#define CPU_FINETRIM_R_FCPU_4_SHIFT 6 /* fcpu3 */
+#define CPU_FINETRIM_R_FCPU_4_MASK (0x3 << CPU_FINETRIM_R_FCPU_4_SHIFT)
+#define CPU_FINETRIM_R_FCPU_5_SHIFT 8 /* fl2 */
+#define CPU_FINETRIM_R_FCPU_5_MASK (0x3 << CPU_FINETRIM_R_FCPU_5_SHIFT)
+#define CPU_FINETRIM_R_FCPU_6_SHIFT 10 /* ftop */
+#define CPU_FINETRIM_R_FCPU_6_MASK (0x3 << CPU_FINETRIM_R_FCPU_6_SHIFT)
+
#define CLK_OUT_ENB_L 0x010
#define CLK_OUT_ENB_H 0x014
#define CLK_OUT_ENB_U 0x018
@@ -127,6 +157,7 @@
#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
#define PMC_CTRL 0
#define PMC_CTRL_BLINK_ENB 7
+#define PMC_BLINK_TIMER 0x40
#define OSC_CTRL 0x50
#define OSC_CTRL_OSC_FREQ_SHIFT 28
@@ -242,6 +273,8 @@
#define CLK_SOURCE_I2CSLOW 0x3fc
#define CLK_SOURCE_SE 0x42c
#define CLK_SOURCE_MSELECT 0x3b4
+#define CLK_SOURCE_DFLL_REF 0x62c
+#define CLK_SOURCE_DFLL_SOC 0x630
#define CLK_SOURCE_SOC_THERM 0x644
#define CLK_SOURCE_XUSB_HOST_SRC 0x600
#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
@@ -250,6 +283,10 @@
#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
#define CLK_SOURCE_EMC 0x19c
+/* PLLM override registers */
+#define PMC_PLLM_WB0_OVERRIDE 0x1dc
+#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
+
/* Tegra CPU clock and reset control regs */
#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470
@@ -267,6 +304,15 @@ static DEFINE_SPINLOCK(clk_doubler_lock);
static DEFINE_SPINLOCK(clk_out_lock);
static DEFINE_SPINLOCK(sysrate_lock);
+static struct div_nmp pllxc_nmp = {
+ .divm_shift = 0,
+ .divm_width = 8,
+ .divn_shift = 8,
+ .divn_width = 8,
+ .divp_shift = 20,
+ .divp_width = 4,
+};
+
static struct pdiv_map pllxc_p[] = {
{ .pdiv = 1, .hw_val = 0 },
{ .pdiv = 2, .hw_val = 1 },
@@ -315,6 +361,16 @@ static struct tegra_clk_pll_params pll_c_params = {
.stepa_shift = 17,
.stepb_shift = 9,
.pdiv_tohw = pllxc_p,
+ .div_nmp = &pllxc_nmp,
+};
+
+static struct div_nmp pllcx_nmp = {
+ .divm_shift = 0,
+ .divm_width = 2,
+ .divn_shift = 8,
+ .divn_width = 8,
+ .divp_shift = 20,
+ .divp_width = 3,
};
static struct pdiv_map pllc_p[] = {
@@ -348,6 +404,8 @@ static struct tegra_clk_pll_params pll_c2_params = {
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
.lock_delay = 300,
.pdiv_tohw = pllc_p,
+ .div_nmp = &pllcx_nmp,
+ .max_p = 7,
.ext_misc_reg[0] = 0x4f0,
.ext_misc_reg[1] = 0x4f4,
.ext_misc_reg[2] = 0x4f8,
@@ -366,11 +424,25 @@ static struct tegra_clk_pll_params pll_c3_params = {
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
.lock_delay = 300,
.pdiv_tohw = pllc_p,
+ .div_nmp = &pllcx_nmp,
+ .max_p = 7,
.ext_misc_reg[0] = 0x504,
.ext_misc_reg[1] = 0x508,
.ext_misc_reg[2] = 0x50c,
};
+static struct div_nmp pllm_nmp = {
+ .divm_shift = 0,
+ .divm_width = 8,
+ .override_divm_shift = 0,
+ .divn_shift = 8,
+ .divn_width = 8,
+ .override_divn_shift = 8,
+ .divp_shift = 20,
+ .divp_width = 1,
+ .override_divp_shift = 27,
+};
+
static struct pdiv_map pllm_p[] = {
{ .pdiv = 1, .hw_val = 0 },
{ .pdiv = 2, .hw_val = 1 },
@@ -400,6 +472,18 @@ static struct tegra_clk_pll_params pll_m_params = {
.lock_delay = 300,
.max_p = 2,
.pdiv_tohw = pllm_p,
+ .div_nmp = &pllm_nmp,
+ .pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
+ .pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
+};
+
+static struct div_nmp pllp_nmp = {
+ .divm_shift = 0,
+ .divm_width = 5,
+ .divn_shift = 8,
+ .divn_width = 10,
+ .divp_shift = 20,
+ .divp_width = 3,
};
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
@@ -423,6 +507,7 @@ static struct tegra_clk_pll_params pll_p_params = {
.lock_mask = PLL_BASE_LOCK,
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
.lock_delay = 300,
+ .div_nmp = &pllp_nmp,
};
static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
@@ -449,6 +534,7 @@ static struct tegra_clk_pll_params pll_a_params = {
.lock_mask = PLL_BASE_LOCK,
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
.lock_delay = 300,
+ .div_nmp = &pllp_nmp,
};
static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
@@ -484,6 +570,7 @@ static struct tegra_clk_pll_params pll_d_params = {
.lock_mask = PLL_BASE_LOCK,
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
.lock_delay = 1000,
+ .div_nmp = &pllp_nmp,
};
static struct tegra_clk_pll_params pll_d2_params = {
@@ -498,6 +585,7 @@ static struct tegra_clk_pll_params pll_d2_params = {
.lock_mask = PLL_BASE_LOCK,
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
.lock_delay = 1000,
+ .div_nmp = &pllp_nmp,
};
static struct pdiv_map pllu_p[] = {
@@ -506,6 +594,15 @@ static struct pdiv_map pllu_p[] = {
{ .pdiv = 0, .hw_val = 0 },
};
+static struct div_nmp pllu_nmp = {
+ .divm_shift = 0,
+ .divm_width = 5,
+ .divn_shift = 8,
+ .divn_width = 10,
+ .divp_shift = 20,
+ .divp_width = 1,
+};
+
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
{12000000, 480000000, 960, 12, 0, 12},
{13000000, 480000000, 960, 13, 0, 12},
@@ -528,6 +625,7 @@ static struct tegra_clk_pll_params pll_u_params = {
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
.lock_delay = 1000,
.pdiv_tohw = pllu_p,
+ .div_nmp = &pllu_nmp,
};
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
@@ -560,6 +658,7 @@ static struct tegra_clk_pll_params pll_x_params = {
.stepa_shift = 16,
.stepb_shift = 24,
.pdiv_tohw = pllxc_p,
+ .div_nmp = &pllxc_nmp,
};
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
@@ -569,6 +668,15 @@ static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
{0, 0, 0, 0, 0, 0},
};
+static struct div_nmp plle_nmp = {
+ .divm_shift = 0,
+ .divm_width = 8,
+ .divn_shift = 8,
+ .divn_width = 8,
+ .divp_shift = 24,
+ .divp_width = 4,
+};
+
static struct tegra_clk_pll_params pll_e_params = {
.input_min = 12000000,
.input_max = 1000000000,
@@ -582,6 +690,16 @@ static struct tegra_clk_pll_params pll_e_params = {
.lock_mask = PLLE_MISC_LOCK,
.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
.lock_delay = 300,
+ .div_nmp = &plle_nmp,
+};
+
+static struct div_nmp pllre_nmp = {
+ .divm_shift = 0,
+ .divm_width = 8,
+ .divn_shift = 8,
+ .divn_width = 8,
+ .divp_shift = 16,
+ .divp_width = 4,
};
static struct tegra_clk_pll_params pll_re_vco_params = {
@@ -598,6 +716,7 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
.lock_delay = 300,
.iddq_reg = PLLRE_MISC,
.iddq_bit_idx = PLLRE_IDDQ_BIT,
+ .div_nmp = &pllre_nmp,
};
/* Peripheral clock registers */
@@ -765,6 +884,7 @@ enum tegra114_clk {
audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3,
blink, xusb_host_src = 252, xusb_falcon_src, xusb_fs_src, xusb_ss_src,
xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk, cclk_g, cclk_lp,
+ dfll_ref = 264, dfll_soc,
/* Mux clocks */
@@ -1202,8 +1322,8 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
/* PLLP_OUT2 */
clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
- TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
- &pll_div_lock);
+ TEGRA_DIVIDER_ROUND_UP | TEGRA_DIVIDER_INT, 24,
+ 8, 1, &pll_div_lock);
clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
clk_base + PLLP_OUTA, 17, 16,
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
@@ -1605,7 +1725,7 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
/* clk_out_2 */
clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
- ARRAY_SIZE(clk_out1_parents), 0,
+ ARRAY_SIZE(clk_out2_parents), 0,
pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
&clk_out_lock);
clks[clk_out_2_mux] = clk;
@@ -1617,7 +1737,7 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
/* clk_out_3 */
clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
- ARRAY_SIZE(clk_out1_parents), 0,
+ ARRAY_SIZE(clk_out3_parents), 0,
pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
&clk_out_lock);
clks[clk_out_3_mux] = clk;
@@ -1628,6 +1748,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
clks[clk_out_3] = clk;
/* blink */
+ /* clear the blink timer register to directly output clk_32k */
+ writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
pmc_base + PMC_DPD_PADS_ORIDE,
PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
@@ -1640,7 +1762,7 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
}
static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
- "pll_p_out3", "pll_p_out2", "unused",
+ "pll_p", "pll_p_out2", "unused",
"clk_32k", "pll_m_out1" };
static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
@@ -1750,7 +1872,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = {
TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi),
TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp),
- TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_h_regs, TEGRA_PERIPH_WAR_1005168, msenc),
+ TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_u_regs, TEGRA_PERIPH_WAR_1005168, msenc),
TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec),
TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x),
TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi),
@@ -1767,6 +1889,8 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = {
TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se),
TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED),
+ TEGRA_INIT_DATA_MUX("dfll_ref", "ref", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, dfll_ref),
+ TEGRA_INIT_DATA_MUX("dfll_soc", "soc", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, dfll_soc),
TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm),
TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src),
TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src),
@@ -2028,6 +2152,10 @@ static const struct of_device_id pmc_match[] __initconst = {
{},
};
+/*
+ * dfll_soc/dfll_ref apparently must be kept enabled, otherwise I2C5
+ * breaks
+ */
static __initdata struct tegra_clk_init_table init_table[] = {
{uarta, pll_p, 408000000, 0},
{uartb, pll_p, 408000000, 0},
@@ -2043,6 +2171,8 @@ static __initdata struct tegra_clk_init_table init_table[] = {
{i2s2, pll_a_out0, 11289600, 0},
{i2s3, pll_a_out0, 11289600, 0},
{i2s4, pll_a_out0, 11289600, 0},
+ {dfll_soc, pll_p, 51000000, 1},
+ {dfll_ref, pll_p, 51000000, 1},
{clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
};
@@ -2051,7 +2181,132 @@ static void __init tegra114_clock_apply_init_table(void)
tegra_init_from_table(init_table, clks, clk_max);
}
-void __init tegra114_clock_init(struct device_node *np)
+
+/**
+ * tegra114_car_barrier - wait for pending writes to the CAR to complete
+ *
+ * Wait for any outstanding writes to the CAR MMIO space from this CPU
+ * to complete before continuing execution. No return value.
+ */
+static void tegra114_car_barrier(void)
+{
+ wmb(); /* probably unnecessary */
+ readl_relaxed(clk_base + CPU_FINETRIM_SELECT);
+}
+
+/**
+ * tegra114_clock_tune_cpu_trimmers_high - use high-voltage propagation delays
+ *
+ * When the CPU rail voltage is in the high-voltage range, use the
+ * built-in hardwired clock propagation delays in the CPU clock
+ * shaper. No return value.
+ */
+void tegra114_clock_tune_cpu_trimmers_high(void)
+{
+ u32 select = 0;
+
+ /* Use hardwired rise->rise & fall->fall clock propagation delays */
+ select |= ~(CPU_FINETRIM_1_FCPU_1 | CPU_FINETRIM_1_FCPU_2 |
+ CPU_FINETRIM_1_FCPU_3 | CPU_FINETRIM_1_FCPU_4 |
+ CPU_FINETRIM_1_FCPU_5 | CPU_FINETRIM_1_FCPU_6);
+ writel_relaxed(select, clk_base + CPU_FINETRIM_SELECT);
+
+ tegra114_car_barrier();
+}
+EXPORT_SYMBOL(tegra114_clock_tune_cpu_trimmers_high);
+
+/**
+ * tegra114_clock_tune_cpu_trimmers_low - use low-voltage propagation delays
+ *
+ * When the CPU rail voltage is in the low-voltage range, use the
+ * extended clock propagation delays set by
+ * tegra114_clock_tune_cpu_trimmers_init(). The intention is to
+ * maintain the input clock duty cycle that the FCPU subsystem
+ * expects. No return value.
+ */
+void tegra114_clock_tune_cpu_trimmers_low(void)
+{
+ u32 select = 0;
+
+ /*
+ * Use software-specified rise->rise & fall->fall clock
+ * propagation delays (from
+ * tegra114_clock_tune_cpu_trimmers_init()
+ */
+ select |= (CPU_FINETRIM_1_FCPU_1 | CPU_FINETRIM_1_FCPU_2 |
+ CPU_FINETRIM_1_FCPU_3 | CPU_FINETRIM_1_FCPU_4 |
+ CPU_FINETRIM_1_FCPU_5 | CPU_FINETRIM_1_FCPU_6);
+ writel_relaxed(select, clk_base + CPU_FINETRIM_SELECT);
+
+ tegra114_car_barrier();
+}
+EXPORT_SYMBOL(tegra114_clock_tune_cpu_trimmers_low);
+
+/**
+ * tegra114_clock_tune_cpu_trimmers_init - set up and enable clk prop delays
+ *
+ * Program extended clock propagation delays into the FCPU clock
+ * shaper and enable them. XXX Define the purpose - peak current
+ * reduction? No return value.
+ */
+/* XXX Initial voltage rail state assumption issues? */
+void tegra114_clock_tune_cpu_trimmers_init(void)
+{
+ u32 dr = 0, r = 0;
+
+ /* Increment the rise->rise clock delay by four steps */
+ r |= (CPU_FINETRIM_R_FCPU_1_MASK | CPU_FINETRIM_R_FCPU_2_MASK |
+ CPU_FINETRIM_R_FCPU_3_MASK | CPU_FINETRIM_R_FCPU_4_MASK |
+ CPU_FINETRIM_R_FCPU_5_MASK | CPU_FINETRIM_R_FCPU_6_MASK);
+ writel_relaxed(r, clk_base + CPU_FINETRIM_R);
+
+ /*
+ * Use the rise->rise clock propagation delay specified in the
+ * r field
+ */
+ dr |= (CPU_FINETRIM_1_FCPU_1 | CPU_FINETRIM_1_FCPU_2 |
+ CPU_FINETRIM_1_FCPU_3 | CPU_FINETRIM_1_FCPU_4 |
+ CPU_FINETRIM_1_FCPU_5 | CPU_FINETRIM_1_FCPU_6);
+ writel_relaxed(dr, clk_base + CPU_FINETRIM_DR);
+
+ tegra114_clock_tune_cpu_trimmers_low();
+}
+EXPORT_SYMBOL(tegra114_clock_tune_cpu_trimmers_init);
+
+/**
+ * tegra114_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
+ *
+ * Assert the reset line of the DFLL's DVCO. No return value.
+ */
+void tegra114_clock_assert_dfll_dvco_reset(void)
+{
+ u32 v;
+
+ v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+ v |= (1 << DVFS_DFLL_RESET_SHIFT);
+ writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+ tegra114_car_barrier();
+}
+EXPORT_SYMBOL(tegra114_clock_assert_dfll_dvco_reset);
+
+/**
+ * tegra114_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
+ *
+ * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
+ * operate. No return value.
+ */
+void tegra114_clock_deassert_dfll_dvco_reset(void)
+{
+ u32 v;
+
+ v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+ v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
+ writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+ tegra114_car_barrier();
+}
+EXPORT_SYMBOL(tegra114_clock_deassert_dfll_dvco_reset);
+
+static void __init tegra114_clock_init(struct device_node *np)
{
struct device_node *node;
int i;
@@ -2104,3 +2359,4 @@ void __init tegra114_clock_init(struct device_node *np)
tegra_cpu_car_ops = &tegra114_cpu_car_ops;
}
+CLK_OF_DECLARE(tegra114, "nvidia,tegra114-car", tegra114_clock_init);