2424#define CLK_HW_DIV 2
2525#define LUT_TURBO_IND 1
2626
27+ #define GT_IRQ_STATUS BIT(2)
28+
2729#define HZ_PER_KHZ 1000
2830
2931struct qcom_cpufreq_soc_data {
3032 u32 reg_enable ;
33+ u32 reg_domain_state ;
3134 u32 reg_dcvs_ctrl ;
3235 u32 reg_freq_lut ;
3336 u32 reg_volt_lut ;
37+ u32 reg_intr_clr ;
3438 u32 reg_current_vote ;
3539 u32 reg_perf_state ;
3640 u8 lut_row_size ;
@@ -280,37 +284,46 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
280284 }
281285}
282286
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 )
284288{
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 ;
286295
287- return ( val & 0x3FF ) * 19200 ;
296+ return lval * xo_rate ;
288297}
289298
290299static void qcom_lmh_dcvs_notify (struct qcom_cpufreq_data * data )
291300{
292301 struct cpufreq_policy * policy = data -> policy ;
293- int cpu = cpumask_first (policy -> cpus );
302+ int cpu = cpumask_first (policy -> related_cpus );
294303 struct device * dev = get_cpu_device (cpu );
295304 unsigned long freq_hz , throttled_freq ;
296305 struct dev_pm_opp * opp ;
297- unsigned int freq ;
298306
299307 /*
300308 * Get the h/w throttled frequency, normalize it using the
301309 * registered opp table and use it to calculate thermal pressure.
302310 */
303- freq = qcom_lmh_get_throttle_freq (data );
304- freq_hz = freq * HZ_PER_KHZ ;
311+ freq_hz = qcom_lmh_get_throttle_freq (data );
305312
306313 opp = dev_pm_opp_find_freq_floor (dev , & freq_hz );
307314 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 ;
309321
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 );
311324
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+ }
314327
315328 /*
316329 * 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)
350363 disable_irq_nosync (c_data -> throttle_irq );
351364 schedule_delayed_work (& c_data -> throttle_work , 0 );
352365
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+
353370 return IRQ_HANDLED ;
354371}
355372
@@ -365,9 +382,11 @@ static const struct qcom_cpufreq_soc_data qcom_soc_data = {
365382
366383static const struct qcom_cpufreq_soc_data epss_soc_data = {
367384 .reg_enable = 0x0 ,
385+ .reg_domain_state = 0x20 ,
368386 .reg_dcvs_ctrl = 0xb0 ,
369387 .reg_freq_lut = 0x100 ,
370388 .reg_volt_lut = 0x200 ,
389+ .reg_intr_clr = 0x308 ,
371390 .reg_perf_state = 0x320 ,
372391 .lut_row_size = 4 ,
373392};
@@ -417,16 +436,39 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
417436 return 0 ;
418437}
419438
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 )
421454{
455+ struct qcom_cpufreq_data * data = policy -> driver_data ;
456+
422457 if (data -> throttle_irq <= 0 )
423- return ;
458+ return 0 ;
424459
425460 mutex_lock (& data -> throttle_lock );
426461 data -> cancel_throttle = true;
427462 mutex_unlock (& data -> throttle_lock );
428463
429464 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+ {
430472 free_irq (data -> throttle_irq , data );
431473}
432474
@@ -583,6 +625,8 @@ static struct cpufreq_driver cpufreq_qcom_hw_driver = {
583625 .get = qcom_cpufreq_hw_get ,
584626 .init = qcom_cpufreq_hw_cpu_init ,
585627 .exit = qcom_cpufreq_hw_cpu_exit ,
628+ .online = qcom_cpufreq_hw_cpu_online ,
629+ .offline = qcom_cpufreq_hw_cpu_offline ,
586630 .register_em = cpufreq_register_em_with_opp ,
587631 .fast_switch = qcom_cpufreq_hw_fast_switch ,
588632 .name = "qcom-cpufreq-hw" ,
0 commit comments