#include <linux/cpufreq.h>
#include <linux/syscore_ops.h>
#include <linux/platform_device.h>
+#include <linux/platform_data/tegra_bpmp.h>
#include <asm/clkdev.h>
#include <mach/edp.h>
#include <mach/hardware.h>
-#include <mach/mc.h>
#include <mach/tegra_emc.h>
+#include <tegra/mc.h>
+
#include "clock.h"
#include "tegra_clocks_ops.h"
#include "dvfs.h"
#include "sleep.h"
#include "devices.h"
#include "tegra_cl_dvfs.h"
+#include "cpu-tegra.h"
/* FIXME: Disable for initial Si bringup */
#undef USE_PLLE_SS
#define SPARE_REG_CLK_M_DIVISOR_SHIFT 2
#define SPARE_REG_CLK_M_DIVISOR_MASK (3 << SPARE_REG_CLK_M_DIVISOR_SHIFT)
+#define AUDIO_SYNC_CLK_DMIC1 0x560
+#define AUDIO_SYNC_CLK_DMIC2 0x564
+#define PERIPH_CLK_SOURCE_NUM4 \
+ ((AUDIO_SYNC_CLK_DMIC2 - AUDIO_SYNC_CLK_DMIC1) / 4 + 1)
+
#define PERIPH_CLK_SOURCE_XUSB_HOST 0x600
+#define PERIPH_CLK_SOURCE_EMC_DLL 0x664
#define PERIPH_CLK_SOURCE_VIC 0x678
-#define PERIPH_CLK_SOURCE_NUM4 \
- ((PERIPH_CLK_SOURCE_VIC - PERIPH_CLK_SOURCE_XUSB_HOST) / 4 + 1)
+#define PERIPH_CLK_SOURCE_NUM5 \
+ ((PERIPH_CLK_SOURCE_VIC - PERIPH_CLK_SOURCE_XUSB_HOST) / 4)
+
+#define PERIPH_CLK_SOURCE_SDMMC_LEGACY 0x694
+#define PERIPH_CLK_SOURCE_NVENC 0x6a0
+#define PERIPH_CLK_SOURCE_NUM6 \
+ ((PERIPH_CLK_SOURCE_NVENC - PERIPH_CLK_SOURCE_SDMMC_LEGACY) / 4 + 1)
+
+#define AUDIO_SYNC_CLK_DMIC3 0x6b8
+#define PERIPH_CLK_SOURCE_DBGAPB 0x718
+#define PERIPH_CLK_SOURCE_NUM7 \
+ ((PERIPH_CLK_SOURCE_DBGAPB - AUDIO_SYNC_CLK_DMIC3) / 4 + 1)
#define PERIPH_CLK_SOURCE_NUM (PERIPH_CLK_SOURCE_NUM1 + \
PERIPH_CLK_SOURCE_NUM2 + \
PERIPH_CLK_SOURCE_NUM3 + \
- PERIPH_CLK_SOURCE_NUM4)
+ PERIPH_CLK_SOURCE_NUM4 + \
+ PERIPH_CLK_SOURCE_NUM5 + \
+ PERIPH_CLK_SOURCE_NUM6 + \
+ PERIPH_CLK_SOURCE_NUM7)
#define CPU_SOFTRST_CTRL 0x380
#define CPU_SOFTRST_CTRL1 0x384
#define AUDIO_SYNC_TAP_NIBBLE_SHIFT(c) ((c->reg_shift - 24) * 4)
#define PERIPH_CLK_SOR_CLK_SEL_SHIFT 14
-#define PERIPH_CLK_SOR_CLK_SEL_MASK (0x3<<PERIPH_CLK_SOR_CLK_SEL_SHIFT)
+#define PERIPH_CLK_SOR0_CLK_SEL_MASK (0x1<<PERIPH_CLK_SOR_CLK_SEL_SHIFT)
+#define PERIPH_CLK_SOR1_CLK_SEL_MASK (0x3<<PERIPH_CLK_SOR_CLK_SEL_SHIFT)
/* Secondary PLL dividers */
#define PLL_OUT_RATIO_MASK (0xFF<<8)
#define SUPER_STATE_RUN (0x2 << SUPER_STATE_SHIFT)
#define SUPER_STATE_IRQ (0x3 << SUPER_STATE_SHIFT)
#define SUPER_STATE_FIQ (0x4 << SUPER_STATE_SHIFT)
-#define SUPER_LP_DIV2_BYPASS (0x1 << 16)
#define SUPER_SOURCE_MASK 0xF
#define SUPER_FIQ_SOURCE_SHIFT 12
#define SUPER_IRQ_SOURCE_SHIFT 8
#define PLLE_AUX_PLLRE_SEL (1<<28)
#define PLLE_AUX_SEQ_STATE_SHIFT 26
#define PLLE_AUX_SEQ_STATE_MASK (0x3<<PLLE_AUX_SEQ_STATE_SHIFT)
+#define PLLE_AUX_SS_SEQ_INCLUDE (1<<31)
#define PLLE_AUX_SEQ_START_STATE (1<<25)
#define PLLE_AUX_SEQ_ENABLE (1<<24)
#define PLLE_AUX_SS_SWCTL (1<<6)
#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL (1<<0)
#define PLLU_HW_PWRDN_CFG0 0x530
+#define PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE (1<<28)
#define PLLU_HW_PWRDN_CFG0_SEQ_START_STATE (1<<25)
#define PLLU_HW_PWRDN_CFG0_SEQ_ENABLE (1<<24)
+#define PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT (1<<7)
#define PLLU_HW_PWRDN_CFG0_USE_LOCKDET (1<<6)
#define PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL (1<<2)
#define PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL (1<<0)
-#define USB_PLLS_SEQ_START_STATE (1<<25)
-#define USB_PLLS_SEQ_ENABLE (1<<24)
-#define USB_PLLS_USE_LOCKDET (1<<6)
-#define USB_PLLS_ENABLE_SWCTL ((1<<2) | (1<<0))
-
-/* XUSB PLL PAD controls */
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0 0x40
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_PWR_OVRD (1<<3)
-#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_IDDQ (1<<0)
+#define XUSB_PLL_CFG0 0x534
+#define XUSB_PLL_CFG0_PLLU_LOCK_DLY_SHIFT 14
+#define XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK \
+ (0x3ff<<XUSB_PLL_CFG0_PLLU_LOCK_DLY_SHIFT)
/* DFLL */
#define DFLL_BASE 0x2f4
#define PLLP_DEFAULT_FIXED_RATE 408000000
/* Use PLL_RE as PLLE input (default - OSC via pll reference divider) */
-#define USE_PLLE_INPUT_PLLRE 0
+#define USE_PLLE_INPUT_PLLRE 1
-static bool tegra21_is_dyn_ramp(struct clk *c,
- unsigned long rate, bool from_vco_min);
+static void pllc4_set_fixed_rates(unsigned long cf);
+static void tegra21_dfll_cpu_late_init(struct clk *c);
static void tegra21_pllp_init_dependencies(unsigned long pllp_rate);
+
static unsigned long tegra21_clk_shared_bus_update(struct clk *bus,
struct clk **bus_top, struct clk **bus_slow, unsigned long *rate_cap);
static unsigned long tegra21_clk_cap_shared_bus(struct clk *bus,
static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
static void __iomem *misc_gp_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
-static void __iomem *reg_xusb_padctl_base = IO_ADDRESS(TEGRA_XUSB_PADCTL_BASE);
#define MISC_GP_HIDREV 0x804
#define MISC_GP_TRANSACTOR_SCRATCH_0 0x864
readl(reg_pmc_base + (reg))
#define chipid_readl() \
__raw_readl(misc_gp_base + MISC_GP_HIDREV)
-#define xusb_padctl_writel(value, reg) \
- __raw_writel(value, reg_xusb_padctl_base + (reg))
-#define xusb_padctl_readl(reg) \
- readl(reg_xusb_padctl_base + (reg))
/*
* Some peripheral clocks share an enable bit, so refcount the enable bits
b->u.shared_bus_user.rate;
}
+static void super_clk_set_u71_div_no_skip(struct clk *c)
+{
+ clk_writel_delay(c->u.cclk.div71 << SUPER_CLOCK_DIV_U71_SHIFT,
+ c->reg + SUPER_CLK_DIVIDER);
+ c->mul = 2;
+ c->div = c->u.cclk.div71 + 2;
+}
+
+static void super_clk_clr_u71_div_no_skip(struct clk *c)
+{
+ clk_writel_delay(0, c->reg + SUPER_CLK_DIVIDER);
+ c->mul = 2;
+ c->div = 2;
+}
+
/* clk_m functions */
static unsigned long tegra21_osc_autodetect_rate(struct clk *c)
{
{
pr_debug("%s on clock %s\n", __func__, c->name);
tegra21_osc_autodetect_rate(c);
+ c->state = ON;
}
static int tegra21_osc_enable(struct clk *c)
const struct clk_mux_sel *sel;
val = clk_readl(c->reg + SUPER_CLK_MUX);
c->state = ON;
-#ifndef CONFIG_ARCH_TEGRA_21x_SOC
BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-#endif
shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
source = (val >> shift) & SUPER_SOURCE_MASK;
val &= ~(SUPER_SOURCE_MASK << shift);
val |= (sel->value & SUPER_SOURCE_MASK) << shift;
- if (c->flags & DIV_U71) {
+ if ((c->flags & DIV_U71) && !c->u.cclk.div71) {
/* Make sure 7.1 divider is 1:1 */
u32 div = clk_readl(c->reg + SUPER_CLK_DIVIDER);
BUG_ON(div & SUPER_CLOCK_DIV_U71_MASK);
}
if (c->refcnt)
- clk_enable(p);
+ tegra_clk_prepare_enable(p);
clk_writel_delay(val, c->reg);
if (c->refcnt && c->parent)
- clk_disable(c->parent);
+ tegra_clk_disable_unprepare(c->parent);
clk_reparent(c, p);
return 0;
*/
static int tegra21_super_clk_set_rate(struct clk *c, unsigned long rate)
{
- /* In tegra21_cpu_clk_set_plls() and tegra21_sbus_cmplx_set_rate()
- * this call is skipped by directly setting rate of source plls. If we
- * ever use 7.1 divider at other than 1:1 setting, or exercise s/w
- * skipper control, not only this function, but cpu and sbus set_rate
- * APIs should be changed accordingly.
+ /*
+ * In tegra21_cpu_clk_set_plls(), tegra21_sbus_cmplx_set_rate(), and
+ * tegra21_adsp_cpu_clk_set_rate() this interface is skipped by directly
+ * setting rate of source plls.
*/
return clk_set_rate(c->parent, rate);
}
*/
static void tegra21_cpu_clk_init(struct clk *c)
{
- c->state = ON;
+ c->state = (!is_lp_cluster() == (c->u.cpu.mode == MODE_G)) ? ON : OFF;
}
static int tegra21_cpu_clk_enable(struct clk *c)
unsigned long old_rate)
{
int ret = 0;
+ bool dramp = false;
bool on_main = false;
unsigned long backup_rate, main_rate;
- unsigned long vco_min = c->u.cpu.main->u.pll.vco_min;
+ struct clk *main_pll = c->u.cpu.main;
/*
* Take an extra reference to the main pll so it doesn't turn off when
* lower current rate to pll VCO minimum level before switching to
* backup source.
*/
- if (c->parent->parent == c->u.cpu.main) {
- bool dramp = (rate > c->u.cpu.backup_rate) &&
- tegra21_is_dyn_ramp(c->u.cpu.main, rate, false);
- clk_enable(c->u.cpu.main);
+ if (c->parent->parent == main_pll) {
+ tegra_clk_prepare_enable(main_pll);
on_main = true;
+ main_rate = rate;
- if (dramp ||
- ((old_rate > vco_min) &&
- tegra21_is_dyn_ramp(c->u.cpu.main, vco_min, false))) {
- main_rate = dramp ? rate : vco_min;
- ret = clk_set_rate(c->u.cpu.main, main_rate);
+ dramp = (rate > c->u.cpu.backup_rate) &&
+ tegra_pll_can_ramp_to_rate(main_pll, rate);
+
+ if (dramp || tegra_pll_can_ramp_to_min(main_pll, &main_rate)) {
+ ret = clk_set_rate(main_pll, main_rate);
if (ret) {
pr_err("Failed to set cpu rate %lu on source"
- " %s\n", main_rate, c->u.cpu.main->name);
+ " %s\n", main_rate, main_pll->name);
goto out;
}
- if (dramp)
+
+ if (main_rate == rate)
goto out;
- } else if (old_rate > vco_min) {
-#if PLLX_USE_DYN_RAMP
- pr_warn("No dynamic ramp down: %s: %lu to %lu\n",
- c->u.cpu.main->name, old_rate, vco_min);
-#endif
+ } else if (main_pll->u.pll.dyn_ramp) {
+ pr_warn("%s: not ready for dynamic ramp to %lu\n",
+ main_pll->name, rate);
}
}
minimum. Use dynamic ramp to reach target rate if it is above VCO
minimum. */
main_rate = rate;
- if (rate > vco_min) {
- if (tegra21_is_dyn_ramp(c->u.cpu.main, rate, true))
- main_rate = vco_min;
-#if PLLX_USE_DYN_RAMP
- else
- pr_warn("No dynamic ramp up: %s: %lu to %lu\n",
- c->u.cpu.main->name, vco_min, rate);
-#endif
+ if (!tegra_pll_can_ramp_from_min(main_pll, rate, &main_rate)) {
+ if (main_pll->u.pll.dyn_ramp)
+ pr_warn("%s: not ready for dynamic ramp to %lu\n",
+ main_pll->name, rate);
}
- ret = clk_set_rate(c->u.cpu.main, main_rate);
+ ret = clk_set_rate(main_pll, main_rate);
if (ret) {
pr_err("Failed to set cpu rate %lu on source"
- " %s\n", main_rate, c->u.cpu.main->name);
+ " %s\n", main_rate, main_pll->name);
goto out;
}
- ret = clk_set_parent(c->parent, c->u.cpu.main);
+
+ ret = clk_set_parent(c->parent, main_pll);
if (ret) {
- pr_err("Failed to switch cpu to %s\n", c->u.cpu.main->name);
+ pr_err("Failed to switch cpu to %s\n", main_pll->name);
goto out;
}
+
if (rate != main_rate) {
- ret = clk_set_rate(c->u.cpu.main, rate);
+ ret = clk_set_rate(main_pll, rate);
if (ret) {
pr_err("Failed to set cpu rate %lu on source"
- " %s\n", rate, c->u.cpu.main->name);
+ " %s\n", rate, main_pll->name);
goto out;
}
}
out:
if (on_main)
- clk_disable(c->u.cpu.main);
+ tegra_clk_disable_unprepare(main_pll);
return ret;
}
" ready is not allowed\n");
return -ENOSYS;
}
- } else { /* for non silicon platform, return zero for now */
- return 0;
}
if (has_dfll && c->dvfs && c->dvfs->dvfs_rail) {
if (tegra_dvfs_is_dfll_range(c->dvfs, rate))
static void tegra21_cpu_cmplx_clk_init(struct clk *c)
{
- c->parent = c->inputs[0].input;
+ int i = is_lp_cluster() ? 1 : 0;
+
+ BUG_ON(c->inputs[0].input->u.cpu.mode != MODE_G);
+ BUG_ON(c->inputs[1].input->u.cpu.mode != MODE_LP);
+
+ c->parent = c->inputs[i].input;
}
/* cpu complex clock provides second level vitualization (on top of
const struct clk_mux_sel *sel;
unsigned long rate = clk_get_rate(c->parent);
struct clk *dfll = c->parent->u.cpu.dynamic ? : p->u.cpu.dynamic;
- struct clk *p_source_old = NULL;
- struct clk *p_source;
+ struct clk *c_source, *p_source;
pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+ if (!c->refcnt) {
+ WARN(1, "%s: cpu refcnt is 0: aborted switch from %s to %s\n",
+ __func__, c->parent->name, p->name);
+ return -EINVAL;
+ }
+ BUG_ON(c->parent->u.cpu.mode != (is_lp_cluster() ? MODE_LP : MODE_G));
for (sel = c->inputs; sel->input != NULL; sel++) {
if (sel->input == p)
flags |= TEGRA_POWER_CLUSTER_PART_DEFAULT;
delay = 0;
}
- flags |= TEGRA_POWER_CLUSTER_G;
+ flags |= (p->u.cpu.mode == MODE_LP) ? TEGRA_POWER_CLUSTER_LP :
+ TEGRA_POWER_CLUSTER_G;
if (p == c->parent) {
if (flags & TEGRA_POWER_CLUSTER_FORCE) {
}
tegra_dvfs_rail_mode_updating(tegra_cpu_rail, true);
- if (c->parent->parent->parent == dfll) {
- /* G (DFLL selected as clock source) => LP switch:
+ c_source = c->parent->parent->parent;
+ if (c_source == dfll) {
+ /*
+ * G (DFLL selected as clock source) => LP switch:
* turn DFLL into open loop mode ("release" VDD_CPU rail)
* select target p_source for LP, and get its rate ready
*/
goto abort;
} else if ((p->parent->parent == dfll) ||
(p->dvfs && tegra_dvfs_is_dfll_range(p->dvfs, rate))) {
- /* LP => G (DFLL selected as clock source) switch:
+ /*
+ * LP => G (DFLL selected as clock source) switch:
* set DFLL rate ready (DFLL is still disabled)
* (set target p_source as dfll, G source is already selected)
*/
p_source = dfll;
ret = clk_set_rate(dfll,
- tegra_dvfs_rail_is_dfll_mode(tegra_cpu_rail) ? rate :
max(rate, p->dvfs->dfll_data.use_dfll_rate_min));
if (ret)
goto abort;
-
- ret = tegra_dvfs_rail_dfll_mode_set_cold(tegra_cpu_rail, dfll);
- if (ret)
- goto abort;
- } else
- /* DFLL is not selected on either side of the switch:
+ } else {
+ /*
+ * DFLL is not selected on either side of the switch:
* set target p_source equal to current clock source
*/
- p_source = c->parent->parent->parent;
+ p_source = c_source;
+ }
/* Switch new parent to target clock source if necessary */
if (p->parent->parent != p_source) {
- clk_enable(p->parent->parent);
- clk_enable(p->parent);
- p_source_old = p->parent->parent;
ret = clk_set_parent(p->parent, p_source);
if (ret) {
pr_err("%s: Failed to set parent %s for %s\n",
}
}
- /* Enabling new parent scales new mode voltage rail in advanvce
- before the switch happens (if p_source is DFLL: open loop mode) */
- if (c->refcnt)
- clk_enable(p);
+ /*
+ * G=>LP switch with c_source DFLL in open loop mode: enabling new
+ * parent record voltage requirement for LP cluster; then restoration
+ * of legacy DVFS rail control scale voltage to max of G and LP required
+ * levels.
+ *
+ * For any other combination of sources, rail is already under legacy
+ * DVFS control, and enabling new parent scales new mode voltage rail
+ * in advanvce before the switch happens. If target p_source is DFLL it
+ * is switched here to open loop mode.
+ */
+ tegra_clk_prepare_enable(p);
+ if (c_source == dfll)
+ tegra_dvfs_dfll_mode_clear(c->parent->dvfs, rate);
/* switch CPU mode */
ret = tegra_cluster_control(delay, flags);
if (ret) {
- if (c->refcnt)
- clk_disable(p);
+ tegra_clk_disable_unprepare(p);
pr_err("%s: Failed to switch %s mode to %s\n",
__func__, c->name, p->name);
goto abort;
}
- /* Disabling old parent scales old mode voltage rail */
- if (c->refcnt)
- clk_disable(c->parent);
- if (p_source_old) {
- clk_disable(p->parent);
- clk_disable(p_source_old);
- }
-
- clk_reparent(c, p);
-
/*
* Lock DFLL now (resume closed loop VDD_CPU control).
* G CPU operations are resumed on DFLL if it was the last G CPU
* when auto-switch between PLL and DFLL is enabled.
*/
if (p_source == dfll) {
- if (tegra_dvfs_rail_is_dfll_mode(tegra_cpu_rail)) {
- tegra_clk_cfg_ex(dfll, TEGRA_CLK_DFLL_LOCK, 1);
- } else {
- clk_set_rate(dfll, rate);
- tegra_clk_cfg_ex(dfll, TEGRA_CLK_DFLL_LOCK, 1);
- tegra_dvfs_dfll_mode_set(p->dvfs, rate);
- }
+ clk_set_rate(dfll, rate);
+ tegra_clk_cfg_ex(dfll, TEGRA_CLK_DFLL_LOCK, 1);
+ tegra_dvfs_dfll_mode_set(p->dvfs, rate);
}
+ /* Disabling old parent scales old mode voltage rail */
+ tegra_clk_disable_unprepare(c->parent);
+
+ clk_reparent(c, p);
+
tegra_dvfs_rail_mode_updating(tegra_cpu_rail, false);
return 0;
abort:
/* Re-lock DFLL if necessary after aborted switch */
- if (c->parent->parent->parent == dfll) {
+ if (c_source == dfll) {
clk_set_rate(dfll, rate);
tegra_clk_cfg_ex(dfll, TEGRA_CLK_DFLL_LOCK, 1);
- }
- if (p_source_old) {
- clk_disable(p->parent);
- clk_disable(p_source_old);
+ tegra_dvfs_dfll_mode_set(c->parent->dvfs, rate);
}
tegra_dvfs_rail_mode_updating(tegra_cpu_rail, false);
.shared_bus_update = tegra21_clk_sbus_update,
};
-/* Blink output functions */
+/*
+ * Virtual ADSP CPU clock operations. Used to hide the sequence of changing
+ * and re-locking ADSP source PLLA1 in flight to configure requested ADSP
+ * target rate.
+ */
+static void tegra21_adsp_cpu_clk_init(struct clk *c)
+{
+ c->state = c->parent->state;
+ c->min_rate = c->u.cpu.main->min_rate;
+}
+
+static int tegra21_adsp_cpu_clk_enable(struct clk *c)
+{
+ return 0;
+}
+
+static void tegra21_adsp_cpu_clk_disable(struct clk *c)
+{
+}
+
+static int tegra21_adsp_cpu_clk_set_rate(struct clk *c, unsigned long rate)
+{
+ int ret = 0;
+ struct clk *main_pll = c->u.cpu.main;
+
+ /*
+ * If ADSP clock is disabled or it is not on main pll (may happen after
+ * boot), set main pll rate, and make sure it is selected as adsp clock
+ * source.
+ */
+ if (!c->refcnt || (c->parent->parent != main_pll)) {
+ ret = clk_set_rate(main_pll, rate);
+ if (ret) {
+ pr_err("Failed to set adsp rate %lu on %s\n",
+ rate, main_pll->name);
+ return ret;
+ }
+
+ if (c->parent->parent == main_pll)
+ return ret;
+
+ ret = clk_set_parent(c->parent, main_pll);
+ if (ret)
+ pr_err("Failed to switch adsp to %s\n", main_pll->name);
+
+ return ret;
+ }
+
+ /*
+ * Take an extra reference to the main pll so it doesn't turn off when
+ * we move the cpu off of it. If possible, use main pll dynamic ramp
+ * to reach target rate in one shot. Otherwise use backup source while
+ * re-locking main.
+ */
+ tegra_clk_prepare_enable(main_pll);
+
+ if (tegra_pll_can_ramp_to_rate(main_pll, rate)) {
+ ret = clk_set_rate(main_pll, rate);
+ if (ret)
+ pr_err("Failed to ramp %s to adsp rate %lu\n",
+ main_pll->name, rate);
+ goto out;
+ }
+
+ /* Set backup divider, and switch to backup source */
+ super_clk_set_u71_div_no_skip(c->parent);
+ ret = clk_set_parent(c->parent, c->u.cpu.backup);
+ if (ret) {
+ super_clk_clr_u71_div_no_skip(c->parent);
+ pr_err("Failed to switch adsp to %s\n", c->u.cpu.backup->name);
+ goto out;
+ }
+
+ /* Set main pll rate, switch back to main, and clear backup divider */
+ ret = clk_set_rate(main_pll, rate);
+ if (ret) {
+ pr_err("Failed set adsp rate %lu on %s\n",
+ rate, main_pll->name);
+ goto out;
+ }
+
+ ret = clk_set_parent(c->parent, main_pll);
+ if (ret) {
+ pr_err("Failed to switch adsp to %s\n", main_pll->name);
+ goto out;
+ }
+ super_clk_clr_u71_div_no_skip(c->parent);
+
+out:
+ tegra_clk_disable_unprepare(main_pll);
+ return ret;
+}
+
+static long tegra21_adsp_cpu_clk_round_rate(struct clk *c, unsigned long rate)
+{
+ if (rate > c->max_rate)
+ rate = c->max_rate;
+ else if (rate < c->min_rate)
+ rate = c->min_rate;
+ return rate;
+}
+
+static struct clk_ops tegra_adsp_cpu_ops = {
+ .init = tegra21_adsp_cpu_clk_init,
+ .enable = tegra21_adsp_cpu_clk_enable,
+ .disable = tegra21_adsp_cpu_clk_disable,
+ .set_rate = tegra21_adsp_cpu_clk_set_rate,
+ .round_rate = tegra21_adsp_cpu_clk_round_rate,
+};
+/* Blink output functions */
static void tegra21_blink_clk_init(struct clk *c)
{
u32 val;
val = pmc_readl(PMC_CTRL);
pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
+ pmc_readl(PMC_CTRL);
return 0;
}
val = pmc_readl(PMC_DPD_PADS_ORIDE);
pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+ pmc_readl(PMC_DPD_PADS_ORIDE);
}
static int tegra21_blink_clk_set_rate(struct clk *c, unsigned long rate)
val |= PMC_BLINK_TIMER_ENB;
pmc_writel(val, c->reg);
}
+ pmc_readl(c->reg);
return 0;
}
};
/* UTMIP PLL configuration */
-static void usb_plls_hw_control_enable(u32 reg)
-{
- u32 val = clk_readl(reg);
- val |= USB_PLLS_USE_LOCKDET | USB_PLLS_SEQ_START_STATE;
- val &= ~USB_PLLS_ENABLE_SWCTL;
- val |= USB_PLLS_SEQ_START_STATE;
- pll_writel_delay(val, reg);
-
- val |= USB_PLLS_SEQ_ENABLE;
- pll_writel_delay(val, reg);
-}
-
static void tegra21_utmi_param_configure(struct clk *c)
{
u32 reg;
pll_writel_delay(PLLCX_MISC3_DEFAULT_VALUE, c->reg + c->u.pll.misc3);
}
+#if PLLCX_USE_DYN_RAMP
static int pllcx_dyn_ramp(struct clk *c, struct clk_pll_freq_table *cfg)
{
-#if PLLCX_USE_DYN_RAMP
u32 reg;
struct clk_pll_controls *ctrl = c->u.pll.controls;
struct clk_pll_div_layout *divs = c->u.pll.div_layout;
tegra_pll_clk_wait_for_lock(c, reg, ctrl->lock_mask);
return 0;
+}
#else
- return -ENOSYS;
+#define pllcx_dyn_ramp NULL
#endif
-}
static void tegra21_pllcx_clk_init(struct clk *c)
{
static void tegra21_pllc4_vco_init(struct clk *c)
{
+ unsigned long input_rate = clk_get_rate(c->parent);
+ unsigned long cf = input_rate / pll_get_fixed_mdiv(c, input_rate);
+ pllc4_set_fixed_rates(cf);
+
plldss_select_ref(c);
tegra_pll_clk_init(c);
}
pll_clk_set_gain(c, &cfg);
pll_clk_verify_fixed_rate(c);
+ pr_info("%s: boot with h/w control already set\n", c->name);
return;
}
tegra_pll_clk_init(c);
}
+static void tegra21_pllu_hw_ctrl_set(struct clk *c)
+{
+ u32 val = clk_readl(c->reg);
+
+ /* Put PLLU under h/w control (if not already) */
+ if (val & PLLU_BASE_OVERRIDE) {
+ val &= ~PLLU_BASE_OVERRIDE;
+ pll_writel_delay(val, c->reg);
+
+ val = clk_readl(PLLU_HW_PWRDN_CFG0);
+ val |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
+ PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
+ PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
+ val &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
+ PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
+ clk_writel(val, PLLU_HW_PWRDN_CFG0);
+
+ val = clk_readl(XUSB_PLL_CFG0);
+ val &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK;
+ pll_writel_delay(val, XUSB_PLL_CFG0);
+
+ val = clk_readl(PLLU_HW_PWRDN_CFG0);
+ val |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
+ pll_writel_delay(val, PLLU_HW_PWRDN_CFG0);
+ }
+
+
+ /* Put UTMI PLL under h/w control (if not already) */
+ val = clk_readl(UTMIPLL_HW_PWRDN_CFG0);
+ if (!(val & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE))
+ tegra21_utmi_param_configure(c);
+}
+
+int tegra21_pllu_clk_enable(struct clk *c)
+{
+ int ret = tegra_pll_clk_enable(c);
+ if (ret)
+ return ret;
+
+ tegra21_pllu_hw_ctrl_set(c);
+ return 0;
+}
+
static struct clk_ops tegra_pllu_vco_ops = {
.init = tegra21_pllu_vco_init,
- .enable = tegra_pll_clk_enable,
+ .enable = tegra21_pllu_clk_enable,
.disable = tegra_pll_clk_disable,
.set_rate = tegra_pll_clk_set_rate,
};
pll_writel_delay(PLLX_MISC5_DEFAULT_VALUE, c->reg + c->u.pll.misc5);
}
+#if PLLX_USE_DYN_RAMP
static int pllx_dyn_ramp(struct clk *c, struct clk_pll_freq_table *cfg)
{
-#if PLLX_USE_DYN_RAMP
u32 reg, val, base, ndiv_new_mask;
struct clk_pll_controls *ctrl = c->u.pll.controls;
struct clk_pll_div_layout *divs = c->u.pll.div_layout;
val &= ~ctrl->dramp_en_mask;
pll_writel_delay(val, reg);
+ pr_debug("%s: dynamic ramp to ndiv = %u\n", c->name, cfg->n);
+
return 0;
-#else
- return -ENOSYS;
-#endif
}
+#endif
static void tegra21_pllx_clk_init(struct clk *c)
{
* PLLE
* Analog interpolator based SS PLL (with optional SDM SS - not used).
*/
-static inline void select_pll_e_input(u32 aux_reg)
+static inline void select_pll_e_input(struct clk *c)
{
+ u32 aux_reg = clk_readl(PLLE_AUX);
#if USE_PLLE_INPUT_PLLRE
aux_reg |= PLLE_AUX_PLLRE_SEL;
+ c->parent = c->inputs[2].input;
#else
aux_reg &= ~(PLLE_AUX_PLLRE_SEL | PLLE_AUX_PLLP_SEL);
+ c->parent = c->inputs[0].input;
#endif
pll_writel_delay(aux_reg, PLLE_AUX);
}
if (c->state == ON) {
WARN(1, "%s: pll_e is left enabled with %s input\n",
__func__, c->parent->name);
- } else {
- c->parent = ref;
- select_pll_e_input(val);
}
}
}
val = clk_readl(c->reg + c->u.pll.misc0);
val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE;
pll_writel_delay(val, c->reg + c->u.pll.misc0);
-
-/* FIXME: Disable for initial Si bringup */
-#if 0
- /* Set XUSB PLL pad pwr override and iddq */
- val = xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
- val |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_PWR_OVRD;
- val |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_IDDQ;
- xusb_padctl_writel(val, XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
- xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-#endif
}
static int tegra21_plle_clk_enable(struct clk *c)
return 0;
}
+ /* Fixed per prod settings input */
+ select_pll_e_input(c);
+ input_rate = clk_get_rate(c->parent);
+
/* PLLE config must be tabulated */
for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
if (sel->input_rate == input_rate && sel->output_rate == rate)
clk_writel(val, c->reg + c->u.pll.misc0);
val = clk_readl(PLLE_AUX);
- val |= PLLE_AUX_USE_LOCKDET;
- val &= ~PLLE_AUX_ENABLE_SWCTL;
+ val |= PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE;
+ val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL);
pll_writel_delay(val, PLLE_AUX);
val |= PLLE_AUX_SEQ_ENABLE;
pll_writel_delay(val, PLLE_AUX);
#endif
-
-/* FIXME: Disable for initial Si bringup */
-#if 0
- /* clear XUSB PLL pad pwr override and iddq */
- val = xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
- val &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_PWR_OVRD;
- val &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_IDDQ;
- xusb_padctl_writel(val, XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
- xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-#endif
-
- /* enable hw control of xusb brick pll */
- usb_plls_hw_control_enable(XUSBIO_PLL_CFG0);
-
return 0;
}
-#ifdef CONFIG_PM_SLEEP
-static void tegra21_plle_clk_resume(struct clk *c)
-{
- u32 val = clk_readl(c->reg);
- if (val & PLLE_BASE_ENABLE)
- return; /* already resumed */
-
- /* Restore parent */
- val = clk_readl(PLLE_AUX);
- select_pll_e_input(val);
-}
-#endif
-
static struct clk_ops tegra_plle_ops = {
.init = tegra21_plle_clk_init,
.enable = tegra21_plle_clk_enable,
};
/*
- * Tegra12 includes dynamic frequency lock loop (DFLL) with automatic voltage
+ * Tegra21 includes dynamic frequency lock loop (DFLL) with automatic voltage
* control as possible CPU clock source. It is included in the Tegra12 clock
* tree as "complex PLL" with standard Tegra clock framework APIs. However,
* DFLL locking logic h/w access APIs are separated in the tegra_cl_dvfs.c
*/
/* DFLL operations */
-static void __init tegra21_dfll_cpu_late_init(struct clk *c)
-{
-#ifdef CONFIG_ARCH_TEGRA_HAS_CL_DVFS
- int ret;
- struct clk *cpu = tegra_get_clock_by_name("cpu_g");
-
- if (!cpu || !cpu->dvfs) {
- pr_err("%s: CPU dvfs is not present\n", __func__);
- return;
- }
-
- /* release dfll clock source reset, init cl_dvfs control logic, and
- move dfll to initialized state, so it can be used as CPU source */
- tegra_periph_reset_deassert(c);
- ret = tegra_init_cl_dvfs();
- if (!ret) {
- c->state = OFF;
- c->u.dfll.cl_dvfs = platform_get_drvdata(&tegra_cl_dvfs_device);
- if (tegra_platform_is_silicon())
- use_dfll = CONFIG_TEGRA_USE_DFLL_RANGE;
- tegra_dvfs_set_dfll_range(cpu->dvfs, use_dfll);
- tegra_cl_dvfs_debug_init(c);
- pr_info("Tegra CPU DFLL is initialized with use_dfll = %d\n", use_dfll);
- }
-#endif
-}
-
-static void tegra21_dfll_clk_init(struct clk *c)
+static void __init tegra21_dfll_clk_init(struct clk *c)
{
c->ops->init = tegra21_dfll_cpu_late_init;
}
unsigned long c_flags, p_flags;
unsigned int old_use_dfll;
struct clk *c = tegra_get_clock_by_name("cpu");
+ struct clk *dfll = tegra_get_clock_by_name("dfll_cpu");
if (!c->parent || !c->parent->dvfs)
return -ENOSYS;
+ ret = tegra_cpu_reg_mode_force_normal(true);
+ if (ret) {
+ pr_err("%s: Failed to force regulator normal mode\n", __func__);
+ return ret;
+ }
+
clk_lock_save(c, &c_flags);
+ if (dfll->state == UNINITIALIZED) {
+ pr_err("%s: DFLL is not initialized\n", __func__);
+ clk_unlock_restore(c, &c_flags);
+ tegra_cpu_reg_mode_force_normal(false);
+ return -ENOSYS;
+ }
+
+ if (c->parent->u.cpu.mode == MODE_LP) {
+ pr_err("%s: DFLL is not used on LP CPU\n", __func__);
+ clk_unlock_restore(c, &c_flags);
+ tegra_cpu_reg_mode_force_normal(false);
+ return -ENOSYS;
+ }
clk_lock_save(c->parent, &p_flags);
old_use_dfll = use_dfll;
}
clk_unlock_restore(c->parent, &p_flags);
clk_unlock_restore(c, &c_flags);
- tegra_recalculate_cpu_edp_limits();
+ tegra_update_cpu_edp_limits();
return ret;
}
.enable = tegra_pll_out_clk_enable,
};
-static void tegra21_pllu_hw_ctrl_set(struct clk *c)
-{
- u32 val = clk_readl(c->reg);
-
- /* Put UTMI PLL under h/w control */
- tegra21_utmi_param_configure(c);
-
- /* Put PLLU under h/w control */
- usb_plls_hw_control_enable(PLLU_HW_PWRDN_CFG0);
-
- if (val & PLLU_BASE_OVERRIDE) {
- val &= ~PLLU_BASE_OVERRIDE;
- pll_writel_delay(val, c->reg);
- } else {
- /* FIXME: should it be WARN() ? */
- pr_info("%s: boot with h/w control already set\n", c->name);
- }
-
-/* FIXME: Disable for initial Si bringup */
-#if 0
- /* Set XUSB PLL pad pwr override and iddq */
- val = xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
- val |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_PWR_OVRD;
- val |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0_PLL_IDDQ;
- xusb_padctl_writel(val, XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
- xusb_padctl_readl(XUSB_PADCTL_IOPHY_PLL_P0_CTL1_0);
-#endif
-}
-
static void tegra21_pllu_out_clk_init(struct clk *c)
{
u32 p, val;
/* Complete PLLU output s/w controlled initialization */
tegra_pll_out_clk_init(c);
}
-
- /* Put USB plls under h/w control */
- tegra21_pllu_hw_ctrl_set(pll);
}
static struct clk_ops tegra_pllu_out_ops = {
{
if (c->flags & DIV_U71) {
u32 val, divu71;
- if (c->parent->state == OFF)
+ if ((c->parent->state == OFF) || (!c->parent->ops->disable &&
+ (c->parent->parent->state == OFF)))
c->ops->disable(c);
val = clk_readl(c->reg);
c->parent = mux->input;
} else {
- if (c->flags & PLLU) {
- /* for xusb_hs clock enforce SS div2 source */
- val &= ~periph_clk_source_mask(c);
- clk_writel_delay(val, c->reg);
- }
c->parent = c->inputs[0].input;
}
u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
c->div = divu16 + 1;
c->mul = 1;
- } else {
+ } else if (!c->div || !c->mul) {
c->div = 1;
c->mul = 1;
}
return 0;
}
- /* FIXME: WAR for HW bug 1438604 */
- if (!(tegra_platform_is_linsim() &&
- (!strcmp(c->name, "nvjpg") || !strcmp(c->name, "nvdec"))))
- clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_SET_REG(c));
+ clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_SET_REG(c));
if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET)) {
if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c)) {
udelay(RESET_PROPAGATION_DELAY);
- clk_writel(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_RST_CLR_REG(c));
+ clk_writel_delay(PERIPH_CLK_TO_BIT(c),
+ PERIPH_CLK_TO_RST_CLR_REG(c));
}
}
spin_unlock_irqrestore(&periph_refcount_lock, flags);
if (c->flags & PERIPH_ON_APB)
val = chipid_readl();
- /* FIXME: WAR for HW bug 1438604 */
- if (!(tegra_platform_is_linsim() &&
- (!strcmp(c->name, "nvjpg") || !strcmp(c->name, "nvdec"))))
- clk_writel_delay(
- PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c));
+ clk_writel_delay(PERIPH_CLK_TO_BIT(c),
+ PERIPH_CLK_TO_ENB_CLR_REG(c));
}
spin_unlock_irqrestore(&periph_refcount_lock, flags);
}
if (c->flags & PERIPH_ON_APB)
val = chipid_readl();
- clk_writel(PERIPH_CLK_TO_BIT(c),
- PERIPH_CLK_TO_RST_SET_REG(c));
+ clk_writel_delay(PERIPH_CLK_TO_BIT(c),
+ PERIPH_CLK_TO_RST_SET_REG(c));
} else
- clk_writel(PERIPH_CLK_TO_BIT(c),
- PERIPH_CLK_TO_RST_CLR_REG(c));
+ clk_writel_delay(PERIPH_CLK_TO_BIT(c),
+ PERIPH_CLK_TO_RST_CLR_REG(c));
}
}
val |= (sel->value << periph_clk_source_shift(c));
if (c->refcnt)
- clk_enable(p);
+ tegra_clk_prepare_enable(p);
clk_writel_delay(val, c->reg);
if (c->refcnt && c->parent)
- clk_disable(c->parent);
+ tegra_clk_disable_unprepare(c->parent);
clk_reparent(c, p);
return 0;
/* Supper skipper ops */
static void tegra21_clk_super_skip_init(struct clk *c)
{
- u32 val = clk_readl(c->reg);
-
if (!c->parent)
c->parent = c - 1;
c->parent->skipper = c;
c->state = ON;
c->max_rate = c->parent->max_rate;
- if (val & SUPER_SKIPPER_ENABLE) {
- c->div = ((val & SUPER_SKIPPER_DIV_MASK) >>
- SUPER_SKIPPER_DIV_SHIFT) + 1;
- c->mul = ((val & SUPER_SKIPPER_MUL_MASK) >>
- SUPER_SKIPPER_MUL_SHIFT) + 1;
- } else {
- c->div = 1;
- c->mul = 1;
- }
+ /* Always set initial 1:1 ratio */
+ clk_writel(0, c->reg);
+ c->div = 1;
+ c->mul = 1;
}
static int tegra21_clk_super_skip_enable(struct clk *c)
c->mul = 1;
}
- /* FIXME: for SCLK c->reg, this write to be replaced with IPC to BPMP */
- clk_writel(val, c->reg);
-
+#ifdef CONFIG_TEGRA_BPMP_SCLK_SKIP
+ /* For SCLK do not touch the register directly - send IPC to BPMP */
+ if (c->flags & DIV_BUS)
+ tegra_bpmp_sclk_skip_set_rate(input_rate, rate);
+ else
+#endif
+ clk_writel(val, c->reg);
+
clk_unlock_restore(c->parent, &flags);
return 0;
}
.shared_bus_update = &tegra21_clk_1xbus_update,
};
-/* Periph extended clock configuration ops */
+/* Periph VI extended clock configuration ops */
static int
tegra21_vi_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
{
.reset = &tegra21_periph_clk_reset,
};
+/* SOR clocks operations */
+static void tegra21_sor_brick_init(struct clk *c)
+{
+ /*
+ * Brick configuration is under DC driver control - wiil be in sync
+ * with h/w after DC SOR init.
+ */
+ c->parent = c->inputs[0].input;
+ c->state = c->parent->state;
+ c->div = 10;
+ c->mul = 10;
+ return;
+}
+
+static int tegra21_sor_brick_set_rate(struct clk *c, unsigned long rate)
+{
+ /*
+ * Brick rate is under DC driver control, this interface is used for
+ * information purposes, as well as for DVFS update.
+ */
+ unsigned long parent_rate = clk_get_rate(c->parent);
+ u64 mul = 10;
+ c->div = 10; /* brick link divisor */
+
+ mul = mul * rate + parent_rate / 2;
+ do_div(mul, parent_rate);
+ c->mul = mul;
+
+ return 0;
+}
+
+static int tegra21_sor_brick_set_parent(struct clk *c, struct clk *p)
+{
+ u32 val;
+ const struct clk_mux_sel *sel;
+
+ if (!(c->flags & MUX))
+ return (p == c->parent) ? 0 : (-EINVAL);
+ /*
+ * Brick parent selection is under DC driver control, this interface
+ * is used to propagate enable/disable relations, for information
+ * purposes, as well as for DVFS update.
+ */
+ for (sel = c->inputs; sel->input != NULL; sel++) {
+ if (sel->input == p) {
+ if (c->refcnt) {
+ tegra_clk_prepare_enable(p);
+ tegra_clk_disable_unprepare(c->parent);
+ }
+ clk_reparent(c, p);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static struct clk_ops tegra_sor_brick_ops = {
+ .init = &tegra21_sor_brick_init,
+ .enable = &tegra21_periph_clk_enable,
+ .disable = &tegra21_periph_clk_disable,
+ .set_parent = &tegra21_sor_brick_set_parent,
+ .set_rate = &tegra21_sor_brick_set_rate,
+};
+
+static void tegra21_sor0_clk_init(struct clk *c)
+{
+ c->u.periph.src_mask = PERIPH_CLK_SOR0_CLK_SEL_MASK;
+ c->u.periph.src_shift = PERIPH_CLK_SOR_CLK_SEL_SHIFT;
+ tegra21_periph_clk_init(c);
+}
+
static int
-tegra21_sor_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+tegra21_sor0_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
{
if (p == TEGRA_CLK_SOR_CLK_SEL) {
- u32 val = clk_readl(c->reg);
- val &= ~PERIPH_CLK_SOR_CLK_SEL_MASK;
- val |= (setting << PERIPH_CLK_SOR_CLK_SEL_SHIFT) &
- PERIPH_CLK_SOR_CLK_SEL_MASK;
- clk_writel(val, c->reg);
- return 0;
+ int i = setting ? 1 : 0;
+ return tegra21_periph_clk_set_parent(c, c->inputs[i].input);
}
return -EINVAL;
}
-static struct clk_ops tegra_sor_clk_ops = {
- .init = &tegra21_periph_clk_init,
+static struct clk_ops tegra_sor0_clk_ops = {
+ .init = &tegra21_sor0_clk_init,
.enable = &tegra21_periph_clk_enable,
.disable = &tegra21_periph_clk_disable,
.set_parent = &tegra21_periph_clk_set_parent,
- .set_rate = &tegra21_periph_clk_set_rate,
- .round_rate = &tegra21_periph_clk_round_rate,
- .clk_cfg_ex = &tegra21_sor_clk_cfg_ex,
+ .clk_cfg_ex = &tegra21_sor0_clk_cfg_ex,
.reset = &tegra21_periph_clk_reset,
};
+static void tegra21_sor1_clk_init(struct clk *c)
+{
+ c->u.periph.src_mask = PERIPH_CLK_SOR1_CLK_SEL_MASK;
+ c->u.periph.src_shift = PERIPH_CLK_SOR_CLK_SEL_SHIFT;
+ tegra21_periph_clk_init(c);
+}
+
+static int tegra21_sor1_clk_set_parent(struct clk *c, struct clk *p)
+{
+ u32 val;
+ unsigned long flags;
+ const struct clk_mux_sel *sel;
+ struct clk *src = c->inputs[2].input; /* sor1_src entry in sor1 mux */
+
+ for (sel = c->inputs; sel->input != NULL; sel++) {
+ if (sel->input == p) {
+ if (c->refcnt)
+ tegra_clk_prepare_enable(p);
+ /*
+ * Since sor1 output mux control setting share the same
+ * register with source mux/divider switch, use switch
+ * lock to protect r-m-w of output mux controls
+ */
+ clk_lock_save(src, &flags);
+ val = clk_readl(c->reg);
+ val &= ~periph_clk_source_mask(c);
+ val |= (sel->value << periph_clk_source_shift(c));
+ clk_writel_delay(val, c->reg);
+ clk_unlock_restore(src, &flags);
+
+ if (c->refcnt)
+ tegra_clk_disable_unprepare(c->parent);
+
+ clk_reparent(c, p);
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int
+tegra21_sor1_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
+{
+
+ if ((p != TEGRA_CLK_SOR_CLK_SEL) || (setting > 3))
+ return -EINVAL;
+ /*
+ * If LSb is set, sor1_brick is selected regardless of MSb. As such
+ * setting 3 and 1 result in the same clock source. The set parent api
+ * always selects the 1st match for requested parent, so effectively
+ * setting 3 is reduced to 1.
+ */
+ return tegra21_sor1_clk_set_parent(c, c->inputs[setting].input);
+}
+
+static struct clk_ops tegra_sor1_clk_ops = {
+ .init = &tegra21_sor1_clk_init,
+ .enable = &tegra21_periph_clk_enable,
+ .disable = &tegra21_periph_clk_disable,
+ .set_parent = &tegra21_sor1_clk_set_parent,
+ .clk_cfg_ex = &tegra21_sor1_clk_cfg_ex,
+ .reset = &tegra21_periph_clk_reset,
+};
+
+/* Periph DTV extended clock configuration ops */
static int
tegra21_dtv_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
{
.reset = &tegra21_periph_clk_reset,
};
+/* FIXME: this now just periph ops, can be removed */
static struct clk_ops tegra_dsi_clk_ops = {
.init = &tegra21_periph_clk_init,
.enable = &tegra21_periph_clk_enable,
val = pmc_readl(c->reg);
val |= (0x1 << c->u.periph.clk_num);
pmc_writel(val, c->reg);
+ pmc_readl(c->reg);
spin_unlock_irqrestore(&clk_out_lock, flags);
return 0;
val = pmc_readl(c->reg);
val &= ~(0x1 << c->u.periph.clk_num);
pmc_writel(val, c->reg);
+ pmc_readl(c->reg);
spin_unlock_irqrestore(&clk_out_lock, flags);
}
for (sel = c->inputs; sel->input != NULL; sel++) {
if (sel->input == p) {
if (c->refcnt)
- clk_enable(p);
+ tegra_clk_prepare_enable(p);
spin_lock_irqsave(&clk_out_lock, flags);
val = pmc_readl(c->reg);
val &= ~periph_clk_source_mask(c);
val |= (sel->value << periph_clk_source_shift(c));
pmc_writel(val, c->reg);
+ pmc_readl(c->reg);
spin_unlock_irqrestore(&clk_out_lock, flags);
if (c->refcnt && c->parent)
- clk_disable(c->parent);
+ tegra_clk_disable_unprepare(c->parent);
clk_reparent(c, p);
return 0;
if (div_value == c->div)
return 0;
} else if (c->refcnt)
- clk_enable(p);
+ tegra_clk_prepare_enable(p);
ret = tegra_emc_set_rate_on_parent(rate, p);
if (ret < 0)
if (p != c->parent) {
if(c->refcnt && c->parent)
- clk_disable(c->parent);
+ tegra_clk_disable_unprepare(c->parent);
clk_reparent(c, p);
}
c->div = div_value;
val |= sel->value;
if (c->refcnt)
- clk_enable(p);
+ tegra_clk_prepare_enable(p);
clk_writel(val, c->reg);
if (c->refcnt && c->parent)
- clk_disable(c->parent);
+ tegra_clk_disable_unprepare(c->parent);
clk_reparent(c, p);
return 0;
bool up)
{
int i;
- const int *millivolts;
if (!c->dvfs) {
if (!c->min_rate)
}
rate = max(rate, c->min_rate);
- millivolts = tegra_dvfs_get_millivolts_pll(c->dvfs);
for (i = 0; ; i++) {
unsigned long f = c->dvfs->freqs[i];
- int mv = millivolts[i];
- if ((f >= rate) || (mv >= c->dvfs->max_millivolts) ||
- ((i + 1) >= c->dvfs->num_freqs)) {
+ if ((f >= rate) || ((i + 1) >= c->dvfs->num_freqs)) {
if (!up && i && (f > rate))
i--;
break;
u.shared_bus_user.node) {
struct clk *client = user->u.shared_bus_user.client;
if (client && client->refcnt && (client->parent == c->parent)) {
- ret = tegra_dvfs_set_rate(c, rate);
+ ret = tegra_dvfs_set_rate(client, rate);
if (ret)
return ret;
}
struct clk *user;
unsigned long rate;
+ if (!(c->shared_bus_flags & SHARED_BUS_USE_SKIPPERS))
+ return;
+
list_for_each_entry(user, &c->shared_bus_list,
u.shared_bus_user.node) {
struct clk *client = user->u.shared_bus_user.client;
if (rate == 0)
return 0;
- ret = clk_enable(c->parent);
+ ret = tegra_clk_prepare_enable(c->parent);
if (ret) {
pr_err("%s: failed to enable %s clock: %d\n",
__func__, c->name, ret);
return ret;
}
- dramp = tegra21_is_dyn_ramp(c->parent, rate * c->div, false);
+ dramp = tegra_pll_can_ramp_to_rate(c->parent, rate * c->div);
if (!dramp) {
c->shared_bus_backup.value = get_next_backup_div(c, rate);
ret = cbus_backup(c);
cbus_skip(c, rate);
out:
- clk_disable(c->parent);
+ tegra_clk_disable_unprepare(c->parent);
return ret;
}
static inline void cbus_move_enabled_user(
struct clk *user, struct clk *dst, struct clk *src)
{
- clk_enable(dst);
+ tegra_clk_prepare_enable(dst);
list_move_tail(&user->u.shared_bus_user.node, &dst->shared_bus_list);
- clk_disable(src);
+ tegra_clk_disable_unprepare(src);
clk_reparent(user, dst);
}
return -EINVAL;
if (c->refcnt)
- clk_enable(p);
+ tegra_clk_prepare_enable(p);
list_move_tail(&c->u.shared_bus_user.node, &p->shared_bus_list);
ret = tegra_clk_shared_bus_update(p);
list_move_tail(&c->u.shared_bus_user.node,
&c->parent->shared_bus_list);
tegra_clk_shared_bus_update(c->parent);
- clk_disable(p);
+ tegra_clk_disable_unprepare(p);
return ret;
}
tegra_clk_shared_bus_update(c->parent);
if (c->refcnt)
- clk_disable(c->parent);
+ tegra_clk_disable_unprepare(c->parent);
clk_reparent(c, p);
rate = c->parent->max_rate;
} else {
/* Skippers allow to run below bus minimum */
+ bool use_skip = c->parent->shared_bus_flags &
+ SHARED_BUS_USE_SKIPPERS;
struct clk *client = c->u.shared_bus_user.client;
- int skip = (client && client->skipper) ?
+ int skip = (use_skip && client && client->skipper) ?
SUPER_SKIPPER_TERM_SIZE : 0;
unsigned long min_rate = c->parent->min_rate >> skip;
c->u.shared_bus_user.enabled = true;
ret = tegra_clk_shared_bus_update_locked(c->parent);
if (!ret && c->u.shared_bus_user.client)
- ret = clk_enable(c->u.shared_bus_user.client);
+ ret = tegra_clk_prepare_enable(c->u.shared_bus_user.client);
clk_unlock_restore(c->parent, &flags);
if (!ret && c->cross_clk_mutex && clk_cansleep(c))
clk_lock_save(c->parent, &flags);
if (c->u.shared_bus_user.client)
- clk_disable(c->u.shared_bus_user.client);
+ tegra_clk_disable_unprepare(c->u.shared_bus_user.client);
c->u.shared_bus_user.enabled = false;
tegra_clk_shared_bus_update_locked(c->parent);
clk_unlock_restore(c->parent, &flags);
if (sel->input == c->parent)
continue;
- ret = clk_enable(sel->input);
+ ret = tegra_clk_prepare_enable(sel->input);
if (ret) {
while (sel != c->inputs) {
sel--;
if (sel->input == c->parent)
continue;
- clk_disable(sel->input);
+ tegra_clk_disable_unprepare(sel->input);
}
return ret;
}
continue;
if (sel->input->set) /* enforce coupling after boot only */
- clk_disable(sel->input);
+ tegra_clk_disable_unprepare(sel->input);
}
}
};
static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
- { 12000000, 282240000, 46, 1, 2, 1, 4424}, /* actual: 282240234 */
- { 12000000, 368640000, 60, 1, 2, 1, 7701}, /* actual: 368640381 */
+ { 12000000, 282240000, 47, 1, 2, 1, 0xf148}, /* actual: 282240234 */
+ { 12000000, 368640000, 61, 1, 2, 1, 0xfe15}, /* actual: 368640381 */
{ 12000000, 240000000, 60, 1, 3, 1, },
- { 13000000, 282240000, 42, 1, 2, 1, 7549}, /* actual: 282239807 */
- { 13000000, 368640000, 55, 1, 2, 1, 9944}, /* actual: 368640137 */
+ { 13000000, 282240000, 43, 1, 2, 1, 0xfd7d}, /* actual: 282239807 */
+ { 13000000, 368640000, 56, 1, 2, 1, 0x06d8}, /* actual: 368640137 */
{ 13000000, 240000000, 55, 1, 3, 1, }, /* actual: 238.3 MHz */
- { 38400000, 282240000, 43, 3, 2, 1, 4915}, /* actual: 282239844 */
- { 38400000, 368640000, 56, 3, 2, 1, 9011}, /* actual: 368639844 */
+ { 38400000, 282240000, 44, 3, 2, 1, 0xf333}, /* actual: 282239844 */
+ { 38400000, 368640000, 57, 3, 2, 1, 0x0333}, /* actual: 368639844 */
{ 38400000, 240000000, 75, 3, 4, 1,},
{ 0, 0, 0, 0, 0, 0 },
};
static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
{ 12000000, 594000000, 99, 1, 2},
- { 13000000, 594000000, 90, 1, 2, 0, 7247}, /* actual: 594000183 */
- { 38400000, 594000000, 91, 3, 2, 0, 10752},
+ { 13000000, 594000000, 91, 1, 2, 0, 0xfc4f}, /* actual: 594000183 */
+ { 38400000, 594000000, 92, 3, 2, 0, 0x0a00},
{ 0, 0, 0, 0, 0, 0 },
};
static struct clk_pll_freq_table tegra_pll_d2_freq_table[] = {
{ 12000000, 594000000, 99, 1, 2},
- { 13000000, 594000000, 90, 1, 2, 0, 7247}, /* actual: 594000183 */
- { 38400000, 594000000, 91, 3, 2, 0, 10752},
+ { 13000000, 594000000, 91, 1, 2, 0, 0xfc4f}, /* actual: 594000183 */
+ { 38400000, 594000000, 92, 3, 2, 0, 0x0a00},
{ 0, 0, 0, 0, 0, 0 },
};
.controls = &pllx_controls,
.div_layout = &pllx_div_layout,
.round_p_to_pdiv = pll_qlin_p_to_pdiv,
+#if PLLX_USE_DYN_RAMP
.dyn_ramp = pllx_dyn_ramp,
+#endif
.set_defaults = pllx_set_defaults,
},
};
},
};
+static struct clk_mux_sel mux_clk_osc[] = {
+ { .input = &tegra_clk_osc, .value = 0},
+ { 0, 0},
+};
+
static struct clk_mux_sel mux_pllp[] = {
{ .input = &tegra_pll_p, .value = 0},
{ 0, 0},
static struct clk tegra_pll_p_out4 = {
.name = "pll_p_out4",
.ops = &tegra_pll_div_ops,
- .flags = DIV_U71 | DIV_U71_FIXED,
+ .flags = DIV_U71 | DIV_U71_INT | DIV_U71_FIXED,
.parent = &tegra_pll_p_out_cpu,
.reg = 0xa8,
.reg_shift = 16,
.max_rate = 408000000,
};
+static struct clk tegra_pll_p_out_sor = {
+ .name = "sor_safe",
+ .lookup = {
+ .dev_id = "sor_safe",
+ },
+ .ops = &tegra_periph_clk_ops,
+ .inputs = mux_pllp,
+ .flags = PERIPH_NO_RESET,
+ .max_rate = 24000000,
+ .mul = 1,
+ .div = 17,
+ .u.periph = {
+ .clk_num = 222,
+ },
+};
+
static struct clk_pll_freq_table tegra_pll_u_vco_freq_table[] = {
{ 12000000, 480000000, 40, 1, 1},
{ 13000000, 480000000, 36, 1, 1}, /* actual: 468.0 MHz */
{ 0, 0, 0, 0, 0, 0 },
};
+static struct clk_mux_sel mux_pll_e_inputs[] = {
+ { .input = &tegra_pll_ref, .value = 0},
+ { .input = &tegra_pll_p, .value = 1},
+ { .input = &tegra_pll_re_vco, .value = 2},
+ { .input = &tegra_pll_re_vco, .value = 3},
+ { 0, 0},
+};
+
static struct clk tegra_pll_e = {
.name = "pll_e",
.flags = PLL_FIXED,
.ops = &tegra_plle_ops,
.reg = 0xe8,
.max_rate = 100000000,
+ .inputs = mux_pll_e_inputs,
.u.pll = {
.input_min = 12000000,
.input_max = 800000000,
},
};
-
-
static struct clk tegra_cml0_clk = {
.name = "cml0",
.parent = &tegra_pll_e,
},
};
-static struct clk tegra_pex_uphy_clk = {
- .name = "pex_uphy",
- .parent = &tegra_pll_e,
- .ops = &tegra_pciex_clk_ops,
- .max_rate = 500000000,
- .u.periph = {
- .clk_num = 205,
- },
-};
-
/* Audio sync clocks */
#define SYNC_SOURCE(_id, _dev) \
{ \
{ 0, 0},
};
+static struct clk_mux_sel mux_cclk_lp[] = {
+ { .input = &tegra_clk_m, .value = 0},
+ { .input = &tegra_clk_32k, .value = 2},
+ { .input = &tegra_pll_p_out_cpu, .value = 4},
+ { .input = &tegra_pll_p_out4, .value = 5},
+ { .input = &tegra_pll_x, .value = 8},
+ { 0, 0},
+};
+
static struct clk_mux_sel mux_sclk[] = {
{ .input = &tegra_clk_m, .value = 0},
{ .input = &tegra_pll_c_out1, .value = 1},
{ 0, 0},
};
+/* ADSP cluster clocks */
static struct clk_mux_sel mux_aclk_adsp[] = {
- { .input = &tegra_pll_a1, .value = 0},
{ .input = &tegra_pll_p_out_adsp, .value = 2},
{ .input = &tegra_pll_a_out0, .value = 3},
{ .input = &tegra_clk_m, .value = 6},
{ .input = &tegra_pll_a, .value = 7},
+ { .input = &tegra_pll_a1, .value = 8},
{ 0, 0},
};
| ADSP_PERIPH | ADSP_INTF | ADSP_CORE;
pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
- clk_writel(val, reg);
+ clk_writel_delay(val, reg);
}
static int tegra21_adsp_clk_enable(struct clk *c)
{
u32 val = ADSP_NEON | ADSP_CORE;
- clk_writel(val, CLK_OUT_ENB_SET_Y);
+ clk_writel_delay(val, CLK_OUT_ENB_SET_Y);
return 0;
}
{
u32 val = ADSP_NEON | ADSP_CORE;
- clk_writel(val, CLK_OUT_ENB_CLR_Y);
+ clk_writel_delay(val, CLK_OUT_ENB_CLR_Y);
+}
+
+static void tegra21_adsp_clk_init(struct clk *c)
+{
+ /*
+ * Check/enforce ADSP clock default configuration:
+ * - parent clk_m
+ * - disabled
+ */
+ tegra21_super_clk_set_parent(c, &tegra_clk_m);
+ tegra21_super_clk_init(c);
+
+ /*
+ * CPU and system super clocks cannot be disabled, and super clock init
+ * always marks clock sate ON, which is not true for ADSP. Need explicit
+ * check here.
+ */
+ c->state = clk_readl(CLK_OUT_ENB_Y)&(ADSP_NEON | ADSP_CORE) ? ON : OFF;
+ if (c->state == ON) {
+ WARN(1, "Tegra ADSP clock is running on boot: turning Off\n");
+ tegra21_adsp_clk_disable(c);
+ c->state = OFF;
+ }
}
static struct clk_ops tegra_adsp_ops = {
- .init = tegra21_super_clk_init,
+ .init = tegra21_adsp_clk_init,
.enable = tegra21_adsp_clk_enable,
.disable = tegra21_adsp_clk_disable,
.set_parent = tegra21_super_clk_set_parent,
- .set_rate = tegra21_super_clk_set_rate,
.reset = tegra21_adsp_clk_reset,
};
-static struct raw_notifier_head adsp_rate_change_nh;
static struct clk tegra_clk_aclk_adsp = {
.name = "adsp",
- .flags = DIV_U71 | DIV_U71_INT | MUX,
+ .flags = DIV_U71 | DIV_U71_INT,
.inputs = mux_aclk_adsp,
.reg = 0x6e0,
.ops = &tegra_adsp_ops,
- .max_rate = 600000000UL,
- .rate_change_nh = &adsp_rate_change_nh,
+ .max_rate = 1200000000,
};
+static struct raw_notifier_head adsp_cpu_rate_change_nh;
+static struct clk tegra_clk_virtual_adsp_cpu = {
+ .name = "adsp_cpu",
+ .parent = &tegra_clk_aclk_adsp,
+ .ops = &tegra_adsp_cpu_ops,
+ .max_rate = 1000000000,
+ .u.cpu = {
+ .main = &tegra_pll_a1,
+ .backup = &tegra_pll_p_out_adsp,
+ },
+ .rate_change_nh = &adsp_cpu_rate_change_nh,
+};
+
+/* CPU clusters clocks */
static struct clk tegra_clk_cclk_g = {
.name = "cclk_g",
- .flags = DIV_U71 | DIV_U71_INT | MUX,
+ .flags = DIV_U71 | DIV_U71_INT,
.inputs = mux_cclk_g,
.reg = 0x368,
.ops = &tegra_super_ops,
.max_rate = 3000000000UL,
};
+static struct clk tegra_clk_cclk_lp = {
+ .name = "cclk_lp",
+ .flags = DIV_U71 | DIV_U71_INT,
+ .inputs = mux_cclk_lp,
+ .reg = 0x370,
+ .ops = &tegra_super_ops,
+ .max_rate = 1350000000,
+};
+
static struct clk tegra_clk_virtual_cpu_g = {
.name = "cpu_g",
.parent = &tegra_clk_cclk_g,
},
};
+static struct clk tegra_clk_virtual_cpu_lp = {
+ .name = "cpu_lp",
+ .parent = &tegra_clk_cclk_lp,
+ .ops = &tegra_cpu_ops,
+ .max_rate = 1350000000,
+ .min_rate = 3187500,
+ .u.cpu = {
+ .main = &tegra_pll_x,
+ .backup = &tegra_pll_p_out4,
+ .mode = MODE_LP,
+ },
+};
+
static struct clk_mux_sel mux_cpu_cmplx[] = {
{ .input = &tegra_clk_virtual_cpu_g, .value = 0},
+ { .input = &tegra_clk_virtual_cpu_lp, .value = 1},
{ 0, 0},
};
.max_rate = 3000000000UL,
};
+/* System bus clocks */
static struct clk tegra_clk_sclk_mux = {
.name = "sclk_mux",
.inputs = mux_sclk,
.reg = 0x28,
.ops = &tegra_super_ops,
- .max_rate = 600000000,
+ .max_rate = 1200000000,
.min_rate = 12000000,
};
static struct clk tegra_clk_sclk = {
.name = "sclk",
+ .flags = DIV_BUS,
.ops = &tegra_clk_super_skip_ops,
.reg = 0x2c,
.parent = &tegra_clk_sclk_div,
.max_rate = 32768,
};
+static struct clk_ops tegra_xusb_padctl_ops = {
+ .reset = tegra21_periph_clk_reset,
+};
+
+static struct clk tegra_clk_xusb_padctl = {
+ .name = "xusb_padctl",
+ .ops = &tegra_xusb_padctl_ops,
+ .u.periph = {
+ .clk_num = 142,
+ },
+};
+
+static struct clk tegra_clk_sata_uphy = {
+ .name = "sata_uphy",
+ .ops = &tegra_xusb_padctl_ops,
+ .u.periph = {
+ .clk_num = 204,
+ },
+};
+
+static struct clk tegra_pex_uphy_clk = {
+ .name = "pex_uphy",
+ .ops = &tegra_xusb_padctl_ops,
+ .u.periph = {
+ .clk_num = 205,
+ },
+};
+
+static struct clk tegra_clk_usb2_hsic_trk = {
+ .name = "usb2_hsic_trk",
+ .flags = DIV_U71 | PERIPH_NO_ENB | PERIPH_NO_RESET,
+ .inputs = mux_clk_osc,
+ .reg = 0x6cc,
+ .ops = &tegra_periph_clk_ops,
+ .max_rate = 38400000,
+};
/* Multimedia modules muxes */
static struct clk_mux_sel mux_pllc2_c_c3_pllp_plla1_clkm[] = {
/* Display subsystem muxes */
-static struct clk_mux_sel mux_pllp_plld_plla_pllc_plld2_clkm[] = {
- {.input = &tegra_pll_p_out_hsio, .value = 0},
- {.input = &tegra_pll_d_out0, .value = 2},
- {.input = &tegra_pll_a_out0, .value = 3},
- {.input = &tegra_pll_c, .value = 4},
- {.input = &tegra_pll_d2, .value = 5},
- {.input = &tegra_clk_m, .value = 6},
- { 0, 0},
-};
-
static struct clk_mux_sel mux_pllp_plld_plld2_clkm[] = {
{.input = &tegra_pll_p_out_hsio, .value = 0},
{.input = &tegra_pll_d_out0, .value = 2},
{ 0, 0},
};
+static struct clk_mux_sel mux_plldp[] = {
+ { .input = &tegra_pll_dp, .value = 0},
+ { 0, 0},
+};
+
+static struct clk tegra_clk_sor0_brick = {
+ .name = "sor0_brick",
+ .lookup = {
+ .dev_id = "sor0_brick",
+ },
+ .ops = &tegra_sor_brick_ops,
+ .max_rate = 600000000,
+ .inputs = mux_plldp,
+ .flags = PERIPH_NO_ENB | PERIPH_NO_RESET,
+};
+
+static struct clk_mux_sel mux_pllp_sor_sor0_brick[] = {
+ { .input = &tegra_pll_p_out_sor, .value = 0},
+ { .input = &tegra_clk_sor0_brick, .value = 1},
+ { 0, 0},
+};
+
+static struct clk tegra_clk_sor1_src = {
+ .name = "sor1_src",
+ .lookup = {
+ .dev_id = "sor1_src",
+ },
+ .ops = &tegra_periph_clk_ops,
+ .reg = 0x410,
+ .max_rate = 600000000,
+ .inputs = mux_pllp_plld_plld2_clkm,
+ .flags = MUX | DIV_U71 | PERIPH_NO_ENB | PERIPH_NO_RESET,
+};
+
+static struct clk_mux_sel mux_plldp_sor1_src[] = {
+ { .input = &tegra_pll_dp, .value = 0},
+ { .input = &tegra_clk_sor1_src, .value = 1},
+ { 0, 0},
+};
+
+static struct clk tegra_clk_sor1_brick = {
+ .name = "sor1_brick",
+ .lookup = {
+ .dev_id = "sor1_brick",
+ },
+ .ops = &tegra_sor_brick_ops,
+ .max_rate = 600000000,
+ .inputs = mux_plldp_sor1_src,
+ .flags = MUX | PERIPH_NO_ENB | PERIPH_NO_RESET,
+};
+
+static struct clk_mux_sel mux_pllp_sor_sor1_brick_sor1_src[] = {
+ { .input = &tegra_pll_p_out_sor, .value = 0},
+ { .input = &tegra_clk_sor1_brick, .value = 1},
+ { .input = &tegra_clk_sor1_src, .value = 2},
+ { .input = &tegra_clk_sor1_brick, .value = 3},
+ { 0, 0},
+};
+
/* Peripheral muxes */
static struct clk_mux_sel mux_pllp_pllc_clkm[] = {
{.input = &tegra_pll_p, .value = 0},
{ 0, 0},
};
+static struct clk_mux_sel mux_pllp_pllc_plla_clkm[] = {
+ {.input = &tegra_pll_p, .value = 0},
+ {.input = &tegra_pll_c, .value = 2},
+ {.input = &tegra_pll_a_out0, .value = 4},
+ {.input = &tegra_clk_m, .value = 6},
+ { 0, 0},
+};
+
static struct clk_mux_sel mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2[] = {
{.input = &tegra_pll_p, .value = 0},
{.input = &tegra_pll_c, .value = 2},
{ 0, 0},
};
+static struct clk_mux_sel mux_clk_usb2_hsic_trk[] = {
+ { .input = &tegra_clk_usb2_hsic_trk, .value = 0},
+ { 0, 0},
+};
+
static struct clk tegra_clk_mc;
static struct clk_mux_sel mux_clk_mc[] = {
{ .input = &tegra_clk_mc, .value = 0},
.name = "emc",
.ops = &tegra_emc_clk_ops,
.reg = 0x19c,
- .max_rate = 1066000000,
+ .max_rate = 1800000000,
.min_rate = 12750000,
.inputs = mux_pllm_pllc_pllp_clkm,
.flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
.reg = 0x180,
.inputs = mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0,
.flags = MUX | DIV_U71 | DIV_U71_INT,
- .max_rate = 408000000,
+ .max_rate = 204000000,
.min_rate = 12000000,
.u.periph = {
.clk_num = 28,
.pll_low = &tegra_pll_p,
- .pll_high = &tegra_pll_c,
+ .pll_high = &tegra_pll_c4_out0,
},
.rate_change_nh = &host1x_rate_change_nh,
};
+static struct raw_notifier_head mselect_rate_change_nh;
+
+static struct clk tegra_clk_mselect = {
+ .name = "mselect",
+ .lookup = {
+ .dev_id = "mselect",
+ },
+ .ops = &tegra_1xbus_clk_ops,
+ .reg = 0x3b4,
+ .inputs = mux_pllp_clkm,
+ .flags = MUX | DIV_U71 | DIV_U71_INT,
+ .max_rate = 408000000,
+ .min_rate = 12000000,
+ .u.periph = {
+ .clk_num = 99,
+ .pll_low = &tegra_pll_p,
+ .pll_high = &tegra_pll_p,
+ .threshold = 408000000,
+ },
+ .rate_change_nh = &mselect_rate_change_nh,
+};
+
static struct raw_notifier_head c2bus_rate_change_nh;
static struct raw_notifier_head c3bus_rate_change_nh;
.shared_bus_backup = {
.input = &tegra_pll_p,
},
+#ifdef CONFIG_TEGRA_CBUS_CAN_USE_SKIPPERS
+ .shared_bus_flags = SHARED_BUS_USE_SKIPPERS,
+#endif
.rate_change_nh = &c2bus_rate_change_nh,
};
static struct clk tegra_clk_c3bus = {
.shared_bus_backup = {
.input = &tegra_pll_p,
},
+#ifdef CONFIG_TEGRA_CBUS_CAN_USE_SKIPPERS
+ .shared_bus_flags = SHARED_BUS_USE_SKIPPERS,
+#endif
.rate_change_nh = &c3bus_rate_change_nh,
};
.reset = &tegra21_periph_clk_reset,
};
-/* This is a dummy clock for gpu. The enable/disable/reset routine controls
- input clock of the actual gpu clock. The input clock itself has a fixed
- frequency. The actual gpu clock's frequency is controlled by gpu driver,
- not here in clock framework. However, we assoicate this dummy clock with
- dvfs to control voltage of gpu rail along with frequency change of actual
- gpu clock. So frequency here and in dvfs are based on the acutal gpu clock. */
-static struct clk tegra_clk_gpu = {
+/*
+ * This clock provides a common gate control for branches of different clocks
+ * supplied to GPU: mselect, memory controller, pll_p_out5, jtag and la. The
+ * mselect and mc clocks are always running; pll_p_out5 is explicitly controlled
+ * by GPU driver; jtag and la clocks are set by debug interface configuration.
+ * Therefore we don't need to propagate refcount to those clocks, and just set
+ * GPU gate clock as OSC child.
+ */
+static struct clk tegra_clk_gpu_gate = {
+ .name = "gpu_gate",
+ .parent = &tegra_clk_osc,
+ .ops = &tegra_clk_gpu_ops,
+ .u.periph = {
+ .clk_num = 184,
+ },
+ .flags = PERIPH_MANUAL_RESET,
+ .max_rate = 48000000,
+ .min_rate = 12000000,
+};
+
+/*
+ * This is a reference clock for GPU. The enable/disable routine control input
+ * clock of the GPCPLL. The reference clock itself has a fixed frequency. The
+ * actual GPU clock's frequency is controlled via gbus, which is a child of this
+ * clock.
+ */
+static struct clk tegra_clk_gpu_ref = {
.name = "gpu_ref",
.ops = &tegra_clk_gpu_ops,
.parent = &tegra_pll_ref,
.u.periph = {
- .clk_num = 184,
+ .clk_num = 189,
},
+ .flags = PERIPH_NO_RESET,
.max_rate = 48000000,
.min_rate = 12000000,
};
else
gbus_round_pass_thru = 0;
}
+int tegra_gbus_round_pass_thru_get(void)
+{
+ return gbus_round_pass_thru;
+}
EXPORT_SYMBOL(tegra_gbus_round_pass_thru_enable);
+EXPORT_SYMBOL(tegra_gbus_round_pass_thru_get);
#else
#define gbus_round_pass_thru 0
#endif
.shared_bus_update = tegra21_clk_shared_connector_update, /* re-use */
};
+static struct raw_notifier_head gbus_rate_change_nh;
+
static struct clk tegra_clk_gbus = {
.name = "gbus",
.ops = &tegra_clk_gbus_ops,
- .parent = &tegra_clk_gpu,
- .max_rate = 1000000000,
+ .parent = &tegra_clk_gpu_ref,
+ .max_rate = 1300000000,
.shared_bus_flags = SHARED_BUS_RETENTION,
+ .rate_change_nh = &gbus_rate_change_nh,
};
static void tegra21_camera_mclk_init(struct clk *c)
struct clk tegra_list_clks[] = {
PERIPH_CLK("apbdma", "tegra-apbdma", NULL, 34, 0, 38400000, mux_clk_m, 0),
PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB),
- PERIPH_CLK("kbc", "tegra-kbc", NULL, 36, 0, 32768, mux_clk_32k, PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("timer", "timer", NULL, 5, 0, 38400000, mux_clk_m, 0),
PERIPH_CLK("spare1", "spare1", NULL, 192, 0, 38400000, mux_clk_m, 0),
PERIPH_CLK("axiap", "axiap", NULL, 196, 0, 38400000, mux_clk_m, 0),
- PERIPH_CLK("sor_safe", "sor_safe", NULL, 222, 0, 600000000, mux_clk_m, PERIPH_NO_RESET),
PERIPH_CLK("iqc1", "iqc1", NULL, 221, 0, 38400000, mux_clk_m, PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("iqc2", "iqc2", NULL, 220, 0, 38400000, mux_clk_m, PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("kfuse", "kfuse-tegra", NULL, 40, 0, 38400000, mux_clk_m, PERIPH_ON_APB),
- PERIPH_CLK("fuse", "fuse-tegra", "fuse", 39, 0, 38400000, mux_clk_m, PERIPH_ON_APB),
- PERIPH_CLK("fuse_burn", "fuse-tegra", "fuse_burn", 39, 0, 38400000, mux_clk_m, PERIPH_ON_APB),
- PERIPH_CLK("apbif", "tegra210-admaif", NULL, 107, 0, 38400000, mux_clk_m, PERIPH_NO_RESET | PERIPH_ON_APB),
- PERIPH_CLK("i2s0", "tegra210-i2s.0", NULL, 30, 0x1d8, 204000000, mux_pllaout0_audio0_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("i2s1", "tegra210-i2s.1", NULL, 11, 0x100, 204000000, mux_pllaout0_audio1_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("i2s2", "tegra210-i2s.2", NULL, 18, 0x104, 204000000, mux_pllaout0_audio2_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("i2s3", "tegra210-i2s.3", NULL, 101, 0x3bc, 204000000, mux_pllaout0_audio3_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("i2s4", "tegra210-i2s.4", NULL, 102, 0x3c0, 204000000, mux_pllaout0_audio4_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("spdif_out", "tegra30-spdif", "spdif_out", 10, 0x108, 24576000, mux_pllaout0_audio_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("spdif_in", "tegra30-spdif", "spdif_in", 10, 0x10c, 408000000, mux_pllp_pllc, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("dmic1", "tegra30-i2s.0", NULL, 161, 0x64c, 24576000, mux_pllaout0_audio0_dmic_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
- PERIPH_CLK("dmic2", "tegra30-i2s.1", NULL, 162, 0x650, 24576000, mux_pllaout0_audio1_dmic_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
- PERIPH_CLK("dmic3", "tegra30-i2s.2", NULL, 197, 0x6bc, 24576000, mux_pllaout0_audio2_dmic_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("fuse", "fuse-tegra", "fuse", 39, 0, 38400000, mux_clk_m, PERIPH_ON_APB),
+ PERIPH_CLK("fuse_burn", "fuse-tegra", "fuse_burn", 39, 0, 38400000, mux_clk_m, PERIPH_ON_APB),
+
+ PERIPH_CLK("apbif", "tegra210-admaif", NULL, 107, 0, 38400000, mux_clk_m, PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("i2s0", "tegra210-i2s.0", NULL, 30, 0x1d8, 204000000, mux_pllaout0_audio0_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("i2s1", "tegra210-i2s.1", NULL, 11, 0x100, 204000000, mux_pllaout0_audio1_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("i2s2", "tegra210-i2s.2", NULL, 18, 0x104, 204000000, mux_pllaout0_audio2_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("i2s3", "tegra210-i2s.3", NULL, 101, 0x3bc, 204000000, mux_pllaout0_audio3_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("i2s4", "tegra210-i2s.4", NULL, 102, 0x3c0, 204000000, mux_pllaout0_audio4_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("spdif_out", "tegra30-spdif", "spdif_out", 10, 0x108, 24576000, mux_pllaout0_audio_2x_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("spdif_in", "tegra30-spdif", "spdif_in", 10, 0x10c, 408000000, mux_pllp_pllc, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("dmic1", "tegra210-dmic.0", NULL, 161, 0x64c, 24576000, mux_pllaout0_audio0_dmic_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("dmic2", "tegra210-dmic.1", NULL, 162, 0x650, 24576000, mux_pllaout0_audio1_dmic_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("dmic3", "tegra210-dmic.2", NULL, 197, 0x6bc, 24576000, mux_pllaout0_audio2_dmic_pllp_clkm, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("ape", NULL, "ape", 198, 0x6c0, 300000000, mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_clkm_pllc4_out2, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("maud", "maud", NULL, 202, 0x6d4, 300000000, mux_pllp_pllp_out3_clkm_clk32k_plla, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
- PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 48000000, mux_pllp_pllc_clk32_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- D_AUDIO_CLK("d_audio", "tegra210-axbar", "ahub", 106, 0x3d0, 48000000, mux_d_audio_clk, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("hda", "tegra30-hda", "hda", 125, 0x428, 108000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("hda2codec_2x", "tegra30-hda", "hda2codec", 111, 0x3e4, 910000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("hda2hdmi", "tegra30-hda", "hda2hdmi", 128, 0, 408000000, mux_clk_m, PERIPH_ON_APB),
+ PERIPH_CLK("maud", "maud", NULL, 202, 0x6d4, 300000000, mux_pllp_pllp_out3_clkm_clk32k_plla, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 48000000, mux_pllp_pllc_clk32_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ D_AUDIO_CLK("d_audio", "tegra210-axbar", "ahub", 106, 0x3d0, 48000000, mux_d_audio_clk, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("hda", "tegra30-hda", "hda", 125, 0x428, 108000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("hda2codec_2x", "tegra30-hda", "hda2codec", 111, 0x3e4, 910000000, mux_pllp_pllc_plla_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("hda2hdmi", "tegra30-hda", "hda2hdmi", 128, 0, 408000000, mux_clk_m, PERIPH_ON_APB),
+
PERIPH_CLK("qspi", "qspi", NULL, 211, 0x6c4, 166000000, mux_pllp_pllc_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("vi_i2c", "vi_i2c", NULL, 208, 0x6c8, 136000000, mux_pllp_pllc_clkm, MUX | DIV_U151 | PERIPH_ON_APB),
- PERIPH_CLK("sbc1", "spi-tegra114.0", NULL, 41, 0x134, 204000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sbc2", "spi-tegra114.1", NULL, 44, 0x118, 204000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sbc3", "spi-tegra114.2", NULL, 46, 0x11c, 204000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sbc4", "spi-tegra114.3", NULL, 68, 0x1b4, 48000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sbc1", "spi-tegra114.0", NULL, 41, 0x134, 51000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sbc2", "spi-tegra114.1", NULL, 44, 0x118, 51000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sbc3", "spi-tegra114.2", NULL, 46, 0x11c, 51000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sbc4", "spi-tegra114.3", NULL, 68, 0x1b4, 51000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("sata_oob", "tegra_sata_oob", NULL, 123, 0x420, 216000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("sata", "tegra_sata", NULL, 124, 0x424, 216000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sata_cold", "tegra_sata_cold", NULL, 129, 0, 48000000, mux_clk_m, PERIPH_ON_APB),
- PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 200000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, 208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x164, 200000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sdmmc1_ddr", "sdhci-tegra.0", "ddr", 14, 0x150, 208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sdmmc2_ddr", "sdhci-tegra.1", "ddr", 9, 0x154, 200000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sdmmc3_ddr", "sdhci-tegra.2", "ddr", 69, 0x1bc, 208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sdmmc4_ddr", "sdhci-tegra.3", "ddr", 15, 0x164, 200000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("sdmmc_legacy", "sdmmc_legacy", NULL, 193, 0x694, 208000000, mux_pllp_out3_clkm_pllp_pllc4, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("sata_cold", "tegra_sata_cold", NULL, 129, 0, 48000000, mux_clk_m, PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 333000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, 208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x164, 333000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc1_ddr", "sdhci-tegra.0", "ddr", 14, 0x150, 208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc2_ddr", "sdhci-tegra.1", "ddr", 9, 0x154, 333000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc3_ddr", "sdhci-tegra.2", "ddr", 69, 0x1bc, 208000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc4_ddr", "sdhci-tegra.3", "ddr", 15, 0x164, 333000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+ PERIPH_CLK("sdmmc_legacy", "sdmmc_legacy", NULL, 193, 0x694, 208000000, mux_pllp_out3_clkm_pllp_pllc4, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+
PERIPH_CLK("vcp", "nvavp", "vcp", 29, 0, 250000000, mux_clk_m, 0),
PERIPH_CLK("bsea", "nvavp", "bsea", 62, 0, 250000000, mux_clk_m, 0),
PERIPH_CLK("bsev", "tegra-aes", "bsev", 63, 0, 250000000, mux_clk_m, 0),
PERIPH_CLK("cec", "tegra_cec", NULL, 136, 0, 250000000, mux_clk_m, PERIPH_ON_APB),
- PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 38400000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("owr", "tegra_w1", NULL, 71, 0x1cc, 38400000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
- PERIPH_CLK("i2c1", "tegra21-i2c.0", "div-clk", 12, 0x124, 136000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
- PERIPH_CLK("i2c2", "tegra21-i2c.1", "div-clk", 54, 0x198, 136000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
- PERIPH_CLK("i2c3", "tegra21-i2c.2", "div-clk", 67, 0x1b8, 136000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
- PERIPH_CLK("i2c4", "tegra21-i2c.3", "div-clk", 103, 0x3c4, 136000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
- PERIPH_CLK("i2c5", "tegra21-i2c.4", "div-clk", 47, 0x128, 58300000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
- PERIPH_CLK("i2c6", "tegra21-i2c.5", "div-clk", 166, 0x65c, 58300000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 38400000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+
+ PERIPH_CLK("owr", "tegra_w1", NULL, 71, 0x1cc, 38400000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c1", "tegra21-i2c.0", "div-clk", 12, 0x124, 136000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c2", "tegra21-i2c.1", "div-clk", 54, 0x198, 136000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c3", "tegra21-i2c.2", "div-clk", 67, 0x1b8, 136000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c4", "tegra21-i2c.3", "div-clk", 103, 0x3c4, 136000000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c5", "tegra21-i2c.4", "div-clk", 47, 0x128, 58300000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
+ PERIPH_CLK("i2c6", "tegra21-i2c.5", "div-clk", 166, 0x65c, 58300000, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB),
PERIPH_CLK("mipibif", "mipibif", NULL, 173, 0x660, 408000000, mux_pllp_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("mipi-cal", "mipi-cal", NULL, 56, 0, 60000000, mux_clk_m, PERIPH_ON_APB),
- PERIPH_CLK("uarta", "serial-tegra.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartb", "serial-tegra.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartc", "serial-tegra.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartd", "serial-tegra.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
- PERIPH_CLK("uartape", "uartape", NULL, 212, 0x710, 50000000, mux_pllp_pllc_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_NO_RESET | PERIPH_ON_APB),
- PERIPH_CLK_EX("vi", "vi", "vi", 20, 0x148, 700000000, mux_pllc2_c_c3_pllp_plla1_pllc4, MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops),
- PERIPH_CLK("vi_sensor", NULL, "vi_sensor", 164, 0x1a8, 408000000, mux_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET),
- PERIPH_CLK("vi_sensor2", NULL, "vi_sensor2", 165, 0x658, 408000000, mux_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("uarta", "serial-tegra.0", NULL, 6, 0x178, 800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartb", "serial-tegra.1", NULL, 7, 0x17c, 800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartc", "serial-tegra.2", NULL, 55, 0x1a0, 800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartd", "serial-tegra.3", NULL, 65, 0x1c0, 800000000, mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB),
+ PERIPH_CLK("uartape", "uartape", NULL, 212, 0x710, 50000000, mux_pllp_pllc_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_NO_RESET | PERIPH_ON_APB),
+
+ PERIPH_CLK("vi_sensor", NULL, "vi_sensor", 164, 0x1a8, 408000000, mux_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("vi_sensor2", NULL, "vi_sensor2", 165, 0x658, 408000000, mux_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET),
PERIPH_CLK_EX("dtv", "dtv", NULL, 79, 0x1dc, 250000000, mux_clk_m, PERIPH_ON_APB, &tegra_dtv_clk_ops),
- PERIPH_CLK("disp1", "tegradc.0", NULL, 27, 0x138, 600000000, mux_pllp_plld_plla_pllc_plld2_clkm, MUX),
- PERIPH_CLK("disp2", "tegradc.1", NULL, 26, 0x13c, 600000000, mux_pllp_plld_plla_pllc_plld2_clkm, MUX),
- PERIPH_CLK_EX("sor0", "sor0", NULL, 182, 0x414, 408000000, mux_pllp_plld_plla_pllc_plld2_clkm, MUX | DIV_U71, &tegra_sor_clk_ops),
- PERIPH_CLK_EX("sor1", "sor1", NULL, 183, 0x410, 600000000, mux_pllp_plld_plld2_clkm, MUX | DIV_U71, &tegra_sor_clk_ops),
+ PERIPH_CLK("disp1", "tegradc.0", NULL, 27, 0x138, 800000000, mux_pllp_plld_plld2_clkm, MUX),
+ PERIPH_CLK("disp2", "tegradc.1", NULL, 26, 0x13c, 800000000, mux_pllp_plld_plld2_clkm, MUX),
+ PERIPH_CLK_EX("sor0", "sor0", NULL, 182, 0x414, 600000000, mux_pllp_sor_sor0_brick, MUX, &tegra_sor0_clk_ops),
+ PERIPH_CLK_EX("sor1", "sor1", NULL, 183, 0x410, 600000000, mux_pllp_sor_sor1_brick_sor1_src, MUX, &tegra_sor1_clk_ops),
PERIPH_CLK("dpaux", "dpaux", NULL, 181, 0, 408000000, mux_pllp, 0),
PERIPH_CLK("dpaux1", "dpaux1", NULL, 207, 0, 408000000, mux_pllp, 0),
+
PERIPH_CLK("usbd", "tegra-udc.0", NULL, 22, 0, 480000000, mux_clk_m, 0),
PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0),
- PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0),
- PERIPH_CLK("hsic_trk", "hsic_trk", NULL, 209, 0x6cc, 38400000, mux_clk_m, PERIPH_NO_RESET),
- PERIPH_CLK("usb2_trk", "usb2_trk", NULL, 210, 0x6cc, 38400000, mux_clk_m, PERIPH_NO_RESET),
- PERIPH_CLK_EX("dsia", "tegradc.0", "dsia", 48, 0xd0, 500000000, mux_plld_out0, PLLD, &tegra_dsi_clk_ops),
- PERIPH_CLK_EX("dsib", "tegradc.1", "dsib", 82, 0x4b8, 500000000, mux_plld_out0, PLLD, &tegra_dsi_clk_ops),
- PERIPH_CLK("dsi1-fixed", "tegradc.0", "dsi-fixed", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB),
- PERIPH_CLK("dsi2-fixed", "tegradc.1", "dsi-fixed", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB),
- PERIPH_CLK("csi", "vi", "csi", 52, 0, 480000000, mux_plld, PLLD),
- PERIPH_CLK("ispa", "isp", "ispa", 23, 0, 700000000, mux_isp, PERIPH_ON_APB),
- PERIPH_CLK("ispb", "isp", "ispb", 3, 0, 700000000, mux_isp, PERIPH_ON_APB),
- PERIPH_CLK("csus", "vi", "csus", 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET),
- PERIPH_CLK("vim2_clk", "vi", "vim2_clk", 171, 0, 150000000, mux_clk_m, PERIPH_NO_RESET),
- PERIPH_CLK("cilab", "vi", "cilab", 144, 0x614, 102000000, mux_pllp_pllc_clkm, MUX | DIV_U71),
- PERIPH_CLK("cilcd", "vi", "cilcd", 145, 0x618, 102000000, mux_pllp_pllc_clkm, MUX | DIV_U71),
- PERIPH_CLK("cile", "vi", "cile", 146, 0x61c, 102000000, mux_pllp_pllc_clkm, MUX | DIV_U71),
- PERIPH_CLK("dsialp", "tegradc.0", "dsialp", 147, 0x620, 156000000, mux_pllp_pllc_clkm, MUX | DIV_U71),
- PERIPH_CLK("dsiblp", "tegradc.1", "dsiblp", 148, 0x624, 156000000, mux_pllp_pllc_clkm, MUX | DIV_U71),
- PERIPH_CLK("entropy", "entropy", NULL, 149, 0x628, 102000000, mux_pllp_clkm_1, MUX | DIV_U71),
- PERIPH_CLK("uart_mipi_cal", "uart_mipi_cal", NULL, 177, 0x66c, 102000000, mux_pllp_out3_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
- PERIPH_CLK("dbgapb", "dbgapb", NULL, 185, 0x718, 136000000, mux_pllp_clkm_2, MUX | DIV_U71 | PERIPH_NO_RESET),
-
- PERIPH_CLK("tsensor", "tegra-tsensor", NULL, 100, 0x3b8, 216000000, mux_pllp_pllc_clkm_clk32, MUX | DIV_U71 | PERIPH_ON_APB),
+ PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, PERIPH_NO_ENB),
+ PERIPH_CLK("hsic_trk", NULL, "hsic_trk", 209, 0, 38400000, mux_clk_usb2_hsic_trk, PERIPH_NO_RESET),
+ PERIPH_CLK("usb2_trk", NULL, "usb2_trk", 210, 0, 38400000, mux_clk_usb2_hsic_trk, PERIPH_NO_RESET),
+
+ PERIPH_CLK_EX("dsia", "tegradc.0", "dsia", 48, 0xd0, 500000000, mux_plld_out0, PLLD, &tegra_dsi_clk_ops),
+ PERIPH_CLK_EX("dsib", "tegradc.1", "dsib", 82, 0x4b8, 500000000, mux_plld_out0, PLLD, &tegra_dsi_clk_ops),
+ PERIPH_CLK("dsi1-fixed", "tegradc.0", "dsi-fixed", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB),
+ PERIPH_CLK("dsi2-fixed", "tegradc.1", "dsi-fixed", 0, 0, 108000000, mux_pllp_out3, PERIPH_NO_ENB),
+ PERIPH_CLK("csi", "vi", "csi", 52, 0, 480000000, mux_plld, PLLD),
+ PERIPH_CLK("csus", "vi", "csus", 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET),
+ PERIPH_CLK("vim2_clk", "vi", "vim2_clk", 171, 0, 150000000, mux_clk_m, PERIPH_NO_RESET),
+ PERIPH_CLK("cilab", "vi", "cilab", 144, 0x614, 102000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("cilcd", "vi", "cilcd", 145, 0x618, 102000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("cile", "vi", "cile", 146, 0x61c, 102000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("dsialp", "tegradc.0", "dsialp", 147, 0x620, 156000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("dsiblp", "tegradc.1", "dsiblp", 148, 0x624, 156000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
+
+ PERIPH_CLK("entropy", "entropy", NULL, 149, 0x628, 102000000, mux_pllp_clkm_1, MUX | DIV_U71),
+ PERIPH_CLK("uart_mipi_cal", "uart_mipi_cal", NULL, 177, 0x66c, 102000000, mux_pllp_out3_pllp_pllc_clkm, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("dbgapb", "dbgapb", NULL, 185, 0x718, 136000000, mux_pllp_clkm_2, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("tsensor", "tegra-tsensor", NULL, 100, 0x3b8, 216000000, mux_pllp_pllc_clkm_clk32, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("actmon", "actmon", NULL, 119, 0x3e8, 216000000, mux_pllp_pllc_clk32_clkm, MUX | DIV_U71),
PERIPH_CLK("extern1", "extern1", NULL, 120, 0x3ec, 216000000, mux_plla_clk32_pllp_clkm_plle, MUX | DIV_U71),
PERIPH_CLK("extern2", "extern2", NULL, 121, 0x3f0, 216000000, mux_plla_clk32_pllp_clkm_plle, MUX | DIV_U71),
PERIPH_CLK("i2cslow", "i2cslow", NULL, 81, 0x3fc, 38400000, mux_pllp_pllc_clk32_clkm, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("pcie", "tegra-pcie", "pcie", 70, 0, 250000000, mux_clk_m, 0),
PERIPH_CLK("afi", "tegra-pcie", "afi", 72, 0, 250000000, mux_clk_m, 0),
- PERIPH_CLK("mselect", "mselect", NULL, 99, 0x3b4, 408000000, mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, MUX | DIV_U71 | DIV_U71_INT),
PERIPH_CLK("cl_dvfs_ref", "tegra_cl_dvfs", "ref", 155, 0x62c, 54000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
PERIPH_CLK("cl_dvfs_soc", "tegra_cl_dvfs", "soc", 155, 0x630, 54000000, mux_pllp_clkm, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
PERIPH_CLK("soc_therm", "soc_therm", NULL, 78, 0x644, 408000000, mux_pllc_pllp_plla_pllc4, MUX | DIV_U71 | PERIPH_ON_APB),
PERIPH_CLK("mc_ccpa", "mc_ccpa", NULL, 201, 0, 1066000000, mux_clk_mc, PERIPH_NO_RESET),
PERIPH_CLK("mc_cdpa", "mc_cdpa", NULL, 200, 0, 1066000000, mux_clk_mc, PERIPH_NO_RESET),
- PERIPH_CLK_SKIP("vic03", "vic03", NULL, 178, 0x678, 0x6f0, 500000000, mux_pllc_pllp_plla1_pllc2_c3_clkm, MUX | DIV_U71),
- PERIPH_CLK_SKIP("msenc", "msenc", NULL, 219, 0x6a0, 0x6e8, 768000000, mux_pllc2_c_c3_pllp_plla1_clkm, MUX | DIV_U71 | DIV_U71_INT),
- PERIPH_CLK_SKIP("nvdec", "nvdec", NULL, 194, 0x698, 0x6f4, 768000000, mux_pllc2_c_c3_pllp_plla1_clkm, MUX | DIV_U71 | DIV_U71_INT),
- PERIPH_CLK_SKIP("nvjpg", "nvjpg", NULL, 195, 0x69c, 0x700, 768000000, mux_pllc2_c_c3_pllp_plla1_clkm, MUX | DIV_U71 | DIV_U71_INT),
+ PERIPH_CLK_SKIP("vic03", "vic03", NULL, 178, 0x678, 0x6f0, 700000000, mux_pllc_pllp_plla1_pllc2_c3_clkm, MUX | DIV_U71),
+ PERIPH_CLK_SKIP("msenc", "msenc", NULL, 219, 0x6a0, 0x6e8, 700000000, mux_pllc2_c_c3_pllp_plla1_clkm, MUX | DIV_U71 | DIV_U71_INT),
+ PERIPH_CLK_SKIP("nvdec", "nvdec", NULL, 194, 0x698, 0x6f4, 700000000, mux_pllc2_c_c3_pllp_plla1_clkm, MUX | DIV_U71 | DIV_U71_INT),
+ PERIPH_CLK_SKIP("nvjpg", "nvjpg", NULL, 195, 0x69c, 0x700, 700000000, mux_pllc2_c_c3_pllp_plla1_clkm, MUX | DIV_U71 | DIV_U71_INT),
#ifdef CONFIG_TEGRA_SE_ON_CBUS
- PERIPH_CLK_SKIP("se", "se", NULL, 127, 0x42c, 0x704, 600000000, mux_pllp_pllc2_c_c3_clkm, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+ PERIPH_CLK_SKIP("se", "se", NULL, 127, 0x42c, 0x704, 700000000, mux_pllp_pllc2_c_c3_clkm, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
#else
- PERIPH_CLK_SKIP("se", "tegra21-se", NULL, 127, 0x42c, 0x704, 600000000, mux_pllp_pllc2_c_c3_clkm, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
+ PERIPH_CLK_SKIP("se", "tegra21-se", NULL, 127, 0x42c, 0x704, 700000000, mux_pllp_pllc2_c_c3_clkm, MUX | DIV_U71 | DIV_U71_INT | PERIPH_ON_APB),
#endif
- PERIPH_CLK_SKIP("tsec", "tsec", NULL, 83, 0x1f4, 0x708, 768000000, mux_pllp_pllc2_c_c3_clkm, MUX | DIV_U71 | DIV_U71_INT),
- PERIPH_CLK_SKIP("tsecb", "tsecb", NULL, 206, 0x6d8, 0x70c, 768000000, mux_pllp_pllc2_c_c3_clkm, MUX | DIV_U71 | DIV_U71_INT),
+ PERIPH_CLK_SKIP("tsec", "tegra_tsec", "tsec", 83, 0x1f4, 0x708, 204000000, mux_pllp_pllc_clkm, MUX | DIV_U71 | DIV_U71_INT),
+ PERIPH_CLK_SKIP("tsecb", "tsecb", NULL, 206, 0x6d8, 0x70c, 700000000, mux_pllp_pllc2_c_c3_clkm, MUX | DIV_U71 | DIV_U71_INT),
+ PERIPH_CLK_SKIP("ispa", "isp", "ispa", 23, 0, 0x6f8, 700000000, mux_isp, PERIPH_ON_APB),
+ PERIPH_CLK_SKIP("ispb", "isp", "ispb", 3, 0, 0x6fc, 700000000, mux_isp, PERIPH_ON_APB),
+ PERIPH_CLK_EX("vi", "vi", "vi", 20, 0x148, 700000000, mux_pllc2_c_c3_pllp_plla1_pllc4, MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops),
+ SUPER_SKIP_CLK("vi_skip", "vi", "skip", 0x6ec, NULL, 0),
SHARED_CLK("avp.sclk", "nvavp", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
SHARED_CLK("bsea.sclk", "tegra-aes", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
SHARED_CLK("camera.sclk","vi", "sclk", &tegra_clk_sbus_cmplx, NULL, 0, 0),
SHARED_CLK("mon.avp", "tegra_actmon", "avp", &tegra_clk_sbus_cmplx, NULL, 0, 0),
SHARED_CLK("cap.sclk", "cap_sclk", NULL, &tegra_clk_sbus_cmplx, NULL, 0, SHARED_CEILING),
+ SHARED_CLK("cap.vcore.sclk", "cap.vcore.sclk", NULL, &tegra_clk_sbus_cmplx, NULL, 0, SHARED_CEILING),
SHARED_CLK("cap.throttle.sclk", "cap_throttle", NULL, &tegra_clk_sbus_cmplx, NULL, 0, SHARED_CEILING),
SHARED_CLK("floor.sclk", "floor_sclk", NULL, &tegra_clk_sbus_cmplx, NULL, 0, 0),
SHARED_CLK("override.sclk", "override_sclk", NULL, &tegra_clk_sbus_cmplx, NULL, 0, SHARED_OVERRIDE),
SHARED_SCLK("sbc2.sclk", "tegra12-spi.1", "sclk", &tegra_clk_apb, NULL, 0, 0),
SHARED_SCLK("sbc3.sclk", "tegra12-spi.2", "sclk", &tegra_clk_apb, NULL, 0, 0),
SHARED_SCLK("sbc4.sclk", "tegra12-spi.3", "sclk", &tegra_clk_apb, NULL, 0, 0),
+ SHARED_SCLK("boot.apb.sclk", "boot.apb.sclk", NULL, &tegra_clk_apb, NULL, 0, 0),
SHARED_EMC_CLK("avp.emc", "nvavp", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
SHARED_EMC_CLK("cpu.emc", "cpu", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
SHARED_EMC_CLK("sdmmc4.emc", "sdhci-tegra.3","emc", &tegra_clk_emc, NULL, 0, 0, 0),
SHARED_EMC_CLK("mon.emc", "tegra_actmon", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
SHARED_EMC_CLK("cap.emc", "cap.emc", NULL, &tegra_clk_emc, NULL, 0, SHARED_CEILING, 0),
+ SHARED_EMC_CLK("cap.vcore.emc", "cap.vcore.emc", NULL, &tegra_clk_emc, NULL, 0, SHARED_CEILING, 0),
SHARED_EMC_CLK("cap.throttle.emc", "cap_throttle", NULL, &tegra_clk_emc, NULL, 0, SHARED_CEILING_BUT_ISO, 0),
- SHARED_EMC_CLK("3d.emc", "tegra_gm20b.0", "emc", &tegra_clk_emc, NULL, 0, 0, BIT(EMC_USER_3D)),
+ SHARED_EMC_CLK("3d.emc", "tegra_gpu.0", "emc", &tegra_clk_emc, NULL, 0, 0, BIT(EMC_USER_3D)),
SHARED_EMC_CLK("msenc.emc", "tegra_msenc", "emc", &tegra_clk_emc, NULL, 0, SHARED_BW, BIT(EMC_USER_MSENC)),
SHARED_EMC_CLK("nvjpg.emc", "tegra_nvjpg", "emc", &tegra_clk_emc, NULL, 0, SHARED_BW, BIT(EMC_USER_NVJPG)),
- SHARED_EMC_CLK("nvdec.emc", "tegra_nvdec", "emc", &tegra_clk_emc, NULL, 0, SHARED_BW, BIT(EMC_USER_NVDEC)),
+ SHARED_EMC_CLK("nvdec.emc", "tegra_nvdec", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
SHARED_EMC_CLK("tsec.emc", "tegra_tsec", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
SHARED_EMC_CLK("tsecb.emc", "tegra_tsecb", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
SHARED_EMC_CLK("camera.emc", "vi", "emc", &tegra_clk_emc, NULL, 0, SHARED_ISO_BW, BIT(EMC_USER_VI)),
SHARED_EMC_CLK("iso.emc", "iso", "emc", &tegra_clk_emc, NULL, 0, SHARED_ISO_BW, 0),
SHARED_EMC_CLK("floor.emc", "floor.emc", NULL, &tegra_clk_emc, NULL, 0, 0, 0),
SHARED_EMC_CLK("override.emc", "override.emc", NULL, &tegra_clk_emc, NULL, 0, SHARED_OVERRIDE, 0),
- SHARED_EMC_CLK("edp.emc", "edp.emc", NULL, &tegra_clk_emc, NULL, 0, SHARED_CEILING, 0),
SHARED_EMC_CLK("vic.emc", "tegra_vic03", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
+ SHARED_EMC_CLK("ape.emc", "ape", "emc", &tegra_clk_emc, NULL, 0, 0, 0),
- DUAL_CBUS_CLK("vic03.cbus", "tegra_vic03", "vic03", &tegra_clk_c2bus, "vic03", 0, 0),
- SHARED_LIMIT("cap.c2bus", "cap.c2bus", NULL, &tegra_clk_c2bus, NULL, 0, SHARED_CEILING),
+ DUAL_CBUS_CLK("nvjpg.cbus", "tegra_nvjpg", "nvjpg", &tegra_clk_c2bus, "nvjpg", 0, 0),
+ DUAL_CBUS_CLK("se.cbus", "tegra21-se", NULL, &tegra_clk_c2bus, "se", 0, 0),
+ SHARED_LIMIT("cap.c2bus", "cap.c2bus", NULL, &tegra_clk_c2bus, NULL, 0, SHARED_CEILING),
+ SHARED_LIMIT("cap.vcore.c2bus", "cap.vcore.c2bus", NULL, &tegra_clk_c2bus, NULL, 0, SHARED_CEILING),
SHARED_LIMIT("cap.throttle.c2bus", "cap_throttle", NULL, &tegra_clk_c2bus, NULL, 0, SHARED_CEILING),
SHARED_LIMIT("floor.c2bus", "floor.c2bus", NULL, &tegra_clk_c2bus, NULL, 0, 0),
- SHARED_CLK("override.c2bus", "override.c2bus", NULL, &tegra_clk_c2bus, NULL, 0, SHARED_OVERRIDE),
- SHARED_LIMIT("edp.c2bus", "edp.c2bus", NULL, &tegra_clk_c2bus, NULL, 0, SHARED_CEILING),
+ SHARED_CLK("override.c2bus", "override.c2bus", NULL, &tegra_clk_c2bus, NULL, 0, SHARED_OVERRIDE),
+ SHARED_LIMIT("edp.c2bus", "edp.c2bus", NULL, &tegra_clk_c2bus, NULL, 0, SHARED_CEILING),
+ DUAL_CBUS_CLK("vic03.cbus", "tegra_vic03", "vic03", &tegra_clk_c3bus, "vic03", 0, 0),
DUAL_CBUS_CLK("msenc.cbus", "tegra_msenc", "msenc", &tegra_clk_c3bus, "msenc", 0, 0),
- DUAL_CBUS_CLK("nvjpg.cbus", "tegra_nvjpg", "nvjpg", &tegra_clk_c3bus, "nvjpg", 0, 0),
DUAL_CBUS_CLK("nvdec.cbus", "tegra_nvdec", "nvdec", &tegra_clk_c3bus, "nvdec", 0, 0),
- DUAL_CBUS_CLK("se.cbus", "tegra21-se", NULL, &tegra_clk_c3bus, "se", 0, 0),
- /* FIXME: move tsec out of cbus */
- DUAL_CBUS_CLK("tsec.cbus", "tegra_tsec", "tsec", &tegra_clk_c3bus, "tsec", 0, 0),
- DUAL_CBUS_CLK("tsecb.cbus", "tegra_tsecb", "tsecb", &tegra_clk_c3bus, "tsecb", 0, 0),
- SHARED_LIMIT("cap.c3bus", "cap.c3bus", NULL, &tegra_clk_c3bus, NULL, 0, SHARED_CEILING),
+ DUAL_CBUS_CLK("tsecb.cbus", "tegra_tsecb", "tsecb", &tegra_clk_c3bus, "tsecb", 0, 0),
+ SHARED_LIMIT("cap.c3bus", "cap.c3bus", NULL, &tegra_clk_c3bus, NULL, 0, SHARED_CEILING),
+ SHARED_LIMIT("cap.vcore.c3bus", "cap.vcore.c3bus", NULL, &tegra_clk_c3bus, NULL, 0, SHARED_CEILING),
SHARED_LIMIT("cap.throttle.c3bus", "cap_throttle", NULL, &tegra_clk_c3bus, NULL, 0, SHARED_CEILING),
SHARED_LIMIT("floor.c3bus", "floor.c3bus", NULL, &tegra_clk_c3bus, NULL, 0, 0),
- SHARED_CLK("override.c3bus", "override.c3bus", NULL, &tegra_clk_c3bus, NULL, 0, SHARED_OVERRIDE),
+ SHARED_CLK("override.c3bus", "override.c3bus", NULL, &tegra_clk_c3bus, NULL, 0, SHARED_OVERRIDE),
- SHARED_CLK("gm20b.gbus", "tegra_gk20a", "gpu", &tegra_clk_gbus, NULL, 0, 0),
- SHARED_LIMIT("cap.gbus", "cap.gbus", NULL, &tegra_clk_gbus, NULL, 0, SHARED_CEILING),
- SHARED_LIMIT("edp.gbus", "edp.gbus", NULL, &tegra_clk_gbus, NULL, 0, SHARED_CEILING),
+ SHARED_CLK("gm20b.gbus", "tegra_gpu.0", "gpu", &tegra_clk_gbus, NULL, 0, 0),
+ SHARED_LIMIT("cap.gbus", "cap.gbus", NULL, &tegra_clk_gbus, NULL, 0, SHARED_CEILING),
+ SHARED_LIMIT("edp.gbus", "edp.gbus", NULL, &tegra_clk_gbus, NULL, 0, SHARED_CEILING),
SHARED_LIMIT("cap.throttle.gbus", "cap_throttle", NULL, &tegra_clk_gbus, NULL, 0, SHARED_CEILING),
SHARED_LIMIT("cap.profile.gbus", "profile.gbus", "cap", &tegra_clk_gbus, NULL, 0, SHARED_CEILING),
- SHARED_CLK("override.gbus", "override.gbus", NULL, &tegra_clk_gbus, NULL, 0, SHARED_OVERRIDE),
- SHARED_LIMIT("floor.gbus", "floor.gbus", NULL, &tegra_clk_gbus, NULL, 0, 0),
- SHARED_LIMIT("floor.profile.gbus", "profile.gbus", "floor", &tegra_clk_gbus, NULL, 0, 0),
+ SHARED_CLK("override.gbus", "override.gbus", NULL, &tegra_clk_gbus, NULL, 0, SHARED_OVERRIDE),
+ SHARED_LIMIT("floor.gbus", "floor.gbus", NULL, &tegra_clk_gbus, NULL, 0, 0),
+ SHARED_LIMIT("floor.profile.gbus", "profile.gbus", "floor", &tegra_clk_gbus, NULL, 0, 0),
SHARED_CLK("nv.host1x", "tegra_host1x", "host1x", &tegra_clk_host1x, NULL, 0, 0),
SHARED_CLK("vi.host1x", "tegra_vi", "host1x", &tegra_clk_host1x, NULL, 0, 0),
SHARED_LIMIT("cap.host1x", "cap.host1x", NULL, &tegra_clk_host1x, NULL, 0, SHARED_CEILING),
+ SHARED_LIMIT("cap.vcore.host1x", "cap.vcore.host1x", NULL, &tegra_clk_host1x, NULL, 0, SHARED_CEILING),
SHARED_LIMIT("floor.host1x", "floor.host1x", NULL, &tegra_clk_host1x, NULL, 0, 0),
SHARED_CLK("override.host1x", "override.host1x", NULL, &tegra_clk_host1x, NULL, 0, SHARED_OVERRIDE),
+
+ SHARED_CLK("cpu.mselect", "cpu", "mselect", &tegra_clk_mselect, NULL, 0, 0),
+ SHARED_CLK("pcie.mselect", "tegra_pcie", "mselect", &tegra_clk_mselect, NULL, 0, 0),
+ SHARED_LIMIT("cap.vcore.mselect", "cap.vcore.mselect", NULL, &tegra_clk_mselect, NULL, 0, SHARED_CEILING),
+ SHARED_CLK("override.mselect", "override.mselect", NULL, &tegra_clk_mselect, NULL, 0, SHARED_OVERRIDE),
};
/* VI, ISP buses */
/* XUSB clocks */
#define XUSB_ID "tegra-xhci"
+#define XUDC_ID "tegra-xudc"
/* xusb common clock gate - enabled on init and never disabled */
static void tegra21_xusb_gate_clk_init(struct clk *c)
{
.name = "xusb_gate",
.flags = ENABLE_ON_INIT | PERIPH_NO_RESET,
.ops = &tegra_xusb_gate_clk_ops,
+ .parent = &tegra_clk_osc,
.rate = 12000000,
.max_rate = 48000000,
.u.periph = {
static struct clk tegra_xusb_source_clks[] = {
PERIPH_CLK("xusb_host_src", XUSB_ID, "host_src", 143, 0x600, 120000000, mux_clkm_pllp_pllre, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
PERIPH_CLK("xusb_falcon_src", XUSB_ID, "falcon_src", 143, 0x604, 350000000, mux_clkm_pllp_pllre, MUX | DIV_U71 | PERIPH_NO_RESET),
- PERIPH_CLK("xusb_fs_src", XUSB_ID, "fs_src", 143, 0x608, 48000000, mux_clkm_48M_pllp_480M, MUX | DIV_U71 | PERIPH_NO_RESET),
- PERIPH_CLK("xusb_ss_src", XUSB_ID, "ss_src", 143, 0x610, 120000000, mux_clkm_pllre_clk32_480M_pllc_ref, MUX | DIV_U71 | PERIPH_NO_RESET),
- PERIPH_CLK("xusb_dev_src", XUSB_ID, "dev_src", 95, 0x60c, 120000000, mux_clkm_pllp_pllre, MUX | DIV_U71 | PERIPH_NO_RESET | PERIPH_ON_APB),
+ PERIPH_CLK("xusb_fs_src", NULL, "fs_src", 143, 0x608, 48000000, mux_clkm_48M_pllp_480M, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("xusb_ss_src", NULL, "ss_src", 143, 0x610, 120000000, mux_clkm_pllre_clk32_480M_pllc_ref, MUX | DIV_U71 | PERIPH_NO_RESET),
+ PERIPH_CLK("xusb_dev_src", XUDC_ID, "dev_src", 95, 0x60c, 120000000, mux_clkm_pllp_pllre, MUX | DIV_U71 | PERIPH_ON_APB),
SHARED_EMC_CLK("xusb.emc", XUSB_ID, "emc", &tegra_clk_emc, NULL, 0, SHARED_BW, 0),
};
static struct clk_mux_sel mux_ss_div2_pllu_60M[] = {
{ .input = &tegra_xusb_ss_div2, .value = 0},
{ .input = &tegra_pll_u_60M, .value = 1},
+ { .input = &tegra_xusb_source_clks[3], .value = 2},
+ { .input = &tegra_xusb_source_clks[3], .value = 3},
{ 0, 0},
};
static struct clk tegra_xusb_hs_src = {
.name = "xusb_hs_src",
.lookup = {
- .dev_id = XUSB_ID,
+ .dev_id = NULL,
.con_id = "hs_src",
},
.ops = &tegra_periph_clk_ops,
.reg = 0x610,
.inputs = mux_ss_div2_pllu_60M,
- .flags = MUX | PLLU | PERIPH_NO_ENB,
- .max_rate = 61200000,
+ .flags = MUX | PLLU | PERIPH_NO_ENB | PERIPH_NO_RESET,
+ .max_rate = 120000000,
.u.periph = {
- .src_mask = 0x1 << 25,
+ .src_mask = 0x3 << 25,
.src_shift = 25,
},
};
static struct clk tegra_xusb_coupled_clks[] = {
PERIPH_CLK_EX("xusb_host", XUSB_ID, "host", 89, 0, 350000000, mux_xusb_host, 0, &tegra_clk_coupled_gate_ops),
- PERIPH_CLK_EX("xusb_ss", XUSB_ID, "ss", 156, 0, 350000000, mux_xusb_ss, 0, &tegra_clk_coupled_gate_ops),
- PERIPH_CLK_EX("xusb_dev", XUSB_ID, "dev", 95, 0, 120000000, mux_xusb_dev, 0, &tegra_clk_coupled_gate_ops),
+ PERIPH_CLK_EX("xusb_ss", NULL, "ss", 156, 0, 350000000, mux_xusb_ss, 0, &tegra_clk_coupled_gate_ops),
+ PERIPH_CLK_EX("xusb_dev", XUDC_ID, "dev", 95, 0, 120000000, mux_xusb_dev, 0, &tegra_clk_coupled_gate_ops),
};
#define CLK_DUPLICATE(_name, _dev, _con) \
.name = _name, \
.lookup = { \
.dev_id = _dev, \
- .con_id = _con, \
+ .con_id = _con, \
}, \
}
CLK_DUPLICATE("i2c5", "tegra_cl_dvfs", "i2c"),
CLK_DUPLICATE("cpu_g", "tegra_cl_dvfs", "safe_dvfs"),
CLK_DUPLICATE("actmon", "tegra_host1x", "actmon"),
- CLK_DUPLICATE("gpu_ref", "tegra_gm20b.0", "PLLG_ref"),
- CLK_DUPLICATE("gbus", "tegra_gm20b.0", "PLLG_out"),
- CLK_DUPLICATE("pll_p_out5", "tegra_gm20b.0", "pwr"),
+ CLK_DUPLICATE("gpu_ref", "tegra_gpu.0", "PLLG_ref"),
+ CLK_DUPLICATE("pll_p_out5", "tegra_gpu.0", "pwr"),
CLK_DUPLICATE("ispa.isp.cbus", "tegra_isp", "isp"),
CLK_DUPLICATE("ispb.isp.cbus", "tegra_isp.1", "isp"),
#ifdef CONFIG_VI_ONE_DEVICE
&tegra_pll_p_out3,
&tegra_pll_p_out4,
&tegra_pll_p_out5,
+ &tegra_pll_p_out_sor,
&tegra_pll_a,
&tegra_pll_a_out0,
&tegra_pll_d,
&tegra_pciex_clk,
&tegra_pex_uphy_clk,
&tegra_clk_cclk_g,
+ &tegra_clk_cclk_lp,
&tegra_clk_sclk_mux,
&tegra_clk_sclk_div,
&tegra_clk_sclk,
&tegra_clk_hclk,
&tegra_clk_pclk,
&tegra_clk_aclk_adsp,
+ &tegra_clk_virtual_adsp_cpu,
&tegra_clk_virtual_cpu_g,
+ &tegra_clk_virtual_cpu_lp,
&tegra_clk_cpu_cmplx,
&tegra_clk_blink,
&tegra_clk_cop,
&tegra_clk_emc,
&tegra_clk_mc,
&tegra_clk_host1x,
+ &tegra_clk_mselect,
&tegra_clk_c2bus,
&tegra_clk_c3bus,
- &tegra_clk_gpu,
+ &tegra_clk_gpu_gate,
+ &tegra_clk_gpu_ref,
&tegra_clk_gbus,
&tegra_clk_isp,
&tegra_clk_cbus,
+ &tegra_clk_sor1_src,
+ &tegra_clk_sor0_brick,
+ &tegra_clk_sor1_brick,
+ &tegra_clk_xusb_padctl,
+ &tegra_clk_sata_uphy,
+ &tegra_clk_usb2_hsic_trk,
};
struct clk *tegra_ptr_camera_mclks[] = {
&tegra_camera_mclk2,
};
-/* Return true from this function if the target rate can be locked without
- switching pll clients to back-up source */
-static bool tegra21_is_dyn_ramp(
- struct clk *c, unsigned long rate, bool from_vco_min)
+/* DFLL late init called with CPU clock lock taken */
+static void __init tegra21_dfll_cpu_late_init(struct clk *c)
{
-#if PLLCX_USE_DYN_RAMP
- /* PLLC2, PLLC3 support dynamic ramp only when output divider <= 8 */
- if ((c == &tegra_pll_c) || (c == &tegra_pll_c2) ||
- (c == &tegra_pll_c3) || (c == &tegra_pll_a1)) {
- struct clk_pll_freq_table cfg, old_cfg;
- unsigned long input_rate = clk_get_rate(c->parent);
+#ifdef CONFIG_ARCH_TEGRA_HAS_CL_DVFS
+ int ret;
+ struct clk *cpu = &tegra_clk_virtual_cpu_g;
- pll_base_parse_cfg(c, &old_cfg);
+ if (!cpu || !cpu->dvfs) {
+ pr_err("%s: CPU dvfs is not present\n", __func__);
+ return;
+ }
- if (!pll_clk_find_cfg(c, &cfg, rate, input_rate, NULL)) {
- if ((cfg.m == old_cfg.m) && (cfg.p == old_cfg.p))
- return c->u.pll.defaults_set;
- }
+ /* release dfll clock source reset, init cl_dvfs control logic, and
+ move dfll to initialized state, so it can be used as CPU source */
+ tegra_periph_reset_deassert(c);
+ ret = tegra_init_cl_dvfs();
+ if (!ret) {
+ c->state = OFF;
+ if (tegra_platform_is_silicon())
+ use_dfll = CONFIG_TEGRA_USE_DFLL_RANGE;
+ tegra_dvfs_set_dfll_range(cpu->dvfs, use_dfll);
+ tegra_cl_dvfs_debug_init(c);
+ pr_info("Tegra CPU DFLL is initialized with use_dfll = %d\n",
+ use_dfll);
}
#endif
+}
-#if PLLX_USE_DYN_RAMP
- /* PPLX, PLLC support dynamic ramp when changing NDIV only */
- if (c == &tegra_pll_x) {
- struct clk_pll_freq_table cfg, old_cfg;
- unsigned long input_rate = clk_get_rate(c->parent);
+/*
+ * Tegra21 clock policy: PLLC4 is a fixed frequency PLL with VCO output catered
+ * to maximum eMMC rate. By default PLLC4 VCO is fixed at ~1GHz, that provides
+ * target rates for DDR HS667 mode (PLLC4_OUT1 = VCO/3), DDR HS400 mode, and SDR
+ * HS200 mode (PLLC4_OUT2 = VCO/5). For other possible eMMC rate targets VCO
+ * rate is tabulated below.
+ *
+ * PLLC4 post-divider PLLC_OUT0 and secondary divider PLLC_OUT3 ratios specified
+ * in the table are selected to provide max input frequency to downstream module
+ * dividers (fort better granularity of possible rates).
+ *
+ * Commonly PLLC_OUT3 is also used as second clock source (along with PLLP) for
+ * the system bus.
+ */
+struct pllc4_sdmmc_map {
+ unsigned long sdmmc_max_rate;
+ unsigned long vco_rate;
+ u32 out0_ratio;
+ u32 out3_ratio;
+ struct clk *bus_source;
+};
- if (from_vco_min) {
- old_cfg.m = pll_get_fixed_mdiv(c, input_rate);
- old_cfg.p = 1;
- } else {
- u32 val = clk_readl(c->reg + PLL_BASE);
- PLL_BASE_PARSE(PLLXC, old_cfg, val);
- old_cfg.p = pllxc_p[old_cfg.p];
- }
+static struct pllc4_sdmmc_map tegra21_pllc4_sdmmc_map[] = {
+ { 0, 1000000000, 1, 1, &tegra_pll_c4_out3 }, /* default cfg */
+ { 266500000, 799500000, 1, 1, &tegra_pll_c4_out3 },
+ { 400000000, 800000000, 1, 1, &tegra_pll_c4_out3 },
+};
+
+static void pllc4_set_fixed_rates(unsigned long cf)
+{
+ int i;
+ u32 val;
+ struct device_node *dn;
+ unsigned long rate, sdmmc_max_rate = 0;
+ struct pllc4_sdmmc_map *pllc4_cfg = &tegra21_pllc4_sdmmc_map[0];
+
+ for_each_compatible_node(dn, NULL, "nvidia,tegra210-sdhci") {
+ if (!of_device_is_available(dn))
+ continue;
- if (!pll_clk_find_cfg(c, &cfg, rate, input_rate, NULL)) {
- if ((cfg.m == old_cfg.m) && (cfg.p == old_cfg.p))
- return true;
+ if (!of_property_read_u32(dn, "max-clk-limit", &val)
+ && (sdmmc_max_rate < val))
+ sdmmc_max_rate = val;
+ }
+
+ if (sdmmc_max_rate) {
+ for (i = 1; i < ARRAY_SIZE(tegra21_pllc4_sdmmc_map); i++) {
+ struct pllc4_sdmmc_map *m = &tegra21_pllc4_sdmmc_map[i];
+ if (m->sdmmc_max_rate == sdmmc_max_rate) {
+ pllc4_cfg = m;
+ break;
+ }
}
}
-#endif
- return false;
+
+ /* Align VCO rate on comparison frequency boundary */
+ rate = (pllc4_cfg->vco_rate / cf) * cf;
+ tegra_pll_c4_vco.u.pll.fixed_rate = rate;
+ tegra_pll_c4_vco.flags |= PLL_FIXED;
+
+ rate = DIV_ROUND_UP(rate, pllc4_cfg->out0_ratio);
+ tegra_pll_c4_out0.u.pll.fixed_rate = rate;
+ tegra_pll_c4_out0.flags |= PLL_FIXED;
+
+ rate = DIV_ROUND_UP(rate, pllc4_cfg->out3_ratio);
+ tegra_pll_c4_out3.u.pll_div.default_rate = rate;
+
+ tegra_clk_sbus_cmplx.u.system.sclk_high = pllc4_cfg->bus_source;
+
+ pr_info("pll_c4 rates match %lu max sdmmc: vco=%lu out0=%lu out3=%lu\n",
+ sdmmc_max_rate,
+ tegra_pll_c4_vco.u.pll.fixed_rate,
+ tegra_pll_c4_out0.u.pll.fixed_rate,
+ tegra_pll_c4_out3.u.pll_div.default_rate);
}
/*
tegra_pll_p_out4.u.pll_div.default_rate = 108000000;
tegra_pll_p_out5.u.pll_div.default_rate = 108000000;
tegra_clk_host1x.u.periph.threshold = 108000000;
+ tegra_clk_aclk_adsp.u.cclk.div71 = 2; /* reg settings */
break;
case 408000000:
tegra_pll_p_out3.u.pll_div.default_rate = 102000000;
tegra_pll_p_out4.u.pll_div.default_rate = 204000000;
tegra_pll_p_out5.u.pll_div.default_rate = 204000000;
tegra_clk_host1x.u.periph.threshold = 204000000;
+ tegra_clk_aclk_adsp.u.cclk.div71 = 2; /* reg settings */
break;
case 204000000:
tegra_pll_p_out3.u.pll_div.default_rate = 102000000;
tegra_pll_p_out4.u.pll_div.default_rate = 204000000;
tegra_pll_p_out5.u.pll_div.default_rate = 204000000;
tegra_clk_host1x.u.periph.threshold = 204000000;
+ tegra_clk_aclk_adsp.u.cclk.div71 = 0; /* reg settings */
break;
default:
pr_err("tegra: PLLP rate: %lu is not supported\n", pllp_rate);
div = pllp_rate / CPU_LP_BACKUP_RATE_TARGET;
backup_rate = pllp_rate / div;
+ tegra_clk_virtual_cpu_lp.u.cpu.backup_rate = backup_rate;
}
static void tegra21_init_one_clock(struct clk *c)
c = tegra_get_clock_by_name("la");
if (WARN(!c, "%s: could not find la clk\n", __func__))
return;
- clk_enable(c);
+ tegra_clk_prepare_enable(c);
if (reg & MISC_GP_TRANSACTOR_SCRATCH_DP2_ENABLE) {
c = tegra_get_clock_by_name("dp2");
if (WARN(!c, "%s: could not find dp2 clk\n", __func__))
return;
- clk_enable(c);
+ tegra_clk_prepare_enable(c);
}
}
unsigned long mselect_rate;
if (!mselect) {
- mselect = tegra_get_clock_by_name("mselect");
+ mselect = tegra_get_clock_by_name("cpu.mselect");
if (!mselect)
return -ENODEV;
}
cpu rate is in kHz, mselect rate is in Hz */
mselect_rate = DIV_ROUND_UP(cpu_rate, 2) * 1000;
mselect_rate = min(mselect_rate, 102000000UL);
-
- if (mselect_rate != clk_get_rate(mselect))
- return clk_set_rate(mselect, mselect_rate);
-
- return 0;
+ return clk_set_rate(mselect, mselect_rate);
}
#endif
#ifdef CONFIG_PM_SLEEP
static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
- PERIPH_CLK_SOURCE_NUM + 26];
+ PERIPH_CLK_SOURCE_NUM + 25];
static int tegra21_clk_suspend(void)
{
unsigned long off;
u32 *ctx = clk_rst_suspend;
- *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+ *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_OSC_FREQ_MASK;
*ctx++ = clk_readl(CPU_SOFTRST_CTRL);
*ctx++ = clk_readl(CPU_SOFTRST_CTRL1);
*ctx++ = clk_readl(CPU_SOFTRST_CTRL2);
+ *ctx++ = clk_readl(SPARE_REG);
+ *ctx++ = clk_readl(MISC_CLK_ENB);
+ *ctx++ = clk_readl(CLK_MASK_ARM);
+
*ctx++ = clk_readl(tegra_pll_p_out3.reg);
*ctx++ = clk_readl(tegra_pll_p_out5.reg);
*ctx++ = clk_readl(tegra_pll_p_out_hsio.reg);
*ctx++ = clk_readl(tegra_pll_c4_out3.reg);
*ctx++ = clk_readl(tegra_pll_re_out1.reg);
- *ctx++ = clk_readl(tegra_clk_pclk.reg);
*ctx++ = clk_readl(tegra_clk_sclk.reg);
*ctx++ = clk_readl(tegra_clk_sclk_div.reg);
*ctx++ = clk_readl(tegra_clk_sclk_mux.reg);
+ *ctx++ = clk_readl(tegra_clk_pclk.reg);
for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_LA;
off += 4) {
for (off = AUDIO_DLY_CLK; off <= AUDIO_SYNC_CLK_SPDIF; off+=4) {
*ctx++ = clk_readl(off);
}
+ for (off = AUDIO_SYNC_CLK_DMIC1;
+ off <= AUDIO_SYNC_CLK_DMIC2; off += 4) {
+ *ctx++ = clk_readl(off);
+ }
for (off = PERIPH_CLK_SOURCE_XUSB_HOST;
- off <= PERIPH_CLK_SOURCE_VIC; off += 4)
+ off <= PERIPH_CLK_SOURCE_VIC; off += 4) {
+ if (off == PERIPH_CLK_SOURCE_EMC_DLL)
+ continue;
*ctx++ = clk_readl(off);
+ }
+ for (off = PERIPH_CLK_SOURCE_SDMMC_LEGACY;
+ off <= PERIPH_CLK_SOURCE_NVENC; off += 4) {
+ *ctx++ = clk_readl(off);
+ }
+ for (off = AUDIO_SYNC_CLK_DMIC3;
+ off <= PERIPH_CLK_SOURCE_DBGAPB; off += 4) {
+ *ctx++ = clk_readl(off);
+ }
*ctx++ = clk_readl(RST_DEVICES_L);
*ctx++ = clk_readl(RST_DEVICES_H);
*ctx++ = clk_readl(tegra_clk_cclk_g.reg);
*ctx++ = clk_readl(tegra_clk_cclk_g.reg + SUPER_CLK_DIVIDER);
- *ctx++ = clk_readl(SPARE_REG);
- *ctx++ = clk_readl(MISC_CLK_ENB);
- *ctx++ = clk_readl(CLK_MASK_ARM);
+ *ctx++ = clk_readl(tegra_clk_cclk_lp.reg);
+ *ctx++ = clk_readl(tegra_clk_cclk_lp.reg + SUPER_CLK_DIVIDER);
+
+ *ctx++ = clk_get_rate_all_locked(&tegra_clk_emc);
+ pr_debug("%s: suspend entries: %d, suspend array: %u\n", __func__,
+ (s32)(ctx - clk_rst_suspend), (u32)ARRAY_SIZE(clk_rst_suspend));
+ BUG_ON((ctx - clk_rst_suspend) > ARRAY_SIZE(clk_rst_suspend));
return 0;
}
static void tegra21_clk_resume(void)
{
- unsigned long off;
+ unsigned long off, rate;
const u32 *ctx = clk_rst_suspend;
- u32 val, pll_u_mask, pll_u_base, pll_u_out12;
+ u32 val, clk_y, pll_u_mask, pll_u_base, pll_u_out12;
u32 pll_p_out_hsio, pll_p_out_mask, pll_p_out34;
u32 pll_a_out0, pll_c_out1, pll_c4_out3, pll_re_out1;
struct clk *p;
(1 << tegra_pll_u_60M.reg_shift) |
(1 << tegra_pll_u_48M.reg_shift);
- /* FIXME: OSC_CTRL already restored by warm boot code? */
- val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK;
+ /*
+ * OSC frequency selection should be already restored by warm boot
+ * code, but just in case make sure it does not change across suspend.
+ */
+ val = clk_readl(OSC_CTRL) & ~OSC_CTRL_OSC_FREQ_MASK;
val |= *ctx++;
clk_writel(val, OSC_CTRL);
clk_writel(*ctx++, CPU_SOFTRST_CTRL);
clk_writel(*ctx++, CPU_SOFTRST_CTRL1);
clk_writel(*ctx++, CPU_SOFTRST_CTRL2);
+ clk_writel(*ctx++, SPARE_REG);
+ clk_writel(*ctx++, MISC_CLK_ENB);
+ clk_writel(*ctx++, CLK_MASK_ARM);
+
/* Since we are going to reset devices and switch clock sources in this
* function, plls and secondary dividers is required to be enabled. The
* actual value will be restored back later. Note that boot plls: pllm,
pll_re_out1 = *ctx++;
clk_writel(pll_re_out1 | val, tegra_pll_re_out1.reg);
- /* FIXME: the oder here to be checked against boot-rom exit state */
+ /*
+ * To make sure system bus is not over-clocked during restoration:
+ * - use fixed safe 1:1:2 SCLK:HCLK:PCLK ratio until SCLK source is set
+ * - defer SCLK divider restoration after SCLK source is restored if
+ * divider set by boot-rom is above saved value.
+ */
+ clk_writel(0x01, tegra_clk_pclk.reg);
+ clk_writel_delay(*ctx++, tegra_clk_sclk.reg);
+ val = *ctx++;
+ if (val > clk_readl(tegra_clk_sclk_div.reg))
+ clk_writel_delay(val, tegra_clk_sclk_div.reg);
+ clk_writel_delay(*ctx++, tegra_clk_sclk_mux.reg);
+ if (val != clk_readl(tegra_clk_sclk_div.reg))
+ clk_writel_delay(val, tegra_clk_sclk_div.reg);
clk_writel(*ctx++, tegra_clk_pclk.reg);
- clk_writel(*ctx++, tegra_clk_sclk.reg);
- clk_writel(*ctx++, tegra_clk_sclk_div.reg);
- clk_writel(*ctx++, tegra_clk_sclk_mux.reg);
/* enable all clocks before configuring clock sources */
clk_writel(CLK_OUT_ENB_L_RESET_MASK, CLK_OUT_ENB_L);
clk_writel(CLK_OUT_ENB_V_RESET_MASK, CLK_OUT_ENB_V);
clk_writel(CLK_OUT_ENB_W_RESET_MASK, CLK_OUT_ENB_W);
clk_writel(CLK_OUT_ENB_X_RESET_MASK, CLK_OUT_ENB_X);
- clk_writel(CLK_OUT_ENB_Y_RESET_MASK, CLK_OUT_ENB_Y);
- wmb();
+ clk_writel_delay(CLK_OUT_ENB_Y_RESET_MASK, CLK_OUT_ENB_Y);
for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_LA;
off += 4) {
for (off = AUDIO_DLY_CLK; off <= AUDIO_SYNC_CLK_SPDIF; off+=4) {
clk_writel(*ctx++, off);
}
+ for (off = AUDIO_SYNC_CLK_DMIC1;
+ off <= AUDIO_SYNC_CLK_DMIC2; off += 4) {
+ clk_writel(*ctx++, off);
+ }
for (off = PERIPH_CLK_SOURCE_XUSB_HOST;
- off <= PERIPH_CLK_SOURCE_VIC; off += 4)
+ off <= PERIPH_CLK_SOURCE_VIC; off += 4) {
+ if (off == PERIPH_CLK_SOURCE_EMC_DLL)
+ continue;
+ clk_writel(*ctx++, off);
+ }
+ for (off = PERIPH_CLK_SOURCE_SDMMC_LEGACY;
+ off <= PERIPH_CLK_SOURCE_NVENC; off += 4) {
+ clk_writel(*ctx++, off);
+ }
+ for (off = AUDIO_SYNC_CLK_DMIC3;
+ off <= PERIPH_CLK_SOURCE_DBGAPB; off += 4) {
clk_writel(*ctx++, off);
+ }
+ clk_readl(off);
udelay(RESET_PROPAGATION_DELAY);
clk_writel(*ctx++, RST_DEVICES_L);
clk_writel(*ctx++, RST_DEVICES_V);
clk_writel(*ctx++, RST_DEVICES_W);
clk_writel(*ctx++, RST_DEVICES_X);
- clk_writel(*ctx++, RST_DEVICES_Y);
- wmb();
+ clk_writel_delay(*ctx++, RST_DEVICES_Y);
clk_writel(*ctx++, CLK_OUT_ENB_L);
clk_writel(*ctx++, CLK_OUT_ENB_H);
clk_writel(*ctx++, CLK_OUT_ENB_V);
clk_writel(*ctx++, CLK_OUT_ENB_W);
clk_writel(*ctx++, CLK_OUT_ENB_X);
- clk_writel(*ctx++, CLK_OUT_ENB_Y);
- wmb();
+
+ /* Keep pllp_out_cpu enabled */
+ clk_y = *ctx++;
+ val = 1 << (tegra_pll_p_out_cpu.u.periph.clk_num % 32);
+ clk_writel_delay(clk_y | val, CLK_OUT_ENB_Y);
/* DFLL resume after cl_dvfs and i2c5 clocks are resumed */
tegra21_dfll_clk_resume(&tegra_dfll_cpu);
clk_writel(*ctx++, tegra_clk_cclk_g.reg);
clk_writel(*ctx++, tegra_clk_cclk_g.reg + SUPER_CLK_DIVIDER);
- clk_writel(*ctx++, SPARE_REG);
- clk_writel(*ctx++, MISC_CLK_ENB);
- clk_writel(*ctx++, CLK_MASK_ARM);
+ /* CPU LP clock restored after PLLs and pllp_out_cpu branch */
+ clk_writel(*ctx++, tegra_clk_cclk_lp.reg);
+ clk_writel_delay(*ctx++, tegra_clk_cclk_lp.reg + SUPER_CLK_DIVIDER);
/* Restore back the actual pll and secondary divider values */
clk_writel(pll_p_out34, tegra_pll_p_out3.reg);
val = clk_readl(tegra_pll_u_vco.reg) & (~pll_u_mask);
clk_writel(val | (pll_u_base & pll_u_mask), tegra_pll_u_vco.reg);
+ clk_writel_delay(clk_y, CLK_OUT_ENB_Y);
+
p = &tegra_pll_c;
if (p->state == OFF)
p->ops->disable(p);
if (tegra_pll_mb.state == OFF)
tegra_pll_mb.ops->disable(&tegra_pll_mb);
- /* FIXME: implement EMC resume */
if (p != tegra_clk_emc.parent) {
pr_debug("EMC parent(refcount) across suspend: %s(%d) : %s(%d)",
p->name, p->refcnt, tegra_clk_emc.parent->name,
tegra_clk_emc.parent->refcnt);
- BUG_ON(!p->refcnt);
- p->refcnt--;
+ /* emc switched to the new parent by low level code, but ref
+ count and s/w state need to be updated */
+ clk_disable_locked(p);
+ clk_enable_locked(tegra_clk_emc.parent);
+ }
- /* the new parent is enabled by low level code, but ref count
- need to be updated up to the root */
- p = tegra_clk_emc.parent;
- while (p && ((p->refcnt++) == 0))
- p = p->parent;
+ /* update DVFS voltage requirements */
+ rate = clk_get_rate_all_locked(&tegra_clk_emc);
+ if (*ctx != rate) {
+ tegra_dvfs_set_rate(&tegra_clk_emc, rate);
+ if (p == tegra_clk_emc.parent) {
+ rate = clk_get_rate_all_locked(p);
+ tegra_dvfs_set_rate(p, rate);
+ }
}
tegra_emc_timing_invalidate();
tegra21_pllu_hw_ctrl_set(&tegra_pll_u_vco); /* PLLU, UTMIP h/w ctrl */
- tegra21_plle_clk_resume(&tegra_pll_e); /* Restore plle parent as pll_re_vco */
}
static struct syscore_ops tegra_clk_syscore_ops = {
static int __init tegra21x_clk_late_init(void)
{
- clk_disable(&tegra_pll_re_vco);
+ tegra_clk_disable_unprepare(&tegra_pll_re_vco);
+ tegra_clk_disable_unprepare(tegra_get_clock_by_name("boot.apb.sclk"));
return 0;
}
late_initcall(tegra21x_clk_late_init);