From nobody Thu Apr 9 15:00:56 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 672AE425CC6; Mon, 2 Mar 2026 16:55:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772470509; cv=none; b=sW9QljGO8STB7OwRgXsaryW3f7XKmTBsbOG09lcmbSlgu3vwe+JtQm0tc7upzfSxT42wMz1Rtyk210EGvX56CAr7Z+w9vLO4a7Ls7v5cS53xxrIgECsEtCJ/PiJw4l4pnSbiIqn1t2Yy5xaFvRtoPnIgn9CNanCreQLSLkRL7gU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772470509; c=relaxed/simple; bh=q+tM+UtASsTL7Oj2PbAvKMqzA0FMmY8zcmlPttQJUao=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HWTU3jxh1IA4Nkd4RvNUJyZWXWBFglj9GQOodsimFLuaald/pNjVCNitxRFIgQT7wKR1xrF9MUQPqF9y+KZ8hTkk3OTZPRbq9EHgzcdbg3NVF3FSCQvYXlkayQ1r05ofJIWleZVHoWWV1j3cijRysfLqXOBwd23og5AjoTWew/s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com; spf=pass smtp.mailfrom=renesas.com; arc=none smtp.client-ip=210.160.252.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=renesas.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=renesas.com X-CSE-ConnectionGUID: Kycd62WBRMOxuxragn1z9Q== X-CSE-MsgGUID: Xjdv8tztTP2mbrdZH8U3XQ== Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie5.idc.renesas.com with ESMTP; 03 Mar 2026 01:55:01 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.92.15]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 64C5C401A65F; Tue, 3 Mar 2026 01:54:57 +0900 (JST) From: Ovidiu Panait To: geert+renesas@glider.be, magnus.damm@gmail.com, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, mturquette@baylibre.com, sboyd@kernel.org, biju.das.jz@bp.renesas.com, fabrizio.castro.jz@renesas.com Cc: linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org Subject: [PATCH v4 3/7] clk: versaclock3: Reference parent clocks by type and index Date: Mon, 2 Mar 2026 16:54:37 +0000 Message-ID: <20260302165441.4457-4-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260302165441.4457-1-ovidiu.panait.rb@renesas.com> References: <20260302165441.4457-1-ovidiu.panait.rb@renesas.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The current implementation uses direct pointers to clk_hw structures (via .parent_hws) to define parent-child relationships between clocks. This works for a single device instance but prevents supporting multiple devices since all instances would share the same static clk_hw pointers. Replace direct pointers with parent references using a type and index pair. For example, VC3_CLK_PARENT(PLL, VC3_PLL1) refers to the first PLL clock. These references are resolved to actual clk_hw pointers at probe time by the new vc3_register_clk() function. This is a preparatory change for adding support for multiple versaclock3 instances, where each device will have its own set of clk_hw structures. Signed-off-by: Ovidiu Panait --- v4 changes: None. v3 changes: New patch. drivers/clk/clk-versaclock3.c | 401 +++++++++++++++++++++++----------- 1 file changed, 276 insertions(+), 125 deletions(-) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index 18ef0f38c85b..d3e23566a38c 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -83,6 +83,8 @@ #define VC3_2_POW_16 (U16_MAX + 1) #define VC3_DIV_MASK(width) ((1 << (width)) - 1) =20 +#define VC3_CLK_PARENT(t, i) { .type =3D VC3_CLK_##t, .idx =3D (i) } + enum vc3_pfd_mux { VC3_PFD2_MUX, VC3_PFD3_MUX, @@ -131,6 +133,26 @@ enum vc3_clk_mux { VC3_DIFF2_MUX =3D VC3_DIFF2 - 1, }; =20 +enum vc3_clk_type { + VC3_CLK_EXT, + VC3_CLK_PFD_MUX, + VC3_CLK_PFD, + VC3_CLK_PLL, + VC3_CLK_DIV_MUX, + VC3_CLK_DIV, + VC3_CLK_CLK_MUX, +}; + +struct vc3_clk_parent { + enum vc3_clk_type type; + u8 idx; +}; + +struct vc3_parent_info { + const struct vc3_clk_parent *parents; + u8 num_parents; +}; + struct vc3_clk_data { u8 offs; u8 bitmsk; @@ -164,6 +186,7 @@ struct vc3_div_data { }; =20 struct vc3_hw_data { + const struct vc3_parent_info *parent_info; struct clk_hw hw; struct regmap *regmap; void *data; @@ -598,11 +621,12 @@ static const struct regmap_config vc3_regmap_config = =3D { .max_register =3D 0x24, }; =20 -static struct vc3_hw_data clk_div[5]; - -static const struct clk_parent_data pfd_mux_parent_data[] =3D { - { .index =3D 0, }, - { .hw =3D &clk_div[VC3_DIV2].hw } +static const struct vc3_parent_info pfd_mux_parents =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(EXT, 0), + VC3_CLK_PARENT(DIV, VC3_DIV2), + }, + .num_parents =3D 2, }; =20 static struct vc3_hw_data clk_pfd_mux[] =3D { @@ -614,10 +638,9 @@ static struct vc3_hw_data clk_pfd_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "pfd2_mux", .ops =3D &vc3_pfd_mux_ops, - .parent_data =3D pfd_mux_parent_data, - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT - } + }, + .parent_info =3D &pfd_mux_parents, }, [VC3_PFD3_MUX] =3D { .data =3D &(struct vc3_clk_data) { @@ -627,13 +650,33 @@ static struct vc3_hw_data clk_pfd_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "pfd3_mux", .ops =3D &vc3_pfd_mux_ops, - .parent_data =3D pfd_mux_parent_data, - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT - } + }, + .parent_info =3D &pfd_mux_parents, } }; =20 +static const struct vc3_parent_info pfd_parents[] =3D { + [VC3_PFD1] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(EXT, 0), + }, + .num_parents =3D 1, + }, + [VC3_PFD2] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PFD_MUX, VC3_PFD2_MUX), + }, + .num_parents =3D 1, + }, + [VC3_PFD3] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PFD_MUX, VC3_PFD3_MUX), + }, + .num_parents =3D 1, + }, +}; + static struct vc3_hw_data clk_pfd[] =3D { [VC3_PFD1] =3D { .data =3D &(struct vc3_pfd_data) { @@ -645,12 +688,9 @@ static struct vc3_hw_data clk_pfd[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "pfd1", .ops =3D &vc3_pfd_ops, - .parent_data =3D &(const struct clk_parent_data) { - .index =3D 0 - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &pfd_parents[VC3_PFD1], }, [VC3_PFD2] =3D { .data =3D &(struct vc3_pfd_data) { @@ -662,12 +702,9 @@ static struct vc3_hw_data clk_pfd[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "pfd2", .ops =3D &vc3_pfd_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_pfd_mux[VC3_PFD2_MUX].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &pfd_parents[VC3_PFD2], }, [VC3_PFD3] =3D { .data =3D &(struct vc3_pfd_data) { @@ -679,15 +716,33 @@ static struct vc3_hw_data clk_pfd[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "pfd3", .ops =3D &vc3_pfd_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_pfd_mux[VC3_PFD3_MUX].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &pfd_parents[VC3_PFD3], } }; =20 +static const struct vc3_parent_info pll_parents[] =3D { + [VC3_PLL1] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PFD, VC3_PFD1), + }, + .num_parents =3D 1, + }, + [VC3_PLL2] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PFD, VC3_PFD2), + }, + .num_parents =3D 1, + }, + [VC3_PLL3] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PFD, VC3_PFD3), + }, + .num_parents =3D 1, + }, +}; + static struct vc3_hw_data clk_pll[] =3D { [VC3_PLL1] =3D { .data =3D &(struct vc3_pll_data) { @@ -702,12 +757,9 @@ static struct vc3_hw_data clk_pll[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "pll1", .ops =3D &vc3_pll_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_pfd[VC3_PFD1].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &pll_parents[VC3_PLL1], }, [VC3_PLL2] =3D { .data =3D &(struct vc3_pll_data) { @@ -718,12 +770,9 @@ static struct vc3_hw_data clk_pll[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "pll2", .ops =3D &vc3_pll_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_pfd[VC3_PFD2].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &pll_parents[VC3_PLL2], }, [VC3_PLL3] =3D { .data =3D &(struct vc3_pll_data) { @@ -738,28 +787,34 @@ static struct vc3_hw_data clk_pll[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "pll3", .ops =3D &vc3_pll_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_pfd[VC3_PFD3].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &pll_parents[VC3_PLL3], } }; =20 -static const struct clk_parent_data div_mux_parent_data[][2] =3D { +static const struct vc3_parent_info div_mux_parents[] =3D { [VC3_DIV1_MUX] =3D { - { .hw =3D &clk_pll[VC3_PLL1].hw }, - { .index =3D 0 } + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PLL, VC3_PLL1), + VC3_CLK_PARENT(EXT, 0), + }, + .num_parents =3D 2, }, [VC3_DIV3_MUX] =3D { - { .hw =3D &clk_pll[VC3_PLL2].hw }, - { .hw =3D &clk_pll[VC3_PLL3].hw } + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PLL, VC3_PLL2), + VC3_CLK_PARENT(PLL, VC3_PLL3), + }, + .num_parents =3D 2, }, [VC3_DIV4_MUX] =3D { - { .hw =3D &clk_pll[VC3_PLL2].hw }, - { .index =3D 0 } - } + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PLL, VC3_PLL2), + VC3_CLK_PARENT(EXT, 0), + }, + .num_parents =3D 2, + }, }; =20 static struct vc3_hw_data clk_div_mux[] =3D { @@ -771,10 +826,9 @@ static struct vc3_hw_data clk_div_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "div1_mux", .ops =3D &vc3_div_mux_ops, - .parent_data =3D div_mux_parent_data[VC3_DIV1_MUX], - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT - } + }, + .parent_info =3D &div_mux_parents[VC3_DIV1_MUX], }, [VC3_DIV3_MUX] =3D { .data =3D &(struct vc3_clk_data) { @@ -784,10 +838,9 @@ static struct vc3_hw_data clk_div_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "div3_mux", .ops =3D &vc3_div_mux_ops, - .parent_data =3D div_mux_parent_data[VC3_DIV3_MUX], - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT - } + }, + .parent_info =3D &div_mux_parents[VC3_DIV3_MUX], }, [VC3_DIV4_MUX] =3D { .data =3D &(struct vc3_clk_data) { @@ -797,13 +850,45 @@ static struct vc3_hw_data clk_div_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "div4_mux", .ops =3D &vc3_div_mux_ops, - .parent_data =3D div_mux_parent_data[VC3_DIV4_MUX], - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT - } + }, + .parent_info =3D &div_mux_parents[VC3_DIV4_MUX], } }; =20 +static const struct vc3_parent_info div_parents[] =3D { + [VC3_DIV1] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(DIV_MUX, VC3_DIV1_MUX), + }, + .num_parents =3D 1, + }, + [VC3_DIV2] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PLL, VC3_PLL1), + }, + .num_parents =3D 1, + }, + [VC3_DIV3] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(DIV_MUX, VC3_DIV3_MUX), + }, + .num_parents =3D 1, + }, + [VC3_DIV4] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(DIV_MUX, VC3_DIV4_MUX), + }, + .num_parents =3D 1, + }, + [VC3_DIV5] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(PLL, VC3_PLL3), + }, + .num_parents =3D 1, + }, +}; + static struct vc3_hw_data clk_div[] =3D { [VC3_DIV1] =3D { .data =3D &(struct vc3_div_data) { @@ -816,12 +901,9 @@ static struct vc3_hw_data clk_div[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "div1", .ops =3D &vc3_div_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_div_mux[VC3_DIV1_MUX].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &div_parents[VC3_DIV1], }, [VC3_DIV2] =3D { .data =3D &(struct vc3_div_data) { @@ -834,12 +916,9 @@ static struct vc3_hw_data clk_div[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "div2", .ops =3D &vc3_div_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_pll[VC3_PLL1].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &div_parents[VC3_DIV2], }, [VC3_DIV3] =3D { .data =3D &(struct vc3_div_data) { @@ -852,12 +931,9 @@ static struct vc3_hw_data clk_div[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "div3", .ops =3D &vc3_div_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_div_mux[VC3_DIV3_MUX].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &div_parents[VC3_DIV3], }, [VC3_DIV4] =3D { .data =3D &(struct vc3_div_data) { @@ -870,12 +946,9 @@ static struct vc3_hw_data clk_div[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "div4", .ops =3D &vc3_div_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_div_mux[VC3_DIV4_MUX].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &div_parents[VC3_DIV4], }, [VC3_DIV5] =3D { .data =3D &(struct vc3_div_data) { @@ -888,15 +961,50 @@ static struct vc3_hw_data clk_div[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "div5", .ops =3D &vc3_div_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_pll[VC3_PLL3].hw - }, - .num_parents =3D 1, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &div_parents[VC3_DIV5], } }; =20 +static const struct vc3_parent_info clk_mux_parents[] =3D { + [VC3_SE1_MUX] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(DIV, VC3_DIV5), + VC3_CLK_PARENT(DIV, VC3_DIV4), + }, + .num_parents =3D 2, + }, + [VC3_SE2_MUX] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(DIV, VC3_DIV5), + VC3_CLK_PARENT(DIV, VC3_DIV4), + }, + .num_parents =3D 2, + }, + [VC3_SE3_MUX] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(DIV, VC3_DIV2), + VC3_CLK_PARENT(DIV, VC3_DIV4), + }, + .num_parents =3D 2, + }, + [VC3_DIFF1_MUX] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(DIV, VC3_DIV1), + VC3_CLK_PARENT(DIV, VC3_DIV3), + }, + .num_parents =3D 2, + }, + [VC3_DIFF2_MUX] =3D { + .parents =3D (const struct vc3_clk_parent[]) { + VC3_CLK_PARENT(DIV, VC3_DIV1), + VC3_CLK_PARENT(DIV, VC3_DIV3), + }, + .num_parents =3D 2, + }, +}; + static struct vc3_hw_data clk_mux[] =3D { [VC3_SE1_MUX] =3D { .data =3D &(struct vc3_clk_data) { @@ -906,13 +1014,9 @@ static struct vc3_hw_data clk_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "se1_mux", .ops =3D &vc3_clk_mux_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_div[VC3_DIV5].hw, - &clk_div[VC3_DIV4].hw - }, - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &clk_mux_parents[VC3_SE1_MUX], }, [VC3_SE2_MUX] =3D { .data =3D &(struct vc3_clk_data) { @@ -921,13 +1025,9 @@ static struct vc3_hw_data clk_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "se2_mux", .ops =3D &vc3_clk_mux_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_div[VC3_DIV5].hw, - &clk_div[VC3_DIV4].hw - }, - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &clk_mux_parents[VC3_SE2_MUX], }, [VC3_SE3_MUX] =3D { .data =3D &(struct vc3_clk_data) { @@ -937,13 +1037,9 @@ static struct vc3_hw_data clk_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "se3_mux", .ops =3D &vc3_clk_mux_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_div[VC3_DIV2].hw, - &clk_div[VC3_DIV4].hw - }, - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &clk_mux_parents[VC3_SE3_MUX], }, [VC3_DIFF1_MUX] =3D { .data =3D &(struct vc3_clk_data) { @@ -953,13 +1049,9 @@ static struct vc3_hw_data clk_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "diff1_mux", .ops =3D &vc3_clk_mux_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_div[VC3_DIV1].hw, - &clk_div[VC3_DIV3].hw - }, - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &clk_mux_parents[VC3_DIFF1_MUX], }, [VC3_DIFF2_MUX] =3D { .data =3D &(struct vc3_clk_data) { @@ -969,16 +1061,81 @@ static struct vc3_hw_data clk_mux[] =3D { .hw.init =3D &(struct clk_init_data) { .name =3D "diff2_mux", .ops =3D &vc3_clk_mux_ops, - .parent_hws =3D (const struct clk_hw *[]) { - &clk_div[VC3_DIV1].hw, - &clk_div[VC3_DIV3].hw - }, - .num_parents =3D 2, .flags =3D CLK_SET_RATE_PARENT - } + }, + .parent_info =3D &clk_mux_parents[VC3_DIFF2_MUX], } }; =20 +static struct clk_hw *vc3_clk_get_hw(const struct vc3_clk_parent *parent) +{ + switch (parent->type) { + case VC3_CLK_EXT: + return NULL; + case VC3_CLK_PFD_MUX: + return &clk_pfd_mux[parent->idx].hw; + case VC3_CLK_PFD: + return &clk_pfd[parent->idx].hw; + case VC3_CLK_PLL: + return &clk_pll[parent->idx].hw; + case VC3_CLK_DIV_MUX: + return &clk_div_mux[parent->idx].hw; + case VC3_CLK_DIV: + return &clk_div[parent->idx].hw; + case VC3_CLK_CLK_MUX: + return &clk_mux[parent->idx].hw; + } + + return NULL; +} + +static struct clk_parent_data * +vc3_setup_parent_data(struct vc3_hw_data *hw_data) +{ + const struct vc3_parent_info *pinfo =3D hw_data->parent_info; + struct clk_parent_data *pd; + + pd =3D kcalloc(pinfo->num_parents, sizeof(*pd), GFP_KERNEL); + if (!pd) + return NULL; + + for (int i =3D 0; i < pinfo->num_parents; i++) { + const struct vc3_clk_parent *parent =3D &pinfo->parents[i]; + + if (parent->type =3D=3D VC3_CLK_EXT) + pd[i].index =3D parent->idx; + else + pd[i].hw =3D vc3_clk_get_hw(parent); + } + + return pd; +} + +static int vc3_register_clk(struct device *dev, struct vc3_hw_data *hw_dat= a, + struct regmap *regmap) +{ + struct clk_parent_data *pd; + struct clk_init_data init; + int ret; + + pd =3D vc3_setup_parent_data(hw_data); + if (!pd) + return -ENOMEM; + + init =3D *hw_data->hw.init; + init.parent_data =3D pd; + init.num_parents =3D hw_data->parent_info->num_parents; + + hw_data->regmap =3D regmap; + hw_data->hw.init =3D &init; + + ret =3D devm_clk_hw_register(dev, &hw_data->hw); + + kfree(pd); + + return ret; +} + static struct clk_hw *vc3_of_clk_get(struct of_phandle_args *clkspec, void *data) { @@ -1029,9 +1186,8 @@ static int vc3_probe(struct i2c_client *client) =20 /* Register pfd muxes */ for (i =3D 0; i < ARRAY_SIZE(clk_pfd_mux); i++) { - clk_pfd_mux[i].regmap =3D regmap; name =3D clk_pfd_mux[i].hw.init->name; - ret =3D devm_clk_hw_register(dev, &clk_pfd_mux[i].hw); + ret =3D vc3_register_clk(dev, &clk_pfd_mux[i], regmap); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1040,9 +1196,8 @@ static int vc3_probe(struct i2c_client *client) =20 /* Register pfd's */ for (i =3D 0; i < ARRAY_SIZE(clk_pfd); i++) { - clk_pfd[i].regmap =3D regmap; name =3D clk_pfd[i].hw.init->name; - ret =3D devm_clk_hw_register(dev, &clk_pfd[i].hw); + ret =3D vc3_register_clk(dev, &clk_pfd[i], regmap); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1053,14 +1208,13 @@ static int vc3_probe(struct i2c_client *client) =20 /* Register pll's */ for (i =3D 0; i < ARRAY_SIZE(clk_pll); i++) { - clk_pll[i].regmap =3D regmap; if (i =3D=3D VC3_PLL2) { struct vc3_pll_data *pll_data =3D clk_pll[i].data; =20 pll_data->vco =3D data->pll2_vco; } name =3D clk_pll[i].hw.init->name; - ret =3D devm_clk_hw_register(dev, &clk_pll[i].hw); + ret =3D vc3_register_clk(dev, &clk_pll[i], regmap); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1069,9 +1223,8 @@ static int vc3_probe(struct i2c_client *client) =20 /* Register divider muxes */ for (i =3D 0; i < ARRAY_SIZE(clk_div_mux); i++) { - clk_div_mux[i].regmap =3D regmap; name =3D clk_div_mux[i].hw.init->name; - ret =3D devm_clk_hw_register(dev, &clk_div_mux[i].hw); + ret =3D vc3_register_clk(dev, &clk_div_mux[i], regmap); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1080,9 +1233,8 @@ static int vc3_probe(struct i2c_client *client) =20 /* Register dividers */ for (i =3D 0; i < ARRAY_SIZE(clk_div); i++) { - clk_div[i].regmap =3D regmap; name =3D clk_div[i].hw.init->name; - ret =3D devm_clk_hw_register(dev, &clk_div[i].hw); + ret =3D vc3_register_clk(dev, &clk_div[i], regmap); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1091,14 +1243,13 @@ static int vc3_probe(struct i2c_client *client) =20 /* Register clk muxes */ for (i =3D 0; i < ARRAY_SIZE(clk_mux); i++) { - clk_mux[i].regmap =3D regmap; if (i =3D=3D VC3_SE2_MUX) { struct vc3_clk_data *clk_data =3D clk_mux[i].data; =20 clk_data->bitmsk =3D data->se2_clk_sel_msk; } name =3D clk_mux[i].hw.init->name; - ret =3D devm_clk_hw_register(dev, &clk_mux[i].hw); + ret =3D vc3_register_clk(dev, &clk_mux[i], regmap); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", --=20 2.51.0