linux/arch/mips/mti-sead3/sead3-time.c
<<
>>
Prefs
   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) 2012 MIPS Technologies, Inc.  All rights reserved.
   7 */
   8#include <linux/init.h>
   9
  10#include <asm/cpu.h>
  11#include <asm/setup.h>
  12#include <asm/time.h>
  13#include <asm/irq.h>
  14#include <asm/mips-boards/generic.h>
  15
  16unsigned long cpu_khz;
  17
  18static int mips_cpu_timer_irq;
  19static int mips_cpu_perf_irq;
  20
  21static void mips_timer_dispatch(void)
  22{
  23        do_IRQ(mips_cpu_timer_irq);
  24}
  25
  26static void mips_perf_dispatch(void)
  27{
  28        do_IRQ(mips_cpu_perf_irq);
  29}
  30
  31static void __iomem *status_reg = (void __iomem *)0xbf000410;
  32
  33/*
  34 * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect.
  35 */
  36static unsigned int __init estimate_cpu_frequency(void)
  37{
  38        unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
  39        unsigned int tick = 0;
  40        unsigned int freq;
  41        unsigned int orig;
  42        unsigned long flags;
  43
  44        local_irq_save(flags);
  45
  46        orig = readl(status_reg) & 0x2;               /* get original sample */
  47        /* wait for transition */
  48        while ((readl(status_reg) & 0x2) == orig)
  49                ;
  50        orig = orig ^ 0x2;                            /* flip the bit */
  51
  52        write_c0_count(0);
  53
  54        /* wait 1 second (the sampling clock transitions every 10ms) */
  55        while (tick < 100) {
  56                /* wait for transition */
  57                while ((readl(status_reg) & 0x2) == orig)
  58                        ;
  59                orig = orig ^ 0x2;                            /* flip the bit */
  60                tick++;
  61        }
  62
  63        freq = read_c0_count();
  64
  65        local_irq_restore(flags);
  66
  67        mips_hpt_frequency = freq;
  68
  69        /* Adjust for processor */
  70        if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
  71                (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
  72                freq *= 2;
  73
  74        freq += 5000;        /* rounding */
  75        freq -= freq%10000;
  76
  77        return freq ;
  78}
  79
  80void read_persistent_clock(struct timespec *ts)
  81{
  82        ts->tv_sec = 0;
  83        ts->tv_nsec = 0;
  84}
  85
  86static void __init plat_perf_setup(void)
  87{
  88        if (cp0_perfcount_irq >= 0) {
  89                if (cpu_has_vint)
  90                        set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
  91                mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
  92        }
  93}
  94
  95unsigned int get_c0_compare_int(void)
  96{
  97        if (cpu_has_vint)
  98                set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
  99        mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
 100        return mips_cpu_timer_irq;
 101}
 102
 103void __init plat_time_init(void)
 104{
 105        unsigned int est_freq;
 106
 107        est_freq = estimate_cpu_frequency();
 108
 109        pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000),
 110                (est_freq % 1000000) * 100 / 1000000);
 111
 112        cpu_khz = est_freq / 1000;
 113
 114        mips_scroll_message();
 115
 116        plat_perf_setup();
 117}
 118