xref: /openbmc/linux/drivers/rtc/rtc-rv3028.c (revision 44c638ce4ec6fb9d33978348ebb90847b9aa274a)
1e6e7376cSAlexandre Belloni // SPDX-License-Identifier: GPL-2.0
2e6e7376cSAlexandre Belloni /*
3e6e7376cSAlexandre Belloni  * RTC driver for the Micro Crystal RV3028
4e6e7376cSAlexandre Belloni  *
5e6e7376cSAlexandre Belloni  * Copyright (C) 2019 Micro Crystal SA
6e6e7376cSAlexandre Belloni  *
7e6e7376cSAlexandre Belloni  * Alexandre Belloni <alexandre.belloni@bootlin.com>
8e6e7376cSAlexandre Belloni  *
9e6e7376cSAlexandre Belloni  */
10e6e7376cSAlexandre Belloni 
11e6e7376cSAlexandre Belloni #include <linux/bcd.h>
12e6e7376cSAlexandre Belloni #include <linux/bitops.h>
13e6e7376cSAlexandre Belloni #include <linux/i2c.h>
14e6e7376cSAlexandre Belloni #include <linux/interrupt.h>
15e6e7376cSAlexandre Belloni #include <linux/kernel.h>
16e6e7376cSAlexandre Belloni #include <linux/log2.h>
17e6e7376cSAlexandre Belloni #include <linux/module.h>
18e6e7376cSAlexandre Belloni #include <linux/of_device.h>
19e6e7376cSAlexandre Belloni #include <linux/regmap.h>
20e6e7376cSAlexandre Belloni #include <linux/rtc.h>
21e6e7376cSAlexandre Belloni 
22e6e7376cSAlexandre Belloni #define RV3028_SEC			0x00
23e6e7376cSAlexandre Belloni #define RV3028_MIN			0x01
24e6e7376cSAlexandre Belloni #define RV3028_HOUR			0x02
25e6e7376cSAlexandre Belloni #define RV3028_WDAY			0x03
26e6e7376cSAlexandre Belloni #define RV3028_DAY			0x04
27e6e7376cSAlexandre Belloni #define RV3028_MONTH			0x05
28e6e7376cSAlexandre Belloni #define RV3028_YEAR			0x06
29e6e7376cSAlexandre Belloni #define RV3028_ALARM_MIN		0x07
30e6e7376cSAlexandre Belloni #define RV3028_ALARM_HOUR		0x08
31e6e7376cSAlexandre Belloni #define RV3028_ALARM_DAY		0x09
32e6e7376cSAlexandre Belloni #define RV3028_STATUS			0x0E
33e6e7376cSAlexandre Belloni #define RV3028_CTRL1			0x0F
34e6e7376cSAlexandre Belloni #define RV3028_CTRL2			0x10
35e6e7376cSAlexandre Belloni #define RV3028_EVT_CTRL			0x13
36e6e7376cSAlexandre Belloni #define RV3028_TS_COUNT			0x14
37e6e7376cSAlexandre Belloni #define RV3028_TS_SEC			0x15
38e6e7376cSAlexandre Belloni #define RV3028_RAM1			0x1F
39e6e7376cSAlexandre Belloni #define RV3028_EEPROM_ADDR		0x25
40e6e7376cSAlexandre Belloni #define RV3028_EEPROM_DATA		0x26
41e6e7376cSAlexandre Belloni #define RV3028_EEPROM_CMD		0x27
42e6e7376cSAlexandre Belloni #define RV3028_CLKOUT			0x35
43e6e7376cSAlexandre Belloni #define RV3028_OFFSET			0x36
44e6e7376cSAlexandre Belloni #define RV3028_BACKUP			0x37
45e6e7376cSAlexandre Belloni 
46e6e7376cSAlexandre Belloni #define RV3028_STATUS_PORF		BIT(0)
47e6e7376cSAlexandre Belloni #define RV3028_STATUS_EVF		BIT(1)
48e6e7376cSAlexandre Belloni #define RV3028_STATUS_AF		BIT(2)
49e6e7376cSAlexandre Belloni #define RV3028_STATUS_TF		BIT(3)
50e6e7376cSAlexandre Belloni #define RV3028_STATUS_UF		BIT(4)
51e6e7376cSAlexandre Belloni #define RV3028_STATUS_BSF		BIT(5)
52e6e7376cSAlexandre Belloni #define RV3028_STATUS_CLKF		BIT(6)
53e6e7376cSAlexandre Belloni #define RV3028_STATUS_EEBUSY		BIT(7)
54e6e7376cSAlexandre Belloni 
55e6e7376cSAlexandre Belloni #define RV3028_CTRL1_EERD		BIT(3)
56e6e7376cSAlexandre Belloni #define RV3028_CTRL1_WADA		BIT(5)
57e6e7376cSAlexandre Belloni 
58e6e7376cSAlexandre Belloni #define RV3028_CTRL2_RESET		BIT(0)
59e6e7376cSAlexandre Belloni #define RV3028_CTRL2_12_24		BIT(1)
60e6e7376cSAlexandre Belloni #define RV3028_CTRL2_EIE		BIT(2)
61e6e7376cSAlexandre Belloni #define RV3028_CTRL2_AIE		BIT(3)
62e6e7376cSAlexandre Belloni #define RV3028_CTRL2_TIE		BIT(4)
63e6e7376cSAlexandre Belloni #define RV3028_CTRL2_UIE		BIT(5)
64e6e7376cSAlexandre Belloni #define RV3028_CTRL2_TSE		BIT(7)
65e6e7376cSAlexandre Belloni 
66e6e7376cSAlexandre Belloni #define RV3028_EVT_CTRL_TSR		BIT(2)
67e6e7376cSAlexandre Belloni 
68e6e7376cSAlexandre Belloni #define RV3028_EEPROM_CMD_WRITE		0x21
69e6e7376cSAlexandre Belloni #define RV3028_EEPROM_CMD_READ		0x22
70e6e7376cSAlexandre Belloni 
71e6e7376cSAlexandre Belloni #define RV3028_EEBUSY_POLL		10000
72e6e7376cSAlexandre Belloni #define RV3028_EEBUSY_TIMEOUT		100000
73e6e7376cSAlexandre Belloni 
74e6e7376cSAlexandre Belloni #define RV3028_BACKUP_TCE		BIT(5)
75e6e7376cSAlexandre Belloni #define RV3028_BACKUP_TCR_MASK		GENMASK(1,0)
76e6e7376cSAlexandre Belloni 
77e6e7376cSAlexandre Belloni #define OFFSET_STEP_PPT			953674
78e6e7376cSAlexandre Belloni 
79e6e7376cSAlexandre Belloni enum rv3028_type {
80e6e7376cSAlexandre Belloni 	rv_3028,
81e6e7376cSAlexandre Belloni };
82e6e7376cSAlexandre Belloni 
83e6e7376cSAlexandre Belloni struct rv3028_data {
84e6e7376cSAlexandre Belloni 	struct regmap *regmap;
85e6e7376cSAlexandre Belloni 	struct rtc_device *rtc;
86e6e7376cSAlexandre Belloni 	enum rv3028_type type;
87e6e7376cSAlexandre Belloni };
88e6e7376cSAlexandre Belloni 
89e6e7376cSAlexandre Belloni static u16 rv3028_trickle_resistors[] = {1000, 3000, 6000, 11000};
90e6e7376cSAlexandre Belloni 
91e6e7376cSAlexandre Belloni static ssize_t timestamp0_store(struct device *dev,
92e6e7376cSAlexandre Belloni 				struct device_attribute *attr,
93e6e7376cSAlexandre Belloni 				const char *buf, size_t count)
94e6e7376cSAlexandre Belloni {
95e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
96e6e7376cSAlexandre Belloni 
97e6e7376cSAlexandre Belloni 	regmap_update_bits(rv3028->regmap, RV3028_EVT_CTRL, RV3028_EVT_CTRL_TSR,
98e6e7376cSAlexandre Belloni 			   RV3028_EVT_CTRL_TSR);
99e6e7376cSAlexandre Belloni 
100e6e7376cSAlexandre Belloni 	return count;
101e6e7376cSAlexandre Belloni };
102e6e7376cSAlexandre Belloni 
103e6e7376cSAlexandre Belloni static ssize_t timestamp0_show(struct device *dev,
104e6e7376cSAlexandre Belloni 			       struct device_attribute *attr, char *buf)
105e6e7376cSAlexandre Belloni {
106e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
107e6e7376cSAlexandre Belloni 	struct rtc_time tm;
108e6e7376cSAlexandre Belloni 	int ret, count;
109e6e7376cSAlexandre Belloni 	u8 date[6];
110e6e7376cSAlexandre Belloni 
111e6e7376cSAlexandre Belloni 	ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
112e6e7376cSAlexandre Belloni 	if (ret)
113e6e7376cSAlexandre Belloni 		return ret;
114e6e7376cSAlexandre Belloni 
115e6e7376cSAlexandre Belloni 	if (!count)
116e6e7376cSAlexandre Belloni 		return 0;
117e6e7376cSAlexandre Belloni 
118e6e7376cSAlexandre Belloni 	ret = regmap_bulk_read(rv3028->regmap, RV3028_TS_SEC, date,
119e6e7376cSAlexandre Belloni 			       sizeof(date));
120e6e7376cSAlexandre Belloni 	if (ret)
121e6e7376cSAlexandre Belloni 		return ret;
122e6e7376cSAlexandre Belloni 
123e6e7376cSAlexandre Belloni 	tm.tm_sec = bcd2bin(date[0]);
124e6e7376cSAlexandre Belloni 	tm.tm_min = bcd2bin(date[1]);
125e6e7376cSAlexandre Belloni 	tm.tm_hour = bcd2bin(date[2]);
126e6e7376cSAlexandre Belloni 	tm.tm_mday = bcd2bin(date[3]);
127e6e7376cSAlexandre Belloni 	tm.tm_mon = bcd2bin(date[4]) - 1;
128e6e7376cSAlexandre Belloni 	tm.tm_year = bcd2bin(date[5]) + 100;
129e6e7376cSAlexandre Belloni 
130e6e7376cSAlexandre Belloni 	ret = rtc_valid_tm(&tm);
131e6e7376cSAlexandre Belloni 	if (ret)
132e6e7376cSAlexandre Belloni 		return ret;
133e6e7376cSAlexandre Belloni 
134e6e7376cSAlexandre Belloni 	return sprintf(buf, "%llu\n",
135e6e7376cSAlexandre Belloni 		       (unsigned long long)rtc_tm_to_time64(&tm));
136e6e7376cSAlexandre Belloni };
137e6e7376cSAlexandre Belloni 
138e6e7376cSAlexandre Belloni static DEVICE_ATTR_RW(timestamp0);
139e6e7376cSAlexandre Belloni 
140e6e7376cSAlexandre Belloni static ssize_t timestamp0_count_show(struct device *dev,
141e6e7376cSAlexandre Belloni 				     struct device_attribute *attr, char *buf)
142e6e7376cSAlexandre Belloni {
143e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
144e6e7376cSAlexandre Belloni 	int ret, count;
145e6e7376cSAlexandre Belloni 
146e6e7376cSAlexandre Belloni 	ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
147e6e7376cSAlexandre Belloni 	if (ret)
148e6e7376cSAlexandre Belloni 		return ret;
149e6e7376cSAlexandre Belloni 
150e6e7376cSAlexandre Belloni 	return sprintf(buf, "%u\n", count);
151e6e7376cSAlexandre Belloni };
152e6e7376cSAlexandre Belloni 
153e6e7376cSAlexandre Belloni static DEVICE_ATTR_RO(timestamp0_count);
154e6e7376cSAlexandre Belloni 
155e6e7376cSAlexandre Belloni static struct attribute *rv3028_attrs[] = {
156e6e7376cSAlexandre Belloni 	&dev_attr_timestamp0.attr,
157e6e7376cSAlexandre Belloni 	&dev_attr_timestamp0_count.attr,
158e6e7376cSAlexandre Belloni 	NULL
159e6e7376cSAlexandre Belloni };
160e6e7376cSAlexandre Belloni 
161e6e7376cSAlexandre Belloni static const struct attribute_group rv3028_attr_group = {
162e6e7376cSAlexandre Belloni 	.attrs	= rv3028_attrs,
163e6e7376cSAlexandre Belloni };
164e6e7376cSAlexandre Belloni 
165e6e7376cSAlexandre Belloni static irqreturn_t rv3028_handle_irq(int irq, void *dev_id)
166e6e7376cSAlexandre Belloni {
167e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_id;
168e6e7376cSAlexandre Belloni 	unsigned long events = 0;
169e6e7376cSAlexandre Belloni 	u32 status = 0, ctrl = 0;
170e6e7376cSAlexandre Belloni 
171e6e7376cSAlexandre Belloni 	if (regmap_read(rv3028->regmap, RV3028_STATUS, &status) < 0 ||
172e6e7376cSAlexandre Belloni 	   status == 0) {
173e6e7376cSAlexandre Belloni 		return IRQ_NONE;
174e6e7376cSAlexandre Belloni 	}
175e6e7376cSAlexandre Belloni 
176e6e7376cSAlexandre Belloni 	if (status & RV3028_STATUS_PORF)
177e6e7376cSAlexandre Belloni 		dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
178e6e7376cSAlexandre Belloni 
179e6e7376cSAlexandre Belloni 	if (status & RV3028_STATUS_TF) {
180e6e7376cSAlexandre Belloni 		status |= RV3028_STATUS_TF;
181e6e7376cSAlexandre Belloni 		ctrl |= RV3028_CTRL2_TIE;
182e6e7376cSAlexandre Belloni 		events |= RTC_PF;
183e6e7376cSAlexandre Belloni 	}
184e6e7376cSAlexandre Belloni 
185e6e7376cSAlexandre Belloni 	if (status & RV3028_STATUS_AF) {
186e6e7376cSAlexandre Belloni 		status |= RV3028_STATUS_AF;
187e6e7376cSAlexandre Belloni 		ctrl |= RV3028_CTRL2_AIE;
188e6e7376cSAlexandre Belloni 		events |= RTC_AF;
189e6e7376cSAlexandre Belloni 	}
190e6e7376cSAlexandre Belloni 
191e6e7376cSAlexandre Belloni 	if (status & RV3028_STATUS_UF) {
192e6e7376cSAlexandre Belloni 		status |= RV3028_STATUS_UF;
193e6e7376cSAlexandre Belloni 		ctrl |= RV3028_CTRL2_UIE;
194e6e7376cSAlexandre Belloni 		events |= RTC_UF;
195e6e7376cSAlexandre Belloni 	}
196e6e7376cSAlexandre Belloni 
197e6e7376cSAlexandre Belloni 	if (events) {
198e6e7376cSAlexandre Belloni 		rtc_update_irq(rv3028->rtc, 1, events);
199e6e7376cSAlexandre Belloni 		regmap_update_bits(rv3028->regmap, RV3028_STATUS, status, 0);
200e6e7376cSAlexandre Belloni 		regmap_update_bits(rv3028->regmap, RV3028_CTRL2, ctrl, 0);
201e6e7376cSAlexandre Belloni 	}
202e6e7376cSAlexandre Belloni 
203e6e7376cSAlexandre Belloni 	if (status & RV3028_STATUS_EVF) {
204e6e7376cSAlexandre Belloni 		sysfs_notify(&rv3028->rtc->dev.kobj, NULL,
205e6e7376cSAlexandre Belloni 			     dev_attr_timestamp0.attr.name);
206e6e7376cSAlexandre Belloni 		dev_warn(&rv3028->rtc->dev, "event detected");
207e6e7376cSAlexandre Belloni 	}
208e6e7376cSAlexandre Belloni 
209e6e7376cSAlexandre Belloni 	return IRQ_HANDLED;
210e6e7376cSAlexandre Belloni }
211e6e7376cSAlexandre Belloni 
212e6e7376cSAlexandre Belloni static int rv3028_get_time(struct device *dev, struct rtc_time *tm)
213e6e7376cSAlexandre Belloni {
214e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
215e6e7376cSAlexandre Belloni 	u8 date[7];
216e6e7376cSAlexandre Belloni 	int ret, status;
217e6e7376cSAlexandre Belloni 
218e6e7376cSAlexandre Belloni 	ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
219e6e7376cSAlexandre Belloni 	if (ret < 0)
220e6e7376cSAlexandre Belloni 		return ret;
221e6e7376cSAlexandre Belloni 
222e6e7376cSAlexandre Belloni 	if (status & RV3028_STATUS_PORF) {
223e6e7376cSAlexandre Belloni 		dev_warn(dev, "Voltage low, data is invalid.\n");
224e6e7376cSAlexandre Belloni 		return -EINVAL;
225e6e7376cSAlexandre Belloni 	}
226e6e7376cSAlexandre Belloni 
227e6e7376cSAlexandre Belloni 	ret = regmap_bulk_read(rv3028->regmap, RV3028_SEC, date, sizeof(date));
228e6e7376cSAlexandre Belloni 	if (ret)
229e6e7376cSAlexandre Belloni 		return ret;
230e6e7376cSAlexandre Belloni 
231e6e7376cSAlexandre Belloni 	tm->tm_sec  = bcd2bin(date[RV3028_SEC] & 0x7f);
232e6e7376cSAlexandre Belloni 	tm->tm_min  = bcd2bin(date[RV3028_MIN] & 0x7f);
233e6e7376cSAlexandre Belloni 	tm->tm_hour = bcd2bin(date[RV3028_HOUR] & 0x3f);
234e6e7376cSAlexandre Belloni 	tm->tm_wday = ilog2(date[RV3028_WDAY] & 0x7f);
235e6e7376cSAlexandre Belloni 	tm->tm_mday = bcd2bin(date[RV3028_DAY] & 0x3f);
236e6e7376cSAlexandre Belloni 	tm->tm_mon  = bcd2bin(date[RV3028_MONTH] & 0x1f) - 1;
237e6e7376cSAlexandre Belloni 	tm->tm_year = bcd2bin(date[RV3028_YEAR]) + 100;
238e6e7376cSAlexandre Belloni 
239e6e7376cSAlexandre Belloni 	return 0;
240e6e7376cSAlexandre Belloni }
241e6e7376cSAlexandre Belloni 
242e6e7376cSAlexandre Belloni static int rv3028_set_time(struct device *dev, struct rtc_time *tm)
243e6e7376cSAlexandre Belloni {
244e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
245e6e7376cSAlexandre Belloni 	u8 date[7];
246e6e7376cSAlexandre Belloni 	int ret;
247e6e7376cSAlexandre Belloni 
248e6e7376cSAlexandre Belloni 	date[RV3028_SEC]   = bin2bcd(tm->tm_sec);
249e6e7376cSAlexandre Belloni 	date[RV3028_MIN]   = bin2bcd(tm->tm_min);
250e6e7376cSAlexandre Belloni 	date[RV3028_HOUR]  = bin2bcd(tm->tm_hour);
251e6e7376cSAlexandre Belloni 	date[RV3028_WDAY]  = 1 << (tm->tm_wday);
252e6e7376cSAlexandre Belloni 	date[RV3028_DAY]   = bin2bcd(tm->tm_mday);
253e6e7376cSAlexandre Belloni 	date[RV3028_MONTH] = bin2bcd(tm->tm_mon + 1);
254e6e7376cSAlexandre Belloni 	date[RV3028_YEAR]  = bin2bcd(tm->tm_year - 100);
255e6e7376cSAlexandre Belloni 
256e6e7376cSAlexandre Belloni 	/*
257e6e7376cSAlexandre Belloni 	 * Writing to the Seconds register has the same effect as setting RESET
258e6e7376cSAlexandre Belloni 	 * bit to 1
259e6e7376cSAlexandre Belloni 	 */
260e6e7376cSAlexandre Belloni 	ret = regmap_bulk_write(rv3028->regmap, RV3028_SEC, date,
261e6e7376cSAlexandre Belloni 				sizeof(date));
262e6e7376cSAlexandre Belloni 	if (ret)
263e6e7376cSAlexandre Belloni 		return ret;
264e6e7376cSAlexandre Belloni 
265e6e7376cSAlexandre Belloni 	ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
266e6e7376cSAlexandre Belloni 				 RV3028_STATUS_PORF, 0);
267e6e7376cSAlexandre Belloni 
268e6e7376cSAlexandre Belloni 	return ret;
269e6e7376cSAlexandre Belloni }
270e6e7376cSAlexandre Belloni 
271e6e7376cSAlexandre Belloni static int rv3028_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
272e6e7376cSAlexandre Belloni {
273e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
274e6e7376cSAlexandre Belloni 	u8 alarmvals[3];
275e6e7376cSAlexandre Belloni 	int status, ctrl, ret;
276e6e7376cSAlexandre Belloni 
277e6e7376cSAlexandre Belloni 	ret = regmap_bulk_read(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
278e6e7376cSAlexandre Belloni 			       sizeof(alarmvals));
279e6e7376cSAlexandre Belloni 	if (ret)
280e6e7376cSAlexandre Belloni 		return ret;
281e6e7376cSAlexandre Belloni 
282e6e7376cSAlexandre Belloni 	ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
283e6e7376cSAlexandre Belloni 	if (ret < 0)
284e6e7376cSAlexandre Belloni 		return ret;
285e6e7376cSAlexandre Belloni 
286e6e7376cSAlexandre Belloni 	ret = regmap_read(rv3028->regmap, RV3028_CTRL2, &ctrl);
287e6e7376cSAlexandre Belloni 	if (ret < 0)
288e6e7376cSAlexandre Belloni 		return ret;
289e6e7376cSAlexandre Belloni 
290e6e7376cSAlexandre Belloni 	alrm->time.tm_sec  = 0;
291e6e7376cSAlexandre Belloni 	alrm->time.tm_min  = bcd2bin(alarmvals[0] & 0x7f);
292e6e7376cSAlexandre Belloni 	alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
293e6e7376cSAlexandre Belloni 	alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
294e6e7376cSAlexandre Belloni 
295e6e7376cSAlexandre Belloni 	alrm->enabled = !!(ctrl & RV3028_CTRL2_AIE);
296e6e7376cSAlexandre Belloni 	alrm->pending = (status & RV3028_STATUS_AF) && alrm->enabled;
297e6e7376cSAlexandre Belloni 
298e6e7376cSAlexandre Belloni 	return 0;
299e6e7376cSAlexandre Belloni }
300e6e7376cSAlexandre Belloni 
301e6e7376cSAlexandre Belloni static int rv3028_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
302e6e7376cSAlexandre Belloni {
303e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
304e6e7376cSAlexandre Belloni 	u8 alarmvals[3];
305e6e7376cSAlexandre Belloni 	u8 ctrl = 0;
306e6e7376cSAlexandre Belloni 	int ret;
307e6e7376cSAlexandre Belloni 
308e6e7376cSAlexandre Belloni 	/* The alarm has no seconds, round up to nearest minute */
309e6e7376cSAlexandre Belloni 	if (alrm->time.tm_sec) {
310e6e7376cSAlexandre Belloni 		time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
311e6e7376cSAlexandre Belloni 
312e6e7376cSAlexandre Belloni 		alarm_time += 60 - alrm->time.tm_sec;
313e6e7376cSAlexandre Belloni 		rtc_time64_to_tm(alarm_time, &alrm->time);
314e6e7376cSAlexandre Belloni 	}
315e6e7376cSAlexandre Belloni 
316e6e7376cSAlexandre Belloni 	ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
317e6e7376cSAlexandre Belloni 				 RV3028_CTRL2_AIE | RV3028_CTRL2_UIE, 0);
318e6e7376cSAlexandre Belloni 	if (ret)
319e6e7376cSAlexandre Belloni 		return ret;
320e6e7376cSAlexandre Belloni 
321e6e7376cSAlexandre Belloni 	alarmvals[0] = bin2bcd(alrm->time.tm_min);
322e6e7376cSAlexandre Belloni 	alarmvals[1] = bin2bcd(alrm->time.tm_hour);
323e6e7376cSAlexandre Belloni 	alarmvals[2] = bin2bcd(alrm->time.tm_mday);
324e6e7376cSAlexandre Belloni 
325e6e7376cSAlexandre Belloni 	ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
326e6e7376cSAlexandre Belloni 				 RV3028_STATUS_AF, 0);
327e6e7376cSAlexandre Belloni 	if (ret)
328e6e7376cSAlexandre Belloni 		return ret;
329e6e7376cSAlexandre Belloni 
330e6e7376cSAlexandre Belloni 	ret = regmap_bulk_write(rv3028->regmap, RV3028_ALARM_MIN, alarmvals,
331e6e7376cSAlexandre Belloni 				sizeof(alarmvals));
332e6e7376cSAlexandre Belloni 	if (ret)
333e6e7376cSAlexandre Belloni 		return ret;
334e6e7376cSAlexandre Belloni 
335e6e7376cSAlexandre Belloni 	if (alrm->enabled) {
336e6e7376cSAlexandre Belloni 		if (rv3028->rtc->uie_rtctimer.enabled)
337e6e7376cSAlexandre Belloni 			ctrl |= RV3028_CTRL2_UIE;
338e6e7376cSAlexandre Belloni 		if (rv3028->rtc->aie_timer.enabled)
339e6e7376cSAlexandre Belloni 			ctrl |= RV3028_CTRL2_AIE;
340e6e7376cSAlexandre Belloni 	}
341e6e7376cSAlexandre Belloni 
342e6e7376cSAlexandre Belloni 	ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
343e6e7376cSAlexandre Belloni 				 RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
344e6e7376cSAlexandre Belloni 
345e6e7376cSAlexandre Belloni 	return ret;
346e6e7376cSAlexandre Belloni }
347e6e7376cSAlexandre Belloni 
348e6e7376cSAlexandre Belloni static int rv3028_alarm_irq_enable(struct device *dev, unsigned int enabled)
349e6e7376cSAlexandre Belloni {
350e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
351e6e7376cSAlexandre Belloni 	int ctrl = 0, ret;
352e6e7376cSAlexandre Belloni 
353e6e7376cSAlexandre Belloni 	if (enabled) {
354e6e7376cSAlexandre Belloni 		if (rv3028->rtc->uie_rtctimer.enabled)
355e6e7376cSAlexandre Belloni 			ctrl |= RV3028_CTRL2_UIE;
356e6e7376cSAlexandre Belloni 		if (rv3028->rtc->aie_timer.enabled)
357e6e7376cSAlexandre Belloni 			ctrl |= RV3028_CTRL2_AIE;
358e6e7376cSAlexandre Belloni 	}
359e6e7376cSAlexandre Belloni 
360e6e7376cSAlexandre Belloni 	ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
361e6e7376cSAlexandre Belloni 				 RV3028_STATUS_AF | RV3028_STATUS_UF, 0);
362e6e7376cSAlexandre Belloni 	if (ret)
363e6e7376cSAlexandre Belloni 		return ret;
364e6e7376cSAlexandre Belloni 
365e6e7376cSAlexandre Belloni 	ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
366e6e7376cSAlexandre Belloni 				 RV3028_CTRL2_UIE | RV3028_CTRL2_AIE, ctrl);
367e6e7376cSAlexandre Belloni 	if (ret)
368e6e7376cSAlexandre Belloni 		return ret;
369e6e7376cSAlexandre Belloni 
370e6e7376cSAlexandre Belloni 	return 0;
371e6e7376cSAlexandre Belloni }
372e6e7376cSAlexandre Belloni 
373e6e7376cSAlexandre Belloni static int rv3028_read_offset(struct device *dev, long *offset)
374e6e7376cSAlexandre Belloni {
375e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
376e6e7376cSAlexandre Belloni 	int ret, value, steps;
377e6e7376cSAlexandre Belloni 
378e6e7376cSAlexandre Belloni 	ret = regmap_read(rv3028->regmap, RV3028_OFFSET, &value);
379e6e7376cSAlexandre Belloni 	if (ret < 0)
380e6e7376cSAlexandre Belloni 		return ret;
381e6e7376cSAlexandre Belloni 
382e6e7376cSAlexandre Belloni 	steps = sign_extend32(value << 1, 8);
383e6e7376cSAlexandre Belloni 
384e6e7376cSAlexandre Belloni 	ret = regmap_read(rv3028->regmap, RV3028_BACKUP, &value);
385e6e7376cSAlexandre Belloni 	if (ret < 0)
386e6e7376cSAlexandre Belloni 		return ret;
387e6e7376cSAlexandre Belloni 
388e6e7376cSAlexandre Belloni 	steps += value >> 7;
389e6e7376cSAlexandre Belloni 
390e6e7376cSAlexandre Belloni 	*offset = DIV_ROUND_CLOSEST(steps * OFFSET_STEP_PPT, 1000);
391e6e7376cSAlexandre Belloni 
392e6e7376cSAlexandre Belloni 	return 0;
393e6e7376cSAlexandre Belloni }
394e6e7376cSAlexandre Belloni 
395e6e7376cSAlexandre Belloni static int rv3028_set_offset(struct device *dev, long offset)
396e6e7376cSAlexandre Belloni {
397e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
398e6e7376cSAlexandre Belloni 	int ret;
399e6e7376cSAlexandre Belloni 
400e6e7376cSAlexandre Belloni 	offset = clamp(offset, -244141L, 243187L) * 1000;
401e6e7376cSAlexandre Belloni 	offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT);
402e6e7376cSAlexandre Belloni 
403e6e7376cSAlexandre Belloni 	ret = regmap_write(rv3028->regmap, RV3028_OFFSET, offset >> 1);
404e6e7376cSAlexandre Belloni 	if (ret < 0)
405e6e7376cSAlexandre Belloni 		return ret;
406e6e7376cSAlexandre Belloni 
407e6e7376cSAlexandre Belloni 	return regmap_update_bits(rv3028->regmap, RV3028_BACKUP, BIT(7),
408e6e7376cSAlexandre Belloni 				  offset << 7);
409e6e7376cSAlexandre Belloni }
410e6e7376cSAlexandre Belloni 
411e6e7376cSAlexandre Belloni static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
412e6e7376cSAlexandre Belloni {
413e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028 = dev_get_drvdata(dev);
414e6e7376cSAlexandre Belloni 	int status, ret = 0;
415e6e7376cSAlexandre Belloni 
416e6e7376cSAlexandre Belloni 	switch (cmd) {
417e6e7376cSAlexandre Belloni 	case RTC_VL_READ:
418e6e7376cSAlexandre Belloni 		ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
419e6e7376cSAlexandre Belloni 		if (ret < 0)
420e6e7376cSAlexandre Belloni 			return ret;
421e6e7376cSAlexandre Belloni 
422e6e7376cSAlexandre Belloni 		if (status & RV3028_STATUS_PORF)
423e6e7376cSAlexandre Belloni 			dev_warn(&rv3028->rtc->dev, "Voltage low, data loss detected.\n");
424e6e7376cSAlexandre Belloni 
425e6e7376cSAlexandre Belloni 		status &= RV3028_STATUS_PORF;
426e6e7376cSAlexandre Belloni 
427e6e7376cSAlexandre Belloni 		if (copy_to_user((void __user *)arg, &status, sizeof(int)))
428e6e7376cSAlexandre Belloni 			return -EFAULT;
429e6e7376cSAlexandre Belloni 
430e6e7376cSAlexandre Belloni 		return 0;
431e6e7376cSAlexandre Belloni 
432e6e7376cSAlexandre Belloni 	case RTC_VL_CLR:
433e6e7376cSAlexandre Belloni 		ret = regmap_update_bits(rv3028->regmap, RV3028_STATUS,
434e6e7376cSAlexandre Belloni 					 RV3028_STATUS_PORF, 0);
435e6e7376cSAlexandre Belloni 
436e6e7376cSAlexandre Belloni 		return ret;
437e6e7376cSAlexandre Belloni 
438e6e7376cSAlexandre Belloni 	default:
439e6e7376cSAlexandre Belloni 		return -ENOIOCTLCMD;
440e6e7376cSAlexandre Belloni 	}
441e6e7376cSAlexandre Belloni }
442e6e7376cSAlexandre Belloni 
443e6e7376cSAlexandre Belloni static int rv3028_nvram_write(void *priv, unsigned int offset, void *val,
444e6e7376cSAlexandre Belloni 			      size_t bytes)
445e6e7376cSAlexandre Belloni {
446e6e7376cSAlexandre Belloni 	return regmap_bulk_write(priv, RV3028_RAM1 + offset, val, bytes);
447e6e7376cSAlexandre Belloni }
448e6e7376cSAlexandre Belloni 
449e6e7376cSAlexandre Belloni static int rv3028_nvram_read(void *priv, unsigned int offset, void *val,
450e6e7376cSAlexandre Belloni 			     size_t bytes)
451e6e7376cSAlexandre Belloni {
452e6e7376cSAlexandre Belloni 	return regmap_bulk_read(priv, RV3028_RAM1 + offset, val, bytes);
453e6e7376cSAlexandre Belloni }
454e6e7376cSAlexandre Belloni 
455e6e7376cSAlexandre Belloni static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
456e6e7376cSAlexandre Belloni 			       size_t bytes)
457e6e7376cSAlexandre Belloni {
458e6e7376cSAlexandre Belloni 	u32 status, ctrl1;
459e6e7376cSAlexandre Belloni 	int i, ret, err;
460e6e7376cSAlexandre Belloni 	u8 *buf = val;
461e6e7376cSAlexandre Belloni 
462e6e7376cSAlexandre Belloni 	ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
463e6e7376cSAlexandre Belloni 	if (ret)
464e6e7376cSAlexandre Belloni 		return ret;
465e6e7376cSAlexandre Belloni 
466e6e7376cSAlexandre Belloni 	if (!(ctrl1 & RV3028_CTRL1_EERD)) {
467e6e7376cSAlexandre Belloni 		ret = regmap_update_bits(priv, RV3028_CTRL1,
468e6e7376cSAlexandre Belloni 					 RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
469e6e7376cSAlexandre Belloni 		if (ret)
470e6e7376cSAlexandre Belloni 			return ret;
471e6e7376cSAlexandre Belloni 
472e6e7376cSAlexandre Belloni 		ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
473e6e7376cSAlexandre Belloni 					       !(status & RV3028_STATUS_EEBUSY),
474e6e7376cSAlexandre Belloni 					       RV3028_EEBUSY_POLL,
475e6e7376cSAlexandre Belloni 					       RV3028_EEBUSY_TIMEOUT);
476e6e7376cSAlexandre Belloni 		if (ret)
477e6e7376cSAlexandre Belloni 			goto restore_eerd;
478e6e7376cSAlexandre Belloni 	}
479e6e7376cSAlexandre Belloni 
480e6e7376cSAlexandre Belloni 	for (i = 0; i < bytes; i++) {
481e6e7376cSAlexandre Belloni 		ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
482e6e7376cSAlexandre Belloni 		if (ret)
483e6e7376cSAlexandre Belloni 			goto restore_eerd;
484e6e7376cSAlexandre Belloni 
485e6e7376cSAlexandre Belloni 		ret = regmap_write(priv, RV3028_EEPROM_DATA, buf[i]);
486e6e7376cSAlexandre Belloni 		if (ret)
487e6e7376cSAlexandre Belloni 			goto restore_eerd;
488e6e7376cSAlexandre Belloni 
489e6e7376cSAlexandre Belloni 		ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
490e6e7376cSAlexandre Belloni 		if (ret)
491e6e7376cSAlexandre Belloni 			goto restore_eerd;
492e6e7376cSAlexandre Belloni 
493e6e7376cSAlexandre Belloni 		ret = regmap_write(priv, RV3028_EEPROM_CMD,
494e6e7376cSAlexandre Belloni 				   RV3028_EEPROM_CMD_WRITE);
495e6e7376cSAlexandre Belloni 		if (ret)
496e6e7376cSAlexandre Belloni 			goto restore_eerd;
497e6e7376cSAlexandre Belloni 
498e6e7376cSAlexandre Belloni 		usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
499e6e7376cSAlexandre Belloni 
500e6e7376cSAlexandre Belloni 		ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
501e6e7376cSAlexandre Belloni 					       !(status & RV3028_STATUS_EEBUSY),
502e6e7376cSAlexandre Belloni 					       RV3028_EEBUSY_POLL,
503e6e7376cSAlexandre Belloni 					       RV3028_EEBUSY_TIMEOUT);
504e6e7376cSAlexandre Belloni 		if (ret)
505e6e7376cSAlexandre Belloni 			goto restore_eerd;
506e6e7376cSAlexandre Belloni 	}
507e6e7376cSAlexandre Belloni 
508e6e7376cSAlexandre Belloni restore_eerd:
509e6e7376cSAlexandre Belloni 	if (!(ctrl1 & RV3028_CTRL1_EERD))
510e6e7376cSAlexandre Belloni 	{
511e6e7376cSAlexandre Belloni 		err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
512e6e7376cSAlexandre Belloni 					 0);
513e6e7376cSAlexandre Belloni 		if (err && !ret)
514e6e7376cSAlexandre Belloni 			ret = err;
515e6e7376cSAlexandre Belloni 	}
516e6e7376cSAlexandre Belloni 
517e6e7376cSAlexandre Belloni 	return ret;
518e6e7376cSAlexandre Belloni }
519e6e7376cSAlexandre Belloni 
520e6e7376cSAlexandre Belloni static int rv3028_eeprom_read(void *priv, unsigned int offset, void *val,
521e6e7376cSAlexandre Belloni 			      size_t bytes)
522e6e7376cSAlexandre Belloni {
523e6e7376cSAlexandre Belloni 	u32 status, ctrl1, data;
524e6e7376cSAlexandre Belloni 	int i, ret, err;
525e6e7376cSAlexandre Belloni 	u8 *buf = val;
526e6e7376cSAlexandre Belloni 
527e6e7376cSAlexandre Belloni 	ret = regmap_read(priv, RV3028_CTRL1, &ctrl1);
528e6e7376cSAlexandre Belloni 	if (ret)
529e6e7376cSAlexandre Belloni 		return ret;
530e6e7376cSAlexandre Belloni 
531e6e7376cSAlexandre Belloni 	if (!(ctrl1 & RV3028_CTRL1_EERD)) {
532e6e7376cSAlexandre Belloni 		ret = regmap_update_bits(priv, RV3028_CTRL1,
533e6e7376cSAlexandre Belloni 					 RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
534e6e7376cSAlexandre Belloni 		if (ret)
535e6e7376cSAlexandre Belloni 			return ret;
536e6e7376cSAlexandre Belloni 
537e6e7376cSAlexandre Belloni 		ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
538e6e7376cSAlexandre Belloni 					       !(status & RV3028_STATUS_EEBUSY),
539e6e7376cSAlexandre Belloni 					       RV3028_EEBUSY_POLL,
540e6e7376cSAlexandre Belloni 					       RV3028_EEBUSY_TIMEOUT);
541e6e7376cSAlexandre Belloni 		if (ret)
542e6e7376cSAlexandre Belloni 			goto restore_eerd;
543e6e7376cSAlexandre Belloni 	}
544e6e7376cSAlexandre Belloni 
545e6e7376cSAlexandre Belloni 	for (i = 0; i < bytes; i++) {
546e6e7376cSAlexandre Belloni 		ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i);
547e6e7376cSAlexandre Belloni 		if (ret)
548e6e7376cSAlexandre Belloni 			goto restore_eerd;
549e6e7376cSAlexandre Belloni 
550e6e7376cSAlexandre Belloni 		ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0);
551e6e7376cSAlexandre Belloni 		if (ret)
552e6e7376cSAlexandre Belloni 			goto restore_eerd;
553e6e7376cSAlexandre Belloni 
554e6e7376cSAlexandre Belloni 		ret = regmap_write(priv, RV3028_EEPROM_CMD,
555e6e7376cSAlexandre Belloni 				   RV3028_EEPROM_CMD_READ);
556e6e7376cSAlexandre Belloni 		if (ret)
557e6e7376cSAlexandre Belloni 			goto restore_eerd;
558e6e7376cSAlexandre Belloni 
559e6e7376cSAlexandre Belloni 		ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
560e6e7376cSAlexandre Belloni 					       !(status & RV3028_STATUS_EEBUSY),
561e6e7376cSAlexandre Belloni 					       RV3028_EEBUSY_POLL,
562e6e7376cSAlexandre Belloni 					       RV3028_EEBUSY_TIMEOUT);
563e6e7376cSAlexandre Belloni 		if (ret)
564e6e7376cSAlexandre Belloni 			goto restore_eerd;
565e6e7376cSAlexandre Belloni 
566e6e7376cSAlexandre Belloni 		ret = regmap_read(priv, RV3028_EEPROM_DATA, &data);
567e6e7376cSAlexandre Belloni 		if (ret)
568e6e7376cSAlexandre Belloni 			goto restore_eerd;
569e6e7376cSAlexandre Belloni 		buf[i] = data;
570e6e7376cSAlexandre Belloni 	}
571e6e7376cSAlexandre Belloni 
572e6e7376cSAlexandre Belloni restore_eerd:
573e6e7376cSAlexandre Belloni 	if (!(ctrl1 & RV3028_CTRL1_EERD))
574e6e7376cSAlexandre Belloni 	{
575e6e7376cSAlexandre Belloni 		err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
576e6e7376cSAlexandre Belloni 					 0);
577e6e7376cSAlexandre Belloni 		if (err && !ret)
578e6e7376cSAlexandre Belloni 			ret = err;
579e6e7376cSAlexandre Belloni 	}
580e6e7376cSAlexandre Belloni 
581e6e7376cSAlexandre Belloni 	return ret;
582e6e7376cSAlexandre Belloni }
583e6e7376cSAlexandre Belloni 
584e6e7376cSAlexandre Belloni static struct rtc_class_ops rv3028_rtc_ops = {
585e6e7376cSAlexandre Belloni 	.read_time = rv3028_get_time,
586e6e7376cSAlexandre Belloni 	.set_time = rv3028_set_time,
587e6e7376cSAlexandre Belloni 	.read_offset = rv3028_read_offset,
588e6e7376cSAlexandre Belloni 	.set_offset = rv3028_set_offset,
589e6e7376cSAlexandre Belloni 	.ioctl = rv3028_ioctl,
590e6e7376cSAlexandre Belloni };
591e6e7376cSAlexandre Belloni 
592e6e7376cSAlexandre Belloni static const struct regmap_config regmap_config = {
593e6e7376cSAlexandre Belloni         .reg_bits = 8,
594e6e7376cSAlexandre Belloni         .val_bits = 8,
595e6e7376cSAlexandre Belloni         .max_register = 0x37,
596e6e7376cSAlexandre Belloni };
597e6e7376cSAlexandre Belloni 
598e6e7376cSAlexandre Belloni static int rv3028_probe(struct i2c_client *client)
599e6e7376cSAlexandre Belloni {
600e6e7376cSAlexandre Belloni 	struct rv3028_data *rv3028;
601e6e7376cSAlexandre Belloni 	int ret, status;
602e6e7376cSAlexandre Belloni 	u32 ohms;
603e6e7376cSAlexandre Belloni 	struct nvmem_config nvmem_cfg = {
604e6e7376cSAlexandre Belloni 		.name = "rv3028_nvram",
605e6e7376cSAlexandre Belloni 		.word_size = 1,
606e6e7376cSAlexandre Belloni 		.stride = 1,
607e6e7376cSAlexandre Belloni 		.size = 2,
608e6e7376cSAlexandre Belloni 		.type = NVMEM_TYPE_BATTERY_BACKED,
609e6e7376cSAlexandre Belloni 		.reg_read = rv3028_nvram_read,
610e6e7376cSAlexandre Belloni 		.reg_write = rv3028_nvram_write,
611e6e7376cSAlexandre Belloni 	};
612e6e7376cSAlexandre Belloni 	struct nvmem_config eeprom_cfg = {
613e6e7376cSAlexandre Belloni 		.name = "rv3028_eeprom",
614e6e7376cSAlexandre Belloni 		.word_size = 1,
615e6e7376cSAlexandre Belloni 		.stride = 1,
616e6e7376cSAlexandre Belloni 		.size = 43,
617e6e7376cSAlexandre Belloni 		.type = NVMEM_TYPE_EEPROM,
618e6e7376cSAlexandre Belloni 		.reg_read = rv3028_eeprom_read,
619e6e7376cSAlexandre Belloni 		.reg_write = rv3028_eeprom_write,
620e6e7376cSAlexandre Belloni 	};
621e6e7376cSAlexandre Belloni 
622e6e7376cSAlexandre Belloni 	rv3028 = devm_kzalloc(&client->dev, sizeof(struct rv3028_data),
623e6e7376cSAlexandre Belloni 			      GFP_KERNEL);
624e6e7376cSAlexandre Belloni 	if (!rv3028)
625e6e7376cSAlexandre Belloni 		return -ENOMEM;
626e6e7376cSAlexandre Belloni 
627e6e7376cSAlexandre Belloni 	rv3028->regmap = devm_regmap_init_i2c(client, &regmap_config);
628e6e7376cSAlexandre Belloni 
629e6e7376cSAlexandre Belloni 	i2c_set_clientdata(client, rv3028);
630e6e7376cSAlexandre Belloni 
631e6e7376cSAlexandre Belloni 	ret = regmap_read(rv3028->regmap, RV3028_STATUS, &status);
632e6e7376cSAlexandre Belloni 	if (ret < 0)
633e6e7376cSAlexandre Belloni 		return ret;
634e6e7376cSAlexandre Belloni 
635e6e7376cSAlexandre Belloni 	if (status & RV3028_STATUS_PORF)
636e6e7376cSAlexandre Belloni 		dev_warn(&client->dev, "Voltage low, data loss detected.\n");
637e6e7376cSAlexandre Belloni 
638e6e7376cSAlexandre Belloni 	if (status & RV3028_STATUS_AF)
639e6e7376cSAlexandre Belloni 		dev_warn(&client->dev, "An alarm may have been missed.\n");
640e6e7376cSAlexandre Belloni 
641e6e7376cSAlexandre Belloni 	rv3028->rtc = devm_rtc_allocate_device(&client->dev);
642*44c638ceSAlexandre Belloni 	if (IS_ERR(rv3028->rtc))
643e6e7376cSAlexandre Belloni 		return PTR_ERR(rv3028->rtc);
644e6e7376cSAlexandre Belloni 
645e6e7376cSAlexandre Belloni 	if (client->irq > 0) {
646e6e7376cSAlexandre Belloni 		ret = devm_request_threaded_irq(&client->dev, client->irq,
647e6e7376cSAlexandre Belloni 						NULL, rv3028_handle_irq,
648e6e7376cSAlexandre Belloni 						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
649e6e7376cSAlexandre Belloni 						"rv3028", rv3028);
650e6e7376cSAlexandre Belloni 		if (ret) {
651e6e7376cSAlexandre Belloni 			dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
652e6e7376cSAlexandre Belloni 			client->irq = 0;
653e6e7376cSAlexandre Belloni 		} else {
654e6e7376cSAlexandre Belloni 			rv3028_rtc_ops.read_alarm = rv3028_get_alarm;
655e6e7376cSAlexandre Belloni 			rv3028_rtc_ops.set_alarm = rv3028_set_alarm;
656e6e7376cSAlexandre Belloni 			rv3028_rtc_ops.alarm_irq_enable = rv3028_alarm_irq_enable;
657e6e7376cSAlexandre Belloni 		}
658e6e7376cSAlexandre Belloni 	}
659e6e7376cSAlexandre Belloni 
660e6e7376cSAlexandre Belloni 	ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1,
661e6e7376cSAlexandre Belloni 				 RV3028_CTRL1_WADA, RV3028_CTRL1_WADA);
662e6e7376cSAlexandre Belloni 	if (ret)
663e6e7376cSAlexandre Belloni 		return ret;
664e6e7376cSAlexandre Belloni 
665e6e7376cSAlexandre Belloni 	/* setup timestamping */
666e6e7376cSAlexandre Belloni 	ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL2,
667e6e7376cSAlexandre Belloni 				 RV3028_CTRL2_EIE | RV3028_CTRL2_TSE,
668e6e7376cSAlexandre Belloni 				 RV3028_CTRL2_EIE | RV3028_CTRL2_TSE);
669e6e7376cSAlexandre Belloni 	if (ret)
670e6e7376cSAlexandre Belloni 		return ret;
671e6e7376cSAlexandre Belloni 
672e6e7376cSAlexandre Belloni 	/* setup trickle charger */
673e6e7376cSAlexandre Belloni 	if (!device_property_read_u32(&client->dev, "trickle-resistor-ohms",
674e6e7376cSAlexandre Belloni 				      &ohms)) {
675e6e7376cSAlexandre Belloni 		int i;
676e6e7376cSAlexandre Belloni 
677e6e7376cSAlexandre Belloni 		for (i = 0; i < ARRAY_SIZE(rv3028_trickle_resistors); i++)
678e6e7376cSAlexandre Belloni 			if (ohms == rv3028_trickle_resistors[i])
679e6e7376cSAlexandre Belloni 				break;
680e6e7376cSAlexandre Belloni 
681e6e7376cSAlexandre Belloni 		if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
682e6e7376cSAlexandre Belloni 			ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP,
683e6e7376cSAlexandre Belloni 						 RV3028_BACKUP_TCE |
684e6e7376cSAlexandre Belloni 						 RV3028_BACKUP_TCR_MASK,
685e6e7376cSAlexandre Belloni 						 RV3028_BACKUP_TCE | i);
686e6e7376cSAlexandre Belloni 			if (ret)
687e6e7376cSAlexandre Belloni 				return ret;
688e6e7376cSAlexandre Belloni 		} else {
689e6e7376cSAlexandre Belloni 			dev_warn(&client->dev, "invalid trickle resistor value\n");
690e6e7376cSAlexandre Belloni 		}
691e6e7376cSAlexandre Belloni 	}
692e6e7376cSAlexandre Belloni 
693e6e7376cSAlexandre Belloni 	ret = rtc_add_group(rv3028->rtc, &rv3028_attr_group);
694e6e7376cSAlexandre Belloni 	if (ret)
695e6e7376cSAlexandre Belloni 		return ret;
696e6e7376cSAlexandre Belloni 
697e6e7376cSAlexandre Belloni 	rv3028->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
698e6e7376cSAlexandre Belloni 	rv3028->rtc->range_max = RTC_TIMESTAMP_END_2099;
699e6e7376cSAlexandre Belloni 	rv3028->rtc->ops = &rv3028_rtc_ops;
700e6e7376cSAlexandre Belloni 	ret = rtc_register_device(rv3028->rtc);
701e6e7376cSAlexandre Belloni 	if (ret)
702e6e7376cSAlexandre Belloni 		return ret;
703e6e7376cSAlexandre Belloni 
704e6e7376cSAlexandre Belloni 	nvmem_cfg.priv = rv3028->regmap;
705e6e7376cSAlexandre Belloni 	rtc_nvmem_register(rv3028->rtc, &nvmem_cfg);
706e6e7376cSAlexandre Belloni 	eeprom_cfg.priv = rv3028->regmap;
707e6e7376cSAlexandre Belloni 	rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
708e6e7376cSAlexandre Belloni 
709e6e7376cSAlexandre Belloni 	rv3028->rtc->max_user_freq = 1;
710e6e7376cSAlexandre Belloni 
711e6e7376cSAlexandre Belloni 	return 0;
712e6e7376cSAlexandre Belloni }
713e6e7376cSAlexandre Belloni 
714e6e7376cSAlexandre Belloni static const struct of_device_id rv3028_of_match[] = {
715e6e7376cSAlexandre Belloni 	{ .compatible = "microcrystal,rv3028", },
716e6e7376cSAlexandre Belloni 	{ }
717e6e7376cSAlexandre Belloni };
718e6e7376cSAlexandre Belloni MODULE_DEVICE_TABLE(of, rv3028_of_match);
719e6e7376cSAlexandre Belloni 
720e6e7376cSAlexandre Belloni static struct i2c_driver rv3028_driver = {
721e6e7376cSAlexandre Belloni 	.driver = {
722e6e7376cSAlexandre Belloni 		.name = "rtc-rv3028",
723e6e7376cSAlexandre Belloni 		.of_match_table = of_match_ptr(rv3028_of_match),
724e6e7376cSAlexandre Belloni 	},
725e6e7376cSAlexandre Belloni 	.probe_new	= rv3028_probe,
726e6e7376cSAlexandre Belloni };
727e6e7376cSAlexandre Belloni module_i2c_driver(rv3028_driver);
728e6e7376cSAlexandre Belloni 
729e6e7376cSAlexandre Belloni MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
730e6e7376cSAlexandre Belloni MODULE_DESCRIPTION("Micro Crystal RV3028 RTC driver");
731e6e7376cSAlexandre Belloni MODULE_LICENSE("GPL v2");
732