From 370294e2667fa1648eb05aab6c4657419634ff83 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 4 Mar 2019 14:11:29 +0100 Subject: clk: meson: g12a: add cpu clocks Add the Amlogic G12A Family CPU Clock tree in read/only for now. The CPU clock can either use the SYS_PLL for > 1GHz frequencies or use a couple of div+mux from 1GHz/667MHz/24MHz source with 2 non-glitch muxes. Proper DVFS support will come in a second time. Signed-off-by: Neil Armstrong Reviewed-by: Martin Blumenstingl Acked-by: Jerome Brunet [narmstrong: fixed cpu clocks namings] Link: https://lkml.kernel.org/r/20190304131129.7762-3-narmstrong@baylibre.com --- drivers/clk/meson/g12a.c | 350 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) (limited to 'drivers/clk/meson/g12a.c') diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 0e1ce8c03259..10ba8bc4646d 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -150,6 +150,318 @@ static struct clk_regmap g12a_sys_pll = { }, }; +static struct clk_regmap g12a_sys_pll_div16_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_pll_div16_en", + .ops = &clk_regmap_gate_ro_ops, + .parent_names = (const char *[]){ "sys_pll" }, + .num_parents = 1, + /* + * This clock is used to debug the sys_pll range + * Linux should not change it at runtime + */ + }, +}; + +static struct clk_fixed_factor g12a_sys_pll_div16 = { + .mult = 1, + .div = 16, + .hw.init = &(struct clk_init_data){ + .name = "sys_pll_div16", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "sys_pll_div16_en" }, + .num_parents = 1, + }, +}; + +/* Datasheet names this field as "premux0" */ +static struct clk_regmap g12a_cpu_clk_premux0 = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x3, + .shift = 0, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn0_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ IN_PREFIX "xtal", + "fclk_div2", + "fclk_div3" }, + .num_parents = 3, + }, +}; + +/* Datasheet names this field as "mux0_divn_tcnt" */ +static struct clk_regmap g12a_cpu_clk_mux0_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .shift = 4, + .width = 6, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn0_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_dyn0_sel" }, + .num_parents = 1, + }, +}; + +/* Datasheet names this field as "postmux0" */ +static struct clk_regmap g12a_cpu_clk_postmux0 = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 2, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn0", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_dyn0_sel", + "cpu_clk_dyn0_div" }, + .num_parents = 2, + }, +}; + +/* Datasheet names this field as "premux1" */ +static struct clk_regmap g12a_cpu_clk_premux1 = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x3, + .shift = 16, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn1_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ IN_PREFIX "xtal", + "fclk_div2", + "fclk_div3" }, + .num_parents = 3, + }, +}; + +/* Datasheet names this field as "Mux1_divn_tcnt" */ +static struct clk_regmap g12a_cpu_clk_mux1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .shift = 20, + .width = 6, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn1_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_dyn1_sel" }, + .num_parents = 1, + }, +}; + +/* Datasheet names this field as "postmux1" */ +static struct clk_regmap g12a_cpu_clk_postmux1 = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 18, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn1", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_dyn1_sel", + "cpu_clk_dyn1_div" }, + .num_parents = 2, + }, +}; + +/* Datasheet names this field as "Final_dyn_mux_sel" */ +static struct clk_regmap g12a_cpu_clk_dyn = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_dyn", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_dyn0", + "cpu_clk_dyn1" }, + .num_parents = 2, + }, +}; + +/* Datasheet names this field as "Final_mux_sel" */ +static struct clk_regmap g12a_cpu_clk = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_SYS_CPU_CLK_CNTL0, + .mask = 0x1, + .shift = 11, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk", + .ops = &clk_regmap_mux_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_dyn", + "sys_pll" }, + .num_parents = 2, + }, +}; + +static struct clk_regmap g12a_cpu_clk_div16_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "cpu_clk_div16_en", + .ops = &clk_regmap_gate_ro_ops, + .parent_names = (const char *[]){ "cpu_clk" }, + .num_parents = 1, + /* + * This clock is used to debug the cpu_clk range + * Linux should not change it at runtime + */ + }, +}; + +static struct clk_fixed_factor g12a_cpu_clk_div16 = { + .mult = 1, + .div = 16, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_div16", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "cpu_clk_div16_en" }, + .num_parents = 1, + }, +}; + +static struct clk_regmap g12a_cpu_clk_apb_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .shift = 3, + .width = 3, + .flags = CLK_DIVIDER_POWER_OF_TWO, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_apb_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "cpu_clk" }, + .num_parents = 1, + }, +}; + +static struct clk_regmap g12a_cpu_clk_apb = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "cpu_clk_apb", + .ops = &clk_regmap_gate_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_apb_div" }, + .num_parents = 1, + /* + * This clock is set by the ROM monitor code, + * Linux should not change it at runtime + */ + }, +}; + +static struct clk_regmap g12a_cpu_clk_atb_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .shift = 6, + .width = 3, + .flags = CLK_DIVIDER_POWER_OF_TWO, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_atb_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "cpu_clk" }, + .num_parents = 1, + }, +}; + +static struct clk_regmap g12a_cpu_clk_atb = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .bit_idx = 17, + }, + .hw.init = &(struct clk_init_data) { + .name = "cpu_clk_atb", + .ops = &clk_regmap_gate_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_atb_div" }, + .num_parents = 1, + /* + * This clock is set by the ROM monitor code, + * Linux should not change it at runtime + */ + }, +}; + +static struct clk_regmap g12a_cpu_clk_axi_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .shift = 9, + .width = 3, + .flags = CLK_DIVIDER_POWER_OF_TWO, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_axi_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "cpu_clk" }, + .num_parents = 1, + }, +}; + +static struct clk_regmap g12a_cpu_clk_axi = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .bit_idx = 18, + }, + .hw.init = &(struct clk_init_data) { + .name = "cpu_clk_axi", + .ops = &clk_regmap_gate_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_axi_div" }, + .num_parents = 1, + /* + * This clock is set by the ROM monitor code, + * Linux should not change it at runtime + */ + }, +}; + +static struct clk_regmap g12a_cpu_clk_trace_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .shift = 20, + .width = 3, + .flags = CLK_DIVIDER_POWER_OF_TWO, + }, + .hw.init = &(struct clk_init_data){ + .name = "cpu_clk_trace_div", + .ops = &clk_regmap_divider_ro_ops, + .parent_names = (const char *[]){ "cpu_clk" }, + .num_parents = 1, + }, +}; + +static struct clk_regmap g12a_cpu_clk_trace = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_SYS_CPU_CLK_CNTL1, + .bit_idx = 23, + }, + .hw.init = &(struct clk_init_data) { + .name = "cpu_clk_trace", + .ops = &clk_regmap_gate_ro_ops, + .parent_names = (const char *[]){ "cpu_clk_trace_div" }, + .num_parents = 1, + /* + * This clock is set by the ROM monitor code, + * Linux should not change it at runtime + */ + }, +}; + static const struct pll_mult_range g12a_gp0_pll_mult_range = { .min = 55, .max = 255, @@ -2167,6 +2479,26 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = { [CLKID_MALI] = &g12a_mali.hw, [CLKID_MPLL_5OM_DIV] = &g12a_mpll_50m_div.hw, [CLKID_MPLL_5OM] = &g12a_mpll_50m.hw, + [CLKID_SYS_PLL_DIV16_EN] = &g12a_sys_pll_div16_en.hw, + [CLKID_SYS_PLL_DIV16] = &g12a_sys_pll_div16.hw, + [CLKID_CPU_CLK_DYN0_SEL] = &g12a_cpu_clk_premux0.hw, + [CLKID_CPU_CLK_DYN0_DIV] = &g12a_cpu_clk_mux0_div.hw, + [CLKID_CPU_CLK_DYN0] = &g12a_cpu_clk_postmux0.hw, + [CLKID_CPU_CLK_DYN1_SEL] = &g12a_cpu_clk_premux1.hw, + [CLKID_CPU_CLK_DYN1_DIV] = &g12a_cpu_clk_mux1_div.hw, + [CLKID_CPU_CLK_DYN1] = &g12a_cpu_clk_postmux1.hw, + [CLKID_CPU_CLK_DYN] = &g12a_cpu_clk_dyn.hw, + [CLKID_CPU_CLK] = &g12a_cpu_clk.hw, + [CLKID_CPU_CLK_DIV16_EN] = &g12a_cpu_clk_div16_en.hw, + [CLKID_CPU_CLK_DIV16] = &g12a_cpu_clk_div16.hw, + [CLKID_CPU_CLK_APB_DIV] = &g12a_cpu_clk_apb_div.hw, + [CLKID_CPU_CLK_APB] = &g12a_cpu_clk_apb.hw, + [CLKID_CPU_CLK_ATB_DIV] = &g12a_cpu_clk_atb_div.hw, + [CLKID_CPU_CLK_ATB] = &g12a_cpu_clk_atb.hw, + [CLKID_CPU_CLK_AXI_DIV] = &g12a_cpu_clk_axi_div.hw, + [CLKID_CPU_CLK_AXI] = &g12a_cpu_clk_axi.hw, + [CLKID_CPU_CLK_TRACE_DIV] = &g12a_cpu_clk_trace_div.hw, + [CLKID_CPU_CLK_TRACE] = &g12a_cpu_clk_trace.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -2335,6 +2667,24 @@ static struct clk_regmap *const g12a_clk_regmaps[] = { &g12a_mali_1, &g12a_mali, &g12a_mpll_50m, + &g12a_sys_pll_div16_en, + &g12a_cpu_clk_premux0, + &g12a_cpu_clk_mux0_div, + &g12a_cpu_clk_postmux0, + &g12a_cpu_clk_premux1, + &g12a_cpu_clk_mux1_div, + &g12a_cpu_clk_postmux1, + &g12a_cpu_clk_dyn, + &g12a_cpu_clk, + &g12a_cpu_clk_div16_en, + &g12a_cpu_clk_apb_div, + &g12a_cpu_clk_apb, + &g12a_cpu_clk_atb_div, + &g12a_cpu_clk_atb, + &g12a_cpu_clk_axi_div, + &g12a_cpu_clk_axi, + &g12a_cpu_clk_trace_div, + &g12a_cpu_clk_trace, }; static const struct meson_eeclkc_data g12a_clkc_data = { -- cgit v1.2.3 From 34775209ba37bff3b4e60ddee0a2d69966146a5d Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Thu, 7 Mar 2019 15:14:55 +0100 Subject: clk: meson-g12a: add PCIE PLL clocks Add the PCIe reference clock feeding the USB3 + PCIE combo PHY. This PLL needs a very precise register sequence to permit to be locked, thus using the specific clk-pll pcie ops. The PLL is then followed by : - a fixed /2 divider - a 5-bit 1-based divider - a final /2 divider This reference clock is fixed to 100MHz, thus only a single PLL setup is added. Signed-off-by: Neil Armstrong Acked-by: Jerome Brunet Link: https://lkml.kernel.org/r/20190307141455.23879-4-narmstrong@baylibre.com --- drivers/clk/meson/g12a.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) (limited to 'drivers/clk/meson/g12a.c') diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 10ba8bc4646d..a47435f91f2f 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -614,6 +614,118 @@ static struct clk_regmap g12a_hifi_pll = { }, }; +/* + * The Meson G12A PCIE PLL is fined tuned to deliver a very precise + * 100MHz reference clock for the PCIe Analog PHY, and thus requires + * a strict register sequence to enable the PLL. + */ +static const struct reg_sequence g12a_pcie_pll_init_regs[] = { + { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x20090496 }, + { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x30090496 }, + { .reg = HHI_PCIE_PLL_CNTL1, .def = 0x00000000 }, + { .reg = HHI_PCIE_PLL_CNTL2, .def = 0x00001100 }, + { .reg = HHI_PCIE_PLL_CNTL3, .def = 0x10058e00 }, + { .reg = HHI_PCIE_PLL_CNTL4, .def = 0x000100c0 }, + { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x68000048 }, + { .reg = HHI_PCIE_PLL_CNTL5, .def = 0x68000068, .delay_us = 20 }, + { .reg = HHI_PCIE_PLL_CNTL4, .def = 0x008100c0, .delay_us = 10 }, + { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x34090496 }, + { .reg = HHI_PCIE_PLL_CNTL0, .def = 0x14090496, .delay_us = 10 }, + { .reg = HHI_PCIE_PLL_CNTL2, .def = 0x00001000 }, +}; + +/* Keep a single entry table for recalc/round_rate() ops */ +static const struct pll_params_table g12a_pcie_pll_table[] = { + PLL_PARAMS(150, 1), + {0, 0}, +}; + +static struct clk_regmap g12a_pcie_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = HHI_PCIE_PLL_CNTL1, + .shift = 0, + .width = 12, + }, + .l = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = HHI_PCIE_PLL_CNTL0, + .shift = 29, + .width = 1, + }, + .table = g12a_pcie_pll_table, + .init_regs = g12a_pcie_pll_init_regs, + .init_count = ARRAY_SIZE(g12a_pcie_pll_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "pcie_pll_dco", + .ops = &meson_clk_pcie_pll_ops, + .parent_names = (const char *[]){ IN_PREFIX "xtal" }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor g12a_pcie_pll_dco_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "pcie_pll_dco_div2", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "pcie_pll_dco" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_pcie_pll_od = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_PCIE_PLL_CNTL0, + .shift = 16, + .width = 5, + .flags = CLK_DIVIDER_ROUND_CLOSEST | + CLK_DIVIDER_ONE_BASED | + CLK_DIVIDER_ALLOW_ZERO, + }, + .hw.init = &(struct clk_init_data){ + .name = "pcie_pll_od", + .ops = &clk_regmap_divider_ops, + .parent_names = (const char *[]){ "pcie_pll_dco_div2" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_fixed_factor g12a_pcie_pll = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "pcie_pll_pll", + .ops = &clk_fixed_factor_ops, + .parent_names = (const char *[]){ "pcie_pll_od" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + static struct clk_regmap g12a_hdmi_pll_dco = { .data = &(struct meson_clk_pll_data){ .en = { @@ -2499,6 +2611,10 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = { [CLKID_CPU_CLK_AXI] = &g12a_cpu_clk_axi.hw, [CLKID_CPU_CLK_TRACE_DIV] = &g12a_cpu_clk_trace_div.hw, [CLKID_CPU_CLK_TRACE] = &g12a_cpu_clk_trace.hw, + [CLKID_PCIE_PLL_DCO] = &g12a_pcie_pll_dco.hw, + [CLKID_PCIE_PLL_DCO_DIV2] = &g12a_pcie_pll_dco_div2.hw, + [CLKID_PCIE_PLL_OD] = &g12a_pcie_pll_od.hw, + [CLKID_PCIE_PLL] = &g12a_pcie_pll.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -2685,6 +2801,8 @@ static struct clk_regmap *const g12a_clk_regmaps[] = { &g12a_cpu_clk_axi, &g12a_cpu_clk_trace_div, &g12a_cpu_clk_trace, + &g12a_pcie_pll_od, + &g12a_pcie_pll_dco, }; static const struct meson_eeclkc_data g12a_clkc_data = { -- cgit v1.2.3 From 4b0f73055acaced436d5de909b26d001ea7f667c Mon Sep 17 00:00:00 2001 From: Maxime Jourdan Date: Tue, 19 Mar 2019 11:11:38 +0100 Subject: clk: meson-g12a: add video decoder clocks Add the necessary clock parts for: - VDEC_1: used to feed VDEC_1 - VDEC_HEVC: the "back" part of the VDEC_HEVC block - VDEC_HEVCF: the "front" part of the VDEC_HEVC block In previous SoC generations (GXL, GXBB), there was only one VDEC_HEVC clock, which got split in two parts for G12A. Signed-off-by: Maxime Jourdan Acked-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://lkml.kernel.org/r/20190319101138.27520-2-mjourdan@baylibre.com --- drivers/clk/meson/g12a.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) (limited to 'drivers/clk/meson/g12a.c') diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index a47435f91f2f..86a7c1b5bd42 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -1495,6 +1495,151 @@ static struct clk_regmap g12a_vpu = { }, }; +/* VDEC clocks */ + +static const char * const g12a_vdec_parent_names[] = { + "fclk_div2p5", "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7", + "hifi_pll", "gp0_pll", +}; + +static struct clk_regmap g12a_vdec_1_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VDEC_CLK_CNTL, + .mask = 0x7, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_1_sel", + .ops = &clk_regmap_mux_ops, + .parent_names = g12a_vdec_parent_names, + .num_parents = ARRAY_SIZE(g12a_vdec_parent_names), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_vdec_1_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VDEC_CLK_CNTL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_1_div", + .ops = &clk_regmap_divider_ops, + .parent_names = (const char *[]){ "vdec_1_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_vdec_1 = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VDEC_CLK_CNTL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_1", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "vdec_1_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_vdec_hevcf_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .mask = 0x7, + .shift = 9, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_hevcf_sel", + .ops = &clk_regmap_mux_ops, + .parent_names = g12a_vdec_parent_names, + .num_parents = ARRAY_SIZE(g12a_vdec_parent_names), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_vdec_hevcf_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .shift = 0, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_hevcf_div", + .ops = &clk_regmap_divider_ops, + .parent_names = (const char *[]){ "vdec_hevcf_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_vdec_hevcf = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_hevcf", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "vdec_hevcf_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_vdec_hevc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .mask = 0x7, + .shift = 25, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_hevc_sel", + .ops = &clk_regmap_mux_ops, + .parent_names = g12a_vdec_parent_names, + .num_parents = ARRAY_SIZE(g12a_vdec_parent_names), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_vdec_hevc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .shift = 16, + .width = 7, + .flags = CLK_DIVIDER_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "vdec_hevc_div", + .ops = &clk_regmap_divider_ops, + .parent_names = (const char *[]){ "vdec_hevc_sel" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap g12a_vdec_hevc = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VDEC2_CLK_CNTL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "vdec_hevc", + .ops = &clk_regmap_gate_ops, + .parent_names = (const char *[]){ "vdec_hevc_div" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + /* VAPB Clock */ static const char * const g12a_vapb_parent_names[] = { @@ -2615,6 +2760,15 @@ static struct clk_hw_onecell_data g12a_hw_onecell_data = { [CLKID_PCIE_PLL_DCO_DIV2] = &g12a_pcie_pll_dco_div2.hw, [CLKID_PCIE_PLL_OD] = &g12a_pcie_pll_od.hw, [CLKID_PCIE_PLL] = &g12a_pcie_pll.hw, + [CLKID_VDEC_1_SEL] = &g12a_vdec_1_sel.hw, + [CLKID_VDEC_1_DIV] = &g12a_vdec_1_div.hw, + [CLKID_VDEC_1] = &g12a_vdec_1.hw, + [CLKID_VDEC_HEVC_SEL] = &g12a_vdec_hevc_sel.hw, + [CLKID_VDEC_HEVC_DIV] = &g12a_vdec_hevc_div.hw, + [CLKID_VDEC_HEVC] = &g12a_vdec_hevc.hw, + [CLKID_VDEC_HEVCF_SEL] = &g12a_vdec_hevcf_sel.hw, + [CLKID_VDEC_HEVCF_DIV] = &g12a_vdec_hevcf_div.hw, + [CLKID_VDEC_HEVCF] = &g12a_vdec_hevcf.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -2803,6 +2957,15 @@ static struct clk_regmap *const g12a_clk_regmaps[] = { &g12a_cpu_clk_trace, &g12a_pcie_pll_od, &g12a_pcie_pll_dco, + &g12a_vdec_1_sel, + &g12a_vdec_1_div, + &g12a_vdec_1, + &g12a_vdec_hevc_sel, + &g12a_vdec_hevc_div, + &g12a_vdec_hevc, + &g12a_vdec_hevcf_sel, + &g12a_vdec_hevcf_div, + &g12a_vdec_hevcf, }; static const struct meson_eeclkc_data g12a_clkc_data = { -- cgit v1.2.3