103 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * pervasive backend for the cbe_cpufreq driver4 *5 * This driver makes use of the pervasive unit to6 * engage the desired frequency.7 *8 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-20079 *10 * Author: Christian Krafft <krafft@de.ibm.com>11 */12 13#include <linux/io.h>14#include <linux/kernel.h>15#include <linux/time.h>16#include <asm/machdep.h>17#include <asm/hw_irq.h>18#include <asm/cell-regs.h>19 20#include "ppc_cbe_cpufreq.h"21 22/* to write to MIC register */23static u64 MIC_Slow_Fast_Timer_table[] = {24 [0 ... 7] = 0x007fc00000000000ull,25};26 27/* more values for the MIC */28static u64 MIC_Slow_Next_Timer_table[] = {29 0x0000240000000000ull,30 0x0000268000000000ull,31 0x000029C000000000ull,32 0x00002D0000000000ull,33 0x0000300000000000ull,34 0x0000334000000000ull,35 0x000039C000000000ull,36 0x00003FC000000000ull,37};38 39 40int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode)41{42 struct cbe_pmd_regs __iomem *pmd_regs;43 struct cbe_mic_tm_regs __iomem *mic_tm_regs;44 unsigned long flags;45 u64 value;46#ifdef DEBUG47 long time;48#endif49 50 local_irq_save(flags);51 52 mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);53 pmd_regs = cbe_get_cpu_pmd_regs(cpu);54 55#ifdef DEBUG56 time = jiffies;57#endif58 59 out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);60 out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);61 62 out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);63 out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);64 65 value = in_be64(&pmd_regs->pmcr);66 /* set bits to zero */67 value &= 0xFFFFFFFFFFFFFFF8ull;68 /* set bits to next pmode */69 value |= pmode;70 71 out_be64(&pmd_regs->pmcr, value);72 73#ifdef DEBUG74 /* wait until new pmode appears in status register */75 value = in_be64(&pmd_regs->pmsr) & 0x07;76 while (value != pmode) {77 cpu_relax();78 value = in_be64(&pmd_regs->pmsr) & 0x07;79 }80 81 time = jiffies - time;82 time = jiffies_to_msecs(time);83 pr_debug("had to wait %lu ms for a transition using " \84 "pervasive unit\n", time);85#endif86 local_irq_restore(flags);87 88 return 0;89}90 91 92int cbe_cpufreq_get_pmode(int cpu)93{94 int ret;95 struct cbe_pmd_regs __iomem *pmd_regs;96 97 pmd_regs = cbe_get_cpu_pmd_regs(cpu);98 ret = in_be64(&pmd_regs->pmsr) & 0x07;99 100 return ret;101}102 103