|
@@ -12,15 +12,15 @@
|
|
|
#include "console.h"
|
|
|
|
|
|
#define RTC_DEVSEL 54
|
|
|
-#define RTC_CALLBACK_MASK ((1 << 8)|(1 << 2))
|
|
|
+#define RTC_CALLBACK_MASK ((1 << 8)|(1 << 2)|(1 << 0))
|
|
|
|
|
|
-#define RTC_MAGIC 0xd3
|
|
|
+#define RTC_MAGIC 211
|
|
|
|
|
|
/* Command and status register bits */
|
|
|
enum rtc_cmd_status {
|
|
|
RTC_READY = 0x01,
|
|
|
RTC_ID = 0x02, /* INP(0) shows magic number */
|
|
|
- RTC_PROGRAM = 0x04,
|
|
|
+ RTC_PROGRAM = 0x04, /* (Ready to) program RTC */
|
|
|
RTC_START_WRITE = 0x40,
|
|
|
RTC_START_READ = 0x80
|
|
|
};
|
|
@@ -43,25 +43,54 @@ static void rtc_latch_time(void)
|
|
|
rdbuf[7] = (tms.hold.tm_tick * ((100ULL << 32) >> 15)) >> 32; /* 1/100 s */
|
|
|
}
|
|
|
|
|
|
+static void rtc_store_time(void)
|
|
|
+{
|
|
|
+ struct tms tms;
|
|
|
+
|
|
|
+ /* XXX: should probably do data validation here, even an error bit */
|
|
|
+
|
|
|
+ memset(&tms, 0, sizeof tms);
|
|
|
+ tms.tm_year = wrbuf[1] + 20;
|
|
|
+ tms.tm_mon = wrbuf[2];
|
|
|
+ tms.tm_mday = wrbuf[3];
|
|
|
+ tms.tm_hour = wrbuf[4];
|
|
|
+ tms.tm_min = wrbuf[5];
|
|
|
+ tms.tm_2sec = wrbuf[6] >> 1;
|
|
|
+ tms.hold.tm_1sec = wrbuf[6] & 1;
|
|
|
+ tms.hold.tm_tick = (wrbuf[7] * ((1ULL << (15+32))/100)) >> 32;
|
|
|
+
|
|
|
+ set_systime(tms);
|
|
|
+ do_write_rtc = true;
|
|
|
+}
|
|
|
+
|
|
|
+static ABC_CALLBACK(rtc_do_program_ready)
|
|
|
+{
|
|
|
+ dev->inp_data[1] |= RTC_PROGRAM;
|
|
|
+ ABC_INP1_DATA = dev->inp_data[1];
|
|
|
+}
|
|
|
+
|
|
|
static ABC_CALLBACK(rtc_do_id)
|
|
|
{
|
|
|
/* Called on end of data read */
|
|
|
- ABC_INP1_DATA = dev->inp_data[1] |= RTC_ID;
|
|
|
+ dev->inp_data[1] |= RTC_ID;
|
|
|
+ ABC_INP1_DATA = dev->inp_data[1];
|
|
|
}
|
|
|
|
|
|
static ABC_CALLBACK(rtc_do_command)
|
|
|
{
|
|
|
if (data & RTC_PROGRAM) {
|
|
|
- need_program = true;
|
|
|
- ABC_INP1_DATA = dev->inp_data[1] &= ~RTC_READY;
|
|
|
+ dev->inp_data[1] &= ~RTC_PROGRAM;
|
|
|
+ ABC_INP1_DATA = dev->inp_data[1];
|
|
|
+ rtc_store_time();
|
|
|
}
|
|
|
if (data & RTC_START_WRITE) {
|
|
|
abc_setup_out_queue(dev, &wrbuf, 8, dev->inp_data[1]|RTC_START_WRITE);
|
|
|
}
|
|
|
if (data & RTC_START_READ) {
|
|
|
+ dev->inp_data[1] &= ~RTC_ID;
|
|
|
+ ABC_INP1_DATA = dev->inp_data[1];
|
|
|
rtc_latch_time();
|
|
|
- abc_setup_inp_queue(dev, &rdbuf, 8,
|
|
|
- (dev->inp_data[1] & ~RTC_ID)|RTC_START_READ);
|
|
|
+ abc_setup_inp_queue(dev, &rdbuf, 8, dev->inp_data[1]|RTC_START_READ);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -72,6 +101,7 @@ static struct abc_dev rtc_iodev = {
|
|
|
.inp_en = 3,
|
|
|
.inp_data_def = RTC_MAGIC,
|
|
|
.inp_data[1] = RTC_READY|RTC_ID,
|
|
|
+ .callback_out[0] = rtc_do_program_ready,
|
|
|
.callback_out[2] = rtc_do_command,
|
|
|
.callback_inp[0] = rtc_do_id
|
|
|
};
|