Dne torek, 26. marec 2024 ob 12:47:39 CET je Andre Przywara napisal(a): > From: Brandon Cheo Fusi <fusibrandon13@xxxxxxxxx> > > Make converting the speed bin value into a speed grade generic and > determined by a platform specific callback. Also change the prototypes > involved to encode the speed bin directly in the return value. > > This allows to extend the driver more easily to support more SoCs. > > Signed-off-by: Brandon Cheo Fusi <fusibrandon13@xxxxxxxxx> > [Andre: merge output into return value] > Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> > --- > drivers/cpufreq/sun50i-cpufreq-nvmem.c | 74 +++++++++++++++++--------- > 1 file changed, 49 insertions(+), 25 deletions(-) > > diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c > index 32a9c88f8ff6d..7b44f3b13e7d2 100644 > --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c > +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c > @@ -25,19 +25,52 @@ > > static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev; > > +struct sunxi_cpufreq_data { > + u32 (*efuse_xlate)(u32 speedbin); > +}; > + > +static u32 sun50i_h6_efuse_xlate(u32 speedbin) > +{ > + u32 efuse_value; > + > + efuse_value = (speedbin >> NVMEM_SHIFT) & NVMEM_MASK; > + > + /* > + * We treat unexpected efuse values as if the SoC was from > + * the slowest bin. Expected efuse values are 1-3, slowest > + * to fastest. > + */ > + if (efuse_value >= 1 && efuse_value <= 3) > + return efuse_value - 1; > + else > + return 0; > +} > + > +static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = { > + .efuse_xlate = sun50i_h6_efuse_xlate, > +}; > + > +static const struct of_device_id cpu_opp_match_list[] = { > + { .compatible = "allwinner,sun50i-h6-operating-points", > + .data = &sun50i_h6_cpufreq_data, > + }, > + {} > +}; > + > /** > * sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value > - * @versions: Set to the value parsed from efuse > * > - * Returns 0 if success. > + * Returns non-negative speed bin index on success, a negative error > + * value otherwise. > */ > -static int sun50i_cpufreq_get_efuse(u32 *versions) > +static int sun50i_cpufreq_get_efuse(void) > { > struct nvmem_cell *speedbin_nvmem; > struct device_node *np; > struct device *cpu_dev; > - u32 *speedbin, efuse_value; > - size_t len; > + const struct of_device_id *match; > + const struct sunxi_cpufreq_data *opp_data; > + u32 *speedbin; nit: reverse christmas tree Other than that, Reviewed-by: Jernej Skrabec <jernej.skrabec@xxxxxxxxx> Best regards, Jernej > int ret; > > cpu_dev = get_cpu_device(0); > @@ -48,12 +81,12 @@ static int sun50i_cpufreq_get_efuse(u32 *versions) > if (!np) > return -ENOENT; > > - ret = of_device_is_compatible(np, > - "allwinner,sun50i-h6-operating-points"); > - if (!ret) { > + match = of_match_node(cpu_opp_match_list, np); > + if (!match) { > of_node_put(np); > return -ENOENT; > } > + opp_data = match->data; > > speedbin_nvmem = of_nvmem_cell_get(np, NULL); > of_node_put(np); > @@ -61,25 +94,16 @@ static int sun50i_cpufreq_get_efuse(u32 *versions) > return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem), > "Could not get nvmem cell\n"); > > - speedbin = nvmem_cell_read(speedbin_nvmem, &len); > + speedbin = nvmem_cell_read(speedbin_nvmem, NULL); > nvmem_cell_put(speedbin_nvmem); > if (IS_ERR(speedbin)) > return PTR_ERR(speedbin); > > - efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK; > - > - /* > - * We treat unexpected efuse values as if the SoC was from > - * the slowest bin. Expected efuse values are 1-3, slowest > - * to fastest. > - */ > - if (efuse_value >= 1 && efuse_value <= 3) > - *versions = efuse_value - 1; > - else > - *versions = 0; > + ret = opp_data->efuse_xlate(*speedbin); > > kfree(speedbin); > - return 0; > + > + return ret; > }; > > static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) > @@ -87,7 +111,7 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) > int *opp_tokens; > char name[MAX_NAME_LEN]; > unsigned int cpu; > - u32 speed = 0; > + int speed; > int ret; > > opp_tokens = kcalloc(num_possible_cpus(), sizeof(*opp_tokens), > @@ -95,10 +119,10 @@ static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) > if (!opp_tokens) > return -ENOMEM; > > - ret = sun50i_cpufreq_get_efuse(&speed); > - if (ret) { > + speed = sun50i_cpufreq_get_efuse(); > + if (speed < 0) { > kfree(opp_tokens); > - return ret; > + return speed; > } > > snprintf(name, MAX_NAME_LEN, "speed%d", speed); >