@@ -49,19 +49,99 @@ struct qcom_cpufreq_drv;
49
49
struct qcom_cpufreq_match_data {
50
50
int (* get_version )(struct device * cpu_dev ,
51
51
struct nvmem_cell * speedbin_nvmem ,
52
+ char * * pvs_name ,
52
53
struct qcom_cpufreq_drv * drv );
53
54
const char * * genpd_names ;
54
55
};
55
56
56
57
struct qcom_cpufreq_drv {
57
- struct opp_table * * opp_tables ;
58
+ struct opp_table * * names_opp_tables ;
59
+ struct opp_table * * hw_opp_tables ;
58
60
struct opp_table * * genpd_opp_tables ;
59
61
u32 versions ;
60
62
const struct qcom_cpufreq_match_data * data ;
61
63
};
62
64
63
65
static struct platform_device * cpufreq_dt_pdev , * cpufreq_pdev ;
64
66
67
+ static void get_krait_bin_format_a (struct device * cpu_dev ,
68
+ int * speed , int * pvs , int * pvs_ver ,
69
+ struct nvmem_cell * pvs_nvmem , u8 * buf )
70
+ {
71
+ u32 pte_efuse ;
72
+
73
+ pte_efuse = * ((u32 * )buf );
74
+
75
+ * speed = pte_efuse & 0xf ;
76
+ if (* speed == 0xf )
77
+ * speed = (pte_efuse >> 4 ) & 0xf ;
78
+
79
+ if (* speed == 0xf ) {
80
+ * speed = 0 ;
81
+ dev_warn (cpu_dev , "Speed bin: Defaulting to %d\n" , * speed );
82
+ } else {
83
+ dev_dbg (cpu_dev , "Speed bin: %d\n" , * speed );
84
+ }
85
+
86
+ * pvs = (pte_efuse >> 10 ) & 0x7 ;
87
+ if (* pvs == 0x7 )
88
+ * pvs = (pte_efuse >> 13 ) & 0x7 ;
89
+
90
+ if (* pvs == 0x7 ) {
91
+ * pvs = 0 ;
92
+ dev_warn (cpu_dev , "PVS bin: Defaulting to %d\n" , * pvs );
93
+ } else {
94
+ dev_dbg (cpu_dev , "PVS bin: %d\n" , * pvs );
95
+ }
96
+ }
97
+
98
+ static void get_krait_bin_format_b (struct device * cpu_dev ,
99
+ int * speed , int * pvs , int * pvs_ver ,
100
+ struct nvmem_cell * pvs_nvmem , u8 * buf )
101
+ {
102
+ u32 pte_efuse , redundant_sel ;
103
+
104
+ pte_efuse = * ((u32 * )buf );
105
+ redundant_sel = (pte_efuse >> 24 ) & 0x7 ;
106
+
107
+ * pvs_ver = (pte_efuse >> 4 ) & 0x3 ;
108
+
109
+ switch (redundant_sel ) {
110
+ case 1 :
111
+ * pvs = ((pte_efuse >> 28 ) & 0x8 ) | ((pte_efuse >> 6 ) & 0x7 );
112
+ * speed = (pte_efuse >> 27 ) & 0xf ;
113
+ break ;
114
+ case 2 :
115
+ * pvs = (pte_efuse >> 27 ) & 0xf ;
116
+ * speed = pte_efuse & 0x7 ;
117
+ break ;
118
+ default :
119
+ /* 4 bits of PVS are in efuse register bits 31, 8-6. */
120
+ * pvs = ((pte_efuse >> 28 ) & 0x8 ) | ((pte_efuse >> 6 ) & 0x7 );
121
+ * speed = pte_efuse & 0x7 ;
122
+ }
123
+
124
+ /* Check SPEED_BIN_BLOW_STATUS */
125
+ if (pte_efuse & BIT (3 )) {
126
+ dev_dbg (cpu_dev , "Speed bin: %d\n" , * speed );
127
+ } else {
128
+ dev_warn (cpu_dev , "Speed bin not set. Defaulting to 0!\n" );
129
+ * speed = 0 ;
130
+ }
131
+
132
+ /* Check PVS_BLOW_STATUS */
133
+ pte_efuse = * (((u32 * )buf ) + 4 );
134
+ pte_efuse &= BIT (21 );
135
+ if (pte_efuse ) {
136
+ dev_dbg (cpu_dev , "PVS bin: %d\n" , * pvs );
137
+ } else {
138
+ dev_warn (cpu_dev , "PVS bin not set. Defaulting to 0!\n" );
139
+ * pvs = 0 ;
140
+ }
141
+
142
+ dev_dbg (cpu_dev , "PVS version: %d\n" , * pvs_ver );
143
+ }
144
+
65
145
static enum _msm8996_version qcom_cpufreq_get_msm_id (void )
66
146
{
67
147
size_t len ;
@@ -93,11 +173,13 @@ static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
93
173
94
174
static int qcom_cpufreq_kryo_name_version (struct device * cpu_dev ,
95
175
struct nvmem_cell * speedbin_nvmem ,
176
+ char * * pvs_name ,
96
177
struct qcom_cpufreq_drv * drv )
97
178
{
98
179
size_t len ;
99
180
u8 * speedbin ;
100
181
enum _msm8996_version msm8996_version ;
182
+ * pvs_name = NULL ;
101
183
102
184
msm8996_version = qcom_cpufreq_get_msm_id ();
103
185
if (NUM_OF_MSM8996_VERSIONS == msm8996_version ) {
@@ -125,10 +207,51 @@ static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
125
207
return 0 ;
126
208
}
127
209
210
+ static int qcom_cpufreq_krait_name_version (struct device * cpu_dev ,
211
+ struct nvmem_cell * speedbin_nvmem ,
212
+ char * * pvs_name ,
213
+ struct qcom_cpufreq_drv * drv )
214
+ {
215
+ int speed = 0 , pvs = 0 , pvs_ver = 0 ;
216
+ u8 * speedbin ;
217
+ size_t len ;
218
+
219
+ speedbin = nvmem_cell_read (speedbin_nvmem , & len );
220
+
221
+ if (IS_ERR (speedbin ))
222
+ return PTR_ERR (speedbin );
223
+
224
+ switch (len ) {
225
+ case 4 :
226
+ get_krait_bin_format_a (cpu_dev , & speed , & pvs , & pvs_ver ,
227
+ speedbin_nvmem , speedbin );
228
+ break ;
229
+ case 8 :
230
+ get_krait_bin_format_b (cpu_dev , & speed , & pvs , & pvs_ver ,
231
+ speedbin_nvmem , speedbin );
232
+ break ;
233
+ default :
234
+ dev_err (cpu_dev , "Unable to read nvmem data. Defaulting to 0!\n" );
235
+ return - ENODEV ;
236
+ }
237
+
238
+ snprintf (* pvs_name , sizeof ("speedXX-pvsXX-vXX" ), "speed%d-pvs%d-v%d" ,
239
+ speed , pvs , pvs_ver );
240
+
241
+ drv -> versions = (1 << speed );
242
+
243
+ kfree (speedbin );
244
+ return 0 ;
245
+ }
246
+
128
247
static const struct qcom_cpufreq_match_data match_data_kryo = {
129
248
.get_version = qcom_cpufreq_kryo_name_version ,
130
249
};
131
250
251
+ static const struct qcom_cpufreq_match_data match_data_krait = {
252
+ .get_version = qcom_cpufreq_krait_name_version ,
253
+ };
254
+
132
255
static const char * qcs404_genpd_names [] = { "cpr" , NULL };
133
256
134
257
static const struct qcom_cpufreq_match_data match_data_qcs404 = {
@@ -141,6 +264,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
141
264
struct nvmem_cell * speedbin_nvmem ;
142
265
struct device_node * np ;
143
266
struct device * cpu_dev ;
267
+ char * pvs_name = "speedXX-pvsXX-vXX" ;
144
268
unsigned cpu ;
145
269
const struct of_device_id * match ;
146
270
int ret ;
@@ -153,7 +277,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
153
277
if (!np )
154
278
return - ENOENT ;
155
279
156
- ret = of_device_is_compatible (np , "operating-points-v2-kryo -cpu" );
280
+ ret = of_device_is_compatible (np , "operating-points-v2-qcom -cpu" );
157
281
if (!ret ) {
158
282
of_node_put (np );
159
283
return - ENOENT ;
@@ -181,7 +305,8 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
181
305
goto free_drv ;
182
306
}
183
307
184
- ret = drv -> data -> get_version (cpu_dev , speedbin_nvmem , drv );
308
+ ret = drv -> data -> get_version (cpu_dev ,
309
+ speedbin_nvmem , & pvs_name , drv );
185
310
if (ret ) {
186
311
nvmem_cell_put (speedbin_nvmem );
187
312
goto free_drv ;
@@ -190,12 +315,20 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
190
315
}
191
316
of_node_put (np );
192
317
193
- drv -> opp_tables = kcalloc (num_possible_cpus (), sizeof (* drv -> opp_tables ),
318
+ drv -> names_opp_tables = kcalloc (num_possible_cpus (),
319
+ sizeof (* drv -> names_opp_tables ),
194
320
GFP_KERNEL );
195
- if (!drv -> opp_tables ) {
321
+ if (!drv -> names_opp_tables ) {
196
322
ret = - ENOMEM ;
197
323
goto free_drv ;
198
324
}
325
+ drv -> hw_opp_tables = kcalloc (num_possible_cpus (),
326
+ sizeof (* drv -> hw_opp_tables ),
327
+ GFP_KERNEL );
328
+ if (!drv -> hw_opp_tables ) {
329
+ ret = - ENOMEM ;
330
+ goto free_opp_names ;
331
+ }
199
332
200
333
drv -> genpd_opp_tables = kcalloc (num_possible_cpus (),
201
334
sizeof (* drv -> genpd_opp_tables ),
@@ -213,11 +346,23 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
213
346
}
214
347
215
348
if (drv -> data -> get_version ) {
216
- drv -> opp_tables [cpu ] =
217
- dev_pm_opp_set_supported_hw (cpu_dev ,
218
- & drv -> versions , 1 );
219
- if (IS_ERR (drv -> opp_tables [cpu ])) {
220
- ret = PTR_ERR (drv -> opp_tables [cpu ]);
349
+
350
+ if (pvs_name ) {
351
+ drv -> names_opp_tables [cpu ] = dev_pm_opp_set_prop_name (
352
+ cpu_dev ,
353
+ pvs_name );
354
+ if (IS_ERR (drv -> names_opp_tables [cpu ])) {
355
+ ret = PTR_ERR (drv -> names_opp_tables [cpu ]);
356
+ dev_err (cpu_dev , "Failed to add OPP name %s\n" ,
357
+ pvs_name );
358
+ goto free_opp ;
359
+ }
360
+ }
361
+
362
+ drv -> hw_opp_tables [cpu ] = dev_pm_opp_set_supported_hw (
363
+ cpu_dev , & drv -> versions , 1 );
364
+ if (IS_ERR (drv -> hw_opp_tables [cpu ])) {
365
+ ret = PTR_ERR (drv -> hw_opp_tables [cpu ]);
221
366
dev_err (cpu_dev ,
222
367
"Failed to set supported hardware\n" );
223
368
goto free_genpd_opp ;
@@ -259,11 +404,18 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
259
404
kfree (drv -> genpd_opp_tables );
260
405
free_opp :
261
406
for_each_possible_cpu (cpu ) {
262
- if (IS_ERR_OR_NULL (drv -> opp_tables [cpu ]))
407
+ if (IS_ERR_OR_NULL (drv -> names_opp_tables [cpu ]))
408
+ break ;
409
+ dev_pm_opp_put_prop_name (drv -> names_opp_tables [cpu ]);
410
+ }
411
+ for_each_possible_cpu (cpu ) {
412
+ if (IS_ERR_OR_NULL (drv -> hw_opp_tables [cpu ]))
263
413
break ;
264
- dev_pm_opp_put_supported_hw (drv -> opp_tables [cpu ]);
414
+ dev_pm_opp_put_supported_hw (drv -> hw_opp_tables [cpu ]);
265
415
}
266
- kfree (drv -> opp_tables );
416
+ kfree (drv -> hw_opp_tables );
417
+ free_opp_names :
418
+ kfree (drv -> names_opp_tables );
267
419
free_drv :
268
420
kfree (drv );
269
421
@@ -278,13 +430,16 @@ static int qcom_cpufreq_remove(struct platform_device *pdev)
278
430
platform_device_unregister (cpufreq_dt_pdev );
279
431
280
432
for_each_possible_cpu (cpu ) {
281
- if (drv -> opp_tables [cpu ])
282
- dev_pm_opp_put_supported_hw (drv -> opp_tables [cpu ]);
433
+ if (drv -> names_opp_tables [cpu ])
434
+ dev_pm_opp_put_supported_hw (drv -> names_opp_tables [cpu ]);
435
+ if (drv -> hw_opp_tables [cpu ])
436
+ dev_pm_opp_put_supported_hw (drv -> hw_opp_tables [cpu ]);
283
437
if (drv -> genpd_opp_tables [cpu ])
284
438
dev_pm_opp_detach_genpd (drv -> genpd_opp_tables [cpu ]);
285
439
}
286
440
287
- kfree (drv -> opp_tables );
441
+ kfree (drv -> names_opp_tables );
442
+ kfree (drv -> hw_opp_tables );
288
443
kfree (drv -> genpd_opp_tables );
289
444
kfree (drv );
290
445
@@ -303,6 +458,10 @@ static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
303
458
{ .compatible = "qcom,apq8096" , .data = & match_data_kryo },
304
459
{ .compatible = "qcom,msm8996" , .data = & match_data_kryo },
305
460
{ .compatible = "qcom,qcs404" , .data = & match_data_qcs404 },
461
+ { .compatible = "qcom,ipq8064" , .data = & match_data_krait },
462
+ { .compatible = "qcom,apq8064" , .data = & match_data_krait },
463
+ { .compatible = "qcom,msm8974" , .data = & match_data_krait },
464
+ { .compatible = "qcom,msm8960" , .data = & match_data_krait },
306
465
{},
307
466
};
308
467
0 commit comments