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 19int use_cyclone = 0; 20static void __iomem *cyclone_ptr; 21 22static cycle_t read_cyclone(void) 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 .mult = 10, 33 .shift = 0, 34 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 35}; 36 37static 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 119arch_initcall(init_cyclone_clocksource); 120