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