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>
59 struct intr_config_hook
69static const struct ofw_compat_data ds1307_compat_data[] = {
70 {
"dallas,ds1307", (uintptr_t)
"Dallas DS1307 RTC"},
71 {
"maxim,ds1307", (uintptr_t)
"Maxim DS1307 RTC"},
72 {
"microchip,mcp7941x", (uintptr_t)
"Microchip MCP7941x RTC"},
99 device_printf(sc->
sc_dev,
"cannot read from RTC.\n");
115 device_printf(sc->
sc_dev,
"cannot write to RTC.\n");
123 int sqwe, error, newv, sqwe_bit;
134 sqwe = newv = (sc->
sc_ctrl & sqwe_bit) ? 1 : 0;
135 error = sysctl_handle_int(oidp, &newv, 0, req);
136 if (error != 0 || req->newptr == NULL)
153 int ds1307_sqw_freq[] = { 1, 4096, 8192, 32768 };
154 int error, freq, i, newf, tmp;
162 if (tmp >= nitems(ds1307_sqw_freq))
163 tmp = nitems(ds1307_sqw_freq) - 1;
164 freq = ds1307_sqw_freq[tmp];
165 error = sysctl_handle_int(oidp, &freq, 0, req);
166 if (error != 0 || req->newptr == NULL)
168 if (freq != ds1307_sqw_freq[tmp]) {
170 for (i = 0; i < nitems(ds1307_sqw_freq); i++)
171 if (freq >= ds1307_sqw_freq[i])
173 sc->
sc_ctrl &= ~DS1307_CTRL_RS_MASK;
186 int sqwe, error, newv;
194 error = sysctl_handle_int(oidp, &newv, 0, req);
195 if (error != 0 || req->newptr == NULL)
198 sc->
sc_ctrl &= ~DS1307_CTRL_OUT;
213 const struct ofw_compat_data *compat;
215 if (!ofw_bus_status_okay(
dev))
218 compat = ofw_bus_search_compatible(
dev, ds1307_compat_data);
219 if (compat->ocd_str != NULL) {
220 device_set_desc(
dev, (
const char *)compat->ocd_data);
221 return (BUS_PROBE_DEFAULT);
224 device_set_desc(
dev,
"Maxim DS1307 RTC");
225 return (BUS_PROBE_NOWILDCARD);
233 sc = device_get_softc(
dev);
239 if (ofw_bus_is_compatible(
dev,
"microchip,mcp7941x"))
247 if (config_intrhook_establish(&sc->
enum_hook) != 0)
257 clock_unregister(
dev);
266 struct sysctl_ctx_list *ctx;
267 struct sysctl_oid *tree_node;
268 struct sysctl_oid_list *tree;
272 dev = (device_t)xdev;
273 sc = device_get_softc(
dev);
274 ctx = device_get_sysctl_ctx(
dev);
275 tree_node = device_get_sysctl_tree(
dev);
276 tree = SYSCTL_CHILDREN(tree_node);
278 config_intrhook_disestablish(&sc->
enum_hook);
282 device_printf(sc->
sc_dev,
"cannot read from RTC.\n");
292 "WARNING: RTC clock stopped, check the battery.\n");
296 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"sqwe",
297 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
299 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"sqw_freq",
300 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
302 "DS1307 square-wave output frequency");
303 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO,
"sqw_out",
304 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
312 clock_register_flags(
dev, 1000000, CLOCKF_SETTIME_NO_ADJ);
313 clock_schedule(
dev, 1);
320 struct bcd_clocktime bct;
322 uint8_t
data[7], hourmask, st_mask;
324 sc = device_get_softc(
dev);
328 device_printf(
dev,
"cannot read from RTC.\n");
357 clock_dbgprint_bcd(sc->
sc_dev, CLOCK_DBG_READ, &bct);
358 return (clock_bcd_to_ts(&bct, ts, sc->
sc_use_ampm));
364 struct bcd_clocktime bct;
370 sc = device_get_softc(
dev);
376 ts->tv_sec -= utc_offset();
378 clock_dbgprint_bcd(sc->
sc_dev, CLOCK_DBG_WRITE, &bct);
398 year = bcd2bin(bct.year >> 8) * 100 + bcd2bin(bct.year & 0xff);
399 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
406 device_printf(
dev,
"cannot write to RTC.\n");
static devclass_t ds1307_devclass
static int ds1307_gettime(device_t dev, struct timespec *ts)
static int ds1307_detach(device_t dev)
static int ds1307_probe(device_t dev)
static int ds1307_read1(device_t dev, uint8_t reg, uint8_t *data)
MODULE_VERSION(ds1307, 1)
static driver_t ds1307_driver
static device_method_t ds1307_methods[]
IICBUS_FDT_PNP_INFO(ds1307_compat_data)
static void ds1307_start(void *)
static int ds1307_attach(device_t dev)
static int ds1307_write1(device_t dev, uint8_t reg, uint8_t data)
DRIVER_MODULE(ds1307, iicbus, ds1307_driver, ds1307_devclass, NULL, NULL)
static int ds1307_ctrl_read(struct ds1307_softc *sc)
MODULE_DEPEND(ds1307, iicbus, 1, 1, 1)
static int ds1307_sqwe_sysctl(SYSCTL_HANDLER_ARGS)
static int ds1307_settime(device_t dev, struct timespec *ts)
static int ds1307_sqw_freq_sysctl(SYSCTL_HANDLER_ARGS)
static int ds1307_ctrl_write(struct ds1307_softc *sc)
static int ds1307_sqw_out_sysctl(SYSCTL_HANDLER_ARGS)
#define DS1307_HOUR_MASK_24HR
#define DS1307_HOUR_IS_PM
#define DS1307_MONTH_MASK
#define DS1307_HOUR_USE_AMPM
#define MCP7941X_CTRL_SQWE
#define MCP7941X_MONTH_LPYR
#define DS1307_HOUR_MASK_12HR
#define DS1307_CTRL_RS_MASK
#define MCP7941X_WEEKDAY_VBATEN
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