1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
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 #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/module.h>
37 #include <sys/rman.h>
38 #include <sys/sx.h>
39
40 #include <dev/iicbus/iiconf.h>
41 #include <dev/iicbus/iicbus.h>
42 #include <dev/ofw/ofw_bus.h>
43 #include <dev/ofw/ofw_bus_subr.h>
44
45 #include "clock_if.h"
46 #include "ofw_iicbus_if.h"
47 #include "max77620.h"
48
49 #define MAX77620_RTC_INT 0x00
50 #define MAX77620_RTC_INTM 0x01
51 #define MAX77620_RTC_CONTROLM 0x02
52 #define MAX77620_RTC_CONTROL 0x03
53 #define RTC_CONTROL_MODE_24 (1 << 1)
54 #define RTC_CONTROL_BCD_EN (1 << 0)
55
56 #define MAX77620_RTC_UPDATE0 0x04
57 #define RTC_UPDATE0_RTC_RBUDR (1 << 4)
58 #define RTC_UPDATE0_RTC_UDR (1 << 0)
59
60 #define MAX77620_WTSR_SMPL_CNTL 0x06
61 #define MAX77620_RTC_SEC 0x07
62 #define MAX77620_RTC_MIN 0x08
63 #define MAX77620_RTC_HOUR 0x09
64 #define MAX77620_RTC_WEEKDAY 0x0A
65 #define MAX77620_RTC_MONTH 0x0B
66 #define MAX77620_RTC_YEAR 0x0C
67 #define MAX77620_RTC_DATE 0x0D
68 #define MAX77620_ALARM1_SEC 0x0E
69 #define MAX77620_ALARM1_MIN 0x0F
70 #define MAX77620_ALARM1_HOUR 0x10
71 #define MAX77620_ALARM1_WEEKDAY 0x11
72 #define MAX77620_ALARM1_MONTH 0x12
73 #define MAX77620_ALARM1_YEAR 0x13
74 #define MAX77620_ALARM1_DATE 0x14
75 #define MAX77620_ALARM2_SEC 0x15
76 #define MAX77620_ALARM2_MIN 0x16
77 #define MAX77620_ALARM2_HOUR 0x17
78 #define MAX77620_ALARM2_WEEKDAY 0x18
79 #define MAX77620_ALARM2_MONTH 0x19
80 #define MAX77620_ALARM2_YEAR 0x1A
81 #define MAX77620_ALARM2_DATE 0x1B
82
83 #define MAX77620_RTC_START_YEAR 2000
84 #define MAX77620_RTC_I2C_ADDR 0x68
85
86 #define LOCK(_sc) sx_xlock(&(_sc)->lock)
87 #define UNLOCK(_sc) sx_xunlock(&(_sc)->lock)
88 #define LOCK_INIT(_sc) sx_init(&(_sc)->lock, "max77620_rtc")
89 #define LOCK_DESTROY(_sc) sx_destroy(&(_sc)->lock);
90
91 struct max77620_rtc_softc {
92 device_t dev;
93 struct sx lock;
94 int bus_addr;
95 };
96
97 char max77620_rtc_compat[] = "maxim,max77620_rtc";
98
99 /*
100 * Raw register access function.
101 */
102 static int
103 max77620_rtc_read(struct max77620_rtc_softc *sc, uint8_t reg, uint8_t *val)
104 {
105 uint8_t addr;
106 int rv;
107 struct iic_msg msgs[2] = {
108 {0, IIC_M_WR, 1, &addr},
109 {0, IIC_M_RD, 1, val},
110 };
111
112 msgs[0].slave = sc->bus_addr;
113 msgs[1].slave = sc->bus_addr;
114 addr = reg;
115
116 rv = iicbus_transfer(sc->dev, msgs, 2);
117 if (rv != 0) {
118 device_printf(sc->dev,
119 "Error when reading reg 0x%02X, rv: %d\n", reg, rv);
120 return (EIO);
121 }
122
123 return (0);
124 }
125
126 static int
127 max77620_rtc_read_buf(struct max77620_rtc_softc *sc, uint8_t reg,
128 uint8_t *buf, size_t size)
129 {
130 uint8_t addr;
131 int rv;
132 struct iic_msg msgs[2] = {
133 {0, IIC_M_WR, 1, &addr},
134 {0, IIC_M_RD, size, buf},
135 };
136
137 msgs[0].slave = sc->bus_addr;
138 msgs[1].slave = sc->bus_addr;
139 addr = reg;
140
141 rv = iicbus_transfer(sc->dev, msgs, 2);
142 if (rv != 0) {
143 device_printf(sc->dev,
144 "Error when reading reg 0x%02X, rv: %d\n", reg, rv);
145 return (EIO);
146 }
147
148 return (0);
149 }
150
151 static int
152 max77620_rtc_write(struct max77620_rtc_softc *sc, uint8_t reg, uint8_t val)
153 {
154 uint8_t data[2];
155 int rv;
156
157 struct iic_msg msgs[1] = {
158 {0, IIC_M_WR, 2, data},
159 };
160
161 msgs[0].slave = sc->bus_addr;
162 data[0] = reg;
163 data[1] = val;
164
165 rv = iicbus_transfer(sc->dev, msgs, 1);
166 if (rv != 0) {
167 device_printf(sc->dev,
168 "Error when writing reg 0x%02X, rv: %d\n", reg, rv);
169 return (EIO);
170 }
171 return (0);
172 }
173
174 static int
175 max77620_rtc_write_buf(struct max77620_rtc_softc *sc, uint8_t reg, uint8_t *buf,
176 size_t size)
177 {
178 uint8_t data[1];
179 int rv;
180 struct iic_msg msgs[2] = {
181 {0, IIC_M_WR, 1, data},
182 {0, IIC_M_WR | IIC_M_NOSTART, size, buf},
183 };
184
185 msgs[0].slave = sc->bus_addr;
186 msgs[1].slave = sc->bus_addr;
187 data[0] = reg;
188
189 rv = iicbus_transfer(sc->dev, msgs, 2);
190 if (rv != 0) {
191 device_printf(sc->dev,
192 "Error when writing reg 0x%02X, rv: %d\n", reg, rv);
193 return (EIO);
194 }
195 return (0);
196 }
197
198 static int
199 max77620_rtc_modify(struct max77620_rtc_softc *sc, uint8_t reg, uint8_t clear,
200 uint8_t set)
201 {
202 uint8_t val;
203 int rv;
204
205 rv = max77620_rtc_read(sc, reg, &val);
206 if (rv != 0)
207 return (rv);
208
209 val &= ~clear;
210 val |= set;
211
212 rv = max77620_rtc_write(sc, reg, val);
213 if (rv != 0)
214 return (rv);
215
216 return (0);
217 }
218
219 static int
220 max77620_rtc_update(struct max77620_rtc_softc *sc, bool for_read)
221 {
222 uint8_t reg;
223 int rv;
224
225 reg = for_read ? RTC_UPDATE0_RTC_RBUDR: RTC_UPDATE0_RTC_UDR;
226 rv = max77620_rtc_modify(sc, MAX77620_RTC_UPDATE0, reg, reg);
227 if (rv != 0)
228 return (rv);
229
230 DELAY(16000);
231 return (rv);
232 }
233
234 static int
235 max77620_rtc_gettime(device_t dev, struct timespec *ts)
236 {
237 struct max77620_rtc_softc *sc;
238 struct clocktime ct;
239 uint8_t buf[7];
240 int rv;
241
242 sc = device_get_softc(dev);
243
244 LOCK(sc);
245 rv = max77620_rtc_update(sc, true);
246 if (rv != 0) {
247 UNLOCK(sc);
248 device_printf(sc->dev, "Failed to strobe RTC data\n");
249 return (rv);
250 }
251
252 rv = max77620_rtc_read_buf(sc, MAX77620_RTC_SEC, buf, nitems(buf));
253 UNLOCK(sc);
254 if (rv != 0) {
255 device_printf(sc->dev, "Failed to read RTC data\n");
256 return (rv);
257 }
258 ct.nsec = 0;
259 ct.sec = bcd2bin(buf[0] & 0x7F);
260 ct.min = bcd2bin(buf[1] & 0x7F);
261 ct.hour = bcd2bin(buf[2] & 0x3F);
262 ct.dow = ffs(buf[3] & 07);
263 ct.mon = bcd2bin(buf[4] & 0x1F);
264 ct.year = bcd2bin(buf[5] & 0x7F) + MAX77620_RTC_START_YEAR;
265 ct.day = bcd2bin(buf[6] & 0x3F);
266
267 return (clock_ct_to_ts(&ct, ts));
268 }
269
270 static int
271 max77620_rtc_settime(device_t dev, struct timespec *ts)
272 {
273 struct max77620_rtc_softc *sc;
274 struct clocktime ct;
275 uint8_t buf[7];
276 int rv;
277
278 sc = device_get_softc(dev);
279 clock_ts_to_ct(ts, &ct);
280
281 if (ct.year < MAX77620_RTC_START_YEAR)
282 return (EINVAL);
283
284 buf[0] = bin2bcd(ct.sec);
285 buf[1] = bin2bcd(ct.min);
286 buf[2] = bin2bcd(ct.hour);
287 buf[3] = 1 << ct.dow;
288 buf[4] = bin2bcd(ct.mon);
289 buf[5] = bin2bcd(ct.year - MAX77620_RTC_START_YEAR);
290 buf[6] = bin2bcd(ct.day);
291
292 LOCK(sc);
293 rv = max77620_rtc_write_buf(sc, MAX77620_RTC_SEC, buf, nitems(buf));
294 if (rv != 0) {
295 UNLOCK(sc);
296 device_printf(sc->dev, "Failed to write RTC data\n");
297 return (rv);
298 }
299 rv = max77620_rtc_update(sc, false);
300 UNLOCK(sc);
301 if (rv != 0) {
302 device_printf(sc->dev, "Failed to update RTC data\n");
303 return (rv);
304 }
305
306 return (0);
307 }
308
309 static int
310 max77620_rtc_probe(device_t dev)
311 {
312 const char *compat;
313
314 /*
315 * TODO:
316 * ofw_bus_is_compatible() should use compat string from devinfo cache
317 * maximum size of OFW property should be defined in public header
318 */
319 if ((compat = ofw_bus_get_compat(dev)) == NULL)
320 return (ENXIO);
321 if (strncasecmp(compat, max77620_rtc_compat, 255) != 0)
322 return (ENXIO);
323
324 device_set_desc(dev, "MAX77620 RTC");
325 return (BUS_PROBE_DEFAULT);
326 }
327
328 static int
329 max77620_rtc_attach(device_t dev)
330 {
331 struct max77620_rtc_softc *sc;
332 uint8_t reg;
333 int rv;
334
335 sc = device_get_softc(dev);
336 sc->dev = dev;
337 sc->bus_addr = iicbus_get_addr(dev);
338
339 LOCK_INIT(sc);
340
341 reg = RTC_CONTROL_MODE_24 | RTC_CONTROL_BCD_EN;
342 rv = max77620_rtc_modify(sc, MAX77620_RTC_CONTROLM, reg, reg);
343 if (rv != 0) {
344 device_printf(sc->dev, "Failed to configure RTC\n");
345 goto fail;
346 }
347
348 rv = max77620_rtc_modify(sc, MAX77620_RTC_CONTROL, reg, reg);
349 if (rv != 0) {
350 device_printf(sc->dev, "Failed to configure RTC\n");
351 goto fail;
352 }
353 rv = max77620_rtc_update(sc, false);
354 if (rv != 0) {
355 device_printf(sc->dev, "Failed to update RTC data\n");
356 return (rv);
357 }
358
359 clock_register(sc->dev, 1000000);
360
361 return (bus_generic_attach(dev));
362
363 fail:
364 LOCK_DESTROY(sc);
365 return (rv);
366 }
367
368 static int
369 max77620_rtc_detach(device_t dev)
370 {
371 struct max77620_softc *sc;
372
373 sc = device_get_softc(dev);
374 LOCK_DESTROY(sc);
375
376 return (bus_generic_detach(dev));
377 }
378
379 /*
380 * The secondary address of MAX77620 (RTC function) is not in DT,
381 * add it manualy as subdevice
382 */
383 int
384 max77620_rtc_create(struct max77620_softc *sc, phandle_t node)
385 {
386 device_t parent, child;
387 int rv;
388
389 parent = device_get_parent(sc->dev);
390
391 child = BUS_ADD_CHILD(parent, 0, NULL, -1);
392 if (child == NULL) {
393 device_printf(sc->dev, "Cannot create MAX77620 RTC device.\n");
394 return (ENXIO);
395 }
396
397 rv = OFW_IICBUS_SET_DEVINFO(parent, child, -1, "rtc@68",
398 max77620_rtc_compat, MAX77620_RTC_I2C_ADDR << 1);
399 if (rv != 0) {
400 device_printf(sc->dev, "Cannot setup MAX77620 RTC device.\n");
401 return (ENXIO);
402 }
403
404 return (0);
405 }
406
407 static device_method_t max77620_rtc_methods[] = {
408 /* Device interface */
409 DEVMETHOD(device_probe, max77620_rtc_probe),
410 DEVMETHOD(device_attach, max77620_rtc_attach),
411 DEVMETHOD(device_detach, max77620_rtc_detach),
412
413 /* RTC interface */
414 DEVMETHOD(clock_gettime, max77620_rtc_gettime),
415 DEVMETHOD(clock_settime, max77620_rtc_settime),
416
417 DEVMETHOD_END
418 };
419
420 static DEFINE_CLASS_0(rtc, max77620_rtc_driver, max77620_rtc_methods,
421 sizeof(struct max77620_rtc_softc));
422 EARLY_DRIVER_MODULE(max77620rtc_, iicbus, max77620_rtc_driver, NULL, NULL, 74);
Cache object: d2118d9072dc0d0f558f0e63f5194f29
|