root/arch/mips/kernel/csrc-r4k.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. c0_hpt_read
  2. r4k_read_sched_clock
  3. rdhwr_count
  4. rdhwr_count_usable
  5. init_r4k_clocksource

   1 /*
   2  * This file is subject to the terms and conditions of the GNU General Public
   3  * License.  See the file "COPYING" in the main directory of this archive
   4  * for more details.
   5  *
   6  * Copyright (C) 2007 by Ralf Baechle
   7  */
   8 #include <linux/clocksource.h>
   9 #include <linux/init.h>
  10 #include <linux/sched_clock.h>
  11 
  12 #include <asm/time.h>
  13 
  14 static u64 c0_hpt_read(struct clocksource *cs)
  15 {
  16         return read_c0_count();
  17 }
  18 
  19 static struct clocksource clocksource_mips = {
  20         .name           = "MIPS",
  21         .read           = c0_hpt_read,
  22         .mask           = CLOCKSOURCE_MASK(32),
  23         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
  24 };
  25 
  26 static u64 __maybe_unused notrace r4k_read_sched_clock(void)
  27 {
  28         return read_c0_count();
  29 }
  30 
  31 static inline unsigned int rdhwr_count(void)
  32 {
  33         unsigned int count;
  34 
  35         __asm__ __volatile__(
  36         "       .set push\n"
  37         "       .set mips32r2\n"
  38         "       rdhwr   %0, $2\n"
  39         "       .set pop\n"
  40         : "=r" (count));
  41 
  42         return count;
  43 }
  44 
  45 static bool rdhwr_count_usable(void)
  46 {
  47         unsigned int prev, curr, i;
  48 
  49         /*
  50          * Older QEMUs have a broken implementation of RDHWR for the CP0 count
  51          * which always returns a constant value. Try to identify this and don't
  52          * use it in the VDSO if it is broken. This workaround can be removed
  53          * once the fix has been in QEMU stable for a reasonable amount of time.
  54          */
  55         for (i = 0, prev = rdhwr_count(); i < 100; i++) {
  56                 curr = rdhwr_count();
  57 
  58                 if (curr != prev)
  59                         return true;
  60 
  61                 prev = curr;
  62         }
  63 
  64         pr_warn("Not using R4K clocksource in VDSO due to broken RDHWR\n");
  65         return false;
  66 }
  67 
  68 int __init init_r4k_clocksource(void)
  69 {
  70         if (!cpu_has_counter || !mips_hpt_frequency)
  71                 return -ENXIO;
  72 
  73         /* Calculate a somewhat reasonable rating value */
  74         clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
  75 
  76         /*
  77          * R2 onwards makes the count accessible to user mode so it can be used
  78          * by the VDSO (HWREna is configured by configure_hwrena()).
  79          */
  80         if (cpu_has_mips_r2_r6 && rdhwr_count_usable())
  81                 clocksource_mips.archdata.vdso_clock_mode = VDSO_CLOCK_R4K;
  82 
  83         clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
  84 
  85 #ifndef CONFIG_CPU_FREQ
  86         sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency);
  87 #endif
  88 
  89         return 0;
  90 }

/* [<][>][^][v][top][bottom][index][help] */