Path: blob/master/arch/powerpc/platforms/cell/cbe_cpufreq_pervasive.c
10818 views
/*1* pervasive backend for the cbe_cpufreq driver2*3* This driver makes use of the pervasive unit to4* engage the desired frequency.5*6* (C) Copyright IBM Deutschland Entwicklung GmbH 2005-20077*8* Author: Christian Krafft <[email protected]>9*10* This program is free software; you can redistribute it and/or modify11* it under the terms of the GNU General Public License as published by12* the Free Software Foundation; either version 2, or (at your option)13* any later version.14*15* This program is distributed in the hope that it will be useful,16* but WITHOUT ANY WARRANTY; without even the implied warranty of17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the18* GNU General Public License for more details.19*20* You should have received a copy of the GNU General Public License21* along with this program; if not, write to the Free Software22* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.23*/2425#include <linux/io.h>26#include <linux/kernel.h>27#include <linux/time.h>28#include <asm/machdep.h>29#include <asm/hw_irq.h>30#include <asm/cell-regs.h>3132#include "cbe_cpufreq.h"3334/* to write to MIC register */35static u64 MIC_Slow_Fast_Timer_table[] = {36[0 ... 7] = 0x007fc00000000000ull,37};3839/* more values for the MIC */40static u64 MIC_Slow_Next_Timer_table[] = {410x0000240000000000ull,420x0000268000000000ull,430x000029C000000000ull,440x00002D0000000000ull,450x0000300000000000ull,460x0000334000000000ull,470x000039C000000000ull,480x00003FC000000000ull,49};505152int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode)53{54struct cbe_pmd_regs __iomem *pmd_regs;55struct cbe_mic_tm_regs __iomem *mic_tm_regs;56unsigned long flags;57u64 value;58#ifdef DEBUG59long time;60#endif6162local_irq_save(flags);6364mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);65pmd_regs = cbe_get_cpu_pmd_regs(cpu);6667#ifdef DEBUG68time = jiffies;69#endif7071out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);72out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);7374out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);75out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);7677value = in_be64(&pmd_regs->pmcr);78/* set bits to zero */79value &= 0xFFFFFFFFFFFFFFF8ull;80/* set bits to next pmode */81value |= pmode;8283out_be64(&pmd_regs->pmcr, value);8485#ifdef DEBUG86/* wait until new pmode appears in status register */87value = in_be64(&pmd_regs->pmsr) & 0x07;88while (value != pmode) {89cpu_relax();90value = in_be64(&pmd_regs->pmsr) & 0x07;91}9293time = jiffies - time;94time = jiffies_to_msecs(time);95pr_debug("had to wait %lu ms for a transition using " \96"pervasive unit\n", time);97#endif98local_irq_restore(flags);99100return 0;101}102103104int cbe_cpufreq_get_pmode(int cpu)105{106int ret;107struct cbe_pmd_regs __iomem *pmd_regs;108109pmd_regs = cbe_get_cpu_pmd_regs(cpu);110ret = in_be64(&pmd_regs->pmsr) & 0x07;111112return ret;113}114115116117