blob: a4ce603ed3b35876befd795576e9374f34f0b9b3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001README for MIPS time services
2
3Jun Sun
4jsun@mvista.com or jsun@junsun.net
5
6
7ABOUT
8-----
9This file describes the new arch/mips/kernel/time.c, related files and the
10services they provide.
11
12If you are short in patience and just want to know how to use time.c for a
13new board or convert an existing board, go to the last section.
14
15
16FILES, COMPATABILITY AND CONFIGS
17---------------------------------
18
19The old arch/mips/kernel/time.c is renamed to old-time.c.
20
21A new time.c is put there, together with include/asm-mips/time.h.
22
23Two configs variables are introduced, CONFIG_OLD_TIME_C and CONFIG_NEW_TIME_C.
24So 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
30However, it is expected every board will move to the new time.c in the near
31future.
32
33
34WHAT THE NEW CODE PROVIDES?
35---------------------------
36
37The new time code provide the following services:
38
39 a) Implements functions required by Linux common code:
40 time_init
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42 b) provides an abstraction of RTC and null RTC implementation as default.
43 extern unsigned long (*rtc_get_time)(void);
44 extern int (*rtc_set_time)(unsigned long);
45
Atsushi Nemoto16b7b2a2006-10-24 00:21:27 +090046 c) high-level and low-level timer interrupt routines where the timer
47 interrupt source may or may not be the CPU timer. The high-level
48 routine is dispatched through do_IRQ() while the low-level is
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 dispatched in assemably code (usually int-handler.S)
50
51
52WHAT THE NEW CODE REQUIRES?
53---------------------------
54
55For the new code to work properly, each board implementation needs to supply
56the following functions or values:
57
58 a) board_time_init - a function pointer. Invoked at the beginnig of
59 time_init(). It is optional.
60 1. (optional) set up RTC routines
Ralf Baechle224dc502006-10-21 02:05:20 +010061 2. (optional) calibrate and set the mips_hpt_frequency
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Ralf Baechle54d0a212006-07-09 21:38:56 +010063 b) plat_timer_setup - a function pointer. Invoked at the end of time_init()
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 1. (optional) over-ride any decisions made in time_init()
65 2. set up the irqaction for timer interrupt.
66 3. enable the timer interrupt
67
68 c) (optional) board-specific RTC routines.
69
Ralf Baechle224dc502006-10-21 02:05:20 +010070 d) (optional) mips_hpt_frequency - It must be definied if the board
Atsushi Nemoto16b7b2a2006-10-24 00:21:27 +090071 is using CPU counter for timer interrupt.
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73
74PORTING GUIDE
75-------------
76
77Step 1: decide how you like to implement the time services.
78
79 a) does this board have a RTC? If yes, implement the two RTC funcs.
80
81 b) does the CPU have counter/compare registers?
82
83 If the answer is no, you need a timer to provide the timer interrupt
84 at 100 HZ speed.
85
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 c) The following sub steps assume your CPU has counter register.
87 Do you plan to use the CPU counter register as the timer interrupt
88 or use an exnternal timer?
89
90 In order to use CPU counter register as the timer interrupt source, you
Ralf Baechle224dc502006-10-21 02:05:20 +010091 must know the counter speed (mips_hpt_frequency). It is usually the
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 same as the CPU speed or an integral divisor of it.
93
94 d) decide on whether you want to use high-level or low-level timer
95 interrupt routines. The low-level one is presumably faster, but should
96 not make too mcuh difference.
97
98
99Step 2: the machine setup() function
100
101 If you supply board_time_init(), set the function poointer.
102
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Ralf Baechle54d0a212006-07-09 21:38:56 +0100104Step 3: implement rtc routines, board_time_init() and plat_timer_setup()
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 if needed.
106
Ralf Baechle54d0a212006-07-09 21:38:56 +0100107 board_time_init() -
Ralf Baechle224dc502006-10-21 02:05:20 +0100108 a) (optional) set up RTC routines,
109 b) (optional) calibrate and set the mips_hpt_frequency
Atsushi Nemoto16b7b2a2006-10-24 00:21:27 +0900110 (only needed if you intended to use cpu counter as timer interrupt
111 source)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
Ralf Baechle54d0a212006-07-09 21:38:56 +0100113 plat_timer_setup() -
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 a) (optional) over-write any choices made above by time_init().
115 b) machine specific code should setup the timer irqaction.
116 c) enable the timer interrupt
117
118
119 If the RTC chip is a common chip, I suggest the routines are put under
120 arch/mips/libs. For example, for DS1386 chip, one would create
121 rtc-ds1386.c under arch/mips/lib directory. Add the following line to
122 the arch/mips/lib/Makefile:
123
124 obj-$(CONFIG_DDB5476) += rtc-ds1386.o
125
126Step 4: if you are using low-level timer interrupt, change your interrupt
127 dispathcing code to check for timer interrupt and jump to
128 ll_timer_interrupt() directly if one is detected.
129
130Step 5: Modify arch/mips/config.in and add CONFIG_NEW_TIME_C to your machine.
131 Modify the appropriate defconfig if applicable.
132
133Final notes:
134
135For some tricky cases, you may need to add your own wrapper functions
136for some of the functions in time.c.
137
138For example, you may define your own timer interrupt routine, which does
139some of its own processing and then calls timer_interrupt().
140
Atsushi Nemoto16b7b2a2006-10-24 00:21:27 +0900141You can also over-ride any of the built-in functions (RTC routines
142and/or timer interrupt routine).
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
144
145PORTING NOTES FOR SMP
146----------------------
147
148If you have a SMP box, things are slightly more complicated.
149
150The time service running every jiffy is logically divided into two parts:
151
152 1) the one for the whole system (defined in timer_interrupt())
153 2) the one that should run for each CPU (defined in local_timer_interrupt())
154
155You need to decide on your timer interrupt sources.
156
157 case 1) - whole system has only one timer interrupt delivered to one CPU
158
159 In this case, you set up timer interrupt as in UP systems. In addtion,
160 you need to set emulate_local_timer_interrupt to 1 so that other
161 CPUs get to call local_timer_interrupt().
162
163 THIS IS CURRENTLY NOT IMPLEMNETED. However, it is rather easy to write
164 one should such a need arise. You simply make a IPI call.
165
166 case 2) - each CPU has a separate timer interrupt
167
168 In this case, you need to set up IRQ such that each of them will
169 call local_timer_interrupt(). In addition, you need to arrange
170 one and only one of them to call timer_interrupt().
171
172 You can also do the low-level version of those interrupt routines,
173 following similar dispatching routes described above.