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
44#include "clock_if.h"
45#include "max77620.h"
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
88struct max77620_rtc_softc {
89	device_t			dev;
90	struct sx			lock;
91	int				bus_addr;
92};
93
94/*
95 * Raw register access function.
96 */
97static int
98max77620_rtc_read(struct max77620_rtc_softc *sc, uint8_t reg, uint8_t *val)
99{
100	uint8_t addr;
101	int rv;
102	struct iic_msg msgs[2] = {
103		{0, IIC_M_WR, 1, &addr},
104		{0, IIC_M_RD, 1, val},
105	};
106
107	msgs[0].slave = sc->bus_addr;
108	msgs[1].slave = sc->bus_addr;
109	addr = reg;
110
111	rv = iicbus_transfer(sc->dev, msgs, 2);
112	if (rv != 0) {
113		device_printf(sc->dev,
114		    "Error when reading reg 0x%02X, rv: %d\n", reg,  rv);
115		return (EIO);
116	}
117
118	return (0);
119}
120
121static int
122max77620_rtc_read_buf(struct max77620_rtc_softc *sc, uint8_t reg,
123    uint8_t *buf, size_t size)
124{
125	uint8_t addr;
126	int rv;
127	struct iic_msg msgs[2] = {
128		{0, IIC_M_WR, 1, &addr},
129		{0, IIC_M_RD, size, buf},
130	};
131
132	msgs[0].slave = sc->bus_addr;
133	msgs[1].slave = sc->bus_addr;
134	addr = reg;
135
136	rv = iicbus_transfer(sc->dev, msgs, 2);
137	if (rv != 0) {
138		device_printf(sc->dev,
139		    "Error when reading reg 0x%02X, rv: %d\n", reg,  rv);
140		return (EIO);
141	}
142
143	return (0);
144}
145
146static int
147max77620_rtc_write(struct max77620_rtc_softc *sc, uint8_t reg, uint8_t val)
148{
149	uint8_t data[2];
150	int rv;
151
152	struct iic_msg msgs[1] = {
153		{0, IIC_M_WR, 2, data},
154	};
155
156	msgs[0].slave = sc->bus_addr;
157	data[0] = reg;
158	data[1] = val;
159
160	rv = iicbus_transfer(sc->dev, msgs, 1);
161	if (rv != 0) {
162		device_printf(sc->dev,
163		    "Error when writing reg 0x%02X, rv: %d\n", reg, rv);
164		return (EIO);
165	}
166	return (0);
167}
168
169static int
170max77620_rtc_write_buf(struct max77620_rtc_softc *sc, uint8_t reg, uint8_t *buf,
171    size_t size)
172{
173	uint8_t data[1];
174	int rv;
175	struct iic_msg msgs[2] = {
176		{0, IIC_M_WR, 1, data},
177		{0, IIC_M_WR | IIC_M_NOSTART, size, buf},
178	};
179
180	msgs[0].slave = sc->bus_addr;
181	msgs[1].slave = sc->bus_addr;
182	data[0] = reg;
183
184	rv = iicbus_transfer(sc->dev, msgs, 2);
185	if (rv != 0) {
186		device_printf(sc->dev,
187		    "Error when writing reg 0x%02X, rv: %d\n", reg, rv);
188		return (EIO);
189	}
190	return (0);
191}
192
193static int
194max77620_rtc_modify(struct max77620_rtc_softc *sc, uint8_t reg, uint8_t clear,
195    uint8_t set)
196{
197	uint8_t val;
198	int rv;
199
200	rv = max77620_rtc_read(sc, reg, &val);
201	if (rv != 0)
202		return (rv);
203
204	val &= ~clear;
205	val |= set;
206
207	rv = max77620_rtc_write(sc, reg, val);
208	if (rv != 0)
209		return (rv);
210
211	return (0);
212}
213
214static int
215max77620_rtc_update(struct max77620_rtc_softc *sc, bool for_read)
216{
217	uint8_t reg;
218	int rv;
219
220	reg = for_read ? RTC_UPDATE0_RTC_RBUDR: RTC_UPDATE0_RTC_UDR;
221	rv = max77620_rtc_modify(sc, MAX77620_RTC_UPDATE0, reg, reg);
222	if (rv != 0)
223		return (rv);
224
225	DELAY(16000);
226	return (rv);
227}
228
229static int
230max77620_rtc_gettime(device_t dev, struct timespec *ts)
231{
232	struct max77620_rtc_softc *sc;
233	struct clocktime ct;
234	uint8_t buf[7];
235	int rv;
236
237	sc = device_get_softc(dev);
238
239	LOCK(sc);
240	rv = max77620_rtc_update(sc, true);
241	if (rv != 0) {
242		UNLOCK(sc);
243		device_printf(sc->dev, "Failed to strobe RTC data\n");
244		return (rv);
245	}
246
247	rv = max77620_rtc_read_buf(sc, MAX77620_RTC_SEC, buf, nitems(buf));
248	UNLOCK(sc);
249	if (rv != 0) {
250		device_printf(sc->dev, "Failed to read RTC data\n");
251		return (rv);
252	}
253	ct.nsec = 0;
254	ct.sec  = bcd2bin(buf[0] & 0x7F);
255	ct.min  = bcd2bin(buf[1] & 0x7F);
256	ct.hour = bcd2bin(buf[2] & 0x3F);
257	ct.dow  = ffs(buf[3] & 07);
258	ct.mon  = bcd2bin(buf[4] & 0x1F);
259	ct.year = bcd2bin(buf[5] & 0x7F) + MAX77620_RTC_START_YEAR;
260	ct.day  = bcd2bin(buf[6] & 0x3F);
261
262	return (clock_ct_to_ts(&ct, ts));
263}
264
265static int
266max77620_rtc_settime(device_t dev, struct timespec *ts)
267{
268	struct max77620_rtc_softc *sc;
269	struct clocktime ct;
270	uint8_t buf[7];
271	int rv;
272
273	sc = device_get_softc(dev);
274	clock_ts_to_ct(ts, &ct);
275
276	if (ct.year < MAX77620_RTC_START_YEAR)
277		return (EINVAL);
278
279	buf[0] = bin2bcd(ct.sec);
280	buf[1] = bin2bcd(ct.min);
281	buf[2] = bin2bcd(ct.hour);
282	buf[3] = 1 << ct.dow;
283	buf[4] = bin2bcd(ct.mon);
284	buf[5] = bin2bcd(ct.year - MAX77620_RTC_START_YEAR);
285	buf[6] = bin2bcd(ct.day);
286
287	LOCK(sc);
288	rv = max77620_rtc_write_buf(sc, MAX77620_RTC_SEC, buf, nitems(buf));
289	if (rv != 0) {
290		UNLOCK(sc);
291		device_printf(sc->dev, "Failed to write RTC data\n");
292		return (rv);
293	}
294	rv = max77620_rtc_update(sc, false);
295	UNLOCK(sc);
296	if (rv != 0) {
297		device_printf(sc->dev, "Failed to update RTC data\n");
298		return (rv);
299	}
300
301	return (0);
302}
303
304static int
305max77620_rtc_probe(device_t dev)
306{
307	struct iicbus_ivar *dinfo;
308
309	dinfo = device_get_ivars(dev);
310	if (dinfo == NULL)
311		return (ENXIO);
312	if (dinfo->addr != MAX77620_RTC_I2C_ADDR << 1)
313		return (ENXIO);
314
315	device_set_desc(dev, "MAX77620 RTC");
316	return (BUS_PROBE_DEFAULT);
317}
318
319static int
320max77620_rtc_attach(device_t dev)
321{
322	struct max77620_rtc_softc *sc;
323	uint8_t reg;
324	int rv;
325
326	sc = device_get_softc(dev);
327	sc->dev = dev;
328	sc->bus_addr = iicbus_get_addr(dev);
329
330	LOCK_INIT(sc);
331
332	reg = RTC_CONTROL_MODE_24 | RTC_CONTROL_BCD_EN;
333	rv = max77620_rtc_modify(sc, MAX77620_RTC_CONTROLM, reg, reg);
334	if (rv != 0) {
335		device_printf(sc->dev, "Failed to configure RTC\n");
336		goto fail;
337	}
338
339	rv = max77620_rtc_modify(sc, MAX77620_RTC_CONTROL, reg, reg);
340	if (rv != 0) {
341		device_printf(sc->dev, "Failed to configure RTC\n");
342		goto fail;
343	}
344	rv = max77620_rtc_update(sc, false);
345	if (rv != 0) {
346		device_printf(sc->dev, "Failed to update RTC data\n");
347		return (rv);
348	}
349
350	clock_register(sc->dev, 1000000);
351
352	return (bus_generic_attach(dev));
353
354fail:
355	LOCK_DESTROY(sc);
356	return (rv);
357}
358
359/*
360 * The secondary address of MAX77620 (RTC function) is not in DTB,
361 * add it manualy
362 */
363static int
364max77620_rtc_detach(device_t dev)
365{
366	struct max77620_softc *sc;
367
368	sc = device_get_softc(dev);
369	LOCK_DESTROY(sc);
370
371	return (bus_generic_detach(dev));
372}
373
374int
375max77620_rtc_create(struct max77620_softc *sc, phandle_t node)
376{
377	device_t parent, child;
378	struct iicbus_ivar *dinfo;
379
380	parent = device_get_parent(sc->dev);
381	child = BUS_ADD_CHILD(parent, 0, NULL, -1);
382	if (child == 0)	{
383		device_printf(sc->dev, "Cannot add MAX77620 RTC device.\n");
384		return (ENXIO);
385	}
386	dinfo = device_get_ivars(child);
387	if (dinfo == NULL)	{
388		device_printf(sc->dev,
389		    "Cannot set I2Caddress for MAX77620 RTC.\n");
390		return (ENXIO);
391	}
392	dinfo->addr = MAX77620_RTC_I2C_ADDR << 1;
393	return (0);
394}
395
396static device_method_t max77620_rtc_methods[] = {
397	/* Device interface */
398	DEVMETHOD(device_probe,		max77620_rtc_probe),
399	DEVMETHOD(device_attach,	max77620_rtc_attach),
400	DEVMETHOD(device_detach,	max77620_rtc_detach),
401
402	/* RTC interface */
403	DEVMETHOD(clock_gettime,	max77620_rtc_gettime),
404	DEVMETHOD(clock_settime,	max77620_rtc_settime),
405
406	DEVMETHOD_END
407};
408
409static devclass_t max77620_rtc_devclass;
410static DEFINE_CLASS_0(rtc, max77620_rtc_driver, max77620_rtc_methods,
411    sizeof(struct max77620_rtc_softc));
412EARLY_DRIVER_MODULE(max77620rtc_, iicbus, max77620_rtc_driver,
413    max77620_rtc_devclass, NULL, NULL, 74);
414