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