Re: [PATCH v2 3/3] clk: meson: a1: add support for Amlogic A1 clock driver

From: Jian Hu
Date: Wed Nov 20 2019 - 04:28:01 EST


Hi, jerome

Is there any problem about fixed_pll_dco's parent_data?

Now both name and fw_name are described in parent_data.

More debug message is in the last email.

On 2019/11/13 22:21, Jian Hu wrote:

On 2019/11/13 0:59, Jerome Brunet wrote:

On Sat 09 Nov 2019 at 12:16, Jian Hu <jian.hu@xxxxxxxxxxx> wrote:

Hi, Jerome

Sorry for late rely

On 2019/11/4 16:24, Jerome Brunet wrote:

On Fri 25 Oct 2019 at 13:32, Jian Hu <jian.hu@xxxxxxxxxxx> wrote:

Hi, Jerome

Thanks for your review

On 2019/10/21 19:41, Jerome Brunet wrote:

On Fri 18 Oct 2019 at 09:14, Jian Hu <jian.hu@xxxxxxxxxxx> wrote:

The Amlogic A1 clock includes three drivers:
peripheral clocks, pll clocks, CPU clocks.
sys pll and CPU clocks will be sent in next patch.

Unlike the previous series, there is no EE/AO domain
in A1 CLK controllers.

Signed-off-by: Jian Hu <jian.hu@xxxxxxxxxxx>
---
 drivers/clk/meson/Kconfig | 10 +
ÂÂÂ drivers/clk/meson/Makefile |ÂÂÂ 1 +
ÂÂÂ drivers/clk/meson/a1-pll.c |Â 345 +++++++
ÂÂÂ drivers/clk/meson/a1-pll.h |ÂÂ 56 ++
ÂÂÂ drivers/clk/meson/a1.cÂÂÂÂ | 2264 ++++++++++++++++++++++++++++++++++++++++++++
ÂÂÂ drivers/clk/meson/a1.hÂÂÂÂ |Â 120 +++
ÂÂÂ 6 files changed, 2796 insertions(+)
ÂÂÂ create mode 100644 drivers/clk/meson/a1-pll.c
ÂÂÂ create mode 100644 drivers/clk/meson/a1-pll.h
ÂÂÂ create mode 100644 drivers/clk/meson/a1.c
ÂÂÂ create mode 100644 drivers/clk/meson/a1.h

In the next version, one
OK, I will send a1 peripheral and pll driver in two patch.


diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index dabeb43..c2809b2 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -93,6 +93,16 @@ config COMMON_CLK_AXG_AUDIO
ÂÂÂÂÂÂÂÂÂ Support for the audio clock controller on AmLogic A113D devices,
ÂÂÂÂÂÂÂÂÂ aka axg, Say Y if you want audio subsystem to work.
ÂÂÂ +config COMMON_CLK_A1
+ÂÂÂ bool
+ÂÂÂ depends on ARCH_MESON
+ÂÂÂ select COMMON_CLK_MESON_REGMAP
+ÂÂÂ select COMMON_CLK_MESON_DUALDIV
+ÂÂÂ select COMMON_CLK_MESON_PLL
+ÂÂÂ help
+ÂÂÂÂÂ Support for the clock controller on Amlogic A113L device,
+ÂÂÂÂÂ aka a1. Say Y if you want peripherals to work.
+
ÂÂÂ config COMMON_CLK_G12A
ÂÂÂÂÂÂÂ bool
ÂÂÂÂÂÂÂ depends on ARCH_MESON
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 3939f21..28cbae1 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o
ÂÂÂÂÂ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
ÂÂÂ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
+obj-$(CONFIG_COMMON_CLK_A1) += a1-pll.o a1.o

So far, all the controller had there own option, I don't see why it
should be different here.

OK, I will add the other option CONFIG_COMMON_CLK_A1_PLL for pll driver
ÂÂÂ obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
ÂÂÂ obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
ÂÂÂ obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c
new file mode 100644
index 0000000..486d964
--- /dev/null
+++ b/drivers/clk/meson/a1-pll.c
@@ -0,0 +1,345 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@xxxxxxxxxxx>
+ */
+
+#include <linux/platform_device.h>

Hum ... looks like some things are missing here

#include <linux/of_device.h>
#include <linux/clk-provider.h>

?
#1
There is <linux/clk-provider.h> in meson-eeclk.h file,

and for A1 driver(a1.c/a1-pll.c) the head file is not requied.

#2
For A1 driver, the file "linux/of_device.h" is not required.
It is required by meson-eeclk.c in fact.

You are using what is provided by these headers directly in this file
If meson-eeclk ever changes, your driver breaks

OK, I will add the two header file.

+#include "clk-pll.h"
+#include "meson-eeclk.h"
+#include "a1-pll.h"

Alphanumeric order please

OK, I will change it in the next version.

+
+static struct clk_regmap a1_fixed_pll_dco = {
+ÂÂÂ .data = &(struct meson_clk_pll_data){
+ÂÂÂÂÂÂÂ .en = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 28,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 1,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .m = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 0,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 8,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .n = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 10,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 5,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .frac = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_FIXPLL_CTRL1,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 0,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 19,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .l = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 31,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 1,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .rst = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 29,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 1,
+ÂÂÂÂÂÂÂ },
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fixed_pll_dco",
+ÂÂÂÂÂÂÂ .ops = &meson_clk_pll_ro_ops,
+ÂÂÂÂÂÂÂ .parent_data = &(const struct clk_parent_data){
+ÂÂÂÂÂÂÂÂÂÂÂ .fw_name = "xtal_fixpll",
+ÂÂÂÂÂÂÂÂÂÂÂ .name = "xtal_fixpll",
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_fixed_pll = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 20,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "fixed_pll",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fixed_pll_dco.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * This clock is fclk_div2/3/4's parent,
+ÂÂÂÂÂÂÂÂ * However, fclk_div2/3/5 feeds AXI/APB/DDR.

is it fclk_div2/3/4 or fclk_div2/3/5 ?

+ÂÂÂÂÂÂÂÂ * It is required by the platform to operate correctly.
+ÂÂÂÂÂÂÂÂ * Until the following condition are met, we need this clock to
+ÂÂÂÂÂÂÂÂ * be marked as critical:
+ÂÂÂÂÂÂÂÂ * a) Mark the clock used by a firmware resource, if possible
+ÂÂÂÂÂÂÂÂ * b) CCF has a clock hand-off mechanism to make the sure the
+ÂÂÂÂÂÂÂÂ *ÂÂÂ clock stays on until the proper driver comes along
+ÂÂÂÂÂÂÂÂ */

Don't blindly copy/paste comments from other drivers. There is no driver
for the devices you are mentionning so the end of the comment is
confusing. The 3 first lines were enough

OK, I will remove the confusing comments

+ÂÂÂÂÂÂÂ .flags = CLK_IS_CRITICAL,

>From your comment, I understand that some child are critical, not this
particular (or at least, not directly). So this can be removed AFAICT

You should even need CLK_IGNORE_UNUSED for this one since the clock will
already be enabled before the late_init() kicks in

OK, I will replace it as CLK_IGNORE_UNUSED.
+ÂÂÂ },
+};
+
+static const struct pll_mult_range a1_hifi_pll_mult_range = {
+ÂÂÂ .min = 32,
+ÂÂÂ .max = 64,
+};
+
+static const struct reg_sequence a1_hifi_init_regs[] = {
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x01800000 },
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 },
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x100a1100 },
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x00302000 },
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f18440 },
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x11f18440, .delay_us = 10 },
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x15f18440, .delay_us = 40 },
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001140 },
+ÂÂÂ { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 },
+};
+
+static struct clk_regmap a1_hifi_pll = {
+ÂÂÂ .data = &(struct meson_clk_pll_data){
+ÂÂÂÂÂÂÂ .en = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 28,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 1,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .m = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 0,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 8,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .n = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_HIFIPLL_CTRL0,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 10,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 5,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .frac = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_HIFIPLL_CTRL1,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 0,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 19,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .l = {
+ÂÂÂÂÂÂÂÂÂÂÂ .reg_off = ANACTRL_HIFIPLL_STS,
+ÂÂÂÂÂÂÂÂÂÂÂ .shiftÂÂ = 31,
+ÂÂÂÂÂÂÂÂÂÂÂ .widthÂÂ = 1,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .range = &a1_hifi_pll_mult_range,
+ÂÂÂÂÂÂÂ .init_regs = a1_hifi_init_regs,
+ÂÂÂÂÂÂÂ .init_count = ARRAY_SIZE(a1_hifi_init_regs),
+ÂÂÂÂÂÂÂ .strict_sequence = true,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "hifi_pll",
+ÂÂÂÂÂÂÂ .ops = &meson_clk_pll_ops,
+ÂÂÂÂÂÂÂ .parent_data = &(const struct clk_parent_data){
+ÂÂÂÂÂÂÂÂÂÂÂ .fw_name = "xtal_fixpll",
+ÂÂÂÂÂÂÂÂÂÂÂ .name = "xtal_fixpll",

Both should provided when a controller transition from the old way of
describing parent to the new way. This is a new controller so it does
not apply.
I do not understand why it does not apply, could you explain more?

Your driver is new, it is not something old transitioning from global
name to clock in DT !


The xtal_fixpll clock is registered in another peripheral driver, If do not
desribe the "name" member in parent_data, "fw_name" does not work because
it has not been registered. the hifi_pll parent will be null in
/sys/kernel/debug/clk/hifi_pll/clk_parent.

HIFI PLL will be a orphan clock, but its parent should be xtal_fixpll.

There will be an orphan yes, temporarily, until both controllers are up.
Once both controller are up, the clock will be reparented if necessary.


So both of "fw_name" of "name" should be described.

No


#1

Here, I am still confused.
ÂFrom the point of view of the phenomenonï the name in parent_data is
required.


HIFI PLL is described like this:

ÂÂÂÂ.parent_data = &(const struct clk_parent_data){
ÂÂÂÂÂÂÂ .fw_name = "xtal_hifipll",
ÂÂÂÂÂÂÂ .name = "xtal_hifipll"
ÂÂÂÂ}

Fixed PLL is described like this:

ÂÂÂÂ.parent_data = &(const struct clk_parent_data){
ÂÂÂÂÂÂÂ .fw_name = "xtal_fixpll",
ÂÂÂÂ},

After the system boot completelyï run cat
/sys/kernel/debug/clk/clk_summary, Here is the result:

# cat /sys/kernel/debug/clk/clk_summary
 enable prepare protect duty
 clock count count count rate accuracy phase cycle
--------------------------------------------------------------------
 xtal 5 5 0 24000000 0 0 50000
ÂÂÂÂ ts_divÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂ 24000000ÂÂÂ 0ÂÂÂÂ 0Â 50000
ÂÂÂÂÂÂÂ tsÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂ 24000000ÂÂÂ 0ÂÂÂÂ 0Â 50000
ÂÂÂÂ pwm_f_selÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂ 24000000ÂÂÂ 0ÂÂÂÂ 0Â 50000
ÂÂÂÂÂÂÂ pwm_f_div 0ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂ 24000000ÂÂÂ 0ÂÂÂÂ 0Â 50000
 pwm_f 0 0 0 24000000 0 0 50000
......
 xtal_syspll 0 0 0 24000000 0 0 50000
ÂÂÂÂ xtal_hifipll 0ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂ 24000000ÂÂÂ 0ÂÂÂÂ 0Â 50000
 hifi_pll 0 0 0 1536000000 0 0 50000
ÂÂÂÂ xtal_usb_ctrl 0ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂ 24000000ÂÂ 0ÂÂÂÂ 0Â 50000
 xtal_usb_phy 0 0 0 24000000 0 0 50000
ÂÂÂÂ xtal_fixpllÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂ 24000000ÂÂ 0ÂÂÂÂ 0Â 50000
 xtal_clktree 0 0 0 24000000 0 0 50000
 fixed_pll_dco 1 1 0 0 0 0 50000

This means that CCF what not able to resolve the parent.
Either:
* you've made a mistake somewhere
* There is bug in CCF when the parent device is not available at probe
time, the clock is not properly reparented


#1 Add DT describtion

DT description:

clkc_pll: pll-clock-controller {
ÂÂÂÂÂ compatible = "amlogic,a1-pll-clkc";
ÂÂÂÂÂ #clock-cells = <1>;
ÂÂÂÂÂ reg = <0 0x7c80 0 0x21c>;
ÂÂÂÂÂ clocks = <&clkc_periphs CLKID_XTAL_FIXPLL>,
ÂÂÂÂÂÂÂÂÂÂÂ <&clkc_periphs CLKID_XTAL_HIFIPLL>;
ÂÂÂÂÂ clock-names = "xtal_fixpll", "xtal_hifipll";
};

clkc_periphs: periphs-clock-controller {
ÂÂÂÂÂ compatible = "amlogic,a1-periphs-clkc";
ÂÂÂÂÂ #clock-cells = <1>;
ÂÂÂÂÂ reg = <0 0x800 0 0x104>;
ÂÂÂÂÂ clocks = <&clkc_pll CLKID_FCLK_DIV2>,
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ <&clkc_pll CLKID_FCLK_DIV3>,
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ <&clkc_pll CLKID_FCLK_DIV5>,
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ <&clkc_pll CLKID_FCLK_DIV7>,
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ <&clkc_pll CLKID_HIFI_PLL>,
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ <&xtal>;
ÂÂÂÂÂ clock-names = "fclk_div2", "fclk_div3", "fclk_div5",
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ "fclk_div7", "hifi_pll", "xtal";
};

And PLL clock driver probe first.

When register xtal_fixpll clock in periphs driver

it will walk the list of orphan clocks, it will try to get the orphan parent.

the code path is :

struct clk_core *parent = __clk_init_parent(orphan)

 -> clk_core_get_parent_by_index(core, index)

ÂÂ ->clk_core_fill_parent_index

ÂÂÂ ->clk_core_get

ÂÂÂÂ ->of_clk_get_hw_from_clkspec

In of_clk_get_hw_from_clkspec function, it will get hw_clk from clk_provider, However the peripheral clock provider has not been
added to "of_clk_providers" LIST, In other words, the peripheral clock
provider does not exist at this time. (devm_of_clk_add_hw_provider has not run)

So It will get parent failed from DT.

even if name is added in parent_data, PTR_ERR(parent) is not equal -ENOENT, it will not run clk_core_lookup, the fixed_pll_dco is still a orphan clock.

#2 Not add DT describtion

the code path is :

struct clk_core *parent = __clk_init_parent(orphan)

 -> clk_core_get_parent_by_index(core, index)

ÂÂ ->clk_core_fill_parent_index

ÂÂÂ ->clk_core_get

ÂÂÂÂ ->clk_find_hw

clk_find_hw is used when the clock is registered by clk_register_clkdev

So it wlll get parented failed by clk_find_hw.

When name is described in parent_data, the parent will be found by

clk_core_lookup.


In this sceneïOnly fw_name in parent_data, the orphan clock's parent can not be found, But add the legacy name, the parent will be found.

#3
When the provider has not been added to the CCF, And fw_name is alone in parent_data in a orphan clock , How to get the orphan clock'parent ?
It seems not supported.

Either way, you'll have to debug a bit more

ÂÂÂÂ fixed_pllÂÂÂÂ 3ÂÂÂÂÂÂÂ 3ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂÂ 0ÂÂ 0ÂÂÂÂ 0Â 50000
ÂÂÂÂÂÂÂ fclk_div7_div 0ÂÂÂÂ 0ÂÂÂÂÂÂÂ 0ÂÂÂÂÂÂÂÂ 0ÂÂ 0ÂÂÂÂ 0Â 50000
....

the hifi_pll's parent is xtal_hifi, And the hifi_pll default rate is right.

but the fixed_pll_dco is a orphan clock, its parent is NULL.And its rate
is zero.When the name in parent_data is added, its parent is xtal_fixpll.

# cat /sys/kernel/debug/clk/fixed_pll_dco/clk_parent
#
# cat /sys/kernel/debug/clk/fixed_pll_dco/clk_rate
0


#2
In ./drivers/clk/qcom/gcc-sm8150.c
For some clocks, Both fw_name and name are described in parent_data
struct.

Those are being migrated to DT description which means that we don't
know if the DT will the correct description

In this case the clock framework will first try DT and if DT does
provide this fw_name, it will fallback to the legacy name.

This is not your case as this is a new platform for which we know the DT
name exist.

It will get parent failed from DT as the previous says.



Same for the other occurences.

Also, I think you meant xtal_hifipll
Yes,I will correct it.

+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂ },
+};
+
+static struct clk_fixed_factor a1_fclk_div2_div = {
+ÂÂÂ .mult = 1,
+ÂÂÂ .div = 2,
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fclk_div2_div",
+ÂÂÂÂÂÂÂ .ops = &clk_fixed_factor_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fixed_pll.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_fclk_div2 = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 21,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fclk_div2",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fclk_div2_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * This clock is used by DDR clock in BL2 firmware
+ÂÂÂÂÂÂÂÂ * and is required by the platform to operate correctly.
+ÂÂÂÂÂÂÂÂ * Until the following condition are met, we need this clock to
+ÂÂÂÂÂÂÂÂ * be marked as critical:
+ÂÂÂÂÂÂÂÂ * a) Mark the clock used by a firmware resource, if possible
+ÂÂÂÂÂÂÂÂ * b) CCF has a clock hand-off mechanism to make the sure the
+ÂÂÂÂÂÂÂÂ *ÂÂÂ clock stays on until the proper driver comes along
+ÂÂÂÂÂÂÂÂ */
+ÂÂÂÂÂÂÂ .flags = CLK_IS_CRITICAL,
+ÂÂÂ },
+};
+
+static struct clk_fixed_factor a1_fclk_div3_div = {
+ÂÂÂ .mult = 1,
+ÂÂÂ .div = 3,
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fclk_div3_div",
+ÂÂÂÂÂÂÂ .ops = &clk_fixed_factor_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fixed_pll.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_fclk_div3 = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 22,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fclk_div3",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fclk_div3_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * This clock is used by APB bus which setted in Romcode
+ÂÂÂÂÂÂÂÂ * and is required by the platform to operate correctly.
+ÂÂÂÂÂÂÂÂ * Until the following condition are met, we need this clock to
+ÂÂÂÂÂÂÂÂ * be marked as critical:
+ÂÂÂÂÂÂÂÂ * a) Mark the clock used by a firmware resource, if possible
+ÂÂÂÂÂÂÂÂ * b) CCF has a clock hand-off mechanism to make the sure the
+ÂÂÂÂÂÂÂÂ *ÂÂÂ clock stays on until the proper driver comes along
+ÂÂÂÂÂÂÂÂ */
+ÂÂÂÂÂÂÂ .flags = CLK_IS_CRITICAL,
+ÂÂÂ },
+};
+
+static struct clk_fixed_factor a1_fclk_div5_div = {
+ÂÂÂ .mult = 1,
+ÂÂÂ .div = 5,
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fclk_div5_div",
+ÂÂÂÂÂÂÂ .ops = &clk_fixed_factor_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fixed_pll.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_fclk_div5 = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 23,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fclk_div5",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fclk_div5_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * This clock is used by AXI bus which setted in Romcode
+ÂÂÂÂÂÂÂÂ * and is required by the platform to operate correctly.
+ÂÂÂÂÂÂÂÂ * Until the following condition are met, we need this clock to
+ÂÂÂÂÂÂÂÂ * be marked as critical:
+ÂÂÂÂÂÂÂÂ * a) Mark the clock used by a firmware resource, if possible
+ÂÂÂÂÂÂÂÂ * b) CCF has a clock hand-off mechanism to make the sure the
+ÂÂÂÂÂÂÂÂ *ÂÂÂ clock stays on until the proper driver comes along
+ÂÂÂÂÂÂÂÂ */
+ÂÂÂÂÂÂÂ .flags = CLK_IS_CRITICAL,
+ÂÂÂ },
+};
+
+static struct clk_fixed_factor a1_fclk_div7_div = {
+ÂÂÂ .mult = 1,
+ÂÂÂ .div = 7,
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fclk_div7_div",
+ÂÂÂÂÂÂÂ .ops = &clk_fixed_factor_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fixed_pll.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_fclk_div7 = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = ANACTRL_FIXPLL_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 24,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "fclk_div7",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_fclk_div7_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂ },
+};
+
+/* Array of all clocks provided by this provider */
+static struct clk_hw_onecell_data a1_pll_hw_onecell_data = {
+ÂÂÂ .hws = {
+ÂÂÂÂÂÂÂ [CLKID_FIXED_PLL_DCO]ÂÂÂÂÂÂÂ = &a1_fixed_pll_dco.hw,
+ÂÂÂÂÂÂÂ [CLKID_FIXED_PLL]ÂÂÂÂÂÂÂ = &a1_fixed_pll.hw,
+ÂÂÂÂÂÂÂ [CLKID_HIFI_PLL]ÂÂÂÂÂÂÂ = &a1_hifi_pll.hw,
+ÂÂÂÂÂÂÂ [CLKID_FCLK_DIV2]ÂÂÂÂÂÂÂ = &a1_fclk_div2.hw,
+ÂÂÂÂÂÂÂ [CLKID_FCLK_DIV3]ÂÂÂÂÂÂÂ = &a1_fclk_div3.hw,
+ÂÂÂÂÂÂÂ [CLKID_FCLK_DIV5]ÂÂÂÂÂÂÂ = &a1_fclk_div5.hw,
+ÂÂÂÂÂÂÂ [CLKID_FCLK_DIV7]ÂÂÂÂÂÂÂ = &a1_fclk_div7.hw,
+ÂÂÂÂÂÂÂ [CLKID_FCLK_DIV2_DIV]ÂÂÂÂÂÂÂ = &a1_fclk_div2_div.hw,
+ÂÂÂÂÂÂÂ [CLKID_FCLK_DIV3_DIV]ÂÂÂÂÂÂÂ = &a1_fclk_div3_div.hw,
+ÂÂÂÂÂÂÂ [CLKID_FCLK_DIV5_DIV]ÂÂÂÂÂÂÂ = &a1_fclk_div5_div.hw,
+ÂÂÂÂÂÂÂ [CLKID_FCLK_DIV7_DIV]ÂÂÂÂÂÂÂ = &a1_fclk_div7_div.hw,
+ÂÂÂÂÂÂÂ [NR_PLL_CLKS]ÂÂÂÂÂÂÂÂÂÂÂ = NULL,
+ÂÂÂ },
+ÂÂÂ .num = NR_PLL_CLKS,
+};
+
+static struct clk_regmap *const a1_pll_regmaps[] = {
+ÂÂÂ &a1_fixed_pll_dco,
+ÂÂÂ &a1_fixed_pll,
+ÂÂÂ &a1_hifi_pll,
+ÂÂÂ &a1_fclk_div2,
+ÂÂÂ &a1_fclk_div3,
+ÂÂÂ &a1_fclk_div5,
+ÂÂÂ &a1_fclk_div7,
+};
+
+static int meson_a1_pll_probe(struct platform_device *pdev)
+{
+ÂÂÂ int ret;
+
+ÂÂÂ ret = meson_eeclkc_probe(pdev);
+ÂÂÂ if (ret)
+ÂÂÂÂÂÂÂ return ret;
+
+ÂÂÂ return 0;
+}

This function is useless.

OK, I will use meson_eeclkc_probe derectly.
+
+static const struct meson_eeclkc_data a1_pll_data = {
+ÂÂÂÂÂÂÂ .regmap_clks = a1_pll_regmaps,
+ÂÂÂÂÂÂÂ .regmap_clk_num = ARRAY_SIZE(a1_pll_regmaps),
+ÂÂÂÂÂÂÂ .hw_onecell_data = &a1_pll_hw_onecell_data,
+};
+static const struct of_device_id clkc_match_table[] = {
+ÂÂÂ {
+ÂÂÂÂÂÂÂ .compatible = "amlogic,a1-pll-clkc",
+ÂÂÂÂÂÂÂ .data = &a1_pll_data
+ÂÂÂ },
+ÂÂÂ { /* sentinel */ }

Nitpick: don't need to write this, just write the line like this

OK, remove it.
' }, {}'

+};
+
+static struct platform_driver a1_driver = {
+ÂÂÂ .probeÂÂÂÂÂÂÂ = meson_a1_pll_probe,
+ÂÂÂ .driverÂÂÂÂÂÂÂ = {
+ÂÂÂÂÂÂÂ .nameÂÂÂ = "a1-pll-clkc",
+ÂÂÂÂÂÂÂ .of_match_table = clkc_match_table,
+ÂÂÂ },
+};
+
+builtin_platform_driver(a1_driver);
diff --git a/drivers/clk/meson/a1-pll.h b/drivers/clk/meson/a1-pll.h
new file mode 100644
index 0000000..99ee2a9
--- /dev/null
+++ b/drivers/clk/meson/a1-pll.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __A1_PLL_H
+#define __A1_PLL_H
+
+/* PLL register offset */
+#define ANACTRL_FIXPLL_CTRL0ÂÂÂÂÂÂÂ 0x80
+#define ANACTRL_FIXPLL_CTRL1ÂÂÂÂÂÂÂ 0x84
+#define ANACTRL_FIXPLL_CTRL2ÂÂÂÂÂÂÂ 0x88
+#define ANACTRL_FIXPLL_CTRL3ÂÂÂÂÂÂÂ 0x8c
+#define ANACTRL_FIXPLL_CTRL4ÂÂÂÂÂÂÂ 0x90
+#define ANACTRL_FIXPLL_STSÂÂÂÂÂÂÂ 0x94
+#define ANACTRL_SYSPLL_CTRL0ÂÂÂÂÂÂÂ 0x100
+#define ANACTRL_SYSPLL_CTRL1ÂÂÂÂÂÂÂ 0x104
+#define ANACTRL_SYSPLL_CTRL2ÂÂÂÂÂÂÂ 0x108
+#define ANACTRL_SYSPLL_CTRL3ÂÂÂÂÂÂÂ 0x10c
+#define ANACTRL_SYSPLL_CTRL4ÂÂÂÂÂÂÂ 0x110
+#define ANACTRL_SYSPLL_STSÂÂÂÂÂÂÂ 0x114
+#define ANACTRL_HIFIPLL_CTRL0ÂÂÂÂÂÂÂ 0x140
+#define ANACTRL_HIFIPLL_CTRL1ÂÂÂÂÂÂÂ 0x144
+#define ANACTRL_HIFIPLL_CTRL2ÂÂÂÂÂÂÂ 0x148
+#define ANACTRL_HIFIPLL_CTRL3ÂÂÂÂÂÂÂ 0x14c
+#define ANACTRL_HIFIPLL_CTRL4ÂÂÂÂÂÂÂ 0x150
+#define ANACTRL_HIFIPLL_STSÂÂÂÂÂÂÂ 0x154
+#define ANACTRL_AUDDDS_CTRL0ÂÂÂÂÂÂÂ 0x180
+#define ANACTRL_AUDDDS_CTRL1ÂÂÂÂÂÂÂ 0x184
+#define ANACTRL_AUDDDS_CTRL2ÂÂÂÂÂÂÂ 0x188
+#define ANACTRL_AUDDDS_CTRL3ÂÂÂÂÂÂÂ 0x18c
+#define ANACTRL_AUDDDS_CTRL4ÂÂÂÂÂÂÂ 0x190
+#define ANACTRL_AUDDDS_STSÂÂÂÂÂÂÂ 0x194
+#define ANACTRL_MISCTOP_CTRL0ÂÂÂÂÂÂÂ 0x1c0
+#define ANACTRL_POR_CNTLÂÂÂÂÂÂÂ 0x208
+
+/*
+ * CLKID index values
+ *
+ * These indices are entirely contrived and do not map onto the hardware.
+ * It has now been decided to expose everything by default in the DT header:
+ * include/dt-bindings/clock/a1-pll-clkc.h. Only the clocks ids we don't want
+ * to expose, such as the internal muxes and dividers of composite clocks,
+ * will remain defined here.
+ */
+#define CLKID_FIXED_PLL_DCOÂÂÂÂÂÂÂ 0
+#define CLKID_FCLK_DIV2_DIVÂÂÂÂÂÂÂ 2
+#define CLKID_FCLK_DIV3_DIVÂÂÂÂÂÂÂ 3
+#define CLKID_FCLK_DIV5_DIVÂÂÂÂÂÂÂ 4
+#define CLKID_FCLK_DIV7_DIVÂÂÂÂÂÂÂ 5
+#define NR_PLL_CLKSÂÂÂÂÂÂÂÂÂÂÂ 11
+
+/* include the CLKIDs that have been made part of the DT binding */
+#include <dt-bindings/clock/a1-pll-clkc.h>
+
+#endif /* __A1_PLL_H */
diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c
new file mode 100644
index 0000000..86a4733
--- /dev/null
+++ b/drivers/clk/meson/a1.c
@@ -0,0 +1,2264 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu@xxxxxxxxxxx>
+ */
+
+#include <linux/platform_device.h>
+#include "clk-pll.h"
+#include "clk-dualdiv.h"
+#include "meson-eeclk.h"
+#include "a1.h"

Same as above
OK, I will change the order.
In fact, the clk-pll.h is not used in the current driver.
I will remove it.

+
+/* PLLs clock in gates, its parent is xtal */
+static struct clk_regmap a1_xtal_clktree = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = SYS_OSCIN_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 0,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "xtal_clktree",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ro_ops,
+ÂÂÂÂÂÂÂ .parent_data = &(const struct clk_parent_data) {
+ÂÂÂÂÂÂÂÂÂÂÂ .fw_name = "xtal",
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * switch for xtal clock
+ÂÂÂÂÂÂÂÂ * Linux should not change it at runtime
+ÂÂÂÂÂÂÂÂ */

Comment not useful: it uses the Ro ops

OK, remove the comments
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_xtal_fixpll = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = SYS_OSCIN_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 1,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "xtal_fixpll",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_data = &(const struct clk_parent_data) {
+ÂÂÂÂÂÂÂÂÂÂÂ .fw_name = "xtal",
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_IS_CRITICAL,
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * it feeds DDR,AXI,APB bus
+ÂÂÂÂÂÂÂÂ * Linux should not change it at runtime
+ÂÂÂÂÂÂÂÂ */

Again, the child are critical, not directly this clock from your
comment.

Remove CRITICAL, put RO is linux is not supposed to touch it.

repace as clk_regmap_gate_ro_ops
+ÂÂÂ },
+};
+

[ ... ]

+
+/* dsp a clk */
+static u32 mux_table_dsp_ab[] = { 0, 1, 2, 3, 4, 7 };
+static const struct clk_parent_data dsp_ab_clk_parent_data[] = {
+ÂÂÂ { .fw_name = "xtal", },
+ÂÂÂ { .fw_name = "fclk_div2", },
+ÂÂÂ { .fw_name = "fclk_div3", },
+ÂÂÂ { .fw_name = "fclk_div5", },
+ÂÂÂ { .fw_name = "hifi_pll", },
+ÂÂÂ { .hw = &a1_rtc_clk.hw },
+};
+
+static struct clk_regmap a1_dspa_a_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .mask = 0x7,
+ÂÂÂÂÂÂÂ .shift = 10,
+ÂÂÂÂÂÂÂ .table = mux_table_dsp_ab,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspa_a_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = dsp_ab_clk_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(dsp_ab_clk_parent_data),

.flags = CLK_SET_RATE_PARENT ?
Yes, I miss the flag.

+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspa_a_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .shift = 0,
+ÂÂÂÂÂÂÂ .width = 10,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspa_a_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspa_a_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspa_a = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 13,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dspa_a",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspa_a_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspa_b_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .mask = 0x7,
+ÂÂÂÂÂÂÂ .shift = 26,
+ÂÂÂÂÂÂÂ .table = mux_table_dsp_ab,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspa_b_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = dsp_ab_clk_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(dsp_ab_clk_parent_data),

.flags = CLK_SET_RATE_PARENT ?

Yes, I will add it.
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspa_b_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .shift = 16,
+ÂÂÂÂÂÂÂ .width = 10,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspa_b_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspa_b_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspa_b = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 29,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dspa_b",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspa_b_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspa_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .mask = 0x1,
+ÂÂÂÂÂÂÂ .shift = 15,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspa_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = (const struct clk_parent_data []) {
+ÂÂÂÂÂÂÂÂÂÂÂ { .hw = &a1_dspa_a.hw },
+ÂÂÂÂÂÂÂÂÂÂÂ { .hw = &a1_dspa_b.hw },
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 2,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspa_en_dspa = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_EN,
+ÂÂÂÂÂÂÂ .bit_idx = 1,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dspa_en_dspa",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspa_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,

Why do you need CLK_IGNORE_UNUSED ?

I should remove it
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspa_en_nic = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DSPA_CLK_EN,
+ÂÂÂÂÂÂÂ .bit_idx = 0,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dspa_en_nic",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspa_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,

Why do you need CLK_IGNORE_UNUSED ?

I should remove it
+ÂÂÂ },
+};
+

Same question and remarks applies to DSP B

got it
+/* dsp b clk */
+static struct clk_regmap a1_dspb_a_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .mask = 0x7,
+ÂÂÂÂÂÂÂ .shift = 10,
+ÂÂÂÂÂÂÂ .table = mux_table_dsp_ab,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspb_a_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = dsp_ab_clk_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(dsp_ab_clk_parent_data),
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspb_a_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .shift = 0,
+ÂÂÂÂÂÂÂ .width = 10,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspb_a_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspb_a_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspb_a = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 13,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dspb_a",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspb_a_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspb_b_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .mask = 0x7,
+ÂÂÂÂÂÂÂ .shift = 26,
+ÂÂÂÂÂÂÂ .table = mux_table_dsp_ab,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspb_b_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = dsp_ab_clk_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(dsp_ab_clk_parent_data),
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspb_b_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .shift = 16,
+ÂÂÂÂÂÂÂ .width = 10,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspb_b_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspb_b_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspb_b = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .bit_idx = 29,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dspb_b",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspb_b_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspb_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_CTRL0,
+ÂÂÂÂÂÂÂ .mask = 0x1,
+ÂÂÂÂÂÂÂ .shift = 15,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dspb_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspb_a.hw, &a1_dspb_b.hw,
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 2,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspb_en_dspb = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_EN,
+ÂÂÂÂÂÂÂ .bit_idx = 1,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dspb_en_dspb",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspb_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dspb_en_nic = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DSPB_CLK_EN,
+ÂÂÂÂÂÂÂ .bit_idx = 0,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dspb_en_nic",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dspb_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+ÂÂÂ },
+};
+
+/* 12M/24M clock */
+static struct clk_regmap a1_24m = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = CLK12_24_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 11,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "24m",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_data = &(const struct clk_parent_data) {
+ÂÂÂÂÂÂÂÂÂÂÂ .fw_name = "xtal",
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂ },
+};
+

[ ... ]

+static struct clk_regmap a1_saradc_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = SAR_ADC_CLK_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x1,
+ÂÂÂÂÂÂÂ .shift = 9,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "saradc_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = (const struct clk_parent_data []) {
+ÂÂÂÂÂÂÂÂÂÂÂ { .fw_name = "xtal", },
+ÂÂÂÂÂÂÂÂÂÂÂ { .hw = &a1_sys_clk.hw, },
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 2,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_saradc_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = SAR_ADC_CLK_CTRL,
+ÂÂÂÂÂÂÂ .shift = 0,
+ÂÂÂÂÂÂÂ .width = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "saradc_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_saradc_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_saradc_clk = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = SAR_ADC_CLK_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "saradc_clk",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_saradc_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+/* pwm a/b/c/d parent data */
+static const struct clk_parent_data pwm_parent_data[] = {
+ÂÂÂ { .fw_name = "xtal", },
+ÂÂÂ { .hw = &a1_sys_clk.hw },
+};

Looks like the same as SAR ADC

OK, I will describe it like SAR ADC for pwm a/b/c/d
+
+/* pwm a clk */
+static struct clk_regmap a1_pwm_a_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_AB_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x1,
+ÂÂÂÂÂÂÂ .shift = 9,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_a_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = pwm_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(pwm_parent_data),
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_a_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_AB_CTRL,
+ÂÂÂÂÂÂÂ .shift = 0,
+ÂÂÂÂÂÂÂ .width = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_a_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_a_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_a = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_AB_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "pwm_a",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_a_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * The CPU working voltage is controlled by pwm_a
+ÂÂÂÂÂÂÂÂ * in BL2 firmware. add the CLK_IGNORE_UNUSED flag
+ÂÂÂÂÂÂÂÂ * to avoid changing at runtime.
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ^ it

+ÂÂÂÂÂÂÂÂ * and is required by the platform to operate correctly.
ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ "blabla. And" is strange

+ÂÂÂÂÂÂÂÂ * Until the following condition are met, we need this clock to
+ÂÂÂÂÂÂÂÂ * be marked as critical:
+ÂÂÂÂÂÂÂÂ * a) Mark the clock used by a firmware resource, if possible
+ÂÂÂÂÂÂÂÂ * b) CCF has a clock hand-off mechanism to make the sure the
+ÂÂÂÂÂÂÂÂ *ÂÂÂ clock stays on until the proper driver comes along
+ÂÂÂÂÂÂÂÂ */
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,

This only skips the late_init() disable of unused clocks

Be aware that this is not fool-proof. If at any time a driver enable
then disable the clock, the clock will be disable and I guess your
platform will die if this provides the CPU voltage.
OK, CLK_IS_CRITICAL is better.

+ÂÂÂ },
+};
+
+/* pwm b clk */
+static struct clk_regmap a1_pwm_b_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_AB_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x1,
+ÂÂÂÂÂÂÂ .shift = 25,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_b_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = pwm_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(pwm_parent_data),
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_b_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_AB_CTRL,
+ÂÂÂÂÂÂÂ .shift = 16,
+ÂÂÂÂÂÂÂ .width = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_b_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_b_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_b = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_AB_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 24,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "pwm_b",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_b_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+/* pwm c clk */
+static struct clk_regmap a1_pwm_c_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_CD_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x1,
+ÂÂÂÂÂÂÂ .shift = 9,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_c_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = pwm_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(pwm_parent_data),
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_c_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_CD_CTRL,
+ÂÂÂÂÂÂÂ .shift = 0,
+ÂÂÂÂÂÂÂ .width = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_c_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_c_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_c = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_CD_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "pwm_c",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_c_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+/* pwm d clk */
+static struct clk_regmap a1_pwm_d_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_CD_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x1,
+ÂÂÂÂÂÂÂ .shift = 25,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_d_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = pwm_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(pwm_parent_data),
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_d_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_CD_CTRL,
+ÂÂÂÂÂÂÂ .shift = 16,
+ÂÂÂÂÂÂÂ .width = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_d_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_d_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_d = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_CD_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 24,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "pwm_d",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_d_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static const struct clk_parent_data pwm_ef_parent_data[] = {
+ÂÂÂ { .fw_name = "xtal", },
+ÂÂÂ { .hw = &a1_sys_clk.hw },
+ÂÂÂ { .fw_name = "fclk_div5", },
+ÂÂÂ { .hw = &a1_rtc_clk.hw },
+};
+
+/* pwm e clk */
+static struct clk_regmap a1_pwm_e_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_EF_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x3,
+ÂÂÂÂÂÂÂ .shift = 9,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_e_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = pwm_ef_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(pwm_ef_parent_data),
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_e_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_EF_CTRL,
+ÂÂÂÂÂÂÂ .shift = 0,
+ÂÂÂÂÂÂÂ .width = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_e_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_e_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_e = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_EF_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "pwm_e",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_e_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+/* pwm f clk */
+static struct clk_regmap a1_pwm_f_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_EF_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x3,
+ÂÂÂÂÂÂÂ .shift = 25,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_f_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = pwm_ef_parent_data,
+ÂÂÂÂÂÂÂ .num_parents = ARRAY_SIZE(pwm_ef_parent_data),
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_f_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_EF_CTRL,
+ÂÂÂÂÂÂÂ .shift = 16,
+ÂÂÂÂÂÂÂ .width = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "pwm_f_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_f_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_pwm_f = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = PWM_CLK_EF_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 24,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "pwm_f",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_pwm_f_div.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+

[ ... ]

+
+/* dmc clk */
+static struct clk_regmap a1_dmc_sel = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = DMC_CLK_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x3,
+ÂÂÂÂÂÂÂ .shift = 9,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dmc_sel",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = sd_emmc_parents,
+ÂÂÂÂÂÂÂ .num_parents = 4,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dmc_div = {
+ÂÂÂ .data = &(struct clk_regmap_div_data){
+ÂÂÂÂÂÂÂ .offset = DMC_CLK_CTRL,
+ÂÂÂÂÂÂÂ .shift = 0,
+ÂÂÂÂÂÂÂ .width = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dmc_div",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_divider_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dmc_sel.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dmc_sel2 = {
+ÂÂÂ .data = &(struct clk_regmap_mux_data){
+ÂÂÂÂÂÂÂ .offset = DMC_CLK_CTRL,
+ÂÂÂÂÂÂÂ .mask = 0x1,
+ÂÂÂÂÂÂÂ .shift = 15,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data){
+ÂÂÂÂÂÂÂ .name = "dmc_sel2",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_mux_ops,
+ÂÂÂÂÂÂÂ .parent_data = (const struct clk_parent_data []) {
+ÂÂÂÂÂÂÂÂÂÂÂ { .hw = &a1_dmc_div.hw },
+ÂÂÂÂÂÂÂÂÂÂÂ { .fw_name = "xtal", },
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 2,
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT,
+ÂÂÂ },
+};
+
+static struct clk_regmap a1_dmc = {
+ÂÂÂ .data = &(struct clk_regmap_gate_data){
+ÂÂÂÂÂÂÂ .offset = DMC_CLK_CTRL,
+ÂÂÂÂÂÂÂ .bit_idx = 8,
+ÂÂÂ },
+ÂÂÂ .hw.init = &(struct clk_init_data) {
+ÂÂÂÂÂÂÂ .name = "dmc",
+ÂÂÂÂÂÂÂ .ops = &clk_regmap_gate_ops,
+ÂÂÂÂÂÂÂ .parent_hws = (const struct clk_hw *[]) {
+ÂÂÂÂÂÂÂÂÂÂÂ &a1_dmc_sel2.hw
+ÂÂÂÂÂÂÂ },
+ÂÂÂÂÂÂÂ .num_parents = 1,
+ÂÂÂÂÂÂÂ /*
+ÂÂÂÂÂÂÂÂ * This clock is used by DDR clock which setted in BL2
+ÂÂÂÂÂÂÂÂ * and is required by the platform to operate correctly.
+ÂÂÂÂÂÂÂÂ * Until the following condition are met, we need this clock to
+ÂÂÂÂÂÂÂÂ * be marked as critical:
+ÂÂÂÂÂÂÂÂ * a) Mark the clock used by a firmware resource, if possible
+ÂÂÂÂÂÂÂÂ * b) CCF has a clock hand-off mechanism to make the sure the
+ÂÂÂÂÂÂÂÂ *ÂÂÂ clock stays on until the proper driver comes along
+ÂÂÂÂÂÂÂÂ */
+ÂÂÂÂÂÂÂ .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
+ÂÂÂ },
+};

Should you put all this DMC stuff in RO until you got a driver for it ?
OK, replace as clk_regmap_gate_ro_ops

[ ... ]
+
+static int meson_a1_periphs_probe(struct platform_device *pdev)
+{
+ÂÂÂ int ret;
+
+ÂÂÂ ret = meson_eeclkc_probe(pdev);
+ÂÂÂ if (ret)
+ÂÂÂÂÂÂÂ return ret;
+
+ÂÂÂ return 0;
+}

Again this function is function is useless and it makes me wonder if you
should really be using meson_eeclkc_probe()

This makes you use syscon which is not correct unless you have a good
reason ?

If it can not use the meson_eeclkc_probe(), I will realize a probe function
which is mostly duplicate with meson_eeclkc_probe() except
"syscon_node_to_regmap"

Maybe another common probe function and a new file are required for A1
three drivers? ïinclude the CPU clock driverï

Maybe

I will add a new function base on meson-eeclk.c

Or using meson_eeclkc_probe is more easier?

It is not question of easiness, but correctness.


Is there anything but clocks and resets in these register region ?
No, there is only clocks in the register region.
the same does the PLL register region.

Then there is no reason to use syscon for those drivers
Add a new probe function for A1

+
+static const struct meson_eeclkc_data a1_periphs_data = {
+ÂÂÂÂÂÂÂ .regmap_clks = a1_periphs_regmaps,
+ÂÂÂÂÂÂÂ .regmap_clk_num = ARRAY_SIZE(a1_periphs_regmaps),
+ÂÂÂÂÂÂÂ .hw_onecell_data = &a1_periphs_hw_onecell_data,
+};
+static const struct of_device_id clkc_match_table[] = {
+ÂÂÂ {
+ÂÂÂÂÂÂÂ .compatible = "amlogic,a1-periphs-clkc",
+ÂÂÂÂÂÂÂ .data = &a1_periphs_data
+ÂÂÂ },
+ÂÂÂ { /* sentinel */ }
+};
+
+static struct platform_driver a1_driver = {
+ÂÂÂ .probeÂÂÂÂÂÂÂ = meson_a1_periphs_probe,
+ÂÂÂ .driverÂÂÂÂÂÂÂ = {
+ÂÂÂÂÂÂÂ .nameÂÂÂ = "a1-periphs-clkc",
+ÂÂÂÂÂÂÂ .of_match_table = clkc_match_table,
+ÂÂÂ },
+};
+
+builtin_platform_driver(a1_driver);
diff --git a/drivers/clk/meson/a1.h b/drivers/clk/meson/a1.h
new file mode 100644
index 0000000..1ae5e04
--- /dev/null
+++ b/drivers/clk/meson/a1.h
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __A1_H
+#define __A1_H
+
+/* peripheral clock controller register offset */
+#define SYS_OSCIN_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0x0
+#define RTC_BY_OSCIN_CTRL0ÂÂÂÂÂÂÂ 0x4
+#define RTC_BY_OSCIN_CTRL1ÂÂÂÂÂÂÂ 0x8
+#define RTC_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xc
+#define SYS_CLK_CTRL0ÂÂÂÂÂÂÂÂÂÂÂ 0x10
+#define AXI_CLK_CTRL0ÂÂÂÂÂÂÂÂÂÂÂ 0x14
+#define SYS_CLK_EN0ÂÂÂÂÂÂÂÂÂÂÂ 0x1c
+#define SYS_CLK_EN1ÂÂÂÂÂÂÂÂÂÂÂ 0x20
+#define AXI_CLK_ENÂÂÂÂÂÂÂÂÂÂÂ 0x24
+#define DSPA_CLK_ENÂÂÂÂÂÂÂÂÂÂÂ 0x28
+#define DSPB_CLK_ENÂÂÂÂÂÂÂÂÂÂÂ 0x2c
+#define DSPA_CLK_CTRL0ÂÂÂÂÂÂÂÂÂÂÂ 0x30
+#define DSPB_CLK_CTRL0ÂÂÂÂÂÂÂÂÂÂÂ 0x34
+#define CLK12_24_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0x38
+#define GEN_CLK_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0x3c
+#define TIMESTAMP_CTRL0ÂÂÂÂÂÂÂÂÂÂÂ 0x40
+#define TIMESTAMP_CTRL1ÂÂÂÂÂÂÂÂÂÂÂ 0x44
+#define TIMESTAMP_CTRL2ÂÂÂÂÂÂÂÂÂÂÂ 0x48
+#define TIMESTAMP_VAL0ÂÂÂÂÂÂÂÂÂÂÂ 0x4c
+#define TIMESTAMP_VAL1ÂÂÂÂÂÂÂÂÂÂÂ 0x50
+#define TIMEBASE_CTRL0ÂÂÂÂÂÂÂÂÂÂÂ 0x54
+#define TIMEBASE_CTRL1ÂÂÂÂÂÂÂÂÂÂÂ 0x58
+#define SAR_ADC_CLK_CTRLÂÂÂÂÂÂÂ 0xc0
+#define PWM_CLK_AB_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xc4
+#define PWM_CLK_CD_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xc8
+#define PWM_CLK_EF_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xcc
+#define SPICC_CLK_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xd0
+#define TS_CLK_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xd4
+#define SPIFC_CLK_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xd8
+#define USB_BUSCLK_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xdc
+#define SD_EMMC_CLK_CTRLÂÂÂÂÂÂÂ 0xe0
+#define CECA_CLK_CTRL0ÂÂÂÂÂÂÂÂÂÂÂ 0xe4
+#define CECA_CLK_CTRL1ÂÂÂÂÂÂÂÂÂÂÂ 0xe8
+#define CECB_CLK_CTRL0ÂÂÂÂÂÂÂÂÂÂÂ 0xec
+#define CECB_CLK_CTRL1ÂÂÂÂÂÂÂÂÂÂÂ 0xf0
+#define PSRAM_CLK_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xf4
+#define DMC_CLK_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0xf8
+#define FCLK_DIV1_SELÂÂÂÂÂÂÂÂÂÂÂ 0xfc
+#define TST_CTRLÂÂÂÂÂÂÂÂÂÂÂ 0x100
+
+#define CLKID_XTAL_CLKTREEÂÂÂÂÂÂÂ 0
+#define CLKID_SYS_A_SELÂÂÂÂÂÂÂÂÂÂÂ 89
+#define CLKID_SYS_A_DIVÂÂÂÂÂÂÂÂÂÂÂ 90
+#define CLKID_SYS_AÂÂÂÂÂÂÂÂÂÂÂ 91
+#define CLKID_SYS_B_SELÂÂÂÂÂÂÂÂÂÂÂ 92
+#define CLKID_SYS_B_DIVÂÂÂÂÂÂÂÂÂÂÂ 93
+#define CLKID_SYS_BÂÂÂÂÂÂÂÂÂÂÂ 94
+#define CLKID_DSPA_A_SELÂÂÂÂÂÂÂ 95
+#define CLKID_DSPA_A_DIVÂÂÂÂÂÂÂ 96
+#define CLKID_DSPA_AÂÂÂÂÂÂÂÂÂÂÂ 97
+#define CLKID_DSPA_B_SELÂÂÂÂÂÂÂ 98
+#define CLKID_DSPA_B_DIVÂÂÂÂÂÂÂ 99
+#define CLKID_DSPA_BÂÂÂÂÂÂÂÂÂÂÂ 100
+#define CLKID_DSPB_A_SELÂÂÂÂÂÂÂ 101
+#define CLKID_DSPB_A_DIVÂÂÂÂÂÂÂ 102
+#define CLKID_DSPB_AÂÂÂÂÂÂÂÂÂÂÂ 103
+#define CLKID_DSPB_B_SELÂÂÂÂÂÂÂ 104
+#define CLKID_DSPB_B_DIVÂÂÂÂÂÂÂ 105
+#define CLKID_DSPB_BÂÂÂÂÂÂÂÂÂÂÂ 106
+#define CLKID_RTC_32K_CLKINÂÂÂÂÂÂÂ 107
+#define CLKID_RTC_32K_DIVÂÂÂÂÂÂÂ 108
+#define CLKID_RTC_32K_XTALÂÂÂÂÂÂÂ 109
+#define CLKID_RTC_32K_SELÂÂÂÂÂÂÂ 110
+#define CLKID_CECB_32K_CLKINÂÂÂÂÂÂÂ 111
+#define CLKID_CECB_32K_DIVÂÂÂÂÂÂÂ 112
+#define CLKID_CECB_32K_SEL_PREÂÂÂÂÂÂÂ 113
+#define CLKID_CECB_32K_SELÂÂÂÂÂÂÂ 114
+#define CLKID_CECA_32K_CLKINÂÂÂÂÂÂÂ 115
+#define CLKID_CECA_32K_DIVÂÂÂÂÂÂÂ 116
+#define CLKID_CECA_32K_SEL_PREÂÂÂÂÂÂÂ 117
+#define CLKID_CECA_32K_SELÂÂÂÂÂÂÂ 118
+#define CLKID_DIV2_PREÂÂÂÂÂÂÂÂÂÂÂ 119
+#define CLKID_24M_DIV2ÂÂÂÂÂÂÂÂÂÂÂ 120
+#define CLKID_GEN_SELÂÂÂÂÂÂÂÂÂÂÂ 121
+#define CLKID_GEN_DIVÂÂÂÂÂÂÂÂÂÂÂ 122
+#define CLKID_SARADC_DIVÂÂÂÂÂÂÂ 123
+#define CLKID_PWM_A_SELÂÂÂÂÂÂÂÂÂÂÂ 124
+#define CLKID_PWM_A_DIVÂÂÂÂÂÂÂÂÂÂÂ 125
+#define CLKID_PWM_B_SELÂÂÂÂÂÂÂÂÂÂÂ 126
+#define CLKID_PWM_B_DIVÂÂÂÂÂÂÂÂÂÂÂ 127
+#define CLKID_PWM_C_SELÂÂÂÂÂÂÂÂÂÂÂ 128
+#define CLKID_PWM_C_DIVÂÂÂÂÂÂÂÂÂÂÂ 129
+#define CLKID_PWM_D_SELÂÂÂÂÂÂÂÂÂÂÂ 130
+#define CLKID_PWM_D_DIVÂÂÂÂÂÂÂÂÂÂÂ 131
+#define CLKID_PWM_E_SELÂÂÂÂÂÂÂÂÂÂÂ 132
+#define CLKID_PWM_E_DIVÂÂÂÂÂÂÂÂÂÂÂ 133
+#define CLKID_PWM_F_SELÂÂÂÂÂÂÂÂÂÂÂ 134
+#define CLKID_PWM_F_DIVÂÂÂÂÂÂÂÂÂÂÂ 135
+#define CLKID_SPICC_SELÂÂÂÂÂÂÂÂÂÂÂ 136
+#define CLKID_SPICC_DIVÂÂÂÂÂÂÂÂÂÂÂ 137
+#define CLKID_SPICC_SEL2ÂÂÂÂÂÂÂ 138
+#define CLKID_TS_DIVÂÂÂÂÂÂÂÂÂÂÂ 139
+#define CLKID_SPIFC_SELÂÂÂÂÂÂÂÂÂÂÂ 140
+#define CLKID_SPIFC_DIVÂÂÂÂÂÂÂÂÂÂÂ 141
+#define CLKID_SPIFC_SEL2ÂÂÂÂÂÂÂ 142
+#define CLKID_USB_BUS_SELÂÂÂÂÂÂÂ 143
+#define CLKID_USB_BUS_DIVÂÂÂÂÂÂÂ 144
+#define CLKID_SD_EMMC_SELÂÂÂÂÂÂÂ 145
+#define CLKID_SD_EMMC_DIVÂÂÂÂÂÂÂ 146
+#define CLKID_SD_EMMC_SEL2ÂÂÂÂÂÂÂ 147
+#define CLKID_PSRAM_SELÂÂÂÂÂÂÂÂÂÂÂ 148
+#define CLKID_PSRAM_DIVÂÂÂÂÂÂÂÂÂÂÂ 149
+#define CLKID_PSRAM_SEL2ÂÂÂÂÂÂÂ 150
+#define CLKID_DMC_SELÂÂÂÂÂÂÂÂÂÂÂ 151
+#define CLKID_DMC_DIVÂÂÂÂÂÂÂÂÂÂÂ 152
+#define CLKID_DMC_SEL2ÂÂÂÂÂÂÂÂÂÂÂ 153
+#define NR_CLKSÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ 154
+
+#include <dt-bindings/clock/a1-clkc.h>
+
+#endif /* __A1_H */

.


.


.