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