Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Machine dependent access functions for RTC registers.
0004  */
0005 #ifndef _ASM_X86_MC146818RTC_H
0006 #define _ASM_X86_MC146818RTC_H
0007 
0008 #include <asm/io.h>
0009 #include <asm/processor.h>
0010 
0011 #ifndef RTC_PORT
0012 #define RTC_PORT(x) (0x70 + (x))
0013 #define RTC_ALWAYS_BCD  1   /* RTC operates in binary mode */
0014 #endif
0015 
0016 #if defined(CONFIG_X86_32)
0017 /*
0018  * This lock provides nmi access to the CMOS/RTC registers.  It has some
0019  * special properties.  It is owned by a CPU and stores the index register
0020  * currently being accessed (if owned).  The idea here is that it works
0021  * like a normal lock (normally).  However, in an NMI, the NMI code will
0022  * first check to see if its CPU owns the lock, meaning that the NMI
0023  * interrupted during the read/write of the device.  If it does, it goes ahead
0024  * and performs the access and then restores the index register.  If it does
0025  * not, it locks normally.
0026  *
0027  * Note that since we are working with NMIs, we need this lock even in
0028  * a non-SMP machine just to mark that the lock is owned.
0029  *
0030  * This only works with compare-and-swap.  There is no other way to
0031  * atomically claim the lock and set the owner.
0032  */
0033 #include <linux/smp.h>
0034 extern volatile unsigned long cmos_lock;
0035 
0036 /*
0037  * All of these below must be called with interrupts off, preempt
0038  * disabled, etc.
0039  */
0040 
0041 static inline void lock_cmos(unsigned char reg)
0042 {
0043     unsigned long new;
0044     new = ((smp_processor_id() + 1) << 8) | reg;
0045     for (;;) {
0046         if (cmos_lock) {
0047             cpu_relax();
0048             continue;
0049         }
0050         if (__cmpxchg(&cmos_lock, 0, new, sizeof(cmos_lock)) == 0)
0051             return;
0052     }
0053 }
0054 
0055 static inline void unlock_cmos(void)
0056 {
0057     cmos_lock = 0;
0058 }
0059 
0060 static inline int do_i_have_lock_cmos(void)
0061 {
0062     return (cmos_lock >> 8) == (smp_processor_id() + 1);
0063 }
0064 
0065 static inline unsigned char current_lock_cmos_reg(void)
0066 {
0067     return cmos_lock & 0xff;
0068 }
0069 
0070 #define lock_cmos_prefix(reg)           \
0071     do {                    \
0072         unsigned long cmos_flags;   \
0073         local_irq_save(cmos_flags); \
0074         lock_cmos(reg)
0075 
0076 #define lock_cmos_suffix(reg)           \
0077     unlock_cmos();              \
0078     local_irq_restore(cmos_flags);      \
0079     } while (0)
0080 #else
0081 #define lock_cmos_prefix(reg) do {} while (0)
0082 #define lock_cmos_suffix(reg) do {} while (0)
0083 #define lock_cmos(reg) do { } while (0)
0084 #define unlock_cmos() do { } while (0)
0085 #define do_i_have_lock_cmos() 0
0086 #define current_lock_cmos_reg() 0
0087 #endif
0088 
0089 /*
0090  * The yet supported machines all access the RTC index register via
0091  * an ISA port access but the way to access the date register differs ...
0092  */
0093 #define CMOS_READ(addr) rtc_cmos_read(addr)
0094 #define CMOS_WRITE(val, addr) rtc_cmos_write(val, addr)
0095 unsigned char rtc_cmos_read(unsigned char addr);
0096 void rtc_cmos_write(unsigned char val, unsigned char addr);
0097 
0098 extern int mach_set_rtc_mmss(const struct timespec64 *now);
0099 extern void mach_get_cmos_time(struct timespec64 *now);
0100 
0101 #define RTC_IRQ 8
0102 
0103 #endif /* _ASM_X86_MC146818RTC_H */