From nobody Mon Feb 9 04:30:53 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 12BA638E11F; Tue, 3 Feb 2026 13:51:50 +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=1770126714; cv=none; b=ssdDxXeMndqb7i+wDrYaQiKy0nySWplWy5UYWB4n/v2D/2l80glT41oi+YuJKuOqMrmjQWgYFyDrJPn3hOmFOYyUpbYuhLiuv1FVzyQNE7vbUSTSX659JdIPvcHSgvkp6oi3oLjnZuv8Brt47lrN/knAKt5CWzjRePyLnUFn3gY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126714; c=relaxed/simple; bh=Ywcjcbu100tGXpUlxb+o6J4x3FEK3msJ3h+zUoxPbfY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Vh4d0ChdQwpJ8DSQCuR6AJT1jyrFhYzQlEyUdehFs4iSsxpIBZPPh8I/2kfCFg7YQCj0kZH7D+WZMttFhkxl7BsjjS20vupBHl7EDAEjnKC6cvItcOD9sRMGLy9Tp4jVdHlEggsgUy+shNHYs//OWiB8UVklieOJtfg6v7I6dLs= 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: ESbQLoKWQhKqVPTuKw55xg== X-CSE-MsgGUID: H7IGw9c8QaKSEMHdcYzV9Q== Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 03 Feb 2026 22:51:49 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.93.5]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id CCE73421BAE7; Tue, 3 Feb 2026 22:51:45 +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 v3 1/8] clk: versaclock3: Fix NULL pointer dereference in error path Date: Tue, 3 Feb 2026 13:51:32 +0000 Message-ID: <20260203135139.28151-2-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203135139.28151-1-ovidiu.panait.rb@renesas.com> References: <20260203135139.28151-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" If devm_clk_hw_register() fails, the driver logs an error using hw.init->name. However, the clock core sets hw->init to NULL in __clk_register() immediately after registration, regardless of success or failure. This leads to a NULL pointer dereference. To fix this, save the clock name before registration and use the saved pointer in the error message. While at it, improve the error message to make it more clear. Fixes: 6e9aff555db7 ("clk: Add support for versa3 clock driver") Signed-off-by: Ovidiu Panait --- v3 changes: New patch. drivers/clk/clk-versaclock3.c | 36 +++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index 27b6cf70f3ae..6dcf3d94db7b 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -1031,19 +1031,23 @@ static int vc3_probe(struct i2c_client *client) /* 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); if (ret) - return dev_err_probe(dev, ret, "%s failed\n", - clk_pfd_mux[i].hw.init->name); + return dev_err_probe(dev, ret, + "failed to register clock %s\n", + name); } =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); if (ret) - return dev_err_probe(dev, ret, "%s failed\n", - clk_pfd[i].hw.init->name); + return dev_err_probe(dev, ret, + "failed to register clock %s\n", + name); } =20 data =3D i2c_get_match_data(client); @@ -1056,28 +1060,34 @@ static int vc3_probe(struct i2c_client *client) =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); if (ret) - return dev_err_probe(dev, ret, "%s failed\n", - clk_pll[i].hw.init->name); + return dev_err_probe(dev, ret, + "failed to register clock %s\n", + name); } =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); if (ret) - return dev_err_probe(dev, ret, "%s failed\n", - clk_div_mux[i].hw.init->name); + return dev_err_probe(dev, ret, + "failed to register clock %s\n", + name); } =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); if (ret) - return dev_err_probe(dev, ret, "%s failed\n", - clk_div[i].hw.init->name); + return dev_err_probe(dev, ret, + "failed to register clock %s\n", + name); } =20 /* Register clk muxes */ @@ -1088,10 +1098,12 @@ static int vc3_probe(struct i2c_client *client) =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); if (ret) - return dev_err_probe(dev, ret, "%s failed\n", - clk_mux[i].hw.init->name); + return dev_err_probe(dev, ret, + "failed to register clock %s\n", + name); } =20 /* Register clk outputs */ --=20 2.51.0 From nobody Mon Feb 9 04:30:53 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C842D3A0B3B; Tue, 3 Feb 2026 13:51:54 +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=1770126716; cv=none; b=A9L05MW+2LiHQGuvh4aZovYEHtKF86tW5YFYYnQn/AFufGBGHIAwrFEP4IoNLwdl1g/PyJ7Vk4sF/5dMzpUprslnVAhNNOBHYE74uL+tD0ROEo2eaaCzGcT+uiVZ4dfh5LH/6uCwwcelXT0vauPivWGMOlub1RiUeQOpgiPgHaM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126716; c=relaxed/simple; bh=C3bdus2WtTzcQe+u+bKGTdm1/X2cWSeluF0Obtmw+RQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WJjMN/xxnKQjgPv81K8nIzXjd00oTInYGjdmoGxEho2fqbijCVh+JlEdR0hhCSBY1nF4gvIkH9KOXdNH22tg3weq0I0zCbcjHWeH2ntZursvlzmGDD7rnYYh47Cw0gDdz4C7QxwmRWEQ9Hc80FaSrvZdo1bj/NLqw3aW2c/X/6U= 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: V4IttBeMTGiG3+J685U/6A== X-CSE-MsgGUID: 3F8sns8qQkSG/hkS6jKriQ== Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 03 Feb 2026 22:51:54 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.93.5]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 7A09F421BAE7; Tue, 3 Feb 2026 22:51:50 +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 v3 2/8] clk: versaclock3: Remove unused SE2 clock select macro Date: Tue, 3 Feb 2026 13:51:33 +0000 Message-ID: <20260203135139.28151-3-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203135139.28151-1-ovidiu.panait.rb@renesas.com> References: <20260203135139.28151-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 VC3_SE2_CTRL_REG0_SE2_CLK_SEL macro is no longer used since commit ae6040cd7c7f8 ("clk: versaclock3: Prepare for the addition of 5L35023 device"), which switched SE2 clock select handling to use variant-specific OF data (se2_clk_sel_msk). Reviewed-by: Fabrizio Castro Signed-off-by: Ovidiu Panait --- v3 changes: - Added "Reviewed-by" tag from Fabrizio. drivers/clk/clk-versaclock3.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index 6dcf3d94db7b..18ef0f38c85b 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -61,7 +61,6 @@ #define VC3_OUTPUT_CTR_DIV4_SRC_SEL BIT(3) =20 #define VC3_SE2_CTRL_REG0 0x1f -#define VC3_SE2_CTRL_REG0_SE2_CLK_SEL BIT(6) =20 #define VC3_SE3_DIFF1_CTRL_REG 0x21 #define VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL BIT(6) --=20 2.51.0 From nobody Mon Feb 9 04:30:53 2026 Received: from relmlie6.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8C77D39C636; Tue, 3 Feb 2026 13:51:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126723; cv=none; b=LEdvc3Qmia4L8HvtDzKPgxptYkoH9eqc2bWnoRIi9AW6YkOCjDpvWfx85Yo4EbL6/CCzD+IVS2k3XZi7Db7s4mTCfFi9tL8T0zSFhEdk0KJ+YnyOw8F/b5oMqhtPBl+IlSxetlP48iUWrQWI/Xf5LMzk1WJJWoZ7pMIMQ6hTNS0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126723; c=relaxed/simple; bh=5E5rs/umqHKRLvBfn2kWJw4MJHkuLU+4u5BenpRw12A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FPKaolyfJXagLJjFxjMli92TaTdrqNwuKWukiWvQVh8nVLo3ut38BBYTB+w+Zci9sv1F7VDpZZ8fLUpWSGcAr9utgzIK/6aW/VAz1VbAfWhHP2yRWJDZ+v0grZ+cyBvX8z2mwYnrvkL6qf5vBJ5+FY5W9l8YPW1WtUQUWJTXi80= 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.172 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: wMkulYr6T9Sz9ihA82Ztqw== X-CSE-MsgGUID: MTdcizkeTZ64CUc0Cl//IQ== Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie6.idc.renesas.com with ESMTP; 03 Feb 2026 22:51:59 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.93.5]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 250D7421BAEF; Tue, 3 Feb 2026 22:51:54 +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 v3 3/8] clk: versaclock3: Reference parent clocks by type and index Date: Tue, 3 Feb 2026 13:51:34 +0000 Message-ID: <20260203135139.28151-4-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203135139.28151-1-ovidiu.panait.rb@renesas.com> References: <20260203135139.28151-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 --- 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 From nobody Mon Feb 9 04:30:53 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 1A6FD3A0B14; Tue, 3 Feb 2026 13:52:04 +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=1770126727; cv=none; b=VWTZyOWQFqhaE951AdJK4yHHVi0l6NFiaT/4Bl6sP6+ywMgM4QTER1qI823/eDWu2JiatwXcLPSpsM/mKQJvia7X8NJdcRcq60RtcgxzZLnfNQPvPWgNCxzfj9qqbjP4D9i674NiUbivip2/Hc9APr/d2R/xn2rCFJGTaI70xdo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126727; c=relaxed/simple; bh=zG5eeBSI9aXLtOguBcjWqWF8FoQhZzbWCEPj2Ix6q+o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Hjcm79ii7fsaBAmDhjCHmmxN7twCVz6JTZZKQYeRDkkSEgn5mWNsaac3MLrE2U7Pdfh07YpSUFPE0DVspjRdn8LxGZv/7R1jAA0y0Rk3B9xJHOmOloUXkRKXoniz+NHf4M6HflQx2go9r6Yr1wea9vAgQp+aY/9Cb1Fn7AQV6Dk= 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: 4yqFbzTrRnaCMrRd3qmrpA== X-CSE-MsgGUID: 2cTuTKFDSOm7MpRcerYMLg== Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 03 Feb 2026 22:52:03 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.93.5]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id C8D3E421BAE7; Tue, 3 Feb 2026 22:51:59 +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 v3 4/8] clk: versaclock3: Add per-device clock data structure Date: Tue, 3 Feb 2026 13:51:35 +0000 Message-ID: <20260203135139.28151-5-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203135139.28151-1-ovidiu.panait.rb@renesas.com> References: <20260203135139.28151-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" Introduce struct vc3_device_data to hold per-device copies of all clock hardware data arrays. The static clock arrays serve as templates describing the clock topology. During probe, these templates are referenced to initialize device-specific clock structures. This is required to support multiple versaclock3 devices simultaneously, as the current static arrays would be shared across all instances. Signed-off-by: Ovidiu Panait --- v3 changes: New patch. drivers/clk/clk-versaclock3.c | 114 +++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 37 deletions(-) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index d3e23566a38c..eb61a2c0b49b 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -13,6 +13,14 @@ =20 #define NUM_CONFIG_REGISTERS 37 =20 +#define VC3_PFD_MUX_NUM 2 +#define VC3_PFD_NUM 3 +#define VC3_PLL_NUM 3 +#define VC3_DIV_MUX_NUM 3 +#define VC3_DIV_NUM 5 +#define VC3_CLK_MUX_NUM 5 +#define VC3_CLK_OUT_NUM 6 + #define VC3_GENERAL_CTR 0x0 #define VC3_GENERAL_CTR_DIV1_SRC_SEL BIT(3) #define VC3_GENERAL_CTR_PLL3_REFIN_SEL BIT(2) @@ -200,6 +208,18 @@ struct vc3_hw_cfg { u32 se2_clk_sel_msk; }; =20 +struct vc3_device_data { + struct i2c_client *client; + struct regmap *regmap; + struct vc3_hw_data clk_pfd_mux[VC3_PFD_MUX_NUM]; + struct vc3_hw_data clk_pfd[VC3_PFD_NUM]; + struct vc3_hw_data clk_pll[VC3_PLL_NUM]; + struct vc3_hw_data clk_div_mux[VC3_DIV_MUX_NUM]; + struct vc3_hw_data clk_div[VC3_DIV_NUM]; + struct vc3_hw_data clk_mux[VC3_CLK_MUX_NUM]; + struct clk_hw *clk_out[VC3_CLK_OUT_NUM]; +}; + static const struct clk_div_table div1_divs[] =3D { { .val =3D 0, .div =3D 1, }, { .val =3D 1, .div =3D 4, }, { .val =3D 2, .div =3D 5, }, { .val =3D 3, .div =3D 6, }, @@ -236,8 +256,6 @@ static const struct clk_div_table div3_divs[] =3D { {} }; =20 -static struct clk_hw *clk_out[6]; - static u8 vc3_pfd_mux_get_parent(struct clk_hw *hw) { struct vc3_hw_data *vc3 =3D container_of(hw, struct vc3_hw_data, hw); @@ -1067,30 +1085,31 @@ static struct vc3_hw_data clk_mux[] =3D { } }; =20 -static struct clk_hw *vc3_clk_get_hw(const struct vc3_clk_parent *parent) +static struct clk_hw *vc3_clk_get_hw(struct vc3_device_data *vc3, + 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; + return &vc3->clk_pfd_mux[parent->idx].hw; case VC3_CLK_PFD: - return &clk_pfd[parent->idx].hw; + return &vc3->clk_pfd[parent->idx].hw; case VC3_CLK_PLL: - return &clk_pll[parent->idx].hw; + return &vc3->clk_pll[parent->idx].hw; case VC3_CLK_DIV_MUX: - return &clk_div_mux[parent->idx].hw; + return &vc3->clk_div_mux[parent->idx].hw; case VC3_CLK_DIV: - return &clk_div[parent->idx].hw; + return &vc3->clk_div[parent->idx].hw; case VC3_CLK_CLK_MUX: - return &clk_mux[parent->idx].hw; + return &vc3->clk_mux[parent->idx].hw; } =20 return NULL; } =20 static struct clk_parent_data * -vc3_setup_parent_data(struct vc3_hw_data *hw_data) +vc3_setup_parent_data(struct vc3_device_data *vc3, struct vc3_hw_data *hw_= data) { const struct vc3_parent_info *pinfo =3D hw_data->parent_info; struct clk_parent_data *pd; @@ -1105,28 +1124,34 @@ vc3_setup_parent_data(struct vc3_hw_data *hw_data) if (parent->type =3D=3D VC3_CLK_EXT) pd[i].index =3D parent->idx; else - pd[i].hw =3D vc3_clk_get_hw(parent); + pd[i].hw =3D vc3_clk_get_hw(vc3, parent); } =20 return pd; } =20 -static int vc3_register_clk(struct device *dev, struct vc3_hw_data *hw_dat= a, - struct regmap *regmap) +static int vc3_register_clk(struct vc3_device_data *vc3, + struct vc3_hw_data *hw_data, + const struct vc3_hw_data *template) { + struct device *dev =3D &vc3->client->dev; struct clk_parent_data *pd; struct clk_init_data init; int ret; =20 - pd =3D vc3_setup_parent_data(hw_data); + if (!hw_data->data) + hw_data->data =3D template->data; + hw_data->parent_info =3D template->parent_info; + + pd =3D vc3_setup_parent_data(vc3, hw_data); if (!pd) return -ENOMEM; =20 - init =3D *hw_data->hw.init; + init =3D *template->hw.init; init.parent_data =3D pd; init.num_parents =3D hw_data->parent_info->num_parents; =20 - hw_data->regmap =3D regmap; + hw_data->regmap =3D vc3->regmap; hw_data->hw.init =3D &init; =20 ret =3D devm_clk_hw_register(dev, &hw_data->hw); @@ -1142,7 +1167,7 @@ static struct clk_hw *vc3_of_clk_get(struct of_phandl= e_args *clkspec, unsigned int idx =3D clkspec->args[0]; struct clk_hw **clkout_hw =3D data; =20 - if (idx >=3D ARRAY_SIZE(clk_out)) { + if (idx >=3D VC3_CLK_OUT_NUM) { pr_err("invalid clk index %u for provider %pOF\n", idx, clkspec->np); return ERR_PTR(-EINVAL); } @@ -1155,13 +1180,18 @@ static int vc3_probe(struct i2c_client *client) struct device *dev =3D &client->dev; u8 settings[NUM_CONFIG_REGISTERS]; const struct vc3_hw_cfg *data; - struct regmap *regmap; + struct vc3_device_data *vc3; const char *name; int ret, i; =20 - regmap =3D devm_regmap_init_i2c(client, &vc3_regmap_config); - if (IS_ERR(regmap)) - return dev_err_probe(dev, PTR_ERR(regmap), + vc3 =3D devm_kzalloc(dev, sizeof(*vc3), GFP_KERNEL); + if (!vc3) + return -ENOMEM; + + vc3->client =3D client; + vc3->regmap =3D devm_regmap_init_i2c(client, &vc3_regmap_config); + if (IS_ERR(vc3->regmap)) + return dev_err_probe(dev, PTR_ERR(vc3->regmap), "failed to allocate register map\n"); =20 ret =3D of_property_read_u8_array(dev->of_node, "renesas,settings", @@ -1172,7 +1202,7 @@ static int vc3_probe(struct i2c_client *client) * settings to the device immediately. */ for (i =3D 0; i < NUM_CONFIG_REGISTERS; i++) { - ret =3D regmap_write(regmap, i, settings[i]); + ret =3D regmap_write(vc3->regmap, i, settings[i]); if (ret) { dev_err(dev, "error writing to chip (%i)\n", ret); return ret; @@ -1187,7 +1217,7 @@ static int vc3_probe(struct i2c_client *client) /* Register pfd muxes */ for (i =3D 0; i < ARRAY_SIZE(clk_pfd_mux); i++) { name =3D clk_pfd_mux[i].hw.init->name; - ret =3D vc3_register_clk(dev, &clk_pfd_mux[i], regmap); + ret =3D vc3_register_clk(vc3, &vc3->clk_pfd_mux[i], &clk_pfd_mux[i]); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1197,7 +1227,7 @@ static int vc3_probe(struct i2c_client *client) /* Register pfd's */ for (i =3D 0; i < ARRAY_SIZE(clk_pfd); i++) { name =3D clk_pfd[i].hw.init->name; - ret =3D vc3_register_clk(dev, &clk_pfd[i], regmap); + ret =3D vc3_register_clk(vc3, &vc3->clk_pfd[i], &clk_pfd[i]); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1209,12 +1239,17 @@ static int vc3_probe(struct i2c_client *client) /* Register pll's */ for (i =3D 0; i < ARRAY_SIZE(clk_pll); i++) { if (i =3D=3D VC3_PLL2) { - struct vc3_pll_data *pll_data =3D clk_pll[i].data; + struct vc3_pll_data *pll_data; =20 + pll_data =3D devm_kmemdup(dev, clk_pll[i].data, + sizeof(*pll_data), GFP_KERNEL); + if (!pll_data) + return -ENOMEM; pll_data->vco =3D data->pll2_vco; + vc3->clk_pll[i].data =3D pll_data; } name =3D clk_pll[i].hw.init->name; - ret =3D vc3_register_clk(dev, &clk_pll[i], regmap); + ret =3D vc3_register_clk(vc3, &vc3->clk_pll[i], &clk_pll[i]); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1224,7 +1259,7 @@ static int vc3_probe(struct i2c_client *client) /* Register divider muxes */ for (i =3D 0; i < ARRAY_SIZE(clk_div_mux); i++) { name =3D clk_div_mux[i].hw.init->name; - ret =3D vc3_register_clk(dev, &clk_div_mux[i], regmap); + ret =3D vc3_register_clk(vc3, &vc3->clk_div_mux[i], &clk_div_mux[i]); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1234,7 +1269,7 @@ static int vc3_probe(struct i2c_client *client) /* Register dividers */ for (i =3D 0; i < ARRAY_SIZE(clk_div); i++) { name =3D clk_div[i].hw.init->name; - ret =3D vc3_register_clk(dev, &clk_div[i], regmap); + ret =3D vc3_register_clk(vc3, &vc3->clk_div[i], &clk_div[i]); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1244,12 +1279,17 @@ static int vc3_probe(struct i2c_client *client) /* Register clk muxes */ for (i =3D 0; i < ARRAY_SIZE(clk_mux); i++) { if (i =3D=3D VC3_SE2_MUX) { - struct vc3_clk_data *clk_data =3D clk_mux[i].data; + struct vc3_clk_data *clk_data; =20 + clk_data =3D devm_kmemdup(dev, clk_mux[i].data, + sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; clk_data->bitmsk =3D data->se2_clk_sel_msk; + vc3->clk_mux[i].data =3D clk_data; } name =3D clk_mux[i].hw.init->name; - ret =3D vc3_register_clk(dev, &clk_mux[i], regmap); + ret =3D vc3_register_clk(vc3, &vc3->clk_mux[i], &clk_mux[i]); if (ret) return dev_err_probe(dev, ret, "failed to register clock %s\n", @@ -1257,7 +1297,7 @@ static int vc3_probe(struct i2c_client *client) } =20 /* Register clk outputs */ - for (i =3D 0; i < ARRAY_SIZE(clk_out); i++) { + for (i =3D 0; i < ARRAY_SIZE(vc3->clk_out); i++) { switch (i) { case VC3_DIFF2: name =3D "diff2"; @@ -1282,17 +1322,17 @@ static int vc3_probe(struct i2c_client *client) } =20 if (i =3D=3D VC3_REF) - clk_out[i] =3D devm_clk_hw_register_fixed_factor_index(dev, + vc3->clk_out[i] =3D devm_clk_hw_register_fixed_factor_index(dev, name, 0, CLK_SET_RATE_PARENT, 1, 1); else - clk_out[i] =3D devm_clk_hw_register_fixed_factor_parent_hw(dev, - name, &clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1); + vc3->clk_out[i] =3D devm_clk_hw_register_fixed_factor_parent_hw(dev, + name, &vc3->clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1); =20 - if (IS_ERR(clk_out[i])) - return PTR_ERR(clk_out[i]); + if (IS_ERR(vc3->clk_out[i])) + return PTR_ERR(vc3->clk_out[i]); } =20 - ret =3D devm_of_clk_add_hw_provider(dev, vc3_of_clk_get, clk_out); + ret =3D devm_of_clk_add_hw_provider(dev, vc3_of_clk_get, vc3->clk_out); if (ret) return dev_err_probe(dev, ret, "unable to add clk provider\n"); =20 --=20 2.51.0 From nobody Mon Feb 9 04:30:53 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C0F163A0B2A; Tue, 3 Feb 2026 13:52:08 +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=1770126730; cv=none; b=DK5zocQNmIhVeD49QcOfa1IDm0ZOVXVDe0UOOhNo7F1Y5vRmC2zVSbpNmeIA6+5gLIdx7JzlQi5JTG1Y2W+mPZQXdIQAX4szmbZbxBIX9u2mhGa4n6a4t0t5zj8NnNN6DylbTN2ejOm0GIFfF5zvOOjVdiiN8baj7B6GsqHNRWs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126730; c=relaxed/simple; bh=NnSUoYFWCPnoIcvtGsBTgKAld6nMfxWpWmkopbxmozg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BZRUclHzhdglcA0HfP3eJ5f28Ynx7NOKk9nIy5VavlF6uowGO7wN5LZMuBDZoYAUgHGA8YswbYIjWVDJzcleFZjeVVXXdZSgaVE3/9pnyVUpWeTL74WZQ5LukF27ExqjhiNUdJag3o6SoUyNp2LAcjJ1ixHkwiZ+BKkkZjlEwug= 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: Gtdtrt3qR7abFRBMveIRgg== X-CSE-MsgGUID: ifXr6rA2TPeIgxJqxtku0A== Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 03 Feb 2026 22:52:08 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.93.5]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 82BCD421BAF7; Tue, 3 Feb 2026 22:52:04 +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 v3 5/8] clk: versaclock3: Prefix clock names with DT node name Date: Tue, 3 Feb 2026 13:51:36 +0000 Message-ID: <20260203135139.28151-6-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203135139.28151-1-ovidiu.panait.rb@renesas.com> References: <20260203135139.28151-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" Similar to commit f491276a5168 ("clk: vc5: Allow Versaclock driver to support multiple instances"), prefix clock names with the device tree node name to allow multiple VersaClock3 devices to be registered simultaneously. Signed-off-by: Ovidiu Panait --- v3 changes: New patch. drivers/clk/clk-versaclock3.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index eb61a2c0b49b..56285c9a48ce 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -1137,6 +1137,7 @@ static int vc3_register_clk(struct vc3_device_data *v= c3, struct device *dev =3D &vc3->client->dev; struct clk_parent_data *pd; struct clk_init_data init; + const char *name; int ret; =20 if (!hw_data->data) @@ -1147,7 +1148,15 @@ static int vc3_register_clk(struct vc3_device_data *= vc3, if (!pd) return -ENOMEM; =20 + name =3D kasprintf(GFP_KERNEL, "%pOFn.%s", dev->of_node, + template->hw.init->name); + if (!name) { + kfree(pd); + return -ENOMEM; + } + init =3D *template->hw.init; + init.name =3D name; init.parent_data =3D pd; init.num_parents =3D hw_data->parent_info->num_parents; =20 @@ -1157,6 +1166,7 @@ static int vc3_register_clk(struct vc3_device_data *v= c3, ret =3D devm_clk_hw_register(dev, &hw_data->hw); =20 kfree(pd); + kfree(name); =20 return ret; } @@ -1321,6 +1331,10 @@ static int vc3_probe(struct i2c_client *client) return dev_err_probe(dev, -EINVAL, "invalid clk output %d\n", i); } =20 + name =3D kasprintf(GFP_KERNEL, "%pOFn.%s", dev->of_node, name); + if (!name) + return -ENOMEM; + if (i =3D=3D VC3_REF) vc3->clk_out[i] =3D devm_clk_hw_register_fixed_factor_index(dev, name, 0, CLK_SET_RATE_PARENT, 1, 1); @@ -1328,6 +1342,8 @@ static int vc3_probe(struct i2c_client *client) vc3->clk_out[i] =3D devm_clk_hw_register_fixed_factor_parent_hw(dev, name, &vc3->clk_mux[i - 1].hw, CLK_SET_RATE_PARENT, 1, 1); =20 + kfree(name); + if (IS_ERR(vc3->clk_out[i])) return PTR_ERR(vc3->clk_out[i]); } --=20 2.51.0 From nobody Mon Feb 9 04:30:53 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 6891C3A0B21; Tue, 3 Feb 2026 13:52:13 +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=1770126735; cv=none; b=sg8omJk+TzSGAfaXTucaFxG4xVkhqhkPIkeJZ6Z7aj4bR5Aw97Siq+ZmYF58oF6RQIpdcSkScwtcDMdUgpV3HvsF/w6aUpDkJyROebGcJI4C8a5FfL61Ic2xR2c/8+M8NbWea77pfLbswihyxvN7txQtmfuYx89mtkIXIROTMyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126735; c=relaxed/simple; bh=PwDS8Wf3zyu9YzfIDDnyUz8/Xcr6LwVp3uvlf76JYTI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pi1UgiV2Ayrl3gJw7ON5SApylBA+D7Mva4Q6YppA4rC0P6LqSlDeoVjM4NuNr7kRbC5lyyJyCwt0rTrM9nUy2SytrIVtESWtsCY5dQk0FwKHBc7L4UVltYEU0bHM3Q3iTLojAvB5a5OycNsHfHXRzEVjALZ5vQMvjEJMRXsfu44= 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: YWUHCO2QQyWMOxdKhxjVtQ== X-CSE-MsgGUID: jE+QRBB7SDCzgn1xtr+z1w== Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 03 Feb 2026 22:52:13 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.93.5]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 1EBA1421BAE7; Tue, 3 Feb 2026 22:52:08 +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 v3 6/8] clk: versaclock3: Add freerunning 32.768kHz clock support Date: Tue, 3 Feb 2026 13:51:37 +0000 Message-ID: <20260203135139.28151-7-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203135139.28151-1-ovidiu.panait.rb@renesas.com> References: <20260203135139.28151-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 Versa 3 clock generator has an internal 32.768kHz oscillator that can be routed to the SE1, SE2 and SE3 outputs. This patch exposes it as a fixed-rate clock and makes it available as a parent for the SE1/SE2/SE3 muxes. The 32.768kHz clock is only intended to be used when explicitly requested (i.e. when a rate of exactly 32768Hz is set). Selecting it as a fallback for other rates can cause issues, for example in audio configurations. To enforce this, introduce a new helper function, _vc3_clk_mux_determine_rate() which rejects configurations where the 32.768kHz parent would otherwise be chosen implicitly. One new field is added to struct vc3_clk_data - clk_32k_bitmsk, which is the bit mask used for selecting the 32.768kHz oscillator as output. It is used by clk_mux callbacks to select the appropriate parent clock. Signed-off-by: Ovidiu Panait --- v3 changes: - Rebased the patch to match the new clock registration logic and dropped the 32k clock parent index number (clk_32k_index). drivers/clk/clk-versaclock3.c | 96 +++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 10 deletions(-) diff --git a/drivers/clk/clk-versaclock3.c b/drivers/clk/clk-versaclock3.c index 56285c9a48ce..6f4c0e0af7d7 100644 --- a/drivers/clk/clk-versaclock3.c +++ b/drivers/clk/clk-versaclock3.c @@ -69,8 +69,10 @@ #define VC3_OUTPUT_CTR_DIV4_SRC_SEL BIT(3) =20 #define VC3_SE2_CTRL_REG0 0x1f +#define VC3_SE2_CTRL_REG0_SE2_FREERUN_32K BIT(7) =20 #define VC3_SE3_DIFF1_CTRL_REG 0x21 +#define VC3_SE3_DIFF1_CTRL_REG_SE3_FREERUN_32K BIT(7) #define VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL BIT(6) =20 #define VC3_DIFF1_CTRL_REG 0x22 @@ -80,6 +82,7 @@ #define VC3_DIFF2_CTRL_REG_DIFF2_CLK_SEL BIT(7) =20 #define VC3_SE1_DIV4_CTRL 0x24 +#define VC3_SE1_DIV4_CTRL_SE1_FREERUN_32K BIT(4) #define VC3_SE1_DIV4_CTRL_SE1_CLK_SEL BIT(3) =20 #define VC3_PLL1_VCO_MIN 300000000UL @@ -91,6 +94,8 @@ #define VC3_2_POW_16 (U16_MAX + 1) #define VC3_DIV_MASK(width) ((1 << (width)) - 1) =20 +#define VC3_CLK_32K_FREQ 32768 + #define VC3_CLK_PARENT(t, i) { .type =3D VC3_CLK_##t, .idx =3D (i) } =20 enum vc3_pfd_mux { @@ -149,6 +154,7 @@ enum vc3_clk_type { VC3_CLK_DIV_MUX, VC3_CLK_DIV, VC3_CLK_CLK_MUX, + VC3_CLK_32K, }; =20 struct vc3_clk_parent { @@ -164,6 +170,7 @@ struct vc3_parent_info { struct vc3_clk_data { u8 offs; u8 bitmsk; + u8 clk_32k_bitmsk; }; =20 struct vc3_pfd_data { @@ -217,6 +224,7 @@ struct vc3_device_data { struct vc3_hw_data clk_div_mux[VC3_DIV_MUX_NUM]; struct vc3_hw_data clk_div[VC3_DIV_NUM]; struct vc3_hw_data clk_mux[VC3_CLK_MUX_NUM]; + struct clk_hw *clk_32k; struct clk_hw *clk_out[VC3_CLK_OUT_NUM]; }; =20 @@ -587,19 +595,52 @@ static const struct clk_ops vc3_div_ops =3D { .set_rate =3D vc3_div_set_rate, }; =20 +static int vc3_get_32k_parent_index(const struct vc3_hw_data *hw_data) +{ + const struct vc3_parent_info *pinfo =3D hw_data->parent_info; + + for (int i =3D 0; i < pinfo->num_parents; i++) { + if (pinfo->parents[i].type =3D=3D VC3_CLK_32K) + return i; + } + + return -1; +} + +static int _vc3_clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + bool is_32k_req =3D (req->rate =3D=3D VC3_CLK_32K_FREQ); + struct clk_rate_request tmp_req; + int ret; + + clk_hw_init_rate_request(hw, &tmp_req, req->rate); + + ret =3D clk_mux_determine_rate_flags(hw, &tmp_req, CLK_SET_RATE_PARENT); + if (ret) + return ret; + + /* Select the 32.768 kHz parent only when explicitly requested. */ + if ((tmp_req.best_parent_rate =3D=3D VC3_CLK_32K_FREQ) && !is_32k_req) + return -EINVAL; + + memcpy(req, &tmp_req, sizeof(*req)); + + return 0; +} + static int vc3_clk_mux_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { int frc; =20 - if (clk_mux_determine_rate_flags(hw, req, CLK_SET_RATE_PARENT)) { + if (_vc3_clk_mux_determine_rate(hw, req)) { /* The below check is equivalent to (best_parent_rate/rate) */ if (req->best_parent_rate >=3D req->rate) { frc =3D DIV_ROUND_CLOSEST_ULL(req->best_parent_rate, req->rate); req->rate *=3D frc; - return clk_mux_determine_rate_flags(hw, req, - CLK_SET_RATE_PARENT); + return _vc3_clk_mux_determine_rate(hw, req); } } =20 @@ -610,10 +651,15 @@ static u8 vc3_clk_mux_get_parent(struct clk_hw *hw) { struct vc3_hw_data *vc3 =3D container_of(hw, struct vc3_hw_data, hw); const struct vc3_clk_data *clk_mux =3D vc3->data; + int clk_32k_index; u32 val; =20 regmap_read(vc3->regmap, clk_mux->offs, &val); =20 + clk_32k_index =3D vc3_get_32k_parent_index(vc3); + if (clk_32k_index >=3D 0 && !(val & clk_mux->clk_32k_bitmsk)) + return clk_32k_index; + return !!(val & clk_mux->bitmsk); } =20 @@ -621,9 +667,17 @@ static int vc3_clk_mux_set_parent(struct clk_hw *hw, u= 8 index) { struct vc3_hw_data *vc3 =3D container_of(hw, struct vc3_hw_data, hw); const struct vc3_clk_data *clk_mux =3D vc3->data; + unsigned int bitmsk =3D clk_mux->clk_32k_bitmsk; + unsigned int val =3D 0; + int clk_32k_index; + + clk_32k_index =3D vc3_get_32k_parent_index(vc3); + if (index !=3D clk_32k_index) { + bitmsk |=3D clk_mux->bitmsk; + val =3D clk_mux->clk_32k_bitmsk | (index ? clk_mux->bitmsk : 0); + } =20 - return regmap_update_bits(vc3->regmap, clk_mux->offs, clk_mux->bitmsk, - index ? clk_mux->bitmsk : 0); + return regmap_update_bits(vc3->regmap, clk_mux->offs, bitmsk, val); } =20 static const struct clk_ops vc3_clk_mux_ops =3D { @@ -990,22 +1044,25 @@ static const struct vc3_parent_info clk_mux_parents[= ] =3D { .parents =3D (const struct vc3_clk_parent[]) { VC3_CLK_PARENT(DIV, VC3_DIV5), VC3_CLK_PARENT(DIV, VC3_DIV4), + VC3_CLK_PARENT(32K, 0), }, - .num_parents =3D 2, + .num_parents =3D 3, }, [VC3_SE2_MUX] =3D { .parents =3D (const struct vc3_clk_parent[]) { VC3_CLK_PARENT(DIV, VC3_DIV5), VC3_CLK_PARENT(DIV, VC3_DIV4), + VC3_CLK_PARENT(32K, 0), }, - .num_parents =3D 2, + .num_parents =3D 3, }, [VC3_SE3_MUX] =3D { .parents =3D (const struct vc3_clk_parent[]) { VC3_CLK_PARENT(DIV, VC3_DIV2), VC3_CLK_PARENT(DIV, VC3_DIV4), + VC3_CLK_PARENT(32K, 0), }, - .num_parents =3D 2, + .num_parents =3D 3, }, [VC3_DIFF1_MUX] =3D { .parents =3D (const struct vc3_clk_parent[]) { @@ -1027,7 +1084,8 @@ static struct vc3_hw_data clk_mux[] =3D { [VC3_SE1_MUX] =3D { .data =3D &(struct vc3_clk_data) { .offs =3D VC3_SE1_DIV4_CTRL, - .bitmsk =3D VC3_SE1_DIV4_CTRL_SE1_CLK_SEL + .bitmsk =3D VC3_SE1_DIV4_CTRL_SE1_CLK_SEL, + .clk_32k_bitmsk =3D VC3_SE1_DIV4_CTRL_SE1_FREERUN_32K, }, .hw.init =3D &(struct clk_init_data) { .name =3D "se1_mux", @@ -1039,6 +1097,7 @@ static struct vc3_hw_data clk_mux[] =3D { [VC3_SE2_MUX] =3D { .data =3D &(struct vc3_clk_data) { .offs =3D VC3_SE2_CTRL_REG0, + .clk_32k_bitmsk =3D VC3_SE2_CTRL_REG0_SE2_FREERUN_32K, }, .hw.init =3D &(struct clk_init_data) { .name =3D "se2_mux", @@ -1050,7 +1109,8 @@ static struct vc3_hw_data clk_mux[] =3D { [VC3_SE3_MUX] =3D { .data =3D &(struct vc3_clk_data) { .offs =3D VC3_SE3_DIFF1_CTRL_REG, - .bitmsk =3D VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL + .bitmsk =3D VC3_SE3_DIFF1_CTRL_REG_SE3_CLK_SEL, + .clk_32k_bitmsk =3D VC3_SE3_DIFF1_CTRL_REG_SE3_FREERUN_32K, }, .hw.init =3D &(struct clk_init_data) { .name =3D "se3_mux", @@ -1103,6 +1163,8 @@ static struct clk_hw *vc3_clk_get_hw(struct vc3_devic= e_data *vc3, return &vc3->clk_div[parent->idx].hw; case VC3_CLK_CLK_MUX: return &vc3->clk_mux[parent->idx].hw; + case VC3_CLK_32K: + return vc3->clk_32k; } =20 return NULL; @@ -1224,6 +1286,20 @@ static int vc3_probe(struct i2c_client *client) return ret; } =20 + /* Register internal 32.768kHz oscillator */ + name =3D kasprintf(GFP_KERNEL, "%pOFn.clk_32k", dev->of_node); + if (!name) + return -ENOMEM; + + vc3->clk_32k =3D devm_clk_hw_register_fixed_rate(dev, name, NULL, 0, + VC3_CLK_32K_FREQ); + kfree(name); + + if (IS_ERR(vc3->clk_32k)) + return dev_err_probe(dev, PTR_ERR(vc3->clk_32k), + "Failed to register %dHz fixed clock\n", + VC3_CLK_32K_FREQ); + /* Register pfd muxes */ for (i =3D 0; i < ARRAY_SIZE(clk_pfd_mux); i++) { name =3D clk_pfd_mux[i].hw.init->name; --=20 2.51.0 From nobody Mon Feb 9 04:30:53 2026 Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 19A603A1A23; Tue, 3 Feb 2026 13:52:18 +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=1770126740; cv=none; b=cDiITZ3vhS3FEzFJ2fmkEXpZ+obiZmMWSWl1HfeZVCtgG+GyWvJNRxV9THhESCjAyN7jIbBFuDeMBeVkBSCQGMGbRwQJsq3yGRcM+9RA/LtbaN8fNlIXb0MvOkx4YQGHuGQVOd2VPlwauZICxbxOGaDVHpk2gNR3Zs647Vw/sNE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126740; c=relaxed/simple; bh=p63swogi0CuVH7cUq8camXOjKahDI8nHL2qzX6L1cNU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YSdS/Q6CRQt2vzIgPMgHMDiobj52trlbYT0eQROAptgNpGEERZ812OjS17D77ZqpikyWM+v2eRu8DrxQpYbkx55nke/u706h4UcM5ldj/ISmb/ThGPohEUMVK2TqpmRZ7lLL4KIxixSPw/oD9nLwg8fBGw55pX5U9cdeIMjVb1A= 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: oPsx2Z5MTKmhdGVfZF93nQ== X-CSE-MsgGUID: euK8msMbQhKeWGQP3RdQxQ== Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 03 Feb 2026 22:52:17 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.93.5]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id BEDFA421BAE7; Tue, 3 Feb 2026 22:52:13 +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 v3 7/8] arm64: dts: renesas: r9a09g057h44-rzv2h-evk: Add versa3 clock generator node Date: Tue, 3 Feb 2026 13:51:38 +0000 Message-ID: <20260203135139.28151-8-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203135139.28151-1-ovidiu.panait.rb@renesas.com> References: <20260203135139.28151-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" Add versa3 clock generator node. It provides clocks for the RTC, PCIe and audio devices. Signed-off-by: Ovidiu Panait --- v3 changes: - Added comments to document rtxin_clk and qextal_clk routing. .../dts/renesas/r9a09g057h44-rzv2h-evk.dts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts b/arch/= arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts index dc4577ebf2e9..4d6197301af4 100644 --- a/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts +++ b/arch/arm64/boot/dts/renesas/r9a09g057h44-rzv2h-evk.dts @@ -108,6 +108,12 @@ vqmmc_sdhi1: regulator-vccq-sdhi1 { states =3D <3300000 0>, <1800000 1>; }; =20 + x1: x1-clock { + compatible =3D "fixed-clock"; + #clock-cells =3D <0>; + clock-frequency =3D <24000000>; + }; + /* 32.768kHz crystal */ x6: x6-clock { compatible =3D "fixed-clock"; @@ -277,6 +283,25 @@ raa215300: pmic@12 { clocks =3D <&x6>; clock-names =3D "xin"; }; + + versa3: clock-generator@69 { + compatible =3D "renesas,5l35023"; + reg =3D <0x69>; + clocks =3D <&x1>; + #clock-cells =3D <1>; + assigned-clocks =3D <&versa3 0>, /* qextal_clk */ + <&versa3 1>, + <&versa3 2>, /* rtxin_clk */ + <&versa3 3>, + <&versa3 4>, + <&versa3 5>; + assigned-clock-rates =3D <24000000>, + <24576000>, + <32768>, + <22579200>, + <100000000>, + <100000000>; + }; }; =20 &mdio0 { --=20 2.51.0 From nobody Mon Feb 9 04:30:53 2026 Received: from relmlie6.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4D7C63A0B14; Tue, 3 Feb 2026 13:52:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=210.160.252.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126745; cv=none; b=JIB6KDIKPMdNVEwqGYpm6A2CpSq+mWdT0aLbPg+PQ1mcdQPld/5vd0Qfvgi1VX9uPvPOHxTf9Jf7ToywrM6wzhyXJP3ApLhYrFc8Ut4Gw6iU4iJcf//g2VJpRCFGQbOJrJ89+o04O/ElcM+iXPWEgN85NfutEMCnR8Y1wuqwZRg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770126745; c=relaxed/simple; bh=TWTKR19mIEbIMPmte3Ec51dV7Dn32+uGL+9SU6Cm9/4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dfqL3TFI4nnydBzR0HgaeSmW6BK82G1Ec3AQKfxnFlVp6MIqjE2+HArbCiUFGZjCuv/RgsBdTvLbOAr+vQj6X0/WNa60WUMd5v86ldBv4lCpLE36aZdkbbGojHNsPpzYqpJ70cAa8aotz600VL2YHBESfkmYpZFodlSoSlEka/U= 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.172 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: MVbFrivoTb2ZpKe661vZ3Q== X-CSE-MsgGUID: cFGzmsm9QfyGagRl8sM4Gg== Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie6.idc.renesas.com with ESMTP; 03 Feb 2026 22:52:22 +0900 Received: from vm01.adwin.renesas.com (unknown [10.226.93.5]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 65D72421BAE7; Tue, 3 Feb 2026 22:52:18 +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 v3 8/8] arm64: dts: renesas: r9a09g056n48-rzv2n-evk: Add versa3 clock generator node Date: Tue, 3 Feb 2026 13:51:39 +0000 Message-ID: <20260203135139.28151-9-ovidiu.panait.rb@renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203135139.28151-1-ovidiu.panait.rb@renesas.com> References: <20260203135139.28151-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" Add versa3 clock generator node. It provides clocks for the RTC, PCIe and audio devices. Signed-off-by: Ovidiu Panait --- v3 changes: - Added comments to document rtxin_clk and qextal_clk routing. .../dts/renesas/r9a09g056n48-rzv2n-evk.dts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r9a09g056n48-rzv2n-evk.dts b/arch/= arm64/boot/dts/renesas/r9a09g056n48-rzv2n-evk.dts index c191ecb39713..4bb47fd646a4 100644 --- a/arch/arm64/boot/dts/renesas/r9a09g056n48-rzv2n-evk.dts +++ b/arch/arm64/boot/dts/renesas/r9a09g056n48-rzv2n-evk.dts @@ -100,6 +100,12 @@ vqmmc_sdhi1: regulator-vqmmc-sdhi1 { states =3D <3300000 0>, <1800000 1>; }; =20 + x1: x1-clock { + compatible =3D "fixed-clock"; + #clock-cells =3D <0>; + clock-frequency =3D <24000000>; + }; + /* 32.768kHz crystal */ x6: x6-clock { compatible =3D "fixed-clock"; @@ -256,6 +262,25 @@ raa215300: pmic@12 { clocks =3D <&x6>; clock-names =3D "xin"; }; + + versa3: clock-generator@69 { + compatible =3D "renesas,5l35023"; + reg =3D <0x69>; + clocks =3D <&x1>; + #clock-cells =3D <1>; + assigned-clocks =3D <&versa3 0>, /* qextal_clk */ + <&versa3 1>, + <&versa3 2>, /* rtxin_clk */ + <&versa3 3>, + <&versa3 4>, + <&versa3 5>; + assigned-clock-rates =3D <24000000>, + <24576000>, + <32768>, + <22579200>, + <100000000>, + <100000000>; + }; }; =20 &mdio0 { --=20 2.51.0