g2rtc.c revision 1.1
11.1Suwe/* $NetBSD: g2rtc.c,v 1.1 2006/09/05 11:09:36 uwe 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.1Suwe__KERNEL_RCSID(0, "$NetBSD: g2rtc.c,v 1.1 2006/09/05 11:09:36 uwe Exp $"); 381.1Suwe 391.1Suwe#include <sys/param.h> 401.1Suwe#include <sys/systm.h> 411.1Suwe 421.1Suwe#include <dev/clock_subr.h> 431.1Suwe 441.1Suwe#include <machine/bus.h> 451.1Suwe#include <dreamcast/dev/g2/g2busvar.h> 461.1Suwe 471.1Suwe 481.1Suwe#define G2RTC_REG_BASE 0x00710000 491.1Suwe#define G2RTC_REG_SIZE 12 501.1Suwe 511.1Suwe/* Offset by 20 years, 5 of them are leap */ 521.1Suwe#define G2RTC_OFFSET (20 * SECYR + 5 * SECDAY) 531.1Suwe 541.1Suwestruct g2rtc_softc { 551.1Suwe struct device sc_dev; 561.1Suwe 571.1Suwe bus_space_tag_t sc_bt; 581.1Suwe bus_space_handle_t sc_bh; 591.1Suwe}; 601.1Suwe 611.1Suwe/* autoconf glue */ 621.1Suwestatic int g2rtc_match(struct device *, struct cfdata *, void *); 631.1Suwestatic void g2rtc_attach(struct device *, struct device *, void *); 641.1Suwe 651.1SuweCFATTACH_DECL(g2rtc, sizeof(struct g2rtc_softc), 661.1Suwe g2rtc_match, g2rtc_attach, NULL, NULL); 671.1Suwe 681.1Suwe 691.1Suwe/* todr(9) methods */ 701.1Suwestatic int g2rtc_todr_gettime(todr_chip_handle_t, volatile struct timeval *); 711.1Suwestatic int g2rtc_todr_settime(todr_chip_handle_t, volatile struct timeval *); 721.1Suwe 731.1Suwestatic struct todr_chip_handle g2rtc_todr_handle = { 741.1Suwe .cookie = NULL, /* set on attach */ 751.1Suwe .todr_gettime = g2rtc_todr_gettime, 761.1Suwe .todr_settime = g2rtc_todr_settime, 771.1Suwe}; 781.1Suwe 791.1Suwe 801.1Suwestatic inline uint32_t g2rtc_read(bus_space_tag_t, bus_space_handle_t); 811.1Suwe 821.1Suwe 831.1Suwestatic int 841.1Suweg2rtc_match(struct device *parent, struct cfdata *cf, void *aux) 851.1Suwe{ 861.1Suwe static int g2rtc_matched = 0; 871.1Suwe 881.1Suwe if (g2rtc_matched) 891.1Suwe return 0; 901.1Suwe 911.1Suwe g2rtc_matched = 1; 921.1Suwe return 1; 931.1Suwe} 941.1Suwe 951.1Suwe 961.1Suwestatic void 971.1Suweg2rtc_attach(struct device *parent, struct device *self, void *aux) 981.1Suwe{ 991.1Suwe struct g2rtc_softc *sc = (void *)self; 1001.1Suwe struct g2bus_attach_args *ga = aux; 1011.1Suwe 1021.1Suwe sc->sc_bt = ga->ga_memt; 1031.1Suwe if (bus_space_map(sc->sc_bt, G2RTC_REG_BASE, G2RTC_REG_SIZE, 0, 1041.1Suwe &sc->sc_bh) != 0) 1051.1Suwe { 1061.1Suwe printf(": unable to map registers\n"); 1071.1Suwe return; 1081.1Suwe } 1091.1Suwe printf(": time-of-day clock\n"); 1101.1Suwe 1111.1Suwe g2rtc_todr_handle.cookie = sc; 1121.1Suwe todr_attach(&g2rtc_todr_handle); 1131.1Suwe} 1141.1Suwe 1151.1Suwe 1161.1Suwestatic inline uint32_t 1171.1Suweg2rtc_read(bus_space_tag_t bt, bus_space_handle_t bh) 1181.1Suwe{ 1191.1Suwe 1201.1Suwe return ((bus_space_read_4(bt, bh, 0) & 0xffff) << 16) 1211.1Suwe | (bus_space_read_4(bt, bh, 4) & 0xffff); 1221.1Suwe} 1231.1Suwe 1241.1Suwe 1251.1Suwe/* 1261.1Suwe * Get time-of-day and convert to `struct timeval'. 1271.1Suwe * Return 0 on success; an error number otherwise. 1281.1Suwe */ 1291.1Suwestatic int 1301.1Suweg2rtc_todr_gettime(todr_chip_handle_t handle, volatile struct timeval *tv) 1311.1Suwe{ 1321.1Suwe struct g2rtc_softc *sc = handle->cookie; 1331.1Suwe uint32_t new, old; 1341.1Suwe int i; 1351.1Suwe 1361.1Suwe for (old = 0;;) { 1371.1Suwe for (i = 0; i < 3; i++) { 1381.1Suwe new = g2rtc_read(sc->sc_bt, sc->sc_bh); 1391.1Suwe if (new != old) 1401.1Suwe break; 1411.1Suwe } 1421.1Suwe if (i < 3) 1431.1Suwe old = new; 1441.1Suwe else 1451.1Suwe break; 1461.1Suwe } 1471.1Suwe 1481.1Suwe tv->tv_sec = new - G2RTC_OFFSET; 1491.1Suwe tv->tv_usec = 0; 1501.1Suwe 1511.1Suwe return 0; 1521.1Suwe} 1531.1Suwe 1541.1Suwe 1551.1Suwe/* 1561.1Suwe * Set the time-of-day clock based on the value of the `struct timeval' arg. 1571.1Suwe * Return 0 on success; an error number otherwise. 1581.1Suwe */ 1591.1Suwestatic int 1601.1Suweg2rtc_todr_settime(todr_chip_handle_t handle, volatile struct timeval *tv) 1611.1Suwe{ 1621.1Suwe struct g2rtc_softc *sc = handle->cookie; 1631.1Suwe uint32_t secs; 1641.1Suwe int i, retry; 1651.1Suwe 1661.1Suwe secs = (uint32_t)tv->tv_sec + G2RTC_OFFSET; 1671.1Suwe 1681.1Suwe for (retry = 0; retry < 5; retry++) { 1691.1Suwe 1701.1Suwe /* Don't change the order */ 1711.1Suwe bus_space_write_4(sc->sc_bt, sc->sc_bh, 8, 1); 1721.1Suwe bus_space_write_4(sc->sc_bt, sc->sc_bh, 4, secs & 0xffff); 1731.1Suwe bus_space_write_4(sc->sc_bt, sc->sc_bh, 0, secs >> 16); 1741.1Suwe 1751.1Suwe /* verify */ 1761.1Suwe for (i = 0; i < 3; i++) 1771.1Suwe if (g2rtc_read(sc->sc_bt, sc->sc_bh) == secs) 1781.1Suwe return 0; /* ok */ 1791.1Suwe } 1801.1Suwe 1811.1Suwe return EIO; 1821.1Suwe 1831.1Suwe} 184