1 /* 2 * Copyright (C) 2000, 2001 Broadcom Corporation 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 #include <linux/clocksource.h> 15 #include <linux/sched_clock.h> 16 17 #include <asm/addrspace.h> 18 #include <asm/io.h> 19 #include <asm/time.h> 20 21 #include <asm/sibyte/sb1250.h> 22 #include <asm/sibyte/sb1250_regs.h> 23 #include <asm/sibyte/sb1250_int.h> 24 #include <asm/sibyte/sb1250_scd.h> 25 26 #define SB1250_HPT_NUM 3 27 #define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */ 28 29 /* 30 * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over 31 * again. 32 */ 33 static inline u64 sb1250_hpt_get_cycles(void) 34 { 35 unsigned int count; 36 void __iomem *addr; 37 38 addr = IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT)); 39 count = G_SCD_TIMER_CNT(__raw_readq(addr)); 40 41 return SB1250_HPT_VALUE - count; 42 } 43 44 static u64 sb1250_hpt_read(struct clocksource *cs) 45 { 46 return sb1250_hpt_get_cycles(); 47 } 48 49 struct clocksource bcm1250_clocksource = { 50 .name = "bcm1250-counter-3", 51 .rating = 200, 52 .read = sb1250_hpt_read, 53 .mask = CLOCKSOURCE_MASK(23), 54 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 55 }; 56 57 static u64 notrace sb1250_read_sched_clock(void) 58 { 59 return sb1250_hpt_get_cycles(); 60 } 61 62 void __init sb1250_clocksource_init(void) 63 { 64 struct clocksource *cs = &bcm1250_clocksource; 65 66 /* Setup hpt using timer #3 but do not enable irq for it */ 67 __raw_writeq(0, 68 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, 69 R_SCD_TIMER_CFG))); 70 __raw_writeq(SB1250_HPT_VALUE, 71 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, 72 R_SCD_TIMER_INIT))); 73 __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS, 74 IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, 75 R_SCD_TIMER_CFG))); 76 77 clocksource_register_hz(cs, V_SCD_TIMER_FREQ); 78 79 sched_clock_register(sb1250_read_sched_clock, 23, V_SCD_TIMER_FREQ); 80 } 81