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

Quelle  gxbb.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2016 AmLogic, Inc.
 * Michael Turquette <mturquette@baylibre.com>
 */


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

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

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

#define SCR    0x2c
#define TIMEOUT_VALUE   0x3c

#define HHI_GP0_PLL_CNTL  0x40
#define HHI_GP0_PLL_CNTL2  0x44
#define HHI_GP0_PLL_CNTL3  0x48
#define HHI_GP0_PLL_CNTL4  0x4c
#define HHI_GP0_PLL_CNTL5  0x50
#define HHI_GP0_PLL_CNTL1  0x58

#define HHI_XTAL_DIVN_CNTL  0xbc
#define HHI_TIMER90K   0xec

#define HHI_MEM_PD_REG0   0x100
#define HHI_MEM_PD_REG1   0x104
#define HHI_VPU_MEM_PD_REG1  0x108
#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_OSCIN_CNTL  0x158
#define HHI_SYS_CPU_CLK_CNTL1  0x15c
#define HHI_SYS_CPU_RESET_CNTL  0x160
#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_SYS_CPU_CLK_CNTL0  0x19c
#define HHI_VID_PLL_CLK_DIV  0x1a0
#define HHI_AUD_CLK_CNTL3  0x1a4
#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_VDEC4_CLK_CNTL  0x1ec
#define HHI_HDCP22_CLK_CNTL  0x1f0
#define HHI_VAPBCLK_CNTL  0x1f4

#define HHI_VPU_CLKB_CNTL  0x20c
#define HHI_USB_CLK_CNTL  0x220
#define HHI_32K_CLK_CNTL  0x224
#define HHI_GEN_CLK_CNTL  0x228

#define HHI_PCM_CLK_CNTL  0x258
#define HHI_NAND_CLK_CNTL  0x25c
#define HHI_SD_EMMC_CLK_CNTL  0x264

#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

#define HHI_MPLL3_CNTL0   0x2e0
#define HHI_MPLL3_CNTL1   0x2e4
#define HHI_VDAC_CNTL0   0x2f4
#define HHI_VDAC_CNTL1   0x2f8

#define HHI_SYS_PLL_CNTL  0x300
#define HHI_SYS_PLL_CNTL2  0x304
#define HHI_SYS_PLL_CNTL3  0x308
#define HHI_SYS_PLL_CNTL4  0x30c
#define HHI_SYS_PLL_CNTL5  0x310
#define HHI_DPLL_TOP_I   0x318
#define HHI_DPLL_TOP2_I   0x31c
#define HHI_HDMI_PLL_CNTL  0x320
#define HHI_HDMI_PLL_CNTL2  0x324
#define HHI_HDMI_PLL_CNTL3  0x328
#define HHI_HDMI_PLL_CNTL4  0x32c
#define HHI_HDMI_PLL_CNTL5  0x330
#define HHI_HDMI_PLL_CNTL6  0x334
#define HHI_HDMI_PLL_CNTL_I  0x338
#define HHI_HDMI_PLL_CNTL7  0x33c

#define HHI_HDMI_PHY_CNTL0  0x3a0
#define HHI_HDMI_PHY_CNTL1  0x3a4
#define HHI_HDMI_PHY_CNTL2  0x3a8
#define HHI_HDMI_PHY_CNTL3  0x3ac

#define HHI_VID_LOCK_CLK_CNTL  0x3c8
#define HHI_BT656_CLK_CNTL  0x3d4
#define HHI_SAR_CLK_CNTL  0x3d8

static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
 PLL_PARAMS(32, 1),
 PLL_PARAMS(33, 1),
 PLL_PARAMS(34, 1),
 PLL_PARAMS(35, 1),
 PLL_PARAMS(36, 1),
 PLL_PARAMS(37, 1),
 PLL_PARAMS(38, 1),
 PLL_PARAMS(39, 1),
 PLL_PARAMS(40, 1),
 PLL_PARAMS(41, 1),
 PLL_PARAMS(42, 1),
 PLL_PARAMS(43, 1),
 PLL_PARAMS(44, 1),
 PLL_PARAMS(45, 1),
 PLL_PARAMS(46, 1),
 PLL_PARAMS(47, 1),
 PLL_PARAMS(48, 1),
 PLL_PARAMS(49, 1),
 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),
 { /* sentinel */ },
};

static const struct pll_params_table gxl_gp0_pll_params_table[] = {
 PLL_PARAMS(42, 1),
 PLL_PARAMS(43, 1),
 PLL_PARAMS(44, 1),
 PLL_PARAMS(45, 1),
 PLL_PARAMS(46, 1),
 PLL_PARAMS(47, 1),
 PLL_PARAMS(48, 1),
 PLL_PARAMS(49, 1),
 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),
 { /* sentinel */ },
};

static struct clk_regmap gxbb_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",
  },
  .num_parents = 1,
 },
};

static struct clk_regmap gxbb_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 *[]) {
   &gxbb_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 gxbb_hdmi_pll_pre_mult = {
 .mult = 2,
 .div = 1,
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_pre_mult",
  .ops = &clk_fixed_factor_ops,
  .parent_data = &(const struct clk_parent_data) {
   .fw_name = "xtal",
  },
  .num_parents = 1,
 },
};

static struct clk_regmap gxbb_hdmi_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 30,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 0,
   .width   = 9,
  },
  .n = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 9,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_HDMI_PLL_CNTL2,
   .shift   = 0,
   .width   = 12,
  },
  .l = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 28,
   .width   = 1,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_dco",
  .ops = &meson_clk_pll_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_hdmi_pll_pre_mult.hw
  },
  .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 gxl_hdmi_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 30,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 0,
   .width   = 9,
  },
  .n = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 9,
   .width   = 5,
  },
  /*
 * On gxl, there is a register shift due to
 * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
 * so we use the HHI_HDMI_PLL_CNTL2 define from GXBB
 * instead which is defined at the same offset.
 */

  .frac = {
   .reg_off = HHI_HDMI_PLL_CNTL2,
   .shift   = 0,
   .width   = 10,
  },
  .l = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_HDMI_PLL_CNTL,
   .shift   = 28,
   .width   = 1,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_pll_dco",
  .ops = &meson_clk_pll_ro_ops,
  .parent_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 gxbb_hdmi_pll_od = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL2,
  .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 *[]) {
   &gxbb_hdmi_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxbb_hdmi_pll_od2 = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL2,
  .shift = 22,
  .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 *[]) {
   &gxbb_hdmi_pll_od.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxbb_hdmi_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL2,
  .shift = 18,
  .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 *[]) {
   &gxbb_hdmi_pll_od2.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxl_hdmi_pll_od = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL + 8,
  .shift = 21,
  .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 *[]) {
   &gxl_hdmi_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxl_hdmi_pll_od2 = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL + 8,
  .shift = 23,
  .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 *[]) {
   &gxl_hdmi_pll_od.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxl_hdmi_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_HDMI_PLL_CNTL + 8,
  .shift = 19,
  .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 *[]) {
   &gxl_hdmi_pll_od2.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxbb_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,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "sys_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 gxbb_sys_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_SYS_PLL_CNTL,
  .shift = 10,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sys_pll",
  .ops = &clk_regmap_divider_ro_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_sys_pll_dco.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct reg_sequence gxbb_gp0_init_regs[] = {
 { .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 },
 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 },
 { .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d },
};

static struct clk_regmap gxbb_gp0_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 30,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 0,
   .width   = 9,
  },
  .n = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 9,
   .width   = 5,
  },
  .l = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 29,
   .width   = 1,
  },
  .table = gxbb_gp0_pll_params_table,
  .init_regs = gxbb_gp0_init_regs,
  .init_count = ARRAY_SIZE(gxbb_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 const struct reg_sequence gxl_gp0_init_regs[] = {
 { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 },
 { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be },
 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
 { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
};

static struct clk_regmap gxl_gp0_pll_dco = {
 .data = &(struct meson_clk_pll_data){
  .en = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 30,
   .width   = 1,
  },
  .m = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 0,
   .width   = 9,
  },
  .n = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 9,
   .width   = 5,
  },
  .frac = {
   .reg_off = HHI_GP0_PLL_CNTL1,
   .shift   = 0,
   .width   = 10,
  },
  .l = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 31,
   .width   = 1,
  },
  .rst = {
   .reg_off = HHI_GP0_PLL_CNTL,
   .shift   = 29,
   .width   = 1,
  },
  .table = gxl_gp0_pll_params_table,
  .init_regs = gxl_gp0_init_regs,
  .init_count = ARRAY_SIZE(gxl_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 gxbb_gp0_pll = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_GP0_PLL_CNTL,
  .shift = 16,
  .width = 2,
  .flags = CLK_DIVIDER_POWER_OF_TWO,
 },
 .hw.init = &(struct clk_init_data){
  .name = "gp0_pll",
  .ops = &clk_regmap_divider_ops,
  .parent_data = &(const struct clk_parent_data) {
   /*
 * Note:
 * GXL and GXBB have different gp0_pll_dco (with
 * different struct clk_hw). We fallback to the global
 * naming string mechanism so gp0_pll picks up the
 * appropriate one.
 */

   .name = "gp0_pll_dco",
   .index = -1,
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

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

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

static struct clk_regmap gxbb_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 *[]) {
   &gxbb_fclk_div3_div.hw
  },
  .num_parents = 1,
  /*
 * FIXME:
 * This clock, as fdiv2, is used by the SCPI FW 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) The SCPI generic driver claims and enable all the clocks
 *    it needs
 * 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 gxbb_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 *[]) { &gxbb_fixed_pll.hw },
  .num_parents = 1,
 },
};

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

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

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

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

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

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

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

static struct clk_regmap gxl_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,
  },
 },
 .hw.init = &(struct clk_init_data){
  .name = "mpll0_div",
  .ops = &meson_clk_mpll_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_mpll_prediv.hw
  },
  .num_parents = 1,
 },
};

static struct clk_regmap gxbb_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_data = &(const struct clk_parent_data) {
   /*
 * Note:
 * GXL and GXBB have different SDM_EN registers. We
 * fallback to the global naming string mechanism so
 * mpll0_div picks up the appropriate one.
 */

   .name = "mpll0_div",
   .index = -1,
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

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

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

static struct clk_regmap gxbb_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 *[]) { &gxbb_mpll2_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 = &gxbb_fclk_div7.hw },
 { .hw = &gxbb_mpll1.hw },
 { .hw = &gxbb_mpll2.hw },
 { .hw = &gxbb_fclk_div4.hw },
 { .hw = &gxbb_fclk_div3.hw },
 { .hw = &gxbb_fclk_div5.hw },
};

static struct clk_regmap gxbb_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,
  /*
 * 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_data = clk81_parent_data,
  .num_parents = ARRAY_SIZE(clk81_parent_data),
 },
};

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

/* the mother of dragons gates */
static struct clk_regmap gxbb_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 *[]) {
   &gxbb_mpeg_clk_div.hw
  },
  .num_parents = 1,
  .flags = CLK_IS_CRITICAL,
 },
};

static struct clk_regmap gxbb_sar_adc_clk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_SAR_CLK_CNTL,
  .mask = 0x3,
  .shift = 9,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sar_adc_clk_sel",
  .ops = &clk_regmap_mux_ops,
  /* NOTE: The datasheet doesn't list the parents for bit 10 */
  .parent_data = (const struct clk_parent_data []) {
   { .fw_name = "xtal", },
   { .hw = &gxbb_clk81.hw },
  },
  .num_parents = 2,
 },
};

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

static struct clk_regmap gxbb_sar_adc_clk = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_SAR_CLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data){
  .name = "sar_adc_clk",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_sar_adc_clk_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. The CCF can 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.
 */


static const struct clk_parent_data gxbb_mali_0_1_parent_data[] = {
 { .fw_name = "xtal", },
 { .hw = &gxbb_gp0_pll.hw },
 { .hw = &gxbb_mpll2.hw },
 { .hw = &gxbb_mpll1.hw },
 { .hw = &gxbb_fclk_div7.hw },
 { .hw = &gxbb_fclk_div4.hw },
 { .hw = &gxbb_fclk_div3.hw },
 { .hw = &gxbb_fclk_div5.hw },
};

static struct clk_regmap gxbb_mali_0_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_MALI_CLK_CNTL,
  .mask = 0x7,
  .shift = 9,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali_0_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = gxbb_mali_0_1_parent_data,
  .num_parents = 8,
  /*
 * Don't request the parent to change the rate because
 * all GPU frequencies can be derived from the fclk_*
 * clocks and one special GP0_PLL setting. This is
 * important because we need the MPLL clocks for audio.
 */

  .flags = 0,
 },
};

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

static struct clk_regmap gxbb_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 *[]) {
   &gxbb_mali_0_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxbb_mali_1_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_MALI_CLK_CNTL,
  .mask = 0x7,
  .shift = 25,
 },
 .hw.init = &(struct clk_init_data){
  .name = "mali_1_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = gxbb_mali_0_1_parent_data,
  .num_parents = 8,
  /*
 * Don't request the parent to change the rate because
 * all GPU frequencies can be derived from the fclk_*
 * clocks and one special GP0_PLL setting. This is
 * important because we need the MPLL clocks for audio.
 */

  .flags = 0,
 },
};

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

static struct clk_regmap gxbb_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 *[]) {
   &gxbb_mali_1_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
 },
};

static const struct clk_hw *gxbb_mali_parent_hws[] = {
 &gxbb_mali_0.hw,
 &gxbb_mali_1.hw,
};

static struct clk_regmap gxbb_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 = gxbb_mali_parent_hws,
  .num_parents = 2,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxbb_cts_amclk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_AUD_CLK_CNTL,
  .mask = 0x3,
  .shift = 9,
  .table = (u32[]){ 1, 2, 3 },
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_amclk_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_mpll0.hw,
   &gxbb_mpll1.hw,
   &gxbb_mpll2.hw,
  },
  .num_parents = 3,
 },
};

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

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

static struct clk_regmap gxbb_cts_mclk_i958_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_AUD_CLK_CNTL2,
  .mask = 0x3,
  .shift = 25,
  .table = (u32[]){ 1, 2, 3 },
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cts_mclk_i958_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_mpll0.hw,
   &gxbb_mpll1.hw,
   &gxbb_mpll2.hw,
  },
  .num_parents = 3,
 },
};

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

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

static struct clk_regmap gxbb_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 *[]) {
   &gxbb_cts_amclk.hw,
   &gxbb_cts_mclk_i958.hw
  },
  .num_parents = 2,
  /*
 *The parent is specific to origin of the audio data. Let the
 * consumer choose the appropriate parent
 */

  .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
 },
};

/*
 * This table skips a clock named 'cts_slow_oscin' in the documentation
 * This clock does not exist yet in this controller or the AO one
 */

static u32 gxbb_32k_clk_parents_val_table[] = { 0, 2, 3 };
static const struct clk_parent_data gxbb_32k_clk_parent_data[] = {
 { .fw_name = "xtal", },
 { .hw = &gxbb_fclk_div3.hw },
 { .hw = &gxbb_fclk_div5.hw },
};

static struct clk_regmap gxbb_32k_clk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_32K_CLK_CNTL,
  .mask = 0x3,
  .shift = 16,
  .table = gxbb_32k_clk_parents_val_table,
  },
 .hw.init = &(struct clk_init_data){
  .name = "32k_clk_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = gxbb_32k_clk_parent_data,
  .num_parents = 4,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxbb_32k_clk_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_32K_CLK_CNTL,
  .shift = 0,
  .width = 14,
 },
 .hw.init = &(struct clk_init_data){
  .name = "32k_clk_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_32k_clk_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static struct clk_regmap gxbb_32k_clk = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_32K_CLK_CNTL,
  .bit_idx = 15,
 },
 .hw.init = &(struct clk_init_data){
  .name = "32k_clk",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_32k_clk_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

static const struct clk_parent_data gxbb_sd_emmc_clk0_parent_data[] = {
 { .fw_name = "xtal", },
 { .hw = &gxbb_fclk_div2.hw },
 { .hw = &gxbb_fclk_div3.hw },
 { .hw = &gxbb_fclk_div5.hw },
 { .hw = &gxbb_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
 * xtal or fclk_div clocks
 */

};

/* SDIO clock */
static struct clk_regmap gxbb_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 = gxbb_sd_emmc_clk0_parent_data,
  .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

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

/* SDcard clock */
static struct clk_regmap gxbb_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 = gxbb_sd_emmc_clk0_parent_data,
  .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

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

/* EMMC/NAND clock */
static struct clk_regmap gxbb_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 = gxbb_sd_emmc_clk0_parent_data,
  .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

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

/* VPU Clock */

static const struct clk_hw *gxbb_vpu_parent_hws[] = {
 &gxbb_fclk_div4.hw,
 &gxbb_fclk_div3.hw,
 &gxbb_fclk_div5.hw,
 &gxbb_fclk_div7.hw,
};

static struct clk_regmap gxbb_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,
  /*
 * bits 9:10 selects from 4 possible parents:
 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
 */

  .parent_hws = gxbb_vpu_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_vpu_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

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

static struct clk_regmap gxbb_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 *[]) { &gxbb_vpu_0_div.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_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,
  /*
 * bits 25:26 selects from 4 possible parents:
 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
 */

  .parent_hws = gxbb_vpu_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_vpu_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

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

static struct clk_regmap gxbb_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 *[]) { &gxbb_vpu_1_div.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_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,
  /*
 * bit 31 selects from 2 possible parents:
 * vpu_0 or vpu_1
 */

  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_vpu_0.hw,
   &gxbb_vpu_1.hw
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

/* VAPB Clock */

static const struct clk_hw *gxbb_vapb_parent_hws[] = {
 &gxbb_fclk_div4.hw,
 &gxbb_fclk_div3.hw,
 &gxbb_fclk_div5.hw,
 &gxbb_fclk_div7.hw,
};

static struct clk_regmap gxbb_vapb_0_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VAPBCLK_CNTL,
  .mask = 0x3,
  .shift = 9,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vapb_0_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * bits 9:10 selects from 4 possible parents:
 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
 */

  .parent_hws = gxbb_vapb_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_vapb_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

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

static struct clk_regmap gxbb_vapb_0 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VAPBCLK_CNTL,
  .bit_idx = 8,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vapb_0",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_vapb_0_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_vapb_1_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VAPBCLK_CNTL,
  .mask = 0x3,
  .shift = 25,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vapb_1_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * bits 25:26 selects from 4 possible parents:
 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
 */

  .parent_hws = gxbb_vapb_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_vapb_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

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

static struct clk_regmap gxbb_vapb_1 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VAPBCLK_CNTL,
  .bit_idx = 24,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vapb_1",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_vapb_1_div.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_vapb_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VAPBCLK_CNTL,
  .mask = 1,
  .shift = 31,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vapb_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * bit 31 selects from 2 possible parents:
 * vapb_0 or vapb_1
 */

  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_vapb_0.hw,
   &gxbb_vapb_1.hw
  },
  .num_parents = 2,
  .flags = CLK_SET_RATE_NO_REPARENT,
 },
};

static struct clk_regmap gxbb_vapb = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VAPBCLK_CNTL,
  .bit_idx = 30,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vapb",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) { &gxbb_vapb_sel.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

/* Video Clocks */

static struct clk_regmap gxbb_vid_pll_div = {
 .data = &(struct meson_vid_pll_div_data){
  .val = {
   .reg_off = HHI_VID_PLL_CLK_DIV,
   .shift   = 0,
   .width   = 15,
  },
  .sel = {
   .reg_off = HHI_VID_PLL_CLK_DIV,
   .shift   = 16,
   .width   = 2,
  },
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vid_pll_div",
  .ops = &meson_vid_pll_div_ro_ops,
  .parent_data = &(const struct clk_parent_data) {
   /*
 * Note:
 * GXL and GXBB have different hdmi_plls (with
 * different struct clk_hw). We fallback to the global
 * naming string mechanism so vid_pll_div picks up the
 * appropriate one.
 */

   .name = "hdmi_pll",
   .index = -1,
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
 },
};

static const struct clk_parent_data gxbb_vid_pll_parent_data[] = {
 { .hw = &gxbb_vid_pll_div.hw },
 /*
 * Note:
 * GXL and GXBB have different hdmi_plls (with
 * different struct clk_hw). We fallback to the global
 * naming string mechanism so vid_pll_div picks up the
 * appropriate one.
 */

 { .name = "hdmi_pll", .index = -1 },
};

static struct clk_regmap gxbb_vid_pll_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_PLL_CLK_DIV,
  .mask = 0x1,
  .shift = 18,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vid_pll_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * bit 18 selects from 2 possible parents:
 * vid_pll_div or hdmi_pll
 */

  .parent_data = gxbb_vid_pll_parent_data,
  .num_parents = ARRAY_SIZE(gxbb_vid_pll_parent_data),
  .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
 },
};

static struct clk_regmap gxbb_vid_pll = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_PLL_CLK_DIV,
  .bit_idx = 19,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vid_pll",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_vid_pll_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static const struct clk_hw *gxbb_vclk_parent_hws[] = {
 &gxbb_vid_pll.hw,
 &gxbb_fclk_div4.hw,
 &gxbb_fclk_div3.hw,
 &gxbb_fclk_div5.hw,
 &gxbb_vid_pll.hw,
 &gxbb_fclk_div7.hw,
 &gxbb_mpll1.hw,
};

static struct clk_regmap gxbb_vclk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_CLK_CNTL,
  .mask = 0x7,
  .shift = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * bits 16:18 selects from 8 possible parents:
 * vid_pll, fclk_div4, fclk_div3, fclk_div5,
 * vid_pll, fclk_div7, mp1
 */

  .parent_hws = gxbb_vclk_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_vclk_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
 },
};

static struct clk_regmap gxbb_vclk2_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VIID_CLK_CNTL,
  .mask = 0x7,
  .shift = 16,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * bits 16:18 selects from 8 possible parents:
 * vid_pll, fclk_div4, fclk_div3, fclk_div5,
 * vid_pll, fclk_div7, mp1
 */

  .parent_hws = gxbb_vclk_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_vclk_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
 },
};

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

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

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

static struct clk_regmap gxbb_vclk2_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_VIID_CLK_DIV,
  .shift = 0,
  .width = 8,
 },
 .hw.init = &(struct clk_init_data){
  .name = "vclk2_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_vclk2_input.hw
  },
  .num_parents = 1,
  .flags = CLK_GET_RATE_NOCACHE,
 },
};

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

static struct clk_regmap gxbb_vclk2 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_CNTL,
  .bit_idx = 19,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vclk2",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2_div.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

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

static struct clk_regmap gxbb_vclk_div2_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL,
  .bit_idx = 1,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vclk_div2_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_vclk_div4_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL,
  .bit_idx = 2,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vclk_div4_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_vclk_div6_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL,
  .bit_idx = 3,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vclk_div6_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_vclk_div12_en = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL,
  .bit_idx = 4,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vclk_div12_en",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_vclk2_div1 = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VIID_CLK_CNTL,
  .bit_idx = 0,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "vclk2_div1",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

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

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

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

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

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

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

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

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

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

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

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

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

static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
static const struct clk_hw *gxbb_cts_parent_hws[] = {
 &gxbb_vclk_div1.hw,
 &gxbb_vclk_div2.hw,
 &gxbb_vclk_div4.hw,
 &gxbb_vclk_div6.hw,
 &gxbb_vclk_div12.hw,
 &gxbb_vclk2_div1.hw,
 &gxbb_vclk2_div2.hw,
 &gxbb_vclk2_div4.hw,
 &gxbb_vclk2_div6.hw,
 &gxbb_vclk2_div12.hw,
};

static struct clk_regmap gxbb_cts_enci_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_CLK_DIV,
  .mask = 0xf,
  .shift = 28,
  .table = mux_table_cts_sel,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_enci_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = gxbb_cts_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
 },
};

static struct clk_regmap gxbb_cts_encp_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VID_CLK_DIV,
  .mask = 0xf,
  .shift = 20,
  .table = mux_table_cts_sel,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_encp_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = gxbb_cts_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
 },
};

static struct clk_regmap gxbb_cts_vdac_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_VIID_CLK_DIV,
  .mask = 0xf,
  .shift = 28,
  .table = mux_table_cts_sel,
 },
 .hw.init = &(struct clk_init_data){
  .name = "cts_vdac_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_hws = gxbb_cts_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
 },
};

/* TOFIX: add support for cts_tcon */
static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
static const struct clk_hw *gxbb_cts_hdmi_tx_parent_hws[] = {
 &gxbb_vclk_div1.hw,
 &gxbb_vclk_div2.hw,
 &gxbb_vclk_div4.hw,
 &gxbb_vclk_div6.hw,
 &gxbb_vclk_div12.hw,
 &gxbb_vclk2_div1.hw,
 &gxbb_vclk2_div2.hw,
 &gxbb_vclk2_div4.hw,
 &gxbb_vclk2_div6.hw,
 &gxbb_vclk2_div12.hw,
};

static struct clk_regmap gxbb_hdmi_tx_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_HDMI_CLK_CNTL,
  .mask = 0xf,
  .shift = 16,
  .table = mux_table_hdmi_tx_sel,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_tx_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * bits 31:28 selects from 12 possible parents:
 * vclk_div1, vclk_div2, vclk_div4, vclk_div6, vclk_div12
 * vclk2_div1, vclk2_div2, vclk2_div4, vclk2_div6, vclk2_div12,
 * cts_tcon
 */

  .parent_hws = gxbb_cts_hdmi_tx_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_cts_hdmi_tx_parent_hws),
  .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
 },
};

static struct clk_regmap gxbb_cts_enci = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL2,
  .bit_idx = 0,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cts_enci",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_cts_enci_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

static struct clk_regmap gxbb_cts_encp = {
 .data = &(struct clk_regmap_gate_data){
  .offset = HHI_VID_CLK_CNTL2,
  .bit_idx = 2,
 },
 .hw.init = &(struct clk_init_data) {
  .name = "cts_encp",
  .ops = &clk_regmap_gate_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_cts_encp_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 },
};

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

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

/* HDMI Clocks */

static const struct clk_parent_data gxbb_hdmi_parent_data[] = {
 { .fw_name = "xtal", },
 { .hw = &gxbb_fclk_div4.hw },
 { .hw = &gxbb_fclk_div3.hw },
 { .hw = &gxbb_fclk_div5.hw },
};

static struct clk_regmap gxbb_hdmi_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_HDMI_CLK_CNTL,
  .mask = 0x3,
  .shift = 9,
  .flags = CLK_MUX_ROUND_CLOSEST,
 },
 .hw.init = &(struct clk_init_data){
  .name = "hdmi_sel",
  .ops = &clk_regmap_mux_ops,
  .parent_data = gxbb_hdmi_parent_data,
  .num_parents = ARRAY_SIZE(gxbb_hdmi_parent_data),
  .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
 },
};

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

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

/* VDEC clocks */

static const struct clk_hw *gxbb_vdec_parent_hws[] = {
 &gxbb_fclk_div4.hw,
 &gxbb_fclk_div3.hw,
 &gxbb_fclk_div5.hw,
 &gxbb_fclk_div7.hw,
};

static struct clk_regmap gxbb_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 = gxbb_vdec_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_vdec_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

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

static struct clk_regmap gxbb_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 = gxbb_vdec_parent_hws,
  .num_parents = ARRAY_SIZE(gxbb_vdec_parent_hws),
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

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

static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
        9, 10, 11, 13, 14, };
static const struct clk_parent_data gen_clk_parent_data[] = {
 { .fw_name = "xtal", },
 { .hw = &gxbb_vdec_1.hw },
 { .hw = &gxbb_vdec_hevc.hw },
 { .hw = &gxbb_mpll0.hw },
 { .hw = &gxbb_mpll1.hw },
 { .hw = &gxbb_mpll2.hw },
 { .hw = &gxbb_fclk_div4.hw },
 { .hw = &gxbb_fclk_div3.hw },
 { .hw = &gxbb_fclk_div5.hw },
 { .hw = &gxbb_fclk_div7.hw },
 { .hw = &gxbb_gp0_pll.hw },
};

static struct clk_regmap gxbb_gen_clk_sel = {
 .data = &(struct clk_regmap_mux_data){
  .offset = HHI_GEN_CLK_CNTL,
  .mask = 0xf,
  .shift = 12,
  .table = mux_table_gen_clk,
 },
 .hw.init = &(struct clk_init_data){
  .name = "gen_clk_sel",
  .ops = &clk_regmap_mux_ops,
  /*
 * bits 15:12 selects from 14 possible parents:
 * xtal, [rtc_oscin_i], [sys_cpu_div16], [ddr_dpll_pt],
 * vid_pll, vid2_pll (hevc), mpll0, mpll1, mpll2, fdiv4,
 * fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll
 */

  .parent_data = gen_clk_parent_data,
  .num_parents = ARRAY_SIZE(gen_clk_parent_data),
 },
};

static struct clk_regmap gxbb_gen_clk_div = {
 .data = &(struct clk_regmap_div_data){
  .offset = HHI_GEN_CLK_CNTL,
  .shift = 0,
  .width = 11,
 },
 .hw.init = &(struct clk_init_data){
  .name = "gen_clk_div",
  .ops = &clk_regmap_divider_ops,
  .parent_hws = (const struct clk_hw *[]) {
   &gxbb_gen_clk_sel.hw
  },
  .num_parents = 1,
  .flags = CLK_SET_RATE_PARENT,
 },
};

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

#define MESON_GATE(_name, _reg, _bit) \
 MESON_PCLK(_name, _reg, _bit, &gxbb_clk81.hw)

/* Everything Else (EE) domain gates */
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
static MESON_GATE(gxbb_isa, HHI_GCLK_MPEG0, 5);
static MESON_GATE(gxbb_pl301, HHI_GCLK_MPEG0, 6);
static MESON_GATE(gxbb_periphs, HHI_GCLK_MPEG0, 7);
static MESON_GATE(gxbb_spicc, HHI_GCLK_MPEG0, 8);
static MESON_GATE(gxbb_i2c, HHI_GCLK_MPEG0, 9);
static MESON_GATE(gxbb_sana, HHI_GCLK_MPEG0, 10);
static MESON_GATE(gxbb_smart_card, HHI_GCLK_MPEG0, 11);
static MESON_GATE(gxbb_rng0, HHI_GCLK_MPEG0, 12);
static MESON_GATE(gxbb_uart0, HHI_GCLK_MPEG0, 13);
--> --------------------

--> maximum size reached

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

Messung V0.5
C=96 H=95 G=95

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