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
48uint8_t rtc_read(uint32_t addr);
49
50static void
51rtc_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 */
60static void
61rtc_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
72static inline void
73rtc_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
84static void
85rtc_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 */
97static void
98rtc_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 */
113static int
114rtc_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
126uint8_t
127rtc_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
162time_t
163getsecs(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