Linux Audio

Check our new training course

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