summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/powermac/cuda.c
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2010-03-23 03:14:44 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2010-03-23 03:14:44 +0000
commitbbf5ab2a3952a5c4354849865f12845751a696fd (patch)
treeed01872a037bb02b93fe09e25506a6a9bb3aa2e3 /sys/powerpc/powermac/cuda.c
parenta4998a854d601c5a59c9f51479188de6d29c8919 (diff)
downloadFreeBSD-src-bbf5ab2a3952a5c4354849865f12845751a696fd.zip
FreeBSD-src-bbf5ab2a3952a5c4354849865f12845751a696fd.tar.gz
Get nexus(4) out of the RTC business. The interface used by nexus(4)
in Open Firmware was Apple-specific, and we have complete coverage of Apple system controllers, so move RTC responsibilities into the system controller drivers. This avoids interesting problems from manipulating these devices through Open Firmware behind the backs of their drivers. Obtained from: NetBSD MFC after: 2 weeks
Diffstat (limited to 'sys/powerpc/powermac/cuda.c')
-rw-r--r--sys/powerpc/powermac/cuda.c65
1 files changed, 64 insertions, 1 deletions
diff --git a/sys/powerpc/powermac/cuda.c b/sys/powerpc/powermac/cuda.c
index 203889c..230298e 100644
--- a/sys/powerpc/powermac/cuda.c
+++ b/sys/powerpc/powermac/cuda.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/clock.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/openfirm.h>
@@ -55,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <dev/adb/adb.h>
+#include "clock_if.h"
#include "cudavar.h"
#include "viareg.h"
@@ -72,6 +74,12 @@ static u_int cuda_poll(device_t dev);
static void cuda_send_inbound(struct cuda_softc *sc);
static void cuda_send_outbound(struct cuda_softc *sc);
+/*
+ * Clock interface
+ */
+static int cuda_gettime(device_t dev, struct timespec *ts);
+static int cuda_settime(device_t dev, struct timespec *ts);
+
static device_method_t cuda_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, cuda_probe),
@@ -90,6 +98,10 @@ static device_method_t cuda_methods[] = {
DEVMETHOD(adb_hb_controller_poll, cuda_poll),
DEVMETHOD(adb_hb_set_autopoll_mask, cuda_adb_autopoll),
+ /* Clock interface */
+ DEVMETHOD(clock_gettime, cuda_gettime),
+ DEVMETHOD(clock_settime, cuda_settime),
+
{ 0, 0 },
};
@@ -173,6 +185,7 @@ cuda_attach(device_t dev)
sc->sc_polling = 0;
sc->sc_state = CUDA_NOTREADY;
sc->sc_autopoll = 0;
+ sc->sc_rtc = -1;
STAILQ_INIT(&sc->sc_inq);
STAILQ_INIT(&sc->sc_outq);
@@ -236,6 +249,8 @@ cuda_attach(device_t dev)
}
}
+ clock_register(dev, 1000);
+
return (bus_generic_attach(dev));
}
@@ -444,8 +459,18 @@ cuda_send_inbound(struct cuda_softc *sc)
break;
case CUDA_PSEUDO:
mtx_lock(&sc->sc_mutex);
- if (pkt->data[0] == CMD_AUTOPOLL)
+ switch (pkt->data[1]) {
+ case CMD_AUTOPOLL:
sc->sc_autopoll = 1;
+ break;
+ case CMD_READ_RTC:
+ memcpy(&sc->sc_rtc, &pkt->data[2],
+ sizeof(sc->sc_rtc));
+ wakeup(&sc->sc_rtc);
+ break;
+ case CMD_WRITE_RTC:
+ break;
+ }
mtx_unlock(&sc->sc_mutex);
break;
case CUDA_ERROR:
@@ -715,3 +740,41 @@ cuda_adb_autopoll(device_t dev, uint16_t mask) {
return (0);
}
+#define DIFF19041970 2082844800
+
+static int
+cuda_gettime(device_t dev, struct timespec *ts)
+{
+ struct cuda_softc *sc = device_get_softc(dev);
+ uint8_t cmd[] = {CUDA_PSEUDO, CMD_READ_RTC};
+
+ mtx_lock(&sc->sc_mutex);
+ sc->sc_rtc = -1;
+ cuda_send(sc, 1, 2, cmd);
+ if (sc->sc_rtc == -1)
+ mtx_sleep(&sc->sc_rtc, &sc->sc_mutex, 0, "rtc", 100);
+
+ ts->tv_sec = sc->sc_rtc - DIFF19041970;
+ ts->tv_nsec = 0;
+ mtx_unlock(&sc->sc_mutex);
+
+ return (0);
+}
+
+static int
+cuda_settime(device_t dev, struct timespec *ts)
+{
+ struct cuda_softc *sc = device_get_softc(dev);
+ uint8_t cmd[] = {CUDA_PSEUDO, CMD_WRITE_RTC, 0, 0, 0, 0};
+ uint32_t sec;
+
+ sec = ts->tv_sec + DIFF19041970;
+ memcpy(&cmd[2], &sec, sizeof(sec));
+
+ mtx_lock(&sc->sc_mutex);
+ cuda_send(sc, 0, 6, cmd);
+ mtx_unlock(&sc->sc_mutex);
+
+ return (0);
+}
+
OpenPOWER on IntegriCloud