1373bbe25SRafal Jaworowski /*- 2373bbe25SRafal Jaworowski * Copyright (C) 2008 MARVELL INTERNATIONAL LTD. 3373bbe25SRafal Jaworowski * All rights reserved. 4373bbe25SRafal Jaworowski * 5373bbe25SRafal Jaworowski * Developed by Semihalf. 6373bbe25SRafal Jaworowski * 7373bbe25SRafal Jaworowski * Redistribution and use in source and binary forms, with or without 8373bbe25SRafal Jaworowski * modification, are permitted provided that the following conditions 9373bbe25SRafal Jaworowski * are met: 10373bbe25SRafal Jaworowski * 1. Redistributions of source code must retain the above copyright 11373bbe25SRafal Jaworowski * notice, this list of conditions and the following disclaimer. 12373bbe25SRafal Jaworowski * 2. Redistributions in binary form must reproduce the above copyright 13373bbe25SRafal Jaworowski * notice, this list of conditions and the following disclaimer in the 14373bbe25SRafal Jaworowski * documentation and/or other materials provided with the distribution. 15373bbe25SRafal Jaworowski * 3. Neither the name of MARVELL nor the names of contributors 16373bbe25SRafal Jaworowski * may be used to endorse or promote products derived from this software 17373bbe25SRafal Jaworowski * without specific prior written permission. 18373bbe25SRafal Jaworowski * 19373bbe25SRafal Jaworowski * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20373bbe25SRafal Jaworowski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21373bbe25SRafal Jaworowski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22373bbe25SRafal Jaworowski * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 23373bbe25SRafal Jaworowski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24373bbe25SRafal Jaworowski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25373bbe25SRafal Jaworowski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26373bbe25SRafal Jaworowski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27373bbe25SRafal Jaworowski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28373bbe25SRafal Jaworowski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29373bbe25SRafal Jaworowski * SUCH DAMAGE. 30373bbe25SRafal Jaworowski */ 31373bbe25SRafal Jaworowski 32373bbe25SRafal Jaworowski #include <sys/cdefs.h> 33373bbe25SRafal Jaworowski __FBSDID("$FreeBSD$"); 34373bbe25SRafal Jaworowski #include <sys/param.h> 35373bbe25SRafal Jaworowski #include <sys/bus.h> 36373bbe25SRafal Jaworowski #include <sys/lock.h> 37373bbe25SRafal Jaworowski #include <sys/time.h> 38373bbe25SRafal Jaworowski #include <sys/clock.h> 39373bbe25SRafal Jaworowski #include <sys/resource.h> 40373bbe25SRafal Jaworowski #include <sys/systm.h> 41373bbe25SRafal Jaworowski #include <sys/rman.h> 42373bbe25SRafal Jaworowski #include <sys/kernel.h> 43373bbe25SRafal Jaworowski #include <sys/module.h> 44373bbe25SRafal Jaworowski 45373bbe25SRafal Jaworowski #include <machine/bus.h> 46373bbe25SRafal Jaworowski #include <machine/resource.h> 47373bbe25SRafal Jaworowski 48373bbe25SRafal Jaworowski #include "clock_if.h" 49373bbe25SRafal Jaworowski 50373bbe25SRafal Jaworowski #define MV_RTC_TIME_REG 0x00 51373bbe25SRafal Jaworowski #define MV_RTC_DATE_REG 0x04 52373bbe25SRafal Jaworowski #define YEAR_BASE 2000 53373bbe25SRafal Jaworowski 54373bbe25SRafal Jaworowski struct mv_rtc_softc { 55373bbe25SRafal Jaworowski device_t dev; 56373bbe25SRafal Jaworowski struct resource *res[1]; 57373bbe25SRafal Jaworowski }; 58373bbe25SRafal Jaworowski 59373bbe25SRafal Jaworowski static struct resource_spec res_spec[] = { 60373bbe25SRafal Jaworowski { SYS_RES_MEMORY, 0, RF_ACTIVE }, 61373bbe25SRafal Jaworowski { -1, 0 } 62373bbe25SRafal Jaworowski }; 63373bbe25SRafal Jaworowski 64373bbe25SRafal Jaworowski static int mv_rtc_probe(device_t dev); 65373bbe25SRafal Jaworowski static int mv_rtc_attach(device_t dev); 66373bbe25SRafal Jaworowski 67373bbe25SRafal Jaworowski static int mv_rtc_gettime(device_t dev, struct timespec *ts); 68373bbe25SRafal Jaworowski static int mv_rtc_settime(device_t dev, struct timespec *ts); 69373bbe25SRafal Jaworowski 70373bbe25SRafal Jaworowski static uint32_t mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off); 71373bbe25SRafal Jaworowski static int mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off, 72373bbe25SRafal Jaworowski uint32_t val); 73373bbe25SRafal Jaworowski 74373bbe25SRafal Jaworowski static device_method_t mv_rtc_methods[] = { 75373bbe25SRafal Jaworowski DEVMETHOD(device_probe, mv_rtc_probe), 76373bbe25SRafal Jaworowski DEVMETHOD(device_attach, mv_rtc_attach), 77373bbe25SRafal Jaworowski 78373bbe25SRafal Jaworowski DEVMETHOD(clock_gettime, mv_rtc_gettime), 79373bbe25SRafal Jaworowski DEVMETHOD(clock_settime, mv_rtc_settime), 80373bbe25SRafal Jaworowski 81373bbe25SRafal Jaworowski { 0, 0 }, 82373bbe25SRafal Jaworowski }; 83373bbe25SRafal Jaworowski 84373bbe25SRafal Jaworowski static driver_t mv_rtc_driver = { 85373bbe25SRafal Jaworowski "rtc", 86373bbe25SRafal Jaworowski mv_rtc_methods, 87373bbe25SRafal Jaworowski sizeof(struct mv_rtc_softc), 88373bbe25SRafal Jaworowski }; 89373bbe25SRafal Jaworowski static devclass_t mv_rtc_devclass; 90373bbe25SRafal Jaworowski 91373bbe25SRafal Jaworowski DRIVER_MODULE(mv_rtc, mbus, mv_rtc_driver, mv_rtc_devclass, 0, 0); 92373bbe25SRafal Jaworowski 93373bbe25SRafal Jaworowski static int 94373bbe25SRafal Jaworowski mv_rtc_probe(device_t dev) 95373bbe25SRafal Jaworowski { 96373bbe25SRafal Jaworowski 97373bbe25SRafal Jaworowski device_set_desc(dev, "Marvell Integrated RTC"); 98373bbe25SRafal Jaworowski return (0); 99373bbe25SRafal Jaworowski } 100373bbe25SRafal Jaworowski 101373bbe25SRafal Jaworowski static int 102373bbe25SRafal Jaworowski mv_rtc_attach(device_t dev) 103373bbe25SRafal Jaworowski { 104373bbe25SRafal Jaworowski struct mv_rtc_softc *sc; 105373bbe25SRafal Jaworowski 106373bbe25SRafal Jaworowski sc = device_get_softc(dev); 107373bbe25SRafal Jaworowski sc->dev = dev; 108373bbe25SRafal Jaworowski 109373bbe25SRafal Jaworowski clock_register(dev, 1000000); 110373bbe25SRafal Jaworowski 111373bbe25SRafal Jaworowski if (bus_alloc_resources(dev, res_spec, sc->res)) { 112373bbe25SRafal Jaworowski device_printf(dev, "could not allocate resources\n"); 113373bbe25SRafal Jaworowski return (ENXIO); 114373bbe25SRafal Jaworowski } 115373bbe25SRafal Jaworowski 116373bbe25SRafal Jaworowski return (0); 117373bbe25SRafal Jaworowski } 118373bbe25SRafal Jaworowski 119373bbe25SRafal Jaworowski static int 120373bbe25SRafal Jaworowski mv_rtc_gettime(device_t dev, struct timespec *ts) 121373bbe25SRafal Jaworowski { 122373bbe25SRafal Jaworowski struct clocktime ct; 123373bbe25SRafal Jaworowski struct mv_rtc_softc *sc; 124373bbe25SRafal Jaworowski uint32_t val; 125373bbe25SRafal Jaworowski 126373bbe25SRafal Jaworowski sc = device_get_softc(dev); 127373bbe25SRafal Jaworowski 128373bbe25SRafal Jaworowski val = mv_rtc_reg_read(sc, MV_RTC_TIME_REG); 129373bbe25SRafal Jaworowski 130373bbe25SRafal Jaworowski ct.nsec = 0; 131373bbe25SRafal Jaworowski ct.sec = FROMBCD(val & 0x7f); 132373bbe25SRafal Jaworowski ct.min = FROMBCD((val & 0x7f00) >> 8); 133373bbe25SRafal Jaworowski ct.hour = FROMBCD((val & 0x3f0000) >> 16); 134373bbe25SRafal Jaworowski ct.dow = FROMBCD((val & 0x7000000) >> 24) - 1; 135373bbe25SRafal Jaworowski 136373bbe25SRafal Jaworowski val = mv_rtc_reg_read(sc, MV_RTC_DATE_REG); 137373bbe25SRafal Jaworowski 138373bbe25SRafal Jaworowski ct.day = FROMBCD(val & 0x7f); 139373bbe25SRafal Jaworowski ct.mon = FROMBCD((val & 0x1f00) >> 8); 140373bbe25SRafal Jaworowski ct.year = YEAR_BASE + FROMBCD((val & 0xff0000) >> 16); 141373bbe25SRafal Jaworowski 142373bbe25SRafal Jaworowski return (clock_ct_to_ts(&ct, ts)); 143373bbe25SRafal Jaworowski } 144373bbe25SRafal Jaworowski 145373bbe25SRafal Jaworowski static int 146373bbe25SRafal Jaworowski mv_rtc_settime(device_t dev, struct timespec *ts) 147373bbe25SRafal Jaworowski { 148373bbe25SRafal Jaworowski struct clocktime ct; 149373bbe25SRafal Jaworowski struct mv_rtc_softc *sc; 150373bbe25SRafal Jaworowski uint32_t val; 151373bbe25SRafal Jaworowski 152373bbe25SRafal Jaworowski sc = device_get_softc(dev); 153373bbe25SRafal Jaworowski 154373bbe25SRafal Jaworowski /* Resolution: 1 sec */ 155373bbe25SRafal Jaworowski if (ts->tv_nsec >= 500000000) 156373bbe25SRafal Jaworowski ts->tv_sec++; 157373bbe25SRafal Jaworowski ts->tv_nsec = 0; 158373bbe25SRafal Jaworowski clock_ts_to_ct(ts, &ct); 159373bbe25SRafal Jaworowski 160373bbe25SRafal Jaworowski val = TOBCD(ct.sec) | (TOBCD(ct.min) << 8) | 161373bbe25SRafal Jaworowski (TOBCD(ct.hour) << 16) | (TOBCD( ct.dow + 1) << 24); 162373bbe25SRafal Jaworowski mv_rtc_reg_write(sc, MV_RTC_TIME_REG, val); 163373bbe25SRafal Jaworowski 164373bbe25SRafal Jaworowski val = TOBCD(ct.day) | (TOBCD(ct.mon) << 8) | 165373bbe25SRafal Jaworowski (TOBCD(ct.year - YEAR_BASE) << 16); 166373bbe25SRafal Jaworowski mv_rtc_reg_write(sc, MV_RTC_DATE_REG, val); 167373bbe25SRafal Jaworowski 168373bbe25SRafal Jaworowski return (0); 169373bbe25SRafal Jaworowski } 170373bbe25SRafal Jaworowski 171373bbe25SRafal Jaworowski static uint32_t 172373bbe25SRafal Jaworowski mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off) 173373bbe25SRafal Jaworowski { 174373bbe25SRafal Jaworowski 175373bbe25SRafal Jaworowski return (bus_read_4(sc->res[0], off)); 176373bbe25SRafal Jaworowski } 177373bbe25SRafal Jaworowski 178373bbe25SRafal Jaworowski static int 179373bbe25SRafal Jaworowski mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off, uint32_t val) 180373bbe25SRafal Jaworowski { 181373bbe25SRafal Jaworowski 182373bbe25SRafal Jaworowski bus_write_4(sc->res[0], off, val); 183373bbe25SRafal Jaworowski return (0); 184373bbe25SRafal Jaworowski } 185