From: Jian Hu <jian.hu@amlogic.com>
To: Jerome Brunet <jbrunet@baylibre.com>,
Jian Hu via B4 Relay <devnull+jian.hu.amlogic.com@kernel.org>
Cc: Michael Turquette <mturquette@baylibre.com>,
Stephen Boyd <sboyd@kernel.org>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
Xianwei Zhao <xianwei.zhao@amlogic.com>,
Kevin Hilman <khilman@baylibre.com>,
Martin Blumenstingl <martin.blumenstingl@googlemail.com>,
linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org,
devicetree@vger.kernel.org, linux-amlogic@lists.infradead.org,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 08/10] clk: amlogic: Add A9 PLL clock controller driver
Date: Wed, 20 May 2026 15:33:07 +0800 [thread overview]
Message-ID: <96aac0a2-7531-4a40-8a55-630e92012bb5@amlogic.com> (raw)
In-Reply-To: <1jh5oa6kcm.fsf@starbuckisacylon.baylibre.com>
On 5/15/2026 12:12 AM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
>
> On lun. 11 mai 2026 at 20:47, Jian Hu via B4 Relay <devnull+jian.hu.amlogic.com@kernel.org> wrote:
>
>> From: Jian Hu <jian.hu@amlogic.com>
>>
>> Add the PLL clock controller driver for the Amlogic A9 SoC family.
>>
>> Signed-off-by: Jian Hu <jian.hu@amlogic.com>
[...]
>> +
>> +/*
>> + * Compared with previous SoC PLLs, the A9 PLL input path has an inherent
>> + * 2-divider. The N pre-divider follows the same calculation rule as OD,
>> + * where the pre-divider ratio equals 2^N.
>> + *
>> + * A9 PLL is composed as follows:
>> + *
>> + * PLL
>> + * +---------------------------------+
>> + * | |
>> + * | +--+ |
>> + * in/2 >>---[ /2^N ]-->| | +-----+ |
>> + * | | |------| DCO |----->> out
>> + * | +--------->| | +--v--+ |
>> + * | | +--+ | |
>> + * | | | |
>> + * | +--[ *(M + (F/Fmax) ]<--+ |
>> + * | |
>> + * +---------------------------------+
>> + *
>> + * out = in / 2 * (m + frac / frac_max) / 2^n
>> + */
>> +
>> +static struct clk_fixed_factor a9_gp0_in_div2_div = {
>> + .mult = 1,
>> + .div = 2,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "gp0_in_div2_div",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_data = &(const struct clk_parent_data) {
>> + .fw_name = "in0",
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap a9_gp0_in_div2 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = GP0PLL_CTRL0,
>> + .bit_idx = 27,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "gp0_in_div2",
>> + .ops = &clk_regmap_gate_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &a9_gp0_in_div2_div.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
> When document something, be sure it matches what you are doing
> afterward. It is confusing otherwise. Your comments above clearly miss
> this gate.
>
> A fixed 2 divider followed by a power of 2 divider ? Is it actually how
> the HW works or your modelisation power of 2 that's shifted by 1,
> mapping :
> * 0 -> 2
> * 1 -> 4
> * etc ...
>
> ?
Sorry for missing the gate in PLL block diagram, above block diagram
focuses on mathematical formulas.
A9 PLL is composed as follows in fact, M and frac have a 0.5 weight factor:
PLL
+-----------------------------------------------------+
| |
| +--+ |
in >>---[ /N ]--> | | +-----+ |
| | |---------------------| DCO | |----->> out
| +--------->| | +--v--+ |
| | +--+ | |
| | | |
| +--[ *(M + (F/Fmax) ] * 0.5 + Enable<--+ |
| |
+-----------------------------------------------------+
out = in * (M + frac / frac_max) * 0.5 / N
If we ignore frac and set N = 1, it simplifies to:
out = in * M * 0.5
This can be rewritten as:
out = (in / 2) * M
The 0.5 weight is hardware-controlled:
For GP0/HIFI PLL: controlled by CTRL0 bit27 (gate)
For MCLK PLL: enabled by default, no gate bit
To model this in the clock tree, we add:
A fixed /2 divider after input clock to represent the 0.5 weight
A gate clock to represent the enable control
The resulting structure is:
input --> fixed div2 --> gate--> dco
I would appreciate your guidance If this is not appropriate.
>> +
>> +/* The output frequency range of the A9 PLL_DCO is 1.4 GHz to 2.8 GHz. */
>> +static const struct pll_mult_range a9_pll_mult_range = {
>> + .min = 117,
>> + .max = 233,
>> +};
> If PLL restriction is actually the DCO output rate, and only the reason
> to keep the pre-devider in the range above, I would definitely welcome a
> rework to express the constraints properly and split the pre-divider out.
>
>> +
>> +static const struct reg_sequence a9_gp0_pll_init_regs[] = {
>> + { .reg = GP0PLL_CTRL0, .def = 0x00010000 },
>> + { .reg = GP0PLL_CTRL1, .def = 0x11480000 },
>> + { .reg = GP0PLL_CTRL2, .def = 0x1219b010 },
>> + { .reg = GP0PLL_CTRL3, .def = 0x00008010 }
>> +};
>> +
>> +static struct clk_regmap a9_gp0_pll_dco = {
>> + .data = &(struct meson_clk_pll_data) {
>> + .en = {
>> + .reg_off = GP0PLL_CTRL0,
>> + .shift = 28,
>> + .width = 1,
>> + },
>> + .m = {
>> + .reg_off = GP0PLL_CTRL0,
>> + .shift = 0,
>> + .width = 9,
>> + },
>> + .n = {
>> + .reg_off = GP0PLL_CTRL0,
>> + .shift = 12,
>> + .width = 3,
>> + },
>> + .frac = {
>> + .reg_off = GP0PLL_CTRL1,
>> + .shift = 0,
>> + .width = 17,
>> + },
>> + .l = {
>> + .reg_off = GP0PLL_CTRL0,
>> + .shift = 31,
>> + .width = 1,
>> + },
>> + .rst = {
>> + .reg_off = GP0PLL_CTRL0,
>> + .shift = 29,
>> + .width = 1,
>> + },
>> + .l_detect = {
>> + .reg_off = GP0PLL_CTRL0,
>> + .shift = 30,
>> + .width = 1,
>> + },
>> + .range = &a9_pll_mult_range,
>> + .init_regs = a9_gp0_pll_init_regs,
>> + .init_count = ARRAY_SIZE(a9_gp0_pll_init_regs),
>> + .flags = CLK_MESON_PLL_RST_ACTIVE_LOW |
>> + CLK_MESON_PLL_N_POWER_OF_TWO |
>> + CLK_MESON_PLL_L_DETECT_ACTIVE_HIGH,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "gp0_pll_dco",
>> + .ops = &meson_clk_pll_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &a9_gp0_in_div2.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +/* For gp0, hifi and mclk pll, the maximum value of od is 4. */
>> +static const struct clk_div_table a9_pll_od_table[] = {
>> + { 0, 1 },
>> + { 1, 2 },
>> + { 2, 4 },
>> + { 3, 8 },
>> + { 4, 16 },
>> + { /* sentinel */ }
>> +};
>> +
>> +static struct clk_regmap a9_gp0_pll = {
>> + .data = &(struct clk_regmap_div_data) {
>> + .offset = GP0PLL_CTRL0,
>> + .shift = 20,
>> + .width = 3,
>> + .table = a9_pll_od_table,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "gp0_pll",
>> + .ops = &clk_regmap_divider_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &a9_gp0_pll_dco.hw
>> + },
>> + .num_parents = 1,
>> + .flags = CLK_SET_RATE_PARENT,
>> + },
>> +};
>> +
>> +static struct clk_fixed_factor a9_hifi0_in_div2_div = {
>> + .mult = 1,
>> + .div = 2,
>> + .hw.init = &(struct clk_init_data){
>> + .name = "hifi0_in_div2_div",
>> + .ops = &clk_fixed_factor_ops,
>> + .parent_data = &(const struct clk_parent_data) {
>> + .fw_name = "in0",
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static struct clk_regmap a9_hifi0_in_div2 = {
>> + .data = &(struct clk_regmap_gate_data) {
>> + .offset = HIFIPLL_CTRL0,
>> + .bit_idx = 27,
>> + },
>> + .hw.init = &(struct clk_init_data) {
>> + .name = "hifi0_in_div2",
>> + .ops = &clk_regmap_gate_ops,
>> + .parent_hws = (const struct clk_hw *[]) {
>> + &a9_hifi0_in_div2_div.hw
>> + },
>> + .num_parents = 1,
>> + },
>> +};
>> +
>> +static const struct reg_sequence a9_hifi0_pll_init_regs[] = {
>> + { .reg = HIFIPLL_CTRL0, .def = 0x00010000 },
>> + { .reg = HIFIPLL_CTRL1, .def = 0x11480000 },
>> + { .reg = HIFIPLL_CTRL2, .def = 0x1219b010 },
>> + { .reg = HIFIPLL_CTRL3, .def = 0x00008010 }
>> +};
> It look like GP0 and HIFI PLL are exactly the same IP, you've even
> documented it as such. Yet all the code is duplicated. That's not OK.
>
> I understand that way we statically declared the clocks so far pushed
> you in that direction. That's something I'd like to fix properly
> someday.
>
> In the meantime, you could at least duplicate the memory at runtime to
> avoid copy/pasting the code. A minor change to clkc utils as suggested
> at the end of this message could help you do so.
>
> Same probably applies to mclks.
You're right, the GP0 and HIFI PLLs are indeed the same IP, differing
only by frac_max:
GP0: frac_max = 2^17
HIFI: frac_max = 100000
Each clock requires its own clk_regmap and clk_hw structure, though the
data in
clk_regmap can be shared between HIFI0 and HIFI1.
I have tried duplicating HIFI1's clock structure from HIFI0 at runtime.
Most members of clk_init_data (except parent_hws / parent_data) can be
easily copied.
However, I have a question regarding dynamic parent assignment:
For example:
Clock B is created dynamically, and its parent is clock A (also created
dynamically).
How should I properly assign this parent relationship?
Furthermore, how to handle more complex parent configurations dynamically?
For example:
Clock D has three parents: C, B, A (in an irregular order).
I would appreciate your guidance on how to handle these dynamic clock
relationships properly.
>
>
[...]
Best regards,
Jian
next prev parent reply other threads:[~2026-05-20 7:33 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-11 12:47 [PATCH 00/10] Add support for A9 family clock controller Jian Hu via B4 Relay
2026-05-11 12:47 ` [PATCH 01/10] dt-bindings: clock: Add Amlogic A9 SCMI " Jian Hu via B4 Relay
2026-05-11 12:47 ` [PATCH 02/10] dt-bindings: clock: Add Amlogic A9 PLL " Jian Hu via B4 Relay
2026-05-15 8:09 ` Krzysztof Kozlowski
2026-05-22 6:20 ` Jian Hu
2026-05-22 9:16 ` Krzysztof Kozlowski
2026-05-22 11:44 ` Jian Hu
2026-05-11 12:47 ` [PATCH 03/10] dt-bindings: clock: Add Amlogic A9 peripherals " Jian Hu via B4 Relay
2026-05-14 16:15 ` Jerome Brunet
2026-05-20 3:16 ` Jian Hu
2026-05-15 8:10 ` Krzysztof Kozlowski
2026-05-22 7:49 ` Jian Hu
2026-05-11 12:47 ` [PATCH 04/10] dt-bindings: clock: Add Amlogic A9 AO " Jian Hu via B4 Relay
2026-05-15 8:10 ` Krzysztof Kozlowski
2026-05-22 8:14 ` Jian Hu
2026-05-11 12:47 ` [PATCH 05/10] clk: amlogic: PLL l_detect signal supports active-high configuration Jian Hu via B4 Relay
2026-05-11 15:47 ` Brian Masney
2026-05-14 15:13 ` Jerome Brunet
2026-05-20 3:25 ` Jian Hu
2026-05-20 7:24 ` Jerome Brunet
2026-05-20 8:46 ` Jian Hu
2026-05-11 12:47 ` [PATCH 06/10] clk: amlogic: PLL reset signal supports active-low configuration Jian Hu via B4 Relay
2026-05-11 15:21 ` Brian Masney
2026-05-13 3:53 ` Jian Hu
2026-05-14 15:16 ` Jerome Brunet
2026-05-20 3:35 ` Jian Hu
2026-05-11 12:47 ` [PATCH 07/10] clk: amlogic: Support POWER_OF_TWO for PLL pre-divider Jian Hu via B4 Relay
2026-05-11 15:23 ` Brian Masney
2026-05-14 15:11 ` Jerome Brunet
2026-05-20 5:47 ` Jian Hu
2026-05-20 7:35 ` Jerome Brunet
2026-05-26 9:58 ` Jian Hu
2026-05-26 12:27 ` Jerome Brunet
2026-05-29 7:08 ` Jian Hu
2026-05-11 12:47 ` [PATCH 08/10] clk: amlogic: Add A9 PLL clock controller driver Jian Hu via B4 Relay
2026-05-11 15:36 ` Brian Masney
2026-05-13 7:25 ` Jian Hu
2026-05-14 16:12 ` Jerome Brunet
2026-05-20 7:33 ` Jian Hu [this message]
2026-05-11 12:47 ` [PATCH 09/10] clk: amlogic: Add A9 peripherals " Jian Hu via B4 Relay
2026-05-11 15:42 ` Brian Masney
2026-05-13 8:50 ` Jian Hu
2026-05-11 12:47 ` [PATCH 10/10] clk: amlogic: Add A9 AO " Jian Hu via B4 Relay
2026-05-11 15:45 ` Brian Masney
2026-05-13 9:19 ` Jian Hu
2026-05-14 16:27 ` Jerome Brunet
2026-05-20 7:37 ` Jian Hu
2026-05-26 7:33 ` [PATCH 00/10] Add support for A9 family clock controller Jerome Brunet
2026-05-26 10:05 ` Jian Hu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=96aac0a2-7531-4a40-8a55-630e92012bb5@amlogic.com \
--to=jian.hu@amlogic.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=devnull+jian.hu.amlogic.com@kernel.org \
--cc=jbrunet@baylibre.com \
--cc=khilman@baylibre.com \
--cc=krzk+dt@kernel.org \
--cc=linux-amlogic@lists.infradead.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-clk@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.blumenstingl@googlemail.com \
--cc=mturquette@baylibre.com \
--cc=neil.armstrong@linaro.org \
--cc=robh@kernel.org \
--cc=sboyd@kernel.org \
--cc=xianwei.zhao@amlogic.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox