All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 00/10] Tegra114 clockframework
@ 2013-02-11 11:04 ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

This is the sixth version of the Tegra114 clockframework. It is based on the
for-next branch of
git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git and
http://www.spinics.net/lists/arm-kernel/msg220452.html.

It has been boottested on Pluto.

Changes from v5:

* Add initialization code for PLLC
* Remove some unnecessary clocks
* Fix bug in PLL locking refactoring
* Add super clocks
* Remove most calls to clk_register_clkdev() for the peripheral clocks

Changes from v4:

* Split the new PLL types patch into smaller patches
* Fix some bugs in the PLL patches

Changes from v3:

* Merge with for-next branch
* Provide empty tegra_cpu_car_ops to make SMP boot not crash

Changes from v2:

* Added missing PLLs
* Added bindings to tegra114.dtsi
* Moved the table patch for clk-mux.c to 'clk: add table lookup to mux'
* Bugfixes

Changes from v1:

* Remove SATA and PCIe clocks. They don't appear in the internal TRM, so I
  assume they don't exist.
* Rebase on top of Hiroshi's latest Tegra114 patches
* More generic mux code. This is necessary for the AHUB and DAM clocks.


Peter De Schrijver (10):
  clk: tegra: Refactor PLL programming code
  clk: tegra: Add TEGRA_PLL_BYPASS flag
  clk: tegra: Add PLL post divider table
  clk: tegra: Add new fields and PLL types for Tegra114
  clk: tegra: Add flags to tegra_clk_periph()
  clk: tegra: Workaround for Tegra114 MSENC problem
  ARM: tegra: Define Tegra114 CAR binding
  ARM: dt: Add references to tegra_car clocks
  clk: tegra: Implement clocks for Tegra114
  clk: tegra: devicetree match for nvidia,tegra114-car

 .../bindings/clock/nvidia,tegra114-car.txt         |  316 +++
 arch/arm/boot/dts/tegra114.dtsi                    |    8 +-
 drivers/clk/tegra/Makefile                         |    1 +
 drivers/clk/tegra/clk-periph-gate.c                |    9 +
 drivers/clk/tegra/clk-periph.c                     |   11 +-
 drivers/clk/tegra/clk-pll.c                        | 1136 ++++++++++-
 drivers/clk/tegra/clk-tegra114.c                   | 2036 ++++++++++++++++++++
 drivers/clk/tegra/clk-tegra20.c                    |  153 +-
 drivers/clk/tegra/clk-tegra30.c                    |  243 ++--
 drivers/clk/tegra/clk.c                            |    1 +
 drivers/clk/tegra/clk.h                            |   90 +-
 11 files changed, 3696 insertions(+), 308 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
 create mode 100644 drivers/clk/tegra/clk-tegra114.c

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 00/10] Tegra114 clockframework
@ 2013-02-11 11:04 ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

This is the sixth version of the Tegra114 clockframework. It is based on the
for-next branch of
git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra.git and
http://www.spinics.net/lists/arm-kernel/msg220452.html.

It has been boottested on Pluto.

Changes from v5:

* Add initialization code for PLLC
* Remove some unnecessary clocks
* Fix bug in PLL locking refactoring
* Add super clocks
* Remove most calls to clk_register_clkdev() for the peripheral clocks

Changes from v4:

* Split the new PLL types patch into smaller patches
* Fix some bugs in the PLL patches

Changes from v3:

* Merge with for-next branch
* Provide empty tegra_cpu_car_ops to make SMP boot not crash

Changes from v2:

* Added missing PLLs
* Added bindings to tegra114.dtsi
* Moved the table patch for clk-mux.c to 'clk: add table lookup to mux'
* Bugfixes

Changes from v1:

* Remove SATA and PCIe clocks. They don't appear in the internal TRM, so I
  assume they don't exist.
* Rebase on top of Hiroshi's latest Tegra114 patches
* More generic mux code. This is necessary for the AHUB and DAM clocks.


Peter De Schrijver (10):
  clk: tegra: Refactor PLL programming code
  clk: tegra: Add TEGRA_PLL_BYPASS flag
  clk: tegra: Add PLL post divider table
  clk: tegra: Add new fields and PLL types for Tegra114
  clk: tegra: Add flags to tegra_clk_periph()
  clk: tegra: Workaround for Tegra114 MSENC problem
  ARM: tegra: Define Tegra114 CAR binding
  ARM: dt: Add references to tegra_car clocks
  clk: tegra: Implement clocks for Tegra114
  clk: tegra: devicetree match for nvidia,tegra114-car

 .../bindings/clock/nvidia,tegra114-car.txt         |  316 +++
 arch/arm/boot/dts/tegra114.dtsi                    |    8 +-
 drivers/clk/tegra/Makefile                         |    1 +
 drivers/clk/tegra/clk-periph-gate.c                |    9 +
 drivers/clk/tegra/clk-periph.c                     |   11 +-
 drivers/clk/tegra/clk-pll.c                        | 1136 ++++++++++-
 drivers/clk/tegra/clk-tegra114.c                   | 2036 ++++++++++++++++++++
 drivers/clk/tegra/clk-tegra20.c                    |  153 +-
 drivers/clk/tegra/clk-tegra30.c                    |  243 ++--
 drivers/clk/tegra/clk.c                            |    1 +
 drivers/clk/tegra/clk.h                            |   90 +-
 11 files changed, 3696 insertions(+), 308 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
 create mode 100644 drivers/clk/tegra/clk-tegra114.c

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 01/10] clk: tegra: Refactor PLL programming code
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

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()
* Split _tegra_clk_register_pll()

Signed-off-by: Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/clk/tegra/clk-pll.c     |  262 ++++++++++++++++++++++++---------------
 drivers/clk/tegra/clk-tegra20.c |  144 +++++++++++-----------
 drivers/clk/tegra/clk-tegra30.c |  234 +++++++++++++++++-----------------
 drivers/clk/tegra/clk.h         |    9 +-
 4 files changed, 356 insertions(+), 293 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 165f247..3feefb1 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,28 @@ 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;
+	if (pll->flags & TEGRA_PLL_LOCK_MISC)
+		lock_addr += pll->params->misc_reg;
+	else
+		lock_addr += 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 +163,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 +180,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 +207,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 +246,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 +293,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 +411,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 +444,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 +453,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 +472,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 +575,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;
 }
 
@@ -577,28 +614,17 @@ const struct clk_ops tegra_clk_plle_ops = {
 	.enable = clk_plle_enable,
 };
 
-static 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_freq_table *freq_table, spinlock_t *lock,
-		const struct clk_ops *ops)
+static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
+		void __iomem *pmc, 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 tegra_clk_pll *pll;
-	struct clk *clk;
-	struct clk_init_data init;
 
 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 	if (!pll)
 		return ERR_PTR(-ENOMEM);
 
-	init.name = name;
-	init.ops = ops;
-	init.flags = flags;
-	init.parent_names = (parent_name ? &parent_name : NULL);
-	init.num_parents = (parent_name ? 1 : 0);
-
 	pll->clk_base = clk_base;
 	pll->pmc = pmc;
 
@@ -615,34 +641,68 @@ static struct clk *_tegra_clk_register_pll(const char *name,
 	pll->divm_shift = PLL_BASE_DIVM_SHIFT;
 	pll->divm_width = PLL_BASE_DIVM_WIDTH;
 
+	return pll;
+}
+
+static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll,
+		const char *name, const char *parent_name, unsigned long flags,
+		const struct clk_ops *ops)
+{
+	struct clk_init_data init;
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
 	/* Data in .init is copied by clk_register(), so stack variable OK */
 	pll->hw.init = &init;
 
-	clk = clk_register(NULL, &pll->hw);
-	if (IS_ERR(clk))
-		kfree(pll);
-
-	return clk;
+	return clk_register(NULL, &pll->hw);
 }
 
 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)
 {
-	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);
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pll_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
 }
 
 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)
 {
-	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);
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+	pll_flags |= TEGRA_PLL_LOCK_MISC;
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_plle_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
 }
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 },
 };
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index a09d7dc..0a9e088 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -182,12 +182,14 @@ 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_LOCK_MISC - Lock bit is in the misc register instead of the
+ *     base register.
  */
 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 +212,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_LOCK_MISC 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);
 
 /**
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 01/10] clk: tegra: Refactor PLL programming code
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

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()
* Split _tegra_clk_register_pll()

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

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 165f247..3feefb1 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,28 @@ 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;
+	if (pll->flags & TEGRA_PLL_LOCK_MISC)
+		lock_addr += pll->params->misc_reg;
+	else
+		lock_addr += 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 +163,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 +180,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 +207,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 +246,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 +293,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 +411,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 +444,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 +453,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 +472,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 +575,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;
 }
 
@@ -577,28 +614,17 @@ const struct clk_ops tegra_clk_plle_ops = {
 	.enable = clk_plle_enable,
 };
 
-static 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_freq_table *freq_table, spinlock_t *lock,
-		const struct clk_ops *ops)
+static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
+		void __iomem *pmc, 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 tegra_clk_pll *pll;
-	struct clk *clk;
-	struct clk_init_data init;
 
 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 	if (!pll)
 		return ERR_PTR(-ENOMEM);
 
-	init.name = name;
-	init.ops = ops;
-	init.flags = flags;
-	init.parent_names = (parent_name ? &parent_name : NULL);
-	init.num_parents = (parent_name ? 1 : 0);
-
 	pll->clk_base = clk_base;
 	pll->pmc = pmc;
 
@@ -615,34 +641,68 @@ static struct clk *_tegra_clk_register_pll(const char *name,
 	pll->divm_shift = PLL_BASE_DIVM_SHIFT;
 	pll->divm_width = PLL_BASE_DIVM_WIDTH;
 
+	return pll;
+}
+
+static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll,
+		const char *name, const char *parent_name, unsigned long flags,
+		const struct clk_ops *ops)
+{
+	struct clk_init_data init;
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
 	/* Data in .init is copied by clk_register(), so stack variable OK */
 	pll->hw.init = &init;
 
-	clk = clk_register(NULL, &pll->hw);
-	if (IS_ERR(clk))
-		kfree(pll);
-
-	return clk;
+	return clk_register(NULL, &pll->hw);
 }
 
 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)
 {
-	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);
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pll_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
 }
 
 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)
 {
-	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);
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+	pll_flags |= TEGRA_PLL_LOCK_MISC;
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_plle_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
 }
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 },
 };
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index a09d7dc..0a9e088 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -182,12 +182,14 @@ 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_LOCK_MISC - Lock bit is in the misc register instead of the
+ *     base register.
  */
 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 +212,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_LOCK_MISC 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);
 
 /**
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

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-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/clk/tegra/clk-pll.c |   12 ++++++++----
 drivers/clk/tegra/clk.h     |    2 ++
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 3feefb1..4ee6d03 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -171,7 +171,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);
 
@@ -188,7 +189,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) {
@@ -459,7 +462,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)) {
@@ -671,6 +674,7 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
 
+	pll_flags |= TEGRA_PLL_BYPASS;
 	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
 			      freq_table, lock);
 	if (IS_ERR(pll))
@@ -692,8 +696,8 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 {
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
-	pll_flags |= TEGRA_PLL_LOCK_MISC;
 
+	pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
 	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
 			      freq_table, lock);
 	if (IS_ERR(pll))
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 0a9e088..2697aa8 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -184,6 +184,7 @@ struct tegra_clk_pll_params {
  * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
  * TEGRA_PLL_LOCK_MISC - Lock bit is in the misc register instead of the
  *     base register.
+ * TEGRA_PLL_BYPASS - PLL has bypass bit
  */
 struct tegra_clk_pll {
 	struct clk_hw	hw;
@@ -213,6 +214,7 @@ struct tegra_clk_pll {
 #define TEGRA_PLL_FIXED BIT(6)
 #define TEGRA_PLLE_CONFIGURE BIT(7)
 #define TEGRA_PLL_LOCK_MISC BIT(8)
+#define TEGRA_PLL_BYPASS BIT(9)
 
 extern const struct clk_ops tegra_clk_pll_ops;
 extern const struct clk_ops tegra_clk_plle_ops;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

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 |   12 ++++++++----
 drivers/clk/tegra/clk.h     |    2 ++
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 3feefb1..4ee6d03 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -171,7 +171,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);
 
@@ -188,7 +189,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) {
@@ -459,7 +462,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)) {
@@ -671,6 +674,7 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
 
+	pll_flags |= TEGRA_PLL_BYPASS;
 	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
 			      freq_table, lock);
 	if (IS_ERR(pll))
@@ -692,8 +696,8 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 {
 	struct tegra_clk_pll *pll;
 	struct clk *clk;
-	pll_flags |= TEGRA_PLL_LOCK_MISC;
 
+	pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
 	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
 			      freq_table, lock);
 	if (IS_ERR(pll))
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 0a9e088..2697aa8 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -184,6 +184,7 @@ struct tegra_clk_pll_params {
  * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
  * TEGRA_PLL_LOCK_MISC - Lock bit is in the misc register instead of the
  *     base register.
+ * TEGRA_PLL_BYPASS - PLL has bypass bit
  */
 struct tegra_clk_pll {
 	struct clk_hw	hw;
@@ -213,6 +214,7 @@ struct tegra_clk_pll {
 #define TEGRA_PLL_FIXED BIT(6)
 #define TEGRA_PLLE_CONFIGURE BIT(7)
 #define TEGRA_PLL_LOCK_MISC BIT(8)
+#define TEGRA_PLL_BYPASS BIT(9)
 
 extern const struct clk_ops tegra_clk_pll_ops;
 extern const struct clk_ops tegra_clk_plle_ops;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 03/10] clk: tegra: Add PLL post divider table
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

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-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 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 4ee6d03..08f4eb7 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -263,6 +263,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;
 
@@ -296,7 +297,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;
@@ -309,8 +309,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;
 }
@@ -457,8 +468,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);
 
@@ -477,10 +490,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 2697aa8..79b93ee 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;
 };
 
 /**
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 03/10] clk: tegra: Add PLL post divider table
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

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 4ee6d03..08f4eb7 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -263,6 +263,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;
 
@@ -296,7 +297,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;
@@ -309,8 +309,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;
 }
@@ -457,8 +468,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);
 
@@ -477,10 +490,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 2697aa8..79b93ee 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;
 };
 
 /**
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 04/10] clk: tegra: Add new fields and PLL types for Tegra114
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

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-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/clk/tegra/clk-pll.c |  836 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/tegra/clk.h     |   48 +++
 2 files changed, 884 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 08f4eb7..914d4f9 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -79,6 +79,48 @@
 #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_ALPHA_SHIFT 18
+#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 PLLCX_MISC_COEF_LOW_RANGE \
+		((0x14 << PLLCX_MISC_KA_SHIFT) | (0x38 << PLLCX_MISC_KB_SHIFT))
+#define PLLCX_MISC_KA_SHIFT 2
+#define PLLCX_MISC_KB_SHIFT 9
+#define PLLCX_MISC_DEFAULT (PLLCX_MISC_COEF_LOW_RANGE | \
+			    (0x19 << PLLCX_MISC_ALPHA_SHIFT) | \
+			    PLLCX_MISC_DIV_LOW_RANGE | \
+			    PLLCX_MISC_RESET)
+#define PLLCX_MISC1_DEFAULT 0x000d2308
+#define PLLCX_MISC2_DEFAULT 0x30211200
+#define PLLCX_MISC3_DEFAULT 0x200
+
+#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 +143,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;
@@ -643,6 +703,520 @@ const struct clk_ops tegra_clk_plle_ops = {
 	.enable = clk_plle_enable,
 };
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+
+static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
+			   unsigned long parent_rate)
+{
+	if (parent_rate > pll_params->cf_max)
+		return 2;
+	else
+		return 1;
+}
+
+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 = _pll_fixed_mdiv(pll->params, parent_rate);
+	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 err = 0;
+
+	err = _get_table_rate(hw, cfg, rate, parent_rate);
+	if (err < 0)
+		err = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate);
+	else if (cfg->m != _pll_fixed_mdiv(pll->params, parent_rate)) {
+			WARN_ON(1);
+			err = -EINVAL;
+			goto out;
+	}
+
+	if (!cfg->p || (cfg->p >  pll->params->max_p))
+		err = -EINVAL;
+
+out:
+	return err;
+}
+
+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 = _pll_fixed_mdiv(pll->params, parent_rate);
+	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 tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
 		void __iomem *pmc, unsigned long fixed_rate,
 		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
@@ -736,3 +1310,265 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 
 	return clk;
 }
+
+#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)
+{
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	if (!pll_params->pdiv_tohw)
+		return ERR_PTR(-EINVAL);
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllxc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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;
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	/* program minimum rate by default */
+
+	val = pll_readl_base(pll);
+	if (val & PLL_BASE_ENABLE)
+		WARN_ON(val & pll_params->iddq_bit_idx);
+	else {
+		int m;
+
+		m = _pll_fixed_mdiv(pll_params, parent_rate);
+		val = m << PLL_BASE_DIVM_SHIFT;
+		val |= (pll_params->vco_min / parent_rate)
+				<< PLL_BASE_DIVN_SHIFT;
+		pll_writel_base(val, pll);
+	}
+
+	/* disable lock override */
+
+	val = pll_readl_misc(pll);
+	val &= ~BIT(29);
+	pll_writel_misc(val, pll);
+
+	pll_flags |= TEGRA_PLL_LOCK_MISC;
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllre_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 tegra_clk_pll *pll;
+	struct clk *clk;
+
+	if (!pll_params->pdiv_tohw)
+		return ERR_PTR(-EINVAL);
+
+	pll_flags |= TEGRA_PLL_BYPASS;
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllxc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 *parent, *clk;
+	struct pdiv_map *p_tohw = pll_params->pdiv_tohw;
+	struct tegra_clk_pll *pll;
+	struct tegra_clk_pll_freq_table cfg;
+	unsigned long parent_rate;
+
+	if (!p_tohw)
+		return ERR_PTR(-EINVAL);
+
+	parent = __clk_lookup(parent_name);
+	if (IS_ERR(parent)) {
+		WARN(1, "parent clk %s of %s must be registered first\n",
+			name, parent_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pll_flags |= TEGRA_PLL_BYPASS;
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	parent_rate = __clk_get_rate(parent);
+
+	/*
+	 * Most of PLLC register fields are shadowed, and can not be read
+	 * directly from PLL h/w. Hence, actual PLLC boot state is unknown.
+	 * Initialize PLL to default state: disabled, reset; shadow registers
+	 * loaded with default parameters; dividers are preset for half of
+	 * minimum VCO rate (the latter assured that shadowed divider settings
+	 * are within supported range).
+	 */
+
+	cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
+	cfg.n = cfg.m * pll_params->vco_min / parent_rate;
+
+	while (p_tohw->pdiv) {
+		if (p_tohw->pdiv == 2) {
+			cfg.p = p_tohw->hw_val;
+			break;
+		}
+		p_tohw++;
+	}
+
+	if (!p_tohw->pdiv) {
+		WARN_ON(1);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pll_writel_base(0, pll);
+	_update_pll_mnp(pll, &cfg);
+
+	pll_writel_misc(PLLCX_MISC_DEFAULT, pll);
+	pll_writel(PLLCX_MISC1_DEFAULT, pll_params->ext_misc_reg[0], pll);
+	pll_writel(PLLCX_MISC2_DEFAULT, pll_params->ext_misc_reg[1], pll);
+	pll_writel(PLLCX_MISC3_DEFAULT, pll_params->ext_misc_reg[2], pll);
+
+	_pllcx_update_dynamic_coef(pll, parent_rate, cfg.n);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 *pll;
+	struct clk *clk;
+	u32 val, val_aux;
+
+	pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params, 0,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	/* ensure parent is set to pll_re_vco */
+
+	val = pll_readl_base(pll);
+	val_aux = pll_readl(pll_params->aux_reg, pll);
+
+	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;
+		pll_writel(val, pll_params->aux_reg, pll);
+	}
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_plle_tegra114_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+#endif
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 79b93ee..ea3cce2 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -156,6 +156,13 @@ 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;
+	u32		ext_misc_reg[3];
+	int		stepa_shift;
+	int		stepb_shift;
 	int		lock_delay;
 	int		max_p;
 	struct pdiv_map *pdiv_tohw;
@@ -236,12 +243,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
  *
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 04/10] clk: tegra: Add new fields and PLL types for Tegra114
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

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 |  836 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/tegra/clk.h     |   48 +++
 2 files changed, 884 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 08f4eb7..914d4f9 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -79,6 +79,48 @@
 #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_ALPHA_SHIFT 18
+#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 PLLCX_MISC_COEF_LOW_RANGE \
+		((0x14 << PLLCX_MISC_KA_SHIFT) | (0x38 << PLLCX_MISC_KB_SHIFT))
+#define PLLCX_MISC_KA_SHIFT 2
+#define PLLCX_MISC_KB_SHIFT 9
+#define PLLCX_MISC_DEFAULT (PLLCX_MISC_COEF_LOW_RANGE | \
+			    (0x19 << PLLCX_MISC_ALPHA_SHIFT) | \
+			    PLLCX_MISC_DIV_LOW_RANGE | \
+			    PLLCX_MISC_RESET)
+#define PLLCX_MISC1_DEFAULT 0x000d2308
+#define PLLCX_MISC2_DEFAULT 0x30211200
+#define PLLCX_MISC3_DEFAULT 0x200
+
+#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 +143,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;
@@ -643,6 +703,520 @@ const struct clk_ops tegra_clk_plle_ops = {
 	.enable = clk_plle_enable,
 };
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+
+static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
+			   unsigned long parent_rate)
+{
+	if (parent_rate > pll_params->cf_max)
+		return 2;
+	else
+		return 1;
+}
+
+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 = _pll_fixed_mdiv(pll->params, parent_rate);
+	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 err = 0;
+
+	err = _get_table_rate(hw, cfg, rate, parent_rate);
+	if (err < 0)
+		err = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate);
+	else if (cfg->m != _pll_fixed_mdiv(pll->params, parent_rate)) {
+			WARN_ON(1);
+			err = -EINVAL;
+			goto out;
+	}
+
+	if (!cfg->p || (cfg->p >  pll->params->max_p))
+		err = -EINVAL;
+
+out:
+	return err;
+}
+
+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 = _pll_fixed_mdiv(pll->params, parent_rate);
+	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 tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
 		void __iomem *pmc, unsigned long fixed_rate,
 		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
@@ -736,3 +1310,265 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 
 	return clk;
 }
+
+#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)
+{
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	if (!pll_params->pdiv_tohw)
+		return ERR_PTR(-EINVAL);
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllxc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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;
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	/* program minimum rate by default */
+
+	val = pll_readl_base(pll);
+	if (val & PLL_BASE_ENABLE)
+		WARN_ON(val & pll_params->iddq_bit_idx);
+	else {
+		int m;
+
+		m = _pll_fixed_mdiv(pll_params, parent_rate);
+		val = m << PLL_BASE_DIVM_SHIFT;
+		val |= (pll_params->vco_min / parent_rate)
+				<< PLL_BASE_DIVN_SHIFT;
+		pll_writel_base(val, pll);
+	}
+
+	/* disable lock override */
+
+	val = pll_readl_misc(pll);
+	val &= ~BIT(29);
+	pll_writel_misc(val, pll);
+
+	pll_flags |= TEGRA_PLL_LOCK_MISC;
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllre_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 tegra_clk_pll *pll;
+	struct clk *clk;
+
+	if (!pll_params->pdiv_tohw)
+		return ERR_PTR(-EINVAL);
+
+	pll_flags |= TEGRA_PLL_BYPASS;
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllxc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 *parent, *clk;
+	struct pdiv_map *p_tohw = pll_params->pdiv_tohw;
+	struct tegra_clk_pll *pll;
+	struct tegra_clk_pll_freq_table cfg;
+	unsigned long parent_rate;
+
+	if (!p_tohw)
+		return ERR_PTR(-EINVAL);
+
+	parent = __clk_lookup(parent_name);
+	if (IS_ERR(parent)) {
+		WARN(1, "parent clk %s of %s must be registered first\n",
+			name, parent_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pll_flags |= TEGRA_PLL_BYPASS;
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	parent_rate = __clk_get_rate(parent);
+
+	/*
+	 * Most of PLLC register fields are shadowed, and can not be read
+	 * directly from PLL h/w. Hence, actual PLLC boot state is unknown.
+	 * Initialize PLL to default state: disabled, reset; shadow registers
+	 * loaded with default parameters; dividers are preset for half of
+	 * minimum VCO rate (the latter assured that shadowed divider settings
+	 * are within supported range).
+	 */
+
+	cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
+	cfg.n = cfg.m * pll_params->vco_min / parent_rate;
+
+	while (p_tohw->pdiv) {
+		if (p_tohw->pdiv == 2) {
+			cfg.p = p_tohw->hw_val;
+			break;
+		}
+		p_tohw++;
+	}
+
+	if (!p_tohw->pdiv) {
+		WARN_ON(1);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pll_writel_base(0, pll);
+	_update_pll_mnp(pll, &cfg);
+
+	pll_writel_misc(PLLCX_MISC_DEFAULT, pll);
+	pll_writel(PLLCX_MISC1_DEFAULT, pll_params->ext_misc_reg[0], pll);
+	pll_writel(PLLCX_MISC2_DEFAULT, pll_params->ext_misc_reg[1], pll);
+	pll_writel(PLLCX_MISC3_DEFAULT, pll_params->ext_misc_reg[2], pll);
+
+	_pllcx_update_dynamic_coef(pll, parent_rate, cfg.n);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 *pll;
+	struct clk *clk;
+	u32 val, val_aux;
+
+	pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params, 0,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	/* ensure parent is set to pll_re_vco */
+
+	val = pll_readl_base(pll);
+	val_aux = pll_readl(pll_params->aux_reg, pll);
+
+	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;
+		pll_writel(val, pll_params->aux_reg, pll);
+	}
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_plle_tegra114_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+#endif
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 79b93ee..ea3cce2 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -156,6 +156,13 @@ 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;
+	u32		ext_misc_reg[3];
+	int		stepa_shift;
+	int		stepb_shift;
 	int		lock_delay;
 	int		max_p;
 	struct pdiv_map *pdiv_tohw;
@@ -236,12 +243,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
  *
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 05/10] clk: tegra: Add flags to tegra_clk_periph()
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

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-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 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 ea3cce2..4c4bf9a 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -415,7 +415,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,
@@ -458,12 +458,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,					\
@@ -478,6 +480,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,\
@@ -488,7 +491,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
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 05/10] clk: tegra: Add flags to tegra_clk_periph()
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

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 ea3cce2..4c4bf9a 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -415,7 +415,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,
@@ -458,12 +458,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,					\
@@ -478,6 +480,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,\
@@ -488,7 +491,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
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 06/10] clk: tegra: Workaround for Tegra114 MSENC problem
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

Workaround a hardware bug in MSENC during clock enable.

Signed-off-by: Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/clk/tegra/clk-periph-gate.c |    9 +++++++++
 drivers/clk/tegra/clk.h             |    2 ++
 2 files changed, 11 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 4c4bf9a..fa21c88 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -356,6 +356,7 @@ struct tegra_clk_periph_regs {
  * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the
  *     bus to flush the write operation in apb bus. This flag indicates
  *     that this peripheral is in apb bus.
+ * TEGRA_PERIPH_WAR_1005168 - Apply workaround for Tegra114 MSENC bug
  */
 struct tegra_clk_periph_gate {
 	u32			magic;
@@ -375,6 +376,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;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 06/10] clk: tegra: Workaround for Tegra114 MSENC problem
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

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             |    2 ++
 2 files changed, 11 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 4c4bf9a..fa21c88 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -356,6 +356,7 @@ struct tegra_clk_periph_regs {
  * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the
  *     bus to flush the write operation in apb bus. This flag indicates
  *     that this peripheral is in apb bus.
+ * TEGRA_PERIPH_WAR_1005168 - Apply workaround for Tegra114 MSENC bug
  */
 struct tegra_clk_periph_gate {
 	u32			magic;
@@ -375,6 +376,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;
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 07/10] ARM: tegra: Define Tegra114 CAR binding
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

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

Signed-off-by: Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 .../bindings/clock/nvidia,tegra114-car.txt         |  316 ++++++++++++++++++++
 1 files changed, 316 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..25e088d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
@@ -0,0 +1,316 @@
+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
+  214	mipi_cal_fast
+  214	dsi1_fixed
+  214	dsi2_fixed
+  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
+  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
+  259	sclk
+  260	hclk
+  261	pclk
+  262	cclk_g
+  263	cclk_lp
+
+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@c5004000 {
+		clocks = <&tegra_car 58>; /* usb2 */
+	};
+};
+
+Example board file:
+
+/ {
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <12000000>;
+		};
+
+		clk_32k: clock@1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	&tegra_car {
+		clocks = <&clk_32k> <&osc>;
+	};
+};
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 07/10] ARM: tegra: Define Tegra114 CAR binding
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

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         |  316 ++++++++++++++++++++
 1 files changed, 316 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..25e088d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
@@ -0,0 +1,316 @@
+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
+  214	mipi_cal_fast
+  214	dsi1_fixed
+  214	dsi2_fixed
+  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
+  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
+  259	sclk
+  260	hclk
+  261	pclk
+  262	cclk_g
+  263	cclk_lp
+
+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>;
+	};
+};
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

Add references to tegra_car clocks for the basic device nodes.

Signed-off-by: Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/boot/dts/tegra114.dtsi |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 96a8235..6b0a01e 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -24,10 +24,11 @@
 			      0 42 0x04
 			      0 121 0x04
 			      0 122 0x04>;
+		clocks = <&tegra_car 5>;
 	};
 
 	tegra_car: clock {
-		compatible = "nvidia,tegra114-car, nvidia,tegra30-car";
+		compatible = "nvidia,tegra114-car";
 		reg = <0x60006000 0x1000>;
 		#clock-cells = <1>;
 	};
@@ -43,6 +44,7 @@
 		reg-shift = <2>;
 		interrupts = <0 36 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 6>;
 	};
 
 	serial@70006040 {
@@ -51,6 +53,7 @@
 		reg-shift = <2>;
 		interrupts = <0 37 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 192>;
 	};
 
 	serial@70006200 {
@@ -59,6 +62,7 @@
 		reg-shift = <2>;
 		interrupts = <0 46 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 55>;
 	};
 
 	serial@70006300 {
@@ -67,12 +71,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 {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

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 |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 96a8235..6b0a01e 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -24,10 +24,11 @@
 			      0 42 0x04
 			      0 121 0x04
 			      0 122 0x04>;
+		clocks = <&tegra_car 5>;
 	};
 
 	tegra_car: clock {
-		compatible = "nvidia,tegra114-car, nvidia,tegra30-car";
+		compatible = "nvidia,tegra114-car";
 		reg = <0x60006000 0x1000>;
 		#clock-cells = <1>;
 	};
@@ -43,6 +44,7 @@
 		reg-shift = <2>;
 		interrupts = <0 36 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 6>;
 	};
 
 	serial at 70006040 {
@@ -51,6 +53,7 @@
 		reg-shift = <2>;
 		interrupts = <0 37 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 192>;
 	};
 
 	serial at 70006200 {
@@ -59,6 +62,7 @@
 		reg-shift = <2>;
 		interrupts = <0 46 0x04>;
 		status = "disabled";
+		clocks = <&tegra_car 55>;
 	};
 
 	serial at 70006300 {
@@ -67,12 +71,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 {
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:04     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

Implement clocks for Tegra114.

Signed-off-by: Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/clk/tegra/Makefile       |    1 +
 drivers/clk/tegra/clk-tegra114.c | 2036 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 2037 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..cd50c18
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -0,0 +1,2036 @@
+/*
+ * 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 CCLKG_BURST_POLICY 0x368
+#define CCLKLP_BURST_POLICY 0x370
+#define SCLK_BURST_POLICY 0x028
+#define SYSTEM_CLK_RATE 0x030
+
+#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 DEFINE_SPINLOCK(sysrate_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 = pll_p_out3, dsi1_fixed = pll_p_out3,
+	dsi2_fixed = pll_p_out3, xusb_host_src, xusb_falcon_src, xusb_fs_src,
+	xusb_ss_src, xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk,
+	cclk_g, cclk_lp,
+
+	/* 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 const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
+			       "pll_p_out3", "pll_p_out2", "unused",
+			       "clk_32k", "pll_m_out1" };
+
+static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+					"pll_p", "pll_p_out4", "unused",
+					"unused", "pll_x" };
+
+static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+					 "pll_p", "pll_p_out4", "unused",
+					 "unused", "pll_x", "pll_x_out0" };
+
+static void __init tegra114_super_clk_init(void __iomem *clk_base)
+{
+	struct clk *clk;
+
+	/* CCLKG */
+	clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
+					ARRAY_SIZE(cclk_g_parents),
+					CLK_SET_RATE_PARENT,
+					clk_base + CCLKG_BURST_POLICY,
+					0, 4, 0, 0, NULL);
+	clk_register_clkdev(clk, "cclk_g", NULL);
+	clks[cclk_g] = clk;
+
+	/* CCLKLP */
+	clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
+					ARRAY_SIZE(cclk_lp_parents),
+					CLK_SET_RATE_PARENT,
+					clk_base + CCLKLP_BURST_POLICY,
+					0, 4, 8, 9, NULL);
+	clk_register_clkdev(clk, "cclk_lp", NULL);
+	clks[cclk_lp] = clk;
+
+	/* SCLK */
+	clk = tegra_clk_register_super_mux("sclk", sclk_parents,
+					ARRAY_SIZE(sclk_parents),
+					CLK_SET_RATE_PARENT,
+					clk_base + SCLK_BURST_POLICY,
+					0, 4, 0, 0, NULL);
+	clk_register_clkdev(clk, "sclk", NULL);
+	clks[sclk] = clk;
+
+	/* HCLK */
+	clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
+				   clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
+				   &sysrate_lock);
+	clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT |
+				CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
+				7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
+	clk_register_clkdev(clk, "hclk", NULL);
+	clks[hclk] = clk;
+
+	/* PCLK */
+	clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
+				   clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
+				   &sysrate_lock);
+	clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT |
+				CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
+				3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
+	clk_register_clkdev(clk, "pclk", NULL);
+	clks[pclk] = 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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	clks[usb3] = 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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	clks[xusb_dev] = clk;
+
+	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);
+		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);
+		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[] = {
+	{uarta, pll_p, 408000000, 0},
+	{uartb, pll_p, 408000000, 0},
+	{uartc, pll_p, 408000000, 0},
+	{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);
+	tegra114_super_clk_init(clk_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;
+}
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
@ 2013-02-11 11:04     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:04 UTC (permalink / raw)
  To: linux-arm-kernel

Implement clocks for Tegra114.

Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/clk/tegra/Makefile       |    1 +
 drivers/clk/tegra/clk-tegra114.c | 2036 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 2037 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..cd50c18
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -0,0 +1,2036 @@
+/*
+ * 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 CCLKG_BURST_POLICY 0x368
+#define CCLKLP_BURST_POLICY 0x370
+#define SCLK_BURST_POLICY 0x028
+#define SYSTEM_CLK_RATE 0x030
+
+#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 DEFINE_SPINLOCK(sysrate_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 = pll_p_out3, dsi1_fixed = pll_p_out3,
+	dsi2_fixed = pll_p_out3, xusb_host_src, xusb_falcon_src, xusb_fs_src,
+	xusb_ss_src, xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk,
+	cclk_g, cclk_lp,
+
+	/* 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 const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
+			       "pll_p_out3", "pll_p_out2", "unused",
+			       "clk_32k", "pll_m_out1" };
+
+static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+					"pll_p", "pll_p_out4", "unused",
+					"unused", "pll_x" };
+
+static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+					 "pll_p", "pll_p_out4", "unused",
+					 "unused", "pll_x", "pll_x_out0" };
+
+static void __init tegra114_super_clk_init(void __iomem *clk_base)
+{
+	struct clk *clk;
+
+	/* CCLKG */
+	clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
+					ARRAY_SIZE(cclk_g_parents),
+					CLK_SET_RATE_PARENT,
+					clk_base + CCLKG_BURST_POLICY,
+					0, 4, 0, 0, NULL);
+	clk_register_clkdev(clk, "cclk_g", NULL);
+	clks[cclk_g] = clk;
+
+	/* CCLKLP */
+	clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
+					ARRAY_SIZE(cclk_lp_parents),
+					CLK_SET_RATE_PARENT,
+					clk_base + CCLKLP_BURST_POLICY,
+					0, 4, 8, 9, NULL);
+	clk_register_clkdev(clk, "cclk_lp", NULL);
+	clks[cclk_lp] = clk;
+
+	/* SCLK */
+	clk = tegra_clk_register_super_mux("sclk", sclk_parents,
+					ARRAY_SIZE(sclk_parents),
+					CLK_SET_RATE_PARENT,
+					clk_base + SCLK_BURST_POLICY,
+					0, 4, 0, 0, NULL);
+	clk_register_clkdev(clk, "sclk", NULL);
+	clks[sclk] = clk;
+
+	/* HCLK */
+	clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
+				   clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
+				   &sysrate_lock);
+	clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT |
+				CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
+				7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
+	clk_register_clkdev(clk, "hclk", NULL);
+	clks[hclk] = clk;
+
+	/* PCLK */
+	clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
+				   clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
+				   &sysrate_lock);
+	clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT |
+				CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
+				3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
+	clk_register_clkdev(clk, "pclk", NULL);
+	clks[pclk] = 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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	clks[usb3] = 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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	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);
+	clks[xusb_dev] = clk;
+
+	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);
+		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);
+		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[] = {
+	{uarta, pll_p, 408000000, 0},
+	{uartb, pll_p, 408000000, 0},
+	{uartc, pll_p, 408000000, 0},
+	{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);
+	tegra114_super_clk_init(clk_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;
+}
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 10/10] clk: tegra: devicetree match for nvidia,tegra114-car
  2013-02-11 11:04 ` Peter De Schrijver
@ 2013-02-11 11:05     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:05 UTC (permalink / raw)
  To: pdeschrijver-DDmLM1+adcrQT0dZR+AlfA
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

Signed-off-by: Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 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 fa21c88..bbdd08b 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -581,4 +581,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 */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* [PATCH v6 10/10] clk: tegra: devicetree match for nvidia, tegra114-car
@ 2013-02-11 11:05     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-11 11:05 UTC (permalink / raw)
  To: linux-arm-kernel

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 fa21c88..bbdd08b 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -581,4 +581,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 */
-- 
1.7.1

^ permalink raw reply related	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
  2013-02-11 11:04     ` Peter De Schrijver
@ 2013-02-12 17:24         ` Stephen Warren
  -1 siblings, 0 replies; 45+ messages in thread
From: Stephen Warren @ 2013-02-12 17:24 UTC (permalink / raw)
  To: Peter De Schrijver
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

On 02/11/2013 04:04 AM, Peter De Schrijver wrote:
> Add references to tegra_car clocks for the basic device nodes.

In this patch, you also need to remove the "clock-frequency" properties
from tegra114-*.dts board files.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
@ 2013-02-12 17:24         ` Stephen Warren
  0 siblings, 0 replies; 45+ messages in thread
From: Stephen Warren @ 2013-02-12 17:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/11/2013 04:04 AM, Peter De Schrijver wrote:
> Add references to tegra_car clocks for the basic device nodes.

In this patch, you also need to remove the "clock-frequency" properties
from tegra114-*.dts board files.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
  2013-02-12 17:24         ` Stephen Warren
@ 2013-02-13 11:38             ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-13 11:38 UTC (permalink / raw)
  To: Stephen Warren
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

On Tue, Feb 12, 2013 at 06:24:05PM +0100, Stephen Warren wrote:
> On 02/11/2013 04:04 AM, Peter De Schrijver wrote:
> > Add references to tegra_car clocks for the basic device nodes.
> 
> In this patch, you also need to remove the "clock-frequency" properties
> from tegra114-*.dts board files.

That would probably break bisectability no? I think this needs to be done
in a separate patch. Also, the UARTD enabling in init_table[] can then be
removed.

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
@ 2013-02-13 11:38             ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-13 11:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 12, 2013 at 06:24:05PM +0100, Stephen Warren wrote:
> On 02/11/2013 04:04 AM, Peter De Schrijver wrote:
> > Add references to tegra_car clocks for the basic device nodes.
> 
> In this patch, you also need to remove the "clock-frequency" properties
> from tegra114-*.dts board files.

That would probably break bisectability no? I think this needs to be done
in a separate patch. Also, the UARTD enabling in init_table[] can then be
removed.

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
  2013-02-13 11:38             ` Peter De Schrijver
@ 2013-02-13 16:48                 ` Stephen Warren
  -1 siblings, 0 replies; 45+ messages in thread
From: Stephen Warren @ 2013-02-13 16:48 UTC (permalink / raw)
  To: Peter De Schrijver
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

On 02/13/2013 04:38 AM, Peter De Schrijver wrote:
> On Tue, Feb 12, 2013 at 06:24:05PM +0100, Stephen Warren wrote:
>> On 02/11/2013 04:04 AM, Peter De Schrijver wrote:
>>> Add references to tegra_car clocks for the basic device nodes.
>>
>> In this patch, you also need to remove the "clock-frequency" properties
>> from tegra114-*.dts board files.
> 
> That would probably break bisectability no?

Oh right, I read the patch order backwards. You can fix this by moving
this patch to the end of the series.

> I think this needs to be done in a separate patch.

To avoid bisect issues, the clock-frequency property should be removed
in the same patch that adds the clocks property, or after it.

> Also, the UARTD enabling in init_table[] can then be removed.

You still need to initialize all the UART clocks in init_table[]. This
is required to make sure the clocks have the correct parent. Without
this explicit initialization, on Tegra30 at least, it was found that
UART C didn't work correctly for Bluetooth since the default parent was
something that wasn't generating the expected frequency.

Before removing the clock-frequency property, you also need to make sure
that init_table[] forces the UART clock on, otherwise since nothing will
clk_get()/enable() the UART clock, clk_disable_unused() will disable it.
After removing clock-frequency property, of_serial.c will
clk_get()/enable() the UART clock based on the clocks property, and
hence init_table[] doesn't need to force the UART clock on.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
@ 2013-02-13 16:48                 ` Stephen Warren
  0 siblings, 0 replies; 45+ messages in thread
From: Stephen Warren @ 2013-02-13 16:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/13/2013 04:38 AM, Peter De Schrijver wrote:
> On Tue, Feb 12, 2013 at 06:24:05PM +0100, Stephen Warren wrote:
>> On 02/11/2013 04:04 AM, Peter De Schrijver wrote:
>>> Add references to tegra_car clocks for the basic device nodes.
>>
>> In this patch, you also need to remove the "clock-frequency" properties
>> from tegra114-*.dts board files.
> 
> That would probably break bisectability no?

Oh right, I read the patch order backwards. You can fix this by moving
this patch to the end of the series.

> I think this needs to be done in a separate patch.

To avoid bisect issues, the clock-frequency property should be removed
in the same patch that adds the clocks property, or after it.

> Also, the UARTD enabling in init_table[] can then be removed.

You still need to initialize all the UART clocks in init_table[]. This
is required to make sure the clocks have the correct parent. Without
this explicit initialization, on Tegra30 at least, it was found that
UART C didn't work correctly for Bluetooth since the default parent was
something that wasn't generating the expected frequency.

Before removing the clock-frequency property, you also need to make sure
that init_table[] forces the UART clock on, otherwise since nothing will
clk_get()/enable() the UART clock, clk_disable_unused() will disable it.
After removing clock-frequency property, of_serial.c will
clk_get()/enable() the UART clock based on the clocks property, and
hence init_table[] doesn't need to force the UART clock on.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
  2013-02-13 16:48                 ` Stephen Warren
@ 2013-02-14 10:01                     ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-14 10:01 UTC (permalink / raw)
  To: Stephen Warren
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

On Wed, Feb 13, 2013 at 05:48:03PM +0100, Stephen Warren wrote:
> On 02/13/2013 04:38 AM, Peter De Schrijver wrote:
> > On Tue, Feb 12, 2013 at 06:24:05PM +0100, Stephen Warren wrote:
> >> On 02/11/2013 04:04 AM, Peter De Schrijver wrote:
> >>> Add references to tegra_car clocks for the basic device nodes.
> >>
> >> In this patch, you also need to remove the "clock-frequency" properties
> >> from tegra114-*.dts board files.
> > 
> > That would probably break bisectability no?
> 
> Oh right, I read the patch order backwards. You can fix this by moving
> this patch to the end of the series.
> 

Probably. Need to check if this doesn't cause other problems.

> > I think this needs to be done in a separate patch.
> 
> To avoid bisect issues, the clock-frequency property should be removed
> in the same patch that adds the clocks property, or after it.
> 
> > Also, the UARTD enabling in init_table[] can then be removed.
> 
> You still need to initialize all the UART clocks in init_table[]. This
> is required to make sure the clocks have the correct parent. Without
> this explicit initialization, on Tegra30 at least, it was found that
> UART C didn't work correctly for Bluetooth since the default parent was
> something that wasn't generating the expected frequency.
> 

Yes. The parent relationships still need to be defined. But I think that's
the only thing we actually need to define still? Also the parent relationships
can be board specific I think in some cases, so maybe we want to move those to
DT as well at some point?

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
@ 2013-02-14 10:01                     ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-14 10:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Feb 13, 2013 at 05:48:03PM +0100, Stephen Warren wrote:
> On 02/13/2013 04:38 AM, Peter De Schrijver wrote:
> > On Tue, Feb 12, 2013 at 06:24:05PM +0100, Stephen Warren wrote:
> >> On 02/11/2013 04:04 AM, Peter De Schrijver wrote:
> >>> Add references to tegra_car clocks for the basic device nodes.
> >>
> >> In this patch, you also need to remove the "clock-frequency" properties
> >> from tegra114-*.dts board files.
> > 
> > That would probably break bisectability no?
> 
> Oh right, I read the patch order backwards. You can fix this by moving
> this patch to the end of the series.
> 

Probably. Need to check if this doesn't cause other problems.

> > I think this needs to be done in a separate patch.
> 
> To avoid bisect issues, the clock-frequency property should be removed
> in the same patch that adds the clocks property, or after it.
> 
> > Also, the UARTD enabling in init_table[] can then be removed.
> 
> You still need to initialize all the UART clocks in init_table[]. This
> is required to make sure the clocks have the correct parent. Without
> this explicit initialization, on Tegra30 at least, it was found that
> UART C didn't work correctly for Bluetooth since the default parent was
> something that wasn't generating the expected frequency.
> 

Yes. The parent relationships still need to be defined. But I think that's
the only thing we actually need to define still? Also the parent relationships
can be board specific I think in some cases, so maybe we want to move those to
DT as well at some point?

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
  2013-02-14 10:01                     ` Peter De Schrijver
@ 2013-02-14 17:30                         ` Stephen Warren
  -1 siblings, 0 replies; 45+ messages in thread
From: Stephen Warren @ 2013-02-14 17:30 UTC (permalink / raw)
  To: Peter De Schrijver
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Prashant Gaikwad

On 02/14/2013 03:01 AM, Peter De Schrijver wrote:
> On Wed, Feb 13, 2013 at 05:48:03PM +0100, Stephen Warren wrote:
...
>> You still need to initialize all the UART clocks in init_table[]. This
...
> Yes. The parent relationships still need to be defined. But I think that's
> the only thing we actually need to define still?

You might want to explicitly set the rate too, if there is a divider in
the clk module that affects it. If not, then parenting is indeed all you
need.

> Also the parent relationships
> can be board specific I think in some cases, so maybe we want to move those to
> DT as well at some point?

Yes, that's the plan. I think/thought Prashant was planning to work on that.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
@ 2013-02-14 17:30                         ` Stephen Warren
  0 siblings, 0 replies; 45+ messages in thread
From: Stephen Warren @ 2013-02-14 17:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 02/14/2013 03:01 AM, Peter De Schrijver wrote:
> On Wed, Feb 13, 2013 at 05:48:03PM +0100, Stephen Warren wrote:
...
>> You still need to initialize all the UART clocks in init_table[]. This
...
> Yes. The parent relationships still need to be defined. But I think that's
> the only thing we actually need to define still?

You might want to explicitly set the rate too, if there is a divider in
the clk module that affects it. If not, then parenting is indeed all you
need.

> Also the parent relationships
> can be board specific I think in some cases, so maybe we want to move those to
> DT as well at some point?

Yes, that's the plan. I think/thought Prashant was planning to work on that.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
  2013-02-11 11:04     ` Peter De Schrijver
@ 2013-02-15  5:39         ` Hiroshi Doyu
  -1 siblings, 0 replies; 45+ messages in thread
From: Hiroshi Doyu @ 2013-02-15  5:39 UTC (permalink / raw)
  To: Peter De Schrijver
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> wrote @ Mon, 11 Feb 2013 12:04:59 +0100:

> +enum tegra114_clk {
.....
> +       i2c4 = 103, sbc5 = 104, sbc6 = 105, apbif = 107, d_audio, dam0, dam1,
> +       dam2, hda2codec_2x = 111, audio0_2x = 113, audio1_2x, audio2_2x,

The above doesn't match the definition in  .../bindings/clock/nvidia,tegra114-car.txt.

....
105	sbc6
106	d_audio
107	apbif
108	dam0
109	dam1
110	dam2
111	hda2codec_2x
....

Taking a look at TRM, d_audio = 106 seems to be correct?

-       i2c4 = 103, sbc5 = 104, sbc6 = 105, apbif = 107, d_audio, dam0, dam1,
+       i2c4 = 103, sbc5 = 104, sbc6 = 105, d_audio, apbif = 107, dam0, dam1,

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
@ 2013-02-15  5:39         ` Hiroshi Doyu
  0 siblings, 0 replies; 45+ messages in thread
From: Hiroshi Doyu @ 2013-02-15  5:39 UTC (permalink / raw)
  To: linux-arm-kernel

Peter De Schrijver <pdeschrijver@nvidia.com> wrote @ Mon, 11 Feb 2013 12:04:59 +0100:

> +enum tegra114_clk {
.....
> +       i2c4 = 103, sbc5 = 104, sbc6 = 105, apbif = 107, d_audio, dam0, dam1,
> +       dam2, hda2codec_2x = 111, audio0_2x = 113, audio1_2x, audio2_2x,

The above doesn't match the definition in  .../bindings/clock/nvidia,tegra114-car.txt.

....
105	sbc6
106	d_audio
107	apbif
108	dam0
109	dam1
110	dam2
111	hda2codec_2x
....

Taking a look at TRM, d_audio = 106 seems to be correct?

-       i2c4 = 103, sbc5 = 104, sbc6 = 105, apbif = 107, d_audio, dam0, dam1,
+       i2c4 = 103, sbc5 = 104, sbc6 = 105, d_audio, apbif = 107, dam0, dam1,

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
  2013-02-11 11:04     ` Peter De Schrijver
@ 2013-02-15  6:18         ` Hiroshi Doyu
  -1 siblings, 0 replies; 45+ messages in thread
From: Hiroshi Doyu @ 2013-02-15  6:18 UTC (permalink / raw)
  To: Peter De Schrijver
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> wrote @ Mon, 11 Feb 2013 12:04:59 +0100:

> +enum tegra114_clk {
> +       rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12,

Why no 'cpu = 0' here?

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
@ 2013-02-15  6:18         ` Hiroshi Doyu
  0 siblings, 0 replies; 45+ messages in thread
From: Hiroshi Doyu @ 2013-02-15  6:18 UTC (permalink / raw)
  To: linux-arm-kernel

Peter De Schrijver <pdeschrijver@nvidia.com> wrote @ Mon, 11 Feb 2013 12:04:59 +0100:

> +enum tegra114_clk {
> +       rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12,

Why no 'cpu = 0' here?

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
  2013-02-15  6:18         ` Hiroshi Doyu
@ 2013-02-15  9:13             ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-15  9:13 UTC (permalink / raw)
  To: Hiroshi Doyu
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

On Fri, Feb 15, 2013 at 07:18:05AM +0100, Hiroshi Doyu wrote:
> Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> wrote @ Mon, 11 Feb 2013 12:04:59 +0100:
> 
> > +enum tegra114_clk {
> > +       rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12,
> 
> Why no 'cpu = 0' here?

It doesn't make sense I think. Yes there is a bit, but we can't use it from
software I think? Also the clock itself doesn't exist. Maybe this should be
removed from the binding document.

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
@ 2013-02-15  9:13             ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-15  9:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 15, 2013 at 07:18:05AM +0100, Hiroshi Doyu wrote:
> Peter De Schrijver <pdeschrijver@nvidia.com> wrote @ Mon, 11 Feb 2013 12:04:59 +0100:
> 
> > +enum tegra114_clk {
> > +       rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12,
> 
> Why no 'cpu = 0' here?

It doesn't make sense I think. Yes there is a bit, but we can't use it from
software I think? Also the clock itself doesn't exist. Maybe this should be
removed from the binding document.

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
  2013-02-14 17:30                         ` Stephen Warren
@ 2013-02-15 12:22                             ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-15 12:22 UTC (permalink / raw)
  To: Stephen Warren
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Prashant Gaikwad

On Thu, Feb 14, 2013 at 06:30:39PM +0100, Stephen Warren wrote:
> On 02/14/2013 03:01 AM, Peter De Schrijver wrote:
> > On Wed, Feb 13, 2013 at 05:48:03PM +0100, Stephen Warren wrote:
> ...
> >> You still need to initialize all the UART clocks in init_table[]. This
> ...
> > Yes. The parent relationships still need to be defined. But I think that's
> > the only thing we actually need to define still?
> 
> You might want to explicitly set the rate too, if there is a divider in
> the clk module that affects it. If not, then parenting is indeed all you
> need.

Yes, for PLLs that might be useful. Device clock rates can also be set by the
driver and probably should be set by the driver.

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks
@ 2013-02-15 12:22                             ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-15 12:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Feb 14, 2013 at 06:30:39PM +0100, Stephen Warren wrote:
> On 02/14/2013 03:01 AM, Peter De Schrijver wrote:
> > On Wed, Feb 13, 2013 at 05:48:03PM +0100, Stephen Warren wrote:
> ...
> >> You still need to initialize all the UART clocks in init_table[]. This
> ...
> > Yes. The parent relationships still need to be defined. But I think that's
> > the only thing we actually need to define still?
> 
> You might want to explicitly set the rate too, if there is a divider in
> the clk module that affects it. If not, then parenting is indeed all you
> need.

Yes, for PLLs that might be useful. Device clock rates can also be set by the
driver and probably should be set by the driver.

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
  2013-02-11 11:04     ` Peter De Schrijver
@ 2013-03-06 23:51         ` Andrew Chew
  -1 siblings, 0 replies; 45+ messages in thread
From: Andrew Chew @ 2013-03-06 23:51 UTC (permalink / raw)
  To: Peter De Schrijver
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

> From: linux-tegra-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org [mailto:linux-tegra-
> owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org] On Behalf Of Peter De Schrijver
> Sent: Monday, February 11, 2013 3:05 AM
> To: Peter De Schrijver
> Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Subject: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
>
> Implement clocks for Tegra114.
>
> Signed-off-by: Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> ---
>  drivers/clk/tegra/Makefile       |    1 +
>  drivers/clk/tegra/clk-tegra114.c | 2036
> ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 2037 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..cd50c18
> --- /dev/null
> +++ b/drivers/clk/tegra/clk-tegra114.c

*snip for brevity*

> +static __initdata struct tegra_periph_init_data tegra_periph_clk_list[] = {

I don't think this should be marked as __initdata.  The stuff in this list
contain clock instances that are referenced after init.

> +     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),

The csite clock needs to be marked CLK_IGNORE_UNUSED, otherwise
drivers/clk/clk.c's clk_disable_unused() will disable it after init, and JTAG
won't work after that point.

> +     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[] = {

I don't think this should be marked as __initdata.  The stuff in this list
contain clock instances that are referenced after init.

> +     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),

For disp1 and disp2, the mux mask should be 7, not 3.

> +};
> +
> +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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     clks[usb3] = 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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     clks[xusb_dev] = clk;
> +
> +     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);
> +             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);
> +             clks[data->clk_id] = clk;
> +     }
> +}

Shouldn't we call clk_register_clkdev for each of these clocks?

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
@ 2013-03-06 23:51         ` Andrew Chew
  0 siblings, 0 replies; 45+ messages in thread
From: Andrew Chew @ 2013-03-06 23:51 UTC (permalink / raw)
  To: linux-arm-kernel

> From: linux-tegra-owner at vger.kernel.org [mailto:linux-tegra-
> owner at vger.kernel.org] On Behalf Of Peter De Schrijver
> Sent: Monday, February 11, 2013 3:05 AM
> To: Peter De Schrijver
> Cc: linux-arm-kernel at lists.infradead.org; linux-tegra at vger.kernel.org
> Subject: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
>
> Implement clocks for Tegra114.
>
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
>  drivers/clk/tegra/Makefile       |    1 +
>  drivers/clk/tegra/clk-tegra114.c | 2036
> ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 2037 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..cd50c18
> --- /dev/null
> +++ b/drivers/clk/tegra/clk-tegra114.c

*snip for brevity*

> +static __initdata struct tegra_periph_init_data tegra_periph_clk_list[] = {

I don't think this should be marked as __initdata.  The stuff in this list
contain clock instances that are referenced after init.

> +     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),

The csite clock needs to be marked CLK_IGNORE_UNUSED, otherwise
drivers/clk/clk.c's clk_disable_unused() will disable it after init, and JTAG
won't work after that point.

> +     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[] = {

I don't think this should be marked as __initdata.  The stuff in this list
contain clock instances that are referenced after init.

> +     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),

For disp1 and disp2, the mux mask should be 7, not 3.

> +};
> +
> +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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     clks[usb3] = 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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     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);
> +     clks[xusb_dev] = clk;
> +
> +     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);
> +             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);
> +             clks[data->clk_id] = clk;
> +     }
> +}

Shouldn't we call clk_register_clkdev for each of these clocks?

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
  2013-03-06 23:51         ` Andrew Chew
@ 2013-03-11  9:25             ` Peter De Schrijver
  -1 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-03-11  9:25 UTC (permalink / raw)
  To: Andrew Chew
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA

On Thu, Mar 07, 2013 at 12:51:16AM +0100, Andrew Chew wrote:
> > From: linux-tegra-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org [mailto:linux-tegra-
> > owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org] On Behalf Of Peter De Schrijver
> > Sent: Monday, February 11, 2013 3:05 AM
> > To: Peter De Schrijver
> > Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org; linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > Subject: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
> >
> > Implement clocks for Tegra114.
> >
> > Signed-off-by: Peter De Schrijver <pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> > ---
> >  drivers/clk/tegra/Makefile       |    1 +
> >  drivers/clk/tegra/clk-tegra114.c | 2036
> > ++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 2037 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..cd50c18
> > --- /dev/null
> > +++ b/drivers/clk/tegra/clk-tegra114.c
> 
> *snip for brevity*
> 
> > +static __initdata struct tegra_periph_init_data tegra_periph_clk_list[] = {
> 
> I don't think this should be marked as __initdata.  The stuff in this list
> contain clock instances that are referenced after init.
> 

This is true indeed. Interesting that the build checks didn't catch this...

...

> > +     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),
> 
> The csite clock needs to be marked CLK_IGNORE_UNUSED, otherwise
> drivers/clk/clk.c's clk_disable_unused() will disable it after init, and JTAG
> won't work after that point.
> 

Ok.

> > +     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",

...

> > 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[] = {
> 
> I don't think this should be marked as __initdata.  The stuff in this list
> contain clock instances that are referenced after init.
> 

This is probably the same as tegra_periph_clk_listp[] then.

> > +     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),
> 
> For disp1 and disp2, the mux mask should be 7, not 3.
> 

Ok. Makes sene...

> > +};
> > +
> > +static __init void tegra114_periph_clk_init(void __iomem *clk_base)
> > +{
> > +     struct tegra_periph_init_data *data;
> > +     struct clk *clk;
> > +     int i;
> > +     u32 val;
> > +

...

> > +
> > +     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);
> > +             clks[data->clk_id] = clk;
> > +     }
> > +}
> 
> Shouldn't we call clk_register_clkdev for each of these clocks?
> 

No. We switched to DT bindings for all our clocks now. So drivers should use
of_clk_get().

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
@ 2013-03-11  9:25             ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-03-11  9:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 07, 2013 at 12:51:16AM +0100, Andrew Chew wrote:
> > From: linux-tegra-owner at vger.kernel.org [mailto:linux-tegra-
> > owner at vger.kernel.org] On Behalf Of Peter De Schrijver
> > Sent: Monday, February 11, 2013 3:05 AM
> > To: Peter De Schrijver
> > Cc: linux-arm-kernel at lists.infradead.org; linux-tegra at vger.kernel.org
> > Subject: [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114
> >
> > Implement clocks for Tegra114.
> >
> > Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> > ---
> >  drivers/clk/tegra/Makefile       |    1 +
> >  drivers/clk/tegra/clk-tegra114.c | 2036
> > ++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 2037 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..cd50c18
> > --- /dev/null
> > +++ b/drivers/clk/tegra/clk-tegra114.c
> 
> *snip for brevity*
> 
> > +static __initdata struct tegra_periph_init_data tegra_periph_clk_list[] = {
> 
> I don't think this should be marked as __initdata.  The stuff in this list
> contain clock instances that are referenced after init.
> 

This is true indeed. Interesting that the build checks didn't catch this...

...

> > +     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),
> 
> The csite clock needs to be marked CLK_IGNORE_UNUSED, otherwise
> drivers/clk/clk.c's clk_disable_unused() will disable it after init, and JTAG
> won't work after that point.
> 

Ok.

> > +     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",

...

> > 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[] = {
> 
> I don't think this should be marked as __initdata.  The stuff in this list
> contain clock instances that are referenced after init.
> 

This is probably the same as tegra_periph_clk_listp[] then.

> > +     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),
> 
> For disp1 and disp2, the mux mask should be 7, not 3.
> 

Ok. Makes sene...

> > +};
> > +
> > +static __init void tegra114_periph_clk_init(void __iomem *clk_base)
> > +{
> > +     struct tegra_periph_init_data *data;
> > +     struct clk *clk;
> > +     int i;
> > +     u32 val;
> > +

...

> > +
> > +     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);
> > +             clks[data->clk_id] = clk;
> > +     }
> > +}
> 
> Shouldn't we call clk_register_clkdev for each of these clocks?
> 

No. We switched to DT bindings for all our clocks now. So drivers should use
of_clk_get().

Cheers,

Peter.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v6 04/10] clk: tegra: Add new fields and PLL types for Tegra114
       [not found] <1360330602-30472-1-git-send-email-pdeschrijver@nvidia.com>
@ 2013-02-08 13:36 ` Peter De Schrijver
  0 siblings, 0 replies; 45+ messages in thread
From: Peter De Schrijver @ 2013-02-08 13:36 UTC (permalink / raw)
  To: pdeschrijver
  Cc: Stephen Warren, Mike Turquette, Prashant Gaikwad, linux-kernel

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 |  836 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/tegra/clk.h     |   48 +++
 2 files changed, 884 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 08f4eb7..914d4f9 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -79,6 +79,48 @@
 #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_ALPHA_SHIFT 18
+#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 PLLCX_MISC_COEF_LOW_RANGE \
+		((0x14 << PLLCX_MISC_KA_SHIFT) | (0x38 << PLLCX_MISC_KB_SHIFT))
+#define PLLCX_MISC_KA_SHIFT 2
+#define PLLCX_MISC_KB_SHIFT 9
+#define PLLCX_MISC_DEFAULT (PLLCX_MISC_COEF_LOW_RANGE | \
+			    (0x19 << PLLCX_MISC_ALPHA_SHIFT) | \
+			    PLLCX_MISC_DIV_LOW_RANGE | \
+			    PLLCX_MISC_RESET)
+#define PLLCX_MISC1_DEFAULT 0x000d2308
+#define PLLCX_MISC2_DEFAULT 0x30211200
+#define PLLCX_MISC3_DEFAULT 0x200
+
+#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 +143,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;
@@ -643,6 +703,520 @@ const struct clk_ops tegra_clk_plle_ops = {
 	.enable = clk_plle_enable,
 };
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+
+static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
+			   unsigned long parent_rate)
+{
+	if (parent_rate > pll_params->cf_max)
+		return 2;
+	else
+		return 1;
+}
+
+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 = _pll_fixed_mdiv(pll->params, parent_rate);
+	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 err = 0;
+
+	err = _get_table_rate(hw, cfg, rate, parent_rate);
+	if (err < 0)
+		err = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate);
+	else if (cfg->m != _pll_fixed_mdiv(pll->params, parent_rate)) {
+			WARN_ON(1);
+			err = -EINVAL;
+			goto out;
+	}
+
+	if (!cfg->p || (cfg->p >  pll->params->max_p))
+		err = -EINVAL;
+
+out:
+	return err;
+}
+
+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 = _pll_fixed_mdiv(pll->params, parent_rate);
+	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 tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
 		void __iomem *pmc, unsigned long fixed_rate,
 		struct tegra_clk_pll_params *pll_params, u32 pll_flags,
@@ -736,3 +1310,265 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
 
 	return clk;
 }
+
+#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)
+{
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	if (!pll_params->pdiv_tohw)
+		return ERR_PTR(-EINVAL);
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllxc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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;
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	/* program minimum rate by default */
+
+	val = pll_readl_base(pll);
+	if (val & PLL_BASE_ENABLE)
+		WARN_ON(val & pll_params->iddq_bit_idx);
+	else {
+		int m;
+
+		m = _pll_fixed_mdiv(pll_params, parent_rate);
+		val = m << PLL_BASE_DIVM_SHIFT;
+		val |= (pll_params->vco_min / parent_rate)
+				<< PLL_BASE_DIVN_SHIFT;
+		pll_writel_base(val, pll);
+	}
+
+	/* disable lock override */
+
+	val = pll_readl_misc(pll);
+	val &= ~BIT(29);
+	pll_writel_misc(val, pll);
+
+	pll_flags |= TEGRA_PLL_LOCK_MISC;
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllre_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 tegra_clk_pll *pll;
+	struct clk *clk;
+
+	if (!pll_params->pdiv_tohw)
+		return ERR_PTR(-EINVAL);
+
+	pll_flags |= TEGRA_PLL_BYPASS;
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllxc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 *parent, *clk;
+	struct pdiv_map *p_tohw = pll_params->pdiv_tohw;
+	struct tegra_clk_pll *pll;
+	struct tegra_clk_pll_freq_table cfg;
+	unsigned long parent_rate;
+
+	if (!p_tohw)
+		return ERR_PTR(-EINVAL);
+
+	parent = __clk_lookup(parent_name);
+	if (IS_ERR(parent)) {
+		WARN(1, "parent clk %s of %s must be registered first\n",
+			name, parent_name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pll_flags |= TEGRA_PLL_BYPASS;
+	pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	parent_rate = __clk_get_rate(parent);
+
+	/*
+	 * Most of PLLC register fields are shadowed, and can not be read
+	 * directly from PLL h/w. Hence, actual PLLC boot state is unknown.
+	 * Initialize PLL to default state: disabled, reset; shadow registers
+	 * loaded with default parameters; dividers are preset for half of
+	 * minimum VCO rate (the latter assured that shadowed divider settings
+	 * are within supported range).
+	 */
+
+	cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
+	cfg.n = cfg.m * pll_params->vco_min / parent_rate;
+
+	while (p_tohw->pdiv) {
+		if (p_tohw->pdiv == 2) {
+			cfg.p = p_tohw->hw_val;
+			break;
+		}
+		p_tohw++;
+	}
+
+	if (!p_tohw->pdiv) {
+		WARN_ON(1);
+		return ERR_PTR(-EINVAL);
+	}
+
+	pll_writel_base(0, pll);
+	_update_pll_mnp(pll, &cfg);
+
+	pll_writel_misc(PLLCX_MISC_DEFAULT, pll);
+	pll_writel(PLLCX_MISC1_DEFAULT, pll_params->ext_misc_reg[0], pll);
+	pll_writel(PLLCX_MISC2_DEFAULT, pll_params->ext_misc_reg[1], pll);
+	pll_writel(PLLCX_MISC3_DEFAULT, pll_params->ext_misc_reg[2], pll);
+
+	_pllcx_update_dynamic_coef(pll, parent_rate, cfg.n);
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_pllc_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+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 *pll;
+	struct clk *clk;
+	u32 val, val_aux;
+
+	pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params, 0,
+			      freq_table, lock);
+	if (IS_ERR(pll))
+		return ERR_CAST(pll);
+
+	/* ensure parent is set to pll_re_vco */
+
+	val = pll_readl_base(pll);
+	val_aux = pll_readl(pll_params->aux_reg, pll);
+
+	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;
+		pll_writel(val, pll_params->aux_reg, pll);
+	}
+
+	clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+				      &tegra_clk_plle_tegra114_ops);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+#endif
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 79b93ee..ea3cce2 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -156,6 +156,13 @@ 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;
+	u32		ext_misc_reg[3];
+	int		stepa_shift;
+	int		stepb_shift;
 	int		lock_delay;
 	int		max_p;
 	struct pdiv_map *pdiv_tohw;
@@ -236,12 +243,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
  *
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2013-03-11  9:25 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-11 11:04 [PATCH v6 00/10] Tegra114 clockframework Peter De Schrijver
2013-02-11 11:04 ` Peter De Schrijver
     [not found] ` <1360580700-10245-1-git-send-email-pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-02-11 11:04   ` [PATCH v6 01/10] clk: tegra: Refactor PLL programming code Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
2013-02-11 11:04   ` [PATCH v6 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
2013-02-11 11:04   ` [PATCH v6 03/10] clk: tegra: Add PLL post divider table Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
2013-02-11 11:04   ` [PATCH v6 04/10] clk: tegra: Add new fields and PLL types for Tegra114 Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
2013-02-11 11:04   ` [PATCH v6 05/10] clk: tegra: Add flags to tegra_clk_periph() Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
2013-02-11 11:04   ` [PATCH v6 06/10] clk: tegra: Workaround for Tegra114 MSENC problem Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
2013-02-11 11:04   ` [PATCH v6 07/10] ARM: tegra: Define Tegra114 CAR binding Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
2013-02-11 11:04   ` [PATCH v6 08/10] ARM: dt: Add references to tegra_car clocks Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
     [not found]     ` <1360580700-10245-9-git-send-email-pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-02-12 17:24       ` Stephen Warren
2013-02-12 17:24         ` Stephen Warren
     [not found]         ` <511A7AB5.4040607-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-02-13 11:38           ` Peter De Schrijver
2013-02-13 11:38             ` Peter De Schrijver
     [not found]             ` <20130213113807.GE3073-Rysk9IDjsxmJz7etNGeUX8VPkgjIgRvpAL8bYrjMMd8@public.gmane.org>
2013-02-13 16:48               ` Stephen Warren
2013-02-13 16:48                 ` Stephen Warren
     [not found]                 ` <511BC3C3.6070402-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-02-14 10:01                   ` Peter De Schrijver
2013-02-14 10:01                     ` Peter De Schrijver
     [not found]                     ` <20130214100112.GH3073-Rysk9IDjsxmJz7etNGeUX8VPkgjIgRvpAL8bYrjMMd8@public.gmane.org>
2013-02-14 17:30                       ` Stephen Warren
2013-02-14 17:30                         ` Stephen Warren
     [not found]                         ` <511D1F3F.1020309-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2013-02-15 12:22                           ` Peter De Schrijver
2013-02-15 12:22                             ` Peter De Schrijver
2013-02-11 11:04   ` [PATCH v6 09/10] clk: tegra: Implement clocks for Tegra114 Peter De Schrijver
2013-02-11 11:04     ` Peter De Schrijver
     [not found]     ` <1360580700-10245-10-git-send-email-pdeschrijver-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-02-15  5:39       ` Hiroshi Doyu
2013-02-15  5:39         ` Hiroshi Doyu
2013-02-15  6:18       ` Hiroshi Doyu
2013-02-15  6:18         ` Hiroshi Doyu
     [not found]         ` <20130215.081805.2193798170330624846.hdoyu-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2013-02-15  9:13           ` Peter De Schrijver
2013-02-15  9:13             ` Peter De Schrijver
2013-03-06 23:51       ` Andrew Chew
2013-03-06 23:51         ` Andrew Chew
     [not found]         ` <643E69AA4436674C8F39DCC2C05F7638629CA50CB4-lR+7xdUAJVNDw2glCA4ptUEOCMrvLtNR@public.gmane.org>
2013-03-11  9:25           ` Peter De Schrijver
2013-03-11  9:25             ` Peter De Schrijver
2013-02-11 11:05   ` [PATCH v6 10/10] clk: tegra: devicetree match for nvidia,tegra114-car Peter De Schrijver
2013-02-11 11:05     ` [PATCH v6 10/10] clk: tegra: devicetree match for nvidia, tegra114-car Peter De Schrijver
     [not found] <1360330602-30472-1-git-send-email-pdeschrijver@nvidia.com>
2013-02-08 13:36 ` [PATCH v6 04/10] clk: tegra: Add new fields and PLL types for Tegra114 Peter De Schrijver

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.