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 145 kB image not shown  

Quelle  g12a.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * Amlogic Meson-G12A Clock Controller Driver
 *
 * Copyright (c) 2016 Baylibre SAS.
 * Author: Michael Turquette <mturquette@baylibre.com>
 *
 * Copyright (c) 2018 Amlogic, inc.
 * Author: Qiufang Dai <qiufang.dai@amlogic.com>
 * Author: Jian Hu <jian.hu@amlogic.com>
 */


#include <linux/clk-provider.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/module.h>

#include "clk-mpll.h"
#include "clk-pll.h"
#include "clk-regmap.h"
#include "clk-cpu-dyndiv.h"
#include "vid-pll-div.h"
#include "vclk.h"
#include "meson-eeclk.h"

#include <dt-bindings/clock/g12a-clkc.h>

#define HHI_MIPI_CNTL0   0x000
#define HHI_MIPI_CNTL1   0x004
#define HHI_MIPI_CNTL2   0x008
#define HHI_MIPI_STS   0x00c
#define HHI_GP0_PLL_CNTL0  0x040
#define HHI_GP0_PLL_CNTL1  0x044
#define HHI_GP0_PLL_CNTL2  0x048
#define HHI_GP0_PLL_CNTL3  0x04c
#define HHI_GP0_PLL_CNTL4  0x050
#define HHI_GP0_PLL_CNTL5  0x054
#define HHI_GP0_PLL_CNTL6  0x058
#define HHI_GP0_PLL_STS   0x05c
#define HHI_GP1_PLL_CNTL0  0x060
#define HHI_GP1_PLL_CNTL1  0x064
#define HHI_GP1_PLL_CNTL2  0x068
#define HHI_GP1_PLL_CNTL3  0x06c
#define HHI_GP1_PLL_CNTL4  0x070
#define HHI_GP1_PLL_CNTL5  0x074
#define HHI_GP1_PLL_CNTL6  0x078
#define HHI_GP1_PLL_STS   0x07c
#define HHI_PCIE_PLL_CNTL0  0x098
#define HHI_PCIE_PLL_CNTL1  0x09c
#define HHI_PCIE_PLL_CNTL2  0x0a0
#define HHI_PCIE_PLL_CNTL3  0x0a4
#define HHI_PCIE_PLL_CNTL4  0x0a8
#define HHI_PCIE_PLL_CNTL5  0x0ac
#define HHI_PCIE_PLL_STS  0x0b8
#define HHI_HIFI_PLL_CNTL0  0x0d8
#define HHI_HIFI_PLL_CNTL1  0x0dc
#define HHI_HIFI_PLL_CNTL2  0x0e0
#define HHI_HIFI_PLL_CNTL3  0x0e4
#define HHI_HIFI_PLL_CNTL4  0x0e8
#define HHI_HIFI_PLL_CNTL5  0x0ec
#define HHI_HIFI_PLL_CNTL6  0x0f0
#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_OTHER2   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_TS_CLK_CNTL   0x190
#define HHI_VID_CLK_CNTL2  0x194
#define HHI_SYS_CPU_CLK_CNTL0  0x19c
#define HHI_VID_PLL_CLK_DIV  0x1a0
#define HHI_MALI_CLK_CNTL  0x1b0
#define HHI_VPU_CLKC_CNTL  0x1b4
#define HHI_VPU_CLK_CNTL  0x1bc
#define HHI_ISP_CLK_CNTL  0x1c0
#define HHI_NNA_CLK_CNTL  0x1c8
#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_VDEC4_CLK_CNTL  0x1ec
#define HHI_HDCP22_CLK_CNTL  0x1f0
#define HHI_VAPBCLK_CNTL  0x1f4
#define HHI_SYS_CPUB_CLK_CNTL1  0x200
#define HHI_SYS_CPUB_CLK_CNTL  0x208
#define HHI_VPU_CLKB_CNTL  0x20c
#define HHI_SYS_CPU_CLK_CNTL2  0x210
#define HHI_SYS_CPU_CLK_CNTL3  0x214
#define HHI_SYS_CPU_CLK_CNTL4  0x218
#define HHI_SYS_CPU_CLK_CNTL5  0x21c
#define HHI_SYS_CPU_CLK_CNTL6  0x220
#define HHI_GEN_CLK_CNTL  0x228
#define HHI_VDIN_MEAS_CLK_CNTL  0x250
#define HHI_MIPIDSI_PHY_CLK_CNTL 0x254
#define HHI_NAND_CLK_CNTL  0x25c
#define HHI_SD_EMMC_CLK_CNTL  0x264
#define HHI_MPLL_CNTL0   0x278
#define HHI_MPLL_CNTL1   0x27c
#define HHI_MPLL_CNTL2   0x280
#define HHI_MPLL_CNTL3   0x284
#define HHI_MPLL_CNTL4   0x288
#define HHI_MPLL_CNTL5   0x28c
#define HHI_MPLL_CNTL6   0x290
#define HHI_MPLL_CNTL7   0x294
#define HHI_MPLL_CNTL8   0x298
#define HHI_FIX_PLL_CNTL0  0x2a0
#define HHI_FIX_PLL_CNTL1  0x2a4
#define HHI_FIX_PLL_CNTL3  0x2ac
#define HHI_SYS_PLL_CNTL0  0x2f4
#define HHI_SYS_PLL_CNTL1  0x2f8
#define HHI_SYS_PLL_CNTL2  0x2fc
#define HHI_SYS_PLL_CNTL3  0x300
#define HHI_SYS_PLL_CNTL4  0x304
#define HHI_SYS_PLL_CNTL5  0x308
#define HHI_SYS_PLL_CNTL6  0x30c
#define HHI_HDMI_PLL_CNTL0  0x320
#define HHI_HDMI_PLL_CNTL1  0x324
#define HHI_HDMI_PLL_CNTL2  0x328
#define HHI_HDMI_PLL_CNTL3  0x32c
#define HHI_HDMI_PLL_CNTL4  0x330
#define HHI_HDMI_PLL_CNTL5  0x334
#define HHI_HDMI_PLL_CNTL6  0x338
#define HHI_SPICC_CLK_CNTL  0x3dc
#define HHI_SYS1_PLL_CNTL0  0x380
#define HHI_SYS1_PLL_CNTL1  0x384
#define HHI_SYS1_PLL_CNTL2  0x388
#define HHI_SYS1_PLL_CNTL3  0x38c
#define HHI_SYS1_PLL_CNTL4  0x390
#define HHI_SYS1_PLL_CNTL5  0x394
#define HHI_SYS1_PLL_CNTL6  0x398

static struct clk_regmap g12a_fixed_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_FIX_PLL_CNTL0,
   .shift   = 28,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_FIX_PLL_CNTL0,
   .shift   = 0,
   .width   = 8,
  },
  .n = {
   .reg_off = HHI_FIX_PLL_CNTL0,
   .shift   = 10,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_FIX_PLL_CNTL1,
   .shift   = 0,
   .width   = 17,
  },
  .l = {
   .reg_off = HHI_FIX_PLL_CNTL0,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_FIX_PLL_CNTL0,
   .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",
  },
  .num_parents = 1,
 },
};

static struct clk_regmap g12a_fixed_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_FIX_PLL_CNTL0,
  .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 *[]) {
   &g12a_fixed_pll_dco.hw
  },
  .num_parents = 1,
  /*
 * This clock won't ever change at runtime so
 * CLK_SET_RATE_PARENT is not required
 */

 },
};

static const struct pll_mult_range g12a_sys_pll_mult_range = {
 .min = 128,
 .max = 250,
};

static struct clk_regmap g12a_sys_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_SYS_PLL_CNTL0,
   .shift   = 28,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_SYS_PLL_CNTL0,
   .shift   = 0,
   .width   = 8,
  },
  .n = {
   .reg_off = HHI_SYS_PLL_CNTL0,
   .shift   = 10,
   .width   = 5,
  },
  .l = {
   .reg_off = HHI_SYS_PLL_CNTL0,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_SYS_PLL_CNTL0,
   .shift   = 29,
   .width   = 1,
  },
  .range = &g12a_sys_pll_mult_range,
 },
 .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",
  },
  .num_parents = 1,
  /* This clock feeds the CPU, avoid disabling it */
  .flags = CLK_IS_CRITICAL,
 },
};

static struct clk_regmap g12a_sys_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_SYS_PLL_CNTL0,
  .shift = 16,
  .width = 3,
  .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 *[]) {
   &g12a_sys_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap g12b_sys1_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_SYS1_PLL_CNTL0,
   .shift   = 28,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_SYS1_PLL_CNTL0,
   .shift   = 0,
   .width   = 8,
  },
  .n = {
   .reg_off = HHI_SYS1_PLL_CNTL0,
   .shift   = 10,
   .width   = 5,
  },
  .l = {
   .reg_off = HHI_SYS1_PLL_CNTL0,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_SYS1_PLL_CNTL0,
   .shift   = 29,
   .width   = 1,
  },
  .range = &g12a_sys_pll_mult_range,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sys1_pll_dco",
  .ops = &meson_clk_pll_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
  },
  .num_parents = 1,
  /* This clock feeds the CPU, avoid disabling it */
  .flags = CLK_IS_CRITICAL,
 },
};

static struct clk_regmap g12b_sys1_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_SYS1_PLL_CNTL0,
  .shift = 16,
  .width = 3,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sys1_pll",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_sys1_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

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_hws = (const struct clk_hw *[]) { &g12a_sys_pll.hw },
  .num_parents = 1,
  /*
 * This clock is used to debug the sys_pll range
 * Linux should not change it at runtime
 */

 },
};

static struct clk_regmap g12b_sys1_pll_div16_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .bit_idx = 24,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "sys1_pll_div16_en",
  .ops = &clk_regmap_gate_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_sys1_pll.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &g12a_sys_pll_div16_en.hw
  },
  .num_parents = 1,
 },
};

static struct clk_fixed_factor g12b_sys1_pll_div16 = {
 .mult = 1,
 .div = 16,
 .hw.init = &(struct clk_init_data){
  .name = "sys1_pll_div16",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_sys1_pll_div16_en.hw
  },
  .num_parents = 1,
 },
};

static struct clk_fixed_factor g12a_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 *[]) { &g12a_fixed_pll.hw },
  .num_parents = 1,
 },
};

static struct clk_regmap g12a_fclk_div2 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_FIX_PLL_CNTL1,
  .bit_idx = 24,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div2",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_fclk_div2_div.hw
  },
  .num_parents = 1,
  /*
 * Similar to fclk_div3, it seems that this clock is used by
 * the resident firmware and is required by the platform to
 * operate correctly.
 * Until the following condition are met, we need this clock to
 * be marked as critical:
 * a) Mark the clock used by a firmware resource, if possible
 * b) CCF has a clock hand-off mechanism to make the sure the
 *    clock stays on until the proper driver comes along
 */

  .flags = CLK_IS_CRITICAL,
 },
};

static struct clk_fixed_factor g12a_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 *[]) { &g12a_fixed_pll.hw },
  .num_parents = 1,
 },
};

static struct clk_regmap g12a_fclk_div3 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_FIX_PLL_CNTL1,
  .bit_idx = 20,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div3",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_fclk_div3_div.hw
  },
  .num_parents = 1,
  /*
 * This clock is used by the resident firmware and is required
 * by the platform to operate correctly.
 * Until the following condition are met, we need this clock to
 * be marked as critical:
 * a) Mark the clock used by a firmware resource, if possible
 * b) CCF has a clock hand-off mechanism to make the sure the
 *    clock stays on until the proper driver comes along
 */

  .flags = CLK_IS_CRITICAL,
 },
};

/* 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,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu_clk_dyn0_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = (const struct clk_parent_data []) {
   { .fw_name = "xtal", },
   { .hw = &g12a_fclk_div2.hw },
   { .hw = &g12a_fclk_div3.hw },
  },
  .num_parents = 3,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* 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_ops,
  .parent_data = (const struct clk_parent_data []) {
   { .fw_name = "xtal", },
   { .hw = &g12a_fclk_div2.hw },
   { .hw = &g12a_fclk_div3.hw },
  },
  .num_parents = 3,
  /* This sub-tree is used a parking clock */
  .flags = CLK_SET_RATE_NO_REPARENT
 },
};

/* Datasheet names this field as "mux0_divn_tcnt" */
static struct clk_regmap g12a_cpu_clk_mux0_div = {
 .data = &(struct meson_clk_cpu_dyndiv_data){
  .div = {
   .reg_off = HHI_SYS_CPU_CLK_CNTL0,
   .shift = 4,
   .width = 6,
  },
  .dyn = {
   .reg_off = HHI_SYS_CPU_CLK_CNTL0,
   .shift = 26,
   .width = 1,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu_clk_dyn0_div",
  .ops = &meson_clk_cpu_dyndiv_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_premux0.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* 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,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu_clk_dyn0",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_premux0.hw,
   &g12a_cpu_clk_mux0_div.hw,
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* 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_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_premux1.hw
  },
  .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_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_premux1.hw,
   &g12a_cpu_clk_mux1_div.hw,
  },
  .num_parents = 2,
  /* This sub-tree is used a parking clock */
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

/* 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,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu_clk_dyn",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_postmux0.hw,
   &g12a_cpu_clk_postmux1.hw,
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* 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,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu_clk",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_dyn.hw,
   &g12a_sys_pll.hw,
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* Datasheet names this field as "Final_mux_sel" */
static struct clk_regmap g12b_cpu_clk = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL0,
  .mask = 0x1,
  .shift = 11,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu_clk",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_dyn.hw,
   &g12b_sys1_pll.hw
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* Datasheet names this field as "premux0" */
static struct clk_regmap g12b_cpub_clk_premux0 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL,
  .mask = 0x3,
  .shift = 0,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_dyn0_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = (const struct clk_parent_data []) {
   { .fw_name = "xtal", },
   { .hw = &g12a_fclk_div2.hw },
   { .hw = &g12a_fclk_div3.hw },
  },
  .num_parents = 3,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* Datasheet names this field as "mux0_divn_tcnt" */
static struct clk_regmap g12b_cpub_clk_mux0_div = {
 .data = &(struct meson_clk_cpu_dyndiv_data){
  .div = {
   .reg_off = HHI_SYS_CPUB_CLK_CNTL,
   .shift = 4,
   .width = 6,
  },
  .dyn = {
   .reg_off = HHI_SYS_CPUB_CLK_CNTL,
   .shift = 26,
   .width = 1,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_dyn0_div",
  .ops = &meson_clk_cpu_dyndiv_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_premux0.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* Datasheet names this field as "postmux0" */
static struct clk_regmap g12b_cpub_clk_postmux0 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL,
  .mask = 0x1,
  .shift = 2,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_dyn0",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_premux0.hw,
   &g12b_cpub_clk_mux0_div.hw
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* Datasheet names this field as "premux1" */
static struct clk_regmap g12b_cpub_clk_premux1 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL,
  .mask = 0x3,
  .shift = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_dyn1_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = (const struct clk_parent_data []) {
   { .fw_name = "xtal", },
   { .hw = &g12a_fclk_div2.hw },
   { .hw = &g12a_fclk_div3.hw },
  },
  .num_parents = 3,
  /* This sub-tree is used a parking clock */
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

/* Datasheet names this field as "Mux1_divn_tcnt" */
static struct clk_regmap g12b_cpub_clk_mux1_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL,
  .shift = 20,
  .width = 6,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_dyn1_div",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_premux1.hw
  },
  .num_parents = 1,
 },
};

/* Datasheet names this field as "postmux1" */
static struct clk_regmap g12b_cpub_clk_postmux1 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL,
  .mask = 0x1,
  .shift = 18,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_dyn1",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_premux1.hw,
   &g12b_cpub_clk_mux1_div.hw
  },
  .num_parents = 2,
  /* This sub-tree is used a parking clock */
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

/* Datasheet names this field as "Final_dyn_mux_sel" */
static struct clk_regmap g12b_cpub_clk_dyn = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL,
  .mask = 0x1,
  .shift = 10,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_dyn",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_postmux0.hw,
   &g12b_cpub_clk_postmux1.hw
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* Datasheet names this field as "Final_mux_sel" */
static struct clk_regmap g12b_cpub_clk = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL,
  .mask = 0x1,
  .shift = 11,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_dyn.hw,
   &g12a_sys_pll.hw
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap sm1_gp1_pll;

/* Datasheet names this field as "premux0" */
static struct clk_regmap sm1_dsu_clk_premux0 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL5,
  .mask = 0x3,
  .shift = 0,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk_dyn0_sel",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_data = (const struct clk_parent_data []) {
   { .fw_name = "xtal", },
   { .hw = &g12a_fclk_div2.hw },
   { .hw = &g12a_fclk_div3.hw },
   { .hw = &sm1_gp1_pll.hw },
  },
  .num_parents = 4,
 },
};

/* Datasheet names this field as "premux1" */
static struct clk_regmap sm1_dsu_clk_premux1 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL5,
  .mask = 0x3,
  .shift = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk_dyn1_sel",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_data = (const struct clk_parent_data []) {
   { .fw_name = "xtal", },
   { .hw = &g12a_fclk_div2.hw },
   { .hw = &g12a_fclk_div3.hw },
   { .hw = &sm1_gp1_pll.hw },
  },
  .num_parents = 4,
 },
};

/* Datasheet names this field as "Mux0_divn_tcnt" */
static struct clk_regmap sm1_dsu_clk_mux0_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_SYS_CPU_CLK_CNTL5,
  .shift = 4,
  .width = 6,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk_dyn0_div",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &sm1_dsu_clk_premux0.hw
  },
  .num_parents = 1,
 },
};

/* Datasheet names this field as "postmux0" */
static struct clk_regmap sm1_dsu_clk_postmux0 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL5,
  .mask = 0x1,
  .shift = 2,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk_dyn0",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &sm1_dsu_clk_premux0.hw,
   &sm1_dsu_clk_mux0_div.hw,
  },
  .num_parents = 2,
 },
};

/* Datasheet names this field as "Mux1_divn_tcnt" */
static struct clk_regmap sm1_dsu_clk_mux1_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_SYS_CPU_CLK_CNTL5,
  .shift = 20,
  .width = 6,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk_dyn1_div",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &sm1_dsu_clk_premux1.hw
  },
  .num_parents = 1,
 },
};

/* Datasheet names this field as "postmux1" */
static struct clk_regmap sm1_dsu_clk_postmux1 = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL5,
  .mask = 0x1,
  .shift = 18,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk_dyn1",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &sm1_dsu_clk_premux1.hw,
   &sm1_dsu_clk_mux1_div.hw,
  },
  .num_parents = 2,
 },
};

/* Datasheet names this field as "Final_dyn_mux_sel" */
static struct clk_regmap sm1_dsu_clk_dyn = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL5,
  .mask = 0x1,
  .shift = 10,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk_dyn",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &sm1_dsu_clk_postmux0.hw,
   &sm1_dsu_clk_postmux1.hw,
  },
  .num_parents = 2,
 },
};

/* Datasheet names this field as "Final_mux_sel" */
static struct clk_regmap sm1_dsu_final_clk = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL5,
  .mask = 0x1,
  .shift = 11,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk_final",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &sm1_dsu_clk_dyn.hw,
   &g12a_sys_pll.hw,
  },
  .num_parents = 2,
 },
};

/* Datasheet names this field as "Cpu_clk_sync_mux_sel" bit 0 */
static struct clk_regmap sm1_cpu1_clk = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL6,
  .mask = 0x1,
  .shift = 24,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu1_clk",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk.hw,
   /* This CPU also have a dedicated clock tree */
  },
  .num_parents = 1,
 },
};

/* Datasheet names this field as "Cpu_clk_sync_mux_sel" bit 1 */
static struct clk_regmap sm1_cpu2_clk = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL6,
  .mask = 0x1,
  .shift = 25,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu2_clk",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk.hw,
   /* This CPU also have a dedicated clock tree */
  },
  .num_parents = 1,
 },
};

/* Datasheet names this field as "Cpu_clk_sync_mux_sel" bit 2 */
static struct clk_regmap sm1_cpu3_clk = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL6,
  .mask = 0x1,
  .shift = 26,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpu3_clk",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk.hw,
   /* This CPU also have a dedicated clock tree */
  },
  .num_parents = 1,
 },
};

/* Datasheet names this field as "Cpu_clk_sync_mux_sel" bit 4 */
static struct clk_regmap sm1_dsu_clk = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPU_CLK_CNTL6,
  .mask = 0x1,
  .shift = 27,
 },
 .hw.init = &(struct clk_init_data){
  .name = "dsu_clk",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk.hw,
   &sm1_dsu_final_clk.hw,
  },
  .num_parents = 2,
 },
};

static int g12a_cpu_clk_mux_notifier_cb(struct notifier_block *nb,
     unsigned long event, void *data)
{
 if (event == POST_RATE_CHANGE || event == PRE_RATE_CHANGE) {
  /* Wait for clock propagation before/after changing the mux */
  udelay(100);
  return NOTIFY_OK;
 }

 return NOTIFY_DONE;
}

static struct notifier_block g12a_cpu_clk_mux_nb = {
 .notifier_call = g12a_cpu_clk_mux_notifier_cb,
};

struct g12a_cpu_clk_postmux_nb_data {
 struct notifier_block nb;
 struct clk_hw *xtal;
 struct clk_hw *cpu_clk_dyn;
 struct clk_hw *cpu_clk_postmux0;
 struct clk_hw *cpu_clk_postmux1;
 struct clk_hw *cpu_clk_premux1;
};

static int g12a_cpu_clk_postmux_notifier_cb(struct notifier_block *nb,
         unsigned long event, void *data)
{
 struct g12a_cpu_clk_postmux_nb_data *nb_data =
  container_of(nb, struct g12a_cpu_clk_postmux_nb_data, nb);

 switch (event) {
 case PRE_RATE_CHANGE:
  /*
 * This notifier means cpu_clk_postmux0 clock will be changed
 * to feed cpu_clk, this is the current path :
 * cpu_clk
 *    \- cpu_clk_dyn
 *          \- cpu_clk_postmux0
 *                \- cpu_clk_muxX_div
 *                      \- cpu_clk_premux0
 * \- fclk_div3 or fclk_div2
 * OR
 *                \- cpu_clk_premux0
 * \- fclk_div3 or fclk_div2
 */


  /* Setup cpu_clk_premux1 to xtal */
  clk_hw_set_parent(nb_data->cpu_clk_premux1,
      nb_data->xtal);

  /* Setup cpu_clk_postmux1 to bypass divider */
  clk_hw_set_parent(nb_data->cpu_clk_postmux1,
      nb_data->cpu_clk_premux1);

  /* Switch to parking clk on cpu_clk_postmux1 */
  clk_hw_set_parent(nb_data->cpu_clk_dyn,
      nb_data->cpu_clk_postmux1);

  /*
 * Now, cpu_clk is 24MHz in the current path :
 * cpu_clk
 *    \- cpu_clk_dyn
 *          \- cpu_clk_postmux1
 *                \- cpu_clk_premux1
 *                      \- xtal
 */


  udelay(100);

  return NOTIFY_OK;

 case POST_RATE_CHANGE:
  /*
 * The cpu_clk_postmux0 has ben updated, now switch back
 * cpu_clk_dyn to cpu_clk_postmux0 and take the changes
 * in account.
 */


  /* Configure cpu_clk_dyn back to cpu_clk_postmux0 */
  clk_hw_set_parent(nb_data->cpu_clk_dyn,
      nb_data->cpu_clk_postmux0);

  /*
 * new path :
 * cpu_clk
 *    \- cpu_clk_dyn
 *          \- cpu_clk_postmux0
 *                \- cpu_clk_muxX_div
 *                      \- cpu_clk_premux0
 * \- fclk_div3 or fclk_div2
 * OR
 *                \- cpu_clk_premux0
 * \- fclk_div3 or fclk_div2
 */


  udelay(100);

  return NOTIFY_OK;

 default:
  return NOTIFY_DONE;
 }
}

static struct g12a_cpu_clk_postmux_nb_data g12a_cpu_clk_postmux0_nb_data = {
 .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw,
 .cpu_clk_postmux0 = &g12a_cpu_clk_postmux0.hw,
 .cpu_clk_postmux1 = &g12a_cpu_clk_postmux1.hw,
 .cpu_clk_premux1 = &g12a_cpu_clk_premux1.hw,
 .nb.notifier_call = g12a_cpu_clk_postmux_notifier_cb,
};

static struct g12a_cpu_clk_postmux_nb_data g12b_cpub_clk_postmux0_nb_data = {
 .cpu_clk_dyn = &g12b_cpub_clk_dyn.hw,
 .cpu_clk_postmux0 = &g12b_cpub_clk_postmux0.hw,
 .cpu_clk_postmux1 = &g12b_cpub_clk_postmux1.hw,
 .cpu_clk_premux1 = &g12b_cpub_clk_premux1.hw,
 .nb.notifier_call = g12a_cpu_clk_postmux_notifier_cb,
};

struct g12a_sys_pll_nb_data {
 struct notifier_block nb;
 struct clk_hw *sys_pll;
 struct clk_hw *cpu_clk;
 struct clk_hw *cpu_clk_dyn;
};

static int g12a_sys_pll_notifier_cb(struct notifier_block *nb,
        unsigned long event, void *data)
{
 struct g12a_sys_pll_nb_data *nb_data =
  container_of(nb, struct g12a_sys_pll_nb_data, nb);

 switch (event) {
 case PRE_RATE_CHANGE:
  /*
 * This notifier means sys_pll clock will be changed
 * to feed cpu_clk, this the current path :
 * cpu_clk
 *    \- sys_pll
 *          \- sys_pll_dco
 */


  /* Configure cpu_clk to use cpu_clk_dyn */
  clk_hw_set_parent(nb_data->cpu_clk,
      nb_data->cpu_clk_dyn);

  /*
 * Now, cpu_clk uses the dyn path
 * cpu_clk
 *    \- cpu_clk_dyn
 *          \- cpu_clk_dynX
 *                \- cpu_clk_dynX_sel
 *      \- cpu_clk_dynX_div
 *                      \- xtal/fclk_div2/fclk_div3
 *                   \- xtal/fclk_div2/fclk_div3
 */


  udelay(100);

  return NOTIFY_OK;

 case POST_RATE_CHANGE:
  /*
 * The sys_pll has ben updated, now switch back cpu_clk to
 * sys_pll
 */


  /* Configure cpu_clk to use sys_pll */
  clk_hw_set_parent(nb_data->cpu_clk,
      nb_data->sys_pll);

  udelay(100);

  /* new path :
 * cpu_clk
 *    \- sys_pll
 *          \- sys_pll_dco
 */


  return NOTIFY_OK;

 default:
  return NOTIFY_DONE;
 }
}

static struct g12a_sys_pll_nb_data g12a_sys_pll_nb_data = {
 .sys_pll = &g12a_sys_pll.hw,
 .cpu_clk = &g12a_cpu_clk.hw,
 .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw,
 .nb.notifier_call = g12a_sys_pll_notifier_cb,
};

/* G12B first CPU cluster uses sys1_pll */
static struct g12a_sys_pll_nb_data g12b_cpu_clk_sys1_pll_nb_data = {
 .sys_pll = &g12b_sys1_pll.hw,
 .cpu_clk = &g12b_cpu_clk.hw,
 .cpu_clk_dyn = &g12a_cpu_clk_dyn.hw,
 .nb.notifier_call = g12a_sys_pll_notifier_cb,
};

/* G12B second CPU cluster uses sys_pll */
static struct g12a_sys_pll_nb_data g12b_cpub_clk_sys_pll_nb_data = {
 .sys_pll = &g12a_sys_pll.hw,
 .cpu_clk = &g12b_cpub_clk.hw,
 .cpu_clk_dyn = &g12b_cpub_clk_dyn.hw,
 .nb.notifier_call = g12a_sys_pll_notifier_cb,
};

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_data = &(const struct clk_parent_data) {
   /*
 * Note:
 * G12A and G12B have different cpu clocks (with
 * different struct clk_hw). We fallback to the global
 * naming string mechanism so this clock picks
 * up the appropriate one. Same goes for the other
 * clock using cpu cluster A clock output and present
 * on both G12 variant.
 */

   .name = "cpu_clk",
   .index = -1,
  },
  .num_parents = 1,
  /*
 * This clock is used to debug the cpu_clk range
 * Linux should not change it at runtime
 */

 },
};

static struct clk_regmap g12b_cpub_clk_div16_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .bit_idx = 1,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cpub_clk_div16_en",
  .ops = &clk_regmap_gate_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_div16_en.hw
  },
  .num_parents = 1,
 },
};

static struct clk_fixed_factor g12b_cpub_clk_div16 = {
 .mult = 1,
 .div = 16,
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_div16",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_div16_en.hw
  },
  .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_data = &(const struct clk_parent_data) {
   .name = "cpu_clk",
   .index = -1,
  },
  .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_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_apb_div.hw
  },
  .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_data = &(const struct clk_parent_data) {
   .name = "cpu_clk",
   .index = -1,
  },
  .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_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_atb_div.hw
  },
  .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_data = &(const struct clk_parent_data) {
   .name = "cpu_clk",
   .index = -1,
  },
  .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_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_axi_div.hw
  },
  .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_data = &(const struct clk_parent_data) {
   .name = "cpu_clk",
   .index = -1,
  },
  .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_hws = (const struct clk_hw *[]) {
   &g12a_cpu_clk_trace_div.hw
  },
  .num_parents = 1,
  /*
 * This clock is set by the ROM monitor code,
 * Linux should not change it at runtime
 */

 },
};

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

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

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

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

static struct clk_fixed_factor g12b_cpub_clk_div6 = {
 .mult = 1,
 .div = 6,
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_div6",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk.hw
  },
  .num_parents = 1,
 },
};

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

static struct clk_fixed_factor g12b_cpub_clk_div8 = {
 .mult = 1,
 .div = 8,
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_div8",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk.hw
  },
  .num_parents = 1,
 },
};

static u32 mux_table_cpub[] = { 1, 2, 3, 4, 5, 6, 7 };
static struct clk_regmap g12b_cpub_clk_apb_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .mask = 7,
  .shift = 3,
  .table = mux_table_cpub,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_apb_sel",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_div2.hw,
   &g12b_cpub_clk_div3.hw,
   &g12b_cpub_clk_div4.hw,
   &g12b_cpub_clk_div5.hw,
   &g12b_cpub_clk_div6.hw,
   &g12b_cpub_clk_div7.hw,
   &g12b_cpub_clk_div8.hw
  },
  .num_parents = 7,
 },
};

static struct clk_regmap g12b_cpub_clk_apb = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .bit_idx = 16,
  .flags = CLK_GATE_SET_TO_DISABLE,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cpub_clk_apb",
  .ops = &clk_regmap_gate_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_apb_sel.hw
  },
  .num_parents = 1,
  /*
 * This clock is set by the ROM monitor code,
 * Linux should not change it at runtime
 */

 },
};

static struct clk_regmap g12b_cpub_clk_atb_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .mask = 7,
  .shift = 6,
  .table = mux_table_cpub,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_atb_sel",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_div2.hw,
   &g12b_cpub_clk_div3.hw,
   &g12b_cpub_clk_div4.hw,
   &g12b_cpub_clk_div5.hw,
   &g12b_cpub_clk_div6.hw,
   &g12b_cpub_clk_div7.hw,
   &g12b_cpub_clk_div8.hw
  },
  .num_parents = 7,
 },
};

static struct clk_regmap g12b_cpub_clk_atb = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .bit_idx = 17,
  .flags = CLK_GATE_SET_TO_DISABLE,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cpub_clk_atb",
  .ops = &clk_regmap_gate_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_atb_sel.hw
  },
  .num_parents = 1,
  /*
 * This clock is set by the ROM monitor code,
 * Linux should not change it at runtime
 */

 },
};

static struct clk_regmap g12b_cpub_clk_axi_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .mask = 7,
  .shift = 9,
  .table = mux_table_cpub,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_axi_sel",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_div2.hw,
   &g12b_cpub_clk_div3.hw,
   &g12b_cpub_clk_div4.hw,
   &g12b_cpub_clk_div5.hw,
   &g12b_cpub_clk_div6.hw,
   &g12b_cpub_clk_div7.hw,
   &g12b_cpub_clk_div8.hw
  },
  .num_parents = 7,
 },
};

static struct clk_regmap g12b_cpub_clk_axi = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .bit_idx = 18,
  .flags = CLK_GATE_SET_TO_DISABLE,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cpub_clk_axi",
  .ops = &clk_regmap_gate_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_axi_sel.hw
  },
  .num_parents = 1,
  /*
 * This clock is set by the ROM monitor code,
 * Linux should not change it at runtime
 */

 },
};

static struct clk_regmap g12b_cpub_clk_trace_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .mask = 7,
  .shift = 20,
  .table = mux_table_cpub,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cpub_clk_trace_sel",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_div2.hw,
   &g12b_cpub_clk_div3.hw,
   &g12b_cpub_clk_div4.hw,
   &g12b_cpub_clk_div5.hw,
   &g12b_cpub_clk_div6.hw,
   &g12b_cpub_clk_div7.hw,
   &g12b_cpub_clk_div8.hw
  },
  .num_parents = 7,
 },
};

static struct clk_regmap g12b_cpub_clk_trace = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SYS_CPUB_CLK_CNTL1,
  .bit_idx = 23,
  .flags = CLK_GATE_SET_TO_DISABLE,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cpub_clk_trace",
  .ops = &clk_regmap_gate_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12b_cpub_clk_trace_sel.hw
  },
  .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 = 125,
 .max = 255,
};

/*
 * Internal gp0 pll emulation configuration parameters
 */

static const struct reg_sequence g12a_gp0_init_regs[] = {
 { .reg = HHI_GP0_PLL_CNTL1, .def = 0x00000000 },
 { .reg = HHI_GP0_PLL_CNTL2, .def = 0x00000000 },
 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x48681c00 },
 { .reg = HHI_GP0_PLL_CNTL4, .def = 0x33771290 },
 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x39272000 },
 { .reg = HHI_GP0_PLL_CNTL6, .def = 0x56540000 },
};

static struct clk_regmap g12a_gp0_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_GP0_PLL_CNTL0,
   .shift   = 28,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_GP0_PLL_CNTL0,
   .shift   = 0,
   .width   = 8,
  },
  .n = {
   .reg_off = HHI_GP0_PLL_CNTL0,
   .shift   = 10,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_GP0_PLL_CNTL1,
   .shift   = 0,
   .width   = 17,
  },
  .l = {
   .reg_off = HHI_GP0_PLL_CNTL0,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_GP0_PLL_CNTL0,
   .shift   = 29,
   .width   = 1,
  },
  .range = &g12a_gp0_pll_mult_range,
  .init_regs = g12a_gp0_init_regs,
  .init_count = ARRAY_SIZE(g12a_gp0_init_regs),
 },
 .hw.init = &(struct clk_init_data){
  .name = "gp0_pll_dco",
  .ops = &meson_clk_pll_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
  },
  .num_parents = 1,
 },
};

static struct clk_regmap g12a_gp0_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_GP0_PLL_CNTL0,
  .shift = 16,
  .width = 3,
  .flags = (CLK_DIVIDER_POWER_OF_TWO |
     CLK_DIVIDER_ROUND_CLOSEST),
 },
 .hw.init = &(struct clk_init_data){
  .name = "gp0_pll",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_gp0_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap sm1_gp1_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_GP1_PLL_CNTL0,
   .shift   = 28,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_GP1_PLL_CNTL0,
   .shift   = 0,
   .width   = 8,
  },
  .n = {
   .reg_off = HHI_GP1_PLL_CNTL0,
   .shift   = 10,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_GP1_PLL_CNTL1,
   .shift   = 0,
   .width   = 17,
  },
  .l = {
   .reg_off = HHI_GP1_PLL_CNTL0,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_GP1_PLL_CNTL0,
   .shift   = 29,
   .width   = 1,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "gp1_pll_dco",
  .ops = &meson_clk_pll_ro_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
  },
  .num_parents = 1,
  /* This clock feeds the DSU, avoid disabling it */
  .flags = CLK_IS_CRITICAL,
 },
};

static struct clk_regmap sm1_gp1_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_GP1_PLL_CNTL0,
  .shift = 16,
  .width = 3,
  .flags = (CLK_DIVIDER_POWER_OF_TWO |
     CLK_DIVIDER_ROUND_CLOSEST),
 },
 .hw.init = &(struct clk_init_data){
  .name = "gp1_pll",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &sm1_gp1_pll_dco.hw
  },
  .num_parents = 1,
 },
};

/*
 * Internal hifi pll emulation configuration parameters
 */

static const struct reg_sequence g12a_hifi_init_regs[] = {
 { .reg = HHI_HIFI_PLL_CNTL1, .def = 0x00000000 },
 { .reg = HHI_HIFI_PLL_CNTL2, .def = 0x00000000 },
 { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x6a285c00 },
 { .reg = HHI_HIFI_PLL_CNTL4, .def = 0x65771290 },
 { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x39272000 },
 { .reg = HHI_HIFI_PLL_CNTL6, .def = 0x56540000 },
};

static struct clk_regmap g12a_hifi_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_HIFI_PLL_CNTL0,
   .shift   = 28,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_HIFI_PLL_CNTL0,
   .shift   = 0,
   .width   = 8,
  },
  .n = {
   .reg_off = HHI_HIFI_PLL_CNTL0,
   .shift   = 10,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_HIFI_PLL_CNTL1,
   .shift   = 0,
   .width   = 17,
  },
  .l = {
   .reg_off = HHI_HIFI_PLL_CNTL0,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_HIFI_PLL_CNTL0,
   .shift   = 29,
   .width   = 1,
  },
  .range = &g12a_gp0_pll_mult_range,
  .init_regs = g12a_hifi_init_regs,
  .init_count = ARRAY_SIZE(g12a_hifi_init_regs),
  .flags = CLK_MESON_PLL_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hifi_pll_dco",
  .ops = &meson_clk_pll_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
  },
  .num_parents = 1,
 },
};

static struct clk_regmap g12a_hifi_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HIFI_PLL_CNTL0,
  .shift = 16,
  .width = 2,
  .flags = (CLK_DIVIDER_POWER_OF_TWO |
     CLK_DIVIDER_ROUND_CLOSEST),
 },
 .hw.init = &(struct clk_init_data){
  .name = "hifi_pll",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_hifi_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/*
 * 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_data = &(const struct clk_parent_data) {
   .fw_name = "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_hws = (const struct clk_hw *[]) {
   &g12a_pcie_pll_dco.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &g12a_pcie_pll_dco_div2.hw
  },
  .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_hws = (const struct clk_hw *[]) {
   &g12a_pcie_pll_od.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap g12a_hdmi_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_HDMI_PLL_CNTL0,
   .shift   = 28,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_HDMI_PLL_CNTL0,
   .shift   = 0,
   .width   = 8,
  },
  .n = {
   .reg_off = HHI_HDMI_PLL_CNTL0,
   .shift   = 10,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_HDMI_PLL_CNTL1,
   .shift   = 0,
   .width   = 16,
  },
  .l = {
   .reg_off = HHI_HDMI_PLL_CNTL0,
   .shift   = 30,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_HDMI_PLL_CNTL0,
   .shift   = 29,
   .width   = 1,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_dco",
  .ops = &meson_clk_pll_ro_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
  },
  .num_parents = 1,
  /*
 * Display directly handle hdmi pll registers ATM, we need
 * NOCACHE to keep our view of the clock as accurate as possible
 */

  .flags = CLK_GET_RATE_NOCACHE,
 },
};

static struct clk_regmap g12a_hdmi_pll_od = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL0,
  .shift = 16,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_od",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_hdmi_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap g12a_hdmi_pll_od2 = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL0,
  .shift = 18,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_od2",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_hdmi_pll_od.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap g12a_hdmi_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL0,
  .shift = 20,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_hdmi_pll_od2.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_fixed_factor g12a_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 *[]) { &g12a_fixed_pll.hw },
  .num_parents = 1,
 },
};

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

static struct clk_fixed_factor g12a_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 *[]) { &g12a_fixed_pll.hw },
  .num_parents = 1,
 },
};

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

static struct clk_fixed_factor g12a_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 *[]) { &g12a_fixed_pll.hw },
  .num_parents = 1,
 },
};

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

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

static struct clk_regmap g12a_fclk_div2p5 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_FIX_PLL_CNTL1,
  .bit_idx = 25,
 },
 .hw.init = &(struct clk_init_data){
  .name = "fclk_div2p5",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_fclk_div2p5_div.hw
  },
  .num_parents = 1,
 },
};

static struct clk_fixed_factor g12a_mpll_50m_div = {
 .mult = 1,
 .div = 80,
 .hw.init = &(struct clk_init_data){
  .name = "mpll_50m_div",
  .ops = &clk_fixed_factor_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_fixed_pll_dco.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap g12a_mpll_50m = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_FIX_PLL_CNTL3,
  .mask = 0x1,
  .shift = 5,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll_50m",
  .ops = &clk_regmap_mux_ro_ops,
  .parent_data = (const struct clk_parent_data []) {
   { .fw_name = "xtal", },
   { .hw = &g12a_mpll_50m_div.hw },
  },
  .num_parents = 2,
 },
};

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

static const struct reg_sequence g12a_mpll0_init_regs[] = {
 { .reg = HHI_MPLL_CNTL2, .def = 0x40000033 },
};

static struct clk_regmap g12a_mpll0_div = {
 .data = &(struct meson_clk_mpll_data){
  .sdm = {
   .reg_off = HHI_MPLL_CNTL1,
   .shift   = 0,
   .width   = 14,
  },
  .sdm_en = {
   .reg_off = HHI_MPLL_CNTL1,
   .shift   = 30,
   .width  = 1,
  },
  .n2 = {
   .reg_off = HHI_MPLL_CNTL1,
   .shift   = 20,
   .width   = 9,
  },
  .ssen = {
   .reg_off = HHI_MPLL_CNTL1,
   .shift   = 29,
   .width  = 1,
  },
  .init_regs = g12a_mpll0_init_regs,
  .init_count = ARRAY_SIZE(g12a_mpll0_init_regs),
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll0_div",
  .ops = &meson_clk_mpll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_mpll_prediv.hw
  },
  .num_parents = 1,
 },
};

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

static const struct reg_sequence g12a_mpll1_init_regs[] = {
 { .reg = HHI_MPLL_CNTL4, .def = 0x40000033 },
};

static struct clk_regmap g12a_mpll1_div = {
 .data = &(struct meson_clk_mpll_data){
  .sdm = {
   .reg_off = HHI_MPLL_CNTL3,
   .shift   = 0,
   .width   = 14,
  },
  .sdm_en = {
   .reg_off = HHI_MPLL_CNTL3,
   .shift   = 30,
   .width  = 1,
  },
  .n2 = {
   .reg_off = HHI_MPLL_CNTL3,
   .shift   = 20,
   .width   = 9,
  },
  .ssen = {
   .reg_off = HHI_MPLL_CNTL3,
   .shift   = 29,
   .width  = 1,
  },
  .init_regs = g12a_mpll1_init_regs,
  .init_count = ARRAY_SIZE(g12a_mpll1_init_regs),
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll1_div",
  .ops = &meson_clk_mpll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_mpll_prediv.hw
  },
  .num_parents = 1,
 },
};

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

static const struct reg_sequence g12a_mpll2_init_regs[] = {
 { .reg = HHI_MPLL_CNTL6, .def = 0x40000033 },
};

static struct clk_regmap g12a_mpll2_div = {
 .data = &(struct meson_clk_mpll_data){
  .sdm = {
   .reg_off = HHI_MPLL_CNTL5,
   .shift   = 0,
   .width   = 14,
  },
  .sdm_en = {
   .reg_off = HHI_MPLL_CNTL5,
   .shift   = 30,
   .width  = 1,
  },
  .n2 = {
   .reg_off = HHI_MPLL_CNTL5,
   .shift   = 20,
   .width   = 9,
  },
  .ssen = {
   .reg_off = HHI_MPLL_CNTL5,
   .shift   = 29,
   .width  = 1,
  },
  .init_regs = g12a_mpll2_init_regs,
  .init_count = ARRAY_SIZE(g12a_mpll2_init_regs),
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll2_div",
  .ops = &meson_clk_mpll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_mpll_prediv.hw
  },
  .num_parents = 1,
 },
};

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

static const struct reg_sequence g12a_mpll3_init_regs[] = {
 { .reg = HHI_MPLL_CNTL8, .def = 0x40000033 },
};

static struct clk_regmap g12a_mpll3_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   = 30,
   .width  = 1,
  },
  .n2 = {
   .reg_off = HHI_MPLL_CNTL7,
   .shift   = 20,
   .width   = 9,
  },
  .ssen = {
   .reg_off = HHI_MPLL_CNTL7,
   .shift   = 29,
   .width  = 1,
  },
  .init_regs = g12a_mpll3_init_regs,
  .init_count = ARRAY_SIZE(g12a_mpll3_init_regs),
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll3_div",
  .ops = &meson_clk_mpll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_mpll_prediv.hw
  },
  .num_parents = 1,
 },
};

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

static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
static const struct clk_parent_data clk81_parent_data[] = {
 { .fw_name = "xtal", },
 { .hw = &g12a_fclk_div7.hw },
 { .hw = &g12a_mpll1.hw },
 { .hw = &g12a_mpll2.hw },
 { .hw = &g12a_fclk_div4.hw },
 { .hw = &g12a_fclk_div3.hw },
 { .hw = &g12a_fclk_div5.hw },
};

static struct clk_regmap g12a_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,
  .parent_data = clk81_parent_data,
  .num_parents = ARRAY_SIZE(clk81_parent_data),
 },
};

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

static struct clk_regmap g12a_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 *[]) {
   &g12a_mpeg_clk_div.hw
  },
  .num_parents = 1,
  .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
 },
};

static const struct clk_parent_data g12a_sd_emmc_clk0_parent_data[] = {
 { .fw_name = "xtal", },
 { .hw = &g12a_fclk_div2.hw },
 { .hw = &g12a_fclk_div3.hw },
 { .hw = &g12a_fclk_div5.hw },
 { .hw = &g12a_fclk_div7.hw },
 /*
 * Following these parent clocks, we should also have had mpll2, mpll3
 * and gp0_pll but these clocks are too precious to be used here. All
 * the necessary rates for MMC and NAND operation can be achieved using
 * g12a_ee_core or fclk_div clocks
 */

};

/* SDIO clock */
static struct clk_regmap g12a_sd_emmc_a_clk0_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SD_EMMC_CLK_CNTL,
  .mask = 0x7,
  .shift = 9,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "sd_emmc_a_clk0_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = g12a_sd_emmc_clk0_parent_data,
  .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_data),
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

static struct clk_regmap g12a_sd_emmc_a_clk0 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SD_EMMC_CLK_CNTL,
  .bit_idx = 7,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sd_emmc_a_clk0",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_sd_emmc_a_clk0_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* SDcard clock */
static struct clk_regmap g12a_sd_emmc_b_clk0_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SD_EMMC_CLK_CNTL,
  .mask = 0x7,
  .shift = 25,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "sd_emmc_b_clk0_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = g12a_sd_emmc_clk0_parent_data,
  .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_data),
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

static struct clk_regmap g12a_sd_emmc_b_clk0 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SD_EMMC_CLK_CNTL,
  .bit_idx = 23,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sd_emmc_b_clk0",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &g12a_sd_emmc_b_clk0_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

/* EMMC/NAND clock */
static struct clk_regmap g12a_sd_emmc_c_clk0_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_NAND_CLK_CNTL,
  .mask = 0x7,
  .shift = 9,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "sd_emmc_c_clk0_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = g12a_sd_emmc_clk0_parent_data,
--> --------------------

--> maximum size reached

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

Messung V0.5
C=97 H=100 G=98

¤ Dauer der Verarbeitung: 0.21 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.