34#include "opt_platform.h"
40#include <sys/kernel.h>
41#include <sys/module.h>
42#include <sys/sysctl.h>
47#include <dev/ofw/openfirm.h>
48#include <dev/ofw/ofw_bus.h>
49#include <dev/ofw/ofw_bus_subr.h>
91 device_printf(sc->
sc_dev,
"cannot read from RTC.\n");
107 device_printf(sc->
sc_dev,
"cannot write to RTC.\n");
119 device_printf(sc->
sc_dev,
"cannot read from RTC.\n");
139 device_printf(sc->
sc_dev,
"cannot write to RTC.\n");
155 buf = (buf8[0] << 8) | (buf8[1] & 0xff);
161 *temp = ((int16_t)
buf >> 8) * 10;
185 error = sysctl_handle_int(oidp, &temp, 0, req);
193 int error, conv, newc;
201 error = sysctl_handle_int(oidp, &newc, 0, req);
202 if (error != 0 || req->newptr == NULL)
204 if (conv == 0 && newc != 0) {
222 int bbsqw, error, newb;
230 error = sysctl_handle_int(oidp, &newb, 0, req);
231 if (error != 0 || req->newptr == NULL)
234 sc->
sc_ctrl &= ~DS3231_CTRL_BBSQW;
248 int ds3231_sqw_freq[] = { 1, 1024, 4096, 8192 };
249 int error, freq, i, newf, tmp;
257 if (tmp >= nitems(ds3231_sqw_freq))
258 tmp = nitems(ds3231_sqw_freq) - 1;
259 freq = ds3231_sqw_freq[tmp];
260 error = sysctl_handle_int(oidp, &freq, 0, req);
261 if (error != 0 || req->newptr == NULL)
263 if (freq != ds3231_sqw_freq[tmp]) {
265 for (i = 0; i < nitems(ds3231_sqw_freq); i++)
266 if (freq >= ds3231_sqw_freq[i])
268 sc->
sc_ctrl &= ~DS3231_CTRL_RS_MASK;
285 if ((
len > 2 && strncasecmp(
"interrupt",
buf,
len) == 0) ||
286 (
len > 2 && strncasecmp(
"int",
buf,
len) == 0)) {
288 }
else if ((
len > 2 && strncasecmp(
"square-wave",
buf,
len) == 0) ||
289 (
len > 2 && strncasecmp(
"sqw",
buf,
len) == 0)) {
300 int error, mode, newm;
309 strlcpy(
buf,
"interrupt",
sizeof(
buf));
312 strlcpy(
buf,
"square-wave",
sizeof(
buf));
314 error = sysctl_handle_string(oidp,
buf,
sizeof(
buf), req);
315 if (error != 0 || req->newptr == NULL)
318 if (newm != -1 && mode != newm) {
319 sc->
sc_ctrl &= ~DS3231_CTRL_INTCN;
333 int error, en32khz, tmp;
341 error = sysctl_handle_int(oidp, &en32khz, 0, req);
342 if (error != 0 || req->newptr == NULL)
344 if (en32khz != tmp) {
362 if (!ofw_bus_status_okay(
dev))
364 if (ofw_bus_is_compatible(
dev,
"maxim,ds3231"))
365 rc = BUS_PROBE_DEFAULT;
368 rc = BUS_PROBE_NOWILDCARD;
370 device_set_desc(
dev,
"Maxim DS3231 RTC");
380 sc = device_get_softc(
dev);
392 if (config_intrhook_establish(&sc->
enum_hook) != 0)
402 clock_unregister(
dev);
411 struct sysctl_ctx_list *ctx;
412 struct sysctl_oid *tree_node;
413 struct sysctl_oid_list *tree;
415 dev = (device_t)xdev;
416 sc = device_get_softc(
dev);
417 ctx = device_get_sysctl_ctx(
dev);
418 tree_node = device_get_sysctl_tree(
dev);
419 tree = SYSCTL_CHILDREN(tree_node);
421 config_intrhook_disestablish(&sc->
enum_hook);
432 "WARNING: RTC clock stopped, check the battery.\n");
448 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"temperature",
449 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
452 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"temp_conv",
453 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
455 "DS3231 start a new temperature converstion");
456 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"bbsqw",
457 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
459 "DS3231 battery-backed square-wave output enable");
460 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"sqw_freq",
461 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
463 "DS3231 square-wave output frequency");
464 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"sqw_mode",
465 CTLFLAG_RW | CTLTYPE_STRING | CTLFLAG_MPSAFE, sc, 0,
467 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"32khz_enable",
468 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
476 clock_register_flags(
dev, 1000000, CLOCKF_SETTIME_NO_ADJ);
477 clock_schedule(
dev, 1);
484 struct bcd_clocktime bct;
486 uint8_t
data[7], hourmask;
488 sc = device_get_softc(
dev);
492 device_printf(
dev,
"cannot read from RTC.\n");
501 device_printf(
dev,
"cannot read from RTC.\n");
535 clock_dbgprint_bcd(sc->
sc_dev, CLOCK_DBG_READ, &bct);
536 return (clock_bcd_to_ts(&bct, ts, sc->
sc_use_ampm));
543 struct bcd_clocktime bct;
548 sc = device_get_softc(
dev);
554 ts->tv_sec -= utc_offset();
556 clock_dbgprint_bcd(sc->
sc_dev, CLOCK_DBG_WRITE, &bct);
580 device_printf(
dev,
"cannot write to RTC.\n");
590 device_printf(
dev,
"cannot read from RTC.\n");
595 device_printf(
dev,
"cannot write to RTC.\n");
static int ds3231_bbsqw_sysctl(SYSCTL_HANDLER_ARGS)
static int ds3231_write1(device_t dev, uint8_t reg, uint8_t data)
static int ds3231_attach(device_t dev)
static int ds3231_gettime(device_t dev, struct timespec *ts)
static int ds3231_probe(device_t dev)
DRIVER_MODULE(ds3231, iicbus, ds3231_driver, ds3231_devclass, NULL, NULL)
MODULE_DEPEND(ds3231, iicbus, 1, 1, 1)
static int ds3231_temp_sysctl(SYSCTL_HANDLER_ARGS)
static int ds3231_en32khz_sysctl(SYSCTL_HANDLER_ARGS)
static void ds3231_start(void *)
static int ds3231_ctrl_read(struct ds3231_softc *sc)
static int ds3231_ctrl_write(struct ds3231_softc *sc)
static int ds3231_detach(device_t dev)
MODULE_VERSION(ds3231, 1)
static int ds3231_status_read(struct ds3231_softc *sc)
static driver_t ds3231_driver
static devclass_t ds3231_devclass
static int ds3231_status_write(struct ds3231_softc *sc, int clear_a1, int clear_a2)
static int ds3231_conv_sysctl(SYSCTL_HANDLER_ARGS)
static int ds3231_sqw_freq_sysctl(SYSCTL_HANDLER_ARGS)
static device_method_t ds3231_methods[]
static int ds3231_sqw_mode_sysctl(SYSCTL_HANDLER_ARGS)
static int ds3231_read1(device_t dev, uint8_t reg, uint8_t *data)
static int ds3231_settime(device_t dev, struct timespec *ts)
static int ds3231_temp_read(struct ds3231_softc *sc, int *temp)
static int ds3231_str_sqw_mode(char *buf)
#define DS3231_STATUS_A2F
#define DS3231_STATUS_EN32KHZ
#define DS3231_CTRL_INTCN
#define DS3231_HOUR_MASK_12HR
#define DS3231_MONTH_MASK
#define DS3231_HOUR_MASK_24HR
#define DS3231_HOUR_USE_AMPM
#define DS3231_STATUS_A1F
#define DS3231_CTRL_RS_MASK
#define DS3231_CTRL_BBSQW
#define DS3231_STATUS_OSF
#define DS3231_HOUR_IS_PM
#define DS3231_STATUS_BUSY
#define DS3231_CTRL_RS_SHIFT
int iicdev_readfrom(device_t slavedev, uint8_t regaddr, void *buffer, uint16_t buflen, int waithow)
int iicdev_writeto(device_t slavedev, uint8_t regaddr, void *buffer, uint16_t buflen, int waithow)
struct intr_config_hook enum_hook