1/* 2 * (C) Copyright 2002 3 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24#include <common.h> 25#include <malloc.h> 26#include <asm/io.h> 27#include <asm/i8254.h> 28#include <asm/ibmpc.h> 29 30struct timer_isr_function { 31 struct timer_isr_function *next; 32 timer_fnc_t *isr_func; 33}; 34 35static struct timer_isr_function *first_timer_isr = NULL; 36static volatile unsigned long system_ticks = 0; 37 38/* 39 * register_timer_isr() allows multiple architecture and board specific 40 * functions to be called every millisecond. Keep the execution time of 41 * each function as low as possible 42 */ 43int register_timer_isr (timer_fnc_t *isr_func) 44{ 45 struct timer_isr_function *new_func; 46 struct timer_isr_function *temp; 47 int flag; 48 49 new_func = malloc(sizeof(struct timer_isr_function)); 50 51 if (new_func == NULL) 52 return 1; 53 54 new_func->isr_func = isr_func + gd->reloc_off; 55 new_func->next = NULL; 56 57 /* 58 * Don't allow timer interrupts while the 59 * linked list is being modified 60 */ 61 flag = disable_interrupts (); 62 63 if (first_timer_isr == NULL) { 64 first_timer_isr = new_func; 65 } else { 66 temp = first_timer_isr; 67 while (temp->next != NULL) 68 temp = temp->next; 69 temp->next = new_func; 70 } 71 72 if (flag) 73 enable_interrupts (); 74 75 return 0; 76} 77 78/* 79 * timer_isr() MUST be the registered interrupt handler for 80 */ 81void timer_isr(void *unused) 82{ 83 struct timer_isr_function *temp = first_timer_isr; 84 85 system_ticks++; 86 87 /* Execute each registered function */ 88 while (temp != NULL) { 89 temp->isr_func (); 90 temp = temp->next; 91 } 92} 93 94void reset_timer (void) 95{ 96 system_ticks = 0; 97} 98 99ulong get_timer (ulong base) 100{ 101 return (system_ticks - base); 102} 103 104void set_timer (ulong t) 105{ 106 system_ticks = t; 107} 108