1 /*-
2 * Copyright (c) 2015 Luiz Otavio O Souza <loos@FreeBSD.org>
3 * Copyright (c) 2022 Mathew McBride <matt@traverse.com.au>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 /*
32 * Driver for Maxim DS1307 I2C real-time clock/calendar.
33 */
34
35 #include "opt_platform.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/bus.h>
40 #include <sys/clock.h>
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/sysctl.h>
44
45 #include <dev/iicbus/iicbus.h>
46 #include <dev/iicbus/iiconf.h>
47 #ifdef FDT
48 #include <dev/ofw/openfirm.h>
49 #include <dev/ofw/ofw_bus.h>
50 #include <dev/ofw/ofw_bus_subr.h>
51 #endif
52
53 #include <dev/iicbus/ds1307reg.h>
54
55 #include "clock_if.h"
56 #include "iicbus_if.h"
57
58 enum {
59 TYPE_DS1307,
60 TYPE_MAXIM1307,
61 TYPE_MICROCHIP_MCP7491X,
62 TYPE_EPSON_RX8035,
63 TYPE_COUNT
64 };
65
66 struct ds1307_softc {
67 device_t sc_dev;
68 struct intr_config_hook enum_hook;
69 uint32_t chiptype;
70 uint8_t sc_ctrl;
71 bool sc_use_ampm;
72 };
73
74 static void ds1307_start(void *);
75
76 #ifdef FDT
77 static const struct ofw_compat_data ds1307_compat_data[] = {
78 {"dallas,ds1307", TYPE_DS1307},
79 {"maxim,ds1307", TYPE_MAXIM1307},
80 {"microchip,mcp7941x", TYPE_MICROCHIP_MCP7491X},
81 {"epson,rx8035", TYPE_EPSON_RX8035},
82 { NULL, 0 }
83 };
84 #endif
85
86 static int
87 ds1307_read1(device_t dev, uint8_t reg, uint8_t *data)
88 {
89
90 return (iicdev_readfrom(dev, reg, data, 1, IIC_INTRWAIT));
91 }
92
93 static int
94 ds1307_write1(device_t dev, uint8_t reg, uint8_t data)
95 {
96
97 return (iicdev_writeto(dev, reg, &data, 1, IIC_INTRWAIT));
98 }
99
100 static int
101 ds1307_ctrl_read(struct ds1307_softc *sc)
102 {
103 int error;
104
105 sc->sc_ctrl = 0;
106 error = ds1307_read1(sc->sc_dev, DS1307_CONTROL, &sc->sc_ctrl);
107 if (error) {
108 device_printf(sc->sc_dev, "%s: cannot read from RTC: %d\n",
109 __func__, error);
110 return (error);
111 }
112
113 return (0);
114 }
115
116 static int
117 ds1307_ctrl_write(struct ds1307_softc *sc)
118 {
119 int error;
120 uint8_t ctrl;
121
122 ctrl = sc->sc_ctrl & DS1307_CTRL_MASK;
123 error = ds1307_write1(sc->sc_dev, DS1307_CONTROL, ctrl);
124 if (error != 0)
125 device_printf(sc->sc_dev, "%s: cannot write to RTC: %d\n",
126 __func__, error);
127
128 return (error);
129 }
130
131 static int
132 ds1307_sqwe_sysctl(SYSCTL_HANDLER_ARGS)
133 {
134 int sqwe, error, newv, sqwe_bit;
135 struct ds1307_softc *sc;
136
137 sc = (struct ds1307_softc *)arg1;
138 error = ds1307_ctrl_read(sc);
139 if (error != 0)
140 return (error);
141 if (sc->chiptype == TYPE_MICROCHIP_MCP7491X)
142 sqwe_bit = MCP7941X_CTRL_SQWE;
143 else
144 sqwe_bit = DS1307_CTRL_SQWE;
145 sqwe = newv = (sc->sc_ctrl & sqwe_bit) ? 1 : 0;
146 error = sysctl_handle_int(oidp, &newv, 0, req);
147 if (error != 0 || req->newptr == NULL)
148 return (error);
149 if (sqwe != newv) {
150 sc->sc_ctrl &= ~sqwe_bit;
151 if (newv)
152 sc->sc_ctrl |= sqwe_bit;
153 error = ds1307_ctrl_write(sc);
154 if (error != 0)
155 return (error);
156 }
157
158 return (error);
159 }
160
161 static int
162 ds1307_sqw_freq_sysctl(SYSCTL_HANDLER_ARGS)
163 {
164 int ds1307_sqw_freq[] = { 1, 4096, 8192, 32768 };
165 int error, freq, i, newf, tmp;
166 struct ds1307_softc *sc;
167
168 sc = (struct ds1307_softc *)arg1;
169 error = ds1307_ctrl_read(sc);
170 if (error != 0)
171 return (error);
172 tmp = (sc->sc_ctrl & DS1307_CTRL_RS_MASK);
173 if (tmp >= nitems(ds1307_sqw_freq))
174 tmp = nitems(ds1307_sqw_freq) - 1;
175 freq = ds1307_sqw_freq[tmp];
176 error = sysctl_handle_int(oidp, &freq, 0, req);
177 if (error != 0 || req->newptr == NULL)
178 return (error);
179 if (freq != ds1307_sqw_freq[tmp]) {
180 newf = 0;
181 for (i = 0; i < nitems(ds1307_sqw_freq); i++)
182 if (freq >= ds1307_sqw_freq[i])
183 newf = i;
184 sc->sc_ctrl &= ~DS1307_CTRL_RS_MASK;
185 sc->sc_ctrl |= newf;
186 error = ds1307_ctrl_write(sc);
187 if (error != 0)
188 return (error);
189 }
190
191 return (error);
192 }
193
194 static int
195 ds1307_sqw_out_sysctl(SYSCTL_HANDLER_ARGS)
196 {
197 int sqwe, error, newv;
198 struct ds1307_softc *sc;
199
200 sc = (struct ds1307_softc *)arg1;
201 error = ds1307_ctrl_read(sc);
202 if (error != 0)
203 return (error);
204 sqwe = newv = (sc->sc_ctrl & DS1307_CTRL_OUT) ? 1 : 0;
205 error = sysctl_handle_int(oidp, &newv, 0, req);
206 if (error != 0 || req->newptr == NULL)
207 return (error);
208 if (sqwe != newv) {
209 sc->sc_ctrl &= ~DS1307_CTRL_OUT;
210 if (newv)
211 sc->sc_ctrl |= DS1307_CTRL_OUT;
212 error = ds1307_ctrl_write(sc);
213 if (error != 0)
214 return (error);
215 }
216
217 return (error);
218 }
219
220 static int
221 ds1307_probe(device_t dev)
222 {
223 #ifdef FDT
224 const struct ofw_compat_data *compat;
225
226 if (!ofw_bus_status_okay(dev))
227 return (ENXIO);
228
229 compat = ofw_bus_search_compatible(dev, ds1307_compat_data);
230 if (compat->ocd_str == NULL)
231 return (ENXIO);
232
233 switch(compat->ocd_data) {
234 case TYPE_DS1307:
235 device_set_desc(dev, "Dallas DS1307");
236 break;
237 case TYPE_MAXIM1307:
238 device_set_desc(dev, "Maxim DS1307");
239 break;
240 case TYPE_MICROCHIP_MCP7491X:
241 device_set_desc(dev, "Microchip MCP7491X");
242 break;
243 case TYPE_EPSON_RX8035:
244 device_set_desc(dev, "Epson RX-8035");
245 break;
246 default:
247 device_set_desc(dev, "Unknown DS1307-like device");
248 break;
249 }
250 return (BUS_PROBE_DEFAULT);
251 #endif
252
253 device_set_desc(dev, "Maxim DS1307 RTC");
254 return (BUS_PROBE_NOWILDCARD);
255 }
256
257 static int
258 ds1307_attach(device_t dev)
259 {
260 #ifdef FDT
261 const struct ofw_compat_data *compat;
262 #endif
263 struct ds1307_softc *sc;
264
265 sc = device_get_softc(dev);
266 sc->sc_dev = dev;
267 sc->enum_hook.ich_func = ds1307_start;
268 sc->enum_hook.ich_arg = dev;
269 #ifdef FDT
270 compat = ofw_bus_search_compatible(dev, ds1307_compat_data);
271 sc->chiptype = compat->ocd_data;
272 /* Unify the chiptypes to DS1307 where possible. */
273 if (sc->chiptype == TYPE_MAXIM1307)
274 sc->chiptype = TYPE_DS1307;
275 #else
276 sc->chiptype = TYPE_DS1307;
277 #endif
278
279 /*
280 * We have to wait until interrupts are enabled. Usually I2C read
281 * and write only works when the interrupts are available.
282 */
283 if (config_intrhook_establish(&sc->enum_hook) != 0)
284 return (ENOMEM);
285
286 return (0);
287 }
288
289 static int
290 ds1307_detach(device_t dev)
291 {
292
293 clock_unregister(dev);
294 return (0);
295 }
296
297 static bool
298 is_epson_time_valid(struct ds1307_softc *sc)
299 {
300 device_t dev;
301 int error;
302 uint8_t ctrl2;
303
304 dev = sc->sc_dev;
305
306 /*
307 * The RX-8035 single register read is non-standard
308 * Refer to section 8.9.5 of the RX-8035 application manual:
309 * "I2C bus basic transfer format", under "Standard Read Method".
310 * Basically, register to read goes into the top 4 bits.
311 */
312 error = ds1307_read1(dev, (RX8035_CTRL_2 << 4), &ctrl2);
313 if (error) {
314 device_printf(dev, "%s cannot read Control 2 register: %d\n",
315 __func__, error);
316 return (false);
317 }
318
319 if (ctrl2 & RX8035_CTRL_2_XSTP) {
320 device_printf(dev, "Oscillation stop detected (ctrl2=%#02x)\n",
321 ctrl2);
322 return (false);
323 }
324
325 /*
326 * Power on reset (PON) generally implies oscillation stop,
327 * but catch it as well to be sure.
328 */
329 if (ctrl2 & RX8035_CTRL_2_PON) {
330 device_printf(dev, "Power-on reset detected (ctrl2=%#02x)\n",
331 ctrl2);
332 return (false);
333 }
334
335 return (true);
336 }
337
338 static int
339 mark_epson_time_valid(struct ds1307_softc *sc)
340 {
341 device_t dev;
342 int error;
343 uint8_t ctrl2;
344 uint8_t control_mask;
345
346 dev = sc->sc_dev;
347
348 error = ds1307_read1(dev, (RX8035_CTRL_2 << 4), &ctrl2);
349 if (error) {
350 device_printf(dev, "%s cannot read Control 2 register: %d\n",
351 __func__, error);
352 return (false);
353 }
354
355 control_mask = (RX8035_CTRL_2_PON | RX8035_CTRL_2_XSTP | RX8035_CTRL_2_VDET);
356 ctrl2 = ctrl2 & ~(control_mask);
357
358 error = ds1307_write1(dev, (RX8035_CTRL_2 << 4), ctrl2);
359 if (error) {
360 device_printf(dev, "%s cannot write to Control 2 register: %d\n",
361 __func__, error);
362 return (false);
363 }
364 return (true);
365 }
366
367 static bool is_dev_time_valid(struct ds1307_softc *sc)
368 {
369 device_t dev;
370 int error;
371 uint8_t osc_en;
372 uint8_t secs;
373
374 /* Epson RTCs have different control/status registers. */
375 if (sc->chiptype == TYPE_EPSON_RX8035)
376 return (is_epson_time_valid(sc));
377
378 dev = sc->sc_dev;
379 /* Check if the oscillator is disabled. */
380 error = ds1307_read1(dev, DS1307_SECS, &secs);
381 if (error) {
382 device_printf(dev, "%s: cannot read from RTC: %d\n",
383 __func__, error);
384 return (false);
385 }
386
387 switch (sc->chiptype) {
388 case TYPE_MICROCHIP_MCP7491X:
389 osc_en = 0x80;
390 break;
391 default:
392 osc_en = 0x00;
393 break;
394 }
395 if (((secs & DS1307_SECS_CH) ^ osc_en) != 0)
396 return (false);
397
398 return (true);
399 }
400
401 static void
402 ds1307_start(void *xdev)
403 {
404 device_t dev;
405 struct ds1307_softc *sc;
406 struct sysctl_ctx_list *ctx;
407 struct sysctl_oid *tree_node;
408 struct sysctl_oid_list *tree;
409
410 dev = (device_t)xdev;
411 sc = device_get_softc(dev);
412
413 config_intrhook_disestablish(&sc->enum_hook);
414
415 if (!is_dev_time_valid(sc))
416 device_printf(dev,
417 "WARNING: RTC clock stopped, check the battery.\n");
418
419 /*
420 * Configuration parameters:
421 * square wave output cannot be changed or inhibited on the RX-8035,
422 * so don't present the sysctls there.
423 */
424 if (sc->chiptype == TYPE_EPSON_RX8035)
425 goto skip_sysctl;
426
427 ctx = device_get_sysctl_ctx(dev);
428 tree_node = device_get_sysctl_tree(dev);
429 tree = SYSCTL_CHILDREN(tree_node);
430
431 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqwe",
432 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
433 ds1307_sqwe_sysctl, "IU", "DS1307 square-wave enable");
434 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_freq",
435 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
436 ds1307_sqw_freq_sysctl, "IU",
437 "DS1307 square-wave output frequency");
438 SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "sqw_out",
439 CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_MPSAFE, sc, 0,
440 ds1307_sqw_out_sysctl, "IU", "DS1307 square-wave output state");
441 skip_sysctl:
442
443 /*
444 * Register as a clock with 1 second resolution. Schedule the
445 * clock_settime() method to be called just after top-of-second;
446 * resetting the time resets top-of-second in the hardware.
447 */
448 clock_register_flags(dev, 1000000, CLOCKF_SETTIME_NO_ADJ);
449 clock_schedule(dev, 1);
450 }
451
452 static int
453 ds1307_gettime(device_t dev, struct timespec *ts)
454 {
455 struct bcd_clocktime bct;
456 struct ds1307_softc *sc;
457 int error;
458 uint8_t data[7], hourmask, ampm_mode;
459
460 sc = device_get_softc(dev);
461 error = iicdev_readfrom(sc->sc_dev, DS1307_SECS, data, sizeof(data),
462 IIC_INTRWAIT);
463 if (error != 0) {
464 device_printf(dev, "%s: cannot read from RTC: %d\n",
465 __func__, error);
466 return (error);
467 }
468
469 if (!is_dev_time_valid(sc)) {
470 device_printf(dev, "Device time not valid.\n");
471 return (EINVAL);
472 }
473
474 /*
475 * If the chip is in AM/PM mode remember that.
476 * The EPSON uses a 1 to signify 24 hour mode, while the DS uses a 0,
477 * in slighly different positions.
478 */
479 if (sc->chiptype == TYPE_EPSON_RX8035)
480 ampm_mode = !(data[DS1307_HOUR] & RX8035_HOUR_USE_24);
481 else
482 ampm_mode = data[DS1307_HOUR] & DS1307_HOUR_USE_AMPM;
483
484 if (ampm_mode) {
485 sc->sc_use_ampm = true;
486 hourmask = DS1307_HOUR_MASK_12HR;
487 } else
488 hourmask = DS1307_HOUR_MASK_24HR;
489
490 bct.nsec = 0;
491 bct.ispm = (data[DS1307_HOUR] & DS1307_HOUR_IS_PM) != 0;
492 bct.sec = data[DS1307_SECS] & DS1307_SECS_MASK;
493 bct.min = data[DS1307_MINS] & DS1307_MINS_MASK;
494 bct.hour = data[DS1307_HOUR] & hourmask;
495 bct.day = data[DS1307_DATE] & DS1307_DATE_MASK;
496 bct.mon = data[DS1307_MONTH] & DS1307_MONTH_MASK;
497 bct.year = data[DS1307_YEAR] & DS1307_YEAR_MASK;
498
499 clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_READ, &bct);
500 return (clock_bcd_to_ts(&bct, ts, sc->sc_use_ampm));
501 }
502
503 static int
504 ds1307_settime(device_t dev, struct timespec *ts)
505 {
506 struct bcd_clocktime bct;
507 struct ds1307_softc *sc;
508 int error, year;
509 uint8_t data[7];
510 uint8_t pmflags;
511
512 sc = device_get_softc(dev);
513
514 /*
515 * We request a timespec with no resolution-adjustment. That also
516 * disables utc adjustment, so apply that ourselves.
517 */
518 ts->tv_sec -= utc_offset();
519 clock_ts_to_bcd(ts, &bct, sc->sc_use_ampm);
520 clock_dbgprint_bcd(sc->sc_dev, CLOCK_DBG_WRITE, &bct);
521
522 /*
523 * If the chip is in AM/PM mode, adjust hour and set flags as needed.
524 * The AM/PM bit polarity and position is different on the EPSON.
525 */
526 if (sc->sc_use_ampm) {
527 pmflags = (sc->chiptype != TYPE_EPSON_RX8035) ?
528 DS1307_HOUR_USE_AMPM : 0;
529 if (bct.ispm)
530 pmflags |= DS1307_HOUR_IS_PM;
531
532 } else if (sc->chiptype == TYPE_EPSON_RX8035)
533 pmflags = RX8035_HOUR_USE_24;
534 else
535 pmflags = 0;
536
537 data[DS1307_SECS] = bct.sec;
538 data[DS1307_MINS] = bct.min;
539 data[DS1307_HOUR] = bct.hour | pmflags;
540 data[DS1307_DATE] = bct.day;
541 data[DS1307_WEEKDAY] = bct.dow;
542 data[DS1307_MONTH] = bct.mon;
543 data[DS1307_YEAR] = bct.year & 0xff;
544 if (sc->chiptype == TYPE_MICROCHIP_MCP7491X) {
545 data[DS1307_SECS] |= MCP7941X_SECS_ST;
546 data[DS1307_WEEKDAY] |= MCP7941X_WEEKDAY_VBATEN;
547 year = bcd2bin(bct.year >> 8) * 100 + bcd2bin(bct.year & 0xff);
548 if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
549 data[DS1307_MONTH] |= MCP7941X_MONTH_LPYR;
550 }
551
552 /* Write the time back to RTC. */
553 error = iicdev_writeto(sc->sc_dev, DS1307_SECS, data, sizeof(data),
554 IIC_INTRWAIT);
555 if (error != 0)
556 device_printf(dev, "%s: cannot write to RTC: %d\n",
557 __func__, error);
558
559 if (sc->chiptype == TYPE_EPSON_RX8035)
560 error = mark_epson_time_valid(sc);
561
562 return (error);
563 }
564
565 static device_method_t ds1307_methods[] = {
566 DEVMETHOD(device_probe, ds1307_probe),
567 DEVMETHOD(device_attach, ds1307_attach),
568 DEVMETHOD(device_detach, ds1307_detach),
569
570 DEVMETHOD(clock_gettime, ds1307_gettime),
571 DEVMETHOD(clock_settime, ds1307_settime),
572
573 DEVMETHOD_END
574 };
575
576 static driver_t ds1307_driver = {
577 "ds1307",
578 ds1307_methods,
579 sizeof(struct ds1307_softc),
580 };
581
582 DRIVER_MODULE(ds1307, iicbus, ds1307_driver, NULL, NULL);
583 MODULE_VERSION(ds1307, 1);
584 MODULE_DEPEND(ds1307, iicbus, 1, 1, 1);
585 IICBUS_FDT_PNP_INFO(ds1307_compat_data);
Cache object: c97b3134d8415aba1e8e6b06b0446f72
|