summaryrefslogtreecommitdiff
path: root/cpu/bf561/interrupts.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/bf561/interrupts.c')
-rw-r--r--cpu/bf561/interrupts.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/cpu/bf561/interrupts.c b/cpu/bf561/interrupts.c
new file mode 100644
index 0000000000..e314f60d2d
--- /dev/null
+++ b/cpu/bf561/interrupts.c
@@ -0,0 +1,171 @@
+/*
+ * U-boot - interrupts.c Interrupt related routines
+ *
+ * Copyright (c) 2005 blackfin.uclinux.org
+ *
+ * This file is based on interrupts.c
+ * Copyright 1996 Roman Zippel
+ * Copyright 1999 D. Jeff Dionne <jeff@uclinux.org>
+ * Copyright 2000-2001 Lineo, Inc. D. Jefff Dionne <jeff@lineo.ca>
+ * Copyright 2002 Arcturus Networks Inc. MaTed <mated@sympatico.ca>
+ * Copyright 2003 Metrowerks/Motorola
+ * Copyright 2003 Bas Vermeulen <bas@buyways.nl>,
+ * BuyWays B.V. (www.buyways.nl)
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <config.h>
+#include <asm/blackfin.h>
+#include "cpu.h"
+
+static ulong timestamp;
+static ulong last_time;
+static int int_flag;
+
+int irq_flags; /* needed by asm-blackfin/system.h */
+
+/* Functions just to satisfy the linker */
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On BF561 it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+ return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On BF561 it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+ ulong tbclk;
+
+ tbclk = CFG_HZ;
+ return tbclk;
+}
+
+void enable_interrupts(void)
+{
+ restore_flags(int_flag);
+}
+
+int disable_interrupts(void)
+{
+ save_and_cli(int_flag);
+ return 1;
+}
+
+int interrupt_init(void)
+{
+ return (0);
+}
+
+void udelay(unsigned long usec)
+{
+ unsigned long delay, start, stop;
+ unsigned long cclk;
+ cclk = (CONFIG_CCLK_HZ);
+
+ while (usec > 1) {
+ /*
+ * how many clock ticks to delay?
+ * - request(in useconds) * clock_ticks(Hz) / useconds/second
+ */
+ if (usec < 1000) {
+ delay = (usec * (cclk / 244)) >> 12;
+ usec = 0;
+ } else {
+ delay = (1000 * (cclk / 244)) >> 12;
+ usec -= 1000;
+ }
+
+ asm volatile (" %0 = CYCLES;":"=r" (start));
+ do {
+ asm volatile (" %0 = CYCLES; ":"=r" (stop));
+ } while (stop - start < delay);
+ }
+
+ return;
+}
+
+void timer_init(void)
+{
+ *pTCNTL = 0x1;
+ *pTSCALE = 0x0;
+ *pTCOUNT = MAX_TIM_LOAD;
+ *pTPERIOD = MAX_TIM_LOAD;
+ *pTCNTL = 0x7;
+ asm("CSYNC;");
+
+ timestamp = 0;
+ last_time = 0;
+}
+
+/*
+ * Any network command or flash
+ * command is started get_timer shall
+ * be called before TCOUNT gets reset,
+ * to implement the accurate timeouts.
+ *
+ * How ever milliconds doesn't return
+ * the number that has been elapsed from
+ * the last reset.
+ *
+ * As get_timer is used in the u-boot
+ * only for timeouts this should be
+ * sufficient
+ */
+ulong get_timer(ulong base)
+{
+ ulong milisec;
+
+ /* Number of clocks elapsed */
+ ulong clocks = (MAX_TIM_LOAD - (*pTCOUNT));
+
+ /*
+ * Find if the TCOUNT is reset
+ * timestamp gives the number of times
+ * TCOUNT got reset
+ */
+ if (clocks < last_time)
+ timestamp++;
+ last_time = clocks;
+
+ /* Get the number of milliseconds */
+ milisec = clocks / (CONFIG_CCLK_HZ / 1000);
+
+ /*
+ * Find the number of millisonds
+ * that got elapsed before this TCOUNT
+ * cycle
+ */
+ milisec += timestamp * (MAX_TIM_LOAD / (CONFIG_CCLK_HZ / 1000));
+
+ return (milisec - base);
+}