brintos

brintos / linux-shallow public Read only

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