Commit f5daf5eb authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Linus Torvalds

[PATCH] Amiga RTC updates

Amiga RTC updates from Kars de Jong <jongk@linux-m68k.org>:
  - Implement mach_get_ss() on Amiga
  - Use OKI recommendations for locking the A2000 clock
  - Streamline clock structure declarations
parent 0ce4dfab
......@@ -21,6 +21,7 @@
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/vt_kern.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#ifdef CONFIG_ZORRO
#include <linux/zorro.h>
......@@ -89,6 +90,7 @@ static unsigned long amiga_gettimeoffset (void);
static int a3000_hwclk (int, struct rtc_time *);
static int a2000_hwclk (int, struct rtc_time *);
static int amiga_set_clock_mmss (unsigned long);
static unsigned int amiga_get_ss (void);
extern void amiga_mksound( unsigned int count, unsigned int ticks );
#ifdef CONFIG_AMIGA_FLOPPY
extern void amiga_floppy_setup(char *, int *);
......@@ -403,6 +405,7 @@ void __init config_amiga(void)
*/
mach_set_clock_mmss = amiga_set_clock_mmss;
mach_get_ss = amiga_get_ss;
#ifdef CONFIG_AMIGA_FLOPPY
mach_floppy_setup = amiga_floppy_setup;
#endif
......@@ -545,96 +548,101 @@ static unsigned long amiga_gettimeoffset (void)
static int a3000_hwclk(int op, struct rtc_time *t)
{
volatile struct tod3000 *tod = TOD_3000;
tod->cntrl1 = TOD3000_CNTRL1_HOLD;
tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD;
if (!op) { /* read */
t->tm_sec = tod->second1 * 10 + tod->second2;
t->tm_min = tod->minute1 * 10 + tod->minute2;
t->tm_hour = tod->hour1 * 10 + tod->hour2;
t->tm_mday = tod->day1 * 10 + tod->day2;
t->tm_wday = tod->weekday;
t->tm_mon = tod->month1 * 10 + tod->month2 - 1;
t->tm_year = tod->year1 * 10 + tod->year2;
t->tm_sec = tod_3000.second1 * 10 + tod_3000.second2;
t->tm_min = tod_3000.minute1 * 10 + tod_3000.minute2;
t->tm_hour = tod_3000.hour1 * 10 + tod_3000.hour2;
t->tm_mday = tod_3000.day1 * 10 + tod_3000.day2;
t->tm_wday = tod_3000.weekday;
t->tm_mon = tod_3000.month1 * 10 + tod_3000.month2 - 1;
t->tm_year = tod_3000.year1 * 10 + tod_3000.year2;
if (t->tm_year <= 69)
t->tm_year += 100;
} else {
tod->second1 = t->tm_sec / 10;
tod->second2 = t->tm_sec % 10;
tod->minute1 = t->tm_min / 10;
tod->minute2 = t->tm_min % 10;
tod->hour1 = t->tm_hour / 10;
tod->hour2 = t->tm_hour % 10;
tod->day1 = t->tm_mday / 10;
tod->day2 = t->tm_mday % 10;
tod_3000.second1 = t->tm_sec / 10;
tod_3000.second2 = t->tm_sec % 10;
tod_3000.minute1 = t->tm_min / 10;
tod_3000.minute2 = t->tm_min % 10;
tod_3000.hour1 = t->tm_hour / 10;
tod_3000.hour2 = t->tm_hour % 10;
tod_3000.day1 = t->tm_mday / 10;
tod_3000.day2 = t->tm_mday % 10;
if (t->tm_wday != -1)
tod->weekday = t->tm_wday;
tod->month1 = (t->tm_mon + 1) / 10;
tod->month2 = (t->tm_mon + 1) % 10;
tod_3000.weekday = t->tm_wday;
tod_3000.month1 = (t->tm_mon + 1) / 10;
tod_3000.month2 = (t->tm_mon + 1) % 10;
if (t->tm_year >= 100)
t->tm_year -= 100;
tod->year1 = t->tm_year / 10;
tod->year2 = t->tm_year % 10;
tod_3000.year1 = t->tm_year / 10;
tod_3000.year2 = t->tm_year % 10;
}
tod->cntrl1 = TOD3000_CNTRL1_FREE;
tod_3000.cntrl1 = TOD3000_CNTRL1_FREE;
return 0;
}
static int a2000_hwclk(int op, struct rtc_time *t)
{
volatile struct tod2000 *tod = TOD_2000;
int cnt = 5;
tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
tod->cntrl1 = TOD2000_CNTRL1_HOLD;
while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
{
tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
udelay(70);
tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
}
while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
;
if (!cnt)
printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1);
if (!op) { /* read */
t->tm_sec = tod->second1 * 10 + tod->second2;
t->tm_min = tod->minute1 * 10 + tod->minute2;
t->tm_hour = (tod->hour1 & 3) * 10 + tod->hour2;
t->tm_mday = tod->day1 * 10 + tod->day2;
t->tm_wday = tod->weekday;
t->tm_mon = tod->month1 * 10 + tod->month2 - 1;
t->tm_year = tod->year1 * 10 + tod->year2;
t->tm_sec = tod_2000.second1 * 10 + tod_2000.second2;
t->tm_min = tod_2000.minute1 * 10 + tod_2000.minute2;
t->tm_hour = (tod_2000.hour1 & 3) * 10 + tod_2000.hour2;
t->tm_mday = tod_2000.day1 * 10 + tod_2000.day2;
t->tm_wday = tod_2000.weekday;
t->tm_mon = tod_2000.month1 * 10 + tod_2000.month2 - 1;
t->tm_year = tod_2000.year1 * 10 + tod_2000.year2;
if (t->tm_year <= 69)
t->tm_year += 100;
if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){
if (!(tod->hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12)
if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)){
if (!(tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12)
t->tm_hour = 0;
else if ((tod->hour1 & TOD2000_HOUR1_PM) && t->tm_hour != 12)
else if ((tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour != 12)
t->tm_hour += 12;
}
} else {
tod->second1 = t->tm_sec / 10;
tod->second2 = t->tm_sec % 10;
tod->minute1 = t->tm_min / 10;
tod->minute2 = t->tm_min % 10;
if (tod->cntrl3 & TOD2000_CNTRL3_24HMODE)
tod->hour1 = t->tm_hour / 10;
tod_2000.second1 = t->tm_sec / 10;
tod_2000.second2 = t->tm_sec % 10;
tod_2000.minute1 = t->tm_min / 10;
tod_2000.minute2 = t->tm_min % 10;
if (tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)
tod_2000.hour1 = t->tm_hour / 10;
else if (t->tm_hour >= 12)
tod->hour1 = TOD2000_HOUR1_PM +
tod_2000.hour1 = TOD2000_HOUR1_PM +
(t->tm_hour - 12) / 10;
else
tod->hour1 = t->tm_hour / 10;
tod->hour2 = t->tm_hour % 10;
tod->day1 = t->tm_mday / 10;
tod->day2 = t->tm_mday % 10;
tod_2000.hour1 = t->tm_hour / 10;
tod_2000.hour2 = t->tm_hour % 10;
tod_2000.day1 = t->tm_mday / 10;
tod_2000.day2 = t->tm_mday % 10;
if (t->tm_wday != -1)
tod->weekday = t->tm_wday;
tod->month1 = (t->tm_mon + 1) / 10;
tod->month2 = (t->tm_mon + 1) % 10;
tod_2000.weekday = t->tm_wday;
tod_2000.month1 = (t->tm_mon + 1) / 10;
tod_2000.month2 = (t->tm_mon + 1) % 10;
if (t->tm_year >= 100)
t->tm_year -= 100;
tod->year1 = t->tm_year / 10;
tod->year2 = t->tm_year % 10;
tod_2000.year1 = t->tm_year / 10;
tod_2000.year2 = t->tm_year % 10;
}
tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
return 0;
}
......@@ -644,35 +652,54 @@ static int amiga_set_clock_mmss (unsigned long nowtime)
short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
if (AMIGAHW_PRESENT(A3000_CLK)) {
volatile struct tod3000 *tod = TOD_3000;
tod->cntrl1 = TOD3000_CNTRL1_HOLD;
tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD;
tod->second1 = real_seconds / 10;
tod->second2 = real_seconds % 10;
tod->minute1 = real_minutes / 10;
tod->minute2 = real_minutes % 10;
tod_3000.second1 = real_seconds / 10;
tod_3000.second2 = real_seconds % 10;
tod_3000.minute1 = real_minutes / 10;
tod_3000.minute2 = real_minutes % 10;
tod->cntrl1 = TOD3000_CNTRL1_FREE;
tod_3000.cntrl1 = TOD3000_CNTRL1_FREE;
} else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
volatile struct tod2000 *tod = TOD_2000;
int cnt = 5;
tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
{
tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
udelay(70);
tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
}
tod->cntrl1 = TOD2000_CNTRL1_HOLD;
while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
;
if (!cnt)
printk(KERN_INFO "set_clock_mmss: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1);
tod->second1 = real_seconds / 10;
tod->second2 = real_seconds % 10;
tod->minute1 = real_minutes / 10;
tod->minute2 = real_minutes % 10;
tod_2000.second1 = real_seconds / 10;
tod_2000.second2 = real_seconds % 10;
tod_2000.minute1 = real_minutes / 10;
tod_2000.minute2 = real_minutes % 10;
tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
}
return 0;
}
static unsigned int amiga_get_ss( void )
{
unsigned int s;
if (AMIGAHW_PRESENT(A3000_CLK)) {
tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD;
s = tod_3000.second1 * 10 + tod_3000.second2;
tod_3000.cntrl1 = TOD3000_CNTRL1_FREE;
} else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
s = tod_2000.second1 * 10 + tod_2000.second2;
}
return s;
}
static NORET_TYPE void amiga_reset( void )
ATTRIB_NORET;
......
......@@ -324,7 +324,7 @@ struct tod3000 {
};
#define TOD3000_CNTRL1_HOLD 0
#define TOD3000_CNTRL1_FREE 9
#define TOD_3000 ((struct tod3000 *)(zTwoBase+0xDC0000))
#define tod_3000 ((*(volatile struct tod3000 *)(zTwoBase+0xDC0000)))
struct tod2000 {
unsigned int :28, second2:4; /* lower digit */
......@@ -349,6 +349,6 @@ struct tod2000 {
#define TOD2000_CNTRL1_BUSY (1<<1)
#define TOD2000_CNTRL3_24HMODE (1<<2)
#define TOD2000_HOUR1_PM (1<<2)
#define TOD_2000 ((struct tod2000 *)(zTwoBase+0xDC0000))
#define tod_2000 ((*(volatile struct tod2000 *)(zTwoBase+0xDC0000)))
#endif /* _M68K_AMIGAHW_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment