1e8c7c482SRalf Baechle /* 278814465SManuel Lauss * Copyright (C) 2008-2009 Manuel Lauss <manuel.lauss@gmail.com> 3e8c7c482SRalf Baechle * 40c694de1SManuel Lauss * Previous incarnations were: 5e8c7c482SRalf Baechle * Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com> 6e8c7c482SRalf Baechle * Copied and modified Carsten Langgaard's time.c 7e8c7c482SRalf Baechle * 8e8c7c482SRalf Baechle * Carsten Langgaard, carstenl@mips.com 9e8c7c482SRalf Baechle * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. 10e8c7c482SRalf Baechle * 11e8c7c482SRalf Baechle * ######################################################################## 12e8c7c482SRalf Baechle * 13e8c7c482SRalf Baechle * This program is free software; you can distribute it and/or modify it 14e8c7c482SRalf Baechle * under the terms of the GNU General Public License (Version 2) as 15e8c7c482SRalf Baechle * published by the Free Software Foundation. 16e8c7c482SRalf Baechle * 17e8c7c482SRalf Baechle * This program is distributed in the hope it will be useful, but WITHOUT 18e8c7c482SRalf Baechle * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19e8c7c482SRalf Baechle * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20e8c7c482SRalf Baechle * for more details. 21e8c7c482SRalf Baechle * 22e8c7c482SRalf Baechle * You should have received a copy of the GNU General Public License along 23e8c7c482SRalf Baechle * with this program; if not, write to the Free Software Foundation, Inc., 24e8c7c482SRalf Baechle * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 25e8c7c482SRalf Baechle * 26e8c7c482SRalf Baechle * ######################################################################## 27e8c7c482SRalf Baechle * 280c694de1SManuel Lauss * Clocksource/event using the 32.768kHz-clocked Counter1 ('RTC' in the 290c694de1SManuel Lauss * databooks). Firmware/Board init code must enable the counters in the 300c694de1SManuel Lauss * counter control register, otherwise the CP0 counter clocksource/event 310c694de1SManuel Lauss * will be installed instead (and use of 'wait' instruction is prohibited). 32e8c7c482SRalf Baechle */ 33e8c7c482SRalf Baechle 340c694de1SManuel Lauss #include <linux/clockchips.h> 350c694de1SManuel Lauss #include <linux/clocksource.h> 360c694de1SManuel Lauss #include <linux/interrupt.h> 37e8c7c482SRalf Baechle #include <linux/spinlock.h> 38e8c7c482SRalf Baechle 39bdc92d74SRalf Baechle #include <asm/idle.h> 402882b0c6SManuel Lauss #include <asm/processor.h> 41e8c7c482SRalf Baechle #include <asm/time.h> 42e8c7c482SRalf Baechle #include <asm/mach-au1x00/au1000.h> 43e8c7c482SRalf Baechle 440c694de1SManuel Lauss /* 32kHz clock enabled and detected */ 450c694de1SManuel Lauss #define CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S) 460c694de1SManuel Lauss 47a5a1d1c2SThomas Gleixner static u64 au1x_counter1_read(struct clocksource *cs) 480c694de1SManuel Lauss { 491d09de7dSManuel Lauss return alchemy_rdsys(AU1000_SYS_RTCREAD); 500c694de1SManuel Lauss } 510c694de1SManuel Lauss 520c694de1SManuel Lauss static struct clocksource au1x_counter1_clocksource = { 530c694de1SManuel Lauss .name = "alchemy-counter1", 540c694de1SManuel Lauss .read = au1x_counter1_read, 550c694de1SManuel Lauss .mask = CLOCKSOURCE_MASK(32), 560c694de1SManuel Lauss .flags = CLOCK_SOURCE_IS_CONTINUOUS, 578e0d7372SManuel Lauss .rating = 1500, 580c694de1SManuel Lauss }; 590c694de1SManuel Lauss 600c694de1SManuel Lauss static int au1x_rtcmatch2_set_next_event(unsigned long delta, 610c694de1SManuel Lauss struct clock_event_device *cd) 620c694de1SManuel Lauss { 631d09de7dSManuel Lauss delta += alchemy_rdsys(AU1000_SYS_RTCREAD); 640c694de1SManuel Lauss /* wait for register access */ 651d09de7dSManuel Lauss while (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_M21) 660c694de1SManuel Lauss ; 671d09de7dSManuel Lauss alchemy_wrsys(delta, AU1000_SYS_RTCMATCH2); 680c694de1SManuel Lauss 690c694de1SManuel Lauss return 0; 700c694de1SManuel Lauss } 710c694de1SManuel Lauss 720c694de1SManuel Lauss static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id) 730c694de1SManuel Lauss { 740c694de1SManuel Lauss struct clock_event_device *cd = dev_id; 750c694de1SManuel Lauss cd->event_handler(cd); 760c694de1SManuel Lauss return IRQ_HANDLED; 770c694de1SManuel Lauss } 780c694de1SManuel Lauss 790c694de1SManuel Lauss static struct clock_event_device au1x_rtcmatch2_clockdev = { 800c694de1SManuel Lauss .name = "rtcmatch2", 810c694de1SManuel Lauss .features = CLOCK_EVT_FEAT_ONESHOT, 828e0d7372SManuel Lauss .rating = 1500, 830c694de1SManuel Lauss .set_next_event = au1x_rtcmatch2_set_next_event, 8451c870a2SRusty Russell .cpumask = cpu_all_mask, 850c694de1SManuel Lauss }; 860c694de1SManuel Lauss 870c694de1SManuel Lauss static struct irqaction au1x_rtcmatch2_irqaction = { 880c694de1SManuel Lauss .handler = au1x_rtcmatch2_irq, 898b5690f8SYong Zhang .flags = IRQF_TIMER, 900c694de1SManuel Lauss .name = "timer", 910c694de1SManuel Lauss .dev_id = &au1x_rtcmatch2_clockdev, 920c694de1SManuel Lauss }; 930c694de1SManuel Lauss 9478814465SManuel Lauss static int __init alchemy_time_init(unsigned int m2int) 95e8c7c482SRalf Baechle { 960c694de1SManuel Lauss struct clock_event_device *cd = &au1x_rtcmatch2_clockdev; 970c694de1SManuel Lauss unsigned long t; 98e8c7c482SRalf Baechle 9978814465SManuel Lauss au1x_rtcmatch2_clockdev.irq = m2int; 10078814465SManuel Lauss 1010c694de1SManuel Lauss /* Check if firmware (YAMON, ...) has enabled 32kHz and clock 1020c694de1SManuel Lauss * has been detected. If so install the rtcmatch2 clocksource, 1030c694de1SManuel Lauss * otherwise don't bother. Note that both bits being set is by 1040c694de1SManuel Lauss * no means a definite guarantee that the counters actually work 1050c694de1SManuel Lauss * (the 32S bit seems to be stuck set to 1 once a single clock- 1060c694de1SManuel Lauss * edge is detected, hence the timeouts). 107e8c7c482SRalf Baechle */ 1081d09de7dSManuel Lauss if (CNTR_OK != (alchemy_rdsys(AU1000_SYS_CNTRCTRL) & CNTR_OK)) 1090c694de1SManuel Lauss goto cntr_err; 110e8c7c482SRalf Baechle 1110c694de1SManuel Lauss /* 1120c694de1SManuel Lauss * setup counter 1 (RTC) to tick at full speed 1130c694de1SManuel Lauss */ 1140c694de1SManuel Lauss t = 0xffffff; 1151d09de7dSManuel Lauss while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_T1S) && --t) 1160c694de1SManuel Lauss asm volatile ("nop"); 1170c694de1SManuel Lauss if (!t) 1180c694de1SManuel Lauss goto cntr_err; 1190c694de1SManuel Lauss 1201d09de7dSManuel Lauss alchemy_wrsys(0, AU1000_SYS_RTCTRIM); /* 32.768 kHz */ 121e8c7c482SRalf Baechle 1220c694de1SManuel Lauss t = 0xffffff; 1231d09de7dSManuel Lauss while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t) 1240c694de1SManuel Lauss asm volatile ("nop"); 1250c694de1SManuel Lauss if (!t) 1260c694de1SManuel Lauss goto cntr_err; 1271d09de7dSManuel Lauss alchemy_wrsys(0, AU1000_SYS_RTCWRITE); 128e8c7c482SRalf Baechle 1290c694de1SManuel Lauss t = 0xffffff; 1301d09de7dSManuel Lauss while ((alchemy_rdsys(AU1000_SYS_CNTRCTRL) & SYS_CNTRL_C1S) && --t) 1310c694de1SManuel Lauss asm volatile ("nop"); 1320c694de1SManuel Lauss if (!t) 1330c694de1SManuel Lauss goto cntr_err; 1340c694de1SManuel Lauss 1350c694de1SManuel Lauss /* register counter1 clocksource and event device */ 13675c4fd8cSJohn Stultz clocksource_register_hz(&au1x_counter1_clocksource, 32768); 1370c694de1SManuel Lauss 1380c694de1SManuel Lauss cd->shift = 32; 1390c694de1SManuel Lauss cd->mult = div_sc(32768, NSEC_PER_SEC, cd->shift); 1400c694de1SManuel Lauss cd->max_delta_ns = clockevent_delta2ns(0xffffffff, cd); 1418e365790SManuel Lauss cd->min_delta_ns = clockevent_delta2ns(9, cd); /* ~0.28ms */ 1420c694de1SManuel Lauss clockevents_register_device(cd); 14378814465SManuel Lauss setup_irq(m2int, &au1x_rtcmatch2_irqaction); 1440c694de1SManuel Lauss 1450c694de1SManuel Lauss printk(KERN_INFO "Alchemy clocksource installed\n"); 1460c694de1SManuel Lauss 14778814465SManuel Lauss return 0; 148e8c7c482SRalf Baechle 1490c694de1SManuel Lauss cntr_err: 15078814465SManuel Lauss return -1; 15178814465SManuel Lauss } 15278814465SManuel Lauss 15378814465SManuel Lauss static int alchemy_m2inttab[] __initdata = { 15478814465SManuel Lauss AU1000_RTC_MATCH2_INT, 15578814465SManuel Lauss AU1500_RTC_MATCH2_INT, 15678814465SManuel Lauss AU1100_RTC_MATCH2_INT, 15778814465SManuel Lauss AU1550_RTC_MATCH2_INT, 15878814465SManuel Lauss AU1200_RTC_MATCH2_INT, 159809f36c6SManuel Lauss AU1300_RTC_MATCH2_INT, 16078814465SManuel Lauss }; 16178814465SManuel Lauss 16278814465SManuel Lauss void __init plat_time_init(void) 16378814465SManuel Lauss { 16478814465SManuel Lauss int t; 16578814465SManuel Lauss 16678814465SManuel Lauss t = alchemy_get_cputype(); 1678e0d7372SManuel Lauss if (t == ALCHEMY_CPU_UNKNOWN || 1688e0d7372SManuel Lauss alchemy_time_init(alchemy_m2inttab[t])) 1698e0d7372SManuel Lauss cpu_wait = NULL; /* wait doesn't work with r4k timer */ 17078814465SManuel Lauss } 171