1/* 2 * arch/arm/mach-at91/at91x40_time.c 3 * 4 * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 */ 20 21#include <linux/kernel.h> 22#include <linux/init.h> 23#include <linux/interrupt.h> 24#include <linux/irq.h> 25#include <linux/time.h> 26#include <linux/io.h> 27#include <mach/hardware.h> 28#include <asm/mach/time.h> 29#include <mach/at91_tc.h> 30 31/* 32 * 3 counter/timer units present. 33 */ 34#define AT91_TC_CLK0BASE 0 35#define AT91_TC_CLK1BASE 0x40 36#define AT91_TC_CLK2BASE 0x80 37 38static unsigned long at91x40_gettimeoffset(void) 39{ 40 return (at91_sys_read(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 / (AT91X40_MASTER_CLOCK / 128)); 41} 42 43static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id) 44{ 45 at91_sys_read(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_SR); 46 timer_tick(); 47 return IRQ_HANDLED; 48} 49 50static struct irqaction at91x40_timer_irq = { 51 .name = "at91_tick", 52 .flags = IRQF_DISABLED | IRQF_TIMER, 53 .handler = at91x40_timer_interrupt 54}; 55 56void __init at91x40_timer_init(void) 57{ 58 unsigned int v; 59 60 at91_sys_write(AT91_TC + AT91_TC_BCR, 0); 61 v = at91_sys_read(AT91_TC + AT91_TC_BMR); 62 v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE; 63 at91_sys_write(AT91_TC + AT91_TC_BMR, v); 64 65 at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CCR, AT91_TC_CLKDIS); 66 at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CMR, (AT91_TC_TIMER_CLOCK4 | AT91_TC_CPCTRG)); 67 at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_IDR, 0xffffffff); 68 at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_RC, (AT91X40_MASTER_CLOCK / 128) / HZ - 1); 69 at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_IER, (1<<4)); 70 71 setup_irq(AT91X40_ID_TC1, &at91x40_timer_irq); 72 73 at91_sys_write(AT91_TC + AT91_TC_CLK1BASE + AT91_TC_CCR, (AT91_TC_SWTRG | AT91_TC_CLKEN)); 74} 75 76struct sys_timer at91x40_timer = { 77 .init = at91x40_timer_init, 78 .offset = at91x40_gettimeoffset, 79}; 80