1 /* 2 * U-boot - interrupts.c Interrupt related routines 3 * 4 * Copyright (c) 2005-2008 Analog Devices Inc. 5 * 6 * This file is based on interrupts.c 7 * Copyright 1996 Roman Zippel 8 * Copyright 1999 D. Jeff Dionne <jeff@uclinux.org> 9 * Copyright 2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca> 10 * Copyright 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca> 11 * Copyright 2003 Metrowerks/Motorola 12 * Copyright 2003 Bas Vermeulen <bas@buyways.nl>, 13 * BuyWays B.V. (www.buyways.nl) 14 * 15 * (C) Copyright 2000-2004 16 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 17 * 18 * Licensed under the GPL-2 or later. 19 */ 20 21 #include <common.h> 22 #include <config.h> 23 #include <watchdog.h> 24 #include <asm/blackfin.h> 25 #include "cpu.h" 26 27 static ulong timestamp; 28 static ulong last_time; 29 static int int_flag; 30 31 int irq_flags; /* needed by asm-blackfin/system.h */ 32 33 /* Functions just to satisfy the linker */ 34 35 /* 36 * This function is derived from PowerPC code (read timebase as long long). 37 * On Blackfin it just returns the timer value. 38 */ get_ticks(void)39unsigned long long get_ticks(void) 40 { 41 return get_timer(0); 42 } 43 44 /* 45 * This function is derived from PowerPC code (timebase clock frequency). 46 * On Blackfin it returns the number of timer ticks per second. 47 */ get_tbclk(void)48ulong get_tbclk(void) 49 { 50 ulong tbclk; 51 52 tbclk = CONFIG_SYS_HZ; 53 return tbclk; 54 } 55 enable_interrupts(void)56void enable_interrupts(void) 57 { 58 local_irq_restore(int_flag); 59 } 60 disable_interrupts(void)61int disable_interrupts(void) 62 { 63 local_irq_save(int_flag); 64 return 1; 65 } 66 __udelay(unsigned long usec)67void __udelay(unsigned long usec) 68 { 69 unsigned long delay, start, stop; 70 unsigned long cclk; 71 cclk = (CONFIG_CCLK_HZ); 72 73 while (usec > 1) { 74 WATCHDOG_RESET(); 75 76 /* 77 * how many clock ticks to delay? 78 * - request(in useconds) * clock_ticks(Hz) / useconds/second 79 */ 80 if (usec < 1000) { 81 delay = (usec * (cclk / 244)) >> 12; 82 usec = 0; 83 } else { 84 delay = (1000 * (cclk / 244)) >> 12; 85 usec -= 1000; 86 } 87 88 asm volatile (" %0 = CYCLES;" : "=r" (start)); 89 do { 90 asm volatile (" %0 = CYCLES; " : "=r" (stop)); 91 } while (stop - start < delay); 92 } 93 94 return; 95 } 96 97 #define MAX_TIM_LOAD 0xFFFFFFFF timer_init(void)98int timer_init(void) 99 { 100 bfin_write_TCNTL(0x1); 101 CSYNC(); 102 bfin_write_TSCALE(0x0); 103 bfin_write_TCOUNT(MAX_TIM_LOAD); 104 bfin_write_TPERIOD(MAX_TIM_LOAD); 105 bfin_write_TCNTL(0x7); 106 CSYNC(); 107 108 timestamp = 0; 109 last_time = 0; 110 111 return 0; 112 } 113 114 /* 115 * Any network command or flash 116 * command is started get_timer shall 117 * be called before TCOUNT gets reset, 118 * to implement the accurate timeouts. 119 * 120 * How ever milliconds doesn't return 121 * the number that has been elapsed from 122 * the last reset. 123 * 124 * As get_timer is used in the u-boot 125 * only for timeouts this should be 126 * sufficient 127 */ get_timer(ulong base)128ulong get_timer(ulong base) 129 { 130 ulong milisec; 131 132 /* Number of clocks elapsed */ 133 ulong clocks = (MAX_TIM_LOAD - bfin_read_TCOUNT()); 134 135 /* 136 * Find if the TCOUNT is reset 137 * timestamp gives the number of times 138 * TCOUNT got reset 139 */ 140 if (clocks < last_time) 141 timestamp++; 142 last_time = clocks; 143 144 /* Get the number of milliseconds */ 145 milisec = clocks / (CONFIG_CCLK_HZ / 1000); 146 147 /* 148 * Find the number of millisonds that 149 * got elapsed before this TCOUNT cycle 150 */ 151 milisec += timestamp * (MAX_TIM_LOAD / (CONFIG_CCLK_HZ / 1000)); 152 153 return (milisec - base); 154 } 155 reset_timer(void)156void reset_timer(void) 157 { 158 timer_init(); 159 } 160