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
This commit is contained in:
parent
0e13104de6
commit
3df9e0375a
@ -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"
|
||||
|
||||
@ -142,12 +140,6 @@ static const char *nexus_ofw_get_name(device_t, device_t);
|
||||
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
|
||||
*/
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user