Linux Audio

Check our new training course

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