linux/drivers/clocksource/cyclone.c
<<
>>
Prefs
   1#include <linux/clocksource.h>
   2#include <linux/string.h>
   3#include <linux/errno.h>
   4#include <linux/timex.h>
   5#include <linux/init.h>
   6
   7#include <asm/pgtable.h>
   8#include <asm/io.h>
   9
  10#include <asm/mach_timer.h>
  11
  12#define CYCLONE_CBAR_ADDR       0xFEB00CD0      /* base address ptr */
  13#define CYCLONE_PMCC_OFFSET     0x51A0          /* offset to control register */
  14#define CYCLONE_MPCS_OFFSET     0x51A8          /* offset to select register */
  15#define CYCLONE_MPMC_OFFSET     0x51D0          /* offset to count register */
  16#define CYCLONE_TIMER_FREQ      99780000        /* 100Mhz, but not really */
  17#define CYCLONE_TIMER_MASK      CLOCKSOURCE_MASK(32) /* 32 bit mask */
  18
  19int use_cyclone = 0;
  20static void __iomem *cyclone_ptr;
  21
  22static cycle_t read_cyclone(struct clocksource *cs)
  23{
  24        return (cycle_t)readl(cyclone_ptr);
  25}
  26
  27static struct clocksource clocksource_cyclone = {
  28        .name           = "cyclone",
  29        .rating         = 250,
  30        .read           = read_cyclone,
  31        .mask           = CYCLONE_TIMER_MASK,
  32        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
  33};
  34
  35static int __init init_cyclone_clocksource(void)
  36{
  37        unsigned long base;     /* saved value from CBAR */
  38        unsigned long offset;
  39        u32 __iomem* volatile cyclone_timer;    /* Cyclone MPMC0 register */
  40        u32 __iomem* reg;
  41        int i;
  42
  43        /* make sure we're on a summit box: */
  44        if (!use_cyclone)
  45                return -ENODEV;
  46
  47        printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
  48
  49        /* find base address: */
  50        offset = CYCLONE_CBAR_ADDR;
  51        reg = ioremap_nocache(offset, sizeof(reg));
  52        if (!reg) {
  53                printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
  54                return -ENODEV;
  55        }
  56        /* even on 64bit systems, this is only 32bits: */
  57        base = readl(reg);
  58        iounmap(reg);
  59        if (!base) {
  60                printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
  61                return -ENODEV;
  62        }
  63
  64        /* setup PMCC: */
  65        offset = base + CYCLONE_PMCC_OFFSET;
  66        reg = ioremap_nocache(offset, sizeof(reg));
  67        if (!reg) {
  68                printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
  69                return -ENODEV;
  70        }
  71        writel(0x00000001,reg);
  72        iounmap(reg);
  73
  74        /* setup MPCS: */
  75        offset = base + CYCLONE_MPCS_OFFSET;
  76        reg = ioremap_nocache(offset, sizeof(reg));
  77        if (!reg) {
  78                printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
  79                return -ENODEV;
  80        }
  81        writel(0x00000001,reg);
  82        iounmap(reg);
  83
  84        /* map in cyclone_timer: */
  85        offset = base + CYCLONE_MPMC_OFFSET;
  86        cyclone_timer = ioremap_nocache(offset, sizeof(u64));
  87        if (!cyclone_timer) {
  88                printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
  89                return -ENODEV;
  90        }
  91
  92        /* quick test to make sure its ticking: */
  93        for (i = 0; i < 3; i++){
  94                u32 old = readl(cyclone_timer);
  95                int stall = 100;
  96
  97                while (stall--)
  98                        barrier();
  99
 100                if (readl(cyclone_timer) == old) {
 101                        printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
 102                        iounmap(cyclone_timer);
 103                        cyclone_timer = NULL;
 104                        return -ENODEV;
 105                }
 106        }
 107        cyclone_ptr = cyclone_timer;
 108
 109        return clocksource_register_hz(&clocksource_cyclone,
 110                                        CYCLONE_TIMER_FREQ);
 111}
 112
 113arch_initcall(init_cyclone_clocksource);
 114
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.