24
24
#define CLK_HW_DIV 2
25
25
#define LUT_TURBO_IND 1
26
26
27
+ #define GT_IRQ_STATUS BIT(2)
28
+
27
29
#define HZ_PER_KHZ 1000
28
30
29
31
struct qcom_cpufreq_soc_data {
30
32
u32 reg_enable ;
33
+ u32 reg_domain_state ;
31
34
u32 reg_dcvs_ctrl ;
32
35
u32 reg_freq_lut ;
33
36
u32 reg_volt_lut ;
37
+ u32 reg_intr_clr ;
34
38
u32 reg_current_vote ;
35
39
u32 reg_perf_state ;
36
40
u8 lut_row_size ;
@@ -280,37 +284,46 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
280
284
}
281
285
}
282
286
283
- static unsigned int qcom_lmh_get_throttle_freq (struct qcom_cpufreq_data * data )
287
+ static unsigned long qcom_lmh_get_throttle_freq (struct qcom_cpufreq_data * data )
284
288
{
285
- unsigned int val = readl_relaxed (data -> base + data -> soc_data -> reg_current_vote );
289
+ unsigned int lval ;
290
+
291
+ if (data -> soc_data -> reg_current_vote )
292
+ lval = readl_relaxed (data -> base + data -> soc_data -> reg_current_vote ) & 0x3ff ;
293
+ else
294
+ lval = readl_relaxed (data -> base + data -> soc_data -> reg_domain_state ) & 0xff ;
286
295
287
- return ( val & 0x3FF ) * 19200 ;
296
+ return lval * xo_rate ;
288
297
}
289
298
290
299
static void qcom_lmh_dcvs_notify (struct qcom_cpufreq_data * data )
291
300
{
292
301
struct cpufreq_policy * policy = data -> policy ;
293
- int cpu = cpumask_first (policy -> cpus );
302
+ int cpu = cpumask_first (policy -> related_cpus );
294
303
struct device * dev = get_cpu_device (cpu );
295
304
unsigned long freq_hz , throttled_freq ;
296
305
struct dev_pm_opp * opp ;
297
- unsigned int freq ;
298
306
299
307
/*
300
308
* Get the h/w throttled frequency, normalize it using the
301
309
* registered opp table and use it to calculate thermal pressure.
302
310
*/
303
- freq = qcom_lmh_get_throttle_freq (data );
304
- freq_hz = freq * HZ_PER_KHZ ;
311
+ freq_hz = qcom_lmh_get_throttle_freq (data );
305
312
306
313
opp = dev_pm_opp_find_freq_floor (dev , & freq_hz );
307
314
if (IS_ERR (opp ) && PTR_ERR (opp ) == - ERANGE )
308
- dev_pm_opp_find_freq_ceil (dev , & freq_hz );
315
+ opp = dev_pm_opp_find_freq_ceil (dev , & freq_hz );
316
+
317
+ if (IS_ERR (opp )) {
318
+ dev_warn (dev , "Can't find the OPP for throttling: %pe!\n" , opp );
319
+ } else {
320
+ throttled_freq = freq_hz / HZ_PER_KHZ ;
309
321
310
- throttled_freq = freq_hz / HZ_PER_KHZ ;
322
+ /* Update thermal pressure (the boost frequencies are accepted) */
323
+ arch_update_thermal_pressure (policy -> related_cpus , throttled_freq );
311
324
312
- /* Update thermal pressure (the boost frequencies are accepted) */
313
- arch_update_thermal_pressure ( policy -> related_cpus , throttled_freq );
325
+ dev_pm_opp_put ( opp );
326
+ }
314
327
315
328
/*
316
329
* In the unlikely case policy is unregistered do not enable
@@ -350,6 +363,10 @@ static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data)
350
363
disable_irq_nosync (c_data -> throttle_irq );
351
364
schedule_delayed_work (& c_data -> throttle_work , 0 );
352
365
366
+ if (c_data -> soc_data -> reg_intr_clr )
367
+ writel_relaxed (GT_IRQ_STATUS ,
368
+ c_data -> base + c_data -> soc_data -> reg_intr_clr );
369
+
353
370
return IRQ_HANDLED ;
354
371
}
355
372
@@ -365,9 +382,11 @@ static const struct qcom_cpufreq_soc_data qcom_soc_data = {
365
382
366
383
static const struct qcom_cpufreq_soc_data epss_soc_data = {
367
384
.reg_enable = 0x0 ,
385
+ .reg_domain_state = 0x20 ,
368
386
.reg_dcvs_ctrl = 0xb0 ,
369
387
.reg_freq_lut = 0x100 ,
370
388
.reg_volt_lut = 0x200 ,
389
+ .reg_intr_clr = 0x308 ,
371
390
.reg_perf_state = 0x320 ,
372
391
.lut_row_size = 4 ,
373
392
};
@@ -417,16 +436,39 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
417
436
return 0 ;
418
437
}
419
438
420
- static void qcom_cpufreq_hw_lmh_exit (struct qcom_cpufreq_data * data )
439
+ static int qcom_cpufreq_hw_cpu_online (struct cpufreq_policy * policy )
440
+ {
441
+ struct qcom_cpufreq_data * data = policy -> driver_data ;
442
+ struct platform_device * pdev = cpufreq_get_driver_data ();
443
+ int ret ;
444
+
445
+ ret = irq_set_affinity_hint (data -> throttle_irq , policy -> cpus );
446
+ if (ret )
447
+ dev_err (& pdev -> dev , "Failed to set CPU affinity of %s[%d]\n" ,
448
+ data -> irq_name , data -> throttle_irq );
449
+
450
+ return ret ;
451
+ }
452
+
453
+ static int qcom_cpufreq_hw_cpu_offline (struct cpufreq_policy * policy )
421
454
{
455
+ struct qcom_cpufreq_data * data = policy -> driver_data ;
456
+
422
457
if (data -> throttle_irq <= 0 )
423
- return ;
458
+ return 0 ;
424
459
425
460
mutex_lock (& data -> throttle_lock );
426
461
data -> cancel_throttle = true;
427
462
mutex_unlock (& data -> throttle_lock );
428
463
429
464
cancel_delayed_work_sync (& data -> throttle_work );
465
+ irq_set_affinity_hint (data -> throttle_irq , NULL );
466
+
467
+ return 0 ;
468
+ }
469
+
470
+ static void qcom_cpufreq_hw_lmh_exit (struct qcom_cpufreq_data * data )
471
+ {
430
472
free_irq (data -> throttle_irq , data );
431
473
}
432
474
@@ -583,6 +625,8 @@ static struct cpufreq_driver cpufreq_qcom_hw_driver = {
583
625
.get = qcom_cpufreq_hw_get ,
584
626
.init = qcom_cpufreq_hw_cpu_init ,
585
627
.exit = qcom_cpufreq_hw_cpu_exit ,
628
+ .online = qcom_cpufreq_hw_cpu_online ,
629
+ .offline = qcom_cpufreq_hw_cpu_offline ,
586
630
.register_em = cpufreq_register_em_with_opp ,
587
631
.fast_switch = qcom_cpufreq_hw_fast_switch ,
588
632
.name = "qcom-cpufreq-hw" ,
0 commit comments