Commit dd44ca51 authored by Thierry Reding's avatar Thierry Reding
Browse files

Merge branch 'for-5.14/clk' into for-5.14/memory

parents 6efb943b e848edae
Loading
Loading
Loading
Loading
+47 −33
Original line number Original line Diff line number Diff line
@@ -48,36 +48,45 @@ static int clk_periph_is_enabled(struct clk_hw *hw)
	return state;
	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);
	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);
	write_enb_set(periph_clk_to_bit(gate), gate);
	udelay(2);
	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) {
	if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
		writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
		writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
		udelay(1);
		udelay(1);
		writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
		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);
	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);
	spin_lock_irqsave(&periph_ref_lock, flags);


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

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

	spin_unlock_irqrestore(&periph_ref_lock, flags);
	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
	 * Some clocks are duplicated and some of them are marked as critical,
	 * flush the write operation in apb bus. This will avoid the
	 * like fuse and fuse_burn for example, thus the enable_refcnt will
	 * peripheral access after disabling clock
	 * be non-zero here if the "unused" duplicate is disabled by CCF.
	 */
	 */
	if (gate->flags & TEGRA_PERIPH_ON_APB)
	if (!gate->enable_refcnt[gate->clk_num])
		tegra_read_chipid();
		clk_periph_disable_locked(hw);

	write_enb_clr(periph_clk_to_bit(gate), gate);


	spin_unlock_irqrestore(&periph_ref_lock, flags);
	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,
	.is_enabled = clk_periph_is_enabled,
	.enable = clk_periph_enable,
	.enable = clk_periph_enable,
	.disable = clk_periph_disable,
	.disable = clk_periph_disable,
	.disable_unused = clk_periph_disable_unused,
};
};


struct clk *tegra_clk_register_periph_gate(const char *name,
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->enable_refcnt = enable_refcnt;
	gate->regs = pregs;
	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 */
	/* Data in .init is copied by clk_register(), so stack variable OK */
	gate->hw.init = &init;
	gate->hw.init = &init;


+11 −0
Original line number Original line Diff line number Diff line
@@ -100,6 +100,15 @@ static void clk_periph_disable(struct clk_hw *hw)
	gate_ops->disable(gate_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)
static void clk_periph_restore_context(struct clk_hw *hw)
{
{
	struct tegra_clk_periph *periph = to_clk_periph(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,
	.is_enabled = clk_periph_is_enabled,
	.enable = clk_periph_enable,
	.enable = clk_periph_enable,
	.disable = clk_periph_disable,
	.disable = clk_periph_disable,
	.disable_unused = clk_periph_disable_unused,
	.restore_context = clk_periph_restore_context,
	.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,
	.is_enabled = clk_periph_is_enabled,
	.enable = clk_periph_enable,
	.enable = clk_periph_enable,
	.disable = clk_periph_disable,
	.disable = clk_periph_disable,
	.disable_unused = clk_periph_disable_unused,
	.restore_context = clk_periph_restore_context,
	.restore_context = clk_periph_restore_context,
};
};


+7 −5
Original line number Original line 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;
	u32 p_div = 0;
	int ret;
	int ret;


	if (!rate)
		return -EINVAL;

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


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


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


	if (clk_pll_is_enabled(hw))
		return 0;

	input_rate = clk_hw_get_rate(__clk_get_hw(osc));
	input_rate = clk_hw_get_rate(__clk_get_hw(osc));


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


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


	ret = clk_pll_wait_for_lock(pll);
	ret = clk_pll_wait_for_lock(pll);
+3 −3
Original line number Original line 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("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("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("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("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, 0, tegra_clk_extern2),
	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, 0, tegra_clk_extern3),
	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_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("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),
	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 Original line Diff line number Diff line
@@ -25,6 +25,8 @@


#define SUPER_CDIV_ENB		BIT(31)
#define SUPER_CDIV_ENB		BIT(31)


#define TSENSOR_SLOWDOWN	BIT(23)

static struct tegra_clk_super_mux *cclk_super;
static struct tegra_clk_super_mux *cclk_super;
static bool cclk_on_pllx;
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,
static unsigned long cclk_super_recalc_rate(struct clk_hw *hw,
					    unsigned long parent_rate)
					    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)
	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,
static int cclk_super_determine_rate(struct clk_hw *hw,
Loading