diff options
Diffstat (limited to 'sys/powerpc/powermac/smu.c')
-rw-r--r-- | sys/powerpc/powermac/smu.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/sys/powerpc/powermac/smu.c b/sys/powerpc/powermac/smu.c index 6754b3ba7d1d..100187678810 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)); +} + |