First round of amlogic clock updates for v5.10

* g12: update audio clock inverter and fdiv2 flag
 * config: allow to disable unnecessary amlogic clock controllers
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE9OFZrhjz9W1fG7cb5vwPHDfy2oUFAl9fpfEACgkQ5vwPHDfy
 2oWZwRAAoi8q5jDtB4fcqubsy9CBu47VIcaunS/LdHE2D8f9HSqcnyvJbDtG6GqU
 soWodIxjy1jE9KKC09/SEko5j21pvoRxHna6AVevg0dceP1zlq+5b4FVt9j6U8Pp
 bXRd+RROE6mHSaX8GKD2WUTMHqSDisr8HY+Bq+1EfqjyvA1+Onz7St6529fSqXO+
 VQ5cwC9WXYmP0SJjP/20QHhdfuPFdn0yIyDBvjSiI0m+Z5DXWUdebSclShRJneps
 T6dKoVFvSILzh5RNbsbF5vdlPsg0yf+V9VWMJBoyPQVC30gO8LMe1whM+GoHkEdr
 0IebivuQEGjTiSw5wmsT0CdISgLnQH/vV/F6fH68YxFXhVvzAdnaXEKxE+w1DXwi
 CyBuNsih2d9Wu+YtW8B/1JkpmapfJgdw1fYRqoJTbOuWZWeOqiszREOcmmRmnU2S
 XgSM8VW+1RfbqiJC6LeiHkTGxEJoDhMAHIlS1AsuzBQRv0bumUtsCD8WT4/tjREg
 ZNtq9FiwMVSpSQzKfhsZElqd5AMghIyLik1JiUw1i6DZrMz2c9Y/Bm1QBVcSrhTV
 7YSbfH0fy8f4pau/Bd9RIddYVRuuwJ9fli6kX7oXzBgXvdnN08FdN1Z8jU58vmB/
 3AERTLTbTkf57KanOTPKyxXUXTr7OmagdZyq8vPkaDz5WlRC9+g=
 =JLsW
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Stephen Boyd 2020-09-21 13:53:15 -07:00
commit 871ca96f1c
5 changed files with 274 additions and 39 deletions

View File

@ -1,4 +1,7 @@
# 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

View File

@ -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,

View File

@ -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");

View File

@ -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 */

View File

@ -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,
},
};