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
54uint8_t rtc_read(uint32_t addr);
55void rtc_write(uint32_t addr, uint8_t data);
56
57static void
58rtc_init(void)
59{
60
61	SHREG_SCSPTR = SCSPTR_SPB1IO | SCSPTR_SPB1DT
62		       | SCSPTR_SPB0IO | SCSPTR_SPB0DT;
63}
64
65/* control RTC chip enable */
66static void
67rtc_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
77static inline void
78rtc_clk(int onoff)
79{
80
81	if (onoff) {
82		SHREG_SCSPTR |= SCSPTR_SPB0DT;
83	} else {
84		SHREG_SCSPTR &= ~SCSPTR_SPB0DT;
85	}
86}
87
88static void
89rtc_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 */
100static void
101rtc_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 */
115static int
116rtc_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
128uint8_t
129rtc_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
164void
165rtc_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
193satime_t
194getsecs(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