]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/blackfin/interrupts.c
imported Ka-Ro specific additions to U-Boot 2009.08 for TX28
[karo-tx-uboot.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         CSYNC();
99         *pTSCALE = 0x0;
100         *pTCOUNT = MAX_TIM_LOAD;
101         *pTPERIOD = MAX_TIM_LOAD;
102         *pTCNTL = 0x7;
103         CSYNC();
104
105         timestamp = 0;
106         last_time = 0;
107
108         return 0;
109 }
110
111 /*
112  * Any network command or flash
113  * command is started get_timer shall
114  * be called before TCOUNT gets reset,
115  * to implement the accurate timeouts.
116  *
117  * How ever milliconds doesn't return
118  * the number that has been elapsed from
119  * the last reset.
120  *
121  * As get_timer is used in the u-boot
122  * only for timeouts this should be
123  * sufficient
124  */
125 ulong get_timer(ulong base)
126 {
127         ulong milisec;
128
129         /* Number of clocks elapsed */
130         ulong clocks = (MAX_TIM_LOAD - (*pTCOUNT));
131
132         /*
133          * Find if the TCOUNT is reset
134          * timestamp gives the number of times
135          * TCOUNT got reset
136          */
137         if (clocks < last_time)
138                 timestamp++;
139         last_time = clocks;
140
141         /* Get the number of milliseconds */
142         milisec = clocks / (CONFIG_CCLK_HZ / 1000);
143
144         /*
145          * Find the number of millisonds that
146          * got elapsed before this TCOUNT cycle
147          */
148         milisec += timestamp * (MAX_TIM_LOAD / (CONFIG_CCLK_HZ / 1000));
149
150         return (milisec - base);
151 }
152
153 void reset_timer(void)
154 {
155         timer_init();
156 }