1 /* Calypso DBB internal Timer Driver */
3 /* (C) 2010 by Harald Welte <laforge@gnumonks.org>
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.
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)))
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
)
51 if (num
< 1 || num
> 2) {
52 printf("Unknown timer %u\n", num
);
56 ctl
= readb(TIMER_REG(num
, CNTL_TIMER
));
58 ctl
|= CNTL_START
|CNTL_CLOCK_ENABLE
;
61 writeb(ctl
, TIMER_REG(num
, CNTL_TIMER
));
64 void hwtimer_config(int num
, uint8_t pre_scale
, int auto_reload
)
68 ctl
= (pre_scale
& 0x7) << 2;
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
))
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
));
98 #define BASE_ADDR_WDOG 0xfffff800
99 #define WDOG_REG(m) (BASE_ADDR_WDOG + m)
102 WD_CNTL_TIMER
= CNTL_TIMER
,
103 WD_LOAD_TIMER
= LOAD_TIMER
,
104 WD_READ_TIMER
= 0x02,
109 WD_CTL_START
= (1 << 7),
110 WD_CTL_AUTO_RELOAD
= (1 << 8)
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
)
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
));
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)
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
));
147 writew(WD_MODE_ENABLE
, WDOG_REG(WD_MODE
));
149 writew(0x0000, WDOG_REG(WD_LOAD_TIMER
));
150 writew(0x0000, WDOG_REG(WD_LOAD_TIMER
));