/*-1* Copyright (c) 2016 Michal Meloun <[email protected]>2* All rights reserved.3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted provided that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND14* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE15* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE17* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT21* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY22* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF23* SUCH DAMAGE.24*/2526#include <sys/param.h>27#include <sys/systm.h>28#include <sys/bus.h>29#include <sys/clock.h>30#include <sys/kernel.h>3132#include <dev/ofw/ofw_bus.h>3334#include "clock_if.h"35#include "as3722.h"3637#define AS3722_RTC_START_YEAR 20003839int40as3722_rtc_gettime(device_t dev, struct timespec *ts)41{42struct as3722_softc *sc;43struct clocktime ct;44uint8_t buf[6];45int rv;4647sc = device_get_softc(dev);4849rv = as3722_read_buf(sc, AS3722_RTC_SECOND, buf, 6);50if (rv != 0) {51device_printf(sc->dev, "Failed to read RTC data\n");52return (rv);53}54ct.nsec = 0;55ct.sec = bcd2bin(buf[0] & 0x7F);56ct.min = bcd2bin(buf[1] & 0x7F);57ct.hour = bcd2bin(buf[2] & 0x3F);58ct.day = bcd2bin(buf[3] & 0x3F);59ct.mon = bcd2bin(buf[4] & 0x1F);60ct.year = bcd2bin(buf[5] & 0x7F) + AS3722_RTC_START_YEAR;61ct.dow = -1;6263return clock_ct_to_ts(&ct, ts);64}6566int67as3722_rtc_settime(device_t dev, struct timespec *ts)68{69struct as3722_softc *sc;70struct clocktime ct;71uint8_t buf[6];72int rv;7374sc = device_get_softc(dev);75clock_ts_to_ct(ts, &ct);7677if (ct.year < AS3722_RTC_START_YEAR)78return (EINVAL);7980buf[0] = bin2bcd(ct.sec);81buf[1] = bin2bcd(ct.min);82buf[2] = bin2bcd(ct.hour);83buf[3] = bin2bcd(ct.day);84buf[4] = bin2bcd(ct.mon);85buf[5] = bin2bcd(ct.year - AS3722_RTC_START_YEAR);8687rv = as3722_write_buf(sc, AS3722_RTC_SECOND, buf, 6);88if (rv != 0) {89device_printf(sc->dev, "Failed to write RTC data\n");90return (rv);91}92return (0);93}9495int96as3722_rtc_attach(struct as3722_softc *sc, phandle_t node)97{98int rv;99100/* Enable RTC, set 24 hours mode and alarms */101rv = RM1(sc, AS3722_RTC_CONTROL,102AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN | AS3722_RTC_AM_PM_MODE,103AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN);104if (rv < 0) {105device_printf(sc->dev, "Failed to initialize RTC controller\n");106return (ENXIO);107}108clock_register(sc->dev, 1000000);109110return (0);111}112113114