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