Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ obj-y += clk-audio-sync.o
obj-y					+= clk-dfll.o
obj-y					+= clk-divider.o
obj-y					+= clk-periph.o
obj-y					+= clk-periph-fixed.o
obj-y					+= clk-periph-gate.o
obj-y					+= clk-pll.o
obj-y					+= clk-pll-out.o
+6 −5
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@
#include <linux/seq_file.h>

#include "clk-dfll.h"
#include "cvb.h"

/*
 * DFLL control registers - access via dfll_{readl,writel}
@@ -442,8 +443,8 @@ static void dfll_tune_low(struct tegra_dfll *td)
{
	td->tune_range = DFLL_TUNE_LOW;

	dfll_writel(td, td->soc->tune0_low, DFLL_TUNE0);
	dfll_writel(td, td->soc->tune1, DFLL_TUNE1);
	dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune0_low, DFLL_TUNE0);
	dfll_writel(td, td->soc->cvb->cpu_dfll_data.tune1, DFLL_TUNE1);
	dfll_wmb(td);

	if (td->soc->set_clock_trimmers_low)
@@ -1449,7 +1450,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
	}
	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);
	if (lut < 0)
		goto out;
@@ -1461,7 +1462,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)
			break;
		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);

		for (;;) {
@@ -1490,7 +1491,7 @@ static int dfll_build_i2c_lut(struct tegra_dfll *td)

	if (!td->dvco_rate_min)
		dev_err(td->dev, "no opp above DFLL minimum voltage %d mV\n",
			td->soc->min_millivolts);
			td->soc->cvb->min_millivolts);
	else
		ret = 0;

+9 −13
Original line number Diff line number Diff line
@@ -24,22 +24,18 @@

/**
 * 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
 * @min_millivolts: minimum voltage (in mV) that the DFLL can operate
 * @tune0_low: DFLL tuning register 0 (low voltage range)
 * @tune0_high: DFLL tuning register 0 (high voltage range)
 * @tune1: DFLL tuning register 1
 * @assert_dvco_reset: fn ptr to place the DVCO in reset
 * @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
 * @dev: struct device * that holds the OPP table for the DFLL
 * @max_freq: maximum frequency supported on this SoC
 * @cvb: CPU frequency table for this SoC
 * @init_clock_trimmers: callback to initialize clock trimmers
 * @set_clock_trimmers_high: callback to tune clock trimmers for high voltage
 * @set_clock_trimmers_low: callback to tune clock trimmers for low voltage
 */
struct tegra_dfll_soc_data {
	struct device *dev;
	unsigned int min_millivolts;
	u32 tune0_low;
	u32 tune0_high;
	u32 tune1;
	unsigned long max_freq;
	const struct cvb_table *cvb;

	void (*init_clock_trimmers)(void);
	void (*set_clock_trimmers_high)(void);
	void (*set_clock_trimmers_low)(void);
+2 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ enum clk_id {
	tegra_clk_disp2_8,
	tegra_clk_dp2,
	tegra_clk_dpaux,
	tegra_clk_dpaux1,
	tegra_clk_dsialp,
	tegra_clk_dsia_mux,
	tegra_clk_dsiblp,
@@ -306,6 +307,7 @@ enum clk_id {
	tegra_clk_xusb_ss_div2,
	tegra_clk_xusb_ssp_src,
	tegra_clk_sclk_mux,
	tegra_clk_sor_safe,
	tegra_clk_max,
};

+120 −0
Original line number Diff line number Diff line
/*
 * 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;
}
Loading