Commit eeafcdea authored by Krzysztof Kozlowski's avatar Krzysztof Kozlowski
Browse files

Merge tag 'tegra-for-5.14-memory' of...

Merge tag 'tegra-for-5.14-memory' of https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into for-v5.14/tegra-mc

memory: tegra: Changes for v5.14-rc1

This stable tag contains Dmitry's power domain work, including all the
necessary dependencies from the regulator, clock and ARM SoC trees.

Further work depends on memory controller changes here.
parents 6efb943b b4f74b59
Loading
Loading
Loading
Loading
+47 −33
Original line number Diff line number Diff line
@@ -48,36 +48,45 @@ static int clk_periph_is_enabled(struct clk_hw *hw)
	return state;
}

static int clk_periph_enable(struct clk_hw *hw)
static void clk_periph_enable_locked(struct clk_hw *hw)
{
	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
	unsigned long flags = 0;

	spin_lock_irqsave(&periph_ref_lock, flags);

	gate->enable_refcnt[gate->clk_num]++;
	if (gate->enable_refcnt[gate->clk_num] > 1) {
		spin_unlock_irqrestore(&periph_ref_lock, flags);
		return 0;
	}

	write_enb_set(periph_clk_to_bit(gate), gate);
	udelay(2);

	if (!(gate->flags & TEGRA_PERIPH_NO_RESET) &&
	    !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) {
		if (read_rst(gate) & periph_clk_to_bit(gate)) {
			udelay(5); /* reset propogation delay */
			write_rst_clr(periph_clk_to_bit(gate), gate);
		}
	}

	if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
		writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
		udelay(1);
		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
	}
}

static void clk_periph_disable_locked(struct clk_hw *hw)
{
	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);

	/*
	 * If peripheral is in the APB bus then read the APB bus to
	 * flush the write operation in apb bus. This will avoid the
	 * peripheral access after disabling clock
	 */
	if (gate->flags & TEGRA_PERIPH_ON_APB)
		tegra_read_chipid();

	write_enb_clr(periph_clk_to_bit(gate), gate);
}

static int clk_periph_enable(struct clk_hw *hw)
{
	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
	unsigned long flags = 0;

	spin_lock_irqsave(&periph_ref_lock, flags);

	if (!gate->enable_refcnt[gate->clk_num]++)
		clk_periph_enable_locked(hw);

	spin_unlock_irqrestore(&periph_ref_lock, flags);

@@ -91,21 +100,28 @@ static void clk_periph_disable(struct clk_hw *hw)

	spin_lock_irqsave(&periph_ref_lock, flags);

	gate->enable_refcnt[gate->clk_num]--;
	if (gate->enable_refcnt[gate->clk_num] > 0) {
	WARN_ON(!gate->enable_refcnt[gate->clk_num]);

	if (--gate->enable_refcnt[gate->clk_num] == 0)
		clk_periph_disable_locked(hw);

	spin_unlock_irqrestore(&periph_ref_lock, flags);
		return;
}

static void clk_periph_disable_unused(struct clk_hw *hw)
{
	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
	unsigned long flags = 0;

	spin_lock_irqsave(&periph_ref_lock, flags);

	/*
	 * If peripheral is in the APB bus then read the APB bus to
	 * flush the write operation in apb bus. This will avoid the
	 * peripheral access after disabling clock
	 * Some clocks are duplicated and some of them are marked as critical,
	 * like fuse and fuse_burn for example, thus the enable_refcnt will
	 * be non-zero here if the "unused" duplicate is disabled by CCF.
	 */
	if (gate->flags & TEGRA_PERIPH_ON_APB)
		tegra_read_chipid();

	write_enb_clr(periph_clk_to_bit(gate), gate);
	if (!gate->enable_refcnt[gate->clk_num])
		clk_periph_disable_locked(hw);

	spin_unlock_irqrestore(&periph_ref_lock, flags);
}
@@ -114,6 +130,7 @@ const struct clk_ops tegra_clk_periph_gate_ops = {
	.is_enabled = clk_periph_is_enabled,
	.enable = clk_periph_enable,
	.disable = clk_periph_disable,
	.disable_unused = clk_periph_disable_unused,
};

struct clk *tegra_clk_register_periph_gate(const char *name,
@@ -148,9 +165,6 @@ struct clk *tegra_clk_register_periph_gate(const char *name,
	gate->enable_refcnt = enable_refcnt;
	gate->regs = pregs;

	if (read_enb(gate) & periph_clk_to_bit(gate))
		enable_refcnt[clk_num]++;

	/* Data in .init is copied by clk_register(), so stack variable OK */
	gate->hw.init = &init;

+11 −0
Original line number Diff line number Diff line
@@ -100,6 +100,15 @@ static void clk_periph_disable(struct clk_hw *hw)
	gate_ops->disable(gate_hw);
}

static void clk_periph_disable_unused(struct clk_hw *hw)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
	const struct clk_ops *gate_ops = periph->gate_ops;
	struct clk_hw *gate_hw = &periph->gate.hw;

	gate_ops->disable_unused(gate_hw);
}

static void clk_periph_restore_context(struct clk_hw *hw)
{
	struct tegra_clk_periph *periph = to_clk_periph(hw);
@@ -126,6 +135,7 @@ const struct clk_ops tegra_clk_periph_ops = {
	.is_enabled = clk_periph_is_enabled,
	.enable = clk_periph_enable,
	.disable = clk_periph_disable,
	.disable_unused = clk_periph_disable_unused,
	.restore_context = clk_periph_restore_context,
};

@@ -135,6 +145,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = {
	.is_enabled = clk_periph_is_enabled,
	.enable = clk_periph_enable,
	.disable = clk_periph_disable,
	.disable_unused = clk_periph_disable_unused,
	.restore_context = clk_periph_restore_context,
};

+7 −5
Original line number Diff line number Diff line
@@ -558,6 +558,9 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
	u32 p_div = 0;
	int ret;

	if (!rate)
		return -EINVAL;

	switch (parent_rate) {
	case 12000000:
	case 26000000:
@@ -1131,6 +1134,7 @@ static int clk_pllu_enable(struct clk_hw *hw)
	if (pll->lock)
		spin_lock_irqsave(pll->lock, flags);

	if (!clk_pll_is_enabled(hw))
		_clk_pll_enable(hw);

	ret = clk_pll_wait_for_lock(pll);
@@ -1748,14 +1752,12 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw)
		return -EINVAL;
	}

	if (clk_pll_is_enabled(hw))
		return 0;

	input_rate = clk_hw_get_rate(__clk_get_hw(osc));

	if (pll->lock)
		spin_lock_irqsave(pll->lock, flags);

	if (!clk_pll_is_enabled(hw))
		_clk_pll_enable(hw);

	ret = clk_pll_wait_for_lock(pll);
+3 −3
Original line number Diff line number Diff line
@@ -712,9 +712,9 @@ static struct tegra_periph_init_data periph_clks[] = {
	MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8),
	MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8),
	MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi),
	MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, 0, tegra_clk_extern1),
	MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
	MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
	MUX8("extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, TEGRA_PERIPH_NO_RESET, tegra_clk_extern1),
	MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, TEGRA_PERIPH_NO_RESET, tegra_clk_extern2),
	MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, TEGRA_PERIPH_NO_RESET, tegra_clk_extern3),
	MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
	MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8),
	MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
+14 −2
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@

#define SUPER_CDIV_ENB		BIT(31)

#define TSENSOR_SLOWDOWN	BIT(23)

static struct tegra_clk_super_mux *cclk_super;
static bool cclk_on_pllx;

@@ -47,10 +49,20 @@ static int cclk_super_set_rate(struct clk_hw *hw, unsigned long rate,
static unsigned long cclk_super_recalc_rate(struct clk_hw *hw,
					    unsigned long parent_rate)
{
	struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
	u32 val = readl_relaxed(super->reg);
	unsigned int div2;

	/* check whether thermal throttling is active */
	if (val & TSENSOR_SLOWDOWN)
		div2 = 1;
	else
		div2 = 0;

	if (cclk_super_get_parent(hw) == PLLX_INDEX)
		return parent_rate;
		return parent_rate >> div2;

	return tegra_clk_super_ops.recalc_rate(hw, parent_rate);
	return tegra_clk_super_ops.recalc_rate(hw, parent_rate) >> div2;
}

static int cclk_super_determine_rate(struct clk_hw *hw,
Loading