xref: /openbmc/linux/drivers/rtc/rtc-ab-eoz9.c (revision ecc23d0a422a3118fcf6e4f0a46e17a6c2047b02)
167075b63SArtem Panfilov // SPDX-License-Identifier: GPL-2.0
267075b63SArtem Panfilov /*
367075b63SArtem Panfilov  * Real Time Clock driver for AB-RTCMC-32.768kHz-EOZ9 chip.
467075b63SArtem Panfilov  * Copyright (C) 2019 Orolia
567075b63SArtem Panfilov  *
667075b63SArtem Panfilov  */
767075b63SArtem Panfilov 
867075b63SArtem Panfilov #include <linux/module.h>
967075b63SArtem Panfilov #include <linux/rtc.h>
1067075b63SArtem Panfilov #include <linux/i2c.h>
1167075b63SArtem Panfilov #include <linux/bcd.h>
1267075b63SArtem Panfilov #include <linux/of.h>
1367075b63SArtem Panfilov #include <linux/regmap.h>
14e70e52e1SLiam Beguin #include <linux/bitfield.h>
1567075b63SArtem Panfilov #include <linux/hwmon.h>
1667075b63SArtem Panfilov #include <linux/hwmon-sysfs.h>
1767075b63SArtem Panfilov 
1867075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1		0x00
1967075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_MASK		GENMASK(7, 0)
2067075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_WE		BIT(0)
2167075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_TE		BIT(1)
2267075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_TAR		BIT(2)
2367075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_EERE		BIT(3)
2467075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_SRON		BIT(4)
2567075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_TD0		BIT(5)
2667075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_TD1		BIT(6)
2767075b63SArtem Panfilov #define ABEOZ9_REG_CTRL1_CLKINT		BIT(7)
2867075b63SArtem Panfilov 
2967075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT		0x01
3067075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_AIE		BIT(0)
3167075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_TIE		BIT(1)
3267075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_V1IE	BIT(2)
3367075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_V2IE	BIT(3)
3467075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_SRIE	BIT(4)
3567075b63SArtem Panfilov 
3667075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_FLAG	0x02
3767075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_FLAG_AF	BIT(0)
3867075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_FLAG_TF	BIT(1)
3967075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_FLAG_V1IF	BIT(2)
4067075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_FLAG_V2IF	BIT(3)
4167075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_INT_FLAG_SRF	BIT(4)
4267075b63SArtem Panfilov 
4367075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_STATUS		0x03
4467075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_STATUS_V1F	BIT(2)
4567075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_STATUS_V2F	BIT(3)
4667075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_STATUS_SR	BIT(4)
4767075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_STATUS_PON	BIT(5)
4867075b63SArtem Panfilov #define ABEOZ9_REG_CTRL_STATUS_EEBUSY	BIT(7)
4967075b63SArtem Panfilov 
5067075b63SArtem Panfilov #define ABEOZ9_REG_SEC			0x08
5167075b63SArtem Panfilov #define ABEOZ9_REG_MIN			0x09
5267075b63SArtem Panfilov #define ABEOZ9_REG_HOURS		0x0A
5367075b63SArtem Panfilov #define ABEOZ9_HOURS_PM			BIT(6)
5467075b63SArtem Panfilov #define ABEOZ9_REG_DAYS			0x0B
5567075b63SArtem Panfilov #define ABEOZ9_REG_WEEKDAYS		0x0C
5667075b63SArtem Panfilov #define ABEOZ9_REG_MONTHS		0x0D
5767075b63SArtem Panfilov #define ABEOZ9_REG_YEARS		0x0E
5867075b63SArtem Panfilov 
5967075b63SArtem Panfilov #define ABEOZ9_SEC_LEN			7
6067075b63SArtem Panfilov 
61e70e52e1SLiam Beguin #define ABEOZ9_REG_ALARM_SEC		0x10
62e70e52e1SLiam Beguin #define ABEOZ9_BIT_ALARM_SEC		GENMASK(6, 0)
63e70e52e1SLiam Beguin #define ABEOZ9_REG_ALARM_MIN		0x11
64e70e52e1SLiam Beguin #define ABEOZ9_BIT_ALARM_MIN		GENMASK(6, 0)
65e70e52e1SLiam Beguin #define ABEOZ9_REG_ALARM_HOURS		0x12
66e70e52e1SLiam Beguin #define ABEOZ9_BIT_ALARM_HOURS_PM	BIT(5)
67e70e52e1SLiam Beguin #define ABEOZ9_BIT_ALARM_HOURS		GENMASK(4, 0)
68e70e52e1SLiam Beguin #define ABEOZ9_REG_ALARM_DAYS		0x13
69e70e52e1SLiam Beguin #define ABEOZ9_BIT_ALARM_DAYS		GENMASK(5, 0)
70e70e52e1SLiam Beguin #define ABEOZ9_REG_ALARM_WEEKDAYS	0x14
71e70e52e1SLiam Beguin #define ABEOZ9_BIT_ALARM_WEEKDAYS	GENMASK(2, 0)
72e70e52e1SLiam Beguin #define ABEOZ9_REG_ALARM_MONTHS		0x15
73e70e52e1SLiam Beguin #define ABEOZ9_BIT_ALARM_MONTHS		GENMASK(4, 0)
74e70e52e1SLiam Beguin #define ABEOZ9_REG_ALARM_YEARS		0x16
75e70e52e1SLiam Beguin 
76e70e52e1SLiam Beguin #define ABEOZ9_ALARM_LEN		7
77e70e52e1SLiam Beguin #define ABEOZ9_BIT_ALARM_AE		BIT(7)
78e70e52e1SLiam Beguin 
7967075b63SArtem Panfilov #define ABEOZ9_REG_REG_TEMP		0x20
8067075b63SArtem Panfilov #define ABEOZ953_TEMP_MAX		120
8167075b63SArtem Panfilov #define ABEOZ953_TEMP_MIN		-60
8267075b63SArtem Panfilov 
8367075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM		0x30
8467075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_MASK		GENMASK(8, 0)
8567075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_THP		BIT(0)
8667075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_THE		BIT(1)
8767075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_FD0		BIT(2)
8867075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_FD1		BIT(3)
8967075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_R1K		BIT(4)
9067075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_R5K		BIT(5)
9167075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_R20K		BIT(6)
9267075b63SArtem Panfilov #define ABEOZ9_REG_EEPROM_R80K		BIT(7)
9367075b63SArtem Panfilov 
9467075b63SArtem Panfilov struct abeoz9_rtc_data {
9567075b63SArtem Panfilov 	struct rtc_device *rtc;
9667075b63SArtem Panfilov 	struct regmap *regmap;
9767075b63SArtem Panfilov 	struct device *hwmon_dev;
9867075b63SArtem Panfilov };
9967075b63SArtem Panfilov 
abeoz9_check_validity(struct device * dev)10067075b63SArtem Panfilov static int abeoz9_check_validity(struct device *dev)
10167075b63SArtem Panfilov {
10267075b63SArtem Panfilov 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
10367075b63SArtem Panfilov 	struct regmap *regmap = data->regmap;
10467075b63SArtem Panfilov 	int ret;
10567075b63SArtem Panfilov 	int val;
10667075b63SArtem Panfilov 
10767075b63SArtem Panfilov 	ret = regmap_read(regmap, ABEOZ9_REG_CTRL_STATUS, &val);
10867075b63SArtem Panfilov 	if (ret < 0) {
10967075b63SArtem Panfilov 		dev_err(dev,
11067075b63SArtem Panfilov 			"unable to get CTRL_STATUS register (%d)\n", ret);
11167075b63SArtem Panfilov 		return ret;
11267075b63SArtem Panfilov 	}
11367075b63SArtem Panfilov 
11467075b63SArtem Panfilov 	if (val & ABEOZ9_REG_CTRL_STATUS_PON) {
11567075b63SArtem Panfilov 		dev_warn(dev, "power-on reset detected, date is invalid\n");
11667075b63SArtem Panfilov 		return -EINVAL;
11767075b63SArtem Panfilov 	}
11867075b63SArtem Panfilov 
11967075b63SArtem Panfilov 	if (val & ABEOZ9_REG_CTRL_STATUS_V1F) {
12067075b63SArtem Panfilov 		dev_warn(dev,
12167075b63SArtem Panfilov 			 "voltage drops below VLOW1 threshold, date is invalid\n");
12267075b63SArtem Panfilov 		return -EINVAL;
12367075b63SArtem Panfilov 	}
12467075b63SArtem Panfilov 
12567075b63SArtem Panfilov 	if ((val & ABEOZ9_REG_CTRL_STATUS_V2F)) {
12667075b63SArtem Panfilov 		dev_warn(dev,
12767075b63SArtem Panfilov 			 "voltage drops below VLOW2 threshold, date is invalid\n");
12867075b63SArtem Panfilov 		return -EINVAL;
12967075b63SArtem Panfilov 	}
13067075b63SArtem Panfilov 
13167075b63SArtem Panfilov 	return 0;
13267075b63SArtem Panfilov }
13367075b63SArtem Panfilov 
abeoz9_reset_validity(struct regmap * regmap)13467075b63SArtem Panfilov static int abeoz9_reset_validity(struct regmap *regmap)
13567075b63SArtem Panfilov {
13667075b63SArtem Panfilov 	return regmap_update_bits(regmap, ABEOZ9_REG_CTRL_STATUS,
13767075b63SArtem Panfilov 				  ABEOZ9_REG_CTRL_STATUS_V1F |
13867075b63SArtem Panfilov 				  ABEOZ9_REG_CTRL_STATUS_V2F |
13967075b63SArtem Panfilov 				  ABEOZ9_REG_CTRL_STATUS_PON,
14067075b63SArtem Panfilov 				  0);
14167075b63SArtem Panfilov }
14267075b63SArtem Panfilov 
abeoz9_rtc_get_time(struct device * dev,struct rtc_time * tm)14367075b63SArtem Panfilov static int abeoz9_rtc_get_time(struct device *dev, struct rtc_time *tm)
14467075b63SArtem Panfilov {
14567075b63SArtem Panfilov 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
14667075b63SArtem Panfilov 	u8 regs[ABEOZ9_SEC_LEN];
14767075b63SArtem Panfilov 	int ret;
14867075b63SArtem Panfilov 
14967075b63SArtem Panfilov 	ret = abeoz9_check_validity(dev);
15067075b63SArtem Panfilov 	if (ret)
15167075b63SArtem Panfilov 		return ret;
15267075b63SArtem Panfilov 
15367075b63SArtem Panfilov 	ret = regmap_bulk_read(data->regmap, ABEOZ9_REG_SEC,
15467075b63SArtem Panfilov 			       regs,
15567075b63SArtem Panfilov 			       sizeof(regs));
15667075b63SArtem Panfilov 	if (ret) {
15767075b63SArtem Panfilov 		dev_err(dev, "reading RTC time failed (%d)\n", ret);
15867075b63SArtem Panfilov 		return ret;
15967075b63SArtem Panfilov 	}
16067075b63SArtem Panfilov 
16167075b63SArtem Panfilov 	tm->tm_sec = bcd2bin(regs[ABEOZ9_REG_SEC - ABEOZ9_REG_SEC] & 0x7F);
16267075b63SArtem Panfilov 	tm->tm_min = bcd2bin(regs[ABEOZ9_REG_MIN - ABEOZ9_REG_SEC] & 0x7F);
16367075b63SArtem Panfilov 
16467075b63SArtem Panfilov 	if (regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC] & ABEOZ9_HOURS_PM) {
16567075b63SArtem Panfilov 		tm->tm_hour =
16667075b63SArtem Panfilov 			bcd2bin(regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC] & 0x1f);
16767075b63SArtem Panfilov 		if (regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC] & ABEOZ9_HOURS_PM)
16867075b63SArtem Panfilov 			tm->tm_hour += 12;
16967075b63SArtem Panfilov 	} else {
17067075b63SArtem Panfilov 		tm->tm_hour = bcd2bin(regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC]);
17167075b63SArtem Panfilov 	}
17267075b63SArtem Panfilov 
17367075b63SArtem Panfilov 	tm->tm_mday = bcd2bin(regs[ABEOZ9_REG_DAYS - ABEOZ9_REG_SEC]);
17467075b63SArtem Panfilov 	tm->tm_wday = bcd2bin(regs[ABEOZ9_REG_WEEKDAYS - ABEOZ9_REG_SEC]);
17567075b63SArtem Panfilov 	tm->tm_mon  = bcd2bin(regs[ABEOZ9_REG_MONTHS - ABEOZ9_REG_SEC]) - 1;
17667075b63SArtem Panfilov 	tm->tm_year = bcd2bin(regs[ABEOZ9_REG_YEARS - ABEOZ9_REG_SEC]) + 100;
17767075b63SArtem Panfilov 
17867075b63SArtem Panfilov 	return ret;
17967075b63SArtem Panfilov }
18067075b63SArtem Panfilov 
abeoz9_rtc_set_time(struct device * dev,struct rtc_time * tm)18167075b63SArtem Panfilov static int abeoz9_rtc_set_time(struct device *dev, struct rtc_time *tm)
18267075b63SArtem Panfilov {
18367075b63SArtem Panfilov 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
18467075b63SArtem Panfilov 	struct regmap *regmap = data->regmap;
18567075b63SArtem Panfilov 	u8 regs[ABEOZ9_SEC_LEN];
18667075b63SArtem Panfilov 	int ret;
18767075b63SArtem Panfilov 
18867075b63SArtem Panfilov 	regs[ABEOZ9_REG_SEC - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_sec);
18967075b63SArtem Panfilov 	regs[ABEOZ9_REG_MIN - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_min);
19067075b63SArtem Panfilov 	regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_hour);
19167075b63SArtem Panfilov 	regs[ABEOZ9_REG_DAYS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_mday);
19267075b63SArtem Panfilov 	regs[ABEOZ9_REG_WEEKDAYS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_wday);
19367075b63SArtem Panfilov 	regs[ABEOZ9_REG_MONTHS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_mon + 1);
19467075b63SArtem Panfilov 	regs[ABEOZ9_REG_YEARS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_year - 100);
19567075b63SArtem Panfilov 
19667075b63SArtem Panfilov 	ret = regmap_bulk_write(data->regmap, ABEOZ9_REG_SEC,
19767075b63SArtem Panfilov 				regs,
19867075b63SArtem Panfilov 				sizeof(regs));
19967075b63SArtem Panfilov 
20067075b63SArtem Panfilov 	if (ret) {
20167075b63SArtem Panfilov 		dev_err(dev, "set RTC time failed (%d)\n", ret);
20267075b63SArtem Panfilov 		return ret;
20367075b63SArtem Panfilov 	}
20467075b63SArtem Panfilov 
20567075b63SArtem Panfilov 	return abeoz9_reset_validity(regmap);
20667075b63SArtem Panfilov }
20767075b63SArtem Panfilov 
abeoz9_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alarm)208e70e52e1SLiam Beguin static int abeoz9_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
209e70e52e1SLiam Beguin {
210e70e52e1SLiam Beguin 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
211e70e52e1SLiam Beguin 	struct regmap *regmap = data->regmap;
212e70e52e1SLiam Beguin 	u8 regs[ABEOZ9_ALARM_LEN];
213e70e52e1SLiam Beguin 	u8 val[2];
214e70e52e1SLiam Beguin 	int ret;
215e70e52e1SLiam Beguin 
216e70e52e1SLiam Beguin 	ret = abeoz9_check_validity(dev);
217e70e52e1SLiam Beguin 	if (ret)
218e70e52e1SLiam Beguin 		return ret;
219e70e52e1SLiam Beguin 
220e70e52e1SLiam Beguin 	ret = regmap_bulk_read(regmap, ABEOZ9_REG_CTRL_INT, val, sizeof(val));
221e70e52e1SLiam Beguin 	if (ret)
222e70e52e1SLiam Beguin 		return ret;
223e70e52e1SLiam Beguin 
224e70e52e1SLiam Beguin 	alarm->enabled = val[0] & ABEOZ9_REG_CTRL_INT_AIE;
225e70e52e1SLiam Beguin 	alarm->pending = val[1] & ABEOZ9_REG_CTRL_INT_FLAG_AF;
226e70e52e1SLiam Beguin 
227e70e52e1SLiam Beguin 	ret = regmap_bulk_read(regmap, ABEOZ9_REG_ALARM_SEC, regs, sizeof(regs));
228e70e52e1SLiam Beguin 	if (ret)
229e70e52e1SLiam Beguin 		return ret;
230e70e52e1SLiam Beguin 
231e70e52e1SLiam Beguin 	alarm->time.tm_sec = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_SEC, regs[0]));
232e70e52e1SLiam Beguin 	alarm->time.tm_min = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_MIN, regs[1]));
233e70e52e1SLiam Beguin 	alarm->time.tm_hour = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_HOURS, regs[2]));
234e70e52e1SLiam Beguin 	if (FIELD_GET(ABEOZ9_BIT_ALARM_HOURS_PM, regs[2]))
235e70e52e1SLiam Beguin 		alarm->time.tm_hour += 12;
236e70e52e1SLiam Beguin 
237e70e52e1SLiam Beguin 	alarm->time.tm_mday = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_DAYS, regs[3]));
238e70e52e1SLiam Beguin 
239e70e52e1SLiam Beguin 	return 0;
240e70e52e1SLiam Beguin }
241e70e52e1SLiam Beguin 
abeoz9_rtc_alarm_irq_enable(struct device * dev,u32 enable)242e70e52e1SLiam Beguin static int abeoz9_rtc_alarm_irq_enable(struct device *dev, u32 enable)
243e70e52e1SLiam Beguin {
244e70e52e1SLiam Beguin 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
245e70e52e1SLiam Beguin 
246e70e52e1SLiam Beguin 	return regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT,
247e70e52e1SLiam Beguin 				  ABEOZ9_REG_CTRL_INT_AIE,
248e70e52e1SLiam Beguin 				  FIELD_PREP(ABEOZ9_REG_CTRL_INT_AIE, enable));
249e70e52e1SLiam Beguin }
250e70e52e1SLiam Beguin 
abeoz9_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alarm)251e70e52e1SLiam Beguin static int abeoz9_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
252e70e52e1SLiam Beguin {
253e70e52e1SLiam Beguin 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
254e70e52e1SLiam Beguin 	u8 regs[ABEOZ9_ALARM_LEN] = {0};
255e70e52e1SLiam Beguin 	int ret;
256e70e52e1SLiam Beguin 
257e70e52e1SLiam Beguin 	ret = regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG,
258e70e52e1SLiam Beguin 				 ABEOZ9_REG_CTRL_INT_FLAG_AF, 0);
259e70e52e1SLiam Beguin 	if (ret)
260e70e52e1SLiam Beguin 		return ret;
261e70e52e1SLiam Beguin 
262e70e52e1SLiam Beguin 	regs[0] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_SEC,
263e70e52e1SLiam Beguin 						   bin2bcd(alarm->time.tm_sec));
264e70e52e1SLiam Beguin 	regs[1] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_MIN,
265e70e52e1SLiam Beguin 						   bin2bcd(alarm->time.tm_min));
266e70e52e1SLiam Beguin 	regs[2] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_HOURS,
267e70e52e1SLiam Beguin 						   bin2bcd(alarm->time.tm_hour));
268e70e52e1SLiam Beguin 	regs[3] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_DAYS,
269e70e52e1SLiam Beguin 						   bin2bcd(alarm->time.tm_mday));
270e70e52e1SLiam Beguin 
271e70e52e1SLiam Beguin 	ret = regmap_bulk_write(data->regmap, ABEOZ9_REG_ALARM_SEC, regs,
272e70e52e1SLiam Beguin 				sizeof(regs));
273e70e52e1SLiam Beguin 	if (ret)
274e70e52e1SLiam Beguin 		return ret;
275e70e52e1SLiam Beguin 
276e70e52e1SLiam Beguin 	return abeoz9_rtc_alarm_irq_enable(dev, alarm->enabled);
277e70e52e1SLiam Beguin }
278e70e52e1SLiam Beguin 
abeoz9_rtc_irq(int irq,void * dev)279e70e52e1SLiam Beguin static irqreturn_t abeoz9_rtc_irq(int irq, void *dev)
280e70e52e1SLiam Beguin {
281e70e52e1SLiam Beguin 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
282e70e52e1SLiam Beguin 	unsigned int val;
283e70e52e1SLiam Beguin 	int ret;
284e70e52e1SLiam Beguin 
285e70e52e1SLiam Beguin 	ret = regmap_read(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG, &val);
286e70e52e1SLiam Beguin 	if (ret)
287e70e52e1SLiam Beguin 		return IRQ_NONE;
288e70e52e1SLiam Beguin 
289e70e52e1SLiam Beguin 	if (!FIELD_GET(ABEOZ9_REG_CTRL_INT_FLAG_AF, val))
290e70e52e1SLiam Beguin 		return IRQ_NONE;
291e70e52e1SLiam Beguin 
292e70e52e1SLiam Beguin 	regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG,
293e70e52e1SLiam Beguin 			   ABEOZ9_REG_CTRL_INT_FLAG_AF, 0);
294e70e52e1SLiam Beguin 
295e70e52e1SLiam Beguin 	rtc_update_irq(data->rtc, 1, RTC_IRQF | RTC_AF);
296e70e52e1SLiam Beguin 
297e70e52e1SLiam Beguin 	return IRQ_HANDLED;
298e70e52e1SLiam Beguin }
299e70e52e1SLiam Beguin 
abeoz9_trickle_parse_dt(struct device_node * node)30067075b63SArtem Panfilov static int abeoz9_trickle_parse_dt(struct device_node *node)
30167075b63SArtem Panfilov {
30267075b63SArtem Panfilov 	u32 ohms = 0;
30367075b63SArtem Panfilov 
30467075b63SArtem Panfilov 	if (of_property_read_u32(node, "trickle-resistor-ohms", &ohms))
30567075b63SArtem Panfilov 		return 0;
30667075b63SArtem Panfilov 
30767075b63SArtem Panfilov 	switch (ohms) {
30867075b63SArtem Panfilov 	case 1000:
30967075b63SArtem Panfilov 		return ABEOZ9_REG_EEPROM_R1K;
31067075b63SArtem Panfilov 	case 5000:
31167075b63SArtem Panfilov 		return ABEOZ9_REG_EEPROM_R5K;
31267075b63SArtem Panfilov 	case 20000:
31367075b63SArtem Panfilov 		return ABEOZ9_REG_EEPROM_R20K;
31467075b63SArtem Panfilov 	case 80000:
31567075b63SArtem Panfilov 		return ABEOZ9_REG_EEPROM_R80K;
31667075b63SArtem Panfilov 	default:
31767075b63SArtem Panfilov 		return 0;
31867075b63SArtem Panfilov 	}
31967075b63SArtem Panfilov }
32067075b63SArtem Panfilov 
abeoz9_rtc_setup(struct device * dev,struct device_node * node)32167075b63SArtem Panfilov static int abeoz9_rtc_setup(struct device *dev, struct device_node *node)
32267075b63SArtem Panfilov {
32367075b63SArtem Panfilov 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
32467075b63SArtem Panfilov 	struct regmap *regmap = data->regmap;
32567075b63SArtem Panfilov 	int ret;
32667075b63SArtem Panfilov 
32767075b63SArtem Panfilov 	/* Enable Self Recovery, Clock for Watch and EEPROM refresh functions */
32867075b63SArtem Panfilov 	ret = regmap_update_bits(regmap, ABEOZ9_REG_CTRL1,
32967075b63SArtem Panfilov 				 ABEOZ9_REG_CTRL1_MASK,
33067075b63SArtem Panfilov 				 ABEOZ9_REG_CTRL1_WE |
33167075b63SArtem Panfilov 				 ABEOZ9_REG_CTRL1_EERE |
33267075b63SArtem Panfilov 				 ABEOZ9_REG_CTRL1_SRON);
33367075b63SArtem Panfilov 	if (ret < 0) {
33467075b63SArtem Panfilov 		dev_err(dev, "unable to set CTRL_1 register (%d)\n", ret);
33567075b63SArtem Panfilov 		return ret;
33667075b63SArtem Panfilov 	}
33767075b63SArtem Panfilov 
33867075b63SArtem Panfilov 	ret = regmap_write(regmap, ABEOZ9_REG_CTRL_INT, 0);
33967075b63SArtem Panfilov 	if (ret < 0) {
34067075b63SArtem Panfilov 		dev_err(dev,
34167075b63SArtem Panfilov 			"unable to set control CTRL_INT register (%d)\n",
34267075b63SArtem Panfilov 			ret);
34367075b63SArtem Panfilov 		return ret;
34467075b63SArtem Panfilov 	}
34567075b63SArtem Panfilov 
34667075b63SArtem Panfilov 	ret = regmap_write(regmap, ABEOZ9_REG_CTRL_INT_FLAG, 0);
34767075b63SArtem Panfilov 	if (ret < 0) {
34867075b63SArtem Panfilov 		dev_err(dev,
34967075b63SArtem Panfilov 			"unable to set control CTRL_INT_FLAG register (%d)\n",
35067075b63SArtem Panfilov 			ret);
35167075b63SArtem Panfilov 		return ret;
35267075b63SArtem Panfilov 	}
35367075b63SArtem Panfilov 
35467075b63SArtem Panfilov 	ret = abeoz9_trickle_parse_dt(node);
35567075b63SArtem Panfilov 
35667075b63SArtem Panfilov 	/* Enable built-in termometer */
35767075b63SArtem Panfilov 	ret |= ABEOZ9_REG_EEPROM_THE;
35867075b63SArtem Panfilov 
35967075b63SArtem Panfilov 	ret = regmap_update_bits(regmap, ABEOZ9_REG_EEPROM,
36067075b63SArtem Panfilov 				 ABEOZ9_REG_EEPROM_MASK,
36167075b63SArtem Panfilov 				 ret);
36267075b63SArtem Panfilov 	if (ret < 0) {
36367075b63SArtem Panfilov 		dev_err(dev, "unable to set EEPROM register (%d)\n", ret);
36467075b63SArtem Panfilov 		return ret;
36567075b63SArtem Panfilov 	}
36667075b63SArtem Panfilov 
36767075b63SArtem Panfilov 	return ret;
36867075b63SArtem Panfilov }
36967075b63SArtem Panfilov 
37067075b63SArtem Panfilov static const struct rtc_class_ops rtc_ops = {
37167075b63SArtem Panfilov 	.read_time = abeoz9_rtc_get_time,
37267075b63SArtem Panfilov 	.set_time = abeoz9_rtc_set_time,
373e70e52e1SLiam Beguin 	.read_alarm = abeoz9_rtc_read_alarm,
374e70e52e1SLiam Beguin 	.set_alarm = abeoz9_rtc_set_alarm,
375e70e52e1SLiam Beguin 	.alarm_irq_enable = abeoz9_rtc_alarm_irq_enable,
376e70e52e1SLiam Beguin };
377e70e52e1SLiam Beguin 
37867075b63SArtem Panfilov static const struct regmap_config abeoz9_rtc_regmap_config = {
37967075b63SArtem Panfilov 	.reg_bits = 8,
38067075b63SArtem Panfilov 	.val_bits = 8,
381f1d30476SLiam Beguin 	.max_register = 0x3f,
38267075b63SArtem Panfilov };
38367075b63SArtem Panfilov 
38467075b63SArtem Panfilov #if IS_REACHABLE(CONFIG_HWMON)
38567075b63SArtem Panfilov 
abeoz9z3_temp_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * temp)38667075b63SArtem Panfilov static int abeoz9z3_temp_read(struct device *dev,
38767075b63SArtem Panfilov 			      enum hwmon_sensor_types type,
38867075b63SArtem Panfilov 			      u32 attr, int channel, long *temp)
38967075b63SArtem Panfilov {
39067075b63SArtem Panfilov 	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);
39167075b63SArtem Panfilov 	struct regmap *regmap = data->regmap;
39267075b63SArtem Panfilov 	int ret;
39367075b63SArtem Panfilov 	unsigned int val;
39467075b63SArtem Panfilov 
39567075b63SArtem Panfilov 	ret = regmap_read(regmap, ABEOZ9_REG_CTRL_STATUS, &val);
39667075b63SArtem Panfilov 	if (ret < 0)
39767075b63SArtem Panfilov 		return ret;
39867075b63SArtem Panfilov 
39967075b63SArtem Panfilov 	switch (attr) {
40067075b63SArtem Panfilov 	case hwmon_temp_input:
40167075b63SArtem Panfilov 		ret = regmap_read(regmap, ABEOZ9_REG_REG_TEMP, &val);
40267075b63SArtem Panfilov 		if (ret < 0)
40367075b63SArtem Panfilov 			return ret;
40467075b63SArtem Panfilov 		*temp = 1000 * (val + ABEOZ953_TEMP_MIN);
40567075b63SArtem Panfilov 		return 0;
40667075b63SArtem Panfilov 	case hwmon_temp_max:
40767075b63SArtem Panfilov 		*temp = 1000 * ABEOZ953_TEMP_MAX;
40867075b63SArtem Panfilov 		return 0;
40967075b63SArtem Panfilov 	case hwmon_temp_min:
41067075b63SArtem Panfilov 		*temp = 1000 * ABEOZ953_TEMP_MIN;
41167075b63SArtem Panfilov 		return 0;
41267075b63SArtem Panfilov 	default:
41367075b63SArtem Panfilov 		return -EOPNOTSUPP;
41467075b63SArtem Panfilov 	}
41567075b63SArtem Panfilov }
41667075b63SArtem Panfilov 
abeoz9_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)41767075b63SArtem Panfilov static umode_t abeoz9_is_visible(const void *data,
41867075b63SArtem Panfilov 				 enum hwmon_sensor_types type,
41967075b63SArtem Panfilov 				 u32 attr, int channel)
42067075b63SArtem Panfilov {
42167075b63SArtem Panfilov 	switch (attr) {
42267075b63SArtem Panfilov 	case hwmon_temp_input:
42367075b63SArtem Panfilov 	case hwmon_temp_max:
42467075b63SArtem Panfilov 	case hwmon_temp_min:
42567075b63SArtem Panfilov 		return 0444;
42667075b63SArtem Panfilov 	default:
42767075b63SArtem Panfilov 		return 0;
42867075b63SArtem Panfilov 	}
42967075b63SArtem Panfilov }
43067075b63SArtem Panfilov 
43167075b63SArtem Panfilov static const u32 abeoz9_chip_config[] = {
43267075b63SArtem Panfilov 	HWMON_C_REGISTER_TZ,
43367075b63SArtem Panfilov 	0
43467075b63SArtem Panfilov };
43567075b63SArtem Panfilov 
43667075b63SArtem Panfilov static const struct hwmon_channel_info abeoz9_chip = {
43767075b63SArtem Panfilov 	.type = hwmon_chip,
43867075b63SArtem Panfilov 	.config = abeoz9_chip_config,
43967075b63SArtem Panfilov };
44067075b63SArtem Panfilov 
44167075b63SArtem Panfilov static const u32 abeoz9_temp_config[] = {
44267075b63SArtem Panfilov 	HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN,
44367075b63SArtem Panfilov 	0
44467075b63SArtem Panfilov };
44567075b63SArtem Panfilov 
44667075b63SArtem Panfilov static const struct hwmon_channel_info abeoz9_temp = {
44767075b63SArtem Panfilov 	.type = hwmon_temp,
44867075b63SArtem Panfilov 	.config = abeoz9_temp_config,
44967075b63SArtem Panfilov };
45067075b63SArtem Panfilov 
451973ef084SKrzysztof Kozlowski static const struct hwmon_channel_info * const abeoz9_info[] = {
45267075b63SArtem Panfilov 	&abeoz9_chip,
45367075b63SArtem Panfilov 	&abeoz9_temp,
45467075b63SArtem Panfilov 	NULL
45567075b63SArtem Panfilov };
45667075b63SArtem Panfilov 
45767075b63SArtem Panfilov static const struct hwmon_ops abeoz9_hwmon_ops = {
45867075b63SArtem Panfilov 	.is_visible = abeoz9_is_visible,
45967075b63SArtem Panfilov 	.read = abeoz9z3_temp_read,
46067075b63SArtem Panfilov };
46167075b63SArtem Panfilov 
46267075b63SArtem Panfilov static const struct hwmon_chip_info abeoz9_chip_info = {
46367075b63SArtem Panfilov 	.ops = &abeoz9_hwmon_ops,
46467075b63SArtem Panfilov 	.info = abeoz9_info,
46567075b63SArtem Panfilov };
46667075b63SArtem Panfilov 
abeoz9_hwmon_register(struct device * dev,struct abeoz9_rtc_data * data)46767075b63SArtem Panfilov static void abeoz9_hwmon_register(struct device *dev,
46867075b63SArtem Panfilov 				  struct abeoz9_rtc_data *data)
46967075b63SArtem Panfilov {
47067075b63SArtem Panfilov 	data->hwmon_dev =
47167075b63SArtem Panfilov 		devm_hwmon_device_register_with_info(dev,
47267075b63SArtem Panfilov 						     "abeoz9",
47367075b63SArtem Panfilov 						     data,
47467075b63SArtem Panfilov 						     &abeoz9_chip_info,
47567075b63SArtem Panfilov 						     NULL);
47667075b63SArtem Panfilov 	if (IS_ERR(data->hwmon_dev)) {
47767075b63SArtem Panfilov 		dev_warn(dev, "unable to register hwmon device %ld\n",
47867075b63SArtem Panfilov 			 PTR_ERR(data->hwmon_dev));
47967075b63SArtem Panfilov 	}
48067075b63SArtem Panfilov }
48167075b63SArtem Panfilov 
48267075b63SArtem Panfilov #else
48367075b63SArtem Panfilov 
abeoz9_hwmon_register(struct device * dev,struct abeoz9_rtc_data * data)48467075b63SArtem Panfilov static void abeoz9_hwmon_register(struct device *dev,
48567075b63SArtem Panfilov 				  struct abeoz9_rtc_data *data)
48667075b63SArtem Panfilov {
48767075b63SArtem Panfilov }
48867075b63SArtem Panfilov 
48967075b63SArtem Panfilov #endif
49067075b63SArtem Panfilov 
abeoz9_probe(struct i2c_client * client)4913f4a3322SStephen Kitt static int abeoz9_probe(struct i2c_client *client)
49267075b63SArtem Panfilov {
49367075b63SArtem Panfilov 	struct abeoz9_rtc_data *data = NULL;
49467075b63SArtem Panfilov 	struct device *dev = &client->dev;
49567075b63SArtem Panfilov 	struct regmap *regmap;
49667075b63SArtem Panfilov 	int ret;
49767075b63SArtem Panfilov 
49867075b63SArtem Panfilov 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
49967075b63SArtem Panfilov 				     I2C_FUNC_SMBUS_BYTE_DATA |
50044c638ceSAlexandre Belloni 				     I2C_FUNC_SMBUS_I2C_BLOCK))
50144c638ceSAlexandre Belloni 		return -ENODEV;
50267075b63SArtem Panfilov 
50367075b63SArtem Panfilov 	regmap = devm_regmap_init_i2c(client, &abeoz9_rtc_regmap_config);
50467075b63SArtem Panfilov 	if (IS_ERR(regmap)) {
50567075b63SArtem Panfilov 		ret = PTR_ERR(regmap);
50667075b63SArtem Panfilov 		dev_err(dev, "regmap allocation failed: %d\n", ret);
50744c638ceSAlexandre Belloni 		return ret;
50867075b63SArtem Panfilov 	}
50967075b63SArtem Panfilov 
51067075b63SArtem Panfilov 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
51144c638ceSAlexandre Belloni 	if (!data)
51244c638ceSAlexandre Belloni 		return -ENOMEM;
51367075b63SArtem Panfilov 
51467075b63SArtem Panfilov 	data->regmap = regmap;
51567075b63SArtem Panfilov 	dev_set_drvdata(dev, data);
51667075b63SArtem Panfilov 
51767075b63SArtem Panfilov 	ret = abeoz9_rtc_setup(dev, client->dev.of_node);
51867075b63SArtem Panfilov 	if (ret)
51944c638ceSAlexandre Belloni 		return ret;
52067075b63SArtem Panfilov 
52167075b63SArtem Panfilov 	data->rtc = devm_rtc_allocate_device(dev);
52267075b63SArtem Panfilov 	ret = PTR_ERR_OR_ZERO(data->rtc);
52367075b63SArtem Panfilov 	if (ret)
52444c638ceSAlexandre Belloni 		return ret;
52567075b63SArtem Panfilov 
52667075b63SArtem Panfilov 	data->rtc->ops = &rtc_ops;
52767075b63SArtem Panfilov 	data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
52867075b63SArtem Panfilov 	data->rtc->range_max = RTC_TIMESTAMP_END_2099;
529c52409ebSLiam Beguin 	clear_bit(RTC_FEATURE_ALARM, data->rtc->features);
530e70e52e1SLiam Beguin 
531e70e52e1SLiam Beguin 	if (client->irq > 0) {
53237abc36eSAlexandre Belloni 		unsigned long irqflags = IRQF_TRIGGER_LOW;
53337abc36eSAlexandre Belloni 
53437abc36eSAlexandre Belloni 		if (dev_fwnode(&client->dev))
53537abc36eSAlexandre Belloni 			irqflags = 0;
53637abc36eSAlexandre Belloni 
537e70e52e1SLiam Beguin 		ret = devm_request_threaded_irq(dev, client->irq, NULL,
538e70e52e1SLiam Beguin 						abeoz9_rtc_irq,
53937abc36eSAlexandre Belloni 						irqflags | IRQF_ONESHOT,
540e70e52e1SLiam Beguin 						dev_name(dev), dev);
541e70e52e1SLiam Beguin 		if (ret) {
542e70e52e1SLiam Beguin 			dev_err(dev, "failed to request alarm irq\n");
543e70e52e1SLiam Beguin 			return ret;
544e70e52e1SLiam Beguin 		}
54527f06af7SAlexandre Belloni 	} else {
54627f06af7SAlexandre Belloni 		clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, data->rtc->features);
547e70e52e1SLiam Beguin 	}
548e70e52e1SLiam Beguin 
549e70e52e1SLiam Beguin 	if (client->irq > 0 || device_property_read_bool(dev, "wakeup-source")) {
550e70e52e1SLiam Beguin 		ret = device_init_wakeup(dev, true);
551c52409ebSLiam Beguin 		set_bit(RTC_FEATURE_ALARM, data->rtc->features);
552e70e52e1SLiam Beguin 	}
55367075b63SArtem Panfilov 
554fdcfd854SBartosz Golaszewski 	ret = devm_rtc_register_device(data->rtc);
55567075b63SArtem Panfilov 	if (ret)
55644c638ceSAlexandre Belloni 		return ret;
55767075b63SArtem Panfilov 
55867075b63SArtem Panfilov 	abeoz9_hwmon_register(dev, data);
55967075b63SArtem Panfilov 	return 0;
56067075b63SArtem Panfilov }
56167075b63SArtem Panfilov 
56267075b63SArtem Panfilov #ifdef CONFIG_OF
56367075b63SArtem Panfilov static const struct of_device_id abeoz9_dt_match[] = {
56467075b63SArtem Panfilov 	{ .compatible = "abracon,abeoz9" },
56567075b63SArtem Panfilov 	{ },
56667075b63SArtem Panfilov };
56767075b63SArtem Panfilov MODULE_DEVICE_TABLE(of, abeoz9_dt_match);
56867075b63SArtem Panfilov #endif
56967075b63SArtem Panfilov 
57067075b63SArtem Panfilov static const struct i2c_device_id abeoz9_id[] = {
57167075b63SArtem Panfilov 	{ "abeoz9", 0 },
57267075b63SArtem Panfilov 	{ }
57367075b63SArtem Panfilov };
57467075b63SArtem Panfilov 
57567075b63SArtem Panfilov static struct i2c_driver abeoz9_driver = {
57667075b63SArtem Panfilov 	.driver = {
57767075b63SArtem Panfilov 		.name = "rtc-ab-eoz9",
57867075b63SArtem Panfilov 		.of_match_table = of_match_ptr(abeoz9_dt_match),
57967075b63SArtem Panfilov 	},
580*31b0cecbSUwe Kleine-König 	.probe = abeoz9_probe,
58167075b63SArtem Panfilov 	.id_table = abeoz9_id,
58267075b63SArtem Panfilov };
58367075b63SArtem Panfilov 
58467075b63SArtem Panfilov module_i2c_driver(abeoz9_driver);
58567075b63SArtem Panfilov 
58667075b63SArtem Panfilov MODULE_AUTHOR("Artem Panfilov <panfilov.artyom@gmail.com>");
58767075b63SArtem Panfilov MODULE_DESCRIPTION("Abracon AB-RTCMC-32.768kHz-EOZ9 RTC driver");
58867075b63SArtem Panfilov MODULE_LICENSE("GPL");
589