summaryrefslogtreecommitdiff
path: root/polux/linux-2.6.10/arch/arm/mach-mse500/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'polux/linux-2.6.10/arch/arm/mach-mse500/time.c')
-rw-r--r--polux/linux-2.6.10/arch/arm/mach-mse500/time.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/polux/linux-2.6.10/arch/arm/mach-mse500/time.c b/polux/linux-2.6.10/arch/arm/mach-mse500/time.c
new file mode 100644
index 0000000000..08ef5b1204
--- /dev/null
+++ b/polux/linux-2.6.10/arch/arm/mach-mse500/time.c
@@ -0,0 +1,155 @@
+/*
+ * arch/arm/mach-spc2XXc/time.c
+ *
+ * (C) Copyright 2007 Scaleo Chip
+ *
+ * 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 <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/time.h>
+#include <asm/system.h>
+#include <asm/arch/system.h>
+
+#define GPIO (CSP_PIO_PTR)CSP_PIO_BASE
+#define GPIO_NUM 0
+
+//#define TIME_COEF (1000000ull)/(TIMER_CLK/PRESCALER)
+#define TIME_COEF (1000*1000)/(TIMER_CLK/PRESCALER)
+
+/**
+ * Function: spc2XXc_gettimeoffset
+ * Parameters: void
+ * Purpose: Returns number of microseconds since last timer interrupt.
+ * Return Value: unsigned long
+ */
+static unsigned long spc2XXc_gettimeoffset(void)
+{
+ unsigned long temp = (CSP_ST16_CHANNEL_GET_CT(CSP_ST0,KERNEL_TIMER) -
+ CSP_ST16_CHANNEL_GET_CCV(CSP_ST0,KERNEL_TIMER)) * TIME_COEF;
+
+ if((CSP_ST16_GET_SR(CSP_ST0) & ST16_CHEND(KERNEL_TIMER)) == ST16_CHEND(KERNEL_TIMER))
+ temp += CSP_ST16_CHANNEL_GET_CT(CSP_ST0,KERNEL_TIMER) * TIME_COEF;
+
+ return temp;
+/* unsigned int time_current;
+// unsigned long temp;
+ unsigned long long lltemp;
+
+ time_current = CSP_ST16_CHANNEL_GET_CCV(CSP_ST0,KERNEL_TIMER);
+ time_current = CSP_ST16_CHANNEL_GET_CCV(CSP_ST0,KERNEL_TIMER);
+
+ lltemp = (CSP_ST16_CHANNEL_GET_CT(CSP_ST0,KERNEL_TIMER) - time_current) * TIME_COEF;
+// lltemp = ((CSP_ST16_CHANNEL_GET_CT(CSP_ST0,KERNEL_TIMER) - time_current) * 1000000ull);
+// lltemp = lltemp / (TIMER_CLK/PRESCALER);
+
+ if((CSP_ST16_GET_SR(CSP_ST0) & ST16_CHEND(KERNEL_TIMER)) == ST16_CHEND(KERNEL_TIMER)) {
+ lltemp += CSP_ST16_CHANNEL_GET_CT(CSP_ST0,KERNEL_TIMER) * TIME_COEF;
+// lltemp += (CSP_ST16_CHANNEL_GET_CT(CSP_ST0,KERNEL_TIMER) * 1000000ull);
+// lltemp = lltemp / (TIMER_CLK/PRESCALER);
+ }
+
+// temp = (unsigned long)lltemp;
+
+ return (unsigned long)lltemp;
+*/
+} /* spc2XXc_gettimeoffset */
+
+extern void wd_trigger(void);
+
+/**
+ * Function: spc2XXc_timer_interrupt
+ * Parameters: int irq, void *dev_id, struct pt_regs *regs
+ * Purpose: IRQ handler for the timer.
+ * Return Value: irqreturn_t
+ */
+static irqreturn_t spc2XXc_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+// static unsigned char value = 0x01;
+ if(CSP_ST16_GET_SR(CSP_ST0) & ST16_CHEND((KERNEL_TIMER)))
+ {
+ write_seqlock(&xtime_lock);
+ /* If yes, clear it */
+ CSP_ST16_SET_CSR(CSP_ST0,ST16_CHEND((KERNEL_TIMER)));
+ timer_tick(regs);
+ write_sequnlock(&xtime_lock);
+
+ if (wd_auto_trigger)
+ wd_trigger();
+
+ return IRQ_HANDLED;
+ }
+ else
+ return IRQ_NONE; /* not handled */
+} /* spc2XXc_timer_interrupt */
+
+
+static struct irqaction spc2XXc_timer_irq = {
+ .name = "SPC2XXC Timer Tick",
+ .flags = SA_SHIRQ | SA_INTERRUPT,
+ .handler = spc2XXc_timer_interrupt
+}; /* spc2XXc_timer_irq */
+
+/**
+ * Function: spc2XXc_timer_init
+ * Parameters: void
+ * Purpose: Set up timer interrupt.
+ * Return Value: void
+ */
+void __init spc2XXc_timer_init(void)
+{
+ unsigned int int_number;
+
+ /* enable Kernel timer */
+ CSP_ST16_SET_ECR(CSP_ST0, ST16_ST);
+ /* disable interrupt*/
+ CSP_ST16_SET_IDR(CSP_ST0,~0ul);
+ /* disable Simple Timer */
+ CSP_ST16_SET_CR(CSP_ST0,ST16_CHDIS(KERNEL_TIMER));
+ /* reset timer*/
+ CSP_ST16_SET_CR(CSP_ST0,ST16_SWRST);
+ CSP_ST16_SET_CSR(CSP_ST0,ST16_CHEND(KERNEL_TIMER));
+
+ /* Set Prescalar Value CPUCLK/128 + autoreload*/
+ CSP_ST16_CHANNEL_SET_PR(CSP_ST0, KERNEL_TIMER, ST16_AUTOREL | ST16_PRESCAL(PRESCAL_POW));
+
+ /* Configure Counter Value */
+ CSP_ST16_CHANNEL_SET_CT(CSP_ST0, KERNEL_TIMER, ST16_LOAD((TIMER_CLK/PRESCALER)/HZ));
+
+ int_number = get_spc2XXc_interrupt_number("OS Timer");
+ setup_irq(int_number, &spc2XXc_timer_irq);
+
+ CSP_ST16_SET_IER(CSP_ST0,ST16_CHEND(KERNEL_TIMER));
+
+ /* Start channel Timer */
+ CSP_ST16_SET_CR(CSP_ST0,ST16_CHEN(KERNEL_TIMER));
+
+
+} /* spc2XXc_timer_init */
+
+struct sys_timer spc2XXc_timer = {
+ .init = spc2XXc_timer_init,
+ .offset = spc2XXc_gettimeoffset,
+}; /* spc2XXc_timer */
+