xref: /freebsd/sys/dev/iicbus/rtc/rv3032.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2023 Beckhoff Automation GmbH & Co. KG
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 #include "opt_platform.h"
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bus.h>
34 #include <sys/clock.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/module.h>
38 #include <sys/sysctl.h>
39 
40 #include <dev/ofw/ofw_bus.h>
41 #include <dev/ofw/ofw_bus_subr.h>
42 
43 #include <dev/iicbus/iiconf.h>
44 #include <dev/iicbus/iicbus.h>
45 
46 #include "clock_if.h"
47 #include "iicbus_if.h"
48 
49 /* Date registers */
50 #define	RV3032_SECS_100TH	0x00
51 #define	RV3032_SECS		0x01
52 #define	RV3032_MINS		0x02
53 #define	RV3032_HOURS		0x03
54 #define	RV3032_WEEKDAY		0x04
55 #define	RV3032_DATE		0x05
56 #define	RV3032_MONTH		0x06
57 #define	RV3032_YEAR		0x07
58 
59 /* Alarm registers */
60 #define	RV3032_ALARM_MINUTES	0x08
61 #define	RV3032_ALARM_HOURS	0x09
62 #define	RV3032_ALARM_DATE	0x0A
63 
64 /* Periodic countdown timer registers */
65 #define	RV3032_TIMER_VALUE0	0x0B
66 #define	RV3032_TIMER_VALUE1	0x0C
67 
68 /* Status register */
69 #define	RV3032_STATUS		0x0D
70 #define	 RV3032_STATUS_VLF	(1 << 0)	/* Voltage Low Flag */
71 #define	 RV3032_STATUS_PORF	(1 << 1)	/* Power On Reset Flag */
72 #define	 RV3032_STATUS_EVF	(1 << 2)	/* External eVent Flag */
73 #define	 RV3032_STATUS_AF	(1 << 3)	/* Alarm Flag */
74 #define	 RV3032_STATUS_TF	(1 << 4)	/* periodic countdown Timer Flag */
75 #define	 RV3032_STATUS_UF	(1 << 5)	/* periodic time Update Flag */
76 #define	 RV3032_STATUS_TLF 	(1 << 6)	/* Temperature Low Flag */
77 #define	 RV3032_STATUS_THF	(1 << 7)	/* Temperature High Flag */
78 
79 /* Temperature registers */
80 #define	RV3032_TEMP_LSB		0x0E
81 #define	 RV3032_TEMP_LSB_BSF	(1 << 0)
82 #define	 RV3032_TEMP_LSB_CLKF	(1 << 1)
83 #define	 RV3032_TEMP_LSB_EEBUSY	(1 << 2)
84 #define	 RV3032_TEMP_LSB_EEF	(1 << 3)
85 #define	 RV3032_TEMP_LSB_MASK	(0xF0)
86 #define	 RV3032_TEMP_LSB_SHIFT	4
87 
88 #define	RV3032_TEMP_MSB		0x0F
89 
90 #define	TEMP_DIV		16
91 #define	TEMP_C_TO_K		273
92 
93 /* Control registers */
94 #define	RV3032_CTRL1		0x10
95 #define	 RV3032_CTRL1_TD_MASK	0x3	/* Timer clock frequency */
96 #define	 RV3032_CTRL1_TD_SHIFT	0
97 #define	 RV3032_CTRL1_TD_4096	0
98 #define	 RV3032_CTRL1_TD_64	1
99 #define	 RV3032_CTRL1_TD_1	2
100 #define	 RV3032_CTRL1_TD_1_60	3
101 #define	 RV3032_CTRL1_EERD	(1 << 2)	/* EEPROM memory refresh disable bit */
102 #define	 RV3032_CTRL1_TE	(1 << 3)	/* Periodic countdown timer enable bit */
103 #define	 RV3032_CTRL1_USEL	(1 << 4)	/* Update interrupt select bit */
104 #define	 RV3032_CTRL1_GP0	(1 << 5)	/* General Purpose bit 0 */
105 
106 #define	RV3032_CTRL2		0x11
107 #define	 RV3032_CTRL2_STOP	(1 << 0)	/* Stop bit */
108 #define	 RV3032_CTRL2_GP1	(1 << 1)	/* General Purpose bit 1 */
109 #define	 RV3032_CTRL2_EIE	(1 << 2)	/* External event interrupt enable bit */
110 #define	 RV3032_CTRL2_AIE	(1 << 3)	/* Alarm interrupt enable bit */
111 #define	 RV3032_CTRL2_TIE	(1 << 4)	/* Periodic countdown timer interrupt enable bit */
112 #define	 RV3032_CTRL2_UIE	(1 << 5)	/* Periodic time update interrupt enable bit */
113 #define	 RV3032_CTRL2_CLKIE	(1 << 6)	/* Interrupt Controlled Clock Output Enable bit */
114 #define	RV3032_CTRL3		0x12
115 #define	 RV3032_CTRL3_TLIE	(1 << 0)	/* Temperature Low Interrupt Enable bit */
116 #define	 RV3032_CTRL3_THIE	(1 << 1)	/* Temperature High Interrupt Enable bit */
117 #define	 RV3032_CTRL3_TLE	(1 << 2)	/* Temperature Low Enable bit */
118 #define	 RV3032_CTRL3_THE	(1 << 3)	/* Temperature High Enable bit */
119 #define	 RV3032_CTRL3_BSIE	(1 << 4)	/* Backup Switchover Interrupt Enable bit */
120 
121 /* EEPROM registers */
122 #define	RV3032_EEPROM_ADDRESS		0x3D
123 #define	RV3032_EEPROM_DATA		0x3E
124 #define	RV3032_EEPROM_COMMAND		0x3F
125 #define RV3032_EEPROM_CMD_UPDATE	0x11
126 #define RV3032_EEPROM_CMD_REFRESH	0x12
127 #define RV3032_EEPROM_CMD_WRITE_ONE	0x21
128 #define RV3032_EEPROM_CMD_READ_ONE	0x22
129 
130 /* PMU register */
131 #define	RV3032_EEPROM_PMU	0xC0
132 #define	 RV3032_PMU_TCM_MASK	0x3
133 #define	 RV3032_PMU_TCM_SHIFT	0
134 #define	 RV3032_PMU_TCM_OFF	0
135 #define	 RV3032_PMU_TCM_175V	1
136 #define	 RV3032_PMU_TCM_30V	2
137 #define	 RV3032_PMU_TCM_45V	3
138 #define	 RV3032_PMU_TCR_MASK	0x3
139 #define	 RV3032_PMU_TCR_SHIFT	2
140 #define	 RV3032_PMU_TCR_06K	0
141 #define	 RV3032_PMU_TCR_2K	1
142 #define	 RV3032_PMU_TCR_7K	2
143 #define	 RV3032_PMU_TCR_12K	3
144 #define	 RV3032_PMU_BSM_MASK	0x3
145 #define	 RV3032_PMU_BSM_SHIFT	4
146 #define	 RV3032_PMU_BSM_OFF	0
147 #define	 RV3032_PMU_BSM_DSM	1
148 #define	 RV3032_PMU_BSM_LSM	2
149 #define	 RV3032_PMU_BSM_OFF2	3
150 #define	 RV3032_PMU_NCLKE	(1 << 6)
151 
152 struct rv3032_softc {
153 	device_t		dev;
154 	device_t		busdev;
155 	struct intr_config_hook	init_hook;
156 };
157 
158 struct rv3032_timeregs {
159 	uint8_t	secs;
160 	uint8_t	mins;
161 	uint8_t	hours;
162 	uint8_t	weekday;
163 	uint8_t	date;
164 	uint8_t	month;
165 	uint8_t	year;
166 };
167 
168 static struct ofw_compat_data compat_data[] = {
169 	{"microcrystal,rv3032",	1},
170 	{NULL,			0},
171 };
172 
173 static int
174 rv3032_update_register(struct rv3032_softc *sc, uint8_t reg, uint8_t value, uint8_t mask)
175 {
176 	int rv;
177 	uint8_t data;
178 
179 	if ((rv = iicdev_readfrom(sc->dev, reg, &data, 1, IIC_WAIT)) != 0)
180 		return (rv);
181 	data &= mask;
182 	data |= value;
183 	if ((rv = iicdev_writeto(sc->dev, reg, &data, 1, IIC_WAIT)) != 0)
184 		return (rv);
185 	return (0);
186 }
187 
188 static int
189 rv3032_eeprom_wait(struct rv3032_softc *sc)
190 {
191 	int rv, timeout;
192 	uint8_t data;
193 
194 	for (timeout = 1000; timeout > 0; timeout--) {
195 		if ((rv = iicdev_readfrom(sc->dev, RV3032_TEMP_LSB, &data, sizeof(data), IIC_WAIT)) != 0)
196 		return (rv);
197 		if ((data & RV3032_TEMP_LSB_EEBUSY) == 0) {
198 			break;
199 		}
200 	}
201 	if (timeout == 0) {
202 		device_printf(sc->dev, "Timeout updating the eeprom\n");
203 		return (ETIMEDOUT);
204 	}
205 	/* Wait 1ms before allowing another eeprom access */
206 	DELAY(1000);
207 
208 	return (0);
209 }
210 
211 static int
212 rv3032_eeprom_disable(struct rv3032_softc *sc)
213 {
214 	int rv;
215 
216 	if ((rv = rv3032_update_register(sc, RV3032_CTRL1, RV3032_CTRL1_EERD, ~RV3032_CTRL1_EERD)) != 0)
217 		return (rv);
218 	/* Wait 1ms before checking EBUSY */
219 	DELAY(1000);
220 	return (rv3032_eeprom_wait(sc));
221 }
222 
223 static int
224 rv3032_eeprom_update(struct rv3032_softc *sc)
225 {
226 	int rv;
227 	uint8_t data;
228 
229 	data = RV3032_EEPROM_CMD_UPDATE;
230 	if ((rv = iicdev_writeto(sc->dev, RV3032_EEPROM_COMMAND, &data, sizeof(data), IIC_WAIT)) != 0)
231 		return (rv);
232 	/* Wait 1ms before checking EBUSY */
233 	DELAY(1000);
234 	return (rv3032_eeprom_wait(sc));
235 }
236 
237 static int
238 rv3032_eeprom_enable(struct rv3032_softc *sc)
239 {
240 	int rv;
241 
242 	/* Restore eeprom refresh */
243 	if ((rv = rv3032_update_register(sc, RV3032_CTRL1, 0, ~RV3032_CTRL1_EERD)) != 0)
244 		return (rv);
245 	DELAY(1000);
246 
247 	return (0);
248 }
249 
250 static int
251 rv3032_update_cfg(struct rv3032_softc *sc)
252 {
253 	int rv;
254 
255 	if ((rv = rv3032_eeprom_disable(sc)) != 0)
256 		return (rv);
257 
258 	/* Save configuration in eeprom and re-enable it */
259 	if ((rv = rv3032_eeprom_update(sc)) != 0)
260 		return (rv);
261 	return (rv3032_eeprom_enable(sc));
262 }
263 
264 static int
265 rv3032_temp_read(struct rv3032_softc *sc, int *temp)
266 {
267 	int rv, temp2;
268 	uint8_t data[2];
269 
270 	if ((rv = iicdev_readfrom(sc->dev, RV3032_TEMP_LSB, &data, sizeof(data), IIC_WAIT)) != 0)
271 		return (rv);
272 
273 	/* Wait for temp to be stable */
274 	*temp = (((data[0] & RV3032_TEMP_LSB_MASK) >> RV3032_TEMP_LSB_SHIFT) |
275 	    (data[1] << RV3032_TEMP_LSB_SHIFT));
276 	do {
277 		temp2 = *temp;
278 		*temp = (((data[0] & RV3032_TEMP_LSB_MASK) >> RV3032_TEMP_LSB_SHIFT) |
279 		    (data[1] << RV3032_TEMP_LSB_SHIFT));
280 	} while (temp2 != *temp);
281 	*temp = (*temp / TEMP_DIV) + TEMP_C_TO_K;
282 	return (0);
283 }
284 
285 static int
286 rv3032_temp_sysctl(SYSCTL_HANDLER_ARGS)
287 {
288 	int error, temp;
289 	struct rv3032_softc *sc;
290 
291 	sc = (struct rv3032_softc *)arg1;
292 	if (rv3032_temp_read(sc, &temp) != 0)
293 		return (EIO);
294 	error = sysctl_handle_int(oidp, &temp, 0, req);
295 
296 	return (error);
297 }
298 
299 static void
300 rv3032_init(void *arg)
301 {
302 	struct rv3032_softc	*sc;
303 	struct sysctl_ctx_list *ctx;
304 	struct sysctl_oid *tree_node;
305 	struct sysctl_oid_list *tree;
306 	int rv;
307 
308 	sc = (struct rv3032_softc*)arg;
309 	config_intrhook_disestablish(&sc->init_hook);
310 
311 	/* Set direct switching mode */
312 	rv3032_update_register(sc,
313 	    RV3032_EEPROM_PMU,
314 	    RV3032_PMU_BSM_DSM << RV3032_PMU_BSM_SHIFT,
315 	    RV3032_PMU_BSM_MASK);
316 	if ((rv = rv3032_update_cfg(sc)) != 0) {
317 		device_printf(sc->dev, "Cannot set to DSM mode (%d)\n", rv);
318 		return;
319 	}
320 
321 	/* Register as clock source */
322 	clock_register_flags(sc->dev, 1000000, CLOCKF_SETTIME_NO_ADJ);
323 	clock_schedule(sc->dev, 1);
324 
325 	ctx = device_get_sysctl_ctx(sc->dev);
326 	tree_node = device_get_sysctl_tree(sc->dev);
327 	tree = SYSCTL_CHILDREN(tree_node);
328 	SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "temperature",
329 	    CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
330 	    rv3032_temp_sysctl, "IK0", "Current temperature");
331 	return;
332 }
333 
334 static int
335 rv3032_probe(device_t dev)
336 {
337 
338 	if (!ofw_bus_status_okay(dev))
339 		return (ENXIO);
340 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
341 		device_set_desc(dev, "Microcrystal RV3032");
342 		return (BUS_PROBE_DEFAULT);
343 	}
344 	return (ENXIO);
345 }
346 
347 static int
348 rv3032_attach(device_t dev)
349 {
350 	struct rv3032_softc	*sc;
351 
352 	sc = device_get_softc(dev);
353 	sc->dev = dev;
354 	sc->busdev = device_get_parent(sc->dev);
355 
356 	sc->init_hook.ich_func = rv3032_init;
357 	sc->init_hook.ich_arg = sc;
358 	if (config_intrhook_establish(&sc->init_hook) != 0)
359 		return (ENOMEM);
360 
361 	return (0);
362 }
363 
364 static int
365 rv3032_detach(device_t dev)
366 {
367 
368 	clock_unregister(dev);
369 	return (0);
370 }
371 
372 static int
373 rv3032_gettime(device_t dev, struct timespec *ts)
374 {
375 	struct rv3032_softc *sc;
376 	struct rv3032_timeregs time_regs;
377 	struct clocktime ct;
378 	uint8_t status;
379 	int rv;
380 
381 	sc = device_get_softc(dev);
382 
383 	if ((rv = iicdev_readfrom(sc->dev, RV3032_STATUS, &status, sizeof(status), IIC_WAIT)) != 0)
384 		return (rv);
385 	if (status & (RV3032_STATUS_PORF | RV3032_STATUS_VLF))
386 		return (EINVAL);
387 	if ((rv = iicdev_readfrom(sc->dev, RV3032_SECS, &time_regs, sizeof(time_regs), IIC_WAIT)) != 0)
388 		return (rv);
389 
390 	bzero(&ct, sizeof(ct));
391 	ct.sec = FROMBCD(time_regs.secs & 0x7f);
392 	ct.min = FROMBCD(time_regs.mins & 0x7f);
393 	ct.hour = FROMBCD(time_regs.hours & 0x3f);
394 	ct.day = FROMBCD(time_regs.date & 0x3f);
395 	ct.mon = FROMBCD(time_regs.month & 0x1f) - 1;
396 	ct.year = FROMBCD(time_regs.year) + 2000;
397 
398 	return (clock_ct_to_ts(&ct, ts));
399 }
400 
401 static int
402 rv3032_settime(device_t dev, struct timespec *ts)
403 {
404 	struct rv3032_softc *sc;
405 	struct rv3032_timeregs time_regs;
406 	struct clocktime ct;
407 	uint8_t status;
408 	int rv;
409 
410 	sc = device_get_softc(dev);
411 	if ((rv = iicdev_readfrom(sc->dev, RV3032_STATUS, &status, sizeof(status), IIC_WAIT)) != 0)
412 		return (rv);
413 
414 	clock_ts_to_ct(ts, &ct);
415 
416 	time_regs.secs = TOBCD(ct.sec);
417 	time_regs.mins = TOBCD(ct.min);
418 	time_regs.hours = TOBCD(ct.hour);
419 	time_regs.date = TOBCD(ct.day);
420 	time_regs.month = TOBCD(ct.mon + 1);
421 	time_regs.year = TOBCD(ct.year - 2000);
422 
423 	if ((rv = iicdev_writeto(sc->dev, RV3032_SECS, &time_regs, sizeof(time_regs), IIC_WAIT)) != 0)
424 		return (rv);
425 
426 	/* Force a power on reset event so rv3032 reload the registers */
427 	status &= ~(RV3032_STATUS_PORF | RV3032_STATUS_VLF);
428 	if ((rv = iicdev_writeto(sc->dev, RV3032_STATUS, &status, sizeof(status), IIC_WAIT)) != 0)
429 		return (rv);
430 	return (0);
431 }
432 
433 static device_method_t rv3032_methods[] = {
434         /* device_if methods */
435 	DEVMETHOD(device_probe,		rv3032_probe),
436 	DEVMETHOD(device_attach,	rv3032_attach),
437 	DEVMETHOD(device_detach,	rv3032_detach),
438 
439         /* clock_if methods */
440 	DEVMETHOD(clock_gettime,	rv3032_gettime),
441 	DEVMETHOD(clock_settime,	rv3032_settime),
442 
443 	DEVMETHOD_END,
444 };
445 
446 static driver_t rv3032_driver = {
447 	"rv3032",
448 	rv3032_methods,
449 	sizeof(struct rv3032_softc),
450 };
451 
452 DRIVER_MODULE(rv3032, iicbus, rv3032_driver, NULL, NULL);
453 MODULE_VERSION(rv3032, 1);
454 MODULE_DEPEND(rv3032, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
455 IICBUS_FDT_PNP_INFO(compat_data);
456