Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * linux/arch/m68k/atari/time.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Atari time and real time clock stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Assembled of parts of former atari/config.c 97-12-18 by Roman Hodek
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * License.  See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/mc146818rtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/rtc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/bcd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/clocksource.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <asm/atariints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) DEFINE_SPINLOCK(rtc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) EXPORT_SYMBOL_GPL(rtc_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static u64 atari_read_clk(struct clocksource *cs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) static struct clocksource atari_clk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	.name   = "mfp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	.rating = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	.read   = atari_read_clk,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	.mask   = CLOCKSOURCE_MASK(32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) static u32 clk_total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) static u8 last_timer_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) static irqreturn_t mfp_timer_c_handler(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	irq_handler_t timer_routine = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		last_timer_count = st_mfp.tim_dt_c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	} while (last_timer_count == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	clk_total += INT_TICKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	timer_routine(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) atari_sched_init(irq_handler_t timer_routine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)     /* set Timer C data Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)     st_mfp.tim_dt_c = INT_TICKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)     /* start timer C, div = 1:100 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)     st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)     /* install interrupt service routine for MFP Timer C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)     if (request_irq(IRQ_MFP_TIMC, mfp_timer_c_handler, IRQF_TIMER, "timer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)                     timer_routine))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	pr_err("Couldn't register timer interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)     clocksource_register_hz(&atari_clk, INT_CLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) /* ++andreas: gettimeoffset fixed to check for pending interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) static u64 atari_read_clk(struct clocksource *cs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	u8 count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	u32 ticks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	/* Ensure that the count is monotonically decreasing, even though
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	 * the result may briefly stop changing after counter wrap-around.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	count = min(st_mfp.tim_dt_c, last_timer_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	last_timer_count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	ticks = INT_TICKS - count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	ticks += clk_total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	return ticks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static void mste_read(struct MSTE_RTC *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) #define COPY(v) val->v=(mste_rtc.v & 0xf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		COPY(year_tens) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	/* prevent from reading the clock while it changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	} while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #undef COPY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static void mste_write(struct MSTE_RTC *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #define COPY(v) mste_rtc.v=val->v
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		COPY(sec_ones) ; COPY(sec_tens) ; COPY(min_ones) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		COPY(min_tens) ; COPY(hr_ones) ; COPY(hr_tens) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		COPY(weekday) ; COPY(day_ones) ; COPY(day_tens) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		COPY(mon_ones) ; COPY(mon_tens) ; COPY(year_ones) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		COPY(year_tens) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	/* prevent from writing the clock while it changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	} while (val->sec_ones != (mste_rtc.sec_ones & 0xf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #undef COPY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define	RTC_READ(reg)				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)     ({	unsigned char	__val;			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		(void) atari_writeb(reg,&tt_rtc.regsel);	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 		__val = tt_rtc.data;		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		__val;				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	})
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) #define	RTC_WRITE(reg,val)			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)     do {					\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 		atari_writeb(reg,&tt_rtc.regsel);	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		tt_rtc.data = (val);		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	} while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) #define HWCLK_POLL_INTERVAL	5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) int atari_mste_hwclk( int op, struct rtc_time *t )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)     int hour, year;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)     int hr24=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)     struct MSTE_RTC val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)     mste_rtc.mode=(mste_rtc.mode | 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)     hr24=mste_rtc.mon_tens & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)     mste_rtc.mode=(mste_rtc.mode & ~1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)     if (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)         /* write: prepare values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)         val.sec_ones = t->tm_sec % 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)         val.sec_tens = t->tm_sec / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)         val.min_ones = t->tm_min % 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)         val.min_tens = t->tm_min / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)         hour = t->tm_hour;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)         if (!hr24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	    if (hour > 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		hour += 20 - 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	    if (hour == 0 || hour == 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		hour += 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)         val.hr_ones = hour % 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)         val.hr_tens = hour / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)         val.day_ones = t->tm_mday % 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)         val.day_tens = t->tm_mday / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)         val.mon_ones = (t->tm_mon+1) % 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)         val.mon_tens = (t->tm_mon+1) / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)         year = t->tm_year - 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)         val.year_ones = year % 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)         val.year_tens = year / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)         val.weekday = t->tm_wday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)         mste_write(&val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)         mste_rtc.mode=(mste_rtc.mode | 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)         val.year_ones = (year % 4);	/* leap year register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)         mste_rtc.mode=(mste_rtc.mode & ~1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)     else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)         mste_read(&val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)         t->tm_sec = val.sec_ones + val.sec_tens * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)         t->tm_min = val.min_ones + val.min_tens * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)         hour = val.hr_ones + val.hr_tens * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	if (!hr24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	    if (hour == 12 || hour == 12 + 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		hour -= 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	    if (hour >= 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)                 hour += 12 - 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	t->tm_hour = hour;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	t->tm_mday = val.day_ones + val.day_tens * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)         t->tm_mon  = val.mon_ones + val.mon_tens * 10 - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)         t->tm_year = val.year_ones + val.year_tens * 10 + 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)         t->tm_wday = val.weekday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)     return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int atari_tt_hwclk( int op, struct rtc_time *t )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)     int sec=0, min=0, hour=0, day=0, mon=0, year=0, wday=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)     unsigned long	flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)     unsigned char	ctrl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)     int pm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)     ctrl = RTC_READ(RTC_CONTROL); /* control registers are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)                                    * independent from the UIP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)     if (op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)         /* write: prepare values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)         sec  = t->tm_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)         min  = t->tm_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)         hour = t->tm_hour;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)         day  = t->tm_mday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)         mon  = t->tm_mon + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)         year = t->tm_year - atari_rtc_year_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)         wday = t->tm_wday + (t->tm_wday >= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)         if (!(ctrl & RTC_24H)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	    if (hour > 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		pm = 0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		if (hour != 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		    hour -= 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	    else if (hour == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		hour = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)         if (!(ctrl & RTC_DM_BINARY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	    sec = bin2bcd(sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	    min = bin2bcd(min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	    hour = bin2bcd(hour);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	    day = bin2bcd(day);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	    mon = bin2bcd(mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	    year = bin2bcd(year);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	    if (wday >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		wday = bin2bcd(wday);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)     /* Reading/writing the clock registers is a bit critical due to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)      * the regular update cycle of the RTC. While an update is in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)      * progress, registers 0..9 shouldn't be touched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)      * The problem is solved like that: If an update is currently in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)      * progress (the UIP bit is set), the process sleeps for a while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)      * (50ms). This really should be enough, since the update cycle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)      * normally needs 2 ms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)      * If the UIP bit reads as 0, we have at least 244 usecs until the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)      * update starts. This should be enough... But to be sure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)      * additionally the RTC_SET bit is set to prevent an update cycle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)     while( RTC_READ(RTC_FREQ_SELECT) & RTC_UIP ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	if (in_atomic() || irqs_disabled())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	    mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	    schedule_timeout_interruptible(HWCLK_POLL_INTERVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)     local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)     RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)     if (!op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)         sec  = RTC_READ( RTC_SECONDS );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)         min  = RTC_READ( RTC_MINUTES );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)         hour = RTC_READ( RTC_HOURS );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)         day  = RTC_READ( RTC_DAY_OF_MONTH );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)         mon  = RTC_READ( RTC_MONTH );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)         year = RTC_READ( RTC_YEAR );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)         wday = RTC_READ( RTC_DAY_OF_WEEK );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)     else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)         RTC_WRITE( RTC_SECONDS, sec );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)         RTC_WRITE( RTC_MINUTES, min );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)         RTC_WRITE( RTC_HOURS, hour + pm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)         RTC_WRITE( RTC_DAY_OF_MONTH, day );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)         RTC_WRITE( RTC_MONTH, mon );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)         RTC_WRITE( RTC_YEAR, year );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)         if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)     RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)     local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)     if (!op) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)         /* read: adjust values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)         if (hour & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	    hour &= ~0x80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	    pm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	if (!(ctrl & RTC_DM_BINARY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	    sec = bcd2bin(sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	    min = bcd2bin(min);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	    hour = bcd2bin(hour);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	    day = bcd2bin(day);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	    mon = bcd2bin(mon);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	    year = bcd2bin(year);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	    wday = bcd2bin(wday);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)         if (!(ctrl & RTC_24H)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	    if (!pm && hour == 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		hour = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	    else if (pm && hour != 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		hour += 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)         }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)         t->tm_sec  = sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)         t->tm_min  = min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)         t->tm_hour = hour;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)         t->tm_mday = day;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)         t->tm_mon  = mon - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)         t->tm_year = year + atari_rtc_year_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)         t->tm_wday = wday - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)     return( 0 );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)  * Local variables:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)  *  c-indent-level: 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)  *  tab-width: 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)  * End:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)  */