Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * pervasive backend for the cbe_cpufreq driver
0004  *
0005  * This driver makes use of the pervasive unit to
0006  * engage the desired frequency.
0007  *
0008  * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
0009  *
0010  * Author: Christian Krafft <krafft@de.ibm.com>
0011  */
0012 
0013 #include <linux/io.h>
0014 #include <linux/kernel.h>
0015 #include <linux/time.h>
0016 #include <asm/machdep.h>
0017 #include <asm/hw_irq.h>
0018 #include <asm/cell-regs.h>
0019 
0020 #include "ppc_cbe_cpufreq.h"
0021 
0022 /* to write to MIC register */
0023 static u64 MIC_Slow_Fast_Timer_table[] = {
0024     [0 ... 7] = 0x007fc00000000000ull,
0025 };
0026 
0027 /* more values for the MIC */
0028 static u64 MIC_Slow_Next_Timer_table[] = {
0029     0x0000240000000000ull,
0030     0x0000268000000000ull,
0031     0x000029C000000000ull,
0032     0x00002D0000000000ull,
0033     0x0000300000000000ull,
0034     0x0000334000000000ull,
0035     0x000039C000000000ull,
0036     0x00003FC000000000ull,
0037 };
0038 
0039 
0040 int cbe_cpufreq_set_pmode(int cpu, unsigned int pmode)
0041 {
0042     struct cbe_pmd_regs __iomem *pmd_regs;
0043     struct cbe_mic_tm_regs __iomem *mic_tm_regs;
0044     unsigned long flags;
0045     u64 value;
0046 #ifdef DEBUG
0047     long time;
0048 #endif
0049 
0050     local_irq_save(flags);
0051 
0052     mic_tm_regs = cbe_get_cpu_mic_tm_regs(cpu);
0053     pmd_regs = cbe_get_cpu_pmd_regs(cpu);
0054 
0055 #ifdef DEBUG
0056     time = jiffies;
0057 #endif
0058 
0059     out_be64(&mic_tm_regs->slow_fast_timer_0, MIC_Slow_Fast_Timer_table[pmode]);
0060     out_be64(&mic_tm_regs->slow_fast_timer_1, MIC_Slow_Fast_Timer_table[pmode]);
0061 
0062     out_be64(&mic_tm_regs->slow_next_timer_0, MIC_Slow_Next_Timer_table[pmode]);
0063     out_be64(&mic_tm_regs->slow_next_timer_1, MIC_Slow_Next_Timer_table[pmode]);
0064 
0065     value = in_be64(&pmd_regs->pmcr);
0066     /* set bits to zero */
0067     value &= 0xFFFFFFFFFFFFFFF8ull;
0068     /* set bits to next pmode */
0069     value |= pmode;
0070 
0071     out_be64(&pmd_regs->pmcr, value);
0072 
0073 #ifdef DEBUG
0074     /* wait until new pmode appears in status register */
0075     value = in_be64(&pmd_regs->pmsr) & 0x07;
0076     while (value != pmode) {
0077         cpu_relax();
0078         value = in_be64(&pmd_regs->pmsr) & 0x07;
0079     }
0080 
0081     time = jiffies  - time;
0082     time = jiffies_to_msecs(time);
0083     pr_debug("had to wait %lu ms for a transition using " \
0084          "pervasive unit\n", time);
0085 #endif
0086     local_irq_restore(flags);
0087 
0088     return 0;
0089 }
0090 
0091 
0092 int cbe_cpufreq_get_pmode(int cpu)
0093 {
0094     int ret;
0095     struct cbe_pmd_regs __iomem *pmd_regs;
0096 
0097     pmd_regs = cbe_get_cpu_pmd_regs(cpu);
0098     ret = in_be64(&pmd_regs->pmsr) & 0x07;
0099 
0100     return ret;
0101 }
0102