linux/drivers/cpufreq/ppc_cbe_cpufreq_pervasive.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * pervasive backend for the cbe_cpufreq driver
   4 *
   5 * This driver makes use of the pervasive unit to
   6 * engage the desired frequency.
   7 *
   8 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005-2007
   9 *
  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 DEBUG
  47        long time;
  48#endif
  49
  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 DEBUG
  56        time = jiffies;
  57#endif
  58
  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 DEBUG
  74        /* 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#endif
  86        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