1*2f16049cSEmmanuel Vadot /*-
2*2f16049cSEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause
3*2f16049cSEmmanuel Vadot *
4*2f16049cSEmmanuel Vadot * Copyright (c) 2012 Yusuke Tanaka
5*2f16049cSEmmanuel Vadot * All rights reserved.
6*2f16049cSEmmanuel Vadot *
7*2f16049cSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
8*2f16049cSEmmanuel Vadot * modification, are permitted provided that the following conditions
9*2f16049cSEmmanuel Vadot * are met:
10*2f16049cSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
11*2f16049cSEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
12*2f16049cSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
13*2f16049cSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
14*2f16049cSEmmanuel Vadot * documentation and/or other materials provided with the distribution.
15*2f16049cSEmmanuel Vadot *
16*2f16049cSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*2f16049cSEmmanuel Vadot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*2f16049cSEmmanuel Vadot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*2f16049cSEmmanuel Vadot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*2f16049cSEmmanuel Vadot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*2f16049cSEmmanuel Vadot * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*2f16049cSEmmanuel Vadot * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*2f16049cSEmmanuel Vadot * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*2f16049cSEmmanuel Vadot * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*2f16049cSEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*2f16049cSEmmanuel Vadot * SUCH DAMAGE.
27*2f16049cSEmmanuel Vadot */
28*2f16049cSEmmanuel Vadot
29*2f16049cSEmmanuel Vadot /*-
30*2f16049cSEmmanuel Vadot * Copyright (c) 2011 Frank Wille.
31*2f16049cSEmmanuel Vadot * All rights reserved.
32*2f16049cSEmmanuel Vadot *
33*2f16049cSEmmanuel Vadot * Written by Frank Wille for The NetBSD Project.
34*2f16049cSEmmanuel Vadot *
35*2f16049cSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without
36*2f16049cSEmmanuel Vadot * modification, are permitted provided that the following conditions
37*2f16049cSEmmanuel Vadot * are met:
38*2f16049cSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright
39*2f16049cSEmmanuel Vadot * notice, this list of conditions and the following disclaimer.
40*2f16049cSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright
41*2f16049cSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the
42*2f16049cSEmmanuel Vadot * documentation and/or other materials provided with the distribution.
43*2f16049cSEmmanuel Vadot *
44*2f16049cSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
45*2f16049cSEmmanuel Vadot * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
46*2f16049cSEmmanuel Vadot * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47*2f16049cSEmmanuel Vadot * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
48*2f16049cSEmmanuel Vadot * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49*2f16049cSEmmanuel Vadot * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50*2f16049cSEmmanuel Vadot * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51*2f16049cSEmmanuel Vadot * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52*2f16049cSEmmanuel Vadot * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53*2f16049cSEmmanuel Vadot * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
54*2f16049cSEmmanuel Vadot * POSSIBILITY OF SUCH DAMAGE.
55*2f16049cSEmmanuel Vadot */
56*2f16049cSEmmanuel Vadot
57*2f16049cSEmmanuel Vadot #include <sys/cdefs.h>
58*2f16049cSEmmanuel Vadot /*
59*2f16049cSEmmanuel Vadot * Driver for Seiko Instruments S-35390A Real-time Clock
60*2f16049cSEmmanuel Vadot */
61*2f16049cSEmmanuel Vadot
62*2f16049cSEmmanuel Vadot #include "opt_platform.h"
63*2f16049cSEmmanuel Vadot
64*2f16049cSEmmanuel Vadot #include <sys/param.h>
65*2f16049cSEmmanuel Vadot #include <sys/systm.h>
66*2f16049cSEmmanuel Vadot #include <sys/bus.h>
67*2f16049cSEmmanuel Vadot #include <sys/clock.h>
68*2f16049cSEmmanuel Vadot #include <sys/kernel.h>
69*2f16049cSEmmanuel Vadot #include <sys/module.h>
70*2f16049cSEmmanuel Vadot
71*2f16049cSEmmanuel Vadot #include <dev/iicbus/iicbus.h>
72*2f16049cSEmmanuel Vadot #include <dev/iicbus/iiconf.h>
73*2f16049cSEmmanuel Vadot
74*2f16049cSEmmanuel Vadot #ifdef FDT
75*2f16049cSEmmanuel Vadot #include <dev/ofw/openfirm.h>
76*2f16049cSEmmanuel Vadot #include <dev/ofw/ofw_bus.h>
77*2f16049cSEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h>
78*2f16049cSEmmanuel Vadot #endif
79*2f16049cSEmmanuel Vadot
80*2f16049cSEmmanuel Vadot #include "clock_if.h"
81*2f16049cSEmmanuel Vadot #include "iicbus_if.h"
82*2f16049cSEmmanuel Vadot
83*2f16049cSEmmanuel Vadot #define S390_DEVNAME "s35390a_rtc"
84*2f16049cSEmmanuel Vadot #define S390_DEVCODE 0x6 /* 0110 */
85*2f16049cSEmmanuel Vadot /*
86*2f16049cSEmmanuel Vadot * S-35390A uses 4-bit device code + 3-bit command in the slave address
87*2f16049cSEmmanuel Vadot * field. The possible combination is 0x60-0x6f including the R/W bit.
88*2f16049cSEmmanuel Vadot * 0x60 means an write access to status register 1.
89*2f16049cSEmmanuel Vadot */
90*2f16049cSEmmanuel Vadot #define S390_ADDR (S390_DEVCODE << 4)
91*2f16049cSEmmanuel Vadot
92*2f16049cSEmmanuel Vadot /* Registers are encoded into the slave address */
93*2f16049cSEmmanuel Vadot #define S390_STATUS1 (0 << 1)
94*2f16049cSEmmanuel Vadot #define S390_STATUS2 (1 << 1)
95*2f16049cSEmmanuel Vadot #define S390_REALTIME1 (2 << 1)
96*2f16049cSEmmanuel Vadot #define S390_REALTIME2 (3 << 1)
97*2f16049cSEmmanuel Vadot #define S390_INT1_1 (4 << 1)
98*2f16049cSEmmanuel Vadot #define S390_INT1_2 (5 << 1)
99*2f16049cSEmmanuel Vadot #define S390_CLOCKADJ (6 << 1)
100*2f16049cSEmmanuel Vadot #define S390_FREE (7 << 1)
101*2f16049cSEmmanuel Vadot
102*2f16049cSEmmanuel Vadot /* Status1 bits */
103*2f16049cSEmmanuel Vadot #define S390_ST1_POC (1 << 7)
104*2f16049cSEmmanuel Vadot #define S390_ST1_BLD (1 << 6)
105*2f16049cSEmmanuel Vadot #define S390_ST1_24H (1 << 1)
106*2f16049cSEmmanuel Vadot #define S390_ST1_RESET (1 << 0)
107*2f16049cSEmmanuel Vadot
108*2f16049cSEmmanuel Vadot /* Status2 bits */
109*2f16049cSEmmanuel Vadot #define S390_ST2_TEST (1 << 7)
110*2f16049cSEmmanuel Vadot
111*2f16049cSEmmanuel Vadot /* Realtime1 data bytes */
112*2f16049cSEmmanuel Vadot #define S390_RT1_NBYTES 7
113*2f16049cSEmmanuel Vadot #define S390_RT1_YEAR 0
114*2f16049cSEmmanuel Vadot #define S390_RT1_MONTH 1
115*2f16049cSEmmanuel Vadot #define S390_RT1_DAY 2
116*2f16049cSEmmanuel Vadot #define S390_RT1_WDAY 3
117*2f16049cSEmmanuel Vadot #define S390_RT1_HOUR 4
118*2f16049cSEmmanuel Vadot #define S390_RT1_MINUTE 5
119*2f16049cSEmmanuel Vadot #define S390_RT1_SECOND 6
120*2f16049cSEmmanuel Vadot
121*2f16049cSEmmanuel Vadot struct s390rtc_softc {
122*2f16049cSEmmanuel Vadot device_t sc_dev;
123*2f16049cSEmmanuel Vadot uint16_t sc_addr;
124*2f16049cSEmmanuel Vadot };
125*2f16049cSEmmanuel Vadot
126*2f16049cSEmmanuel Vadot /*
127*2f16049cSEmmanuel Vadot * S-35390A interprets bits in each byte on SDA in reverse order.
128*2f16049cSEmmanuel Vadot * bitreverse() reverses the bits in uint8_t.
129*2f16049cSEmmanuel Vadot */
130*2f16049cSEmmanuel Vadot static const uint8_t nibbletab[] = {
131*2f16049cSEmmanuel Vadot /* 0x0 0000 -> 0000 */ 0x0,
132*2f16049cSEmmanuel Vadot /* 0x1 0001 -> 1000 */ 0x8,
133*2f16049cSEmmanuel Vadot /* 0x2 0010 -> 0100 */ 0x4,
134*2f16049cSEmmanuel Vadot /* 0x3 0011 -> 1100 */ 0xc,
135*2f16049cSEmmanuel Vadot /* 0x4 0100 -> 0010 */ 0x2,
136*2f16049cSEmmanuel Vadot /* 0x5 0101 -> 1010 */ 0xa,
137*2f16049cSEmmanuel Vadot /* 0x6 0110 -> 0110 */ 0x6,
138*2f16049cSEmmanuel Vadot /* 0x7 0111 -> 1110 */ 0xe,
139*2f16049cSEmmanuel Vadot /* 0x8 1000 -> 0001 */ 0x1,
140*2f16049cSEmmanuel Vadot /* 0x9 1001 -> 1001 */ 0x9,
141*2f16049cSEmmanuel Vadot /* 0xa 1010 -> 0101 */ 0x5,
142*2f16049cSEmmanuel Vadot /* 0xb 1011 -> 1101 */ 0xd,
143*2f16049cSEmmanuel Vadot /* 0xc 1100 -> 0011 */ 0x3,
144*2f16049cSEmmanuel Vadot /* 0xd 1101 -> 1011 */ 0xb,
145*2f16049cSEmmanuel Vadot /* 0xe 1110 -> 0111 */ 0x7,
146*2f16049cSEmmanuel Vadot /* 0xf 1111 -> 1111 */ 0xf, };
147*2f16049cSEmmanuel Vadot
148*2f16049cSEmmanuel Vadot static uint8_t
bitreverse(uint8_t x)149*2f16049cSEmmanuel Vadot bitreverse(uint8_t x)
150*2f16049cSEmmanuel Vadot {
151*2f16049cSEmmanuel Vadot
152*2f16049cSEmmanuel Vadot return (nibbletab[x & 0xf] << 4) | nibbletab[x >> 4];
153*2f16049cSEmmanuel Vadot }
154*2f16049cSEmmanuel Vadot
155*2f16049cSEmmanuel Vadot static int
s390rtc_read(device_t dev,uint8_t reg,uint8_t * buf,size_t len)156*2f16049cSEmmanuel Vadot s390rtc_read(device_t dev, uint8_t reg, uint8_t *buf, size_t len)
157*2f16049cSEmmanuel Vadot {
158*2f16049cSEmmanuel Vadot struct s390rtc_softc *sc = device_get_softc(dev);
159*2f16049cSEmmanuel Vadot struct iic_msg msg[] = {
160*2f16049cSEmmanuel Vadot {
161*2f16049cSEmmanuel Vadot .slave = sc->sc_addr | reg,
162*2f16049cSEmmanuel Vadot .flags = IIC_M_RD,
163*2f16049cSEmmanuel Vadot .len = len,
164*2f16049cSEmmanuel Vadot .buf = buf,
165*2f16049cSEmmanuel Vadot },
166*2f16049cSEmmanuel Vadot };
167*2f16049cSEmmanuel Vadot int i;
168*2f16049cSEmmanuel Vadot int error;
169*2f16049cSEmmanuel Vadot
170*2f16049cSEmmanuel Vadot error = iicbus_transfer_excl(dev, msg, 1, IIC_WAIT);
171*2f16049cSEmmanuel Vadot if (error)
172*2f16049cSEmmanuel Vadot return (error);
173*2f16049cSEmmanuel Vadot
174*2f16049cSEmmanuel Vadot /* this chip returns each byte in reverse order */
175*2f16049cSEmmanuel Vadot for (i = 0; i < len; ++i)
176*2f16049cSEmmanuel Vadot buf[i] = bitreverse(buf[i]);
177*2f16049cSEmmanuel Vadot
178*2f16049cSEmmanuel Vadot return (0);
179*2f16049cSEmmanuel Vadot }
180*2f16049cSEmmanuel Vadot
181*2f16049cSEmmanuel Vadot static int
s390rtc_write(device_t dev,uint8_t reg,uint8_t * buf,size_t len)182*2f16049cSEmmanuel Vadot s390rtc_write(device_t dev, uint8_t reg, uint8_t *buf, size_t len)
183*2f16049cSEmmanuel Vadot {
184*2f16049cSEmmanuel Vadot struct s390rtc_softc *sc = device_get_softc(dev);
185*2f16049cSEmmanuel Vadot struct iic_msg msg[] = {
186*2f16049cSEmmanuel Vadot {
187*2f16049cSEmmanuel Vadot .slave = sc->sc_addr | reg,
188*2f16049cSEmmanuel Vadot .flags = IIC_M_WR,
189*2f16049cSEmmanuel Vadot .len = len,
190*2f16049cSEmmanuel Vadot .buf = buf,
191*2f16049cSEmmanuel Vadot },
192*2f16049cSEmmanuel Vadot };
193*2f16049cSEmmanuel Vadot int i;
194*2f16049cSEmmanuel Vadot
195*2f16049cSEmmanuel Vadot /* this chip expects each byte in reverse order */
196*2f16049cSEmmanuel Vadot for (i = 0; i < len; ++i)
197*2f16049cSEmmanuel Vadot buf[i] = bitreverse(buf[i]);
198*2f16049cSEmmanuel Vadot
199*2f16049cSEmmanuel Vadot return (iicbus_transfer_excl(dev, msg, 1, IIC_WAIT));
200*2f16049cSEmmanuel Vadot }
201*2f16049cSEmmanuel Vadot
202*2f16049cSEmmanuel Vadot static int
s390rtc_probe(device_t dev)203*2f16049cSEmmanuel Vadot s390rtc_probe(device_t dev)
204*2f16049cSEmmanuel Vadot {
205*2f16049cSEmmanuel Vadot
206*2f16049cSEmmanuel Vadot #ifdef FDT
207*2f16049cSEmmanuel Vadot if (!ofw_bus_status_okay(dev))
208*2f16049cSEmmanuel Vadot return (ENXIO);
209*2f16049cSEmmanuel Vadot
210*2f16049cSEmmanuel Vadot if (!ofw_bus_is_compatible(dev, "sii,s35390a"))
211*2f16049cSEmmanuel Vadot return (ENXIO);
212*2f16049cSEmmanuel Vadot #else
213*2f16049cSEmmanuel Vadot if (iicbus_get_addr(dev) != S390_ADDR) {
214*2f16049cSEmmanuel Vadot if (bootverbose)
215*2f16049cSEmmanuel Vadot device_printf(dev, "slave address mismatch. "
216*2f16049cSEmmanuel Vadot "(%02x != %02x)\n", iicbus_get_addr(dev),
217*2f16049cSEmmanuel Vadot S390_ADDR);
218*2f16049cSEmmanuel Vadot return (ENXIO);
219*2f16049cSEmmanuel Vadot }
220*2f16049cSEmmanuel Vadot #endif
221*2f16049cSEmmanuel Vadot device_set_desc(dev, "Seiko Instruments S-35390A RTC");
222*2f16049cSEmmanuel Vadot
223*2f16049cSEmmanuel Vadot return (BUS_PROBE_DEFAULT);
224*2f16049cSEmmanuel Vadot }
225*2f16049cSEmmanuel Vadot
226*2f16049cSEmmanuel Vadot static void
s390rtc_start(void * arg)227*2f16049cSEmmanuel Vadot s390rtc_start(void *arg)
228*2f16049cSEmmanuel Vadot {
229*2f16049cSEmmanuel Vadot device_t dev;
230*2f16049cSEmmanuel Vadot uint8_t reg;
231*2f16049cSEmmanuel Vadot int error;
232*2f16049cSEmmanuel Vadot
233*2f16049cSEmmanuel Vadot dev = arg;
234*2f16049cSEmmanuel Vadot
235*2f16049cSEmmanuel Vadot /* Reset the chip and turn on 24h mode, after power-off or battery. */
236*2f16049cSEmmanuel Vadot error = s390rtc_read(dev, S390_STATUS1, ®, 1);
237*2f16049cSEmmanuel Vadot if (error) {
238*2f16049cSEmmanuel Vadot device_printf(dev, "%s: cannot read status1 register\n",
239*2f16049cSEmmanuel Vadot __func__);
240*2f16049cSEmmanuel Vadot return;
241*2f16049cSEmmanuel Vadot }
242*2f16049cSEmmanuel Vadot if (reg & (S390_ST1_POC | S390_ST1_BLD)) {
243*2f16049cSEmmanuel Vadot reg |= S390_ST1_24H | S390_ST1_RESET;
244*2f16049cSEmmanuel Vadot error = s390rtc_write(dev, S390_STATUS1, ®, 1);
245*2f16049cSEmmanuel Vadot if (error) {
246*2f16049cSEmmanuel Vadot device_printf(dev,
247*2f16049cSEmmanuel Vadot "%s: cannot initialize\n", __func__);
248*2f16049cSEmmanuel Vadot return;
249*2f16049cSEmmanuel Vadot }
250*2f16049cSEmmanuel Vadot }
251*2f16049cSEmmanuel Vadot
252*2f16049cSEmmanuel Vadot /* Disable the test mode, when enabled. */
253*2f16049cSEmmanuel Vadot error = s390rtc_read(dev, S390_STATUS2, ®, 1);
254*2f16049cSEmmanuel Vadot if (error) {
255*2f16049cSEmmanuel Vadot device_printf(dev, "%s: cannot read status2 register\n",
256*2f16049cSEmmanuel Vadot __func__);
257*2f16049cSEmmanuel Vadot return;
258*2f16049cSEmmanuel Vadot }
259*2f16049cSEmmanuel Vadot if (reg & S390_ST2_TEST) {
260*2f16049cSEmmanuel Vadot reg &= ~S390_ST2_TEST;
261*2f16049cSEmmanuel Vadot error = s390rtc_write(dev, S390_STATUS2, ®, 1);
262*2f16049cSEmmanuel Vadot if (error) {
263*2f16049cSEmmanuel Vadot device_printf(dev,
264*2f16049cSEmmanuel Vadot "%s: cannot disable the test mode\n", __func__);
265*2f16049cSEmmanuel Vadot return;
266*2f16049cSEmmanuel Vadot }
267*2f16049cSEmmanuel Vadot }
268*2f16049cSEmmanuel Vadot
269*2f16049cSEmmanuel Vadot clock_register(dev, 1000000); /* 1 second resolution */
270*2f16049cSEmmanuel Vadot }
271*2f16049cSEmmanuel Vadot
272*2f16049cSEmmanuel Vadot static int
s390rtc_attach(device_t dev)273*2f16049cSEmmanuel Vadot s390rtc_attach(device_t dev)
274*2f16049cSEmmanuel Vadot {
275*2f16049cSEmmanuel Vadot struct s390rtc_softc *sc;
276*2f16049cSEmmanuel Vadot
277*2f16049cSEmmanuel Vadot sc = device_get_softc(dev);
278*2f16049cSEmmanuel Vadot sc->sc_dev = dev;
279*2f16049cSEmmanuel Vadot sc->sc_addr = iicbus_get_addr(dev);
280*2f16049cSEmmanuel Vadot
281*2f16049cSEmmanuel Vadot config_intrhook_oneshot(s390rtc_start, dev);
282*2f16049cSEmmanuel Vadot
283*2f16049cSEmmanuel Vadot return (0);
284*2f16049cSEmmanuel Vadot }
285*2f16049cSEmmanuel Vadot
286*2f16049cSEmmanuel Vadot static int
s390rtc_detach(device_t dev)287*2f16049cSEmmanuel Vadot s390rtc_detach(device_t dev)
288*2f16049cSEmmanuel Vadot {
289*2f16049cSEmmanuel Vadot
290*2f16049cSEmmanuel Vadot clock_unregister(dev);
291*2f16049cSEmmanuel Vadot return (0);
292*2f16049cSEmmanuel Vadot }
293*2f16049cSEmmanuel Vadot
294*2f16049cSEmmanuel Vadot static int
s390rtc_gettime(device_t dev,struct timespec * ts)295*2f16049cSEmmanuel Vadot s390rtc_gettime(device_t dev, struct timespec *ts)
296*2f16049cSEmmanuel Vadot {
297*2f16049cSEmmanuel Vadot uint8_t bcd[S390_RT1_NBYTES];
298*2f16049cSEmmanuel Vadot struct bcd_clocktime bct;
299*2f16049cSEmmanuel Vadot int error;
300*2f16049cSEmmanuel Vadot
301*2f16049cSEmmanuel Vadot error = s390rtc_read(dev, S390_REALTIME1, bcd, S390_RT1_NBYTES);
302*2f16049cSEmmanuel Vadot if (error) {
303*2f16049cSEmmanuel Vadot device_printf(dev, "%s: cannot read realtime1 register\n",
304*2f16049cSEmmanuel Vadot __func__);
305*2f16049cSEmmanuel Vadot return (error);
306*2f16049cSEmmanuel Vadot }
307*2f16049cSEmmanuel Vadot
308*2f16049cSEmmanuel Vadot /*
309*2f16049cSEmmanuel Vadot * Convert the register values into something useable.
310*2f16049cSEmmanuel Vadot */
311*2f16049cSEmmanuel Vadot bct.nsec = 0;
312*2f16049cSEmmanuel Vadot bct.sec = bcd[S390_RT1_SECOND];
313*2f16049cSEmmanuel Vadot bct.min = bcd[S390_RT1_MINUTE];
314*2f16049cSEmmanuel Vadot bct.hour = bcd[S390_RT1_HOUR] & 0x3f;
315*2f16049cSEmmanuel Vadot bct.day = bcd[S390_RT1_DAY];
316*2f16049cSEmmanuel Vadot bct.dow = bcd[S390_RT1_WDAY] & 0x07;
317*2f16049cSEmmanuel Vadot bct.mon = bcd[S390_RT1_MONTH];
318*2f16049cSEmmanuel Vadot bct.year = bcd[S390_RT1_YEAR];
319*2f16049cSEmmanuel Vadot
320*2f16049cSEmmanuel Vadot clock_dbgprint_bcd(dev, CLOCK_DBG_READ, &bct);
321*2f16049cSEmmanuel Vadot return (clock_bcd_to_ts(&bct, ts, false));
322*2f16049cSEmmanuel Vadot }
323*2f16049cSEmmanuel Vadot
324*2f16049cSEmmanuel Vadot static int
s390rtc_settime(device_t dev,struct timespec * ts)325*2f16049cSEmmanuel Vadot s390rtc_settime(device_t dev, struct timespec *ts)
326*2f16049cSEmmanuel Vadot {
327*2f16049cSEmmanuel Vadot uint8_t bcd[S390_RT1_NBYTES];
328*2f16049cSEmmanuel Vadot struct bcd_clocktime bct;
329*2f16049cSEmmanuel Vadot
330*2f16049cSEmmanuel Vadot clock_ts_to_bcd(ts, &bct, false);
331*2f16049cSEmmanuel Vadot clock_dbgprint_bcd(dev, CLOCK_DBG_WRITE, &bct);
332*2f16049cSEmmanuel Vadot
333*2f16049cSEmmanuel Vadot /*
334*2f16049cSEmmanuel Vadot * Convert our time representation into something the S-xx390
335*2f16049cSEmmanuel Vadot * can understand.
336*2f16049cSEmmanuel Vadot */
337*2f16049cSEmmanuel Vadot bcd[S390_RT1_SECOND] = bct.sec;
338*2f16049cSEmmanuel Vadot bcd[S390_RT1_MINUTE] = bct.min;
339*2f16049cSEmmanuel Vadot bcd[S390_RT1_HOUR] = bct.hour;
340*2f16049cSEmmanuel Vadot bcd[S390_RT1_DAY] = bct.day;
341*2f16049cSEmmanuel Vadot bcd[S390_RT1_WDAY] = bct.dow;
342*2f16049cSEmmanuel Vadot bcd[S390_RT1_MONTH] = bct.mon;
343*2f16049cSEmmanuel Vadot bcd[S390_RT1_YEAR] = bct.year & 0xff;
344*2f16049cSEmmanuel Vadot
345*2f16049cSEmmanuel Vadot return (s390rtc_write(dev, S390_REALTIME1, bcd, S390_RT1_NBYTES));
346*2f16049cSEmmanuel Vadot }
347*2f16049cSEmmanuel Vadot
348*2f16049cSEmmanuel Vadot static device_method_t s390rtc_methods[] = {
349*2f16049cSEmmanuel Vadot DEVMETHOD(device_probe, s390rtc_probe),
350*2f16049cSEmmanuel Vadot DEVMETHOD(device_attach, s390rtc_attach),
351*2f16049cSEmmanuel Vadot DEVMETHOD(device_detach, s390rtc_detach),
352*2f16049cSEmmanuel Vadot
353*2f16049cSEmmanuel Vadot DEVMETHOD(clock_gettime, s390rtc_gettime),
354*2f16049cSEmmanuel Vadot DEVMETHOD(clock_settime, s390rtc_settime),
355*2f16049cSEmmanuel Vadot
356*2f16049cSEmmanuel Vadot DEVMETHOD_END
357*2f16049cSEmmanuel Vadot };
358*2f16049cSEmmanuel Vadot
359*2f16049cSEmmanuel Vadot static driver_t s390rtc_driver = {
360*2f16049cSEmmanuel Vadot S390_DEVNAME,
361*2f16049cSEmmanuel Vadot s390rtc_methods,
362*2f16049cSEmmanuel Vadot sizeof(struct s390rtc_softc),
363*2f16049cSEmmanuel Vadot };
364*2f16049cSEmmanuel Vadot
365*2f16049cSEmmanuel Vadot DRIVER_MODULE(s35390a, iicbus, s390rtc_driver, NULL, NULL);
366*2f16049cSEmmanuel Vadot MODULE_VERSION(s35390a, 1);
367*2f16049cSEmmanuel Vadot MODULE_DEPEND(s35390a, iicbus, 1, 1, 1);
368