25
25
26
26
static struct platform_device * cpufreq_dt_pdev , * sun50i_cpufreq_pdev ;
27
27
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
+
28
60
/**
29
61
* sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value
30
- * @versions: Set to the value parsed from efuse
31
62
*
32
- * Returns 0 if success.
63
+ * Returns non-negative speed bin index on success, a negative error
64
+ * value otherwise.
33
65
*/
34
- static int sun50i_cpufreq_get_efuse (u32 * versions )
66
+ static int sun50i_cpufreq_get_efuse (void )
35
67
{
68
+ const struct sunxi_cpufreq_data * opp_data ;
36
69
struct nvmem_cell * speedbin_nvmem ;
70
+ const struct of_device_id * match ;
37
71
struct device_node * np ;
38
72
struct device * cpu_dev ;
39
- u32 * speedbin , efuse_value ;
40
- size_t len ;
73
+ u32 * speedbin ;
41
74
int ret ;
42
75
43
76
cpu_dev = get_cpu_device (0 );
@@ -48,57 +81,48 @@ static int sun50i_cpufreq_get_efuse(u32 *versions)
48
81
if (!np )
49
82
return - ENOENT ;
50
83
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 ) {
54
86
of_node_put (np );
55
87
return - ENOENT ;
56
88
}
89
+ opp_data = match -> data ;
57
90
58
91
speedbin_nvmem = of_nvmem_cell_get (np , NULL );
59
92
of_node_put (np );
60
93
if (IS_ERR (speedbin_nvmem ))
61
94
return dev_err_probe (cpu_dev , PTR_ERR (speedbin_nvmem ),
62
95
"Could not get nvmem cell\n" );
63
96
64
- speedbin = nvmem_cell_read (speedbin_nvmem , & len );
97
+ speedbin = nvmem_cell_read (speedbin_nvmem , NULL );
65
98
nvmem_cell_put (speedbin_nvmem );
66
99
if (IS_ERR (speedbin ))
67
100
return PTR_ERR (speedbin );
68
101
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 );
80
103
81
104
kfree (speedbin );
82
- return 0 ;
105
+
106
+ return ret ;
83
107
};
84
108
85
109
static int sun50i_cpufreq_nvmem_probe (struct platform_device * pdev )
86
110
{
87
111
int * opp_tokens ;
88
112
char name [MAX_NAME_LEN ];
89
113
unsigned int cpu ;
90
- u32 speed = 0 ;
114
+ int speed ;
91
115
int ret ;
92
116
93
117
opp_tokens = kcalloc (num_possible_cpus (), sizeof (* opp_tokens ),
94
118
GFP_KERNEL );
95
119
if (!opp_tokens )
96
120
return - ENOMEM ;
97
121
98
- ret = sun50i_cpufreq_get_efuse (& speed );
99
- if (ret ) {
122
+ speed = sun50i_cpufreq_get_efuse ();
123
+ if (speed < 0 ) {
100
124
kfree (opp_tokens );
101
- return ret ;
125
+ return speed ;
102
126
}
103
127
104
128
snprintf (name , MAX_NAME_LEN , "speed%d" , speed );
0 commit comments