1294434Szbb/*- 2294434Szbb * Copyright (c) 2015 Semihalf. 3294434Szbb * Copyright (c) 2015 Stormshield. 4294434Szbb * All rights reserved. 5294434Szbb * 6294434Szbb * Redistribution and use in source and binary forms, with or without 7294434Szbb * modification, are permitted provided that the following conditions 8294434Szbb * are met: 9294434Szbb * 1. Redistributions of source code must retain the above copyright 10294434Szbb * notice, this list of conditions and the following disclaimer. 11294434Szbb * 2. Redistributions in binary form must reproduce the above copyright 12294434Szbb * notice, this list of conditions and the following disclaimer in the 13294434Szbb * documentation and/or other materials provided with the distribution. 14294434Szbb * 15294434Szbb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16294434Szbb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17294434Szbb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18294434Szbb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19294434Szbb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20294434Szbb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21294434Szbb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22294434Szbb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23294434Szbb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24294434Szbb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25294434Szbb * SUCH DAMAGE. 26294434Szbb */ 27294434Szbb 28294434Szbb#include <sys/cdefs.h> 29294434Szbb__FBSDID("$FreeBSD$"); 30294434Szbb 31294434Szbb#include <sys/param.h> 32294434Szbb#include <sys/bus.h> 33294434Szbb#include <sys/lock.h> 34294434Szbb#include <sys/time.h> 35294434Szbb#include <sys/proc.h> 36294434Szbb#include <sys/conf.h> 37294434Szbb#include <sys/rman.h> 38294434Szbb#include <sys/clock.h> 39294434Szbb#include <sys/systm.h> 40294434Szbb#include <sys/mutex.h> 41294434Szbb#include <sys/types.h> 42294434Szbb#include <sys/kernel.h> 43294434Szbb#include <sys/module.h> 44294434Szbb#include <sys/resource.h> 45294434Szbb 46294434Szbb#include <machine/bus.h> 47294434Szbb#include <machine/resource.h> 48294434Szbb 49294434Szbb#include <dev/ofw/ofw_bus.h> 50294434Szbb#include <dev/ofw/ofw_bus_subr.h> 51294434Szbb 52294434Szbb#include "clock_if.h" 53294434Szbb 54294434Szbb#define RTC_RES_US 1000000 55294434Szbb#define HALF_OF_SEC_NS 500000000 56294434Szbb 57294434Szbb#define RTC_STATUS 0x0 58294434Szbb#define RTC_TIME 0xC 59294434Szbb 60294434Szbb#define MV_RTC_LOCK(sc) mtx_lock(&(sc)->mutex) 61294434Szbb#define MV_RTC_UNLOCK(sc) mtx_unlock(&(sc)->mutex) 62294434Szbb 63294434Szbbstatic struct resource_spec res_spec[] = { 64294434Szbb { SYS_RES_MEMORY, 0, RF_ACTIVE }, 65294434Szbb { -1, 0 } 66294434Szbb}; 67294434Szbb 68294434Szbbstruct mv_rtc_softc { 69294434Szbb device_t dev; 70294434Szbb struct resource *res; 71294434Szbb struct mtx mutex; 72294434Szbb}; 73294434Szbb 74294434Szbbstatic int mv_rtc_probe(device_t dev); 75294434Szbbstatic int mv_rtc_attach(device_t dev); 76294434Szbbstatic int mv_rtc_detach(device_t dev); 77294434Szbb 78294434Szbbstatic int mv_rtc_gettime(device_t dev, struct timespec *ts); 79294434Szbbstatic int mv_rtc_settime(device_t dev, struct timespec *ts); 80294434Szbb 81294434Szbbstatic uint32_t mv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off); 82294434Szbbstatic int mv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off, 83294434Szbb uint32_t val); 84294434Szbb 85294434Szbbstatic device_method_t mv_rtc_methods[] = { 86294434Szbb DEVMETHOD(device_probe, mv_rtc_probe), 87294434Szbb DEVMETHOD(device_attach, mv_rtc_attach), 88294434Szbb DEVMETHOD(device_detach, mv_rtc_detach), 89294434Szbb 90294434Szbb DEVMETHOD(clock_gettime, mv_rtc_gettime), 91294434Szbb DEVMETHOD(clock_settime, mv_rtc_settime), 92294434Szbb 93294434Szbb { 0, 0 }, 94294434Szbb}; 95294434Szbb 96294434Szbbstatic driver_t mv_rtc_driver = { 97294434Szbb "rtc", 98294434Szbb mv_rtc_methods, 99294434Szbb sizeof(struct mv_rtc_softc), 100294434Szbb}; 101294434Szbb 102294434Szbbstatic devclass_t mv_rtc_devclass; 103294434Szbb 104294434SzbbDRIVER_MODULE(mv_rtc, simplebus, mv_rtc_driver, mv_rtc_devclass, 0, 0); 105294434Szbb 106294434Szbbstatic int 107294434Szbbmv_rtc_probe(device_t dev) 108294434Szbb{ 109294434Szbb 110294434Szbb if (!ofw_bus_status_okay(dev)) 111294434Szbb return (ENXIO); 112294434Szbb 113294434Szbb if (!ofw_bus_is_compatible(dev, "marvell,armada-380-rtc")) 114294434Szbb return (ENXIO); 115294434Szbb 116294434Szbb device_set_desc(dev, "Marvell Integrated RTC"); 117294434Szbb 118294434Szbb return (BUS_PROBE_DEFAULT); 119294434Szbb} 120294434Szbb 121294434Szbbstatic int 122294434Szbbmv_rtc_attach(device_t dev) 123294434Szbb{ 124294434Szbb struct mv_rtc_softc *sc; 125294434Szbb int unit, ret; 126294434Szbb 127294434Szbb unit = device_get_unit(dev); 128294434Szbb 129294434Szbb sc = device_get_softc(dev); 130294434Szbb sc->dev = dev; 131294434Szbb 132294434Szbb clock_register(dev, RTC_RES_US); 133294434Szbb 134294434Szbb mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_DEF); 135294434Szbb 136294434Szbb ret = bus_alloc_resources(dev, res_spec, &sc->res); 137294434Szbb if (ret != 0) { 138294434Szbb device_printf(dev, "could not allocate resources\n"); 139294434Szbb mtx_destroy(&sc->mutex); 140294434Szbb return (ENXIO); 141294434Szbb } 142294434Szbb 143294434Szbb return (0); 144294434Szbb} 145294434Szbb 146294434Szbbstatic int 147294434Szbbmv_rtc_detach(device_t dev) 148294434Szbb{ 149294434Szbb struct mv_rtc_softc *sc; 150294434Szbb 151294434Szbb sc = device_get_softc(dev); 152294434Szbb 153294434Szbb mtx_destroy(&sc->mutex); 154294434Szbb 155294434Szbb bus_release_resources(dev, res_spec, &sc->res); 156294434Szbb 157294434Szbb return (0); 158294434Szbb} 159294434Szbb 160294434Szbbstatic int 161294434Szbbmv_rtc_gettime(device_t dev, struct timespec *ts) 162294434Szbb{ 163294434Szbb struct mv_rtc_softc *sc; 164294434Szbb uint32_t val, val_check; 165294434Szbb 166294434Szbb sc = device_get_softc(dev); 167294434Szbb 168294434Szbb MV_RTC_LOCK(sc); 169294434Szbb /* 170294434Szbb * According to HW Errata if more than one second between 171294434Szbb * two time reads is detected, then read once again 172294434Szbb */ 173294434Szbb val = mv_rtc_reg_read(sc, RTC_TIME); 174294434Szbb val_check = mv_rtc_reg_read(sc, RTC_TIME); 175294434Szbb if (val_check - val > 1) 176294434Szbb val_check = mv_rtc_reg_read(sc, RTC_TIME); 177294434Szbb 178294434Szbb MV_RTC_UNLOCK(sc); 179294434Szbb 180294434Szbb ts->tv_sec = val_check; 181294434Szbb /* RTC resolution is 1 sec */ 182294434Szbb ts->tv_nsec = 0; 183294434Szbb 184294434Szbb return (0); 185294434Szbb} 186294434Szbb 187294434Szbbstatic int 188294434Szbbmv_rtc_settime(device_t dev, struct timespec *ts) 189294434Szbb{ 190294434Szbb struct mv_rtc_softc *sc; 191294434Szbb 192294434Szbb sc = device_get_softc(dev); 193294434Szbb 194294434Szbb /* RTC resolution is 1 sec */ 195294434Szbb if (ts->tv_nsec >= HALF_OF_SEC_NS) 196294434Szbb ts->tv_sec++; 197294434Szbb ts->tv_nsec = 0; 198294434Szbb 199294434Szbb MV_RTC_LOCK(sc); 200294434Szbb 201294434Szbb /* 202294434Szbb * According to errata FE-3124064, Write to RTC TIME register 203294434Szbb * may fail. As a workaround, before writing to RTC TIME register, 204294434Szbb * issue a dummy write of 0x0 twice to RTC Status register. 205294434Szbb */ 206294434Szbb mv_rtc_reg_write(sc, RTC_STATUS, 0x0); 207294434Szbb mv_rtc_reg_write(sc, RTC_STATUS, 0x0); 208294434Szbb mv_rtc_reg_write(sc, RTC_TIME, ts->tv_sec); 209294434Szbb 210294434Szbb MV_RTC_UNLOCK(sc); 211294434Szbb 212294434Szbb return (0); 213294434Szbb} 214294434Szbb 215294434Szbbstatic uint32_t 216294434Szbbmv_rtc_reg_read(struct mv_rtc_softc *sc, bus_size_t off) 217294434Szbb{ 218294434Szbb 219294434Szbb return (bus_read_4(sc->res, off)); 220294434Szbb} 221294434Szbb 222294434Szbb/* 223294434Szbb * According to the datasheet, the OS should wait 5us after every 224294434Szbb * register write to the RTC hard macro so that the required update 225294434Szbb * can occur without holding off the system bus 226294434Szbb */ 227294434Szbbstatic int 228294434Szbbmv_rtc_reg_write(struct mv_rtc_softc *sc, bus_size_t off, uint32_t val) 229294434Szbb{ 230294434Szbb 231294434Szbb bus_write_4(sc->res, off, val); 232294434Szbb DELAY(5); 233294434Szbb 234294434Szbb return (0); 235294434Szbb} 236