linux-old/Documentation/mips/time.README
<<
>>
Prefs
   1README 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
  33In Linux 2.5 and Linux 2.4.26 CONFIG_OLD_TIME_C was removed.
  34
  35WHAT THE NEW CODE PROVIDES?
  36--------------------------- 
  37
  38The 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
  58WHAT THE NEW CODE REQUIRES?
  59---------------------------
  60
  61For the new code to work properly, each board implementation needs to supply
  62the 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
  81PORTING GUIDE
  82-------------
  83
  84Step 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
 116Step 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
 123Step 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
 145Step 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
 149Step 5: Modify arch/mips/config.in and add CONFIG_NEW_TIME_C to your machine.
 150  Modify the appropriate defconfig if applicable.
 151
 152Final notes: 
 153
 154For some tricky cases, you may need to add your own wrapper functions 
 155for some of the functions in time.c.  
 156
 157For example, you may define your own timer interrupt routine, which does
 158some of its own processing and then calls timer_interrupt().
 159
 160You can also over-ride any of the built-in functions (gettimeoffset,
 161RTC routines and/or timer interrupt routine).
 162
 163
 164PORTING NOTES FOR SMP
 165----------------------
 166
 167If you have a SMP box, things are slightly more complicated.  
 168
 169The 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
 174You 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
 194Note 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.
 200
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.