Blame view
arch/arm/mach-pnx4008/time.c
3.52 KB
78818e477 [ARM] 3466/1: [2/... |
1 2 3 4 5 6 7 8 9 10 11 12 |
/* * arch/arm/mach-pnx4008/time.c * * PNX4008 Timers * * Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin <source@mvista.com> * * 2005 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ |
78818e477 [ARM] 3466/1: [2/... |
13 14 15 16 17 18 19 20 |
#include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/module.h> #include <linux/kallsyms.h> |
5904a7f91 [ARM] 3709/1: pnx... |
21 22 23 |
#include <linux/time.h> #include <linux/timex.h> #include <linux/irq.h> |
fced80c73 [ARM] Convert asm... |
24 |
#include <linux/io.h> |
78818e477 [ARM] 3466/1: [2/... |
25 26 |
#include <asm/system.h> |
a09e64fbc [ARM] Move includ... |
27 |
#include <mach/hardware.h> |
78818e477 [ARM] 3466/1: [2/... |
28 |
#include <asm/leds.h> |
78818e477 [ARM] 3466/1: [2/... |
29 |
#include <asm/mach/time.h> |
78818e477 [ARM] 3466/1: [2/... |
30 |
#include <asm/errno.h> |
2781681ea ARM: PNX4008: rem... |
31 |
#include "time.h" |
78818e477 [ARM] 3466/1: [2/... |
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
/*! Note: all timers are UPCOUNTING */ /*! * Returns number of us since last clock interrupt. Note that interrupts * will have been disabled by do_gettimeoffset() */ static unsigned long pnx4008_gettimeoffset(void) { u32 ticks_to_match = __raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER); u32 elapsed = LATCH - ticks_to_match; return (elapsed * (tick_nsec / 1000)) / LATCH; } /*! * IRQ handler for the timer */ |
0cd61b68c Initial blind fix... |
49 |
static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id) |
78818e477 [ARM] 3466/1: [2/... |
50 51 |
{ if (__raw_readl(HSTIM_INT) & MATCH0_INT) { |
78818e477 [ARM] 3466/1: [2/... |
52 |
do { |
0cd61b68c Initial blind fix... |
53 |
timer_tick(); |
78818e477 [ARM] 3466/1: [2/... |
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
/* * this algorithm takes care of possible delay * for this interrupt handling longer than a normal * timer period */ __raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH, HSTIM_MATCH0); __raw_writel(MATCH0_INT, HSTIM_INT); /* clear interrupt */ /* * The goal is to keep incrementing HSTIM_MATCH0 * register until HSTIM_MATCH0 indicates time after * what HSTIM_COUNTER indicates. */ } while ((signed) (__raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER)) < 0); |
78818e477 [ARM] 3466/1: [2/... |
72 73 74 75 76 77 78 |
} return IRQ_HANDLED; } static struct irqaction pnx4008_timer_irq = { .name = "PNX4008 Tick Timer", |
b30fabada Add IRQF_IRQPOLL ... |
79 |
.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, |
78818e477 [ARM] 3466/1: [2/... |
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
.handler = pnx4008_timer_interrupt }; /*! * Set up timer and timer interrupt. */ static __init void pnx4008_setup_timer(void) { __raw_writel(RESET_COUNT, MSTIM_CTRL); while (__raw_readl(MSTIM_COUNTER)) ; /* wait for reset to complete. 100% guarantee event */ __raw_writel(0, MSTIM_CTRL); /* stop the timer */ __raw_writel(0, MSTIM_MCTRL); __raw_writel(RESET_COUNT, HSTIM_CTRL); while (__raw_readl(HSTIM_COUNTER)) ; /* wait for reset to complete. 100% guarantee event */ __raw_writel(0, HSTIM_CTRL); __raw_writel(0, HSTIM_MCTRL); __raw_writel(0, HSTIM_CCR); __raw_writel(12, HSTIM_PMATCH); /* scale down to 1 MHZ */ __raw_writel(LATCH, HSTIM_MATCH0); __raw_writel(MR0_INT, HSTIM_MCTRL); setup_irq(HSTIMER_INT, &pnx4008_timer_irq); __raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL); /*start timer, stop when JTAG active */ } /* Timer Clock Control in PM register */ #define TIMCLK_CTRL_REG IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC)) #define WATCHDOG_CLK_EN 1 #define TIMER_CLK_EN 2 /* HS and MS timers? */ static u32 timclk_ctrl_reg_save; void pnx4008_timer_suspend(void) { timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG); __raw_writel(0, TIMCLK_CTRL_REG); /* disable timers */ } void pnx4008_timer_resume(void) { __raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG); /* enable timers */ } struct sys_timer pnx4008_timer = { .init = pnx4008_setup_timer, .offset = pnx4008_gettimeoffset, .suspend = pnx4008_timer_suspend, .resume = pnx4008_timer_resume, }; |