Amlogic clock changes for v5.4

* Migrate to new clock description method
 * Add DVFS support to g12
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE9OFZrhjz9W1fG7cb5vwPHDfy2oUFAl1RLUQACgkQ5vwPHDfy
 2oUeNA/9GSr1WUdlsGiWdjRmqiKTMSo8Evq0/LlSanDBR9lkCrgaWPG2vjxS5r8c
 3Is/klVnPnVtG7wugrPXCrlE0VLsrbclN20dziUyLnK8eNsBG3UBtZLiGGV26nRA
 MInv/AfI4dad4nMYcNlIszHLewVeoTz+KyAaSEK/mhJca8kv4E4m0CXr0ZW6AAKF
 qpVKIMScmF+rDn4UtjE4XbTa3dm8vJva6GqUvy2IgUukg8UQ4zwOd2/m9870GvRA
 lKBtm4yiegkgmd8ykRcEg3QMs4CatAKIujeLftg4DQB7h3O8aDwobAeAgtVcJlKM
 Upy+9CMEPJQ6UC/bc4+RBlUpmOBWKEYANEObAZf83Mi5zzFYqsuAdnuzkWqxcKhF
 ptt/UxfgpoVG7QljjDbrQsQfhniZ7oSFog+FT52AzbbN0ch391MRW9ek5UwrT99A
 o36JXWl6YZivbSaF9KDzGVBZr7KUdLypXd9EkPdt+Xx6lIAsqBAlSC3KnYhndllz
 r4doYZs8PvK6K8nZFYXslwMc06+rMUGb7B6TixstozKyF+IUp8i3peXFxpKf3u/C
 1ewriDsaakKMZvQ1dEQdw3Ls2qWl0Zf/BQYEQn7u9NzBpdmUA9JFkw4AcgxFxY9k
 JVle4Zb1iT5P2Lsuu+DcqKxPNbKcl1EQTuxttfhQh6UkcrKBs5A=
 =2py5
 -----END PGP SIGNATURE-----

Merge tag 'clk-meson-v5.4-1' of git://github.com/BayLibre/clk-meson into v5.4/dt64

Amlogic clock changes for v5.4

* Migrate to new clock description method
* Add DVFS support to g12

# gpg: Signature made Mon 12 Aug 2019 02:11:32 AM PDT
# gpg:                using RSA key F4E159AE18F3F56D5F1BB71BE6FC0F1C37F2DA85
# gpg: Good signature from "Jerome Brunet <jbrunet@baylibre.com>" [full]
# gpg:                 aka "Jerome Brunet <jerome@liltaz.com>" [full]
# gpg:                 aka "Jerome Brunet <jerome.brunet@gmail.com>" [full]

* tag 'clk-meson-v5.4-1' of git://github.com/BayLibre/clk-meson:
  clk: meson: g12a: expose CPUB clock ID for G12B
  clk: meson: g12a: add notifiers to handle cpu clock change
  clk: meson: add g12a cpu dynamic divider driver
  clk: core: introduce clk_hw_set_parent()
  clk: meson: remove clk input helper
  clk: meson: remove ee input bypass clocks
  clk: meson: clk-regmap: migrate to new parent description method
  clk: meson: meson8b: migrate to the new parent description method
  clk: meson: axg: migrate to the new parent description method
  clk: meson: gxbb: migrate to the new parent description method
  clk: meson: g12a: migrate to the new parent description method
  clk: meson: remove ao input bypass clocks
  clk: meson: axg-aoclk: migrate to the new parent description method
  clk: meson: gxbb-aoclk: migrate to the new parent description method
  clk: meson: g12a-aoclk: migrate to the new parent description method
  clk: meson: axg-audio: migrate to the new parent description method
  clk: meson: g12a: fix hifi typo in mali parent_names
This commit is contained in:
Kevin Hilman 2019-08-12 13:21:00 -07:00
commit b69337d38e
23 changed files with 2924 additions and 1584 deletions

View File

@ -2487,6 +2487,12 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
return ret;
}
int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *parent)
{
return clk_core_set_parent_nolock(hw->core, parent->core);
}
EXPORT_SYMBOL_GPL(clk_hw_set_parent);
/**
* clk_set_parent - switch the parent of a mux clk
* @clk: the mux clk whose input we are switching

View File

@ -1,7 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
config COMMON_CLK_MESON_INPUT
tristate
config COMMON_CLK_MESON_REGMAP
tristate
select REGMAP
@ -33,13 +30,15 @@ config COMMON_CLK_MESON_VID_PLL_DIV
config COMMON_CLK_MESON_AO_CLKC
tristate
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_INPUT
select RESET_CONTROLLER
config COMMON_CLK_MESON_EE_CLKC
tristate
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_INPUT
config COMMON_CLK_MESON_CPU_DYNDIV
tristate
select COMMON_CLK_MESON_REGMAP
config COMMON_CLK_MESON8B
bool
@ -86,7 +85,6 @@ config COMMON_CLK_AXG
config COMMON_CLK_AXG_AUDIO
tristate "Meson AXG Audio Clock Controller Driver"
depends on ARCH_MESON
select COMMON_CLK_MESON_INPUT
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_PHASE
select COMMON_CLK_MESON_SCLK_DIV
@ -104,6 +102,7 @@ config COMMON_CLK_G12A
select COMMON_CLK_MESON_PLL
select COMMON_CLK_MESON_AO_CLKC
select COMMON_CLK_MESON_EE_CLKC
select COMMON_CLK_MESON_CPU_DYNDIV
select MFD_SYSCON
help
Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2

View File

@ -2,9 +2,9 @@
# Amlogic clock drivers
obj-$(CONFIG_COMMON_CLK_MESON_AO_CLKC) += meson-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON_CPU_DYNDIV) += clk-cpu-dyndiv.o
obj-$(CONFIG_COMMON_CLK_MESON_DUALDIV) += clk-dualdiv.o
obj-$(CONFIG_COMMON_CLK_MESON_EE_CLKC) += meson-eeclk.o
obj-$(CONFIG_COMMON_CLK_MESON_INPUT) += clk-input.o
obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o
obj-$(CONFIG_COMMON_CLK_MESON_PHASE) += clk-phase.o
obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o

View File

@ -18,8 +18,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
#define IN_PREFIX "ao-in-"
/*
* AO Configuration Clock registers offsets
* Register offsets from the data sheet must be multiplied by 4.
@ -42,7 +40,9 @@ static struct clk_regmap axg_aoclk_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "axg_ao_" #_name, \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "mpeg-clk", \
}, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@ -64,7 +64,9 @@ static struct clk_regmap axg_aoclk_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@ -77,7 +79,9 @@ static struct clk_regmap axg_aoclk_32k_pre = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_pre",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "cts_oscin" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_cts_oscin.hw
},
.num_parents = 1,
},
};
@ -124,7 +128,9 @@ static struct clk_regmap axg_aoclk_32k_div = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_div",
.ops = &meson_clk_dualdiv_ops,
.parent_names = (const char *[]){ "axg_ao_32k_pre" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_32k_pre.hw
},
.num_parents = 1,
},
};
@ -139,8 +145,10 @@ static struct clk_regmap axg_aoclk_32k_sel = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "axg_ao_32k_div",
"axg_ao_32k_pre" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_32k_div.hw,
&axg_aoclk_32k_pre.hw,
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -154,7 +162,9 @@ static struct clk_regmap axg_aoclk_32k = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "axg_ao_32k_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_32k_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -170,8 +180,10 @@ static struct clk_regmap axg_aoclk_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "axg_ao_32k",
IN_PREFIX "ext_32k-0" },
.parent_data = (const struct clk_parent_data []) {
{ .hw = &axg_aoclk_32k.hw },
{ .fw_name = "ext_32k-0", },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -187,8 +199,10 @@ static struct clk_regmap axg_aoclk_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
"axg_ao_cts_rtc_oscin"},
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "mpeg-clk", },
{ .hw = &axg_aoclk_cts_rtc_oscin.hw },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -203,8 +217,10 @@ static struct clk_regmap axg_aoclk_saradc_mux = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_mux",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal",
"axg_ao_clk81" },
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", },
{ .hw = &axg_aoclk_clk81.hw },
},
.num_parents = 2,
},
};
@ -218,7 +234,9 @@ static struct clk_regmap axg_aoclk_saradc_div = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "axg_ao_saradc_mux" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_saradc_mux.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -232,7 +250,9 @@ static struct clk_regmap axg_aoclk_saradc_gate = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_gate",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "axg_ao_saradc_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_saradc_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -290,12 +310,6 @@ static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
.num = NR_CLKS,
};
static const struct meson_aoclk_input axg_aoclk_inputs[] = {
{ .name = "xtal", .required = true },
{ .name = "mpeg-clk", .required = true },
{ .name = "ext-32k-0", .required = false },
};
static const struct meson_aoclk_data axg_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(axg_aoclk_reset),
@ -303,9 +317,6 @@ static const struct meson_aoclk_data axg_aoclkc_data = {
.num_clks = ARRAY_SIZE(axg_aoclk_regmap),
.clks = axg_aoclk_regmap,
.hw_data = &axg_aoclk_onecell_data,
.inputs = axg_aoclk_inputs,
.num_inputs = ARRAY_SIZE(axg_aoclk_inputs),
.input_prefix = IN_PREFIX,
};
static const struct of_device_id axg_aoclkc_match_table[] = {

View File

@ -15,7 +15,6 @@
#include <linux/slab.h>
#include "axg-audio.h"
#include "clk-input.h"
#include "clk-regmap.h"
#include "clk-phase.h"
#include "sclk-div.h"
@ -24,7 +23,7 @@
#define AUD_SLV_SCLK_COUNT 10
#define AUD_SLV_LRCLK_COUNT 10
#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) \
#define AUD_GATE(_name, _reg, _bit, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (_reg), \
@ -33,13 +32,13 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ _pname }, \
.parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
}
#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pnames, _iflags) \
#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_mux_data){ \
.offset = (_reg), \
@ -50,13 +49,13 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data){ \
.name = "aud_"#_name, \
.ops = &clk_regmap_mux_ops, \
.parent_names = (_pnames), \
.num_parents = ARRAY_SIZE(_pnames), \
.parent_data = _pdata, \
.num_parents = ARRAY_SIZE(_pdata), \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
}
#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) \
#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_div_data){ \
.offset = (_reg), \
@ -67,15 +66,27 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data){ \
.name = "aud_"#_name, \
.ops = &clk_regmap_divider_ops, \
.parent_names = (const char *[]) { _pname }, \
.parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = (_iflags), \
}, \
}
#define AUD_PCLK_GATE(_name, _bit) \
AUD_GATE(_name, AUDIO_CLK_GATE_EN, _bit, "audio_pclk", 0)
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (AUDIO_CLK_GATE_EN), \
.bit_idx = (_bit), \
}, \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &clk_regmap_gate_ops, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "pclk", \
}, \
.num_parents = 1, \
}, \
}
/* Audio peripheral clocks */
static AUD_PCLK_GATE(ddr_arb, 0);
static AUD_PCLK_GATE(pdm, 1);
@ -100,14 +111,20 @@ static AUD_PCLK_GATE(power_detect, 19);
static AUD_PCLK_GATE(spdifout_b, 21);
/* Audio Master Clocks */
static const char * const mst_mux_parent_names[] = {
"aud_mst_in0", "aud_mst_in1", "aud_mst_in2", "aud_mst_in3",
"aud_mst_in4", "aud_mst_in5", "aud_mst_in6", "aud_mst_in7",
static const struct clk_parent_data mst_mux_parent_data[] = {
{ .fw_name = "mst_in0", },
{ .fw_name = "mst_in1", },
{ .fw_name = "mst_in2", },
{ .fw_name = "mst_in3", },
{ .fw_name = "mst_in4", },
{ .fw_name = "mst_in5", },
{ .fw_name = "mst_in6", },
{ .fw_name = "mst_in7", },
};
#define AUD_MST_MUX(_name, _reg, _flag) \
AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
mst_mux_parent_names, CLK_SET_RATE_PARENT)
mst_mux_parent_data, 0)
#define AUD_MST_MCLK_MUX(_name, _reg) \
AUD_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
@ -129,7 +146,7 @@ static AUD_MST_MCLK_MUX(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
#define AUD_MST_DIV(_name, _reg, _flag) \
AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
"aud_"#_name"_sel", CLK_SET_RATE_PARENT) \
aud_##_name##_sel, CLK_SET_RATE_PARENT) \
#define AUD_MST_MCLK_DIV(_name, _reg) \
AUD_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
@ -150,7 +167,7 @@ static AUD_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
static AUD_MST_MCLK_DIV(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
#define AUD_MST_MCLK_GATE(_name, _reg) \
AUD_GATE(_name, _reg, 31, "aud_"#_name"_div", \
AUD_GATE(_name, _reg, 31, aud_##_name##_div, \
CLK_SET_RATE_PARENT)
static AUD_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);
@ -168,7 +185,7 @@ static AUD_MST_MCLK_GATE(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
/* Sample Clocks */
#define AUD_MST_SCLK_PRE_EN(_name, _reg) \
AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31, \
"aud_mst_"#_name"_mclk", 0)
aud_mst_##_name##_mclk, 0)
static AUD_MST_SCLK_PRE_EN(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_SCLK_PRE_EN(b, AUDIO_MST_B_SCLK_CTRL0);
@ -178,7 +195,7 @@ static AUD_MST_SCLK_PRE_EN(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_PRE_EN(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width, \
_hi_shift, _hi_width, _pname, _iflags) \
_hi_shift, _hi_width, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct meson_sclk_div_data) { \
.div = { \
@ -195,7 +212,7 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &meson_sclk_div_ops, \
.parent_names = (const char *[]) { _pname }, \
.parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = (_iflags), \
}, \
@ -203,7 +220,7 @@ struct clk_regmap aud_##_name = { \
#define AUD_MST_SCLK_DIV(_name, _reg) \
AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0, \
"aud_mst_"#_name"_sclk_pre_en", \
aud_mst_##_name##_sclk_pre_en, \
CLK_SET_RATE_PARENT)
static AUD_MST_SCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
@ -214,8 +231,8 @@ static AUD_MST_SCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_MST_SCLK_POST_EN(_name, _reg) \
AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \
"aud_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT)
AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \
aud_mst_##_name##_sclk_div, CLK_SET_RATE_PARENT)
static AUD_MST_SCLK_POST_EN(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(b, AUDIO_MST_B_SCLK_CTRL0);
@ -224,8 +241,8 @@ static AUD_MST_SCLK_POST_EN(d, AUDIO_MST_D_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
_pname, _iflags) \
#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
_phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct meson_clk_triphase_data) { \
.ph0 = { \
@ -247,7 +264,7 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &meson_clk_triphase_ops, \
.parent_names = (const char *[]) { _pname }, \
.parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
@ -255,7 +272,7 @@ struct clk_regmap aud_##_name = { \
#define AUD_MST_SCLK(_name, _reg) \
AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4, \
"aud_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT)
aud_mst_##_name##_sclk_post_en, CLK_SET_RATE_PARENT)
static AUD_MST_SCLK(a, AUDIO_MST_A_SCLK_CTRL1);
static AUD_MST_SCLK(b, AUDIO_MST_B_SCLK_CTRL1);
@ -266,7 +283,7 @@ static AUD_MST_SCLK(f, AUDIO_MST_F_SCLK_CTRL1);
#define AUD_MST_LRCLK_DIV(_name, _reg) \
AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10, \
"aud_mst_"#_name"_sclk_post_en", 0) \
aud_mst_##_name##_sclk_post_en, 0) \
static AUD_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_LRCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
@ -277,7 +294,7 @@ static AUD_MST_LRCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_MST_LRCLK(_name, _reg) \
AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5, \
"aud_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT)
aud_mst_##_name##_lrclk_div, CLK_SET_RATE_PARENT)
static AUD_MST_LRCLK(a, AUDIO_MST_A_SCLK_CTRL1);
static AUD_MST_LRCLK(b, AUDIO_MST_B_SCLK_CTRL1);
@ -286,19 +303,29 @@ static AUD_MST_LRCLK(d, AUDIO_MST_D_SCLK_CTRL1);
static AUD_MST_LRCLK(e, AUDIO_MST_E_SCLK_CTRL1);
static AUD_MST_LRCLK(f, AUDIO_MST_F_SCLK_CTRL1);
static const char * const tdm_sclk_parent_names[] = {
"aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
"aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
"aud_slv_sclk0", "aud_slv_sclk1", "aud_slv_sclk2",
"aud_slv_sclk3", "aud_slv_sclk4", "aud_slv_sclk5",
"aud_slv_sclk6", "aud_slv_sclk7", "aud_slv_sclk8",
"aud_slv_sclk9"
static const struct clk_parent_data tdm_sclk_parent_data[] = {
{ .hw = &aud_mst_a_sclk.hw, },
{ .hw = &aud_mst_b_sclk.hw, },
{ .hw = &aud_mst_c_sclk.hw, },
{ .hw = &aud_mst_d_sclk.hw, },
{ .hw = &aud_mst_e_sclk.hw, },
{ .hw = &aud_mst_f_sclk.hw, },
{ .fw_name = "slv_sclk0", },
{ .fw_name = "slv_sclk1", },
{ .fw_name = "slv_sclk2", },
{ .fw_name = "slv_sclk3", },
{ .fw_name = "slv_sclk4", },
{ .fw_name = "slv_sclk5", },
{ .fw_name = "slv_sclk6", },
{ .fw_name = "slv_sclk7", },
{ .fw_name = "slv_sclk8", },
{ .fw_name = "slv_sclk9", },
};
#define AUD_TDM_SCLK_MUX(_name, _reg) \
AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24, \
CLK_MUX_ROUND_CLOSEST, \
tdm_sclk_parent_names, 0)
tdm_sclk_parent_data, 0)
static AUD_TDM_SCLK_MUX(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_MUX(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@ -310,7 +337,7 @@ static AUD_TDM_SCLK_MUX(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
#define AUD_TDM_SCLK_PRE_EN(_name, _reg) \
AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31, \
"aud_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT)
aud_tdm##_name##_sclk_sel, CLK_SET_RATE_PARENT)
static AUD_TDM_SCLK_PRE_EN(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_PRE_EN(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@ -322,7 +349,7 @@ static AUD_TDM_SCLK_PRE_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
#define AUD_TDM_SCLK_POST_EN(_name, _reg) \
AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30, \
"aud_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT)
aud_tdm##_name##_sclk_pre_en, CLK_SET_RATE_PARENT)
static AUD_TDM_SCLK_POST_EN(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_POST_EN(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@ -344,8 +371,9 @@ static AUD_TDM_SCLK_POST_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
.hw.init = &(struct clk_init_data) { \
.name = "aud_tdm"#_name"_sclk", \
.ops = &meson_clk_phase_ops, \
.parent_names = (const char *[]) \
{ "aud_tdm"#_name"_sclk_post_en" }, \
.parent_hws = (const struct clk_hw *[]) { \
&aud_tdm##_name##_sclk_post_en.hw \
}, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT, \
}, \
@ -359,19 +387,29 @@ static AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
static const char * const tdm_lrclk_parent_names[] = {
"aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
"aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
"aud_slv_lrclk0", "aud_slv_lrclk1", "aud_slv_lrclk2",
"aud_slv_lrclk3", "aud_slv_lrclk4", "aud_slv_lrclk5",
"aud_slv_lrclk6", "aud_slv_lrclk7", "aud_slv_lrclk8",
"aud_slv_lrclk9"
static const struct clk_parent_data tdm_lrclk_parent_data[] = {
{ .hw = &aud_mst_a_lrclk.hw, },
{ .hw = &aud_mst_b_lrclk.hw, },
{ .hw = &aud_mst_c_lrclk.hw, },
{ .hw = &aud_mst_d_lrclk.hw, },
{ .hw = &aud_mst_e_lrclk.hw, },
{ .hw = &aud_mst_f_lrclk.hw, },
{ .fw_name = "slv_lrclk0", },
{ .fw_name = "slv_lrclk1", },
{ .fw_name = "slv_lrclk2", },
{ .fw_name = "slv_lrclk3", },
{ .fw_name = "slv_lrclk4", },
{ .fw_name = "slv_lrclk5", },
{ .fw_name = "slv_lrclk6", },
{ .fw_name = "slv_lrclk7", },
{ .fw_name = "slv_lrclk8", },
{ .fw_name = "slv_lrclk9", },
};
#define AUD_TDM_LRLCK(_name, _reg) \
AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
CLK_MUX_ROUND_CLOSEST, \
tdm_lrclk_parent_names, 0)
#define AUD_TDM_LRLCK(_name, _reg) \
AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
CLK_MUX_ROUND_CLOSEST, \
tdm_lrclk_parent_data, 0)
static AUD_TDM_LRLCK(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_LRLCK(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@ -386,39 +424,51 @@ static AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
AUD_MUX(tdm_##_name, _reg, 0x7, _shift, 0, _parents, \
CLK_SET_RATE_NO_REPARENT)
static const char * const mclk_pad_ctrl_parent_names[] = {
"aud_mst_a_mclk", "aud_mst_b_mclk", "aud_mst_c_mclk",
"aud_mst_d_mclk", "aud_mst_e_mclk", "aud_mst_f_mclk",
static const struct clk_parent_data mclk_pad_ctrl_parent_data[] = {
{ .hw = &aud_mst_a_mclk.hw },
{ .hw = &aud_mst_b_mclk.hw },
{ .hw = &aud_mst_c_mclk.hw },
{ .hw = &aud_mst_d_mclk.hw },
{ .hw = &aud_mst_e_mclk.hw },
{ .hw = &aud_mst_f_mclk.hw },
};
static AUD_TDM_PAD_CTRL(mclk_pad_0, AUDIO_MST_PAD_CTRL0, 0,
mclk_pad_ctrl_parent_names);
mclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(mclk_pad_1, AUDIO_MST_PAD_CTRL0, 4,
mclk_pad_ctrl_parent_names);
mclk_pad_ctrl_parent_data);
static const char * const lrclk_pad_ctrl_parent_names[] = {
"aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
"aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
{ .hw = &aud_mst_a_lrclk.hw },
{ .hw = &aud_mst_b_lrclk.hw },
{ .hw = &aud_mst_c_lrclk.hw },
{ .hw = &aud_mst_d_lrclk.hw },
{ .hw = &aud_mst_e_lrclk.hw },
{ .hw = &aud_mst_f_lrclk.hw },
};
static AUD_TDM_PAD_CTRL(lrclk_pad_0, AUDIO_MST_PAD_CTRL1, 16,
lrclk_pad_ctrl_parent_names);
lrclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(lrclk_pad_1, AUDIO_MST_PAD_CTRL1, 20,
lrclk_pad_ctrl_parent_names);
lrclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(lrclk_pad_2, AUDIO_MST_PAD_CTRL1, 24,
lrclk_pad_ctrl_parent_names);
lrclk_pad_ctrl_parent_data);
static const char * const sclk_pad_ctrl_parent_names[] = {
"aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
"aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
static const struct clk_parent_data sclk_pad_ctrl_parent_data[] = {
{ .hw = &aud_mst_a_sclk.hw },
{ .hw = &aud_mst_b_sclk.hw },
{ .hw = &aud_mst_c_sclk.hw },
{ .hw = &aud_mst_d_sclk.hw },
{ .hw = &aud_mst_e_sclk.hw },
{ .hw = &aud_mst_f_sclk.hw },
};
static AUD_TDM_PAD_CTRL(sclk_pad_0, AUDIO_MST_PAD_CTRL1, 0,
sclk_pad_ctrl_parent_names);
sclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(sclk_pad_1, AUDIO_MST_PAD_CTRL1, 4,
sclk_pad_ctrl_parent_names);
sclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(sclk_pad_2, AUDIO_MST_PAD_CTRL1, 8,
sclk_pad_ctrl_parent_names);
sclk_pad_ctrl_parent_data);
/*
* Array of all clocks provided by this provider
@ -868,54 +918,6 @@ static int devm_clk_get_enable(struct device *dev, char *id)
return 0;
}
static int axg_register_clk_hw_input(struct device *dev,
const char *name)
{
char *clk_name;
struct clk_hw *hw;
int err = 0;
clk_name = kasprintf(GFP_KERNEL, "aud_%s", name);
if (!clk_name)
return -ENOMEM;
hw = meson_clk_hw_register_input(dev, name, clk_name, 0);
if (IS_ERR(hw)) {
/* It is ok if an input clock is missing */
if (PTR_ERR(hw) == -ENOENT) {
dev_dbg(dev, "%s not provided", name);
} else {
err = PTR_ERR(hw);
if (err != -EPROBE_DEFER)
dev_err(dev, "failed to get %s clock", name);
}
}
kfree(clk_name);
return err;
}
static int axg_register_clk_hw_inputs(struct device *dev,
const char *basename,
unsigned int count)
{
char *name;
int i, ret;
for (i = 0; i < count; i++) {
name = kasprintf(GFP_KERNEL, "%s%d", basename, i);
if (!name)
return -ENOMEM;
ret = axg_register_clk_hw_input(dev, name);
kfree(name);
if (ret)
return ret;
}
return 0;
}
static const struct regmap_config axg_audio_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
@ -963,29 +965,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
return ret;
}
/* Register the peripheral input clock */
hw = meson_clk_hw_register_input(dev, "pclk", "audio_pclk", 0);
if (IS_ERR(hw))
return PTR_ERR(hw);
/* Register optional input master clocks */
ret = axg_register_clk_hw_inputs(dev, "mst_in",
AUD_MST_IN_COUNT);
if (ret)
return ret;
/* Register optional input slave sclks */
ret = axg_register_clk_hw_inputs(dev, "slv_sclk",
AUD_SLV_SCLK_COUNT);
if (ret)
return ret;
/* Register optional input slave lrclks */
ret = axg_register_clk_hw_inputs(dev, "slv_lrclk",
AUD_SLV_LRCLK_COUNT);
if (ret)
return ret;
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < ARRAY_SIZE(aud_clk_regmaps); i++)
aud_clk_regmaps[i]->map = map;

View File

@ -14,7 +14,6 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-input.h"
#include "clk-regmap.h"
#include "clk-pll.h"
#include "clk-mpll.h"
@ -59,7 +58,9 @@ static struct clk_regmap axg_fixed_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@ -74,7 +75,9 @@ static struct clk_regmap axg_fixed_pll = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fixed_pll_dco.hw
},
.num_parents = 1,
/*
* This clock won't ever change at runtime so
@ -114,7 +117,9 @@ static struct clk_regmap axg_sys_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@ -129,7 +134,9 @@ static struct clk_regmap axg_sys_pll = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "sys_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sys_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -215,7 +222,9 @@ static struct clk_regmap axg_gp0_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@ -230,7 +239,9 @@ static struct clk_regmap axg_gp0_pll = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "gp0_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_gp0_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -284,7 +295,9 @@ static struct clk_regmap axg_hifi_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "hifi_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@ -299,7 +312,9 @@ static struct clk_regmap axg_hifi_pll = {
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "hifi_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_hifi_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -311,7 +326,7 @@ static struct clk_fixed_factor axg_fclk_div2_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@ -324,7 +339,9 @@ static struct clk_regmap axg_fclk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div2_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div2_div.hw
},
.num_parents = 1,
.flags = CLK_IS_CRITICAL,
},
@ -336,7 +353,7 @@ static struct clk_fixed_factor axg_fclk_div3_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@ -349,7 +366,9 @@ static struct clk_regmap axg_fclk_div3 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div3_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div3_div.hw
},
.num_parents = 1,
/*
* FIXME:
@ -372,7 +391,7 @@ static struct clk_fixed_factor axg_fclk_div4_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@ -385,7 +404,9 @@ static struct clk_regmap axg_fclk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div4_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div4_div.hw
},
.num_parents = 1,
},
};
@ -396,7 +417,7 @@ static struct clk_fixed_factor axg_fclk_div5_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@ -409,7 +430,9 @@ static struct clk_regmap axg_fclk_div5 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div5_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div5_div.hw
},
.num_parents = 1,
},
};
@ -420,7 +443,9 @@ static struct clk_fixed_factor axg_fclk_div7_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fixed_pll.hw
},
.num_parents = 1,
},
};
@ -433,7 +458,9 @@ static struct clk_regmap axg_fclk_div7 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div7_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div7_div.hw
},
.num_parents = 1,
},
};
@ -447,7 +474,9 @@ static struct clk_regmap axg_mpll_prediv = {
.hw.init = &(struct clk_init_data){
.name = "mpll_prediv",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fixed_pll.hw
},
.num_parents = 1,
},
};
@ -480,7 +509,9 @@ static struct clk_regmap axg_mpll0_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
.parent_names = (const char *[]){ "mpll_prediv" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll_prediv.hw
},
.num_parents = 1,
},
};
@ -493,7 +524,9 @@ static struct clk_regmap axg_mpll0 = {
.hw.init = &(struct clk_init_data){
.name = "mpll0",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpll0_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -527,7 +560,9 @@ static struct clk_regmap axg_mpll1_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
.parent_names = (const char *[]){ "mpll_prediv" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll_prediv.hw
},
.num_parents = 1,
},
};
@ -540,7 +575,9 @@ static struct clk_regmap axg_mpll1 = {
.hw.init = &(struct clk_init_data){
.name = "mpll1",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpll1_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll1_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -579,7 +616,9 @@ static struct clk_regmap axg_mpll2_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
.parent_names = (const char *[]){ "mpll_prediv" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll_prediv.hw
},
.num_parents = 1,
},
};
@ -592,7 +631,9 @@ static struct clk_regmap axg_mpll2 = {
.hw.init = &(struct clk_init_data){
.name = "mpll2",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpll2_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll2_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -626,7 +667,9 @@ static struct clk_regmap axg_mpll3_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll3_div",
.ops = &meson_clk_mpll_ops,
.parent_names = (const char *[]){ "mpll_prediv" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll_prediv.hw
},
.num_parents = 1,
},
};
@ -639,7 +682,9 @@ static struct clk_regmap axg_mpll3 = {
.hw.init = &(struct clk_init_data){
.name = "mpll3",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpll3_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll3_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -702,7 +747,9 @@ static struct clk_regmap axg_pcie_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@ -717,7 +764,9 @@ static struct clk_regmap axg_pcie_pll_od = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_od",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "pcie_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_pcie_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -733,7 +782,9 @@ static struct clk_regmap axg_pcie_pll = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "pcie_pll_od" },
.parent_hws = (const struct clk_hw *[]) {
&axg_pcie_pll_od.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -750,7 +801,7 @@ static struct clk_regmap axg_pcie_mux = {
.hw.init = &(struct clk_init_data){
.name = "pcie_mux",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "pcie_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_pcie_pll.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -767,7 +818,7 @@ static struct clk_regmap axg_pcie_ref = {
.hw.init = &(struct clk_init_data){
.name = "pcie_ref",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "pcie_mux" },
.parent_hws = (const struct clk_hw *[]) { &axg_pcie_mux.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -781,7 +832,7 @@ static struct clk_regmap axg_pcie_cml_en0 = {
.hw.init = &(struct clk_init_data) {
.name = "pcie_cml_en0",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "pcie_ref" },
.parent_hws = (const struct clk_hw *[]) { &axg_pcie_ref.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@ -796,16 +847,21 @@ static struct clk_regmap axg_pcie_cml_en1 = {
.hw.init = &(struct clk_init_data) {
.name = "pcie_cml_en1",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "pcie_ref" },
.parent_hws = (const struct clk_hw *[]) { &axg_pcie_ref.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
static const char * const clk81_parent_names[] = {
IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
"fclk_div3", "fclk_div5"
static const struct clk_parent_data clk81_parent_data[] = {
{ .fw_name = "xtal", },
{ .hw = &axg_fclk_div7.hw },
{ .hw = &axg_mpll1.hw },
{ .hw = &axg_mpll2.hw },
{ .hw = &axg_fclk_div4.hw },
{ .hw = &axg_fclk_div3.hw },
{ .hw = &axg_fclk_div5.hw },
};
static struct clk_regmap axg_mpeg_clk_sel = {
@ -818,8 +874,8 @@ static struct clk_regmap axg_mpeg_clk_sel = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = clk81_parent_names,
.num_parents = ARRAY_SIZE(clk81_parent_names),
.parent_data = clk81_parent_data,
.num_parents = ARRAY_SIZE(clk81_parent_data),
},
};
@ -832,7 +888,9 @@ static struct clk_regmap axg_mpeg_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "mpeg_clk_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpeg_clk_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -846,15 +904,20 @@ static struct clk_regmap axg_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "clk81",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpeg_clk_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpeg_clk_div.hw
},
.num_parents = 1,
.flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
},
};
static const char * const axg_sd_emmc_clk0_parent_names[] = {
IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
static const struct clk_parent_data axg_sd_emmc_clk0_parent_data[] = {
{ .fw_name = "xtal", },
{ .hw = &axg_fclk_div2.hw },
{ .hw = &axg_fclk_div3.hw },
{ .hw = &axg_fclk_div5.hw },
{ .hw = &axg_fclk_div7.hw },
/*
* Following these parent clocks, we should also have had mpll2, mpll3
* and gp0_pll but these clocks are too precious to be used here. All
@ -873,8 +936,8 @@ static struct clk_regmap axg_sd_emmc_b_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = axg_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
.parent_data = axg_sd_emmc_clk0_parent_data,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@ -889,7 +952,9 @@ static struct clk_regmap axg_sd_emmc_b_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sd_emmc_b_clk0_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -903,7 +968,9 @@ static struct clk_regmap axg_sd_emmc_b_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_b_clk0",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sd_emmc_b_clk0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -919,8 +986,8 @@ static struct clk_regmap axg_sd_emmc_c_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = axg_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
.parent_data = axg_sd_emmc_clk0_parent_data,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@ -935,7 +1002,9 @@ static struct clk_regmap axg_sd_emmc_c_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sd_emmc_c_clk0_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -949,7 +1018,9 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_c_clk0",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sd_emmc_c_clk0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -957,9 +1028,18 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
9, 10, 11, 13, 14, };
static const char * const gen_clk_parent_names[] = {
IN_PREFIX "xtal", "hifi_pll", "mpll0", "mpll1", "mpll2", "mpll3",
"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
static const struct clk_parent_data gen_clk_parent_data[] = {
{ .fw_name = "xtal", },
{ .hw = &axg_hifi_pll.hw },
{ .hw = &axg_mpll0.hw },
{ .hw = &axg_mpll1.hw },
{ .hw = &axg_mpll2.hw },
{ .hw = &axg_mpll3.hw },
{ .hw = &axg_fclk_div4.hw },
{ .hw = &axg_fclk_div3.hw },
{ .hw = &axg_fclk_div5.hw },
{ .hw = &axg_fclk_div7.hw },
{ .hw = &axg_gp0_pll.hw },
};
static struct clk_regmap axg_gen_clk_sel = {
@ -978,8 +1058,8 @@ static struct clk_regmap axg_gen_clk_sel = {
* hifi_pll, mpll0, mpll1, mpll2, mpll3, fdiv4,
* fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll
*/
.parent_names = gen_clk_parent_names,
.num_parents = ARRAY_SIZE(gen_clk_parent_names),
.parent_data = gen_clk_parent_data,
.num_parents = ARRAY_SIZE(gen_clk_parent_data),
},
};
@ -992,7 +1072,9 @@ static struct clk_regmap axg_gen_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "gen_clk_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "gen_clk_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_gen_clk_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -1006,12 +1088,17 @@ static struct clk_regmap axg_gen_clk = {
.hw.init = &(struct clk_init_data){
.name = "gen_clk",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "gen_clk_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_gen_clk_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
#define MESON_GATE(_name, _reg, _bit) \
MESON_PCLK(_name, _reg, _bit, &axg_clk81.hw)
/* Everything Else (EE) domain gates */
static MESON_GATE(axg_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(axg_audio_locker, HHI_GCLK_MPEG0, 2);

View File

@ -0,0 +1,73 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (c) 2019 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include "clk-regmap.h"
#include "clk-cpu-dyndiv.h"
static inline struct meson_clk_cpu_dyndiv_data *
meson_clk_cpu_dyndiv_data(struct clk_regmap *clk)
{
return (struct meson_clk_cpu_dyndiv_data *)clk->data;
}
static unsigned long meson_clk_cpu_dyndiv_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
return divider_recalc_rate(hw, prate,
meson_parm_read(clk->map, &data->div),
NULL, 0, data->div.width);
}
static long meson_clk_cpu_dyndiv_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *prate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
return divider_round_rate(hw, rate, prate, NULL, data->div.width, 0);
}
static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
unsigned int val;
int ret;
ret = divider_get_val(rate, parent_rate, NULL, data->div.width, 0);
if (ret < 0)
return ret;
val = (unsigned int)ret << data->div.shift;
/* Write the SYS_CPU_DYN_ENABLE bit before changing the divider */
meson_parm_write(clk->map, &data->dyn, 1);
/* Update the divider while removing the SYS_CPU_DYN_ENABLE bit */
return regmap_update_bits(clk->map, data->div.reg_off,
SETPMASK(data->div.width, data->div.shift) |
SETPMASK(data->dyn.width, data->dyn.shift),
val);
};
const struct clk_ops meson_clk_cpu_dyndiv_ops = {
.recalc_rate = meson_clk_cpu_dyndiv_recalc_rate,
.round_rate = meson_clk_cpu_dyndiv_round_rate,
.set_rate = meson_clk_cpu_dyndiv_set_rate,
};
EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops);
MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
#ifndef __MESON_CLK_CPU_DYNDIV_H
#define __MESON_CLK_CPU_DYNDIV_H
#include <linux/clk-provider.h>
#include "parm.h"
struct meson_clk_cpu_dyndiv_data {
struct parm div;
struct parm dyn;
};
extern const struct clk_ops meson_clk_cpu_dyndiv_ops;
#endif /* __MESON_CLK_CPU_DYNDIV_H */

View File

@ -1,49 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (c) 2018 BayLibre, SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/module.h>
#include "clk-input.h"
static const struct clk_ops meson_clk_no_ops = {};
struct clk_hw *meson_clk_hw_register_input(struct device *dev,
const char *of_name,
const char *clk_name,
unsigned long flags)
{
struct clk *parent_clk = devm_clk_get(dev, of_name);
struct clk_init_data init;
const char *parent_name;
struct clk_hw *hw;
int ret;
if (IS_ERR(parent_clk))
return (struct clk_hw *)parent_clk;
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return ERR_PTR(-ENOMEM);
parent_name = __clk_get_name(parent_clk);
init.name = clk_name;
init.ops = &meson_clk_no_ops;
init.flags = flags;
init.parent_names = &parent_name;
init.num_parents = 1;
hw->init = &init;
ret = devm_clk_hw_register(dev, hw);
return ret ? ERR_PTR(ret) : hw;
}
EXPORT_SYMBOL_GPL(meson_clk_hw_register_input);
MODULE_DESCRIPTION("Amlogic clock input helper");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL v2");

View File

@ -1,19 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 BayLibre, SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*/
#ifndef __MESON_CLK_INPUT_H
#define __MESON_CLK_INPUT_H
#include <linux/clk-provider.h>
struct device;
struct clk_hw *meson_clk_hw_register_input(struct device *dev,
const char *of_name,
const char *clk_name,
unsigned long flags);
#endif /* __MESON_CLK_INPUT_H */

View File

@ -111,7 +111,7 @@ clk_get_regmap_mux_data(struct clk_regmap *clk)
extern const struct clk_ops clk_regmap_mux_ops;
extern const struct clk_ops clk_regmap_mux_ro_ops;
#define __MESON_GATE(_name, _reg, _bit, _ops) \
#define __MESON_PCLK(_name, _reg, _bit, _ops, _pname) \
struct clk_regmap _name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (_reg), \
@ -120,15 +120,15 @@ struct clk_regmap _name = { \
.hw.init = &(struct clk_init_data) { \
.name = #_name, \
.ops = _ops, \
.parent_names = (const char *[]){ "clk81" }, \
.parent_hws = (const struct clk_hw *[]) { _pname }, \
.num_parents = 1, \
.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
}, \
}
#define MESON_GATE(_name, _reg, _bit) \
__MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ops)
#define MESON_PCLK(_name, _reg, _bit, _pname) \
__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pname)
#define MESON_GATE_RO(_name, _reg, _bit) \
__MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ro_ops)
#define MESON_PCLK_RO(_name, _reg, _bit, _pname) \
__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pname)
#endif /* __CLK_REGMAP_H */

View File

@ -18,8 +18,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
#define IN_PREFIX "ao-in-"
/*
* AO Configuration Clock registers offsets
* Register offsets from the data sheet must be multiplied by 4.
@ -51,7 +49,9 @@ static struct clk_regmap g12a_aoclk_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "g12a_ao_" #_name, \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "mpeg-clk", \
}, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@ -81,7 +81,9 @@ static struct clk_regmap g12a_aoclk_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@ -106,7 +108,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_pre = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_pre",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "cts_oscin" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cts_oscin.hw
},
.num_parents = 1,
},
};
@ -143,7 +147,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_div",
.ops = &meson_clk_dualdiv_ops,
.parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_pre" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_32k_by_oscin_pre.hw
},
.num_parents = 1,
},
};
@ -158,8 +164,10 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_sel = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_div",
"g12a_ao_32k_by_oscin_pre" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_32k_by_oscin_div.hw,
&g12a_aoclk_32k_by_oscin_pre.hw,
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -173,7 +181,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_sel" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_32k_by_oscin_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -189,7 +199,9 @@ static struct clk_regmap g12a_aoclk_cec_pre = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_pre",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "cts_oscin" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cts_oscin.hw
},
.num_parents = 1,
},
};
@ -226,7 +238,9 @@ static struct clk_regmap g12a_aoclk_cec_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_div",
.ops = &meson_clk_dualdiv_ops,
.parent_names = (const char *[]){ "g12a_ao_cec_pre" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cec_pre.hw
},
.num_parents = 1,
},
};
@ -241,8 +255,10 @@ static struct clk_regmap g12a_aoclk_cec_sel = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "g12a_ao_cec_div",
"g12a_ao_cec_pre" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cec_div.hw,
&g12a_aoclk_cec_pre.hw,
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -256,7 +272,9 @@ static struct clk_regmap g12a_aoclk_cec = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "g12a_ao_cec_sel" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cec_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -272,8 +290,10 @@ static struct clk_regmap g12a_aoclk_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "g12a_ao_32k_by_oscin",
IN_PREFIX "ext_32k-0" },
.parent_data = (const struct clk_parent_data []) {
{ .hw = &g12a_aoclk_32k_by_oscin.hw },
{ .fw_name = "ext-32k-0", },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -289,8 +309,10 @@ static struct clk_regmap g12a_aoclk_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
"g12a_ao_cts_rtc_oscin"},
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "mpeg-clk", },
{ .hw = &g12a_aoclk_cts_rtc_oscin.hw },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -305,8 +327,10 @@ static struct clk_regmap g12a_aoclk_saradc_mux = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_mux",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal",
"g12a_ao_clk81" },
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", },
{ .hw = &g12a_aoclk_clk81.hw },
},
.num_parents = 2,
},
};
@ -320,7 +344,9 @@ static struct clk_regmap g12a_aoclk_saradc_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "g12a_ao_saradc_mux" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_saradc_mux.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -334,7 +360,9 @@ static struct clk_regmap g12a_aoclk_saradc_gate = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_gate",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "g12a_ao_saradc_div" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_saradc_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -417,12 +445,6 @@ static const struct clk_hw_onecell_data g12a_aoclk_onecell_data = {
.num = NR_CLKS,
};
static const struct meson_aoclk_input g12a_aoclk_inputs[] = {
{ .name = "xtal", .required = true },
{ .name = "mpeg-clk", .required = true },
{ .name = "ext-32k-0", .required = false },
};
static const struct meson_aoclk_data g12a_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(g12a_aoclk_reset),
@ -430,9 +452,6 @@ static const struct meson_aoclk_data g12a_aoclkc_data = {
.num_clks = ARRAY_SIZE(g12a_aoclk_regmap),
.clks = g12a_aoclk_regmap,
.hw_data = &g12a_aoclk_onecell_data,
.inputs = g12a_aoclk_inputs,
.num_inputs = ARRAY_SIZE(g12a_aoclk_inputs),
.input_prefix = IN_PREFIX,
};
static const struct of_device_id g12a_aoclkc_match_table[] = {

File diff suppressed because it is too large Load Diff

View File

@ -216,7 +216,6 @@
#define CLKID_CPUB_CLK_DYN1_DIV 221
#define CLKID_CPUB_CLK_DYN1 222
#define CLKID_CPUB_CLK_DYN 223
#define CLKID_CPUB_CLK 224
#define CLKID_CPUB_CLK_DIV16_EN 225
#define CLKID_CPUB_CLK_DIV16 226
#define CLKID_CPUB_CLK_DIV2 227

View File

@ -11,8 +11,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
#define IN_PREFIX "ao-in-"
/* AO Configuration Clock registers offsets */
#define AO_RTI_PWR_CNTL_REG1 0x0c
#define AO_RTI_PWR_CNTL_REG0 0x10
@ -31,7 +29,9 @@ static struct clk_regmap _name##_ao = { \
.hw.init = &(struct clk_init_data) { \
.name = #_name "_ao", \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "mpeg-clk", \
}, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@ -52,7 +52,9 @@ static struct clk_regmap ao_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "ao_cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@ -65,7 +67,7 @@ static struct clk_regmap ao_32k_pre = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_pre",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "ao_cts_oscin" },
.parent_hws = (const struct clk_hw *[]) { &ao_cts_oscin.hw },
.num_parents = 1,
},
};
@ -112,7 +114,7 @@ static struct clk_regmap ao_32k_div = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_div",
.ops = &meson_clk_dualdiv_ops,
.parent_names = (const char *[]){ "ao_32k_pre" },
.parent_hws = (const struct clk_hw *[]) { &ao_32k_pre.hw },
.num_parents = 1,
},
};
@ -127,8 +129,10 @@ static struct clk_regmap ao_32k_sel = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "ao_32k_div",
"ao_32k_pre" },
.parent_hws = (const struct clk_hw *[]) {
&ao_32k_div.hw,
&ao_32k_pre.hw
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -142,7 +146,7 @@ static struct clk_regmap ao_32k = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "ao_32k_sel" },
.parent_hws = (const struct clk_hw *[]) { &ao_32k_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@ -159,10 +163,12 @@ static struct clk_regmap ao_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ IN_PREFIX "ext-32k-0",
IN_PREFIX "ext-32k-1",
IN_PREFIX "ext-32k-2",
"ao_32k" },
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "ext-32k-0", },
{ .fw_name = "ext-32k-1", },
{ .fw_name = "ext-32k-2", },
{ .hw = &ao_32k.hw },
},
.num_parents = 4,
.flags = CLK_SET_RATE_PARENT,
},
@ -178,8 +184,10 @@ static struct clk_regmap ao_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
"ao_cts_rtc_oscin" },
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "mpeg-clk", },
{ .hw = &ao_cts_rtc_oscin.hw },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -208,8 +216,10 @@ static struct clk_regmap ao_cts_cec = {
* Until CCF gets fixed, adding this fake parent that won't
* ever be registered should work around the problem
*/
.parent_names = (const char *[]){ "fixme",
"ao_cts_rtc_oscin" },
.parent_data = (const struct clk_parent_data []) {
{ .name = "fixme", .index = -1, },
{ .hw = &ao_cts_rtc_oscin.hw },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@ -261,14 +271,6 @@ static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
.num = NR_CLKS,
};
static const struct meson_aoclk_input gxbb_aoclk_inputs[] = {
{ .name = "xtal", .required = true, },
{ .name = "mpeg-clk", .required = true, },
{. name = "ext-32k-0", .required = false, },
{. name = "ext-32k-1", .required = false, },
{. name = "ext-32k-2", .required = false, },
};
static const struct meson_aoclk_data gxbb_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(gxbb_aoclk_reset),
@ -276,9 +278,6 @@ static const struct meson_aoclk_data gxbb_aoclkc_data = {
.num_clks = ARRAY_SIZE(gxbb_aoclk),
.clks = gxbb_aoclk,
.hw_data = &gxbb_aoclk_onecell_data,
.inputs = gxbb_aoclk_inputs,
.num_inputs = ARRAY_SIZE(gxbb_aoclk_inputs),
.input_prefix = IN_PREFIX,
};
static const struct of_device_id gxbb_aoclkc_match_table[] = {

File diff suppressed because it is too large Load Diff

View File

@ -17,8 +17,6 @@
#include <linux/slab.h>
#include "meson-aoclk.h"
#include "clk-input.h"
static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
@ -33,37 +31,6 @@ static const struct reset_control_ops meson_aoclk_reset_ops = {
.reset = meson_aoclk_do_reset,
};
static int meson_aoclkc_register_inputs(struct device *dev,
struct meson_aoclk_data *data)
{
struct clk_hw *hw;
char *str;
int i;
for (i = 0; i < data->num_inputs; i++) {
const struct meson_aoclk_input *in = &data->inputs[i];
str = kasprintf(GFP_KERNEL, "%s%s", data->input_prefix,
in->name);
if (!str)
return -ENOMEM;
hw = meson_clk_hw_register_input(dev, in->name, str, 0);
kfree(str);
if (IS_ERR(hw)) {
if (!in->required && PTR_ERR(hw) == -ENOENT)
continue;
else if (PTR_ERR(hw) != -EPROBE_DEFER)
dev_err(dev, "failed to register input %s\n",
in->name);
return PTR_ERR(hw);
}
}
return 0;
}
int meson_aoclkc_probe(struct platform_device *pdev)
{
struct meson_aoclk_reset_controller *rstc;
@ -86,10 +53,6 @@ int meson_aoclkc_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
}
ret = meson_aoclkc_register_inputs(dev, data);
if (ret)
return ret;
/* Reset Controller */
rstc->data = data;
rstc->regmap = regmap;

View File

@ -18,20 +18,12 @@
#include "clk-regmap.h"
struct meson_aoclk_input {
const char *name;
bool required;
};
struct meson_aoclk_data {
const unsigned int reset_reg;
const int num_reset;
const unsigned int *reset;
const int num_clks;
struct clk_regmap **clks;
const int num_inputs;
const struct meson_aoclk_input *inputs;
const char *input_prefix;
const struct clk_hw_onecell_data *hw_data;
};

View File

@ -10,7 +10,6 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "clk-input.h"
#include "clk-regmap.h"
#include "meson-eeclk.h"
@ -18,7 +17,6 @@ int meson_eeclkc_probe(struct platform_device *pdev)
{
const struct meson_eeclkc_data *data;
struct device *dev = &pdev->dev;
struct clk_hw *input;
struct regmap *map;
int ret, i;
@ -37,14 +35,6 @@ int meson_eeclkc_probe(struct platform_device *pdev)
if (data->init_count)
regmap_multi_reg_write(map, data->init_regs, data->init_count);
input = meson_clk_hw_register_input(dev, "xtal", IN_PREFIX "xtal", 0);
if (IS_ERR(input)) {
ret = PTR_ERR(input);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get input clock");
return ret;
}
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < data->regmap_clk_num; i++)
data->regmap_clks[i]->map = map;

View File

@ -10,8 +10,6 @@
#include <linux/clk-provider.h>
#include "clk-regmap.h"
#define IN_PREFIX "ee-in-"
struct platform_device;
struct meson_eeclkc_data {

File diff suppressed because it is too large Load Diff

View File

@ -137,5 +137,6 @@
#define CLKID_VDEC_HEVC 207
#define CLKID_VDEC_HEVCF 210
#define CLKID_TS 212
#define CLKID_CPUB_CLK 224
#endif /* __G12A_CLKC_H */

View File

@ -817,6 +817,7 @@ unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
unsigned int index);
int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *new_parent);
unsigned int __clk_get_enable_count(struct clk *clk);
unsigned long clk_hw_get_rate(const struct clk_hw *hw);
unsigned long __clk_get_flags(struct clk *clk);