g2rtc.c revision 1.2
11.2She/* $NetBSD: g2rtc.c,v 1.2 2008/01/06 10:33:24 he Exp $ */ 21.1Suwe 31.1Suwe/*- 41.1Suwe * Copyright (c) 2002 The NetBSD Foundation, Inc. 51.1Suwe * All rights reserved. 61.1Suwe * 71.1Suwe * Redistribution and use in source and binary forms, with or without 81.1Suwe * modification, are permitted provided that the following conditions 91.1Suwe * are met: 101.1Suwe * 1. Redistributions of source code must retain the above copyright 111.1Suwe * notice, this list of conditions and the following disclaimer. 121.1Suwe * 2. Redistributions in binary form must reproduce the above copyright 131.1Suwe * notice, this list of conditions and the following disclaimer in the 141.1Suwe * documentation and/or other materials provided with the distribution. 151.1Suwe * 3. All advertising materials mentioning features or use of this software 161.1Suwe * must display the following acknowledgement: 171.1Suwe * This product includes software developed by the NetBSD 181.1Suwe * Foundation, Inc. and its contributors. 191.1Suwe * 4. Neither the name of The NetBSD Foundation nor the names of its 201.1Suwe * contributors may be used to endorse or promote products derived 211.1Suwe * from this software without specific prior written permission. 221.1Suwe * 231.1Suwe * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 241.1Suwe * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 251.1Suwe * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 261.1Suwe * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 271.1Suwe * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 281.1Suwe * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 291.1Suwe * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 301.1Suwe * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 311.1Suwe * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 321.1Suwe * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 331.1Suwe * POSSIBILITY OF SUCH DAMAGE. 341.1Suwe */ 351.1Suwe 361.1Suwe#include <sys/cdefs.h> 371.2She__KERNEL_RCSID(0, "$NetBSD: g2rtc.c,v 1.2 2008/01/06 10:33:24 he Exp $"); 381.1Suwe 391.1Suwe#include <sys/param.h> 401.1Suwe#include <sys/systm.h> 411.2She#include <sys/device.h> 421.1Suwe 431.1Suwe#include <dev/clock_subr.h> 441.1Suwe 451.1Suwe#include <machine/bus.h> 461.1Suwe#include <dreamcast/dev/g2/g2busvar.h> 471.1Suwe 481.1Suwe 491.1Suwe#define G2RTC_REG_BASE 0x00710000 501.1Suwe#define G2RTC_REG_SIZE 12 511.1Suwe 521.1Suwe/* Offset by 20 years, 5 of them are leap */ 531.1Suwe#define G2RTC_OFFSET (20 * SECYR + 5 * SECDAY) 541.1Suwe 551.1Suwestruct g2rtc_softc { 561.1Suwe struct device sc_dev; 571.1Suwe 581.1Suwe bus_space_tag_t sc_bt; 591.1Suwe bus_space_handle_t sc_bh; 601.1Suwe}; 611.1Suwe 621.1Suwe/* autoconf glue */ 631.1Suwestatic int g2rtc_match(struct device *, struct cfdata *, void *); 641.1Suwestatic void g2rtc_attach(struct device *, struct device *, void *); 651.1Suwe 661.1SuweCFATTACH_DECL(g2rtc, sizeof(struct g2rtc_softc), 671.1Suwe g2rtc_match, g2rtc_attach, NULL, NULL); 681.1Suwe 691.1Suwe 701.1Suwe/* todr(9) methods */ 711.1Suwestatic int g2rtc_todr_gettime(todr_chip_handle_t, volatile struct timeval *); 721.1Suwestatic int g2rtc_todr_settime(todr_chip_handle_t, volatile struct timeval *); 731.1Suwe 741.1Suwestatic struct todr_chip_handle g2rtc_todr_handle = { 751.1Suwe .cookie = NULL, /* set on attach */ 761.1Suwe .todr_gettime = g2rtc_todr_gettime, 771.1Suwe .todr_settime = g2rtc_todr_settime, 781.1Suwe}; 791.1Suwe 801.1Suwe 811.1Suwestatic inline uint32_t g2rtc_read(bus_space_tag_t, bus_space_handle_t); 821.1Suwe 831.1Suwe 841.1Suwestatic int 851.1Suweg2rtc_match(struct device *parent, struct cfdata *cf, void *aux) 861.1Suwe{ 871.1Suwe static int g2rtc_matched = 0; 881.1Suwe 891.1Suwe if (g2rtc_matched) 901.1Suwe return 0; 911.1Suwe 921.1Suwe g2rtc_matched = 1; 931.1Suwe return 1; 941.1Suwe} 951.1Suwe 961.1Suwe 971.1Suwestatic void 981.1Suweg2rtc_attach(struct device *parent, struct device *self, void *aux) 991.1Suwe{ 1001.1Suwe struct g2rtc_softc *sc = (void *)self; 1011.1Suwe struct g2bus_attach_args *ga = aux; 1021.1Suwe 1031.1Suwe sc->sc_bt = ga->ga_memt; 1041.1Suwe if (bus_space_map(sc->sc_bt, G2RTC_REG_BASE, G2RTC_REG_SIZE, 0, 1051.1Suwe &sc->sc_bh) != 0) 1061.1Suwe { 1071.1Suwe printf(": unable to map registers\n"); 1081.1Suwe return; 1091.1Suwe } 1101.1Suwe printf(": time-of-day clock\n"); 1111.1Suwe 1121.1Suwe g2rtc_todr_handle.cookie = sc; 1131.1Suwe todr_attach(&g2rtc_todr_handle); 1141.1Suwe} 1151.1Suwe 1161.1Suwe 1171.1Suwestatic inline uint32_t 1181.1Suweg2rtc_read(bus_space_tag_t bt, bus_space_handle_t bh) 1191.1Suwe{ 1201.1Suwe 1211.1Suwe return ((bus_space_read_4(bt, bh, 0) & 0xffff) << 16) 1221.1Suwe | (bus_space_read_4(bt, bh, 4) & 0xffff); 1231.1Suwe} 1241.1Suwe 1251.1Suwe 1261.1Suwe/* 1271.1Suwe * Get time-of-day and convert to `struct timeval'. 1281.1Suwe * Return 0 on success; an error number otherwise. 1291.1Suwe */ 1301.1Suwestatic int 1311.1Suweg2rtc_todr_gettime(todr_chip_handle_t handle, volatile struct timeval *tv) 1321.1Suwe{ 1331.1Suwe struct g2rtc_softc *sc = handle->cookie; 1341.1Suwe uint32_t new, old; 1351.1Suwe int i; 1361.1Suwe 1371.1Suwe for (old = 0;;) { 1381.1Suwe for (i = 0; i < 3; i++) { 1391.1Suwe new = g2rtc_read(sc->sc_bt, sc->sc_bh); 1401.1Suwe if (new != old) 1411.1Suwe break; 1421.1Suwe } 1431.1Suwe if (i < 3) 1441.1Suwe old = new; 1451.1Suwe else 1461.1Suwe break; 1471.1Suwe } 1481.1Suwe 1491.1Suwe tv->tv_sec = new - G2RTC_OFFSET; 1501.1Suwe tv->tv_usec = 0; 1511.1Suwe 1521.1Suwe return 0; 1531.1Suwe} 1541.1Suwe 1551.1Suwe 1561.1Suwe/* 1571.1Suwe * Set the time-of-day clock based on the value of the `struct timeval' arg. 1581.1Suwe * Return 0 on success; an error number otherwise. 1591.1Suwe */ 1601.1Suwestatic int 1611.1Suweg2rtc_todr_settime(todr_chip_handle_t handle, volatile struct timeval *tv) 1621.1Suwe{ 1631.1Suwe struct g2rtc_softc *sc = handle->cookie; 1641.1Suwe uint32_t secs; 1651.1Suwe int i, retry; 1661.1Suwe 1671.1Suwe secs = (uint32_t)tv->tv_sec + G2RTC_OFFSET; 1681.1Suwe 1691.1Suwe for (retry = 0; retry < 5; retry++) { 1701.1Suwe 1711.1Suwe /* Don't change the order */ 1721.1Suwe bus_space_write_4(sc->sc_bt, sc->sc_bh, 8, 1); 1731.1Suwe bus_space_write_4(sc->sc_bt, sc->sc_bh, 4, secs & 0xffff); 1741.1Suwe bus_space_write_4(sc->sc_bt, sc->sc_bh, 0, secs >> 16); 1751.1Suwe 1761.1Suwe /* verify */ 1771.1Suwe for (i = 0; i < 3; i++) 1781.1Suwe if (g2rtc_read(sc->sc_bt, sc->sc_bh) == secs) 1791.1Suwe return 0; /* ok */ 1801.1Suwe } 1811.1Suwe 1821.1Suwe return EIO; 1831.1Suwe 1841.1Suwe} 185