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 @@ ...@@ -21,6 +21,7 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/vt_kern.h> #include <linux/vt_kern.h>
#include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#ifdef CONFIG_ZORRO #ifdef CONFIG_ZORRO
#include <linux/zorro.h> #include <linux/zorro.h>
...@@ -89,6 +90,7 @@ static unsigned long amiga_gettimeoffset (void); ...@@ -89,6 +90,7 @@ static unsigned long amiga_gettimeoffset (void);
static int a3000_hwclk (int, struct rtc_time *); static int a3000_hwclk (int, struct rtc_time *);
static int a2000_hwclk (int, struct rtc_time *); static int a2000_hwclk (int, struct rtc_time *);
static int amiga_set_clock_mmss (unsigned long); 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 ); extern void amiga_mksound( unsigned int count, unsigned int ticks );
#ifdef CONFIG_AMIGA_FLOPPY #ifdef CONFIG_AMIGA_FLOPPY
extern void amiga_floppy_setup(char *, int *); extern void amiga_floppy_setup(char *, int *);
...@@ -403,6 +405,7 @@ void __init config_amiga(void) ...@@ -403,6 +405,7 @@ void __init config_amiga(void)
*/ */
mach_set_clock_mmss = amiga_set_clock_mmss; mach_set_clock_mmss = amiga_set_clock_mmss;
mach_get_ss = amiga_get_ss;
#ifdef CONFIG_AMIGA_FLOPPY #ifdef CONFIG_AMIGA_FLOPPY
mach_floppy_setup = amiga_floppy_setup; mach_floppy_setup = amiga_floppy_setup;
#endif #endif
...@@ -545,96 +548,101 @@ static unsigned long amiga_gettimeoffset (void) ...@@ -545,96 +548,101 @@ static unsigned long amiga_gettimeoffset (void)
static int a3000_hwclk(int op, struct rtc_time *t) static int a3000_hwclk(int op, struct rtc_time *t)
{ {
volatile struct tod3000 *tod = TOD_3000; tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD;
tod->cntrl1 = TOD3000_CNTRL1_HOLD;
if (!op) { /* read */ if (!op) { /* read */
t->tm_sec = tod->second1 * 10 + tod->second2; t->tm_sec = tod_3000.second1 * 10 + tod_3000.second2;
t->tm_min = tod->minute1 * 10 + tod->minute2; t->tm_min = tod_3000.minute1 * 10 + tod_3000.minute2;
t->tm_hour = tod->hour1 * 10 + tod->hour2; t->tm_hour = tod_3000.hour1 * 10 + tod_3000.hour2;
t->tm_mday = tod->day1 * 10 + tod->day2; t->tm_mday = tod_3000.day1 * 10 + tod_3000.day2;
t->tm_wday = tod->weekday; t->tm_wday = tod_3000.weekday;
t->tm_mon = tod->month1 * 10 + tod->month2 - 1; t->tm_mon = tod_3000.month1 * 10 + tod_3000.month2 - 1;
t->tm_year = tod->year1 * 10 + tod->year2; t->tm_year = tod_3000.year1 * 10 + tod_3000.year2;
if (t->tm_year <= 69) if (t->tm_year <= 69)
t->tm_year += 100; t->tm_year += 100;
} else { } else {
tod->second1 = t->tm_sec / 10; tod_3000.second1 = t->tm_sec / 10;
tod->second2 = t->tm_sec % 10; tod_3000.second2 = t->tm_sec % 10;
tod->minute1 = t->tm_min / 10; tod_3000.minute1 = t->tm_min / 10;
tod->minute2 = t->tm_min % 10; tod_3000.minute2 = t->tm_min % 10;
tod->hour1 = t->tm_hour / 10; tod_3000.hour1 = t->tm_hour / 10;
tod->hour2 = t->tm_hour % 10; tod_3000.hour2 = t->tm_hour % 10;
tod->day1 = t->tm_mday / 10; tod_3000.day1 = t->tm_mday / 10;
tod->day2 = t->tm_mday % 10; tod_3000.day2 = t->tm_mday % 10;
if (t->tm_wday != -1) if (t->tm_wday != -1)
tod->weekday = t->tm_wday; tod_3000.weekday = t->tm_wday;
tod->month1 = (t->tm_mon + 1) / 10; tod_3000.month1 = (t->tm_mon + 1) / 10;
tod->month2 = (t->tm_mon + 1) % 10; tod_3000.month2 = (t->tm_mon + 1) % 10;
if (t->tm_year >= 100) if (t->tm_year >= 100)
t->tm_year -= 100; t->tm_year -= 100;
tod->year1 = t->tm_year / 10; tod_3000.year1 = t->tm_year / 10;
tod->year2 = t->tm_year % 10; tod_3000.year2 = t->tm_year % 10;
} }
tod->cntrl1 = TOD3000_CNTRL1_FREE; tod_3000.cntrl1 = TOD3000_CNTRL1_FREE;
return 0; return 0;
} }
static int a2000_hwclk(int op, struct rtc_time *t) static int a2000_hwclk(int op, struct rtc_time *t)
{ {
volatile struct tod2000 *tod = TOD_2000; int cnt = 5;
tod->cntrl1 = TOD2000_CNTRL1_HOLD; tod_2000.cntrl1 = TOD2000_CNTRL1_HOLD;
while (tod->cntrl1 & TOD2000_CNTRL1_BUSY) while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
; {
tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
udelay(70);
tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
}
if (!cnt)
printk(KERN_INFO "hwclk: timed out waiting for RTC (0x%x)\n", tod_2000.cntrl1);
if (!op) { /* read */ if (!op) { /* read */
t->tm_sec = tod->second1 * 10 + tod->second2; t->tm_sec = tod_2000.second1 * 10 + tod_2000.second2;
t->tm_min = tod->minute1 * 10 + tod->minute2; t->tm_min = tod_2000.minute1 * 10 + tod_2000.minute2;
t->tm_hour = (tod->hour1 & 3) * 10 + tod->hour2; t->tm_hour = (tod_2000.hour1 & 3) * 10 + tod_2000.hour2;
t->tm_mday = tod->day1 * 10 + tod->day2; t->tm_mday = tod_2000.day1 * 10 + tod_2000.day2;
t->tm_wday = tod->weekday; t->tm_wday = tod_2000.weekday;
t->tm_mon = tod->month1 * 10 + tod->month2 - 1; t->tm_mon = tod_2000.month1 * 10 + tod_2000.month2 - 1;
t->tm_year = tod->year1 * 10 + tod->year2; t->tm_year = tod_2000.year1 * 10 + tod_2000.year2;
if (t->tm_year <= 69) if (t->tm_year <= 69)
t->tm_year += 100; t->tm_year += 100;
if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){ if (!(tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)){
if (!(tod->hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12) if (!(tod_2000.hour1 & TOD2000_HOUR1_PM) && t->tm_hour == 12)
t->tm_hour = 0; 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; t->tm_hour += 12;
} }
} else { } else {
tod->second1 = t->tm_sec / 10; tod_2000.second1 = t->tm_sec / 10;
tod->second2 = t->tm_sec % 10; tod_2000.second2 = t->tm_sec % 10;
tod->minute1 = t->tm_min / 10; tod_2000.minute1 = t->tm_min / 10;
tod->minute2 = t->tm_min % 10; tod_2000.minute2 = t->tm_min % 10;
if (tod->cntrl3 & TOD2000_CNTRL3_24HMODE) if (tod_2000.cntrl3 & TOD2000_CNTRL3_24HMODE)
tod->hour1 = t->tm_hour / 10; tod_2000.hour1 = t->tm_hour / 10;
else if (t->tm_hour >= 12) else if (t->tm_hour >= 12)
tod->hour1 = TOD2000_HOUR1_PM + tod_2000.hour1 = TOD2000_HOUR1_PM +
(t->tm_hour - 12) / 10; (t->tm_hour - 12) / 10;
else else
tod->hour1 = t->tm_hour / 10; tod_2000.hour1 = t->tm_hour / 10;
tod->hour2 = t->tm_hour % 10; tod_2000.hour2 = t->tm_hour % 10;
tod->day1 = t->tm_mday / 10; tod_2000.day1 = t->tm_mday / 10;
tod->day2 = t->tm_mday % 10; tod_2000.day2 = t->tm_mday % 10;
if (t->tm_wday != -1) if (t->tm_wday != -1)
tod->weekday = t->tm_wday; tod_2000.weekday = t->tm_wday;
tod->month1 = (t->tm_mon + 1) / 10; tod_2000.month1 = (t->tm_mon + 1) / 10;
tod->month2 = (t->tm_mon + 1) % 10; tod_2000.month2 = (t->tm_mon + 1) % 10;
if (t->tm_year >= 100) if (t->tm_year >= 100)
t->tm_year -= 100; t->tm_year -= 100;
tod->year1 = t->tm_year / 10; tod_2000.year1 = t->tm_year / 10;
tod->year2 = t->tm_year % 10; tod_2000.year2 = t->tm_year % 10;
} }
tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD; tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
return 0; return 0;
} }
...@@ -644,35 +652,54 @@ static int amiga_set_clock_mmss (unsigned long nowtime) ...@@ -644,35 +652,54 @@ static int amiga_set_clock_mmss (unsigned long nowtime)
short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
if (AMIGAHW_PRESENT(A3000_CLK)) { if (AMIGAHW_PRESENT(A3000_CLK)) {
volatile struct tod3000 *tod = TOD_3000; tod_3000.cntrl1 = TOD3000_CNTRL1_HOLD;
tod->cntrl1 = TOD3000_CNTRL1_HOLD; 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->second1 = real_seconds / 10; tod_3000.cntrl1 = TOD3000_CNTRL1_FREE;
tod->second2 = real_seconds % 10;
tod->minute1 = real_minutes / 10;
tod->minute2 = real_minutes % 10;
tod->cntrl1 = TOD3000_CNTRL1_FREE;
} else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ { } else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
volatile struct tod2000 *tod = TOD_2000; int cnt = 5;
tod->cntrl1 = TOD2000_CNTRL1_HOLD; tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
while (tod->cntrl1 & TOD2000_CNTRL1_BUSY) while ((tod_2000.cntrl1 & TOD2000_CNTRL1_BUSY) && cnt--)
; {
tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
udelay(70);
tod_2000.cntrl1 |= TOD2000_CNTRL1_HOLD;
}
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_2000.second1 = real_seconds / 10;
tod->second2 = real_seconds % 10; tod_2000.second2 = real_seconds % 10;
tod->minute1 = real_minutes / 10; tod_2000.minute1 = real_minutes / 10;
tod->minute2 = real_minutes % 10; tod_2000.minute2 = real_minutes % 10;
tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD; tod_2000.cntrl1 &= ~TOD2000_CNTRL1_HOLD;
} }
return 0; 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 ) static NORET_TYPE void amiga_reset( void )
ATTRIB_NORET; ATTRIB_NORET;
......
...@@ -324,7 +324,7 @@ struct tod3000 { ...@@ -324,7 +324,7 @@ struct tod3000 {
}; };
#define TOD3000_CNTRL1_HOLD 0 #define TOD3000_CNTRL1_HOLD 0
#define TOD3000_CNTRL1_FREE 9 #define TOD3000_CNTRL1_FREE 9
#define TOD_3000 ((struct tod3000 *)(zTwoBase+0xDC0000)) #define tod_3000 ((*(volatile struct tod3000 *)(zTwoBase+0xDC0000)))
struct tod2000 { struct tod2000 {
unsigned int :28, second2:4; /* lower digit */ unsigned int :28, second2:4; /* lower digit */
...@@ -349,6 +349,6 @@ struct tod2000 { ...@@ -349,6 +349,6 @@ struct tod2000 {
#define TOD2000_CNTRL1_BUSY (1<<1) #define TOD2000_CNTRL1_BUSY (1<<1)
#define TOD2000_CNTRL3_24HMODE (1<<2) #define TOD2000_CNTRL3_24HMODE (1<<2)
#define TOD2000_HOUR1_PM (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 */ #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