diff --git a/sys/arch/dreamcast/dreamcast/clock_machdep.c b/sys/arch/dreamcast/dreamcast/clock_machdep.c index 71f5008b9758..388ead58a377 100644 --- a/sys/arch/dreamcast/dreamcast/clock_machdep.c +++ b/sys/arch/dreamcast/dreamcast/clock_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: clock_machdep.c,v 1.2 2003/07/15 01:31:41 lukem Exp $ */ +/* $NetBSD: clock_machdep.c,v 1.3 2003/08/07 23:14:13 marcus Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: clock_machdep.c,v 1.2 2003/07/15 01:31:41 lukem Exp $"); +__KERNEL_RCSID(0, "$NetBSD: clock_machdep.c,v 1.3 2003/08/07 23:14:13 marcus Exp $"); #include #include @@ -42,19 +42,22 @@ __KERNEL_RCSID(0, "$NetBSD: clock_machdep.c,v 1.2 2003/07/15 01:31:41 lukem Exp #include #include +#include + #ifdef DEBUG #define STATIC #else #define STATIC static #endif -#define DREAMCAST_RTC 0xa0710000 +#define DREAMCAST_RTC 0x00710000 STATIC void dreamcast_rtc_init(void *); STATIC void dreamcast_rtc_get(void *, time_t, struct clock_ymdhms *); STATIC void dreamcast_rtc_set(void *, struct clock_ymdhms *); STATIC u_int32_t dreamcast_read_rtc(void); +STATIC void dreamcast_write_rtc(u_int32_t); STATIC struct rtc_ops dreamcast_rtc_ops = { .init = dreamcast_rtc_init, @@ -62,6 +65,9 @@ STATIC struct rtc_ops dreamcast_rtc_ops = { .set = dreamcast_rtc_set }; +static bus_space_tag_t rtc_tag; +static bus_space_handle_t rtc_handle; + void machine_clock_init() { @@ -72,7 +78,20 @@ machine_clock_init() void dreamcast_rtc_init(void *cookie) { - /* Nothing to do */ + struct device *dv; + + /* Find g2bus device */ + for (dv = TAILQ_FIRST(&alldevs); dv != NULL; + dv = TAILQ_NEXT(dv, dv_list)) + if (!strcmp(dv->dv_xname, "g2bus0")) + break; + + if (!dv) + panic("No g2bus!"); + + rtc_tag = &((struct g2bus_softc *)dv)->sc_memt; + + bus_space_map(rtc_tag, DREAMCAST_RTC, 12, 0, &rtc_handle); } void @@ -86,19 +105,21 @@ void dreamcast_rtc_set(void *cookie, struct clock_ymdhms *dt) { - /* Not suppoted */ + dreamcast_write_rtc(clock_ymdhms_to_secs(dt)); } u_int32_t dreamcast_read_rtc() { - __volatile__ u_int32_t *rtc = (__volatile__ u_int32_t *)DREAMCAST_RTC; u_int32_t new, old; int i; for (old = 0;;) { for (i = 0; i < 3; i++) { - new = ((rtc[0] & 0xffff) << 16) | (rtc[1] & 0xffff); + new = ((bus_space_read_4(rtc_tag, rtc_handle, 0) + & 0xffff) << 16) + | (bus_space_read_4(rtc_tag, rtc_handle, 4) + & 0xffff); if (new != old) break; } @@ -111,3 +132,33 @@ dreamcast_read_rtc() /* offset 20 years */ return (new - 631152000); } + +void +dreamcast_write_rtc(u_int32_t secs) +{ + u_int32_t new; + int i, retry; + + /* offset 20 years */ + secs += 631152000; + + for (retry = 0; retry < 5; retry++) { + + /* Don't change an order */ + bus_space_write_4(rtc_tag, rtc_handle, 8, 1); + bus_space_write_4(rtc_tag, rtc_handle, 4, secs & 0xffff); + bus_space_write_4(rtc_tag, rtc_handle, 0, secs >> 16); + + /* verify */ + for (i = 0; i < 3; i++) { + new = ((bus_space_read_4(rtc_tag, rtc_handle, 0) + & 0xffff) << 16) + | (bus_space_read_4(rtc_tag, rtc_handle, 4) + & 0xffff); + if (new == secs) + return; + } + } + /* set failure. but nothing to do */ +} +