Update for meson clocks targeted at v4.21
- Add GX video clocks - Switch to HHI syscon for meson8b - Fix meson8b cpu clock - Add support for meson8b CPU scaling - Add Meson8b CPU post-dividers clocks -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJb+AvnAAoJEHfc29rIyEnRhgEP/3Q4h0eBkObRikKUUFs104vb Yd+n2AWNaM54CxMOVJancOxRZGo5/BHV+TT0718sIjEZDzMhm88kkVXNSUMegGXz 0Xt1T10clMlftzqCos6Be6Rnd9gUl2xUp0urZw965DBIGkelrV2CSb+FdRJb9OWE CutcdQuSrF+nf3qe3W9upC7vbcjOHT5KOZfFdLpjgFZI2+5X+4SyErW1PlSJHziR NpEklJxL0T2FdKYu/rPm245FFGd04CV4b21YVVclF/yEtERO6cVIfVVSfvr94Tz4 hOiRoM1Bb0GBGjovubKCFrEbtZAI7CgdPOLqvyYsFJNpbAKTCeCQahB9SO4pJ6X+ xV9KOylnvmT5I8fTvJ+6/G2KsepuR/9WEzyCaP1JXwRVBd5OwyLjKTzrSExabhnp 2Njg8krfcxZpqRzq9gGu6FHv9edj30K+N/zxmBa0aW9VCb7g29m8r0GTUAB4pXIM fWBCBGt4Gay5mXQZcFvyAhkeh8XKYVcd26Z+68E48UhXUCcccuFdLU48eCKdG9vx ewEUNLsu+G44MQjZrB4wtw04mv3hALjUabnZzWoTDfVFLNJxYSVjXThsq5eZ/B8a 4CBvWfJ0tv4jpW6cp6Xqp2fWIZKRgU8841GPZcK49gyZ9CLJFdi8IhsLYAQfO+5E O0R0FwyO0IjJCazScyJj =JJGs -----END PGP SIGNATURE----- Merge tag 'meson-clk-4.21-1' of https://github.com/BayLibre/clk-meson into clk-meson Pull amlogic meson clk driver updates from Neil Armstrong: - Add GX video clocks - Switch to HHI syscon for meson8b - Fix meson8b cpu clock - Add support for meson8b CPU scaling - Add Meson8b CPU post-dividers clocks * tag 'meson-clk-4.21-1' of https://github.com/BayLibre/clk-meson: clk: meson: meson8b: add the CPU clock post divider clocks clk: meson: meson8b: rename cpu_div2/cpu_div3 to cpu_in_div2/cpu_in_div3 clk: meson: clk-regmap: add read-only gate ops clk: meson: meson8b: allow changing the CPU clock tree clk: meson: meson8b: run from the XTAL when changing the CPU frequency clk: meson: meson8b: add support for more M/N values in sys_pll clk: meson: meson8b: mark the CPU clock as CLK_IS_CRITICAL clk: meson: meson8b: do not use cpu_div3 for cpu_scale_out_sel clk: meson: clk-pll: check if the clock is already enabled clk: meson: meson8b: fix the width of the cpu_scale_div clock clk: meson: meson8b: fix incorrect divider mapping in cpu_scale_table clk: meson: meson8b: use the HHI syscon if available dt-bindings: clock: meson8b: use the registers from the HHI syscon clk: meson-gxbb: Add video clocks dt-bindings: clk: meson-gxbb: Add Video clock bindings clk: meson-gxbb: Fix HDMI PLL for GXL SoCs clk: meson: Add vid_pll divider driver dt-bindings: clock: meson8b: export the CPU post dividers
This commit is contained in:
Коммит
4946166e46
|
@ -9,15 +9,13 @@ Required Properties:
|
|||
- "amlogic,meson8-clkc" for Meson8 (S802) SoCs
|
||||
- "amlogic,meson8b-clkc" for Meson8 (S805) SoCs
|
||||
- "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs
|
||||
- reg: it must be composed by two tuples:
|
||||
0) physical base address of the xtal register and length of memory
|
||||
mapped region.
|
||||
1) physical base address of the clock controller and length of memory
|
||||
mapped region.
|
||||
|
||||
- #clock-cells: should be 1.
|
||||
- #reset-cells: should be 1.
|
||||
|
||||
Parent node should have the following properties :
|
||||
- compatible: "amlogic,meson-hhi-sysctrl", "simple-mfd", "syscon"
|
||||
- reg: base address and size of the HHI system control register space.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. All available clocks are defined as
|
||||
preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be
|
||||
|
@ -30,9 +28,8 @@ device tree sources).
|
|||
|
||||
Example: Clock controller node:
|
||||
|
||||
clkc: clock-controller@c1104000 {
|
||||
clkc: clock-controller {
|
||||
compatible = "amlogic,meson8b-clkc";
|
||||
reg = <0xc1108000 0x4>, <0xc1104000 0x460>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Makefile for Meson specific clk
|
||||
#
|
||||
|
||||
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o
|
||||
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o vid-pll-div.o
|
||||
obj-$(CONFIG_COMMON_CLK_AMLOGIC_AUDIO) += clk-triphase.o sclk-div.o
|
||||
obj-$(CONFIG_COMMON_CLK_MESON_AO) += meson-aoclk.o
|
||||
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
|
||||
|
|
|
@ -200,11 +200,28 @@ static void meson_clk_pll_init(struct clk_hw *hw)
|
|||
}
|
||||
}
|
||||
|
||||
static int meson_clk_pll_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
|
||||
|
||||
if (meson_parm_read(clk->map, &pll->rst) ||
|
||||
!meson_parm_read(clk->map, &pll->en) ||
|
||||
!meson_parm_read(clk->map, &pll->l))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int meson_clk_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
|
||||
|
||||
/* do nothing if the PLL is already enabled */
|
||||
if (clk_hw_is_enabled(hw))
|
||||
return 0;
|
||||
|
||||
/* Make sure the pll is in reset */
|
||||
meson_parm_write(clk->map, &pll->rst, 1);
|
||||
|
||||
|
@ -288,10 +305,12 @@ const struct clk_ops meson_clk_pll_ops = {
|
|||
.recalc_rate = meson_clk_pll_recalc_rate,
|
||||
.round_rate = meson_clk_pll_round_rate,
|
||||
.set_rate = meson_clk_pll_set_rate,
|
||||
.is_enabled = meson_clk_pll_is_enabled,
|
||||
.enable = meson_clk_pll_enable,
|
||||
.disable = meson_clk_pll_disable
|
||||
};
|
||||
|
||||
const struct clk_ops meson_clk_pll_ro_ops = {
|
||||
.recalc_rate = meson_clk_pll_recalc_rate,
|
||||
.is_enabled = meson_clk_pll_is_enabled,
|
||||
};
|
||||
|
|
|
@ -50,6 +50,11 @@ const struct clk_ops clk_regmap_gate_ops = {
|
|||
};
|
||||
EXPORT_SYMBOL_GPL(clk_regmap_gate_ops);
|
||||
|
||||
const struct clk_ops clk_regmap_gate_ro_ops = {
|
||||
.is_enabled = clk_regmap_gate_is_enabled,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_regmap_gate_ro_ops);
|
||||
|
||||
static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long prate)
|
||||
{
|
||||
|
|
|
@ -51,6 +51,7 @@ clk_get_regmap_gate_data(struct clk_regmap *clk)
|
|||
}
|
||||
|
||||
extern const struct clk_ops clk_regmap_gate_ops;
|
||||
extern const struct clk_ops clk_regmap_gate_ro_ops;
|
||||
|
||||
/**
|
||||
* struct clk_regmap_div_data - regmap backed adjustable divider specific data
|
||||
|
|
|
@ -90,6 +90,11 @@ struct meson_clk_phase_data {
|
|||
int meson_clk_degrees_from_val(unsigned int val, unsigned int width);
|
||||
unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width);
|
||||
|
||||
struct meson_vid_pll_div_data {
|
||||
struct parm val;
|
||||
struct parm sel;
|
||||
};
|
||||
|
||||
#define MESON_GATE(_name, _reg, _bit) \
|
||||
struct clk_regmap _name = { \
|
||||
.data = &(struct clk_regmap_gate_data){ \
|
||||
|
@ -112,5 +117,6 @@ extern const struct clk_ops meson_clk_cpu_ops;
|
|||
extern const struct clk_ops meson_clk_mpll_ro_ops;
|
||||
extern const struct clk_ops meson_clk_mpll_ops;
|
||||
extern const struct clk_ops meson_clk_phase_ops;
|
||||
extern const struct clk_ops meson_vid_pll_div_ro_ops;
|
||||
|
||||
#endif /* __CLKC_H */
|
||||
|
|
|
@ -199,6 +199,52 @@ static struct clk_regmap gxbb_hdmi_pll_dco = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxl_hdmi_pll_dco = {
|
||||
.data = &(struct meson_clk_pll_data){
|
||||
.en = {
|
||||
.reg_off = HHI_HDMI_PLL_CNTL,
|
||||
.shift = 30,
|
||||
.width = 1,
|
||||
},
|
||||
.m = {
|
||||
.reg_off = HHI_HDMI_PLL_CNTL,
|
||||
.shift = 0,
|
||||
.width = 9,
|
||||
},
|
||||
.n = {
|
||||
.reg_off = HHI_HDMI_PLL_CNTL,
|
||||
.shift = 9,
|
||||
.width = 5,
|
||||
},
|
||||
.frac = {
|
||||
.reg_off = HHI_HDMI_PLL_CNTL2,
|
||||
.shift = 0,
|
||||
.width = 12,
|
||||
},
|
||||
.l = {
|
||||
.reg_off = HHI_HDMI_PLL_CNTL,
|
||||
.shift = 31,
|
||||
.width = 1,
|
||||
},
|
||||
.rst = {
|
||||
.reg_off = HHI_HDMI_PLL_CNTL,
|
||||
.shift = 28,
|
||||
.width = 1,
|
||||
},
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hdmi_pll_dco",
|
||||
.ops = &meson_clk_pll_ro_ops,
|
||||
.parent_names = (const char *[]){ "xtal" },
|
||||
.num_parents = 1,
|
||||
/*
|
||||
* Display directly handle hdmi pll registers ATM, we need
|
||||
* NOCACHE to keep our view of the clock as accurate as possible
|
||||
*/
|
||||
.flags = CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_hdmi_pll_od = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_HDMI_PLL_CNTL2,
|
||||
|
@ -1512,6 +1558,616 @@ static struct clk_regmap gxbb_vapb = {
|
|||
},
|
||||
};
|
||||
|
||||
/* Video Clocks */
|
||||
|
||||
static struct clk_regmap gxbb_vid_pll_div = {
|
||||
.data = &(struct meson_vid_pll_div_data){
|
||||
.val = {
|
||||
.reg_off = HHI_VID_PLL_CLK_DIV,
|
||||
.shift = 0,
|
||||
.width = 15,
|
||||
},
|
||||
.sel = {
|
||||
.reg_off = HHI_VID_PLL_CLK_DIV,
|
||||
.shift = 16,
|
||||
.width = 2,
|
||||
},
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vid_pll_div",
|
||||
.ops = &meson_vid_pll_div_ro_ops,
|
||||
.parent_names = (const char *[]){ "hdmi_pll" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
const char *gxbb_vid_pll_parent_names[] = { "vid_pll_div", "hdmi_pll" };
|
||||
|
||||
static struct clk_regmap gxbb_vid_pll_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VID_PLL_CLK_DIV,
|
||||
.mask = 0x1,
|
||||
.shift = 18,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vid_pll_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
/*
|
||||
* bit 18 selects from 2 possible parents:
|
||||
* vid_pll_div or hdmi_pll
|
||||
*/
|
||||
.parent_names = gxbb_vid_pll_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_vid_pll_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vid_pll = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_PLL_CLK_DIV,
|
||||
.bit_idx = 19,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vid_pll",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vid_pll_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
const char *gxbb_vclk_parent_names[] = {
|
||||
"vid_pll", "fclk_div4", "fclk_div3", "fclk_div5", "vid_pll",
|
||||
"fclk_div7", "mpll1",
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 16,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
/*
|
||||
* bits 16:18 selects from 8 possible parents:
|
||||
* vid_pll, fclk_div4, fclk_div3, fclk_div5,
|
||||
* vid_pll, fclk_div7, mp1
|
||||
*/
|
||||
.parent_names = gxbb_vclk_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_vclk_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.mask = 0x7,
|
||||
.shift = 16,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
/*
|
||||
* bits 16:18 selects from 8 possible parents:
|
||||
* vid_pll, fclk_div4, fclk_div3, fclk_div5,
|
||||
* vid_pll, fclk_div7, mp1
|
||||
*/
|
||||
.parent_names = gxbb_vclk_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_vclk_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk_input = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_DIV,
|
||||
.bit_idx = 16,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_input",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2_input = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_DIV,
|
||||
.bit_idx = 16,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_input",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk2_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VID_CLK_DIV,
|
||||
.shift = 0,
|
||||
.width = 8,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_names = (const char *[]){ "vclk_input" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_VIID_CLK_DIV,
|
||||
.shift = 0,
|
||||
.width = 8,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_names = (const char *[]){ "vclk2_input" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 19,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 19,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk2_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk_div1 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 0,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div1",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk_div2_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 1,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div2_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk_div4_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 2,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div4_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk_div6_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 3,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div6_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk_div12_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL,
|
||||
.bit_idx = 4,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk_div12_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2_div1 = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 0,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div1",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk2" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2_div2_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 1,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div2_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk2" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2_div4_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 2,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div4_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk2" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2_div6_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 3,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div6_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk2" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_vclk2_div12_en = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VIID_CLK_CNTL,
|
||||
.bit_idx = 4,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "vclk2_div12_en",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "vclk2" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor gxbb_vclk_div2 = {
|
||||
.mult = 1,
|
||||
.div = 2,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div2",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "vclk_div2_en" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor gxbb_vclk_div4 = {
|
||||
.mult = 1,
|
||||
.div = 4,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div4",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "vclk_div4_en" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor gxbb_vclk_div6 = {
|
||||
.mult = 1,
|
||||
.div = 6,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div6",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "vclk_div6_en" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor gxbb_vclk_div12 = {
|
||||
.mult = 1,
|
||||
.div = 12,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk_div12",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "vclk_div12_en" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor gxbb_vclk2_div2 = {
|
||||
.mult = 1,
|
||||
.div = 2,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div2",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "vclk2_div2_en" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor gxbb_vclk2_div4 = {
|
||||
.mult = 1,
|
||||
.div = 4,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div4",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "vclk2_div4_en" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor gxbb_vclk2_div6 = {
|
||||
.mult = 1,
|
||||
.div = 6,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div6",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "vclk2_div6_en" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor gxbb_vclk2_div12 = {
|
||||
.mult = 1,
|
||||
.div = 12,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "vclk2_div12",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "vclk2_div12_en" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
|
||||
const char *gxbb_cts_parent_names[] = {
|
||||
"vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
|
||||
"vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
|
||||
"vclk2_div6", "vclk2_div12"
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_cts_enci_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VID_CLK_DIV,
|
||||
.mask = 0xf,
|
||||
.shift = 28,
|
||||
.table = mux_table_cts_sel,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_enci_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = gxbb_cts_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_cts_encp_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VID_CLK_DIV,
|
||||
.mask = 0xf,
|
||||
.shift = 20,
|
||||
.table = mux_table_cts_sel,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_encp_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = gxbb_cts_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_cts_vdac_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_VIID_CLK_DIV,
|
||||
.mask = 0xf,
|
||||
.shift = 28,
|
||||
.table = mux_table_cts_sel,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cts_vdac_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = gxbb_cts_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
/* TOFIX: add support for cts_tcon */
|
||||
static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
|
||||
const char *gxbb_cts_hdmi_tx_parent_names[] = {
|
||||
"vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
|
||||
"vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
|
||||
"vclk2_div6", "vclk2_div12"
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_hdmi_tx_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_HDMI_CLK_CNTL,
|
||||
.mask = 0xf,
|
||||
.shift = 16,
|
||||
.table = mux_table_hdmi_tx_sel,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hdmi_tx_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
/*
|
||||
* bits 31:28 selects from 12 possible parents:
|
||||
* vclk_div1, vclk_div2, vclk_div4, vclk_div6, vclk_div12
|
||||
* vclk2_div1, vclk2_div2, vclk2_div4, vclk2_div6, vclk2_div12,
|
||||
* cts_tcon
|
||||
*/
|
||||
.parent_names = gxbb_cts_hdmi_tx_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_cts_hdmi_tx_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_cts_enci = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL2,
|
||||
.bit_idx = 0,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "cts_enci",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "cts_enci_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_cts_encp = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL2,
|
||||
.bit_idx = 2,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "cts_encp",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "cts_encp_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_cts_vdac = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL2,
|
||||
.bit_idx = 4,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "cts_vdac",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "cts_vdac_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_hdmi_tx = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_VID_CLK_CNTL2,
|
||||
.bit_idx = 5,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hdmi_tx",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "hdmi_tx_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
/* HDMI Clocks */
|
||||
|
||||
static const char * const gxbb_hdmi_parent_names[] = {
|
||||
"xtal", "fclk_div4", "fclk_div3", "fclk_div5"
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_hdmi_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_HDMI_CLK_CNTL,
|
||||
.mask = 0x3,
|
||||
.shift = 9,
|
||||
.flags = CLK_MUX_ROUND_CLOSEST,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hdmi_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = gxbb_hdmi_parent_names,
|
||||
.num_parents = ARRAY_SIZE(gxbb_hdmi_parent_names),
|
||||
.flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_hdmi_div = {
|
||||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_HDMI_CLK_CNTL,
|
||||
.shift = 0,
|
||||
.width = 7,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "hdmi_div",
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_names = (const char *[]){ "hdmi_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_GET_RATE_NOCACHE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap gxbb_hdmi = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_HDMI_CLK_CNTL,
|
||||
.bit_idx = 8,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data) {
|
||||
.name = "hdmi",
|
||||
.ops = &clk_regmap_gate_ops,
|
||||
.parent_names = (const char *[]){ "hdmi_div" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
},
|
||||
};
|
||||
|
||||
/* VDEC clocks */
|
||||
|
||||
static const char * const gxbb_vdec_parent_names[] = {
|
||||
|
@ -1923,6 +2579,46 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
|
|||
[CLKID_HDMI_PLL_OD2] = &gxbb_hdmi_pll_od2.hw,
|
||||
[CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
|
||||
[CLKID_GP0_PLL_DCO] = &gxbb_gp0_pll_dco.hw,
|
||||
[CLKID_VID_PLL_DIV] = &gxbb_vid_pll_div.hw,
|
||||
[CLKID_VID_PLL_SEL] = &gxbb_vid_pll_sel.hw,
|
||||
[CLKID_VID_PLL] = &gxbb_vid_pll.hw,
|
||||
[CLKID_VCLK_SEL] = &gxbb_vclk_sel.hw,
|
||||
[CLKID_VCLK2_SEL] = &gxbb_vclk2_sel.hw,
|
||||
[CLKID_VCLK_INPUT] = &gxbb_vclk_input.hw,
|
||||
[CLKID_VCLK2_INPUT] = &gxbb_vclk2_input.hw,
|
||||
[CLKID_VCLK_DIV] = &gxbb_vclk_div.hw,
|
||||
[CLKID_VCLK2_DIV] = &gxbb_vclk2_div.hw,
|
||||
[CLKID_VCLK] = &gxbb_vclk.hw,
|
||||
[CLKID_VCLK2] = &gxbb_vclk2.hw,
|
||||
[CLKID_VCLK_DIV1] = &gxbb_vclk_div1.hw,
|
||||
[CLKID_VCLK_DIV2_EN] = &gxbb_vclk_div2_en.hw,
|
||||
[CLKID_VCLK_DIV2] = &gxbb_vclk_div2.hw,
|
||||
[CLKID_VCLK_DIV4_EN] = &gxbb_vclk_div4_en.hw,
|
||||
[CLKID_VCLK_DIV4] = &gxbb_vclk_div4.hw,
|
||||
[CLKID_VCLK_DIV6_EN] = &gxbb_vclk_div6_en.hw,
|
||||
[CLKID_VCLK_DIV6] = &gxbb_vclk_div6.hw,
|
||||
[CLKID_VCLK_DIV12_EN] = &gxbb_vclk_div12_en.hw,
|
||||
[CLKID_VCLK_DIV12] = &gxbb_vclk_div12.hw,
|
||||
[CLKID_VCLK2_DIV1] = &gxbb_vclk2_div1.hw,
|
||||
[CLKID_VCLK2_DIV2_EN] = &gxbb_vclk2_div2_en.hw,
|
||||
[CLKID_VCLK2_DIV2] = &gxbb_vclk2_div2.hw,
|
||||
[CLKID_VCLK2_DIV4_EN] = &gxbb_vclk2_div4_en.hw,
|
||||
[CLKID_VCLK2_DIV4] = &gxbb_vclk2_div4.hw,
|
||||
[CLKID_VCLK2_DIV6_EN] = &gxbb_vclk2_div6_en.hw,
|
||||
[CLKID_VCLK2_DIV6] = &gxbb_vclk2_div6.hw,
|
||||
[CLKID_VCLK2_DIV12_EN] = &gxbb_vclk2_div12_en.hw,
|
||||
[CLKID_VCLK2_DIV12] = &gxbb_vclk2_div12.hw,
|
||||
[CLKID_CTS_ENCI_SEL] = &gxbb_cts_enci_sel.hw,
|
||||
[CLKID_CTS_ENCP_SEL] = &gxbb_cts_encp_sel.hw,
|
||||
[CLKID_CTS_VDAC_SEL] = &gxbb_cts_vdac_sel.hw,
|
||||
[CLKID_HDMI_TX_SEL] = &gxbb_hdmi_tx_sel.hw,
|
||||
[CLKID_CTS_ENCI] = &gxbb_cts_enci.hw,
|
||||
[CLKID_CTS_ENCP] = &gxbb_cts_encp.hw,
|
||||
[CLKID_CTS_VDAC] = &gxbb_cts_vdac.hw,
|
||||
[CLKID_HDMI_TX] = &gxbb_hdmi_tx.hw,
|
||||
[CLKID_HDMI_SEL] = &gxbb_hdmi_sel.hw,
|
||||
[CLKID_HDMI_DIV] = &gxbb_hdmi_div.hw,
|
||||
[CLKID_HDMI] = &gxbb_hdmi.hw,
|
||||
[NR_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
|
@ -2089,11 +2785,51 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
|
|||
[CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
|
||||
[CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
|
||||
[CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
|
||||
[CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
|
||||
[CLKID_HDMI_PLL_DCO] = &gxl_hdmi_pll_dco.hw,
|
||||
[CLKID_HDMI_PLL_OD] = &gxl_hdmi_pll_od.hw,
|
||||
[CLKID_HDMI_PLL_OD2] = &gxl_hdmi_pll_od2.hw,
|
||||
[CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
|
||||
[CLKID_GP0_PLL_DCO] = &gxl_gp0_pll_dco.hw,
|
||||
[CLKID_VID_PLL_DIV] = &gxbb_vid_pll_div.hw,
|
||||
[CLKID_VID_PLL_SEL] = &gxbb_vid_pll_sel.hw,
|
||||
[CLKID_VID_PLL] = &gxbb_vid_pll.hw,
|
||||
[CLKID_VCLK_SEL] = &gxbb_vclk_sel.hw,
|
||||
[CLKID_VCLK2_SEL] = &gxbb_vclk2_sel.hw,
|
||||
[CLKID_VCLK_INPUT] = &gxbb_vclk_input.hw,
|
||||
[CLKID_VCLK2_INPUT] = &gxbb_vclk2_input.hw,
|
||||
[CLKID_VCLK_DIV] = &gxbb_vclk_div.hw,
|
||||
[CLKID_VCLK2_DIV] = &gxbb_vclk2_div.hw,
|
||||
[CLKID_VCLK] = &gxbb_vclk.hw,
|
||||
[CLKID_VCLK2] = &gxbb_vclk2.hw,
|
||||
[CLKID_VCLK_DIV1] = &gxbb_vclk_div1.hw,
|
||||
[CLKID_VCLK_DIV2_EN] = &gxbb_vclk_div2_en.hw,
|
||||
[CLKID_VCLK_DIV2] = &gxbb_vclk_div2.hw,
|
||||
[CLKID_VCLK_DIV4_EN] = &gxbb_vclk_div4_en.hw,
|
||||
[CLKID_VCLK_DIV4] = &gxbb_vclk_div4.hw,
|
||||
[CLKID_VCLK_DIV6_EN] = &gxbb_vclk_div6_en.hw,
|
||||
[CLKID_VCLK_DIV6] = &gxbb_vclk_div6.hw,
|
||||
[CLKID_VCLK_DIV12_EN] = &gxbb_vclk_div12_en.hw,
|
||||
[CLKID_VCLK_DIV12] = &gxbb_vclk_div12.hw,
|
||||
[CLKID_VCLK2_DIV1] = &gxbb_vclk2_div1.hw,
|
||||
[CLKID_VCLK2_DIV2_EN] = &gxbb_vclk2_div2_en.hw,
|
||||
[CLKID_VCLK2_DIV2] = &gxbb_vclk2_div2.hw,
|
||||
[CLKID_VCLK2_DIV4_EN] = &gxbb_vclk2_div4_en.hw,
|
||||
[CLKID_VCLK2_DIV4] = &gxbb_vclk2_div4.hw,
|
||||
[CLKID_VCLK2_DIV6_EN] = &gxbb_vclk2_div6_en.hw,
|
||||
[CLKID_VCLK2_DIV6] = &gxbb_vclk2_div6.hw,
|
||||
[CLKID_VCLK2_DIV12_EN] = &gxbb_vclk2_div12_en.hw,
|
||||
[CLKID_VCLK2_DIV12] = &gxbb_vclk2_div12.hw,
|
||||
[CLKID_CTS_ENCI_SEL] = &gxbb_cts_enci_sel.hw,
|
||||
[CLKID_CTS_ENCP_SEL] = &gxbb_cts_encp_sel.hw,
|
||||
[CLKID_CTS_VDAC_SEL] = &gxbb_cts_vdac_sel.hw,
|
||||
[CLKID_HDMI_TX_SEL] = &gxbb_hdmi_tx_sel.hw,
|
||||
[CLKID_CTS_ENCI] = &gxbb_cts_enci.hw,
|
||||
[CLKID_CTS_ENCP] = &gxbb_cts_encp.hw,
|
||||
[CLKID_CTS_VDAC] = &gxbb_cts_vdac.hw,
|
||||
[CLKID_HDMI_TX] = &gxbb_hdmi_tx.hw,
|
||||
[CLKID_HDMI_SEL] = &gxbb_hdmi_sel.hw,
|
||||
[CLKID_HDMI_DIV] = &gxbb_hdmi_div.hw,
|
||||
[CLKID_HDMI] = &gxbb_hdmi.hw,
|
||||
[NR_CLKS] = NULL,
|
||||
},
|
||||
.num = NR_CLKS,
|
||||
|
@ -2104,6 +2840,7 @@ static struct clk_regmap *const gxbb_clk_regmaps[] = {
|
|||
&gxbb_hdmi_pll,
|
||||
&gxbb_hdmi_pll_od,
|
||||
&gxbb_hdmi_pll_od2,
|
||||
&gxbb_hdmi_pll_dco,
|
||||
};
|
||||
|
||||
static struct clk_regmap *const gxl_clk_regmaps[] = {
|
||||
|
@ -2111,6 +2848,7 @@ static struct clk_regmap *const gxl_clk_regmaps[] = {
|
|||
&gxl_hdmi_pll,
|
||||
&gxl_hdmi_pll_od,
|
||||
&gxl_hdmi_pll_od2,
|
||||
&gxl_hdmi_pll_dco,
|
||||
};
|
||||
|
||||
static struct clk_regmap *const gx_clk_regmaps[] = {
|
||||
|
@ -2266,9 +3004,40 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
|
|||
&gxbb_gen_clk_div,
|
||||
&gxbb_gen_clk,
|
||||
&gxbb_fixed_pll_dco,
|
||||
&gxbb_hdmi_pll_dco,
|
||||
&gxbb_sys_pll_dco,
|
||||
&gxbb_gp0_pll,
|
||||
&gxbb_vid_pll,
|
||||
&gxbb_vid_pll_sel,
|
||||
&gxbb_vid_pll_div,
|
||||
&gxbb_vclk,
|
||||
&gxbb_vclk_sel,
|
||||
&gxbb_vclk_div,
|
||||
&gxbb_vclk_input,
|
||||
&gxbb_vclk_div1,
|
||||
&gxbb_vclk_div2_en,
|
||||
&gxbb_vclk_div4_en,
|
||||
&gxbb_vclk_div6_en,
|
||||
&gxbb_vclk_div12_en,
|
||||
&gxbb_vclk2,
|
||||
&gxbb_vclk2_sel,
|
||||
&gxbb_vclk2_div,
|
||||
&gxbb_vclk2_input,
|
||||
&gxbb_vclk2_div1,
|
||||
&gxbb_vclk2_div2_en,
|
||||
&gxbb_vclk2_div4_en,
|
||||
&gxbb_vclk2_div6_en,
|
||||
&gxbb_vclk2_div12_en,
|
||||
&gxbb_cts_enci,
|
||||
&gxbb_cts_enci_sel,
|
||||
&gxbb_cts_encp,
|
||||
&gxbb_cts_encp_sel,
|
||||
&gxbb_cts_vdac,
|
||||
&gxbb_cts_vdac_sel,
|
||||
&gxbb_hdmi_tx,
|
||||
&gxbb_hdmi_tx_sel,
|
||||
&gxbb_hdmi_sel,
|
||||
&gxbb_hdmi_div,
|
||||
&gxbb_hdmi,
|
||||
};
|
||||
|
||||
struct clkc_data {
|
||||
|
|
|
@ -165,8 +165,30 @@
|
|||
#define CLKID_HDMI_PLL_OD2 163
|
||||
#define CLKID_SYS_PLL_DCO 164
|
||||
#define CLKID_GP0_PLL_DCO 165
|
||||
#define CLKID_VID_PLL_SEL 167
|
||||
#define CLKID_VID_PLL_DIV 168
|
||||
#define CLKID_VCLK_SEL 169
|
||||
#define CLKID_VCLK2_SEL 170
|
||||
#define CLKID_VCLK_INPUT 171
|
||||
#define CLKID_VCLK2_INPUT 172
|
||||
#define CLKID_VCLK_DIV 173
|
||||
#define CLKID_VCLK2_DIV 174
|
||||
#define CLKID_VCLK_DIV2_EN 177
|
||||
#define CLKID_VCLK_DIV4_EN 178
|
||||
#define CLKID_VCLK_DIV6_EN 179
|
||||
#define CLKID_VCLK_DIV12_EN 180
|
||||
#define CLKID_VCLK2_DIV2_EN 181
|
||||
#define CLKID_VCLK2_DIV4_EN 182
|
||||
#define CLKID_VCLK2_DIV6_EN 183
|
||||
#define CLKID_VCLK2_DIV12_EN 184
|
||||
#define CLKID_CTS_ENCI_SEL 195
|
||||
#define CLKID_CTS_ENCP_SEL 196
|
||||
#define CLKID_CTS_VDAC_SEL 197
|
||||
#define CLKID_HDMI_TX_SEL 198
|
||||
#define CLKID_HDMI_SEL 203
|
||||
#define CLKID_HDMI_DIV 204
|
||||
|
||||
#define NR_CLKS 166
|
||||
#define NR_CLKS 206
|
||||
|
||||
/* include the CLKIDs that have been made part of the DT binding */
|
||||
#include <dt-bindings/clock/gxbb-clkc.h>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -42,6 +43,11 @@ static const struct pll_params_table sys_pll_params_table[] = {
|
|||
PLL_PARAMS(62, 1),
|
||||
PLL_PARAMS(63, 1),
|
||||
PLL_PARAMS(64, 1),
|
||||
PLL_PARAMS(65, 1),
|
||||
PLL_PARAMS(66, 1),
|
||||
PLL_PARAMS(67, 1),
|
||||
PLL_PARAMS(68, 1),
|
||||
PLL_PARAMS(84, 1),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
@ -197,7 +203,7 @@ static struct clk_regmap meson8b_sys_pll_dco = {
|
|||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "sys_pll_dco",
|
||||
.ops = &meson_clk_pll_ro_ops,
|
||||
.ops = &meson_clk_pll_ops,
|
||||
.parent_names = (const char *[]){ "xtal" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
|
@ -212,7 +218,7 @@ static struct clk_regmap meson8b_sys_pll = {
|
|||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "sys_pll",
|
||||
.ops = &clk_regmap_divider_ro_ops,
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_names = (const char *[]){ "sys_pll_dco" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
|
@ -546,7 +552,7 @@ static struct clk_regmap meson8b_cpu_in_sel = {
|
|||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_in_sel",
|
||||
.ops = &clk_regmap_mux_ro_ops,
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = (const char *[]){ "xtal", "sys_pll" },
|
||||
.num_parents = 2,
|
||||
.flags = (CLK_SET_RATE_PARENT |
|
||||
|
@ -554,11 +560,11 @@ static struct clk_regmap meson8b_cpu_in_sel = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_div2 = {
|
||||
static struct clk_fixed_factor meson8b_cpu_in_div2 = {
|
||||
.mult = 1,
|
||||
.div = 2,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_div2",
|
||||
.name = "cpu_in_div2",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_in_sel" },
|
||||
.num_parents = 1,
|
||||
|
@ -566,11 +572,11 @@ static struct clk_fixed_factor meson8b_cpu_div2 = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_div3 = {
|
||||
static struct clk_fixed_factor meson8b_cpu_in_div3 = {
|
||||
.mult = 1,
|
||||
.div = 3,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_div3",
|
||||
.name = "cpu_in_div3",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_in_sel" },
|
||||
.num_parents = 1,
|
||||
|
@ -579,13 +585,14 @@ static struct clk_fixed_factor meson8b_cpu_div3 = {
|
|||
};
|
||||
|
||||
static const struct clk_div_table cpu_scale_table[] = {
|
||||
{ .val = 2, .div = 4 },
|
||||
{ .val = 3, .div = 6 },
|
||||
{ .val = 4, .div = 8 },
|
||||
{ .val = 5, .div = 10 },
|
||||
{ .val = 6, .div = 12 },
|
||||
{ .val = 7, .div = 14 },
|
||||
{ .val = 8, .div = 16 },
|
||||
{ .val = 1, .div = 4 },
|
||||
{ .val = 2, .div = 6 },
|
||||
{ .val = 3, .div = 8 },
|
||||
{ .val = 4, .div = 10 },
|
||||
{ .val = 5, .div = 12 },
|
||||
{ .val = 6, .div = 14 },
|
||||
{ .val = 7, .div = 16 },
|
||||
{ .val = 8, .div = 18 },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
|
@ -593,33 +600,40 @@ static struct clk_regmap meson8b_cpu_scale_div = {
|
|||
.data = &(struct clk_regmap_div_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.shift = 20,
|
||||
.width = 9,
|
||||
.width = 10,
|
||||
.table = cpu_scale_table,
|
||||
.flags = CLK_DIVIDER_ALLOW_ZERO,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_scale_div",
|
||||
.ops = &clk_regmap_divider_ro_ops,
|
||||
.ops = &clk_regmap_divider_ops,
|
||||
.parent_names = (const char *[]){ "cpu_in_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 mux_table_cpu_scale_out_sel[] = { 0, 1, 3 };
|
||||
static struct clk_regmap meson8b_cpu_scale_out_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL0,
|
||||
.mask = 0x3,
|
||||
.shift = 2,
|
||||
.table = mux_table_cpu_scale_out_sel,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_scale_out_sel",
|
||||
.ops = &clk_regmap_mux_ro_ops,
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
/*
|
||||
* NOTE: We are skipping the parent with value 0x2 (which is
|
||||
* "cpu_in_div3") because it results in a duty cycle of 33%
|
||||
* which makes the system unstable and can result in a lockup
|
||||
* of the whole system.
|
||||
*/
|
||||
.parent_names = (const char *[]) { "cpu_in_sel",
|
||||
"cpu_div2",
|
||||
"cpu_div3",
|
||||
"cpu_in_div2",
|
||||
"cpu_scale_div" },
|
||||
.num_parents = 4,
|
||||
.num_parents = 3,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
@ -632,12 +646,13 @@ static struct clk_regmap meson8b_cpu_clk = {
|
|||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_clk",
|
||||
.ops = &clk_regmap_mux_ro_ops,
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = (const char *[]){ "xtal",
|
||||
"cpu_scale_out_sel" },
|
||||
.num_parents = 2,
|
||||
.flags = (CLK_SET_RATE_PARENT |
|
||||
CLK_SET_RATE_NO_REPARENT),
|
||||
CLK_SET_RATE_NO_REPARENT |
|
||||
CLK_IS_CRITICAL),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -689,6 +704,227 @@ static struct clk_regmap meson8b_nand_clk_gate = {
|
|||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_clk_div2 = {
|
||||
.mult = 1,
|
||||
.div = 2,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_clk_div2",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_clk_div3 = {
|
||||
.mult = 1,
|
||||
.div = 3,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_clk_div3",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_clk_div4 = {
|
||||
.mult = 1,
|
||||
.div = 4,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_clk_div4",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_clk_div5 = {
|
||||
.mult = 1,
|
||||
.div = 5,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_clk_div5",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_clk_div6 = {
|
||||
.mult = 1,
|
||||
.div = 6,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_clk_div6",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_clk_div7 = {
|
||||
.mult = 1,
|
||||
.div = 7,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_clk_div7",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_fixed_factor meson8b_cpu_clk_div8 = {
|
||||
.mult = 1,
|
||||
.div = 8,
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "cpu_clk_div8",
|
||||
.ops = &clk_fixed_factor_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk" },
|
||||
.num_parents = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 mux_table_abp[] = { 1, 2, 3, 4, 5, 6, 7 };
|
||||
static struct clk_regmap meson8b_abp_clk_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.mask = 0x7,
|
||||
.shift = 3,
|
||||
.table = mux_table_abp,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "abp_clk_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk_div2",
|
||||
"cpu_clk_div3",
|
||||
"cpu_clk_div4",
|
||||
"cpu_clk_div5",
|
||||
"cpu_clk_div6",
|
||||
"cpu_clk_div7",
|
||||
"cpu_clk_div8", },
|
||||
.num_parents = 7,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap meson8b_abp_clk_gate = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.bit_idx = 16,
|
||||
.flags = CLK_GATE_SET_TO_DISABLE,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "abp_clk_dis",
|
||||
.ops = &clk_regmap_gate_ro_ops,
|
||||
.parent_names = (const char *[]){ "abp_clk_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap meson8b_periph_clk_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.mask = 0x7,
|
||||
.shift = 6,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "periph_clk_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk_div2",
|
||||
"cpu_clk_div3",
|
||||
"cpu_clk_div4",
|
||||
"cpu_clk_div5",
|
||||
"cpu_clk_div6",
|
||||
"cpu_clk_div7",
|
||||
"cpu_clk_div8", },
|
||||
.num_parents = 7,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap meson8b_periph_clk_gate = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.bit_idx = 17,
|
||||
.flags = CLK_GATE_SET_TO_DISABLE,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "periph_clk_dis",
|
||||
.ops = &clk_regmap_gate_ro_ops,
|
||||
.parent_names = (const char *[]){ "periph_clk_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static u32 mux_table_axi[] = { 1, 2, 3, 4, 5, 6, 7 };
|
||||
static struct clk_regmap meson8b_axi_clk_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.mask = 0x7,
|
||||
.shift = 9,
|
||||
.table = mux_table_axi,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "axi_clk_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk_div2",
|
||||
"cpu_clk_div3",
|
||||
"cpu_clk_div4",
|
||||
"cpu_clk_div5",
|
||||
"cpu_clk_div6",
|
||||
"cpu_clk_div7",
|
||||
"cpu_clk_div8", },
|
||||
.num_parents = 7,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap meson8b_axi_clk_gate = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.bit_idx = 18,
|
||||
.flags = CLK_GATE_SET_TO_DISABLE,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "axi_clk_dis",
|
||||
.ops = &clk_regmap_gate_ro_ops,
|
||||
.parent_names = (const char *[]){ "axi_clk_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap meson8b_l2_dram_clk_sel = {
|
||||
.data = &(struct clk_regmap_mux_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.mask = 0x7,
|
||||
.shift = 12,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "l2_dram_clk_sel",
|
||||
.ops = &clk_regmap_mux_ops,
|
||||
.parent_names = (const char *[]){ "cpu_clk_div2",
|
||||
"cpu_clk_div3",
|
||||
"cpu_clk_div4",
|
||||
"cpu_clk_div5",
|
||||
"cpu_clk_div6",
|
||||
"cpu_clk_div7",
|
||||
"cpu_clk_div8", },
|
||||
.num_parents = 7,
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_regmap meson8b_l2_dram_clk_gate = {
|
||||
.data = &(struct clk_regmap_gate_data){
|
||||
.offset = HHI_SYS_CPU_CLK_CNTL1,
|
||||
.bit_idx = 19,
|
||||
.flags = CLK_GATE_SET_TO_DISABLE,
|
||||
},
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "l2_dram_clk_dis",
|
||||
.ops = &clk_regmap_gate_ro_ops,
|
||||
.parent_names = (const char *[]){ "l2_dram_clk_sel" },
|
||||
.num_parents = 1,
|
||||
.flags = CLK_SET_RATE_PARENT,
|
||||
},
|
||||
};
|
||||
|
||||
/* Everything Else (EE) domain gates */
|
||||
|
||||
static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
|
||||
|
@ -874,8 +1110,8 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
|
|||
[CLKID_MPLL1_DIV] = &meson8b_mpll1_div.hw,
|
||||
[CLKID_MPLL2_DIV] = &meson8b_mpll2_div.hw,
|
||||
[CLKID_CPU_IN_SEL] = &meson8b_cpu_in_sel.hw,
|
||||
[CLKID_CPU_DIV2] = &meson8b_cpu_div2.hw,
|
||||
[CLKID_CPU_DIV3] = &meson8b_cpu_div3.hw,
|
||||
[CLKID_CPU_IN_DIV2] = &meson8b_cpu_in_div2.hw,
|
||||
[CLKID_CPU_IN_DIV3] = &meson8b_cpu_in_div3.hw,
|
||||
[CLKID_CPU_SCALE_DIV] = &meson8b_cpu_scale_div.hw,
|
||||
[CLKID_CPU_SCALE_OUT_SEL] = &meson8b_cpu_scale_out_sel.hw,
|
||||
[CLKID_MPLL_PREDIV] = &meson8b_mpll_prediv.hw,
|
||||
|
@ -890,6 +1126,21 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
|
|||
[CLKID_PLL_FIXED_DCO] = &meson8b_fixed_pll_dco.hw,
|
||||
[CLKID_PLL_VID_DCO] = &meson8b_vid_pll_dco.hw,
|
||||
[CLKID_PLL_SYS_DCO] = &meson8b_sys_pll_dco.hw,
|
||||
[CLKID_CPU_CLK_DIV2] = &meson8b_cpu_clk_div2.hw,
|
||||
[CLKID_CPU_CLK_DIV3] = &meson8b_cpu_clk_div3.hw,
|
||||
[CLKID_CPU_CLK_DIV4] = &meson8b_cpu_clk_div4.hw,
|
||||
[CLKID_CPU_CLK_DIV5] = &meson8b_cpu_clk_div5.hw,
|
||||
[CLKID_CPU_CLK_DIV6] = &meson8b_cpu_clk_div6.hw,
|
||||
[CLKID_CPU_CLK_DIV7] = &meson8b_cpu_clk_div7.hw,
|
||||
[CLKID_CPU_CLK_DIV8] = &meson8b_cpu_clk_div8.hw,
|
||||
[CLKID_ABP_SEL] = &meson8b_abp_clk_sel.hw,
|
||||
[CLKID_ABP] = &meson8b_abp_clk_gate.hw,
|
||||
[CLKID_PERIPH_SEL] = &meson8b_periph_clk_sel.hw,
|
||||
[CLKID_PERIPH] = &meson8b_periph_clk_gate.hw,
|
||||
[CLKID_AXI_SEL] = &meson8b_axi_clk_sel.hw,
|
||||
[CLKID_AXI] = &meson8b_axi_clk_gate.hw,
|
||||
[CLKID_L2_DRAM_SEL] = &meson8b_l2_dram_clk_sel.hw,
|
||||
[CLKID_L2_DRAM] = &meson8b_l2_dram_clk_gate.hw,
|
||||
[CLK_NR_CLKS] = NULL,
|
||||
},
|
||||
.num = CLK_NR_CLKS,
|
||||
|
@ -1001,6 +1252,14 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
|
|||
&meson8b_fixed_pll_dco,
|
||||
&meson8b_vid_pll_dco,
|
||||
&meson8b_sys_pll_dco,
|
||||
&meson8b_abp_clk_sel,
|
||||
&meson8b_abp_clk_gate,
|
||||
&meson8b_periph_clk_sel,
|
||||
&meson8b_periph_clk_gate,
|
||||
&meson8b_axi_clk_sel,
|
||||
&meson8b_axi_clk_gate,
|
||||
&meson8b_l2_dram_clk_sel,
|
||||
&meson8b_l2_dram_clk_gate,
|
||||
};
|
||||
|
||||
static const struct meson8b_clk_reset_line {
|
||||
|
@ -1101,6 +1360,53 @@ static const struct reset_control_ops meson8b_clk_reset_ops = {
|
|||
.deassert = meson8b_clk_reset_deassert,
|
||||
};
|
||||
|
||||
struct meson8b_nb_data {
|
||||
struct notifier_block nb;
|
||||
struct clk_hw_onecell_data *onecell_data;
|
||||
};
|
||||
|
||||
static int meson8b_cpu_clk_notifier_cb(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct meson8b_nb_data *nb_data =
|
||||
container_of(nb, struct meson8b_nb_data, nb);
|
||||
struct clk_hw **hws = nb_data->onecell_data->hws;
|
||||
struct clk_hw *cpu_clk_hw, *parent_clk_hw;
|
||||
struct clk *cpu_clk, *parent_clk;
|
||||
int ret;
|
||||
|
||||
switch (event) {
|
||||
case PRE_RATE_CHANGE:
|
||||
parent_clk_hw = hws[CLKID_XTAL];
|
||||
break;
|
||||
|
||||
case POST_RATE_CHANGE:
|
||||
parent_clk_hw = hws[CLKID_CPU_SCALE_OUT_SEL];
|
||||
break;
|
||||
|
||||
default:
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
cpu_clk_hw = hws[CLKID_CPUCLK];
|
||||
cpu_clk = __clk_lookup(clk_hw_get_name(cpu_clk_hw));
|
||||
|
||||
parent_clk = __clk_lookup(clk_hw_get_name(parent_clk_hw));
|
||||
|
||||
ret = clk_set_parent(cpu_clk, parent_clk);
|
||||
if (ret)
|
||||
return notifier_from_errno(ret);
|
||||
|
||||
udelay(100);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct meson8b_nb_data meson8b_cpu_nb_data = {
|
||||
.nb.notifier_call = meson8b_cpu_clk_notifier_cb,
|
||||
.onecell_data = &meson8b_hw_onecell_data,
|
||||
};
|
||||
|
||||
static const struct regmap_config clkc_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.val_bits = 32,
|
||||
|
@ -1110,20 +1416,27 @@ static const struct regmap_config clkc_regmap_config = {
|
|||
static void __init meson8b_clkc_init(struct device_node *np)
|
||||
{
|
||||
struct meson8b_clk_reset *rstc;
|
||||
const char *notifier_clk_name;
|
||||
struct clk *notifier_clk;
|
||||
void __iomem *clk_base;
|
||||
struct regmap *map;
|
||||
int i, ret;
|
||||
|
||||
/* Generic clocks, PLLs and some of the reset-bits */
|
||||
clk_base = of_iomap(np, 1);
|
||||
if (!clk_base) {
|
||||
pr_err("%s: Unable to map clk base\n", __func__);
|
||||
return;
|
||||
}
|
||||
map = syscon_node_to_regmap(of_get_parent(np));
|
||||
if (IS_ERR(map)) {
|
||||
pr_info("failed to get HHI regmap - Trying obsolete regs\n");
|
||||
|
||||
map = regmap_init_mmio(NULL, clk_base, &clkc_regmap_config);
|
||||
if (IS_ERR(map))
|
||||
return;
|
||||
/* Generic clocks, PLLs and some of the reset-bits */
|
||||
clk_base = of_iomap(np, 1);
|
||||
if (!clk_base) {
|
||||
pr_err("%s: Unable to map clk base\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
map = regmap_init_mmio(NULL, clk_base, &clkc_regmap_config);
|
||||
if (IS_ERR(map))
|
||||
return;
|
||||
}
|
||||
|
||||
rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
|
||||
if (!rstc)
|
||||
|
@ -1159,6 +1472,20 @@ static void __init meson8b_clkc_init(struct device_node *np)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME we shouldn't program the muxes in notifier handlers. The
|
||||
* tricky programming sequence will be handled by the forthcoming
|
||||
* coordinated clock rates mechanism once that feature is released.
|
||||
*/
|
||||
notifier_clk_name = clk_hw_get_name(&meson8b_cpu_scale_out_sel.hw);
|
||||
notifier_clk = __clk_lookup(notifier_clk_name);
|
||||
ret = clk_notifier_register(notifier_clk, &meson8b_cpu_nb_data.nb);
|
||||
if (ret) {
|
||||
pr_err("%s: failed to register the CPU clock notifier\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
|
||||
&meson8b_hw_onecell_data);
|
||||
if (ret)
|
||||
|
|
|
@ -63,8 +63,8 @@
|
|||
#define CLKID_MPLL1_DIV 97
|
||||
#define CLKID_MPLL2_DIV 98
|
||||
#define CLKID_CPU_IN_SEL 99
|
||||
#define CLKID_CPU_DIV2 100
|
||||
#define CLKID_CPU_DIV3 101
|
||||
#define CLKID_CPU_IN_DIV2 100
|
||||
#define CLKID_CPU_IN_DIV3 101
|
||||
#define CLKID_CPU_SCALE_DIV 102
|
||||
#define CLKID_CPU_SCALE_OUT_SEL 103
|
||||
#define CLKID_MPLL_PREDIV 104
|
||||
|
@ -78,8 +78,19 @@
|
|||
#define CLKID_PLL_FIXED_DCO 113
|
||||
#define CLKID_PLL_VID_DCO 114
|
||||
#define CLKID_PLL_SYS_DCO 115
|
||||
#define CLKID_CPU_CLK_DIV2 116
|
||||
#define CLKID_CPU_CLK_DIV3 117
|
||||
#define CLKID_CPU_CLK_DIV4 118
|
||||
#define CLKID_CPU_CLK_DIV5 119
|
||||
#define CLKID_CPU_CLK_DIV6 120
|
||||
#define CLKID_CPU_CLK_DIV7 121
|
||||
#define CLKID_CPU_CLK_DIV8 122
|
||||
#define CLKID_ABP_SEL 123
|
||||
#define CLKID_PERIPH_SEL 125
|
||||
#define CLKID_AXI_SEL 127
|
||||
#define CLKID_L2_DRAM_SEL 129
|
||||
|
||||
#define CLK_NR_CLKS 116
|
||||
#define CLK_NR_CLKS 131
|
||||
|
||||
/*
|
||||
* include the CLKID and RESETID that have
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2018 BayLibre, SAS.
|
||||
* Author: Neil Armstrong <narmstrong@baylibre.com>
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include "clkc.h"
|
||||
|
||||
static inline struct meson_vid_pll_div_data *
|
||||
meson_vid_pll_div_data(struct clk_regmap *clk)
|
||||
{
|
||||
return (struct meson_vid_pll_div_data *)clk->data;
|
||||
}
|
||||
|
||||
/*
|
||||
* This vid_pll divided is a fully programmable fractionnal divider to
|
||||
* achieve complex video clock rates.
|
||||
*
|
||||
* Here are provided the commonly used fraction values provided by Amlogic.
|
||||
*/
|
||||
|
||||
struct vid_pll_div {
|
||||
unsigned int shift_val;
|
||||
unsigned int shift_sel;
|
||||
unsigned int divider;
|
||||
unsigned int multiplier;
|
||||
};
|
||||
|
||||
#define VID_PLL_DIV(_val, _sel, _ft, _fb) \
|
||||
{ \
|
||||
.shift_val = (_val), \
|
||||
.shift_sel = (_sel), \
|
||||
.divider = (_ft), \
|
||||
.multiplier = (_fb), \
|
||||
}
|
||||
|
||||
static const struct vid_pll_div vid_pll_div_table[] = {
|
||||
VID_PLL_DIV(0x0aaa, 0, 2, 1), /* 2/1 => /2 */
|
||||
VID_PLL_DIV(0x5294, 2, 5, 2), /* 5/2 => /2.5 */
|
||||
VID_PLL_DIV(0x0db6, 0, 3, 1), /* 3/1 => /3 */
|
||||
VID_PLL_DIV(0x36cc, 1, 7, 2), /* 7/2 => /3.5 */
|
||||
VID_PLL_DIV(0x6666, 2, 15, 4), /* 15/4 => /3.75 */
|
||||
VID_PLL_DIV(0x0ccc, 0, 4, 1), /* 4/1 => /4 */
|
||||
VID_PLL_DIV(0x739c, 2, 5, 1), /* 5/1 => /5 */
|
||||
VID_PLL_DIV(0x0e38, 0, 6, 1), /* 6/1 => /6 */
|
||||
VID_PLL_DIV(0x0000, 3, 25, 4), /* 25/4 => /6.25 */
|
||||
VID_PLL_DIV(0x3c78, 1, 7, 1), /* 7/1 => /7 */
|
||||
VID_PLL_DIV(0x78f0, 2, 15, 2), /* 15/2 => /7.5 */
|
||||
VID_PLL_DIV(0x0fc0, 0, 12, 1), /* 12/1 => /12 */
|
||||
VID_PLL_DIV(0x3f80, 1, 14, 1), /* 14/1 => /14 */
|
||||
VID_PLL_DIV(0x7f80, 2, 15, 1), /* 15/1 => /15 */
|
||||
};
|
||||
|
||||
#define to_meson_vid_pll_div(_hw) \
|
||||
container_of(_hw, struct meson_vid_pll_div, hw)
|
||||
|
||||
const struct vid_pll_div *_get_table_val(unsigned int shift_val,
|
||||
unsigned int shift_sel)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < ARRAY_SIZE(vid_pll_div_table) ; ++i) {
|
||||
if (vid_pll_div_table[i].shift_val == shift_val &&
|
||||
vid_pll_div_table[i].shift_sel == shift_sel)
|
||||
return &vid_pll_div_table[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_regmap *clk = to_clk_regmap(hw);
|
||||
struct meson_vid_pll_div_data *pll_div = meson_vid_pll_div_data(clk);
|
||||
const struct vid_pll_div *div;
|
||||
|
||||
div = _get_table_val(meson_parm_read(clk->map, &pll_div->val),
|
||||
meson_parm_read(clk->map, &pll_div->sel));
|
||||
if (!div || !div->divider) {
|
||||
pr_info("%s: Invalid config value for vid_pll_div\n", __func__);
|
||||
return parent_rate;
|
||||
}
|
||||
|
||||
return DIV_ROUND_UP_ULL(parent_rate * div->multiplier, div->divider);
|
||||
}
|
||||
|
||||
const struct clk_ops meson_vid_pll_div_ro_ops = {
|
||||
.recalc_rate = meson_vid_pll_div_recalc_rate,
|
||||
};
|
|
@ -128,5 +128,23 @@
|
|||
#define CLKID_VDEC_1 153
|
||||
#define CLKID_VDEC_HEVC 156
|
||||
#define CLKID_GEN_CLK 159
|
||||
#define CLKID_VID_PLL 166
|
||||
#define CLKID_VCLK 175
|
||||
#define CLKID_VCLK2 176
|
||||
#define CLKID_VCLK_DIV1 185
|
||||
#define CLKID_VCLK_DIV2 186
|
||||
#define CLKID_VCLK_DIV4 187
|
||||
#define CLKID_VCLK_DIV6 188
|
||||
#define CLKID_VCLK_DIV12 189
|
||||
#define CLKID_VCLK2_DIV1 190
|
||||
#define CLKID_VCLK2_DIV2 191
|
||||
#define CLKID_VCLK2_DIV4 192
|
||||
#define CLKID_VCLK2_DIV6 193
|
||||
#define CLKID_VCLK2_DIV12 194
|
||||
#define CLKID_CTS_ENCI 199
|
||||
#define CLKID_CTS_ENCP 200
|
||||
#define CLKID_CTS_VDAC 201
|
||||
#define CLKID_HDMI_TX 202
|
||||
#define CLKID_HDMI 205
|
||||
|
||||
#endif /* __GXBB_CLKC_H */
|
||||
|
|
|
@ -103,5 +103,9 @@
|
|||
#define CLKID_MPLL1 94
|
||||
#define CLKID_MPLL2 95
|
||||
#define CLKID_NAND_CLK 112
|
||||
#define CLKID_ABP 124
|
||||
#define CLKID_PERIPH 126
|
||||
#define CLKID_AXI 128
|
||||
#define CLKID_L2_DRAM 130
|
||||
|
||||
#endif /* __MESON8B_CLKC_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче