From a34b4231c09bccb22640a3a1cb5bd159357951ba Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 17 Nov 2018 12:49:07 +0000 Subject: [PATCH] sam: first cut at rtc support --- Kernel/platform-sam/Makefile | 2 +- Kernel/platform-sam/README | 1 + Kernel/platform-sam/config.h | 3 +- Kernel/platform-sam/discard.c | 2 + Kernel/platform-sam/fuzix.lnk | 1 + Kernel/platform-sam/msm6242b.c | 115 +++++++++++++++++++++++++++++++++ Kernel/platform-sam/msm6242b.h | 4 ++ Kernel/platform-sam/sam.s | 26 ++++++++ 8 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 Kernel/platform-sam/msm6242b.c create mode 100644 Kernel/platform-sam/msm6242b.h diff --git a/Kernel/platform-sam/Makefile b/Kernel/platform-sam/Makefile index 3d807314..292f5fea 100644 --- a/Kernel/platform-sam/Makefile +++ b/Kernel/platform-sam/Makefile @@ -1,5 +1,5 @@ -CSRCS = devlpr.c devtty.c devfd.c devatom.c +CSRCS = devlpr.c devtty.c devfd.c devatom.c msm6242b.c CSRCS += devices.c main.c DSRCS = ../dev/devide.c ../dev/mbr.c ../dev/blkdev.c diff --git a/Kernel/platform-sam/README b/Kernel/platform-sam/README index fcca7668..c1f6a123 100644 --- a/Kernel/platform-sam/README +++ b/Kernel/platform-sam/README @@ -39,6 +39,7 @@ and all the bank juggling tricks Stub code is in the low parts of the low banks and the top of the high banks so we have two copier routines one for each half. + - Control key debugging - AtomIDE driver (prob need minimal copiers in high stubs) - RTC driver - Serial driver diff --git a/Kernel/platform-sam/config.h b/Kernel/platform-sam/config.h index e20d507e..df1c54eb 100644 --- a/Kernel/platform-sam/config.h +++ b/Kernel/platform-sam/config.h @@ -1,5 +1,4 @@ -/* RTC support is to do */ -#undef CONFIG_RTC +#define CONFIG_RTC /* Enable to make ^Z dump the inode table for debug */ #undef CONFIG_IDUMP /* Enable to make ^A drop back into the monitor */ diff --git a/Kernel/platform-sam/discard.c b/Kernel/platform-sam/discard.c index 64e58b55..7b26ec14 100644 --- a/Kernel/platform-sam/discard.c +++ b/Kernel/platform-sam/discard.c @@ -5,6 +5,7 @@ #include #include #include +#include void map_init(void) { @@ -32,6 +33,7 @@ void device_init(void) { #ifdef CONFIG_RTC /* Time of day clock */ + platform_rtc_probe(); inittod(); #endif if (atom_probe()) diff --git a/Kernel/platform-sam/fuzix.lnk b/Kernel/platform-sam/fuzix.lnk index 0201675c..8987261c 100644 --- a/Kernel/platform-sam/fuzix.lnk +++ b/Kernel/platform-sam/fuzix.lnk @@ -46,4 +46,5 @@ platform-sam/mbr.rel platform-sam/sam.rel platform-sam/sam_vt.rel platform-sam/tricks.rel +platform-sam/msm6242b.rel -e diff --git a/Kernel/platform-sam/msm6242b.c b/Kernel/platform-sam/msm6242b.c new file mode 100644 index 00000000..0b32f2ef --- /dev/null +++ b/Kernel/platform-sam/msm6242b.c @@ -0,0 +1,115 @@ +/* + * RTC driver for the OKI MSM6242B (aka the SamDOS clock) + */ + +#include +#include +#include +#include + +static uint8_t rtc_buf[6]; +static uint8_t samrtc = 0; + +uint8_t platform_rtc_secs(void) +{ + uint8_t r, v; + + if (!samrtc) + return 0xFF; + + do { + r = samrtc_in(0); + v = samrtc_in(1); + } while (r != samrtc_in(0)); + + return v * 10 + r; +} + +static void read_clock_once(void) +{ + uint8_t *p = rtc_buf; + uint8_t n = 0; + + while(n < 12) { + *p++ = samrtc_in(n) | (samrtc_in(n + 1) << 4); + n += 2; + } +} + +static void read_clock(void) +{ + uint8_t r; + + do { + r = samrtc_in(0); + read_clock_once(); + } while(samrtc_in(0) != r); +} + +int platform_rtc_read(void) +{ + uint16_t len = sizeof(struct cmos_rtc); + uint16_t y; + struct cmos_rtc cmos; + uint8_t *p = cmos.data.bytes; + + if (!samrtc) { + udata.u_error = -EOPNOTSUPP; + return -1; + } + if (udata.u_count < len) + len = udata.u_count; + + read_clock(); + + y = rtc_buf[5]; + /* 1980 based year , if its 0x20 or more we are in 2000-2079 and + need to adjust the clock up by 2000 and back by 10. If not well + then its 1980-1999 so just needs 0x1980 adding to the 0-9 we have */ + if (y >= 0x20) + y += 0x19F0; + else + y += 0x1980; + *p++ = y >> 8; + *p++ = y; + *p++ = rtc_buf[4]; /* month */ + *p++ = rtc_buf[3]; /* day */ + *p++ = rtc_buf[2]; /* Hour */ + *p++ = rtc_buf[1]; /* Minute */ + *p = rtc_buf[0]; /* Second */ + cmos.type = CMOS_RTC_BCD; + if (uput(&cmos, udata.u_base, len) == -1) + return -1; + return len; +} + +/* For now */ +int platform_rtc_write(void) +{ + udata.u_error = -EOPNOTSUPP; + return -1; +} + +uint8_t platform_rtc_probe(void) +{ + uint8_t r; + + for (r = 0; r < 12; r++) { + if (samrtc_in(r) > 9) + return 0; + } + + /* Now play with 24 hour mode */ + r = samrtc_in(15); + r &= ~4; + samrtc_out(15 | (r << 8)); + if (samrtc_in(15) != r) + return 0; + r |= 4; /* 24 hour */ + samrtc_out(15 | (r << 8)); + if (samrtc_in(15) != r) + return 0; + /* Looks like we have a valid Sam RTC */ + samrtc = 1; + return 1; +} diff --git a/Kernel/platform-sam/msm6242b.h b/Kernel/platform-sam/msm6242b.h new file mode 100644 index 00000000..1a892f4b --- /dev/null +++ b/Kernel/platform-sam/msm6242b.h @@ -0,0 +1,4 @@ +extern uint8_t samrtc_in(uint8_t reg) __z88dk_fastcall; +extern void samrtc_out(uint16_t rv) __z88dk_fastcall; + +extern uint8_t platform_rtc_probe(void); diff --git a/Kernel/platform-sam/sam.s b/Kernel/platform-sam/sam.s index f94cd243..b1dfd00f 100644 --- a/Kernel/platform-sam/sam.s +++ b/Kernel/platform-sam/sam.s @@ -281,6 +281,32 @@ keyscl: ld (hl), a ret +; +; Real time clock on port 239 +; +; The upper address bits select the actual RTC port read or +; written. +; +; This appears to be an OKI6242B +; + + .globl _samrtc_in + .globl _samrtc_out + +_samrtc_in: + ld b,l + ld c,#239 + in a,(c) + and #0x0f + ld l,a + ret +_samrtc_out: + ld b,l + ld c,#239 + out (c),h + ret + + .area _PAGE0 ; ; This exists at the bottom of each process mapping we are using -- 2.34.1