Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/clk/meson/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 105 kB image not shown  

Quelle  meson8b.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2015 Endless Mobile, Inc.
 * Author: Carlo Caione <carlo@endlessm.com>
 *
 * Copyright (c) 2016 BayLibre, Inc.
 * Michael Turquette <mturquette@baylibre.com>
 */


#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>
#include <linux/regmap.h>

#include "clk-regmap.h"
#include "meson-clkc-utils.h"
#include "clk-pll.h"
#include "clk-mpll.h"

#include <dt-bindings/clock/meson8b-clkc.h>
#include <dt-bindings/reset/amlogic,meson8b-clkc-reset.h>

/*
 * Clock controller register offsets
 *
 * Register offsets from the HardKernel[0] data sheet must be multiplied
 * by 4 before adding them to the base address to get the right value
 *
 * [0] https://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
 */

#define HHI_GP_PLL_CNTL   0x40
#define HHI_GP_PLL_CNTL2  0x44
#define HHI_GP_PLL_CNTL3  0x48
#define HHI_GP_PLL_CNTL4  0x4C
#define HHI_GP_PLL_CNTL5  0x50
#define HHI_VIID_CLK_DIV  0x128
#define HHI_VIID_CLK_CNTL  0x12c
#define HHI_GCLK_MPEG0   0x140
#define HHI_GCLK_MPEG1   0x144
#define HHI_GCLK_MPEG2   0x148
#define HHI_GCLK_OTHER   0x150
#define HHI_GCLK_AO   0x154
#define HHI_SYS_CPU_CLK_CNTL1  0x15c
#define HHI_VID_CLK_DIV   0x164
#define HHI_MPEG_CLK_CNTL  0x174
#define HHI_AUD_CLK_CNTL  0x178
#define HHI_VID_CLK_CNTL  0x17c
#define HHI_AUD_CLK_CNTL2  0x190
#define HHI_VID_CLK_CNTL2  0x194
#define HHI_VID_DIVIDER_CNTL  0x198
#define HHI_SYS_CPU_CLK_CNTL0  0x19c
#define HHI_MALI_CLK_CNTL  0x1b0
#define HHI_VPU_CLK_CNTL  0x1bc
#define HHI_HDMI_CLK_CNTL  0x1cc
#define HHI_VDEC_CLK_CNTL  0x1e0
#define HHI_VDEC2_CLK_CNTL  0x1e4
#define HHI_VDEC3_CLK_CNTL  0x1e8
#define HHI_NAND_CLK_CNTL  0x25c
#define HHI_MPLL_CNTL   0x280
#define HHI_SYS_PLL_CNTL  0x300
#define HHI_VID_PLL_CNTL  0x320
#define HHI_VID_PLL_CNTL2  0x324
#define HHI_VID_PLL_CNTL3  0x328
#define HHI_VID_PLL_CNTL4  0x32c
#define HHI_VID_PLL_CNTL5  0x330
#define HHI_VID_PLL_CNTL6  0x334
#define HHI_VID2_PLL_CNTL  0x380
#define HHI_VID2_PLL_CNTL2  0x384
#define HHI_VID2_PLL_CNTL3  0x388
#define HHI_VID2_PLL_CNTL4  0x38c
#define HHI_VID2_PLL_CNTL5  0x390
#define HHI_VID2_PLL_CNTL6  0x394

/*
 * MPLL register offeset taken from the S905 datasheet. Vendor kernel source
 * confirm these are the same for the S805.
 */

#define HHI_MPLL_CNTL   0x280
#define HHI_MPLL_CNTL2   0x284
#define HHI_MPLL_CNTL3   0x288
#define HHI_MPLL_CNTL4   0x28c
#define HHI_MPLL_CNTL5   0x290
#define HHI_MPLL_CNTL6   0x294
#define HHI_MPLL_CNTL7   0x298
#define HHI_MPLL_CNTL8   0x29c
#define HHI_MPLL_CNTL9   0x2a0
#define HHI_MPLL_CNTL10   0x2a4

struct meson8b_clk_reset {
 struct reset_controller_dev reset;
 struct regmap *regmap;
};

static const struct pll_params_table sys_pll_params_table[] = {
 PLL_PARAMS(50, 1),
 PLL_PARAMS(51, 1),
 PLL_PARAMS(52, 1),
 PLL_PARAMS(53, 1),
 PLL_PARAMS(54, 1),
 PLL_PARAMS(55, 1),
 PLL_PARAMS(56, 1),
 PLL_PARAMS(57, 1),
 PLL_PARAMS(58, 1),
 PLL_PARAMS(59, 1),
 PLL_PARAMS(60, 1),
 PLL_PARAMS(61, 1),
 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 */ },
};

static struct clk_regmap meson8b_fixed_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_MPLL_CNTL,
   .shift   = 30,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_MPLL_CNTL,
   .shift   = 0,
   .width   = 9,
  },
  .n = {
   .reg_off = HHI_MPLL_CNTL,
   .shift   = 9,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_MPLL_CNTL2,
   .shift   = 0,
   .width   = 12,
  },
  .l = {
   .reg_off = HHI_MPLL_CNTL,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_MPLL_CNTL,
   .shift   = 29,
   .width   = 1,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "fixed_pll_dco",
  .ops = &meson_clk_pll_ro_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
   .name = "xtal",
   .index = -1,
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_fixed_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_MPLL_CNTL,
  .shift = 16,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fixed_pll",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fixed_pll_dco.hw
  },
  .num_parents = 1,
  /*
 * This clock won't ever change at runtime so
 * CLK_SET_RATE_PARENT is not required
 */

 },
};

static struct clk_fixed_factor hdmi_pll_dco_in = {
 .mult = 2,
 .div = 1,
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_dco_in",
  .ops = &clk_fixed_factor_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
   .index = -1,
  },
  .num_parents = 1,
 },
};

/*
 * Taken from the vendor driver for the 2970/2975MHz (both only differ in the
 * FRAC part in HHI_VID_PLL_CNTL2) where these values are identical for Meson8,
 * Meson8b and Meson8m2. This doubles the input (or output - it's not clear
 * which one but the result is the same) clock. The vendor driver additionally
 * has the following comment about: "optimise HPLL VCO 2.97GHz performance".
 */

static const struct reg_sequence meson8b_hdmi_pll_init_regs[] = {
 { .reg = HHI_VID_PLL_CNTL2, .def = 0x69c84000 },
 { .reg = HHI_VID_PLL_CNTL3, .def = 0x8a46c023 },
 { .reg = HHI_VID_PLL_CNTL4, .def = 0x4123b100 },
 { .reg = HHI_VID_PLL_CNTL5, .def = 0x00012385 },
 { .reg = HHI_VID2_PLL_CNTL2, .def = 0x0430a800 },
};

static const struct pll_params_table hdmi_pll_params_table[] = {
 PLL_PARAMS(40, 1),
 PLL_PARAMS(42, 1),
 PLL_PARAMS(44, 1),
 PLL_PARAMS(45, 1),
 PLL_PARAMS(49, 1),
 PLL_PARAMS(52, 1),
 PLL_PARAMS(54, 1),
 PLL_PARAMS(56, 1),
 PLL_PARAMS(59, 1),
 PLL_PARAMS(60, 1),
 PLL_PARAMS(61, 1),
 PLL_PARAMS(62, 1),
 PLL_PARAMS(64, 1),
 PLL_PARAMS(66, 1),
 PLL_PARAMS(68, 1),
 PLL_PARAMS(71, 1),
 PLL_PARAMS(82, 1),
 { /* sentinel */ }
};

static struct clk_regmap meson8b_hdmi_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_VID_PLL_CNTL,
   .shift   = 30,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_VID_PLL_CNTL,
   .shift   = 0,
   .width   = 9,
  },
  .n = {
   .reg_off = HHI_VID_PLL_CNTL,
   .shift   = 10,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_VID_PLL_CNTL2,
   .shift   = 0,
   .width   = 12,
  },
  .l = {
   .reg_off = HHI_VID_PLL_CNTL,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_VID_PLL_CNTL,
   .shift   = 29,
   .width   = 1,
  },
  .table = hdmi_pll_params_table,
  .init_regs = meson8b_hdmi_pll_init_regs,
  .init_count = ARRAY_SIZE(meson8b_hdmi_pll_init_regs),
 },
 .hw.init = &(struct clk_init_data){
  /* sometimes also called "HPLL" or "HPLL PLL" */
  .name = "hdmi_pll_dco",
  .ops = &meson_clk_pll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &hdmi_pll_dco_in.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_hdmi_pll_lvds_out = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_VID_PLL_CNTL,
  .shift = 16,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_lvds_out",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_hdmi_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_hdmi_pll_hdmi_out = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_VID_PLL_CNTL,
  .shift = 18,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_hdmi_out",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_hdmi_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_sys_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_SYS_PLL_CNTL,
   .shift   = 30,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_SYS_PLL_CNTL,
   .shift   = 0,
   .width   = 9,
  },
  .n = {
   .reg_off = HHI_SYS_PLL_CNTL,
   .shift   = 9,
   .width   = 5,
  },
  .l = {
   .reg_off = HHI_SYS_PLL_CNTL,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_SYS_PLL_CNTL,
   .shift   = 29,
   .width   = 1,
  },
  .table = sys_pll_params_table,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sys_pll_dco",
  .ops = &meson_clk_pll_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
   .name = "xtal",
   .index = -1,
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_sys_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_SYS_PLL_CNTL,
  .shift = 16,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sys_pll",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_sys_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_fclk_div2_div = {
 .mult = 1,
 .div = 2,
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div2_div",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fixed_pll.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_fclk_div2 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPLL_CNTL6,
  .bit_idx = 27,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div2",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fclk_div2_div.hw
  },
  .num_parents = 1,
 },
};

static struct clk_fixed_factor meson8b_fclk_div3_div = {
 .mult = 1,
 .div = 3,
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div3_div",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fixed_pll.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_fclk_div3 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPLL_CNTL6,
  .bit_idx = 28,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div3",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fclk_div3_div.hw
  },
  .num_parents = 1,
 },
};

static struct clk_fixed_factor meson8b_fclk_div4_div = {
 .mult = 1,
 .div = 4,
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div4_div",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fixed_pll.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_fclk_div4 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPLL_CNTL6,
  .bit_idx = 29,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div4",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fclk_div4_div.hw
  },
  .num_parents = 1,
 },
};

static struct clk_fixed_factor meson8b_fclk_div5_div = {
 .mult = 1,
 .div = 5,
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div5_div",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fixed_pll.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_fclk_div5 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPLL_CNTL6,
  .bit_idx = 30,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div5",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fclk_div5_div.hw
  },
  .num_parents = 1,
 },
};

static struct clk_fixed_factor meson8b_fclk_div7_div = {
 .mult = 1,
 .div = 7,
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div7_div",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fixed_pll.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_fclk_div7 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPLL_CNTL6,
  .bit_idx = 31,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div7",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fclk_div7_div.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_mpll_prediv = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_MPLL_CNTL5,
  .shift = 12,
  .width = 1,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll_prediv",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fixed_pll.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_mpll0_div = {
 .data = &(struct meson_clk_mpll_data){
  .sdm = {
   .reg_off = HHI_MPLL_CNTL7,
   .shift   = 0,
   .width   = 14,
  },
  .sdm_en = {
   .reg_off = HHI_MPLL_CNTL7,
   .shift   = 15,
   .width   = 1,
  },
  .n2 = {
   .reg_off = HHI_MPLL_CNTL7,
   .shift   = 16,
   .width   = 9,
  },
  .ssen = {
   .reg_off = HHI_MPLL_CNTL,
   .shift   = 25,
   .width   = 1,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll0_div",
  .ops = &meson_clk_mpll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mpll_prediv.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_mpll0 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPLL_CNTL7,
  .bit_idx = 14,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll0",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mpll0_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_mpll1_div = {
 .data = &(struct meson_clk_mpll_data){
  .sdm = {
   .reg_off = HHI_MPLL_CNTL8,
   .shift   = 0,
   .width   = 14,
  },
  .sdm_en = {
   .reg_off = HHI_MPLL_CNTL8,
   .shift   = 15,
   .width   = 1,
  },
  .n2 = {
   .reg_off = HHI_MPLL_CNTL8,
   .shift   = 16,
   .width   = 9,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll1_div",
  .ops = &meson_clk_mpll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mpll_prediv.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_mpll1 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPLL_CNTL8,
  .bit_idx = 14,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll1",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mpll1_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_mpll2_div = {
 .data = &(struct meson_clk_mpll_data){
  .sdm = {
   .reg_off = HHI_MPLL_CNTL9,
   .shift   = 0,
   .width   = 14,
  },
  .sdm_en = {
   .reg_off = HHI_MPLL_CNTL9,
   .shift   = 15,
   .width   = 1,
  },
  .n2 = {
   .reg_off = HHI_MPLL_CNTL9,
   .shift   = 16,
   .width   = 9,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll2_div",
  .ops = &meson_clk_mpll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mpll_prediv.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_mpll2 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPLL_CNTL9,
  .bit_idx = 14,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll2",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mpll2_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static u32 mux_table_clk81[] = { 6, 5, 7 };
static struct clk_regmap meson8b_mpeg_clk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_MPEG_CLK_CNTL,
  .mask = 0x7,
  .shift = 12,
  .table = mux_table_clk81,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpeg_clk_sel",
  .ops = &clk_regmap_mux_ro_ops,
  /*
 * FIXME bits 14:12 selects from 8 possible parents:
 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
 * fclk_div4, fclk_div3, fclk_div5
 */

  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_fclk_div3.hw,
   &meson8b_fclk_div4.hw,
   &meson8b_fclk_div5.hw,
  },
  .num_parents = 3,
 },
};

static struct clk_regmap meson8b_mpeg_clk_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_MPEG_CLK_CNTL,
  .shift = 0,
  .width = 7,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpeg_clk_div",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mpeg_clk_sel.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8b_clk81 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MPEG_CLK_CNTL,
  .bit_idx = 7,
 },
 .hw.init = &(struct clk_init_data){
  .name = "clk81",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mpeg_clk_div.hw
  },
  .num_parents = 1,
  .flags = CLK_IS_CRITICAL,
 },
};

static struct clk_regmap meson8b_cpu_in_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL0,
  .mask = 0x1,
  .shift = 0,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu_in_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = (const struct clk_parent_data[]) {
   { .fw_name = "xtal", .name = "xtal", .index = -1, },
   { .hw = &meson8b_sys_pll.hw, },
  },
  .num_parents = 2,
  .flags = (CLK_SET_RATE_PARENT |
     CLK_SET_RATE_NO_REPARENT),
 },
};

static struct clk_fixed_factor meson8b_cpu_in_div2 = {
 .mult = 1,
 .div = 2,
 .hw.init = &(struct clk_init_data){
  .name = "cpu_in_div2",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_in_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_cpu_in_div3 = {
 .mult = 1,
 .div = 3,
 .hw.init = &(struct clk_init_data){
  .name = "cpu_in_div3",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_in_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct clk_div_table cpu_scale_table[] = {
 { .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 */ },
};

static struct clk_regmap meson8b_cpu_scale_div = {
 .data = &(struct clk_regmap_div_data){
  .offset =  HHI_SYS_CPU_CLK_CNTL1,
  .shift = 20,
  .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_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_in_sel.hw
  },
  .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_ops,
  /*
 * NOTE: We are skipping the parent with value 0x2 (which is
 * meson8b_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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_in_sel.hw,
   &meson8b_cpu_in_div2.hw,
   &meson8b_cpu_scale_div.hw,
  },
  .num_parents = 3,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cpu_clk = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL0,
  .mask = 0x1,
  .shift = 7,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu_clk",
  .ops = &clk_regmap_mux_ops,
  .parent_data = (const struct clk_parent_data[]) {
   { .fw_name = "xtal", .name = "xtal", .index = -1, },
   { .hw = &meson8b_cpu_scale_out_sel.hw, },
  },
  .num_parents = 2,
  .flags = (CLK_SET_RATE_PARENT |
     CLK_SET_RATE_NO_REPARENT |
     CLK_IS_CRITICAL),
 },
};

static struct clk_regmap meson8b_nand_clk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_NAND_CLK_CNTL,
  .mask = 0x7,
  .shift = 9,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "nand_clk_sel",
  .ops = &clk_regmap_mux_ops,
  /* FIXME all other parents are unknown: */
  .parent_data = (const struct clk_parent_data[]) {
   { .hw = &meson8b_fclk_div4.hw, },
   { .hw = &meson8b_fclk_div3.hw, },
   { .hw = &meson8b_fclk_div5.hw, },
   { .hw = &meson8b_fclk_div7.hw, },
   { .fw_name = "xtal", .name = "xtal", .index = -1, },
  },
  .num_parents = 5,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_nand_clk_div = {
 .data = &(struct clk_regmap_div_data){
  .offset =  HHI_NAND_CLK_CNTL,
  .shift = 0,
  .width = 7,
  .flags = CLK_DIVIDER_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "nand_clk_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_nand_clk_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_nand_clk_gate = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_NAND_CLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data){
  .name = "nand_clk_gate",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_nand_clk_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk.hw
  },
  .num_parents = 1,
 },
};

static u32 mux_table_apb[] = { 1, 2, 3, 4, 5, 6, 7 };
static struct clk_regmap meson8b_apb_clk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL1,
  .mask = 0x7,
  .shift = 3,
  .table = mux_table_apb,
 },
 .hw.init = &(struct clk_init_data){
  .name = "apb_clk_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk_div2.hw,
   &meson8b_cpu_clk_div3.hw,
   &meson8b_cpu_clk_div4.hw,
   &meson8b_cpu_clk_div5.hw,
   &meson8b_cpu_clk_div6.hw,
   &meson8b_cpu_clk_div7.hw,
   &meson8b_cpu_clk_div8.hw,
  },
  .num_parents = 7,
 },
};

static struct clk_regmap meson8b_apb_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 = "apb_clk_dis",
  .ops = &clk_regmap_gate_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_apb_clk_sel.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk_div2.hw,
   &meson8b_cpu_clk_div3.hw,
   &meson8b_cpu_clk_div4.hw,
   &meson8b_cpu_clk_div5.hw,
   &meson8b_cpu_clk_div6.hw,
   &meson8b_cpu_clk_div7.hw,
   &meson8b_cpu_clk_div8.hw,
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_periph_clk_sel.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk_div2.hw,
   &meson8b_cpu_clk_div3.hw,
   &meson8b_cpu_clk_div4.hw,
   &meson8b_cpu_clk_div5.hw,
   &meson8b_cpu_clk_div6.hw,
   &meson8b_cpu_clk_div7.hw,
   &meson8b_cpu_clk_div8.hw,
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_axi_clk_sel.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_cpu_clk_div2.hw,
   &meson8b_cpu_clk_div3.hw,
   &meson8b_cpu_clk_div4.hw,
   &meson8b_cpu_clk_div5.hw,
   &meson8b_cpu_clk_div6.hw,
   &meson8b_cpu_clk_div7.hw,
   &meson8b_cpu_clk_div8.hw,
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_l2_dram_clk_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* also called LVDS_CLK_EN */
static struct clk_regmap meson8b_vid_pll_lvds_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_DIVIDER_CNTL,
  .bit_idx = 11,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vid_pll_lvds_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_hdmi_pll_lvds_out.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vid_pll_in_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_DIVIDER_CNTL,
  .mask = 0x1,
  .shift = 15,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vid_pll_in_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * TODO: depending on the SoC there is also a second parent:
 * Meson8: unknown
 * Meson8b: hdmi_pll_dco
 * Meson8m2: vid2_pll
 */

  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vid_pll_lvds_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vid_pll_in_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_DIVIDER_CNTL,
  .bit_idx = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vid_pll_in_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vid_pll_in_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vid_pll_pre_div = {
 .data = &(struct clk_regmap_div_data){
  .offset =  HHI_VID_DIVIDER_CNTL,
  .shift = 4,
  .width = 3,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vid_pll_pre_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vid_pll_in_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vid_pll_post_div = {
 .data = &(struct clk_regmap_div_data){
  .offset =  HHI_VID_DIVIDER_CNTL,
  .shift = 12,
  .width = 3,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vid_pll_post_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vid_pll_pre_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vid_pll = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_DIVIDER_CNTL,
  .mask = 0x3,
  .shift = 8,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vid_pll",
  .ops = &clk_regmap_mux_ops,
  /* TODO: parent 0x2 is vid_pll_pre_div_mult7_div2 */
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vid_pll_pre_div.hw,
   &meson8b_vid_pll_post_div.hw,
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vid_pll_final_div = {
 .data = &(struct clk_regmap_div_data){
  .offset =  HHI_VID_CLK_DIV,
  .shift = 0,
  .width = 8,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vid_pll_final_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vid_pll.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct clk_hw *meson8b_vclk_mux_parent_hws[] = {
 &meson8b_vid_pll_final_div.hw,
 &meson8b_fclk_div4.hw,
 &meson8b_fclk_div3.hw,
 &meson8b_fclk_div5.hw,
 &meson8b_vid_pll_final_div.hw,
 &meson8b_fclk_div7.hw,
 &meson8b_mpll1.hw,
};

static struct clk_regmap meson8b_vclk_in_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_CLK_CNTL,
  .mask = 0x7,
  .shift = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk_in_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vclk_mux_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parent_hws),
  .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
 },
};

static struct clk_regmap meson8b_vclk_in_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_DIV,
  .bit_idx = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk_in_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_in_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vclk_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL,
  .bit_idx = 19,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_in_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vclk_div1_gate = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL,
  .bit_idx = 0,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk_div1_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_vclk_div2_div = {
 .mult = 1,
 .div = 2,
 .hw.init = &(struct clk_init_data){
  .name = "vclk_div2",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 }
};

static struct clk_regmap meson8b_vclk_div2_div_gate = {
 .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_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_div2_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_vclk_div4_div = {
 .mult = 1,
 .div = 4,
 .hw.init = &(struct clk_init_data){
  .name = "vclk_div4",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 }
};

static struct clk_regmap meson8b_vclk_div4_div_gate = {
 .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_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_div4_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_vclk_div6_div = {
 .mult = 1,
 .div = 6,
 .hw.init = &(struct clk_init_data){
  .name = "vclk_div6",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 }
};

static struct clk_regmap meson8b_vclk_div6_div_gate = {
 .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_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_div6_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_vclk_div12_div = {
 .mult = 1,
 .div = 12,
 .hw.init = &(struct clk_init_data){
  .name = "vclk_div12",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 }
};

static struct clk_regmap meson8b_vclk_div12_div_gate = {
 .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_hws = (const struct clk_hw *[]) {
   &meson8b_vclk_div12_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vclk2_in_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VIID_CLK_CNTL,
  .mask = 0x7,
  .shift = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_in_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vclk_mux_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vclk_mux_parent_hws),
  .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
 },
};

static struct clk_regmap meson8b_vclk2_clk_in_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_DIV,
  .bit_idx = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_in_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_in_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vclk2_clk_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_DIV,
  .bit_idx = 19,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_clk_in_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vclk2_div1_gate = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_DIV,
  .bit_idx = 0,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div1_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_clk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_vclk2_div2_div = {
 .mult = 1,
 .div = 2,
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div2",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_clk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 }
};

static struct clk_regmap meson8b_vclk2_div2_div_gate = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_DIV,
  .bit_idx = 1,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div2_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_div2_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_vclk2_div4_div = {
 .mult = 1,
 .div = 4,
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div4",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_clk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 }
};

static struct clk_regmap meson8b_vclk2_div4_div_gate = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_DIV,
  .bit_idx = 2,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div4_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_div4_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_vclk2_div6_div = {
 .mult = 1,
 .div = 6,
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div6",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_clk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 }
};

static struct clk_regmap meson8b_vclk2_div6_div_gate = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_DIV,
  .bit_idx = 3,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div6_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_div6_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor meson8b_vclk2_div12_div = {
 .mult = 1,
 .div = 12,
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div12",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_clk_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 }
};

static struct clk_regmap meson8b_vclk2_div12_div_gate = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_DIV,
  .bit_idx = 4,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div12_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vclk2_div12_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct clk_hw *meson8b_vclk_enc_mux_parent_hws[] = {
 &meson8b_vclk_div1_gate.hw,
 &meson8b_vclk_div2_div_gate.hw,
 &meson8b_vclk_div4_div_gate.hw,
 &meson8b_vclk_div6_div_gate.hw,
 &meson8b_vclk_div12_div_gate.hw,
};

static struct clk_regmap meson8b_cts_enct_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_CLK_DIV,
  .mask = 0xf,
  .shift = 20,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_enct_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vclk_enc_mux_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_enct = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL2,
  .bit_idx = 1,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_enct",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cts_enct_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_encp_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_CLK_DIV,
  .mask = 0xf,
  .shift = 24,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_encp_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vclk_enc_mux_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_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_hws = (const struct clk_hw *[]) {
   &meson8b_cts_encp_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_enci_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_CLK_DIV,
  .mask = 0xf,
  .shift = 28,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_enci_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vclk_enc_mux_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_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_hws = (const struct clk_hw *[]) {
   &meson8b_cts_enci_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_hdmi_tx_pixel_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_HDMI_CLK_CNTL,
  .mask = 0xf,
  .shift = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_tx_pixel_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vclk_enc_mux_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vclk_enc_mux_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_hdmi_tx_pixel = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL2,
  .bit_idx = 5,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_tx_pixel",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_hdmi_tx_pixel_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct clk_hw *meson8b_vclk2_enc_mux_parent_hws[] = {
 &meson8b_vclk2_div1_gate.hw,
 &meson8b_vclk2_div2_div_gate.hw,
 &meson8b_vclk2_div4_div_gate.hw,
 &meson8b_vclk2_div6_div_gate.hw,
 &meson8b_vclk2_div12_div_gate.hw,
};

static struct clk_regmap meson8b_cts_encl_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VIID_CLK_DIV,
  .mask = 0xf,
  .shift = 12,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_encl_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vclk2_enc_mux_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_encl = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL2,
  .bit_idx = 3,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_encl",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cts_encl_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_vdac0_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VIID_CLK_DIV,
  .mask = 0xf,
  .shift = 28,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_vdac0_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vclk2_enc_mux_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vclk2_enc_mux_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_vdac0 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL2,
  .bit_idx = 4,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_vdac0",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cts_vdac0_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_hdmi_sys_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_sys_sel",
  .ops = &clk_regmap_mux_ops,
  /* FIXME: all other parents are unknown */
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
   .name = "xtal",
   .index = -1,
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

static struct clk_regmap meson8b_hdmi_sys_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_CLK_CNTL,
  .shift = 0,
  .width = 7,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_sys_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_hdmi_sys_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_hdmi_sys = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_HDMI_CLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "hdmi_sys",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_hdmi_sys_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/*
 * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
 * muxed by a glitch-free switch on Meson8b and Meson8m2. The CCF can
 * actually manage this glitch-free mux because it does top-to-bottom
 * updates the each clock tree and switches to the "inactive" one when
 * CLK_SET_RATE_GATE is set.
 * Meson8 only has mali_0 and no glitch-free mux.
 */

static const struct clk_parent_data meson8b_mali_0_1_parent_data[] = {
 { .fw_name = "xtal", .name = "xtal", .index = -1, },
 { .hw = &meson8b_mpll2.hw, },
 { .hw = &meson8b_mpll1.hw, },
 { .hw = &meson8b_fclk_div7.hw, },
 { .hw = &meson8b_fclk_div4.hw, },
 { .hw = &meson8b_fclk_div3.hw, },
 { .hw = &meson8b_fclk_div5.hw, },
};

static u32 meson8b_mali_0_1_mux_table[] = { 0, 2, 3, 4, 5, 6, 7 };

static struct clk_regmap meson8b_mali_0_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_MALI_CLK_CNTL,
  .mask = 0x7,
  .shift = 9,
  .table = meson8b_mali_0_1_mux_table,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali_0_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = meson8b_mali_0_1_parent_data,
  .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_data),
  /*
 * Don't propagate rate changes up because the only changeable
 * parents are mpll1 and mpll2 but we need those for audio and
 * RGMII (Ethernet). We don't want to change the audio or
 * Ethernet clocks when setting the GPU frequency.
 */

  .flags = 0,
 },
};

static struct clk_regmap meson8b_mali_0_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_MALI_CLK_CNTL,
  .shift = 0,
  .width = 7,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali_0_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mali_0_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_mali_0 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MALI_CLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali_0",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mali_0_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_mali_1_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_MALI_CLK_CNTL,
  .mask = 0x7,
  .shift = 25,
  .table = meson8b_mali_0_1_mux_table,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali_1_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = meson8b_mali_0_1_parent_data,
  .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_data),
  /*
 * Don't propagate rate changes up because the only changeable
 * parents are mpll1 and mpll2 but we need those for audio and
 * RGMII (Ethernet). We don't want to change the audio or
 * Ethernet clocks when setting the GPU frequency.
 */

  .flags = 0,
 },
};

static struct clk_regmap meson8b_mali_1_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_MALI_CLK_CNTL,
  .shift = 16,
  .width = 7,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali_1_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mali_1_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_mali_1 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_MALI_CLK_CNTL,
  .bit_idx = 24,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali_1",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mali_1_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_mali = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_MALI_CLK_CNTL,
  .mask = 1,
  .shift = 31,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_mali_0.hw,
   &meson8b_mali_1.hw,
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct reg_sequence meson8m2_gp_pll_init_regs[] = {
 { .reg = HHI_GP_PLL_CNTL2, .def = 0x59c88000 },
 { .reg = HHI_GP_PLL_CNTL3, .def = 0xca463823 },
 { .reg = HHI_GP_PLL_CNTL4, .def = 0x0286a027 },
 { .reg = HHI_GP_PLL_CNTL5, .def = 0x00003000 },
};

static const struct pll_params_table meson8m2_gp_pll_params_table[] = {
 PLL_PARAMS(182, 3),
 { /* sentinel */ },
};

static struct clk_regmap meson8m2_gp_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_GP_PLL_CNTL,
   .shift   = 30,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_GP_PLL_CNTL,
   .shift   = 0,
   .width   = 9,
  },
  .n = {
   .reg_off = HHI_GP_PLL_CNTL,
   .shift   = 9,
   .width   = 5,
  },
  .l = {
   .reg_off = HHI_GP_PLL_CNTL,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_GP_PLL_CNTL,
   .shift   = 29,
   .width   = 1,
  },
  .table = meson8m2_gp_pll_params_table,
  .init_regs = meson8m2_gp_pll_init_regs,
  .init_count = ARRAY_SIZE(meson8m2_gp_pll_init_regs),
 },
 .hw.init = &(struct clk_init_data){
  .name = "gp_pll_dco",
  .ops = &meson_clk_pll_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
   .name = "xtal",
   .index = -1,
  },
  .num_parents = 1,
 },
};

static struct clk_regmap meson8m2_gp_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_GP_PLL_CNTL,
  .shift = 16,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "gp_pll",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8m2_gp_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct clk_hw *meson8b_vpu_0_1_parent_hws[] = {
 &meson8b_fclk_div4.hw,
 &meson8b_fclk_div3.hw,
 &meson8b_fclk_div5.hw,
 &meson8b_fclk_div7.hw,
};

static const struct clk_hw *mmeson8m2_vpu_0_1_parent_hws[] = {
 &meson8b_fclk_div4.hw,
 &meson8b_fclk_div3.hw,
 &meson8b_fclk_div5.hw,
 &meson8m2_gp_pll.hw,
};

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_hws = meson8b_vpu_0_1_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_hws),
  .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_hws = mmeson8m2_vpu_0_1_parent_hws,
  .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_hws),
  .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_data = &(const struct clk_parent_data) {
   /*
 * Note:
 * meson8b and meson8m2 have different vpu_0_sels (with
 * different struct clk_hw). We fallback to the global
 * naming string mechanism so vpu_0_div picks up the
 * appropriate one.
 */

   .name = "vpu_0_sel",
   .index = -1,
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_vpu_0_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_GATE | 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_hws = meson8b_vpu_0_1_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vpu_0_1_parent_hws),
  .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_hws = mmeson8m2_vpu_0_1_parent_hws,
  .num_parents = ARRAY_SIZE(mmeson8m2_vpu_0_1_parent_hws),
  .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_data = &(const struct clk_parent_data) {
   /*
 * Note:
 * meson8b and meson8m2 have different vpu_1_sels (with
 * different struct clk_hw). We fallback to the global
 * naming string mechanism so vpu_1_div picks up the
 * appropriate one.
 */

   .name = "vpu_1_sel",
   .index = -1,
  },
  .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_hws = (const struct clk_hw *[]) {
   &meson8b_vpu_1_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
 },
};

/*
 * The VPU clock has two identical clock trees (vpu_0 and vpu_1)
 * muxed by a glitch-free switch on Meson8b and Meson8m2. The CCF can
 * actually manage this glitch-free mux because it does top-to-bottom
 * updates the each clock tree and switches to the "inactive" one when
 * CLK_SET_RATE_GATE is set.
 * Meson8 only has vpu_0 and no glitch-free mux.
 */

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_hws = (const struct clk_hw *[]) {
   &meson8b_vpu_0.hw,
   &meson8b_vpu_1.hw,
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct clk_hw *meson8b_vdec_parent_hws[] = {
 &meson8b_fclk_div4.hw,
 &meson8b_fclk_div3.hw,
 &meson8b_fclk_div5.hw,
 &meson8b_fclk_div7.hw,
 &meson8b_mpll2.hw,
 &meson8b_mpll1.hw,
};

static struct clk_regmap meson8b_vdec_1_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VDEC_CLK_CNTL,
  .mask = 0x3,
  .shift = 9,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vdec_1_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vdec_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_1_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_1_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_1_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_1_1 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VDEC_CLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vdec_1_1",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_1_1_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_1_2_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_VDEC3_CLK_CNTL,
  .shift = 0,
  .width = 7,
  .flags = CLK_DIVIDER_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vdec_1_2_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_1_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_1_2 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VDEC3_CLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vdec_1_2",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_1_2_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_1 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VDEC3_CLK_CNTL,
  .mask = 0x1,
  .shift = 15,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vdec_1",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_1_1.hw,
   &meson8b_vdec_1_2.hw,
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_hcodec_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VDEC_CLK_CNTL,
  .mask = 0x3,
  .shift = 25,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vdec_hcodec_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vdec_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_hcodec_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_VDEC_CLK_CNTL,
  .shift = 16,
  .width = 7,
  .flags = CLK_DIVIDER_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vdec_hcodec_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_hcodec_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_hcodec = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VDEC_CLK_CNTL,
  .bit_idx = 24,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vdec_hcodec",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_hcodec_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_2_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VDEC2_CLK_CNTL,
  .mask = 0x3,
  .shift = 9,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vdec_2_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vdec_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_2_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_2_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_2_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_2 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VDEC2_CLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vdec_2",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_2_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_hevc_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VDEC2_CLK_CNTL,
  .mask = 0x3,
  .shift = 25,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vdec_hevc_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_vdec_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_vdec_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_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_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_hevc_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_hevc_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VDEC2_CLK_CNTL,
  .bit_idx = 24,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vdec_hevc_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_hevc_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_vdec_hevc = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VDEC2_CLK_CNTL,
  .mask = 0x1,
  .shift = 31,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vdec_hevc",
  .ops = &clk_regmap_mux_ops,
  /* TODO: The second parent is currently unknown */
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_vdec_hevc_en.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* TODO: the clock at index 0 is "DDR_PLL" which we don't support yet */
static const struct clk_hw *meson8b_cts_amclk_parent_hws[] = {
 &meson8b_mpll0.hw,
 &meson8b_mpll1.hw,
 &meson8b_mpll2.hw
};

static u32 meson8b_cts_amclk_mux_table[] = { 1, 2, 3 };

static struct clk_regmap meson8b_cts_amclk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_AUD_CLK_CNTL,
  .mask = 0x3,
  .shift = 9,
  .table = meson8b_cts_amclk_mux_table,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_amclk_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_cts_amclk_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_cts_amclk_parent_hws),
 },
};

static struct clk_regmap meson8b_cts_amclk_div = {
 .data = &(struct clk_regmap_div_data) {
  .offset = HHI_AUD_CLK_CNTL,
  .shift = 0,
  .width = 8,
  .flags = CLK_DIVIDER_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_amclk_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cts_amclk_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_amclk = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_AUD_CLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_amclk",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cts_amclk_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* TODO: the clock at index 0 is "DDR_PLL" which we don't support yet */
static const struct clk_hw *meson8b_cts_mclk_i958_parent_hws[] = {
 &meson8b_mpll0.hw,
 &meson8b_mpll1.hw,
 &meson8b_mpll2.hw
};

static u32 meson8b_cts_mclk_i958_mux_table[] = { 1, 2, 3 };

static struct clk_regmap meson8b_cts_mclk_i958_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_AUD_CLK_CNTL2,
  .mask = 0x3,
  .shift = 25,
  .table = meson8b_cts_mclk_i958_mux_table,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cts_mclk_i958_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = meson8b_cts_mclk_i958_parent_hws,
  .num_parents = ARRAY_SIZE(meson8b_cts_mclk_i958_parent_hws),
 },
};

static struct clk_regmap meson8b_cts_mclk_i958_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_AUD_CLK_CNTL2,
  .shift = 16,
  .width = 8,
  .flags = CLK_DIVIDER_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cts_mclk_i958_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cts_mclk_i958_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_mclk_i958 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_AUD_CLK_CNTL2,
  .bit_idx = 24,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_mclk_i958",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cts_mclk_i958_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap meson8b_cts_i958 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_AUD_CLK_CNTL2,
  .mask = 0x1,
  .shift = 27,
  },
 .hw.init = &(struct clk_init_data){
  .name = "cts_i958",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &meson8b_cts_amclk.hw,
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=99 H=100 G=99

¤ Dauer der Verarbeitung: 0.20 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.