root/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cbe_cpufreq_set_pmode_pmi
  2. cbe_cpufreq_handle_pmi
  3. cbe_cpufreq_pmi_policy_init
  4. cbe_cpufreq_pmi_policy_exit
  5. cbe_cpufreq_pmi_init
  6. cbe_cpufreq_pmi_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * pmi backend for the cbe_cpufreq driver
   4  *
   5  * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
   6  *
   7  * Author: Christian Krafft <krafft@de.ibm.com>
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/types.h>
  12 #include <linux/timer.h>
  13 #include <linux/init.h>
  14 #include <linux/of_platform.h>
  15 #include <linux/pm_qos.h>
  16 
  17 #include <asm/processor.h>
  18 #include <asm/prom.h>
  19 #include <asm/pmi.h>
  20 #include <asm/cell-regs.h>
  21 
  22 #ifdef DEBUG
  23 #include <asm/time.h>
  24 #endif
  25 
  26 #include "ppc_cbe_cpufreq.h"
  27 
  28 bool cbe_cpufreq_has_pmi = false;
  29 EXPORT_SYMBOL_GPL(cbe_cpufreq_has_pmi);
  30 
  31 /*
  32  * hardware specific functions
  33  */
  34 
  35 int cbe_cpufreq_set_pmode_pmi(int cpu, unsigned int pmode)
  36 {
  37         int ret;
  38         pmi_message_t pmi_msg;
  39 #ifdef DEBUG
  40         long time;
  41 #endif
  42         pmi_msg.type = PMI_TYPE_FREQ_CHANGE;
  43         pmi_msg.data1 = cbe_cpu_to_node(cpu);
  44         pmi_msg.data2 = pmode;
  45 
  46 #ifdef DEBUG
  47         time = jiffies;
  48 #endif
  49         pmi_send_message(pmi_msg);
  50 
  51 #ifdef DEBUG
  52         time = jiffies  - time;
  53         time = jiffies_to_msecs(time);
  54         pr_debug("had to wait %lu ms for a transition using " \
  55                  "PMI\n", time);
  56 #endif
  57         ret = pmi_msg.data2;
  58         pr_debug("PMI returned slow mode %d\n", ret);
  59 
  60         return ret;
  61 }
  62 EXPORT_SYMBOL_GPL(cbe_cpufreq_set_pmode_pmi);
  63 
  64 
  65 static void cbe_cpufreq_handle_pmi(pmi_message_t pmi_msg)
  66 {
  67         struct cpufreq_policy *policy;
  68         struct freq_qos_request *req;
  69         u8 node, slow_mode;
  70         int cpu, ret;
  71 
  72         BUG_ON(pmi_msg.type != PMI_TYPE_FREQ_CHANGE);
  73 
  74         node = pmi_msg.data1;
  75         slow_mode = pmi_msg.data2;
  76 
  77         cpu = cbe_node_to_cpu(node);
  78 
  79         pr_debug("cbe_handle_pmi: node: %d max_freq: %d\n", node, slow_mode);
  80 
  81         policy = cpufreq_cpu_get(cpu);
  82         if (!policy) {
  83                 pr_warn("cpufreq policy not found cpu%d\n", cpu);
  84                 return;
  85         }
  86 
  87         req = policy->driver_data;
  88 
  89         ret = freq_qos_update_request(req,
  90                         policy->freq_table[slow_mode].frequency);
  91         if (ret < 0)
  92                 pr_warn("Failed to update freq constraint: %d\n", ret);
  93         else
  94                 pr_debug("limiting node %d to slow mode %d\n", node, slow_mode);
  95 
  96         cpufreq_cpu_put(policy);
  97 }
  98 
  99 static struct pmi_handler cbe_pmi_handler = {
 100         .type                   = PMI_TYPE_FREQ_CHANGE,
 101         .handle_pmi_message     = cbe_cpufreq_handle_pmi,
 102 };
 103 
 104 void cbe_cpufreq_pmi_policy_init(struct cpufreq_policy *policy)
 105 {
 106         struct freq_qos_request *req;
 107         int ret;
 108 
 109         if (!cbe_cpufreq_has_pmi)
 110                 return;
 111 
 112         req = kzalloc(sizeof(*req), GFP_KERNEL);
 113         if (!req)
 114                 return;
 115 
 116         ret = freq_qos_add_request(&policy->constraints, req, FREQ_QOS_MAX,
 117                                    policy->freq_table[0].frequency);
 118         if (ret < 0) {
 119                 pr_err("Failed to add freq constraint (%d)\n", ret);
 120                 kfree(req);
 121                 return;
 122         }
 123 
 124         policy->driver_data = req;
 125 }
 126 EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_init);
 127 
 128 void cbe_cpufreq_pmi_policy_exit(struct cpufreq_policy *policy)
 129 {
 130         struct freq_qos_request *req = policy->driver_data;
 131 
 132         if (cbe_cpufreq_has_pmi) {
 133                 freq_qos_remove_request(req);
 134                 kfree(req);
 135         }
 136 }
 137 EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_policy_exit);
 138 
 139 void cbe_cpufreq_pmi_init(void)
 140 {
 141         if (!pmi_register_handler(&cbe_pmi_handler))
 142                 cbe_cpufreq_has_pmi = true;
 143 }
 144 EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_init);
 145 
 146 void cbe_cpufreq_pmi_exit(void)
 147 {
 148         pmi_unregister_handler(&cbe_pmi_handler);
 149         cbe_cpufreq_has_pmi = false;
 150 }
 151 EXPORT_SYMBOL_GPL(cbe_cpufreq_pmi_exit);

/* [<][>][^][v][top][bottom][index][help] */