aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/tegra')
-rw-r--r--drivers/clk/tegra/Makefile1
-rw-r--r--drivers/clk/tegra/clk-dfll.c11
-rw-r--r--drivers/clk/tegra/clk-dfll.h22
-rw-r--r--drivers/clk/tegra/clk-id.h2
-rw-r--r--drivers/clk/tegra/clk-periph-fixed.c120
-rw-r--r--drivers/clk/tegra/clk-periph-gate.c2
-rw-r--r--drivers/clk/tegra/clk-periph.c2
-rw-r--r--drivers/clk/tegra/clk-pll.c46
-rw-r--r--drivers/clk/tegra/clk-tegra-fixed.c1
-rw-r--r--drivers/clk/tegra/clk-tegra-periph.c5
-rw-r--r--drivers/clk/tegra/clk-tegra114.c6
-rw-r--r--drivers/clk/tegra/clk-tegra124-dfll-fcpu.c103
-rw-r--r--drivers/clk/tegra/clk-tegra124.c4
-rw-r--r--drivers/clk/tegra/clk-tegra210.c29
-rw-r--r--drivers/clk/tegra/clk-tegra30.c12
-rw-r--r--drivers/clk/tegra/clk.c4
-rw-r--r--drivers/clk/tegra/clk.h27
-rw-r--r--drivers/clk/tegra/cvb.c71
-rw-r--r--drivers/clk/tegra/cvb.h15
19 files changed, 369 insertions, 114 deletions
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
index 97984c503bbb..33fd0938d79e 100644
--- a/drivers/clk/tegra/Makefile
+++ b/drivers/clk/tegra/Makefile
@@ -3,6 +3,7 @@ obj-y += clk-audio-sync.o
3obj-y += clk-dfll.o 3obj-y += clk-dfll.o
4obj-y += clk-divider.o 4obj-y += clk-divider.o
5obj-y += clk-periph.o 5obj-y += clk-periph.o
6obj-y += clk-periph-fixed.o
6obj-y += clk-periph-gate.o 7obj-y += clk-periph-gate.o
7obj-y += clk-pll.o 8obj-y += clk-pll.o
8obj-y += clk-pll-out.o 9obj-y += clk-pll-out.o
diff --git a/drivers/clk/tegra/clk-dfll.c b/drivers/clk/tegra/clk-dfll.c
index 19bfa07e24b1..f010562534eb 100644
--- a/drivers/clk/tegra/clk-dfll.c
+++ b/drivers/clk/tegra/clk-dfll.c
@@ -55,6 +55,7 @@
55#include <linux/seq_file.h> 55#include <linux/seq_file.h>
56 56
57#include "clk-dfll.h" 57#include "clk-dfll.h"
58#include "cvb.h"
58 59
59/* 60/*
60 * DFLL control registers - access via dfll_{readl,writel} 61 * DFLL control registers - access via dfll_{readl,writel}
@@ -442,8 +443,8 @@ static void dfll_tune_low(struct tegra_dfll *td)
442{ 443{
443 td->tune_range = DFLL_TUNE_LOW; 444 td->tune_range = DFLL_TUNE_LOW;
444 445
445 dfll_writel(td, td->soc->tune0_low, DFLL_TUNE0); 446 dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune0_low, DFLL_TUNE0);
446 dfll_writel(td, td->soc->tune1, DFLL_TUNE1); 447 dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1, DFLL_TUNE1);
447 dfll_wmb(td); 448 dfll_wmb(td);
448 449
449 if (td->soc->set_clock_trimmers_low) 450 if (td->soc->set_clock_trimmers_low)
@@ -1449,7 +1450,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
1449 } 1450 }
1450 v_max = dev_pm_opp_get_voltage(opp); 1451 v_max = dev_pm_opp_get_voltage(opp);
1451 1452
1452 v = td->soc->min_millivolts * 1000; 1453 v = td->soc->cvb->min_millivolts * 1000;
1453 lut = find_vdd_map_entry_exact(td, v); 1454 lut = find_vdd_map_entry_exact(td, v);
1454 if (lut < 0) 1455 if (lut < 0)
1455 goto out; 1456 goto out;
@@ -1461,7 +1462,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
1461 break; 1462 break;
1462 v_opp = dev_pm_opp_get_voltage(opp); 1463 v_opp = dev_pm_opp_get_voltage(opp);
1463 1464
1464 if (v_opp <= td->soc->min_millivolts * 1000) 1465 if (v_opp <= td->soc->cvb->min_millivolts * 1000)
1465 td->dvco_rate_min = dev_pm_opp_get_freq(opp); 1466 td->dvco_rate_min = dev_pm_opp_get_freq(opp);
1466 1467
1467 for (;;) { 1468 for (;;) {
@@ -1490,7 +1491,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
1490 1491
1491 if (!td->dvco_rate_min) 1492 if (!td->dvco_rate_min)
1492 dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n", 1493 dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
1493 td->soc->min_millivolts); 1494 td->soc->cvb->min_millivolts);
1494 else 1495 else
1495 ret = 0; 1496 ret = 0;
1496 1497
diff --git a/drivers/clk/tegra/clk-dfll.h b/drivers/clk/tegra/clk-dfll.h
index 2e4c0772a5dc..ed2ad888268f 100644
--- a/drivers/clk/tegra/clk-dfll.h
+++ b/drivers/clk/tegra/clk-dfll.h
@@ -24,22 +24,18 @@
24 24
25/** 25/**
26 * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver 26 * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
27 * @opp_dev: struct device * that holds the OPP table for the DFLL 27 * @dev: struct device * that holds the OPP table for the DFLL
28 * @min_millivolts: minimum voltage (in mV) that the DFLL can operate 28 * @max_freq: maximum frequency supported on this SoC
29 * @tune0_low: DFLL tuning register 0 (low voltage range) 29 * @cvb: CPU frequency table for this SoC
30 * @tune0_high: DFLL tuning register 0 (high voltage range) 30 * @init_clock_trimmers: callback to initialize clock trimmers
31 * @tune1: DFLL tuning register 1 31 * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage
32 * @assert_dvco_reset: fn ptr to place the DVCO in reset 32 * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage
33 * @deassert_dvco_reset: fn ptr to release the DVCO reset
34 * @set_clock_trimmers_high: fn ptr to tune clock trimmers for high voltage
35 * @set_clock_trimmers_low: fn ptr to tune clock trimmers for low voltage
36 */ 33 */
37struct tegra_dfll_soc_data { 34struct tegra_dfll_soc_data {
38 struct device *dev; 35 struct device *dev;
39 unsigned int min_millivolts; 36 unsigned long max_freq;
40 u32 tune0_low; 37 const struct cvb_table *cvb;
41 u32 tune0_high; 38
42 u32 tune1;
43 void (*init_clock_trimmers)(void); 39 void (*init_clock_trimmers)(void);
44 void (*set_clock_trimmers_high)(void); 40 void (*set_clock_trimmers_high)(void);
45 void (*set_clock_trimmers_low)(void); 41 void (*set_clock_trimmers_low)(void);
diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h
index 62ea38187b71..36c974916d4f 100644
--- a/drivers/clk/tegra/clk-id.h
+++ b/drivers/clk/tegra/clk-id.h
@@ -71,6 +71,7 @@ enum clk_id {
71 tegra_clk_disp2_8, 71 tegra_clk_disp2_8,
72 tegra_clk_dp2, 72 tegra_clk_dp2,
73 tegra_clk_dpaux, 73 tegra_clk_dpaux,
74 tegra_clk_dpaux1,
74 tegra_clk_dsialp, 75 tegra_clk_dsialp,
75 tegra_clk_dsia_mux, 76 tegra_clk_dsia_mux,
76 tegra_clk_dsiblp, 77 tegra_clk_dsiblp,
@@ -306,6 +307,7 @@ enum clk_id {
306 tegra_clk_xusb_ss_div2, 307 tegra_clk_xusb_ss_div2,
307 tegra_clk_xusb_ssp_src, 308 tegra_clk_xusb_ssp_src,
308 tegra_clk_sclk_mux, 309 tegra_clk_sclk_mux,
310 tegra_clk_sor_safe,
309 tegra_clk_max, 311 tegra_clk_max,
310}; 312};
311 313
diff --git a/drivers/clk/tegra/clk-periph-fixed.c b/drivers/clk/tegra/clk-periph-fixed.c
new file mode 100644
index 000000000000..c57dfb037b10
--- /dev/null
+++ b/drivers/clk/tegra/clk-periph-fixed.c
@@ -0,0 +1,120 @@
1/*
2 * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/clk-provider.h>
18
19#include "clk.h"
20
21static inline struct tegra_clk_periph_fixed *
22to_tegra_clk_periph_fixed(struct clk_hw *hw)
23{
24 return container_of(hw, struct tegra_clk_periph_fixed, hw);
25}
26
27static int tegra_clk_periph_fixed_is_enabled(struct clk_hw *hw)
28{
29 struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
30 u32 mask = 1 << (fixed->num % 32), value;
31
32 value = readl(fixed->base + fixed->regs->enb_reg);
33 if (value & mask) {
34 value = readl(fixed->base + fixed->regs->rst_reg);
35 if ((value & mask) == 0)
36 return 1;
37 }
38
39 return 0;
40}
41
42static int tegra_clk_periph_fixed_enable(struct clk_hw *hw)
43{
44 struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
45 u32 mask = 1 << (fixed->num % 32);
46
47 writel(mask, fixed->base + fixed->regs->enb_set_reg);
48
49 return 0;
50}
51
52static void tegra_clk_periph_fixed_disable(struct clk_hw *hw)
53{
54 struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
55 u32 mask = 1 << (fixed->num % 32);
56
57 writel(mask, fixed->base + fixed->regs->enb_clr_reg);
58}
59
60static unsigned long
61tegra_clk_periph_fixed_recalc_rate(struct clk_hw *hw,
62 unsigned long parent_rate)
63{
64 struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
65 unsigned long long rate;
66
67 rate = (unsigned long long)parent_rate * fixed->mul;
68 do_div(rate, fixed->div);
69
70 return (unsigned long)rate;
71}
72
73static const struct clk_ops tegra_clk_periph_fixed_ops = {
74 .is_enabled = tegra_clk_periph_fixed_is_enabled,
75 .enable = tegra_clk_periph_fixed_enable,
76 .disable = tegra_clk_periph_fixed_disable,
77 .recalc_rate = tegra_clk_periph_fixed_recalc_rate,
78};
79
80struct clk *tegra_clk_register_periph_fixed(const char *name,
81 const char *parent,
82 unsigned long flags,
83 void __iomem *base,
84 unsigned int mul,
85 unsigned int div,
86 unsigned int num)
87{
88 const struct tegra_clk_periph_regs *regs;
89 struct tegra_clk_periph_fixed *fixed;
90 struct clk_init_data init;
91 struct clk *clk;
92
93 regs = get_reg_bank(num);
94 if (!regs)
95 return ERR_PTR(-EINVAL);
96
97 fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
98 if (!fixed)
99 return ERR_PTR(-ENOMEM);
100
101 init.name = name;
102 init.flags = flags;
103 init.parent_names = parent ? &parent : NULL;
104 init.num_parents = parent ? 1 : 0;
105 init.ops = &tegra_clk_periph_fixed_ops;
106
107 fixed->base = base;
108 fixed->regs = regs;
109 fixed->mul = mul;
110 fixed->div = div;
111 fixed->num = num;
112
113 fixed->hw.init = &init;
114
115 clk = clk_register(NULL, &fixed->hw);
116 if (IS_ERR(clk))
117 kfree(fixed);
118
119 return clk;
120}
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
index d28d6e95020f..88127828befe 100644
--- a/drivers/clk/tegra/clk-periph-gate.c
+++ b/drivers/clk/tegra/clk-periph-gate.c
@@ -134,7 +134,7 @@ struct clk *tegra_clk_register_periph_gate(const char *name,
134 struct tegra_clk_periph_gate *gate; 134 struct tegra_clk_periph_gate *gate;
135 struct clk *clk; 135 struct clk *clk;
136 struct clk_init_data init; 136 struct clk_init_data init;
137 struct tegra_clk_periph_regs *pregs; 137 const struct tegra_clk_periph_regs *pregs;
138 138
139 pregs = get_reg_bank(clk_num); 139 pregs = get_reg_bank(clk_num);
140 if (!pregs) 140 if (!pregs)
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index ec5b6113b012..a17ca6d7f649 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -145,7 +145,7 @@ static struct clk *_tegra_clk_register_periph(const char *name,
145{ 145{
146 struct clk *clk; 146 struct clk *clk;
147 struct clk_init_data init; 147 struct clk_init_data init;
148 struct tegra_clk_periph_regs *bank; 148 const struct tegra_clk_periph_regs *bank;
149 bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV); 149 bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV);
150 150
151 if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) { 151 if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) {
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index 6ac3f843e7ca..4e194ecc8d5e 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -2013,6 +2013,52 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
2013#endif 2013#endif
2014 2014
2015#if defined(CONFIG_ARCH_TEGRA_210_SOC) 2015#if defined(CONFIG_ARCH_TEGRA_210_SOC)
2016struct clk *tegra_clk_register_pllre_tegra210(const char *name,
2017 const char *parent_name, void __iomem *clk_base,
2018 void __iomem *pmc, unsigned long flags,
2019 struct tegra_clk_pll_params *pll_params,
2020 spinlock_t *lock, unsigned long parent_rate)
2021{
2022 u32 val;
2023 struct tegra_clk_pll *pll;
2024 struct clk *clk;
2025
2026 pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
2027
2028 if (pll_params->adjust_vco)
2029 pll_params->vco_min = pll_params->adjust_vco(pll_params,
2030 parent_rate);
2031
2032 pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
2033 if (IS_ERR(pll))
2034 return ERR_CAST(pll);
2035
2036 /* program minimum rate by default */
2037
2038 val = pll_readl_base(pll);
2039 if (val & PLL_BASE_ENABLE)
2040 WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) &
2041 BIT(pll_params->iddq_bit_idx));
2042 else {
2043 val = 0x4 << divm_shift(pll);
2044 val |= 0x41 << divn_shift(pll);
2045 pll_writel_base(val, pll);
2046 }
2047
2048 /* disable lock override */
2049
2050 val = pll_readl_misc(pll);
2051 val &= ~BIT(29);
2052 pll_writel_misc(val, pll);
2053
2054 clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
2055 &tegra_clk_pllre_ops);
2056 if (IS_ERR(clk))
2057 kfree(pll);
2058
2059 return clk;
2060}
2061
2016static int clk_plle_tegra210_enable(struct clk_hw *hw) 2062static int clk_plle_tegra210_enable(struct clk_hw *hw)
2017{ 2063{
2018 struct tegra_clk_pll *pll = to_clk_pll(hw); 2064 struct tegra_clk_pll *pll = to_clk_pll(hw);
diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c
index d64ec7a1b976..91c38f1666c1 100644
--- a/drivers/clk/tegra/clk-tegra-fixed.c
+++ b/drivers/clk/tegra/clk-tegra-fixed.c
@@ -107,4 +107,3 @@ void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
107 *dt_clk = clk; 107 *dt_clk = clk;
108 } 108 }
109} 109}
110
diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c
index ea2b9cbf9e70..29d04c663abf 100644
--- a/drivers/clk/tegra/clk-tegra-periph.c
+++ b/drivers/clk/tegra/clk-tegra-periph.c
@@ -803,7 +803,7 @@ static struct tegra_periph_init_data gate_clks[] = {
803 GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0), 803 GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0),
804 GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0), 804 GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0),
805 GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0), 805 GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0),
806 GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0), 806 GATE("mipi-cal", "clk72mhz", 56, 0, tegra_clk_mipi_cal, 0),
807 GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0), 807 GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0),
808 GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0), 808 GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
809 GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0), 809 GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
@@ -821,7 +821,6 @@ static struct tegra_periph_init_data gate_clks[] = {
821 GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0), 821 GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
822 GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0), 822 GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
823 GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0), 823 GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
824 GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0),
825 GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0), 824 GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
826 GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0), 825 GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0),
827 GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0), 826 GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0),
@@ -877,7 +876,7 @@ static void __init periph_clk_init(void __iomem *clk_base,
877 struct clk **dt_clk; 876 struct clk **dt_clk;
878 877
879 for (i = 0; i < ARRAY_SIZE(periph_clks); i++) { 878 for (i = 0; i < ARRAY_SIZE(periph_clks); i++) {
880 struct tegra_clk_periph_regs *bank; 879 const struct tegra_clk_periph_regs *bank;
881 struct tegra_periph_init_data *data; 880 struct tegra_periph_init_data *data;
882 881
883 data = periph_clks + i; 882 data = periph_clks + i;
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index df47ec3169c3..b78054fac0a8 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -743,7 +743,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
743 [tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true }, 743 [tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true },
744 [tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true }, 744 [tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true },
745 [tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true }, 745 [tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true },
746 [tegra_clk_mipi_cal] = { .dt_id = TEGRA114_CLK_MIPI_CAL, .present = true },
747 [tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true }, 746 [tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true },
748 [tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true }, 747 [tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true },
749 [tegra_clk_usb3] = { .dt_id = TEGRA114_CLK_USB3, .present = true }, 748 [tegra_clk_usb3] = { .dt_id = TEGRA114_CLK_USB3, .present = true },
@@ -1237,6 +1236,11 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
1237 &emc_lock); 1236 &emc_lock);
1238 clks[TEGRA114_CLK_MC] = clk; 1237 clks[TEGRA114_CLK_MC] = clk;
1239 1238
1239 clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base,
1240 CLK_SET_RATE_PARENT, 56,
1241 periph_clk_enb_refcnt);
1242 clks[TEGRA114_CLK_MIPI_CAL] = clk;
1243
1240 for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { 1244 for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
1241 data = &tegra_periph_clk_list[i]; 1245 data = &tegra_periph_clk_list[i];
1242 clk = tegra_clk_register_periph(data->name, 1246 clk = tegra_clk_register_periph(data->name,
diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
index 61253330c12b..c205809ba580 100644
--- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
+++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
@@ -47,32 +47,32 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
47 }, 47 },
48 .speedo_scale = 100, 48 .speedo_scale = 100,
49 .voltage_scale = 1000, 49 .voltage_scale = 1000,
50 .cvb_table = { 50 .entries = {
51 {204000000UL, {1112619, -29295, 402} }, 51 { 204000000UL, { 1112619, -29295, 402 } },
52 {306000000UL, {1150460, -30585, 402} }, 52 { 306000000UL, { 1150460, -30585, 402 } },
53 {408000000UL, {1190122, -31865, 402} }, 53 { 408000000UL, { 1190122, -31865, 402 } },
54 {510000000UL, {1231606, -33155, 402} }, 54 { 510000000UL, { 1231606, -33155, 402 } },
55 {612000000UL, {1274912, -34435, 402} }, 55 { 612000000UL, { 1274912, -34435, 402 } },
56 {714000000UL, {1320040, -35725, 402} }, 56 { 714000000UL, { 1320040, -35725, 402 } },
57 {816000000UL, {1366990, -37005, 402} }, 57 { 816000000UL, { 1366990, -37005, 402 } },
58 {918000000UL, {1415762, -38295, 402} }, 58 { 918000000UL, { 1415762, -38295, 402 } },
59 {1020000000UL, {1466355, -39575, 402} }, 59 { 1020000000UL, { 1466355, -39575, 402 } },
60 {1122000000UL, {1518771, -40865, 402} }, 60 { 1122000000UL, { 1518771, -40865, 402 } },
61 {1224000000UL, {1573009, -42145, 402} }, 61 { 1224000000UL, { 1573009, -42145, 402 } },
62 {1326000000UL, {1629068, -43435, 402} }, 62 { 1326000000UL, { 1629068, -43435, 402 } },
63 {1428000000UL, {1686950, -44715, 402} }, 63 { 1428000000UL, { 1686950, -44715, 402 } },
64 {1530000000UL, {1746653, -46005, 402} }, 64 { 1530000000UL, { 1746653, -46005, 402 } },
65 {1632000000UL, {1808179, -47285, 402} }, 65 { 1632000000UL, { 1808179, -47285, 402 } },
66 {1734000000UL, {1871526, -48575, 402} }, 66 { 1734000000UL, { 1871526, -48575, 402 } },
67 {1836000000UL, {1936696, -49855, 402} }, 67 { 1836000000UL, { 1936696, -49855, 402 } },
68 {1938000000UL, {2003687, -51145, 402} }, 68 { 1938000000UL, { 2003687, -51145, 402 } },
69 {2014500000UL, {2054787, -52095, 402} }, 69 { 2014500000UL, { 2054787, -52095, 402 } },
70 {2116500000UL, {2124957, -53385, 402} }, 70 { 2116500000UL, { 2124957, -53385, 402 } },
71 {2218500000UL, {2196950, -54665, 402} }, 71 { 2218500000UL, { 2196950, -54665, 402 } },
72 {2320500000UL, {2270765, -55955, 402} }, 72 { 2320500000UL, { 2270765, -55955, 402 } },
73 {2422500000UL, {2346401, -57235, 402} }, 73 { 2422500000UL, { 2346401, -57235, 402 } },
74 {2524500000UL, {2437299, -58535, 402} }, 74 { 2524500000UL, { 2437299, -58535, 402 } },
75 {0, { 0, 0, 0} }, 75 { 0UL, { 0, 0, 0 } },
76 }, 76 },
77 .cpu_dfll_data = { 77 .cpu_dfll_data = {
78 .tune0_low = 0x005020ff, 78 .tune0_low = 0x005020ff,
@@ -84,9 +84,8 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
84 84
85static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) 85static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
86{ 86{
87 int process_id, speedo_id, speedo_value; 87 int process_id, speedo_id, speedo_value, err;
88 struct tegra_dfll_soc_data *soc; 88 struct tegra_dfll_soc_data *soc;
89 const struct cvb_table *cvb;
90 89
91 process_id = tegra_sku_info.cpu_process_id; 90 process_id = tegra_sku_info.cpu_process_id;
92 speedo_id = tegra_sku_info.cpu_speedo_id; 91 speedo_id = tegra_sku_info.cpu_speedo_id;
@@ -108,23 +107,41 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
108 return -ENODEV; 107 return -ENODEV;
109 } 108 }
110 109
111 cvb = tegra_cvb_build_opp_table(tegra124_cpu_cvb_tables, 110 soc->max_freq = cpu_max_freq_table[speedo_id];
112 ARRAY_SIZE(tegra124_cpu_cvb_tables), 111
113 process_id, speedo_id, speedo_value, 112 soc->cvb = tegra_cvb_add_opp_table(soc->dev, tegra124_cpu_cvb_tables,
114 cpu_max_freq_table[speedo_id], 113 ARRAY_SIZE(tegra124_cpu_cvb_tables),
115 soc->dev); 114 process_id, speedo_id, speedo_value,
116 if (IS_ERR(cvb)) { 115 soc->max_freq);
117 dev_err(&pdev->dev, "couldn't build OPP table: %ld\n", 116 if (IS_ERR(soc->cvb)) {
118 PTR_ERR(cvb)); 117 dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
119 return PTR_ERR(cvb); 118 PTR_ERR(soc->cvb));
119 return PTR_ERR(soc->cvb);
120 }
121
122 err = tegra_dfll_register(pdev, soc);
123 if (err < 0) {
124 tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
125 return err;
120 } 126 }
121 127
122 soc->min_millivolts = cvb->min_millivolts; 128 platform_set_drvdata(pdev, soc);
123 soc->tune0_low = cvb->cpu_dfll_data.tune0_low; 129
124 soc->tune0_high = cvb->cpu_dfll_data.tune0_high; 130 return 0;
125 soc->tune1 = cvb->cpu_dfll_data.tune1; 131}
132
133static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
134{
135 struct tegra_dfll_soc_data *soc = platform_get_drvdata(pdev);
136 int err;
137
138 err = tegra_dfll_unregister(pdev);
139 if (err < 0)
140 dev_err(&pdev->dev, "failed to unregister DFLL: %d\n", err);
141
142 tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
126 143
127 return tegra_dfll_register(pdev, soc); 144 return 0;
128} 145}
129 146
130static const struct of_device_id tegra124_dfll_fcpu_of_match[] = { 147static const struct of_device_id tegra124_dfll_fcpu_of_match[] = {
@@ -140,7 +157,7 @@ static const struct dev_pm_ops tegra124_dfll_pm_ops = {
140 157
141static struct platform_driver tegra124_dfll_fcpu_driver = { 158static struct platform_driver tegra124_dfll_fcpu_driver = {
142 .probe = tegra124_dfll_fcpu_probe, 159 .probe = tegra124_dfll_fcpu_probe,
143 .remove = tegra_dfll_unregister, 160 .remove = tegra124_dfll_fcpu_remove,
144 .driver = { 161 .driver = {
145 .name = "tegra124-dfll", 162 .name = "tegra124-dfll",
146 .of_match_table = tegra124_dfll_fcpu_of_match, 163 .of_match_table = tegra124_dfll_fcpu_of_match,
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c
index 1627258292d2..f4fbbf16a056 100644
--- a/drivers/clk/tegra/clk-tegra124.c
+++ b/drivers/clk/tegra/clk-tegra124.c
@@ -1155,6 +1155,10 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
1155 1, 2); 1155 1, 2);
1156 clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk; 1156 clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk;
1157 1157
1158 clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base,
1159 1, 17, 181);
1160 clks[TEGRA124_CLK_DPAUX] = clk;
1161
1158 clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, 1162 clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
1159 clk_base + PLLD_MISC, 30, 0, &pll_d_lock); 1163 clk_base + PLLD_MISC, 30, 0, &pll_d_lock);
1160 clks[TEGRA124_CLK_PLL_D_DSI_OUT] = clk; 1164 clks[TEGRA124_CLK_PLL_D_DSI_OUT] = clk;
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c
index 3d0edee1f9fe..b8551813ec43 100644
--- a/drivers/clk/tegra/clk-tegra210.c
+++ b/drivers/clk/tegra/clk-tegra210.c
@@ -92,6 +92,7 @@
92#define PLLE_AUX 0x48c 92#define PLLE_AUX 0x48c
93#define PLLRE_BASE 0x4c4 93#define PLLRE_BASE 0x4c4
94#define PLLRE_MISC0 0x4c8 94#define PLLRE_MISC0 0x4c8
95#define PLLRE_OUT1 0x4cc
95#define PLLDP_BASE 0x590 96#define PLLDP_BASE 0x590
96#define PLLDP_MISC 0x594 97#define PLLDP_MISC 0x594
97 98
@@ -2150,6 +2151,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
2150 [tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true }, 2151 [tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true },
2151 [tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true }, 2152 [tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true },
2152 [tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true }, 2153 [tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true },
2154 [tegra_clk_dpaux1] = { .dt_id = TEGRA210_CLK_DPAUX1, .present = true },
2153 [tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true }, 2155 [tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true },
2154 [tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true }, 2156 [tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true },
2155 [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, 2157 [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true },
@@ -2461,6 +2463,18 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
2461 1, 2); 2463 1, 2);
2462 clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk; 2464 clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk;
2463 2465
2466 clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base,
2467 1, 17, 181);
2468 clks[TEGRA210_CLK_DPAUX] = clk;
2469
2470 clk = tegra_clk_register_periph_fixed("dpaux1", "pll_p", 0, clk_base,
2471 1, 17, 207);
2472 clks[TEGRA210_CLK_DPAUX1] = clk;
2473
2474 clk = tegra_clk_register_periph_fixed("sor_safe", "pll_p", 0, clk_base,
2475 1, 17, 222);
2476 clks[TEGRA210_CLK_SOR_SAFE] = clk;
2477
2464 /* pll_d_dsi_out */ 2478 /* pll_d_dsi_out */
2465 clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, 2479 clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
2466 clk_base + PLLD_MISC0, 21, 0, &pll_d_lock); 2480 clk_base + PLLD_MISC0, 21, 0, &pll_d_lock);
@@ -2640,8 +2654,10 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
2640 clks[TEGRA210_CLK_PLL_D_OUT0] = clk; 2654 clks[TEGRA210_CLK_PLL_D_OUT0] = clk;
2641 2655
2642 /* PLLRE */ 2656 /* PLLRE */
2643 clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, 2657 clk = tegra_clk_register_pllre_tegra210("pll_re_vco", "pll_ref",
2644 0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); 2658 clk_base, pmc, 0,
2659 &pll_re_vco_params,
2660 &pll_re_lock, pll_ref_freq);
2645 clk_register_clkdev(clk, "pll_re_vco", NULL); 2661 clk_register_clkdev(clk, "pll_re_vco", NULL);
2646 clks[TEGRA210_CLK_PLL_RE_VCO] = clk; 2662 clks[TEGRA210_CLK_PLL_RE_VCO] = clk;
2647 2663
@@ -2651,6 +2667,15 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
2651 clk_register_clkdev(clk, "pll_re_out", NULL); 2667 clk_register_clkdev(clk, "pll_re_out", NULL);
2652 clks[TEGRA210_CLK_PLL_RE_OUT] = clk; 2668 clks[TEGRA210_CLK_PLL_RE_OUT] = clk;
2653 2669
2670 clk = tegra_clk_register_divider("pll_re_out1_div", "pll_re_vco",
2671 clk_base + PLLRE_OUT1, 0,
2672 TEGRA_DIVIDER_ROUND_UP,
2673 8, 8, 1, NULL);
2674 clk = tegra_clk_register_pll_out("pll_re_out1", "pll_re_out1_div",
2675 clk_base + PLLRE_OUT1, 1, 0,
2676 CLK_SET_RATE_PARENT, 0, NULL);
2677 clks[TEGRA210_CLK_PLL_RE_OUT1] = clk;
2678
2654 /* PLLE */ 2679 /* PLLE */
2655 clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref", 2680 clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref",
2656 clk_base, 0, &pll_e_params, NULL); 2681 clk_base, 0, &pll_e_params, NULL);
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 0478565cf292..9396f4930da7 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -339,11 +339,11 @@ static const struct pdiv_map pllu_p[] = {
339}; 339};
340 340
341static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { 341static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
342 { 12000000, 480000000, 960, 12, 1, 12 }, 342 { 12000000, 480000000, 960, 12, 2, 12 },
343 { 13000000, 480000000, 960, 13, 1, 12 }, 343 { 13000000, 480000000, 960, 13, 2, 12 },
344 { 16800000, 480000000, 400, 7, 1, 5 }, 344 { 16800000, 480000000, 400, 7, 2, 5 },
345 { 19200000, 480000000, 200, 4, 1, 3 }, 345 { 19200000, 480000000, 200, 4, 2, 3 },
346 { 26000000, 480000000, 960, 26, 1, 12 }, 346 { 26000000, 480000000, 960, 26, 2, 12 },
347 { 0, 0, 0, 0, 0, 0 }, 347 { 0, 0, 0, 0, 0, 0 },
348}; 348};
349 349
@@ -1372,6 +1372,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
1372 { TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 }, 1372 { TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 },
1373 { TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 }, 1373 { TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 },
1374 { TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 }, 1374 { TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 },
1375 { TEGRA30_CLK_PLL_C, TEGRA30_CLK_CLK_MAX, 600000000, 0 },
1375 { TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 }, 1376 { TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 },
1376 { TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 }, 1377 { TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 },
1377 { TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 }, 1378 { TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 },
@@ -1379,6 +1380,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
1379 { TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 }, 1380 { TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 },
1380 { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, 1381 { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 },
1381 { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, 1382 { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 },
1383 { TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 },
1382 /* must be the last entry */ 1384 /* must be the last entry */
1383 { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 }, 1385 { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
1384}; 1386};
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index f60fe2e344ca..b2cdd9a235f4 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -84,7 +84,7 @@ static int (*special_reset_assert)(unsigned long);
84static int (*special_reset_deassert)(unsigned long); 84static int (*special_reset_deassert)(unsigned long);
85static unsigned int num_special_reset; 85static unsigned int num_special_reset;
86 86
87static struct tegra_clk_periph_regs periph_regs[] = { 87static const struct tegra_clk_periph_regs periph_regs[] = {
88 [0] = { 88 [0] = {
89 .enb_reg = CLK_OUT_ENB_L, 89 .enb_reg = CLK_OUT_ENB_L,
90 .enb_set_reg = CLK_OUT_ENB_SET_L, 90 .enb_set_reg = CLK_OUT_ENB_SET_L,
@@ -182,7 +182,7 @@ static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
182 return -EINVAL; 182 return -EINVAL;
183} 183}
184 184
185struct tegra_clk_periph_regs *get_reg_bank(int clkid) 185const struct tegra_clk_periph_regs *get_reg_bank(int clkid)
186{ 186{
187 int reg_bank = clkid / 32; 187 int reg_bank = clkid / 32;
188 188
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
index 4dbcfaec576a..9421f0310999 100644
--- a/drivers/clk/tegra/clk.h
+++ b/drivers/clk/tegra/clk.h
@@ -386,6 +386,12 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
386 struct tegra_clk_pll_params *pll_params, 386 struct tegra_clk_pll_params *pll_params,
387 spinlock_t *lock, unsigned long parent_rate); 387 spinlock_t *lock, unsigned long parent_rate);
388 388
389struct clk *tegra_clk_register_pllre_tegra210(const char *name,
390 const char *parent_name, void __iomem *clk_base,
391 void __iomem *pmc, unsigned long flags,
392 struct tegra_clk_pll_params *pll_params,
393 spinlock_t *lock, unsigned long parent_rate);
394
389struct clk *tegra_clk_register_plle_tegra114(const char *name, 395struct clk *tegra_clk_register_plle_tegra114(const char *name,
390 const char *parent_name, 396 const char *parent_name,
391 void __iomem *clk_base, unsigned long flags, 397 void __iomem *clk_base, unsigned long flags,
@@ -496,7 +502,7 @@ struct tegra_clk_periph_gate {
496 u8 flags; 502 u8 flags;
497 int clk_num; 503 int clk_num;
498 int *enable_refcnt; 504 int *enable_refcnt;
499 struct tegra_clk_periph_regs *regs; 505 const struct tegra_clk_periph_regs *regs;
500}; 506};
501 507
502#define to_clk_periph_gate(_hw) \ 508#define to_clk_periph_gate(_hw) \
@@ -516,6 +522,23 @@ struct clk *tegra_clk_register_periph_gate(const char *name,
516 const char *parent_name, u8 gate_flags, void __iomem *clk_base, 522 const char *parent_name, u8 gate_flags, void __iomem *clk_base,
517 unsigned long flags, int clk_num, int *enable_refcnt); 523 unsigned long flags, int clk_num, int *enable_refcnt);
518 524
525struct tegra_clk_periph_fixed {
526 struct clk_hw hw;
527 void __iomem *base;
528 const struct tegra_clk_periph_regs *regs;
529 unsigned int mul;
530 unsigned int div;
531 unsigned int num;
532};
533
534struct clk *tegra_clk_register_periph_fixed(const char *name,
535 const char *parent,
536 unsigned long flags,
537 void __iomem *base,
538 unsigned int mul,
539 unsigned int div,
540 unsigned int num);
541
519/** 542/**
520 * struct clk-periph - peripheral clock 543 * struct clk-periph - peripheral clock
521 * 544 *
@@ -716,7 +739,7 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl,
716void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, 739void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
717 struct clk *clks[], int clk_max); 740 struct clk *clks[], int clk_max);
718 741
719struct tegra_clk_periph_regs *get_reg_bank(int clkid); 742const struct tegra_clk_periph_regs *get_reg_bank(int clkid);
720struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks); 743struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks);
721 744
722struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); 745struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk);
diff --git a/drivers/clk/tegra/cvb.c b/drivers/clk/tegra/cvb.c
index 69c74eec3a4b..624115e82ff9 100644
--- a/drivers/clk/tegra/cvb.c
+++ b/drivers/clk/tegra/cvb.c
@@ -61,29 +61,28 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up)
61 return mv; 61 return mv;
62} 62}
63 63
64static int build_opp_table(const struct cvb_table *d, 64static int build_opp_table(struct device *dev, const struct cvb_table *table,
65 int speedo_value, 65 int speedo_value, unsigned long max_freq)
66 unsigned long max_freq,
67 struct device *opp_dev)
68{ 66{
67 const struct rail_alignment *align = &table->alignment;
69 int i, ret, dfll_mv, min_mv, max_mv; 68 int i, ret, dfll_mv, min_mv, max_mv;
70 const struct cvb_table_freq_entry *table = NULL;
71 const struct rail_alignment *align = &d->alignment;
72 69
73 min_mv = round_voltage(d->min_millivolts, align, UP); 70 min_mv = round_voltage(table->min_millivolts, align, UP);
74 max_mv = round_voltage(d->max_millivolts, align, DOWN); 71 max_mv = round_voltage(table->max_millivolts, align, DOWN);
75 72
76 for (i = 0; i < MAX_DVFS_FREQS; i++) { 73 for (i = 0; i < MAX_DVFS_FREQS; i++) {
77 table = &d->cvb_table[i]; 74 const struct cvb_table_freq_entry *entry = &table->entries[i];
78 if (!table->freq || (table->freq > max_freq)) 75
76 if (!entry->freq || (entry->freq > max_freq))
79 break; 77 break;
80 78
81 dfll_mv = get_cvb_voltage( 79 dfll_mv = get_cvb_voltage(speedo_value, table->speedo_scale,
82 speedo_value, d->speedo_scale, &table->coefficients); 80 &entry->coefficients);
83 dfll_mv = round_cvb_voltage(dfll_mv, d->voltage_scale, align); 81 dfll_mv = round_cvb_voltage(dfll_mv, table->voltage_scale,
82 align);
84 dfll_mv = clamp(dfll_mv, min_mv, max_mv); 83 dfll_mv = clamp(dfll_mv, min_mv, max_mv);
85 84
86 ret = dev_pm_opp_add(opp_dev, table->freq, dfll_mv * 1000); 85 ret = dev_pm_opp_add(dev, entry->freq, dfll_mv * 1000);
87 if (ret) 86 if (ret)
88 return ret; 87 return ret;
89 } 88 }
@@ -92,7 +91,7 @@ static int build_opp_table(const struct cvb_table *d,
92} 91}
93 92
94/** 93/**
95 * tegra_cvb_build_opp_table - build OPP table from Tegra CVB tables 94 * tegra_cvb_add_opp_table - build OPP table from Tegra CVB tables
96 * @cvb_tables: array of CVB tables 95 * @cvb_tables: array of CVB tables
97 * @sz: size of the previously mentioned array 96 * @sz: size of the previously mentioned array
98 * @process_id: process id of the HW module 97 * @process_id: process id of the HW module
@@ -108,26 +107,42 @@ static int build_opp_table(const struct cvb_table *d,
108 * given @opp_dev. Returns a pointer to the struct cvb_table that matched 107 * given @opp_dev. Returns a pointer to the struct cvb_table that matched
109 * or an ERR_PTR on failure. 108 * or an ERR_PTR on failure.
110 */ 109 */
111const struct cvb_table *tegra_cvb_build_opp_table( 110const struct cvb_table *
112 const struct cvb_table *cvb_tables, 111tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
113 size_t sz, int process_id, 112 size_t count, int process_id, int speedo_id,
114 int speedo_id, int speedo_value, 113 int speedo_value, unsigned long max_freq)
115 unsigned long max_rate,
116 struct device *opp_dev)
117{ 114{
118 int i, ret; 115 size_t i;
116 int ret;
119 117
120 for (i = 0; i < sz; i++) { 118 for (i = 0; i < count; i++) {
121 const struct cvb_table *d = &cvb_tables[i]; 119 const struct cvb_table *table = &tables[i];
122 120
123 if (d->speedo_id != -1 && d->speedo_id != speedo_id) 121 if (table->speedo_id != -1 && table->speedo_id != speedo_id)
124 continue; 122 continue;
125 if (d->process_id != -1 && d->process_id != process_id) 123
124 if (table->process_id != -1 && table->process_id != process_id)
126 continue; 125 continue;
127 126
128 ret = build_opp_table(d, speedo_value, max_rate, opp_dev); 127 ret = build_opp_table(dev, table, speedo_value, max_freq);
129 return ret ? ERR_PTR(ret) : d; 128 return ret ? ERR_PTR(ret) : table;
130 } 129 }
131 130
132 return ERR_PTR(-EINVAL); 131 return ERR_PTR(-EINVAL);
133} 132}
133
134void tegra_cvb_remove_opp_table(struct device *dev,
135 const struct cvb_table *table,
136 unsigned long max_freq)
137{
138 unsigned int i;
139
140 for (i = 0; i < MAX_DVFS_FREQS; i++) {
141 const struct cvb_table_freq_entry *entry = &table->entries[i];
142
143 if (!entry->freq || (entry->freq > max_freq))
144 break;
145
146 dev_pm_opp_remove(dev, entry->freq);
147 }
148}
diff --git a/drivers/clk/tegra/cvb.h b/drivers/clk/tegra/cvb.h
index f62cdc4f4234..c1f077993b2a 100644
--- a/drivers/clk/tegra/cvb.h
+++ b/drivers/clk/tegra/cvb.h
@@ -53,15 +53,16 @@ struct cvb_table {
53 53
54 int speedo_scale; 54 int speedo_scale;
55 int voltage_scale; 55 int voltage_scale;
56 struct cvb_table_freq_entry cvb_table[MAX_DVFS_FREQS]; 56 struct cvb_table_freq_entry entries[MAX_DVFS_FREQS];
57 struct cvb_cpu_dfll_data cpu_dfll_data; 57 struct cvb_cpu_dfll_data cpu_dfll_data;
58}; 58};
59 59
60const struct cvb_table *tegra_cvb_build_opp_table( 60const struct cvb_table *
61 const struct cvb_table *cvb_tables, 61tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
62 size_t sz, int process_id, 62 size_t count, int process_id, int speedo_id,
63 int speedo_id, int speedo_value, 63 int speedo_value, unsigned long max_freq);
64 unsigned long max_rate, 64void tegra_cvb_remove_opp_table(struct device *dev,
65 struct device *opp_dev); 65 const struct cvb_table *table,
66 unsigned long max_freq);
66 67
67#endif 68#endif