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