Skip to content

Commit 6cc4bcc

Browse files
cheofusivireshk
authored andcommitted
cpufreq: sun50i: Refactor speed bin decoding
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 <[email protected]> [Andre: merge output into return value] Signed-off-by: Andre Przywara <[email protected]> Reviewed-by: Jernej Skrabec <[email protected]> Signed-off-by: Viresh Kumar <[email protected]>
1 parent 83d4e04 commit 6cc4bcc

File tree

1 file changed

+49
-25
lines changed

1 file changed

+49
-25
lines changed

drivers/cpufreq/sun50i-cpufreq-nvmem.c

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,52 @@
2525

2626
static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev;
2727

28+
struct sunxi_cpufreq_data {
29+
u32 (*efuse_xlate)(u32 speedbin);
30+
};
31+
32+
static u32 sun50i_h6_efuse_xlate(u32 speedbin)
33+
{
34+
u32 efuse_value;
35+
36+
efuse_value = (speedbin >> NVMEM_SHIFT) & NVMEM_MASK;
37+
38+
/*
39+
* We treat unexpected efuse values as if the SoC was from
40+
* the slowest bin. Expected efuse values are 1-3, slowest
41+
* to fastest.
42+
*/
43+
if (efuse_value >= 1 && efuse_value <= 3)
44+
return efuse_value - 1;
45+
else
46+
return 0;
47+
}
48+
49+
static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = {
50+
.efuse_xlate = sun50i_h6_efuse_xlate,
51+
};
52+
53+
static const struct of_device_id cpu_opp_match_list[] = {
54+
{ .compatible = "allwinner,sun50i-h6-operating-points",
55+
.data = &sun50i_h6_cpufreq_data,
56+
},
57+
{}
58+
};
59+
2860
/**
2961
* sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value
30-
* @versions: Set to the value parsed from efuse
3162
*
32-
* Returns 0 if success.
63+
* Returns non-negative speed bin index on success, a negative error
64+
* value otherwise.
3365
*/
34-
static int sun50i_cpufreq_get_efuse(u32 *versions)
66+
static int sun50i_cpufreq_get_efuse(void)
3567
{
68+
const struct sunxi_cpufreq_data *opp_data;
3669
struct nvmem_cell *speedbin_nvmem;
70+
const struct of_device_id *match;
3771
struct device_node *np;
3872
struct device *cpu_dev;
39-
u32 *speedbin, efuse_value;
40-
size_t len;
73+
u32 *speedbin;
4174
int ret;
4275

4376
cpu_dev = get_cpu_device(0);
@@ -48,57 +81,48 @@ static int sun50i_cpufreq_get_efuse(u32 *versions)
4881
if (!np)
4982
return -ENOENT;
5083

51-
ret = of_device_is_compatible(np,
52-
"allwinner,sun50i-h6-operating-points");
53-
if (!ret) {
84+
match = of_match_node(cpu_opp_match_list, np);
85+
if (!match) {
5486
of_node_put(np);
5587
return -ENOENT;
5688
}
89+
opp_data = match->data;
5790

5891
speedbin_nvmem = of_nvmem_cell_get(np, NULL);
5992
of_node_put(np);
6093
if (IS_ERR(speedbin_nvmem))
6194
return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
6295
"Could not get nvmem cell\n");
6396

64-
speedbin = nvmem_cell_read(speedbin_nvmem, &len);
97+
speedbin = nvmem_cell_read(speedbin_nvmem, NULL);
6598
nvmem_cell_put(speedbin_nvmem);
6699
if (IS_ERR(speedbin))
67100
return PTR_ERR(speedbin);
68101

69-
efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK;
70-
71-
/*
72-
* We treat unexpected efuse values as if the SoC was from
73-
* the slowest bin. Expected efuse values are 1-3, slowest
74-
* to fastest.
75-
*/
76-
if (efuse_value >= 1 && efuse_value <= 3)
77-
*versions = efuse_value - 1;
78-
else
79-
*versions = 0;
102+
ret = opp_data->efuse_xlate(*speedbin);
80103

81104
kfree(speedbin);
82-
return 0;
105+
106+
return ret;
83107
};
84108

85109
static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)
86110
{
87111
int *opp_tokens;
88112
char name[MAX_NAME_LEN];
89113
unsigned int cpu;
90-
u32 speed = 0;
114+
int speed;
91115
int ret;
92116

93117
opp_tokens = kcalloc(num_possible_cpus(), sizeof(*opp_tokens),
94118
GFP_KERNEL);
95119
if (!opp_tokens)
96120
return -ENOMEM;
97121

98-
ret = sun50i_cpufreq_get_efuse(&speed);
99-
if (ret) {
122+
speed = sun50i_cpufreq_get_efuse();
123+
if (speed < 0) {
100124
kfree(opp_tokens);
101-
return ret;
125+
return speed;
102126
}
103127

104128
snprintf(name, MAX_NAME_LEN, "speed%d", speed);

0 commit comments

Comments
 (0)