Initial import of OsmocomBB into git repository
[osmocom-bb.git] / src / target / firmware / calypso / timer.c
1 /* Calypso DBB internal Timer Driver */
2
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
4  *
5  * All Rights Reserved
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22
23 #include <stdio.h>
24 #include <memory.h>
25 #include <stdint.h>
26
27 #include <calypso/timer.h>
28 #include <calypso/irq.h>
29
30 #define BASE_ADDR_TIMER         0xfffe3800
31 #define TIMER2_OFFSET           0x3000
32
33 #define TIMER_REG(n, m)         (((n)-1) ? (BASE_ADDR_TIMER + TIMER2_OFFSET + (m)) : (BASE_ADDR_TIMER + (m)))
34
35 enum timer_reg {
36         CNTL_TIMER      = 0x00,
37         LOAD_TIMER      = 0x02,
38         READ_TIMER      = 0x04,
39 };
40
41 enum timer_ctl {
42         CNTL_START              = (1 << 0),
43         CNTL_AUTO_RELOAD        = (1 << 1),
44         CNTL_CLOCK_ENABLE       = (1 << 5),
45 };
46
47 /* Regular Timers (1 and 2) */
48
49 void hwtimer_enable(int num, int on)
50 {
51         uint8_t ctl;
52
53         if (num < 1 || num > 2) {
54                 printf("Unknown timer %u\n", num);
55                 return;
56         }
57
58         ctl = readb(TIMER_REG(num, CNTL_TIMER));
59         if (on)
60                 ctl |= CNTL_START|CNTL_CLOCK_ENABLE;
61         else
62                 ctl &= ~CNTL_START;
63         writeb(ctl, TIMER_REG(num, CNTL_TIMER));
64 }
65
66 void hwtimer_config(int num, uint8_t pre_scale, int auto_reload)
67 {
68         uint8_t ctl;
69
70         ctl = (pre_scale & 0x7) << 2;
71         if (auto_reload)
72                 ctl |= CNTL_AUTO_RELOAD;
73
74         writeb(ctl, TIMER_REG(num, CNTL_TIMER));
75 }
76
77 void hwtimer_load(int num, uint16_t val)
78 {
79         writew(val, TIMER_REG(num, LOAD_TIMER));
80 }
81
82 uint16_t hwtimer_read(int num)
83 {
84         uint8_t ctl = readb(TIMER_REG(num, CNTL_TIMER));
85
86         /* somehow a read results in an abort */
87         if ((ctl & (CNTL_START|CNTL_CLOCK_ENABLE)) != (CNTL_START|CNTL_CLOCK_ENABLE))
88                 return 0xFFFF;
89         return readw(TIMER_REG(num, READ_TIMER));
90 }
91
92 void hwtimer_init(void)
93 {
94         writeb(CNTL_CLOCK_ENABLE, TIMER_REG(1, CNTL_TIMER));
95         writeb(CNTL_CLOCK_ENABLE, TIMER_REG(2, CNTL_TIMER));
96 }
97
98 /* Watchdog Timer */
99
100 #define BASE_ADDR_WDOG          0xfffff800
101 #define WDOG_REG(m)             (BASE_ADDR_WDOG + m)
102
103 enum wdog_reg {
104         WD_CNTL_TIMER   = CNTL_TIMER,
105         WD_LOAD_TIMER   = LOAD_TIMER,
106         WD_READ_TIMER   = 0x02,
107         WD_MODE         = 0x04,
108 };
109
110 static void wdog_irq(enum irq_nr nr)
111 {
112         puts("=> WATCHDOG\n");
113 }
114
115 void wdog_enable(int on)
116 {
117         if (on) {
118                 irq_config(IRQ_WATCHDOG, 0, 0, 0);
119                 irq_register_handler(IRQ_WATCHDOG, &wdog_irq);
120                 irq_enable(IRQ_WATCHDOG);
121                 writew(0x8000, WDOG_REG(WD_MODE));
122         } else {
123                 writew(0xF5, WDOG_REG(WD_MODE));
124                 writew(0xA0, WDOG_REG(WD_MODE));
125         }
126 }
127