Commit 871ca96f authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge tag 'clk-meson-v5.10-1' of https://github.com/BayLibre/clk-meson into clk-amlogic

Pull amlogic clk driver updates from Jerome Brunet:

 - g12: update audio clock inverter and fdiv2 flag
 - config: allow to disable unnecessary amlogic clock controllers

* tag 'clk-meson-v5.10-1' of https://github.com/BayLibre/clk-meson:
  clk: meson: make shipped controller configurable
  clk: meson: g12a: mark fclk_div2 as critical
  clk: meson: axg-audio: fix g12a tdmout sclk inverter
  clk: meson: axg-audio: separate axg and g12a regmap tables
  clk: meson: add sclk-ws driver
parents 9123e3a7 7b5c5720
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only
menu "Clock support for Amlogic platforms"
	depends on ARCH_MESON || COMPILE_TEST

config COMMON_CLK_MESON_REGMAP
	tristate
	select REGMAP
@@ -41,8 +44,9 @@ config COMMON_CLK_MESON_CPU_DYNDIV
	select COMMON_CLK_MESON_REGMAP

config COMMON_CLK_MESON8B
	bool
	depends on ARCH_MESON
	bool "Meson8 SoC Clock controller support"
	depends on ARM
	default y
	select COMMON_CLK_MESON_REGMAP
	select COMMON_CLK_MESON_MPLL
	select COMMON_CLK_MESON_PLL
@@ -54,8 +58,9 @@ config COMMON_CLK_MESON8B
	  want peripherals and CPU frequency scaling to work.

config COMMON_CLK_GXBB
	bool
	depends on ARCH_MESON
	bool "GXBB and GXL SoC clock controllers support"
	depends on ARM64
	default y
	select COMMON_CLK_MESON_REGMAP
	select COMMON_CLK_MESON_DUALDIV
	select COMMON_CLK_MESON_VID_PLL_DIV
@@ -69,8 +74,9 @@ config COMMON_CLK_GXBB
	  Say Y if you want peripherals and CPU frequency scaling to work.

config COMMON_CLK_AXG
	bool
	depends on ARCH_MESON
	bool "AXG SoC clock controllers support"
	depends on ARM64
	default y
	select COMMON_CLK_MESON_REGMAP
	select COMMON_CLK_MESON_DUALDIV
	select COMMON_CLK_MESON_MPLL
@@ -84,7 +90,7 @@ config COMMON_CLK_AXG

config COMMON_CLK_AXG_AUDIO
	tristate "Meson AXG Audio Clock Controller Driver"
	depends on ARCH_MESON
	depends on ARM64
	select COMMON_CLK_MESON_REGMAP
	select COMMON_CLK_MESON_PHASE
	select COMMON_CLK_MESON_SCLK_DIV
@@ -94,8 +100,9 @@ config COMMON_CLK_AXG_AUDIO
	  aka axg, Say Y if you want audio subsystem to work.

config COMMON_CLK_G12A
	bool
	depends on ARCH_MESON
	bool "G12 and SM1 SoC clock controllers support"
	depends on ARM64
	default y
	select COMMON_CLK_MESON_REGMAP
	select COMMON_CLK_MESON_DUALDIV
	select COMMON_CLK_MESON_MPLL
@@ -107,3 +114,4 @@ config COMMON_CLK_G12A
	help
	  Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
	  devices, aka g12a. Say Y if you want peripherals to work.
endmenu
+184 −30
Original line number Diff line number Diff line
@@ -147,6 +147,29 @@
	},								\
}

#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname,	\
		    _iflags) {						\
	.data = &(struct meson_sclk_ws_inv_data) {			\
		.ph = {							\
			.reg_off = (_reg),				\
			.shift   = (_shift_ph),				\
			.width   = (_width),				\
		},							\
		.ws = {							\
			.reg_off = (_reg),				\
			.shift   = (_shift_ws),				\
			.width   = (_width),				\
		},							\
	},								\
	.hw.init = &(struct clk_init_data) {				\
		.name = "aud_"#_name,					\
		.ops = &meson_clk_phase_ops,				\
		.parent_names = (const char *[]){ #_pname },		\
		.num_parents = 1,					\
		.flags = (_iflags),					\
	},								\
}

/* Audio Master Clocks */
static const struct clk_parent_data mst_mux_parent_data[] = {
	{ .fw_name = "mst_in0", },
@@ -254,6 +277,10 @@ static const struct clk_parent_data tdm_lrclk_parent_data[] = {
	AUD_PHASE(tdm##_name##_sclk, _reg, 1, 29,			\
		  aud_tdm##_name##_sclk_post_en,			\
		  CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)
#define AUD_TDM_SCLK_WS(_name, _reg)					\
	AUD_SCLK_WS(tdm##_name##_sclk, _reg, 1, 29, 28,			\
		    aud_tdm##_name##_sclk_post_en,			\
		    CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)

#define AUD_TDM_LRLCK(_name, _reg)					\
	AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20,			\
@@ -499,12 +526,6 @@ static struct clk_regmap tdmin_c_sclk =
	AUD_TDM_SCLK(in_c, AUDIO_CLK_TDMIN_C_CTRL);
static struct clk_regmap tdmin_lb_sclk =
	AUD_TDM_SCLK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
static struct clk_regmap tdmout_a_sclk =
	AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static struct clk_regmap tdmout_b_sclk =
	AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static struct clk_regmap tdmout_c_sclk =
	AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);

static struct clk_regmap tdmin_a_lrclk =
	AUD_TDM_LRLCK(in_a, AUDIO_CLK_TDMIN_A_CTRL);
@@ -521,6 +542,14 @@ static struct clk_regmap tdmout_b_lrclk =
static struct clk_regmap tdmout_c_lrclk =
	AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);

/* AXG Clocks */
static struct clk_regmap axg_tdmout_a_sclk =
	AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static struct clk_regmap axg_tdmout_b_sclk =
	AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static struct clk_regmap axg_tdmout_c_sclk =
	AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);

/* AXG/G12A Clocks */
static struct clk_hw axg_aud_top = {
	.init = &(struct clk_init_data) {
@@ -591,7 +620,13 @@ static struct clk_regmap g12a_tdm_sclk_pad_1 = AUD_TDM_PAD_CTRL(
static struct clk_regmap g12a_tdm_sclk_pad_2 = AUD_TDM_PAD_CTRL(
	sclk_pad_2, AUDIO_MST_PAD_CTRL1, 8, sclk_pad_ctrl_parent_data);

/* G12a/SM1 clocks */
static struct clk_regmap g12a_tdmout_a_sclk =
	AUD_TDM_SCLK_WS(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static struct clk_regmap g12a_tdmout_b_sclk =
	AUD_TDM_SCLK_WS(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static struct clk_regmap g12a_tdmout_c_sclk =
	AUD_TDM_SCLK_WS(out_c, AUDIO_CLK_TDMOUT_C_CTRL);

static struct clk_regmap toram =
	AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20);
static struct clk_regmap spdifout_b =
@@ -889,9 +924,9 @@ static struct clk_hw_onecell_data axg_audio_hw_onecell_data = {
		[AUD_CLKID_TDMIN_B_SCLK]	= &tdmin_b_sclk.hw,
		[AUD_CLKID_TDMIN_C_SCLK]	= &tdmin_c_sclk.hw,
		[AUD_CLKID_TDMIN_LB_SCLK]	= &tdmin_lb_sclk.hw,
		[AUD_CLKID_TDMOUT_A_SCLK]	= &tdmout_a_sclk.hw,
		[AUD_CLKID_TDMOUT_B_SCLK]	= &tdmout_b_sclk.hw,
		[AUD_CLKID_TDMOUT_C_SCLK]	= &tdmout_c_sclk.hw,
		[AUD_CLKID_TDMOUT_A_SCLK]	= &axg_tdmout_a_sclk.hw,
		[AUD_CLKID_TDMOUT_B_SCLK]	= &axg_tdmout_b_sclk.hw,
		[AUD_CLKID_TDMOUT_C_SCLK]	= &axg_tdmout_c_sclk.hw,
		[AUD_CLKID_TDMIN_A_LRCLK]	= &tdmin_a_lrclk.hw,
		[AUD_CLKID_TDMIN_B_LRCLK]	= &tdmin_b_lrclk.hw,
		[AUD_CLKID_TDMIN_C_LRCLK]	= &tdmin_c_lrclk.hw,
@@ -1026,9 +1061,9 @@ static struct clk_hw_onecell_data g12a_audio_hw_onecell_data = {
		[AUD_CLKID_TDMIN_B_SCLK]	= &tdmin_b_sclk.hw,
		[AUD_CLKID_TDMIN_C_SCLK]	= &tdmin_c_sclk.hw,
		[AUD_CLKID_TDMIN_LB_SCLK]	= &tdmin_lb_sclk.hw,
		[AUD_CLKID_TDMOUT_A_SCLK]	= &tdmout_a_sclk.hw,
		[AUD_CLKID_TDMOUT_B_SCLK]	= &tdmout_b_sclk.hw,
		[AUD_CLKID_TDMOUT_C_SCLK]	= &tdmout_c_sclk.hw,
		[AUD_CLKID_TDMOUT_A_SCLK]	= &g12a_tdmout_a_sclk.hw,
		[AUD_CLKID_TDMOUT_B_SCLK]	= &g12a_tdmout_b_sclk.hw,
		[AUD_CLKID_TDMOUT_C_SCLK]	= &g12a_tdmout_c_sclk.hw,
		[AUD_CLKID_TDMIN_A_LRCLK]	= &tdmin_a_lrclk.hw,
		[AUD_CLKID_TDMIN_B_LRCLK]	= &tdmin_b_lrclk.hw,
		[AUD_CLKID_TDMIN_C_LRCLK]	= &tdmin_c_lrclk.hw,
@@ -1170,9 +1205,9 @@ static struct clk_hw_onecell_data sm1_audio_hw_onecell_data = {
		[AUD_CLKID_TDMIN_B_SCLK]	= &tdmin_b_sclk.hw,
		[AUD_CLKID_TDMIN_C_SCLK]	= &tdmin_c_sclk.hw,
		[AUD_CLKID_TDMIN_LB_SCLK]	= &tdmin_lb_sclk.hw,
		[AUD_CLKID_TDMOUT_A_SCLK]	= &tdmout_a_sclk.hw,
		[AUD_CLKID_TDMOUT_B_SCLK]	= &tdmout_b_sclk.hw,
		[AUD_CLKID_TDMOUT_C_SCLK]	= &tdmout_c_sclk.hw,
		[AUD_CLKID_TDMOUT_A_SCLK]	= &g12a_tdmout_a_sclk.hw,
		[AUD_CLKID_TDMOUT_B_SCLK]	= &g12a_tdmout_b_sclk.hw,
		[AUD_CLKID_TDMOUT_C_SCLK]	= &g12a_tdmout_c_sclk.hw,
		[AUD_CLKID_TDMIN_A_LRCLK]	= &tdmin_a_lrclk.hw,
		[AUD_CLKID_TDMIN_B_LRCLK]	= &tdmin_b_lrclk.hw,
		[AUD_CLKID_TDMIN_C_LRCLK]	= &tdmin_c_lrclk.hw,
@@ -1209,13 +1244,132 @@ static struct clk_hw_onecell_data sm1_audio_hw_onecell_data = {
};


/* Convenience table to populate regmap in .probe()
 * Note that this table is shared between both AXG and G12A,
 * with spdifout_b clocks being exclusive to G12A. Since those
 * clocks are not declared within the AXG onecell table, we do not
 * feel the need to have separate AXG/G12A regmap tables.
 */
/* Convenience table to populate regmap in .probe(). */
static struct clk_regmap *const axg_clk_regmaps[] = {
	&ddr_arb,
	&pdm,
	&tdmin_a,
	&tdmin_b,
	&tdmin_c,
	&tdmin_lb,
	&tdmout_a,
	&tdmout_b,
	&tdmout_c,
	&frddr_a,
	&frddr_b,
	&frddr_c,
	&toddr_a,
	&toddr_b,
	&toddr_c,
	&loopback,
	&spdifin,
	&spdifout,
	&resample,
	&power_detect,
	&mst_a_mclk_sel,
	&mst_b_mclk_sel,
	&mst_c_mclk_sel,
	&mst_d_mclk_sel,
	&mst_e_mclk_sel,
	&mst_f_mclk_sel,
	&mst_a_mclk_div,
	&mst_b_mclk_div,
	&mst_c_mclk_div,
	&mst_d_mclk_div,
	&mst_e_mclk_div,
	&mst_f_mclk_div,
	&mst_a_mclk,
	&mst_b_mclk,
	&mst_c_mclk,
	&mst_d_mclk,
	&mst_e_mclk,
	&mst_f_mclk,
	&spdifout_clk_sel,
	&spdifout_clk_div,
	&spdifout_clk,
	&spdifin_clk_sel,
	&spdifin_clk_div,
	&spdifin_clk,
	&pdm_dclk_sel,
	&pdm_dclk_div,
	&pdm_dclk,
	&pdm_sysclk_sel,
	&pdm_sysclk_div,
	&pdm_sysclk,
	&mst_a_sclk_pre_en,
	&mst_b_sclk_pre_en,
	&mst_c_sclk_pre_en,
	&mst_d_sclk_pre_en,
	&mst_e_sclk_pre_en,
	&mst_f_sclk_pre_en,
	&mst_a_sclk_div,
	&mst_b_sclk_div,
	&mst_c_sclk_div,
	&mst_d_sclk_div,
	&mst_e_sclk_div,
	&mst_f_sclk_div,
	&mst_a_sclk_post_en,
	&mst_b_sclk_post_en,
	&mst_c_sclk_post_en,
	&mst_d_sclk_post_en,
	&mst_e_sclk_post_en,
	&mst_f_sclk_post_en,
	&mst_a_sclk,
	&mst_b_sclk,
	&mst_c_sclk,
	&mst_d_sclk,
	&mst_e_sclk,
	&mst_f_sclk,
	&mst_a_lrclk_div,
	&mst_b_lrclk_div,
	&mst_c_lrclk_div,
	&mst_d_lrclk_div,
	&mst_e_lrclk_div,
	&mst_f_lrclk_div,
	&mst_a_lrclk,
	&mst_b_lrclk,
	&mst_c_lrclk,
	&mst_d_lrclk,
	&mst_e_lrclk,
	&mst_f_lrclk,
	&tdmin_a_sclk_sel,
	&tdmin_b_sclk_sel,
	&tdmin_c_sclk_sel,
	&tdmin_lb_sclk_sel,
	&tdmout_a_sclk_sel,
	&tdmout_b_sclk_sel,
	&tdmout_c_sclk_sel,
	&tdmin_a_sclk_pre_en,
	&tdmin_b_sclk_pre_en,
	&tdmin_c_sclk_pre_en,
	&tdmin_lb_sclk_pre_en,
	&tdmout_a_sclk_pre_en,
	&tdmout_b_sclk_pre_en,
	&tdmout_c_sclk_pre_en,
	&tdmin_a_sclk_post_en,
	&tdmin_b_sclk_post_en,
	&tdmin_c_sclk_post_en,
	&tdmin_lb_sclk_post_en,
	&tdmout_a_sclk_post_en,
	&tdmout_b_sclk_post_en,
	&tdmout_c_sclk_post_en,
	&tdmin_a_sclk,
	&tdmin_b_sclk,
	&tdmin_c_sclk,
	&tdmin_lb_sclk,
	&axg_tdmout_a_sclk,
	&axg_tdmout_b_sclk,
	&axg_tdmout_c_sclk,
	&tdmin_a_lrclk,
	&tdmin_b_lrclk,
	&tdmin_c_lrclk,
	&tdmin_lb_lrclk,
	&tdmout_a_lrclk,
	&tdmout_b_lrclk,
	&tdmout_c_lrclk,
};

static struct clk_regmap *const g12a_clk_regmaps[] = {
	&ddr_arb,
	&pdm,
	&tdmin_a,
@@ -1328,9 +1482,9 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
	&tdmin_b_sclk,
	&tdmin_c_sclk,
	&tdmin_lb_sclk,
	&tdmout_a_sclk,
	&tdmout_b_sclk,
	&tdmout_c_sclk,
	&g12a_tdmout_a_sclk,
	&g12a_tdmout_b_sclk,
	&g12a_tdmout_c_sclk,
	&tdmin_a_lrclk,
	&tdmin_b_lrclk,
	&tdmin_c_lrclk,
@@ -1465,9 +1619,9 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
	&tdmin_b_sclk,
	&tdmin_c_sclk,
	&tdmin_lb_sclk,
	&tdmout_a_sclk,
	&tdmout_b_sclk,
	&tdmout_c_sclk,
	&g12a_tdmout_a_sclk,
	&g12a_tdmout_b_sclk,
	&g12a_tdmout_c_sclk,
	&tdmin_a_lrclk,
	&tdmin_b_lrclk,
	&tdmin_c_lrclk,
@@ -1713,8 +1867,8 @@ static const struct audioclk_data axg_audioclk_data = {
};

static const struct audioclk_data g12a_audioclk_data = {
	.regmap_clks = axg_clk_regmaps,
	.regmap_clk_num = ARRAY_SIZE(axg_clk_regmaps),
	.regmap_clks = g12a_clk_regmaps,
	.regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
	.hw_onecell_data = &g12a_audio_hw_onecell_data,
	.reset_offset = AUDIO_SW_RESET,
	.reset_num = 26,
+56 −0
Original line number Diff line number Diff line
@@ -125,6 +125,62 @@ const struct clk_ops meson_clk_triphase_ops = {
};
EXPORT_SYMBOL_GPL(meson_clk_triphase_ops);

/*
 * This is a special clock for the audio controller.
 * This drive a bit clock inverter for which the
 * opposite value of the inverter bit needs to be manually
 * set into another bit
 */
static inline struct meson_sclk_ws_inv_data *
meson_sclk_ws_inv_data(struct clk_regmap *clk)
{
	return (struct meson_sclk_ws_inv_data *)clk->data;
}

static int meson_sclk_ws_inv_sync(struct clk_hw *hw)
{
	struct clk_regmap *clk = to_clk_regmap(hw);
	struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk);
	unsigned int val;

	/* Get phase and sync the inverted value to ws */
	val = meson_parm_read(clk->map, &tph->ph);
	meson_parm_write(clk->map, &tph->ws, val ? 0 : 1);

	return 0;
}

static int meson_sclk_ws_inv_get_phase(struct clk_hw *hw)
{
	struct clk_regmap *clk = to_clk_regmap(hw);
	struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk);
	unsigned int val;

	val = meson_parm_read(clk->map, &tph->ph);

	return meson_clk_degrees_from_val(val, tph->ph.width);
}

static int meson_sclk_ws_inv_set_phase(struct clk_hw *hw, int degrees)
{
	struct clk_regmap *clk = to_clk_regmap(hw);
	struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk);
	unsigned int val;

	val = meson_clk_degrees_to_val(degrees, tph->ph.width);
	meson_parm_write(clk->map, &tph->ph, val);
	meson_parm_write(clk->map, &tph->ws, val ? 0 : 1);
	return 0;
}

const struct clk_ops meson_sclk_ws_inv_ops = {
	.init		= meson_sclk_ws_inv_sync,
	.get_phase	= meson_sclk_ws_inv_get_phase,
	.set_phase	= meson_sclk_ws_inv_set_phase,
};
EXPORT_SYMBOL_GPL(meson_sclk_ws_inv_ops);


MODULE_DESCRIPTION("Amlogic phase driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL v2");
+6 −0
Original line number Diff line number Diff line
@@ -20,7 +20,13 @@ struct meson_clk_triphase_data {
	struct parm ph2;
};

struct meson_sclk_ws_inv_data {
	struct parm ph;
	struct parm ws;
};

extern const struct clk_ops meson_clk_phase_ops;
extern const struct clk_ops meson_clk_triphase_ops;
extern const struct clk_ops meson_sclk_ws_inv_ops;

#endif /* __MESON_CLK_PHASE_H */
+11 −0
Original line number Diff line number Diff line
@@ -298,6 +298,17 @@ static struct clk_regmap g12a_fclk_div2 = {
			&g12a_fclk_div2_div.hw
		},
		.num_parents = 1,
		/*
		 * Similar to fclk_div3, it seems that this clock is used by
		 * the resident firmware and is required by the platform to
		 * operate correctly.
		 * Until the following condition are met, we need this clock to
		 * be marked as critical:
		 * a) Mark the clock used by a firmware resource, if possible
		 * b) CCF has a clock hand-off mechanism to make the sure the
		 *    clock stays on until the proper driver comes along
		 */
		.flags = CLK_IS_CRITICAL,
	},
};