more changes on original files
[linux-2.4.git] / Documentation / mips / time.README
1 README for MIPS time services
2
3 Jun Sun
4 jsun@mvista.com or jsun@junsun.net
5
6
7 ABOUT
8 -----
9 This file describes the new arch/mips/kernel/time.c, related files and the 
10 services they provide. 
11
12 If you are short in patience and just want to know how to use time.c for a 
13 new board or convert an existing board, go to the last section.
14
15
16 FILES, COMPATABILITY AND CONFIGS
17 ---------------------------------
18
19 The old arch/mips/kernel/time.c is renamed to old-time.c.
20
21 A new time.c is put there, together with include/asm-mips/time.h.
22
23 Two configs variables are introduced, CONFIG_OLD_TIME_C and CONFIG_NEW_TIME_C.
24 So we allow boards using 
25
26         1) old time.c (CONFIG_OLD_TIME_C)
27         2) new time.c (CONFIG_NEW_TIME_C)
28         3) neither (their own private time.c)
29
30 However, it is expected every board will move to the new time.c in the near
31 future.
32
33 In Linux 2.5 and Linux 2.4.26 CONFIG_OLD_TIME_C was removed.
34
35 WHAT THE NEW CODE PROVIDES?
36 --------------------------- 
37
38 The new time code provide the following services:
39
40   a) Implements functions required by Linux common code:
41         time_init
42         do_gettimeofday
43         do_settimeofday
44
45   b) provides an abstraction of RTC and null RTC implementation as default.
46         extern unsigned long (*rtc_get_time)(void);
47         extern int (*rtc_set_time)(unsigned long);
48
49   c) a set of gettimeoffset functions for different CPUs and different
50      needs.
51
52   d) high-level and low-level timer interrupt routines where the timer 
53      interrupt source  may or may not be the CPU timer.  The high-level 
54      routine is dispatched through do_IRQ() while the low-level is 
55      dispatched in assemably code (usually int-handler.S)
56
57
58 WHAT THE NEW CODE REQUIRES?
59 ---------------------------
60
61 For the new code to work properly, each board implementation needs to supply
62 the following functions or values:
63
64   a) board_time_init - a function pointer.  Invoked at the beginnig of
65      time_init().  It is optional.
66         1. (optional) set up RTC routines
67         2. (optional) calibrate and set the mips_counter_frequency
68
69   b) board_timer_setup - a function pointer.  Invoked at the end of time_init()
70         1. (optional) over-ride any decisions made in time_init()
71         2. set up the irqaction for timer interrupt.
72         3. enable the timer interrupt
73
74   c) (optional) board-specific RTC routines.
75
76   d) (optional) mips_counter_frequency - It must be definied if the board
77      is using CPU counter for timer interrupt or it is using fixed rate
78      gettimeoffset().
79
80
81 PORTING GUIDE
82 -------------
83
84 Step 1: decide how you like to implement the time services.
85
86   a) does this board have a RTC?  If yes, implement the two RTC funcs.
87
88   b) does the CPU have counter/compare registers? 
89
90      If the answer is no, you need a timer to provide the timer interrupt
91      at 100 HZ speed.
92
93      You cannot use the fast gettimeoffset functions, i.e.,
94
95         unsigned long fixed_rate_gettimeoffset(void);
96         unsigned long calibrate_div32_gettimeoffset(void);
97         unsigned long calibrate_div64_gettimeoffset(void);
98
99     You can use null_gettimeoffset() will gives the same time resolution as
100     jiffy.  Or you can implement your own gettimeoffset (probably based on 
101     some ad hoc hardware on your machine.)
102
103   c) The following sub steps assume your CPU has counter register.
104      Do you plan to use the CPU counter register as the timer interrupt
105      or use an exnternal timer?
106
107      In order to use CPU counter register as the timer interrupt source, you 
108      must know the counter speed (mips_counter_frequency).  It is usually the
109      same as the CPU speed or an integral divisor of it.
110
111   d) decide on whether you want to use high-level or low-level timer
112      interrupt routines.  The low-level one is presumably faster, but should
113      not make too mcuh difference.
114
115
116 Step 2:  the machine setup() function
117
118   If you supply board_time_init(), set the function poointer.
119
120   Set the function pointer board_timer_setup() (mandatory)
121
122
123 Step 3: implement rtc routines, board_time_init() and board_timer_setup()
124   if needed.
125
126   board_time_init() - 
127         a) (optional) set up RTC routines, 
128         b) (optional) calibrate and set the mips_counter_frequency
129             (only needed if you intended to use fixed_rate_gettimeoffset
130              or use cpu counter as timer interrupt source)
131
132   board_timer_setup() - 
133         a) (optional) over-write any choices made above by time_init().
134         b) machine specific code should setup the timer irqaction.
135         c) enable the timer interrupt
136
137
138   If the RTC chip is a common chip, I suggest the routines are put under
139   arch/mips/libs.  For example, for DS1386 chip, one would create
140   rtc-ds1386.c under arch/mips/lib directory.  Add the following line to
141   the arch/mips/lib/Makefile:
142
143         obj-$(CONFIG_DDB5476) += rtc-ds1386.o
144
145 Step 4: if you are using low-level timer interrupt, change your interrupt
146   dispathcing code to check for timer interrupt and jump to 
147   ll_timer_interrupt() directly  if one is detected.
148
149 Step 5: Modify arch/mips/config.in and add CONFIG_NEW_TIME_C to your machine.
150   Modify the appropriate defconfig if applicable.
151
152 Final notes: 
153
154 For some tricky cases, you may need to add your own wrapper functions 
155 for some of the functions in time.c.  
156
157 For example, you may define your own timer interrupt routine, which does
158 some of its own processing and then calls timer_interrupt().
159
160 You can also over-ride any of the built-in functions (gettimeoffset,
161 RTC routines and/or timer interrupt routine).
162
163
164 PORTING NOTES FOR SMP
165 ----------------------
166
167 If you have a SMP box, things are slightly more complicated.  
168
169 The time service running every jiffy is logically divided into two parts:
170
171   1) the one for the whole system  (defined in timer_interrupt())
172   2) the one that should run for each CPU (defined in local_timer_interrupt())
173
174 You need to decide on your timer interrupt sources.
175
176   case 1) - whole system has only one timer interrupt delivered to one CPU
177
178         In this case, you set up timer interrupt as in UP systems.  In addtion,
179         you need to set emulate_local_timer_interrupt to 1 so that other
180         CPUs get to call local_timer_interrupt().
181
182         THIS IS CURRENTLY NOT IMPLEMNETED.  However, it is rather easy to write
183         one should such a need arise.  You simply make a IPI call.
184
185   case 2) - each CPU has a separate timer interrupt
186
187         In this case, you need to set up IRQ such that each of them will
188         call local_timer_interrupt().  In addition, you need to arrange
189         one and only one of them to call timer_interrupt().
190
191         You can also do the low-level version of those interrupt routines,
192         following similar dispatching routes described above.
193
194 Note about do_gettimeoffset():
195   
196   It is very likely the CPU counter registers are not sync'ed up in a SMP box.
197   Therefore you cannot really use the many of the existing routines that
198   are based on CPU counter.  You should wirte your own gettimeoffset rouinte
199   if you want intra-jiffy resolution.