Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 01/10] clk: tegra: Refactor PLL programming code
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

Refactor the PLL programming code to make it useable by the new PLL types
introduced by Tegra114.

The following changes were done:

* Split programming the PLL into updating m,n,p and updating cpcon
* Move locking from _update_pll_cpcon() to clk_pll_set_rate()
* Introduce _get_pll_mnp() helper
* Move check for identical m,n,p values to clk_pll_set_rate()
* struct tegra_clk_pll_freq_table will always contain the values as defined
  by the hardware.
* Simplify the arguments to clk_pll_wait_for_lock()

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/clk-pll.c     |  178 +++++++++++++++++------------
 drivers/clk/tegra/clk-tegra20.c |  144 ++++++++++++------------
 drivers/clk/tegra/clk-tegra30.c |  234 +++++++++++++++++++-------------------
 3 files changed, 294 insertions(+), 262 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 165f247..912c977 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012, 2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -113,20 +113,23 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
 	pll_writel_misc(val, pll);
 }
 
-static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
-				 void __iomem *lock_addr, u32 lock_bit_idx)
+static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
 {
 	int i;
-	u32 val;
+	u32 val, lock_bit;
+	void __iomem *lock_addr;
 
 	if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
 		udelay(pll->params->lock_delay);
 		return 0;
 	}
 
+	lock_addr = pll->clk_base + pll->params->base_reg;
+	lock_bit = BIT(pll->params->lock_bit_idx);
+
 	for (i = 0; i < pll->params->lock_delay; i++) {
 		val = readl_relaxed(lock_addr);
-		if (val & BIT(lock_bit_idx)) {
+		if (val & lock_bit) {
 			udelay(PLL_POST_LOCK_DELAY);
 			return 0;
 		}
@@ -155,7 +158,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw)
 	return val & PLL_BASE_ENABLE ? 1 : 0;
 }
 
-static int _clk_pll_enable(struct clk_hw *hw)
+static void _clk_pll_enable(struct clk_hw *hw)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
 	u32 val;
@@ -172,11 +175,6 @@ static int _clk_pll_enable(struct clk_hw *hw)
 		val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
 		writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
 	}
-
-	clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->base_reg,
-			      pll->params->lock_bit_idx);
-
-	return 0;
 }
 
 static void _clk_pll_disable(struct clk_hw *hw)
@@ -204,7 +202,9 @@ static int clk_pll_enable(struct clk_hw *hw)
 	if (pll->lock)
 		spin_lock_irqsave(pll->lock, flags);
 
-	ret = _clk_pll_enable(hw);
+	_clk_pll_enable(hw);
+
+	ret = clk_pll_wait_for_lock(pll);
 
 	if (pll->lock)
 		spin_unlock_irqrestore(pll->lock, flags);
@@ -241,8 +241,6 @@ static int _get_table_rate(struct clk_hw *hw,
 	if (sel->input_rate == 0)
 		return -EINVAL;
 
-	BUG_ON(sel->p < 1);
-
 	cfg->input_rate = sel->input_rate;
 	cfg->output_rate = sel->output_rate;
 	cfg->m = sel->m;
@@ -290,88 +288,109 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 	     cfg->output_rate <<= 1)
 		p_div++;
 
-	cfg->p = 1 << p_div;
+	cfg->p = p_div;
 	cfg->m = parent_rate / cfreq;
 	cfg->n = cfg->output_rate / cfreq;
 	cfg->cpcon = OUT_OF_TABLE_CPCON;
 
 	if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
-	    cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) {
+	    (1 << p_div) > divp_max(pll)
+	    || cfg->output_rate > pll->params->vco_max) {
 		pr_err("%s: Failed to set %s rate %lu\n",
 		       __func__, __clk_get_name(hw->clk), rate);
 		return -EINVAL;
 	}
 
+	if (pll->flags & TEGRA_PLLU)
+		cfg->p ^= 1;
+
 	return 0;
 }
 
-static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
-			unsigned long rate)
+static void _update_pll_mnp(struct tegra_clk_pll *pll,
+			    struct tegra_clk_pll_freq_table *cfg)
 {
-	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	unsigned long flags = 0;
-	u32 divp, val, old_base;
-	int state;
-
-	divp = __ffs(cfg->p);
-
-	if (pll->flags & TEGRA_PLLU)
-		divp ^= 1;
+	u32 val;
 
-	if (pll->lock)
-		spin_lock_irqsave(pll->lock, flags);
+	val = pll_readl_base(pll);
 
-	old_base = val = pll_readl_base(pll);
 	val &= ~((divm_mask(pll) << pll->divm_shift) |
 		 (divn_mask(pll) << pll->divn_shift) |
 		 (divp_mask(pll) << pll->divp_shift));
 	val |= ((cfg->m << pll->divm_shift) |
 		(cfg->n << pll->divn_shift) |
-		(divp << pll->divp_shift));
-	if (val == old_base) {
-		if (pll->lock)
-			spin_unlock_irqrestore(pll->lock, flags);
-		return 0;
+		(cfg->p << pll->divp_shift));
+
+	pll_writel_base(val, pll);
+}
+
+static void _get_pll_mnp(struct tegra_clk_pll *pll,
+			 struct tegra_clk_pll_freq_table *cfg)
+{
+	u32 val;
+
+	val = pll_readl_base(pll);
+
+	cfg->m = (val >> pll->divm_shift) & (divm_mask(pll));
+	cfg->n = (val >> pll->divn_shift) & (divn_mask(pll));
+	cfg->p = (val >> pll->divp_shift) & (divp_mask(pll));
+}
+
+static void _update_pll_cpcon(struct tegra_clk_pll *pll,
+			      struct tegra_clk_pll_freq_table *cfg,
+			      unsigned long rate)
+{
+	u32 val;
+
+	val = pll_readl_misc(pll);
+
+	val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
+	val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
+
+	if (pll->flags & TEGRA_PLL_SET_LFCON) {
+		val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
+		if (cfg->n >= PLLDU_LFCON_SET_DIVN)
+			val |= 1 << PLL_MISC_LFCON_SHIFT;
+	} else if (pll->flags & TEGRA_PLL_SET_DCCON) {
+		val &= ~(1 << PLL_MISC_DCCON_SHIFT);
+		if (rate >= (pll->params->vco_max >> 1))
+			val |= 1 << PLL_MISC_DCCON_SHIFT;
 	}
 
+	pll_writel_misc(val, pll);
+}
+
+static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
+			unsigned long rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	int state, ret = 0;
+
 	state = clk_pll_is_enabled(hw);
 
-	if (state) {
+	if (state)
 		_clk_pll_disable(hw);
-		val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
-	}
-	pll_writel_base(val, pll);
 
-	if (pll->flags & TEGRA_PLL_HAS_CPCON) {
-		val = pll_readl_misc(pll);
-		val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
-		val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
-		if (pll->flags & TEGRA_PLL_SET_LFCON) {
-			val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
-			if (cfg->n >= PLLDU_LFCON_SET_DIVN)
-				val |= 0x1 << PLL_MISC_LFCON_SHIFT;
-		} else if (pll->flags & TEGRA_PLL_SET_DCCON) {
-			val &= ~(0x1 << PLL_MISC_DCCON_SHIFT);
-			if (rate >= (pll->params->vco_max >> 1))
-				val |= 0x1 << PLL_MISC_DCCON_SHIFT;
-		}
-		pll_writel_misc(val, pll);
-	}
+	_update_pll_mnp(pll, cfg);
 
-	if (pll->lock)
-		spin_unlock_irqrestore(pll->lock, flags);
+	if (pll->flags & TEGRA_PLL_HAS_CPCON)
+		_update_pll_cpcon(pll, cfg, rate);
 
-	if (state)
-		clk_pll_enable(hw);
+	if (state) {
+		_clk_pll_enable(hw);
+		ret = clk_pll_wait_for_lock(pll);
+	}
 
-	return 0;
+	return ret;
 }
 
 static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 			unsigned long parent_rate)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	struct tegra_clk_pll_freq_table cfg;
+	struct tegra_clk_pll_freq_table cfg, old_cfg;
+	unsigned long flags = 0;
+	int ret = 0;
 
 	if (pll->flags & TEGRA_PLL_FIXED) {
 		if (rate != pll->fixed_rate) {
@@ -387,7 +406,18 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 	    _calc_rate(hw, &cfg, rate, parent_rate))
 		return -EINVAL;
 
-	return _program_pll(hw, &cfg, rate);
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	_get_pll_mnp(pll, &old_cfg);
+
+	if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p)
+		ret = _program_pll(hw, &cfg, rate);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
 }
 
 static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -409,7 +439,7 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 		return -EINVAL;
 
 	output_rate *= cfg.n;
-	do_div(output_rate, cfg.m * cfg.p);
+	do_div(output_rate, cfg.m * (1 << cfg.p));
 
 	return output_rate;
 }
@@ -418,10 +448,12 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 					 unsigned long parent_rate)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
-	u32 val = pll_readl_base(pll);
-	u32 divn = 0, divm = 0, divp = 0;
+	struct tegra_clk_pll_freq_table cfg;
+	u32 val;
 	u64 rate = parent_rate;
 
+	val = pll_readl_base(pll);
+
 	if (val & PLL_BASE_BYPASS)
 		return parent_rate;
 
@@ -435,16 +467,16 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 		return pll->fixed_rate;
 	}
 
-	divp = (val >> pll->divp_shift) & (divp_mask(pll));
+	_get_pll_mnp(pll, &cfg);
+
 	if (pll->flags & TEGRA_PLLU)
-		divp ^= 1;
+		cfg.p ^= 1;
 
-	divn = (val >> pll->divn_shift) & (divn_mask(pll));
-	divm = (val >> pll->divm_shift) & (divm_mask(pll));
-	divm *= (1 << divp);
+	cfg.m *= 1 << cfg.p;
+
+	rate *= cfg.n;
+	do_div(rate, cfg.m);
 
-	rate *= divn;
-	do_div(rate, divm);
 	return rate;
 }
 
@@ -538,8 +570,8 @@ static int clk_plle_enable(struct clk_hw *hw)
 	val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
 	pll_writel_base(val, pll);
 
-	clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg,
-			      pll->params->lock_bit_idx);
+	clk_pll_wait_for_lock(pll);
+
 	return 0;
 }
 
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 5d41569..30bd3fd 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -247,125 +247,125 @@ static struct clk *clks[clk_max];
 static struct clk_onecell_data clk_data;
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
-	{ 12000000, 600000000, 600, 12, 1, 8 },
-	{ 13000000, 600000000, 600, 13, 1, 8 },
-	{ 19200000, 600000000, 500, 16, 1, 6 },
-	{ 26000000, 600000000, 600, 26, 1, 8 },
+	{ 12000000, 600000000, 600, 12, 0, 8 },
+	{ 13000000, 600000000, 600, 13, 0, 8 },
+	{ 19200000, 600000000, 500, 16, 0, 6 },
+	{ 26000000, 600000000, 600, 26, 0, 8 },
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
-	{ 12000000, 666000000, 666, 12, 1, 8},
-	{ 13000000, 666000000, 666, 13, 1, 8},
-	{ 19200000, 666000000, 555, 16, 1, 8},
-	{ 26000000, 666000000, 666, 26, 1, 8},
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
+	{ 12000000, 666000000, 666, 12, 0, 8},
+	{ 13000000, 666000000, 666, 13, 0, 8},
+	{ 19200000, 666000000, 555, 16, 0, 8},
+	{ 26000000, 666000000, 666, 26, 0, 8},
+	{ 12000000, 600000000, 600, 12, 0, 8},
+	{ 13000000, 600000000, 600, 13, 0, 8},
+	{ 19200000, 600000000, 375, 12, 0, 6},
+	{ 26000000, 600000000, 600, 26, 0, 8},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-	{ 12000000, 216000000, 432, 12, 2, 8},
-	{ 13000000, 216000000, 432, 13, 2, 8},
-	{ 19200000, 216000000, 90,   4, 2, 1},
-	{ 26000000, 216000000, 432, 26, 2, 8},
-	{ 12000000, 432000000, 432, 12, 1, 8},
-	{ 13000000, 432000000, 432, 13, 1, 8},
-	{ 19200000, 432000000, 90,   4, 1, 1},
-	{ 26000000, 432000000, 432, 26, 1, 8},
+	{ 12000000, 216000000, 432, 12, 1, 8},
+	{ 13000000, 216000000, 432, 13, 1, 8},
+	{ 19200000, 216000000, 90,   4, 1, 1},
+	{ 26000000, 216000000, 432, 26, 1, 8},
+	{ 12000000, 432000000, 432, 12, 0, 8},
+	{ 13000000, 432000000, 432, 13, 0, 8},
+	{ 19200000, 432000000, 90,   4, 0, 1},
+	{ 26000000, 432000000, 432, 26, 0, 8},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
-	{ 28800000, 56448000, 49, 25, 1, 1},
-	{ 28800000, 73728000, 64, 25, 1, 1},
-	{ 28800000, 24000000,  5,  6, 1, 1},
+	{ 28800000, 56448000, 49, 25, 0, 1},
+	{ 28800000, 73728000, 64, 25, 0, 1},
+	{ 28800000, 24000000,  5,  6, 0, 1},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
-	{ 12000000, 216000000, 216, 12, 1, 4},
-	{ 13000000, 216000000, 216, 13, 1, 4},
-	{ 19200000, 216000000, 135, 12, 1, 3},
-	{ 26000000, 216000000, 216, 26, 1, 4},
+	{ 12000000, 216000000, 216, 12, 0, 4},
+	{ 13000000, 216000000, 216, 13, 0, 4},
+	{ 19200000, 216000000, 135, 12, 0, 3},
+	{ 26000000, 216000000, 216, 26, 0, 4},
 
-	{ 12000000, 594000000, 594, 12, 1, 8},
-	{ 13000000, 594000000, 594, 13, 1, 8},
-	{ 19200000, 594000000, 495, 16, 1, 8},
-	{ 26000000, 594000000, 594, 26, 1, 8},
+	{ 12000000, 594000000, 594, 12, 0, 8},
+	{ 13000000, 594000000, 594, 13, 0, 8},
+	{ 19200000, 594000000, 495, 16, 0, 8},
+	{ 26000000, 594000000, 594, 26, 0, 8},
 
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
+	{ 12000000, 1000000000, 1000, 12, 0, 12},
+	{ 13000000, 1000000000, 1000, 13, 0, 12},
+	{ 19200000, 1000000000, 625,  12, 0, 8},
+	{ 26000000, 1000000000, 1000, 26, 0, 12},
 
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 2, 0},
-	{ 13000000, 480000000, 960, 13, 2, 0},
-	{ 19200000, 480000000, 200, 4,  2, 0},
-	{ 26000000, 480000000, 960, 26, 2, 0},
+	{ 12000000, 480000000, 960, 12, 0, 0},
+	{ 13000000, 480000000, 960, 13, 0, 0},
+	{ 19200000, 480000000, 200, 4,  0, 0},
+	{ 26000000, 480000000, 960, 26, 0, 0},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
 	/* 1 GHz */
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
+	{ 12000000, 1000000000, 1000, 12, 0, 12},
+	{ 13000000, 1000000000, 1000, 13, 0, 12},
+	{ 19200000, 1000000000, 625,  12, 0, 8},
+	{ 26000000, 1000000000, 1000, 26, 0, 12},
 
 	/* 912 MHz */
-	{ 12000000, 912000000,  912,  12, 1, 12},
-	{ 13000000, 912000000,  912,  13, 1, 12},
-	{ 19200000, 912000000,  760,  16, 1, 8},
-	{ 26000000, 912000000,  912,  26, 1, 12},
+	{ 12000000, 912000000,  912,  12, 0, 12},
+	{ 13000000, 912000000,  912,  13, 0, 12},
+	{ 19200000, 912000000,  760,  16, 0, 8},
+	{ 26000000, 912000000,  912,  26, 0, 12},
 
 	/* 816 MHz */
-	{ 12000000, 816000000,  816,  12, 1, 12},
-	{ 13000000, 816000000,  816,  13, 1, 12},
-	{ 19200000, 816000000,  680,  16, 1, 8},
-	{ 26000000, 816000000,  816,  26, 1, 12},
+	{ 12000000, 816000000,  816,  12, 0, 12},
+	{ 13000000, 816000000,  816,  13, 0, 12},
+	{ 19200000, 816000000,  680,  16, 0, 8},
+	{ 26000000, 816000000,  816,  26, 0, 12},
 
 	/* 760 MHz */
-	{ 12000000, 760000000,  760,  12, 1, 12},
-	{ 13000000, 760000000,  760,  13, 1, 12},
-	{ 19200000, 760000000,  950,  24, 1, 8},
-	{ 26000000, 760000000,  760,  26, 1, 12},
+	{ 12000000, 760000000,  760,  12, 0, 12},
+	{ 13000000, 760000000,  760,  13, 0, 12},
+	{ 19200000, 760000000,  950,  24, 0, 8},
+	{ 26000000, 760000000,  760,  26, 0, 12},
 
 	/* 750 MHz */
-	{ 12000000, 750000000,  750,  12, 1, 12},
-	{ 13000000, 750000000,  750,  13, 1, 12},
-	{ 19200000, 750000000,  625,  16, 1, 8},
-	{ 26000000, 750000000,  750,  26, 1, 12},
+	{ 12000000, 750000000,  750,  12, 0, 12},
+	{ 13000000, 750000000,  750,  13, 0, 12},
+	{ 19200000, 750000000,  625,  16, 0, 8},
+	{ 26000000, 750000000,  750,  26, 0, 12},
 
 	/* 608 MHz */
-	{ 12000000, 608000000,  608,  12, 1, 12},
-	{ 13000000, 608000000,  608,  13, 1, 12},
-	{ 19200000, 608000000,  380,  12, 1, 8},
-	{ 26000000, 608000000,  608,  26, 1, 12},
+	{ 12000000, 608000000,  608,  12, 0, 12},
+	{ 13000000, 608000000,  608,  13, 0, 12},
+	{ 19200000, 608000000,  380,  12, 0, 8},
+	{ 26000000, 608000000,  608,  26, 0, 12},
 
 	/* 456 MHz */
-	{ 12000000, 456000000,  456,  12, 1, 12},
-	{ 13000000, 456000000,  456,  13, 1, 12},
-	{ 19200000, 456000000,  380,  16, 1, 8},
-	{ 26000000, 456000000,  456,  26, 1, 12},
+	{ 12000000, 456000000,  456,  12, 0, 12},
+	{ 13000000, 456000000,  456,  13, 0, 12},
+	{ 19200000, 456000000,  380,  16, 0, 8},
+	{ 26000000, 456000000,  456,  26, 0, 12},
 
 	/* 312 MHz */
-	{ 12000000, 312000000,  312,  12, 1, 12},
-	{ 13000000, 312000000,  312,  13, 1, 12},
-	{ 19200000, 312000000,  260,  16, 1, 8},
-	{ 26000000, 312000000,  312,  26, 1, 12},
+	{ 12000000, 312000000,  312,  12, 0, 12},
+	{ 13000000, 312000000,  312,  13, 0, 12},
+	{ 19200000, 312000000,  260,  16, 0, 8},
+	{ 26000000, 312000000,  312,  26, 0, 12},
 
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
-	{ 12000000, 100000000,  200,  24, 1, 0 },
+	{ 12000000, 100000000,  200,  24, 0, 0 },
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index a163812..28a2997 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -373,164 +373,164 @@ static const struct utmi_clk_param utmi_parameters[] = {
 };
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
-	{ 12000000, 1040000000, 520,  6, 1, 8},
-	{ 13000000, 1040000000, 480,  6, 1, 8},
-	{ 16800000, 1040000000, 495,  8, 1, 8},	/* actual: 1039.5 MHz */
-	{ 19200000, 1040000000, 325,  6, 1, 6},
-	{ 26000000, 1040000000, 520, 13, 1, 8},
-
-	{ 12000000, 832000000, 416,  6, 1, 8},
-	{ 13000000, 832000000, 832, 13, 1, 8},
-	{ 16800000, 832000000, 396,  8, 1, 8},	/* actual: 831.6 MHz */
-	{ 19200000, 832000000, 260,  6, 1, 8},
-	{ 26000000, 832000000, 416, 13, 1, 8},
-
-	{ 12000000, 624000000, 624, 12, 1, 8},
-	{ 13000000, 624000000, 624, 13, 1, 8},
-	{ 16800000, 600000000, 520, 14, 1, 8},
-	{ 19200000, 624000000, 520, 16, 1, 8},
-	{ 26000000, 624000000, 624, 26, 1, 8},
-
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 16800000, 600000000, 500, 14, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
-
-	{ 12000000, 520000000, 520, 12, 1, 8},
-	{ 13000000, 520000000, 520, 13, 1, 8},
-	{ 16800000, 520000000, 495, 16, 1, 8},	/* actual: 519.75 MHz */
-	{ 19200000, 520000000, 325, 12, 1, 6},
-	{ 26000000, 520000000, 520, 26, 1, 8},
-
-	{ 12000000, 416000000, 416, 12, 1, 8},
-	{ 13000000, 416000000, 416, 13, 1, 8},
-	{ 16800000, 416000000, 396, 16, 1, 8},	/* actual: 415.8 MHz */
-	{ 19200000, 416000000, 260, 12, 1, 6},
-	{ 26000000, 416000000, 416, 26, 1, 8},
+	{ 12000000, 1040000000, 520,  6, 0, 8},
+	{ 13000000, 1040000000, 480,  6, 0, 8},
+	{ 16800000, 1040000000, 495,  8, 0, 8},	/* actual: 1039.5 MHz */
+	{ 19200000, 1040000000, 325,  6, 0, 6},
+	{ 26000000, 1040000000, 520, 13, 0, 8},
+
+	{ 12000000, 832000000, 416,  6, 0, 8},
+	{ 13000000, 832000000, 832, 13, 0, 8},
+	{ 16800000, 832000000, 396,  8, 0, 8},	/* actual: 831.6 MHz */
+	{ 19200000, 832000000, 260,  6, 0, 8},
+	{ 26000000, 832000000, 416, 13, 0, 8},
+
+	{ 12000000, 624000000, 624, 12, 0, 8},
+	{ 13000000, 624000000, 624, 13, 0, 8},
+	{ 16800000, 600000000, 520, 14, 0, 8},
+	{ 19200000, 624000000, 520, 16, 0, 8},
+	{ 26000000, 624000000, 624, 26, 0, 8},
+
+	{ 12000000, 600000000, 600, 12, 0, 8},
+	{ 13000000, 600000000, 600, 13, 0, 8},
+	{ 16800000, 600000000, 500, 14, 0, 8},
+	{ 19200000, 600000000, 375, 12, 0, 6},
+	{ 26000000, 600000000, 600, 26, 0, 8},
+
+	{ 12000000, 520000000, 520, 12, 0, 8},
+	{ 13000000, 520000000, 520, 13, 0, 8},
+	{ 16800000, 520000000, 495, 16, 0, 8},	/* actual: 519.75 MHz */
+	{ 19200000, 520000000, 325, 12, 0, 6},
+	{ 26000000, 520000000, 520, 26, 0, 8},
+
+	{ 12000000, 416000000, 416, 12, 0, 8},
+	{ 13000000, 416000000, 416, 13, 0, 8},
+	{ 16800000, 416000000, 396, 16, 0, 8},	/* actual: 415.8 MHz */
+	{ 19200000, 416000000, 260, 12, 0, 6},
+	{ 26000000, 416000000, 416, 26, 0, 8},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
-	{ 12000000, 666000000, 666, 12, 1, 8},
-	{ 13000000, 666000000, 666, 13, 1, 8},
-	{ 16800000, 666000000, 555, 14, 1, 8},
-	{ 19200000, 666000000, 555, 16, 1, 8},
-	{ 26000000, 666000000, 666, 26, 1, 8},
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 16800000, 600000000, 500, 14, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
+	{ 12000000, 666000000, 666, 12, 0, 8},
+	{ 13000000, 666000000, 666, 13, 0, 8},
+	{ 16800000, 666000000, 555, 14, 0, 8},
+	{ 19200000, 666000000, 555, 16, 0, 8},
+	{ 26000000, 666000000, 666, 26, 0, 8},
+	{ 12000000, 600000000, 600, 12, 0, 8},
+	{ 13000000, 600000000, 600, 13, 0, 8},
+	{ 16800000, 600000000, 500, 14, 0, 8},
+	{ 19200000, 600000000, 375, 12, 0, 6},
+	{ 26000000, 600000000, 600, 26, 0, 8},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-	{ 12000000, 216000000, 432, 12, 2, 8},
-	{ 13000000, 216000000, 432, 13, 2, 8},
-	{ 16800000, 216000000, 360, 14, 2, 8},
-	{ 19200000, 216000000, 360, 16, 2, 8},
-	{ 26000000, 216000000, 432, 26, 2, 8},
+	{ 12000000, 216000000, 432, 12, 1, 8},
+	{ 13000000, 216000000, 432, 13, 1, 8},
+	{ 16800000, 216000000, 360, 14, 1, 8},
+	{ 19200000, 216000000, 360, 16, 1, 8},
+	{ 26000000, 216000000, 432, 26, 1, 8},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
-	{ 9600000, 564480000, 294, 5, 1, 4},
-	{ 9600000, 552960000, 288, 5, 1, 4},
-	{ 9600000, 24000000,  5,   2, 1, 1},
+	{ 9600000, 564480000, 294, 5, 0, 4},
+	{ 9600000, 552960000, 288, 5, 0, 4},
+	{ 9600000, 24000000,  5,   2, 0, 1},
 
-	{ 28800000, 56448000, 49, 25, 1, 1},
-	{ 28800000, 73728000, 64, 25, 1, 1},
-	{ 28800000, 24000000,  5,  6, 1, 1},
+	{ 28800000, 56448000, 49, 25, 0, 1},
+	{ 28800000, 73728000, 64, 25, 0, 1},
+	{ 28800000, 24000000,  5,  6, 0, 1},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
-	{ 12000000, 216000000, 216, 12, 1, 4},
-	{ 13000000, 216000000, 216, 13, 1, 4},
-	{ 16800000, 216000000, 180, 14, 1, 4},
-	{ 19200000, 216000000, 180, 16, 1, 4},
-	{ 26000000, 216000000, 216, 26, 1, 4},
-
-	{ 12000000, 594000000, 594, 12, 1, 8},
-	{ 13000000, 594000000, 594, 13, 1, 8},
-	{ 16800000, 594000000, 495, 14, 1, 8},
-	{ 19200000, 594000000, 495, 16, 1, 8},
-	{ 26000000, 594000000, 594, 26, 1, 8},
-
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
+	{ 12000000, 216000000, 216, 12, 0, 4},
+	{ 13000000, 216000000, 216, 13, 0, 4},
+	{ 16800000, 216000000, 180, 14, 0, 4},
+	{ 19200000, 216000000, 180, 16, 0, 4},
+	{ 26000000, 216000000, 216, 26, 0, 4},
+
+	{ 12000000, 594000000, 594, 12, 0, 8},
+	{ 13000000, 594000000, 594, 13, 0, 8},
+	{ 16800000, 594000000, 495, 14, 0, 8},
+	{ 19200000, 594000000, 495, 16, 0, 8},
+	{ 26000000, 594000000, 594, 26, 0, 8},
+
+	{ 12000000, 1000000000, 1000, 12, 0, 12},
+	{ 13000000, 1000000000, 1000, 13, 0, 12},
+	{ 19200000, 1000000000, 625,  12, 0, 8},
+	{ 26000000, 1000000000, 1000, 26, 0, 12},
 
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 2, 12},
-	{ 13000000, 480000000, 960, 13, 2, 12},
-	{ 16800000, 480000000, 400, 7,  2, 5},
-	{ 19200000, 480000000, 200, 4,  2, 3},
-	{ 26000000, 480000000, 960, 26, 2, 12},
+	{ 12000000, 480000000, 960, 12, 0, 12},
+	{ 13000000, 480000000, 960, 13, 0, 12},
+	{ 16800000, 480000000, 400, 7,  0, 5},
+	{ 19200000, 480000000, 200, 4,  0, 3},
+	{ 26000000, 480000000, 960, 26, 0, 12},
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
 	/* 1.7 GHz */
-	{ 12000000, 1700000000, 850,  6,  1, 8},
-	{ 13000000, 1700000000, 915,  7,  1, 8},	/* actual: 1699.2 MHz */
-	{ 16800000, 1700000000, 708,  7,  1, 8},	/* actual: 1699.2 MHz */
-	{ 19200000, 1700000000, 885,  10, 1, 8},	/* actual: 1699.2 MHz */
-	{ 26000000, 1700000000, 850,  13, 1, 8},
+	{ 12000000, 1700000000, 850,  6,  0, 8},
+	{ 13000000, 1700000000, 915,  7,  0, 8},	/* actual: 1699.2 MHz */
+	{ 16800000, 1700000000, 708,  7,  0, 8},	/* actual: 1699.2 MHz */
+	{ 19200000, 1700000000, 885,  10, 0, 8},	/* actual: 1699.2 MHz */
+	{ 26000000, 1700000000, 850,  13, 0, 8},
 
 	/* 1.6 GHz */
-	{ 12000000, 1600000000, 800,  6,  1, 8},
-	{ 13000000, 1600000000, 738,  6,  1, 8},	/* actual: 1599.0 MHz */
-	{ 16800000, 1600000000, 857,  9,  1, 8},	/* actual: 1599.7 MHz */
-	{ 19200000, 1600000000, 500,  6,  1, 8},
-	{ 26000000, 1600000000, 800,  13, 1, 8},
+	{ 12000000, 1600000000, 800,  6,  0, 8},
+	{ 13000000, 1600000000, 738,  6,  0, 8},	/* actual: 1599.0 MHz */
+	{ 16800000, 1600000000, 857,  9,  0, 8},	/* actual: 1599.7 MHz */
+	{ 19200000, 1600000000, 500,  6,  0, 8},
+	{ 26000000, 1600000000, 800,  13, 0, 8},
 
 	/* 1.5 GHz */
-	{ 12000000, 1500000000, 750,  6,  1, 8},
-	{ 13000000, 1500000000, 923,  8,  1, 8},	/* actual: 1499.8 MHz */
-	{ 16800000, 1500000000, 625,  7,  1, 8},
-	{ 19200000, 1500000000, 625,  8,  1, 8},
-	{ 26000000, 1500000000, 750,  13, 1, 8},
+	{ 12000000, 1500000000, 750,  6,  0, 8},
+	{ 13000000, 1500000000, 923,  8,  0, 8},	/* actual: 1499.8 MHz */
+	{ 16800000, 1500000000, 625,  7,  0, 8},
+	{ 19200000, 1500000000, 625,  8,  0, 8},
+	{ 26000000, 1500000000, 750,  13, 0, 8},
 
 	/* 1.4 GHz */
-	{ 12000000, 1400000000, 700,  6,  1, 8},
-	{ 13000000, 1400000000, 969,  9,  1, 8},	/* actual: 1399.7 MHz */
-	{ 16800000, 1400000000, 1000, 12, 1, 8},
-	{ 19200000, 1400000000, 875,  12, 1, 8},
-	{ 26000000, 1400000000, 700,  13, 1, 8},
+	{ 12000000, 1400000000, 700,  6,  0, 8},
+	{ 13000000, 1400000000, 969,  9,  0, 8},	/* actual: 1399.7 MHz */
+	{ 16800000, 1400000000, 1000, 12, 0, 8},
+	{ 19200000, 1400000000, 875,  12, 0, 8},
+	{ 26000000, 1400000000, 700,  13, 0, 8},
 
 	/* 1.3 GHz */
-	{ 12000000, 1300000000, 975,  9,  1, 8},
-	{ 13000000, 1300000000, 1000, 10, 1, 8},
-	{ 16800000, 1300000000, 928,  12, 1, 8},	/* actual: 1299.2 MHz */
-	{ 19200000, 1300000000, 812,  12, 1, 8},	/* actual: 1299.2 MHz */
-	{ 26000000, 1300000000, 650,  13, 1, 8},
+	{ 12000000, 1300000000, 975,  9,  0, 8},
+	{ 13000000, 1300000000, 1000, 10, 0, 8},
+	{ 16800000, 1300000000, 928,  12, 0, 8},	/* actual: 1299.2 MHz */
+	{ 19200000, 1300000000, 812,  12, 0, 8},	/* actual: 1299.2 MHz */
+	{ 26000000, 1300000000, 650,  13, 0, 8},
 
 	/* 1.2 GHz */
-	{ 12000000, 1200000000, 1000, 10, 1, 8},
-	{ 13000000, 1200000000, 923,  10, 1, 8},	/* actual: 1199.9 MHz */
-	{ 16800000, 1200000000, 1000, 14, 1, 8},
-	{ 19200000, 1200000000, 1000, 16, 1, 8},
-	{ 26000000, 1200000000, 600,  13, 1, 8},
+	{ 12000000, 1200000000, 1000, 10, 0, 8},
+	{ 13000000, 1200000000, 923,  10, 0, 8},	/* actual: 1199.9 MHz */
+	{ 16800000, 1200000000, 1000, 14, 0, 8},
+	{ 19200000, 1200000000, 1000, 16, 0, 8},
+	{ 26000000, 1200000000, 600,  13, 0, 8},
 
 	/* 1.1 GHz */
-	{ 12000000, 1100000000, 825,  9,  1, 8},
-	{ 13000000, 1100000000, 846,  10, 1, 8},	/* actual: 1099.8 MHz */
-	{ 16800000, 1100000000, 982,  15, 1, 8},	/* actual: 1099.8 MHz */
-	{ 19200000, 1100000000, 859,  15, 1, 8},	/* actual: 1099.5 MHz */
-	{ 26000000, 1100000000, 550,  13, 1, 8},
+	{ 12000000, 1100000000, 825,  9,  0, 8},
+	{ 13000000, 1100000000, 846,  10, 0, 8},	/* actual: 1099.8 MHz */
+	{ 16800000, 1100000000, 982,  15, 0, 8},	/* actual: 1099.8 MHz */
+	{ 19200000, 1100000000, 859,  15, 0, 8},	/* actual: 1099.5 MHz */
+	{ 26000000, 1100000000, 550,  13, 0, 8},
 
 	/* 1 GHz */
-	{ 12000000, 1000000000, 1000, 12, 1, 8},
-	{ 13000000, 1000000000, 1000, 13, 1, 8},
-	{ 16800000, 1000000000, 833,  14, 1, 8},	/* actual: 999.6 MHz */
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 8},
+	{ 12000000, 1000000000, 1000, 12, 0, 8},
+	{ 13000000, 1000000000, 1000, 13, 0, 8},
+	{ 16800000, 1000000000, 833,  14, 0, 8},	/* actual: 999.6 MHz */
+	{ 19200000, 1000000000, 625,  12, 0, 8},
+	{ 26000000, 1000000000, 1000, 26, 0, 8},
 
 	{ 0, 0, 0, 0, 0, 0 },
 };

^ permalink raw reply related

* [PATCH v5 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

Not all PLLs in Tegra114 have a bypass bit. Adapt the common code to only use
this bit when available.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/clk-pll.c |   15 ++++++++++-----
 drivers/clk/tegra/clk.h     |    8 +++++---
 2 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 912c977..3c3a25e 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -166,7 +166,8 @@ static void _clk_pll_enable(struct clk_hw *hw)
 	clk_pll_enable_lock(pll);
 
 	val = pll_readl_base(pll);
-	val &= ~PLL_BASE_BYPASS;
+	if (pll->flags & TEGRA_PLL_BYPASS)
+		val &= ~PLL_BASE_BYPASS;
 	val |= PLL_BASE_ENABLE;
 	pll_writel_base(val, pll);
 
@@ -183,7 +184,9 @@ static void _clk_pll_disable(struct clk_hw *hw)
 	u32 val;
 
 	val = pll_readl_base(pll);
-	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+	if (pll->flags & TEGRA_PLL_BYPASS)
+		val &= ~PLL_BASE_BYPASS;
+	val &= ~PLL_BASE_ENABLE;
 	pll_writel_base(val, pll);
 
 	if (pll->flags & TEGRA_PLLM) {
@@ -454,7 +457,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 
 	val = pll_readl_base(pll);
 
-	if (val & PLL_BASE_BYPASS)
+	if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
 		return parent_rate;
 
 	if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
@@ -660,9 +663,10 @@ static struct clk *_tegra_clk_register_pll(const char *name,
 struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
 		void __iomem *clk_base, void __iomem *pmc,
 		unsigned long flags, unsigned long fixed_rate,
-		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
 		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
 {
+	pll_flags |= TEGRA_PLL_BYPASS;
 	return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
 			flags, fixed_rate, pll_params, pll_flags, freq_table,
 			lock, &tegra_clk_pll_ops);
@@ -671,9 +675,10 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
 struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 		void __iomem *clk_base, void __iomem *pmc,
 		unsigned long flags, unsigned long fixed_rate,
-		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
 		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
 {
+	pll_flags |= TEGRA_PLL_BYPASS;
 	return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
 			flags, fixed_rate, pll_params, pll_flags, freq_table,
 			lock, &tegra_clk_plle_ops);
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index a09d7dc..3cff1df 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -182,12 +182,13 @@ struct tegra_clk_pll_params {
  * TEGRA_PLL_FIXED - We are not supposed to change output frequency
  *     of some plls.
  * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
+ * TEGRA_PLL_BYPASS - PLL has bypass bit
  */
 struct tegra_clk_pll {
 	struct clk_hw	hw;
 	void __iomem	*clk_base;
 	void __iomem	*pmc;
-	u8		flags;
+	u32		flags;
 	unsigned long	fixed_rate;
 	spinlock_t	*lock;
 	u8		divn_shift;
@@ -210,18 +211,19 @@ struct tegra_clk_pll {
 #define TEGRA_PLLM BIT(5)
 #define TEGRA_PLL_FIXED BIT(6)
 #define TEGRA_PLLE_CONFIGURE BIT(7)
+#define TEGRA_PLL_BYPASS BIT(8)
 
 extern const struct clk_ops tegra_clk_pll_ops;
 extern const struct clk_ops tegra_clk_plle_ops;
 struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
 		void __iomem *clk_base, void __iomem *pmc,
 		unsigned long flags, unsigned long fixed_rate,
-		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
 		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
 struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 		void __iomem *clk_base, void __iomem *pmc,
 		unsigned long flags, unsigned long fixed_rate,
-		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
 		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
 
 /**

^ permalink raw reply related

* [PATCH v5 03/10] clk: tegra: Add PLL post divider table
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

Some PLLs in Tegra114 don't use a power of 2 mapping for the post divider.
Introduce a table based approach and switch PLLU to it.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/clk-pll.c     |   38 ++++++++++++++++++++++++++++++++------
 drivers/clk/tegra/clk-tegra20.c |    7 +++++++
 drivers/clk/tegra/clk-tegra30.c |    7 +++++++
 drivers/clk/tegra/clk.h         |   13 +++++++++++++
 4 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 3c3a25e..87d2f34 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -258,6 +258,7 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 		      unsigned long rate, unsigned long parent_rate)
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
 	unsigned long cfreq;
 	u32 p_div = 0;
 
@@ -291,7 +292,6 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 	     cfg->output_rate <<= 1)
 		p_div++;
 
-	cfg->p = p_div;
 	cfg->m = parent_rate / cfreq;
 	cfg->n = cfg->output_rate / cfreq;
 	cfg->cpcon = OUT_OF_TABLE_CPCON;
@@ -304,8 +304,19 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
 		return -EINVAL;
 	}
 
-	if (pll->flags & TEGRA_PLLU)
-		cfg->p ^= 1;
+	if (p_tohw) {
+		p_div = 1 << p_div;
+		while (p_tohw->pdiv) {
+			if (p_div <= p_tohw->pdiv) {
+				cfg->p = p_tohw->hw_val;
+				break;
+			}
+			p_tohw++;
+		}
+		if (!p_tohw->pdiv)
+			return -EINVAL;
+	} else
+		cfg->p = p_div;
 
 	return 0;
 }
@@ -452,8 +463,10 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 {
 	struct tegra_clk_pll *pll = to_clk_pll(hw);
 	struct tegra_clk_pll_freq_table cfg;
+	struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
 	u32 val;
 	u64 rate = parent_rate;
+	int pdiv;
 
 	val = pll_readl_base(pll);
 
@@ -472,10 +485,23 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
 
 	_get_pll_mnp(pll, &cfg);
 
-	if (pll->flags & TEGRA_PLLU)
-		cfg.p ^= 1;
+	if (p_tohw) {
+		while (p_tohw->pdiv) {
+			if (cfg.p == p_tohw->hw_val) {
+				pdiv = p_tohw->pdiv;
+				break;
+			}
+			p_tohw++;
+		}
+
+		if (!p_tohw->pdiv) {
+			WARN_ON(1);
+			pdiv = 1;
+		}
+	} else
+		pdiv = 1 << cfg.p;
 
-	cfg.m *= 1 << cfg.p;
+	cfg.m *= pdiv;
 
 	rate *= cfg.n;
 	do_div(rate, cfg.m);
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 30bd3fd..54c6777 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -440,6 +440,12 @@ static struct tegra_clk_pll_params pll_d_params = {
 	.lock_delay = 1000,
 };
 
+static struct pdiv_map pllu_p[] = {
+	{ .pdiv = 1, .hw_val = 1 },
+	{ .pdiv = 2, .hw_val = 0 },
+	{ .pdiv = 0, .hw_val = 0 },
+};
+
 static struct tegra_clk_pll_params pll_u_params = {
 	.input_min = 2000000,
 	.input_max = 40000000,
@@ -452,6 +458,7 @@ static struct tegra_clk_pll_params pll_u_params = {
 	.lock_bit_idx = PLL_BASE_LOCK,
 	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
 	.lock_delay = 1000,
+	.pdiv_tohw = pllu_p,
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 28a2997..078f9b8 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -466,6 +466,12 @@ static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
+static struct pdiv_map pllu_p[] = {
+	{ .pdiv = 1, .hw_val = 1 },
+	{ .pdiv = 2, .hw_val = 0 },
+	{ .pdiv = 0, .hw_val = 0 },
+};
+
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
 	{ 12000000, 480000000, 960, 12, 0, 12},
 	{ 13000000, 480000000, 960, 13, 0, 12},
@@ -639,6 +645,7 @@ static struct tegra_clk_pll_params pll_u_params = {
 	.lock_bit_idx = PLL_BASE_LOCK,
 	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
 	.lock_delay = 1000,
+	.pdiv_tohw = pllu_p,
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 3cff1df..1b9cbcd 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -117,6 +117,17 @@ struct tegra_clk_pll_freq_table {
 };
 
 /**
+ * struct pdiv_map - map post divider to hw value
+ *
+ * @pdiv:		post divider
+ * @hw_val:		value to be written to the PLL hw
+ */
+struct pdiv_map {
+	u8 pdiv;
+	u8 hw_val;
+};
+
+/**
  * struct clk_pll_params - PLL parameters
  *
  * @input_min:			Minimum input frequency
@@ -146,6 +157,8 @@ struct tegra_clk_pll_params {
 	u32		lock_bit_idx;
 	u32		lock_enable_bit_idx;
 	int		lock_delay;
+	int		max_p;
+	struct pdiv_map *pdiv_tohw;
 };
 
 /**

^ permalink raw reply related

* [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

Tegra114 introduces new PLL types. This requires new clocktypes as well
as some new fields in the pll structure.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/clk-pll.c |  719 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/tegra/clk.h     |   47 +++
 2 files changed, 766 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 87d2f34..50114b7 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -79,6 +79,36 @@
 #define PLLE_SS_CTRL 0x68
 #define PLLE_SS_DISABLE (7 << 10)
 
+#define PLLE_AUX_PLLP_SEL	BIT(2)
+#define PLLE_AUX_ENABLE_SWCTL	BIT(4)
+#define PLLE_AUX_SEQ_ENABLE	BIT(24)
+#define PLLE_AUX_PLLRE_SEL	BIT(28)
+
+#define PLLE_MISC_PLLE_PTS	BIT(8)
+#define PLLE_MISC_IDDQ_SW_VALUE	BIT(13)
+#define PLLE_MISC_IDDQ_SW_CTRL	BIT(14)
+#define PLLE_MISC_VREG_BG_CTRL_SHIFT	4
+#define PLLE_MISC_VREG_BG_CTRL_MASK	(3 << PLLE_MISC_VREG_BG_CTRL_SHIFT)
+#define PLLE_MISC_VREG_CTRL_SHIFT	2
+#define PLLE_MISC_VREG_CTRL_MASK	(2 << PLLE_MISC_VREG_CTRL_SHIFT)
+
+#define PLLCX_MISC_STROBE	BIT(31)
+#define PLLCX_MISC_RESET	BIT(30)
+#define PLLCX_MISC_SDM_DIV_SHIFT 28
+#define PLLCX_MISC_SDM_DIV_MASK (0x3 << PLLCX_MISC_SDM_DIV_SHIFT)
+#define PLLCX_MISC_FILT_DIV_SHIFT 26
+#define PLLCX_MISC_FILT_DIV_MASK (0x3 << PLLCX_MISC_FILT_DIV_SHIFT)
+#define PLLCX_MISC_DIV_LOW_RANGE \
+		((0x2 << PLLCX_MISC_SDM_DIV_SHIFT) | \
+		(0x2 << PLLCX_MISC_FILT_DIV_SHIFT))
+#define PLLCX_MISC_DIV_HIGH_RANGE \
+		((0x1 << PLLCX_MISC_SDM_DIV_SHIFT) | \
+		(0x1 << PLLCX_MISC_FILT_DIV_SHIFT))
+
+#define PMC_PLLM_WB0_OVERRIDE	0x1dc
+#define PMC_PLLM_WB0_OVERRIDE_2	0x2b0
+#define PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK BIT(27)
+
 #define PMC_SATA_PWRGT 0x1ac
 #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
 #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
@@ -101,6 +131,24 @@
 #define divn_max(p) (divn_mask(p))
 #define divp_max(p) (1 << (divp_mask(p)))
 
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+/* PLLXC has 4-bit PDIV, but entry 15 is not allowed in h/w */
+#define PLLXC_PDIV_MAX			14
+
+/* non-monotonic mapping below is not a typo */
+static u8 pllxc_p[PLLXC_PDIV_MAX + 1] = {
+	/* PDIV: 0, 1, 2, 3, 4, 5, 6,  7,  8,  9, 10, 11, 12, 13, 14 */
+	/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32
+};
+
+#define PLLCX_PDIV_MAX 7
+static u8 pllcx_p[PLLCX_PDIV_MAX + 1] = {
+	/* PDIV: 0, 1, 2, 3, 4, 5,  6,  7 */
+	/* p: */ 1, 2, 3, 4, 6, 8, 12, 16
+};
+#endif
+
 static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
 {
 	u32 val;
@@ -638,6 +686,515 @@ const struct clk_ops tegra_clk_plle_ops = {
 	.enable = clk_plle_enable,
 };
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+
+static int clk_pll_iddq_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+
+	u32 val;
+	int ret;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	val = pll_readl(pll->params->iddq_reg, pll);
+	val &= ~BIT(pll->params->iddq_bit_idx);
+	pll_writel(val, pll->params->iddq_reg, pll);
+	udelay(2);
+
+	_clk_pll_enable(hw);
+
+	ret = clk_pll_wait_for_lock(pll);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return 0;
+}
+
+static void clk_pll_iddq_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	u32 val;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	_clk_pll_disable(hw);
+
+	val = pll_readl(pll->params->iddq_reg, pll);
+	val |= BIT(pll->params->iddq_bit_idx);
+	pll_writel(val, pll->params->iddq_reg, pll);
+	udelay(2);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int _calc_dynamic_ramp_rate(struct clk_hw *hw,
+				struct tegra_clk_pll_freq_table *cfg,
+				unsigned long rate, unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned int p;
+
+	if (!rate)
+		return -EINVAL;
+
+	p = DIV_ROUND_UP(pll->params->vco_min, rate);
+	cfg->m = (parent_rate > pll->params->cf_max) ? 2 : 1;
+	cfg->p = p;
+	cfg->output_rate = rate * cfg->p;
+	cfg->n = cfg->output_rate * cfg->m / parent_rate;
+
+	if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int _pll_ramp_calc_pll(struct clk_hw *hw,
+			      struct tegra_clk_pll_freq_table *cfg,
+			      unsigned long rate, unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	int ret = 0;
+
+	ret = _get_table_rate(hw, cfg, rate, parent_rate);
+	if (ret < 0) {
+		ret = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate);
+		return ret;
+	} else {
+		int fixed_mdiv;
+
+		fixed_mdiv = (parent_rate > pll->params->cf_max) ? 2 : 1;
+		if (cfg->m != fixed_mdiv) {
+			WARN_ON(1);
+			return -EINVAL;
+		}
+	}
+
+	if (!cfg->p || (cfg->p >  pll->params->max_p))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct tegra_clk_pll_freq_table cfg, old_cfg;
+	unsigned long flags = 0;
+	int ret = 0;
+	u8 old_p;
+
+	ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+	if (ret < 0)
+		return ret;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	_get_pll_mnp(pll, &old_cfg);
+
+	old_p = pllxc_p[old_cfg.p];
+	if (old_cfg.m != cfg.m && old_cfg.n != cfg.n && old_p != cfg.p) {
+		cfg.p -= 1;
+		ret = _program_pll(hw, &cfg, rate);
+	}
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
+}
+
+static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	struct tegra_clk_pll_freq_table cfg;
+	int ret = 0;
+	u64 output_rate = *prate;
+
+	ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate);
+	if (ret < 0)
+		return ret;
+
+	output_rate *= cfg.n;
+	do_div(output_rate, cfg.m * cfg.p);
+
+	return output_rate;
+}
+
+static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct tegra_clk_pll_freq_table cfg;
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	int state, ret = 0;
+	u32 val;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	state = clk_pll_is_enabled(hw);
+	if (state) {
+		if (rate != clk_get_rate(hw->clk)) {
+			pr_err("%s: Cannot change active PLLM\n", __func__);
+			ret = -EINVAL;
+			goto out;
+		}
+		goto out;
+	}
+
+	ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+	if (ret < 0)
+		goto out;
+
+	cfg.p -= 1;
+
+	val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+	if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) {
+		val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE_2);
+		val = cfg.p ? (val | PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK) :
+			(val & ~PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK);
+		writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE_2);
+
+		val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+		val &= ~(divn_mask(pll) | divm_mask(pll));
+		val |= (cfg.m << pll->divm_shift) | (cfg.n << pll->divn_shift);
+		writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+	} else
+		_update_pll_mnp(pll, &cfg);
+
+
+out:
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
+}
+
+static void _pllcx_strobe(struct tegra_clk_pll *pll)
+{
+	u32 val;
+
+	val = pll_readl_misc(pll);
+	val |= PLLCX_MISC_STROBE;
+	pll_writel_misc(val, pll);
+	udelay(2);
+
+	val &= ~PLLCX_MISC_STROBE;
+	pll_writel_misc(val, pll);
+}
+
+static int clk_pllc_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val;
+	int ret = 0;
+	unsigned long flags = 0;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	_clk_pll_enable(hw);
+	udelay(2);
+
+	val = pll_readl_misc(pll);
+	val &= ~PLLCX_MISC_RESET;
+	pll_writel_misc(val, pll);
+	udelay(2);
+
+	_pllcx_strobe(pll);
+
+	ret = clk_pll_wait_for_lock(pll);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
+}
+
+static void _clk_pllc_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val;
+
+	_clk_pll_disable(hw);
+
+	val = pll_readl_misc(pll);
+	val |= PLLCX_MISC_RESET;
+	pll_writel_misc(val, pll);
+	udelay(2);
+}
+
+static void clk_pllc_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	_clk_pllc_disable(hw);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int _pllcx_update_dynamic_coef(struct tegra_clk_pll *pll,
+					unsigned long input_rate, u32 n)
+{
+	u32 val, n_threshold;
+
+	switch (input_rate) {
+	case 12000000:
+		n_threshold = 70;
+		break;
+	case 13000000:
+	case 26000000:
+		n_threshold = 71;
+		break;
+	case 16800000:
+		n_threshold = 55;
+		break;
+	case 19200000:
+		n_threshold = 48;
+		break;
+	default:
+		pr_err("%s: Unexpected reference rate %lu\n",
+			__func__, input_rate);
+		return -EINVAL;
+	}
+
+	val = pll_readl_misc(pll);
+	val &= ~(PLLCX_MISC_SDM_DIV_MASK | PLLCX_MISC_FILT_DIV_MASK);
+	val |= n <= n_threshold ?
+		PLLCX_MISC_DIV_LOW_RANGE : PLLCX_MISC_DIV_HIGH_RANGE;
+	pll_writel_misc(val, pll);
+
+	return 0;
+}
+
+static int clk_pllc_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct tegra_clk_pll_freq_table cfg;
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	int state, ret = 0;
+	u32 val;
+	u16 old_m, old_n;
+	u8 old_p;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+	if (ret < 0)
+		goto out;
+
+	val = pll_readl_base(pll);
+	old_m = (val >> pll->divm_shift) & (divm_mask(pll));
+	old_n = (val >> pll->divn_shift) & (divn_mask(pll));
+	old_p = pllcx_p[(val >> pll->divp_shift) & (divp_mask(pll))];
+
+	if (cfg.m != old_m) {
+		WARN_ON(1);
+		goto out;
+	}
+
+	if (old_n == cfg.n && old_p == cfg.p)
+		goto out;
+
+	cfg.p -= 1;
+
+	state = clk_pll_is_enabled(hw);
+	if (state)
+		_clk_pllc_disable(hw);
+
+	ret = _pllcx_update_dynamic_coef(pll, parent_rate, cfg.n);
+	if (ret < 0)
+		goto out;
+
+	_update_pll_mnp(pll, &cfg);
+
+	if (state)
+		ret = clk_pllc_enable(hw);
+
+out:
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
+}
+
+static long _pllre_calc_rate(struct tegra_clk_pll *pll,
+			     struct tegra_clk_pll_freq_table *cfg,
+			     unsigned long rate, unsigned long parent_rate)
+{
+	u16 m, n;
+	u64 output_rate = parent_rate;
+
+	m = (parent_rate > pll->params->cf_max ? 2 : 1);
+	n = rate * m / parent_rate;
+
+	output_rate *= n;
+	do_div(output_rate, m);
+
+	if (cfg) {
+		cfg->m = m;
+		cfg->n = n;
+	}
+
+	return output_rate;
+}
+static int clk_pllre_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct tegra_clk_pll_freq_table cfg, old_cfg;
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	int state, ret = 0;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	_pllre_calc_rate(pll, &cfg, rate, parent_rate);
+	_get_pll_mnp(pll, &old_cfg);
+	cfg.p = old_cfg.p;
+
+	if (cfg.m != old_cfg.m || cfg.n != old_cfg.n) {
+		state = clk_pll_is_enabled(hw);
+		if (state)
+			_clk_pll_disable(hw);
+
+		_update_pll_mnp(pll, &cfg);
+
+		if (state) {
+			_clk_pll_enable(hw);
+			ret = clk_pll_wait_for_lock(pll);
+		}
+	}
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
+}
+
+static unsigned long clk_pllre_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct tegra_clk_pll_freq_table cfg;
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u64 rate = parent_rate;
+
+	_get_pll_mnp(pll, &cfg);
+
+	rate *= cfg.n;
+	do_div(rate, cfg.m);
+
+	return rate;
+}
+
+static long clk_pllre_round_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *prate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+
+	return _pllre_calc_rate(pll, NULL, rate, *prate);
+}
+
+static int clk_plle_tegra114_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct tegra_clk_pll_freq_table sel;
+	u32 val;
+	int ret;
+	unsigned long flags = 0;
+	unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+
+	if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
+		return -EINVAL;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	val = pll_readl_base(pll);
+	val &= ~BIT(29); /* Disable lock override */
+	pll_writel_base(val, pll);
+
+	val = pll_readl(pll->params->aux_reg, pll);
+	val |= PLLE_AUX_ENABLE_SWCTL;
+	val &= ~PLLE_AUX_SEQ_ENABLE;
+	pll_writel(val, pll->params->aux_reg, pll);
+	udelay(1);
+
+	val = pll_readl_misc(pll);
+	val |= PLLE_MISC_LOCK_ENABLE;
+	val |= PLLE_MISC_IDDQ_SW_CTRL;
+	val &= ~PLLE_MISC_IDDQ_SW_VALUE;
+	val |= PLLE_MISC_PLLE_PTS;
+	val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK;
+	pll_writel_misc(val, pll);
+	udelay(5);
+
+	val = pll_readl(PLLE_SS_CTRL, pll);
+	val |= PLLE_SS_DISABLE;
+	pll_writel(val, PLLE_SS_CTRL, pll);
+
+	val = pll_readl_base(pll);
+	val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
+	val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
+	val |= sel.m << pll->divm_shift;
+	val |= sel.n << pll->divn_shift;
+	val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
+	pll_writel_base(val, pll);
+	udelay(1);
+
+	_clk_pll_enable(hw);
+	ret = clk_pll_wait_for_lock(pll);
+
+	if (ret < 0)
+		goto out;
+
+	/* TODO: enable hw control of xusb brick pll */
+
+out:
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
+}
+
+static void clk_plle_tegra114_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	u32 val;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	_clk_pll_disable(hw);
+
+	val = pll_readl_misc(pll);
+	val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE;
+	pll_writel_misc(val, pll);
+	udelay(1);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+}
+#endif
+
 static struct clk *_tegra_clk_register_pll(const char *name,
 		const char *parent_name, void __iomem *clk_base,
 		void __iomem *pmc, unsigned long flags,
@@ -709,3 +1266,165 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 			flags, fixed_rate, pll_params, pll_flags, freq_table,
 			lock, &tegra_clk_plle_ops);
 }
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+const struct clk_ops tegra_clk_pllxc_ops = {
+	.is_enabled = clk_pll_is_enabled,
+	.enable = clk_pll_iddq_enable,
+	.disable = clk_pll_iddq_disable,
+	.recalc_rate = clk_pll_recalc_rate,
+	.round_rate = clk_pll_ramp_round_rate,
+	.set_rate = clk_pllxc_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllm_ops = {
+	.is_enabled = clk_pll_is_enabled,
+	.enable = clk_pll_iddq_enable,
+	.disable = clk_pll_iddq_disable,
+	.recalc_rate = clk_pll_recalc_rate,
+	.round_rate = clk_pll_ramp_round_rate,
+	.set_rate = clk_pllm_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllc_ops = {
+	.is_enabled = clk_pll_is_enabled,
+	.enable = clk_pllc_enable,
+	.disable = clk_pllc_disable,
+	.recalc_rate = clk_pll_recalc_rate,
+	.round_rate = clk_pll_ramp_round_rate,
+	.set_rate = clk_pllc_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllre_ops = {
+	.is_enabled = clk_pll_is_enabled,
+	.enable = clk_pll_iddq_enable,
+	.disable = clk_pll_iddq_disable,
+	.recalc_rate = clk_pllre_recalc_rate,
+	.round_rate = clk_pllre_round_rate,
+	.set_rate = clk_pllre_set_rate,
+};
+
+const struct clk_ops tegra_clk_plle_tegra114_ops = {
+	.is_enabled =  clk_pll_is_enabled,
+	.enable = clk_plle_tegra114_enable,
+	.disable = clk_plle_tegra114_disable,
+	.recalc_rate = clk_pll_recalc_rate,
+};
+
+
+struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
+			  void __iomem *clk_base, void __iomem *pmc,
+			  unsigned long flags, unsigned long fixed_rate,
+			  struct tegra_clk_pll_params *pll_params,
+			  u32 pll_flags,
+			  struct tegra_clk_pll_freq_table *freq_table,
+			  spinlock_t *lock)
+{
+	if (!pll_params->pdiv_tohw)
+		return -EINVAL;
+
+	return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, flags,
+			      fixed_rate, pll_params, pll_flags, freq_table,
+			      lock, &tegra_clk_pllxc_ops);
+}
+
+struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
+			  void __iomem *clk_base, void __iomem *pmc,
+			  unsigned long flags, unsigned long fixed_rate,
+			  struct tegra_clk_pll_params *pll_params,
+			  u32 pll_flags,
+			  struct tegra_clk_pll_freq_table *freq_table,
+			  spinlock_t *lock, unsigned long parent_rate)
+{
+	u32 val;
+
+	/* program minimum rate by default */
+
+	val = readl_relaxed(clk_base + pll_params->base_reg);
+	if (val & PLL_BASE_ENABLE)
+		WARN_ON(val & pll_params->iddq_bit_idx);
+	else {
+		int m;
+
+		m = (parent_rate > pll_params->cf_max) ? 2 : 1;
+		val = m << PLL_BASE_DIVM_SHIFT;
+		val |= (pll_params->vco_min / parent_rate)
+				<< PLL_BASE_DIVN_SHIFT;
+		writel_relaxed(val, clk_base + pll_params->base_reg);
+	}
+
+	/* disable lock override */
+
+	val = readl_relaxed(clk_base + pll_params->misc_reg);
+	val &= ~BIT(29);
+	writel_relaxed(val, clk_base + pll_params->misc_reg);
+
+	return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, flags,
+			      fixed_rate, pll_params, pll_flags, freq_table,
+			      lock, &tegra_clk_pllre_ops);
+}
+
+struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
+			  void __iomem *clk_base, void __iomem *pmc,
+			  unsigned long flags, unsigned long fixed_rate,
+			  struct tegra_clk_pll_params *pll_params,
+			  u32 pll_flags,
+			  struct tegra_clk_pll_freq_table *freq_table,
+			  spinlock_t *lock)
+{
+	if (!pll_params->pdiv_tohw)
+		return -EINVAL;
+
+	pll_flags |= TEGRA_PLL_BYPASS;
+	return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, flags,
+			      fixed_rate, pll_params, pll_flags, freq_table,
+			      lock, &tegra_clk_pllm_ops);
+}
+
+struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
+			  void __iomem *clk_base, void __iomem *pmc,
+			  unsigned long flags, unsigned long fixed_rate,
+			  struct tegra_clk_pll_params *pll_params,
+			  u32 pll_flags,
+			  struct tegra_clk_pll_freq_table *freq_table,
+			  spinlock_t *lock)
+{
+	if (!pll_params->pdiv_tohw)
+		return -EINVAL;
+
+	pll_flags |= TEGRA_PLL_BYPASS;
+	return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, flags,
+			      fixed_rate, pll_params, pll_flags, freq_table,
+			      lock, &tegra_clk_pllc_ops);
+
+}
+
+struct clk *tegra_clk_register_plle_tegra114(const char *name,
+				const char *parent_name,
+				void __iomem *clk_base, unsigned long flags,
+				unsigned long fixed_rate,
+				struct tegra_clk_pll_params *pll_params,
+				struct tegra_clk_pll_freq_table *freq_table,
+				spinlock_t *lock)
+{
+	u32 val, val_aux;
+
+	/* ensure parent is set to pll_re_vco */
+
+	val = readl_relaxed(clk_base + pll_params->base_reg);
+	val_aux = readl_relaxed(clk_base + pll_params->aux_reg);
+
+	if (val & PLL_BASE_ENABLE) {
+		if (!(val_aux & PLLE_AUX_PLLRE_SEL))
+			WARN(1, "pll_e enabled with unsupported parent %s\n",
+			  (val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref");
+	} else {
+		val_aux |= PLLE_AUX_PLLRE_SEL;
+		writel_relaxed(val, clk_base + pll_params->aux_reg);
+	}
+
+	return _tegra_clk_register_pll(name, parent_name, clk_base, NULL, flags,
+			      fixed_rate, pll_params, 0, freq_table, lock,
+			      &tegra_clk_plle_tegra114_ops);
+}
+#endif
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 1b9cbcd..4d0f556 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -156,6 +156,12 @@ struct tegra_clk_pll_params {
 	u32		lock_reg;
 	u32		lock_bit_idx;
 	u32		lock_enable_bit_idx;
+	u32		iddq_reg;
+	u32		iddq_bit_idx;
+	u32		aux_reg;
+	u32		dyn_ramp_reg;
+	int		stepa_shift;
+	int		stepb_shift;
 	int		lock_delay;
 	int		max_p;
 	struct pdiv_map *pdiv_tohw;
@@ -233,12 +239,53 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
 		unsigned long flags, unsigned long fixed_rate,
 		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
 		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+
 struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 		void __iomem *clk_base, void __iomem *pmc,
 		unsigned long flags, unsigned long fixed_rate,
 		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
 		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
 
+struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
+			    void __iomem *clk_base, void __iomem *pmc,
+			    unsigned long flags, unsigned long fixed_rate,
+			    struct tegra_clk_pll_params *pll_params,
+			    u32 pll_flags,
+			    struct tegra_clk_pll_freq_table *freq_table,
+			    spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
+			   void __iomem *clk_base, void __iomem *pmc,
+			   unsigned long flags, unsigned long fixed_rate,
+			   struct tegra_clk_pll_params *pll_params,
+			   u32 pll_flags,
+			   struct tegra_clk_pll_freq_table *freq_table,
+			   spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
+			   void __iomem *clk_base, void __iomem *pmc,
+			   unsigned long flags, unsigned long fixed_rate,
+			   struct tegra_clk_pll_params *pll_params,
+			   u32 pll_flags,
+			   struct tegra_clk_pll_freq_table *freq_table,
+			   spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
+			   void __iomem *clk_base, void __iomem *pmc,
+			   unsigned long flags, unsigned long fixed_rate,
+			   struct tegra_clk_pll_params *pll_params,
+			   u32 pll_flags,
+			   struct tegra_clk_pll_freq_table *freq_table,
+			   spinlock_t *lock, unsigned long parent_rate);
+
+struct clk *tegra_clk_register_plle_tegra114(const char *name,
+				const char *parent_name,
+				void __iomem *clk_base, unsigned long flags,
+				unsigned long fixed_rate,
+				struct tegra_clk_pll_params *pll_params,
+				struct tegra_clk_pll_freq_table *freq_table,
+				spinlock_t *lock);
+
 /**
  * struct tegra_clk_pll_out - PLL divider down clock
  *

^ permalink raw reply related

* [PATCH v5 05/10] clk: tegra: Add flags to tegra_clk_periph()
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

We will need some tegra peripheral clocks with the CLK_IGNORE_UNUSED flag,
most notably mselect, which is a bridge between AXI and most peripherals.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/clk-periph.c  |   11 ++++++-----
 drivers/clk/tegra/clk-tegra20.c |    2 +-
 drivers/clk/tegra/clk-tegra30.c |    2 +-
 drivers/clk/tegra/clk.h         |    9 ++++++---
 4 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index 788486e..067abb3 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -170,14 +170,15 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = {
 static struct clk *_tegra_clk_register_periph(const char *name,
 			const char **parent_names, int num_parents,
 			struct tegra_clk_periph *periph,
-			void __iomem *clk_base, u32 offset, bool div)
+			void __iomem *clk_base, u32 offset, bool div,
+			unsigned long flags)
 {
 	struct clk *clk;
 	struct clk_init_data init;
 
 	init.name = name;
 	init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
-	init.flags = div ? 0 : CLK_SET_RATE_PARENT;
+	init.flags = flags;
 	init.parent_names = parent_names;
 	init.num_parents = num_parents;
 
@@ -202,10 +203,10 @@ static struct clk *_tegra_clk_register_periph(const char *name,
 struct clk *tegra_clk_register_periph(const char *name,
 		const char **parent_names, int num_parents,
 		struct tegra_clk_periph *periph, void __iomem *clk_base,
-		u32 offset)
+		u32 offset, unsigned long flags)
 {
 	return _tegra_clk_register_periph(name, parent_names, num_parents,
-			periph, clk_base, offset, true);
+			periph, clk_base, offset, true, flags);
 }
 
 struct clk *tegra_clk_register_periph_nodiv(const char *name,
@@ -214,5 +215,5 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
 		u32 offset)
 {
 	return _tegra_clk_register_periph(name, parent_names, num_parents,
-			periph, clk_base, offset, false);
+			periph, clk_base, offset, false, CLK_SET_RATE_PARENT);
 }
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 54c6777..870349e 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -1048,7 +1048,7 @@ static void __init tegra20_periph_clk_init(void)
 		data = &tegra_periph_clk_list[i];
 		clk = tegra_clk_register_periph(data->name, data->parent_names,
 				data->num_parents, &data->periph,
-				clk_base, data->offset);
+				clk_base, data->offset, data->flags);
 		clk_register_clkdev(clk, data->con_id, data->dev_id);
 		clks[data->clk_id] = clk;
 	}
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 078f9b8..126747b 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -1665,7 +1665,7 @@ static void __init tegra30_periph_clk_init(void)
 		data = &tegra_periph_clk_list[i];
 		clk = tegra_clk_register_periph(data->name, data->parent_names,
 				data->num_parents, &data->periph,
-				clk_base, data->offset);
+				clk_base, data->offset, data->flags);
 		clk_register_clkdev(clk, data->con_id, data->dev_id);
 		clks[data->clk_id] = clk;
 	}
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 4d0f556..79f5e2a 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -411,7 +411,7 @@ extern const struct clk_ops tegra_clk_periph_ops;
 struct clk *tegra_clk_register_periph(const char *name,
 		const char **parent_names, int num_parents,
 		struct tegra_clk_periph *periph, void __iomem *clk_base,
-		u32 offset);
+		u32 offset, unsigned long flags);
 struct clk *tegra_clk_register_periph_nodiv(const char *name,
 		const char **parent_names, int num_parents,
 		struct tegra_clk_periph *periph, void __iomem *clk_base,
@@ -454,12 +454,14 @@ struct tegra_periph_init_data {
 	u32 offset;
 	const char *con_id;
 	const char *dev_id;
+	unsigned long flags;
 };
 
 #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
 			_mux_shift, _mux_mask, _mux_flags, _div_shift,	\
 			_div_width, _div_frac_width, _div_flags, _regs,	\
-			_clk_num, _enb_refcnt, _gate_flags, _clk_id, _table) \
+			_clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\
+			_flags) \
 	{								\
 		.name = _name,						\
 		.clk_id = _clk_id,					\
@@ -474,6 +476,7 @@ struct tegra_periph_init_data {
 		.offset = _offset,					\
 		.con_id = _con_id,					\
 		.dev_id = _dev_id,					\
+		.flags = _flags						\
 	}
 
 #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
@@ -484,7 +487,7 @@ struct tegra_periph_init_data {
 			_mux_shift, BIT(_mux_width) - 1, _mux_flags,	\
 			_div_shift, _div_width, _div_frac_width, _div_flags, \
 			_regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\
-			NULL)
+			NULL, 0)
 
 /**
  * struct clk_super_mux - super clock

^ permalink raw reply related

* [PATCH v5 06/10] clk: tegra: Workaround for Tegra114 MSENC problem
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

Workaround a hardware bug in MSENC during clock enable.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/clk-periph-gate.c |    9 +++++++++
 drivers/clk/tegra/clk.h             |    1 +
 2 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
index 6dd5332..c9083fb 100644
--- a/drivers/clk/tegra/clk-periph-gate.c
+++ b/drivers/clk/tegra/clk-periph-gate.c
@@ -43,6 +43,8 @@ static DEFINE_SPINLOCK(periph_ref_lock);
 
 #define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32))
 
+#define LVL2_CLK_GATE_OVRE 0x554
+
 /* Peripheral gate clock ops */
 static int clk_periph_is_enabled(struct clk_hw *hw)
 {
@@ -83,6 +85,13 @@ static int clk_periph_enable(struct clk_hw *hw)
 		}
 	}
 
+	if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
+		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
+		writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
+		udelay(1);
+		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
+	}
+
 	spin_unlock_irqrestore(&periph_ref_lock, flags);
 
 	return 0;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 79f5e2a..8756d9f 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -371,6 +371,7 @@ struct tegra_clk_periph_gate {
 #define TEGRA_PERIPH_NO_RESET BIT(0)
 #define TEGRA_PERIPH_MANUAL_RESET BIT(1)
 #define TEGRA_PERIPH_ON_APB BIT(2)
+#define TEGRA_PERIPH_WAR_1005168 BIT(3)
 
 void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
 extern const struct clk_ops tegra_clk_periph_gate_ops;

^ permalink raw reply related

* [PATCH v5 07/10] ARM: tegra: Define Tegra114 CAR binding
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

The device tree binding models Tegra114 CAR (Clock And Reset) as a single
monolithic clock provider.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 .../bindings/clock/nvidia,tegra114-car.txt         |  311 ++++++++++++++++++++
 1 files changed, 311 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt

diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
new file mode 100644
index 0000000..516b9d3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
@@ -0,0 +1,311 @@
+NVIDIA Tegra114 Clock And Reset Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
+for muxing and gating Tegra's clocks, and setting their rates.
+
+Required properties :
+- compatible : Should be "nvidia,tegra114-car"
+- reg : Should contain CAR registers location and length
+- clocks : Should contain phandle and clock specifiers for two clocks:
+  the 32 KHz "32k_in", and the board-specific oscillator "osc".
+- #clock-cells : Should be 1.
+  In clock consumers, this cell represents the clock ID exposed by the CAR.
+
+  The first 160 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+  registers. These IDs often match those in the CAR's RST_DEVICES registers,
+  but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+  this case, those clocks are assigned IDs above 160 in order to highlight
+  this issue. Implementations that interpret these clock IDs as bit values
+  within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+  explicitly handle these special cases.
+
+  The balance of the clocks controlled by the CAR are assigned IDs of 160 and
+  above.
+
+  0	cpu
+  1	unassigned
+  2	unassigned
+  3	unassigned
+  4	rtc
+  5	timer
+  6	uarta
+  7	unassigned	(register bit affects uartb and vfir)
+  8	unassigned
+  9	sdmmc2
+  10	unassigned	(register bit affects spdif_in and spdif_out)
+  11	i2s1
+  12	i2c1
+  13	ndflash
+  14	sdmmc1
+  15	sdmmc4
+  16	unassigned
+  17	pwm
+  18	i2s2
+  19	epp
+  20	unassigned	(register bit affects vi and vi_sensor)
+  21	2d
+  22	usbd
+  23	isp
+  24	3d
+  25	unassigned
+  26	disp2
+  27	disp1
+  28	host1x
+  29	vcp
+  30	i2s0
+  31	unassigned
+
+  32	unassigned
+  33	unassigned
+  34	apbdma
+  35	unassigned
+  36	kbc
+  37	unassigned
+  38	unassigned
+  39	unassigned	(register bit affects fuse and fuse_burn)
+  40	kfuse
+  41	sbc1
+  42	nor
+  43	unassigned
+  44	sbc2
+  45	unassigned
+  46	sbc3
+  47	i2c5
+  48	dsia
+  49	unassigned
+  50	mipi
+  51	hdmi
+  52	csi
+  53	unassigned
+  54	i2c2
+  55	uartc
+  56	mipi-cal
+  57	unassigned
+  58	usb2
+  59	usb3
+  60	msenc
+  61	vde
+  62	bsea
+  63	bsev
+
+  64	unassigned
+  65	uartd
+  66	unassigned
+  67	i2c3
+  68	sbc4
+  69	sdmmc3
+  70	unassigned
+  71	owr
+  72	afi
+  73	csite
+  74	unassigned
+  75	unassigned
+  76	la
+  77	trace
+  78	soc_therm
+  79	dtv
+  80	ndspeed
+  81	i2cslow
+  82	dsib
+  83	tsec
+  84	unassigned
+  85	unassigned
+  86	unassigned
+  87	unassigned
+  88	unassigned
+  89	xusb_host
+  90	unassigned
+  91	msenc
+  92	csus
+  93	unassigned
+  94	unassigned
+  95	unassigned	(bit affects xusb_dev and xusb_dev_src)
+
+  96	unassigned
+  97	unassigned
+  98	unassigned
+  99	mselect
+  100	tsensor
+  101	i2s3
+  102	i2s4
+  103	i2c4
+  104	sbc5
+  105	sbc6
+  106	d_audio
+  107	apbif
+  108	dam0
+  109	dam1
+  110	dam2
+  111	hda2codec_2x
+  112	unassigned
+  113	audio0_2x
+  114	audio1_2x
+  115	audio2_2x
+  116	audio3_2x
+  117	audio4_2x
+  118	spdif_2x
+  119	actmon
+  120	extern1
+  121	extern2
+  122	extern3
+  123	unassigned
+  124	unassigned
+  125	hda
+  126	unassigned
+  127	se
+
+  128	hda2hdmi
+  129	unassigned
+  130	unassigned
+  131	unassigned
+  132	unassigned
+  133	unassigned
+  134	unassigned
+  135	unassigned
+  136	unassigned
+  137	unassigned
+  138	unassigned
+  139	unassigned
+  140	unassigned
+  141	unassigned
+  142	unassigned
+  143	unassigned	(bit affects xusb_falcon_src, xusb_fs_src,
+			 xusb_host_src and xusb_ss_src)
+  144	cilab
+  145	cilcd
+  146	cile
+  147	dsialp
+  148	dsiblp
+  149	unassigned
+  150	dds
+  151	unassigned
+  152	dp2
+  153	amx
+  154	adx
+  155	unassigned
+  156	xusb_ss
+
+  192	uartb
+  193	vfir
+  194	spdif_in
+  195	spdif_out
+  196	vi
+  197	vi_sensor
+  198	fuse
+  199	fuse_burn
+  200	clk_32k
+  201	clk_m
+  202	clk_m_div2
+  203	clk_m_div4
+  204	pll_ref
+  205	pll_c
+  206	pll_c_out1
+  207	pll_c2
+  208	pll_c3
+  209	pll_m
+  210	pll_m_out1
+  211	pll_p
+  212	pll_p_out1
+  213	pll_p_out2
+  214	pll_p_out3
+  215	pll_p_out4
+  216	pll_a
+  217	pll_a_out1
+  218	pll_d
+  219	pll_d_out0
+  220	pll_d2
+  221	pll_d2_out0
+  222	pll_u
+  223	pll_u_480M
+  224	pll_u_60M
+  225	pll_u_48M
+  226	pll_u_12M
+  227	pll_x
+  228	pll_x_out0
+  229	pll_re_vco
+  230	pll_re_out
+  231	pll_e_out0
+  232	spdif_in_sync
+  233	i2s0_sync
+  234	i2s1_sync
+  235	i2s2_sync
+  236	i2s3_sync
+  237	i2s4_sync
+  238	vimclk_sync
+  239	audio0
+  240	audio1
+  241	audio2
+  242	audio3
+  243	audio4
+  244	spdif
+  245	clk_out_1
+  246	clk_out_2
+  247	clk_out_3
+  248	blink
+  249	mipi_cal_fast
+  250	dsi1_fixed
+  251	dsi2_fixed
+  252	xusb_host_src
+  253	xusb_falcon_src
+  254	xusb_fs_src
+  255	xusb_ss_src
+  256	xusb_dev_src
+  257	xusb_dev
+  258	xusb_hs_src
+
+Mux clocks
+
+  300	audio0_mux
+  301	audio1_mux
+  302	audio2_mux
+  303	audio3_mux
+  304	audio4_mux
+  305	spdif_mux
+  306	clk_out_1_mux
+  307	clk_out_2_mux
+  308	clk_out_3_mux
+
+Example SoC include file:
+
+/ {
+	tegra_car: clock {
+		compatible = "nvidia,tegra114-car";
+		reg = <0x60006000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	usb at c5004000 {
+		clocks = <&tegra_car 58>; /* usb2 */
+	};
+};
+
+Example board file:
+
+/ {
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc: clock at 0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <12000000>;
+		};
+
+		clk_32k: clock at 1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	&tegra_car {
+		clocks = <&clk_32k> <&osc>;
+	};
+};

^ permalink raw reply related

* [PATCH v5 08/10] ARM: dt: Add references to tegra_car clocks
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

Add references to tegra_car clocks for the basic device nodes.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/boot/dts/tegra114.dtsi |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 96a8235..1dec620 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -27,7 +27,7 @@
 	};
 
 	tegra_car: clock {
-		compatible = "nvidia,tegra114-car, nvidia,tegra30-car";
+		compatible = "nvidia,tegra114-car";
 		reg = <0x60006000 0x1000>;
 		#clock-cells = <1>;
 	};
@@ -43,6 +43,7 @@
 		reg-shift = <2>;
 		interrupts = <0 36 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 6>;
 	};
 
 	serial at 70006040 {
@@ -51,6 +52,7 @@
 		reg-shift = <2>;
 		interrupts = <0 37 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 192>;
 	};
 
 	serial at 70006200 {
@@ -59,6 +61,7 @@
 		reg-shift = <2>;
 		interrupts = <0 46 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 55>;
 	};
 
 	serial at 70006300 {
@@ -67,12 +70,14 @@
 		reg-shift = <2>;
 		interrupts = <0 90 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 65>;
 	};
 
 	rtc {
 		compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc";
 		reg = <0x7000e000 0x100>;
 		interrupts = <0 2 0x04>;
+		clocks = <&tegra_car 4>;
 	};
 
 	pmc {

^ permalink raw reply related

* [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

Implement most clocks for Tegra114. The super clocks for the CPU complex
are still missing and will be implemented in a future version.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/Makefile       |    1 +
 drivers/clk/tegra/clk-tegra114.c | 2002 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 2003 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/tegra/clk-tegra114.c

diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 2b41b0f..f49fac2 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -9,3 +9,4 @@ obj-y					+= clk-super.o
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clk-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += clk-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= clk-tegra114.o
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
new file mode 100644
index 0000000..f8165d2
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -0,0 +1,2002 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+
+#define RST_DEVICES_L			0x004
+#define RST_DEVICES_H			0x008
+#define RST_DEVICES_U			0x00C
+#define RST_DEVICES_V			0x358
+#define RST_DEVICES_W			0x35C
+#define RST_DEVICES_X			0x28C
+#define RST_DEVICES_SET_L		0x300
+#define RST_DEVICES_CLR_L		0x304
+#define RST_DEVICES_SET_H		0x308
+#define RST_DEVICES_CLR_H		0x30c
+#define RST_DEVICES_SET_U		0x310
+#define RST_DEVICES_CLR_U		0x314
+#define RST_DEVICES_SET_V		0x430
+#define RST_DEVICES_CLR_V		0x434
+#define RST_DEVICES_SET_W		0x438
+#define RST_DEVICES_CLR_W		0x43c
+#define RST_DEVICES_NUM			5
+
+#define CLK_OUT_ENB_L			0x010
+#define CLK_OUT_ENB_H			0x014
+#define CLK_OUT_ENB_U			0x018
+#define CLK_OUT_ENB_V			0x360
+#define CLK_OUT_ENB_W			0x364
+#define CLK_OUT_ENB_X			0x280
+#define CLK_OUT_ENB_SET_L		0x320
+#define CLK_OUT_ENB_CLR_L		0x324
+#define CLK_OUT_ENB_SET_H		0x328
+#define CLK_OUT_ENB_CLR_H		0x32c
+#define CLK_OUT_ENB_SET_U		0x330
+#define CLK_OUT_ENB_CLR_U		0x334
+#define CLK_OUT_ENB_SET_V		0x440
+#define CLK_OUT_ENB_CLR_V		0x444
+#define CLK_OUT_ENB_SET_W		0x448
+#define CLK_OUT_ENB_CLR_W		0x44c
+#define CLK_OUT_ENB_SET_X		0x284
+#define CLK_OUT_ENB_CLR_X		0x288
+#define CLK_OUT_ENB_NUM			6
+
+#define PLLC_BASE 0x80
+#define PLLC_MISC2 0x88
+#define PLLC_MISC 0x8c
+#define PLLC2_BASE 0x4e8
+#define PLLC2_MISC 0x4ec
+#define PLLC3_BASE 0x4fc
+#define PLLC3_MISC 0x500
+#define PLLM_BASE 0x90
+#define PLLM_MISC 0x9c
+#define PLLP_BASE 0xa0
+#define PLLP_MISC 0xac
+#define PLLX_BASE 0xe0
+#define PLLX_MISC 0xe4
+#define PLLX_MISC2 0x514
+#define PLLX_MISC3 0x518
+#define PLLD_BASE 0xd0
+#define PLLD_MISC 0xdc
+#define PLLD2_BASE 0x4b8
+#define PLLD2_MISC 0x4bc
+#define PLLE_BASE 0xe8
+#define PLLE_MISC 0xec
+#define PLLA_BASE 0xb0
+#define PLLA_MISC 0xbc
+#define PLLU_BASE 0xc0
+#define PLLU_MISC 0xcc
+#define PLLRE_BASE 0x4c4
+#define PLLRE_MISC 0x4c8
+
+#define PLL_MISC_LOCK_ENABLE 18
+#define PLLDU_MISC_LOCK_ENABLE 22
+#define PLLE_MISC_LOCK_ENABLE 9
+#define PLLRE_MISC_LOCK_ENABLE 30
+
+#define PLLC_IDDQ_BIT 26
+#define PLLX_IDDQ_BIT 3
+#define PLLRE_IDDQ_BIT 16
+
+#define PLL_BASE_LOCK 27
+#define PLLE_MISC_LOCK 11
+#define PLLRE_MISC_LOCK 24
+
+#define PLLE_AUX 0x48c
+#define PLLC_OUT 0x84
+#define PLLM_OUT 0x94
+#define PLLP_OUTA 0xa4
+#define PLLP_OUTB 0xa8
+#define PLLA_OUT 0xb4
+
+#define AUDIO_SYNC_CLK_I2S0 0x4a0
+#define AUDIO_SYNC_CLK_I2S1 0x4a4
+#define AUDIO_SYNC_CLK_I2S2 0x4a8
+#define AUDIO_SYNC_CLK_I2S3 0x4ac
+#define AUDIO_SYNC_CLK_I2S4 0x4b0
+#define AUDIO_SYNC_CLK_SPDIF 0x4b4
+
+#define AUDIO_SYNC_DOUBLER 0x49c
+
+#define PMC_CLK_OUT_CNTRL 0x1a8
+#define PMC_DPD_PADS_ORIDE 0x1c
+#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
+#define PMC_CTRL 0
+#define PMC_CTRL_BLINK_ENB 7
+
+#define OSC_CTRL			0x50
+#define OSC_CTRL_OSC_FREQ_SHIFT		28
+#define OSC_CTRL_PLL_REF_DIV_SHIFT	26
+
+#define PLLXC_SW_MAX_P			6
+
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
+
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+
+#define UTMIPLL_HW_PWRDN_CFG0			0x52c
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE	BIT(25)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE	BIT(24)
+#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET	BIT(6)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE	BIT(5)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL	BIT(4)
+#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL	BIT(2)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE	BIT(1)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL	BIT(0)
+
+#define CLK_SOURCE_I2S0 0x1d8
+#define CLK_SOURCE_I2S1 0x100
+#define CLK_SOURCE_I2S2 0x104
+#define CLK_SOURCE_NDFLASH 0x160
+#define CLK_SOURCE_I2S3 0x3bc
+#define CLK_SOURCE_I2S4 0x3c0
+#define CLK_SOURCE_SPDIF_OUT 0x108
+#define CLK_SOURCE_SPDIF_IN 0x10c
+#define CLK_SOURCE_PWM 0x110
+#define CLK_SOURCE_ADX 0x638
+#define CLK_SOURCE_AMX 0x63c
+#define CLK_SOURCE_HDA 0x428
+#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
+#define CLK_SOURCE_SBC1 0x134
+#define CLK_SOURCE_SBC2 0x118
+#define CLK_SOURCE_SBC3 0x11c
+#define CLK_SOURCE_SBC4 0x1b4
+#define CLK_SOURCE_SBC5 0x3c8
+#define CLK_SOURCE_SBC6 0x3cc
+#define CLK_SOURCE_SATA_OOB 0x420
+#define CLK_SOURCE_SATA 0x424
+#define CLK_SOURCE_NDSPEED 0x3f8
+#define CLK_SOURCE_VFIR 0x168
+#define CLK_SOURCE_SDMMC1 0x150
+#define CLK_SOURCE_SDMMC2 0x154
+#define CLK_SOURCE_SDMMC3 0x1bc
+#define CLK_SOURCE_SDMMC4 0x164
+#define CLK_SOURCE_VDE 0x1c8
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_LA 0x1f8
+#define CLK_SOURCE_TRACE 0x634
+#define CLK_SOURCE_OWR 0x1cc
+#define CLK_SOURCE_NOR 0x1d0
+#define CLK_SOURCE_MIPI 0x174
+#define CLK_SOURCE_I2C1 0x124
+#define CLK_SOURCE_I2C2 0x198
+#define CLK_SOURCE_I2C3 0x1b8
+#define CLK_SOURCE_I2C4 0x3c4
+#define CLK_SOURCE_I2C5 0x128
+#define CLK_SOURCE_UARTA 0x178
+#define CLK_SOURCE_UARTB 0x17c
+#define CLK_SOURCE_UARTC 0x1a0
+#define CLK_SOURCE_UARTD 0x1c0
+#define CLK_SOURCE_UARTE 0x1c4
+#define CLK_SOURCE_UARTA_DBG 0x178
+#define CLK_SOURCE_UARTB_DBG 0x17c
+#define CLK_SOURCE_UARTC_DBG 0x1a0
+#define CLK_SOURCE_UARTD_DBG 0x1c0
+#define CLK_SOURCE_UARTE_DBG 0x1c4
+#define CLK_SOURCE_3D 0x158
+#define CLK_SOURCE_2D 0x15c
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+#define CLK_SOURCE_VI 0x148
+#define CLK_SOURCE_EPP 0x16c
+#define CLK_SOURCE_MSENC 0x1f0
+#define CLK_SOURCE_TSEC 0x1f4
+#define CLK_SOURCE_HOST1X 0x180
+#define CLK_SOURCE_HDMI 0x18c
+#define CLK_SOURCE_DISP1 0x138
+#define CLK_SOURCE_DISP2 0x13c
+#define CLK_SOURCE_CILAB 0x614
+#define CLK_SOURCE_CILCD 0x618
+#define CLK_SOURCE_CILE 0x61c
+#define CLK_SOURCE_DSIALP 0x620
+#define CLK_SOURCE_DSIBLP 0x624
+#define CLK_SOURCE_TSENSOR 0x3b8
+#define CLK_SOURCE_D_AUDIO 0x3d0
+#define CLK_SOURCE_DAM0 0x3d8
+#define CLK_SOURCE_DAM1 0x3dc
+#define CLK_SOURCE_DAM2 0x3e0
+#define CLK_SOURCE_ACTMON 0x3e8
+#define CLK_SOURCE_EXTERN1 0x3ec
+#define CLK_SOURCE_EXTERN2 0x3f0
+#define CLK_SOURCE_EXTERN3 0x3f4
+#define CLK_SOURCE_I2CSLOW 0x3fc
+#define CLK_SOURCE_SE 0x42c
+#define CLK_SOURCE_MSELECT 0x3b4
+#define CLK_SOURCE_SOC_THERM 0x644
+#define CLK_SOURCE_XUSB_HOST_SRC 0x600
+#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
+#define CLK_SOURCE_XUSB_FS_SRC 0x608
+#define CLK_SOURCE_XUSB_SS_SRC 0x610
+#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
+
+static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
+
+static void __iomem *clk_base;
+static void __iomem *pmc_base;
+
+static DEFINE_SPINLOCK(pll_d_lock);
+static DEFINE_SPINLOCK(pll_d2_lock);
+static DEFINE_SPINLOCK(pll_u_lock);
+static DEFINE_SPINLOCK(pll_div_lock);
+static DEFINE_SPINLOCK(pll_re_lock);
+static DEFINE_SPINLOCK(clk_doubler_lock);
+static DEFINE_SPINLOCK(clk_out_lock);
+
+static struct pdiv_map pllxc_p[] = {
+	{ .pdiv = 1, .hw_val = 0 },
+	{ .pdiv = 2, .hw_val = 1 },
+	{ .pdiv = 3, .hw_val = 2 },
+	{ .pdiv = 4, .hw_val = 3 },
+	{ .pdiv = 5, .hw_val = 4 },
+	{ .pdiv = 6, .hw_val = 5 },
+	{ .pdiv = 8, .hw_val = 6 },
+	{ .pdiv = 10, .hw_val = 7 },
+	{ .pdiv = 12, .hw_val = 8 },
+	{ .pdiv = 16, .hw_val = 9 },
+	{ .pdiv = 12, .hw_val = 10 },
+	{ .pdiv = 16, .hw_val = 11 },
+	{ .pdiv = 20, .hw_val = 12 },
+	{ .pdiv = 24, .hw_val = 13 },
+	{ .pdiv = 32, .hw_val = 14 },
+	{ .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
+	{ 12000000, 624000000, 104, 0, 2},
+	{ 12000000, 600000000, 100, 0, 2},
+	{ 13000000, 600000000,  92, 0, 2},	/* actual: 598.0 MHz */
+	{ 16800000, 600000000,  71, 0, 2},	/* actual: 596.4 MHz */
+	{ 19200000, 600000000,  62, 0, 2},	/* actual: 595.2 MHz */
+	{ 26000000, 600000000,  92, 1, 2},	/* actual: 598.0 MHz */
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_c_params = {
+	.input_min = 12000000,
+	.input_max = 800000000,
+	.cf_min = 12000000,
+	.cf_max = 19200000,	/* s/w policy, h/w capability 50 MHz */
+	.vco_min = 600000000,
+	.vco_max = 1400000000,
+	.base_reg = PLLC_BASE,
+	.misc_reg = PLLC_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.iddq_reg = PLLC_MISC,
+	.iddq_bit_idx = PLLC_IDDQ_BIT,
+	.max_p = PLLXC_SW_MAX_P,
+	.dyn_ramp_reg = PLLC_MISC2,
+	.stepa_shift = 17,
+	.stepb_shift = 9,
+	.pdiv_tohw = pllxc_p,
+};
+
+static struct pdiv_map pllc_p[] = {
+	{ .pdiv = 1, .hw_val = 0 },
+	{ .pdiv = 2, .hw_val = 1 },
+	{ .pdiv = 4, .hw_val = 3 },
+	{ .pdiv = 8, .hw_val = 5 },
+	{ .pdiv = 16, .hw_val = 7 },
+	{ .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
+	{12000000, 600000000, 100, 0, 2},
+	{13000000, 600000000, 92, 0, 2},	/* actual: 598.0 MHz */
+	{16800000, 600000000, 71, 0, 2},	/* actual: 596.4 MHz */
+	{19200000, 600000000, 62, 0, 2},	/* actual: 595.2 MHz */
+	{26000000, 600000000, 92, 1, 2},	/* actual: 598.0 MHz */
+	{0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_c2_params = {
+	.input_min = 12000000,
+	.input_max = 48000000,
+	.cf_min = 12000000,
+	.cf_max = 19200000,
+	.vco_min = 600000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLC2_BASE,
+	.misc_reg = PLLC2_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.pdiv_tohw = pllc_p,
+};
+
+static struct tegra_clk_pll_params pll_c3_params = {
+	.input_min = 12000000,
+	.input_max = 48000000,
+	.cf_min = 12000000,
+	.cf_max = 19200000,
+	.vco_min = 600000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLC3_BASE,
+	.misc_reg = PLLC3_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.pdiv_tohw = pllc_p,
+};
+
+static struct pdiv_map pllm_p[] = {
+	{ .pdiv = 1, .hw_val = 0 },
+	{ .pdiv = 2, .hw_val = 1 },
+	{ .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
+	{12000000, 800000000, 66, 0, 1},	/* actual: 792.0 MHz */
+	{13000000, 800000000, 61, 0, 1},	/* actual: 793.0 MHz */
+	{16800000, 800000000, 47, 0, 1},	/* actual: 789.6 MHz */
+	{19200000, 800000000, 41, 0, 1},	/* actual: 787.2 MHz */
+	{26000000, 800000000, 61, 1, 1},	/* actual: 793.0 MHz */
+	{0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_m_params = {
+	.input_min = 12000000,
+	.input_max = 500000000,
+	.cf_min = 12000000,
+	.cf_max = 19200000,	/* s/w policy, h/w capability 50 MHz */
+	.vco_min = 400000000,
+	.vco_max = 1066000000,
+	.base_reg = PLLM_BASE,
+	.misc_reg = PLLM_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.max_p = 2,
+	.pdiv_tohw = pllm_p,
+};
+
+static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
+	{12000000, 216000000, 432, 12, 1, 8},
+	{13000000, 216000000, 432, 13, 1, 8},
+	{16800000, 216000000, 360, 14, 1, 8},
+	{19200000, 216000000, 360, 16, 1, 8},
+	{26000000, 216000000, 432, 26, 1, 8},
+	{0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_p_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 200000000,
+	.vco_max = 700000000,
+	.base_reg = PLLP_BASE,
+	.misc_reg = PLLP_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
+	{9600000, 282240000, 147, 5, 0, 4},
+	{9600000, 368640000, 192, 5, 0, 4},
+	{9600000, 240000000, 200, 8, 0, 8},
+
+	{28800000, 282240000, 245, 25, 0, 8},
+	{28800000, 368640000, 320, 25, 0, 8},
+	{28800000, 240000000, 200, 24, 0, 8},
+	{0, 0, 0, 0, 0, 0},
+};
+
+
+static struct tegra_clk_pll_params pll_a_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 200000000,
+	.vco_max = 700000000,
+	.base_reg = PLLA_BASE,
+	.misc_reg = PLLA_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
+	{12000000, 216000000, 864, 12, 2, 12},
+	{13000000, 216000000, 864, 13, 2, 12},
+	{16800000, 216000000, 720, 14, 2, 12},
+	{19200000, 216000000, 720, 16, 2, 12},
+	{26000000, 216000000, 864, 26, 2, 12},
+
+	{12000000, 594000000, 594, 12, 0, 12},
+	{13000000, 594000000, 594, 13, 0, 12},
+	{16800000, 594000000, 495, 14, 0, 12},
+	{19200000, 594000000, 495, 16, 0, 12},
+	{26000000, 594000000, 594, 26, 0, 12},
+
+	{12000000, 1000000000, 1000, 12, 0, 12},
+	{13000000, 1000000000, 1000, 13, 0, 12},
+	{19200000, 1000000000, 625, 12, 0, 12},
+	{26000000, 1000000000, 1000, 26, 0, 12},
+
+	{0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_d_params = {
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 500000000,
+	.vco_max = 1000000000,
+	.base_reg = PLLD_BASE,
+	.misc_reg = PLLD_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_params pll_d2_params = {
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 500000000,
+	.vco_max = 1000000000,
+	.base_reg = PLLD2_BASE,
+	.misc_reg = PLLD2_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
+	{12000000, 480000000, 960, 12, 0, 12},
+	{13000000, 480000000, 960, 13, 0, 12},
+	{16800000, 480000000, 400, 7, 0, 5},
+	{19200000, 480000000, 200, 4, 0, 3},
+	{26000000, 480000000, 960, 26, 0, 12},
+	{0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_u_params = {
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 480000000,
+	.vco_max = 960000000,
+	.base_reg = PLLU_BASE,
+	.misc_reg = PLLU_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
+	/* 1 GHz */
+	{12000000, 1000000000, 83, 0, 1},	/* actual: 996.0 MHz */
+	{13000000, 1000000000, 76, 0, 1},	/* actual: 988.0 MHz */
+	{16800000, 1000000000, 59, 0, 1},	/* actual: 991.2 MHz */
+	{19200000, 1000000000, 52, 0, 1},	/* actual: 998.4 MHz */
+	{26000000, 1000000000, 76, 1, 1},	/* actual: 988.0 MHz */
+
+	{0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_x_params = {
+	.input_min = 12000000,
+	.input_max = 800000000,
+	.cf_min = 12000000,
+	.cf_max = 19200000,	/* s/w policy, h/w capability 50 MHz */
+	.vco_min = 700000000,
+	.vco_max = 2400000000U,
+	.base_reg = PLLX_BASE,
+	.misc_reg = PLLX_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.iddq_reg = PLLX_MISC3,
+	.iddq_bit_idx = PLLX_IDDQ_BIT,
+	.max_p = PLLXC_SW_MAX_P,
+	.dyn_ramp_reg = PLLC_MISC2,
+	.stepa_shift = 16,
+	.stepb_shift = 24,
+	.pdiv_tohw = pllxc_p,
+};
+
+static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
+	/* PLLE special case: use cpcon field to store cml divider value */
+	{336000000, 100000000, 100, 21, 16, 11},
+	{312000000, 100000000, 200, 26, 24, 13},
+	{0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_e_params = {
+	.input_min = 12000000,
+	.input_max = 1000000000,
+	.cf_min = 12000000,
+	.cf_max = 75000000,
+	.vco_min = 1600000000,
+	.vco_max = 2400000000U,
+	.base_reg = PLLE_BASE,
+	.misc_reg = PLLE_MISC,
+	.aux_reg = PLLE_AUX,
+	.lock_bit_idx = PLLE_MISC_LOCK,
+	.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_re_vco_params = {
+	.input_min = 12000000,
+	.input_max = 1000000000,
+	.cf_min = 12000000,
+	.cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */
+	.vco_min = 300000000,
+	.vco_max = 600000000,
+	.base_reg = PLLRE_BASE,
+	.misc_reg = PLLRE_MISC,
+	.lock_bit_idx = PLLRE_MISC_LOCK,
+	.lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+	.iddq_reg = PLLRE_MISC,
+	.iddq_bit_idx = PLLRE_IDDQ_BIT,
+};
+
+/* Peripheral clock registers */
+
+static struct tegra_clk_periph_regs periph_l_regs = {
+	.enb_reg = CLK_OUT_ENB_L,
+	.enb_set_reg = CLK_OUT_ENB_SET_L,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_L,
+	.rst_reg = RST_DEVICES_L,
+	.rst_set_reg = RST_DEVICES_SET_L,
+	.rst_clr_reg = RST_DEVICES_CLR_L,
+};
+
+static struct tegra_clk_periph_regs periph_h_regs = {
+	.enb_reg = CLK_OUT_ENB_H,
+	.enb_set_reg = CLK_OUT_ENB_SET_H,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_H,
+	.rst_reg = RST_DEVICES_H,
+	.rst_set_reg = RST_DEVICES_SET_H,
+	.rst_clr_reg = RST_DEVICES_CLR_H,
+};
+
+static struct tegra_clk_periph_regs periph_u_regs = {
+	.enb_reg = CLK_OUT_ENB_U,
+	.enb_set_reg = CLK_OUT_ENB_SET_U,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_U,
+	.rst_reg = RST_DEVICES_U,
+	.rst_set_reg = RST_DEVICES_SET_U,
+	.rst_clr_reg = RST_DEVICES_CLR_U,
+};
+
+static struct tegra_clk_periph_regs periph_v_regs = {
+	.enb_reg = CLK_OUT_ENB_V,
+	.enb_set_reg = CLK_OUT_ENB_SET_V,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_V,
+	.rst_reg = RST_DEVICES_V,
+	.rst_set_reg = RST_DEVICES_SET_V,
+	.rst_clr_reg = RST_DEVICES_CLR_V,
+};
+
+static struct tegra_clk_periph_regs periph_w_regs = {
+	.enb_reg = CLK_OUT_ENB_W,
+	.enb_set_reg = CLK_OUT_ENB_SET_W,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_W,
+	.rst_reg = RST_DEVICES_W,
+	.rst_set_reg = RST_DEVICES_SET_W,
+	.rst_clr_reg = RST_DEVICES_CLR_W,
+};
+
+/* possible OSC frequencies in Hz */
+static unsigned long tegra114_input_freq[] = {
+	[0] = 13000000,
+	[1] = 16800000,
+	[4] = 19200000,
+	[5] = 38400000,
+	[8] = 12000000,
+	[9] = 48000000,
+	[12] = 260000000,
+};
+
+#define MASK(x) (BIT(x) - 1)
+
+#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset,	\
+			    _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+			30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num,	\
+			periph_clk_enb_refcnt, _gate_flags, _clk_id,	\
+			_parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \
+			     _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+			29, MASK(3), 0, 0, 8, 1, 0, _regs, _clk_num,	\
+			periph_clk_enb_refcnt, _gate_flags, _clk_id,	\
+			_parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset,	\
+			    _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+			30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\
+			    _clk_num, _regs, _gate_flags, _clk_id, flags)\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+			30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id, _parents##_idx, flags)
+
+#define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\
+			    _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+			29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\
+			     _clk_num, _regs, _clk_id)			\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+			30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs,\
+			_clk_num, periph_clk_enb_refcnt, 0, _clk_id,	\
+			_parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\
+			     _clk_num, _regs, _clk_id)			\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+			30, MASK(2), 0, 0, 16, 0, 0, _regs, _clk_num,	\
+			periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \
+			      _mux_shift, _mux_mask, _clk_num, _regs,	\
+			      _gate_flags, _clk_id)			\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+			_mux_shift, _mux_mask, 0, 0, 0, 0, 0, _regs,	\
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \
+			     _clk_num, _regs, _gate_flags, _clk_id)	 \
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \
+			29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	 \
+			_clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset,  _clk_num,\
+				 _regs, _gate_flags, _clk_id)		\
+	TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk,	\
+			_offset, 16, 0xE01F, 0, 0, 8, 1, 0, _regs, _clk_num, \
+			periph_clk_enb_refcnt, _gate_flags , _clk_id,	\
+			mux_d_audio_clk_idx, 0)
+
+enum tegra114_clk {
+	rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12,
+	ndflash = 13, sdmmc1 = 14, sdmmc4 = 15, pwm = 17, i2s2 = 18, epp = 19,
+	gr_2d = 21, usbd = 22, isp = 23, gr_3d = 24, disp2 = 26, disp1 = 27,
+	host1x = 28, vcp = 29, i2s0 = 30, apbdma = 34, kbc = 36, kfuse = 40,
+	sbc1 = 41, nor = 42, sbc2 = 44, sbc3 = 46, i2c5 = 47, dsia = 48,
+	mipi = 50, hdmi = 51, csi = 52, i2c2 = 54, uartc = 55, mipi_cal = 56,
+	usb2 = 58, usb3 = 59, vde = 61, bsea = 62, bsev = 63, uartd = 65,
+	uarte = 66, i2c3 = 67, sbc4 = 68, sdmmc3 = 69, owr = 71, csite = 73,
+	la = 76, trace = 77, soc_therm = 78, dtv = 79, ndspeed = 80,
+	i2cslow = 81, dsib = 82, tsec = 83, xusb_host = 89, msenc = 91,
+	csus = 92, mselect = 99, tsensor = 100, i2s3 = 101, i2s4 = 102,
+	i2c4 = 103, sbc5 = 104, sbc6 = 105, apbif = 107, d_audio, dam0, dam1,
+	dam2, hda2codec_2x = 111, audio0_2x = 113, audio1_2x, audio2_2x,
+	audio3_2x, audio4_2x, spdif_2x, actmon = 119, extern1 = 120,
+	extern2 = 121, extern3 = 122, hda = 125, se = 127, hda2hdmi = 128,
+	cilab = 144, cilcd = 145, cile = 146, dsialp = 147, dsiblp = 148,
+	dds = 150, dp2 = 152, amx = 153, adx = 154, xusb_ss = 156, uartb = 192,
+	vfir, spdif_in, spdif_out, vi, vi_sensor, fuse, fuse_burn, clk_32k,
+	clk_m, clk_m_div2, clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_c2,
+	pll_c3, pll_m, pll_m_out1, pll_p, pll_p_out1, pll_p_out2, pll_p_out3,
+	pll_p_out4, pll_a, pll_a_out0, pll_d, pll_d_out0, pll_d2, pll_d2_out0,
+	pll_u, pll_u_480M, pll_u_60M, pll_u_48M, pll_u_12M, pll_x, pll_x_out0,
+	pll_re_vco, pll_re_out, pll_e_out0, spdif_in_sync, i2s0_sync,
+	i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync, vimclk_sync, audio0,
+	audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3,
+	blink, mipi_cal_fast, dsi1_fixed, dsi2_fixed, xusb_host_src,
+	xusb_falcon_src, xusb_fs_src, xusb_ss_src, xusb_dev_src, xusb_dev,
+	xusb_hs_src,
+
+	/* Mux clocks */
+
+	audio0_mux = 300, audio1_mux, audio2_mux, audio3_mux, audio4_mux,
+	spdif_mux, clk_out_1_mux, clk_out_2_mux, clk_out_3_mux, dsia_mux,
+	dsib_mux, clk_max,
+};
+
+struct utmi_clk_param {
+	/* Oscillator Frequency in KHz */
+	u32 osc_frequency;
+	/* UTMIP PLL Enable Delay Count  */
+	u8 enable_delay_count;
+	/* UTMIP PLL Stable count */
+	u8 stable_count;
+	/*  UTMIP PLL Active delay count */
+	u8 active_delay_count;
+	/* UTMIP PLL Xtal frequency count */
+	u8 xtal_freq_count;
+};
+
+static const struct utmi_clk_param utmi_parameters[] = {
+	{.osc_frequency = 13000000, .enable_delay_count = 0x02,
+	 .stable_count = 0x33, .active_delay_count = 0x05,
+	 .xtal_freq_count = 0x7F},
+	{.osc_frequency = 19200000, .enable_delay_count = 0x03,
+	 .stable_count = 0x4B, .active_delay_count = 0x06,
+	 .xtal_freq_count = 0xBB},
+	{.osc_frequency = 12000000, .enable_delay_count = 0x02,
+	 .stable_count = 0x2F, .active_delay_count = 0x04,
+	 .xtal_freq_count = 0x76},
+	{.osc_frequency = 26000000, .enable_delay_count = 0x04,
+	 .stable_count = 0x66, .active_delay_count = 0x09,
+	 .xtal_freq_count = 0xFE},
+	{.osc_frequency = 16800000, .enable_delay_count = 0x03,
+	 .stable_count = 0x41, .active_delay_count = 0x0A,
+	 .xtal_freq_count = 0xA4},
+};
+
+/* peripheral mux definitions */
+
+#define MUX_I2S_SPDIF(_id)						\
+static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
+							   #_id, "pll_p",\
+							   "clk_m"};
+MUX_I2S_SPDIF(audio0)
+MUX_I2S_SPDIF(audio1)
+MUX_I2S_SPDIF(audio2)
+MUX_I2S_SPDIF(audio3)
+MUX_I2S_SPDIF(audio4)
+MUX_I2S_SPDIF(audio)
+
+#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL
+
+static const char *mux_pllp_pllc_pllm_clkm[] = {
+	"pll_p", "pll_c", "pll_m", "clk_m"
+};
+#define mux_pllp_pllc_pllm_clkm_idx NULL
+
+static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" };
+#define mux_pllp_pllc_pllm_idx NULL
+
+static const char *mux_pllp_pllc_clk32_clkm[] = {
+	"pll_p", "pll_c", "clk_32k", "clk_m"
+};
+#define mux_pllp_pllc_clk32_clkm_idx NULL
+
+static const char *mux_plla_pllc_pllp_clkm[] = {
+	"pll_a_out0", "pll_c", "pll_p", "clk_m"
+};
+#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx
+
+static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = {
+	"pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m"
+};
+static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = {
+	[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
+};
+
+static const char *mux_pllp_clkm[] = {
+	"pll_p", "clk_m"
+};
+static u32 mux_pllp_clkm_idx[] = {
+	[0] = 0, [1] = 3,
+};
+
+static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
+	"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
+};
+#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx
+
+static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
+	"pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c",
+	"pll_d2_out0", "clk_m"
+};
+#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL
+
+static const char *mux_pllm_pllc_pllp_plla[] = {
+	"pll_m", "pll_c", "pll_p", "pll_a_out0"
+};
+#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
+
+static const char *mux_pllp_pllc_clkm[] = {
+	"pll_p", "pll_c", "pll_m"
+};
+static u32 mux_pllp_pllc_clkm_idx[] = {
+	[0] = 0, [1] = 1, [2] = 3,
+};
+
+static const char *mux_pllp_pllc_clkm_clk32[] = {
+	"pll_p", "pll_c", "clk_m", "clk_32k"
+};
+#define mux_pllp_pllc_clkm_clk32_idx NULL
+
+static const char *mux_plla_clk32_pllp_clkm_plle[] = {
+	"pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0"
+};
+#define mux_plla_clk32_pllp_clkm_plle_idx NULL
+
+static const char *mux_clkm_pllp_pllc_pllre[] = {
+	"clk_m", "pll_p", "pll_c", "pll_re_out"
+};
+static u32 mux_clkm_pllp_pllc_pllre_idx[] = {
+	[0] = 0, [1] = 1, [2] = 3, [3] = 5,
+};
+
+static const char *mux_clkm_48M_pllp_480M[] = {
+	"clk_m", "pll_u_48M", "pll_p", "pll_u_480M"
+};
+#define mux_clkm_48M_pllp_480M_idx NULL
+
+static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
+	"clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
+};
+static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
+	[0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
+};
+
+static const char *mux_plld_out0_plld2_out0[] = {
+	"pll_d_out0", "pll_d2_out0",
+};
+#define mux_plld_out0_plld2_out0_idx NULL
+
+static const char *mux_d_audio_clk[] = {
+	"pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
+	"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+};
+static u32 mux_d_audio_clk_idx[] = {
+	[0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001,
+	[5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007,
+};
+
+static const struct clk_div_table pll_re_div_table[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 3 },
+	{ .val = 3, .div = 4 },
+	{ .val = 4, .div = 5 },
+	{ .val = 5, .div = 6 },
+	{ .val = 0, .div = 0 },
+};
+
+static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
+
+static unsigned long osc_freq;
+static unsigned long pll_ref_freq;
+
+static int __init tegra114_osc_clk_init(void __iomem *clk_base)
+{
+	struct clk *clk;
+	u32 val, pll_ref_div;
+
+	val = readl_relaxed(clk_base + OSC_CTRL);
+
+	osc_freq = tegra114_input_freq[val >> OSC_CTRL_OSC_FREQ_SHIFT];
+	if (!osc_freq) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	/* clk_m */
+	clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
+				      osc_freq);
+	clk_register_clkdev(clk, "clk_m", NULL);
+	clks[clk_m] = clk;
+
+	/* pll_ref */
+	val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
+	pll_ref_div = 1 << val;
+	clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
+					CLK_SET_RATE_PARENT, 1, pll_ref_div);
+	clk_register_clkdev(clk, "pll_ref", NULL);
+	clks[pll_ref] = clk;
+
+	pll_ref_freq = osc_freq / pll_ref_div;
+
+	return 0;
+}
+
+static void __init tegra114_fixed_clk_init(void __iomem *clk_base)
+{
+	struct clk *clk;
+
+	/* clk_32k */
+	clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT,
+				      32768);
+	clk_register_clkdev(clk, "clk_32k", NULL);
+	clks[clk_32k] = clk;
+
+	/* clk_m_div2 */
+	clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "clk_m_div2", NULL);
+	clks[clk_m_div2] = clk;
+
+	/* clk_m_div4 */
+	clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
+					CLK_SET_RATE_PARENT, 1, 4);
+	clk_register_clkdev(clk, "clk_m_div4", NULL);
+	clks[clk_m_div4] = clk;
+
+}
+
+static __init void tegra114_utmi_param_configure(void __iomem *clk_base)
+{
+	u32 reg;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+		if (osc_freq == utmi_parameters[i].osc_frequency)
+			break;
+	}
+
+	if (i >= ARRAY_SIZE(utmi_parameters)) {
+		pr_err("%s: Unexpected oscillator freq %lu\n", __func__,
+		       osc_freq);
+		return;
+	}
+
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+
+	/* Program UTMIP PLL stable and active counts */
+	/* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
+	reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+	reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count);
+
+	reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+
+	reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].
+					    active_delay_count);
+
+	/* Remove power downs from UTMIP PLL control bits */
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+	/* Program UTMIP PLL delay and oscillator frequency counts */
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+	reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+
+	reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].
+					    enable_delay_count);
+
+	reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+	reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i].
+					   xtal_freq_count);
+
+	/* Remove power downs from UTMIP PLL control bits */
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+	/* Setup HW control of UTMIPLL */
+	reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+	reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+	reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+	reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
+	writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+	udelay(1);
+
+	/* Setup SW override of UTMIPLL assuming USB2.0
+	   ports are assigned to USB2 */
+	reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+	reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
+	reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+	writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+	udelay(1);
+
+	/* Enable HW control UTMIPLL */
+	reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+	reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+	writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+}
+
+static void __init _clip_vco_min(struct tegra_clk_pll_params *pll_params)
+{
+	pll_params->vco_min =
+		DIV_ROUND_UP(pll_params->vco_min, pll_ref_freq) * pll_ref_freq;
+}
+
+static int __init _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
+				      void __iomem *clk_base)
+{
+	u32 val;
+	u32 step_a, step_b;
+
+	switch (pll_ref_freq) {
+	case 12000000:
+	case 13000000:
+	case 26000000:
+		step_a = 0x2B;
+		step_b = 0x0B;
+		break;
+	case 16800000:
+		step_a = 0x1A;
+		step_b = 0x09;
+		break;
+	case 19200000:
+		step_a = 0x12;
+		step_b = 0x08;
+		break;
+	default:
+		pr_err("%s: Unexpected reference rate %lu\n",
+			__func__, pll_ref_freq);
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
+	val = step_a << pll_params->stepa_shift;
+	val |= step_b << pll_params->stepb_shift;
+	writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
+
+	return 0;
+}
+
+static void __init _init_iddq(struct tegra_clk_pll_params *pll_params,
+			      void __iomem *clk_base)
+{
+	u32 val, val_iddq;
+
+	val = readl_relaxed(clk_base + pll_params->base_reg);
+	val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
+
+	if (val & BIT(30))
+		WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
+	else {
+		val_iddq |= BIT(pll_params->iddq_bit_idx);
+		writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
+	}
+}
+
+static void __init tegra114_pll_init(void __iomem *clk_base,
+				     void __iomem *pmc)
+{
+	struct clk *clk;
+
+	/* PLLC */
+	_clip_vco_min(&pll_c_params);
+	if (_setup_dynamic_ramp(&pll_c_params, clk_base) >= 0) {
+		_init_iddq(&pll_c_params, clk_base);
+		clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
+				pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK,
+				pll_c_freq_table, NULL);
+		clk_register_clkdev(clk, "pll_c", NULL);
+		clks[pll_c] = clk;
+
+		/* PLLC_OUT1 */
+		clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+				clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+		clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+					clk_base + PLLC_OUT, 1, 0,
+					CLK_SET_RATE_PARENT, 0, NULL);
+		clk_register_clkdev(clk, "pll_c_out1", NULL);
+		clks[pll_c_out1] = clk;
+	}
+
+	/* PLLC2 */
+	_clip_vco_min(&pll_c2_params);
+	clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0,
+			     &pll_c2_params, TEGRA_PLL_USE_LOCK,
+			     pll_cx_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_c2", NULL);
+	clks[pll_c2] = clk;
+
+	/* PLLC3 */
+	_clip_vco_min(&pll_c3_params);
+	clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0,
+			     &pll_c3_params, TEGRA_PLL_USE_LOCK,
+			     pll_cx_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_c3", NULL);
+	clks[pll_c3] = clk;
+
+	/* PLLP */
+	clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0,
+			    408000000, &pll_p_params,
+			    TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
+			    pll_p_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_p", NULL);
+	clks[pll_p] = clk;
+
+	/* PLLP_OUT1 */
+	clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p",
+				clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
+				TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div",
+				clk_base + PLLP_OUTA, 1, 0,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out1", NULL);
+	clks[pll_p_out1] = clk;
+
+	/* PLLP_OUT2 */
+	clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
+				clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
+				TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
+				&pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
+				clk_base + PLLP_OUTA, 17, 16,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out2", NULL);
+	clks[pll_p_out2] = clk;
+
+	/* PLLP_OUT3 */
+	clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p",
+				clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
+				TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div",
+				clk_base + PLLP_OUTB, 1, 0,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out3", NULL);
+	clks[pll_p_out3] = clk;
+
+	/* PLLP_OUT4 */
+	clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p",
+				clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
+				TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
+				&pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div",
+				clk_base + PLLP_OUTB, 17, 16,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out4", NULL);
+	clks[pll_p_out4] = clk;
+
+	/* PLLM */
+	_clip_vco_min(&pll_m_params);
+	clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
+			     CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
+			     &pll_m_params, TEGRA_PLL_USE_LOCK,
+			     pll_m_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_m", NULL);
+	clks[pll_m] = clk;
+
+	/* PLLM_OUT1 */
+	clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
+				clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
+				clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+				CLK_SET_RATE_PARENT, 0, NULL);
+	clk_register_clkdev(clk, "pll_m_out1", NULL);
+	clks[pll_m_out1] = clk;
+
+	/* PLLX */
+	_clip_vco_min(&pll_x_params);
+	if (_setup_dynamic_ramp(&pll_x_params, clk_base) >= 0) {
+		_init_iddq(&pll_c_params, clk_base);
+		clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
+				pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params,
+				TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL);
+		clk_register_clkdev(clk, "pll_x", NULL);
+		clks[pll_x] = clk;
+	}
+
+	/* PLLX_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_x_out0", NULL);
+	clks[pll_x_out0] = clk;
+
+	/* PLLU */
+	clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0,
+			    0, &pll_u_params, TEGRA_PLLU |
+			    TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+			    TEGRA_PLL_USE_LOCK, pll_u_freq_table, &pll_u_lock);
+	clk_register_clkdev(clk, "pll_u", NULL);
+	clks[pll_u] = clk;
+
+	tegra114_utmi_param_configure(clk_base);
+
+	/* PLLU_480M */
+	clk = clk_register_gate(NULL, "pll_u_480M", "pll_u",
+				CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+				22, 0, &pll_u_lock);
+	clk_register_clkdev(clk, "pll_u_480M", NULL);
+	clks[pll_u_480M] = clk;
+
+	/* PLLU_60M */
+	clk = clk_register_fixed_factor(NULL, "pll_u_60M_div", "pll_u",
+					CLK_SET_RATE_PARENT, 1, 8);
+	clk = clk_register_gate(NULL, "pll_u_60M", "pll_u_60M_div",
+				CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+				23, 0, &pll_u_lock);
+	clk_register_clkdev(clk, "pll_u_60M", NULL);
+	clks[pll_u_60M] = clk;
+
+	/* PLLU_48M */
+	clk = clk_register_fixed_factor(NULL, "pll_u_48M_div", "pll_u",
+					CLK_SET_RATE_PARENT, 1, 10);
+	clk = clk_register_gate(NULL, "pll_u_48M", "pll_u_48M_div",
+				CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+				25, 0, &pll_u_lock);
+	clk_register_clkdev(clk, "pll_u_48M", NULL);
+	clks[pll_u_48M] = clk;
+
+	/* PLLU_12M */
+	clk = clk_register_fixed_factor(NULL, "pll_u_12M_div", "pll_u",
+					CLK_SET_RATE_PARENT, 1, 40);
+	clk = clk_register_gate(NULL, "pll_u_12M", "pll_u_12M_div",
+				CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+				21, 0, &pll_u_lock);
+	clk_register_clkdev(clk, "pll_u_12M", NULL);
+	clks[pll_u_12M] = clk;
+
+	/* PLLD */
+	clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0,
+			    0, &pll_d_params,
+			    TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+			    TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d_lock);
+	clk_register_clkdev(clk, "pll_d", NULL);
+	clks[pll_d] = clk;
+
+	/* PLLD_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_d_out0", NULL);
+	clks[pll_d_out0] = clk;
+
+	/* PLLD2 */
+	clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc, 0,
+			    0, &pll_d2_params,
+			    TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+			    TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d2_lock);
+	clk_register_clkdev(clk, "pll_d2", NULL);
+	clks[pll_d2] = clk;
+
+	/* PLLD2_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_d2_out0", NULL);
+	clks[pll_d2_out0] = clk;
+
+	/* PLLA */
+	clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0,
+			    0, &pll_a_params, TEGRA_PLL_HAS_CPCON |
+			    TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_a", NULL);
+	clks[pll_a] = clk;
+
+	/* PLLA_OUT0 */
+	clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
+				clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
+				clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
+				CLK_SET_RATE_PARENT, 0, NULL);
+	clk_register_clkdev(clk, "pll_a_out0", NULL);
+	clks[pll_a_out0] = clk;
+
+	/* PLLRE */
+	_clip_vco_min(&pll_re_vco_params);
+	clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
+			     0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK,
+			     NULL, &pll_re_lock, pll_ref_freq);
+	clk_register_clkdev(clk, "pll_re_vco", NULL);
+	clks[pll_re_vco] = clk;
+
+	clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0,
+					 clk_base + PLLRE_BASE, 16, 4, 0,
+					 pll_re_div_table, &pll_re_lock);
+	clk_register_clkdev(clk, "pll_re_out", NULL);
+	clks[pll_re_out] = clk;
+
+	/* PLLE */
+	clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_re_vco",
+				      clk_base, 0, 100000000, &pll_e_params,
+				      pll_e_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_e_out0", NULL);
+	clks[pll_e_out0] = clk;
+}
+
+static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
+	"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+};
+
+static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
+	"clk_m_div4", "extern1",
+};
+
+static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
+	"clk_m_div4", "extern2",
+};
+
+static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
+	"clk_m_div4", "extern3",
+};
+
+static void __init tegra114_audio_clk_init(void __iomem *clk_base)
+{
+	struct clk *clk;
+
+	/* spdif_in_sync */
+	clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000,
+					     24000000);
+	clk_register_clkdev(clk, "spdif_in_sync", NULL);
+	clks[spdif_in_sync] = clk;
+
+	/* i2s0_sync */
+	clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s0_sync", NULL);
+	clks[i2s0_sync] = clk;
+
+	/* i2s1_sync */
+	clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s1_sync", NULL);
+	clks[i2s1_sync] = clk;
+
+	/* i2s2_sync */
+	clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s2_sync", NULL);
+	clks[i2s2_sync] = clk;
+
+	/* i2s3_sync */
+	clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s3_sync", NULL);
+	clks[i2s3_sync] = clk;
+
+	/* i2s4_sync */
+	clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s4_sync", NULL);
+	clks[i2s4_sync] = clk;
+
+	/* vimclk_sync */
+	clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "vimclk_sync", NULL);
+	clks[vimclk_sync] = clk;
+
+	/* audio0 */
+	clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
+			       ARRAY_SIZE(mux_audio_sync_clk), 0,
+			       clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0,
+			       NULL);
+	clks[audio0_mux] = clk;
+	clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S0, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio0", NULL);
+	clks[audio0] = clk;
+
+	/* audio1 */
+	clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
+			       ARRAY_SIZE(mux_audio_sync_clk), 0,
+			       clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0,
+			       NULL);
+	clks[audio1_mux] = clk;
+	clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S1, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio1", NULL);
+	clks[audio1] = clk;
+
+	/* audio2 */
+	clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
+			       ARRAY_SIZE(mux_audio_sync_clk), 0,
+			       clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0,
+			       NULL);
+	clks[audio2_mux] = clk;
+	clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S2, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio2", NULL);
+	clks[audio2] = clk;
+
+	/* audio3 */
+	clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
+			       ARRAY_SIZE(mux_audio_sync_clk), 0,
+			       clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0,
+			       NULL);
+	clks[audio3_mux] = clk;
+	clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S3, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio3", NULL);
+	clks[audio3] = clk;
+
+	/* audio4 */
+	clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
+			       ARRAY_SIZE(mux_audio_sync_clk), 0,
+			       clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0,
+			       NULL);
+	clks[audio4_mux] = clk;
+	clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S4, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio4", NULL);
+	clks[audio4] = clk;
+
+	/* spdif */
+	clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
+			       ARRAY_SIZE(mux_audio_sync_clk), 0,
+			       clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0,
+			       NULL);
+	clks[spdif_mux] = clk;
+	clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_SPDIF, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "spdif", NULL);
+	clks[spdif] = clk;
+
+	/* audio0_2x */
+	clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio0_div", "audio0_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1,
+				0, &clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div",
+				  TEGRA_PERIPH_NO_RESET, clk_base,
+				  CLK_SET_RATE_PARENT, 113, &periph_v_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio0_2x", NULL);
+	clks[audio0_2x] = clk;
+
+	/* audio1_2x */
+	clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio1_div", "audio1_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1,
+				0, &clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div",
+				  TEGRA_PERIPH_NO_RESET, clk_base,
+				  CLK_SET_RATE_PARENT, 114, &periph_v_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio1_2x", NULL);
+	clks[audio1_2x] = clk;
+
+	/* audio2_2x */
+	clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio2_div", "audio2_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1,
+				0, &clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div",
+				  TEGRA_PERIPH_NO_RESET, clk_base,
+				  CLK_SET_RATE_PARENT, 115, &periph_v_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio2_2x", NULL);
+	clks[audio2_2x] = clk;
+
+	/* audio3_2x */
+	clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio3_div", "audio3_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1,
+				0, &clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div",
+				  TEGRA_PERIPH_NO_RESET, clk_base,
+				  CLK_SET_RATE_PARENT, 116, &periph_v_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio3_2x", NULL);
+	clks[audio3_2x] = clk;
+
+	/* audio4_2x */
+	clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio4_div", "audio4_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1,
+				0, &clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div",
+				  TEGRA_PERIPH_NO_RESET, clk_base,
+				  CLK_SET_RATE_PARENT, 117, &periph_v_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio4_2x", NULL);
+	clks[audio4_2x] = clk;
+
+	/* spdif_2x */
+	clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("spdif_div", "spdif_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1,
+				0, &clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div",
+				  TEGRA_PERIPH_NO_RESET, clk_base,
+				  CLK_SET_RATE_PARENT, 118,
+				  &periph_v_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "spdif_2x", NULL);
+	clks[spdif_2x] = clk;
+}
+
+static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
+{
+	struct clk *clk;
+
+	/* clk_out_1 */
+	clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
+			       ARRAY_SIZE(clk_out1_parents), 0,
+			       pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
+			       &clk_out_lock);
+	clks[clk_out_1_mux] = clk;
+	clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0,
+				pmc_base + PMC_CLK_OUT_CNTRL, 2, 0,
+				&clk_out_lock);
+	clk_register_clkdev(clk, "extern1", "clk_out_1");
+	clks[clk_out_1] = clk;
+
+	/* clk_out_2 */
+	clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
+			       ARRAY_SIZE(clk_out1_parents), 0,
+			       pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
+			       &clk_out_lock);
+	clks[clk_out_2_mux] = clk;
+	clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
+				pmc_base + PMC_CLK_OUT_CNTRL, 10, 0,
+				&clk_out_lock);
+	clk_register_clkdev(clk, "extern2", "clk_out_2");
+	clks[clk_out_2] = clk;
+
+	/* clk_out_3 */
+	clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
+			       ARRAY_SIZE(clk_out1_parents), 0,
+			       pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
+			       &clk_out_lock);
+	clks[clk_out_3_mux] = clk;
+	clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
+				pmc_base + PMC_CLK_OUT_CNTRL, 18, 0,
+				&clk_out_lock);
+	clk_register_clkdev(clk, "extern3", "clk_out_3");
+	clks[clk_out_3] = clk;
+
+	/* blink */
+	clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
+				pmc_base + PMC_DPD_PADS_ORIDE,
+				PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
+	clk = clk_register_gate(NULL, "blink", "blink_override", 0,
+				pmc_base + PMC_CTRL,
+				PMC_CTRL_BLINK_ENB, 0, NULL);
+	clk_register_clkdev(clk, "blink", NULL);
+	clks[blink] = clk;
+
+}
+
+static __initdata struct tegra_periph_init_data tegra_periph_clk_list[] = {
+	TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0),
+	TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1),
+	TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2),
+	TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3),
+	TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4),
+	TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out),
+	TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in),
+	TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, &periph_l_regs, TEGRA_PERIPH_ON_APB, pwm),
+	TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, &periph_w_regs, TEGRA_PERIPH_ON_APB, adx),
+	TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, amx),
+	TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda),
+	TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda2codec_2x),
+	TEGRA_INIT_DATA_MUX("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1),
+	TEGRA_INIT_DATA_MUX("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2),
+	TEGRA_INIT_DATA_MUX("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3),
+	TEGRA_INIT_DATA_MUX("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4),
+	TEGRA_INIT_DATA_MUX("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5),
+	TEGRA_INIT_DATA_MUX("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6),
+	TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
+	TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
+	TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir),
+	TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1),
+	TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2),
+	TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3),
+	TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4),
+	TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde),
+	TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, csite),
+	TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, la),
+	TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, trace),
+	TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr),
+	TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor),
+	TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi),
+	TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, i2c1),
+	TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, i2c2),
+	TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, i2c3),
+	TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, i2c4),
+	TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, i2c5),
+	TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, uarta),
+	TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, uartb),
+	TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, uartc),
+	TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, uartd),
+	TEGRA_INIT_DATA_UART("uarte", NULL, "tegra_uart.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, &periph_u_regs, uarte),
+	TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, gr_3d),
+	TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr_2d),
+	TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
+	TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi),
+	TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp),
+	TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_h_regs, TEGRA_PERIPH_WAR_1005168, msenc),
+	TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec),
+	TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x),
+	TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi),
+	TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, &periph_w_regs, 0, cilab),
+	TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, &periph_w_regs, 0, cilcd),
+	TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, &periph_w_regs, 0, cile),
+	TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, &periph_w_regs, 0, dsialp),
+	TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, &periph_w_regs, 0, dsiblp),
+	TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor),
+	TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, actmon),
+	TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, extern1),
+	TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, extern2),
+	TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, extern3),
+	TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
+	TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se),
+	TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED),
+	TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm),
+	TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src),
+	TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src),
+	TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_fs_src),
+	TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_ss_src),
+	TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, &periph_u_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_dev_src),
+	TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, TEGRA_PERIPH_ON_APB, d_audio),
+	TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam0),
+	TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam1),
+	TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam2),
+};
+
+static __initdata struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
+	TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 3, 27, &periph_l_regs, 0, disp1),
+	TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 3, 26, &periph_l_regs, 0, disp2),
+};
+
+static __init void tegra114_periph_clk_init(void __iomem *clk_base)
+{
+	struct tegra_periph_init_data *data;
+	struct clk *clk;
+	int i;
+	u32 val;
+
+	/* apbdma */
+	clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base,
+				  0, 34, &periph_h_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "apbdma", "tegra-dma");
+	clks[apbdma] = clk;
+
+	/* rtc */
+	clk = tegra_clk_register_periph_gate("rtc", "clk_32k",
+				    TEGRA_PERIPH_ON_APB |
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    0, 4, &periph_l_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "rtc-tegra");
+	clks[rtc] = clk;
+
+	/* kbc */
+	clk = tegra_clk_register_periph_gate("kbc", "clk_32k",
+				    TEGRA_PERIPH_ON_APB |
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    0, 36, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-kbc");
+	clks[kbc] = clk;
+
+	/* timer */
+	clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base,
+				  0, 5, &periph_l_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "timer");
+	clks[timer] = clk;
+
+	/* kfuse */
+	clk = tegra_clk_register_periph_gate("kfuse", "clk_m",
+				  TEGRA_PERIPH_ON_APB, clk_base,  0, 40,
+				  &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "kfuse-tegra");
+	clks[kfuse] = clk;
+
+	/* fuse */
+	clk = tegra_clk_register_periph_gate("fuse", "clk_m",
+				  TEGRA_PERIPH_ON_APB, clk_base,  0, 39,
+				  &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "fuse", "fuse-tegra");
+	clks[fuse] = clk;
+
+	/* fuse_burn */
+	clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m",
+				  TEGRA_PERIPH_ON_APB, clk_base,  0, 39,
+				  &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "fuse_burn", "fuse-tegra");
+	clks[fuse_burn] = clk;
+
+	/* apbif */
+	clk = tegra_clk_register_periph_gate("apbif", "clk_m",
+				  TEGRA_PERIPH_ON_APB, clk_base,  0, 107,
+				  &periph_v_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "apbif", "tegra30-ahub");
+	clks[apbif] = clk;
+
+	/* hda2hdmi */
+	clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m",
+				    TEGRA_PERIPH_ON_APB, clk_base,  0, 128,
+				    &periph_w_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "hda2hdmi", "tegra30-hda");
+	clks[hda2hdmi] = clk;
+
+	/* vcp */
+	clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base,  0,
+				  29, &periph_l_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "vcp", "tegra-avp");
+	clks[vcp] = clk;
+
+	/* bsea */
+	clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base,
+				  0, 62, &periph_h_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "bsea", "tegra-avp");
+	clks[bsea] = clk;
+
+	/* bsev */
+	clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base,
+				  0, 63, &periph_h_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "bsev", "tegra-aes");
+	clks[bsev] = clk;
+
+	/* mipi-cal */
+	clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base,
+				   0, 56, &periph_h_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "mipi-cal", "mipi-cal");
+	clks[mipi_cal] = clk;
+
+	/* usbd */
+	clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base,
+				  0, 22, &periph_l_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "usbd", "tegra-udc.0");
+	clks[usbd] = clk;
+
+	/* usb2 */
+	clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base,
+				  0, 58, &periph_h_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "usb2", "tegra-ehci.1");
+	clks[usb2] = clk;
+
+	/* usb3 */
+	clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base,
+				  0, 59, &periph_h_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "usb3", "tegra-ehci.2");
+	clks[usb3] = clk;
+
+	/* dsi1-fixed */
+	clk = clk_register_fixed_factor(NULL, "dsi1-fixed", "pll_p_out3",
+					CLK_SET_RATE_PARENT, 1, 1);
+	clks[dsi1_fixed] = clk;
+
+	/* dsi2-fixed */
+	clk = clk_register_fixed_factor(NULL, "dsi2-fixed", "pll_p_out3",
+					CLK_SET_RATE_PARENT, 1, 1);
+	clks[dsi2_fixed] = clk;
+
+	/* mipi-cal-fast */
+	clk = clk_register_fixed_factor(NULL, "mipi-cal-fast", "pll_p_out3",
+					CLK_SET_RATE_PARENT, 1, 1);
+	clk_register_clkdev(clk, "fast-clk", "mipi-cal");
+	clks[mipi_cal_fast] = clk;
+
+	/* csi */
+	clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base,
+				   0, 52, &periph_h_regs,
+				  periph_clk_enb_refcnt);
+	clks[csi] = clk;
+
+	/* isp */
+	clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0,
+				  23, &periph_l_regs,
+				  periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "isp", "tegra_camera");
+	clks[isp] = clk;
+
+	/* csus */
+	clk = tegra_clk_register_periph_gate("csus", "clk_m",
+				  TEGRA_PERIPH_NO_RESET, clk_base, 0, 92,
+				  &periph_u_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "csus", "tegra_camera");
+	clks[csus] = clk;
+
+	/* dds */
+	clk = tegra_clk_register_periph_gate("dds", "clk_m",
+				  TEGRA_PERIPH_ON_APB, clk_base, 0, 150,
+				  &periph_w_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "dds", "dds");
+	clks[dds] = clk;
+
+	/* dp2 */
+	clk = tegra_clk_register_periph_gate("dp2", "clk_m",
+				  TEGRA_PERIPH_ON_APB, clk_base, 0, 152,
+				  &periph_w_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "dp2", "dp2");
+	clks[dp2] = clk;
+
+	/* dtv */
+	clk = tegra_clk_register_periph_gate("dtv", "clk_m",
+				    TEGRA_PERIPH_ON_APB, clk_base, 0, 79,
+				    &periph_u_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "dtv");
+	clks[dtv] = clk;
+
+	/* dsia */
+	clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
+			       ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+			       clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
+	clks[dsia_mux] = clk;
+	clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
+				    0, 48, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "dsia", "tegradc.0");
+	clks[dsia] = clk;
+
+	/* dsib */
+	clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
+			       ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+			       clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
+	clks[dsib_mux] = clk;
+	clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
+				    0, 82, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "dsib", "tegradc.1");
+	clks[dsib] = clk;
+
+	/* xusb_hs_src */
+	val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC);
+	val |= BIT(25); /* always select PLLU_60M */
+	writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC);
+
+	clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0,
+					1, 1);
+	clks[xusb_hs_src] = clk;
+
+	/* xusb_host */
+	clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0,
+				    clk_base, 0, 89, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "tegra_xhci", "host");
+	clks[xusb_host] = clk;
+
+	/* xusb_ss */
+	clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0,
+				    clk_base, 0, 156, &periph_w_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "tegra_xhci", "ss");
+	clks[xusb_host] = clk;
+
+	/* xusb_dev */
+	clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0,
+				    clk_base, 0, 95, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "tegra_xhci", "dev");
+
+	for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
+		data = &tegra_periph_clk_list[i];
+		clk = tegra_clk_register_periph(data->name, data->parent_names,
+				data->num_parents, &data->periph,
+				clk_base, data->offset, data->flags);
+		clk_register_clkdev(clk, data->con_id, data->dev_id);
+		clks[data->clk_id] = clk;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
+		data = &tegra_periph_nodiv_clk_list[i];
+		clk = tegra_clk_register_periph_nodiv(data->name,
+				data->parent_names, data->num_parents,
+				&data->periph, clk_base, data->offset);
+		clk_register_clkdev(clk, data->con_id, data->dev_id);
+		clks[data->clk_id] = clk;
+	}
+}
+
+static struct tegra_cpu_car_ops tegra114_cpu_car_ops;
+
+static const struct of_device_id pmc_match[] __initconst = {
+	{ .compatible = "nvidia,tegra114-pmc" },
+	{},
+};
+
+static __initdata struct tegra_clk_init_table init_table[] = {
+	{uartd, pll_p, 408000000, 1},
+	{clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
+};
+
+void __init tegra114_clock_init(struct device_node *np)
+{
+	struct device_node *node;
+	int i;
+
+	clk_base = of_iomap(np, 0);
+	if (!clk_base) {
+		pr_err("ioremap tegra114 CAR failed\n");
+		return;
+	}
+
+	node = of_find_matching_node(NULL, pmc_match);
+	if (!node) {
+		pr_err("Failed to find pmc node\n");
+		WARN_ON(1);
+		return;
+	}
+
+	pmc_base = of_iomap(node, 0);
+	if (!pmc_base) {
+		pr_err("Can't map pmc registers\n");
+		WARN_ON(1);
+		return;
+	}
+
+	if (tegra114_osc_clk_init(clk_base) < 0)
+		return;
+
+	tegra114_fixed_clk_init(clk_base);
+	tegra114_pll_init(clk_base, pmc_base);
+	tegra114_periph_clk_init(clk_base);
+	tegra114_audio_clk_init(clk_base);
+	tegra114_pmc_clk_init(pmc_base);
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++) {
+		if (IS_ERR(clks[i])) {
+			pr_err
+			    ("Tegra114 clk %d: register failed with %ld\n",
+			     i, PTR_ERR(clks[i]));
+		}
+		if (!clks[i])
+			clks[i] = ERR_PTR(-EINVAL);
+	}
+
+	clk_data.clks = clks;
+	clk_data.clk_num = ARRAY_SIZE(clks);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	tegra_init_from_table(init_table, clks, clk_max);
+
+	tegra_cpu_car_ops = &tegra114_cpu_car_ops;
+}

^ permalink raw reply related

* [PATCH v5 10/10] clk: tegra: devicetree match for nvidia, tegra114-car
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359713962-16822-1-git-send-email-pdeschrijver@nvidia.com>

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/clk.c |    1 +
 drivers/clk/tegra/clk.h |    7 +++++++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index a603b9a..a328365 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -76,6 +76,7 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
 static const struct of_device_id tegra_dt_clk_match[] = {
 	{ .compatible = "nvidia,tegra20-car", .data = tegra20_clock_init },
 	{ .compatible = "nvidia,tegra30-car", .data = tegra30_clock_init },
+	{ .compatible = "nvidia,tegra114-car", .data = tegra114_clock_init },
 	{ }
 };
 
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 8756d9f..8097850 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -576,4 +576,11 @@ void tegra30_clock_init(struct device_node *np);
 static inline void tegra30_clock_init(struct device_node *np) {}
 #endif /* CONFIG_ARCH_TEGRA_3x_SOC */
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+void tegra114_clock_init(struct device_node *np);
+#else
+static inline void tegra114_clock_init(struct device_node *np) {}
+#endif /* CONFIG_ARCH_TEGRA114_SOC */
+
+
 #endif /* TEGRA_CLK_H */

^ permalink raw reply related

* [Consult]: how to join to linux-arm-kernel@lists.infradead.org
From: Chen Gang F T @ 2013-02-01 10:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <510B1EBC.8000408@gmail.com>


  ok, joined, not need reply this mail.



? 2013?02?01? 09:47, Chen Gang F T ??:
> Hello All:
> 
>   May I join into linux-arm-kernel at lists.infradead.org mailing list ?
> 
>   for I can not find it in http://vger.kernel.org/vger-lists.html
>   maybe:
>     A) need some qualifications.
>     B) or there is another place for it.
>     C) or it is my fault (still in http://vger.kernel.org/vger-lists.html)
>     D) none of above.
> 
>   welcome any members to providing relative informations.
> 
>   thanks.
> 


-- 
Chen Gang

Flying Transformer

^ permalink raw reply

* [PATCH] ARM: OMAP2+: dpll: Add missing soc_is_am33xx() check
From: AnilKumar Ch @ 2013-02-01 10:27 UTC (permalink / raw)
  To: linux-arm-kernel

Add missing soc_is_am33xx() check in noncore DPLL set rate function.
Without this, dpll set_rate function throughs warnings for am33xx
family of devices.

Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
---
 arch/arm/mach-omap2/dpll3xxx.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index 0a02aab5..4bb3f78 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -501,7 +501,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
 			return -EINVAL;
 
 		/* No freqsel on OMAP4 and OMAP3630 */
-		if (!cpu_is_omap44xx() && !cpu_is_omap3630()) {
+		if (!cpu_is_omap44xx() && !cpu_is_omap3630() &&
+					!soc_is_am33xx()) {
 			freqsel = _omap3_dpll_compute_freqsel(clk,
 						dd->last_rounded_n);
 			WARN_ON(!freqsel);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] ARM: OMAP2: AM33XX: id: Add support for AM335x PG2.0
From: AnilKumar Ch @ 2013-02-01 10:28 UTC (permalink / raw)
  To: linux-arm-kernel

Add support for chip id recognition of AM335x PG2.0 silicon. By default
omap3xxx_check_revision() recognizes PG1.0, which is extended by adding
PG2.0 support

Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
---
 arch/arm/mach-omap2/id.c  |   14 ++++++++++++--
 arch/arm/mach-omap2/soc.h |    1 +
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 45cc7ed4..8a68f1e 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -399,8 +399,18 @@ void __init omap3xxx_check_revision(void)
 		}
 		break;
 	case 0xb944:
-		omap_revision = AM335X_REV_ES1_0;
-		cpu_rev = "1.0";
+		switch (rev) {
+		case 0:
+			omap_revision = AM335X_REV_ES1_0;
+			cpu_rev = "1.0";
+			break;
+		case 1:
+		/* FALLTHROUGH */
+		default:
+			omap_revision = AM335X_REV_ES2_0;
+			cpu_rev = "2.0";
+			break;
+		}
 		break;
 	case 0xb8f2:
 		switch (rev) {
diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h
index 092aedd..c62116b 100644
--- a/arch/arm/mach-omap2/soc.h
+++ b/arch/arm/mach-omap2/soc.h
@@ -395,6 +395,7 @@ IS_OMAP_TYPE(3430, 0x3430)
 
 #define AM335X_CLASS		0x33500033
 #define AM335X_REV_ES1_0	AM335X_CLASS
+#define AM335X_REV_ES2_0	(AM335X_CLASS | (0x1 << 8))
 
 #define OMAP443X_CLASS		0x44300044
 #define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 1/5] ARM: OMAP2+: Display correct system timer name
From: Jon Hunter @ 2013-02-01 10:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <B5906170F1614E41A8A28DE3B8D121433ED073A5@DBDE01.ent.ti.com>


On 02/01/2013 03:31 AM, Bedia, Vaibhav wrote:
> On Fri, Feb 01, 2013 at 14:23:43, Hunter, Jon wrote:
> [...]
>>>>  
>>>> +/* Timer name needs to be big enough to store a string of "timerXX" */
>>>> +static char timer_name[10];
>>>> +
>>>
>>> Why not move this inside omap_dm_timer_init_one()?
>>
>> In the non-DT case, the name member of the clocksource/event struct will
>> point to this array and so it needs to reside in memory permanently and
>> not just temporary. Once we migrate completely to DT then we will be
>> able to remove this completely. See following snippet ...
>>
>> -		sprintf(name, "timer%d", gptimer_id);
>> -		oh_name = name;
>> +		sprintf(timer_name, "timer%d", gptimer_id);
>> +		*name = timer_name;
> 
> Ok. But in case of non-DT boot if someone selects gptimers for both clkevt and
> clksrc, both the name members will end up pointing to the same memory location.
> To be specific, in the current code the clkevt timer name will point to the clksrc
> name. This won't be noticeable during boot since the clkevt name gets printed
> before it is over-written.

Yes you are right! Good catch. Will fix that.

Cheers
Jon

^ permalink raw reply

* [PATCH] arm: mvebu: enable the SD card slot on Armada 370 Reference Design board
From: Florian Fainelli @ 2013-02-01 10:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130131175743.GF7717@titan.lakedaemon.net>

The Armada 370 Reference Design board has one SD card slot, directly
connected to the SDIO IP of the SoC, so we enable this IP. there are no
GPIOs for card-detect and write-protect so we do not specify any.

Signed-off-by: Florian Fainelli <florian@openwrt.org>
---
Jason,

This is against your mvebu/dt branch

 arch/arm/boot/dts/armada-370-rd.dts |    7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts
index d62dfac..f8e4855 100644
--- a/arch/arm/boot/dts/armada-370-rd.dts
+++ b/arch/arm/boot/dts/armada-370-rd.dts
@@ -57,5 +57,12 @@
 			phy = <&phy1>;
 			phy-mode = "rgmii-id";
 		};
+
+		mvsdio at d00d4000 {
+			pinctrl-0 = <&sdio_pins1>;
+			pinctrl-names = "default";
+			status = "okay";
+			/* No CD or WP GPIOs */
+		};
 	};
 };
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v4] arm: use built-in byte swap function
From: Russell King - ARM Linux @ 2013-02-01 10:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130131183747.d56289dbd89b165cf12a9d28@freescale.com>

On Thu, Jan 31, 2013 at 06:37:47PM -0600, Kim Phillips wrote:
> +#if GCC_VERSION >= 40600
> +#define __HAVE_BUILTIN_BSWAP32__
> +#define __HAVE_BUILTIN_BSWAP64__

You really aren't listening to anything that's been said to you.

^ permalink raw reply

* [PATCHv2 for soc 4/4] arm: socfpga: Add SMP support for actual socfpga harware
From: Pavel Machek @ 2013-02-01 10:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130201035040.GE4838@quad.lixom.net>

Hi!

> > Because the CPU1 start address is different for socfpga-vt and
> > socfpga-cyclone5, we add code to use the correct CPU1 start addr.

> > @@ -72,6 +73,13 @@ void __init socfpga_sysmgr_init(void)
> >  	struct device_node *np;
> >  
> >  	np = of_find_compatible_node(NULL, NULL, "altr,sys-mgr");
> > +
> > +	if (of_property_read_u32(np, "cpu1-start-addr",
> > +			(u32 *) &cpu1start_addr)) {
> > +		early_printk("Need cpu1-start-addr in device tree.\n");
> > +		panic("Need cpu1-start-addr in device tree.\n");
> > +	}
> > +
> >  	sys_manager_base_addr = of_iomap(np, 0);
> 
> Wouldn't it be easier to diagnose this failure if you just printed the error
> and continued booting without the second CPU? An early panic is usually really
> hard to debug since you might not get early console without extra work.

I actually thought about that... but could not think of non-ugly way
of doing that. I hope dts will normally be "right" for any production
system...
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* [PATCHv2 for soc 4/4] arm: socfpga: Add SMP support for actual socfpga harware
From: Pavel Machek @ 2013-02-01 10:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359651943-21752-5-git-send-email-dinguyen@altera.com>

On Thu 2013-01-31 11:05:43, dinguyen at altera.com wrote:
> From: Dinh Nguyen <dinguyen@altera.com>
> 
> Because the CPU1 start address is different for socfpga-vt and
> socfpga-cyclone5, we add code to use the correct CPU1 start addr.
> 
> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Pavel Machek <pavel@denx.de>
Signed-off-by: Pavel Machek <pavel@denx.de>

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* [PATCH 2/4] ARM: mach-shmobile: r8a7779: Allow initialisation of GIC by DT
From: Mark Rutland @ 2013-02-01 10:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130201003410.GA30007@verge.net.au>

On Fri, Feb 01, 2013 at 12:34:10AM +0000, Simon Horman wrote:
> On Fri, Feb 01, 2013 at 09:11:19AM +0900, Simon Horman wrote:
> > On Thu, Jan 31, 2013 at 12:32:13PM +0000, Mark Rutland wrote:
> > > Hi Simon,
> > > 
> > > On Thu, Jan 31, 2013 at 01:50:49AM +0000, Simon Horman wrote:
> > > > This allows the GIC interrupt controller of the  r8a7779 SoC to be
> > > > initialised using a flattened device tree blob.
> > > > 
> > > > Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
> > > > ---
> > > >  arch/arm/boot/dts/r8a7779.dtsi               |   40 ++++++++++++++++++++++++++
> > > >  arch/arm/mach-shmobile/include/mach/common.h |    1 +
> > > >  arch/arm/mach-shmobile/intc-r8a7779.c        |   27 +++++++++++++----
> > > >  3 files changed, 62 insertions(+), 6 deletions(-)
> > > >  create mode 100644 arch/arm/boot/dts/r8a7779.dtsi
> > > > 
> > > > diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
> > > > new file mode 100644
> > > > index 0000000..eadc12e
> > > > --- /dev/null
> > > > +++ b/arch/arm/boot/dts/r8a7779.dtsi
> > > > @@ -0,0 +1,40 @@
> > > > +/*
> > > > + * Device Tree Source for Renesas r8a7740
> > > > + *
> > > > + * Copyright (C) 2013 Renesas Solutions Corp.
> > > > + * Copyright (C) 2013 Simon Horman
> > > > + *
> > > > + * This file is licensed under the terms of the GNU General Public License
> > > > + * version 2.  This program is licensed "as is" without any warranty of any
> > > > + * kind, whether express or implied.
> > > > + */
> > > > +
> > > > +/include/ "skeleton.dtsi"
> > > > +
> > > > +/ {
> > > > +	compatible = "renesas,r8a7779";
> > > > +
> > > > +	cpus {
> > > > +		cpu at 0 {
> > > > +			compatible = "arm,cortex-a9";
> > > > +		};
> > > > +		cpu at 1 {
> > > > +			compatible = "arm,cortex-a9";
> > > > +		};
> > > > +		cpu at 2 {
> > > > +			compatible = "arm,cortex-a9";
> > > > +		};
> > > > +		cpu at 3 {
> > > > +			compatible = "arm,cortex-a9";
> > > > +		};
> > > > +	};
> > > 
> > > Sorry to sound like a broken record, but it'd be good to see reg and
> > > device_type set here.
> > 
> > Sure, will do.
> > 
> > > > +
> > > > +        gic: interrupt-controller at f0001000 {
> > > > +                compatible = "arm,cortex-a9-gic";
> > > > +                #interrupt-cells = <3>;
> > > > +                #address-cells = <1>;
> > > 
> > > Why is #address-cells needed here (and without #size-cells)? I see it's in the
> > > binding document example, but I can't figure out why.
> > 
> > Its here because I copied the example.
> > I will see about removing it from here.

Rob, Grant, do either of you know if there's a reason for this that we've
missed?

The gic doesn't have any direct children, and this doesn't seem to be
some decvicetree interrupt-controller magic.

If this is superfluous, how about the patch below?

I took a quick look at arch/arm/boot/dts/. Some gic nodes don't have
#address-cells, some have it but not #size-cells, and some have both. These
should probably be cleaned up too.

[...]

Thanks,
Mark.

---->8----

>From dc734edb8040513785429c11e40a420870dc55a4 Mon Sep 17 00:00:00 2001
From: Mark Rutland <mark.rutland@arm.com>
Date: Fri, 1 Feb 2013 10:18:05 +0000
Subject: [PATCH] Docs: gic: remove #address-cells from example

The gic has no child nodes, and so doesn't need #address-cells. Having
the property defined in the example only serves as a source of
confusion.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
---
 Documentation/devicetree/bindings/arm/gic.txt | 1 -
 1 file changed, 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/gic.txt b/Documentation/devicetree/bindings/arm/gic.txt
index 62eb8df..45b99ab 100644
--- a/Documentation/devicetree/bindings/arm/gic.txt
+++ b/Documentation/devicetree/bindings/arm/gic.txt
@@ -54,7 +54,6 @@ Example:
 	intc: interrupt-controller at fff11000 {
 		compatible = "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
-		#address-cells = <1>;
 		interrupt-controller;
 		reg = <0xfff11000 0x1000>,
 		      <0xfff10100 0x100>;
-- 
1.8.1.1

^ permalink raw reply related

* [PATCH 5/5] s5p-fimc: Redefine platform data structure for fimc-is
From: Sylwester Nawrocki @ 2013-02-01 11:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359566606-31394-6-git-send-email-s.nawrocki@samsung.com>

On 01/30/2013 06:23 PM, Sylwester Nawrocki wrote:
> Newer Exynos4 SoC are equipped with a local camera ISP that
> controls external raw image sensor directly. Such sensors
> can be connected through FIMC-LITEn (and MIPI-CSISn) IPs to
> the ISP, which then feeds image data to the FIMCn IP. Thus
> there can be two busses associated with an image source
> (sensor). Rename struct s5p_fimc_isp_info describing external
> image sensor (video decoder) to struct fimc_source_info to
> avoid confusion. bus_type is split into fimc_bus_type and
> sensor_bus_type. The bus type enumeration is extended to
> include both FIMC Writeback input types.
> 
> The bus_type enumeration and the data structure name in the
> board files are modified according to the above changes.
> 
> Cc: Kukjin Kim <kgene.kim@samsung.com>
> Cc: linux-samsung-soc at vger.kernel.org
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>

Kukjin, can I please have your ack on this patch so it can be
merged through the media tree ?

--

Thanks,
Sylwester
> ---
>  arch/arm/mach-exynos/mach-nuri.c                |    8 ++--
>  arch/arm/mach-exynos/mach-universal_c210.c      |    8 ++--
>  arch/arm/mach-s5pv210/mach-goni.c               |    6 +--
>  drivers/media/platform/s5p-fimc/fimc-lite-reg.c |    8 ++--
>  drivers/media/platform/s5p-fimc/fimc-lite-reg.h |    4 +-
>  drivers/media/platform/s5p-fimc/fimc-mdevice.c  |   16 ++++----
>  drivers/media/platform/s5p-fimc/fimc-mdevice.h  |    2 +-
>  drivers/media/platform/s5p-fimc/fimc-reg.c      |   34 +++++++++-------
>  drivers/media/platform/s5p-fimc/fimc-reg.h      |    6 +--
>  include/media/s5p_fimc.h                        |   49 ++++++++++++++---------
>  10 files changed, 79 insertions(+), 62 deletions(-)
> 
> diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
> index 27d4ed8..7c2600e 100644
> --- a/arch/arm/mach-exynos/mach-nuri.c
> +++ b/arch/arm/mach-exynos/mach-nuri.c
> @@ -1209,25 +1209,25 @@ static struct i2c_board_info m5mols_board_info = {
>  	.platform_data	= &m5mols_platdata,
>  };
> 
> -static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
> +static struct fimc_source_info nuri_camera_sensors[] = {
>  	{
>  		.flags		= V4L2_MBUS_PCLK_SAMPLE_RISING |
>  				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
> -		.bus_type	= FIMC_ITU_601,
> +		.fimc_bus_type	= FIMC_BUS_TYPE_ITU_601,
>  		.board_info	= &s5k6aa_board_info,
>  		.clk_frequency	= 24000000UL,
>  		.i2c_bus_num	= 6,
>  	}, {
>  		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
>  				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
> -		.bus_type	= FIMC_MIPI_CSI2,
> +		.fimc_bus_type	= FIMC_BUS_TYPE_MIPI_CSI2,
>  		.board_info	= &m5mols_board_info,
>  		.clk_frequency	= 24000000UL,
>  	},
>  };
> 
>  static struct s5p_platform_fimc fimc_md_platdata = {
> -	.isp_info	= nuri_camera_sensors,
> +	.source_info	= nuri_camera_sensors,
>  	.num_clients	= ARRAY_SIZE(nuri_camera_sensors),
>  };
> 
> diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
> index 9e3340f..c09290a 100644
> --- a/arch/arm/mach-exynos/mach-universal_c210.c
> +++ b/arch/arm/mach-exynos/mach-universal_c210.c
> @@ -988,12 +988,12 @@ static struct i2c_board_info m5mols_board_info = {
>  	.platform_data = &m5mols_platdata,
>  };
> 
> -static struct s5p_fimc_isp_info universal_camera_sensors[] = {
> +static struct fimc_source_info universal_camera_sensors[] = {
>  	{
>  		.mux_id		= 0,
>  		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
>  				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
> -		.bus_type	= FIMC_ITU_601,
> +		.fimc_bus_type	= FIMC_BUS_TYPE_ITU_601,
>  		.board_info	= &s5k6aa_board_info,
>  		.i2c_bus_num	= 0,
>  		.clk_frequency	= 24000000UL,
> @@ -1001,7 +1001,7 @@ static struct s5p_fimc_isp_info universal_camera_sensors[] = {
>  		.mux_id		= 0,
>  		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
>  				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
> -		.bus_type	= FIMC_MIPI_CSI2,
> +		.fimc_bus_type	= FIMC_BUS_TYPE_MIPI_CSI2,
>  		.board_info	= &m5mols_board_info,
>  		.i2c_bus_num	= 0,
>  		.clk_frequency	= 24000000UL,
> @@ -1009,7 +1009,7 @@ static struct s5p_fimc_isp_info universal_camera_sensors[] = {
>  };
> 
>  static struct s5p_platform_fimc fimc_md_platdata = {
> -	.isp_info	= universal_camera_sensors,
> +	.source_info	= universal_camera_sensors,
>  	.num_clients	= ARRAY_SIZE(universal_camera_sensors),
>  };
> 
> diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
> index c72b310..423f6b6 100644
> --- a/arch/arm/mach-s5pv210/mach-goni.c
> +++ b/arch/arm/mach-s5pv210/mach-goni.c
> @@ -841,12 +841,12 @@ static struct i2c_board_info noon010pc30_board_info = {
>  	.platform_data = &noon010pc30_pldata,
>  };
> 
> -static struct s5p_fimc_isp_info goni_camera_sensors[] = {
> +static struct fimc_source_info goni_camera_sensors[] = {
>  	{
>  		.mux_id		= 0,
>  		.flags		= V4L2_MBUS_PCLK_SAMPLE_FALLING |
>  				  V4L2_MBUS_VSYNC_ACTIVE_LOW,
> -		.bus_type	= FIMC_ITU_601,
> +		.bus_type	= FIMC_BUS_TYPE_ITU_601,
>  		.board_info	= &noon010pc30_board_info,
>  		.i2c_bus_num	= 0,
>  		.clk_frequency	= 16000000UL,
> @@ -854,7 +854,7 @@ static struct s5p_fimc_isp_info goni_camera_sensors[] = {
>  };
> 
>  static struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
> -	.isp_info	= goni_camera_sensors,
> +	.source_info	= goni_camera_sensors,
>  	.num_clients	= ARRAY_SIZE(goni_camera_sensors),
>  };
> 
> diff --git a/drivers/media/platform/s5p-fimc/fimc-lite-reg.c b/drivers/media/platform/s5p-fimc/fimc-lite-reg.c
> index 962652d..f0af075 100644
> --- a/drivers/media/platform/s5p-fimc/fimc-lite-reg.c
> +++ b/drivers/media/platform/s5p-fimc/fimc-lite-reg.c
> @@ -187,12 +187,12 @@ static void flite_hw_set_camera_port(struct fimc_lite *dev, int id)
> 
>  /* Select serial or parallel bus, camera port (A,B) and set signals polarity */
>  void flite_hw_set_camera_bus(struct fimc_lite *dev,
> -			     struct s5p_fimc_isp_info *s_info)
> +			     struct fimc_source_info *si)
>  {
>  	u32 cfg = readl(dev->regs + FLITE_REG_CIGCTRL);
> -	unsigned int flags = s_info->flags;
> +	unsigned int flags = si->flags;
> 
> -	if (s_info->bus_type != FIMC_MIPI_CSI2) {
> +	if (si->sensor_bus_type != FIMC_BUS_TYPE_MIPI_CSI2) {
>  		cfg &= ~(FLITE_REG_CIGCTRL_SELCAM_MIPI |
>  			 FLITE_REG_CIGCTRL_INVPOLPCLK |
>  			 FLITE_REG_CIGCTRL_INVPOLVSYNC |
> @@ -212,7 +212,7 @@ void flite_hw_set_camera_bus(struct fimc_lite *dev,
> 
>  	writel(cfg, dev->regs + FLITE_REG_CIGCTRL);
> 
> -	flite_hw_set_camera_port(dev, s_info->mux_id);
> +	flite_hw_set_camera_port(dev, si->mux_id);
>  }
> 
>  static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
> diff --git a/drivers/media/platform/s5p-fimc/fimc-lite-reg.h b/drivers/media/platform/s5p-fimc/fimc-lite-reg.h
> index adb9e9e..0e34584 100644
> --- a/drivers/media/platform/s5p-fimc/fimc-lite-reg.h
> +++ b/drivers/media/platform/s5p-fimc/fimc-lite-reg.h
> @@ -131,9 +131,9 @@ void flite_hw_set_interrupt_mask(struct fimc_lite *dev);
>  void flite_hw_capture_start(struct fimc_lite *dev);
>  void flite_hw_capture_stop(struct fimc_lite *dev);
>  void flite_hw_set_camera_bus(struct fimc_lite *dev,
> -			     struct s5p_fimc_isp_info *s_info);
> +			     struct fimc_source_info *s_info);
>  void flite_hw_set_camera_polarity(struct fimc_lite *dev,
> -				  struct s5p_fimc_isp_info *cam);
> +				  struct fimc_source_info *cam);
>  void flite_hw_set_window_offset(struct fimc_lite *dev, struct flite_frame *f);
>  void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f);
> 
> diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
> index d940454..f49f6f1 100644
> --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
> +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
> @@ -290,7 +290,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
>  	for (i = 0; i < num_clients; i++) {
>  		struct v4l2_subdev *sd;
> 
> -		fmd->sensor[i].pdata = pdata->isp_info[i];
> +		fmd->sensor[i].pdata = pdata->source_info[i];
>  		ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
>  		if (ret)
>  			break;
> @@ -504,7 +504,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd,
>  					    struct v4l2_subdev *sensor,
>  					    int pad, int link_mask)
>  {
> -	struct fimc_sensor_info *s_info;
> +	struct fimc_sensor_info *s_info = NULL;
>  	struct media_entity *sink;
>  	unsigned int flags = 0;
>  	int ret, i;
> @@ -614,7 +614,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  {
>  	struct v4l2_subdev *csi_sensors[CSIS_MAX_ENTITIES] = { NULL };
>  	struct v4l2_subdev *sensor, *csis;
> -	struct s5p_fimc_isp_info *pdata;
> +	struct fimc_source_info *pdata;
>  	struct fimc_sensor_info *s_info;
>  	struct media_entity *source, *sink;
>  	int i, pad, fimc_id = 0, ret = 0;
> @@ -632,8 +632,8 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  		source = NULL;
>  		pdata = &s_info->pdata;
> 
> -		switch (pdata->bus_type) {
> -		case FIMC_MIPI_CSI2:
> +		switch (pdata->sensor_bus_type) {
> +		case FIMC_BUS_TYPE_MIPI_CSI2:
>  			if (WARN(pdata->mux_id >= CSIS_MAX_ENTITIES,
>  				"Wrong CSI channel id: %d\n", pdata->mux_id))
>  				return -EINVAL;
> @@ -659,14 +659,14 @@ static int fimc_md_create_links(struct fimc_md *fmd)
>  			csi_sensors[pdata->mux_id] = sensor;
>  			break;
> 
> -		case FIMC_ITU_601...FIMC_ITU_656:
> +		case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656:
>  			source = &sensor->entity;
>  			pad = 0;
>  			break;
> 
>  		default:
>  			v4l2_err(&fmd->v4l2_dev, "Wrong bus_type: %x\n",
> -				 pdata->bus_type);
> +				 pdata->sensor_bus_type);
>  			return -EINVAL;
>  		}
>  		if (source == NULL)
> @@ -762,7 +762,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
>  				struct fimc_sensor_info *s_info,
>  				bool on)
>  {
> -	struct s5p_fimc_isp_info *pdata = &s_info->pdata;
> +	struct fimc_source_info *pdata = &s_info->pdata;
>  	struct fimc_camclk_info *camclk;
>  	int ret = 0;
> 
> diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.h b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
> index da7d992..06b0d82 100644
> --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.h
> +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.h
> @@ -53,7 +53,7 @@ struct fimc_camclk_info {
>   * This data structure applies to image sensor and the writeback subdevs.
>   */
>  struct fimc_sensor_info {
> -	struct s5p_fimc_isp_info pdata;
> +	struct fimc_source_info pdata;
>  	struct v4l2_subdev *subdev;
>  	struct fimc_dev *host;
>  };
> diff --git a/drivers/media/platform/s5p-fimc/fimc-reg.c b/drivers/media/platform/s5p-fimc/fimc-reg.c
> index c05d044..50b97c7 100644
> --- a/drivers/media/platform/s5p-fimc/fimc-reg.c
> +++ b/drivers/media/platform/s5p-fimc/fimc-reg.c
> @@ -554,7 +554,7 @@ void fimc_hw_set_output_addr(struct fimc_dev *dev,
>  }
> 
>  int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
> -				struct s5p_fimc_isp_info *cam)
> +				struct fimc_source_info *cam)
>  {
>  	u32 cfg = readl(fimc->regs + FIMC_REG_CIGCTRL);
> 
> @@ -596,14 +596,15 @@ static const struct mbus_pixfmt_desc pix_desc[] = {
>  };
> 
>  int fimc_hw_set_camera_source(struct fimc_dev *fimc,
> -			      struct s5p_fimc_isp_info *cam)
> +			      struct fimc_source_info *source)
>  {
>  	struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
> -	u32 cfg = 0;
> -	u32 bus_width;
> +	u32 bus_width, cfg = 0;
>  	int i;
> 
> -	if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
> +	switch (source->fimc_bus_type) {
> +	case FIMC_BUS_TYPE_ITU_601:
> +	case FIMC_BUS_TYPE_ITU_656:
>  		for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
>  			if (fimc->vid_cap.mf.code == pix_desc[i].pixelcode) {
>  				cfg = pix_desc[i].cisrcfmt;
> @@ -619,15 +620,17 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
>  			return -EINVAL;
>  		}
> 
> -		if (cam->bus_type == FIMC_ITU_601) {
> +		if (source->fimc_bus_type == FIMC_BUS_TYPE_ITU_601) {
>  			if (bus_width == 8)
>  				cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
>  			else if (bus_width == 16)
>  				cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
>  		} /* else defaults to ITU-R BT.656 8-bit */
> -	} else if (cam->bus_type == FIMC_MIPI_CSI2) {
> +		break;
> +	case FIMC_BUS_TYPE_MIPI_CSI2:
>  		if (fimc_fmt_is_user_defined(f->fmt->color))
>  			cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
> +		break;
>  	}
> 
>  	cfg |= (f->o_width << 16) | f->o_height;
> @@ -655,7 +658,7 @@ void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f)
>  }
> 
>  int fimc_hw_set_camera_type(struct fimc_dev *fimc,
> -			    struct s5p_fimc_isp_info *cam)
> +			    struct fimc_source_info *source)
>  {
>  	u32 cfg, tmp;
>  	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
> @@ -668,11 +671,11 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
>  		FIMC_REG_CIGCTRL_SELCAM_MIPI | FIMC_REG_CIGCTRL_CAMIF_SELWB |
>  		FIMC_REG_CIGCTRL_SELCAM_MIPI_A | FIMC_REG_CIGCTRL_CAM_JPEG);
> 
> -	switch (cam->bus_type) {
> -	case FIMC_MIPI_CSI2:
> +	switch (source->fimc_bus_type) {
> +	case FIMC_BUS_TYPE_MIPI_CSI2:
>  		cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI;
> 
> -		if (cam->mux_id == 0)
> +		if (source->mux_id == 0)
>  			cfg |= FIMC_REG_CIGCTRL_SELCAM_MIPI_A;
> 
>  		/* TODO: add remaining supported formats. */
> @@ -695,15 +698,16 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
> 
>  		writel(tmp, fimc->regs + FIMC_REG_CSIIMGFMT);
>  		break;
> -	case FIMC_ITU_601...FIMC_ITU_656:
> -		if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
> +	case FIMC_BUS_TYPE_ITU_601...FIMC_BUS_TYPE_ITU_656:
> +		if (source->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
>  			cfg |= FIMC_REG_CIGCTRL_SELCAM_ITU_A;
>  		break;
> -	case FIMC_LCD_WB:
> +	case FIMC_BUS_TYPE_LCD_WRITEBACK_A:
>  		cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
>  		break;
>  	default:
> -		v4l2_err(&vid_cap->vfd, "Invalid camera bus type selected\n");
> +		v4l2_err(&vid_cap->vfd, "Invalid FIMC bus type selected: %d\n",
> +			 source->fimc_bus_type);
>  		return -EINVAL;
>  	}
>  	writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
> diff --git a/drivers/media/platform/s5p-fimc/fimc-reg.h b/drivers/media/platform/s5p-fimc/fimc-reg.h
> index f3e0b78..1a40df6 100644
> --- a/drivers/media/platform/s5p-fimc/fimc-reg.h
> +++ b/drivers/media/platform/s5p-fimc/fimc-reg.h
> @@ -297,12 +297,12 @@ void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr);
>  void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr,
>  			     int index);
>  int fimc_hw_set_camera_source(struct fimc_dev *fimc,
> -			      struct s5p_fimc_isp_info *cam);
> +			      struct fimc_source_info *cam);
>  void fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f);
>  int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
> -				struct s5p_fimc_isp_info *cam);
> +				struct fimc_source_info *cam);
>  int fimc_hw_set_camera_type(struct fimc_dev *fimc,
> -			    struct s5p_fimc_isp_info *cam);
> +			    struct fimc_source_info *cam);
>  void fimc_hw_clear_irq(struct fimc_dev *dev);
>  void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on);
>  void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on);
> diff --git a/include/media/s5p_fimc.h b/include/media/s5p_fimc.h
> index eaea62a..28f3590 100644
> --- a/include/media/s5p_fimc.h
> +++ b/include/media/s5p_fimc.h
> @@ -1,8 +1,8 @@
>  /*
> - * Samsung S5P SoC camera interface driver header
> + * Samsung S5P/Exynos4 SoC series camera interface driver header
>   *
> - * Copyright (c) 2010 Samsung Electronics Co., Ltd
> - * Author: Sylwester Nawrocki, <s.nawrocki@samsung.com>
> + * Copyright (C) 2010 - 2013 Samsung Electronics Co., Ltd.
> + * Sylwester Nawrocki <s.nawrocki@samsung.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -14,45 +14,58 @@
> 
>  #include <media/media-entity.h>
> 
> -enum cam_bus_type {
> -	FIMC_ITU_601 = 1,
> -	FIMC_ITU_656,
> -	FIMC_MIPI_CSI2,
> -	FIMC_LCD_WB, /* FIFO link from LCD mixer */
> +/*
> + * Enumeration of the FIMC data bus types.
> + */
> +enum fimc_bus_type {
> +	/* Camera parallel bus */
> +	FIMC_BUS_TYPE_ITU_601 = 1,
> +	/* Camera parallel bus with embedded synchronization */
> +	FIMC_BUS_TYPE_ITU_656,
> +	/* Camera MIPI-CSI2 serial bus */
> +	FIMC_BUS_TYPE_MIPI_CSI2,
> +	/* FIFO link from LCD controller (WriteBack A) */
> +	FIMC_BUS_TYPE_LCD_WRITEBACK_A,
> +	/* FIFO link from LCD controller (WriteBack B) */
> +	FIMC_BUS_TYPE_LCD_WRITEBACK_B,
> +	/* FIFO link from FIMC-IS */
> +	FIMC_BUS_TYPE_ISP_WRITEBACK = FIMC_BUS_TYPE_LCD_WRITEBACK_B,
>  };
> 
>  struct i2c_board_info;
> 
>  /**
> - * struct s5p_fimc_isp_info - image sensor information required for host
> - *			      interace configuration.
> + * struct fimc_source_info - video source description required for the host
> + *			     interface configuration
>   *
>   * @board_info: pointer to I2C subdevice's board info
>   * @clk_frequency: frequency of the clock the host interface provides to sensor
> - * @bus_type: determines bus type, MIPI, ITU-R BT.601 etc.
> + * @fimc_bus_type: FIMC camera input type
> + * @sensor_bus_type: image sensor bus type, MIPI, ITU-R BT.601 etc.
> + * @flags: the parallel sensor bus flags defining signals polarity (V4L2_MBUS_*)
>   * @i2c_bus_num: i2c control bus id the sensor is attached to
>   * @mux_id: FIMC camera interface multiplexer index (separate for MIPI and ITU)
>   * @clk_id: index of the SoC peripheral clock for sensors
> - * @flags: the parallel bus flags defining signals polarity (V4L2_MBUS_*)
>   */
> -struct s5p_fimc_isp_info {
> +struct fimc_source_info {
>  	struct i2c_board_info *board_info;
>  	unsigned long clk_frequency;
> -	enum cam_bus_type bus_type;
> +	enum fimc_bus_type fimc_bus_type;
> +	enum fimc_bus_type sensor_bus_type;
> +	u16 flags;
>  	u16 i2c_bus_num;
>  	u16 mux_id;
> -	u16 flags;
>  	u8 clk_id;
>  };
> 
>  /**
>   * struct s5p_platform_fimc - camera host interface platform data
>   *
> - * @isp_info: properties of camera sensor required for host interface setup
> - * @num_clients: the number of attached image sensors
> + * @source_info: properties of an image source for the host interface setup
> + * @num_clients: the number of attached image sources
>   */
>  struct s5p_platform_fimc {
> -	struct s5p_fimc_isp_info *isp_info;
> +	struct fimc_source_info *source_info;
>  	int num_clients;
>  };
> 
> --
> 1.7.9.5

^ permalink raw reply

* [PATCH 3/6] ARM: mm: fix numerous hideous errors in proc-arm740.S
From: Hyok S. Choi @ 2013-02-01 11:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359556069-28289-4-git-send-email-will.deacon@arm.com>

Hmm, in previous years, for arm7xx platforms, boot up was not done by
typical bootloaders.
I've read the code and seems good to me to add "Acked-by".

Hyok

-----Original Message-----
From: Will Deacon [mailto:will.deacon at arm.com] 
Sent: Wednesday, January 30, 2013 11:28 PM
To: linux-arm-kernel at lists.infradead.org
Cc: Will Deacon; Hyok S. Choi
Subject: [PATCH 3/6] ARM: mm: fix numerous hideous errors in proc-arm740.S

The setup code in proc-arm740.S is completely broken and, as far as I can
tell, always has been. I was >this< close to ripping it out, when a 740t
core-tile materialised in the office, so I've had a crack at fixing things
up:

	- Fix the ram/flash area calculations so that we actually set
	  the condition flags before testing them...
	- Fix the proc_info structure so that __cpu_io_mmu_flags are
	  defined as 0, placing the __cpu_flush pointer at the correct
	  offset
	- Re-number the registers used during __arm740_setup so that
	  we don't clobber the machine ID et al
	- Advertise Thumb support via the hwcaps, since 740T is the only
	  740 implementation.

Cc: Hyok S. Choi <hyok.choi@samsung.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/mm/proc-arm740.S | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S index
2088234..fde2d2a 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -77,24 +77,27 @@ __arm740_setup:
 	mcr	p15, 0, r0, c6,	c0		@ set area 0, default
 
 	ldr	r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
-	ldr	r1, =(CONFIG_DRAM_SIZE >> 12)	@ size of RAM (must be >=
4KB)
-	mov	r2, #10				@ 11 is the minimum (4KB)
-1:	add	r2, r2, #1			@ area size *= 2
-	mov	r1, r1, lsr #1
+	ldr	r3, =(CONFIG_DRAM_SIZE >> 12)	@ size of RAM (must be >=
4KB)
+	mov	r4, #10				@ 11 is the minimum (4KB)
+1:	add	r4, r4, #1			@ area size *= 2
+	movs	r3, r3, lsr #1
 	bne	1b				@ count not zero r-shift
-	orr	r0, r0, r2, lsl #1		@ the area register value
+	orr	r0, r0, r4, lsl #1		@ the area register value
 	orr	r0, r0, #1			@ set enable bit
 	mcr	p15, 0, r0, c6,	c1		@ set area 1, RAM
 
 	ldr	r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of
FLASH
-	ldr	r1, =(CONFIG_FLASH_SIZE >> 12)	@ size of FLASH (must be >=
4KB)
-	mov	r2, #10				@ 11 is the minimum (4KB)
-1:	add	r2, r2, #1			@ area size *= 2
-	mov	r1, r1, lsr #1
+	ldr	r3, =(CONFIG_FLASH_SIZE >> 12)	@ size of FLASH (must be >=
4KB)
+	cmp	r3, #0
+	moveq	r0, #0
+	beq	2f
+	mov	r4, #10				@ 11 is the minimum (4KB)
+1:	add	r4, r4, #1			@ area size *= 2
+	movs	r3, r3, lsr #1
 	bne	1b				@ count not zero r-shift
-	orr	r0, r0, r2, lsl #1		@ the area register value
+	orr	r0, r0, r4, lsl #1		@ the area register value
 	orr	r0, r0, #1			@ set enable bit
-	mcr	p15, 0, r0, c6,	c2		@ set area 2, ROM/FLASH
+2:	mcr	p15, 0, r0, c6,	c2		@ set area 2, ROM/FLASH
 
 	mov	r0, #0x06
 	mcr	p15, 0, r0, c2, c0		@ Region 1&2 cacheable
@@ -137,10 +140,11 @@ __arm740_proc_info:
 	.long	0x41807400
 	.long	0xfffffff0
 	.long	0
+	.long	0
 	b	__arm740_setup
 	.long	cpu_arch_name
 	.long	cpu_elf_name
-	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+	.long	HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_26BIT
 	.long	cpu_arm740_name
 	.long	arm740_processor_functions
 	.long	0
--
1.8.0

^ permalink raw reply

* [PATCHv5 15/16] ARM: hyp: initialize CNTVOFF to zero
From: Dave Martin @ 2013-02-01 11:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359634539-9580-16-git-send-email-mark.rutland@arm.com>

On Thu, Jan 31, 2013 at 12:15:38PM +0000, Mark Rutland wrote:
> From: Marc Zyngier <Marc.Zyngier@arm.com>
> 
> In order to be able to use the virtual counter in a safe way,
> make sure it is initialized to zero before dropping to SVC.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Dave Martin <dave.martin@arm.com>
> ---
>  arch/arm/kernel/hyp-stub.S | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
> index 65b2417..455603a 100644
> --- a/arch/arm/kernel/hyp-stub.S
> +++ b/arch/arm/kernel/hyp-stub.S
> @@ -152,6 +152,9 @@ THUMB(	orr	r7, #(1 << 30)	)	@ HSCTLR.TE
>  	mrc	p15, 4, r7, c14, c1, 0	@ CNTHCTL
>  	orr	r7, r7, #3		@ PL1PCEN | PL1PCTEN
>  	mcr	p15, 4, r7, c14, c1, 0	@ CNTHCTL
> +	mov	r6, #0
> +	mov	r7, #0
> +	mcrr	p15, 4, r6, r7, c14	@ CNTVOFF

Is this required for safety, or is it more a sanity feature?

The architected timer counters are supposed to be monotonic time sources
only, so applying a random offset shouldn't really change anything.

The main thing I can think of is that it is easier for the host to
manage guests' virtual counter offsets if the host's offset is 0 (and
we don't really want to be changing the host offset after the host kernel
boots).

Cheers
---Dave

^ permalink raw reply

* [PATCH] ARM: dts: AM33XX: Corrects typo in interrupt field in SPI node
From: Peter Korsgaard @ 2013-02-01 11:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359697047-1816-1-git-send-email-avinashphilip@ti.com>

>>>>> "Philip" == Philip Avinash <avinashphilip@ti.com> writes:

 Philip> DT field of "interrupts" was mentioned wrongly as "interrupt" in SPI
 Philip> node. This went unnoticed as spi-omap2 driver not making use of
 Philip> interrupt. Fixes the typo.

 Philip> Signed-off-by: Philip Avinash <avinashphilip@ti.com>

Acked-by: Peter Korsgaard <jacmet@sunsite.dk>

-- 
Bye, Peter Korsgaard

^ permalink raw reply

* [PATCHv2 for soc 3/4] arm: Add v7_invalidate_l1 to cache-v7.S
From: Santosh Shilimkar @ 2013-02-01 11:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1359651943-21752-4-git-send-email-dinguyen@altera.com>

+ Lorenzo,

On Thursday 31 January 2013 10:35 PM, dinguyen at altera.com wrote:
> From: Dinh Nguyen <dinguyen@altera.com>
>
> mach-socfpga is another platform that needs to use
> v7_invalidate_l1 to bringup additional cores. There was a comment that
> the ideal place for v7_invalidate_l1 should be in arm/mm/cache-v7.S
>
> Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
> Acked-by: Simon Horman <horms+renesas@verge.net.au>
> Tested-by: Pavel Machek <pavel@denx.de>
> Reviewed-by: Pavel Machek <pavel@denx.de>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: Magnus Damm <magnus.damm@gmail.com>
> Cc: Stephen Warren <swarren@wwwdotorg.org>
> ---
>   arch/arm/mach-imx/headsmp.S      |   47 -------------------------------------
>   arch/arm/mach-shmobile/headsmp.S |   48 --------------------------------------
>   arch/arm/mach-tegra/headsmp.S    |   43 ----------------------------------
>   arch/arm/mm/cache-v7.S           |   46 ++++++++++++++++++++++++++++++++++++
>   4 files changed, 46 insertions(+), 138 deletions(-)
>
[..]

> diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
> index 7539ec2..15451ee 100644
> --- a/arch/arm/mm/cache-v7.S
> +++ b/arch/arm/mm/cache-v7.S
> @@ -19,6 +19,52 @@
>   #include "proc-macros.S"
>
>   /*
> + * The secondary kernel init calls v7_flush_dcache_all before it enables
> + * the L1; however, the L1 comes out of reset in an undefined state, so
> + * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
> + * of cache lines with uninitialized data and uninitialized tags to get
> + * written out to memory, which does really unpleasant things to the main
> + * processor.  We fix this by performing an invalidate, rather than a
> + * clean + invalidate, before jumping into the kernel.
> + *
> + * This function is cloned from arch/arm/mach-tegra/headsmp.S, and needs
> + * to be called for both secondary cores startup and primary core resume
> + * procedures.
> + */
> +ENTRY(v7_invalidate_l1)
Now since we are moving the code under common place, probably we should
update this a function a bit so that it invalidates the CPU cache till
line of unification. Just to be consistent with other flush API.

Lorenzo,
Does that make sense ?

Regards,
Santosh

^ permalink raw reply

* [PATCH v2 19/27] pci: PCIe driver for Marvell Armada 370/XP systems
From: Arnd Bergmann @ 2013-02-01 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130131224459.GA11846@obsidianresearch.com>

On Thursday 31 January 2013, Jason Gunthorpe wrote:
> On Thu, Jan 31, 2013 at 08:46:22PM +0000, Arnd Bergmann wrote:
> 
> > > If it is 0xDEAD0000, then Thomas has to keep what he has now, you
> > > can't mess with this address. Verify that the full 32 bit address
> > > exactly matching the MBUS window address is written to the PCI-PCI
> > > bridge IO base/limit registers.
> > 
> > If you do this, you break all sorts of expectations in the kernel and
> > I guess you'd have to set the io_offset value of that bus to 0x21530000
> > in order to make Linux I/O port 0 go to the first byte of the window
> > and come out as 0xDEAD0000 on the bus, but you still won't be able to
> > use legacy devices with hardcoded I/O port numbers.
> 
> I'm not sure exactly how the PCI core handles this, but it does look
> like pci_add_resource_offset via io_offset is the answer. I'm not sure
> what goes in the struct resource passed to the PCI core - the *bus* IO
> address range or the *kernel* IO address range..

IO Resources are always expressed in the kernel's view, so they are in
the range from 0 to IO_SPACE_LIMIT. The idea is that you can have multiple
buses that each have their own address space start at 0, but can put
them into the kernel address space at a different address.

Each device on any bus can still use I/O addresses starting at zero,
and you could have e.g. a VGA card on two buses each respond to I/O cycles
on port 0x3c0, but the PCI core will translate the resources to appear
in the kernel space at 0x103c0 for the second one.

> > > If it is 0x00000000 then the mmap scheme I outlined before must be
> > > used, and verify that only 0->0xFFFF is written to the PCI-PCI bridge
> > > IO base/limit registers..
> > 
> > For the primary bus, yes, but there are still two options for the
> > second one: you can either start at 0 again or you can continue
> 
> No, for *all* links. You use a mmap scheme with 4k granularity, I
> explained in a past email, but to quickly review..
> 
> - Each link gets 64k of reserved physical address space for IO,
>   this is just set aside, no MBUS windows are permantently assigned.
> - Linux is told to use a 64k IO range with bus IO address 0->0xFFFF
> - When the IO base/limit register in the link PCI-PCI bridge is programmed
>   the driver gets a 4k aligned region somewhere from 0->0xFFFF and then:
>     - Allocates a 64k MBUS window that translates physical address
>       0xZZZZxxxx to IO bus address 0x0000xxxx (goes in the TLP) for
>       that link
>     - Uses pci_ioremap_io to map the fraction of the link's 64k MBUS window
>       allocated to that bridge to the correct offset in the 
>       PCI_IO_VIRT_BASE region

We'd have to change pci_ioremap_io to allow mapping less than 64k, but
yes, that would work, too. I don't see an advantage to it though,
other than having io_offset always be zero.

> > at 0x10000 as we do for mv78xx0 and kirkwood for instance. Both
> > approaches probably have their merit.
> 
> Kirkwood uses the MBUS remapping registers to set the TLP address of
> link 0 to start at 0 and of link 1 to start at 0x10000 - so it is
> consistent with what you describe..

Right, so it also uses io_offset = 0 all the time, which means the
bus I/O port numbers are identical to the Linux I/O port numbers,
but they go beyond 64K on the bus on the second and later links.

> However, this is a suboptimal way to run the HW. It would be much
> better to place each link in a seperate PCI domain and have each link
> start its bus IO address at 0, and assign the kernel IO address in
> sequential 64k blocks as today.

I agree.

	Arnd

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox