From nobody Tue Feb 10 13:36:47 2026 Received: from mail-pl1-f177.google.com (mail-pl1-f177.google.com [209.85.214.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC9EE34B419 for ; Tue, 28 Oct 2025 16:52:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761670339; cv=none; b=NNLc6dWm8KxdL7rq/cNsupQTFg8AJKHUQKERzIc+DcQ+DzerJFD7OQJT9/NPNv5+t95GKK+FV+8kGghKEBzjyw2na9aO52WLqR3/loi+dRItzsWL4aN9T4BQicKCMkofAMWLB+6s2MCkSi4Av6FgENB1hlxMbegdYpNYtY8w/r8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761670339; c=relaxed/simple; bh=WFew7RLc9Zd+tpZCR+smsad3xkEUOcASLxfJhKIGvy4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tkfv6OGrlkOuZ4/fvulGIa2F2CGah+YWXs9Dw3ihaFhrQusRgFlpIcyRVx1Ny8Ws8TvI7K7HsOzkm9AynPNkDLJU7OVHKS9zNa8YziCPsooW1y3MRFe3L5kULBofD3iwaVRzOtlSpyoDOqp7GPperRNIpif0BH/VbDrG2Bz4qG4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IxWNFNEY; arc=none smtp.client-ip=209.85.214.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IxWNFNEY" Received: by mail-pl1-f177.google.com with SMTP id d9443c01a7336-294cc96d187so16824375ad.3 for ; Tue, 28 Oct 2025 09:52:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1761670337; x=1762275137; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=b2Zr7HjUEXtUzytWwmBSdtq4q5NXObpurWZ+b8YgjWQ=; b=IxWNFNEYxhQTCM2rMYn9CW50pF1EGoNavVi50nn8nqXEI7ayg8E3DmJDMY/+5dk+D/ S7fLZNaC+GdqZwCCojlM6FelFlmo5/IBmObTjSMlYFn30Zv7+e3v06wUawTlBndVajPp 1PzwKDkts6rHMUv2NGYzVIq0WcsZRoMmuHnrelmVBPp2+PBT7LXUs/jOql2QWiDtPTs/ ow0VgzyvUdJtTwuJJYCJXPoczTq8nR8/WHOEs183cBdDFztPATx7tos7SEYDRKD01lS2 R5P6tVl9QnJb2bj/MOAgOYA6IQiB7dkqVWpejmpOe9fUmCMK3sHkUHGs1LHwtckac1RS /CcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761670337; x=1762275137; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=b2Zr7HjUEXtUzytWwmBSdtq4q5NXObpurWZ+b8YgjWQ=; b=S1OnphGN1MrX0Az/xGLEB24lMUxI4eB9KvfKQD/+uVJfHHUjwQSKZ3eW1wmY4Xfnl4 V5t3kEtU8ciVtA9840n16JrFUFvzh0hrX5vD3zk8tk75IiHl/5+Um8kdyv6OdYb2kjsG AxLHq7sr+vXsLRQWZCV2djKC9qROGVx31xLOq9N7GQHMCtNgCNzbve2jS3YrT5GNK1D6 afDVwDcs+fIrgIpRoSC5eznBwBMEaKOK5gPi/OsEDBI1xUyra3LMIXWIYHUxeNnAUAZV R9ZHRVd17l8+ECOfjPgpD+FUaKc6i9Mf6kpfo1biMOLMdNtNV3S0HDrQTRyLRyWoVurB 7Geg== X-Forwarded-Encrypted: i=1; AJvYcCXReuWXMWjfxeR7YKNB/rPJ2RKNBX1mWQ1RtK8i3NqN4uQ0qARgOYJ6n+tBvhN9pkeSSRBjiVDWhvHmsMM=@vger.kernel.org X-Gm-Message-State: AOJu0YxUyFcbqvlcmmjvhDRiOSuc19NxL9PfseQUx4ddfaKAR2YAPHwR VlT5lt2JIblxtEZhs1CuSL0rT85P3ZNhf4Ii5rnlSrNJustLaP91YC+O X-Gm-Gg: ASbGncvE/+PbfwPfow9Tz7ol762+T19XoPJEd0DZ5jwrc+W8M0/Q+Aje9XU+Gfj4ery uC4UOCmwZdjzbeftM7N0hl/y8K9c3xQveLUjF8vUBwc89sxTXMzW2H9Y1gfq0qFy0dD/1HR8np7 Le3dMHXn0gxSomGuOTrp9B3fP1a5n9c/RrFxVQ2scSipNf+LtvxyUq8QDW22mUMvVn3MrrNIZtx 10mmUzp9zlVHc6ejLi7ZiAtIHQyZ5jRZwwpq0htc0/9IXV6waKLOTd086HMXh7ZLsjSCAquaBuE 7UySn6PNNs2CITdMk+DhR1Bsev16sMqLM0BHYvHsMHPD4T+SW++279s5bTPtYtVqaxDdiNrjp5t yb5QZihvwk1DWVF0E/5UatzAeRE/fE4r1cu5lhYyJ+NbhA6S24Lz3T2bIiuxeMz8EbghXIJxzVJ 0izBp2WACMXbYx5qP9u6gX/g== X-Google-Smtp-Source: AGHT+IEgwFJI5NAIzF94P9PLCgQBGcLOI50Ks257zb4cT6sx/wW+6XXdpe9DB0mcBPoFARxUuU9xfg== X-Received: by 2002:a17:902:f68f:b0:26f:f489:bba6 with SMTP id d9443c01a7336-294cb540d36mr54558825ad.50.1761670336773; Tue, 28 Oct 2025 09:52:16 -0700 (PDT) Received: from iku.. ([2401:4900:1c06:77f0:168f:479e:bf92:ce93]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29498f0be0esm122123665ad.96.2025.10.28.09.52.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Oct 2025 09:52:16 -0700 (PDT) From: Prabhakar X-Google-Original-From: Prabhakar To: Geert Uytterhoeven , Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Magnus Damm Cc: linux-renesas-soc@vger.kernel.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Prabhakar , Biju Das , Fabrizio Castro , Lad Prabhakar Subject: [PATCH v2 5/5] clk: renesas: r9a09g077: Add xSPI core and module clocks Date: Tue, 28 Oct 2025 16:51:27 +0000 Message-ID: <20251028165127.991351-6-prabhakar.mahadev-lad.rj@bp.renesas.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251028165127.991351-1-prabhakar.mahadev-lad.rj@bp.renesas.com> References: <20251028165127.991351-1-prabhakar.mahadev-lad.rj@bp.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" From: Lad Prabhakar Add core clocks and module clock definitions required by the xSPI (Expanded SPI) IP on the R9A09G077 SoC. Define the new SCKCR fields FSELXSPI0/FSELXSPI1 and DIVSEL_XSPI0/1 and add two new core clocks XSPI_CLK0 and XSPI_CLK1. The xSPI block uses PCLKH as its bus clock (use as module clock parent) while the operation clock (XSPI_CLKn) is derived from PLL4. To support this arrangement provide mux/div selectors and divider tables for the supported XSPI operating rates. Add CLK_TYPE_RZT2H_FSELXSPI to implement a custom divider/mux clock where the determine_rate() callback enforces the hardware constraint: when the parent output is 600MHz only dividers 8 and 16 are valid, whereas for 800MHz operation the full divider set (6,8,16,32,64) may be used. The custom determine_rate() picks the best parent/divider pair to match the requested rate and programs the appropriate SCKCR fields. Signed-off-by: Lad Prabhakar --- v1->v2: - Added custom divider clock type for XSPI clocks to enforce hardware constraints on supported operating rates. --- drivers/clk/renesas/r9a09g077-cpg.c | 155 +++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) diff --git a/drivers/clk/renesas/r9a09g077-cpg.c b/drivers/clk/renesas/r9a0= 9g077-cpg.c index b46167d42084..678dc36461c0 100644 --- a/drivers/clk/renesas/r9a09g077-cpg.c +++ b/drivers/clk/renesas/r9a09g077-cpg.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include =20 #include #include @@ -54,12 +56,19 @@ #define DIVSCI3ASYNC CONF_PACK(SCKCR3, 12, 2) #define DIVSCI4ASYNC CONF_PACK(SCKCR3, 14, 2) =20 +#define FSELXSPI0 CONF_PACK(SCKCR, 0, 3) +#define FSELXSPI1 CONF_PACK(SCKCR, 8, 3) +#define DIVSEL_XSPI0 CONF_PACK(SCKCR, 6, 1) +#define DIVSEL_XSPI1 CONF_PACK(SCKCR, 14, 1) #define SEL_PLL CONF_PACK(SCKCR, 22, 1) =20 +#define DIVSELXSPI_RATE_600MHZ 600000000UL +#define DIVSELXSPI_RATE_800MHZ 800000000UL =20 enum rzt2h_clk_types { CLK_TYPE_RZT2H_DIV =3D CLK_TYPE_CUSTOM, /* Clock with divider */ CLK_TYPE_RZT2H_MUX, /* Clock with clock source selector */ + CLK_TYPE_RZT2H_FSELXSPI, }; =20 #define DEF_DIV(_name, _id, _parent, _conf, _dtable) \ @@ -69,10 +78,13 @@ enum rzt2h_clk_types { DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_MUX, .conf =3D _conf, \ .parent_names =3D _parent_names, .num_parents =3D _num_parents, \ .flag =3D 0, .mux_flags =3D _mux_flags) +#define DEF_DIV_FSELXSPI(_name, _id, _parent, _conf, _dtable) \ + DEF_TYPE(_name, _id, CLK_TYPE_RZT2H_FSELXSPI, .conf =3D _conf, \ + .parent =3D _parent, .dtable =3D _dtable, .flag =3D 0) =20 enum clk_ids { /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK =3D R9A09G077_ETCLKE, + LAST_DT_CORE_CLK =3D R9A09G077_XSPI_CLK1, =20 /* External Input Clocks */ CLK_EXTAL, @@ -88,12 +100,16 @@ enum clk_ids { CLK_SEL_CLK_PLL2, CLK_SEL_CLK_PLL4, CLK_PLL4D1, + CLK_PLL4D1_DIV3, + CLK_PLL4D1_DIV4, CLK_SCI0ASYNC, CLK_SCI1ASYNC, CLK_SCI2ASYNC, CLK_SCI3ASYNC, CLK_SCI4ASYNC, CLK_SCI5ASYNC, + CLK_DIVSELXSPI0_SCKCR, + CLK_DIVSELXSPI1_SCKCR, =20 /* Module Clocks */ MOD_CLK_BASE, @@ -105,6 +121,15 @@ static const struct clk_div_table dtable_1_2[] =3D { {0, 0}, }; =20 +static const struct clk_div_table dtable_6_8_16_32_64[] =3D { + {6, 64}, + {5, 32}, + {4, 16}, + {3, 8}, + {2, 6}, + {0, 0}, +}; + static const struct clk_div_table dtable_24_25_30_32[] =3D { {0, 32}, {1, 30}, @@ -119,6 +144,7 @@ static const char * const sel_clk_pll0[] =3D { ".loco",= ".pll0" }; static const char * const sel_clk_pll1[] =3D { ".loco", ".pll1" }; static const char * const sel_clk_pll2[] =3D { ".loco", ".pll2" }; static const char * const sel_clk_pll4[] =3D { ".loco", ".pll4" }; +static const char * const sel_clk_pll4d1_div3_div4[] =3D { ".pll4d1_div3",= ".pll4d1_div4" }; =20 static const struct cpg_core_clk r9a09g077_core_clks[] __initconst =3D { /* External Clock Inputs */ @@ -154,6 +180,15 @@ static const struct cpg_core_clk r9a09g077_core_clks[]= __initconst =3D { DEF_DIV(".sci5async", CLK_SCI5ASYNC, CLK_PLL4D1, DIVSCI5ASYNC, dtable_24_25_30_32), =20 + DEF_FIXED(".pll4d1_div3", CLK_PLL4D1_DIV3, CLK_PLL4D1, 3, 1), + DEF_FIXED(".pll4d1_div4", CLK_PLL4D1_DIV4, CLK_PLL4D1, 4, 1), + DEF_MUX(".divselxspi0", CLK_DIVSELXSPI0_SCKCR, DIVSEL_XSPI0, + sel_clk_pll4d1_div3_div4, + ARRAY_SIZE(sel_clk_pll4d1_div3_div4), 0), + DEF_MUX(".divselxspi1", CLK_DIVSELXSPI1_SCKCR, DIVSEL_XSPI1, + sel_clk_pll4d1_div3_div4, + ARRAY_SIZE(sel_clk_pll4d1_div3_div4), 0), + /* Core output clk */ DEF_DIV("CA55C0", R9A09G077_CLK_CA55C0, CLK_SEL_CLK_PLL0, DIVCA55C0, dtable_1_2), @@ -178,9 +213,15 @@ static const struct cpg_core_clk r9a09g077_core_clks[]= __initconst =3D { DEF_FIXED("ETCLKC", R9A09G077_ETCLKC, CLK_SEL_CLK_PLL1, 10, 1), DEF_FIXED("ETCLKD", R9A09G077_ETCLKD, CLK_SEL_CLK_PLL1, 20, 1), DEF_FIXED("ETCLKE", R9A09G077_ETCLKE, CLK_SEL_CLK_PLL1, 40, 1), + DEF_DIV_FSELXSPI("XSPI_CLK0", R9A09G077_XSPI_CLK0, CLK_DIVSELXSPI0_SCKCR, + FSELXSPI0, dtable_6_8_16_32_64), + DEF_DIV_FSELXSPI("XSPI_CLK1", R9A09G077_XSPI_CLK1, CLK_DIVSELXSPI1_SCKCR, + FSELXSPI1, dtable_6_8_16_32_64), }; =20 static const struct mssr_mod_clk r9a09g077_mod_clks[] __initconst =3D { + DEF_MOD("xspi0", 4, R9A09G077_CLK_PCLKH), + DEF_MOD("xspi1", 5, R9A09G077_CLK_PCLKH), DEF_MOD("sci0fck", 8, CLK_SCI0ASYNC), DEF_MOD("sci1fck", 9, CLK_SCI1ASYNC), DEF_MOD("sci2fck", 10, CLK_SCI2ASYNC), @@ -264,6 +305,116 @@ r9a09g077_cpg_mux_clk_register(struct device *dev, return clk_hw->clk; } =20 +static int r9a09g077_cpg_fselxspi_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_divider *divider =3D to_clk_divider(hw); + unsigned long parent_rate, best =3D 0, now; + const struct clk_div_table *clkt; + unsigned long rate =3D req->rate; + int div =3D 0; + + if (!rate) + rate =3D 1; + + for (clkt =3D divider->table; clkt->div; clkt++) { + parent_rate =3D clk_hw_round_rate(req->best_parent_hw, rate * clkt->div); + /* + * DIVSELXSPIx supports 800MHz and 600MHz operation. + * When the parent_rate is 600MHz, only dividers of 8 and 16 + * are supported otherwise dividers of 6, 8, 16, 32, 64 are supported. + * This check ensures that FSELXSPIx is set correctly. + */ + if (parent_rate =3D=3D DIVSELXSPI_RATE_600MHZ && + (clkt->div !=3D 8 && clkt->div !=3D 16)) + continue; + now =3D DIV_ROUND_UP_ULL((u64)parent_rate, clkt->div); + if (abs(rate - now) < abs(rate - best)) { + div =3D clkt->div; + best =3D now; + req->best_parent_rate =3D parent_rate; + } + } + + if (!div) { + u8 maxdiv =3D 0; + + req->best_parent_rate =3D clk_hw_round_rate(req->best_parent_hw, 1); + /* + * If DIVSELXSPIx is set to 800MHz set the maximum divider + * or else fall back to divider of 16 which is a maximum + * supported divider for 600MHz operation. + */ + if (req->best_parent_rate =3D=3D DIVSELXSPI_RATE_800MHZ) { + for (clkt =3D divider->table; clkt->div; clkt++) { + if (clkt->div > maxdiv) + maxdiv =3D clkt->div; + } + div =3D maxdiv; + } else { + div =3D 16; + } + } + + req->rate =3D DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div); + + return 0; +} + +static struct clk * __init +r9a09g077_cpg_fselxspi_div_clk_register(struct device *dev, + const struct cpg_core_clk *core, + void __iomem *addr, + struct cpg_mssr_pub *pub) +{ + static struct clk_ops *xspi_div_ops; + struct clk_init_data init =3D {}; + const struct clk *parent; + const char *parent_name; + struct clk_divider *div; + struct clk_hw *hw; + int ret; + + parent =3D pub->clks[core->parent]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + + div =3D devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); + if (!div) + return ERR_PTR(-ENOMEM); + + if (!xspi_div_ops) { + xspi_div_ops =3D devm_kzalloc(dev, sizeof(*xspi_div_ops), GFP_KERNEL); + if (!xspi_div_ops) + return ERR_PTR(-ENOMEM); + memcpy(xspi_div_ops, &clk_divider_ops, + sizeof(const struct clk_ops)); + xspi_div_ops->determine_rate =3D r9a09g077_cpg_fselxspi_determine_rate; + } + + parent_name =3D __clk_get_name(parent); + init.name =3D core->name; + init.ops =3D xspi_div_ops; + init.flags =3D CLK_SET_RATE_PARENT; + init.parent_names =3D &parent_name; + init.num_parents =3D 1; + + div->reg =3D addr; + div->shift =3D GET_SHIFT(core->conf); + div->width =3D GET_WIDTH(core->conf); + div->flags =3D core->flag; + div->lock =3D &pub->rmw_lock; + div->hw.init =3D &init; + div->table =3D core->dtable; + + hw =3D &div->hw; + ret =3D devm_clk_hw_register(dev, hw); + if (ret) + return ERR_PTR(ret); + + return hw->clk; +} + static struct clk * __init r9a09g077_cpg_clk_register(struct device *dev, const struct cpg_core_clk *= core, const struct cpg_mssr_info *info, @@ -278,6 +429,8 @@ r9a09g077_cpg_clk_register(struct device *dev, const st= ruct cpg_core_clk *core, return r9a09g077_cpg_div_clk_register(dev, core, addr, pub); case CLK_TYPE_RZT2H_MUX: return r9a09g077_cpg_mux_clk_register(dev, core, addr, pub); + case CLK_TYPE_RZT2H_FSELXSPI: + return r9a09g077_cpg_fselxspi_div_clk_register(dev, core, addr, pub); default: return ERR_PTR(-EINVAL); } --=20 2.43.0