#include <linux/platform_device.h>
 
 #include "gxbb.h"
-#include "clk-input.h"
 #include "clk-regmap.h"
 #include "clk-pll.h"
 #include "clk-mpll.h"
 #include "meson-eeclk.h"
 #include "vid-pll-div.h"
 
-#define IN_PREFIX "ee-in-"
-
 static DEFINE_SPINLOCK(meson_clk_lock);
 
 static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
        .hw.init = &(struct clk_init_data){
                .name = "fixed_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "fixed_pll",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "fixed_pll_dco" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_fixed_pll_dco.hw
+               },
                .num_parents = 1,
                /*
                 * This clock won't ever change at runtime so
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_pre_mult",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_hdmi_pll_pre_mult.hw
+               },
                .num_parents = 1,
                /*
                 * Display directly handle hdmi pll registers ATM, we need
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+               },
                .num_parents = 1,
                /*
                 * Display directly handle hdmi pll registers ATM, we need
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_od",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "hdmi_pll_dco" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_hdmi_pll_dco.hw
+               },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_od2",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "hdmi_pll_od" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_hdmi_pll_od.hw
+               },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "hdmi_pll_od2" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_hdmi_pll_od2.hw
+               },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_od",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "hdmi_pll_dco" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxl_hdmi_pll_dco.hw
+               },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_od2",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "hdmi_pll_od" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxl_hdmi_pll_od.hw
+               },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "hdmi_pll_od2" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxl_hdmi_pll_od2.hw
+               },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "sys_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "sys_pll",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "sys_pll_dco" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_sys_pll_dco.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .parent_data = &(const struct clk_parent_data) {
+                       .fw_name = "xtal",
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "gp0_pll_dco" },
+               .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,
        },
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div2_div",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_fixed_pll.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div2",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "fclk_div2_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_fclk_div2_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_IS_CRITICAL,
        },
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div3_div",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div3",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "fclk_div3_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_fclk_div3_div.hw
+               },
                .num_parents = 1,
                /*
                 * FIXME:
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div4_div",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div4",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "fclk_div4_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_fclk_div4_div.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div5_div",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div5",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "fclk_div5_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_fclk_div5_div.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div7_div",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "fclk_div7",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "fclk_div7_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_fclk_div7_div.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "mpll_prediv",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "fixed_pll" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_fixed_pll.hw },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "mpll0_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "mpll_prediv" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mpll_prediv.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "mpll0",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "mpll0_div" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "mpll1_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "mpll_prediv" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mpll_prediv.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "mpll1",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "mpll1_div" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_mpll1_div.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "mpll2_div",
                .ops = &meson_clk_mpll_ops,
-               .parent_names = (const char *[]){ "mpll_prediv" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mpll_prediv.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "mpll2",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "mpll2_div" },
+               .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 char * const clk81_parent_names[] = {
-       IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
-       "fclk_div3", "fclk_div5"
+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 = {
                 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
                 * fclk_div4, fclk_div3, fclk_div5
                 */
-               .parent_names = clk81_parent_names,
-               .num_parents = ARRAY_SIZE(clk81_parent_names),
+               .parent_data = clk81_parent_data,
+               .num_parents = ARRAY_SIZE(clk81_parent_data),
        },
 };
 
        .hw.init = &(struct clk_init_data){
                .name = "mpeg_clk_div",
                .ops = &clk_regmap_divider_ro_ops,
-               .parent_names = (const char *[]){ "mpeg_clk_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mpeg_clk_sel.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "clk81",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "mpeg_clk_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mpeg_clk_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_IS_CRITICAL,
        },
                .name = "sar_adc_clk_sel",
                .ops = &clk_regmap_mux_ops,
                /* NOTE: The datasheet doesn't list the parents for bit 10 */
-               .parent_names = (const char *[]){ IN_PREFIX "xtal", "clk81", },
+               .parent_data = (const struct clk_parent_data []) {
+                       { .fw_name = "xtal", },
+                       { .hw = &gxbb_clk81.hw },
+               },
                .num_parents = 2,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "sar_adc_clk_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "sar_adc_clk_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_sar_adc_clk_sel.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "sar_adc_clk",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "sar_adc_clk_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_sar_adc_clk_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
  * muxed by a glitch-free switch.
  */
 
-static const char * const gxbb_mali_0_1_parent_names[] = {
-       IN_PREFIX "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
-       "fclk_div4", "fclk_div3", "fclk_div5"
+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 = {
                 * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
                 * fclk_div4, fclk_div3, fclk_div5
                 */
-               .parent_names = gxbb_mali_0_1_parent_names,
+               .parent_data = gxbb_mali_0_1_parent_data,
                .num_parents = 8,
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "mali_0_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "mali_0_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mali_0_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "mali_0",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "mali_0_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mali_0_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
                 * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
                 * fclk_div4, fclk_div3, fclk_div5
                 */
-               .parent_names = gxbb_mali_0_1_parent_names,
+               .parent_data = gxbb_mali_0_1_parent_data,
                .num_parents = 8,
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "mali_1_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "mali_1_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mali_1_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "mali_1",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "mali_1_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mali_1_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static const char * const gxbb_mali_parent_names[] = {
-       "mali_0", "mali_1"
+static const struct clk_hw *gxbb_mali_parent_hws[] = {
+       &gxbb_mali_0.hw,
+       &gxbb_mali_1.hw,
 };
 
 static struct clk_regmap gxbb_mali = {
        .hw.init = &(struct clk_init_data){
                .name = "mali",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_mali_parent_names,
+               .parent_hws = gxbb_mali_parent_hws,
                .num_parents = 2,
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cts_amclk_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mpll0.hw,
+                       &gxbb_mpll1.hw,
+                       &gxbb_mpll2.hw,
+               },
                .num_parents = 3,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "cts_amclk_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "cts_amclk_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_cts_amclk_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cts_amclk",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "cts_amclk_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_cts_amclk_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "cts_mclk_i958_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_mpll0.hw,
+                       &gxbb_mpll1.hw,
+                       &gxbb_mpll2.hw,
+               },
                .num_parents = 3,
        },
 };
        .hw.init = &(struct clk_init_data) {
                .name = "cts_mclk_i958_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "cts_mclk_i958_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_cts_mclk_i958_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cts_mclk_i958",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "cts_mclk_i958_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_cts_mclk_i958_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "cts_i958",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" },
+               .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
        },
 };
 
+static const struct clk_parent_data gxbb_32k_clk_parent_data[] = {
+       { .fw_name = "xtal", },
+       /*
+        * FIXME: This clock is provided by the ao clock controller but the
+        * clock is not yet part of the binding of this controller, so string
+        * name must be use to set this parent.
+        */
+       { .name = "cts_slow_oscin", .index = -1 },
+       { .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,
+               },
+       .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,
        .hw.init = &(struct clk_init_data){
                .name = "32k_clk_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "32k_clk_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_32k_clk_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "32k_clk",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "32k_clk_div" },
-               .num_parents = 1,
-               .flags = CLK_SET_RATE_PARENT,
-       },
-};
-
-static const char * const gxbb_32k_clk_parent_names[] = {
-       IN_PREFIX "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
-};
-
-static struct clk_regmap gxbb_32k_clk_sel = {
-       .data = &(struct clk_regmap_mux_data){
-               .offset = HHI_32K_CLK_CNTL,
-               .mask = 0x3,
-               .shift = 16,
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_32k_clk_div.hw
                },
-       .hw.init = &(struct clk_init_data){
-               .name = "32k_clk_sel",
-               .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_32k_clk_parent_names,
-               .num_parents = 4,
+               .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
 };
 
-static const char * const gxbb_sd_emmc_clk0_parent_names[] = {
-       IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
-
+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
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_a_clk0_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_sd_emmc_clk0_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
+               .parent_data = gxbb_sd_emmc_clk0_parent_data,
+               .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_a_clk0_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_sd_emmc_a_clk0_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "sd_emmc_a_clk0",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_sd_emmc_a_clk0_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_b_clk0_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_sd_emmc_clk0_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
+               .parent_data = gxbb_sd_emmc_clk0_parent_data,
+               .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_b_clk0_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_sd_emmc_b_clk0_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "sd_emmc_b_clk0",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_sd_emmc_b_clk0_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_c_clk0_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_sd_emmc_clk0_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names),
+               .parent_data = gxbb_sd_emmc_clk0_parent_data,
+               .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_data),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
        .hw.init = &(struct clk_init_data) {
                .name = "sd_emmc_c_clk0_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_sd_emmc_c_clk0_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "sd_emmc_c_clk0",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
+               .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 char * const gxbb_vpu_parent_names[] = {
-       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+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 = {
                 * bits 9:10 selects from 4 possible parents:
                 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
                 */
-               .parent_names = gxbb_vpu_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names),
+               .parent_hws = gxbb_vpu_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_vpu_parent_hws),
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vpu_0_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "vpu_0_sel" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_0_sel.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vpu_0",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vpu_0_div" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_0_div.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
                 * bits 25:26 selects from 4 possible parents:
                 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
                 */
-               .parent_names = gxbb_vpu_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vpu_parent_names),
+               .parent_hws = gxbb_vpu_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_vpu_parent_hws),
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vpu_1_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "vpu_1_sel" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_1_sel.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vpu_1",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vpu_1_div" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vpu_1_div.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
                 * bit 31 selects from 2 possible parents:
                 * vpu_0 or vpu_1
                 */
-               .parent_names = (const char *[]){ "vpu_0", "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 char * const gxbb_vapb_parent_names[] = {
-       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+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 = {
                 * bits 9:10 selects from 4 possible parents:
                 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
                 */
-               .parent_names = gxbb_vapb_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names),
+               .parent_hws = gxbb_vapb_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_vapb_parent_hws),
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vapb_0_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "vapb_0_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vapb_0_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vapb_0",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vapb_0_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vapb_0_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
                 * bits 25:26 selects from 4 possible parents:
                 * fclk_div4, fclk_div3, fclk_div5, fclk_div7,
                 */
-               .parent_names = gxbb_vapb_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vapb_parent_names),
+               .parent_hws = gxbb_vapb_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_vapb_parent_hws),
                .flags = CLK_SET_RATE_NO_REPARENT,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vapb_1_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "vapb_1_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vapb_1_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vapb_1",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vapb_1_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vapb_1_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
                 * bit 31 selects from 2 possible parents:
                 * vapb_0 or vapb_1
                 */
-               .parent_names = (const char *[]){ "vapb_0", "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,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vapb",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vapb_sel" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vapb_sel.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vid_pll_div",
                .ops = &meson_vid_pll_div_ro_ops,
-               .parent_names = (const char *[]){ "hdmi_pll" },
+               .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 char * const gxbb_vid_pll_parent_names[] = { "vid_pll_div", "hdmi_pll" };
+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){
                 * bit 18 selects from 2 possible parents:
                 * vid_pll_div or hdmi_pll
                 */
-               .parent_names = gxbb_vid_pll_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vid_pll_parent_names),
+               .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,
        },
 };
        .hw.init = &(struct clk_init_data) {
                .name = "vid_pll",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vid_pll_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vid_pll_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
 };
 
-static const char * const gxbb_vclk_parent_names[] = {
-       "vid_pll", "fclk_div4", "fclk_div3", "fclk_div5", "vid_pll",
-       "fclk_div7", "mpll1",
+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 = {
                 * vid_pll, fclk_div4, fclk_div3, fclk_div5,
                 * vid_pll, fclk_div7, mp1
                 */
-               .parent_names = gxbb_vclk_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vclk_parent_names),
+               .parent_hws = gxbb_vclk_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_vclk_parent_hws),
                .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
        },
 };
                 * vid_pll, fclk_div4, fclk_div3, fclk_div5,
                 * vid_pll, fclk_div7, mp1
                 */
-               .parent_names = gxbb_vclk_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vclk_parent_names),
+               .parent_hws = gxbb_vclk_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_vclk_parent_hws),
                .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
        },
 };
        .hw.init = &(struct clk_init_data) {
                .name = "vclk_input",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk_sel" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk_sel.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk2_input",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk2_sel" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2_sel.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data){
                .name = "vclk_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "vclk_input" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk_input.hw
+               },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE,
        },
        .hw.init = &(struct clk_init_data){
                .name = "vclk2_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "vclk2_input" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk2_input.hw
+               },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk_div" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk_div.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk2",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk2_div" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2_div.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk_div1",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk_div2_en",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk_div4_en",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk_div6_en",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk_div12_en",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk2_div1",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk2" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk2_div2_en",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk2" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk2_div4_en",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk2" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk2_div6_en",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk2" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vclk2_div12_en",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vclk2" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_vclk2.hw },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data){
                .name = "vclk_div2",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "vclk_div2_en" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk_div2_en.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vclk_div4",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "vclk_div4_en" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk_div4_en.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vclk_div6",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "vclk_div6_en" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk_div6_en.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vclk_div12",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "vclk_div12_en" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk_div12_en.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vclk2_div2",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "vclk2_div2_en" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk2_div2_en.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vclk2_div4",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "vclk2_div4_en" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk2_div4_en.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vclk2_div6",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "vclk2_div6_en" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vclk2_div6_en.hw
+               },
                .num_parents = 1,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vclk2_div12",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "vclk2_div12_en" },
+               .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 char * const gxbb_cts_parent_names[] = {
-       "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
-       "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
-       "vclk2_div6", "vclk2_div12"
+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 = {
        .hw.init = &(struct clk_init_data){
                .name = "cts_enci_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_cts_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
+               .parent_hws = gxbb_cts_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws),
                .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "cts_encp_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_cts_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
+               .parent_hws = gxbb_cts_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_cts_parent_hws),
                .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "cts_vdac_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_cts_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_cts_parent_names),
+               .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 char * const gxbb_cts_hdmi_tx_parent_names[] = {
-       "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
-       "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
-       "vclk2_div6", "vclk2_div12"
+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 = {
                 * vclk2_div1, vclk2_div2, vclk2_div4, vclk2_div6, vclk2_div12,
                 * cts_tcon
                 */
-               .parent_names = gxbb_cts_hdmi_tx_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_cts_hdmi_tx_parent_names),
+               .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,
        },
 };
        .hw.init = &(struct clk_init_data) {
                .name = "cts_enci",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "cts_enci_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_cts_enci_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "cts_encp",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "cts_encp_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_cts_encp_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "cts_vdac",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "cts_vdac_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_cts_vdac_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "hdmi_tx",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "hdmi_tx_sel" },
+               .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 char * const gxbb_hdmi_parent_names[] = {
-       IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5"
+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 = {
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_hdmi_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_hdmi_parent_names),
+               .parent_data = gxbb_hdmi_parent_data,
+               .num_parents = ARRAY_SIZE(gxbb_hdmi_parent_data),
                .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "hdmi_sel" },
+               .parent_hws = (const struct clk_hw *[]) { &gxbb_hdmi_sel.hw },
                .num_parents = 1,
                .flags = CLK_GET_RATE_NOCACHE,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "hdmi",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "hdmi_div" },
+               .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 char * const gxbb_vdec_parent_names[] = {
-       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
+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 = {
        .hw.init = &(struct clk_init_data){
                .name = "vdec_1_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_vdec_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vdec_parent_names),
+               .parent_hws = gxbb_vdec_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_vdec_parent_hws),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vdec_1_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "vdec_1_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vdec_1_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vdec_1",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vdec_1_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vdec_1_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "vdec_hevc_sel",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = gxbb_vdec_parent_names,
-               .num_parents = ARRAY_SIZE(gxbb_vdec_parent_names),
+               .parent_hws = gxbb_vdec_parent_hws,
+               .num_parents = ARRAY_SIZE(gxbb_vdec_parent_hws),
                .flags = CLK_SET_RATE_PARENT,
        },
 };
        .hw.init = &(struct clk_init_data){
                .name = "vdec_hevc_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "vdec_hevc_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_vdec_hevc_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data) {
                .name = "vdec_hevc",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "vdec_hevc_div" },
+               .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 char * const gen_clk_parent_names[] = {
-       IN_PREFIX "xtal", "vdec_1", "vdec_hevc", "mpll0", "mpll1", "mpll2",
-       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
+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 = {
                 * vid_pll, vid2_pll (hevc), mpll0, mpll1, mpll2, fdiv4,
                 * fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll
                 */
-               .parent_names = gen_clk_parent_names,
-               .num_parents = ARRAY_SIZE(gen_clk_parent_names),
+               .parent_data = gen_clk_parent_data,
+               .num_parents = ARRAY_SIZE(gen_clk_parent_data),
        },
 };
 
        .hw.init = &(struct clk_init_data){
                .name = "gen_clk_div",
                .ops = &clk_regmap_divider_ops,
-               .parent_names = (const char *[]){ "gen_clk_sel" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_gen_clk_sel.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
        .hw.init = &(struct clk_init_data){
                .name = "gen_clk",
                .ops = &clk_regmap_gate_ops,
-               .parent_names = (const char *[]){ "gen_clk_div" },
+               .parent_hws = (const struct clk_hw *[]) {
+                       &gxbb_gen_clk_div.hw
+               },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },