Commit 5bc75324 authored by Stephen Boyd's avatar Stephen Boyd

Merge tag 'tegra-for-4.7-clk' of...

Merge tag 'tegra-for-4.7-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into clk-next

Pull tegra clk driver changes from Thierry Reding:

This set of changes contains a bunch of cleanups and minor fixes along
with some new clocks, mainly on Tegra210, in preparation for supporting
DisplayPort and HDMI 2.0.

* tag 'tegra-for-4.7-clk' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  clk: tegra: dfll: Reformat CVB frequency table
  clk: tegra: dfll: Properly clean up on failure and removal
  clk: tegra: dfll: Make code more comprehensible
  clk: tegra: dfll: Reference CVB table instead of copying data
  clk: tegra: dfll: Update kerneldoc
  clk: tegra: Fix PLL_U post divider and initial rate on Tegra30
  clk: tegra: Initialize PLL_C to sane rate on Tegra30
  clk: tegra: Fix pllre Tegra210 and add pll_re_out1
  clk: tegra: Add sor_safe clock
  clk: tegra: dpaux and dpaux1 are fixed factor clocks
  clk: tegra: Add dpaux1 clock
  clk: tegra: Use correct parent for dpaux clock
  clk: tegra: Add fixed factor peripheral clock type
  clk: tegra: Special-case mipi-cal parent on Tegra114
  clk: tegra: Remove trailing blank line
  clk: tegra: Constify peripheral clock registers
  clk: tegra: Add interface to enable hardware control of SATA/XUSB PLLs
parents 5569aedf 2690e912
...@@ -3,6 +3,7 @@ obj-y += clk-audio-sync.o ...@@ -3,6 +3,7 @@ obj-y += clk-audio-sync.o
obj-y += clk-dfll.o obj-y += clk-dfll.o
obj-y += clk-divider.o obj-y += clk-divider.o
obj-y += clk-periph.o obj-y += clk-periph.o
obj-y += clk-periph-fixed.o
obj-y += clk-periph-gate.o obj-y += clk-periph-gate.o
obj-y += clk-pll.o obj-y += clk-pll.o
obj-y += clk-pll-out.o obj-y += clk-pll-out.o
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include "clk-dfll.h" #include "clk-dfll.h"
#include "cvb.h"
/* /*
* DFLL control registers - access via dfll_{readl,writel} * DFLL control registers - access via dfll_{readl,writel}
...@@ -442,8 +443,8 @@ static void dfll_tune_low(struct tegra_dfll *td) ...@@ -442,8 +443,8 @@ static void dfll_tune_low(struct tegra_dfll *td)
{ {
td->tune_range = DFLL_TUNE_LOW; td->tune_range = DFLL_TUNE_LOW;
dfll_writel(td, td->soc->tune0_low, DFLL_TUNE0); dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune0_low, DFLL_TUNE0);
dfll_writel(td, td->soc->tune1, DFLL_TUNE1); dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1, DFLL_TUNE1);
dfll_wmb(td); dfll_wmb(td);
if (td->soc->set_clock_trimmers_low) if (td->soc->set_clock_trimmers_low)
...@@ -1449,7 +1450,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) ...@@ -1449,7 +1450,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
} }
v_max = dev_pm_opp_get_voltage(opp); v_max = dev_pm_opp_get_voltage(opp);
v = td->soc->min_millivolts * 1000; v = td->soc->cvb->min_millivolts * 1000;
lut = find_vdd_map_entry_exact(td, v); lut = find_vdd_map_entry_exact(td, v);
if (lut < 0) if (lut < 0)
goto out; goto out;
...@@ -1461,7 +1462,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) ...@@ -1461,7 +1462,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
break; break;
v_opp = dev_pm_opp_get_voltage(opp); v_opp = dev_pm_opp_get_voltage(opp);
if (v_opp <= td->soc->min_millivolts * 1000) if (v_opp <= td->soc->cvb->min_millivolts * 1000)
td->dvco_rate_min = dev_pm_opp_get_freq(opp); td->dvco_rate_min = dev_pm_opp_get_freq(opp);
for (;;) { for (;;) {
...@@ -1490,7 +1491,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td) ...@@ -1490,7 +1491,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
if (!td->dvco_rate_min) if (!td->dvco_rate_min)
dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n", dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
td->soc->min_millivolts); td->soc->cvb->min_millivolts);
else else
ret = 0; ret = 0;
......
...@@ -24,22 +24,18 @@ ...@@ -24,22 +24,18 @@
/** /**
* struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver * struct tegra_dfll_soc_data - SoC-specific hooks/integration for the DFLL driver
* @opp_dev: struct device * that holds the OPP table for the DFLL * @dev: struct device * that holds the OPP table for the DFLL
* @min_millivolts: minimum voltage (in mV) that the DFLL can operate * @max_freq: maximum frequency supported on this SoC
* @tune0_low: DFLL tuning register 0 (low voltage range) * @cvb: CPU frequency table for this SoC
* @tune0_high: DFLL tuning register 0 (high voltage range) * @init_clock_trimmers: callback to initialize clock trimmers
* @tune1: DFLL tuning register 1 * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage
* @assert_dvco_reset: fn ptr to place the DVCO in reset * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage
* @deassert_dvco_reset: fn ptr to release the DVCO reset
* @set_clock_trimmers_high: fn ptr to tune clock trimmers for high voltage
* @set_clock_trimmers_low: fn ptr to tune clock trimmers for low voltage
*/ */
struct tegra_dfll_soc_data { struct tegra_dfll_soc_data {
struct device *dev; struct device *dev;
unsigned int min_millivolts; unsigned long max_freq;
u32 tune0_low; const struct cvb_table *cvb;
u32 tune0_high;
u32 tune1;
void (*init_clock_trimmers)(void); void (*init_clock_trimmers)(void);
void (*set_clock_trimmers_high)(void); void (*set_clock_trimmers_high)(void);
void (*set_clock_trimmers_low)(void); void (*set_clock_trimmers_low)(void);
......
...@@ -71,6 +71,7 @@ enum clk_id { ...@@ -71,6 +71,7 @@ enum clk_id {
tegra_clk_disp2_8, tegra_clk_disp2_8,
tegra_clk_dp2, tegra_clk_dp2,
tegra_clk_dpaux, tegra_clk_dpaux,
tegra_clk_dpaux1,
tegra_clk_dsialp, tegra_clk_dsialp,
tegra_clk_dsia_mux, tegra_clk_dsia_mux,
tegra_clk_dsiblp, tegra_clk_dsiblp,
...@@ -306,6 +307,7 @@ enum clk_id { ...@@ -306,6 +307,7 @@ enum clk_id {
tegra_clk_xusb_ss_div2, tegra_clk_xusb_ss_div2,
tegra_clk_xusb_ssp_src, tegra_clk_xusb_ssp_src,
tegra_clk_sclk_mux, tegra_clk_sclk_mux,
tegra_clk_sor_safe,
tegra_clk_max, tegra_clk_max,
}; };
......
/*
* Copyright (c) 2015, 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/clk-provider.h>
#include "clk.h"
static inline struct tegra_clk_periph_fixed *
to_tegra_clk_periph_fixed(struct clk_hw *hw)
{
return container_of(hw, struct tegra_clk_periph_fixed, hw);
}
static int tegra_clk_periph_fixed_is_enabled(struct clk_hw *hw)
{
struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
u32 mask = 1 << (fixed->num % 32), value;
value = readl(fixed->base + fixed->regs->enb_reg);
if (value & mask) {
value = readl(fixed->base + fixed->regs->rst_reg);
if ((value & mask) == 0)
return 1;
}
return 0;
}
static int tegra_clk_periph_fixed_enable(struct clk_hw *hw)
{
struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
u32 mask = 1 << (fixed->num % 32);
writel(mask, fixed->base + fixed->regs->enb_set_reg);
return 0;
}
static void tegra_clk_periph_fixed_disable(struct clk_hw *hw)
{
struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
u32 mask = 1 << (fixed->num % 32);
writel(mask, fixed->base + fixed->regs->enb_clr_reg);
}
static unsigned long
tegra_clk_periph_fixed_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct tegra_clk_periph_fixed *fixed = to_tegra_clk_periph_fixed(hw);
unsigned long long rate;
rate = (unsigned long long)parent_rate * fixed->mul;
do_div(rate, fixed->div);
return (unsigned long)rate;
}
static const struct clk_ops tegra_clk_periph_fixed_ops = {
.is_enabled = tegra_clk_periph_fixed_is_enabled,
.enable = tegra_clk_periph_fixed_enable,
.disable = tegra_clk_periph_fixed_disable,
.recalc_rate = tegra_clk_periph_fixed_recalc_rate,
};
struct clk *tegra_clk_register_periph_fixed(const char *name,
const char *parent,
unsigned long flags,
void __iomem *base,
unsigned int mul,
unsigned int div,
unsigned int num)
{
const struct tegra_clk_periph_regs *regs;
struct tegra_clk_periph_fixed *fixed;
struct clk_init_data init;
struct clk *clk;
regs = get_reg_bank(num);
if (!regs)
return ERR_PTR(-EINVAL);
fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
if (!fixed)
return ERR_PTR(-ENOMEM);
init.name = name;
init.flags = flags;
init.parent_names = parent ? &parent : NULL;
init.num_parents = parent ? 1 : 0;
init.ops = &tegra_clk_periph_fixed_ops;
fixed->base = base;
fixed->regs = regs;
fixed->mul = mul;
fixed->div = div;
fixed->num = num;
fixed->hw.init = &init;
clk = clk_register(NULL, &fixed->hw);
if (IS_ERR(clk))
kfree(fixed);
return clk;
}
...@@ -134,7 +134,7 @@ struct clk *tegra_clk_register_periph_gate(const char *name, ...@@ -134,7 +134,7 @@ struct clk *tegra_clk_register_periph_gate(const char *name,
struct tegra_clk_periph_gate *gate; struct tegra_clk_periph_gate *gate;
struct clk *clk; struct clk *clk;
struct clk_init_data init; struct clk_init_data init;
struct tegra_clk_periph_regs *pregs; const struct tegra_clk_periph_regs *pregs;
pregs = get_reg_bank(clk_num); pregs = get_reg_bank(clk_num);
if (!pregs) if (!pregs)
......
...@@ -145,7 +145,7 @@ static struct clk *_tegra_clk_register_periph(const char *name, ...@@ -145,7 +145,7 @@ static struct clk *_tegra_clk_register_periph(const char *name,
{ {
struct clk *clk; struct clk *clk;
struct clk_init_data init; struct clk_init_data init;
struct tegra_clk_periph_regs *bank; const struct tegra_clk_periph_regs *bank;
bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV); bool div = !(periph->gate.flags & TEGRA_PERIPH_NO_DIV);
if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) { if (periph->gate.flags & TEGRA_PERIPH_NO_DIV) {
......
...@@ -2013,6 +2013,52 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name, ...@@ -2013,6 +2013,52 @@ struct clk *tegra_clk_register_pllss(const char *name, const char *parent_name,
#endif #endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC) #if defined(CONFIG_ARCH_TEGRA_210_SOC)
struct clk *tegra_clk_register_pllre_tegra210(const char *name,
const char *parent_name, void __iomem *clk_base,
void __iomem *pmc, unsigned long flags,
struct tegra_clk_pll_params *pll_params,
spinlock_t *lock, unsigned long parent_rate)
{
u32 val;
struct tegra_clk_pll *pll;
struct clk *clk;
pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate);
if (pll_params->adjust_vco)
pll_params->vco_min = pll_params->adjust_vco(pll_params,
parent_rate);
pll = _tegra_init_pll(clk_base, pmc, pll_params, lock);
if (IS_ERR(pll))
return ERR_CAST(pll);
/* program minimum rate by default */
val = pll_readl_base(pll);
if (val & PLL_BASE_ENABLE)
WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) &
BIT(pll_params->iddq_bit_idx));
else {
val = 0x4 << divm_shift(pll);
val |= 0x41 << divn_shift(pll);
pll_writel_base(val, pll);
}
/* disable lock override */
val = pll_readl_misc(pll);
val &= ~BIT(29);
pll_writel_misc(val, pll);
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
&tegra_clk_pllre_ops);
if (IS_ERR(clk))
kfree(pll);
return clk;
}
static int clk_plle_tegra210_enable(struct clk_hw *hw) static int clk_plle_tegra210_enable(struct clk_hw *hw)
{ {
struct tegra_clk_pll *pll = to_clk_pll(hw); struct tegra_clk_pll *pll = to_clk_pll(hw);
......
...@@ -107,4 +107,3 @@ void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks) ...@@ -107,4 +107,3 @@ void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)
*dt_clk = clk; *dt_clk = clk;
} }
} }
...@@ -803,7 +803,7 @@ static struct tegra_periph_init_data gate_clks[] = { ...@@ -803,7 +803,7 @@ static struct tegra_periph_init_data gate_clks[] = {
GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0), GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0),
GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0), GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0),
GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0), GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0),
GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0), GATE("mipi-cal", "clk72mhz", 56, 0, tegra_clk_mipi_cal, 0),
GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0), GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0),
GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0), GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0), GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
...@@ -821,7 +821,6 @@ static struct tegra_periph_init_data gate_clks[] = { ...@@ -821,7 +821,6 @@ static struct tegra_periph_init_data gate_clks[] = {
GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0), GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0), GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0), GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0),
GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0), GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0), GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0),
GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0), 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,7 +876,7 @@ static void __init periph_clk_init(void __iomem *clk_base,
struct clk **dt_clk; struct clk **dt_clk;
for (i = 0; i < ARRAY_SIZE(periph_clks); i++) { for (i = 0; i < ARRAY_SIZE(periph_clks); i++) {
struct tegra_clk_periph_regs *bank; const struct tegra_clk_periph_regs *bank;
struct tegra_periph_init_data *data; struct tegra_periph_init_data *data;
data = periph_clks + i; data = periph_clks + i;
......
...@@ -743,7 +743,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = { ...@@ -743,7 +743,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
[tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true }, [tegra_clk_csi] = { .dt_id = TEGRA114_CLK_CSI, .present = true },
[tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true }, [tegra_clk_i2c2] = { .dt_id = TEGRA114_CLK_I2C2, .present = true },
[tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true }, [tegra_clk_uartc] = { .dt_id = TEGRA114_CLK_UARTC, .present = true },
[tegra_clk_mipi_cal] = { .dt_id = TEGRA114_CLK_MIPI_CAL, .present = true },
[tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true }, [tegra_clk_emc] = { .dt_id = TEGRA114_CLK_EMC, .present = true },
[tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true }, [tegra_clk_usb2] = { .dt_id = TEGRA114_CLK_USB2, .present = true },
[tegra_clk_usb3] = { .dt_id = TEGRA114_CLK_USB3, .present = true }, [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,6 +1236,11 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
&emc_lock); &emc_lock);
clks[TEGRA114_CLK_MC] = clk; clks[TEGRA114_CLK_MC] = clk;
clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base,
CLK_SET_RATE_PARENT, 56,
periph_clk_enb_refcnt);
clks[TEGRA114_CLK_MIPI_CAL] = clk;
for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
data = &tegra_periph_clk_list[i]; data = &tegra_periph_clk_list[i];
clk = tegra_clk_register_periph(data->name, clk = tegra_clk_register_periph(data->name,
......
...@@ -47,32 +47,32 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = { ...@@ -47,32 +47,32 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
}, },
.speedo_scale = 100, .speedo_scale = 100,
.voltage_scale = 1000, .voltage_scale = 1000,
.cvb_table = { .entries = {
{204000000UL, {1112619, -29295, 402} }, { 204000000UL, { 1112619, -29295, 402 } },
{306000000UL, {1150460, -30585, 402} }, { 306000000UL, { 1150460, -30585, 402 } },
{408000000UL, {1190122, -31865, 402} }, { 408000000UL, { 1190122, -31865, 402 } },
{510000000UL, {1231606, -33155, 402} }, { 510000000UL, { 1231606, -33155, 402 } },
{612000000UL, {1274912, -34435, 402} }, { 612000000UL, { 1274912, -34435, 402 } },
{714000000UL, {1320040, -35725, 402} }, { 714000000UL, { 1320040, -35725, 402 } },
{816000000UL, {1366990, -37005, 402} }, { 816000000UL, { 1366990, -37005, 402 } },
{918000000UL, {1415762, -38295, 402} }, { 918000000UL, { 1415762, -38295, 402 } },
{1020000000UL, {1466355, -39575, 402} }, { 1020000000UL, { 1466355, -39575, 402 } },
{1122000000UL, {1518771, -40865, 402} }, { 1122000000UL, { 1518771, -40865, 402 } },
{1224000000UL, {1573009, -42145, 402} }, { 1224000000UL, { 1573009, -42145, 402 } },
{1326000000UL, {1629068, -43435, 402} }, { 1326000000UL, { 1629068, -43435, 402 } },
{1428000000UL, {1686950, -44715, 402} }, { 1428000000UL, { 1686950, -44715, 402 } },
{1530000000UL, {1746653, -46005, 402} }, { 1530000000UL, { 1746653, -46005, 402 } },
{1632000000UL, {1808179, -47285, 402} }, { 1632000000UL, { 1808179, -47285, 402 } },
{1734000000UL, {1871526, -48575, 402} }, { 1734000000UL, { 1871526, -48575, 402 } },
{1836000000UL, {1936696, -49855, 402} }, { 1836000000UL, { 1936696, -49855, 402 } },
{1938000000UL, {2003687, -51145, 402} }, { 1938000000UL, { 2003687, -51145, 402 } },
{2014500000UL, {2054787, -52095, 402} }, { 2014500000UL, { 2054787, -52095, 402 } },
{2116500000UL, {2124957, -53385, 402} }, { 2116500000UL, { 2124957, -53385, 402 } },
{2218500000UL, {2196950, -54665, 402} }, { 2218500000UL, { 2196950, -54665, 402 } },
{2320500000UL, {2270765, -55955, 402} }, { 2320500000UL, { 2270765, -55955, 402 } },
{2422500000UL, {2346401, -57235, 402} }, { 2422500000UL, { 2346401, -57235, 402 } },
{2524500000UL, {2437299, -58535, 402} }, { 2524500000UL, { 2437299, -58535, 402 } },
{0, { 0, 0, 0} }, { 0UL, { 0, 0, 0 } },
}, },
.cpu_dfll_data = { .cpu_dfll_data = {
.tune0_low = 0x005020ff, .tune0_low = 0x005020ff,
...@@ -84,9 +84,8 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = { ...@@ -84,9 +84,8 @@ static const struct cvb_table tegra124_cpu_cvb_tables[] = {
static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
{ {
int process_id, speedo_id, speedo_value; int process_id, speedo_id, speedo_value, err;
struct tegra_dfll_soc_data *soc; struct tegra_dfll_soc_data *soc;
const struct cvb_table *cvb;
process_id = tegra_sku_info.cpu_process_id; process_id = tegra_sku_info.cpu_process_id;
speedo_id = tegra_sku_info.cpu_speedo_id; speedo_id = tegra_sku_info.cpu_speedo_id;
...@@ -108,23 +107,41 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev) ...@@ -108,23 +107,41 @@ static int tegra124_dfll_fcpu_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
cvb = tegra_cvb_build_opp_table(tegra124_cpu_cvb_tables, soc->max_freq = cpu_max_freq_table[speedo_id];
ARRAY_SIZE(tegra124_cpu_cvb_tables),
process_id, speedo_id, speedo_value, soc->cvb = tegra_cvb_add_opp_table(soc->dev, tegra124_cpu_cvb_tables,
cpu_max_freq_table[speedo_id], ARRAY_SIZE(tegra124_cpu_cvb_tables),
soc->dev); process_id, speedo_id, speedo_value,
if (IS_ERR(cvb)) { soc->max_freq);
dev_err(&pdev->dev, "couldn't build OPP table: %ld\n", if (IS_ERR(soc->cvb)) {
PTR_ERR(cvb)); dev_err(&pdev->dev, "couldn't add OPP table: %ld\n",
return PTR_ERR(cvb); PTR_ERR(soc->cvb));
return PTR_ERR(soc->cvb);
}
err = tegra_dfll_register(pdev, soc);
if (err < 0) {
tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
return err;
} }
soc->min_millivolts = cvb->min_millivolts; platform_set_drvdata(pdev, soc);
soc->tune0_low = cvb->cpu_dfll_data.tune0_low;
soc->tune0_high = cvb->cpu_dfll_data.tune0_high; return 0;
soc->tune1 = cvb->cpu_dfll_data.tune1; }
static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
{
struct tegra_dfll_soc_data *soc = platform_get_drvdata(pdev);
int err;
err = tegra_dfll_unregister(pdev);
if (err < 0)
dev_err(&pdev->dev, "failed to unregister DFLL: %d\n", err);
tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
return tegra_dfll_register(pdev, soc); return 0;
} }
static const struct of_device_id tegra124_dfll_fcpu_of_match[] = { static 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,7 +157,7 @@ static const struct dev_pm_ops tegra124_dfll_pm_ops = {
static struct platform_driver tegra124_dfll_fcpu_driver = { static struct platform_driver tegra124_dfll_fcpu_driver = {
.probe = tegra124_dfll_fcpu_probe, .probe = tegra124_dfll_fcpu_probe,
.remove = tegra_dfll_unregister, .remove = tegra124_dfll_fcpu_remove,
.driver = { .driver = {
.name = "tegra124-dfll", .name = "tegra124-dfll",
.of_match_table = tegra124_dfll_fcpu_of_match, .of_match_table = tegra124_dfll_fcpu_of_match,
......
...@@ -1155,6 +1155,10 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base, ...@@ -1155,6 +1155,10 @@ static __init void tegra124_periph_clk_init(void __iomem *clk_base,
1, 2); 1, 2);
clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk; clks[TEGRA124_CLK_XUSB_SS_DIV2] = clk;
clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base,
1, 17, 181);
clks[TEGRA124_CLK_DPAUX] = clk;
clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
clk_base + PLLD_MISC, 30, 0, &pll_d_lock); clk_base + PLLD_MISC, 30, 0, &pll_d_lock);
clks[TEGRA124_CLK_PLL_D_DSI_OUT] = clk; clks[TEGRA124_CLK_PLL_D_DSI_OUT] = clk;
......
...@@ -92,6 +92,7 @@ ...@@ -92,6 +92,7 @@
#define PLLE_AUX 0x48c #define PLLE_AUX 0x48c
#define PLLRE_BASE 0x4c4 #define PLLRE_BASE 0x4c4
#define PLLRE_MISC0 0x4c8 #define PLLRE_MISC0 0x4c8
#define PLLRE_OUT1 0x4cc
#define PLLDP_BASE 0x590 #define PLLDP_BASE 0x590
#define PLLDP_MISC 0x594 #define PLLDP_MISC 0x594
...@@ -175,6 +176,19 @@ ...@@ -175,6 +176,19 @@
#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) #define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) #define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
#define SATA_PLL_CFG0 0x490
#define SATA_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0)
#define SATA_PLL_CFG0_PADPLL_USE_LOCKDET BIT(2)
#define SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ BIT(13)
#define SATA_PLL_CFG0_SEQ_ENABLE BIT(24)
#define XUSBIO_PLL_CFG0 0x51c
#define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL BIT(0)
#define XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL BIT(2)
#define XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET BIT(6)
#define XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ BIT(13)
#define XUSBIO_PLL_CFG0_SEQ_ENABLE BIT(24)
#define UTMIPLL_HW_PWRDN_CFG0 0x52c #define UTMIPLL_HW_PWRDN_CFG0 0x52c
#define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31) #define UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK BIT(31)
#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) #define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25)
...@@ -416,6 +430,51 @@ static const char *mux_pllmcp_clkm[] = { ...@@ -416,6 +430,51 @@ static const char *mux_pllmcp_clkm[] = {
#define PLLU_MISC0_WRITE_MASK 0xbfffffff #define PLLU_MISC0_WRITE_MASK 0xbfffffff
#define PLLU_MISC1_WRITE_MASK 0x00000007 #define PLLU_MISC1_WRITE_MASK 0x00000007
void tegra210_xusb_pll_hw_control_enable(void)
{
u32 val;
val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
val &= ~(XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL |
XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL);
val |= XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET |
XUSBIO_PLL_CFG0_PADPLL_SLEEP_IDDQ;
writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
}
EXPORT_SYMBOL_GPL(tegra210_xusb_pll_hw_control_enable);
void tegra210_xusb_pll_hw_sequence_start(void)
{
u32 val;
val = readl_relaxed(clk_base + XUSBIO_PLL_CFG0);
val |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
writel_relaxed(val, clk_base + XUSBIO_PLL_CFG0);
}
EXPORT_SYMBOL_GPL(tegra210_xusb_pll_hw_sequence_start);
void tegra210_sata_pll_hw_control_enable(void)
{
u32 val;
val = readl_relaxed(clk_base + SATA_PLL_CFG0);
val &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL;
val |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET |
SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ;
writel_relaxed(val, clk_base + SATA_PLL_CFG0);
}
EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_control_enable);
void tegra210_sata_pll_hw_sequence_start(void)
{
u32 val;
val = readl_relaxed(clk_base + SATA_PLL_CFG0);
val |= SATA_PLL_CFG0_SEQ_ENABLE;
writel_relaxed(val, clk_base + SATA_PLL_CFG0);
}
EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_sequence_start);
static inline void _pll_misc_chk_default(void __iomem *base, static inline void _pll_misc_chk_default(void __iomem *base,
struct tegra_clk_pll_params *params, struct tegra_clk_pll_params *params,
u8 misc_num, u32 default_val, u32 mask) u8 misc_num, u32 default_val, u32 mask)
...@@ -2092,6 +2151,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { ...@@ -2092,6 +2151,7 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
[tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true }, [tegra_clk_clk72Mhz_8] = { .dt_id = TEGRA210_CLK_CLK72MHZ, .present = true },
[tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true }, [tegra_clk_vic03_8] = { .dt_id = TEGRA210_CLK_VIC03, .present = true },
[tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true }, [tegra_clk_dpaux] = { .dt_id = TEGRA210_CLK_DPAUX, .present = true },
[tegra_clk_dpaux1] = { .dt_id = TEGRA210_CLK_DPAUX1, .present = true },
[tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true }, [tegra_clk_sor0] = { .dt_id = TEGRA210_CLK_SOR0, .present = true },
[tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true }, [tegra_clk_sor0_lvds] = { .dt_id = TEGRA210_CLK_SOR0_LVDS, .present = true },
[tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true },
...@@ -2403,6 +2463,18 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, ...@@ -2403,6 +2463,18 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
1, 2); 1, 2);
clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk; clks[TEGRA210_CLK_XUSB_SS_DIV2] = clk;
clk = tegra_clk_register_periph_fixed("dpaux", "pll_p", 0, clk_base,
1, 17, 181);
clks[TEGRA210_CLK_DPAUX] = clk;
clk = tegra_clk_register_periph_fixed("dpaux1", "pll_p", 0, clk_base,
1, 17, 207);
clks[TEGRA210_CLK_DPAUX1] = clk;
clk = tegra_clk_register_periph_fixed("sor_safe", "pll_p", 0, clk_base,
1, 17, 222);
clks[TEGRA210_CLK_SOR_SAFE] = clk;
/* pll_d_dsi_out */ /* pll_d_dsi_out */
clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0, clk = clk_register_gate(NULL, "pll_d_dsi_out", "pll_d_out0", 0,
clk_base + PLLD_MISC0, 21, 0, &pll_d_lock); clk_base + PLLD_MISC0, 21, 0, &pll_d_lock);
...@@ -2582,8 +2654,10 @@ static void __init tegra210_pll_init(void __iomem *clk_base, ...@@ -2582,8 +2654,10 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
clks[TEGRA210_CLK_PLL_D_OUT0] = clk; clks[TEGRA210_CLK_PLL_D_OUT0] = clk;
/* PLLRE */ /* PLLRE */
clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, clk = tegra_clk_register_pllre_tegra210("pll_re_vco", "pll_ref",
0, &pll_re_vco_params, &pll_re_lock, pll_ref_freq); clk_base, pmc, 0,
&pll_re_vco_params,
&pll_re_lock, pll_ref_freq);
clk_register_clkdev(clk, "pll_re_vco", NULL); clk_register_clkdev(clk, "pll_re_vco", NULL);
clks[TEGRA210_CLK_PLL_RE_VCO] = clk; clks[TEGRA210_CLK_PLL_RE_VCO] = clk;
...@@ -2593,6 +2667,15 @@ static void __init tegra210_pll_init(void __iomem *clk_base, ...@@ -2593,6 +2667,15 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
clk_register_clkdev(clk, "pll_re_out", NULL); clk_register_clkdev(clk, "pll_re_out", NULL);
clks[TEGRA210_CLK_PLL_RE_OUT] = clk; clks[TEGRA210_CLK_PLL_RE_OUT] = clk;
clk = tegra_clk_register_divider("pll_re_out1_div", "pll_re_vco",
clk_base + PLLRE_OUT1, 0,
TEGRA_DIVIDER_ROUND_UP,
8, 8, 1, NULL);
clk = tegra_clk_register_pll_out("pll_re_out1", "pll_re_out1_div",
clk_base + PLLRE_OUT1, 1, 0,
CLK_SET_RATE_PARENT, 0, NULL);
clks[TEGRA210_CLK_PLL_RE_OUT1] = clk;
/* PLLE */ /* PLLE */
clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref", clk = tegra_clk_register_plle_tegra210("pll_e", "pll_ref",
clk_base, 0, &pll_e_params, NULL); clk_base, 0, &pll_e_params, NULL);
......
...@@ -339,11 +339,11 @@ static const struct pdiv_map pllu_p[] = { ...@@ -339,11 +339,11 @@ static const struct pdiv_map pllu_p[] = {
}; };
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
{ 12000000, 480000000, 960, 12, 1, 12 }, { 12000000, 480000000, 960, 12, 2, 12 },
{ 13000000, 480000000, 960, 13, 1, 12 }, { 13000000, 480000000, 960, 13, 2, 12 },
{ 16800000, 480000000, 400, 7, 1, 5 }, { 16800000, 480000000, 400, 7, 2, 5 },
{ 19200000, 480000000, 200, 4, 1, 3 }, { 19200000, 480000000, 200, 4, 2, 3 },
{ 26000000, 480000000, 960, 26, 1, 12 }, { 26000000, 480000000, 960, 26, 2, 12 },
{ 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 },
}; };
...@@ -1372,6 +1372,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { ...@@ -1372,6 +1372,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 }, { TEGRA30_CLK_SBC4, TEGRA30_CLK_PLL_P, 100000000, 0 },
{ TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 }, { TEGRA30_CLK_SBC5, TEGRA30_CLK_PLL_P, 100000000, 0 },
{ TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 }, { TEGRA30_CLK_SBC6, TEGRA30_CLK_PLL_P, 100000000, 0 },
{ TEGRA30_CLK_PLL_C, TEGRA30_CLK_CLK_MAX, 600000000, 0 },
{ TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 }, { TEGRA30_CLK_HOST1X, TEGRA30_CLK_PLL_C, 150000000, 0 },
{ TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 }, { TEGRA30_CLK_DISP1, TEGRA30_CLK_PLL_P, 600000000, 0 },
{ TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 }, { TEGRA30_CLK_DISP2, TEGRA30_CLK_PLL_P, 600000000, 0 },
...@@ -1379,6 +1380,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { ...@@ -1379,6 +1380,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_GR2D, TEGRA30_CLK_PLL_C, 300000000, 0 },
{ TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 },
{ TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 },
{ TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 },
/* must be the last entry */ /* must be the last entry */
{ TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 }, { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
}; };
......
...@@ -84,7 +84,7 @@ static int (*special_reset_assert)(unsigned long); ...@@ -84,7 +84,7 @@ static int (*special_reset_assert)(unsigned long);
static int (*special_reset_deassert)(unsigned long); static int (*special_reset_deassert)(unsigned long);
static unsigned int num_special_reset; static unsigned int num_special_reset;
static struct tegra_clk_periph_regs periph_regs[] = { static const struct tegra_clk_periph_regs periph_regs[] = {
[0] = { [0] = {
.enb_reg = CLK_OUT_ENB_L, .enb_reg = CLK_OUT_ENB_L,
.enb_set_reg = CLK_OUT_ENB_SET_L, .enb_set_reg = CLK_OUT_ENB_SET_L,
...@@ -182,7 +182,7 @@ static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev, ...@@ -182,7 +182,7 @@ static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
return -EINVAL; return -EINVAL;
} }
struct tegra_clk_periph_regs *get_reg_bank(int clkid) const struct tegra_clk_periph_regs *get_reg_bank(int clkid)
{ {
int reg_bank = clkid / 32; int reg_bank = clkid / 32;
......
...@@ -386,6 +386,12 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, ...@@ -386,6 +386,12 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
struct tegra_clk_pll_params *pll_params, struct tegra_clk_pll_params *pll_params,
spinlock_t *lock, unsigned long parent_rate); spinlock_t *lock, unsigned long parent_rate);
struct clk *tegra_clk_register_pllre_tegra210(const char *name,
const char *parent_name, void __iomem *clk_base,
void __iomem *pmc, unsigned long flags,
struct tegra_clk_pll_params *pll_params,
spinlock_t *lock, unsigned long parent_rate);
struct clk *tegra_clk_register_plle_tegra114(const char *name, struct clk *tegra_clk_register_plle_tegra114(const char *name,
const char *parent_name, const char *parent_name,
void __iomem *clk_base, unsigned long flags, void __iomem *clk_base, unsigned long flags,
...@@ -496,7 +502,7 @@ struct tegra_clk_periph_gate { ...@@ -496,7 +502,7 @@ struct tegra_clk_periph_gate {
u8 flags; u8 flags;
int clk_num; int clk_num;
int *enable_refcnt; int *enable_refcnt;
struct tegra_clk_periph_regs *regs; const struct tegra_clk_periph_regs *regs;
}; };
#define to_clk_periph_gate(_hw) \ #define to_clk_periph_gate(_hw) \
...@@ -516,6 +522,23 @@ struct clk *tegra_clk_register_periph_gate(const char *name, ...@@ -516,6 +522,23 @@ struct clk *tegra_clk_register_periph_gate(const char *name,
const char *parent_name, u8 gate_flags, void __iomem *clk_base, const char *parent_name, u8 gate_flags, void __iomem *clk_base,
unsigned long flags, int clk_num, int *enable_refcnt); unsigned long flags, int clk_num, int *enable_refcnt);
struct tegra_clk_periph_fixed {
struct clk_hw hw;
void __iomem *base;
const struct tegra_clk_periph_regs *regs;
unsigned int mul;
unsigned int div;
unsigned int num;
};
struct clk *tegra_clk_register_periph_fixed(const char *name,
const char *parent,
unsigned long flags,
void __iomem *base,
unsigned int mul,
unsigned int div,
unsigned int num);
/** /**
* struct clk-periph - peripheral clock * struct clk-periph - peripheral clock
* *
...@@ -716,7 +739,7 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl, ...@@ -716,7 +739,7 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl,
void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
struct clk *clks[], int clk_max); struct clk *clks[], int clk_max);
struct tegra_clk_periph_regs *get_reg_bank(int clkid); const struct tegra_clk_periph_regs *get_reg_bank(int clkid);
struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks); struct clk **tegra_clk_init(void __iomem *clk_base, int num, int periph_banks);
struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk);
......
...@@ -61,29 +61,28 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up) ...@@ -61,29 +61,28 @@ static int round_voltage(int mv, const struct rail_alignment *align, int up)
return mv; return mv;
} }
static int build_opp_table(const struct cvb_table *d, static int build_opp_table(struct device *dev, const struct cvb_table *table,
int speedo_value, int speedo_value, unsigned long max_freq)
unsigned long max_freq,
struct device *opp_dev)
{ {
const struct rail_alignment *align = &table->alignment;
int i, ret, dfll_mv, min_mv, max_mv; int i, ret, dfll_mv, min_mv, max_mv;
const struct cvb_table_freq_entry *table = NULL;
const struct rail_alignment *align = &d->alignment;
min_mv = round_voltage(d->min_millivolts, align, UP); min_mv = round_voltage(table->min_millivolts, align, UP);
max_mv = round_voltage(d->max_millivolts, align, DOWN); max_mv = round_voltage(table->max_millivolts, align, DOWN);
for (i = 0; i < MAX_DVFS_FREQS; i++) { for (i = 0; i < MAX_DVFS_FREQS; i++) {
table = &d->cvb_table[i]; const struct cvb_table_freq_entry *entry = &table->entries[i];
if (!table->freq || (table->freq > max_freq))
if (!entry->freq || (entry->freq > max_freq))
break; break;
dfll_mv = get_cvb_voltage( dfll_mv = get_cvb_voltage(speedo_value, table->speedo_scale,
speedo_value, d->speedo_scale, &table->coefficients); &entry->coefficients);
dfll_mv = round_cvb_voltage(dfll_mv, d->voltage_scale, align); dfll_mv = round_cvb_voltage(dfll_mv, table->voltage_scale,
align);
dfll_mv = clamp(dfll_mv, min_mv, max_mv); dfll_mv = clamp(dfll_mv, min_mv, max_mv);
ret = dev_pm_opp_add(opp_dev, table->freq, dfll_mv * 1000); ret = dev_pm_opp_add(dev, entry->freq, dfll_mv * 1000);
if (ret) if (ret)
return ret; return ret;
} }
...@@ -92,7 +91,7 @@ static int build_opp_table(const struct cvb_table *d, ...@@ -92,7 +91,7 @@ static int build_opp_table(const struct cvb_table *d,
} }
/** /**
* tegra_cvb_build_opp_table - build OPP table from Tegra CVB tables * tegra_cvb_add_opp_table - build OPP table from Tegra CVB tables
* @cvb_tables: array of CVB tables * @cvb_tables: array of CVB tables
* @sz: size of the previously mentioned array * @sz: size of the previously mentioned array
* @process_id: process id of the HW module * @process_id: process id of the HW module
...@@ -108,26 +107,42 @@ static int build_opp_table(const struct cvb_table *d, ...@@ -108,26 +107,42 @@ static int build_opp_table(const struct cvb_table *d,
* given @opp_dev. Returns a pointer to the struct cvb_table that matched * given @opp_dev. Returns a pointer to the struct cvb_table that matched
* or an ERR_PTR on failure. * or an ERR_PTR on failure.
*/ */
const struct cvb_table *tegra_cvb_build_opp_table( const struct cvb_table *
const struct cvb_table *cvb_tables, tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *tables,
size_t sz, int process_id, size_t count, int process_id, int speedo_id,
int speedo_id, int speedo_value, int speedo_value, unsigned long max_freq)
unsigned long max_rate,
struct device *opp_dev)
{ {
int i, ret; size_t i;
int ret;
for (i = 0; i < sz; i++) { for (i = 0; i < count; i++) {
const struct cvb_table *d = &cvb_tables[i]; const struct cvb_table *table = &tables[i];
if (d->speedo_id != -1 && d->speedo_id != speedo_id) if (table->speedo_id != -1 && table->speedo_id != speedo_id)
continue; continue;
if (d->process_id != -1 && d->process_id != process_id)
if (table->process_id != -1 && table->process_id != process_id)
continue; continue;
ret = build_opp_table(d, speedo_value, max_rate, opp_dev); ret = build_opp_table(dev, table, speedo_value, max_freq);
return ret ? ERR_PTR(ret) : d; return ret ? ERR_PTR(ret) : table;
} }
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
void tegra_cvb_remove_opp_table(struct device *dev,
const struct cvb_table *table,
unsigned long max_freq)
{
unsigned int i;
for (i = 0; i < MAX_DVFS_FREQS; i++) {
const struct cvb_table_freq_entry *entry = &table->entries[i];
if (!entry->freq || (entry->freq > max_freq))
break;
dev_pm_opp_remove(dev, entry->freq);
}
}
...@@ -53,15 +53,16 @@ struct cvb_table { ...@@ -53,15 +53,16 @@ struct cvb_table {
int speedo_scale; int speedo_scale;
int voltage_scale; int voltage_scale;
struct cvb_table_freq_entry cvb_table[MAX_DVFS_FREQS]; struct cvb_table_freq_entry entries[MAX_DVFS_FREQS];
struct cvb_cpu_dfll_data cpu_dfll_data; struct cvb_cpu_dfll_data cpu_dfll_data;
}; };
const struct cvb_table *tegra_cvb_build_opp_table( const struct cvb_table *
const struct cvb_table *cvb_tables, tegra_cvb_add_opp_table(struct device *dev, const struct cvb_table *cvb_tables,
size_t sz, int process_id, size_t count, int process_id, int speedo_id,
int speedo_id, int speedo_value, int speedo_value, unsigned long max_freq);
unsigned long max_rate, void tegra_cvb_remove_opp_table(struct device *dev,
struct device *opp_dev); const struct cvb_table *table,
unsigned long max_freq);
#endif #endif
...@@ -346,7 +346,7 @@ ...@@ -346,7 +346,7 @@
#define TEGRA210_CLK_PLL_P_OUT_HSIO 316 #define TEGRA210_CLK_PLL_P_OUT_HSIO 316
#define TEGRA210_CLK_PLL_P_OUT_XUSB 317 #define TEGRA210_CLK_PLL_P_OUT_XUSB 317
#define TEGRA210_CLK_XUSB_SSP_SRC 318 #define TEGRA210_CLK_XUSB_SSP_SRC 318
/* 319 */ #define TEGRA210_CLK_PLL_RE_OUT1 319
/* 320 */ /* 320 */
/* 321 */ /* 321 */
/* 322 */ /* 322 */
......
...@@ -121,4 +121,9 @@ static inline void tegra_cpu_clock_resume(void) ...@@ -121,4 +121,9 @@ static inline void tegra_cpu_clock_resume(void)
} }
#endif #endif
extern void tegra210_xusb_pll_hw_control_enable(void);
extern void tegra210_xusb_pll_hw_sequence_start(void);
extern void tegra210_sata_pll_hw_control_enable(void);
extern void tegra210_sata_pll_hw_sequence_start(void);
#endif /* __LINUX_CLK_TEGRA_H_ */ #endif /* __LINUX_CLK_TEGRA_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment