xref: /freebsd/sys/arm64/nvidia/tegra210/max77620_rtc.c (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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/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);
423