Commit 41785ce5 authored by Martin Blumenstingl's avatar Martin Blumenstingl Committed by Neil Armstrong
Browse files

clk: meson: meson8b: add the VPU clock trees



The VPU clock tree is slightly different on all three supported SoCs:

Meson8 only has an input mux (which chooses between "fclk_div4",
"fclk_div3", "fclk_div5" and "fclk_div7"), a divider and a gate.

Meson8b has two VPU clock trees, each with an input mux (using the same
parents as the input mux on Meson8), divider and a gates. The final VPU
clock is a glitch-free mux which chooses between VPU_1 and VPU_2.

Meson8m2 uses a similar clock tree as Meson8b but the last input clock
is different: instead of using "fclk_div7" as input Meson8m2 uses
"gp_pll". This was probably done in hardware to improve the accuracy of
the clock because fclk_div7 gives us 2550MHz / 7 = 364.286MHz while
GP_PLL can achieve 364.0MHz.

Signed-off-by: default avatarMartin Blumenstingl <martin.blumenstingl@googlemail.com>
Reviewed-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Acked-by: default avatarJerome Brunet <jbrunet@baylibre.com>
Signed-off-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Link: https://lkml.kernel.org/r/20190324151104.18397-5-martin.blumenstingl@googlemail.com
parent b882964b
Loading
Loading
Loading
Loading
+167 −0
Original line number Diff line number Diff line
@@ -1761,6 +1761,147 @@ static struct clk_regmap meson8m2_gp_pll = {
	},
};

static const char * const mmeson8b_vpu_0_1_parent_names[] = {
	"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
};

static const char * const mmeson8m2_vpu_0_1_parent_names[] = {
	"fclk_div4", "fclk_div3", "fclk_div5", "gp_pll"
};

static struct clk_regmap meson8b_vpu_0_sel = {
	.data = &(struct clk_regmap_mux_data){
		.offset = HHI_VPU_CLK_CNTL,
		.mask = 0x3,
		.shift = 9,
	},
	.hw.init = &(struct clk_init_data){
		.name = "vpu_0_sel",
		.ops = &clk_regmap_mux_ops,
		.parent_names = mmeson8b_vpu_0_1_parent_names,
		.num_parents = ARRAY_SIZE(mmeson8b_vpu_0_1_parent_names),
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap meson8m2_vpu_0_sel = {
	.data = &(struct clk_regmap_mux_data){
		.offset = HHI_VPU_CLK_CNTL,
		.mask = 0x3,
		.shift = 9,
	},
	.hw.init = &(struct clk_init_data){
		.name = "vpu_0_sel",
		.ops = &clk_regmap_mux_ops,
		.parent_names = mmeson8m2_vpu_0_1_parent_names,
		.num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_names),
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap meson8b_vpu_0_div = {
	.data = &(struct clk_regmap_div_data){
		.offset = HHI_VPU_CLK_CNTL,
		.shift = 0,
		.width = 7,
	},
	.hw.init = &(struct clk_init_data){
		.name = "vpu_0_div",
		.ops = &clk_regmap_divider_ops,
		.parent_names = (const char *[]){ "vpu_0_sel" },
		.num_parents = 1,
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap meson8b_vpu_0 = {
	.data = &(struct clk_regmap_gate_data){
		.offset = HHI_VPU_CLK_CNTL,
		.bit_idx = 8,
	},
	.hw.init = &(struct clk_init_data) {
		.name = "vpu_0",
		.ops = &clk_regmap_gate_ops,
		.parent_names = (const char *[]){ "vpu_0_div" },
		.num_parents = 1,
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap meson8b_vpu_1_sel = {
	.data = &(struct clk_regmap_mux_data){
		.offset = HHI_VPU_CLK_CNTL,
		.mask = 0x3,
		.shift = 25,
	},
	.hw.init = &(struct clk_init_data){
		.name = "vpu_1_sel",
		.ops = &clk_regmap_mux_ops,
		.parent_names = mmeson8b_vpu_0_1_parent_names,
		.num_parents = ARRAY_SIZE(mmeson8b_vpu_0_1_parent_names),
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap meson8m2_vpu_1_sel = {
	.data = &(struct clk_regmap_mux_data){
		.offset = HHI_VPU_CLK_CNTL,
		.mask = 0x3,
		.shift = 25,
	},
	.hw.init = &(struct clk_init_data){
		.name = "vpu_1_sel",
		.ops = &clk_regmap_mux_ops,
		.parent_names = mmeson8m2_vpu_0_1_parent_names,
		.num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_names),
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap meson8b_vpu_1_div = {
	.data = &(struct clk_regmap_div_data){
		.offset = HHI_VPU_CLK_CNTL,
		.shift = 16,
		.width = 7,
	},
	.hw.init = &(struct clk_init_data){
		.name = "vpu_1_div",
		.ops = &clk_regmap_divider_ops,
		.parent_names = (const char *[]){ "vpu_1_sel" },
		.num_parents = 1,
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap meson8b_vpu_1 = {
	.data = &(struct clk_regmap_gate_data){
		.offset = HHI_VPU_CLK_CNTL,
		.bit_idx = 24,
	},
	.hw.init = &(struct clk_init_data) {
		.name = "vpu_1",
		.ops = &clk_regmap_gate_ops,
		.parent_names = (const char *[]){ "vpu_1_div" },
		.num_parents = 1,
		.flags = CLK_SET_RATE_PARENT,
	},
};

static struct clk_regmap meson8b_vpu = {
	.data = &(struct clk_regmap_mux_data){
		.offset = HHI_VPU_CLK_CNTL,
		.mask = 1,
		.shift = 31,
	},
	.hw.init = &(struct clk_init_data){
		.name = "vpu",
		.ops = &clk_regmap_mux_ops,
		.parent_names = (const char *[]){ "vpu_0", "vpu_1" },
		.num_parents = 2,
		.flags = CLK_SET_RATE_NO_REPARENT,
	},
};

/* Everything Else (EE) domain gates */

static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
@@ -2024,6 +2165,9 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = {
		[CLKID_MALI_0_SEL]	    = &meson8b_mali_0_sel.hw,
		[CLKID_MALI_0_DIV]	    = &meson8b_mali_0_div.hw,
		[CLKID_MALI]		    = &meson8b_mali_0.hw,
		[CLKID_VPU_0_SEL]	    = &meson8b_vpu_0_sel.hw,
		[CLKID_VPU_0_DIV]	    = &meson8b_vpu_0_div.hw,
		[CLKID_VPU]		    = &meson8b_vpu_0.hw,
		[CLK_NR_CLKS]		    = NULL,
	},
	.num = CLK_NR_CLKS,
@@ -2210,6 +2354,13 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
		[CLKID_MALI_1_DIV]	    = &meson8b_mali_1_div.hw,
		[CLKID_MALI_1]		    = &meson8b_mali_1.hw,
		[CLKID_MALI]		    = &meson8b_mali.hw,
		[CLKID_VPU_0_SEL]	    = &meson8b_vpu_0_sel.hw,
		[CLKID_VPU_0_DIV]	    = &meson8b_vpu_0_div.hw,
		[CLKID_VPU_0]		    = &meson8b_vpu_0.hw,
		[CLKID_VPU_1_SEL]	    = &meson8b_vpu_1_sel.hw,
		[CLKID_VPU_1_DIV]	    = &meson8b_vpu_1_div.hw,
		[CLKID_VPU_1]		    = &meson8b_vpu_1.hw,
		[CLKID_VPU]		    = &meson8b_vpu.hw,
		[CLK_NR_CLKS]		    = NULL,
	},
	.num = CLK_NR_CLKS,
@@ -2398,6 +2549,13 @@ static struct clk_hw_onecell_data meson8m2_hw_onecell_data = {
		[CLKID_MALI]		    = &meson8b_mali.hw,
		[CLKID_GP_PLL_DCO]	    = &meson8m2_gp_pll_dco.hw,
		[CLKID_GP_PLL]		    = &meson8m2_gp_pll.hw,
		[CLKID_VPU_0_SEL]	    = &meson8m2_vpu_0_sel.hw,
		[CLKID_VPU_0_DIV]	    = &meson8b_vpu_0_div.hw,
		[CLKID_VPU_0]		    = &meson8b_vpu_0.hw,
		[CLKID_VPU_1_SEL]	    = &meson8m2_vpu_1_sel.hw,
		[CLKID_VPU_1_DIV]	    = &meson8b_vpu_1_div.hw,
		[CLKID_VPU_1]		    = &meson8b_vpu_1.hw,
		[CLKID_VPU]		    = &meson8b_vpu.hw,
		[CLK_NR_CLKS]		    = NULL,
	},
	.num = CLK_NR_CLKS,
@@ -2562,6 +2720,15 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
	&meson8b_mali,
	&meson8m2_gp_pll_dco,
	&meson8m2_gp_pll,
	&meson8b_vpu_0_sel,
	&meson8m2_vpu_0_sel,
	&meson8b_vpu_0_div,
	&meson8b_vpu_0,
	&meson8b_vpu_1_sel,
	&meson8m2_vpu_1_sel,
	&meson8b_vpu_1_div,
	&meson8b_vpu_1,
	&meson8b_vpu,
};

static const struct meson8b_clk_reset_line {
+8 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#define HHI_VID_DIVIDER_CNTL		0x198 /* 0x66 offset in data sheet */
#define HHI_SYS_CPU_CLK_CNTL0		0x19c /* 0x67 offset in data sheet */
#define HHI_MALI_CLK_CNTL		0x1b0 /* 0x6c offset in data sheet */
#define HHI_VPU_CLK_CNTL		0x1bc /* 0x6f offset in data sheet */
#define HHI_HDMI_CLK_CNTL		0x1cc /* 0x73 offset in data sheet */
#define HHI_NAND_CLK_CNTL		0x25c /* 0x97 offset in data sheet */
#define HHI_MPLL_CNTL			0x280 /* 0xa0 offset in data sheet */
@@ -149,8 +150,14 @@
#define CLKID_MALI_1		180
#define CLKID_GP_PLL_DCO	181
#define CLKID_GP_PLL		182
#define CLKID_VPU_0_SEL		183
#define CLKID_VPU_0_DIV		184
#define CLKID_VPU_0		185
#define CLKID_VPU_1_SEL		186
#define CLKID_VPU_1_DIV		187
#define CLKID_VPU_1		189

#define CLK_NR_CLKS		183
#define CLK_NR_CLKS		191

/*
 * include the CLKID and RESETID that have