22
22
#include <linux/slab.h>
23
23
#include <linux/mutex.h>
24
24
#include <linux/string.h>
25
+ #include <linux/delay.h>
25
26
#ifdef CONFIG_RTC_DRV_M41T80_WDT
26
27
#include <linux/fs.h>
27
28
#include <linux/ioctl.h>
@@ -204,7 +205,7 @@ static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
204
205
return flags ;
205
206
206
207
if (flags & M41T80_FLAGS_OF ) {
207
- dev_err (& client -> dev , "Oscillator failure, data is invalid .\n" );
208
+ dev_err (& client -> dev , "Oscillator failure, time may not be accurate, write time to RTC to fix it .\n" );
208
209
return - EINVAL ;
209
210
}
210
211
@@ -227,21 +228,31 @@ static int m41t80_rtc_read_time(struct device *dev, struct rtc_time *tm)
227
228
return 0 ;
228
229
}
229
230
230
- static int m41t80_rtc_set_time (struct device * dev , struct rtc_time * tm )
231
+ static int m41t80_rtc_set_time (struct device * dev , struct rtc_time * in_tm )
231
232
{
232
233
struct i2c_client * client = to_i2c_client (dev );
233
234
struct m41t80_data * clientdata = i2c_get_clientdata (client );
235
+ struct rtc_time tm = * in_tm ;
234
236
unsigned char buf [8 ];
235
237
int err , flags ;
238
+ time64_t time = 0 ;
236
239
240
+ flags = i2c_smbus_read_byte_data (client , M41T80_REG_FLAGS );
241
+ if (flags < 0 )
242
+ return flags ;
243
+ if (flags & M41T80_FLAGS_OF ) {
244
+ /* add 4sec of oscillator stablize time otherwise we are behind 4sec */
245
+ time = rtc_tm_to_time64 (& tm );
246
+ rtc_time64_to_tm (time + 4 , & tm );
247
+ }
237
248
buf [M41T80_REG_SSEC ] = 0 ;
238
- buf [M41T80_REG_SEC ] = bin2bcd (tm -> tm_sec );
239
- buf [M41T80_REG_MIN ] = bin2bcd (tm -> tm_min );
240
- buf [M41T80_REG_HOUR ] = bin2bcd (tm -> tm_hour );
241
- buf [M41T80_REG_DAY ] = bin2bcd (tm -> tm_mday );
242
- buf [M41T80_REG_MON ] = bin2bcd (tm -> tm_mon + 1 );
243
- buf [M41T80_REG_YEAR ] = bin2bcd (tm -> tm_year - 100 );
244
- buf [M41T80_REG_WDAY ] = tm -> tm_wday ;
249
+ buf [M41T80_REG_SEC ] = bin2bcd (tm . tm_sec );
250
+ buf [M41T80_REG_MIN ] = bin2bcd (tm . tm_min );
251
+ buf [M41T80_REG_HOUR ] = bin2bcd (tm . tm_hour );
252
+ buf [M41T80_REG_DAY ] = bin2bcd (tm . tm_mday );
253
+ buf [M41T80_REG_MON ] = bin2bcd (tm . tm_mon + 1 );
254
+ buf [M41T80_REG_YEAR ] = bin2bcd (tm . tm_year - 100 );
255
+ buf [M41T80_REG_WDAY ] = tm . tm_wday ;
245
256
246
257
/* If the square wave output is controlled in the weekday register */
247
258
if (clientdata -> features & M41T80_FEATURE_SQ_ALT ) {
@@ -260,17 +271,34 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm)
260
271
dev_err (& client -> dev , "Unable to write to date registers\n" );
261
272
return err ;
262
273
}
263
-
264
- /* Clear the OF bit of Flags Register */
265
- flags = i2c_smbus_read_byte_data (client , M41T80_REG_FLAGS );
266
- if (flags < 0 )
267
- return flags ;
268
-
269
- err = i2c_smbus_write_byte_data (client , M41T80_REG_FLAGS ,
270
- flags & ~M41T80_FLAGS_OF );
271
- if (err < 0 ) {
272
- dev_err (& client -> dev , "Unable to write flags register\n" );
273
- return err ;
274
+ if (flags & M41T80_FLAGS_OF ) {
275
+ /* OF cannot be immediately reset: oscillator has to be restarted. */
276
+ dev_warn (& client -> dev , "OF bit is still set, kickstarting clock.\n" );
277
+ err = i2c_smbus_write_byte_data (client , M41T80_REG_SEC , M41T80_SEC_ST );
278
+ if (err < 0 ) {
279
+ dev_err (& client -> dev , "Can't set ST bit\n" );
280
+ return err ;
281
+ }
282
+ err = i2c_smbus_write_byte_data (client , M41T80_REG_SEC , flags & ~M41T80_SEC_ST );
283
+ if (err < 0 ) {
284
+ dev_err (& client -> dev , "Can't clear ST bit\n" );
285
+ return err ;
286
+ }
287
+ /* oscillator must run for 4sec before we attempt to reset OF bit */
288
+ msleep (4000 );
289
+ /* Clear the OF bit of Flags Register */
290
+ err = i2c_smbus_write_byte_data (client , M41T80_REG_FLAGS , flags & ~M41T80_FLAGS_OF );
291
+ if (err < 0 ) {
292
+ dev_err (& client -> dev , "Unable to write flags register\n" );
293
+ return err ;
294
+ }
295
+ flags = i2c_smbus_read_byte_data (client , M41T80_REG_FLAGS );
296
+ if (flags < 0 ) {
297
+ return flags ;
298
+ } else if (flags & M41T80_FLAGS_OF ) {
299
+ dev_err (& client -> dev , "Can't clear the OF bit check battery\n" );
300
+ return err ;
301
+ }
274
302
}
275
303
276
304
return err ;
0 commit comments