Project

General

Profile

Download (3.2 KB) Statistics
| Branch: | Tag: | Revision:
1 32985a29 laforge
/* Periodic Interval Timer Implementation for OpenPCD
2
 * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
3
 *
4
 *  This program is free software; you can redistribute it and/or modify
5
 *  it under the terms of the GNU General Public License as published by 
6
 *  the Free Software Foundation; either version 2 of the License, or
7
 *  (at your option) any later version.
8
 *
9
 *  This program is distributed in the hope that it will be useful,
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 *  GNU General Public License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License
15
 *  along with this program; if not, write to the Free Software
16
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18 6c0b462a laforge
 *
19
 * TODO: handle jiffies wrap correctly!
20 32985a29 laforge
 */
21 677e0b6e (no author)
22
#include <errno.h>
23
#include <sys/types.h>
24 6c0b462a laforge
#include <asm/system.h>
25
26 677e0b6e (no author)
#include <lib_AT91SAM7.h>
27
#include <AT91SAM7.h>
28 6c0b462a laforge
#include <os/pit.h>
29 f796b3e4 laforge
#include <os/dbgu.h>
30 bfff30bf laforge
#include <os/system_irq.h>
31 6c0b462a laforge
32 677e0b6e (no author)
#include "../openpcd.h"
33
34
/* PIT runs at MCK/16 (= 3MHz) */
35
#define PIV_MS(x)		(x * 3000)
36
37 6c0b462a laforge
static struct timer_list *timers;
38
39 f796b3e4 laforge
volatile unsigned long jiffies;
40 6c0b462a laforge
41
static void __timer_insert(struct timer_list *new)
42
{
43
	struct timer_list *tl, *tl_prev = NULL;
44
45
	if (!timers) {
46
		/* optimize for the common, fast case */
47
		new->next = NULL;
48
		timers = new;
49
		return;
50
	}
51
52
	for (tl = timers; tl != NULL; tl = tl->next) {
53
		if (tl->expires < new->expires) {
54
			/* we need ot add just before this one */
55
			if (!tl_prev) {
56
				new->next = timers;
57
				timers = new;
58
			} else {
59
				new->next = tl;
60
				tl_prev->next = new;
61
			}
62
		}
63
		tl_prev = tl;
64
	}
65
}
66
67 f796b3e4 laforge
static int __timer_remove(struct timer_list *old)
68 6c0b462a laforge
{
69
	struct timer_list *tl, *tl_prev = NULL;
70
71
	for (tl = timers; tl != NULL; tl = tl->next) {
72
		if (tl == old) {
73
			if (tl == timers)
74
				timers = tl->next;
75
			else
76
				tl_prev->next = tl->next;
77 f796b3e4 laforge
			return 1;
78 6c0b462a laforge
		}
79
		tl_prev = tl;
80
	}
81 f796b3e4 laforge
82
	return 0;
83 6c0b462a laforge
}
84
85
int timer_del(struct timer_list *tl)
86
{
87
	unsigned long flags;
88 f796b3e4 laforge
	int ret;
89 6c0b462a laforge
90
	local_irq_save(flags);
91 f796b3e4 laforge
	ret = __timer_remove(tl);
92 6c0b462a laforge
	local_irq_restore(flags);
93 f796b3e4 laforge
94
	return ret;
95 6c0b462a laforge
}
96
97
void timer_add(struct timer_list *tl)
98
{
99
	unsigned long flags;
100
101
	local_irq_save(flags);
102
	__timer_insert(tl);
103
	local_irq_restore(flags);
104
}
105
106 373c172a Harald Welte
static void pit_irq(uint32_t sr)
107 677e0b6e (no author)
{
108 f796b3e4 laforge
	struct timer_list *tl, *next;
109 6c0b462a laforge
110 f796b3e4 laforge
	if (!(sr & 0x1))
111
		return;
112
113
	jiffies += *AT91C_PITC_PIVR >> 20;
114 6c0b462a laforge
115
	/* this is the most simple/stupid algorithm one can come up with, but
116
	 * hey, we're on a small embedded platform with only a hand ful
117
	 * of timers, at all */
118 f796b3e4 laforge
	for (tl = timers; tl != NULL; tl = next) {
119
		next = tl->next;
120
		if (tl->expires <= jiffies) {
121 6c0b462a laforge
			/* delete timer from list */
122 f796b3e4 laforge
			timer_del(tl);
123
			tl->function(tl->data);
124 6c0b462a laforge
		}
125
	}
126 677e0b6e (no author)
}
127
128 373c172a Harald Welte
void pit_mdelay(uint32_t ms)
129 677e0b6e (no author)
{
130 373c172a Harald Welte
	uint32_t end;
131 677e0b6e (no author)
132
	end = (AT91F_PITGetPIIR(AT91C_BASE_PITC) + ms) % 20;
133
134
	while (end < AT91F_PITGetPIIR(AT91C_BASE_PITC)) { }
135
}
136
137 373c172a Harald Welte
void mdelay(uint32_t ms)
138 28eb4a57 laforge
{
139
	return pit_mdelay(ms);
140
}
141
142 373c172a Harald Welte
void usleep(uint32_t us)
143 28eb4a57 laforge
{
144
	return;
145
	return pit_mdelay(us/1000);
146
}
147
148 677e0b6e (no author)
void pit_init(void)
149
{
150
	AT91F_PITC_CfgPMC();
151
152 f796b3e4 laforge
	AT91F_PITInit(AT91C_BASE_PITC, 1000000/HZ /* uS */, 48 /* MHz */);
153 677e0b6e (no author)
154 bfff30bf laforge
	sysirq_register(AT91SAM7_SYSIRQ_PIT, &pit_irq);	
155 677e0b6e (no author)
156 bfff30bf laforge
	AT91F_PITEnableInt(AT91C_BASE_PITC);
157 677e0b6e (no author)
}
Add picture from clipboard (Maximum size: 48.8 MB)