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
rv3032_update_register(struct rv3032_softc * sc,uint8_t reg,uint8_t value,uint8_t mask)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
rv3032_eeprom_wait(struct rv3032_softc * sc)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
rv3032_eeprom_disable(struct rv3032_softc * sc)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
rv3032_eeprom_update(struct rv3032_softc * sc)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
rv3032_eeprom_enable(struct rv3032_softc * sc)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
rv3032_update_cfg(struct rv3032_softc * sc)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
rv3032_temp_read(struct rv3032_softc * sc,int * temp)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
rv3032_temp_sysctl(SYSCTL_HANDLER_ARGS)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
rv3032_init(void * arg)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
rv3032_probe(device_t dev)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
rv3032_attach(device_t dev)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
rv3032_detach(device_t dev)365 rv3032_detach(device_t dev)
366 {
367
368 clock_unregister(dev);
369 return (0);
370 }
371
372 static int
rv3032_gettime(device_t dev,struct timespec * ts)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
rv3032_settime(device_t dev,struct timespec * ts)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