Blame view

drivers/rtc/rtc-rv3029c2.c 23.1 KB
52365230e   Heiko Schocher   rtc: add rv3029c2...
1
  /*
c2a1c1454   Mylène Josserand   rtc: rv3029: Add ...
2
   * Micro Crystal RV-3029 / RV-3049 rtc class driver
52365230e   Heiko Schocher   rtc: add rv3029c2...
3
4
   *
   * Author: Gregory Hermant <gregory.hermant@calao-systems.com>
2dca3d9e1   Michael Buesch   rtc: rv3029: Add ...
5
   *         Michael Buesch <m@bues.ch>
52365230e   Heiko Schocher   rtc: add rv3029c2...
6
7
8
9
10
11
12
   *
   * based on previously existing rtc class drivers
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
52365230e   Heiko Schocher   rtc: add rv3029c2...
13
14
15
16
   */
  
  #include <linux/module.h>
  #include <linux/i2c.h>
c2a1c1454   Mylène Josserand   rtc: rv3029: Add ...
17
  #include <linux/spi/spi.h>
52365230e   Heiko Schocher   rtc: add rv3029c2...
18
19
  #include <linux/bcd.h>
  #include <linux/rtc.h>
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
20
21
  #include <linux/delay.h>
  #include <linux/of.h>
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
22
23
  #include <linux/hwmon.h>
  #include <linux/hwmon-sysfs.h>
e6e380821   Mylène Josserand   rtc: rv3029: conv...
24
  #include <linux/regmap.h>
52365230e   Heiko Schocher   rtc: add rv3029c2...
25
26
27
  
  /* Register map */
  /* control section */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
28
  #define RV3029_ONOFF_CTRL		0x00
7697de35f   Michael Buesch   rtc: rv3029: Add ...
29
30
31
32
33
34
35
36
  #define RV3029_ONOFF_CTRL_WE		BIT(0)
  #define RV3029_ONOFF_CTRL_TE		BIT(1)
  #define RV3029_ONOFF_CTRL_TAR		BIT(2)
  #define RV3029_ONOFF_CTRL_EERE		BIT(3)
  #define RV3029_ONOFF_CTRL_SRON		BIT(4)
  #define RV3029_ONOFF_CTRL_TD0		BIT(5)
  #define RV3029_ONOFF_CTRL_TD1		BIT(6)
  #define RV3029_ONOFF_CTRL_CLKINT	BIT(7)
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
37
  #define RV3029_IRQ_CTRL			0x01
7697de35f   Michael Buesch   rtc: rv3029: Add ...
38
39
40
41
42
  #define RV3029_IRQ_CTRL_AIE		BIT(0)
  #define RV3029_IRQ_CTRL_TIE		BIT(1)
  #define RV3029_IRQ_CTRL_V1IE		BIT(2)
  #define RV3029_IRQ_CTRL_V2IE		BIT(3)
  #define RV3029_IRQ_CTRL_SRIE		BIT(4)
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
43
  #define RV3029_IRQ_FLAGS		0x02
7697de35f   Michael Buesch   rtc: rv3029: Add ...
44
45
46
47
48
  #define RV3029_IRQ_FLAGS_AF		BIT(0)
  #define RV3029_IRQ_FLAGS_TF		BIT(1)
  #define RV3029_IRQ_FLAGS_V1IF		BIT(2)
  #define RV3029_IRQ_FLAGS_V2IF		BIT(3)
  #define RV3029_IRQ_FLAGS_SRF		BIT(4)
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
49
  #define RV3029_STATUS			0x03
7697de35f   Michael Buesch   rtc: rv3029: Add ...
50
51
52
53
54
  #define RV3029_STATUS_VLOW1		BIT(2)
  #define RV3029_STATUS_VLOW2		BIT(3)
  #define RV3029_STATUS_SR		BIT(4)
  #define RV3029_STATUS_PON		BIT(5)
  #define RV3029_STATUS_EEBUSY		BIT(7)
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
55
  #define RV3029_RST_CTRL			0x04
7697de35f   Michael Buesch   rtc: rv3029: Add ...
56
  #define RV3029_RST_CTRL_SYSR		BIT(4)
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
57
  #define RV3029_CONTROL_SECTION_LEN	0x05
52365230e   Heiko Schocher   rtc: add rv3029c2...
58
59
  
  /* watch section */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
60
61
62
  #define RV3029_W_SEC			0x08
  #define RV3029_W_MINUTES		0x09
  #define RV3029_W_HOURS			0x0A
7697de35f   Michael Buesch   rtc: rv3029: Add ...
63
64
  #define RV3029_REG_HR_12_24		BIT(6) /* 24h/12h mode */
  #define RV3029_REG_HR_PM		BIT(5) /* PM/AM bit in 12h mode */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
65
66
67
68
69
  #define RV3029_W_DATE			0x0B
  #define RV3029_W_DAYS			0x0C
  #define RV3029_W_MONTHS			0x0D
  #define RV3029_W_YEARS			0x0E
  #define RV3029_WATCH_SECTION_LEN	0x07
52365230e   Heiko Schocher   rtc: add rv3029c2...
70
71
  
  /* alarm section */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
72
73
74
75
76
77
78
  #define RV3029_A_SC			0x10
  #define RV3029_A_MN			0x11
  #define RV3029_A_HR			0x12
  #define RV3029_A_DT			0x13
  #define RV3029_A_DW			0x14
  #define RV3029_A_MO			0x15
  #define RV3029_A_YR			0x16
dc492e866   Mylène Josserand   rtc: rv3029: fix ...
79
  #define RV3029_A_AE_X			BIT(7)
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
80
  #define RV3029_ALARM_SECTION_LEN	0x07
52365230e   Heiko Schocher   rtc: add rv3029c2...
81
82
  
  /* timer section */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
83
84
  #define RV3029_TIMER_LOW		0x18
  #define RV3029_TIMER_HIGH		0x19
52365230e   Heiko Schocher   rtc: add rv3029c2...
85
86
  
  /* temperature section */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
87
  #define RV3029_TEMP_PAGE		0x20
52365230e   Heiko Schocher   rtc: add rv3029c2...
88
89
  
  /* eeprom data section */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
90
91
  #define RV3029_E2P_EEDATA1		0x28
  #define RV3029_E2P_EEDATA2		0x29
7697de35f   Michael Buesch   rtc: rv3029: Add ...
92
  #define RV3029_E2PDATA_SECTION_LEN	0x02
52365230e   Heiko Schocher   rtc: add rv3029c2...
93
94
  
  /* eeprom control section */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
95
  #define RV3029_CONTROL_E2P_EECTRL	0x30
7697de35f   Michael Buesch   rtc: rv3029: Add ...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  #define RV3029_EECTRL_THP		BIT(0) /* temp scan interval */
  #define RV3029_EECTRL_THE		BIT(1) /* thermometer enable */
  #define RV3029_EECTRL_FD0		BIT(2) /* CLKOUT */
  #define RV3029_EECTRL_FD1		BIT(3) /* CLKOUT */
  #define RV3029_TRICKLE_1K		BIT(4) /* 1.5K resistance */
  #define RV3029_TRICKLE_5K		BIT(5) /* 5K   resistance */
  #define RV3029_TRICKLE_20K		BIT(6) /* 20K  resistance */
  #define RV3029_TRICKLE_80K		BIT(7) /* 80K  resistance */
  #define RV3029_TRICKLE_MASK		(RV3029_TRICKLE_1K |\
  					 RV3029_TRICKLE_5K |\
  					 RV3029_TRICKLE_20K |\
  					 RV3029_TRICKLE_80K)
  #define RV3029_TRICKLE_SHIFT		4
  #define RV3029_CONTROL_E2P_XOFFS	0x31 /* XTAL offset */
  #define RV3029_CONTROL_E2P_XOFFS_SIGN	BIT(7) /* Sign: 1->pos, 0->neg */
  #define RV3029_CONTROL_E2P_QCOEF	0x32 /* XTAL temp drift coef */
  #define RV3029_CONTROL_E2P_TURNOVER	0x33 /* XTAL turnover temp (in *C) */
  #define RV3029_CONTROL_E2P_TOV_MASK	0x3F /* XTAL turnover temp mask */
52365230e   Heiko Schocher   rtc: add rv3029c2...
114
115
  
  /* user ram section */
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
116
117
118
119
  #define RV3029_USR1_RAM_PAGE		0x38
  #define RV3029_USR1_SECTION_LEN		0x04
  #define RV3029_USR2_RAM_PAGE		0x3C
  #define RV3029_USR2_SECTION_LEN		0x04
52365230e   Heiko Schocher   rtc: add rv3029c2...
120

e6e380821   Mylène Josserand   rtc: rv3029: conv...
121
122
123
124
125
126
127
128
  struct rv3029_data {
  	struct device		*dev;
  	struct rtc_device	*rtc;
  	struct regmap		*regmap;
  	int irq;
  };
  
  static int rv3029_read_regs(struct device *dev, u8 reg, u8 *buf,
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
129
  			    unsigned int len)
52365230e   Heiko Schocher   rtc: add rv3029c2...
130
  {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
131
  	struct rv3029_data *rv3029 = dev_get_drvdata(dev);
52365230e   Heiko Schocher   rtc: add rv3029c2...
132

aba39d27b   Michael Buesch   rtc: rv3029: Remo...
133
  	if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
134
  	    (reg + len > RV3029_USR1_RAM_PAGE + 8))
52365230e   Heiko Schocher   rtc: add rv3029c2...
135
  		return -EINVAL;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
136
  	return regmap_bulk_read(rv3029->regmap, reg, buf, len);
52365230e   Heiko Schocher   rtc: add rv3029c2...
137
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
138
  static int rv3029_write_regs(struct device *dev, u8 reg, u8 const buf[],
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
139
  			     unsigned int len)
52365230e   Heiko Schocher   rtc: add rv3029c2...
140
  {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
141
  	struct rv3029_data *rv3029 = dev_get_drvdata(dev);
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
142
  	if ((reg > RV3029_USR1_RAM_PAGE + 7) ||
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
143
  	    (reg + len > RV3029_USR1_RAM_PAGE + 8))
52365230e   Heiko Schocher   rtc: add rv3029c2...
144
  		return -EINVAL;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
145
  	return regmap_bulk_write(rv3029->regmap, reg, buf, len);
52365230e   Heiko Schocher   rtc: add rv3029c2...
146
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
147
  static int rv3029_update_bits(struct device *dev, u8 reg, u8 mask, u8 set)
2dca3d9e1   Michael Buesch   rtc: rv3029: Add ...
148
149
150
  {
  	u8 buf;
  	int ret;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
151
  	ret = rv3029_read_regs(dev, reg, &buf, 1);
2dca3d9e1   Michael Buesch   rtc: rv3029: Add ...
152
153
154
155
  	if (ret < 0)
  		return ret;
  	buf &= ~mask;
  	buf |= set & mask;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
156
  	ret = rv3029_write_regs(dev, reg, &buf, 1);
2dca3d9e1   Michael Buesch   rtc: rv3029: Add ...
157
158
159
160
161
  	if (ret < 0)
  		return ret;
  
  	return 0;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
162
  static int rv3029_get_sr(struct device *dev, u8 *buf)
52365230e   Heiko Schocher   rtc: add rv3029c2...
163
  {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
164
  	int ret = rv3029_read_regs(dev, RV3029_STATUS, buf, 1);
52365230e   Heiko Schocher   rtc: add rv3029c2...
165
166
167
  
  	if (ret < 0)
  		return -EIO;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
168
169
  	dev_dbg(dev, "status = 0x%.2x (%d)
  ", buf[0], buf[0]);
52365230e   Heiko Schocher   rtc: add rv3029c2...
170
171
  	return 0;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
172
  static int rv3029_set_sr(struct device *dev, u8 val)
52365230e   Heiko Schocher   rtc: add rv3029c2...
173
174
175
176
177
  {
  	u8 buf[1];
  	int sr;
  
  	buf[0] = val;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
178
179
180
  	sr = rv3029_write_regs(dev, RV3029_STATUS, buf, 1);
  	dev_dbg(dev, "status = 0x%.2x (%d)
  ", buf[0], buf[0]);
52365230e   Heiko Schocher   rtc: add rv3029c2...
181
182
183
184
  	if (sr < 0)
  		return -EIO;
  	return 0;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
185
  static int rv3029_eeprom_busywait(struct device *dev)
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
186
187
188
189
190
  {
  	int i, ret;
  	u8 sr;
  
  	for (i = 100; i > 0; i--) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
191
  		ret = rv3029_get_sr(dev, &sr);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
192
193
194
195
196
197
198
  		if (ret < 0)
  			break;
  		if (!(sr & RV3029_STATUS_EEBUSY))
  			break;
  		usleep_range(1000, 10000);
  	}
  	if (i <= 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
199
200
  		dev_err(dev, "EEPROM busy wait timeout.
  ");
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
201
202
203
204
205
  		return -ETIMEDOUT;
  	}
  
  	return ret;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
206
  static int rv3029_eeprom_exit(struct device *dev)
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
207
208
  {
  	/* Re-enable eeprom refresh */
e6e380821   Mylène Josserand   rtc: rv3029: conv...
209
  	return rv3029_update_bits(dev, RV3029_ONOFF_CTRL,
4e7f1a605   Mylène Josserand   rtc: rv3029: remo...
210
211
  				  RV3029_ONOFF_CTRL_EERE,
  				  RV3029_ONOFF_CTRL_EERE);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
212
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
213
  static int rv3029_eeprom_enter(struct device *dev)
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
214
215
216
217
218
  {
  	int ret;
  	u8 sr;
  
  	/* Check whether we are in the allowed voltage range. */
e6e380821   Mylène Josserand   rtc: rv3029: conv...
219
  	ret = rv3029_get_sr(dev, &sr);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
220
221
222
223
224
225
226
227
  	if (ret < 0)
  		return ret;
  	if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
  		/* We clear the bits and retry once just in case
  		 * we had a brown out in early startup.
  		 */
  		sr &= ~RV3029_STATUS_VLOW1;
  		sr &= ~RV3029_STATUS_VLOW2;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
228
  		ret = rv3029_set_sr(dev, sr);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
229
230
231
  		if (ret < 0)
  			return ret;
  		usleep_range(1000, 10000);
e6e380821   Mylène Josserand   rtc: rv3029: conv...
232
  		ret = rv3029_get_sr(dev, &sr);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
233
234
235
  		if (ret < 0)
  			return ret;
  		if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
236
  			dev_err(dev,
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
237
238
239
240
241
242
243
  				"Supply voltage is too low to safely access the EEPROM.
  ");
  			return -ENODEV;
  		}
  	}
  
  	/* Disable eeprom refresh. */
e6e380821   Mylène Josserand   rtc: rv3029: conv...
244
245
  	ret = rv3029_update_bits(dev, RV3029_ONOFF_CTRL, RV3029_ONOFF_CTRL_EERE,
  				 0);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
246
247
248
249
  	if (ret < 0)
  		return ret;
  
  	/* Wait for any previous eeprom accesses to finish. */
e6e380821   Mylène Josserand   rtc: rv3029: conv...
250
  	ret = rv3029_eeprom_busywait(dev);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
251
  	if (ret < 0)
e6e380821   Mylène Josserand   rtc: rv3029: conv...
252
  		rv3029_eeprom_exit(dev);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
253
254
255
  
  	return ret;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
256
  static int rv3029_eeprom_read(struct device *dev, u8 reg,
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
257
258
259
  			      u8 buf[], size_t len)
  {
  	int ret, err;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
260
  	err = rv3029_eeprom_enter(dev);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
261
262
  	if (err < 0)
  		return err;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
263
  	ret = rv3029_read_regs(dev, reg, buf, len);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
264

e6e380821   Mylène Josserand   rtc: rv3029: conv...
265
  	err = rv3029_eeprom_exit(dev);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
266
267
268
269
270
  	if (err < 0)
  		return err;
  
  	return ret;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
271
  static int rv3029_eeprom_write(struct device *dev, u8 reg,
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
272
273
274
275
276
  			       u8 const buf[], size_t len)
  {
  	int ret, err;
  	size_t i;
  	u8 tmp;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
277
  	err = rv3029_eeprom_enter(dev);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
278
279
280
281
  	if (err < 0)
  		return err;
  
  	for (i = 0; i < len; i++, reg++) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
282
  		ret = rv3029_read_regs(dev, reg, &tmp, 1);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
283
284
285
  		if (ret < 0)
  			break;
  		if (tmp != buf[i]) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
286
  			ret = rv3029_write_regs(dev, reg, &buf[i], 1);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
287
288
289
  			if (ret < 0)
  				break;
  		}
e6e380821   Mylène Josserand   rtc: rv3029: conv...
290
  		ret = rv3029_eeprom_busywait(dev);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
291
292
293
  		if (ret < 0)
  			break;
  	}
e6e380821   Mylène Josserand   rtc: rv3029: conv...
294
  	err = rv3029_eeprom_exit(dev);
a7f6e2874   Michael Buesch   rtc: rv3029: Add ...
295
296
297
298
299
  	if (err < 0)
  		return err;
  
  	return ret;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
300
  static int rv3029_eeprom_update_bits(struct device *dev,
39387dc2c   Michael Buesch   rtc: rv3029: Add ...
301
302
303
304
  				     u8 reg, u8 mask, u8 set)
  {
  	u8 buf;
  	int ret;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
305
  	ret = rv3029_eeprom_read(dev, reg, &buf, 1);
39387dc2c   Michael Buesch   rtc: rv3029: Add ...
306
307
308
309
  	if (ret < 0)
  		return ret;
  	buf &= ~mask;
  	buf |= set & mask;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
310
  	ret = rv3029_eeprom_write(dev, reg, &buf, 1);
39387dc2c   Michael Buesch   rtc: rv3029: Add ...
311
312
313
314
315
  	if (ret < 0)
  		return ret;
  
  	return 0;
  }
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  static irqreturn_t rv3029_handle_irq(int irq, void *dev_id)
  {
  	struct device *dev = dev_id;
  	struct rv3029_data *rv3029 = dev_get_drvdata(dev);
  	struct mutex *lock = &rv3029->rtc->ops_lock;
  	unsigned long events = 0;
  	u8 flags, controls;
  	int ret;
  
  	mutex_lock(lock);
  
  	ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
  	if (ret) {
  		dev_warn(dev, "Read IRQ Control Register error %d
  ", ret);
  		mutex_unlock(lock);
  		return IRQ_NONE;
  	}
  
  	ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
  	if (ret) {
  		dev_warn(dev, "Read IRQ Flags Register error %d
  ", ret);
  		mutex_unlock(lock);
  		return IRQ_NONE;
  	}
  
  	if (flags & RV3029_IRQ_FLAGS_AF) {
  		flags &= ~RV3029_IRQ_FLAGS_AF;
  		controls &= ~RV3029_IRQ_CTRL_AIE;
  		events |= RTC_AF;
  	}
  
  	if (events) {
  		rtc_update_irq(rv3029->rtc, 1, events);
  		rv3029_write_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
  		rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
  	}
  	mutex_unlock(lock);
  
  	return IRQ_HANDLED;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
358
  static int rv3029_read_time(struct device *dev, struct rtc_time *tm)
52365230e   Heiko Schocher   rtc: add rv3029c2...
359
360
361
  {
  	u8 buf[1];
  	int ret;
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
362
  	u8 regs[RV3029_WATCH_SECTION_LEN] = { 0, };
52365230e   Heiko Schocher   rtc: add rv3029c2...
363

e6e380821   Mylène Josserand   rtc: rv3029: conv...
364
  	ret = rv3029_get_sr(dev, buf);
52365230e   Heiko Schocher   rtc: add rv3029c2...
365
  	if (ret < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
366
367
  		dev_err(dev, "%s: reading SR failed
  ", __func__);
52365230e   Heiko Schocher   rtc: add rv3029c2...
368
369
  		return -EIO;
  	}
e6e380821   Mylène Josserand   rtc: rv3029: conv...
370
  	ret = rv3029_read_regs(dev, RV3029_W_SEC, regs,
4e7f1a605   Mylène Josserand   rtc: rv3029: remo...
371
  			       RV3029_WATCH_SECTION_LEN);
52365230e   Heiko Schocher   rtc: add rv3029c2...
372
  	if (ret < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
373
374
  		dev_err(dev, "%s: reading RTC section failed
  ", __func__);
52365230e   Heiko Schocher   rtc: add rv3029c2...
375
376
  		return ret;
  	}
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
377
378
  	tm->tm_sec = bcd2bin(regs[RV3029_W_SEC - RV3029_W_SEC]);
  	tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES - RV3029_W_SEC]);
52365230e   Heiko Schocher   rtc: add rv3029c2...
379
380
381
  
  	/* HR field has a more complex interpretation */
  	{
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
382
  		const u8 _hr = regs[RV3029_W_HOURS - RV3029_W_SEC];
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
383
384
  
  		if (_hr & RV3029_REG_HR_12_24) {
52365230e   Heiko Schocher   rtc: add rv3029c2...
385
386
  			/* 12h format */
  			tm->tm_hour = bcd2bin(_hr & 0x1f);
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
387
  			if (_hr & RV3029_REG_HR_PM)	/* PM flag set */
52365230e   Heiko Schocher   rtc: add rv3029c2...
388
389
390
391
  				tm->tm_hour += 12;
  		} else /* 24h format */
  			tm->tm_hour = bcd2bin(_hr & 0x3f);
  	}
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
392
393
394
395
  	tm->tm_mday = bcd2bin(regs[RV3029_W_DATE - RV3029_W_SEC]);
  	tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS - RV3029_W_SEC]) - 1;
  	tm->tm_year = bcd2bin(regs[RV3029_W_YEARS - RV3029_W_SEC]) + 100;
  	tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS - RV3029_W_SEC]) - 1;
52365230e   Heiko Schocher   rtc: add rv3029c2...
396
397
398
  
  	return 0;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
399
  static int rv3029_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
52365230e   Heiko Schocher   rtc: add rv3029c2...
400
401
402
  {
  	struct rtc_time *const tm = &alarm->time;
  	int ret;
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
403
  	u8 regs[8], controls, flags;
52365230e   Heiko Schocher   rtc: add rv3029c2...
404

e6e380821   Mylène Josserand   rtc: rv3029: conv...
405
  	ret = rv3029_get_sr(dev, regs);
52365230e   Heiko Schocher   rtc: add rv3029c2...
406
  	if (ret < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
407
408
  		dev_err(dev, "%s: reading SR failed
  ", __func__);
52365230e   Heiko Schocher   rtc: add rv3029c2...
409
410
  		return -EIO;
  	}
e6e380821   Mylène Josserand   rtc: rv3029: conv...
411
  	ret = rv3029_read_regs(dev, RV3029_A_SC, regs,
4e7f1a605   Mylène Josserand   rtc: rv3029: remo...
412
  			       RV3029_ALARM_SECTION_LEN);
52365230e   Heiko Schocher   rtc: add rv3029c2...
413
414
  
  	if (ret < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
415
416
  		dev_err(dev, "%s: reading alarm section failed
  ", __func__);
52365230e   Heiko Schocher   rtc: add rv3029c2...
417
418
  		return ret;
  	}
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
419
420
421
422
423
424
425
426
427
428
429
430
  	ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
  	if (ret) {
  		dev_err(dev, "Read IRQ Control Register error %d
  ", ret);
  		return ret;
  	}
  	ret = rv3029_read_regs(dev, RV3029_IRQ_FLAGS, &flags, 1);
  	if (ret < 0) {
  		dev_err(dev, "Read IRQ Flags Register error %d
  ", ret);
  		return ret;
  	}
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
431
432
433
434
435
436
437
  	tm->tm_sec = bcd2bin(regs[RV3029_A_SC - RV3029_A_SC] & 0x7f);
  	tm->tm_min = bcd2bin(regs[RV3029_A_MN - RV3029_A_SC] & 0x7f);
  	tm->tm_hour = bcd2bin(regs[RV3029_A_HR - RV3029_A_SC] & 0x3f);
  	tm->tm_mday = bcd2bin(regs[RV3029_A_DT - RV3029_A_SC] & 0x3f);
  	tm->tm_mon = bcd2bin(regs[RV3029_A_MO - RV3029_A_SC] & 0x1f) - 1;
  	tm->tm_year = bcd2bin(regs[RV3029_A_YR - RV3029_A_SC] & 0x7f) + 100;
  	tm->tm_wday = bcd2bin(regs[RV3029_A_DW - RV3029_A_SC] & 0x07) - 1;
52365230e   Heiko Schocher   rtc: add rv3029c2...
438

0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
439
440
  	alarm->enabled = !!(controls & RV3029_IRQ_CTRL_AIE);
  	alarm->pending = (flags & RV3029_IRQ_FLAGS_AF) && alarm->enabled;
52365230e   Heiko Schocher   rtc: add rv3029c2...
441
442
  	return 0;
  }
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
443
  static int rv3029_alarm_irq_enable(struct device *dev, unsigned int enable)
52365230e   Heiko Schocher   rtc: add rv3029c2...
444
445
  {
  	int ret;
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
446
447
448
449
450
451
452
453
  	u8 controls;
  
  	ret = rv3029_read_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
  	if (ret < 0) {
  		dev_warn(dev, "Read IRQ Control Register error %d
  ", ret);
  		return ret;
  	}
52365230e   Heiko Schocher   rtc: add rv3029c2...
454

2dca3d9e1   Michael Buesch   rtc: rv3029: Add ...
455
  	/* enable/disable AIE irq */
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
456
457
458
459
460
461
  	if (enable)
  		controls |= RV3029_IRQ_CTRL_AIE;
  	else
  		controls &= ~RV3029_IRQ_CTRL_AIE;
  
  	ret = rv3029_write_regs(dev, RV3029_IRQ_CTRL, &controls, 1);
52365230e   Heiko Schocher   rtc: add rv3029c2...
462
  	if (ret < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
463
464
  		dev_err(dev, "can't update INT reg
  ");
52365230e   Heiko Schocher   rtc: add rv3029c2...
465
466
467
468
469
  		return ret;
  	}
  
  	return 0;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
470
  static int rv3029_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
52365230e   Heiko Schocher   rtc: add rv3029c2...
471
472
473
474
475
476
477
478
479
480
481
482
  {
  	struct rtc_time *const tm = &alarm->time;
  	int ret;
  	u8 regs[8];
  
  	/*
  	 * The clock has an 8 bit wide bcd-coded register (they never learn)
  	 * for the year. tm_year is an offset from 1900 and we are interested
  	 * in the 2000-2099 range, so any value less than 100 is invalid.
  	*/
  	if (tm->tm_year < 100)
  		return -EINVAL;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
483
  	ret = rv3029_get_sr(dev, regs);
52365230e   Heiko Schocher   rtc: add rv3029c2...
484
  	if (ret < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
485
486
  		dev_err(dev, "%s: reading SR failed
  ", __func__);
52365230e   Heiko Schocher   rtc: add rv3029c2...
487
488
  		return -EIO;
  	}
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
489

dc492e866   Mylène Josserand   rtc: rv3029: fix ...
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  	/* Activate all the alarms with AE_x bit */
  	regs[RV3029_A_SC - RV3029_A_SC] = bin2bcd(tm->tm_sec) | RV3029_A_AE_X;
  	regs[RV3029_A_MN - RV3029_A_SC] = bin2bcd(tm->tm_min) | RV3029_A_AE_X;
  	regs[RV3029_A_HR - RV3029_A_SC] = (bin2bcd(tm->tm_hour) & 0x3f)
  		| RV3029_A_AE_X;
  	regs[RV3029_A_DT - RV3029_A_SC] = (bin2bcd(tm->tm_mday) & 0x3f)
  		| RV3029_A_AE_X;
  	regs[RV3029_A_MO - RV3029_A_SC] = (bin2bcd(tm->tm_mon + 1) & 0x1f)
  		| RV3029_A_AE_X;
  	regs[RV3029_A_DW - RV3029_A_SC] = (bin2bcd(tm->tm_wday + 1) & 0x7)
  		| RV3029_A_AE_X;
  	regs[RV3029_A_YR - RV3029_A_SC] = (bin2bcd(tm->tm_year - 100))
  		| RV3029_A_AE_X;
  
  	/* Write the alarm */
e6e380821   Mylène Josserand   rtc: rv3029: conv...
505
  	ret = rv3029_write_regs(dev, RV3029_A_SC, regs,
4e7f1a605   Mylène Josserand   rtc: rv3029: remo...
506
  				RV3029_ALARM_SECTION_LEN);
52365230e   Heiko Schocher   rtc: add rv3029c2...
507
508
509
510
  	if (ret < 0)
  		return ret;
  
  	if (alarm->enabled) {
52365230e   Heiko Schocher   rtc: add rv3029c2...
511
  		/* enable AIE irq */
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
512
  		ret = rv3029_alarm_irq_enable(dev, 1);
52365230e   Heiko Schocher   rtc: add rv3029c2...
513
514
  		if (ret)
  			return ret;
52365230e   Heiko Schocher   rtc: add rv3029c2...
515
516
  	} else {
  		/* disable AIE irq */
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
517
  		ret = rv3029_alarm_irq_enable(dev, 0);
52365230e   Heiko Schocher   rtc: add rv3029c2...
518
519
  		if (ret)
  			return ret;
52365230e   Heiko Schocher   rtc: add rv3029c2...
520
521
522
523
  	}
  
  	return 0;
  }
e6e380821   Mylène Josserand   rtc: rv3029: conv...
524
  static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
52365230e   Heiko Schocher   rtc: add rv3029c2...
525
526
527
528
529
530
531
532
533
534
535
  {
  	u8 regs[8];
  	int ret;
  
  	/*
  	 * The clock has an 8 bit wide bcd-coded register (they never learn)
  	 * for the year. tm_year is an offset from 1900 and we are interested
  	 * in the 2000-2099 range, so any value less than 100 is invalid.
  	*/
  	if (tm->tm_year < 100)
  		return -EINVAL;
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
536
537
538
539
540
  	regs[RV3029_W_SEC - RV3029_W_SEC] = bin2bcd(tm->tm_sec);
  	regs[RV3029_W_MINUTES - RV3029_W_SEC] = bin2bcd(tm->tm_min);
  	regs[RV3029_W_HOURS - RV3029_W_SEC] = bin2bcd(tm->tm_hour);
  	regs[RV3029_W_DATE - RV3029_W_SEC] = bin2bcd(tm->tm_mday);
  	regs[RV3029_W_MONTHS - RV3029_W_SEC] = bin2bcd(tm->tm_mon + 1);
38201ca3c   Mylène Josserand   rtc: rv3029: fix ...
541
  	regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd(tm->tm_wday + 1) & 0x7;
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
542
  	regs[RV3029_W_YEARS - RV3029_W_SEC] = bin2bcd(tm->tm_year - 100);
52365230e   Heiko Schocher   rtc: add rv3029c2...
543

e6e380821   Mylène Josserand   rtc: rv3029: conv...
544
  	ret = rv3029_write_regs(dev, RV3029_W_SEC, regs,
4e7f1a605   Mylène Josserand   rtc: rv3029: remo...
545
  				RV3029_WATCH_SECTION_LEN);
52365230e   Heiko Schocher   rtc: add rv3029c2...
546
547
  	if (ret < 0)
  		return ret;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
548
  	ret = rv3029_get_sr(dev, regs);
52365230e   Heiko Schocher   rtc: add rv3029c2...
549
  	if (ret < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
550
551
  		dev_err(dev, "%s: reading SR failed
  ", __func__);
52365230e   Heiko Schocher   rtc: add rv3029c2...
552
553
554
  		return ret;
  	}
  	/* clear PON bit */
e6e380821   Mylène Josserand   rtc: rv3029: conv...
555
  	ret = rv3029_set_sr(dev, (regs[0] & ~RV3029_STATUS_PON));
52365230e   Heiko Schocher   rtc: add rv3029c2...
556
  	if (ret < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
557
558
  		dev_err(dev, "%s: reading SR failed
  ", __func__);
52365230e   Heiko Schocher   rtc: add rv3029c2...
559
560
561
562
563
  		return ret;
  	}
  
  	return 0;
  }
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
564

e27e21603   Michael Buesch   rtc: rv3029: Add ...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
  static const struct rv3029_trickle_tab_elem {
  	u32 r;		/* resistance in ohms */
  	u8 conf;	/* trickle config bits */
  } rv3029_trickle_tab[] = {
  	{
  		.r	= 1076,
  		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
  			  RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
  	}, {
  		.r	= 1091,
  		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
  			  RV3029_TRICKLE_20K,
  	}, {
  		.r	= 1137,
  		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
  			  RV3029_TRICKLE_80K,
  	}, {
  		.r	= 1154,
  		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_5K,
  	}, {
  		.r	= 1371,
  		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_20K |
  			  RV3029_TRICKLE_80K,
  	}, {
  		.r	= 1395,
  		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_20K,
  	}, {
  		.r	= 1472,
  		.conf	= RV3029_TRICKLE_1K | RV3029_TRICKLE_80K,
  	}, {
  		.r	= 1500,
  		.conf	= RV3029_TRICKLE_1K,
  	}, {
  		.r	= 3810,
  		.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_20K |
  			  RV3029_TRICKLE_80K,
  	}, {
  		.r	= 4000,
  		.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_20K,
  	}, {
  		.r	= 4706,
  		.conf	= RV3029_TRICKLE_5K | RV3029_TRICKLE_80K,
  	}, {
  		.r	= 5000,
  		.conf	= RV3029_TRICKLE_5K,
  	}, {
  		.r	= 16000,
  		.conf	= RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
  	}, {
  		.r	= 20000,
  		.conf	= RV3029_TRICKLE_20K,
  	}, {
  		.r	= 80000,
  		.conf	= RV3029_TRICKLE_80K,
  	},
  };
e6e380821   Mylène Josserand   rtc: rv3029: conv...
621
  static void rv3029_trickle_config(struct device *dev)
e27e21603   Michael Buesch   rtc: rv3029: Add ...
622
  {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
623
  	struct device_node *of_node = dev->of_node;
e27e21603   Michael Buesch   rtc: rv3029: Add ...
624
625
626
  	const struct rv3029_trickle_tab_elem *elem;
  	int i, err;
  	u32 ohms;
39387dc2c   Michael Buesch   rtc: rv3029: Add ...
627
  	u8 trickle_set_bits;
e27e21603   Michael Buesch   rtc: rv3029: Add ...
628
629
630
631
632
  
  	if (!of_node)
  		return;
  
  	/* Configure the trickle charger. */
e27e21603   Michael Buesch   rtc: rv3029: Add ...
633
634
635
  	err = of_property_read_u32(of_node, "trickle-resistor-ohms", &ohms);
  	if (err) {
  		/* Disable trickle charger. */
39387dc2c   Michael Buesch   rtc: rv3029: Add ...
636
  		trickle_set_bits = 0;
e27e21603   Michael Buesch   rtc: rv3029: Add ...
637
638
639
640
641
642
643
  	} else {
  		/* Enable trickle charger. */
  		for (i = 0; i < ARRAY_SIZE(rv3029_trickle_tab); i++) {
  			elem = &rv3029_trickle_tab[i];
  			if (elem->r >= ohms)
  				break;
  		}
39387dc2c   Michael Buesch   rtc: rv3029: Add ...
644
  		trickle_set_bits = elem->conf;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
645
  		dev_info(dev,
e27e21603   Michael Buesch   rtc: rv3029: Add ...
646
647
648
649
  			 "Trickle charger enabled at %d ohms resistance.
  ",
  			 elem->r);
  	}
e6e380821   Mylène Josserand   rtc: rv3029: conv...
650
  	err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
39387dc2c   Michael Buesch   rtc: rv3029: Add ...
651
652
  					RV3029_TRICKLE_MASK,
  					trickle_set_bits);
abe2f551e   Mylène Josserand   rtc: rv3029: Remo...
653
  	if (err < 0)
e6e380821   Mylène Josserand   rtc: rv3029: conv...
654
655
  		dev_err(dev, "Failed to update trickle charger config
  ");
e27e21603   Michael Buesch   rtc: rv3029: Add ...
656
  }
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
657
  #ifdef CONFIG_RTC_DRV_RV3029_HWMON
e6e380821   Mylène Josserand   rtc: rv3029: conv...
658
  static int rv3029_read_temp(struct device *dev, int *temp_mC)
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
659
660
661
  {
  	int ret;
  	u8 temp;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
662
  	ret = rv3029_read_regs(dev, RV3029_TEMP_PAGE, &temp, 1);
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
663
664
665
666
667
668
669
670
671
672
673
674
  	if (ret < 0)
  		return ret;
  
  	*temp_mC = ((int)temp - 60) * 1000;
  
  	return 0;
  }
  
  static ssize_t rv3029_hwmon_show_temp(struct device *dev,
  				      struct device_attribute *attr,
  				      char *buf)
  {
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
675
  	int ret, temp_mC;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
676
  	ret = rv3029_read_temp(dev, &temp_mC);
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
677
678
679
680
681
682
683
684
685
686
687
688
  	if (ret < 0)
  		return ret;
  
  	return sprintf(buf, "%d
  ", temp_mC);
  }
  
  static ssize_t rv3029_hwmon_set_update_interval(struct device *dev,
  						struct device_attribute *attr,
  						const char *buf,
  						size_t count)
  {
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
689
690
691
692
693
694
695
696
697
698
699
700
701
  	unsigned long interval_ms;
  	int ret;
  	u8 th_set_bits = 0;
  
  	ret = kstrtoul(buf, 10, &interval_ms);
  	if (ret < 0)
  		return ret;
  
  	if (interval_ms != 0) {
  		th_set_bits |= RV3029_EECTRL_THE;
  		if (interval_ms >= 16000)
  			th_set_bits |= RV3029_EECTRL_THP;
  	}
e6e380821   Mylène Josserand   rtc: rv3029: conv...
702
  	ret = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
703
704
705
706
707
708
709
710
711
712
713
714
  					RV3029_EECTRL_THE | RV3029_EECTRL_THP,
  					th_set_bits);
  	if (ret < 0)
  		return ret;
  
  	return count;
  }
  
  static ssize_t rv3029_hwmon_show_update_interval(struct device *dev,
  						 struct device_attribute *attr,
  						 char *buf)
  {
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
715
716
  	int ret, interval_ms;
  	u8 eectrl;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
717
  	ret = rv3029_eeprom_read(dev, RV3029_CONTROL_E2P_EECTRL,
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  				 &eectrl, 1);
  	if (ret < 0)
  		return ret;
  
  	if (eectrl & RV3029_EECTRL_THE) {
  		if (eectrl & RV3029_EECTRL_THP)
  			interval_ms = 16000;
  		else
  			interval_ms = 1000;
  	} else {
  		interval_ms = 0;
  	}
  
  	return sprintf(buf, "%d
  ", interval_ms);
  }
  
  static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, rv3029_hwmon_show_temp,
  			  NULL, 0);
  static SENSOR_DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO,
  			  rv3029_hwmon_show_update_interval,
  			  rv3029_hwmon_set_update_interval, 0);
  
  static struct attribute *rv3029_hwmon_attrs[] = {
  	&sensor_dev_attr_temp1_input.dev_attr.attr,
  	&sensor_dev_attr_update_interval.dev_attr.attr,
  	NULL,
  };
  ATTRIBUTE_GROUPS(rv3029_hwmon);
e6e380821   Mylène Josserand   rtc: rv3029: conv...
747
  static void rv3029_hwmon_register(struct device *dev, const char *name)
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
748
  {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
749
  	struct rv3029_data *rv3029 = dev_get_drvdata(dev);
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
750
  	struct device *hwmon_dev;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
751
752
  	hwmon_dev = devm_hwmon_device_register_with_groups(dev, name, rv3029,
  							   rv3029_hwmon_groups);
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
753
  	if (IS_ERR(hwmon_dev)) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
754
755
  		dev_warn(dev, "unable to register hwmon device %ld
  ",
4e7f1a605   Mylène Josserand   rtc: rv3029: remo...
756
  			 PTR_ERR(hwmon_dev));
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
757
758
759
760
  	}
  }
  
  #else /* CONFIG_RTC_DRV_RV3029_HWMON */
e6e380821   Mylène Josserand   rtc: rv3029: conv...
761
  static void rv3029_hwmon_register(struct device *dev, const char *name)
a696b31e2   Michael Buesch   rtc: rv3029: Add ...
762
763
764
765
  {
  }
  
  #endif /* CONFIG_RTC_DRV_RV3029_HWMON */
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
766
  static struct rtc_class_ops rv3029_rtc_ops = {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
767
768
  	.read_time	= rv3029_read_time,
  	.set_time	= rv3029_set_time,
52365230e   Heiko Schocher   rtc: add rv3029c2...
769
  };
e6e380821   Mylène Josserand   rtc: rv3029: conv...
770
771
  static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,
  			const char *name)
52365230e   Heiko Schocher   rtc: add rv3029c2...
772
  {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
773
  	struct rv3029_data *rv3029;
52365230e   Heiko Schocher   rtc: add rv3029c2...
774
775
  	int rc = 0;
  	u8 buf[1];
e6e380821   Mylène Josserand   rtc: rv3029: conv...
776
777
778
779
780
781
782
783
  	rv3029 = devm_kzalloc(dev, sizeof(*rv3029), GFP_KERNEL);
  	if (!rv3029)
  		return -ENOMEM;
  
  	rv3029->regmap = regmap;
  	rv3029->irq = irq;
  	rv3029->dev = dev;
  	dev_set_drvdata(dev, rv3029);
52365230e   Heiko Schocher   rtc: add rv3029c2...
784

e6e380821   Mylène Josserand   rtc: rv3029: conv...
785
  	rc = rv3029_get_sr(dev, buf);
67ab2440b   Gregory Hermant   drivers/rtc/rtc-r...
786
  	if (rc < 0) {
e6e380821   Mylène Josserand   rtc: rv3029: conv...
787
788
  		dev_err(dev, "reading status failed
  ");
67ab2440b   Gregory Hermant   drivers/rtc/rtc-r...
789
790
  		return rc;
  	}
e6e380821   Mylène Josserand   rtc: rv3029: conv...
791
792
793
794
795
  	rv3029_trickle_config(dev);
  	rv3029_hwmon_register(dev, name);
  
  	rv3029->rtc = devm_rtc_device_register(dev, name, &rv3029_rtc_ops,
  					       THIS_MODULE);
0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
796
797
798
799
800
  	if (IS_ERR(rv3029->rtc)) {
  		dev_err(dev, "unable to register the class device
  ");
  		return PTR_ERR(rv3029->rtc);
  	}
e27e21603   Michael Buesch   rtc: rv3029: Add ...
801

0ddc5b89c   Mylène Josserand   rtc: rv3029: add ...
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
  	if (rv3029->irq > 0) {
  		rc = devm_request_threaded_irq(dev, rv3029->irq,
  					       NULL, rv3029_handle_irq,
  					       IRQF_TRIGGER_LOW | IRQF_ONESHOT,
  					       "rv3029", dev);
  		if (rc) {
  			dev_warn(dev, "unable to request IRQ, alarms disabled
  ");
  			rv3029->irq = 0;
  		} else {
  			rv3029_rtc_ops.read_alarm = rv3029_read_alarm;
  			rv3029_rtc_ops.set_alarm = rv3029_set_alarm;
  			rv3029_rtc_ops.alarm_irq_enable = rv3029_alarm_irq_enable;
  		}
  	}
  
  	return 0;
e6e380821   Mylène Josserand   rtc: rv3029: conv...
819
  }
52365230e   Heiko Schocher   rtc: add rv3029c2...
820

c2a1c1454   Mylène Josserand   rtc: rv3029: Add ...
821
  #if IS_ENABLED(CONFIG_I2C)
e6e380821   Mylène Josserand   rtc: rv3029: conv...
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
  static int rv3029_i2c_probe(struct i2c_client *client,
  			    const struct i2c_device_id *id)
  {
  	struct regmap *regmap;
  	static const struct regmap_config config = {
  		.reg_bits = 8,
  		.val_bits = 8,
  	};
  
  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK |
  				     I2C_FUNC_SMBUS_BYTE)) {
  		dev_err(&client->dev, "Adapter does not support SMBUS_I2C_BLOCK or SMBUS_I2C_BYTE
  ");
  		return -ENODEV;
  	}
52365230e   Heiko Schocher   rtc: add rv3029c2...
837

e6e380821   Mylène Josserand   rtc: rv3029: conv...
838
839
840
841
842
843
844
  	regmap = devm_regmap_init_i2c(client, &config);
  	if (IS_ERR(regmap)) {
  		dev_err(&client->dev, "%s: regmap allocation failed: %ld
  ",
  			__func__, PTR_ERR(regmap));
  		return PTR_ERR(regmap);
  	}
52365230e   Heiko Schocher   rtc: add rv3029c2...
845

e6e380821   Mylène Josserand   rtc: rv3029: conv...
846
  	return rv3029_probe(&client->dev, regmap, client->irq, client->name);
52365230e   Heiko Schocher   rtc: add rv3029c2...
847
  }
814db2bc4   Arnd Bergmann   rtc: rv3029: hide...
848
849
850
851
852
853
  static struct i2c_device_id rv3029_id[] = {
  	{ "rv3029", 0 },
  	{ "rv3029c2", 0 },
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, rv3029_id);
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
854
  static struct i2c_driver rv3029_driver = {
52365230e   Heiko Schocher   rtc: add rv3029c2...
855
856
857
  	.driver = {
  		.name = "rtc-rv3029c2",
  	},
e6e380821   Mylène Josserand   rtc: rv3029: conv...
858
  	.probe		= rv3029_i2c_probe,
aba39d27b   Michael Buesch   rtc: rv3029: Remo...
859
  	.id_table	= rv3029_id,
52365230e   Heiko Schocher   rtc: add rv3029c2...
860
  };
c2a1c1454   Mylène Josserand   rtc: rv3029: Add ...
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
  static int rv3029_register_driver(void)
  {
  	return i2c_add_driver(&rv3029_driver);
  }
  
  static void rv3029_unregister_driver(void)
  {
  	i2c_del_driver(&rv3029_driver);
  }
  
  #else
  
  static int rv3029_register_driver(void)
  {
  	return 0;
  }
  
  static void rv3029_unregister_driver(void)
  {
  }
  
  #endif
  
  #if IS_ENABLED(CONFIG_SPI_MASTER)
  
  static int rv3049_probe(struct spi_device *spi)
  {
  	static const struct regmap_config config = {
  		.reg_bits = 8,
  		.val_bits = 8,
  	};
  	struct regmap *regmap;
  
  	regmap = devm_regmap_init_spi(spi, &config);
  	if (IS_ERR(regmap)) {
  		dev_err(&spi->dev, "%s: regmap allocation failed: %ld
  ",
  			__func__, PTR_ERR(regmap));
  		return PTR_ERR(regmap);
  	}
  
  	return rv3029_probe(&spi->dev, regmap, spi->irq, "rv3049");
  }
  
  static struct spi_driver rv3049_driver = {
  	.driver = {
  		.name    = "rv3049",
  	},
  	.probe   = rv3049_probe,
  };
  
  static int rv3049_register_driver(void)
  {
  	return spi_register_driver(&rv3049_driver);
  }
  
  static void rv3049_unregister_driver(void)
  {
  	spi_unregister_driver(&rv3049_driver);
  }
  
  #else
  
  static int rv3049_register_driver(void)
  {
  	return 0;
  }
  
  static void rv3049_unregister_driver(void)
  {
  }
  
  #endif
  
  static int __init rv30x9_init(void)
  {
  	int ret;
  
  	ret = rv3029_register_driver();
  	if (ret) {
  		pr_err("Failed to register rv3029 driver: %d
  ", ret);
  		return ret;
  	}
  
  	ret = rv3049_register_driver();
  	if (ret) {
  		pr_err("Failed to register rv3049 driver: %d
  ", ret);
  		rv3029_unregister_driver();
  	}
  
  	return ret;
  }
  module_init(rv30x9_init)
  
  static void __exit rv30x9_exit(void)
  {
  	rv3049_unregister_driver();
  	rv3029_unregister_driver();
  }
  module_exit(rv30x9_exit)
52365230e   Heiko Schocher   rtc: add rv3029c2...
963
964
  
  MODULE_AUTHOR("Gregory Hermant <gregory.hermant@calao-systems.com>");
2dca3d9e1   Michael Buesch   rtc: rv3029: Add ...
965
  MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
c2a1c1454   Mylène Josserand   rtc: rv3029: Add ...
966
  MODULE_DESCRIPTION("Micro Crystal RV3029/RV3049 RTC driver");
52365230e   Heiko Schocher   rtc: add rv3029c2...
967
  MODULE_LICENSE("GPL");
c2a1c1454   Mylène Josserand   rtc: rv3029: Add ...
968
  MODULE_ALIAS("spi:rv3049");