Unverified Commit 853a7a63 authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge tag 'thead-clk-for-v6.17-p2' of...

Merge tag 'thead-clk-for-v6.17-p2' of git://git.kernel.org/pub/scm/linux/kernel/git/fustini/linux into clk-thead

Pull one more T-HEAD clk driver update from Drew Fustini:

Yao Zi has fixed an issue where the c910 mux clk could end up as an
orphan in CCF when the bootloader reparents it to the c910-i0 mux clk.
The solution is to refactor the handling of mux clocks by embedding a
clk_mux structure directly in ccu_mux. This allows the mux clocks to be
registered with devm_clk_hw_register() without allocating any new clk_hw
pointer which solves the orphan issue.

This change has been tested in linux-next. The LPi4a still boots okay
without clk_ignore_unused and peripherals like serial, emmc and ethernet
are functional. The file /sys/kernel/debug/clk/c910/clk_possible_parents
now correctly outputs: "c910-i0 cpu-pll1"

* tag 'thead-clk-for-v6.17-p2' of git://git.kernel.org/pub/scm/linux/kernel/git/fustini/linux:
  clk: thead: th1520-ap: Describe mux clocks with clk_mux
parents ab8cfde3 54edba91
Loading
Loading
Loading
Loading
+37 −58
Original line number Diff line number Diff line
@@ -42,8 +42,9 @@ struct ccu_common {
};

struct ccu_mux {
	struct ccu_internal	mux;
	struct ccu_common	common;
	int			clkid;
	u32			reg;
	struct clk_mux		mux;
};

struct ccu_gate {
@@ -75,6 +76,17 @@ struct ccu_pll {
		.flags	= _flags,					\
	}

#define TH_CCU_MUX(_name, _parents, _shift, _width)			\
	{								\
		.mask		= GENMASK(_width - 1, 0),		\
		.shift		= _shift,				\
		.hw.init	= CLK_HW_INIT_PARENTS_DATA(		\
					_name,				\
					_parents,			\
					&clk_mux_ops,			\
					0),				\
	}

#define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _gate, _flags)	\
	struct ccu_gate _struct = {					\
		.enable	= _gate,					\
@@ -94,13 +106,6 @@ static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)
	return container_of(hw, struct ccu_common, hw);
}

static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)
{
	struct ccu_common *common = hw_to_ccu_common(hw);

	return container_of(common, struct ccu_mux, common);
}

static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw)
{
	struct ccu_common *common = hw_to_ccu_common(hw);
@@ -415,32 +420,20 @@ static const struct clk_parent_data c910_i0_parents[] = {
};

static struct ccu_mux c910_i0_clk = {
	.mux	= TH_CCU_ARG(1, 1),
	.common	= {
	.clkid	= CLK_C910_I0,
		.cfg0		= 0x100,
		.hw.init	= CLK_HW_INIT_PARENTS_DATA("c910-i0",
					      c910_i0_parents,
					      &clk_mux_ops,
					      0),
	}
	.reg	= 0x100,
	.mux	= TH_CCU_MUX("c910-i0", c910_i0_parents, 1, 1),
};

static const struct clk_parent_data c910_parents[] = {
	{ .hw = &c910_i0_clk.common.hw },
	{ .hw = &c910_i0_clk.mux.hw },
	{ .hw = &cpu_pll1_clk.common.hw }
};

static struct ccu_mux c910_clk = {
	.mux	= TH_CCU_ARG(0, 1),
	.common	= {
	.clkid	= CLK_C910,
		.cfg0		= 0x100,
		.hw.init	= CLK_HW_INIT_PARENTS_DATA("c910",
					      c910_parents,
					      &clk_mux_ops,
					      0),
	}
	.reg	= 0x100,
	.mux	= TH_CCU_MUX("c910", c910_parents, 0, 1),
};

static const struct clk_parent_data ahb2_cpusys_parents[] = {
@@ -925,15 +918,9 @@ static const struct clk_parent_data uart_sclk_parents[] = {
};

static struct ccu_mux uart_sclk = {
	.mux	= TH_CCU_ARG(0, 1),
	.common	= {
	.clkid	= CLK_UART_SCLK,
		.cfg0		= 0x210,
		.hw.init	= CLK_HW_INIT_PARENTS_DATA("uart-sclk",
					      uart_sclk_parents,
					      &clk_mux_ops,
					      0),
	}
	.reg	= 0x210,
	.mux	= TH_CCU_MUX("uart-sclk", uart_sclk_parents, 0, 1),
};

static struct ccu_common *th1520_pll_clks[] = {
@@ -970,10 +957,10 @@ static struct ccu_common *th1520_div_clks[] = {
	&dpu1_clk.common,
};

static struct ccu_common *th1520_mux_clks[] = {
	&c910_i0_clk.common,
	&c910_clk.common,
	&uart_sclk.common,
static struct ccu_mux *th1520_mux_clks[] = {
	&c910_i0_clk,
	&c910_clk,
	&uart_sclk,
};

static struct ccu_common *th1520_gate_clks[] = {
@@ -1075,7 +1062,7 @@ static const struct regmap_config th1520_clk_regmap_config = {
struct th1520_plat_data {
	struct ccu_common **th1520_pll_clks;
	struct ccu_common **th1520_div_clks;
	struct ccu_common **th1520_mux_clks;
	struct ccu_mux	  **th1520_mux_clks;
	struct ccu_common **th1520_gate_clks;

	int nr_clks;
@@ -1162,23 +1149,15 @@ static int th1520_clk_probe(struct platform_device *pdev)
	}

	for (i = 0; i < plat_data->nr_mux_clks; i++) {
		struct ccu_mux *cm = hw_to_ccu_mux(&plat_data->th1520_mux_clks[i]->hw);
		const struct clk_init_data *init = cm->common.hw.init;

		plat_data->th1520_mux_clks[i]->map = map;
		hw = devm_clk_hw_register_mux_parent_data_table(dev,
								init->name,
								init->parent_data,
								init->num_parents,
								0,
								base + cm->common.cfg0,
								cm->mux.shift,
								cm->mux.width,
								0, NULL, NULL);
		if (IS_ERR(hw))
			return PTR_ERR(hw);
		struct ccu_mux *cm = plat_data->th1520_mux_clks[i];

		cm->mux.reg = base + cm->reg;

		ret = devm_clk_hw_register(dev, &cm->mux.hw);
		if (ret)
			return ret;

		priv->hws[cm->common.clkid] = hw;
		priv->hws[cm->clkid] = &cm->mux.hw;
	}

	for (i = 0; i < plat_data->nr_gate_clks; i++) {