linux/arch/mips/kernel/csrc-powertv.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2008 Scientific-Atlanta, Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License
   6 * as published by the Free Software Foundation; either version 2
   7 * of the License, or (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17 */
  18/*
  19 * The file comes from kernel/csrc-r4k.c
  20 */
  21#include <linux/clocksource.h>
  22#include <linux/init.h>
  23
  24#include <asm/time.h>                   /* Not included in linux/time.h */
  25
  26#include <asm/mach-powertv/asic_regs.h>
  27#include "powertv-clock.h"
  28
  29/* MIPS PLL Register Definitions */
  30#define PLL_GET_M(x)            (((x) >> 8) & 0x000000FF)
  31#define PLL_GET_N(x)            (((x) >> 16) & 0x000000FF)
  32#define PLL_GET_P(x)            (((x) >> 24) & 0x00000007)
  33
  34/*
  35 * returns:  Clock frequency in kHz
  36 */
  37unsigned int __init mips_get_pll_freq(void)
  38{
  39        unsigned int pll_reg, m, n, p;
  40        unsigned int fin = 54000; /* Base frequency in kHz */
  41        unsigned int fout;
  42
  43        /* Read PLL register setting */
  44        pll_reg = asic_read(mips_pll_setup);
  45        m = PLL_GET_M(pll_reg);
  46        n = PLL_GET_N(pll_reg);
  47        p = PLL_GET_P(pll_reg);
  48        pr_info("MIPS PLL Register:0x%x  M=%d  N=%d  P=%d\n", pll_reg, m, n, p);
  49
  50        /* Calculate clock frequency = (2 * N * 54MHz) / (M * (2**P)) */
  51        fout = ((2 * n * fin) / (m * (0x01 << p)));
  52
  53        pr_info("MIPS Clock Freq=%d kHz\n", fout);
  54
  55        return fout;
  56}
  57
  58static cycle_t c0_hpt_read(struct clocksource *cs)
  59{
  60        return read_c0_count();
  61}
  62
  63static struct clocksource clocksource_mips = {
  64        .name           = "powertv-counter",
  65        .read           = c0_hpt_read,
  66        .mask           = CLOCKSOURCE_MASK(32),
  67        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
  68};
  69
  70static void __init powertv_c0_hpt_clocksource_init(void)
  71{
  72        unsigned int pll_freq = mips_get_pll_freq();
  73
  74        pr_info("CPU frequency %d.%02d MHz\n", pll_freq / 1000,
  75                (pll_freq % 1000) * 100 / 1000);
  76
  77        mips_hpt_frequency = pll_freq / 2 * 1000;
  78
  79        clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
  80
  81        clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
  82}
  83
  84/**
  85 * struct tim_c - free running counter
  86 * @hi: High 16 bits of the counter
  87 * @lo: Low 32 bits of the counter
  88 *
  89 * Lays out the structure of the free running counter in memory. This counter
  90 * increments at a rate of 27 MHz/8 on all platforms.
  91 */
  92struct tim_c {
  93        unsigned int hi;
  94        unsigned int lo;
  95};
  96
  97static struct tim_c *tim_c;
  98
  99static cycle_t tim_c_read(struct clocksource *cs)
 100{
 101        unsigned int hi;
 102        unsigned int next_hi;
 103        unsigned int lo;
 104
 105        hi = readl(&tim_c->hi);
 106
 107        for (;;) {
 108                lo = readl(&tim_c->lo);
 109                next_hi = readl(&tim_c->hi);
 110                if (next_hi == hi)
 111                        break;
 112                hi = next_hi;
 113        }
 114
 115pr_crit("%s: read %llx\n", __func__, ((u64) hi << 32) | lo);
 116        return ((u64) hi << 32) | lo;
 117}
 118
 119#define TIM_C_SIZE              48              /* # bits in the timer */
 120
 121static struct clocksource clocksource_tim_c = {
 122        .name           = "powertv-tim_c",
 123        .read           = tim_c_read,
 124        .mask           = CLOCKSOURCE_MASK(TIM_C_SIZE),
 125        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 126};
 127
 128/**
 129 * powertv_tim_c_clocksource_init - set up a clock source for the TIM_C clock
 130 *
 131 * We know that TIM_C counts at 27 MHz/8, so each cycle corresponds to
 132 * 1 / (27,000,000/8) seconds.
 133 */
 134static void __init powertv_tim_c_clocksource_init(void)
 135{
 136        const unsigned long     counts_per_second = 27000000 / 8;
 137
 138        clocksource_tim_c.rating = 200;
 139
 140        clocksource_register_hz(&clocksource_tim_c, counts_per_second);
 141        tim_c = (struct tim_c *) asic_reg_addr(tim_ch);
 142}
 143
 144/**
 145 powertv_clocksource_init - initialize all clocksources
 146 */
 147void __init powertv_clocksource_init(void)
 148{
 149        powertv_c0_hpt_clocksource_init();
 150        powertv_tim_c_clocksource_init();
 151}
 152