treewide: remove FSF address
[osmocom-bb.git] / src / target / firmware / calypso / timer.c
blob5141a837f72b2b8e56151be8f958f8a2c2a41efe
1 /* Calypso DBB internal Timer Driver */
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
5 * All Rights Reserved
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.
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.
19 #include <stdio.h>
20 #include <memory.h>
21 #include <stdint.h>
23 #include <defines.h>
25 #include <calypso/timer.h>
26 #include <calypso/irq.h>
28 #define BASE_ADDR_TIMER 0xfffe3800
29 #define TIMER2_OFFSET 0x3000
31 #define TIMER_REG(n, m) (((n)-1) ? (BASE_ADDR_TIMER + TIMER2_OFFSET + (m)) : (BASE_ADDR_TIMER + (m)))
33 enum timer_reg {
34 CNTL_TIMER = 0x00,
35 LOAD_TIMER = 0x02,
36 READ_TIMER = 0x04,
39 enum timer_ctl {
40 CNTL_START = (1 << 0),
41 CNTL_AUTO_RELOAD = (1 << 1),
42 CNTL_CLOCK_ENABLE = (1 << 5),
45 /* Regular Timers (1 and 2) */
47 void hwtimer_enable(int num, int on)
49 uint8_t ctl;
51 if (num < 1 || num > 2) {
52 printf("Unknown timer %u\n", num);
53 return;
56 ctl = readb(TIMER_REG(num, CNTL_TIMER));
57 if (on)
58 ctl |= CNTL_START|CNTL_CLOCK_ENABLE;
59 else
60 ctl &= ~CNTL_START;
61 writeb(ctl, TIMER_REG(num, CNTL_TIMER));
64 void hwtimer_config(int num, uint8_t pre_scale, int auto_reload)
66 uint8_t ctl;
68 ctl = (pre_scale & 0x7) << 2;
69 if (auto_reload)
70 ctl |= CNTL_AUTO_RELOAD;
72 writeb(ctl, TIMER_REG(num, CNTL_TIMER));
75 void hwtimer_load(int num, uint16_t val)
77 writew(val, TIMER_REG(num, LOAD_TIMER));
80 uint16_t hwtimer_read(int num)
82 uint8_t ctl = readb(TIMER_REG(num, CNTL_TIMER));
84 /* somehow a read results in an abort */
85 if ((ctl & (CNTL_START|CNTL_CLOCK_ENABLE)) != (CNTL_START|CNTL_CLOCK_ENABLE))
86 return 0xFFFF;
87 return readw(TIMER_REG(num, READ_TIMER));
90 void hwtimer_init(void)
92 writeb(CNTL_CLOCK_ENABLE, TIMER_REG(1, CNTL_TIMER));
93 writeb(CNTL_CLOCK_ENABLE, TIMER_REG(2, CNTL_TIMER));
96 /* Watchdog Timer */
98 #define BASE_ADDR_WDOG 0xfffff800
99 #define WDOG_REG(m) (BASE_ADDR_WDOG + m)
101 enum wdog_reg {
102 WD_CNTL_TIMER = CNTL_TIMER,
103 WD_LOAD_TIMER = LOAD_TIMER,
104 WD_READ_TIMER = 0x02,
105 WD_MODE = 0x04,
108 enum wdog_ctl {
109 WD_CTL_START = (1 << 7),
110 WD_CTL_AUTO_RELOAD = (1 << 8)
113 enum wdog_mode {
114 WD_MODE_DIS_ARM = 0xF5,
115 WD_MODE_DIS_CONFIRM = 0xA0,
116 WD_MODE_ENABLE = (1 << 15)
119 #define WD_CTL_PRESCALE(value) (((value)&0x07) << 9)
121 static void wdog_irq(__unused enum irq_nr nr)
123 puts("=> WATCHDOG\n");
126 void wdog_enable(int on)
128 if (on) {
129 irq_config(IRQ_WATCHDOG, 0, 0, 0);
130 irq_register_handler(IRQ_WATCHDOG, &wdog_irq);
131 irq_enable(IRQ_WATCHDOG);
132 writew(WD_MODE_ENABLE, WDOG_REG(WD_MODE));
133 } else {
134 writew(WD_MODE_DIS_ARM, WDOG_REG(WD_MODE));
135 writew(WD_MODE_DIS_CONFIRM, WDOG_REG(WD_MODE));
139 void wdog_reset(void)
141 #if 0
142 // XXX: this is supposed to reset immediately but does not seem to
143 writew(0xF5, WDOG_REG(WD_MODE));
144 writew(0xFF, WDOG_REG(WD_MODE));
145 #else
146 // enable watchdog
147 writew(WD_MODE_ENABLE, WDOG_REG(WD_MODE));
148 // force expiration
149 writew(0x0000, WDOG_REG(WD_LOAD_TIMER));
150 writew(0x0000, WDOG_REG(WD_LOAD_TIMER));
151 #endif