xref: /freebsd/sys/arm/nvidia/as3722_rtc.c (revision ef2ee5d07af6ab1f4c33d67b23c0d7fbabb45c70)
1*ef2ee5d0SMichal Meloun /*-
2*ef2ee5d0SMichal Meloun  * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
3*ef2ee5d0SMichal Meloun  * All rights reserved.
4*ef2ee5d0SMichal Meloun  *
5*ef2ee5d0SMichal Meloun  * Redistribution and use in source and binary forms, with or without
6*ef2ee5d0SMichal Meloun  * modification, are permitted provided that the following conditions
7*ef2ee5d0SMichal Meloun  * are met:
8*ef2ee5d0SMichal Meloun  * 1. Redistributions of source code must retain the above copyright
9*ef2ee5d0SMichal Meloun  *    notice, this list of conditions and the following disclaimer.
10*ef2ee5d0SMichal Meloun  * 2. Redistributions in binary form must reproduce the above copyright
11*ef2ee5d0SMichal Meloun  *    notice, this list of conditions and the following disclaimer in the
12*ef2ee5d0SMichal Meloun  *    documentation and/or other materials provided with the distribution.
13*ef2ee5d0SMichal Meloun  *
14*ef2ee5d0SMichal Meloun  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*ef2ee5d0SMichal Meloun  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*ef2ee5d0SMichal Meloun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*ef2ee5d0SMichal Meloun  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*ef2ee5d0SMichal Meloun  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*ef2ee5d0SMichal Meloun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*ef2ee5d0SMichal Meloun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*ef2ee5d0SMichal Meloun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*ef2ee5d0SMichal Meloun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*ef2ee5d0SMichal Meloun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*ef2ee5d0SMichal Meloun  * SUCH DAMAGE.
25*ef2ee5d0SMichal Meloun  */
26*ef2ee5d0SMichal Meloun 
27*ef2ee5d0SMichal Meloun #include <sys/cdefs.h>
28*ef2ee5d0SMichal Meloun __FBSDID("$FreeBSD$");
29*ef2ee5d0SMichal Meloun 
30*ef2ee5d0SMichal Meloun #include <sys/param.h>
31*ef2ee5d0SMichal Meloun #include <sys/systm.h>
32*ef2ee5d0SMichal Meloun #include <sys/bus.h>
33*ef2ee5d0SMichal Meloun #include <sys/clock.h>
34*ef2ee5d0SMichal Meloun #include <sys/kernel.h>
35*ef2ee5d0SMichal Meloun 
36*ef2ee5d0SMichal Meloun #include <dev/ofw/ofw_bus.h>
37*ef2ee5d0SMichal Meloun 
38*ef2ee5d0SMichal Meloun #include "clock_if.h"
39*ef2ee5d0SMichal Meloun #include "as3722.h"
40*ef2ee5d0SMichal Meloun 
41*ef2ee5d0SMichal Meloun #define	AS3722_RTC_START_YEAR	2000
42*ef2ee5d0SMichal Meloun 
43*ef2ee5d0SMichal Meloun int
44*ef2ee5d0SMichal Meloun as3722_rtc_gettime(device_t dev, struct timespec *ts)
45*ef2ee5d0SMichal Meloun {
46*ef2ee5d0SMichal Meloun 	struct as3722_softc *sc;
47*ef2ee5d0SMichal Meloun 	struct clocktime ct;
48*ef2ee5d0SMichal Meloun 	uint8_t buf[6];
49*ef2ee5d0SMichal Meloun 	int rv;
50*ef2ee5d0SMichal Meloun 
51*ef2ee5d0SMichal Meloun 	sc = device_get_softc(dev);
52*ef2ee5d0SMichal Meloun 
53*ef2ee5d0SMichal Meloun 	rv = as3722_read_buf(sc, AS3722_RTC_SECOND, buf, 6);
54*ef2ee5d0SMichal Meloun 	if (rv != 0) {
55*ef2ee5d0SMichal Meloun 		device_printf(sc->dev, "Failed to read RTC data\n");
56*ef2ee5d0SMichal Meloun 		return (rv);
57*ef2ee5d0SMichal Meloun 	}
58*ef2ee5d0SMichal Meloun 	ct.nsec = 0;
59*ef2ee5d0SMichal Meloun 	ct.sec = bcd2bin(buf[0] & 0x7F);
60*ef2ee5d0SMichal Meloun 	ct.min = bcd2bin(buf[1] & 0x7F);
61*ef2ee5d0SMichal Meloun 	ct.hour = bcd2bin(buf[2] & 0x3F);
62*ef2ee5d0SMichal Meloun 	ct.day = bcd2bin(buf[3] & 0x3F);
63*ef2ee5d0SMichal Meloun 	ct.mon = bcd2bin(buf[4] & 0x1F);
64*ef2ee5d0SMichal Meloun 	ct.year = bcd2bin(buf[5] & 0x7F) + AS3722_RTC_START_YEAR;
65*ef2ee5d0SMichal Meloun 	ct.dow = -1;
66*ef2ee5d0SMichal Meloun 
67*ef2ee5d0SMichal Meloun 	return clock_ct_to_ts(&ct, ts);
68*ef2ee5d0SMichal Meloun }
69*ef2ee5d0SMichal Meloun 
70*ef2ee5d0SMichal Meloun int
71*ef2ee5d0SMichal Meloun as3722_rtc_settime(device_t dev, struct timespec *ts)
72*ef2ee5d0SMichal Meloun {
73*ef2ee5d0SMichal Meloun 	struct as3722_softc *sc;
74*ef2ee5d0SMichal Meloun 	struct clocktime ct;
75*ef2ee5d0SMichal Meloun 	uint8_t buf[6];
76*ef2ee5d0SMichal Meloun 	int rv;
77*ef2ee5d0SMichal Meloun 
78*ef2ee5d0SMichal Meloun 	sc = device_get_softc(dev);
79*ef2ee5d0SMichal Meloun 	clock_ts_to_ct(ts, &ct);
80*ef2ee5d0SMichal Meloun 
81*ef2ee5d0SMichal Meloun 	if (ct.year < AS3722_RTC_START_YEAR)
82*ef2ee5d0SMichal Meloun 		return (EINVAL);
83*ef2ee5d0SMichal Meloun 
84*ef2ee5d0SMichal Meloun 	buf[0] = bin2bcd(ct.sec);
85*ef2ee5d0SMichal Meloun 	buf[1] = bin2bcd(ct.min);
86*ef2ee5d0SMichal Meloun 	buf[2] = bin2bcd(ct.hour);
87*ef2ee5d0SMichal Meloun 	buf[3] = bin2bcd(ct.day);
88*ef2ee5d0SMichal Meloun 	buf[4] = bin2bcd(ct.mon);
89*ef2ee5d0SMichal Meloun 	buf[5] = bin2bcd(ct.year - AS3722_RTC_START_YEAR);
90*ef2ee5d0SMichal Meloun 
91*ef2ee5d0SMichal Meloun 	rv = as3722_write_buf(sc, AS3722_RTC_SECOND, buf, 6);
92*ef2ee5d0SMichal Meloun 	if (rv != 0) {
93*ef2ee5d0SMichal Meloun 		device_printf(sc->dev, "Failed to write RTC data\n");
94*ef2ee5d0SMichal Meloun 		return (rv);
95*ef2ee5d0SMichal Meloun 	}
96*ef2ee5d0SMichal Meloun 	return (0);
97*ef2ee5d0SMichal Meloun }
98*ef2ee5d0SMichal Meloun 
99*ef2ee5d0SMichal Meloun int
100*ef2ee5d0SMichal Meloun as3722_rtc_attach(struct as3722_softc *sc, phandle_t node)
101*ef2ee5d0SMichal Meloun {
102*ef2ee5d0SMichal Meloun 	int rv;
103*ef2ee5d0SMichal Meloun 
104*ef2ee5d0SMichal Meloun 	/* Enable RTC, set 24 hours mode  and alarms */
105*ef2ee5d0SMichal Meloun 	rv = RM1(sc, AS3722_RTC_CONTROL,
106*ef2ee5d0SMichal Meloun 	    AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN | AS3722_RTC_AM_PM_MODE,
107*ef2ee5d0SMichal Meloun 	    AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN);
108*ef2ee5d0SMichal Meloun 	if (rv < 0) {
109*ef2ee5d0SMichal Meloun 		device_printf(sc->dev, "Failed to initialize RTC controller\n");
110*ef2ee5d0SMichal Meloun 		return (ENXIO);
111*ef2ee5d0SMichal Meloun 	}
112*ef2ee5d0SMichal Meloun 	clock_register(sc->dev, 1000000);
113*ef2ee5d0SMichal Meloun 
114*ef2ee5d0SMichal Meloun 	return (0);
115*ef2ee5d0SMichal Meloun }
116