Blame view

include/asm-i386/mc146818rtc.h 2.57 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  /*
   * Machine dependent access functions for RTC registers.
   */
  #ifndef _ASM_MC146818RTC_H
  #define _ASM_MC146818RTC_H
  
  #include <asm/io.h>
  #include <asm/system.h>
  #include <linux/mc146818rtc.h>
  
  #ifndef RTC_PORT
  #define RTC_PORT(x)	(0x70 + (x))
  #define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
  #endif
  
  #ifdef __HAVE_ARCH_CMPXCHG
  /*
   * This lock provides nmi access to the CMOS/RTC registers.  It has some
   * special properties.  It is owned by a CPU and stores the index register
   * currently being accessed (if owned).  The idea here is that it works
   * like a normal lock (normally).  However, in an NMI, the NMI code will
   * first check to see if its CPU owns the lock, meaning that the NMI
   * interrupted during the read/write of the device.  If it does, it goes ahead
   * and performs the access and then restores the index register.  If it does
   * not, it locks normally.
   *
   * Note that since we are working with NMIs, we need this lock even in
   * a non-SMP machine just to mark that the lock is owned.
   *
   * This only works with compare-and-swap.  There is no other way to
   * atomically claim the lock and set the owner.
   */
  #include <linux/smp.h>
  extern volatile unsigned long cmos_lock;
  
  /*
   * All of these below must be called with interrupts off, preempt
   * disabled, etc.
   */
  
  static inline void lock_cmos(unsigned char reg)
  {
  	unsigned long new;
  	new = ((smp_processor_id()+1) << 8) | reg;
  	for (;;) {
  		if (cmos_lock)
  			continue;
  		if (__cmpxchg(&cmos_lock, 0, new, sizeof(cmos_lock)) == 0)
  			return;
  	}
  }
  
  static inline void unlock_cmos(void)
  {
  	cmos_lock = 0;
  }
  static inline int do_i_have_lock_cmos(void)
  {
  	return (cmos_lock >> 8) == (smp_processor_id()+1);
  }
  static inline unsigned char current_lock_cmos_reg(void)
  {
  	return cmos_lock & 0xff;
  }
  #define lock_cmos_prefix(reg) \
  	do {					\
  		unsigned long cmos_flags;	\
  		local_irq_save(cmos_flags);	\
  		lock_cmos(reg)
  #define lock_cmos_suffix(reg) \
  		unlock_cmos();			\
  		local_irq_restore(cmos_flags);	\
  	} while (0)
  #else
  #define lock_cmos_prefix(reg) do {} while (0)
  #define lock_cmos_suffix(reg) do {} while (0)
  #define lock_cmos(reg)
  #define unlock_cmos()
  #define do_i_have_lock_cmos() 0
  #define current_lock_cmos_reg() 0
  #endif
  
  /*
   * The yet supported machines all access the RTC index register via
   * an ISA port access but the way to access the date register differs ...
   */
  #define CMOS_READ(addr) rtc_cmos_read(addr)
  #define CMOS_WRITE(val, addr) rtc_cmos_write(val, addr)
  unsigned char rtc_cmos_read(unsigned char addr);
  void rtc_cmos_write(unsigned char val, unsigned char addr);
  
  #define RTC_IRQ 8
  
  #endif /* _ASM_MC146818RTC_H */