rename CFG_ macros to CONFIG_SYS
[oweals/u-boot.git] / cpu / blackfin / interrupts.c
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 <asm/blackfin.h>
24 #include "cpu.h"
25
26 static ulong timestamp;
27 static ulong last_time;
28 static int int_flag;
29
30 int irq_flags;                  /* needed by asm-blackfin/system.h */
31
32 /* Functions just to satisfy the linker */
33
34 /*
35  * This function is derived from PowerPC code (read timebase as long long).
36  * On Blackfin it just returns the timer value.
37  */
38 unsigned long long get_ticks(void)
39 {
40         return get_timer(0);
41 }
42
43 /*
44  * This function is derived from PowerPC code (timebase clock frequency).
45  * On Blackfin it returns the number of timer ticks per second.
46  */
47 ulong get_tbclk(void)
48 {
49         ulong tbclk;
50
51         tbclk = CONFIG_SYS_HZ;
52         return tbclk;
53 }
54
55 void enable_interrupts(void)
56 {
57         local_irq_restore(int_flag);
58 }
59
60 int disable_interrupts(void)
61 {
62         local_irq_save(int_flag);
63         return 1;
64 }
65
66 void udelay(unsigned long usec)
67 {
68         unsigned long delay, start, stop;
69         unsigned long cclk;
70         cclk = (CONFIG_CCLK_HZ);
71
72         while (usec > 1) {
73                 /*
74                  * how many clock ticks to delay?
75                  *  - request(in useconds) * clock_ticks(Hz) / useconds/second
76                  */
77                 if (usec < 1000) {
78                         delay = (usec * (cclk / 244)) >> 12;
79                         usec = 0;
80                 } else {
81                         delay = (1000 * (cclk / 244)) >> 12;
82                         usec -= 1000;
83                 }
84
85                 asm volatile (" %0 = CYCLES;" : "=r" (start));
86                 do {
87                         asm volatile (" %0 = CYCLES; " : "=r" (stop));
88                 } while (stop - start < delay);
89         }
90
91         return;
92 }
93
94 #define MAX_TIM_LOAD    0xFFFFFFFF
95 int timer_init(void)
96 {
97         *pTCNTL = 0x1;
98         *pTSCALE = 0x0;
99         *pTCOUNT = MAX_TIM_LOAD;
100         *pTPERIOD = MAX_TIM_LOAD;
101         *pTCNTL = 0x7;
102         asm("CSYNC;");
103
104         timestamp = 0;
105         last_time = 0;
106
107         return 0;
108 }
109
110 /*
111  * Any network command or flash
112  * command is started get_timer shall
113  * be called before TCOUNT gets reset,
114  * to implement the accurate timeouts.
115  *
116  * How ever milliconds doesn't return
117  * the number that has been elapsed from
118  * the last reset.
119  *
120  * As get_timer is used in the u-boot
121  * only for timeouts this should be
122  * sufficient
123  */
124 ulong get_timer(ulong base)
125 {
126         ulong milisec;
127
128         /* Number of clocks elapsed */
129         ulong clocks = (MAX_TIM_LOAD - (*pTCOUNT));
130
131         /*
132          * Find if the TCOUNT is reset
133          * timestamp gives the number of times
134          * TCOUNT got reset
135          */
136         if (clocks < last_time)
137                 timestamp++;
138         last_time = clocks;
139
140         /* Get the number of milliseconds */
141         milisec = clocks / (CONFIG_CCLK_HZ / 1000);
142
143         /*
144          * Find the number of millisonds that
145          * got elapsed before this TCOUNT cycle
146          */
147         milisec += timestamp * (MAX_TIM_LOAD / (CONFIG_CCLK_HZ / 1000));
148
149         return (milisec - base);
150 }
151
152 void reset_timer(void)
153 {
154         timestamp = 0;
155 }