1 /* $OpenBSD: getsecs.c,v 1.8 2023/04/13 02:19:04 jsg Exp $ */
2 /* $NetBSD: getsecs.c,v 1.4 2022/08/24 14:22:35 nonaka Exp $ */
3
4 /*-
5 * Copyright (c) 2005 NONAKA Kimihiro
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/param.h>
31
32 #include <libsa.h>
33
34 #include <sh/devreg.h>
35 #include <arch/sh/dev/scireg.h>
36
37 #include <arch/landisk/dev/rs5c313reg.h>
38
39 /**
40 * RICOH RS5C313
41 *
42 * Web page: http://www.ricoh.co.jp/LSI/product_rtc/3wire/5c313/
43 *
44 * How to control RS5C313 on LANDISK
45 * see http://www.mizore.jp/wiki/index.php?LANDISK/rtc
46 */
47
48 uint8_t rtc_read(uint32_t addr);
49
50 static void
rtc_init(void)51 rtc_init(void)
52 {
53
54 SHREG_SCSPTR = SCSPTR_SPB1IO | SCSPTR_SPB1DT
55 | SCSPTR_SPB0IO | SCSPTR_SPB0DT;
56 delay(1);
57 }
58
59 /* control RTC chip enable */
60 static void
rtc_ce(int onoff)61 rtc_ce(int onoff)
62 {
63
64 if (onoff) {
65 _reg_write_1(0xb0000003, (1 << 1));
66 } else {
67 _reg_write_1(0xb0000003, (0 << 1));
68 }
69 delay(1);
70 }
71
72 static inline void
rtc_clk(int onoff)73 rtc_clk(int onoff)
74 {
75
76 if (onoff) {
77 SHREG_SCSPTR |= SCSPTR_SPB0DT;
78 } else {
79 SHREG_SCSPTR &= ~SCSPTR_SPB0DT;
80 }
81 delay(1);
82 }
83
84 static void
rtc_dir(int output)85 rtc_dir(int output)
86 {
87
88 if (output) {
89 SHREG_SCSPTR |= SCSPTR_SPB1IO;
90 } else {
91 SHREG_SCSPTR &= ~SCSPTR_SPB1IO;
92 }
93 delay(1);
94 }
95
96 /* data-out */
97 static void
rtc_do(int onoff)98 rtc_do(int onoff)
99 {
100
101 if (onoff) {
102 SHREG_SCSPTR |= SCSPTR_SPB1DT;
103 } else {
104 SHREG_SCSPTR &= ~SCSPTR_SPB1DT;
105 }
106 delay(1);
107
108 rtc_clk(0);
109 rtc_clk(1);
110 }
111
112 /* data-in */
113 static int
rtc_di(void)114 rtc_di(void)
115 {
116 int d;
117
118 d = (SHREG_SCSPTR & SCSPTR_SPB1DT) ? 1 : 0;
119
120 rtc_clk(0);
121 rtc_clk(1);
122
123 return d;
124 }
125
126 uint8_t
rtc_read(uint32_t addr)127 rtc_read(uint32_t addr)
128 {
129 uint8_t data;
130
131 rtc_init();
132 rtc_ce(1);
133
134 rtc_dir(1);
135 rtc_do(1); /* Don't care */
136 rtc_do(1); /* R/#W = 1(READ) */
137 rtc_do(1); /* AD = 1 */
138 rtc_do(0); /* DT = 0 */
139 rtc_do(addr & 0x8); /* A3 */
140 rtc_do(addr & 0x4); /* A2 */
141 rtc_do(addr & 0x2); /* A1 */
142 rtc_do(addr & 0x1); /* A0 */
143
144 rtc_dir(0);
145 (void)rtc_di();
146 (void)rtc_di();
147 (void)rtc_di();
148 (void)rtc_di();
149 data = rtc_di(); /* D3 */
150 data <<= 1;
151 data |= rtc_di(); /* D2 */
152 data <<= 1;
153 data |= rtc_di(); /* D1 */
154 data <<= 1;
155 data |= rtc_di(); /* D0 */
156
157 rtc_ce(0);
158
159 return data & 0xf;
160 }
161
162 time_t
getsecs(void)163 getsecs(void)
164 {
165 uint32_t sec, min, hour, day;
166 #if 0
167 uint32_t mon, year;
168 #endif
169 time_t secs;
170
171 sec = rtc_read(RS5C313_SEC1);
172 sec += rtc_read(RS5C313_SEC10) * 10;
173 min = rtc_read(RS5C313_MIN1);
174 min += rtc_read(RS5C313_MIN10) * 10;
175 hour = rtc_read(RS5C313_HOUR1);
176 hour += rtc_read(RS5C313_HOUR10) * 10;
177 day = rtc_read(RS5C313_DAY1);
178 day += rtc_read(RS5C313_DAY10) * 10;
179 #if 0
180 mon = rtc_read(RS5C313_MON1);
181 mon += rtc_read(RS5C313_MON10) * 10;
182 year = rtc_read(RS5C313_YEAR1);
183 year += rtc_read(RS5C313_YEAR10) * 10;
184 #endif
185
186 secs = sec;
187 secs += min * 60;
188 secs += hour * 60 * 60;
189 secs += day * 60 * 60 * 24;
190 #if 0
191 /* XXX mon, year */
192 #endif
193
194 #if defined(DEBUG)
195 printf("getsecs: secs = %d\n", (uint32_t)secs);
196 #endif
197
198 return secs;
199 }
200