diff --git a/bsp/rockchip/dm/clk/clk-rk-gate.h b/bsp/rockchip/dm/clk/clk-rk-gate.h index 4683218a7d..c4d91072ad 100755 --- a/bsp/rockchip/dm/clk/clk-rk-gate.h +++ b/bsp/rockchip/dm/clk/clk-rk-gate.h @@ -27,6 +27,20 @@ .gate_flags = gf, \ } +#define GATE_NO_SET_RATE(_id, cname, pname, f, o, b, gf) \ +(void *)&(struct rockchip_clk_cell) \ +{ \ + .cell.name = cname, \ + .cell.ops = &rockchip_gate_clk_ops, \ + .cell.parent_name = pname, \ + .cell.parents_nr = 1, \ + .cell.flags = f | RT_CLK_F_SET_RATE_PARENT, \ + .id = _id, \ + .gate_offset = o, \ + .gate_shift = b, \ + .gate_flags = gf, \ +} + extern const struct rt_clk_ops rockchip_gate_clk_ops; #endif /* __CLK_RK_GATE_H__ */ diff --git a/bsp/rockchip/dm/clk/clk-rk-half-divider.h b/bsp/rockchip/dm/clk/clk-rk-half-divider.h index 2f801867e2..088bf50611 100755 --- a/bsp/rockchip/dm/clk/clk-rk-half-divider.h +++ b/bsp/rockchip/dm/clk/clk-rk-half-divider.h @@ -63,7 +63,7 @@ struct rockchip_half_divider_clk_cell .rk_cell.init = rockchip_half_divider_clk_cell_init,\ } -#define COMPOSITE_NOGATE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df) \ +#define COMPOSITE_NOGATE_HALFDIV(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw, df) \ (void *)&(struct rockchip_half_divider_clk_cell) \ { \ .rk_cell.cell.name = cname, \ @@ -82,7 +82,8 @@ struct rockchip_half_divider_clk_cell .rk_cell.init = rockchip_half_divider_clk_cell_init,\ } -#define COMPOSITE_NOMUX_HALFDIV(_id, cname, pname, f, mo, ds, dw, df, go, gs, gf) \ +#define COMPOSITE_NOMUX_HALFDIV(_id, cname, pname, f, mo, ds, dw, df, go, gs, gf) \ +(void *)&(struct rockchip_half_divider_clk_cell) \ { \ .rk_cell.cell.name = cname, \ .rk_cell.cell.parent_name = pname, \ diff --git a/components/drivers/clk/clk-scmi.c b/components/drivers/clk/clk-scmi.c index d6240fa406..038c702589 100755 --- a/components/drivers/clk/clk-scmi.c +++ b/components/drivers/clk/clk-scmi.c @@ -230,7 +230,7 @@ static rt_err_t scmi_clk_probe(struct rt_scmi_device *sdev) for (int id = 0; id < cell_count; ++id) { const char *clk_name; - rt_uint32_t flags, rates_nr, rate_discrete; + rt_uint32_t flags, rate_discrete; in.id = rt_cpu_to_le32(id); in.rate_index = rt_cpu_to_le32(0); @@ -242,7 +242,6 @@ static rt_err_t scmi_clk_probe(struct rt_scmi_device *sdev) } flags = rt_le32_to_cpu(out->num_rates_flags); - rates_nr = SCMI_NUM_REMAINING(flags); rate_discrete = SCMI_RATE_DISCRETE(flags); if (rate_discrete) @@ -263,12 +262,40 @@ static rt_err_t scmi_clk_probe(struct rt_scmi_device *sdev) if (rate_discrete) { - for (int i = 0; i < rates_nr; ++i) + /* + * SCMI: [11:0] = rates in this message, [31:16] = remaining to query. + * Using REMAINING as the copy count overflows rates[] and corrupts heap. + */ + int idx = 0; + + for (;;) { - clk_data->info.list.rates[i] = SCMI_RATE_TO_U64(out->rate[i]); + rt_uint32_t nr = SCMI_NUM_RETURNED(flags); + rt_uint32_t remaining = SCMI_NUM_REMAINING(flags); + + for (rt_uint32_t i = 0; i < nr && idx < SCMI_MAX_NUM_RATES; ++i, ++idx) + { + clk_data->info.list.rates[idx] = SCMI_RATE_TO_U64(out->rate[i]); + } + + if (remaining == 0 || idx >= SCMI_MAX_NUM_RATES) + { + break; + } + + in.rate_index = rt_cpu_to_le32(idx); + msg = RT_SCMI_MSG_RAW(SCMI_CLOCK_DESCRIBE_RATES, &in, sizeof(in), out, out_size); + + if ((err = rt_scmi_process_msg(sclk->sdev, &msg))) + { + rt_free(clk_data); + goto _fail; + } + + flags = rt_le32_to_cpu(out->num_rates_flags); } - clk_data->info.list.rates_nr = rates_nr; + clk_data->info.list.rates_nr = idx; } else {