1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2ed13d89bSAkshay Bhat /*
3ed13d89bSAkshay Bhat * Driver for the Epson RTC module RX-8010 SJ
4ed13d89bSAkshay Bhat *
5ed13d89bSAkshay Bhat * Copyright(C) Timesys Corporation 2015
6ed13d89bSAkshay Bhat * Copyright(C) General Electric Company 2015
7ed13d89bSAkshay Bhat */
8ed13d89bSAkshay Bhat
9ed13d89bSAkshay Bhat #include <linux/bcd.h>
10ed13d89bSAkshay Bhat #include <linux/bitops.h>
11ed13d89bSAkshay Bhat #include <linux/i2c.h>
12ed13d89bSAkshay Bhat #include <linux/kernel.h>
13ed13d89bSAkshay Bhat #include <linux/module.h>
149868bc1cSBartosz Golaszewski #include <linux/regmap.h>
15ed13d89bSAkshay Bhat #include <linux/rtc.h>
16ed13d89bSAkshay Bhat
17ed13d89bSAkshay Bhat #define RX8010_SEC 0x10
18ed13d89bSAkshay Bhat #define RX8010_MIN 0x11
19ed13d89bSAkshay Bhat #define RX8010_HOUR 0x12
20ed13d89bSAkshay Bhat #define RX8010_WDAY 0x13
21ed13d89bSAkshay Bhat #define RX8010_MDAY 0x14
22ed13d89bSAkshay Bhat #define RX8010_MONTH 0x15
23ed13d89bSAkshay Bhat #define RX8010_YEAR 0x16
24ed13d89bSAkshay Bhat #define RX8010_RESV17 0x17
25ed13d89bSAkshay Bhat #define RX8010_ALMIN 0x18
26ed13d89bSAkshay Bhat #define RX8010_ALHOUR 0x19
27ed13d89bSAkshay Bhat #define RX8010_ALWDAY 0x1A
28ed13d89bSAkshay Bhat #define RX8010_TCOUNT0 0x1B
29ed13d89bSAkshay Bhat #define RX8010_TCOUNT1 0x1C
30ed13d89bSAkshay Bhat #define RX8010_EXT 0x1D
31ed13d89bSAkshay Bhat #define RX8010_FLAG 0x1E
32ed13d89bSAkshay Bhat #define RX8010_CTRL 0x1F
33ed13d89bSAkshay Bhat /* 0x20 to 0x2F are user registers */
34ed13d89bSAkshay Bhat #define RX8010_RESV30 0x30
35abf57f73SAkshay Bhat #define RX8010_RESV31 0x31
36ed13d89bSAkshay Bhat #define RX8010_IRQ 0x32
37ed13d89bSAkshay Bhat
38ed13d89bSAkshay Bhat #define RX8010_EXT_WADA BIT(3)
39ed13d89bSAkshay Bhat
40ed13d89bSAkshay Bhat #define RX8010_FLAG_VLF BIT(1)
41ed13d89bSAkshay Bhat #define RX8010_FLAG_AF BIT(3)
42ed13d89bSAkshay Bhat #define RX8010_FLAG_TF BIT(4)
43ed13d89bSAkshay Bhat #define RX8010_FLAG_UF BIT(5)
44ed13d89bSAkshay Bhat
45ed13d89bSAkshay Bhat #define RX8010_CTRL_AIE BIT(3)
46ed13d89bSAkshay Bhat #define RX8010_CTRL_UIE BIT(5)
47ed13d89bSAkshay Bhat #define RX8010_CTRL_STOP BIT(6)
48ed13d89bSAkshay Bhat #define RX8010_CTRL_TEST BIT(7)
49ed13d89bSAkshay Bhat
50ed13d89bSAkshay Bhat #define RX8010_ALARM_AE BIT(7)
51ed13d89bSAkshay Bhat
52ed13d89bSAkshay Bhat static const struct i2c_device_id rx8010_id[] = {
53ed13d89bSAkshay Bhat { "rx8010", 0 },
54ed13d89bSAkshay Bhat { }
55ed13d89bSAkshay Bhat };
56ed13d89bSAkshay Bhat MODULE_DEVICE_TABLE(i2c, rx8010_id);
57ed13d89bSAkshay Bhat
58782d3ebfSAlexandre Belloni static const __maybe_unused struct of_device_id rx8010_of_match[] = {
5981b779ceSJavier Martinez Canillas { .compatible = "epson,rx8010" },
6081b779ceSJavier Martinez Canillas { }
6181b779ceSJavier Martinez Canillas };
6281b779ceSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, rx8010_of_match);
6381b779ceSJavier Martinez Canillas
64ed13d89bSAkshay Bhat struct rx8010_data {
659868bc1cSBartosz Golaszewski struct regmap *regs;
66ed13d89bSAkshay Bhat struct rtc_device *rtc;
67ed13d89bSAkshay Bhat u8 ctrlreg;
68ed13d89bSAkshay Bhat };
69ed13d89bSAkshay Bhat
rx8010_irq_1_handler(int irq,void * dev_id)70ed13d89bSAkshay Bhat static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id)
71ed13d89bSAkshay Bhat {
72ed13d89bSAkshay Bhat struct i2c_client *client = dev_id;
73ed13d89bSAkshay Bhat struct rx8010_data *rx8010 = i2c_get_clientdata(client);
749868bc1cSBartosz Golaszewski int flagreg, err;
75ed13d89bSAkshay Bhat
762dbbedb9SAlexandre Belloni rtc_lock(rx8010->rtc);
77ed13d89bSAkshay Bhat
789868bc1cSBartosz Golaszewski err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg);
799868bc1cSBartosz Golaszewski if (err) {
802dbbedb9SAlexandre Belloni rtc_unlock(rx8010->rtc);
81ed13d89bSAkshay Bhat return IRQ_NONE;
82ed13d89bSAkshay Bhat }
83ed13d89bSAkshay Bhat
84ed13d89bSAkshay Bhat if (flagreg & RX8010_FLAG_VLF)
85ed13d89bSAkshay Bhat dev_warn(&client->dev, "Frequency stop detected\n");
86ed13d89bSAkshay Bhat
87ed13d89bSAkshay Bhat if (flagreg & RX8010_FLAG_TF) {
88ed13d89bSAkshay Bhat flagreg &= ~RX8010_FLAG_TF;
89ed13d89bSAkshay Bhat rtc_update_irq(rx8010->rtc, 1, RTC_PF | RTC_IRQF);
90ed13d89bSAkshay Bhat }
91ed13d89bSAkshay Bhat
92ed13d89bSAkshay Bhat if (flagreg & RX8010_FLAG_AF) {
93ed13d89bSAkshay Bhat flagreg &= ~RX8010_FLAG_AF;
94ed13d89bSAkshay Bhat rtc_update_irq(rx8010->rtc, 1, RTC_AF | RTC_IRQF);
95ed13d89bSAkshay Bhat }
96ed13d89bSAkshay Bhat
97ed13d89bSAkshay Bhat if (flagreg & RX8010_FLAG_UF) {
98ed13d89bSAkshay Bhat flagreg &= ~RX8010_FLAG_UF;
99ed13d89bSAkshay Bhat rtc_update_irq(rx8010->rtc, 1, RTC_UF | RTC_IRQF);
100ed13d89bSAkshay Bhat }
101ed13d89bSAkshay Bhat
1029868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_FLAG, flagreg);
1032dbbedb9SAlexandre Belloni rtc_unlock(rx8010->rtc);
1049868bc1cSBartosz Golaszewski return err ? IRQ_NONE : IRQ_HANDLED;
105ed13d89bSAkshay Bhat }
106ed13d89bSAkshay Bhat
rx8010_get_time(struct device * dev,struct rtc_time * dt)107ed13d89bSAkshay Bhat static int rx8010_get_time(struct device *dev, struct rtc_time *dt)
108ed13d89bSAkshay Bhat {
109ed13d89bSAkshay Bhat struct rx8010_data *rx8010 = dev_get_drvdata(dev);
110f702699cSBartosz Golaszewski u8 date[RX8010_YEAR - RX8010_SEC + 1];
11175677971SBartosz Golaszewski int flagreg, err;
112ed13d89bSAkshay Bhat
1139868bc1cSBartosz Golaszewski err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg);
1149868bc1cSBartosz Golaszewski if (err)
1159868bc1cSBartosz Golaszewski return err;
116ed13d89bSAkshay Bhat
117ed13d89bSAkshay Bhat if (flagreg & RX8010_FLAG_VLF) {
118ed13d89bSAkshay Bhat dev_warn(dev, "Frequency stop detected\n");
119ed13d89bSAkshay Bhat return -EINVAL;
120ed13d89bSAkshay Bhat }
121ed13d89bSAkshay Bhat
1229868bc1cSBartosz Golaszewski err = regmap_bulk_read(rx8010->regs, RX8010_SEC, date, sizeof(date));
1239868bc1cSBartosz Golaszewski if (err)
1249868bc1cSBartosz Golaszewski return err;
125ed13d89bSAkshay Bhat
126ed13d89bSAkshay Bhat dt->tm_sec = bcd2bin(date[RX8010_SEC - RX8010_SEC] & 0x7f);
127ed13d89bSAkshay Bhat dt->tm_min = bcd2bin(date[RX8010_MIN - RX8010_SEC] & 0x7f);
128ed13d89bSAkshay Bhat dt->tm_hour = bcd2bin(date[RX8010_HOUR - RX8010_SEC] & 0x3f);
129ed13d89bSAkshay Bhat dt->tm_mday = bcd2bin(date[RX8010_MDAY - RX8010_SEC] & 0x3f);
130ed13d89bSAkshay Bhat dt->tm_mon = bcd2bin(date[RX8010_MONTH - RX8010_SEC] & 0x1f) - 1;
131ed13d89bSAkshay Bhat dt->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 100;
132ed13d89bSAkshay Bhat dt->tm_wday = ffs(date[RX8010_WDAY - RX8010_SEC] & 0x7f);
133ed13d89bSAkshay Bhat
13422652ba7SAlexandre Belloni return 0;
135ed13d89bSAkshay Bhat }
136ed13d89bSAkshay Bhat
rx8010_set_time(struct device * dev,struct rtc_time * dt)137ed13d89bSAkshay Bhat static int rx8010_set_time(struct device *dev, struct rtc_time *dt)
138ed13d89bSAkshay Bhat {
139ed13d89bSAkshay Bhat struct rx8010_data *rx8010 = dev_get_drvdata(dev);
140f702699cSBartosz Golaszewski u8 date[RX8010_YEAR - RX8010_SEC + 1];
1419868bc1cSBartosz Golaszewski int err;
142ed13d89bSAkshay Bhat
143ed13d89bSAkshay Bhat /* set STOP bit before changing clock/calendar */
1449868bc1cSBartosz Golaszewski err = regmap_set_bits(rx8010->regs, RX8010_CTRL, RX8010_CTRL_STOP);
1459868bc1cSBartosz Golaszewski if (err)
14613952c9eSBartosz Golaszewski return err;
147ed13d89bSAkshay Bhat
148ed13d89bSAkshay Bhat date[RX8010_SEC - RX8010_SEC] = bin2bcd(dt->tm_sec);
149ed13d89bSAkshay Bhat date[RX8010_MIN - RX8010_SEC] = bin2bcd(dt->tm_min);
150ed13d89bSAkshay Bhat date[RX8010_HOUR - RX8010_SEC] = bin2bcd(dt->tm_hour);
151ed13d89bSAkshay Bhat date[RX8010_MDAY - RX8010_SEC] = bin2bcd(dt->tm_mday);
152ed13d89bSAkshay Bhat date[RX8010_MONTH - RX8010_SEC] = bin2bcd(dt->tm_mon + 1);
153ed13d89bSAkshay Bhat date[RX8010_YEAR - RX8010_SEC] = bin2bcd(dt->tm_year - 100);
154ed13d89bSAkshay Bhat date[RX8010_WDAY - RX8010_SEC] = bin2bcd(1 << dt->tm_wday);
155ed13d89bSAkshay Bhat
1569868bc1cSBartosz Golaszewski err = regmap_bulk_write(rx8010->regs, RX8010_SEC, date, sizeof(date));
1579868bc1cSBartosz Golaszewski if (err)
15813952c9eSBartosz Golaszewski return err;
159ed13d89bSAkshay Bhat
160ed13d89bSAkshay Bhat /* clear STOP bit after changing clock/calendar */
1619868bc1cSBartosz Golaszewski err = regmap_clear_bits(rx8010->regs, RX8010_CTRL, RX8010_CTRL_STOP);
1629868bc1cSBartosz Golaszewski if (err)
16313952c9eSBartosz Golaszewski return err;
164ed13d89bSAkshay Bhat
1659868bc1cSBartosz Golaszewski err = regmap_clear_bits(rx8010->regs, RX8010_FLAG, RX8010_FLAG_VLF);
1669868bc1cSBartosz Golaszewski if (err)
1679868bc1cSBartosz Golaszewski return err;
168ed13d89bSAkshay Bhat
169ed13d89bSAkshay Bhat return 0;
170ed13d89bSAkshay Bhat }
171ed13d89bSAkshay Bhat
rx8010_init(struct device * dev)172ba1bcafbSBartosz Golaszewski static int rx8010_init(struct device *dev)
173ed13d89bSAkshay Bhat {
1749868bc1cSBartosz Golaszewski struct rx8010_data *rx8010 = dev_get_drvdata(dev);
175ed13d89bSAkshay Bhat u8 ctrl[2];
176b3ff7fd6SBartosz Golaszewski int need_clear = 0, err;
177ed13d89bSAkshay Bhat
178ed13d89bSAkshay Bhat /* Initialize reserved registers as specified in datasheet */
1799868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_RESV17, 0xD8);
1809868bc1cSBartosz Golaszewski if (err)
181ed13d89bSAkshay Bhat return err;
182ed13d89bSAkshay Bhat
1839868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_RESV30, 0x00);
1849868bc1cSBartosz Golaszewski if (err)
185ed13d89bSAkshay Bhat return err;
186ed13d89bSAkshay Bhat
1879868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_RESV31, 0x08);
1889868bc1cSBartosz Golaszewski if (err)
189ed13d89bSAkshay Bhat return err;
190ed13d89bSAkshay Bhat
1919868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_IRQ, 0x00);
1929868bc1cSBartosz Golaszewski if (err)
193ed13d89bSAkshay Bhat return err;
194ed13d89bSAkshay Bhat
1959868bc1cSBartosz Golaszewski err = regmap_bulk_read(rx8010->regs, RX8010_FLAG, ctrl, 2);
1969868bc1cSBartosz Golaszewski if (err)
1979868bc1cSBartosz Golaszewski return err;
198ed13d89bSAkshay Bhat
199ed13d89bSAkshay Bhat if (ctrl[0] & RX8010_FLAG_VLF)
2009868bc1cSBartosz Golaszewski dev_warn(dev, "Frequency stop was detected\n");
201ed13d89bSAkshay Bhat
202ed13d89bSAkshay Bhat if (ctrl[0] & RX8010_FLAG_AF) {
2039868bc1cSBartosz Golaszewski dev_warn(dev, "Alarm was detected\n");
204ed13d89bSAkshay Bhat need_clear = 1;
205ed13d89bSAkshay Bhat }
206ed13d89bSAkshay Bhat
207ed13d89bSAkshay Bhat if (ctrl[0] & RX8010_FLAG_TF)
208ed13d89bSAkshay Bhat need_clear = 1;
209ed13d89bSAkshay Bhat
210ed13d89bSAkshay Bhat if (ctrl[0] & RX8010_FLAG_UF)
211ed13d89bSAkshay Bhat need_clear = 1;
212ed13d89bSAkshay Bhat
213ed13d89bSAkshay Bhat if (need_clear) {
214ed13d89bSAkshay Bhat ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF);
2159868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_FLAG, ctrl[0]);
2169868bc1cSBartosz Golaszewski if (err)
217ed13d89bSAkshay Bhat return err;
218ed13d89bSAkshay Bhat }
219ed13d89bSAkshay Bhat
220ed13d89bSAkshay Bhat rx8010->ctrlreg = (ctrl[1] & ~RX8010_CTRL_TEST);
221ed13d89bSAkshay Bhat
222804a6cfeSAkshay Bhat return 0;
223ed13d89bSAkshay Bhat }
224ed13d89bSAkshay Bhat
rx8010_read_alarm(struct device * dev,struct rtc_wkalrm * t)225ed13d89bSAkshay Bhat static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
226ed13d89bSAkshay Bhat {
227ed13d89bSAkshay Bhat struct rx8010_data *rx8010 = dev_get_drvdata(dev);
228ed13d89bSAkshay Bhat u8 alarmvals[3];
22975677971SBartosz Golaszewski int flagreg, err;
230ed13d89bSAkshay Bhat
2319868bc1cSBartosz Golaszewski err = regmap_bulk_read(rx8010->regs, RX8010_ALMIN, alarmvals, 3);
2329868bc1cSBartosz Golaszewski if (err)
2339868bc1cSBartosz Golaszewski return err;
234ed13d89bSAkshay Bhat
2359868bc1cSBartosz Golaszewski err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg);
2369868bc1cSBartosz Golaszewski if (err)
2379868bc1cSBartosz Golaszewski return err;
238ed13d89bSAkshay Bhat
239ed13d89bSAkshay Bhat t->time.tm_sec = 0;
240ed13d89bSAkshay Bhat t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
241ed13d89bSAkshay Bhat t->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
242ed13d89bSAkshay Bhat
24356d86a7eSUwe Kleine-König if (!(alarmvals[2] & RX8010_ALARM_AE))
244ed13d89bSAkshay Bhat t->time.tm_mday = bcd2bin(alarmvals[2] & 0x7f);
245ed13d89bSAkshay Bhat
246ed13d89bSAkshay Bhat t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE);
247ed13d89bSAkshay Bhat t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled;
248ed13d89bSAkshay Bhat
249804a6cfeSAkshay Bhat return 0;
250ed13d89bSAkshay Bhat }
251ed13d89bSAkshay Bhat
rx8010_set_alarm(struct device * dev,struct rtc_wkalrm * t)252ed13d89bSAkshay Bhat static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t)
253ed13d89bSAkshay Bhat {
254ed13d89bSAkshay Bhat struct rx8010_data *rx8010 = dev_get_drvdata(dev);
255ed13d89bSAkshay Bhat u8 alarmvals[3];
2569868bc1cSBartosz Golaszewski int err;
257ed13d89bSAkshay Bhat
258ed13d89bSAkshay Bhat if (rx8010->ctrlreg & (RX8010_CTRL_AIE | RX8010_CTRL_UIE)) {
259ed13d89bSAkshay Bhat rx8010->ctrlreg &= ~(RX8010_CTRL_AIE | RX8010_CTRL_UIE);
2609868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_CTRL, rx8010->ctrlreg);
2619868bc1cSBartosz Golaszewski if (err)
262ed13d89bSAkshay Bhat return err;
263ed13d89bSAkshay Bhat }
264ed13d89bSAkshay Bhat
2659868bc1cSBartosz Golaszewski err = regmap_clear_bits(rx8010->regs, RX8010_FLAG, RX8010_FLAG_AF);
2669868bc1cSBartosz Golaszewski if (err)
267ed13d89bSAkshay Bhat return err;
268ed13d89bSAkshay Bhat
269ed13d89bSAkshay Bhat alarmvals[0] = bin2bcd(t->time.tm_min);
270ed13d89bSAkshay Bhat alarmvals[1] = bin2bcd(t->time.tm_hour);
271ed13d89bSAkshay Bhat alarmvals[2] = bin2bcd(t->time.tm_mday);
272ed13d89bSAkshay Bhat
2739868bc1cSBartosz Golaszewski err = regmap_bulk_write(rx8010->regs, RX8010_ALMIN, alarmvals, 2);
2749868bc1cSBartosz Golaszewski if (err)
275ed13d89bSAkshay Bhat return err;
276ed13d89bSAkshay Bhat
2779868bc1cSBartosz Golaszewski err = regmap_clear_bits(rx8010->regs, RX8010_EXT, RX8010_EXT_WADA);
2789868bc1cSBartosz Golaszewski if (err)
279ed13d89bSAkshay Bhat return err;
280ed13d89bSAkshay Bhat
281ed13d89bSAkshay Bhat if (alarmvals[2] == 0)
282ed13d89bSAkshay Bhat alarmvals[2] |= RX8010_ALARM_AE;
283ed13d89bSAkshay Bhat
2849868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_ALWDAY, alarmvals[2]);
2859868bc1cSBartosz Golaszewski if (err)
286ed13d89bSAkshay Bhat return err;
287ed13d89bSAkshay Bhat
288ed13d89bSAkshay Bhat if (t->enabled) {
289ed13d89bSAkshay Bhat if (rx8010->rtc->uie_rtctimer.enabled)
290ed13d89bSAkshay Bhat rx8010->ctrlreg |= RX8010_CTRL_UIE;
291ed13d89bSAkshay Bhat if (rx8010->rtc->aie_timer.enabled)
292ed13d89bSAkshay Bhat rx8010->ctrlreg |=
293ed13d89bSAkshay Bhat (RX8010_CTRL_AIE | RX8010_CTRL_UIE);
294ed13d89bSAkshay Bhat
2959868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_CTRL, rx8010->ctrlreg);
2969868bc1cSBartosz Golaszewski if (err)
297ed13d89bSAkshay Bhat return err;
298ed13d89bSAkshay Bhat }
299ed13d89bSAkshay Bhat
300ed13d89bSAkshay Bhat return 0;
301ed13d89bSAkshay Bhat }
302ed13d89bSAkshay Bhat
rx8010_alarm_irq_enable(struct device * dev,unsigned int enabled)303ed13d89bSAkshay Bhat static int rx8010_alarm_irq_enable(struct device *dev,
304ed13d89bSAkshay Bhat unsigned int enabled)
305ed13d89bSAkshay Bhat {
306ed13d89bSAkshay Bhat struct rx8010_data *rx8010 = dev_get_drvdata(dev);
3079868bc1cSBartosz Golaszewski int err;
308ed13d89bSAkshay Bhat u8 ctrl;
309ed13d89bSAkshay Bhat
310ed13d89bSAkshay Bhat ctrl = rx8010->ctrlreg;
311ed13d89bSAkshay Bhat
312ed13d89bSAkshay Bhat if (enabled) {
313ed13d89bSAkshay Bhat if (rx8010->rtc->uie_rtctimer.enabled)
314ed13d89bSAkshay Bhat ctrl |= RX8010_CTRL_UIE;
315ed13d89bSAkshay Bhat if (rx8010->rtc->aie_timer.enabled)
316ed13d89bSAkshay Bhat ctrl |= (RX8010_CTRL_AIE | RX8010_CTRL_UIE);
317ed13d89bSAkshay Bhat } else {
318ed13d89bSAkshay Bhat if (!rx8010->rtc->uie_rtctimer.enabled)
319ed13d89bSAkshay Bhat ctrl &= ~RX8010_CTRL_UIE;
320ed13d89bSAkshay Bhat if (!rx8010->rtc->aie_timer.enabled)
321ed13d89bSAkshay Bhat ctrl &= ~RX8010_CTRL_AIE;
322ed13d89bSAkshay Bhat }
323ed13d89bSAkshay Bhat
3249868bc1cSBartosz Golaszewski err = regmap_clear_bits(rx8010->regs, RX8010_FLAG, RX8010_FLAG_AF);
3259868bc1cSBartosz Golaszewski if (err)
326ed13d89bSAkshay Bhat return err;
327ed13d89bSAkshay Bhat
328ed13d89bSAkshay Bhat if (ctrl != rx8010->ctrlreg) {
329ed13d89bSAkshay Bhat rx8010->ctrlreg = ctrl;
3309868bc1cSBartosz Golaszewski err = regmap_write(rx8010->regs, RX8010_CTRL, rx8010->ctrlreg);
3319868bc1cSBartosz Golaszewski if (err)
332ed13d89bSAkshay Bhat return err;
333ed13d89bSAkshay Bhat }
334ed13d89bSAkshay Bhat
335ed13d89bSAkshay Bhat return 0;
336ed13d89bSAkshay Bhat }
337ed13d89bSAkshay Bhat
rx8010_ioctl(struct device * dev,unsigned int cmd,unsigned long arg)338ed13d89bSAkshay Bhat static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
339ed13d89bSAkshay Bhat {
340ed13d89bSAkshay Bhat struct rx8010_data *rx8010 = dev_get_drvdata(dev);
3419868bc1cSBartosz Golaszewski int tmp, flagreg, err;
342ed13d89bSAkshay Bhat
343ed13d89bSAkshay Bhat switch (cmd) {
344ed13d89bSAkshay Bhat case RTC_VL_READ:
3459868bc1cSBartosz Golaszewski err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg);
3469868bc1cSBartosz Golaszewski if (err)
3479868bc1cSBartosz Golaszewski return err;
348ed13d89bSAkshay Bhat
3498049c113SAlexandre Belloni tmp = flagreg & RX8010_FLAG_VLF ? RTC_VL_DATA_INVALID : 0;
3508049c113SAlexandre Belloni return put_user(tmp, (unsigned int __user *)arg);
351ed13d89bSAkshay Bhat
352ed13d89bSAkshay Bhat default:
353ed13d89bSAkshay Bhat return -ENOIOCTLCMD;
354ed13d89bSAkshay Bhat }
355ed13d89bSAkshay Bhat }
356ed13d89bSAkshay Bhat
357aaaea29cSAlexandre Belloni static const struct rtc_class_ops rx8010_rtc_ops = {
358d3b14296SBartosz Golaszewski .read_time = rx8010_get_time,
359d3b14296SBartosz Golaszewski .set_time = rx8010_set_time,
360d3b14296SBartosz Golaszewski .ioctl = rx8010_ioctl,
361d3b14296SBartosz Golaszewski .read_alarm = rx8010_read_alarm,
362d3b14296SBartosz Golaszewski .set_alarm = rx8010_set_alarm,
363d3b14296SBartosz Golaszewski .alarm_irq_enable = rx8010_alarm_irq_enable,
364d3b14296SBartosz Golaszewski };
365d3b14296SBartosz Golaszewski
3669868bc1cSBartosz Golaszewski static const struct regmap_config rx8010_regmap_config = {
3679868bc1cSBartosz Golaszewski .name = "rx8010-rtc",
3689868bc1cSBartosz Golaszewski .reg_bits = 8,
3699868bc1cSBartosz Golaszewski .val_bits = 8,
3709868bc1cSBartosz Golaszewski };
3719868bc1cSBartosz Golaszewski
rx8010_probe(struct i2c_client * client)372cee015d9SBartosz Golaszewski static int rx8010_probe(struct i2c_client *client)
373ed13d89bSAkshay Bhat {
374955a123cSBartosz Golaszewski struct device *dev = &client->dev;
375ed13d89bSAkshay Bhat struct rx8010_data *rx8010;
376ed13d89bSAkshay Bhat int err = 0;
377ed13d89bSAkshay Bhat
378666f2141SBartosz Golaszewski rx8010 = devm_kzalloc(dev, sizeof(*rx8010), GFP_KERNEL);
379ed13d89bSAkshay Bhat if (!rx8010)
380ed13d89bSAkshay Bhat return -ENOMEM;
381ed13d89bSAkshay Bhat
382ed13d89bSAkshay Bhat i2c_set_clientdata(client, rx8010);
383ed13d89bSAkshay Bhat
3849868bc1cSBartosz Golaszewski rx8010->regs = devm_regmap_init_i2c(client, &rx8010_regmap_config);
3859868bc1cSBartosz Golaszewski if (IS_ERR(rx8010->regs))
3869868bc1cSBartosz Golaszewski return PTR_ERR(rx8010->regs);
3879868bc1cSBartosz Golaszewski
388ba1bcafbSBartosz Golaszewski err = rx8010_init(dev);
389ed13d89bSAkshay Bhat if (err)
390ed13d89bSAkshay Bhat return err;
391ed13d89bSAkshay Bhat
3920ce62778SBartosz Golaszewski rx8010->rtc = devm_rtc_allocate_device(dev);
3930ce62778SBartosz Golaszewski if (IS_ERR(rx8010->rtc))
3940ce62778SBartosz Golaszewski return PTR_ERR(rx8010->rtc);
3950ce62778SBartosz Golaszewski
396ed13d89bSAkshay Bhat if (client->irq > 0) {
3974bbdced5SAlexandre Belloni unsigned long irqflags = IRQF_TRIGGER_LOW;
3984bbdced5SAlexandre Belloni
3994bbdced5SAlexandre Belloni if (dev_fwnode(&client->dev))
4004bbdced5SAlexandre Belloni irqflags = 0;
4014bbdced5SAlexandre Belloni
402955a123cSBartosz Golaszewski err = devm_request_threaded_irq(dev, client->irq, NULL,
403ed13d89bSAkshay Bhat rx8010_irq_1_handler,
4044bbdced5SAlexandre Belloni irqflags | IRQF_ONESHOT,
405ed13d89bSAkshay Bhat "rx8010", client);
406ed13d89bSAkshay Bhat if (err) {
407955a123cSBartosz Golaszewski dev_err(dev, "unable to request IRQ\n");
408d3b14296SBartosz Golaszewski return err;
409ed13d89bSAkshay Bhat }
410d3b14296SBartosz Golaszewski } else {
411aaaea29cSAlexandre Belloni clear_bit(RTC_FEATURE_ALARM, rx8010->rtc->features);
412ed13d89bSAkshay Bhat }
413ed13d89bSAkshay Bhat
414aaaea29cSAlexandre Belloni rx8010->rtc->ops = &rx8010_rtc_ops;
415ed13d89bSAkshay Bhat rx8010->rtc->max_user_freq = 1;
4162fc1af30SBartosz Golaszewski rx8010->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
4172fc1af30SBartosz Golaszewski rx8010->rtc->range_max = RTC_TIMESTAMP_END_2099;
418ed13d89bSAkshay Bhat
419fdcfd854SBartosz Golaszewski return devm_rtc_register_device(rx8010->rtc);
420ed13d89bSAkshay Bhat }
421ed13d89bSAkshay Bhat
422ed13d89bSAkshay Bhat static struct i2c_driver rx8010_driver = {
423ed13d89bSAkshay Bhat .driver = {
424ed13d89bSAkshay Bhat .name = "rtc-rx8010",
42581b779ceSJavier Martinez Canillas .of_match_table = of_match_ptr(rx8010_of_match),
426ed13d89bSAkshay Bhat },
427*31b0cecbSUwe Kleine-König .probe = rx8010_probe,
428ed13d89bSAkshay Bhat .id_table = rx8010_id,
429ed13d89bSAkshay Bhat };
430ed13d89bSAkshay Bhat
431ed13d89bSAkshay Bhat module_i2c_driver(rx8010_driver);
432ed13d89bSAkshay Bhat
433ed13d89bSAkshay Bhat MODULE_AUTHOR("Akshay Bhat <akshay.bhat@timesys.com>");
434ed13d89bSAkshay Bhat MODULE_DESCRIPTION("Epson RX8010SJ RTC driver");
435ed13d89bSAkshay Bhat MODULE_LICENSE("GPL v2");
436