2023-10-01 04:34:17

by Peng Fan (OSS)

[permalink] [raw]
Subject: [PATCH v3 0/2] firmware: arm_scmi: clock: support parents commands

V2:
Add determine_rate hooks

SCMI v3.2 spec adds parents commands, this patchset is to support them:
CLOCK_POSSIBLE_PARENTS_GET
CLOCK_PARENT_SET
CLOCK_PARENT_GET

Besides firmware api clock driver update, the clk_scmi driver also
updated to support set_parent and get_parent ops.

Signed-off-by: Peng Fan <[email protected]>
---
Changes in v3:
Address Cristian's comments:
- Drop SCMI_MAX_NUM_PARENTS, alloc memory dynamically
- Check clk_id, parent_id
- Add comment for parent_get/set
- Link to v2: https://lore.kernel.org/r/[email protected]

---
Peng Fan (2):
firmware: arm_scmi: clock: support clock parents
clk: scmi: add set/get_parent support

drivers/clk/clk-scmi.c | 50 ++++++++++-
drivers/firmware/arm_scmi/clock.c | 182 ++++++++++++++++++++++++++++++++++++--
include/linux/scmi_protocol.h | 6 ++
3 files changed, 231 insertions(+), 7 deletions(-)
---
base-commit: 8fff9184d1b5810dca5dd1a02726d4f844af88fc
change-id: 20230925-scmi-clock-v2-042cf8e5cb77

Best regards,
--
Peng Fan <[email protected]>


2023-10-01 07:41:03

by Peng Fan (OSS)

[permalink] [raw]
Subject: [PATCH v3 1/2] firmware: arm_scmi: clock: support clock parents

From: Peng Fan <[email protected]>

SCMI v3.2 spec introduces CLOCK_POSSIBLE_PARENTS_GET, CLOCK_PARENT_SET
and CLOCK_PARENT_GET. This patch is to add the upper three new
commands.

Signed-off-by: Peng Fan <[email protected]>
---
drivers/firmware/arm_scmi/clock.c | 182 ++++++++++++++++++++++++++++++++++++--
include/linux/scmi_protocol.h | 6 ++
2 files changed, 182 insertions(+), 6 deletions(-)

diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index d18bf789fc24..9b95239d63ae 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -22,6 +22,9 @@ enum scmi_clock_protocol_cmd {
CLOCK_RATE_NOTIFY = 0x9,
CLOCK_RATE_CHANGE_REQUESTED_NOTIFY = 0xA,
CLOCK_CONFIG_GET = 0xB,
+ CLOCK_POSSIBLE_PARENTS_GET = 0xC,
+ CLOCK_PARENT_SET = 0xD,
+ CLOCK_PARENT_GET = 0xE,
};

enum clk_state {
@@ -42,10 +45,28 @@ struct scmi_msg_resp_clock_attributes {
#define SUPPORTS_RATE_CHANGED_NOTIF(x) ((x) & BIT(31))
#define SUPPORTS_RATE_CHANGE_REQUESTED_NOTIF(x) ((x) & BIT(30))
#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(29))
+#define SUPPORTS_PARENT_CLOCK(x) ((x) & BIT(28))
u8 name[SCMI_SHORT_NAME_MAX_SIZE];
__le32 clock_enable_latency;
};

+struct scmi_msg_clock_possible_parents {
+ __le32 id;
+ __le32 skip_parents;
+};
+
+struct scmi_msg_resp_clock_possible_parents {
+ __le32 num_parent_flags;
+#define NUM_PARENTS_RETURNED(x) ((x) & 0xff)
+#define NUM_PARENTS_REMAINING(x) ((x) >> 24)
+ u32 possible_parents[];
+};
+
+struct scmi_msg_clock_set_parent {
+ __le32 id;
+ __le32 parent_id;
+};
+
struct scmi_msg_clock_config_set_v2 {
__le32 id;
__le32 attributes;
@@ -167,6 +188,99 @@ scmi_clock_protocol_attributes_get(const struct scmi_protocol_handle *ph,
return ret;
}

+struct scmi_clk_ipriv {
+ struct device *dev;
+ u32 clk_id;
+ struct scmi_clock_info *clk;
+};
+
+static void iter_clk_possible_parents_prepare_message(void *message, unsigned int desc_index,
+ const void *priv)
+{
+ struct scmi_msg_clock_possible_parents *msg = message;
+ const struct scmi_clk_ipriv *p = priv;
+
+ msg->id = cpu_to_le32(p->clk_id);
+ /* Set the number of OPPs to be skipped/already read */
+ msg->skip_parents = cpu_to_le32(desc_index);
+}
+
+static int iter_clk_possible_parents_update_state(struct scmi_iterator_state *st,
+ const void *response, void *priv)
+{
+ const struct scmi_msg_resp_clock_possible_parents *r = response;
+ struct scmi_clk_ipriv *p = priv;
+ struct device *dev = ((struct scmi_clk_ipriv *)p)->dev;
+ u32 flags;
+
+ flags = le32_to_cpu(r->num_parent_flags);
+ st->num_returned = NUM_PARENTS_RETURNED(flags);
+ st->num_remaining = NUM_PARENTS_REMAINING(flags);
+
+ /*
+ * num parents is not declared previously anywhere so we
+ * assume it's returned+remaining on first call.
+ */
+ if (!st->max_resources) {
+ p->clk->num_parents = st->num_returned + st->num_remaining;
+ p->clk->parents = devm_kcalloc(dev, p->clk->num_parents,
+ sizeof(*p->clk->parents),
+ GFP_KERNEL);
+ if (!p->clk->parents) {
+ p->clk->num_parents = 0;
+ return -ENOMEM;
+ }
+
+ st->max_resources = st->num_returned + st->num_remaining;
+ };
+
+ return 0;
+}
+
+static int iter_clk_possible_parents_process_response(const struct scmi_protocol_handle *ph,
+ const void *response,
+ struct scmi_iterator_state *st,
+ void *priv)
+{
+ const struct scmi_msg_resp_clock_possible_parents *r = response;
+ struct scmi_clk_ipriv *p = priv;
+
+ u32 *parent = &p->clk->parents[st->desc_index + st->loop_idx];
+
+ *parent = le32_to_cpu(r->possible_parents[st->loop_idx]);
+
+ return 0;
+}
+
+static int scmi_clock_possible_parents(const struct scmi_protocol_handle *ph, u32 clk_id,
+ struct scmi_clock_info *clk)
+{
+ struct scmi_iterator_ops ops = {
+ .prepare_message = iter_clk_possible_parents_prepare_message,
+ .update_state = iter_clk_possible_parents_update_state,
+ .process_response = iter_clk_possible_parents_process_response,
+ };
+
+ struct scmi_clk_ipriv ppriv = {
+ .clk_id = clk_id,
+ .clk = clk,
+ .dev = ph->dev,
+ };
+ void *iter;
+ int ret;
+
+ iter = ph->hops->iter_response_init(ph, &ops, 0,
+ CLOCK_POSSIBLE_PARENTS_GET,
+ sizeof(struct scmi_msg_clock_possible_parents),
+ &ppriv);
+ if (IS_ERR(iter))
+ return PTR_ERR(iter);
+
+ ret = ph->hops->iter_response_run(iter);
+
+ return ret;
+}
+
static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
u32 clk_id, struct scmi_clock_info *clk,
u32 version)
@@ -211,6 +325,8 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
clk->rate_changed_notifications = true;
if (SUPPORTS_RATE_CHANGE_REQUESTED_NOTIF(attributes))
clk->rate_change_requested_notifications = true;
+ if (SUPPORTS_PARENT_CLOCK(attributes))
+ scmi_clock_possible_parents(ph, clk_id, clk);
}

return ret;
@@ -228,12 +344,6 @@ static int rate_cmp_func(const void *_r1, const void *_r2)
return 1;
}

-struct scmi_clk_ipriv {
- struct device *dev;
- u32 clk_id;
- struct scmi_clock_info *clk;
-};
-
static void iter_clk_describe_prepare_message(void *message,
const unsigned int desc_index,
const void *priv)
@@ -457,6 +567,64 @@ scmi_clock_config_set_v2(const struct scmi_protocol_handle *ph, u32 clk_id,
return ret;
}

+static int
+scmi_clock_set_parent(const struct scmi_protocol_handle *ph, u32 clk_id,
+ u32 parent_id)
+{
+ int ret;
+ struct scmi_xfer *t;
+ struct scmi_msg_clock_set_parent *cfg;
+ struct clock_info *ci = ph->get_priv(ph);
+ struct scmi_clock_info *clk;
+
+ if (clk_id >= ci->num_clocks)
+ return -EINVAL;
+
+ clk = ci->clk + clk_id;
+
+ if (parent_id >= clk->num_parents)
+ return -EINVAL;
+
+ ret = ph->xops->xfer_get_init(ph, CLOCK_PARENT_SET,
+ sizeof(*cfg), 0, &t);
+ if (ret)
+ return ret;
+
+ t->hdr.poll_completion = false;
+
+ cfg = t->tx.buf;
+ cfg->id = cpu_to_le32(clk_id);
+ cfg->parent_id = cpu_to_le32(clk->parents[parent_id]);
+
+ ret = ph->xops->do_xfer(ph, t);
+
+ ph->xops->xfer_put(ph, t);
+
+ return ret;
+}
+
+static int
+scmi_clock_get_parent(const struct scmi_protocol_handle *ph, u32 clk_id,
+ u32 *parent_id)
+{
+ int ret;
+ struct scmi_xfer *t;
+
+ ret = ph->xops->xfer_get_init(ph, CLOCK_PARENT_GET,
+ sizeof(__le32), sizeof(u32), &t);
+ if (ret)
+ return ret;
+
+ put_unaligned_le32(clk_id, t->tx.buf);
+
+ ret = ph->xops->do_xfer(ph, t);
+ if (!ret)
+ *parent_id = get_unaligned_le32(t->rx.buf);
+
+ ph->xops->xfer_put(ph, t);
+ return ret;
+}
+
static int
scmi_clock_config_set_v21(const struct scmi_protocol_handle *ph, u32 clk_id,
enum clk_state state, u8 oem_type, u32 oem_val,
@@ -647,6 +815,8 @@ static const struct scmi_clk_proto_ops clk_proto_ops = {
.state_get = scmi_clock_state_get,
.config_oem_get = scmi_clock_config_oem_get,
.config_oem_set = scmi_clock_config_oem_set,
+ .parent_set = scmi_clock_set_parent,
+ .parent_get = scmi_clock_get_parent,
};

static int scmi_clk_rate_notify(const struct scmi_protocol_handle *ph,
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 27bfa5a65b45..f2f05fb42d28 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -58,6 +58,8 @@ struct scmi_clock_info {
u64 step_size;
} range;
};
+ int num_parents;
+ u32 *parents;
};

enum scmi_power_scale {
@@ -83,6 +85,8 @@ struct scmi_protocol_handle;
* @state_get: get the status of the specified clock
* @config_oem_get: get the value of an OEM specific clock config
* @config_oem_set: set the value of an OEM specific clock config
+ * @parent_get: get the parent id of a clk
+ * @parent_set: set the parent of a clock
*/
struct scmi_clk_proto_ops {
int (*count_get)(const struct scmi_protocol_handle *ph);
@@ -104,6 +108,8 @@ struct scmi_clk_proto_ops {
bool atomic);
int (*config_oem_set)(const struct scmi_protocol_handle *ph, u32 clk_id,
u8 oem_type, u32 oem_val, bool atomic);
+ int (*parent_get)(const struct scmi_protocol_handle *ph, u32 clk_id, u32 *parent_id);
+ int (*parent_set)(const struct scmi_protocol_handle *ph, u32 clk_id, u32 parent_id);
};

struct scmi_perf_domain_info {

--
2.37.1

2023-10-01 10:57:05

by Peng Fan (OSS)

[permalink] [raw]
Subject: [PATCH v3 2/2] clk: scmi: add set/get_parent support

From: Peng Fan <[email protected]>

SCMI v3.2 adds set/get parent clock commands, so update the clk driver
to support them.

Signed-off-by: Peng Fan <[email protected]>
---
drivers/clk/clk-scmi.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index 2e1337b511eb..5aaca674830f 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -24,6 +24,7 @@ struct scmi_clk {
struct clk_hw hw;
const struct scmi_clock_info *info;
const struct scmi_protocol_handle *ph;
+ struct clk_parent_data *parent_data;
};

#define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
@@ -78,6 +79,35 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
}

+static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+
+ return scmi_proto_clk_ops->parent_set(clk->ph, clk->id, parent_index);
+}
+
+static u8 scmi_clk_get_parent(struct clk_hw *hw)
+{
+ struct scmi_clk *clk = to_scmi_clk(hw);
+ u32 parent_id;
+ int ret;
+
+ ret = scmi_proto_clk_ops->parent_get(clk->ph, clk->id, &parent_id);
+ if (ret)
+ return 0;
+
+ return parent_id;
+}
+
+static int scmi_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+ /*
+ * Suppose all the requested rates are supported, and let firmware
+ * to handle the left work.
+ */
+ return 0;
+}
+
static int scmi_clk_enable(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
@@ -139,6 +169,9 @@ static const struct clk_ops scmi_clk_ops = {
.set_rate = scmi_clk_set_rate,
.prepare = scmi_clk_enable,
.unprepare = scmi_clk_disable,
+ .set_parent = scmi_clk_set_parent,
+ .get_parent = scmi_clk_get_parent,
+ .determine_rate = scmi_clk_determine_rate,
};

static const struct clk_ops scmi_atomic_clk_ops = {
@@ -148,6 +181,9 @@ static const struct clk_ops scmi_atomic_clk_ops = {
.enable = scmi_clk_atomic_enable,
.disable = scmi_clk_atomic_disable,
.is_enabled = scmi_clk_atomic_is_enabled,
+ .set_parent = scmi_clk_set_parent,
+ .get_parent = scmi_clk_get_parent,
+ .determine_rate = scmi_clk_determine_rate,
};

static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,
@@ -158,9 +194,10 @@ static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk,

struct clk_init_data init = {
.flags = CLK_GET_RATE_NOCACHE,
- .num_parents = 0,
+ .num_parents = sclk->info->num_parents,
.ops = scmi_ops,
.name = sclk->info->name,
+ .parent_data = sclk->parent_data,
};

sclk->hw.init = &init;
@@ -250,6 +287,17 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
else
scmi_ops = &scmi_clk_ops;

+ /* Initialize clock parent data. */
+ if (sclk->info->num_parents > 0) {
+ sclk->parent_data = devm_kcalloc(dev, sclk->info->num_parents,
+ sizeof(*sclk->parent_data), GFP_KERNEL);
+
+ for (int i = 0; i < sclk->info->num_parents; i++) {
+ sclk->parent_data[i].index = sclk->info->parents[i];
+ sclk->parent_data[i].hw = hws[sclk->info->parents[i]];
+ }
+ }
+
err = scmi_clk_ops_init(dev, sclk, scmi_ops);
if (err) {
dev_err(dev, "failed to register clock %d\n", idx);

--
2.37.1

2023-10-02 16:41:07

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v3 2/2] clk: scmi: add set/get_parent support

Hi Stephen,

On Sun, Oct 01, 2023 at 12:38:44PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <[email protected]>
>
> SCMI v3.2 adds set/get parent clock commands, so update the clk driver
> to support them.
>

The SCMI changes look good. If you are happy with this driver change, please
Ack so that I can take it along with the SCMI changes. There are other patches
clk driver patches that you have already acked in my branch, hence the need to
route it via SCMI tree.

--
Regards,
Sudeep

2023-10-02 17:21:08

by Cristian Marussi

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] firmware: arm_scmi: clock: support clock parents

On Sun, Oct 01, 2023 at 12:38:43PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <[email protected]>
>
> SCMI v3.2 spec introduces CLOCK_POSSIBLE_PARENTS_GET, CLOCK_PARENT_SET
> and CLOCK_PARENT_GET. This patch is to add the upper three new
> commands.
>

Hi,

I tested this on some emulated setup and it works fine, can see well
formed SCMI messages going back and forth.

Reviewed-by: Cristian Marussi <[email protected]>

Thanks,
Cristian

2023-10-02 17:27:11

by Cristian Marussi

[permalink] [raw]
Subject: Re: [PATCH v3 0/2] firmware: arm_scmi: clock: support parents commands

On Sun, Oct 01, 2023 at 12:38:42PM +0800, Peng Fan (OSS) wrote:
> V2:
> Add determine_rate hooks
>
> SCMI v3.2 spec adds parents commands, this patchset is to support them:
> CLOCK_POSSIBLE_PARENTS_GET
> CLOCK_PARENT_SET
> CLOCK_PARENT_GET
>

Hi Peng,

thanks for your update.

The SCMI part looks good to me but I'll made a few notes on clk-scmi
driver

Thanks,
Cristian

2023-10-02 18:07:33

by Cristian Marussi

[permalink] [raw]
Subject: Re: [PATCH v3 2/2] clk: scmi: add set/get_parent support

On Sun, Oct 01, 2023 at 12:38:44PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <[email protected]>
>
> SCMI v3.2 adds set/get parent clock commands, so update the clk driver
> to support them.
>

Hi,

a few notes down below.

> Signed-off-by: Peng Fan <[email protected]>
> ---
> drivers/clk/clk-scmi.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 49 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
> index 2e1337b511eb..5aaca674830f 100644
> --- a/drivers/clk/clk-scmi.c
> +++ b/drivers/clk/clk-scmi.c
> @@ -24,6 +24,7 @@ struct scmi_clk {
> struct clk_hw hw;
> const struct scmi_clock_info *info;
> const struct scmi_protocol_handle *ph;
> + struct clk_parent_data *parent_data;
> };
>
> #define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw)
> @@ -78,6 +79,35 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
> }
>
> +static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
> +{
> + struct scmi_clk *clk = to_scmi_clk(hw);
> +
> + return scmi_proto_clk_ops->parent_set(clk->ph, clk->id, parent_index);
> +}
> +
> +static u8 scmi_clk_get_parent(struct clk_hw *hw)
> +{
> + struct scmi_clk *clk = to_scmi_clk(hw);
> + u32 parent_id;
> + int ret;
> +
> + ret = scmi_proto_clk_ops->parent_get(clk->ph, clk->id, &parent_id);
> + if (ret)
> + return 0;
> +
> + return parent_id;
> +}
> +

While testing using CLK Debugfs with CLOCK_ALLOW_WRITE_DEBUGFS 1 I
noticed that I can correctly change the clk_parent and then read back the
clk_possible_parents, BUT if I read clk_parent right after boot (OR
after loading the clk-scmi module) I cannot get back any value from debugfs
even though I can see the correct SCMI messages being exchanged from the
traces.

My guess was that, while scmi_clk_set_parent is invoked by the CLK core
with a parent_index that has been remapped by the core to the SCMI clock
domain ID, this is not done by scmi_clk_get_parent() so you are
returning to the clock framework as parent_id the raw SCMI clock domain
id as returned by the platform instead of the clk parent id used by the
core.

This does not happen after you issue at first a reparent because in that
case on the following read of clk_parent the CLK framework returns the last
value you have set that it had cached previously.

This fixes for me the issue:

---8<----

diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index 5aaca674830f..fd47232d4021 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -89,14 +89,21 @@ static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
static u8 scmi_clk_get_parent(struct clk_hw *hw)
{
struct scmi_clk *clk = to_scmi_clk(hw);
- u32 parent_id;
+ u32 parent_id, p_idx;
int ret;

ret = scmi_proto_clk_ops->parent_get(clk->ph, clk->id, &parent_id);
if (ret)
return 0;

- return parent_id;
+ for (p_idx = 0; p_idx < clk->info->num_parents; p_idx++)
+ if (clk->parent_data[p_idx].index == parent_id)
+ break;
+
+ if (p_idx == clk->info->num_parents)
+ return 0;
+
+ return p_idx;
}

----8<-----

Not sure if there is a clever way to do it.

Aside from this, another inherent issue is that you cannot really return
an error from .get_parent() so if the SCMI get_parent ops should fail
(ex. timeout) you return 0... (and me too in the above fix) but this is due
to the CLK framework callback definition itself.

Thanks,
Cristian

2023-10-02 19:06:48

by Sudeep Holla

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] firmware: arm_scmi: clock: support clock parents

On Sun, Oct 01, 2023 at 12:38:43PM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <[email protected]>
>
> SCMI v3.2 spec introduces CLOCK_POSSIBLE_PARENTS_GET, CLOCK_PARENT_SET
> and CLOCK_PARENT_GET. This patch is to add the upper three new
> commands.
>

Looks good to me as well. Please rebase this on [1] when you address
Cristian's comment and post v4. I will queue once Stephen is fine with
clk driver changes.

--
Regards,
Sudeep

[1] https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=for-next/scmi/updates

2023-10-03 09:46:16

by Peng Fan

[permalink] [raw]
Subject: RE: [PATCH v3 2/2] clk: scmi: add set/get_parent support

Hi Cristian,

> Subject: Re: [PATCH v3 2/2] clk: scmi: add set/get_parent support
>
> On Sun, Oct 01, 2023 at 12:38:44PM +0800, Peng Fan (OSS) wrote:
> > From: Peng Fan <[email protected]>
> >
> > SCMI v3.2 adds set/get parent clock commands, so update the clk driver
> > to support them.
> >
>
> Hi,
>
> a few notes down below.
>
> > Signed-off-by: Peng Fan <[email protected]>
> > ---
> > drivers/clk/clk-scmi.c | 50
> > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > 1 file changed, 49 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index
> > 2e1337b511eb..5aaca674830f 100644
> > --- a/drivers/clk/clk-scmi.c
> > +++ b/drivers/clk/clk-scmi.c
> > @@ -24,6 +24,7 @@ struct scmi_clk {
> > struct clk_hw hw;
> > const struct scmi_clock_info *info;
> > const struct scmi_protocol_handle *ph;
> > + struct clk_parent_data *parent_data;
> > };
> >
> > #define to_scmi_clk(clk) container_of(clk, struct scmi_clk, hw) @@
> > -78,6 +79,35 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned
> long rate,
> > return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate); }
> >
> > +static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index) {
> > + struct scmi_clk *clk = to_scmi_clk(hw);
> > +
> > + return scmi_proto_clk_ops->parent_set(clk->ph, clk->id,
> > +parent_index); }
> > +
> > +static u8 scmi_clk_get_parent(struct clk_hw *hw) {
> > + struct scmi_clk *clk = to_scmi_clk(hw);
> > + u32 parent_id;
> > + int ret;
> > +
> > + ret = scmi_proto_clk_ops->parent_get(clk->ph, clk->id, &parent_id);
> > + if (ret)
> > + return 0;
> > +
> > + return parent_id;
> > +}
> > +
>
> While testing using CLK Debugfs with CLOCK_ALLOW_WRITE_DEBUGFS 1 I
> noticed that I can correctly change the clk_parent and then read back the
> clk_possible_parents, BUT if I read clk_parent right after boot (OR after
> loading the clk-scmi module) I cannot get back any value from debugfs even
> though I can see the correct SCMI messages being exchanged from the traces.
>
> My guess was that, while scmi_clk_set_parent is invoked by the CLK core with
> a parent_index that has been remapped by the core to the SCMI clock
> domain ID, this is not done by scmi_clk_get_parent() so you are returning to
> the clock framework as parent_id the raw SCMI clock domain id as returned
> by the platform instead of the clk parent id used by the core.
>
> This does not happen after you issue at first a reparent because in that case
> on the following read of clk_parent the CLK framework returns the last value
> you have set that it had cached previously.
>
> This fixes for me the issue:
>
> ---8<----
>
> diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c index
> 5aaca674830f..fd47232d4021 100644
> --- a/drivers/clk/clk-scmi.c
> +++ b/drivers/clk/clk-scmi.c
> @@ -89,14 +89,21 @@ static int scmi_clk_set_parent(struct clk_hw *hw, u8
> parent_index) static u8 scmi_clk_get_parent(struct clk_hw *hw) {
> struct scmi_clk *clk = to_scmi_clk(hw);
> - u32 parent_id;
> + u32 parent_id, p_idx;
> int ret;
>
> ret = scmi_proto_clk_ops->parent_get(clk->ph, clk->id, &parent_id);
> if (ret)
> return 0;
>
> - return parent_id;
> + for (p_idx = 0; p_idx < clk->info->num_parents; p_idx++)
> + if (clk->parent_data[p_idx].index == parent_id)
> + break;
> +
> + if (p_idx == clk->info->num_parents)
> + return 0;
> +
> + return p_idx;
> }
>


You are right. Thanks for doing the fix.

> ----8<-----
>
> Not sure if there is a clever way to do it.
>
> Aside from this, another inherent issue is that you cannot really return an
> error from .get_parent() so if the SCMI get_parent ops should fail (ex. timeout)
> you return 0... (and me too in the above fix) but this is due to the CLK
> framework callback definition itself.

Yes. Right. I will include your fix and do a test, then out v4, should be soon.

Thanks,
Peng.

>
> Thanks,
> Cristian