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

Commit eae14465 authored by Michael Turquette's avatar Michael Turquette
Browse files

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

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

clk: tegra: Changes for v4.4-rc1

This contains a patch that allows the DFLL to use clock rates higher
than 2^31-1 Hz by using the ->determine_rate() operation instead of the
->round_rate() operation. Other than that there's a couple of cleanups
in preparation for Tegra210 support.
parents b30c6450 88d909be
Loading
Loading
Loading
Loading
+57 −57
Original line number Diff line number Diff line
@@ -468,56 +468,6 @@ static unsigned long dfll_scale_dvco_rate(int scale_bits,
	return (u64)dvco_rate * (scale_bits + 1) / DFLL_FREQ_REQ_SCALE_MAX;
}

/*
 * Monitor control
 */

/**
 * dfll_calc_monitored_rate - convert DFLL_MONITOR_DATA_VAL rate into real freq
 * @monitor_data: value read from the DFLL_MONITOR_DATA_VAL bitfield
 * @ref_rate: DFLL reference clock rate
 *
 * Convert @monitor_data from DFLL_MONITOR_DATA_VAL units into cycles
 * per second. Returns the converted value.
 */
static u64 dfll_calc_monitored_rate(u32 monitor_data,
				    unsigned long ref_rate)
{
	return monitor_data * (ref_rate / REF_CLK_CYC_PER_DVCO_SAMPLE);
}

/**
 * dfll_read_monitor_rate - return the DFLL's output rate from internal monitor
 * @td: DFLL instance
 *
 * If the DFLL is enabled, return the last rate reported by the DFLL's
 * internal monitoring hardware. This works in both open-loop and
 * closed-loop mode, and takes the output scaler setting into account.
 * Assumes that the monitor was programmed to monitor frequency before
 * the sample period started. If the driver believes that the DFLL is
 * currently uninitialized or disabled, it will return 0, since
 * otherwise the DFLL monitor data register will return the last
 * measured rate from when the DFLL was active.
 */
static u64 dfll_read_monitor_rate(struct tegra_dfll *td)
{
	u32 v, s;
	u64 pre_scaler_rate, post_scaler_rate;

	if (!dfll_is_running(td))
		return 0;

	v = dfll_readl(td, DFLL_MONITOR_DATA);
	v = (v & DFLL_MONITOR_DATA_VAL_MASK) >> DFLL_MONITOR_DATA_VAL_SHIFT;
	pre_scaler_rate = dfll_calc_monitored_rate(v, td->ref_rate);

	s = dfll_readl(td, DFLL_FREQ_REQ);
	s = (s & DFLL_FREQ_REQ_SCALE_MASK) >> DFLL_FREQ_REQ_SCALE_SHIFT;
	post_scaler_rate = dfll_scale_dvco_rate(s, pre_scaler_rate);

	return post_scaler_rate;
}

/*
 * DFLL mode switching
 */
@@ -1006,24 +956,25 @@ static unsigned long dfll_clk_recalc_rate(struct clk_hw *hw,
	return td->last_unrounded_rate;
}

static long dfll_clk_round_rate(struct clk_hw *hw,
				unsigned long rate,
				unsigned long *parent_rate)
/* Must use determine_rate since it allows for rates exceeding 2^31-1 */
static int dfll_clk_determine_rate(struct clk_hw *hw,
				   struct clk_rate_request *clk_req)
{
	struct tegra_dfll *td = clk_hw_to_dfll(hw);
	struct dfll_rate_req req;
	int ret;

	ret = dfll_calculate_rate_request(td, &req, rate);
	ret = dfll_calculate_rate_request(td, &req, clk_req->rate);
	if (ret)
		return ret;

	/*
	 * Don't return the rounded rate, since it doesn't really matter as
	 * Don't set the rounded rate, since it doesn't really matter as
	 * the output rate will be voltage controlled anyway, and cpufreq
	 * freaks out if any rounding happens.
	 */
	return rate;

	return 0;
}

static int dfll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -1039,7 +990,7 @@ static const struct clk_ops dfll_clk_ops = {
	.enable		= dfll_clk_enable,
	.disable	= dfll_clk_disable,
	.recalc_rate	= dfll_clk_recalc_rate,
	.round_rate	= dfll_clk_round_rate,
	.determine_rate	= dfll_clk_determine_rate,
	.set_rate	= dfll_clk_set_rate,
};

@@ -1101,6 +1052,55 @@ static void dfll_unregister_clk(struct tegra_dfll *td)
 */

#ifdef CONFIG_DEBUG_FS
/*
 * Monitor control
 */

/**
 * dfll_calc_monitored_rate - convert DFLL_MONITOR_DATA_VAL rate into real freq
 * @monitor_data: value read from the DFLL_MONITOR_DATA_VAL bitfield
 * @ref_rate: DFLL reference clock rate
 *
 * Convert @monitor_data from DFLL_MONITOR_DATA_VAL units into cycles
 * per second. Returns the converted value.
 */
static u64 dfll_calc_monitored_rate(u32 monitor_data,
				    unsigned long ref_rate)
{
	return monitor_data * (ref_rate / REF_CLK_CYC_PER_DVCO_SAMPLE);
}

/**
 * dfll_read_monitor_rate - return the DFLL's output rate from internal monitor
 * @td: DFLL instance
 *
 * If the DFLL is enabled, return the last rate reported by the DFLL's
 * internal monitoring hardware. This works in both open-loop and
 * closed-loop mode, and takes the output scaler setting into account.
 * Assumes that the monitor was programmed to monitor frequency before
 * the sample period started. If the driver believes that the DFLL is
 * currently uninitialized or disabled, it will return 0, since
 * otherwise the DFLL monitor data register will return the last
 * measured rate from when the DFLL was active.
 */
static u64 dfll_read_monitor_rate(struct tegra_dfll *td)
{
	u32 v, s;
	u64 pre_scaler_rate, post_scaler_rate;

	if (!dfll_is_running(td))
		return 0;

	v = dfll_readl(td, DFLL_MONITOR_DATA);
	v = (v & DFLL_MONITOR_DATA_VAL_MASK) >> DFLL_MONITOR_DATA_VAL_SHIFT;
	pre_scaler_rate = dfll_calc_monitored_rate(v, td->ref_rate);

	s = dfll_readl(td, DFLL_FREQ_REQ);
	s = (s & DFLL_FREQ_REQ_SCALE_MASK) >> DFLL_FREQ_REQ_SCALE_SHIFT;
	post_scaler_rate = dfll_scale_dvco_rate(s, pre_scaler_rate);

	return post_scaler_rate;
}

static int attr_enable_get(void *data, u64 *val)
{
+18 −7
Original line number Diff line number Diff line
@@ -125,19 +125,30 @@ static struct tegra_audio2x_clk_initdata audio2x_clks[] = {

void __init tegra_audio_clk_init(void __iomem *clk_base,
			void __iomem *pmc_base, struct tegra_clk *tegra_clks,
			struct tegra_clk_pll_params *pll_a_params)
			struct tegra_audio_clk_info *audio_info,
			unsigned int num_plls)
{
	struct clk *clk;
	struct clk **dt_clk;
	int i;

	/* PLLA */
	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a, tegra_clks);
	if (!audio_info || num_plls < 1) {
		pr_err("No audio data passed to tegra_audio_clk_init\n");
		WARN_ON(1);
		return;
	}

	for (i = 0; i < num_plls; i++) {
		struct tegra_audio_clk_info *info = &audio_info[i];

		dt_clk = tegra_lookup_dt_id(info->clk_id, tegra_clks);
		if (dt_clk) {
		clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base,
				pmc_base, 0, pll_a_params, NULL);
			clk = tegra_clk_register_pll(info->name, info->parent,
					clk_base, pmc_base, 0, info->pll_params,
					NULL);
			*dt_clk = clk;
		}
	}

	/* PLLA_OUT0 */
	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a_out0, tegra_clks);
+7 −1
Original line number Diff line number Diff line
@@ -933,6 +933,10 @@ static u32 mux_pllm_pllc2_c_c3_pllp_plla_idx[] = {
	[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
};

static struct tegra_audio_clk_info tegra114_audio_plls[] = {
	{ "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" },
};

static struct clk **clks;

static unsigned long osc_freq;
@@ -1481,7 +1485,9 @@ static void __init tegra114_clock_init(struct device_node *np)
	tegra114_fixed_clk_init(clk_base);
	tegra114_pll_init(clk_base, pmc_base);
	tegra114_periph_clk_init(clk_base, pmc_base);
	tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks, &pll_a_params);
	tegra_audio_clk_init(clk_base, pmc_base, tegra114_clks,
			     tegra114_audio_plls,
			     ARRAY_SIZE(tegra114_audio_plls));
	tegra_pmc_clk_init(pmc_base, tegra114_clks);
	tegra_super_clk_gen4_init(clk_base, pmc_base, tegra114_clks,
					&pll_x_params);
+7 −1
Original line number Diff line number Diff line
@@ -1417,6 +1417,10 @@ static struct tegra_clk_init_table tegra132_init_table[] __initdata = {
	{TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0},
};

static struct tegra_audio_clk_info tegra124_audio_plls[] = {
	{ "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" },
};

/**
 * tegra124_clock_apply_init_table - initialize clocks on Tegra124 SoCs
 *
@@ -1555,7 +1559,9 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np)
	tegra_fixed_clk_init(tegra124_clks);
	tegra124_pll_init(clk_base, pmc_base);
	tegra124_periph_clk_init(clk_base, pmc_base);
	tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks, &pll_a_params);
	tegra_audio_clk_init(clk_base, pmc_base, tegra124_clks,
			     tegra124_audio_plls,
			     ARRAY_SIZE(tegra124_audio_plls));
	tegra_pmc_clk_init(pmc_base, tegra124_clks);

	/* For Tegra124 & Tegra132, PLLD is the only source for DSIA & DSIB */
+7 −1
Original line number Diff line number Diff line
@@ -1405,6 +1405,10 @@ static const struct of_device_id pmc_match[] __initconst = {
	{},
};

static struct tegra_audio_clk_info tegra30_audio_plls[] = {
	{ "pll_a", &pll_a_params, tegra_clk_pll_a, "pll_p_out1" },
};

static void __init tegra30_clock_init(struct device_node *np)
{
	struct device_node *node;
@@ -1442,7 +1446,9 @@ static void __init tegra30_clock_init(struct device_node *np)
	tegra30_pll_init();
	tegra30_super_clk_init();
	tegra30_periph_clk_init();
	tegra_audio_clk_init(clk_base, pmc_base, tegra30_clks, &pll_a_params);
	tegra_audio_clk_init(clk_base, pmc_base, tegra30_clks,
			     tegra30_audio_plls,
			     ARRAY_SIZE(tegra30_audio_plls));
	tegra_pmc_clk_init(pmc_base, tegra30_clks);

	tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX);
Loading