text: /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  
  /* Timer module for Chrome EC operating system */
  
  #ifndef __CROS_EC_TIMER_H
  #define __CROS_EC_TIMER_H
  
  #include "common.h"
  #include "task_id.h"
  
  /* Time units in microseconds */
  #define MSEC         1000
  #define SECOND    1000000
  #define MINUTE   60000000
  #define HOUR   3600000000ull  /* Too big to fit in a signed int */
  
  /* Microsecond timestamp. */
  typedef union {
  	uint64_t val;
  	struct {
  		uint32_t lo;
  		uint32_t hi;
  	} le /* little endian words */;
  } timestamp_t;
  
  /**
   * Initialize the timer module.
   */
  void timer_init(void);
  
  /**
   * Launch a one-shot timer for a task.
   *
   * Note that each task can have only a single active timer.
   *
   * @param tstamp	Expiration timestamp for timer
   * @param tskid		Task to set timer for
   *
   * @return EC_SUCCESS, or non-zero if error.
   */
  int timer_arm(timestamp_t tstamp, task_id_t tskid);
  
  /**
   * Cancel a running timer for the specified task id.
   */
  void timer_cancel(task_id_t tskid);
  
  /**
   * Check if a timestamp has passed / expired
   *
   * @param deadline	deadline timer value to check
   * @param now		pointer to value of time_now() if known, else NULL
   * @return 0 if deadline has not yet passed, 1 if it has passed
   */
  int timestamp_expired(timestamp_t deadline, const timestamp_t *now);
  
  /**
   * Busy-wait.
   *
   * This may be called with interrupts disabled, at any time after timer_init()
   * has been called.
   *
   * Note that calling this with us>1000 may impact system performance; use
   * usleep() for longer delays.
   *
   * @param us		Number of microseconds to delay.
   */
  void udelay(unsigned us);
  
  /**
   * Sleep.
   *
   * The current task will be de-scheduled for at least the specified delay (and
   * perhaps longer, if a higher-priority task is running when the delay
   * expires).
   *
   * This may only be called from a task function, with interrupts enabled.
   *
   * @param us		Number of microseconds to sleep.
   */
  void usleep(unsigned us);
  
  /**
   * Sleep for milliseconds.
   *
   * Otherwise the same as usleep().
   *
   * @param ms		Number of milliseconds to sleep.
   */
  static inline void msleep(unsigned ms)
  {
  	usleep(ms * MSEC);
  }
  
  /**
   * Sleep for seconds
   *
   * Otherwise the same as usleep().
   *
   * @param sec		Number of seconds to sleep.
   */
  static inline void sleep(unsigned sec)
  {
  	usleep(sec * SECOND);
  }
  
  /**
   * Get the current timestamp from the system timer.
   */
  timestamp_t get_time(void);
  
  /**
   * Force the current value of the system timer.
   *
   * This function is for the power management implementation which wants to fix
   * the system time when waking up from a mode with clocks turned off.
   *
   * Note: must be called with interrupts disabled.
   */
  void force_time(timestamp_t ts);
  
  /**
   * Print the current timer information using the command output channel.
   *
   * This may be called from interrupt level.
   */
  void timer_print_info(void);
  
  /**
   * Returns the number of microseconds that have elapsed from a start time.
   *
   * This function is for timing short delays typically of a few milliseconds
   * or so.
   *
   * Note that this is limited to a maximum of 32 bits, which is around an
   * hour. After that, the value returned will wrap.
   *
   * @param start		Start time to compare against
   * @return number of microseconds that have elspsed since that start time
   */
  static inline unsigned time_since32(timestamp_t start)
  {
  	return get_time().le.lo - start.le.lo;
  }
  
  /**
   * To compare time and deal with rollover
   *
   * Return true if a is after b.
   */
  static inline int time_after(uint32_t a, uint32_t b)
  {
  	return (int32_t)(b - a) < 0;
  }
  
  #endif  /* __CROS_EC_TIMER_H */
  