summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/powerpc/aim/nexus.c60
-rw-r--r--sys/powerpc/powermac/cuda.c65
-rw-r--r--sys/powerpc/powermac/cudavar.h1
-rw-r--r--sys/powerpc/powermac/pmu.c59
-rw-r--r--sys/powerpc/powermac/smu.c67
5 files changed, 190 insertions, 62 deletions
diff --git a/sys/powerpc/aim/nexus.c b/sys/powerpc/aim/nexus.c
index d92090b..54567b1 100644
--- a/sys/powerpc/aim/nexus.c
+++ b/sys/powerpc/aim/nexus.c
@@ -60,7 +60,6 @@
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
-#include <sys/clock.h>
#include <sys/cons.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
@@ -74,7 +73,6 @@
#include <sys/rman.h>
-#include "clock_if.h"
#include "ofw_bus_if.h"
#include "pic_if.h"
@@ -143,12 +141,6 @@ static const char *nexus_ofw_get_type(device_t, device_t);
static const char *nexus_ofw_get_compat(device_t, device_t);
/*
- * Clock interface.
- */
-static int nexus_gettime(device_t, struct timespec *);
-static int nexus_settime(device_t, struct timespec *);
-
-/*
* Local routines
*/
static device_t nexus_device_from_node(device_t, phandle_t);
@@ -181,10 +173,6 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(ofw_bus_get_type, nexus_ofw_get_type),
DEVMETHOD(ofw_bus_get_compat, nexus_ofw_get_compat),
- /* Clock interface */
- DEVMETHOD(clock_gettime, nexus_gettime),
- DEVMETHOD(clock_settime, nexus_settime),
-
{ 0, 0 }
};
@@ -240,7 +228,6 @@ nexus_attach(device_t dev)
}
- clock_register(dev, 1000);
return (bus_generic_attach(dev));
}
@@ -512,50 +499,3 @@ nexus_ofw_get_compat(device_t bus, device_t dev)
return (dinfo->ndi_compatible);
}
-#define DIFF19041970 2082844800
-
-static int
-nexus_gettime(device_t dev, struct timespec *ts)
-{
- char path[128];
- ihandle_t ih;
- phandle_t ph;
- u_int rtc;
-
- ph = OF_finddevice("rtc");
- if (ph == -1)
- return (ENOENT);
-
- OF_package_to_path(ph, path, sizeof(path));
- ih = OF_open(path);
- if (ih == -1)
- return (ENXIO);
-
- if (OF_call_method("read-rtc", ih, 0, 1, &rtc))
- return (EIO);
-
- ts->tv_sec = rtc - DIFF19041970;
- ts->tv_nsec = 0;
- return (0);
-}
-
-static int
-nexus_settime(device_t dev, struct timespec *ts)
-{
- char path[128];
- ihandle_t ih;
- phandle_t ph;
- u_int rtc;
-
- ph = OF_finddevice("rtc");
- if (ph == -1)
- return (ENOENT);
-
- OF_package_to_path(ph, path, sizeof(path));
- ih = OF_open(path);
- if (ih == -1)
- return (ENXIO);
-
- rtc = ts->tv_sec + DIFF19041970;
- return ((OF_call_method("write-rtc", ih, 1, 0, rtc) != 0) ? EIO : 0);
-}
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);
+}
+
diff --git a/sys/powerpc/powermac/cudavar.h b/sys/powerpc/powermac/cudavar.h
index 02791cb..2254464 100644
--- a/sys/powerpc/powermac/cudavar.h
+++ b/sys/powerpc/powermac/cudavar.h
@@ -90,6 +90,7 @@ struct cuda_softc {
int sc_polling;
int sc_iic_done;
volatile int sc_autopoll;
+ uint32_t sc_rtc;
int sc_i2c_read_len;
diff --git a/sys/powerpc/powermac/pmu.c b/sys/powerpc/powermac/pmu.c
index 9ddba9e..a980622 100644
--- a/sys/powerpc/powermac/pmu.c
+++ b/sys/powerpc/powermac/pmu.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/clock.h>
#include <sys/sysctl.h>
#include <dev/ofw/ofw_bus.h>
@@ -55,16 +56,27 @@ __FBSDID("$FreeBSD$");
#include <dev/adb/adb.h>
+#include "clock_if.h"
#include "pmuvar.h"
#include "viareg.h"
/*
- * MacIO interface
+ * Bus interface
*/
static int pmu_probe(device_t);
static int pmu_attach(device_t);
static int pmu_detach(device_t);
+/*
+ * Clock interface
+ */
+static int pmu_gettime(device_t dev, struct timespec *ts);
+static int pmu_settime(device_t dev, struct timespec *ts);
+
+/*
+ * ADB Interface
+ */
+
static u_int pmu_adb_send(device_t dev, u_char command_byte, int len,
u_char *data, u_char poll);
static u_int pmu_adb_autopoll(device_t dev, uint16_t mask);
@@ -110,6 +122,10 @@ static device_method_t pmu_methods[] = {
DEVMETHOD(adb_hb_controller_poll, pmu_poll),
DEVMETHOD(adb_hb_set_autopoll_mask, pmu_adb_autopoll),
+ /* Clock interface */
+ DEVMETHOD(clock_gettime, pmu_gettime),
+ DEVMETHOD(clock_settime, pmu_settime),
+
{ 0, 0 },
};
@@ -453,6 +469,12 @@ pmu_attach(device_t dev)
sc->sc_leddev = led_create(pmu_set_sleepled, sc, "sleepled");
+ /*
+ * Register RTC
+ */
+
+ clock_register(dev, 1000);
+
return (bus_generic_attach(dev));
}
@@ -926,3 +948,38 @@ pmu_battquery_sysctl(SYSCTL_HANDLER_ARGS)
return (error);
}
+#define DIFF19041970 2082844800
+
+static int
+pmu_gettime(device_t dev, struct timespec *ts)
+{
+ struct pmu_softc *sc = device_get_softc(dev);
+ uint8_t resp[16];
+ uint32_t sec;
+
+ mtx_lock(&sc->sc_mutex);
+ pmu_send(sc, PMU_READ_RTC, 0, NULL, 16, resp);
+ mtx_unlock(&sc->sc_mutex);
+
+ memcpy(&sec, &resp[1], 4);
+ ts->tv_sec = sec - DIFF19041970;
+ ts->tv_nsec = 0;
+
+ return (0);
+}
+
+static int
+pmu_settime(device_t dev, struct timespec *ts)
+{
+ struct pmu_softc *sc = device_get_softc(dev);
+ uint32_t sec;
+
+ sec = ts->tv_sec + DIFF19041970;
+
+ mtx_lock(&sc->sc_mutex);
+ pmu_send(sc, PMU_SET_RTC, sizeof(sec), (uint8_t *)&sec, 0, NULL);
+ mtx_unlock(&sc->sc_mutex);
+
+ return (0);
+}
+
diff --git a/sys/powerpc/powermac/smu.c b/sys/powerpc/powermac/smu.c
index 6754b3b..1001876 100644
--- a/sys/powerpc/powermac/smu.c
+++ b/sys/powerpc/powermac/smu.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/conf.h>
#include <sys/cpu.h>
+#include <sys/clock.h>
#include <sys/ctype.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
@@ -51,6 +52,8 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <powerpc/powermac/macgpiovar.h>
+#include "clock_if.h"
+
struct smu_cmd {
volatile uint8_t cmd;
uint8_t len;
@@ -140,6 +143,10 @@ static int smu_attach(device_t);
static void smu_cpufreq_pre_change(device_t, const struct cf_level *level);
static void smu_cpufreq_post_change(device_t, const struct cf_level *level);
+/* clock interface */
+static int smu_gettime(device_t dev, struct timespec *ts);
+static int smu_settime(device_t dev, struct timespec *ts);
+
/* utility functions */
static int smu_run_cmd(device_t dev, struct smu_cmd *cmd, int wait);
static int smu_get_datablock(device_t dev, int8_t id, uint8_t *buf,
@@ -160,6 +167,10 @@ static device_method_t smu_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, smu_probe),
DEVMETHOD(device_attach, smu_attach),
+
+ /* Clock interface */
+ DEVMETHOD(clock_gettime, smu_gettime),
+ DEVMETHOD(clock_settime, smu_settime),
{ 0, 0 },
};
@@ -192,6 +203,9 @@ MALLOC_DEFINE(M_SMU, "smu", "SMU Sensor Information");
#define SMU_PWR_GET_POWERUP 0x00
#define SMU_PWR_SET_POWERUP 0x01
#define SMU_PWR_CLR_POWERUP 0x02
+#define SMU_RTC 0x8e
+#define SMU_RTC_GET 0x81
+#define SMU_RTC_SET 0x80
/* Power event types */
#define SMU_WAKEUP_KEYPRESS 0x01
@@ -349,6 +363,11 @@ smu_attach(device_t dev)
powerpc_config_intr(rman_get_start(sc->sc_doorbellirq),
INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);
+ /*
+ * Connect RTC interface.
+ */
+ clock_register(dev, 1000);
+
return (0);
}
@@ -1043,3 +1062,51 @@ smu_server_mode(SYSCTL_HANDLER_ARGS)
return (smu_run_cmd(smu, &cmd, 1));
}
+static int
+smu_gettime(device_t dev, struct timespec *ts)
+{
+ struct smu_cmd cmd;
+ struct clocktime ct;
+
+ cmd.cmd = SMU_RTC;
+ cmd.len = 1;
+ cmd.data[0] = SMU_RTC_GET;
+
+ if (smu_run_cmd(dev, &cmd, 1) != 0)
+ return (ENXIO);
+
+ ct.nsec = 0;
+ ct.sec = bcd2bin(cmd.data[0]);
+ ct.min = bcd2bin(cmd.data[1]);
+ ct.hour = bcd2bin(cmd.data[2]);
+ ct.dow = bcd2bin(cmd.data[3]);
+ ct.day = bcd2bin(cmd.data[4]);
+ ct.mon = bcd2bin(cmd.data[5]);
+ ct.year = bcd2bin(cmd.data[6]) + 2000;
+
+ return (clock_ct_to_ts(&ct, ts));
+}
+
+static int
+smu_settime(device_t dev, struct timespec *ts)
+{
+ struct smu_cmd cmd;
+ struct clocktime ct;
+
+ cmd.cmd = SMU_RTC;
+ cmd.len = 8;
+ cmd.data[0] = SMU_RTC_SET;
+
+ clock_ts_to_ct(ts, &ct);
+
+ cmd.data[1] = bin2bcd(ct.sec);
+ cmd.data[2] = bin2bcd(ct.min);
+ cmd.data[3] = bin2bcd(ct.hour);
+ cmd.data[4] = bin2bcd(ct.dow);
+ cmd.data[5] = bin2bcd(ct.day);
+ cmd.data[6] = bin2bcd(ct.mon);
+ cmd.data[7] = bin2bcd(ct.year - 2000);
+
+ return (smu_run_cmd(dev, &cmd, 1));
+}
+
OpenPOWER on IntegriCloud