Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/arch/arm/boot/dts/microchip/   (Linux Kernel Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  sparc-us3-cpufreq.c  Sprache: unbekannt

 
// SPDX-License-Identifier: GPL-2.0-only
/* us3_cpufreq.c: UltraSPARC-III cpu frequency support
 *
 * Copyright (C) 2003 David S. Miller (davem@redhat.com)
 *
 * Many thanks to Dominik Brodowski for fixing up the cpufreq
 * infrastructure in order to make this driver easier to implement.
 */


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/cpufreq.h>
#include <linux/threads.h>
#include <linux/slab.h>
#include <linux/init.h>

#include <asm/head.h>
#include <asm/timer.h>

struct us3_freq_percpu_info {
 struct cpufreq_frequency_table table[4];
};

/* Indexed by cpu number. */
static struct us3_freq_percpu_info *us3_freq_table;

/* UltraSPARC-III has three dividers: 1, 2, and 32.  These are controlled
 * in the Safari config register.
 */

#define SAFARI_CFG_DIV_1 0x0000000000000000UL
#define SAFARI_CFG_DIV_2 0x0000000040000000UL
#define SAFARI_CFG_DIV_32 0x0000000080000000UL
#define SAFARI_CFG_DIV_MASK 0x00000000C0000000UL

static void read_safari_cfg(void *arg)
{
 unsigned long ret, *val = arg;

 __asm__ __volatile__("ldxa [%%g0] %1, %0"
        : "=&r" (ret)
        : "i" (ASI_SAFARI_CONFIG));
 *val = ret;
}

static void update_safari_cfg(void *arg)
{
 unsigned long reg, *new_bits = arg;

 read_safari_cfg(®);
 reg &= ~SAFARI_CFG_DIV_MASK;
 reg |= *new_bits;

 __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
        "membar #Sync"
        : /* no outputs */
        : "r" (reg), "i" (ASI_SAFARI_CONFIG)
        : "memory");
}

static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg)
{
 unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
 unsigned long ret;

 switch (safari_cfg & SAFARI_CFG_DIV_MASK) {
 case SAFARI_CFG_DIV_1:
  ret = clock_tick / 1;
  break;
 case SAFARI_CFG_DIV_2:
  ret = clock_tick / 2;
  break;
 case SAFARI_CFG_DIV_32:
  ret = clock_tick / 32;
  break;
 default:
  BUG();
 }

 return ret;
}

static unsigned int us3_freq_get(unsigned int cpu)
{
 unsigned long reg;

 if (smp_call_function_single(cpu, read_safari_cfg, ®, 1))
  return 0;
 return get_current_freq(cpu, reg);
}

static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index)
{
 unsigned int cpu = policy->cpu;
 unsigned long new_bits, new_freq;

 new_freq = sparc64_get_clock_tick(cpu) / 1000;
 switch (index) {
 case 0:
  new_bits = SAFARI_CFG_DIV_1;
  new_freq /= 1;
  break;
 case 1:
  new_bits = SAFARI_CFG_DIV_2;
  new_freq /= 2;
  break;
 case 2:
  new_bits = SAFARI_CFG_DIV_32;
  new_freq /= 32;
  break;

 default:
  BUG();
 }

 return smp_call_function_single(cpu, update_safari_cfg, &new_bits, 1);
}

static int us3_freq_cpu_init(struct cpufreq_policy *policy)
{
 unsigned int cpu = policy->cpu;
 unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
 struct cpufreq_frequency_table *table =
  &us3_freq_table[cpu].table[0];

 table[0].driver_data = 0;
 table[0].frequency = clock_tick / 1;
 table[1].driver_data = 1;
 table[1].frequency = clock_tick / 2;
 table[2].driver_data = 2;
 table[2].frequency = clock_tick / 32;
 table[3].driver_data = 0;
 table[3].frequency = CPUFREQ_TABLE_END;

 policy->cpuinfo.transition_latency = 0;
 policy->cur = clock_tick;
 policy->freq_table = table;

 return 0;
}

static void us3_freq_cpu_exit(struct cpufreq_policy *policy)
{
 us3_freq_target(policy, 0);
}

static struct cpufreq_driver cpufreq_us3_driver = {
 .name = "UltraSPARC-III",
 .init = us3_freq_cpu_init,
 .verify = cpufreq_generic_frequency_table_verify,
 .target_index = us3_freq_target,
 .get = us3_freq_get,
 .exit = us3_freq_cpu_exit,
};

static int __init us3_freq_init(void)
{
 unsigned long manuf, impl, ver;
 int ret;

 if (tlb_type != cheetah && tlb_type != cheetah_plus)
  return -ENODEV;

 __asm__("rdpr %%ver, %0" : "=r" (ver));
 manuf = ((ver >> 48) & 0xffff);
 impl  = ((ver >> 32) & 0xffff);

 if (manuf == CHEETAH_MANUF &&
     (impl == CHEETAH_IMPL ||
      impl == CHEETAH_PLUS_IMPL ||
      impl == JAGUAR_IMPL ||
      impl == PANTHER_IMPL)) {
  us3_freq_table = kcalloc(NR_CPUS, sizeof(*us3_freq_table),
      GFP_KERNEL);
  if (!us3_freq_table)
   return -ENOMEM;

  ret = cpufreq_register_driver(&cpufreq_us3_driver);
  if (ret)
   kfree(us3_freq_table);

  return ret;
 }

 return -ENODEV;
}

static void __exit us3_freq_exit(void)
{
 cpufreq_unregister_driver(&cpufreq_us3_driver);
 kfree(us3_freq_table);
}

MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-III");
MODULE_LICENSE("GPL");

module_init(us3_freq_init);
module_exit(us3_freq_exit);

Messung V0.5 in Prozent
C=98 H=96 G=96

[Dauer der Verarbeitung: 0.15 Sekunden, vorverarbeitet 2026-09-29]