blob: abb7dc1d1ddfb0693ae5e33b6a01da0b61d161bf [file] [log] [blame]
Aubrey Li51185db2007-03-20 18:16:24 +08001/*
Bin Meng75574052016-02-05 19:30:11 -08002 * U-Boot - interrupts.c Interrupt related routines
Aubrey Li51185db2007-03-20 18:16:24 +08003 *
Mike Frysinger94bae5c2008-03-30 15:46:13 -04004 * Copyright (c) 2005-2008 Analog Devices Inc.
Aubrey Li51185db2007-03-20 18:16:24 +08005 *
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.
Aubrey Li51185db2007-03-20 18:16:24 +080017 *
Mike Frysinger94bae5c2008-03-30 15:46:13 -040018 * Licensed under the GPL-2 or later.
Aubrey Li51185db2007-03-20 18:16:24 +080019 */
20
21#include <common.h>
Aubrey Li51185db2007-03-20 18:16:24 +080022#include <config.h>
Mike Frysingerf3352e32009-10-09 02:24:33 -040023#include <watchdog.h>
Aubrey Li51185db2007-03-20 18:16:24 +080024#include <asm/blackfin.h>
25#include "cpu.h"
26
27static ulong timestamp;
28static ulong last_time;
29static int int_flag;
30
31int 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).
Mike Frysinger94bae5c2008-03-30 15:46:13 -040037 * On Blackfin it just returns the timer value.
Aubrey Li51185db2007-03-20 18:16:24 +080038 */
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).
Mike Frysinger94bae5c2008-03-30 15:46:13 -040046 * On Blackfin it returns the number of timer ticks per second.
Aubrey Li51185db2007-03-20 18:16:24 +080047 */
48ulong get_tbclk(void)
49{
Masahiro Yamada04cfea52016-09-06 22:17:38 +090050 return CONFIG_SYS_HZ;
Aubrey Li51185db2007-03-20 18:16:24 +080051}
52
53void enable_interrupts(void)
54{
Mike Frysinger94bae5c2008-03-30 15:46:13 -040055 local_irq_restore(int_flag);
Aubrey Li51185db2007-03-20 18:16:24 +080056}
57
58int disable_interrupts(void)
59{
Mike Frysinger94bae5c2008-03-30 15:46:13 -040060 local_irq_save(int_flag);
Aubrey Li51185db2007-03-20 18:16:24 +080061 return 1;
62}
63
Ingo van Lilf0f778a2009-11-24 14:09:21 +010064void __udelay(unsigned long usec)
Aubrey Li51185db2007-03-20 18:16:24 +080065{
66 unsigned long delay, start, stop;
67 unsigned long cclk;
68 cclk = (CONFIG_CCLK_HZ);
69
70 while (usec > 1) {
Mike Frysingerf3352e32009-10-09 02:24:33 -040071 WATCHDOG_RESET();
72
Aubrey Li51185db2007-03-20 18:16:24 +080073 /*
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
Mike Frysinger94bae5c2008-03-30 15:46:13 -040085 asm volatile (" %0 = CYCLES;" : "=r" (start));
Aubrey Li51185db2007-03-20 18:16:24 +080086 do {
Mike Frysinger94bae5c2008-03-30 15:46:13 -040087 asm volatile (" %0 = CYCLES; " : "=r" (stop));
Aubrey Li51185db2007-03-20 18:16:24 +080088 } while (stop - start < delay);
89 }
90
91 return;
92}
93
Mike Frysinger94bae5c2008-03-30 15:46:13 -040094#define MAX_TIM_LOAD 0xFFFFFFFF
95int timer_init(void)
Aubrey Li51185db2007-03-20 18:16:24 +080096{
Mike Frysinger3b7ed5a2009-11-12 18:42:53 -050097 bfin_write_TCNTL(0x1);
Graf Yang52840a72009-05-19 04:40:08 -040098 CSYNC();
Mike Frysinger3b7ed5a2009-11-12 18:42:53 -050099 bfin_write_TSCALE(0x0);
100 bfin_write_TCOUNT(MAX_TIM_LOAD);
101 bfin_write_TPERIOD(MAX_TIM_LOAD);
102 bfin_write_TCNTL(0x7);
Graf Yang52840a72009-05-19 04:40:08 -0400103 CSYNC();
Aubrey Li51185db2007-03-20 18:16:24 +0800104
105 timestamp = 0;
106 last_time = 0;
Mike Frysinger94bae5c2008-03-30 15:46:13 -0400107
108 return 0;
Aubrey Li51185db2007-03-20 18:16:24 +0800109}
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 */
125ulong get_timer(ulong base)
126{
127 ulong milisec;
128
129 /* Number of clocks elapsed */
Mike Frysinger3b7ed5a2009-11-12 18:42:53 -0500130 ulong clocks = (MAX_TIM_LOAD - bfin_read_TCOUNT());
Aubrey Li51185db2007-03-20 18:16:24 +0800131
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 /*
Mike Frysinger94bae5c2008-03-30 15:46:13 -0400145 * Find the number of millisonds that
146 * got elapsed before this TCOUNT cycle
Aubrey Li51185db2007-03-20 18:16:24 +0800147 */
148 milisec += timestamp * (MAX_TIM_LOAD / (CONFIG_CCLK_HZ / 1000));
149
150 return (milisec - base);
151}