sam: first cut at rtc support
authorAlan Cox <alan@linux.intel.com>
Sat, 17 Nov 2018 12:49:07 +0000 (12:49 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 17 Nov 2018 12:49:07 +0000 (12:49 +0000)
Kernel/platform-sam/Makefile
Kernel/platform-sam/README
Kernel/platform-sam/config.h
Kernel/platform-sam/discard.c
Kernel/platform-sam/fuzix.lnk
Kernel/platform-sam/msm6242b.c [new file with mode: 0644]
Kernel/platform-sam/msm6242b.h [new file with mode: 0644]
Kernel/platform-sam/sam.s

index 3d80731..292f5fe 100644 (file)
@@ -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
index fcca766..c1f6a12 100644 (file)
@@ -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
index e20d507..df1c54e 100644 (file)
@@ -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 */
index 64e58b5..7b26ec1 100644 (file)
@@ -5,6 +5,7 @@
 #include <devtty.h>
 #include <devide.h>
 #include <devatom.h>
+#include <msm6242b.h>
 
 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())
index 0201675..8987261 100644 (file)
@@ -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 (file)
index 0000000..0b32f2e
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ *     RTC driver for the OKI MSM6242B (aka the SamDOS clock)
+ */
+
+#include <kernel.h>
+#include <kdata.h>
+#include <rtc.h>
+#include <msm6242b.h>
+
+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 (file)
index 0000000..1a892f4
--- /dev/null
@@ -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);
index f94cd24..b1dfd00 100644 (file)
@@ -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