* RTC can now be set to a new date.

Thanks to Ryo Shimizu for sending in a patch.
* Use proper G2 bus space functions to enforce locking protocol.
This commit is contained in:
marcus 2003-08-07 23:14:13 +00:00
parent a8f065cf19
commit c17ec7adc5
1 changed files with 58 additions and 7 deletions

View File

@ -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 <sys/cdefs.h>
__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 <sys/param.h>
#include <sys/systm.h>
@ -42,19 +42,22 @@ __KERNEL_RCSID(0, "$NetBSD: clock_machdep.c,v 1.2 2003/07/15 01:31:41 lukem Exp
#include <dev/clock_subr.h>
#include <sh3/clock.h>
#include <dreamcast/dev/g2/g2busvar.h>
#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 */
}