cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ppc_cbe_cpufreq.c (3693B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * cpufreq driver for the cell processor
      4 *
      5 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
      6 *
      7 * Author: Christian Krafft <krafft@de.ibm.com>
      8 */
      9
     10#include <linux/cpufreq.h>
     11#include <linux/module.h>
     12#include <linux/of_platform.h>
     13
     14#include <asm/machdep.h>
     15#include <asm/cell-regs.h>
     16
     17#include "ppc_cbe_cpufreq.h"
     18
     19/* the CBE supports an 8 step frequency scaling */
     20static struct cpufreq_frequency_table cbe_freqs[] = {
     21	{0, 1,	0},
     22	{0, 2,	0},
     23	{0, 3,	0},
     24	{0, 4,	0},
     25	{0, 5,	0},
     26	{0, 6,	0},
     27	{0, 8,	0},
     28	{0, 10,	0},
     29	{0, 0,	CPUFREQ_TABLE_END},
     30};
     31
     32/*
     33 * hardware specific functions
     34 */
     35
     36static int set_pmode(unsigned int cpu, unsigned int slow_mode)
     37{
     38	int rc;
     39
     40	if (cbe_cpufreq_has_pmi)
     41		rc = cbe_cpufreq_set_pmode_pmi(cpu, slow_mode);
     42	else
     43		rc = cbe_cpufreq_set_pmode(cpu, slow_mode);
     44
     45	pr_debug("register contains slow mode %d\n", cbe_cpufreq_get_pmode(cpu));
     46
     47	return rc;
     48}
     49
     50/*
     51 * cpufreq functions
     52 */
     53
     54static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
     55{
     56	struct cpufreq_frequency_table *pos;
     57	const u32 *max_freqp;
     58	u32 max_freq;
     59	int cur_pmode;
     60	struct device_node *cpu;
     61
     62	cpu = of_get_cpu_node(policy->cpu, NULL);
     63
     64	if (!cpu)
     65		return -ENODEV;
     66
     67	pr_debug("init cpufreq on CPU %d\n", policy->cpu);
     68
     69	/*
     70	 * Let's check we can actually get to the CELL regs
     71	 */
     72	if (!cbe_get_cpu_pmd_regs(policy->cpu) ||
     73	    !cbe_get_cpu_mic_tm_regs(policy->cpu)) {
     74		pr_info("invalid CBE regs pointers for cpufreq\n");
     75		of_node_put(cpu);
     76		return -EINVAL;
     77	}
     78
     79	max_freqp = of_get_property(cpu, "clock-frequency", NULL);
     80
     81	of_node_put(cpu);
     82
     83	if (!max_freqp)
     84		return -EINVAL;
     85
     86	/* we need the freq in kHz */
     87	max_freq = *max_freqp / 1000;
     88
     89	pr_debug("max clock-frequency is at %u kHz\n", max_freq);
     90	pr_debug("initializing frequency table\n");
     91
     92	/* initialize frequency table */
     93	cpufreq_for_each_entry(pos, cbe_freqs) {
     94		pos->frequency = max_freq / pos->driver_data;
     95		pr_debug("%d: %d\n", (int)(pos - cbe_freqs), pos->frequency);
     96	}
     97
     98	/* if DEBUG is enabled set_pmode() measures the latency
     99	 * of a transition */
    100	policy->cpuinfo.transition_latency = 25000;
    101
    102	cur_pmode = cbe_cpufreq_get_pmode(policy->cpu);
    103	pr_debug("current pmode is at %d\n",cur_pmode);
    104
    105	policy->cur = cbe_freqs[cur_pmode].frequency;
    106
    107#ifdef CONFIG_SMP
    108	cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
    109#endif
    110
    111	policy->freq_table = cbe_freqs;
    112	cbe_cpufreq_pmi_policy_init(policy);
    113	return 0;
    114}
    115
    116static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
    117{
    118	cbe_cpufreq_pmi_policy_exit(policy);
    119	return 0;
    120}
    121
    122static int cbe_cpufreq_target(struct cpufreq_policy *policy,
    123			      unsigned int cbe_pmode_new)
    124{
    125	pr_debug("setting frequency for cpu %d to %d kHz, " \
    126		 "1/%d of max frequency\n",
    127		 policy->cpu,
    128		 cbe_freqs[cbe_pmode_new].frequency,
    129		 cbe_freqs[cbe_pmode_new].driver_data);
    130
    131	return set_pmode(policy->cpu, cbe_pmode_new);
    132}
    133
    134static struct cpufreq_driver cbe_cpufreq_driver = {
    135	.verify		= cpufreq_generic_frequency_table_verify,
    136	.target_index	= cbe_cpufreq_target,
    137	.init		= cbe_cpufreq_cpu_init,
    138	.exit		= cbe_cpufreq_cpu_exit,
    139	.name		= "cbe-cpufreq",
    140	.flags		= CPUFREQ_CONST_LOOPS,
    141};
    142
    143/*
    144 * module init and destoy
    145 */
    146
    147static int __init cbe_cpufreq_init(void)
    148{
    149	int ret;
    150
    151	if (!machine_is(cell))
    152		return -ENODEV;
    153
    154	cbe_cpufreq_pmi_init();
    155
    156	ret = cpufreq_register_driver(&cbe_cpufreq_driver);
    157	if (ret)
    158		cbe_cpufreq_pmi_exit();
    159
    160	return ret;
    161}
    162
    163static void __exit cbe_cpufreq_exit(void)
    164{
    165	cpufreq_unregister_driver(&cbe_cpufreq_driver);
    166	cbe_cpufreq_pmi_exit();
    167}
    168
    169module_init(cbe_cpufreq_init);
    170module_exit(cbe_cpufreq_exit);
    171
    172MODULE_LICENSE("GPL");
    173MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");