Move c/h files implementing/defining standard library stuff into a new libc directory...
[kugel-rb.git] / firmware / target / arm / s5l8700 / timer-s5l8700.c
blob7152c2f07c7ba5f86a90d851c066351cdb374108
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 Bertrik Sikken
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "config.h"
24 #include "inttypes.h"
25 #include "s5l8700.h"
26 #include "system.h"
27 #include "timer.h"
29 /* Timer driver for the S5L8700
31 The S5L8700 timer resolution is only 16-bit. Larger counts are done by using
32 both the clock-select and the clock prescaler to bring the count down into
33 the range of the 16-bit counter.
36 void INT_TIMERC(void)
38 /* clear interrupt */
39 TCCON = TCCON;
41 if (pfn_timer != NULL) {
42 pfn_timer();
46 bool timer_set(long cycles, bool start)
48 static const int cs_table[] = {1, 2, 4, 6};
49 int prescale, cs;
50 long count;
52 /* stop and clear timer */
53 TCCMD = (1 << 1); /* TD_CLR */
55 /* optionally unregister any previously registered timer user */
56 if (start) {
57 if (pfn_unregister != NULL) {
58 pfn_unregister();
59 pfn_unregister = NULL;
63 /* scale the count down with the clock select */
64 for (cs = 0; cs < 4; cs++) {
65 count = cycles >> cs_table[cs];
66 if ((count < 65536) || (cs == 3)) {
67 break;
71 /* scale the count down with the prescaler */
72 prescale = 1;
73 while (count >= 65536) {
74 count >>= 1;
75 prescale <<= 1;
78 /* configure timer */
79 TCCON = (1 << 12) | /* TD_INT0_EN */
80 (cs << 8) | /* TS_CS */
81 (0 << 4); /* TD_MODE_SEL, 0 = interval mode */
82 TCPRE = prescale - 1;
83 TCDATA0 = count;
84 TCCMD = (1 << 0); /* TD_ENABLE */
86 /* enable interrupt */
87 INTMSK |= INTMSK_TIMERC;
89 return true;
92 bool timer_start(void)
94 TCCMD = (1 << 0); /* TD_ENABLE */
95 return true;
98 void timer_stop(void)
100 TCCMD = (0 << 0); /* TD_ENABLE */