Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * tegra 2 SoC clocks; excludes cortex-a timers.
3
 *
4
 * SoC provides these shared clocks:
5
 * 4 29-bit count-down `timers' @ 1MHz,
6
 * 1 32-bit count-up time-stamp counter @ 1MHz,
7
 * and a real-time clock @ 32KHz.
8
 * the tegra watchdog (tegra 2 ref man §5.4.1) is tied to timers, not rtc.
9
 */
10
#include "u.h"
11
#include "../port/lib.h"
12
#include "mem.h"
13
#include "dat.h"
14
#include "fns.h"
15
#include "arm.h"
16
 
17
typedef struct Shrdtmr Shrdtmr;
18
typedef struct µscnt µscnt;
19
 
20
/* tegra2 shared-intr timer registers */
21
struct Shrdtmr {		/* 29-bit count-down timer (4); unused */
22
	ulong	trigger;
23
	ulong	prescnt;
24
};
25
 
26
enum {
27
	/* trigger bits */
28
	Enable =	1u<<31,
29
	Periodintr =	1<<30,
30
	Countmask =	MASK(29),
31
 
32
	/* prescnt bits */
33
	Intrclr =	1<<30,
34
	/* Countmask is ro */
35
};
36
 
37
struct µscnt {		/* tegra2 shared 32-bit count-up µs counter (1) */
38
	ulong	cntr;
39
	/*
40
	 * oscillator clock fraction - 1; initially 0xb (11) from u-boot
41
	 * for 12MHz periphclk.
42
	 */
43
	ulong	cfg;
44
	uchar	_pad0[0x3c - 0x8];
45
	ulong	freeze;
46
};
47
 
48
enum {
49
	/* cfg bits */
50
	Dividendshift =	8,
51
	Dividendmask =	MASK(8),
52
	Divisorshift =	0,
53
	Divisormask =	MASK(8),
54
};
55
 
56
void
57
tegclockintr(void)
58
{
59
	int junk;
60
	Shrdtmr *tmr;
61
 
62
	/* appease the tegra dog */
63
	tmr = (Shrdtmr *)soc.tmr[0];
64
	junk = tmr->trigger;
65
	USED(junk);
66
}
67
 
68
/*
69
 * if on cpu0, shutdown the shared tegra2 watchdog timer.
70
 */
71
void
72
tegclockshutdown(void)
73
{
74
	Shrdtmr *tmr;
75
 
76
	if (m->machno == 0) {
77
		tmr = (Shrdtmr *)soc.tmr[0];
78
		tmr->prescnt = tmr->trigger = 0;
79
		coherence();
80
	}
81
}
82
 
83
void
84
tegwdogintr(Ureg *, void *v)
85
{
86
	int junk;
87
	Shrdtmr *tmr;
88
 
89
	tmr = (Shrdtmr *)v;
90
	tmr->prescnt |= Intrclr;
91
	coherence();
92
	/* the lousy documentation says we also have to read trigger */
93
	junk = tmr->trigger;
94
	USED(junk);
95
}
96
 
97
/* start tegra2 shared watch dog */
98
void
99
tegclock0init(void)
100
{
101
	Shrdtmr *tmr;
102
 
103
	tmr = (Shrdtmr *)soc.tmr[0];
104
	irqenable(Tn0irq, tegwdogintr, tmr, "tegra watchdog");
105
 
106
	/*
107
	 * tegra watchdog only fires on the second missed interrupt, thus /2.
108
	 */
109
	tmr->trigger = (Dogsectimeout * Mhz / 2 - 1) | Periodintr | Enable;
110
	coherence();
111
}
112
 
113
/*
114
 * µscnt is a freerunning timer (cycle counter); it needs no
115
 * initialisation, wraps and does not dispatch interrupts.
116
 */
117
void
118
tegclockinit(void)
119
{
120
	ulong old;
121
	µscnt *µs = (µscnt *)soc.µs;
122
 
123
	/* verify µs counter sanity */
124
	assert(µs->cfg == 0xb);			/* set by u-boot */
125
	old = µs->cntr;
126
	delay(1);
127
	assert(old != µs->cntr);
128
}
129
 
130
ulong
131
perfticks(void)			/* MHz rate, assumed by timing loops */
132
{
133
	ulong v;
134
 
135
	/* keep it non-zero to prevent m->fastclock ever going to zero. */
136
	v = ((µscnt *)soc.µs)->cntr;
137
	return v == 0? 1: v;
138
}