* [PATCH v5 00/10] Tegra114 clockframework
@ 2013-02-01 10:18 Peter De Schrijver
2013-02-01 10:18 ` [PATCH v5 01/10] clk: tegra: Refactor PLL programming code Peter De Schrijver
` (9 more replies)
0 siblings, 10 replies; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, linux-arm-kernel
This is the fifth 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 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.
TODO:
* Remove clk_register_clkdev() where possible
* PLL clock init functions are incomplete and/or need refactoring
* Superclocks are missing
* The audio clocks are almost the same then Tegra30. Refactor the code to
avoid duplication.
* Should blink and blink_override be 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 | 311 +++
arch/arm/boot/dts/tegra114.dtsi | 7 +-
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 | 940 +++++++++-
drivers/clk/tegra/clk-tegra114.c | 2002 ++++++++++++++++++++
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 | 85 +-
11 files changed, 3481 insertions(+), 282 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] 34+ messages in thread
* [PATCH v5 01/10] clk: tegra: Refactor PLL programming code
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 6:06 ` Prashant Gaikwad
2013-02-04 21:57 ` Stephen Warren
2013-02-01 10:18 ` [PATCH v5 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag Peter De Schrijver
` (8 subsequent siblings)
9 siblings, 2 replies; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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()
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
drivers/clk/tegra/clk-pll.c | 178 +++++++++++++++++------------
drivers/clk/tegra/clk-tegra20.c | 144 ++++++++++++------------
drivers/clk/tegra/clk-tegra30.c | 234 +++++++++++++++++++-------------------
3 files changed, 294 insertions(+), 262 deletions(-)
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 165f247..912c977 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -113,20 +113,23 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
pll_writel_misc(val, pll);
}
-static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
- void __iomem *lock_addr, u32 lock_bit_idx)
+static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
{
int i;
- u32 val;
+ u32 val, lock_bit;
+ void __iomem *lock_addr;
if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
udelay(pll->params->lock_delay);
return 0;
}
+ lock_addr = pll->clk_base + pll->params->base_reg;
+ lock_bit = BIT(pll->params->lock_bit_idx);
+
for (i = 0; i < pll->params->lock_delay; i++) {
val = readl_relaxed(lock_addr);
- if (val & BIT(lock_bit_idx)) {
+ if (val & lock_bit) {
udelay(PLL_POST_LOCK_DELAY);
return 0;
}
@@ -155,7 +158,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw)
return val & PLL_BASE_ENABLE ? 1 : 0;
}
-static int _clk_pll_enable(struct clk_hw *hw)
+static void _clk_pll_enable(struct clk_hw *hw)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
u32 val;
@@ -172,11 +175,6 @@ static int _clk_pll_enable(struct clk_hw *hw)
val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
}
-
- clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->base_reg,
- pll->params->lock_bit_idx);
-
- return 0;
}
static void _clk_pll_disable(struct clk_hw *hw)
@@ -204,7 +202,9 @@ static int clk_pll_enable(struct clk_hw *hw)
if (pll->lock)
spin_lock_irqsave(pll->lock, flags);
- ret = _clk_pll_enable(hw);
+ _clk_pll_enable(hw);
+
+ ret = clk_pll_wait_for_lock(pll);
if (pll->lock)
spin_unlock_irqrestore(pll->lock, flags);
@@ -241,8 +241,6 @@ static int _get_table_rate(struct clk_hw *hw,
if (sel->input_rate == 0)
return -EINVAL;
- BUG_ON(sel->p < 1);
-
cfg->input_rate = sel->input_rate;
cfg->output_rate = sel->output_rate;
cfg->m = sel->m;
@@ -290,88 +288,109 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
cfg->output_rate <<= 1)
p_div++;
- cfg->p = 1 << p_div;
+ cfg->p = p_div;
cfg->m = parent_rate / cfreq;
cfg->n = cfg->output_rate / cfreq;
cfg->cpcon = OUT_OF_TABLE_CPCON;
if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
- cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) {
+ (1 << p_div) > divp_max(pll)
+ || cfg->output_rate > pll->params->vco_max) {
pr_err("%s: Failed to set %s rate %lu\n",
__func__, __clk_get_name(hw->clk), rate);
return -EINVAL;
}
+ if (pll->flags & TEGRA_PLLU)
+ cfg->p ^= 1;
+
return 0;
}
-static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
- unsigned long rate)
+static void _update_pll_mnp(struct tegra_clk_pll *pll,
+ struct tegra_clk_pll_freq_table *cfg)
{
- struct tegra_clk_pll *pll = to_clk_pll(hw);
- unsigned long flags = 0;
- u32 divp, val, old_base;
- int state;
-
- divp = __ffs(cfg->p);
-
- if (pll->flags & TEGRA_PLLU)
- divp ^= 1;
+ u32 val;
- if (pll->lock)
- spin_lock_irqsave(pll->lock, flags);
+ val = pll_readl_base(pll);
- old_base = val = pll_readl_base(pll);
val &= ~((divm_mask(pll) << pll->divm_shift) |
(divn_mask(pll) << pll->divn_shift) |
(divp_mask(pll) << pll->divp_shift));
val |= ((cfg->m << pll->divm_shift) |
(cfg->n << pll->divn_shift) |
- (divp << pll->divp_shift));
- if (val == old_base) {
- if (pll->lock)
- spin_unlock_irqrestore(pll->lock, flags);
- return 0;
+ (cfg->p << pll->divp_shift));
+
+ pll_writel_base(val, pll);
+}
+
+static void _get_pll_mnp(struct tegra_clk_pll *pll,
+ struct tegra_clk_pll_freq_table *cfg)
+{
+ u32 val;
+
+ val = pll_readl_base(pll);
+
+ cfg->m = (val >> pll->divm_shift) & (divm_mask(pll));
+ cfg->n = (val >> pll->divn_shift) & (divn_mask(pll));
+ cfg->p = (val >> pll->divp_shift) & (divp_mask(pll));
+}
+
+static void _update_pll_cpcon(struct tegra_clk_pll *pll,
+ struct tegra_clk_pll_freq_table *cfg,
+ unsigned long rate)
+{
+ u32 val;
+
+ val = pll_readl_misc(pll);
+
+ val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
+ val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
+
+ if (pll->flags & TEGRA_PLL_SET_LFCON) {
+ val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
+ if (cfg->n >= PLLDU_LFCON_SET_DIVN)
+ val |= 1 << PLL_MISC_LFCON_SHIFT;
+ } else if (pll->flags & TEGRA_PLL_SET_DCCON) {
+ val &= ~(1 << PLL_MISC_DCCON_SHIFT);
+ if (rate >= (pll->params->vco_max >> 1))
+ val |= 1 << PLL_MISC_DCCON_SHIFT;
}
+ pll_writel_misc(val, pll);
+}
+
+static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
+ unsigned long rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ int state, ret = 0;
+
state = clk_pll_is_enabled(hw);
- if (state) {
+ if (state)
_clk_pll_disable(hw);
- val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
- }
- pll_writel_base(val, pll);
- if (pll->flags & TEGRA_PLL_HAS_CPCON) {
- val = pll_readl_misc(pll);
- val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
- val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
- if (pll->flags & TEGRA_PLL_SET_LFCON) {
- val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
- if (cfg->n >= PLLDU_LFCON_SET_DIVN)
- val |= 0x1 << PLL_MISC_LFCON_SHIFT;
- } else if (pll->flags & TEGRA_PLL_SET_DCCON) {
- val &= ~(0x1 << PLL_MISC_DCCON_SHIFT);
- if (rate >= (pll->params->vco_max >> 1))
- val |= 0x1 << PLL_MISC_DCCON_SHIFT;
- }
- pll_writel_misc(val, pll);
- }
+ _update_pll_mnp(pll, cfg);
- if (pll->lock)
- spin_unlock_irqrestore(pll->lock, flags);
+ if (pll->flags & TEGRA_PLL_HAS_CPCON)
+ _update_pll_cpcon(pll, cfg, rate);
- if (state)
- clk_pll_enable(hw);
+ if (state) {
+ _clk_pll_enable(hw);
+ ret = clk_pll_wait_for_lock(pll);
+ }
- return 0;
+ return ret;
}
static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
- struct tegra_clk_pll_freq_table cfg;
+ struct tegra_clk_pll_freq_table cfg, old_cfg;
+ unsigned long flags = 0;
+ int ret = 0;
if (pll->flags & TEGRA_PLL_FIXED) {
if (rate != pll->fixed_rate) {
@@ -387,7 +406,18 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
_calc_rate(hw, &cfg, rate, parent_rate))
return -EINVAL;
- return _program_pll(hw, &cfg, rate);
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ _get_pll_mnp(pll, &old_cfg);
+
+ if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p)
+ ret = _program_pll(hw, &cfg, rate);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
}
static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -409,7 +439,7 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL;
output_rate *= cfg.n;
- do_div(output_rate, cfg.m * cfg.p);
+ do_div(output_rate, cfg.m * (1 << cfg.p));
return output_rate;
}
@@ -418,10 +448,12 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
- u32 val = pll_readl_base(pll);
- u32 divn = 0, divm = 0, divp = 0;
+ struct tegra_clk_pll_freq_table cfg;
+ u32 val;
u64 rate = parent_rate;
+ val = pll_readl_base(pll);
+
if (val & PLL_BASE_BYPASS)
return parent_rate;
@@ -435,16 +467,16 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
return pll->fixed_rate;
}
- divp = (val >> pll->divp_shift) & (divp_mask(pll));
+ _get_pll_mnp(pll, &cfg);
+
if (pll->flags & TEGRA_PLLU)
- divp ^= 1;
+ cfg.p ^= 1;
- divn = (val >> pll->divn_shift) & (divn_mask(pll));
- divm = (val >> pll->divm_shift) & (divm_mask(pll));
- divm *= (1 << divp);
+ cfg.m *= 1 << cfg.p;
+
+ rate *= cfg.n;
+ do_div(rate, cfg.m);
- rate *= divn;
- do_div(rate, divm);
return rate;
}
@@ -538,8 +570,8 @@ static int clk_plle_enable(struct clk_hw *hw)
val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
pll_writel_base(val, pll);
- clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg,
- pll->params->lock_bit_idx);
+ clk_pll_wait_for_lock(pll);
+
return 0;
}
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 5d41569..30bd3fd 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -247,125 +247,125 @@ static struct clk *clks[clk_max];
static struct clk_onecell_data clk_data;
static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
- { 12000000, 600000000, 600, 12, 1, 8 },
- { 13000000, 600000000, 600, 13, 1, 8 },
- { 19200000, 600000000, 500, 16, 1, 6 },
- { 26000000, 600000000, 600, 26, 1, 8 },
+ { 12000000, 600000000, 600, 12, 0, 8 },
+ { 13000000, 600000000, 600, 13, 0, 8 },
+ { 19200000, 600000000, 500, 16, 0, 6 },
+ { 26000000, 600000000, 600, 26, 0, 8 },
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
- { 12000000, 666000000, 666, 12, 1, 8},
- { 13000000, 666000000, 666, 13, 1, 8},
- { 19200000, 666000000, 555, 16, 1, 8},
- { 26000000, 666000000, 666, 26, 1, 8},
- { 12000000, 600000000, 600, 12, 1, 8},
- { 13000000, 600000000, 600, 13, 1, 8},
- { 19200000, 600000000, 375, 12, 1, 6},
- { 26000000, 600000000, 600, 26, 1, 8},
+ { 12000000, 666000000, 666, 12, 0, 8},
+ { 13000000, 666000000, 666, 13, 0, 8},
+ { 19200000, 666000000, 555, 16, 0, 8},
+ { 26000000, 666000000, 666, 26, 0, 8},
+ { 12000000, 600000000, 600, 12, 0, 8},
+ { 13000000, 600000000, 600, 13, 0, 8},
+ { 19200000, 600000000, 375, 12, 0, 6},
+ { 26000000, 600000000, 600, 26, 0, 8},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
- { 12000000, 216000000, 432, 12, 2, 8},
- { 13000000, 216000000, 432, 13, 2, 8},
- { 19200000, 216000000, 90, 4, 2, 1},
- { 26000000, 216000000, 432, 26, 2, 8},
- { 12000000, 432000000, 432, 12, 1, 8},
- { 13000000, 432000000, 432, 13, 1, 8},
- { 19200000, 432000000, 90, 4, 1, 1},
- { 26000000, 432000000, 432, 26, 1, 8},
+ { 12000000, 216000000, 432, 12, 1, 8},
+ { 13000000, 216000000, 432, 13, 1, 8},
+ { 19200000, 216000000, 90, 4, 1, 1},
+ { 26000000, 216000000, 432, 26, 1, 8},
+ { 12000000, 432000000, 432, 12, 0, 8},
+ { 13000000, 432000000, 432, 13, 0, 8},
+ { 19200000, 432000000, 90, 4, 0, 1},
+ { 26000000, 432000000, 432, 26, 0, 8},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
- { 28800000, 56448000, 49, 25, 1, 1},
- { 28800000, 73728000, 64, 25, 1, 1},
- { 28800000, 24000000, 5, 6, 1, 1},
+ { 28800000, 56448000, 49, 25, 0, 1},
+ { 28800000, 73728000, 64, 25, 0, 1},
+ { 28800000, 24000000, 5, 6, 0, 1},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
- { 12000000, 216000000, 216, 12, 1, 4},
- { 13000000, 216000000, 216, 13, 1, 4},
- { 19200000, 216000000, 135, 12, 1, 3},
- { 26000000, 216000000, 216, 26, 1, 4},
+ { 12000000, 216000000, 216, 12, 0, 4},
+ { 13000000, 216000000, 216, 13, 0, 4},
+ { 19200000, 216000000, 135, 12, 0, 3},
+ { 26000000, 216000000, 216, 26, 0, 4},
- { 12000000, 594000000, 594, 12, 1, 8},
- { 13000000, 594000000, 594, 13, 1, 8},
- { 19200000, 594000000, 495, 16, 1, 8},
- { 26000000, 594000000, 594, 26, 1, 8},
+ { 12000000, 594000000, 594, 12, 0, 8},
+ { 13000000, 594000000, 594, 13, 0, 8},
+ { 19200000, 594000000, 495, 16, 0, 8},
+ { 26000000, 594000000, 594, 26, 0, 8},
- { 12000000, 1000000000, 1000, 12, 1, 12},
- { 13000000, 1000000000, 1000, 13, 1, 12},
- { 19200000, 1000000000, 625, 12, 1, 8},
- { 26000000, 1000000000, 1000, 26, 1, 12},
+ { 12000000, 1000000000, 1000, 12, 0, 12},
+ { 13000000, 1000000000, 1000, 13, 0, 12},
+ { 19200000, 1000000000, 625, 12, 0, 8},
+ { 26000000, 1000000000, 1000, 26, 0, 12},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
- { 12000000, 480000000, 960, 12, 2, 0},
- { 13000000, 480000000, 960, 13, 2, 0},
- { 19200000, 480000000, 200, 4, 2, 0},
- { 26000000, 480000000, 960, 26, 2, 0},
+ { 12000000, 480000000, 960, 12, 0, 0},
+ { 13000000, 480000000, 960, 13, 0, 0},
+ { 19200000, 480000000, 200, 4, 0, 0},
+ { 26000000, 480000000, 960, 26, 0, 0},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
/* 1 GHz */
- { 12000000, 1000000000, 1000, 12, 1, 12},
- { 13000000, 1000000000, 1000, 13, 1, 12},
- { 19200000, 1000000000, 625, 12, 1, 8},
- { 26000000, 1000000000, 1000, 26, 1, 12},
+ { 12000000, 1000000000, 1000, 12, 0, 12},
+ { 13000000, 1000000000, 1000, 13, 0, 12},
+ { 19200000, 1000000000, 625, 12, 0, 8},
+ { 26000000, 1000000000, 1000, 26, 0, 12},
/* 912 MHz */
- { 12000000, 912000000, 912, 12, 1, 12},
- { 13000000, 912000000, 912, 13, 1, 12},
- { 19200000, 912000000, 760, 16, 1, 8},
- { 26000000, 912000000, 912, 26, 1, 12},
+ { 12000000, 912000000, 912, 12, 0, 12},
+ { 13000000, 912000000, 912, 13, 0, 12},
+ { 19200000, 912000000, 760, 16, 0, 8},
+ { 26000000, 912000000, 912, 26, 0, 12},
/* 816 MHz */
- { 12000000, 816000000, 816, 12, 1, 12},
- { 13000000, 816000000, 816, 13, 1, 12},
- { 19200000, 816000000, 680, 16, 1, 8},
- { 26000000, 816000000, 816, 26, 1, 12},
+ { 12000000, 816000000, 816, 12, 0, 12},
+ { 13000000, 816000000, 816, 13, 0, 12},
+ { 19200000, 816000000, 680, 16, 0, 8},
+ { 26000000, 816000000, 816, 26, 0, 12},
/* 760 MHz */
- { 12000000, 760000000, 760, 12, 1, 12},
- { 13000000, 760000000, 760, 13, 1, 12},
- { 19200000, 760000000, 950, 24, 1, 8},
- { 26000000, 760000000, 760, 26, 1, 12},
+ { 12000000, 760000000, 760, 12, 0, 12},
+ { 13000000, 760000000, 760, 13, 0, 12},
+ { 19200000, 760000000, 950, 24, 0, 8},
+ { 26000000, 760000000, 760, 26, 0, 12},
/* 750 MHz */
- { 12000000, 750000000, 750, 12, 1, 12},
- { 13000000, 750000000, 750, 13, 1, 12},
- { 19200000, 750000000, 625, 16, 1, 8},
- { 26000000, 750000000, 750, 26, 1, 12},
+ { 12000000, 750000000, 750, 12, 0, 12},
+ { 13000000, 750000000, 750, 13, 0, 12},
+ { 19200000, 750000000, 625, 16, 0, 8},
+ { 26000000, 750000000, 750, 26, 0, 12},
/* 608 MHz */
- { 12000000, 608000000, 608, 12, 1, 12},
- { 13000000, 608000000, 608, 13, 1, 12},
- { 19200000, 608000000, 380, 12, 1, 8},
- { 26000000, 608000000, 608, 26, 1, 12},
+ { 12000000, 608000000, 608, 12, 0, 12},
+ { 13000000, 608000000, 608, 13, 0, 12},
+ { 19200000, 608000000, 380, 12, 0, 8},
+ { 26000000, 608000000, 608, 26, 0, 12},
/* 456 MHz */
- { 12000000, 456000000, 456, 12, 1, 12},
- { 13000000, 456000000, 456, 13, 1, 12},
- { 19200000, 456000000, 380, 16, 1, 8},
- { 26000000, 456000000, 456, 26, 1, 12},
+ { 12000000, 456000000, 456, 12, 0, 12},
+ { 13000000, 456000000, 456, 13, 0, 12},
+ { 19200000, 456000000, 380, 16, 0, 8},
+ { 26000000, 456000000, 456, 26, 0, 12},
/* 312 MHz */
- { 12000000, 312000000, 312, 12, 1, 12},
- { 13000000, 312000000, 312, 13, 1, 12},
- { 19200000, 312000000, 260, 16, 1, 8},
- { 26000000, 312000000, 312, 26, 1, 12},
+ { 12000000, 312000000, 312, 12, 0, 12},
+ { 13000000, 312000000, 312, 13, 0, 12},
+ { 19200000, 312000000, 260, 16, 0, 8},
+ { 26000000, 312000000, 312, 26, 0, 12},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
- { 12000000, 100000000, 200, 24, 1, 0 },
+ { 12000000, 100000000, 200, 24, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
};
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index a163812..28a2997 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -373,164 +373,164 @@ static const struct utmi_clk_param utmi_parameters[] = {
};
static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
- { 12000000, 1040000000, 520, 6, 1, 8},
- { 13000000, 1040000000, 480, 6, 1, 8},
- { 16800000, 1040000000, 495, 8, 1, 8}, /* actual: 1039.5 MHz */
- { 19200000, 1040000000, 325, 6, 1, 6},
- { 26000000, 1040000000, 520, 13, 1, 8},
-
- { 12000000, 832000000, 416, 6, 1, 8},
- { 13000000, 832000000, 832, 13, 1, 8},
- { 16800000, 832000000, 396, 8, 1, 8}, /* actual: 831.6 MHz */
- { 19200000, 832000000, 260, 6, 1, 8},
- { 26000000, 832000000, 416, 13, 1, 8},
-
- { 12000000, 624000000, 624, 12, 1, 8},
- { 13000000, 624000000, 624, 13, 1, 8},
- { 16800000, 600000000, 520, 14, 1, 8},
- { 19200000, 624000000, 520, 16, 1, 8},
- { 26000000, 624000000, 624, 26, 1, 8},
-
- { 12000000, 600000000, 600, 12, 1, 8},
- { 13000000, 600000000, 600, 13, 1, 8},
- { 16800000, 600000000, 500, 14, 1, 8},
- { 19200000, 600000000, 375, 12, 1, 6},
- { 26000000, 600000000, 600, 26, 1, 8},
-
- { 12000000, 520000000, 520, 12, 1, 8},
- { 13000000, 520000000, 520, 13, 1, 8},
- { 16800000, 520000000, 495, 16, 1, 8}, /* actual: 519.75 MHz */
- { 19200000, 520000000, 325, 12, 1, 6},
- { 26000000, 520000000, 520, 26, 1, 8},
-
- { 12000000, 416000000, 416, 12, 1, 8},
- { 13000000, 416000000, 416, 13, 1, 8},
- { 16800000, 416000000, 396, 16, 1, 8}, /* actual: 415.8 MHz */
- { 19200000, 416000000, 260, 12, 1, 6},
- { 26000000, 416000000, 416, 26, 1, 8},
+ { 12000000, 1040000000, 520, 6, 0, 8},
+ { 13000000, 1040000000, 480, 6, 0, 8},
+ { 16800000, 1040000000, 495, 8, 0, 8}, /* actual: 1039.5 MHz */
+ { 19200000, 1040000000, 325, 6, 0, 6},
+ { 26000000, 1040000000, 520, 13, 0, 8},
+
+ { 12000000, 832000000, 416, 6, 0, 8},
+ { 13000000, 832000000, 832, 13, 0, 8},
+ { 16800000, 832000000, 396, 8, 0, 8}, /* actual: 831.6 MHz */
+ { 19200000, 832000000, 260, 6, 0, 8},
+ { 26000000, 832000000, 416, 13, 0, 8},
+
+ { 12000000, 624000000, 624, 12, 0, 8},
+ { 13000000, 624000000, 624, 13, 0, 8},
+ { 16800000, 600000000, 520, 14, 0, 8},
+ { 19200000, 624000000, 520, 16, 0, 8},
+ { 26000000, 624000000, 624, 26, 0, 8},
+
+ { 12000000, 600000000, 600, 12, 0, 8},
+ { 13000000, 600000000, 600, 13, 0, 8},
+ { 16800000, 600000000, 500, 14, 0, 8},
+ { 19200000, 600000000, 375, 12, 0, 6},
+ { 26000000, 600000000, 600, 26, 0, 8},
+
+ { 12000000, 520000000, 520, 12, 0, 8},
+ { 13000000, 520000000, 520, 13, 0, 8},
+ { 16800000, 520000000, 495, 16, 0, 8}, /* actual: 519.75 MHz */
+ { 19200000, 520000000, 325, 12, 0, 6},
+ { 26000000, 520000000, 520, 26, 0, 8},
+
+ { 12000000, 416000000, 416, 12, 0, 8},
+ { 13000000, 416000000, 416, 13, 0, 8},
+ { 16800000, 416000000, 396, 16, 0, 8}, /* actual: 415.8 MHz */
+ { 19200000, 416000000, 260, 12, 0, 6},
+ { 26000000, 416000000, 416, 26, 0, 8},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
- { 12000000, 666000000, 666, 12, 1, 8},
- { 13000000, 666000000, 666, 13, 1, 8},
- { 16800000, 666000000, 555, 14, 1, 8},
- { 19200000, 666000000, 555, 16, 1, 8},
- { 26000000, 666000000, 666, 26, 1, 8},
- { 12000000, 600000000, 600, 12, 1, 8},
- { 13000000, 600000000, 600, 13, 1, 8},
- { 16800000, 600000000, 500, 14, 1, 8},
- { 19200000, 600000000, 375, 12, 1, 6},
- { 26000000, 600000000, 600, 26, 1, 8},
+ { 12000000, 666000000, 666, 12, 0, 8},
+ { 13000000, 666000000, 666, 13, 0, 8},
+ { 16800000, 666000000, 555, 14, 0, 8},
+ { 19200000, 666000000, 555, 16, 0, 8},
+ { 26000000, 666000000, 666, 26, 0, 8},
+ { 12000000, 600000000, 600, 12, 0, 8},
+ { 13000000, 600000000, 600, 13, 0, 8},
+ { 16800000, 600000000, 500, 14, 0, 8},
+ { 19200000, 600000000, 375, 12, 0, 6},
+ { 26000000, 600000000, 600, 26, 0, 8},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
- { 12000000, 216000000, 432, 12, 2, 8},
- { 13000000, 216000000, 432, 13, 2, 8},
- { 16800000, 216000000, 360, 14, 2, 8},
- { 19200000, 216000000, 360, 16, 2, 8},
- { 26000000, 216000000, 432, 26, 2, 8},
+ { 12000000, 216000000, 432, 12, 1, 8},
+ { 13000000, 216000000, 432, 13, 1, 8},
+ { 16800000, 216000000, 360, 14, 1, 8},
+ { 19200000, 216000000, 360, 16, 1, 8},
+ { 26000000, 216000000, 432, 26, 1, 8},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
- { 9600000, 564480000, 294, 5, 1, 4},
- { 9600000, 552960000, 288, 5, 1, 4},
- { 9600000, 24000000, 5, 2, 1, 1},
+ { 9600000, 564480000, 294, 5, 0, 4},
+ { 9600000, 552960000, 288, 5, 0, 4},
+ { 9600000, 24000000, 5, 2, 0, 1},
- { 28800000, 56448000, 49, 25, 1, 1},
- { 28800000, 73728000, 64, 25, 1, 1},
- { 28800000, 24000000, 5, 6, 1, 1},
+ { 28800000, 56448000, 49, 25, 0, 1},
+ { 28800000, 73728000, 64, 25, 0, 1},
+ { 28800000, 24000000, 5, 6, 0, 1},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
- { 12000000, 216000000, 216, 12, 1, 4},
- { 13000000, 216000000, 216, 13, 1, 4},
- { 16800000, 216000000, 180, 14, 1, 4},
- { 19200000, 216000000, 180, 16, 1, 4},
- { 26000000, 216000000, 216, 26, 1, 4},
-
- { 12000000, 594000000, 594, 12, 1, 8},
- { 13000000, 594000000, 594, 13, 1, 8},
- { 16800000, 594000000, 495, 14, 1, 8},
- { 19200000, 594000000, 495, 16, 1, 8},
- { 26000000, 594000000, 594, 26, 1, 8},
-
- { 12000000, 1000000000, 1000, 12, 1, 12},
- { 13000000, 1000000000, 1000, 13, 1, 12},
- { 19200000, 1000000000, 625, 12, 1, 8},
- { 26000000, 1000000000, 1000, 26, 1, 12},
+ { 12000000, 216000000, 216, 12, 0, 4},
+ { 13000000, 216000000, 216, 13, 0, 4},
+ { 16800000, 216000000, 180, 14, 0, 4},
+ { 19200000, 216000000, 180, 16, 0, 4},
+ { 26000000, 216000000, 216, 26, 0, 4},
+
+ { 12000000, 594000000, 594, 12, 0, 8},
+ { 13000000, 594000000, 594, 13, 0, 8},
+ { 16800000, 594000000, 495, 14, 0, 8},
+ { 19200000, 594000000, 495, 16, 0, 8},
+ { 26000000, 594000000, 594, 26, 0, 8},
+
+ { 12000000, 1000000000, 1000, 12, 0, 12},
+ { 13000000, 1000000000, 1000, 13, 0, 12},
+ { 19200000, 1000000000, 625, 12, 0, 8},
+ { 26000000, 1000000000, 1000, 26, 0, 12},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
- { 12000000, 480000000, 960, 12, 2, 12},
- { 13000000, 480000000, 960, 13, 2, 12},
- { 16800000, 480000000, 400, 7, 2, 5},
- { 19200000, 480000000, 200, 4, 2, 3},
- { 26000000, 480000000, 960, 26, 2, 12},
+ { 12000000, 480000000, 960, 12, 0, 12},
+ { 13000000, 480000000, 960, 13, 0, 12},
+ { 16800000, 480000000, 400, 7, 0, 5},
+ { 19200000, 480000000, 200, 4, 0, 3},
+ { 26000000, 480000000, 960, 26, 0, 12},
{ 0, 0, 0, 0, 0, 0 },
};
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
/* 1.7 GHz */
- { 12000000, 1700000000, 850, 6, 1, 8},
- { 13000000, 1700000000, 915, 7, 1, 8}, /* actual: 1699.2 MHz */
- { 16800000, 1700000000, 708, 7, 1, 8}, /* actual: 1699.2 MHz */
- { 19200000, 1700000000, 885, 10, 1, 8}, /* actual: 1699.2 MHz */
- { 26000000, 1700000000, 850, 13, 1, 8},
+ { 12000000, 1700000000, 850, 6, 0, 8},
+ { 13000000, 1700000000, 915, 7, 0, 8}, /* actual: 1699.2 MHz */
+ { 16800000, 1700000000, 708, 7, 0, 8}, /* actual: 1699.2 MHz */
+ { 19200000, 1700000000, 885, 10, 0, 8}, /* actual: 1699.2 MHz */
+ { 26000000, 1700000000, 850, 13, 0, 8},
/* 1.6 GHz */
- { 12000000, 1600000000, 800, 6, 1, 8},
- { 13000000, 1600000000, 738, 6, 1, 8}, /* actual: 1599.0 MHz */
- { 16800000, 1600000000, 857, 9, 1, 8}, /* actual: 1599.7 MHz */
- { 19200000, 1600000000, 500, 6, 1, 8},
- { 26000000, 1600000000, 800, 13, 1, 8},
+ { 12000000, 1600000000, 800, 6, 0, 8},
+ { 13000000, 1600000000, 738, 6, 0, 8}, /* actual: 1599.0 MHz */
+ { 16800000, 1600000000, 857, 9, 0, 8}, /* actual: 1599.7 MHz */
+ { 19200000, 1600000000, 500, 6, 0, 8},
+ { 26000000, 1600000000, 800, 13, 0, 8},
/* 1.5 GHz */
- { 12000000, 1500000000, 750, 6, 1, 8},
- { 13000000, 1500000000, 923, 8, 1, 8}, /* actual: 1499.8 MHz */
- { 16800000, 1500000000, 625, 7, 1, 8},
- { 19200000, 1500000000, 625, 8, 1, 8},
- { 26000000, 1500000000, 750, 13, 1, 8},
+ { 12000000, 1500000000, 750, 6, 0, 8},
+ { 13000000, 1500000000, 923, 8, 0, 8}, /* actual: 1499.8 MHz */
+ { 16800000, 1500000000, 625, 7, 0, 8},
+ { 19200000, 1500000000, 625, 8, 0, 8},
+ { 26000000, 1500000000, 750, 13, 0, 8},
/* 1.4 GHz */
- { 12000000, 1400000000, 700, 6, 1, 8},
- { 13000000, 1400000000, 969, 9, 1, 8}, /* actual: 1399.7 MHz */
- { 16800000, 1400000000, 1000, 12, 1, 8},
- { 19200000, 1400000000, 875, 12, 1, 8},
- { 26000000, 1400000000, 700, 13, 1, 8},
+ { 12000000, 1400000000, 700, 6, 0, 8},
+ { 13000000, 1400000000, 969, 9, 0, 8}, /* actual: 1399.7 MHz */
+ { 16800000, 1400000000, 1000, 12, 0, 8},
+ { 19200000, 1400000000, 875, 12, 0, 8},
+ { 26000000, 1400000000, 700, 13, 0, 8},
/* 1.3 GHz */
- { 12000000, 1300000000, 975, 9, 1, 8},
- { 13000000, 1300000000, 1000, 10, 1, 8},
- { 16800000, 1300000000, 928, 12, 1, 8}, /* actual: 1299.2 MHz */
- { 19200000, 1300000000, 812, 12, 1, 8}, /* actual: 1299.2 MHz */
- { 26000000, 1300000000, 650, 13, 1, 8},
+ { 12000000, 1300000000, 975, 9, 0, 8},
+ { 13000000, 1300000000, 1000, 10, 0, 8},
+ { 16800000, 1300000000, 928, 12, 0, 8}, /* actual: 1299.2 MHz */
+ { 19200000, 1300000000, 812, 12, 0, 8}, /* actual: 1299.2 MHz */
+ { 26000000, 1300000000, 650, 13, 0, 8},
/* 1.2 GHz */
- { 12000000, 1200000000, 1000, 10, 1, 8},
- { 13000000, 1200000000, 923, 10, 1, 8}, /* actual: 1199.9 MHz */
- { 16800000, 1200000000, 1000, 14, 1, 8},
- { 19200000, 1200000000, 1000, 16, 1, 8},
- { 26000000, 1200000000, 600, 13, 1, 8},
+ { 12000000, 1200000000, 1000, 10, 0, 8},
+ { 13000000, 1200000000, 923, 10, 0, 8}, /* actual: 1199.9 MHz */
+ { 16800000, 1200000000, 1000, 14, 0, 8},
+ { 19200000, 1200000000, 1000, 16, 0, 8},
+ { 26000000, 1200000000, 600, 13, 0, 8},
/* 1.1 GHz */
- { 12000000, 1100000000, 825, 9, 1, 8},
- { 13000000, 1100000000, 846, 10, 1, 8}, /* actual: 1099.8 MHz */
- { 16800000, 1100000000, 982, 15, 1, 8}, /* actual: 1099.8 MHz */
- { 19200000, 1100000000, 859, 15, 1, 8}, /* actual: 1099.5 MHz */
- { 26000000, 1100000000, 550, 13, 1, 8},
+ { 12000000, 1100000000, 825, 9, 0, 8},
+ { 13000000, 1100000000, 846, 10, 0, 8}, /* actual: 1099.8 MHz */
+ { 16800000, 1100000000, 982, 15, 0, 8}, /* actual: 1099.8 MHz */
+ { 19200000, 1100000000, 859, 15, 0, 8}, /* actual: 1099.5 MHz */
+ { 26000000, 1100000000, 550, 13, 0, 8},
/* 1 GHz */
- { 12000000, 1000000000, 1000, 12, 1, 8},
- { 13000000, 1000000000, 1000, 13, 1, 8},
- { 16800000, 1000000000, 833, 14, 1, 8}, /* actual: 999.6 MHz */
- { 19200000, 1000000000, 625, 12, 1, 8},
- { 26000000, 1000000000, 1000, 26, 1, 8},
+ { 12000000, 1000000000, 1000, 12, 0, 8},
+ { 13000000, 1000000000, 1000, 13, 0, 8},
+ { 16800000, 1000000000, 833, 14, 0, 8}, /* actual: 999.6 MHz */
+ { 19200000, 1000000000, 625, 12, 0, 8},
+ { 26000000, 1000000000, 1000, 26, 0, 8},
{ 0, 0, 0, 0, 0, 0 },
};
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
2013-02-01 10:18 ` [PATCH v5 01/10] clk: tegra: Refactor PLL programming code Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 6:13 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 03/10] clk: tegra: Add PLL post divider table Peter De Schrijver
` (7 subsequent siblings)
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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 | 15 ++++++++++-----
drivers/clk/tegra/clk.h | 8 +++++---
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 912c977..3c3a25e 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -166,7 +166,8 @@ static void _clk_pll_enable(struct clk_hw *hw)
clk_pll_enable_lock(pll);
val = pll_readl_base(pll);
- val &= ~PLL_BASE_BYPASS;
+ if (pll->flags & TEGRA_PLL_BYPASS)
+ val &= ~PLL_BASE_BYPASS;
val |= PLL_BASE_ENABLE;
pll_writel_base(val, pll);
@@ -183,7 +184,9 @@ static void _clk_pll_disable(struct clk_hw *hw)
u32 val;
val = pll_readl_base(pll);
- val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+ if (pll->flags & TEGRA_PLL_BYPASS)
+ val &= ~PLL_BASE_BYPASS;
+ val &= ~PLL_BASE_ENABLE;
pll_writel_base(val, pll);
if (pll->flags & TEGRA_PLLM) {
@@ -454,7 +457,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
val = pll_readl_base(pll);
- if (val & PLL_BASE_BYPASS)
+ if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
return parent_rate;
if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
@@ -660,9 +663,10 @@ static struct clk *_tegra_clk_register_pll(const char *name,
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
- struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
{
+ pll_flags |= TEGRA_PLL_BYPASS;
return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
flags, fixed_rate, pll_params, pll_flags, freq_table,
lock, &tegra_clk_pll_ops);
@@ -671,9 +675,10 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
- struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
{
+ pll_flags |= TEGRA_PLL_BYPASS;
return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
flags, fixed_rate, pll_params, pll_flags, freq_table,
lock, &tegra_clk_plle_ops);
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index a09d7dc..3cff1df 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -182,12 +182,13 @@ struct tegra_clk_pll_params {
* TEGRA_PLL_FIXED - We are not supposed to change output frequency
* of some plls.
* TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
+ * TEGRA_PLL_BYPASS - PLL has bypass bit
*/
struct tegra_clk_pll {
struct clk_hw hw;
void __iomem *clk_base;
void __iomem *pmc;
- u8 flags;
+ u32 flags;
unsigned long fixed_rate;
spinlock_t *lock;
u8 divn_shift;
@@ -210,18 +211,19 @@ struct tegra_clk_pll {
#define TEGRA_PLLM BIT(5)
#define TEGRA_PLL_FIXED BIT(6)
#define TEGRA_PLLE_CONFIGURE BIT(7)
+#define TEGRA_PLL_BYPASS BIT(8)
extern const struct clk_ops tegra_clk_pll_ops;
extern const struct clk_ops tegra_clk_plle_ops;
struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
- struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
- struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+ struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
/**
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 03/10] clk: tegra: Add PLL post divider table
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
2013-02-01 10:18 ` [PATCH v5 01/10] clk: tegra: Refactor PLL programming code Peter De Schrijver
2013-02-01 10:18 ` [PATCH v5 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 6:28 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114 Peter De Schrijver
` (6 subsequent siblings)
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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 3c3a25e..87d2f34 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -258,6 +258,7 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
unsigned long rate, unsigned long parent_rate)
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
+ struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
unsigned long cfreq;
u32 p_div = 0;
@@ -291,7 +292,6 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
cfg->output_rate <<= 1)
p_div++;
- cfg->p = p_div;
cfg->m = parent_rate / cfreq;
cfg->n = cfg->output_rate / cfreq;
cfg->cpcon = OUT_OF_TABLE_CPCON;
@@ -304,8 +304,19 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
return -EINVAL;
}
- if (pll->flags & TEGRA_PLLU)
- cfg->p ^= 1;
+ if (p_tohw) {
+ p_div = 1 << p_div;
+ while (p_tohw->pdiv) {
+ if (p_div <= p_tohw->pdiv) {
+ cfg->p = p_tohw->hw_val;
+ break;
+ }
+ p_tohw++;
+ }
+ if (!p_tohw->pdiv)
+ return -EINVAL;
+ } else
+ cfg->p = p_div;
return 0;
}
@@ -452,8 +463,10 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
{
struct tegra_clk_pll *pll = to_clk_pll(hw);
struct tegra_clk_pll_freq_table cfg;
+ struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
u32 val;
u64 rate = parent_rate;
+ int pdiv;
val = pll_readl_base(pll);
@@ -472,10 +485,23 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
_get_pll_mnp(pll, &cfg);
- if (pll->flags & TEGRA_PLLU)
- cfg.p ^= 1;
+ if (p_tohw) {
+ while (p_tohw->pdiv) {
+ if (cfg.p == p_tohw->hw_val) {
+ pdiv = p_tohw->pdiv;
+ break;
+ }
+ p_tohw++;
+ }
+
+ if (!p_tohw->pdiv) {
+ WARN_ON(1);
+ pdiv = 1;
+ }
+ } else
+ pdiv = 1 << cfg.p;
- cfg.m *= 1 << cfg.p;
+ cfg.m *= pdiv;
rate *= cfg.n;
do_div(rate, cfg.m);
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 30bd3fd..54c6777 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -440,6 +440,12 @@ static struct tegra_clk_pll_params pll_d_params = {
.lock_delay = 1000,
};
+static struct pdiv_map pllu_p[] = {
+ { .pdiv = 1, .hw_val = 1 },
+ { .pdiv = 2, .hw_val = 0 },
+ { .pdiv = 0, .hw_val = 0 },
+};
+
static struct tegra_clk_pll_params pll_u_params = {
.input_min = 2000000,
.input_max = 40000000,
@@ -452,6 +458,7 @@ static struct tegra_clk_pll_params pll_u_params = {
.lock_bit_idx = PLL_BASE_LOCK,
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
.lock_delay = 1000,
+ .pdiv_tohw = pllu_p,
};
static struct tegra_clk_pll_params pll_x_params = {
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 28a2997..078f9b8 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -466,6 +466,12 @@ static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
{ 0, 0, 0, 0, 0, 0 },
};
+static struct pdiv_map pllu_p[] = {
+ { .pdiv = 1, .hw_val = 1 },
+ { .pdiv = 2, .hw_val = 0 },
+ { .pdiv = 0, .hw_val = 0 },
+};
+
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
{ 12000000, 480000000, 960, 12, 0, 12},
{ 13000000, 480000000, 960, 13, 0, 12},
@@ -639,6 +645,7 @@ static struct tegra_clk_pll_params pll_u_params = {
.lock_bit_idx = PLL_BASE_LOCK,
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
.lock_delay = 1000,
+ .pdiv_tohw = pllu_p,
};
static struct tegra_clk_pll_params pll_x_params = {
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 3cff1df..1b9cbcd 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -117,6 +117,17 @@ struct tegra_clk_pll_freq_table {
};
/**
+ * struct pdiv_map - map post divider to hw value
+ *
+ * @pdiv: post divider
+ * @hw_val: value to be written to the PLL hw
+ */
+struct pdiv_map {
+ u8 pdiv;
+ u8 hw_val;
+};
+
+/**
* struct clk_pll_params - PLL parameters
*
* @input_min: Minimum input frequency
@@ -146,6 +157,8 @@ struct tegra_clk_pll_params {
u32 lock_bit_idx;
u32 lock_enable_bit_idx;
int lock_delay;
+ int max_p;
+ struct pdiv_map *pdiv_tohw;
};
/**
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
` (2 preceding siblings ...)
2013-02-01 10:18 ` [PATCH v5 03/10] clk: tegra: Add PLL post divider table Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-01 19:40 ` Rhyland Klein
2013-02-01 10:18 ` [PATCH v5 05/10] clk: tegra: Add flags to tegra_clk_periph() Peter De Schrijver
` (5 subsequent siblings)
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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 | 719 +++++++++++++++++++++++++++++++++++++++++++
drivers/clk/tegra/clk.h | 47 +++
2 files changed, 766 insertions(+), 0 deletions(-)
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 87d2f34..50114b7 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -79,6 +79,36 @@
#define PLLE_SS_CTRL 0x68
#define PLLE_SS_DISABLE (7 << 10)
+#define PLLE_AUX_PLLP_SEL BIT(2)
+#define PLLE_AUX_ENABLE_SWCTL BIT(4)
+#define PLLE_AUX_SEQ_ENABLE BIT(24)
+#define PLLE_AUX_PLLRE_SEL BIT(28)
+
+#define PLLE_MISC_PLLE_PTS BIT(8)
+#define PLLE_MISC_IDDQ_SW_VALUE BIT(13)
+#define PLLE_MISC_IDDQ_SW_CTRL BIT(14)
+#define PLLE_MISC_VREG_BG_CTRL_SHIFT 4
+#define PLLE_MISC_VREG_BG_CTRL_MASK (3 << PLLE_MISC_VREG_BG_CTRL_SHIFT)
+#define PLLE_MISC_VREG_CTRL_SHIFT 2
+#define PLLE_MISC_VREG_CTRL_MASK (2 << PLLE_MISC_VREG_CTRL_SHIFT)
+
+#define PLLCX_MISC_STROBE BIT(31)
+#define PLLCX_MISC_RESET BIT(30)
+#define PLLCX_MISC_SDM_DIV_SHIFT 28
+#define PLLCX_MISC_SDM_DIV_MASK (0x3 << PLLCX_MISC_SDM_DIV_SHIFT)
+#define PLLCX_MISC_FILT_DIV_SHIFT 26
+#define PLLCX_MISC_FILT_DIV_MASK (0x3 << PLLCX_MISC_FILT_DIV_SHIFT)
+#define PLLCX_MISC_DIV_LOW_RANGE \
+ ((0x2 << PLLCX_MISC_SDM_DIV_SHIFT) | \
+ (0x2 << PLLCX_MISC_FILT_DIV_SHIFT))
+#define PLLCX_MISC_DIV_HIGH_RANGE \
+ ((0x1 << PLLCX_MISC_SDM_DIV_SHIFT) | \
+ (0x1 << PLLCX_MISC_FILT_DIV_SHIFT))
+
+#define PMC_PLLM_WB0_OVERRIDE 0x1dc
+#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
+#define PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK BIT(27)
+
#define PMC_SATA_PWRGT 0x1ac
#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
@@ -101,6 +131,24 @@
#define divn_max(p) (divn_mask(p))
#define divp_max(p) (1 << (divp_mask(p)))
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+/* PLLXC has 4-bit PDIV, but entry 15 is not allowed in h/w */
+#define PLLXC_PDIV_MAX 14
+
+/* non-monotonic mapping below is not a typo */
+static u8 pllxc_p[PLLXC_PDIV_MAX + 1] = {
+ /* PDIV: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */
+ /* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32
+};
+
+#define PLLCX_PDIV_MAX 7
+static u8 pllcx_p[PLLCX_PDIV_MAX + 1] = {
+ /* PDIV: 0, 1, 2, 3, 4, 5, 6, 7 */
+ /* p: */ 1, 2, 3, 4, 6, 8, 12, 16
+};
+#endif
+
static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
{
u32 val;
@@ -638,6 +686,515 @@ const struct clk_ops tegra_clk_plle_ops = {
.enable = clk_plle_enable,
};
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+
+static int clk_pll_iddq_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+
+ u32 val;
+ int ret;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ val = pll_readl(pll->params->iddq_reg, pll);
+ val &= ~BIT(pll->params->iddq_bit_idx);
+ pll_writel(val, pll->params->iddq_reg, pll);
+ udelay(2);
+
+ _clk_pll_enable(hw);
+
+ ret = clk_pll_wait_for_lock(pll);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return 0;
+}
+
+static void clk_pll_iddq_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+ u32 val;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ _clk_pll_disable(hw);
+
+ val = pll_readl(pll->params->iddq_reg, pll);
+ val |= BIT(pll->params->iddq_bit_idx);
+ pll_writel(val, pll->params->iddq_reg, pll);
+ udelay(2);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int _calc_dynamic_ramp_rate(struct clk_hw *hw,
+ struct tegra_clk_pll_freq_table *cfg,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned int p;
+
+ if (!rate)
+ return -EINVAL;
+
+ p = DIV_ROUND_UP(pll->params->vco_min, rate);
+ cfg->m = (parent_rate > pll->params->cf_max) ? 2 : 1;
+ cfg->p = p;
+ cfg->output_rate = rate * cfg->p;
+ cfg->n = cfg->output_rate * cfg->m / parent_rate;
+
+ if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int _pll_ramp_calc_pll(struct clk_hw *hw,
+ struct tegra_clk_pll_freq_table *cfg,
+ unsigned long rate, unsigned long parent_rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ int ret = 0;
+
+ ret = _get_table_rate(hw, cfg, rate, parent_rate);
+ if (ret < 0) {
+ ret = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate);
+ return ret;
+ } else {
+ int fixed_mdiv;
+
+ fixed_mdiv = (parent_rate > pll->params->cf_max) ? 2 : 1;
+ if (cfg->m != fixed_mdiv) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ }
+
+ if (!cfg->p || (cfg->p > pll->params->max_p))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ struct tegra_clk_pll_freq_table cfg, old_cfg;
+ unsigned long flags = 0;
+ int ret = 0;
+ u8 old_p;
+
+ ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+ if (ret < 0)
+ return ret;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ _get_pll_mnp(pll, &old_cfg);
+
+ old_p = pllxc_p[old_cfg.p];
+ if (old_cfg.m != cfg.m && old_cfg.n != cfg.n && old_p != cfg.p) {
+ cfg.p -= 1;
+ ret = _program_pll(hw, &cfg, rate);
+ }
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct tegra_clk_pll_freq_table cfg;
+ int ret = 0;
+ u64 output_rate = *prate;
+
+ ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate);
+ if (ret < 0)
+ return ret;
+
+ output_rate *= cfg.n;
+ do_div(output_rate, cfg.m * cfg.p);
+
+ return output_rate;
+}
+
+static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_pll_freq_table cfg;
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+ int state, ret = 0;
+ u32 val;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ state = clk_pll_is_enabled(hw);
+ if (state) {
+ if (rate != clk_get_rate(hw->clk)) {
+ pr_err("%s: Cannot change active PLLM\n", __func__);
+ ret = -EINVAL;
+ goto out;
+ }
+ goto out;
+ }
+
+ ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+ if (ret < 0)
+ goto out;
+
+ cfg.p -= 1;
+
+ val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+ if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) {
+ val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE_2);
+ val = cfg.p ? (val | PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK) :
+ (val & ~PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK);
+ writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE_2);
+
+ val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+ val &= ~(divn_mask(pll) | divm_mask(pll));
+ val |= (cfg.m << pll->divm_shift) | (cfg.n << pll->divn_shift);
+ writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+ } else
+ _update_pll_mnp(pll, &cfg);
+
+
+out:
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static void _pllcx_strobe(struct tegra_clk_pll *pll)
+{
+ u32 val;
+
+ val = pll_readl_misc(pll);
+ val |= PLLCX_MISC_STROBE;
+ pll_writel_misc(val, pll);
+ udelay(2);
+
+ val &= ~PLLCX_MISC_STROBE;
+ pll_writel_misc(val, pll);
+}
+
+static int clk_pllc_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ u32 val;
+ int ret = 0;
+ unsigned long flags = 0;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ _clk_pll_enable(hw);
+ udelay(2);
+
+ val = pll_readl_misc(pll);
+ val &= ~PLLCX_MISC_RESET;
+ pll_writel_misc(val, pll);
+ udelay(2);
+
+ _pllcx_strobe(pll);
+
+ ret = clk_pll_wait_for_lock(pll);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static void _clk_pllc_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ u32 val;
+
+ _clk_pll_disable(hw);
+
+ val = pll_readl_misc(pll);
+ val |= PLLCX_MISC_RESET;
+ pll_writel_misc(val, pll);
+ udelay(2);
+}
+
+static void clk_pllc_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ _clk_pllc_disable(hw);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int _pllcx_update_dynamic_coef(struct tegra_clk_pll *pll,
+ unsigned long input_rate, u32 n)
+{
+ u32 val, n_threshold;
+
+ switch (input_rate) {
+ case 12000000:
+ n_threshold = 70;
+ break;
+ case 13000000:
+ case 26000000:
+ n_threshold = 71;
+ break;
+ case 16800000:
+ n_threshold = 55;
+ break;
+ case 19200000:
+ n_threshold = 48;
+ break;
+ default:
+ pr_err("%s: Unexpected reference rate %lu\n",
+ __func__, input_rate);
+ return -EINVAL;
+ }
+
+ val = pll_readl_misc(pll);
+ val &= ~(PLLCX_MISC_SDM_DIV_MASK | PLLCX_MISC_FILT_DIV_MASK);
+ val |= n <= n_threshold ?
+ PLLCX_MISC_DIV_LOW_RANGE : PLLCX_MISC_DIV_HIGH_RANGE;
+ pll_writel_misc(val, pll);
+
+ return 0;
+}
+
+static int clk_pllc_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_pll_freq_table cfg;
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+ int state, ret = 0;
+ u32 val;
+ u16 old_m, old_n;
+ u8 old_p;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+ if (ret < 0)
+ goto out;
+
+ val = pll_readl_base(pll);
+ old_m = (val >> pll->divm_shift) & (divm_mask(pll));
+ old_n = (val >> pll->divn_shift) & (divn_mask(pll));
+ old_p = pllcx_p[(val >> pll->divp_shift) & (divp_mask(pll))];
+
+ if (cfg.m != old_m) {
+ WARN_ON(1);
+ goto out;
+ }
+
+ if (old_n == cfg.n && old_p == cfg.p)
+ goto out;
+
+ cfg.p -= 1;
+
+ state = clk_pll_is_enabled(hw);
+ if (state)
+ _clk_pllc_disable(hw);
+
+ ret = _pllcx_update_dynamic_coef(pll, parent_rate, cfg.n);
+ if (ret < 0)
+ goto out;
+
+ _update_pll_mnp(pll, &cfg);
+
+ if (state)
+ ret = clk_pllc_enable(hw);
+
+out:
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static long _pllre_calc_rate(struct tegra_clk_pll *pll,
+ struct tegra_clk_pll_freq_table *cfg,
+ unsigned long rate, unsigned long parent_rate)
+{
+ u16 m, n;
+ u64 output_rate = parent_rate;
+
+ m = (parent_rate > pll->params->cf_max ? 2 : 1);
+ n = rate * m / parent_rate;
+
+ output_rate *= n;
+ do_div(output_rate, m);
+
+ if (cfg) {
+ cfg->m = m;
+ cfg->n = n;
+ }
+
+ return output_rate;
+}
+static int clk_pllre_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_pll_freq_table cfg, old_cfg;
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+ int state, ret = 0;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ _pllre_calc_rate(pll, &cfg, rate, parent_rate);
+ _get_pll_mnp(pll, &old_cfg);
+ cfg.p = old_cfg.p;
+
+ if (cfg.m != old_cfg.m || cfg.n != old_cfg.n) {
+ state = clk_pll_is_enabled(hw);
+ if (state)
+ _clk_pll_disable(hw);
+
+ _update_pll_mnp(pll, &cfg);
+
+ if (state) {
+ _clk_pll_enable(hw);
+ ret = clk_pll_wait_for_lock(pll);
+ }
+ }
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static unsigned long clk_pllre_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct tegra_clk_pll_freq_table cfg;
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ u64 rate = parent_rate;
+
+ _get_pll_mnp(pll, &cfg);
+
+ rate *= cfg.n;
+ do_div(rate, cfg.m);
+
+ return rate;
+}
+
+static long clk_pllre_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+
+ return _pllre_calc_rate(pll, NULL, rate, *prate);
+}
+
+static int clk_plle_tegra114_enable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ struct tegra_clk_pll_freq_table sel;
+ u32 val;
+ int ret;
+ unsigned long flags = 0;
+ unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+
+ if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
+ return -EINVAL;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ val = pll_readl_base(pll);
+ val &= ~BIT(29); /* Disable lock override */
+ pll_writel_base(val, pll);
+
+ val = pll_readl(pll->params->aux_reg, pll);
+ val |= PLLE_AUX_ENABLE_SWCTL;
+ val &= ~PLLE_AUX_SEQ_ENABLE;
+ pll_writel(val, pll->params->aux_reg, pll);
+ udelay(1);
+
+ val = pll_readl_misc(pll);
+ val |= PLLE_MISC_LOCK_ENABLE;
+ val |= PLLE_MISC_IDDQ_SW_CTRL;
+ val &= ~PLLE_MISC_IDDQ_SW_VALUE;
+ val |= PLLE_MISC_PLLE_PTS;
+ val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK;
+ pll_writel_misc(val, pll);
+ udelay(5);
+
+ val = pll_readl(PLLE_SS_CTRL, pll);
+ val |= PLLE_SS_DISABLE;
+ pll_writel(val, PLLE_SS_CTRL, pll);
+
+ val = pll_readl_base(pll);
+ val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
+ val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
+ val |= sel.m << pll->divm_shift;
+ val |= sel.n << pll->divn_shift;
+ val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
+ pll_writel_base(val, pll);
+ udelay(1);
+
+ _clk_pll_enable(hw);
+ ret = clk_pll_wait_for_lock(pll);
+
+ if (ret < 0)
+ goto out;
+
+ /* TODO: enable hw control of xusb brick pll */
+
+out:
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+
+ return ret;
+}
+
+static void clk_plle_tegra114_disable(struct clk_hw *hw)
+{
+ struct tegra_clk_pll *pll = to_clk_pll(hw);
+ unsigned long flags = 0;
+ u32 val;
+
+ if (pll->lock)
+ spin_lock_irqsave(pll->lock, flags);
+
+ _clk_pll_disable(hw);
+
+ val = pll_readl_misc(pll);
+ val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE;
+ pll_writel_misc(val, pll);
+ udelay(1);
+
+ if (pll->lock)
+ spin_unlock_irqrestore(pll->lock, flags);
+}
+#endif
+
static struct clk *_tegra_clk_register_pll(const char *name,
const char *parent_name, void __iomem *clk_base,
void __iomem *pmc, unsigned long flags,
@@ -709,3 +1266,165 @@ struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
flags, fixed_rate, pll_params, pll_flags, freq_table,
lock, &tegra_clk_plle_ops);
}
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+const struct clk_ops tegra_clk_pllxc_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .enable = clk_pll_iddq_enable,
+ .disable = clk_pll_iddq_disable,
+ .recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_ramp_round_rate,
+ .set_rate = clk_pllxc_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllm_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .enable = clk_pll_iddq_enable,
+ .disable = clk_pll_iddq_disable,
+ .recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_ramp_round_rate,
+ .set_rate = clk_pllm_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllc_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .enable = clk_pllc_enable,
+ .disable = clk_pllc_disable,
+ .recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_ramp_round_rate,
+ .set_rate = clk_pllc_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllre_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .enable = clk_pll_iddq_enable,
+ .disable = clk_pll_iddq_disable,
+ .recalc_rate = clk_pllre_recalc_rate,
+ .round_rate = clk_pllre_round_rate,
+ .set_rate = clk_pllre_set_rate,
+};
+
+const struct clk_ops tegra_clk_plle_tegra114_ops = {
+ .is_enabled = clk_pll_is_enabled,
+ .enable = clk_plle_tegra114_enable,
+ .disable = clk_plle_tegra114_disable,
+ .recalc_rate = clk_pll_recalc_rate,
+};
+
+
+struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ u32 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock)
+{
+ if (!pll_params->pdiv_tohw)
+ return -EINVAL;
+
+ return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, flags,
+ fixed_rate, pll_params, pll_flags, freq_table,
+ lock, &tegra_clk_pllxc_ops);
+}
+
+struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ u32 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock, unsigned long parent_rate)
+{
+ u32 val;
+
+ /* program minimum rate by default */
+
+ val = readl_relaxed(clk_base + pll_params->base_reg);
+ if (val & PLL_BASE_ENABLE)
+ WARN_ON(val & pll_params->iddq_bit_idx);
+ else {
+ int m;
+
+ m = (parent_rate > pll_params->cf_max) ? 2 : 1;
+ val = m << PLL_BASE_DIVM_SHIFT;
+ val |= (pll_params->vco_min / parent_rate)
+ << PLL_BASE_DIVN_SHIFT;
+ writel_relaxed(val, clk_base + pll_params->base_reg);
+ }
+
+ /* disable lock override */
+
+ val = readl_relaxed(clk_base + pll_params->misc_reg);
+ val &= ~BIT(29);
+ writel_relaxed(val, clk_base + pll_params->misc_reg);
+
+ return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, flags,
+ fixed_rate, pll_params, pll_flags, freq_table,
+ lock, &tegra_clk_pllre_ops);
+}
+
+struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ u32 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock)
+{
+ if (!pll_params->pdiv_tohw)
+ return -EINVAL;
+
+ pll_flags |= TEGRA_PLL_BYPASS;
+ return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, flags,
+ fixed_rate, pll_params, pll_flags, freq_table,
+ lock, &tegra_clk_pllm_ops);
+}
+
+struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ u32 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock)
+{
+ if (!pll_params->pdiv_tohw)
+ return -EINVAL;
+
+ pll_flags |= TEGRA_PLL_BYPASS;
+ return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, flags,
+ fixed_rate, pll_params, pll_flags, freq_table,
+ lock, &tegra_clk_pllc_ops);
+
+}
+
+struct clk *tegra_clk_register_plle_tegra114(const char *name,
+ const char *parent_name,
+ void __iomem *clk_base, unsigned long flags,
+ unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock)
+{
+ u32 val, val_aux;
+
+ /* ensure parent is set to pll_re_vco */
+
+ val = readl_relaxed(clk_base + pll_params->base_reg);
+ val_aux = readl_relaxed(clk_base + pll_params->aux_reg);
+
+ if (val & PLL_BASE_ENABLE) {
+ if (!(val_aux & PLLE_AUX_PLLRE_SEL))
+ WARN(1, "pll_e enabled with unsupported parent %s\n",
+ (val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref");
+ } else {
+ val_aux |= PLLE_AUX_PLLRE_SEL;
+ writel_relaxed(val, clk_base + pll_params->aux_reg);
+ }
+
+ return _tegra_clk_register_pll(name, parent_name, clk_base, NULL, flags,
+ fixed_rate, pll_params, 0, freq_table, lock,
+ &tegra_clk_plle_tegra114_ops);
+}
+#endif
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 1b9cbcd..4d0f556 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -156,6 +156,12 @@ struct tegra_clk_pll_params {
u32 lock_reg;
u32 lock_bit_idx;
u32 lock_enable_bit_idx;
+ u32 iddq_reg;
+ u32 iddq_bit_idx;
+ u32 aux_reg;
+ u32 dyn_ramp_reg;
+ int stepa_shift;
+ int stepb_shift;
int lock_delay;
int max_p;
struct pdiv_map *pdiv_tohw;
@@ -233,12 +239,53 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
unsigned long flags, unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+
struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
void __iomem *clk_base, void __iomem *pmc,
unsigned long flags, unsigned long fixed_rate,
struct tegra_clk_pll_params *pll_params, u32 pll_flags,
struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ u32 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ u32 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ u32 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
+ void __iomem *clk_base, void __iomem *pmc,
+ unsigned long flags, unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ u32 pll_flags,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock, unsigned long parent_rate);
+
+struct clk *tegra_clk_register_plle_tegra114(const char *name,
+ const char *parent_name,
+ void __iomem *clk_base, unsigned long flags,
+ unsigned long fixed_rate,
+ struct tegra_clk_pll_params *pll_params,
+ struct tegra_clk_pll_freq_table *freq_table,
+ spinlock_t *lock);
+
/**
* struct tegra_clk_pll_out - PLL divider down clock
*
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 05/10] clk: tegra: Add flags to tegra_clk_periph()
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
` (3 preceding siblings ...)
2013-02-01 10:18 ` [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114 Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 6:33 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 06/10] clk: tegra: Workaround for Tegra114 MSENC problem Peter De Schrijver
` (4 subsequent siblings)
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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 4d0f556..79f5e2a 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -411,7 +411,7 @@ extern const struct clk_ops tegra_clk_periph_ops;
struct clk *tegra_clk_register_periph(const char *name,
const char **parent_names, int num_parents,
struct tegra_clk_periph *periph, void __iomem *clk_base,
- u32 offset);
+ u32 offset, unsigned long flags);
struct clk *tegra_clk_register_periph_nodiv(const char *name,
const char **parent_names, int num_parents,
struct tegra_clk_periph *periph, void __iomem *clk_base,
@@ -454,12 +454,14 @@ struct tegra_periph_init_data {
u32 offset;
const char *con_id;
const char *dev_id;
+ unsigned long flags;
};
#define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
_mux_shift, _mux_mask, _mux_flags, _div_shift, \
_div_width, _div_frac_width, _div_flags, _regs, \
- _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table) \
+ _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\
+ _flags) \
{ \
.name = _name, \
.clk_id = _clk_id, \
@@ -474,6 +476,7 @@ struct tegra_periph_init_data {
.offset = _offset, \
.con_id = _con_id, \
.dev_id = _dev_id, \
+ .flags = _flags \
}
#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
@@ -484,7 +487,7 @@ struct tegra_periph_init_data {
_mux_shift, BIT(_mux_width) - 1, _mux_flags, \
_div_shift, _div_width, _div_frac_width, _div_flags, \
_regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\
- NULL)
+ NULL, 0)
/**
* struct clk_super_mux - super clock
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 06/10] clk: tegra: Workaround for Tegra114 MSENC problem
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
` (4 preceding siblings ...)
2013-02-01 10:18 ` [PATCH v5 05/10] clk: tegra: Add flags to tegra_clk_periph() Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 6:39 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 07/10] ARM: tegra: Define Tegra114 CAR binding Peter De Schrijver
` (3 subsequent siblings)
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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 | 1 +
2 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
index 6dd5332..c9083fb 100644
--- a/drivers/clk/tegra/clk-periph-gate.c
+++ b/drivers/clk/tegra/clk-periph-gate.c
@@ -43,6 +43,8 @@ static DEFINE_SPINLOCK(periph_ref_lock);
#define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32))
+#define LVL2_CLK_GATE_OVRE 0x554
+
/* Peripheral gate clock ops */
static int clk_periph_is_enabled(struct clk_hw *hw)
{
@@ -83,6 +85,13 @@ static int clk_periph_enable(struct clk_hw *hw)
}
}
+ if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
+ writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
+ writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
+ udelay(1);
+ writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
+ }
+
spin_unlock_irqrestore(&periph_ref_lock, flags);
return 0;
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 79f5e2a..8756d9f 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -371,6 +371,7 @@ struct tegra_clk_periph_gate {
#define TEGRA_PERIPH_NO_RESET BIT(0)
#define TEGRA_PERIPH_MANUAL_RESET BIT(1)
#define TEGRA_PERIPH_ON_APB BIT(2)
+#define TEGRA_PERIPH_WAR_1005168 BIT(3)
void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
extern const struct clk_ops tegra_clk_periph_gate_ops;
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 07/10] ARM: tegra: Define Tegra114 CAR binding
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
` (5 preceding siblings ...)
2013-02-01 10:18 ` [PATCH v5 06/10] clk: tegra: Workaround for Tegra114 MSENC problem Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 21:16 ` Stephen Warren
2013-02-01 10:18 ` [PATCH v5 08/10] ARM: dt: Add references to tegra_car clocks Peter De Schrijver
` (2 subsequent siblings)
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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 | 311 ++++++++++++++++++++
1 files changed, 311 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
new file mode 100644
index 0000000..516b9d3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
@@ -0,0 +1,311 @@
+NVIDIA Tegra114 Clock And Reset Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
+for muxing and gating Tegra's clocks, and setting their rates.
+
+Required properties :
+- compatible : Should be "nvidia,tegra114-car"
+- reg : Should contain CAR registers location and length
+- clocks : Should contain phandle and clock specifiers for two clocks:
+ the 32 KHz "32k_in", and the board-specific oscillator "osc".
+- #clock-cells : Should be 1.
+ In clock consumers, this cell represents the clock ID exposed by the CAR.
+
+ The first 160 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+ registers. These IDs often match those in the CAR's RST_DEVICES registers,
+ but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+ this case, those clocks are assigned IDs above 160 in order to highlight
+ this issue. Implementations that interpret these clock IDs as bit values
+ within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+ explicitly handle these special cases.
+
+ The balance of the clocks controlled by the CAR are assigned IDs of 160 and
+ above.
+
+ 0 cpu
+ 1 unassigned
+ 2 unassigned
+ 3 unassigned
+ 4 rtc
+ 5 timer
+ 6 uarta
+ 7 unassigned (register bit affects uartb and vfir)
+ 8 unassigned
+ 9 sdmmc2
+ 10 unassigned (register bit affects spdif_in and spdif_out)
+ 11 i2s1
+ 12 i2c1
+ 13 ndflash
+ 14 sdmmc1
+ 15 sdmmc4
+ 16 unassigned
+ 17 pwm
+ 18 i2s2
+ 19 epp
+ 20 unassigned (register bit affects vi and vi_sensor)
+ 21 2d
+ 22 usbd
+ 23 isp
+ 24 3d
+ 25 unassigned
+ 26 disp2
+ 27 disp1
+ 28 host1x
+ 29 vcp
+ 30 i2s0
+ 31 unassigned
+
+ 32 unassigned
+ 33 unassigned
+ 34 apbdma
+ 35 unassigned
+ 36 kbc
+ 37 unassigned
+ 38 unassigned
+ 39 unassigned (register bit affects fuse and fuse_burn)
+ 40 kfuse
+ 41 sbc1
+ 42 nor
+ 43 unassigned
+ 44 sbc2
+ 45 unassigned
+ 46 sbc3
+ 47 i2c5
+ 48 dsia
+ 49 unassigned
+ 50 mipi
+ 51 hdmi
+ 52 csi
+ 53 unassigned
+ 54 i2c2
+ 55 uartc
+ 56 mipi-cal
+ 57 unassigned
+ 58 usb2
+ 59 usb3
+ 60 msenc
+ 61 vde
+ 62 bsea
+ 63 bsev
+
+ 64 unassigned
+ 65 uartd
+ 66 unassigned
+ 67 i2c3
+ 68 sbc4
+ 69 sdmmc3
+ 70 unassigned
+ 71 owr
+ 72 afi
+ 73 csite
+ 74 unassigned
+ 75 unassigned
+ 76 la
+ 77 trace
+ 78 soc_therm
+ 79 dtv
+ 80 ndspeed
+ 81 i2cslow
+ 82 dsib
+ 83 tsec
+ 84 unassigned
+ 85 unassigned
+ 86 unassigned
+ 87 unassigned
+ 88 unassigned
+ 89 xusb_host
+ 90 unassigned
+ 91 msenc
+ 92 csus
+ 93 unassigned
+ 94 unassigned
+ 95 unassigned (bit affects xusb_dev and xusb_dev_src)
+
+ 96 unassigned
+ 97 unassigned
+ 98 unassigned
+ 99 mselect
+ 100 tsensor
+ 101 i2s3
+ 102 i2s4
+ 103 i2c4
+ 104 sbc5
+ 105 sbc6
+ 106 d_audio
+ 107 apbif
+ 108 dam0
+ 109 dam1
+ 110 dam2
+ 111 hda2codec_2x
+ 112 unassigned
+ 113 audio0_2x
+ 114 audio1_2x
+ 115 audio2_2x
+ 116 audio3_2x
+ 117 audio4_2x
+ 118 spdif_2x
+ 119 actmon
+ 120 extern1
+ 121 extern2
+ 122 extern3
+ 123 unassigned
+ 124 unassigned
+ 125 hda
+ 126 unassigned
+ 127 se
+
+ 128 hda2hdmi
+ 129 unassigned
+ 130 unassigned
+ 131 unassigned
+ 132 unassigned
+ 133 unassigned
+ 134 unassigned
+ 135 unassigned
+ 136 unassigned
+ 137 unassigned
+ 138 unassigned
+ 139 unassigned
+ 140 unassigned
+ 141 unassigned
+ 142 unassigned
+ 143 unassigned (bit affects xusb_falcon_src, xusb_fs_src,
+ xusb_host_src and xusb_ss_src)
+ 144 cilab
+ 145 cilcd
+ 146 cile
+ 147 dsialp
+ 148 dsiblp
+ 149 unassigned
+ 150 dds
+ 151 unassigned
+ 152 dp2
+ 153 amx
+ 154 adx
+ 155 unassigned
+ 156 xusb_ss
+
+ 192 uartb
+ 193 vfir
+ 194 spdif_in
+ 195 spdif_out
+ 196 vi
+ 197 vi_sensor
+ 198 fuse
+ 199 fuse_burn
+ 200 clk_32k
+ 201 clk_m
+ 202 clk_m_div2
+ 203 clk_m_div4
+ 204 pll_ref
+ 205 pll_c
+ 206 pll_c_out1
+ 207 pll_c2
+ 208 pll_c3
+ 209 pll_m
+ 210 pll_m_out1
+ 211 pll_p
+ 212 pll_p_out1
+ 213 pll_p_out2
+ 214 pll_p_out3
+ 215 pll_p_out4
+ 216 pll_a
+ 217 pll_a_out1
+ 218 pll_d
+ 219 pll_d_out0
+ 220 pll_d2
+ 221 pll_d2_out0
+ 222 pll_u
+ 223 pll_u_480M
+ 224 pll_u_60M
+ 225 pll_u_48M
+ 226 pll_u_12M
+ 227 pll_x
+ 228 pll_x_out0
+ 229 pll_re_vco
+ 230 pll_re_out
+ 231 pll_e_out0
+ 232 spdif_in_sync
+ 233 i2s0_sync
+ 234 i2s1_sync
+ 235 i2s2_sync
+ 236 i2s3_sync
+ 237 i2s4_sync
+ 238 vimclk_sync
+ 239 audio0
+ 240 audio1
+ 241 audio2
+ 242 audio3
+ 243 audio4
+ 244 spdif
+ 245 clk_out_1
+ 246 clk_out_2
+ 247 clk_out_3
+ 248 blink
+ 249 mipi_cal_fast
+ 250 dsi1_fixed
+ 251 dsi2_fixed
+ 252 xusb_host_src
+ 253 xusb_falcon_src
+ 254 xusb_fs_src
+ 255 xusb_ss_src
+ 256 xusb_dev_src
+ 257 xusb_dev
+ 258 xusb_hs_src
+
+Mux clocks
+
+ 300 audio0_mux
+ 301 audio1_mux
+ 302 audio2_mux
+ 303 audio3_mux
+ 304 audio4_mux
+ 305 spdif_mux
+ 306 clk_out_1_mux
+ 307 clk_out_2_mux
+ 308 clk_out_3_mux
+
+Example SoC include file:
+
+/ {
+ tegra_car: clock {
+ compatible = "nvidia,tegra114-car";
+ reg = <0x60006000 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ usb@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>;
+ };
+};
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 08/10] ARM: dt: Add references to tegra_car clocks
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
` (6 preceding siblings ...)
2013-02-01 10:18 ` [PATCH v5 07/10] ARM: tegra: Define Tegra114 CAR binding Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 6:45 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114 Peter De Schrijver
2013-02-01 10:18 ` [PATCH v5 10/10] clk: tegra: devicetree match for nvidia,tegra114-car Peter De Schrijver
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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 | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 96a8235..1dec620 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -27,7 +27,7 @@
};
tegra_car: clock {
- compatible = "nvidia,tegra114-car, nvidia,tegra30-car";
+ compatible = "nvidia,tegra114-car";
reg = <0x60006000 0x1000>;
#clock-cells = <1>;
};
@@ -43,6 +43,7 @@
reg-shift = <2>;
interrupts = <0 36 0x04>;
status = "disabled";
+ clocks = <&tegra_car 6>;
};
serial@70006040 {
@@ -51,6 +52,7 @@
reg-shift = <2>;
interrupts = <0 37 0x04>;
status = "disabled";
+ clocks = <&tegra_car 192>;
};
serial@70006200 {
@@ -59,6 +61,7 @@
reg-shift = <2>;
interrupts = <0 46 0x04>;
status = "disabled";
+ clocks = <&tegra_car 55>;
};
serial@70006300 {
@@ -67,12 +70,14 @@
reg-shift = <2>;
interrupts = <0 90 0x04>;
status = "disabled";
+ clocks = <&tegra_car 65>;
};
rtc {
compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc";
reg = <0x7000e000 0x100>;
interrupts = <0 2 0x04>;
+ clocks = <&tegra_car 4>;
};
pmc {
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
` (7 preceding siblings ...)
2013-02-01 10:18 ` [PATCH v5 08/10] ARM: dt: Add references to tegra_car clocks Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 7:08 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 10/10] clk: tegra: devicetree match for nvidia,tegra114-car Peter De Schrijver
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, linux-arm-kernel
Implement most clocks for Tegra114. The super clocks for the CPU complex
are still missing and will be implemented in a future version.
Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
drivers/clk/tegra/Makefile | 1 +
drivers/clk/tegra/clk-tegra114.c | 2002 ++++++++++++++++++++++++++++++++++++++
2 files changed, 2003 insertions(+), 0 deletions(-)
create mode 100644 drivers/clk/tegra/clk-tegra114.c
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 2b41b0f..f49fac2 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -9,3 +9,4 @@ obj-y += clk-super.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
new file mode 100644
index 0000000..f8165d2
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -0,0 +1,2002 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+
+#define RST_DEVICES_L 0x004
+#define RST_DEVICES_H 0x008
+#define RST_DEVICES_U 0x00C
+#define RST_DEVICES_V 0x358
+#define RST_DEVICES_W 0x35C
+#define RST_DEVICES_X 0x28C
+#define RST_DEVICES_SET_L 0x300
+#define RST_DEVICES_CLR_L 0x304
+#define RST_DEVICES_SET_H 0x308
+#define RST_DEVICES_CLR_H 0x30c
+#define RST_DEVICES_SET_U 0x310
+#define RST_DEVICES_CLR_U 0x314
+#define RST_DEVICES_SET_V 0x430
+#define RST_DEVICES_CLR_V 0x434
+#define RST_DEVICES_SET_W 0x438
+#define RST_DEVICES_CLR_W 0x43c
+#define RST_DEVICES_NUM 5
+
+#define CLK_OUT_ENB_L 0x010
+#define CLK_OUT_ENB_H 0x014
+#define CLK_OUT_ENB_U 0x018
+#define CLK_OUT_ENB_V 0x360
+#define CLK_OUT_ENB_W 0x364
+#define CLK_OUT_ENB_X 0x280
+#define CLK_OUT_ENB_SET_L 0x320
+#define CLK_OUT_ENB_CLR_L 0x324
+#define CLK_OUT_ENB_SET_H 0x328
+#define CLK_OUT_ENB_CLR_H 0x32c
+#define CLK_OUT_ENB_SET_U 0x330
+#define CLK_OUT_ENB_CLR_U 0x334
+#define CLK_OUT_ENB_SET_V 0x440
+#define CLK_OUT_ENB_CLR_V 0x444
+#define CLK_OUT_ENB_SET_W 0x448
+#define CLK_OUT_ENB_CLR_W 0x44c
+#define CLK_OUT_ENB_SET_X 0x284
+#define CLK_OUT_ENB_CLR_X 0x288
+#define CLK_OUT_ENB_NUM 6
+
+#define PLLC_BASE 0x80
+#define PLLC_MISC2 0x88
+#define PLLC_MISC 0x8c
+#define PLLC2_BASE 0x4e8
+#define PLLC2_MISC 0x4ec
+#define PLLC3_BASE 0x4fc
+#define PLLC3_MISC 0x500
+#define PLLM_BASE 0x90
+#define PLLM_MISC 0x9c
+#define PLLP_BASE 0xa0
+#define PLLP_MISC 0xac
+#define PLLX_BASE 0xe0
+#define PLLX_MISC 0xe4
+#define PLLX_MISC2 0x514
+#define PLLX_MISC3 0x518
+#define PLLD_BASE 0xd0
+#define PLLD_MISC 0xdc
+#define PLLD2_BASE 0x4b8
+#define PLLD2_MISC 0x4bc
+#define PLLE_BASE 0xe8
+#define PLLE_MISC 0xec
+#define PLLA_BASE 0xb0
+#define PLLA_MISC 0xbc
+#define PLLU_BASE 0xc0
+#define PLLU_MISC 0xcc
+#define PLLRE_BASE 0x4c4
+#define PLLRE_MISC 0x4c8
+
+#define PLL_MISC_LOCK_ENABLE 18
+#define PLLDU_MISC_LOCK_ENABLE 22
+#define PLLE_MISC_LOCK_ENABLE 9
+#define PLLRE_MISC_LOCK_ENABLE 30
+
+#define PLLC_IDDQ_BIT 26
+#define PLLX_IDDQ_BIT 3
+#define PLLRE_IDDQ_BIT 16
+
+#define PLL_BASE_LOCK 27
+#define PLLE_MISC_LOCK 11
+#define PLLRE_MISC_LOCK 24
+
+#define PLLE_AUX 0x48c
+#define PLLC_OUT 0x84
+#define PLLM_OUT 0x94
+#define PLLP_OUTA 0xa4
+#define PLLP_OUTB 0xa8
+#define PLLA_OUT 0xb4
+
+#define AUDIO_SYNC_CLK_I2S0 0x4a0
+#define AUDIO_SYNC_CLK_I2S1 0x4a4
+#define AUDIO_SYNC_CLK_I2S2 0x4a8
+#define AUDIO_SYNC_CLK_I2S3 0x4ac
+#define AUDIO_SYNC_CLK_I2S4 0x4b0
+#define AUDIO_SYNC_CLK_SPDIF 0x4b4
+
+#define AUDIO_SYNC_DOUBLER 0x49c
+
+#define PMC_CLK_OUT_CNTRL 0x1a8
+#define PMC_DPD_PADS_ORIDE 0x1c
+#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
+#define PMC_CTRL 0
+#define PMC_CTRL_BLINK_ENB 7
+
+#define OSC_CTRL 0x50
+#define OSC_CTRL_OSC_FREQ_SHIFT 28
+#define OSC_CTRL_PLL_REF_DIV_SHIFT 26
+
+#define PLLXC_SW_MAX_P 6
+
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
+
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+
+#define UTMIPLL_HW_PWRDN_CFG0 0x52c
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24)
+#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4)
+#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0)
+
+#define CLK_SOURCE_I2S0 0x1d8
+#define CLK_SOURCE_I2S1 0x100
+#define CLK_SOURCE_I2S2 0x104
+#define CLK_SOURCE_NDFLASH 0x160
+#define CLK_SOURCE_I2S3 0x3bc
+#define CLK_SOURCE_I2S4 0x3c0
+#define CLK_SOURCE_SPDIF_OUT 0x108
+#define CLK_SOURCE_SPDIF_IN 0x10c
+#define CLK_SOURCE_PWM 0x110
+#define CLK_SOURCE_ADX 0x638
+#define CLK_SOURCE_AMX 0x63c
+#define CLK_SOURCE_HDA 0x428
+#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
+#define CLK_SOURCE_SBC1 0x134
+#define CLK_SOURCE_SBC2 0x118
+#define CLK_SOURCE_SBC3 0x11c
+#define CLK_SOURCE_SBC4 0x1b4
+#define CLK_SOURCE_SBC5 0x3c8
+#define CLK_SOURCE_SBC6 0x3cc
+#define CLK_SOURCE_SATA_OOB 0x420
+#define CLK_SOURCE_SATA 0x424
+#define CLK_SOURCE_NDSPEED 0x3f8
+#define CLK_SOURCE_VFIR 0x168
+#define CLK_SOURCE_SDMMC1 0x150
+#define CLK_SOURCE_SDMMC2 0x154
+#define CLK_SOURCE_SDMMC3 0x1bc
+#define CLK_SOURCE_SDMMC4 0x164
+#define CLK_SOURCE_VDE 0x1c8
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_LA 0x1f8
+#define CLK_SOURCE_TRACE 0x634
+#define CLK_SOURCE_OWR 0x1cc
+#define CLK_SOURCE_NOR 0x1d0
+#define CLK_SOURCE_MIPI 0x174
+#define CLK_SOURCE_I2C1 0x124
+#define CLK_SOURCE_I2C2 0x198
+#define CLK_SOURCE_I2C3 0x1b8
+#define CLK_SOURCE_I2C4 0x3c4
+#define CLK_SOURCE_I2C5 0x128
+#define CLK_SOURCE_UARTA 0x178
+#define CLK_SOURCE_UARTB 0x17c
+#define CLK_SOURCE_UARTC 0x1a0
+#define CLK_SOURCE_UARTD 0x1c0
+#define CLK_SOURCE_UARTE 0x1c4
+#define CLK_SOURCE_UARTA_DBG 0x178
+#define CLK_SOURCE_UARTB_DBG 0x17c
+#define CLK_SOURCE_UARTC_DBG 0x1a0
+#define CLK_SOURCE_UARTD_DBG 0x1c0
+#define CLK_SOURCE_UARTE_DBG 0x1c4
+#define CLK_SOURCE_3D 0x158
+#define CLK_SOURCE_2D 0x15c
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+#define CLK_SOURCE_VI 0x148
+#define CLK_SOURCE_EPP 0x16c
+#define CLK_SOURCE_MSENC 0x1f0
+#define CLK_SOURCE_TSEC 0x1f4
+#define CLK_SOURCE_HOST1X 0x180
+#define CLK_SOURCE_HDMI 0x18c
+#define CLK_SOURCE_DISP1 0x138
+#define CLK_SOURCE_DISP2 0x13c
+#define CLK_SOURCE_CILAB 0x614
+#define CLK_SOURCE_CILCD 0x618
+#define CLK_SOURCE_CILE 0x61c
+#define CLK_SOURCE_DSIALP 0x620
+#define CLK_SOURCE_DSIBLP 0x624
+#define CLK_SOURCE_TSENSOR 0x3b8
+#define CLK_SOURCE_D_AUDIO 0x3d0
+#define CLK_SOURCE_DAM0 0x3d8
+#define CLK_SOURCE_DAM1 0x3dc
+#define CLK_SOURCE_DAM2 0x3e0
+#define CLK_SOURCE_ACTMON 0x3e8
+#define CLK_SOURCE_EXTERN1 0x3ec
+#define CLK_SOURCE_EXTERN2 0x3f0
+#define CLK_SOURCE_EXTERN3 0x3f4
+#define CLK_SOURCE_I2CSLOW 0x3fc
+#define CLK_SOURCE_SE 0x42c
+#define CLK_SOURCE_MSELECT 0x3b4
+#define CLK_SOURCE_SOC_THERM 0x644
+#define CLK_SOURCE_XUSB_HOST_SRC 0x600
+#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
+#define CLK_SOURCE_XUSB_FS_SRC 0x608
+#define CLK_SOURCE_XUSB_SS_SRC 0x610
+#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
+
+static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
+
+static void __iomem *clk_base;
+static void __iomem *pmc_base;
+
+static DEFINE_SPINLOCK(pll_d_lock);
+static DEFINE_SPINLOCK(pll_d2_lock);
+static DEFINE_SPINLOCK(pll_u_lock);
+static DEFINE_SPINLOCK(pll_div_lock);
+static DEFINE_SPINLOCK(pll_re_lock);
+static DEFINE_SPINLOCK(clk_doubler_lock);
+static DEFINE_SPINLOCK(clk_out_lock);
+
+static struct pdiv_map pllxc_p[] = {
+ { .pdiv = 1, .hw_val = 0 },
+ { .pdiv = 2, .hw_val = 1 },
+ { .pdiv = 3, .hw_val = 2 },
+ { .pdiv = 4, .hw_val = 3 },
+ { .pdiv = 5, .hw_val = 4 },
+ { .pdiv = 6, .hw_val = 5 },
+ { .pdiv = 8, .hw_val = 6 },
+ { .pdiv = 10, .hw_val = 7 },
+ { .pdiv = 12, .hw_val = 8 },
+ { .pdiv = 16, .hw_val = 9 },
+ { .pdiv = 12, .hw_val = 10 },
+ { .pdiv = 16, .hw_val = 11 },
+ { .pdiv = 20, .hw_val = 12 },
+ { .pdiv = 24, .hw_val = 13 },
+ { .pdiv = 32, .hw_val = 14 },
+ { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
+ { 12000000, 624000000, 104, 0, 2},
+ { 12000000, 600000000, 100, 0, 2},
+ { 13000000, 600000000, 92, 0, 2}, /* actual: 598.0 MHz */
+ { 16800000, 600000000, 71, 0, 2}, /* actual: 596.4 MHz */
+ { 19200000, 600000000, 62, 0, 2}, /* actual: 595.2 MHz */
+ { 26000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */
+ { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_c_params = {
+ .input_min = 12000000,
+ .input_max = 800000000,
+ .cf_min = 12000000,
+ .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */
+ .vco_min = 600000000,
+ .vco_max = 1400000000,
+ .base_reg = PLLC_BASE,
+ .misc_reg = PLLC_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+ .iddq_reg = PLLC_MISC,
+ .iddq_bit_idx = PLLC_IDDQ_BIT,
+ .max_p = PLLXC_SW_MAX_P,
+ .dyn_ramp_reg = PLLC_MISC2,
+ .stepa_shift = 17,
+ .stepb_shift = 9,
+ .pdiv_tohw = pllxc_p,
+};
+
+static struct pdiv_map pllc_p[] = {
+ { .pdiv = 1, .hw_val = 0 },
+ { .pdiv = 2, .hw_val = 1 },
+ { .pdiv = 4, .hw_val = 3 },
+ { .pdiv = 8, .hw_val = 5 },
+ { .pdiv = 16, .hw_val = 7 },
+ { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
+ {12000000, 600000000, 100, 0, 2},
+ {13000000, 600000000, 92, 0, 2}, /* actual: 598.0 MHz */
+ {16800000, 600000000, 71, 0, 2}, /* actual: 596.4 MHz */
+ {19200000, 600000000, 62, 0, 2}, /* actual: 595.2 MHz */
+ {26000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */
+ {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_c2_params = {
+ .input_min = 12000000,
+ .input_max = 48000000,
+ .cf_min = 12000000,
+ .cf_max = 19200000,
+ .vco_min = 600000000,
+ .vco_max = 1200000000,
+ .base_reg = PLLC2_BASE,
+ .misc_reg = PLLC2_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+ .pdiv_tohw = pllc_p,
+};
+
+static struct tegra_clk_pll_params pll_c3_params = {
+ .input_min = 12000000,
+ .input_max = 48000000,
+ .cf_min = 12000000,
+ .cf_max = 19200000,
+ .vco_min = 600000000,
+ .vco_max = 1200000000,
+ .base_reg = PLLC3_BASE,
+ .misc_reg = PLLC3_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+ .pdiv_tohw = pllc_p,
+};
+
+static struct pdiv_map pllm_p[] = {
+ { .pdiv = 1, .hw_val = 0 },
+ { .pdiv = 2, .hw_val = 1 },
+ { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
+ {12000000, 800000000, 66, 0, 1}, /* actual: 792.0 MHz */
+ {13000000, 800000000, 61, 0, 1}, /* actual: 793.0 MHz */
+ {16800000, 800000000, 47, 0, 1}, /* actual: 789.6 MHz */
+ {19200000, 800000000, 41, 0, 1}, /* actual: 787.2 MHz */
+ {26000000, 800000000, 61, 1, 1}, /* actual: 793.0 MHz */
+ {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_m_params = {
+ .input_min = 12000000,
+ .input_max = 500000000,
+ .cf_min = 12000000,
+ .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */
+ .vco_min = 400000000,
+ .vco_max = 1066000000,
+ .base_reg = PLLM_BASE,
+ .misc_reg = PLLM_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+ .max_p = 2,
+ .pdiv_tohw = pllm_p,
+};
+
+static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
+ {12000000, 216000000, 432, 12, 1, 8},
+ {13000000, 216000000, 432, 13, 1, 8},
+ {16800000, 216000000, 360, 14, 1, 8},
+ {19200000, 216000000, 360, 16, 1, 8},
+ {26000000, 216000000, 432, 26, 1, 8},
+ {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_p_params = {
+ .input_min = 2000000,
+ .input_max = 31000000,
+ .cf_min = 1000000,
+ .cf_max = 6000000,
+ .vco_min = 200000000,
+ .vco_max = 700000000,
+ .base_reg = PLLP_BASE,
+ .misc_reg = PLLP_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+};
+
+static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
+ {9600000, 282240000, 147, 5, 0, 4},
+ {9600000, 368640000, 192, 5, 0, 4},
+ {9600000, 240000000, 200, 8, 0, 8},
+
+ {28800000, 282240000, 245, 25, 0, 8},
+ {28800000, 368640000, 320, 25, 0, 8},
+ {28800000, 240000000, 200, 24, 0, 8},
+ {0, 0, 0, 0, 0, 0},
+};
+
+
+static struct tegra_clk_pll_params pll_a_params = {
+ .input_min = 2000000,
+ .input_max = 31000000,
+ .cf_min = 1000000,
+ .cf_max = 6000000,
+ .vco_min = 200000000,
+ .vco_max = 700000000,
+ .base_reg = PLLA_BASE,
+ .misc_reg = PLLA_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+};
+
+static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
+ {12000000, 216000000, 864, 12, 2, 12},
+ {13000000, 216000000, 864, 13, 2, 12},
+ {16800000, 216000000, 720, 14, 2, 12},
+ {19200000, 216000000, 720, 16, 2, 12},
+ {26000000, 216000000, 864, 26, 2, 12},
+
+ {12000000, 594000000, 594, 12, 0, 12},
+ {13000000, 594000000, 594, 13, 0, 12},
+ {16800000, 594000000, 495, 14, 0, 12},
+ {19200000, 594000000, 495, 16, 0, 12},
+ {26000000, 594000000, 594, 26, 0, 12},
+
+ {12000000, 1000000000, 1000, 12, 0, 12},
+ {13000000, 1000000000, 1000, 13, 0, 12},
+ {19200000, 1000000000, 625, 12, 0, 12},
+ {26000000, 1000000000, 1000, 26, 0, 12},
+
+ {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_d_params = {
+ .input_min = 2000000,
+ .input_max = 40000000,
+ .cf_min = 1000000,
+ .cf_max = 6000000,
+ .vco_min = 500000000,
+ .vco_max = 1000000000,
+ .base_reg = PLLD_BASE,
+ .misc_reg = PLLD_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+ .lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_params pll_d2_params = {
+ .input_min = 2000000,
+ .input_max = 40000000,
+ .cf_min = 1000000,
+ .cf_max = 6000000,
+ .vco_min = 500000000,
+ .vco_max = 1000000000,
+ .base_reg = PLLD2_BASE,
+ .misc_reg = PLLD2_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+ .lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
+ {12000000, 480000000, 960, 12, 0, 12},
+ {13000000, 480000000, 960, 13, 0, 12},
+ {16800000, 480000000, 400, 7, 0, 5},
+ {19200000, 480000000, 200, 4, 0, 3},
+ {26000000, 480000000, 960, 26, 0, 12},
+ {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_u_params = {
+ .input_min = 2000000,
+ .input_max = 40000000,
+ .cf_min = 1000000,
+ .cf_max = 6000000,
+ .vco_min = 480000000,
+ .vco_max = 960000000,
+ .base_reg = PLLU_BASE,
+ .misc_reg = PLLU_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+ .lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
+ /* 1 GHz */
+ {12000000, 1000000000, 83, 0, 1}, /* actual: 996.0 MHz */
+ {13000000, 1000000000, 76, 0, 1}, /* actual: 988.0 MHz */
+ {16800000, 1000000000, 59, 0, 1}, /* actual: 991.2 MHz */
+ {19200000, 1000000000, 52, 0, 1}, /* actual: 998.4 MHz */
+ {26000000, 1000000000, 76, 1, 1}, /* actual: 988.0 MHz */
+
+ {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_x_params = {
+ .input_min = 12000000,
+ .input_max = 800000000,
+ .cf_min = 12000000,
+ .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */
+ .vco_min = 700000000,
+ .vco_max = 2400000000U,
+ .base_reg = PLLX_BASE,
+ .misc_reg = PLLX_MISC,
+ .lock_bit_idx = PLL_BASE_LOCK,
+ .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+ .iddq_reg = PLLX_MISC3,
+ .iddq_bit_idx = PLLX_IDDQ_BIT,
+ .max_p = PLLXC_SW_MAX_P,
+ .dyn_ramp_reg = PLLC_MISC2,
+ .stepa_shift = 16,
+ .stepb_shift = 24,
+ .pdiv_tohw = pllxc_p,
+};
+
+static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
+ /* PLLE special case: use cpcon field to store cml divider value */
+ {336000000, 100000000, 100, 21, 16, 11},
+ {312000000, 100000000, 200, 26, 24, 13},
+ {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_e_params = {
+ .input_min = 12000000,
+ .input_max = 1000000000,
+ .cf_min = 12000000,
+ .cf_max = 75000000,
+ .vco_min = 1600000000,
+ .vco_max = 2400000000U,
+ .base_reg = PLLE_BASE,
+ .misc_reg = PLLE_MISC,
+ .aux_reg = PLLE_AUX,
+ .lock_bit_idx = PLLE_MISC_LOCK,
+ .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_re_vco_params = {
+ .input_min = 12000000,
+ .input_max = 1000000000,
+ .cf_min = 12000000,
+ .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */
+ .vco_min = 300000000,
+ .vco_max = 600000000,
+ .base_reg = PLLRE_BASE,
+ .misc_reg = PLLRE_MISC,
+ .lock_bit_idx = PLLRE_MISC_LOCK,
+ .lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE,
+ .lock_delay = 300,
+ .iddq_reg = PLLRE_MISC,
+ .iddq_bit_idx = PLLRE_IDDQ_BIT,
+};
+
+/* Peripheral clock registers */
+
+static struct tegra_clk_periph_regs periph_l_regs = {
+ .enb_reg = CLK_OUT_ENB_L,
+ .enb_set_reg = CLK_OUT_ENB_SET_L,
+ .enb_clr_reg = CLK_OUT_ENB_CLR_L,
+ .rst_reg = RST_DEVICES_L,
+ .rst_set_reg = RST_DEVICES_SET_L,
+ .rst_clr_reg = RST_DEVICES_CLR_L,
+};
+
+static struct tegra_clk_periph_regs periph_h_regs = {
+ .enb_reg = CLK_OUT_ENB_H,
+ .enb_set_reg = CLK_OUT_ENB_SET_H,
+ .enb_clr_reg = CLK_OUT_ENB_CLR_H,
+ .rst_reg = RST_DEVICES_H,
+ .rst_set_reg = RST_DEVICES_SET_H,
+ .rst_clr_reg = RST_DEVICES_CLR_H,
+};
+
+static struct tegra_clk_periph_regs periph_u_regs = {
+ .enb_reg = CLK_OUT_ENB_U,
+ .enb_set_reg = CLK_OUT_ENB_SET_U,
+ .enb_clr_reg = CLK_OUT_ENB_CLR_U,
+ .rst_reg = RST_DEVICES_U,
+ .rst_set_reg = RST_DEVICES_SET_U,
+ .rst_clr_reg = RST_DEVICES_CLR_U,
+};
+
+static struct tegra_clk_periph_regs periph_v_regs = {
+ .enb_reg = CLK_OUT_ENB_V,
+ .enb_set_reg = CLK_OUT_ENB_SET_V,
+ .enb_clr_reg = CLK_OUT_ENB_CLR_V,
+ .rst_reg = RST_DEVICES_V,
+ .rst_set_reg = RST_DEVICES_SET_V,
+ .rst_clr_reg = RST_DEVICES_CLR_V,
+};
+
+static struct tegra_clk_periph_regs periph_w_regs = {
+ .enb_reg = CLK_OUT_ENB_W,
+ .enb_set_reg = CLK_OUT_ENB_SET_W,
+ .enb_clr_reg = CLK_OUT_ENB_CLR_W,
+ .rst_reg = RST_DEVICES_W,
+ .rst_set_reg = RST_DEVICES_SET_W,
+ .rst_clr_reg = RST_DEVICES_CLR_W,
+};
+
+/* possible OSC frequencies in Hz */
+static unsigned long tegra114_input_freq[] = {
+ [0] = 13000000,
+ [1] = 16800000,
+ [4] = 19200000,
+ [5] = 38400000,
+ [8] = 12000000,
+ [9] = 48000000,
+ [12] = 260000000,
+};
+
+#define MASK(x) (BIT(x) - 1)
+
+#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \
+ _clk_num, _regs, _gate_flags, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+ 30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num, \
+ periph_clk_enb_refcnt, _gate_flags, _clk_id, \
+ _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \
+ _clk_num, _regs, _gate_flags, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+ 29, MASK(3), 0, 0, 8, 1, 0, _regs, _clk_num, \
+ periph_clk_enb_refcnt, _gate_flags, _clk_id, \
+ _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \
+ _clk_num, _regs, _gate_flags, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+ _clk_num, periph_clk_enb_refcnt, _gate_flags, \
+ _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\
+ _clk_num, _regs, _gate_flags, _clk_id, flags)\
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+ 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+ _clk_num, periph_clk_enb_refcnt, _gate_flags, \
+ _clk_id, _parents##_idx, flags)
+
+#define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\
+ _clk_num, _regs, _gate_flags, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+ _clk_num, periph_clk_enb_refcnt, _gate_flags, \
+ _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\
+ _clk_num, _regs, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+ 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs,\
+ _clk_num, periph_clk_enb_refcnt, 0, _clk_id, \
+ _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\
+ _clk_num, _regs, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+ 30, MASK(2), 0, 0, 16, 0, 0, _regs, _clk_num, \
+ periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \
+ _mux_shift, _mux_mask, _clk_num, _regs, \
+ _gate_flags, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+ _mux_shift, _mux_mask, 0, 0, 0, 0, 0, _regs, \
+ _clk_num, periph_clk_enb_refcnt, _gate_flags, \
+ _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \
+ _clk_num, _regs, _gate_flags, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \
+ 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \
+ _clk_num, periph_clk_enb_refcnt, _gate_flags, \
+ _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset, _clk_num,\
+ _regs, _gate_flags, _clk_id) \
+ TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk, \
+ _offset, 16, 0xE01F, 0, 0, 8, 1, 0, _regs, _clk_num, \
+ periph_clk_enb_refcnt, _gate_flags , _clk_id, \
+ mux_d_audio_clk_idx, 0)
+
+enum tegra114_clk {
+ rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12,
+ ndflash = 13, sdmmc1 = 14, sdmmc4 = 15, pwm = 17, i2s2 = 18, epp = 19,
+ gr_2d = 21, usbd = 22, isp = 23, gr_3d = 24, disp2 = 26, disp1 = 27,
+ host1x = 28, vcp = 29, i2s0 = 30, apbdma = 34, kbc = 36, kfuse = 40,
+ sbc1 = 41, nor = 42, sbc2 = 44, sbc3 = 46, i2c5 = 47, dsia = 48,
+ mipi = 50, hdmi = 51, csi = 52, i2c2 = 54, uartc = 55, mipi_cal = 56,
+ usb2 = 58, usb3 = 59, vde = 61, bsea = 62, bsev = 63, uartd = 65,
+ uarte = 66, i2c3 = 67, sbc4 = 68, sdmmc3 = 69, owr = 71, csite = 73,
+ la = 76, trace = 77, soc_therm = 78, dtv = 79, ndspeed = 80,
+ i2cslow = 81, dsib = 82, tsec = 83, xusb_host = 89, msenc = 91,
+ csus = 92, mselect = 99, tsensor = 100, i2s3 = 101, i2s4 = 102,
+ i2c4 = 103, sbc5 = 104, sbc6 = 105, apbif = 107, d_audio, dam0, dam1,
+ dam2, hda2codec_2x = 111, audio0_2x = 113, audio1_2x, audio2_2x,
+ audio3_2x, audio4_2x, spdif_2x, actmon = 119, extern1 = 120,
+ extern2 = 121, extern3 = 122, hda = 125, se = 127, hda2hdmi = 128,
+ cilab = 144, cilcd = 145, cile = 146, dsialp = 147, dsiblp = 148,
+ dds = 150, dp2 = 152, amx = 153, adx = 154, xusb_ss = 156, uartb = 192,
+ vfir, spdif_in, spdif_out, vi, vi_sensor, fuse, fuse_burn, clk_32k,
+ clk_m, clk_m_div2, clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_c2,
+ pll_c3, pll_m, pll_m_out1, pll_p, pll_p_out1, pll_p_out2, pll_p_out3,
+ pll_p_out4, pll_a, pll_a_out0, pll_d, pll_d_out0, pll_d2, pll_d2_out0,
+ pll_u, pll_u_480M, pll_u_60M, pll_u_48M, pll_u_12M, pll_x, pll_x_out0,
+ pll_re_vco, pll_re_out, pll_e_out0, spdif_in_sync, i2s0_sync,
+ i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync, vimclk_sync, audio0,
+ audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3,
+ blink, mipi_cal_fast, dsi1_fixed, dsi2_fixed, xusb_host_src,
+ xusb_falcon_src, xusb_fs_src, xusb_ss_src, xusb_dev_src, xusb_dev,
+ xusb_hs_src,
+
+ /* Mux clocks */
+
+ audio0_mux = 300, audio1_mux, audio2_mux, audio3_mux, audio4_mux,
+ spdif_mux, clk_out_1_mux, clk_out_2_mux, clk_out_3_mux, dsia_mux,
+ dsib_mux, clk_max,
+};
+
+struct utmi_clk_param {
+ /* Oscillator Frequency in KHz */
+ u32 osc_frequency;
+ /* UTMIP PLL Enable Delay Count */
+ u8 enable_delay_count;
+ /* UTMIP PLL Stable count */
+ u8 stable_count;
+ /* UTMIP PLL Active delay count */
+ u8 active_delay_count;
+ /* UTMIP PLL Xtal frequency count */
+ u8 xtal_freq_count;
+};
+
+static const struct utmi_clk_param utmi_parameters[] = {
+ {.osc_frequency = 13000000, .enable_delay_count = 0x02,
+ .stable_count = 0x33, .active_delay_count = 0x05,
+ .xtal_freq_count = 0x7F},
+ {.osc_frequency = 19200000, .enable_delay_count = 0x03,
+ .stable_count = 0x4B, .active_delay_count = 0x06,
+ .xtal_freq_count = 0xBB},
+ {.osc_frequency = 12000000, .enable_delay_count = 0x02,
+ .stable_count = 0x2F, .active_delay_count = 0x04,
+ .xtal_freq_count = 0x76},
+ {.osc_frequency = 26000000, .enable_delay_count = 0x04,
+ .stable_count = 0x66, .active_delay_count = 0x09,
+ .xtal_freq_count = 0xFE},
+ {.osc_frequency = 16800000, .enable_delay_count = 0x03,
+ .stable_count = 0x41, .active_delay_count = 0x0A,
+ .xtal_freq_count = 0xA4},
+};
+
+/* peripheral mux definitions */
+
+#define MUX_I2S_SPDIF(_id) \
+static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
+ #_id, "pll_p",\
+ "clk_m"};
+MUX_I2S_SPDIF(audio0)
+MUX_I2S_SPDIF(audio1)
+MUX_I2S_SPDIF(audio2)
+MUX_I2S_SPDIF(audio3)
+MUX_I2S_SPDIF(audio4)
+MUX_I2S_SPDIF(audio)
+
+#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL
+
+static const char *mux_pllp_pllc_pllm_clkm[] = {
+ "pll_p", "pll_c", "pll_m", "clk_m"
+};
+#define mux_pllp_pllc_pllm_clkm_idx NULL
+
+static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" };
+#define mux_pllp_pllc_pllm_idx NULL
+
+static const char *mux_pllp_pllc_clk32_clkm[] = {
+ "pll_p", "pll_c", "clk_32k", "clk_m"
+};
+#define mux_pllp_pllc_clk32_clkm_idx NULL
+
+static const char *mux_plla_pllc_pllp_clkm[] = {
+ "pll_a_out0", "pll_c", "pll_p", "clk_m"
+};
+#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx
+
+static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = {
+ "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m"
+};
+static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = {
+ [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
+};
+
+static const char *mux_pllp_clkm[] = {
+ "pll_p", "clk_m"
+};
+static u32 mux_pllp_clkm_idx[] = {
+ [0] = 0, [1] = 3,
+};
+
+static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
+ "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
+};
+#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx
+
+static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
+ "pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c",
+ "pll_d2_out0", "clk_m"
+};
+#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL
+
+static const char *mux_pllm_pllc_pllp_plla[] = {
+ "pll_m", "pll_c", "pll_p", "pll_a_out0"
+};
+#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
+
+static const char *mux_pllp_pllc_clkm[] = {
+ "pll_p", "pll_c", "pll_m"
+};
+static u32 mux_pllp_pllc_clkm_idx[] = {
+ [0] = 0, [1] = 1, [2] = 3,
+};
+
+static const char *mux_pllp_pllc_clkm_clk32[] = {
+ "pll_p", "pll_c", "clk_m", "clk_32k"
+};
+#define mux_pllp_pllc_clkm_clk32_idx NULL
+
+static const char *mux_plla_clk32_pllp_clkm_plle[] = {
+ "pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0"
+};
+#define mux_plla_clk32_pllp_clkm_plle_idx NULL
+
+static const char *mux_clkm_pllp_pllc_pllre[] = {
+ "clk_m", "pll_p", "pll_c", "pll_re_out"
+};
+static u32 mux_clkm_pllp_pllc_pllre_idx[] = {
+ [0] = 0, [1] = 1, [2] = 3, [3] = 5,
+};
+
+static const char *mux_clkm_48M_pllp_480M[] = {
+ "clk_m", "pll_u_48M", "pll_p", "pll_u_480M"
+};
+#define mux_clkm_48M_pllp_480M_idx NULL
+
+static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
+ "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
+};
+static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
+ [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
+};
+
+static const char *mux_plld_out0_plld2_out0[] = {
+ "pll_d_out0", "pll_d2_out0",
+};
+#define mux_plld_out0_plld2_out0_idx NULL
+
+static const char *mux_d_audio_clk[] = {
+ "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
+ "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+};
+static u32 mux_d_audio_clk_idx[] = {
+ [0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001,
+ [5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007,
+};
+
+static const struct clk_div_table pll_re_div_table[] = {
+ { .val = 0, .div = 1 },
+ { .val = 1, .div = 2 },
+ { .val = 2, .div = 3 },
+ { .val = 3, .div = 4 },
+ { .val = 4, .div = 5 },
+ { .val = 5, .div = 6 },
+ { .val = 0, .div = 0 },
+};
+
+static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
+
+static unsigned long osc_freq;
+static unsigned long pll_ref_freq;
+
+static int __init tegra114_osc_clk_init(void __iomem *clk_base)
+{
+ struct clk *clk;
+ u32 val, pll_ref_div;
+
+ val = readl_relaxed(clk_base + OSC_CTRL);
+
+ osc_freq = tegra114_input_freq[val >> OSC_CTRL_OSC_FREQ_SHIFT];
+ if (!osc_freq) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ /* clk_m */
+ clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
+ osc_freq);
+ clk_register_clkdev(clk, "clk_m", NULL);
+ clks[clk_m] = clk;
+
+ /* pll_ref */
+ val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
+ pll_ref_div = 1 << val;
+ clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
+ CLK_SET_RATE_PARENT, 1, pll_ref_div);
+ clk_register_clkdev(clk, "pll_ref", NULL);
+ clks[pll_ref] = clk;
+
+ pll_ref_freq = osc_freq / pll_ref_div;
+
+ return 0;
+}
+
+static void __init tegra114_fixed_clk_init(void __iomem *clk_base)
+{
+ struct clk *clk;
+
+ /* clk_32k */
+ clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT,
+ 32768);
+ clk_register_clkdev(clk, "clk_32k", NULL);
+ clks[clk_32k] = clk;
+
+ /* clk_m_div2 */
+ clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "clk_m_div2", NULL);
+ clks[clk_m_div2] = clk;
+
+ /* clk_m_div4 */
+ clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
+ CLK_SET_RATE_PARENT, 1, 4);
+ clk_register_clkdev(clk, "clk_m_div4", NULL);
+ clks[clk_m_div4] = clk;
+
+}
+
+static __init void tegra114_utmi_param_configure(void __iomem *clk_base)
+{
+ u32 reg;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+ if (osc_freq == utmi_parameters[i].osc_frequency)
+ break;
+ }
+
+ if (i >= ARRAY_SIZE(utmi_parameters)) {
+ pr_err("%s: Unexpected oscillator freq %lu\n", __func__,
+ osc_freq);
+ return;
+ }
+
+ reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+
+ /* Program UTMIP PLL stable and active counts */
+ /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
+ reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+ reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count);
+
+ reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+
+ reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].
+ active_delay_count);
+
+ /* Remove power downs from UTMIP PLL control bits */
+ reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+ reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+ reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+
+ writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+ /* Program UTMIP PLL delay and oscillator frequency counts */
+ reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+ reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+
+ reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].
+ enable_delay_count);
+
+ reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+ reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i].
+ xtal_freq_count);
+
+ /* Remove power downs from UTMIP PLL control bits */
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+ writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+ /* Setup HW control of UTMIPLL */
+ reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+ reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+ reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+ reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
+ writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+ reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+ writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+ udelay(1);
+
+ /* Setup SW override of UTMIPLL assuming USB2.0
+ ports are assigned to USB2 */
+ reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+ reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
+ reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+ writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+ udelay(1);
+
+ /* Enable HW control UTMIPLL */
+ reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+ reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+ writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+}
+
+static void __init _clip_vco_min(struct tegra_clk_pll_params *pll_params)
+{
+ pll_params->vco_min =
+ DIV_ROUND_UP(pll_params->vco_min, pll_ref_freq) * pll_ref_freq;
+}
+
+static int __init _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
+ void __iomem *clk_base)
+{
+ u32 val;
+ u32 step_a, step_b;
+
+ switch (pll_ref_freq) {
+ case 12000000:
+ case 13000000:
+ case 26000000:
+ step_a = 0x2B;
+ step_b = 0x0B;
+ break;
+ case 16800000:
+ step_a = 0x1A;
+ step_b = 0x09;
+ break;
+ case 19200000:
+ step_a = 0x12;
+ step_b = 0x08;
+ break;
+ default:
+ pr_err("%s: Unexpected reference rate %lu\n",
+ __func__, pll_ref_freq);
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ val = step_a << pll_params->stepa_shift;
+ val |= step_b << pll_params->stepb_shift;
+ writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
+
+ return 0;
+}
+
+static void __init _init_iddq(struct tegra_clk_pll_params *pll_params,
+ void __iomem *clk_base)
+{
+ u32 val, val_iddq;
+
+ val = readl_relaxed(clk_base + pll_params->base_reg);
+ val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
+
+ if (val & BIT(30))
+ WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
+ else {
+ val_iddq |= BIT(pll_params->iddq_bit_idx);
+ writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
+ }
+}
+
+static void __init tegra114_pll_init(void __iomem *clk_base,
+ void __iomem *pmc)
+{
+ struct clk *clk;
+
+ /* PLLC */
+ _clip_vco_min(&pll_c_params);
+ if (_setup_dynamic_ramp(&pll_c_params, clk_base) >= 0) {
+ _init_iddq(&pll_c_params, clk_base);
+ clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
+ pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK,
+ pll_c_freq_table, NULL);
+ clk_register_clkdev(clk, "pll_c", NULL);
+ clks[pll_c] = clk;
+
+ /* PLLC_OUT1 */
+ clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+ clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+ 8, 8, 1, NULL);
+ clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+ clk_base + PLLC_OUT, 1, 0,
+ CLK_SET_RATE_PARENT, 0, NULL);
+ clk_register_clkdev(clk, "pll_c_out1", NULL);
+ clks[pll_c_out1] = clk;
+ }
+
+ /* PLLC2 */
+ _clip_vco_min(&pll_c2_params);
+ clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0,
+ &pll_c2_params, TEGRA_PLL_USE_LOCK,
+ pll_cx_freq_table, NULL);
+ clk_register_clkdev(clk, "pll_c2", NULL);
+ clks[pll_c2] = clk;
+
+ /* PLLC3 */
+ _clip_vco_min(&pll_c3_params);
+ clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0,
+ &pll_c3_params, TEGRA_PLL_USE_LOCK,
+ pll_cx_freq_table, NULL);
+ clk_register_clkdev(clk, "pll_c3", NULL);
+ clks[pll_c3] = clk;
+
+ /* PLLP */
+ clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0,
+ 408000000, &pll_p_params,
+ TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
+ pll_p_freq_table, NULL);
+ clk_register_clkdev(clk, "pll_p", NULL);
+ clks[pll_p] = clk;
+
+ /* PLLP_OUT1 */
+ clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p",
+ clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
+ TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock);
+ clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div",
+ clk_base + PLLP_OUTA, 1, 0,
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+ &pll_div_lock);
+ clk_register_clkdev(clk, "pll_p_out1", NULL);
+ clks[pll_p_out1] = clk;
+
+ /* PLLP_OUT2 */
+ clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
+ clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
+ TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
+ &pll_div_lock);
+ clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
+ clk_base + PLLP_OUTA, 17, 16,
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+ &pll_div_lock);
+ clk_register_clkdev(clk, "pll_p_out2", NULL);
+ clks[pll_p_out2] = clk;
+
+ /* PLLP_OUT3 */
+ clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p",
+ clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
+ TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock);
+ clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div",
+ clk_base + PLLP_OUTB, 1, 0,
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+ &pll_div_lock);
+ clk_register_clkdev(clk, "pll_p_out3", NULL);
+ clks[pll_p_out3] = clk;
+
+ /* PLLP_OUT4 */
+ clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p",
+ clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
+ TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
+ &pll_div_lock);
+ clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div",
+ clk_base + PLLP_OUTB, 17, 16,
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+ &pll_div_lock);
+ clk_register_clkdev(clk, "pll_p_out4", NULL);
+ clks[pll_p_out4] = clk;
+
+ /* PLLM */
+ _clip_vco_min(&pll_m_params);
+ clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
+ &pll_m_params, TEGRA_PLL_USE_LOCK,
+ pll_m_freq_table, NULL);
+ clk_register_clkdev(clk, "pll_m", NULL);
+ clks[pll_m] = clk;
+
+ /* PLLM_OUT1 */
+ clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
+ clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+ 8, 8, 1, NULL);
+ clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
+ clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+ CLK_SET_RATE_PARENT, 0, NULL);
+ clk_register_clkdev(clk, "pll_m_out1", NULL);
+ clks[pll_m_out1] = clk;
+
+ /* PLLX */
+ _clip_vco_min(&pll_x_params);
+ if (_setup_dynamic_ramp(&pll_x_params, clk_base) >= 0) {
+ _init_iddq(&pll_c_params, clk_base);
+ clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
+ pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params,
+ TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL);
+ clk_register_clkdev(clk, "pll_x", NULL);
+ clks[pll_x] = clk;
+ }
+
+ /* PLLX_OUT0 */
+ clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll_x_out0", NULL);
+ clks[pll_x_out0] = clk;
+
+ /* PLLU */
+ clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0,
+ 0, &pll_u_params, TEGRA_PLLU |
+ TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+ TEGRA_PLL_USE_LOCK, pll_u_freq_table, &pll_u_lock);
+ clk_register_clkdev(clk, "pll_u", NULL);
+ clks[pll_u] = clk;
+
+ tegra114_utmi_param_configure(clk_base);
+
+ /* PLLU_480M */
+ clk = clk_register_gate(NULL, "pll_u_480M", "pll_u",
+ CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+ 22, 0, &pll_u_lock);
+ clk_register_clkdev(clk, "pll_u_480M", NULL);
+ clks[pll_u_480M] = clk;
+
+ /* PLLU_60M */
+ clk = clk_register_fixed_factor(NULL, "pll_u_60M_div", "pll_u",
+ CLK_SET_RATE_PARENT, 1, 8);
+ clk = clk_register_gate(NULL, "pll_u_60M", "pll_u_60M_div",
+ CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+ 23, 0, &pll_u_lock);
+ clk_register_clkdev(clk, "pll_u_60M", NULL);
+ clks[pll_u_60M] = clk;
+
+ /* PLLU_48M */
+ clk = clk_register_fixed_factor(NULL, "pll_u_48M_div", "pll_u",
+ CLK_SET_RATE_PARENT, 1, 10);
+ clk = clk_register_gate(NULL, "pll_u_48M", "pll_u_48M_div",
+ CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+ 25, 0, &pll_u_lock);
+ clk_register_clkdev(clk, "pll_u_48M", NULL);
+ clks[pll_u_48M] = clk;
+
+ /* PLLU_12M */
+ clk = clk_register_fixed_factor(NULL, "pll_u_12M_div", "pll_u",
+ CLK_SET_RATE_PARENT, 1, 40);
+ clk = clk_register_gate(NULL, "pll_u_12M", "pll_u_12M_div",
+ CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+ 21, 0, &pll_u_lock);
+ clk_register_clkdev(clk, "pll_u_12M", NULL);
+ clks[pll_u_12M] = clk;
+
+ /* PLLD */
+ clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0,
+ 0, &pll_d_params,
+ TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+ TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d_lock);
+ clk_register_clkdev(clk, "pll_d", NULL);
+ clks[pll_d] = clk;
+
+ /* PLLD_OUT0 */
+ clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll_d_out0", NULL);
+ clks[pll_d_out0] = clk;
+
+ /* PLLD2 */
+ clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc, 0,
+ 0, &pll_d2_params,
+ TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+ TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d2_lock);
+ clk_register_clkdev(clk, "pll_d2", NULL);
+ clks[pll_d2] = clk;
+
+ /* PLLD2_OUT0 */
+ clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
+ CLK_SET_RATE_PARENT, 1, 2);
+ clk_register_clkdev(clk, "pll_d2_out0", NULL);
+ clks[pll_d2_out0] = clk;
+
+ /* PLLA */
+ clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0,
+ 0, &pll_a_params, TEGRA_PLL_HAS_CPCON |
+ TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL);
+ clk_register_clkdev(clk, "pll_a", NULL);
+ clks[pll_a] = clk;
+
+ /* PLLA_OUT0 */
+ clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
+ clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+ 8, 8, 1, NULL);
+ clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
+ clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
+ CLK_SET_RATE_PARENT, 0, NULL);
+ clk_register_clkdev(clk, "pll_a_out0", NULL);
+ clks[pll_a_out0] = clk;
+
+ /* PLLRE */
+ _clip_vco_min(&pll_re_vco_params);
+ clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
+ 0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK,
+ NULL, &pll_re_lock, pll_ref_freq);
+ clk_register_clkdev(clk, "pll_re_vco", NULL);
+ clks[pll_re_vco] = clk;
+
+ clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0,
+ clk_base + PLLRE_BASE, 16, 4, 0,
+ pll_re_div_table, &pll_re_lock);
+ clk_register_clkdev(clk, "pll_re_out", NULL);
+ clks[pll_re_out] = clk;
+
+ /* PLLE */
+ clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_re_vco",
+ clk_base, 0, 100000000, &pll_e_params,
+ pll_e_freq_table, NULL);
+ clk_register_clkdev(clk, "pll_e_out0", NULL);
+ clks[pll_e_out0] = clk;
+}
+
+static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
+ "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+};
+
+static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
+ "clk_m_div4", "extern1",
+};
+
+static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
+ "clk_m_div4", "extern2",
+};
+
+static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
+ "clk_m_div4", "extern3",
+};
+
+static void __init tegra114_audio_clk_init(void __iomem *clk_base)
+{
+ struct clk *clk;
+
+ /* spdif_in_sync */
+ clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000,
+ 24000000);
+ clk_register_clkdev(clk, "spdif_in_sync", NULL);
+ clks[spdif_in_sync] = clk;
+
+ /* i2s0_sync */
+ clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000);
+ clk_register_clkdev(clk, "i2s0_sync", NULL);
+ clks[i2s0_sync] = clk;
+
+ /* i2s1_sync */
+ clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000);
+ clk_register_clkdev(clk, "i2s1_sync", NULL);
+ clks[i2s1_sync] = clk;
+
+ /* i2s2_sync */
+ clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000);
+ clk_register_clkdev(clk, "i2s2_sync", NULL);
+ clks[i2s2_sync] = clk;
+
+ /* i2s3_sync */
+ clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000);
+ clk_register_clkdev(clk, "i2s3_sync", NULL);
+ clks[i2s3_sync] = clk;
+
+ /* i2s4_sync */
+ clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000);
+ clk_register_clkdev(clk, "i2s4_sync", NULL);
+ clks[i2s4_sync] = clk;
+
+ /* vimclk_sync */
+ clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000);
+ clk_register_clkdev(clk, "vimclk_sync", NULL);
+ clks[vimclk_sync] = clk;
+
+ /* audio0 */
+ clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
+ ARRAY_SIZE(mux_audio_sync_clk), 0,
+ clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0,
+ NULL);
+ clks[audio0_mux] = clk;
+ clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0,
+ clk_base + AUDIO_SYNC_CLK_I2S0, 4,
+ CLK_GATE_SET_TO_DISABLE, NULL);
+ clk_register_clkdev(clk, "audio0", NULL);
+ clks[audio0] = clk;
+
+ /* audio1 */
+ clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
+ ARRAY_SIZE(mux_audio_sync_clk), 0,
+ clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0,
+ NULL);
+ clks[audio1_mux] = clk;
+ clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0,
+ clk_base + AUDIO_SYNC_CLK_I2S1, 4,
+ CLK_GATE_SET_TO_DISABLE, NULL);
+ clk_register_clkdev(clk, "audio1", NULL);
+ clks[audio1] = clk;
+
+ /* audio2 */
+ clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
+ ARRAY_SIZE(mux_audio_sync_clk), 0,
+ clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0,
+ NULL);
+ clks[audio2_mux] = clk;
+ clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0,
+ clk_base + AUDIO_SYNC_CLK_I2S2, 4,
+ CLK_GATE_SET_TO_DISABLE, NULL);
+ clk_register_clkdev(clk, "audio2", NULL);
+ clks[audio2] = clk;
+
+ /* audio3 */
+ clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
+ ARRAY_SIZE(mux_audio_sync_clk), 0,
+ clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0,
+ NULL);
+ clks[audio3_mux] = clk;
+ clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0,
+ clk_base + AUDIO_SYNC_CLK_I2S3, 4,
+ CLK_GATE_SET_TO_DISABLE, NULL);
+ clk_register_clkdev(clk, "audio3", NULL);
+ clks[audio3] = clk;
+
+ /* audio4 */
+ clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
+ ARRAY_SIZE(mux_audio_sync_clk), 0,
+ clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0,
+ NULL);
+ clks[audio4_mux] = clk;
+ clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0,
+ clk_base + AUDIO_SYNC_CLK_I2S4, 4,
+ CLK_GATE_SET_TO_DISABLE, NULL);
+ clk_register_clkdev(clk, "audio4", NULL);
+ clks[audio4] = clk;
+
+ /* spdif */
+ clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
+ ARRAY_SIZE(mux_audio_sync_clk), 0,
+ clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0,
+ NULL);
+ clks[spdif_mux] = clk;
+ clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0,
+ clk_base + AUDIO_SYNC_CLK_SPDIF, 4,
+ CLK_GATE_SET_TO_DISABLE, NULL);
+ clk_register_clkdev(clk, "spdif", NULL);
+ clks[spdif] = clk;
+
+ /* audio0_2x */
+ clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0",
+ CLK_SET_RATE_PARENT, 2, 1);
+ clk = tegra_clk_register_divider("audio0_div", "audio0_doubler",
+ clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1,
+ 0, &clk_doubler_lock);
+ clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div",
+ TEGRA_PERIPH_NO_RESET, clk_base,
+ CLK_SET_RATE_PARENT, 113, &periph_v_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "audio0_2x", NULL);
+ clks[audio0_2x] = clk;
+
+ /* audio1_2x */
+ clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1",
+ CLK_SET_RATE_PARENT, 2, 1);
+ clk = tegra_clk_register_divider("audio1_div", "audio1_doubler",
+ clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1,
+ 0, &clk_doubler_lock);
+ clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div",
+ TEGRA_PERIPH_NO_RESET, clk_base,
+ CLK_SET_RATE_PARENT, 114, &periph_v_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "audio1_2x", NULL);
+ clks[audio1_2x] = clk;
+
+ /* audio2_2x */
+ clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2",
+ CLK_SET_RATE_PARENT, 2, 1);
+ clk = tegra_clk_register_divider("audio2_div", "audio2_doubler",
+ clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1,
+ 0, &clk_doubler_lock);
+ clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div",
+ TEGRA_PERIPH_NO_RESET, clk_base,
+ CLK_SET_RATE_PARENT, 115, &periph_v_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "audio2_2x", NULL);
+ clks[audio2_2x] = clk;
+
+ /* audio3_2x */
+ clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3",
+ CLK_SET_RATE_PARENT, 2, 1);
+ clk = tegra_clk_register_divider("audio3_div", "audio3_doubler",
+ clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1,
+ 0, &clk_doubler_lock);
+ clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div",
+ TEGRA_PERIPH_NO_RESET, clk_base,
+ CLK_SET_RATE_PARENT, 116, &periph_v_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "audio3_2x", NULL);
+ clks[audio3_2x] = clk;
+
+ /* audio4_2x */
+ clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4",
+ CLK_SET_RATE_PARENT, 2, 1);
+ clk = tegra_clk_register_divider("audio4_div", "audio4_doubler",
+ clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1,
+ 0, &clk_doubler_lock);
+ clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div",
+ TEGRA_PERIPH_NO_RESET, clk_base,
+ CLK_SET_RATE_PARENT, 117, &periph_v_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "audio4_2x", NULL);
+ clks[audio4_2x] = clk;
+
+ /* spdif_2x */
+ clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif",
+ CLK_SET_RATE_PARENT, 2, 1);
+ clk = tegra_clk_register_divider("spdif_div", "spdif_doubler",
+ clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1,
+ 0, &clk_doubler_lock);
+ clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div",
+ TEGRA_PERIPH_NO_RESET, clk_base,
+ CLK_SET_RATE_PARENT, 118,
+ &periph_v_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "spdif_2x", NULL);
+ clks[spdif_2x] = clk;
+}
+
+static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
+{
+ struct clk *clk;
+
+ /* clk_out_1 */
+ clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
+ ARRAY_SIZE(clk_out1_parents), 0,
+ pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
+ &clk_out_lock);
+ clks[clk_out_1_mux] = clk;
+ clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0,
+ pmc_base + PMC_CLK_OUT_CNTRL, 2, 0,
+ &clk_out_lock);
+ clk_register_clkdev(clk, "extern1", "clk_out_1");
+ clks[clk_out_1] = clk;
+
+ /* clk_out_2 */
+ clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
+ ARRAY_SIZE(clk_out1_parents), 0,
+ pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
+ &clk_out_lock);
+ clks[clk_out_2_mux] = clk;
+ clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
+ pmc_base + PMC_CLK_OUT_CNTRL, 10, 0,
+ &clk_out_lock);
+ clk_register_clkdev(clk, "extern2", "clk_out_2");
+ clks[clk_out_2] = clk;
+
+ /* clk_out_3 */
+ clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
+ ARRAY_SIZE(clk_out1_parents), 0,
+ pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
+ &clk_out_lock);
+ clks[clk_out_3_mux] = clk;
+ clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
+ pmc_base + PMC_CLK_OUT_CNTRL, 18, 0,
+ &clk_out_lock);
+ clk_register_clkdev(clk, "extern3", "clk_out_3");
+ clks[clk_out_3] = clk;
+
+ /* blink */
+ clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
+ pmc_base + PMC_DPD_PADS_ORIDE,
+ PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
+ clk = clk_register_gate(NULL, "blink", "blink_override", 0,
+ pmc_base + PMC_CTRL,
+ PMC_CTRL_BLINK_ENB, 0, NULL);
+ clk_register_clkdev(clk, "blink", NULL);
+ clks[blink] = clk;
+
+}
+
+static __initdata struct tegra_periph_init_data tegra_periph_clk_list[] = {
+ TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0),
+ TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1),
+ TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2),
+ TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3),
+ TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4),
+ TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out),
+ TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in),
+ TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, &periph_l_regs, TEGRA_PERIPH_ON_APB, pwm),
+ TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, &periph_w_regs, TEGRA_PERIPH_ON_APB, adx),
+ TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, amx),
+ TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda),
+ TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda2codec_2x),
+ TEGRA_INIT_DATA_MUX("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1),
+ TEGRA_INIT_DATA_MUX("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2),
+ TEGRA_INIT_DATA_MUX("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3),
+ TEGRA_INIT_DATA_MUX("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4),
+ TEGRA_INIT_DATA_MUX("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5),
+ TEGRA_INIT_DATA_MUX("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6),
+ TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
+ TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
+ TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir),
+ TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1),
+ TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2),
+ TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3),
+ TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4),
+ TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde),
+ TEGRA_INIT_DATA_MUX("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, csite),
+ TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, la),
+ TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, trace),
+ TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr),
+ TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor),
+ TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi),
+ TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, i2c1),
+ TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, i2c2),
+ TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, i2c3),
+ TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, i2c4),
+ TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, i2c5),
+ TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, uarta),
+ TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, uartb),
+ TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, uartc),
+ TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, uartd),
+ TEGRA_INIT_DATA_UART("uarte", NULL, "tegra_uart.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, &periph_u_regs, uarte),
+ TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, gr_3d),
+ TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr_2d),
+ TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
+ TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi),
+ TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp),
+ TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_h_regs, TEGRA_PERIPH_WAR_1005168, msenc),
+ TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec),
+ TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x),
+ TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi),
+ TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, &periph_w_regs, 0, cilab),
+ TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, &periph_w_regs, 0, cilcd),
+ TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, &periph_w_regs, 0, cile),
+ TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, &periph_w_regs, 0, dsialp),
+ TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, &periph_w_regs, 0, dsiblp),
+ TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor),
+ TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, actmon),
+ TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, extern1),
+ TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, extern2),
+ TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, extern3),
+ TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
+ TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se),
+ TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED),
+ TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm),
+ TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src),
+ TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src),
+ TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_fs_src),
+ TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_ss_src),
+ TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, &periph_u_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_dev_src),
+ TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, TEGRA_PERIPH_ON_APB, d_audio),
+ TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam0),
+ TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam1),
+ TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam2),
+};
+
+static __initdata struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
+ TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 3, 27, &periph_l_regs, 0, disp1),
+ TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 3, 26, &periph_l_regs, 0, disp2),
+};
+
+static __init void tegra114_periph_clk_init(void __iomem *clk_base)
+{
+ struct tegra_periph_init_data *data;
+ struct clk *clk;
+ int i;
+ u32 val;
+
+ /* apbdma */
+ clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base,
+ 0, 34, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "apbdma", "tegra-dma");
+ clks[apbdma] = clk;
+
+ /* rtc */
+ clk = tegra_clk_register_periph_gate("rtc", "clk_32k",
+ TEGRA_PERIPH_ON_APB |
+ TEGRA_PERIPH_NO_RESET, clk_base,
+ 0, 4, &periph_l_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, NULL, "rtc-tegra");
+ clks[rtc] = clk;
+
+ /* kbc */
+ clk = tegra_clk_register_periph_gate("kbc", "clk_32k",
+ TEGRA_PERIPH_ON_APB |
+ TEGRA_PERIPH_NO_RESET, clk_base,
+ 0, 36, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, NULL, "tegra-kbc");
+ clks[kbc] = clk;
+
+ /* timer */
+ clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base,
+ 0, 5, &periph_l_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, NULL, "timer");
+ clks[timer] = clk;
+
+ /* kfuse */
+ clk = tegra_clk_register_periph_gate("kfuse", "clk_m",
+ TEGRA_PERIPH_ON_APB, clk_base, 0, 40,
+ &periph_h_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, NULL, "kfuse-tegra");
+ clks[kfuse] = clk;
+
+ /* fuse */
+ clk = tegra_clk_register_periph_gate("fuse", "clk_m",
+ TEGRA_PERIPH_ON_APB, clk_base, 0, 39,
+ &periph_h_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "fuse", "fuse-tegra");
+ clks[fuse] = clk;
+
+ /* fuse_burn */
+ clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m",
+ TEGRA_PERIPH_ON_APB, clk_base, 0, 39,
+ &periph_h_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "fuse_burn", "fuse-tegra");
+ clks[fuse_burn] = clk;
+
+ /* apbif */
+ clk = tegra_clk_register_periph_gate("apbif", "clk_m",
+ TEGRA_PERIPH_ON_APB, clk_base, 0, 107,
+ &periph_v_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "apbif", "tegra30-ahub");
+ clks[apbif] = clk;
+
+ /* hda2hdmi */
+ clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m",
+ TEGRA_PERIPH_ON_APB, clk_base, 0, 128,
+ &periph_w_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "hda2hdmi", "tegra30-hda");
+ clks[hda2hdmi] = clk;
+
+ /* vcp */
+ clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0,
+ 29, &periph_l_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "vcp", "tegra-avp");
+ clks[vcp] = clk;
+
+ /* bsea */
+ clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base,
+ 0, 62, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "bsea", "tegra-avp");
+ clks[bsea] = clk;
+
+ /* bsev */
+ clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base,
+ 0, 63, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "bsev", "tegra-aes");
+ clks[bsev] = clk;
+
+ /* mipi-cal */
+ clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base,
+ 0, 56, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "mipi-cal", "mipi-cal");
+ clks[mipi_cal] = clk;
+
+ /* usbd */
+ clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base,
+ 0, 22, &periph_l_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "usbd", "tegra-udc.0");
+ clks[usbd] = clk;
+
+ /* usb2 */
+ clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base,
+ 0, 58, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "usb2", "tegra-ehci.1");
+ clks[usb2] = clk;
+
+ /* usb3 */
+ clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base,
+ 0, 59, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "usb3", "tegra-ehci.2");
+ clks[usb3] = clk;
+
+ /* dsi1-fixed */
+ clk = clk_register_fixed_factor(NULL, "dsi1-fixed", "pll_p_out3",
+ CLK_SET_RATE_PARENT, 1, 1);
+ clks[dsi1_fixed] = clk;
+
+ /* dsi2-fixed */
+ clk = clk_register_fixed_factor(NULL, "dsi2-fixed", "pll_p_out3",
+ CLK_SET_RATE_PARENT, 1, 1);
+ clks[dsi2_fixed] = clk;
+
+ /* mipi-cal-fast */
+ clk = clk_register_fixed_factor(NULL, "mipi-cal-fast", "pll_p_out3",
+ CLK_SET_RATE_PARENT, 1, 1);
+ clk_register_clkdev(clk, "fast-clk", "mipi-cal");
+ clks[mipi_cal_fast] = clk;
+
+ /* csi */
+ clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base,
+ 0, 52, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clks[csi] = clk;
+
+ /* isp */
+ clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0,
+ 23, &periph_l_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "isp", "tegra_camera");
+ clks[isp] = clk;
+
+ /* csus */
+ clk = tegra_clk_register_periph_gate("csus", "clk_m",
+ TEGRA_PERIPH_NO_RESET, clk_base, 0, 92,
+ &periph_u_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "csus", "tegra_camera");
+ clks[csus] = clk;
+
+ /* dds */
+ clk = tegra_clk_register_periph_gate("dds", "clk_m",
+ TEGRA_PERIPH_ON_APB, clk_base, 0, 150,
+ &periph_w_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "dds", "dds");
+ clks[dds] = clk;
+
+ /* dp2 */
+ clk = tegra_clk_register_periph_gate("dp2", "clk_m",
+ TEGRA_PERIPH_ON_APB, clk_base, 0, 152,
+ &periph_w_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "dp2", "dp2");
+ clks[dp2] = clk;
+
+ /* dtv */
+ clk = tegra_clk_register_periph_gate("dtv", "clk_m",
+ TEGRA_PERIPH_ON_APB, clk_base, 0, 79,
+ &periph_u_regs, periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, NULL, "dtv");
+ clks[dtv] = clk;
+
+ /* dsia */
+ clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
+ ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+ clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
+ clks[dsia_mux] = clk;
+ clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
+ 0, 48, &periph_h_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "dsia", "tegradc.0");
+ clks[dsia] = clk;
+
+ /* dsib */
+ clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
+ ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+ clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
+ clks[dsib_mux] = clk;
+ clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
+ 0, 82, &periph_u_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "dsib", "tegradc.1");
+ clks[dsib] = clk;
+
+ /* xusb_hs_src */
+ val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC);
+ val |= BIT(25); /* always select PLLU_60M */
+ writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC);
+
+ clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0,
+ 1, 1);
+ clks[xusb_hs_src] = clk;
+
+ /* xusb_host */
+ clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0,
+ clk_base, 0, 89, &periph_u_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "tegra_xhci", "host");
+ clks[xusb_host] = clk;
+
+ /* xusb_ss */
+ clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0,
+ clk_base, 0, 156, &periph_w_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "tegra_xhci", "ss");
+ clks[xusb_host] = clk;
+
+ /* xusb_dev */
+ clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0,
+ clk_base, 0, 95, &periph_u_regs,
+ periph_clk_enb_refcnt);
+ clk_register_clkdev(clk, "tegra_xhci", "dev");
+
+ for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
+ data = &tegra_periph_clk_list[i];
+ clk = tegra_clk_register_periph(data->name, data->parent_names,
+ data->num_parents, &data->periph,
+ clk_base, data->offset, data->flags);
+ clk_register_clkdev(clk, data->con_id, data->dev_id);
+ clks[data->clk_id] = clk;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
+ data = &tegra_periph_nodiv_clk_list[i];
+ clk = tegra_clk_register_periph_nodiv(data->name,
+ data->parent_names, data->num_parents,
+ &data->periph, clk_base, data->offset);
+ clk_register_clkdev(clk, data->con_id, data->dev_id);
+ clks[data->clk_id] = clk;
+ }
+}
+
+static struct tegra_cpu_car_ops tegra114_cpu_car_ops;
+
+static const struct of_device_id pmc_match[] __initconst = {
+ { .compatible = "nvidia,tegra114-pmc" },
+ {},
+};
+
+static __initdata struct tegra_clk_init_table init_table[] = {
+ {uartd, pll_p, 408000000, 1},
+ {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
+};
+
+void __init tegra114_clock_init(struct device_node *np)
+{
+ struct device_node *node;
+ int i;
+
+ clk_base = of_iomap(np, 0);
+ if (!clk_base) {
+ pr_err("ioremap tegra114 CAR failed\n");
+ return;
+ }
+
+ node = of_find_matching_node(NULL, pmc_match);
+ if (!node) {
+ pr_err("Failed to find pmc node\n");
+ WARN_ON(1);
+ return;
+ }
+
+ pmc_base = of_iomap(node, 0);
+ if (!pmc_base) {
+ pr_err("Can't map pmc registers\n");
+ WARN_ON(1);
+ return;
+ }
+
+ if (tegra114_osc_clk_init(clk_base) < 0)
+ return;
+
+ tegra114_fixed_clk_init(clk_base);
+ tegra114_pll_init(clk_base, pmc_base);
+ tegra114_periph_clk_init(clk_base);
+ tegra114_audio_clk_init(clk_base);
+ tegra114_pmc_clk_init(pmc_base);
+
+ for (i = 0; i < ARRAY_SIZE(clks); i++) {
+ if (IS_ERR(clks[i])) {
+ pr_err
+ ("Tegra114 clk %d: register failed with %ld\n",
+ i, PTR_ERR(clks[i]));
+ }
+ if (!clks[i])
+ clks[i] = ERR_PTR(-EINVAL);
+ }
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+ tegra_init_from_table(init_table, clks, clk_max);
+
+ tegra_cpu_car_ops = &tegra114_cpu_car_ops;
+}
^ permalink raw reply related [flat|nested] 34+ messages in thread
* [PATCH v5 10/10] clk: tegra: devicetree match for nvidia,tegra114-car
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
` (8 preceding siblings ...)
2013-02-01 10:18 ` [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114 Peter De Schrijver
@ 2013-02-01 10:18 ` Peter De Schrijver
2013-02-04 7:10 ` Prashant Gaikwad
9 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-01 10:18 UTC (permalink / raw)
To: pdeschrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, 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 8756d9f..8097850 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -576,4 +576,11 @@ void tegra30_clock_init(struct device_node *np);
static inline void tegra30_clock_init(struct device_node *np) {}
#endif /* CONFIG_ARCH_TEGRA_3x_SOC */
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+void tegra114_clock_init(struct device_node *np);
+#else
+static inline void tegra114_clock_init(struct device_node *np) {}
+#endif /* CONFIG_ARCH_TEGRA114_SOC */
+
+
#endif /* TEGRA_CLK_H */
^ permalink raw reply related [flat|nested] 34+ messages in thread
* Re: [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114
2013-02-01 10:18 ` [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114 Peter De Schrijver
@ 2013-02-01 19:40 ` Rhyland Klein
2013-02-04 6:35 ` Prashant Gaikwad
0 siblings, 1 reply; 34+ messages in thread
From: Rhyland Klein @ 2013-02-01 19:40 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Prashant Gaikwad, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, linux-arm-kernel
On 2/1/2013 5:18 AM, Peter De Schrijver wrote:
> Tegra114 introduces new PLL types. This requires new clocktypes as well
> as some new fields in the pll structure.
>
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
> drivers/clk/tegra/clk-pll.c | 719 +++++++++++++++++++++++++++++++++++++++++++
> drivers/clk/tegra/clk.h | 47 +++
> 2 files changed, 766 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
> index 87d2f34..50114b7 100644
> --- a/drivers/clk/tegra/clk-pll.c
> +++ b/drivers/clk/tegra/clk-pll.c
> [snip]
> +struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
> + void __iomem *clk_base, void __iomem *pmc,
> + unsigned long flags, unsigned long fixed_rate,
> + struct tegra_clk_pll_params *pll_params,
> + u32 pll_flags,
> + struct tegra_clk_pll_freq_table *freq_table,
> + spinlock_t *lock)
> +{
> + if (!pll_params->pdiv_tohw)
> + return -EINVAL;
> +
This will cause the following warning:
warning: return makes pointer from integer without a cast
Same with occurrences in tegra_clk_register_pllm and
tegra_clk_register_pllc.
Should this instead be returning NULL?
-rhyland
--
nvpublic
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 01/10] clk: tegra: Refactor PLL programming code
2013-02-01 10:18 ` [PATCH v5 01/10] clk: tegra: Refactor PLL programming code Peter De Schrijver
@ 2013-02-04 6:06 ` Prashant Gaikwad
2013-02-04 14:32 ` Peter De Schrijver
2013-02-04 21:57 ` Stephen Warren
1 sibling, 1 reply; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 6:06 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> Refactor the PLL programming code to make it useable by the new PLL types
> introduced by Tegra114.
>
> The following changes were done:
>
> * Split programming the PLL into updating m,n,p and updating cpcon
> * Move locking from _update_pll_cpcon() to clk_pll_set_rate()
> * Introduce _get_pll_mnp() helper
> * Move check for identical m,n,p values to clk_pll_set_rate()
> * struct tegra_clk_pll_freq_table will always contain the values as defined
> by the hardware.
> * Simplify the arguments to clk_pll_wait_for_lock()
>
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
> drivers/clk/tegra/clk-pll.c | 178 +++++++++++++++++------------
> drivers/clk/tegra/clk-tegra20.c | 144 ++++++++++++------------
> drivers/clk/tegra/clk-tegra30.c | 234 +++++++++++++++++++-------------------
> 3 files changed, 294 insertions(+), 262 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
> index 165f247..912c977 100644
> --- a/drivers/clk/tegra/clk-pll.c
> +++ b/drivers/clk/tegra/clk-pll.c
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
> + * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
> *
> * This program is free software; you can redistribute it and/or modify it
> * under the terms and conditions of the GNU General Public License,
> @@ -113,20 +113,23 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
> pll_writel_misc(val, pll);
> }
>
> -static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
> - void __iomem *lock_addr, u32 lock_bit_idx)
> +static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
> {
> int i;
> - u32 val;
> + u32 val, lock_bit;
> + void __iomem *lock_addr;
>
> if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
> udelay(pll->params->lock_delay);
> return 0;
> }
>
> + lock_addr = pll->clk_base + pll->params->base_reg;
This will not work for PLLE. Lock bit for PLLE is in misc register.
> + 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) {
Need to change the lock bit idx parameter for Tegra20 and Tegra30 PLLs
else this patch will break those.
> udelay(PLL_POST_LOCK_DELAY);
> return 0;
> }
> @@ -155,7 +158,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw)
> return val & PLL_BASE_ENABLE ? 1 : 0;
> }
<snip>
> @@ -538,8 +570,8 @@ static int clk_plle_enable(struct clk_hw *hw)
> val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
> pll_writel_base(val, pll);
>
> - clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg,
> - pll->params->lock_bit_idx);
> + clk_pll_wait_for_lock(pll);
> +
> return 0;
> }
<snip>
> static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
> /* 1.7 GHz */
> - { 12000000, 1700000000, 850, 6, 1, 8},
> - { 13000000, 1700000000, 915, 7, 1, 8}, /* actual: 1699.2 MHz */
> - { 16800000, 1700000000, 708, 7, 1, 8}, /* actual: 1699.2 MHz */
> - { 19200000, 1700000000, 885, 10, 1, 8}, /* actual: 1699.2 MHz */
> - { 26000000, 1700000000, 850, 13, 1, 8},
> + { 12000000, 1700000000, 850, 6, 0, 8},
> + { 13000000, 1700000000, 915, 7, 0, 8}, /* actual: 1699.2 MHz */
> + { 16800000, 1700000000, 708, 7, 0, 8}, /* actual: 1699.2 MHz */
> + { 19200000, 1700000000, 885, 10, 0, 8}, /* actual: 1699.2 MHz */
> + { 26000000, 1700000000, 850, 13, 0, 8},
>
> /* 1.6 GHz */
> - { 12000000, 1600000000, 800, 6, 1, 8},
> - { 13000000, 1600000000, 738, 6, 1, 8}, /* actual: 1599.0 MHz */
> - { 16800000, 1600000000, 857, 9, 1, 8}, /* actual: 1599.7 MHz */
> - { 19200000, 1600000000, 500, 6, 1, 8},
> - { 26000000, 1600000000, 800, 13, 1, 8},
> + { 12000000, 1600000000, 800, 6, 0, 8},
> + { 13000000, 1600000000, 738, 6, 0, 8}, /* actual: 1599.0 MHz */
> + { 16800000, 1600000000, 857, 9, 0, 8}, /* actual: 1599.7 MHz */
> + { 19200000, 1600000000, 500, 6, 0, 8},
> + { 26000000, 1600000000, 800, 13, 0, 8},
>
> /* 1.5 GHz */
> - { 12000000, 1500000000, 750, 6, 1, 8},
> - { 13000000, 1500000000, 923, 8, 1, 8}, /* actual: 1499.8 MHz */
> - { 16800000, 1500000000, 625, 7, 1, 8},
> - { 19200000, 1500000000, 625, 8, 1, 8},
> - { 26000000, 1500000000, 750, 13, 1, 8},
> + { 12000000, 1500000000, 750, 6, 0, 8},
> + { 13000000, 1500000000, 923, 8, 0, 8}, /* actual: 1499.8 MHz */
> + { 16800000, 1500000000, 625, 7, 0, 8},
> + { 19200000, 1500000000, 625, 8, 0, 8},
> + { 26000000, 1500000000, 750, 13, 0, 8},
>
> /* 1.4 GHz */
> - { 12000000, 1400000000, 700, 6, 1, 8},
> - { 13000000, 1400000000, 969, 9, 1, 8}, /* actual: 1399.7 MHz */
> - { 16800000, 1400000000, 1000, 12, 1, 8},
> - { 19200000, 1400000000, 875, 12, 1, 8},
> - { 26000000, 1400000000, 700, 13, 1, 8},
> + { 12000000, 1400000000, 700, 6, 0, 8},
> + { 13000000, 1400000000, 969, 9, 0, 8}, /* actual: 1399.7 MHz */
> + { 16800000, 1400000000, 1000, 12, 0, 8},
> + { 19200000, 1400000000, 875, 12, 0, 8},
> + { 26000000, 1400000000, 700, 13, 0, 8},
>
> /* 1.3 GHz */
> - { 12000000, 1300000000, 975, 9, 1, 8},
> - { 13000000, 1300000000, 1000, 10, 1, 8},
> - { 16800000, 1300000000, 928, 12, 1, 8}, /* actual: 1299.2 MHz */
> - { 19200000, 1300000000, 812, 12, 1, 8}, /* actual: 1299.2 MHz */
> - { 26000000, 1300000000, 650, 13, 1, 8},
> + { 12000000, 1300000000, 975, 9, 0, 8},
> + { 13000000, 1300000000, 1000, 10, 0, 8},
> + { 16800000, 1300000000, 928, 12, 0, 8}, /* actual: 1299.2 MHz */
> + { 19200000, 1300000000, 812, 12, 0, 8}, /* actual: 1299.2 MHz */
> + { 26000000, 1300000000, 650, 13, 0, 8},
>
> /* 1.2 GHz */
> - { 12000000, 1200000000, 1000, 10, 1, 8},
> - { 13000000, 1200000000, 923, 10, 1, 8}, /* actual: 1199.9 MHz */
> - { 16800000, 1200000000, 1000, 14, 1, 8},
> - { 19200000, 1200000000, 1000, 16, 1, 8},
> - { 26000000, 1200000000, 600, 13, 1, 8},
> + { 12000000, 1200000000, 1000, 10, 0, 8},
> + { 13000000, 1200000000, 923, 10, 0, 8}, /* actual: 1199.9 MHz */
> + { 16800000, 1200000000, 1000, 14, 0, 8},
> + { 19200000, 1200000000, 1000, 16, 0, 8},
> + { 26000000, 1200000000, 600, 13, 0, 8},
>
> /* 1.1 GHz */
> - { 12000000, 1100000000, 825, 9, 1, 8},
> - { 13000000, 1100000000, 846, 10, 1, 8}, /* actual: 1099.8 MHz */
> - { 16800000, 1100000000, 982, 15, 1, 8}, /* actual: 1099.8 MHz */
> - { 19200000, 1100000000, 859, 15, 1, 8}, /* actual: 1099.5 MHz */
> - { 26000000, 1100000000, 550, 13, 1, 8},
> + { 12000000, 1100000000, 825, 9, 0, 8},
> + { 13000000, 1100000000, 846, 10, 0, 8}, /* actual: 1099.8 MHz */
> + { 16800000, 1100000000, 982, 15, 0, 8}, /* actual: 1099.8 MHz */
> + { 19200000, 1100000000, 859, 15, 0, 8}, /* actual: 1099.5 MHz */
> + { 26000000, 1100000000, 550, 13, 0, 8},
>
> /* 1 GHz */
> - { 12000000, 1000000000, 1000, 12, 1, 8},
> - { 13000000, 1000000000, 1000, 13, 1, 8},
> - { 16800000, 1000000000, 833, 14, 1, 8}, /* actual: 999.6 MHz */
> - { 19200000, 1000000000, 625, 12, 1, 8},
> - { 26000000, 1000000000, 1000, 26, 1, 8},
> + { 12000000, 1000000000, 1000, 12, 0, 8},
> + { 13000000, 1000000000, 1000, 13, 0, 8},
> + { 16800000, 1000000000, 833, 14, 0, 8}, /* actual: 999.6 MHz */
> + { 19200000, 1000000000, 625, 12, 0, 8},
> + { 26000000, 1000000000, 1000, 26, 0, 8},
>
> { 0, 0, 0, 0, 0, 0 },
> };
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag
2013-02-01 10:18 ` [PATCH v5 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag Peter De Schrijver
@ 2013-02-04 6:13 ` Prashant Gaikwad
0 siblings, 0 replies; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 6:13 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> 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>
> ---
Looks good to me.
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
> drivers/clk/tegra/clk-pll.c | 15 ++++++++++-----
> drivers/clk/tegra/clk.h | 8 +++++---
> 2 files changed, 15 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
> index 912c977..3c3a25e 100644
> --- a/drivers/clk/tegra/clk-pll.c
> +++ b/drivers/clk/tegra/clk-pll.c
> @@ -166,7 +166,8 @@ static void _clk_pll_enable(struct clk_hw *hw)
> clk_pll_enable_lock(pll);
>
> val = pll_readl_base(pll);
> - val &= ~PLL_BASE_BYPASS;
> + if (pll->flags & TEGRA_PLL_BYPASS)
> + val &= ~PLL_BASE_BYPASS;
> val |= PLL_BASE_ENABLE;
> pll_writel_base(val, pll);
>
> @@ -183,7 +184,9 @@ static void _clk_pll_disable(struct clk_hw *hw)
> u32 val;
>
> val = pll_readl_base(pll);
> - val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
> + if (pll->flags & TEGRA_PLL_BYPASS)
> + val &= ~PLL_BASE_BYPASS;
> + val &= ~PLL_BASE_ENABLE;
> pll_writel_base(val, pll);
>
> if (pll->flags & TEGRA_PLLM) {
> @@ -454,7 +457,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
>
> val = pll_readl_base(pll);
>
> - if (val & PLL_BASE_BYPASS)
> + if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
> return parent_rate;
>
> if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
> @@ -660,9 +663,10 @@ static struct clk *_tegra_clk_register_pll(const char *name,
> struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
> void __iomem *clk_base, void __iomem *pmc,
> unsigned long flags, unsigned long fixed_rate,
> - struct tegra_clk_pll_params *pll_params, u8 pll_flags,
> + struct tegra_clk_pll_params *pll_params, u32 pll_flags,
> struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
> {
> + pll_flags |= TEGRA_PLL_BYPASS;
> return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
> flags, fixed_rate, pll_params, pll_flags, freq_table,
> lock, &tegra_clk_pll_ops);
> @@ -671,9 +675,10 @@ struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
> struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
> void __iomem *clk_base, void __iomem *pmc,
> unsigned long flags, unsigned long fixed_rate,
> - struct tegra_clk_pll_params *pll_params, u8 pll_flags,
> + struct tegra_clk_pll_params *pll_params, u32 pll_flags,
> struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
> {
> + pll_flags |= TEGRA_PLL_BYPASS;
> return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
> flags, fixed_rate, pll_params, pll_flags, freq_table,
> lock, &tegra_clk_plle_ops);
> diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
> index a09d7dc..3cff1df 100644
> --- a/drivers/clk/tegra/clk.h
> +++ b/drivers/clk/tegra/clk.h
> @@ -182,12 +182,13 @@ struct tegra_clk_pll_params {
> * TEGRA_PLL_FIXED - We are not supposed to change output frequency
> * of some plls.
> * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
> + * TEGRA_PLL_BYPASS - PLL has bypass bit
> */
> struct tegra_clk_pll {
> struct clk_hw hw;
> void __iomem *clk_base;
> void __iomem *pmc;
> - u8 flags;
> + u32 flags;
> unsigned long fixed_rate;
> spinlock_t *lock;
> u8 divn_shift;
> @@ -210,18 +211,19 @@ struct tegra_clk_pll {
> #define TEGRA_PLLM BIT(5)
> #define TEGRA_PLL_FIXED BIT(6)
> #define TEGRA_PLLE_CONFIGURE BIT(7)
> +#define TEGRA_PLL_BYPASS BIT(8)
>
> extern const struct clk_ops tegra_clk_pll_ops;
> extern const struct clk_ops tegra_clk_plle_ops;
> struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
> void __iomem *clk_base, void __iomem *pmc,
> unsigned long flags, unsigned long fixed_rate,
> - struct tegra_clk_pll_params *pll_params, u8 pll_flags,
> + struct tegra_clk_pll_params *pll_params, u32 pll_flags,
> struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
> struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
> void __iomem *clk_base, void __iomem *pmc,
> unsigned long flags, unsigned long fixed_rate,
> - struct tegra_clk_pll_params *pll_params, u8 pll_flags,
> + struct tegra_clk_pll_params *pll_params, u32 pll_flags,
> struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
>
> /**
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 03/10] clk: tegra: Add PLL post divider table
2013-02-01 10:18 ` [PATCH v5 03/10] clk: tegra: Add PLL post divider table Peter De Schrijver
@ 2013-02-04 6:28 ` Prashant Gaikwad
0 siblings, 0 replies; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 6:28 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> 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>
> ---
Looks good to me.
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
> drivers/clk/tegra/clk-pll.c | 38 ++++++++++++++++++++++++++++++++------
> drivers/clk/tegra/clk-tegra20.c | 7 +++++++
> drivers/clk/tegra/clk-tegra30.c | 7 +++++++
> drivers/clk/tegra/clk.h | 13 +++++++++++++
> 4 files changed, 59 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
> index 3c3a25e..87d2f34 100644
> --- a/drivers/clk/tegra/clk-pll.c
> +++ b/drivers/clk/tegra/clk-pll.c
> @@ -258,6 +258,7 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
> unsigned long rate, unsigned long parent_rate)
> {
> struct tegra_clk_pll *pll = to_clk_pll(hw);
> + struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
> unsigned long cfreq;
> u32 p_div = 0;
>
> @@ -291,7 +292,6 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
> cfg->output_rate <<= 1)
> p_div++;
>
> - cfg->p = p_div;
> cfg->m = parent_rate / cfreq;
> cfg->n = cfg->output_rate / cfreq;
> cfg->cpcon = OUT_OF_TABLE_CPCON;
> @@ -304,8 +304,19 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
> return -EINVAL;
> }
>
> - if (pll->flags & TEGRA_PLLU)
> - cfg->p ^= 1;
> + if (p_tohw) {
> + p_div = 1 << p_div;
> + while (p_tohw->pdiv) {
> + if (p_div <= p_tohw->pdiv) {
> + cfg->p = p_tohw->hw_val;
> + break;
> + }
> + p_tohw++;
> + }
> + if (!p_tohw->pdiv)
> + return -EINVAL;
> + } else
> + cfg->p = p_div;
>
> return 0;
> }
> @@ -452,8 +463,10 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
> {
> struct tegra_clk_pll *pll = to_clk_pll(hw);
> struct tegra_clk_pll_freq_table cfg;
> + struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
> u32 val;
> u64 rate = parent_rate;
> + int pdiv;
>
> val = pll_readl_base(pll);
>
> @@ -472,10 +485,23 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
>
> _get_pll_mnp(pll, &cfg);
>
> - if (pll->flags & TEGRA_PLLU)
> - cfg.p ^= 1;
> + if (p_tohw) {
> + while (p_tohw->pdiv) {
> + if (cfg.p == p_tohw->hw_val) {
> + pdiv = p_tohw->pdiv;
> + break;
> + }
> + p_tohw++;
> + }
> +
> + if (!p_tohw->pdiv) {
> + WARN_ON(1);
> + pdiv = 1;
> + }
> + } else
> + pdiv = 1 << cfg.p;
>
> - cfg.m *= 1 << cfg.p;
> + cfg.m *= pdiv;
>
> rate *= cfg.n;
> do_div(rate, cfg.m);
> diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
> index 30bd3fd..54c6777 100644
> --- a/drivers/clk/tegra/clk-tegra20.c
> +++ b/drivers/clk/tegra/clk-tegra20.c
> @@ -440,6 +440,12 @@ static struct tegra_clk_pll_params pll_d_params = {
> .lock_delay = 1000,
> };
>
> +static struct pdiv_map pllu_p[] = {
> + { .pdiv = 1, .hw_val = 1 },
> + { .pdiv = 2, .hw_val = 0 },
> + { .pdiv = 0, .hw_val = 0 },
> +};
> +
> static struct tegra_clk_pll_params pll_u_params = {
> .input_min = 2000000,
> .input_max = 40000000,
> @@ -452,6 +458,7 @@ static struct tegra_clk_pll_params pll_u_params = {
> .lock_bit_idx = PLL_BASE_LOCK,
> .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
> .lock_delay = 1000,
> + .pdiv_tohw = pllu_p,
> };
>
> static struct tegra_clk_pll_params pll_x_params = {
> diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
> index 28a2997..078f9b8 100644
> --- a/drivers/clk/tegra/clk-tegra30.c
> +++ b/drivers/clk/tegra/clk-tegra30.c
> @@ -466,6 +466,12 @@ static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
> { 0, 0, 0, 0, 0, 0 },
> };
>
> +static struct pdiv_map pllu_p[] = {
> + { .pdiv = 1, .hw_val = 1 },
> + { .pdiv = 2, .hw_val = 0 },
> + { .pdiv = 0, .hw_val = 0 },
> +};
> +
> static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
> { 12000000, 480000000, 960, 12, 0, 12},
> { 13000000, 480000000, 960, 13, 0, 12},
> @@ -639,6 +645,7 @@ static struct tegra_clk_pll_params pll_u_params = {
> .lock_bit_idx = PLL_BASE_LOCK,
> .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
> .lock_delay = 1000,
> + .pdiv_tohw = pllu_p,
> };
>
> static struct tegra_clk_pll_params pll_x_params = {
> diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
> index 3cff1df..1b9cbcd 100644
> --- a/drivers/clk/tegra/clk.h
> +++ b/drivers/clk/tegra/clk.h
> @@ -117,6 +117,17 @@ struct tegra_clk_pll_freq_table {
> };
>
> /**
> + * struct pdiv_map - map post divider to hw value
> + *
> + * @pdiv: post divider
> + * @hw_val: value to be written to the PLL hw
> + */
> +struct pdiv_map {
> + u8 pdiv;
> + u8 hw_val;
> +};
> +
> +/**
> * struct clk_pll_params - PLL parameters
> *
> * @input_min: Minimum input frequency
> @@ -146,6 +157,8 @@ struct tegra_clk_pll_params {
> u32 lock_bit_idx;
> u32 lock_enable_bit_idx;
> int lock_delay;
> + int max_p;
> + struct pdiv_map *pdiv_tohw;
> };
>
> /**
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 05/10] clk: tegra: Add flags to tegra_clk_periph()
2013-02-01 10:18 ` [PATCH v5 05/10] clk: tegra: Add flags to tegra_clk_periph() Peter De Schrijver
@ 2013-02-04 6:33 ` Prashant Gaikwad
0 siblings, 0 replies; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 6:33 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> 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>
> ---
Looks good to me.
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
> drivers/clk/tegra/clk-periph.c | 11 ++++++-----
> drivers/clk/tegra/clk-tegra20.c | 2 +-
> drivers/clk/tegra/clk-tegra30.c | 2 +-
> drivers/clk/tegra/clk.h | 9 ++++++---
> 4 files changed, 14 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
> index 788486e..067abb3 100644
> --- a/drivers/clk/tegra/clk-periph.c
> +++ b/drivers/clk/tegra/clk-periph.c
> @@ -170,14 +170,15 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = {
> static struct clk *_tegra_clk_register_periph(const char *name,
> const char **parent_names, int num_parents,
> struct tegra_clk_periph *periph,
> - void __iomem *clk_base, u32 offset, bool div)
> + void __iomem *clk_base, u32 offset, bool div,
> + unsigned long flags)
> {
> struct clk *clk;
> struct clk_init_data init;
>
> init.name = name;
> init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
> - init.flags = div ? 0 : CLK_SET_RATE_PARENT;
> + init.flags = flags;
> init.parent_names = parent_names;
> init.num_parents = num_parents;
>
> @@ -202,10 +203,10 @@ static struct clk *_tegra_clk_register_periph(const char *name,
> struct clk *tegra_clk_register_periph(const char *name,
> const char **parent_names, int num_parents,
> struct tegra_clk_periph *periph, void __iomem *clk_base,
> - u32 offset)
> + u32 offset, unsigned long flags)
> {
> return _tegra_clk_register_periph(name, parent_names, num_parents,
> - periph, clk_base, offset, true);
> + periph, clk_base, offset, true, flags);
> }
>
> struct clk *tegra_clk_register_periph_nodiv(const char *name,
> @@ -214,5 +215,5 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
> u32 offset)
> {
> return _tegra_clk_register_periph(name, parent_names, num_parents,
> - periph, clk_base, offset, false);
> + periph, clk_base, offset, false, CLK_SET_RATE_PARENT);
> }
> diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
> index 54c6777..870349e 100644
> --- a/drivers/clk/tegra/clk-tegra20.c
> +++ b/drivers/clk/tegra/clk-tegra20.c
> @@ -1048,7 +1048,7 @@ static void __init tegra20_periph_clk_init(void)
> data = &tegra_periph_clk_list[i];
> clk = tegra_clk_register_periph(data->name, data->parent_names,
> data->num_parents, &data->periph,
> - clk_base, data->offset);
> + clk_base, data->offset, data->flags);
> clk_register_clkdev(clk, data->con_id, data->dev_id);
> clks[data->clk_id] = clk;
> }
> diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
> index 078f9b8..126747b 100644
> --- a/drivers/clk/tegra/clk-tegra30.c
> +++ b/drivers/clk/tegra/clk-tegra30.c
> @@ -1665,7 +1665,7 @@ static void __init tegra30_periph_clk_init(void)
> data = &tegra_periph_clk_list[i];
> clk = tegra_clk_register_periph(data->name, data->parent_names,
> data->num_parents, &data->periph,
> - clk_base, data->offset);
> + clk_base, data->offset, data->flags);
> clk_register_clkdev(clk, data->con_id, data->dev_id);
> clks[data->clk_id] = clk;
> }
> diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
> index 4d0f556..79f5e2a 100644
> --- a/drivers/clk/tegra/clk.h
> +++ b/drivers/clk/tegra/clk.h
> @@ -411,7 +411,7 @@ extern const struct clk_ops tegra_clk_periph_ops;
> struct clk *tegra_clk_register_periph(const char *name,
> const char **parent_names, int num_parents,
> struct tegra_clk_periph *periph, void __iomem *clk_base,
> - u32 offset);
> + u32 offset, unsigned long flags);
> struct clk *tegra_clk_register_periph_nodiv(const char *name,
> const char **parent_names, int num_parents,
> struct tegra_clk_periph *periph, void __iomem *clk_base,
> @@ -454,12 +454,14 @@ struct tegra_periph_init_data {
> u32 offset;
> const char *con_id;
> const char *dev_id;
> + unsigned long flags;
> };
>
> #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
> _mux_shift, _mux_mask, _mux_flags, _div_shift, \
> _div_width, _div_frac_width, _div_flags, _regs, \
> - _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table) \
> + _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\
> + _flags) \
> { \
> .name = _name, \
> .clk_id = _clk_id, \
> @@ -474,6 +476,7 @@ struct tegra_periph_init_data {
> .offset = _offset, \
> .con_id = _con_id, \
> .dev_id = _dev_id, \
> + .flags = _flags \
> }
>
> #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
> @@ -484,7 +487,7 @@ struct tegra_periph_init_data {
> _mux_shift, BIT(_mux_width) - 1, _mux_flags, \
> _div_shift, _div_width, _div_frac_width, _div_flags, \
> _regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\
> - NULL)
> + NULL, 0)
>
> /**
> * struct clk_super_mux - super clock
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114
2013-02-01 19:40 ` Rhyland Klein
@ 2013-02-04 6:35 ` Prashant Gaikwad
2013-02-04 10:37 ` Peter De Schrijver
0 siblings, 1 reply; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 6:35 UTC (permalink / raw)
To: Rhyland Klein
Cc: Peter De Schrijver, Grant Likely, Rob Herring, Rob Landley,
Stephen Warren, Russell King, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, linux-arm-kernel
On Saturday 02 February 2013 01:10 AM, Rhyland Klein wrote:
> On 2/1/2013 5:18 AM, Peter De Schrijver wrote:
>> Tegra114 introduces new PLL types. This requires new clocktypes as well
>> as some new fields in the pll structure.
>>
>> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
>> ---
>> drivers/clk/tegra/clk-pll.c | 719 +++++++++++++++++++++++++++++++++++++++++++
>> drivers/clk/tegra/clk.h | 47 +++
>> 2 files changed, 766 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
>> index 87d2f34..50114b7 100644
>> --- a/drivers/clk/tegra/clk-pll.c
>> +++ b/drivers/clk/tegra/clk-pll.c
>> [snip]
>> +struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
>> + void __iomem *clk_base, void __iomem *pmc,
>> + unsigned long flags, unsigned long fixed_rate,
>> + struct tegra_clk_pll_params *pll_params,
>> + u32 pll_flags,
>> + struct tegra_clk_pll_freq_table *freq_table,
>> + spinlock_t *lock)
>> +{
>> + if (!pll_params->pdiv_tohw)
>> + return -EINVAL;
>> +
> This will cause the following warning:
> warning: return makes pointer from integer without a cast
>
> Same with occurrences in tegra_clk_register_pllm and
> tegra_clk_register_pllc.
>
> Should this instead be returning NULL?
return ERR_PTR(-EINVAL)
>
> -rhyland
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 06/10] clk: tegra: Workaround for Tegra114 MSENC problem
2013-02-01 10:18 ` [PATCH v5 06/10] clk: tegra: Workaround for Tegra114 MSENC problem Peter De Schrijver
@ 2013-02-04 6:39 ` Prashant Gaikwad
0 siblings, 0 replies; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 6:39 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> Workaround a hardware bug in MSENC during clock enable.
>
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
> drivers/clk/tegra/clk-periph-gate.c | 9 +++++++++
> drivers/clk/tegra/clk.h | 1 +
> 2 files changed, 10 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
> index 6dd5332..c9083fb 100644
> --- a/drivers/clk/tegra/clk-periph-gate.c
> +++ b/drivers/clk/tegra/clk-periph-gate.c
> @@ -43,6 +43,8 @@ static DEFINE_SPINLOCK(periph_ref_lock);
>
> #define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32))
>
> +#define LVL2_CLK_GATE_OVRE 0x554
> +
> /* Peripheral gate clock ops */
> static int clk_periph_is_enabled(struct clk_hw *hw)
> {
> @@ -83,6 +85,13 @@ static int clk_periph_enable(struct clk_hw *hw)
> }
> }
>
> + if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
> + writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
> + writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
> + udelay(1);
> + writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
> + }
> +
> spin_unlock_irqrestore(&periph_ref_lock, flags);
>
> return 0;
> diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
> index 79f5e2a..8756d9f 100644
> --- a/drivers/clk/tegra/clk.h
> +++ b/drivers/clk/tegra/clk.h
> @@ -371,6 +371,7 @@ struct tegra_clk_periph_gate {
> #define TEGRA_PERIPH_NO_RESET BIT(0)
> #define TEGRA_PERIPH_MANUAL_RESET BIT(1)
> #define TEGRA_PERIPH_ON_APB BIT(2)
> +#define TEGRA_PERIPH_WAR_1005168 BIT(3)
>
Comment for this flag, otherwise
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
> void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
> extern const struct clk_ops tegra_clk_periph_gate_ops;
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 08/10] ARM: dt: Add references to tegra_car clocks
2013-02-01 10:18 ` [PATCH v5 08/10] ARM: dt: Add references to tegra_car clocks Peter De Schrijver
@ 2013-02-04 6:45 ` Prashant Gaikwad
0 siblings, 0 replies; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 6:45 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> Add references to tegra_car clocks for the basic device nodes.
>
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
> arch/arm/boot/dts/tegra114.dtsi | 7 ++++++-
> 1 files changed, 6 insertions(+), 1 deletions(-)
>
> diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
> index 96a8235..1dec620 100644
> --- a/arch/arm/boot/dts/tegra114.dtsi
> +++ b/arch/arm/boot/dts/tegra114.dtsi
> @@ -27,7 +27,7 @@
> };
>
> tegra_car: clock {
> - compatible = "nvidia,tegra114-car, nvidia,tegra30-car";
> + compatible = "nvidia,tegra114-car";
> reg = <0x60006000 0x1000>;
> #clock-cells = <1>;
> };
> @@ -43,6 +43,7 @@
> reg-shift = <2>;
> interrupts = <0 36 0x04>;
> status = "disabled";
> + clocks = <&tegra_car 6>;
> };
>
> serial@70006040 {
> @@ -51,6 +52,7 @@
> reg-shift = <2>;
> interrupts = <0 37 0x04>;
> status = "disabled";
> + clocks = <&tegra_car 192>;
> };
>
> serial@70006200 {
> @@ -59,6 +61,7 @@
> reg-shift = <2>;
> interrupts = <0 46 0x04>;
> status = "disabled";
> + clocks = <&tegra_car 55>;
> };
>
> serial@70006300 {
> @@ -67,12 +70,14 @@
> reg-shift = <2>;
> interrupts = <0 90 0x04>;
> status = "disabled";
> + clocks = <&tegra_car 65>;
> };
>
> rtc {
> compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc";
> reg = <0x7000e000 0x100>;
> interrupts = <0 2 0x04>;
> + clocks = <&tegra_car 4>;
> };
>
> pmc {
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
2013-02-01 10:18 ` [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114 Peter De Schrijver
@ 2013-02-04 7:08 ` Prashant Gaikwad
2013-02-04 10:45 ` Peter De Schrijver
2013-02-04 14:34 ` Peter De Schrijver
0 siblings, 2 replies; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 7:08 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> Implement most clocks for Tegra114. The super clocks for the CPU complex
> are still missing and will be implemented in a future version.
>
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
> drivers/clk/tegra/Makefile | 1 +
> drivers/clk/tegra/clk-tegra114.c | 2002 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 2003 insertions(+), 0 deletions(-)
> create mode 100644 drivers/clk/tegra/clk-tegra114.c
>
> diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
> index 2b41b0f..f49fac2 100644
> --- a/drivers/clk/tegra/Makefile
> +++ b/drivers/clk/tegra/Makefile
> @@ -9,3 +9,4 @@ obj-y += clk-super.o
>
> obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o
> obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o
> +obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o
> diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
> new file mode 100644
> index 0000000..f8165d2
> --- /dev/null
> +++ b/drivers/clk/tegra/clk-tegra114.c
> @@ -0,0 +1,2002 @@
> +/*
> + * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/delay.h>
> +#include <linux/clk/tegra.h>
> +
> +#include "clk.h"
> +
> +#define RST_DEVICES_L 0x004
> +#define RST_DEVICES_H 0x008
> +#define RST_DEVICES_U 0x00C
> +#define RST_DEVICES_V 0x358
> +#define RST_DEVICES_W 0x35C
> +#define RST_DEVICES_X 0x28C
> +#define RST_DEVICES_SET_L 0x300
> +#define RST_DEVICES_CLR_L 0x304
> +#define RST_DEVICES_SET_H 0x308
> +#define RST_DEVICES_CLR_H 0x30c
> +#define RST_DEVICES_SET_U 0x310
> +#define RST_DEVICES_CLR_U 0x314
> +#define RST_DEVICES_SET_V 0x430
> +#define RST_DEVICES_CLR_V 0x434
> +#define RST_DEVICES_SET_W 0x438
> +#define RST_DEVICES_CLR_W 0x43c
> +#define RST_DEVICES_NUM 5
RST_DEVICES_SET/CLR_X?
> +
> +#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
<snip>
> +
> + /* dsia */
> + clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
> + ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
> + clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
> + clks[dsia_mux] = clk;
> + clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
> + 0, 48, &periph_h_regs,
> + periph_clk_enb_refcnt);
> + clk_register_clkdev(clk, "dsia", "tegradc.0");
> + clks[dsia] = clk;
> +
> + /* dsib */
> + clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
> + ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
> + clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
> + clks[dsib_mux] = clk;
> + clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
> + 0, 82, &periph_u_regs,
> + periph_clk_enb_refcnt);
> + clk_register_clkdev(clk, "dsib", "tegradc.1");
> + clks[dsib] = clk;
> +
Can we use periph no div clock here for dsia and dsib?
> + /* 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;
> +
With device tree we can directly use pll_u_60M, no need to register
clock with fixed factor 1.
Same comment for dis1-fixed, dsi2-fixed and mipi-cal-fast clocks.
> + /* xusb_host */
> + clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0,
> + clk_base, 0, 89, &periph_u_regs,
> + periph_clk_enb_refcnt);
> + clk_register_clkdev(clk, "tegra_xhci", "host");
> + clks[xusb_host] = clk;
> +
> + /* xusb_ss */
> + clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0,
> + clk_base, 0, 156, &periph_w_regs,
> + periph_clk_enb_refcnt);
> + clk_register_clkdev(clk, "tegra_xhci", "ss");
> + clks[xusb_host] = clk;
> +
> + /* xusb_dev */
> + clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0,
> + clk_base, 0, 95, &periph_u_regs,
> + periph_clk_enb_refcnt);
> + clk_register_clkdev(clk, "tegra_xhci", "dev");
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);
> + clk_register_clkdev(clk, data->con_id, data->dev_id);
> + clks[data->clk_id] = clk;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
> + data = &tegra_periph_nodiv_clk_list[i];
> + clk = tegra_clk_register_periph_nodiv(data->name,
> + data->parent_names, data->num_parents,
> + &data->periph, clk_base, data->offset);
> + clk_register_clkdev(clk, data->con_id, data->dev_id);
> + clks[data->clk_id] = clk;
> + }
> +}
> +
> +static struct tegra_cpu_car_ops tegra114_cpu_car_ops;
> +
> +static const struct of_device_id pmc_match[] __initconst = {
> + { .compatible = "nvidia,tegra114-pmc" },
> + {},
> +};
> +
> +static __initdata struct tegra_clk_init_table init_table[] = {
> + {uartd, pll_p, 408000000, 1},
> + {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
> +};
> +
> +void __init tegra114_clock_init(struct device_node *np)
> +{
> + struct device_node *node;
> + int i;
> +
> + clk_base = of_iomap(np, 0);
> + if (!clk_base) {
> + pr_err("ioremap tegra114 CAR failed\n");
> + return;
> + }
> +
> + node = of_find_matching_node(NULL, pmc_match);
> + if (!node) {
> + pr_err("Failed to find pmc node\n");
> + WARN_ON(1);
> + return;
> + }
> +
> + pmc_base = of_iomap(node, 0);
> + if (!pmc_base) {
> + pr_err("Can't map pmc registers\n");
> + WARN_ON(1);
> + return;
> + }
> +
> + if (tegra114_osc_clk_init(clk_base) < 0)
> + return;
> +
> + tegra114_fixed_clk_init(clk_base);
> + tegra114_pll_init(clk_base, pmc_base);
> + tegra114_periph_clk_init(clk_base);
> + tegra114_audio_clk_init(clk_base);
> + tegra114_pmc_clk_init(pmc_base);
> +
> + for (i = 0; i < ARRAY_SIZE(clks); i++) {
> + if (IS_ERR(clks[i])) {
> + pr_err
> + ("Tegra114 clk %d: register failed with %ld\n",
> + i, PTR_ERR(clks[i]));
> + }
> + if (!clks[i])
> + clks[i] = ERR_PTR(-EINVAL);
> + }
> +
> + clk_data.clks = clks;
> + clk_data.clk_num = ARRAY_SIZE(clks);
> + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
> +
> + tegra_init_from_table(init_table, clks, clk_max);
> +
> + tegra_cpu_car_ops = &tegra114_cpu_car_ops;
> +}
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 10/10] clk: tegra: devicetree match for nvidia,tegra114-car
2013-02-01 10:18 ` [PATCH v5 10/10] clk: tegra: devicetree match for nvidia,tegra114-car Peter De Schrijver
@ 2013-02-04 7:10 ` Prashant Gaikwad
0 siblings, 0 replies; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-04 7:10 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
> drivers/clk/tegra/clk.c | 1 +
> drivers/clk/tegra/clk.h | 7 +++++++
> 2 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
> index a603b9a..a328365 100644
> --- a/drivers/clk/tegra/clk.c
> +++ b/drivers/clk/tegra/clk.c
> @@ -76,6 +76,7 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
> static const struct of_device_id tegra_dt_clk_match[] = {
> { .compatible = "nvidia,tegra20-car", .data = tegra20_clock_init },
> { .compatible = "nvidia,tegra30-car", .data = tegra30_clock_init },
> + { .compatible = "nvidia,tegra114-car", .data = tegra114_clock_init },
> { }
> };
>
> diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
> index 8756d9f..8097850 100644
> --- a/drivers/clk/tegra/clk.h
> +++ b/drivers/clk/tegra/clk.h
> @@ -576,4 +576,11 @@ void tegra30_clock_init(struct device_node *np);
> static inline void tegra30_clock_init(struct device_node *np) {}
> #endif /* CONFIG_ARCH_TEGRA_3x_SOC */
>
> +#ifdef CONFIG_ARCH_TEGRA_114_SOC
> +void tegra114_clock_init(struct device_node *np);
> +#else
> +static inline void tegra114_clock_init(struct device_node *np) {}
> +#endif /* CONFIG_ARCH_TEGRA114_SOC */
> +
> +
> #endif /* TEGRA_CLK_H */
>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114
2013-02-04 6:35 ` Prashant Gaikwad
@ 2013-02-04 10:37 ` Peter De Schrijver
0 siblings, 0 replies; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-04 10:37 UTC (permalink / raw)
To: Prashant Gaikwad
Cc: Rhyland Klein, Grant Likely, Rob Herring, Rob Landley,
Stephen Warren, Russell King, Simon Glass, Mike Turquette,
Joseph Lo, devicetree-discuss, linux-doc, linux-kernel,
linux-tegra, linux-arm-kernel
On Mon, Feb 04, 2013 at 07:35:29AM +0100, Prashant Gaikwad wrote:
> On Saturday 02 February 2013 01:10 AM, Rhyland Klein wrote:
> > On 2/1/2013 5:18 AM, Peter De Schrijver wrote:
> >> Tegra114 introduces new PLL types. This requires new clocktypes as well
> >> as some new fields in the pll structure.
> >>
> >> Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> >> ---
> >> drivers/clk/tegra/clk-pll.c | 719 +++++++++++++++++++++++++++++++++++++++++++
> >> drivers/clk/tegra/clk.h | 47 +++
> >> 2 files changed, 766 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
> >> index 87d2f34..50114b7 100644
> >> --- a/drivers/clk/tegra/clk-pll.c
> >> +++ b/drivers/clk/tegra/clk-pll.c
> >> [snip]
> >> +struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
> >> + void __iomem *clk_base, void __iomem *pmc,
> >> + unsigned long flags, unsigned long fixed_rate,
> >> + struct tegra_clk_pll_params *pll_params,
> >> + u32 pll_flags,
> >> + struct tegra_clk_pll_freq_table *freq_table,
> >> + spinlock_t *lock)
> >> +{
> >> + if (!pll_params->pdiv_tohw)
> >> + return -EINVAL;
> >> +
> > This will cause the following warning:
> > warning: return makes pointer from integer without a cast
> >
> > Same with occurrences in tegra_clk_register_pllm and
> > tegra_clk_register_pllc.
> >
> > Should this instead be returning NULL?
>
> return ERR_PTR(-EINVAL)
>
Indeed. I noticed that only after I sent this patchset. Already fixed in
my own tree.
Cheers,
Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
2013-02-04 7:08 ` Prashant Gaikwad
@ 2013-02-04 10:45 ` Peter De Schrijver
2013-02-04 14:07 ` Peter De Schrijver
` (2 more replies)
2013-02-04 14:34 ` Peter De Schrijver
1 sibling, 3 replies; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-04 10:45 UTC (permalink / raw)
To: Prashant Gaikwad
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Mon, Feb 04, 2013 at 08:08:55AM +0100, Prashant Gaikwad wrote:
...
> > +#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
>
> RST_DEVICES_SET/CLR_X?
>
For all I can see (from the not yet public TRM), this is not actually used?
So I decided to not mention it here.
> > +
> > +#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
>
> <snip>
>
> > +
> > + /* dsia */
> > + clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
> > + ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
> > + clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
> > + clks[dsia_mux] = clk;
> > + clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
> > + 0, 48, &periph_h_regs,
> > + periph_clk_enb_refcnt);
> > + clk_register_clkdev(clk, "dsia", "tegradc.0");
> > + clks[dsia] = clk;
> > +
> > + /* dsib */
> > + clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
> > + ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
> > + clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
> > + clks[dsib_mux] = clk;
> > + clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
> > + 0, 82, &periph_u_regs,
> > + periph_clk_enb_refcnt);
> > + clk_register_clkdev(clk, "dsib", "tegradc.1");
> > + clks[dsib] = clk;
> > +
>
> Can we use periph no div clock here for dsia and dsib?
>
Will check.
> > + /* 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;
> > +
>
> With device tree we can directly use pll_u_60M, no need to register
> clock with fixed factor 1.
This is true for now. In the future these clocks will need to be dvfs aware
though. I think it makes sense to have a separate clock then?
> Same comment for dis1-fixed, dsi2-fixed and mipi-cal-fast clocks.
>
Those might not need to become dvfs aware.
> > + /* xusb_host */
> > + clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0,
> > + clk_base, 0, 89, &periph_u_regs,
> > + periph_clk_enb_refcnt);
> > + clk_register_clkdev(clk, "tegra_xhci", "host");
> > + clks[xusb_host] = clk;
> > +
> > + /* xusb_ss */
> > + clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0,
> > + clk_base, 0, 156, &periph_w_regs,
> > + periph_clk_enb_refcnt);
> > + clk_register_clkdev(clk, "tegra_xhci", "ss");
> > + clks[xusb_host] = clk;
> > +
> > + /* xusb_dev */
> > + clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0,
> > + clk_base, 0, 95, &periph_u_regs,
> > + periph_clk_enb_refcnt);
> > + clk_register_clkdev(clk, "tegra_xhci", "dev");
>
> clks[xusb_dev] = clk;
>
Missing indeed.
Cheers,
Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
2013-02-04 10:45 ` Peter De Schrijver
@ 2013-02-04 14:07 ` Peter De Schrijver
2013-02-04 21:01 ` Stephen Warren
2013-02-07 16:18 ` Peter De Schrijver
2 siblings, 0 replies; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-04 14:07 UTC (permalink / raw)
To: Prashant Gaikwad
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Mon, Feb 04, 2013 at 11:45:31AM +0100, Peter De Schrijver wrote:
> On Mon, Feb 04, 2013 at 08:08:55AM +0100, Prashant Gaikwad wrote:
...
> > > +
> > > + /* dsia */
> > > + clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
> > > + ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
> > > + clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
> > > + clks[dsia_mux] = clk;
> > > + clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
> > > + 0, 48, &periph_h_regs,
> > > + periph_clk_enb_refcnt);
> > > + clk_register_clkdev(clk, "dsia", "tegradc.0");
> > > + clks[dsia] = clk;
> > > +
> > > + /* dsib */
> > > + clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
> > > + ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
> > > + clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
> > > + clks[dsib_mux] = clk;
> > > + clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
> > > + 0, 82, &periph_u_regs,
> > > + periph_clk_enb_refcnt);
> > > + clk_register_clkdev(clk, "dsib", "tegradc.1");
> > > + clks[dsib] = clk;
> > > +
> >
> > Can we use periph no div clock here for dsia and dsib?
> >
>
> Will check.
>
Not as such. As you can see the muxes need a lock to protect access to the
PLLD_BASE and PLLD2_BASE registers respectively. The periph no div clock
doesn't provide for these locks though. Do you think it makes sense to add
the lock support for these 2 clocks?
Cheers,
Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 01/10] clk: tegra: Refactor PLL programming code
2013-02-04 6:06 ` Prashant Gaikwad
@ 2013-02-04 14:32 ` Peter De Schrijver
2013-02-05 5:42 ` Prashant Gaikwad
0 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-04 14:32 UTC (permalink / raw)
To: Prashant Gaikwad
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Mon, Feb 04, 2013 at 07:06:47AM +0100, Prashant Gaikwad wrote:
> On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
...
> >
> > -static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
> > - void __iomem *lock_addr, u32 lock_bit_idx)
> > +static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
> > {
> > int i;
> > - u32 val;
> > + u32 val, lock_bit;
> > + void __iomem *lock_addr;
> >
> > if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
> > udelay(pll->params->lock_delay);
> > return 0;
> > }
> >
> > + lock_addr = pll->clk_base + pll->params->base_reg;
>
> This will not work for PLLE. Lock bit for PLLE is in misc register.
>
> > + 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) {
>
> Need to change the lock bit idx parameter for Tegra20 and Tegra30 PLLs
> else this patch will break those.
>
Looking at commit 37c26a906527b8a6a252614ca83d21ad318c4e84 and commit
b08e8c0ecc42afa3a2e1019851af741980dd5a6b, these fields seem correctly
initialized for both Tegra20 and Tegra30? Or am I missing something?
Thanks,
Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
2013-02-04 7:08 ` Prashant Gaikwad
2013-02-04 10:45 ` Peter De Schrijver
@ 2013-02-04 14:34 ` Peter De Schrijver
2013-02-05 5:36 ` Prashant Gaikwad
1 sibling, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-04 14:34 UTC (permalink / raw)
To: Prashant Gaikwad
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Mon, Feb 04, 2013 at 08:08:55AM +0100, Prashant Gaikwad wrote:
> On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
...
> > + /* 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;
> > +
>
> With device tree we can directly use pll_u_60M, no need to register
> clock with fixed factor 1.
> Same comment for dis1-fixed, dsi2-fixed and mipi-cal-fast clocks.
>
Does it make sense to have separate DT IDs at all then?
Cheers,
Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
2013-02-04 10:45 ` Peter De Schrijver
2013-02-04 14:07 ` Peter De Schrijver
@ 2013-02-04 21:01 ` Stephen Warren
2013-02-07 16:18 ` Peter De Schrijver
2 siblings, 0 replies; 34+ messages in thread
From: Stephen Warren @ 2013-02-04 21:01 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Prashant Gaikwad, Grant Likely, Rob Herring, Rob Landley,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On 02/04/2013 03:45 AM, Peter De Schrijver wrote:
> On Mon, Feb 04, 2013 at 08:08:55AM +0100, Prashant Gaikwad wrote:
>>> + /* 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;
>>> +
>>
>> With device tree we can directly use pll_u_60M, no need to register
>> clock with fixed factor 1.
>
> This is true for now. In the future these clocks will need to be dvfs aware
> though. I think it makes sense to have a separate clock then?
Why does DVFS-awareness require it to be a different clock/ID?
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 07/10] ARM: tegra: Define Tegra114 CAR binding
2013-02-01 10:18 ` [PATCH v5 07/10] ARM: tegra: Define Tegra114 CAR binding Peter De Schrijver
@ 2013-02-04 21:16 ` Stephen Warren
0 siblings, 0 replies; 34+ messages in thread
From: Stephen Warren @ 2013-02-04 21:16 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Russell King,
Prashant Gaikwad, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On 02/01/2013 03:18 AM, Peter De Schrijver wrote:
> The device tree binding models Tegra114 CAR (Clock And Reset) as a single
> monolithic clock provider.
...
> +- #clock-cells : Should be 1.
> + In clock consumers, this cell represents the clock ID exposed by the CAR.
...
> + 222 pll_u
> + 223 pll_u_480M
> + 224 pll_u_60M
> + 225 pll_u_48M
> + 226 pll_u_12M
I notice here that we have separate clock IDs for the various PLL u
outputs. We don't have this on Tegra20 or Tegra30, but I wonder if we
should have them there too?
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 01/10] clk: tegra: Refactor PLL programming code
2013-02-01 10:18 ` [PATCH v5 01/10] clk: tegra: Refactor PLL programming code Peter De Schrijver
2013-02-04 6:06 ` Prashant Gaikwad
@ 2013-02-04 21:57 ` Stephen Warren
1 sibling, 0 replies; 34+ messages in thread
From: Stephen Warren @ 2013-02-04 21:57 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Russell King,
Prashant Gaikwad, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On 02/01/2013 03:18 AM, Peter De Schrijver wrote:
> Refactor the PLL programming code to make it useable by the new PLL types
> introduced by Tegra114.
I tested this series on Tegra20 and Tegra30 for regressions and found
none. Note that I didn't test on Tegra114. The series,
Tested-by: Stephen Warren <swarren@nvidia.com>
Also, I briefly reviewed the code and aside from comments that have
already been made, so the series,
Reviewed-by: Stephen Warren <swarren@nvidia.com>
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
2013-02-04 14:34 ` Peter De Schrijver
@ 2013-02-05 5:36 ` Prashant Gaikwad
0 siblings, 0 replies; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-05 5:36 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Monday 04 February 2013 08:04 PM, Peter De Schrijver wrote:
> On Mon, Feb 04, 2013 at 08:08:55AM +0100, Prashant Gaikwad wrote:
>> On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> ...
>
>>> + /* 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;
>>> +
>> With device tree we can directly use pll_u_60M, no need to register
>> clock with fixed factor 1.
>> Same comment for dis1-fixed, dsi2-fixed and mipi-cal-fast clocks.
>>
> Does it make sense to have separate DT IDs at all then?
We can use same DT ID.
> Cheers,
>
> Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 01/10] clk: tegra: Refactor PLL programming code
2013-02-04 14:32 ` Peter De Schrijver
@ 2013-02-05 5:42 ` Prashant Gaikwad
2013-02-05 13:23 ` Peter De Schrijver
0 siblings, 1 reply; 34+ messages in thread
From: Prashant Gaikwad @ 2013-02-05 5:42 UTC (permalink / raw)
To: Peter De Schrijver
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Monday 04 February 2013 08:02 PM, Peter De Schrijver wrote:
> On Mon, Feb 04, 2013 at 07:06:47AM +0100, Prashant Gaikwad wrote:
>> On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> ...
>
>>> -static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
>>> - void __iomem *lock_addr, u32 lock_bit_idx)
>>> +static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
>>> {
>>> int i;
>>> - u32 val;
>>> + u32 val, lock_bit;
>>> + void __iomem *lock_addr;
>>>
>>> if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
>>> udelay(pll->params->lock_delay);
>>> return 0;
>>> }
>>>
>>> + lock_addr = pll->clk_base + pll->params->base_reg;
>> This will not work for PLLE. Lock bit for PLLE is in misc register.
>>
>>> + 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) {
>> Need to change the lock bit idx parameter for Tegra20 and Tegra30 PLLs
>> else this patch will break those.
>>
> Looking at commit 37c26a906527b8a6a252614ca83d21ad318c4e84 and commit
> b08e8c0ecc42afa3a2e1019851af741980dd5a6b, these fields seem correctly
> initialized for both Tegra20 and Tegra30? Or am I missing something?
Ohh, I missed to read
lock_bit = BIT(pll->params->lock_bit_idx);
Am I missing something about PLLE lock_addr also?
> Thanks,
>
> Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 01/10] clk: tegra: Refactor PLL programming code
2013-02-05 5:42 ` Prashant Gaikwad
@ 2013-02-05 13:23 ` Peter De Schrijver
2013-02-06 12:32 ` Peter De Schrijver
0 siblings, 1 reply; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-05 13:23 UTC (permalink / raw)
To: Prashant Gaikwad
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
On Tue, Feb 05, 2013 at 06:42:11AM +0100, Prashant Gaikwad wrote:
> On Monday 04 February 2013 08:02 PM, Peter De Schrijver wrote:
> > On Mon, Feb 04, 2013 at 07:06:47AM +0100, Prashant Gaikwad wrote:
> >> On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> > ...
> >
> >>> -static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
> >>> - void __iomem *lock_addr, u32 lock_bit_idx)
> >>> +static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
> >>> {
> >>> int i;
> >>> - u32 val;
> >>> + u32 val, lock_bit;
> >>> + void __iomem *lock_addr;
> >>>
> >>> if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
> >>> udelay(pll->params->lock_delay);
> >>> return 0;
> >>> }
> >>>
> >>> + lock_addr = pll->clk_base + pll->params->base_reg;
> >> This will not work for PLLE. Lock bit for PLLE is in misc register.
> >>
> >>> + 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) {
> >> Need to change the lock bit idx parameter for Tegra20 and Tegra30 PLLs
> >> else this patch will break those.
> >>
> > Looking at commit 37c26a906527b8a6a252614ca83d21ad318c4e84 and commit
> > b08e8c0ecc42afa3a2e1019851af741980dd5a6b, these fields seem correctly
> > initialized for both Tegra20 and Tegra30? Or am I missing something?
>
> Ohh, I missed to read
>
> lock_bit = BIT(pll->params->lock_bit_idx);
>
>
> Am I missing something about PLLE lock_addr also?
>
Ah no indeed... my bad. So we need a lock_addr field.
Cheers,
Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 01/10] clk: tegra: Refactor PLL programming code
2013-02-05 13:23 ` Peter De Schrijver
@ 2013-02-06 12:32 ` Peter De Schrijver
0 siblings, 0 replies; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-06 12:32 UTC (permalink / raw)
To: Prashant Gaikwad
Cc: Russell King, linux-doc, linux-kernel, Rob Herring, Joseph Lo,
linux-tegra, Mike Turquette, devicetree-discuss,
linux-arm-kernel
On Tue, Feb 05, 2013 at 02:23:55PM +0100, Peter De Schrijver wrote:
> On Tue, Feb 05, 2013 at 06:42:11AM +0100, Prashant Gaikwad wrote:
> > On Monday 04 February 2013 08:02 PM, Peter De Schrijver wrote:
> > > On Mon, Feb 04, 2013 at 07:06:47AM +0100, Prashant Gaikwad wrote:
> > >> On Friday 01 February 2013 03:48 PM, Peter De Schrijver wrote:
> > > ...
> > >
> > >>> -static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
> > >>> - void __iomem *lock_addr, u32 lock_bit_idx)
> > >>> +static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
> > >>> {
> > >>> int i;
> > >>> - u32 val;
> > >>> + u32 val, lock_bit;
> > >>> + void __iomem *lock_addr;
> > >>>
> > >>> if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
> > >>> udelay(pll->params->lock_delay);
> > >>> return 0;
> > >>> }
> > >>>
> > >>> + lock_addr = pll->clk_base + pll->params->base_reg;
> > >> This will not work for PLLE. Lock bit for PLLE is in misc register.
> > >>
> > >>> + 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) {
> > >> Need to change the lock bit idx parameter for Tegra20 and Tegra30 PLLs
> > >> else this patch will break those.
> > >>
> > > Looking at commit 37c26a906527b8a6a252614ca83d21ad318c4e84 and commit
> > > b08e8c0ecc42afa3a2e1019851af741980dd5a6b, these fields seem correctly
> > > initialized for both Tegra20 and Tegra30? Or am I missing something?
> >
> > Ohh, I missed to read
> >
> > lock_bit = BIT(pll->params->lock_bit_idx);
> >
> >
> > Am I missing something about PLLE lock_addr also?
> >
>
> Ah no indeed... my bad. So we need a lock_addr field.
>
Or a flag. Flag seems less invasive for now.
Cheers,
Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
* Re: [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114
2013-02-04 10:45 ` Peter De Schrijver
2013-02-04 14:07 ` Peter De Schrijver
2013-02-04 21:01 ` Stephen Warren
@ 2013-02-07 16:18 ` Peter De Schrijver
2 siblings, 0 replies; 34+ messages in thread
From: Peter De Schrijver @ 2013-02-07 16:18 UTC (permalink / raw)
To: Prashant Gaikwad
Cc: Grant Likely, Rob Herring, Rob Landley, Stephen Warren,
Russell King, Simon Glass, Mike Turquette, Joseph Lo,
devicetree-discuss, linux-doc, linux-kernel, linux-tegra,
linux-arm-kernel
>
> > > + /* 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;
> > > +
> >
> > With device tree we can directly use pll_u_60M, no need to register
> > clock with fixed factor 1.
>
> This is true for now. In the future these clocks will need to be dvfs aware
> though. I think it makes sense to have a separate clock then?
>
As this seems to be a different clock (ie. the hw allows you to select a
different parent), I think keeping this node makes sense.
Cheers,
Peter.
^ permalink raw reply [flat|nested] 34+ messages in thread
end of thread, other threads:[~2013-02-07 16:18 UTC | newest]
Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-01 10:18 [PATCH v5 00/10] Tegra114 clockframework Peter De Schrijver
2013-02-01 10:18 ` [PATCH v5 01/10] clk: tegra: Refactor PLL programming code Peter De Schrijver
2013-02-04 6:06 ` Prashant Gaikwad
2013-02-04 14:32 ` Peter De Schrijver
2013-02-05 5:42 ` Prashant Gaikwad
2013-02-05 13:23 ` Peter De Schrijver
2013-02-06 12:32 ` Peter De Schrijver
2013-02-04 21:57 ` Stephen Warren
2013-02-01 10:18 ` [PATCH v5 02/10] clk: tegra: Add TEGRA_PLL_BYPASS flag Peter De Schrijver
2013-02-04 6:13 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 03/10] clk: tegra: Add PLL post divider table Peter De Schrijver
2013-02-04 6:28 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 04/10] clk: tegra: Add new fields and PLL types for Tegra114 Peter De Schrijver
2013-02-01 19:40 ` Rhyland Klein
2013-02-04 6:35 ` Prashant Gaikwad
2013-02-04 10:37 ` Peter De Schrijver
2013-02-01 10:18 ` [PATCH v5 05/10] clk: tegra: Add flags to tegra_clk_periph() Peter De Schrijver
2013-02-04 6:33 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 06/10] clk: tegra: Workaround for Tegra114 MSENC problem Peter De Schrijver
2013-02-04 6:39 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 07/10] ARM: tegra: Define Tegra114 CAR binding Peter De Schrijver
2013-02-04 21:16 ` Stephen Warren
2013-02-01 10:18 ` [PATCH v5 08/10] ARM: dt: Add references to tegra_car clocks Peter De Schrijver
2013-02-04 6:45 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 09/10] clk: tegra: Implement clocks for Tegra114 Peter De Schrijver
2013-02-04 7:08 ` Prashant Gaikwad
2013-02-04 10:45 ` Peter De Schrijver
2013-02-04 14:07 ` Peter De Schrijver
2013-02-04 21:01 ` Stephen Warren
2013-02-07 16:18 ` Peter De Schrijver
2013-02-04 14:34 ` Peter De Schrijver
2013-02-05 5:36 ` Prashant Gaikwad
2013-02-01 10:18 ` [PATCH v5 10/10] clk: tegra: devicetree match for nvidia,tegra114-car Peter De Schrijver
2013-02-04 7:10 ` Prashant Gaikwad
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).