Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 "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 
 19 int use_cyclone = 0;
 20 static void __iomem *cyclone_ptr;
 21 
 22 static cycle_t read_cyclone(void)
 23 {
 24         return (cycle_t)readl(cyclone_ptr);
 25 }
 26 
 27 static struct clocksource clocksource_cyclone = {
 28         .name           = "cyclone",
 29         .rating         = 250,
 30         .read           = read_cyclone,
 31         .mask           = CYCLONE_TIMER_MASK,
 32         .mult           = 10,
 33         .shift          = 0,
 34         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 35 };
 36 
 37 static int __init init_cyclone_clocksource(void)
 38 {
 39         unsigned long base;     /* saved value from CBAR */
 40         unsigned long offset;
 41         u32 __iomem* volatile cyclone_timer;    /* Cyclone MPMC0 register */
 42         u32 __iomem* reg;
 43         int i;
 44 
 45         /* make sure we're on a summit box: */
 46         if (!use_cyclone)
 47                 return -ENODEV;
 48 
 49         printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
 50 
 51         /* find base address: */
 52         offset = CYCLONE_CBAR_ADDR;
 53         reg = ioremap_nocache(offset, sizeof(reg));
 54         if (!reg) {
 55                 printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
 56                 return -ENODEV;
 57         }
 58         /* even on 64bit systems, this is only 32bits: */
 59         base = readl(reg);
 60         if (!base) {
 61                 printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
 62                 return -ENODEV;
 63         }
 64         iounmap(reg);
 65 
 66         /* setup PMCC: */
 67         offset = base + CYCLONE_PMCC_OFFSET;
 68         reg = ioremap_nocache(offset, sizeof(reg));
 69         if (!reg) {
 70                 printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
 71                 return -ENODEV;
 72         }
 73         writel(0x00000001,reg);
 74         iounmap(reg);
 75 
 76         /* setup MPCS: */
 77         offset = base + CYCLONE_MPCS_OFFSET;
 78         reg = ioremap_nocache(offset, sizeof(reg));
 79         if (!reg) {
 80                 printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
 81                 return -ENODEV;
 82         }
 83         writel(0x00000001,reg);
 84         iounmap(reg);
 85 
 86         /* map in cyclone_timer: */
 87         offset = base + CYCLONE_MPMC_OFFSET;
 88         cyclone_timer = ioremap_nocache(offset, sizeof(u64));
 89         if (!cyclone_timer) {
 90                 printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
 91                 return -ENODEV;
 92         }
 93 
 94         /* quick test to make sure its ticking: */
 95         for (i = 0; i < 3; i++){
 96                 u32 old = readl(cyclone_timer);
 97                 int stall = 100;
 98 
 99                 while (stall--)
100                         barrier();
101 
102                 if (readl(cyclone_timer) == old) {
103                         printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
104                         iounmap(cyclone_timer);
105                         cyclone_timer = NULL;
106                         return -ENODEV;
107                 }
108         }
109         cyclone_ptr = cyclone_timer;
110 
111         /* sort out mult/shift values: */
112         clocksource_cyclone.shift = 22;
113         clocksource_cyclone.mult = clocksource_hz2mult(CYCLONE_TIMER_FREQ,
114                                                 clocksource_cyclone.shift);
115 
116         return clocksource_register(&clocksource_cyclone);
117 }
118 
119 arch_initcall(init_cyclone_clocksource);
120 
  This page was automatically generated by the LXR engine.