Blame view

drivers/rtc/rtc-ds1307.c 24.5 KB
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
1
2
3
4
5
  /*
   * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips.
   *
   *  Copyright (C) 2005 James Chapman (ds1337 core)
   *  Copyright (C) 2006 David Brownell
a21668581   Matthias Fuchs   rtc: add EPSON RX...
6
   *  Copyright (C) 2009 Matthias Fuchs (rx8025 support)
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   *
   * 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.
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/i2c.h>
  #include <linux/string.h>
  #include <linux/rtc.h>
  #include <linux/bcd.h>
  
  
  
  /* We can't determine type by probing, but if we expect pre-Linux code
   * to have set the chip up as a clock (turning on the oscillator and
   * setting the date and time), Linux can ignore the non-clock features.
   * That's a natural job for a factory or repair bench.
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
27
28
   */
  enum ds_type {
045e0e85f   David Brownell   rtc-ds1307 cleanups
29
30
31
32
33
  	ds_1307,
  	ds_1337,
  	ds_1338,
  	ds_1339,
  	ds_1340,
33df2ee1b   Joakim Tjernlund   rtc: rtc-ds1307 a...
34
  	ds_1388,
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
35
  	ds_3231,
045e0e85f   David Brownell   rtc-ds1307 cleanups
36
  	m41t00,
43fcb8155   David Anders   rtc: add initial ...
37
  	mcp7941x,
a21668581   Matthias Fuchs   rtc: add EPSON RX...
38
  	rx_8025,
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
39
40
  	// rs5c372 too?  different address...
  };
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
41
42
43
44
  
  /* RTC registers don't differ much, except for the century flag */
  #define DS1307_REG_SECS		0x00	/* 00-59 */
  #	define DS1307_BIT_CH		0x80
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
45
  #	define DS1340_BIT_nEOSC		0x80
43fcb8155   David Anders   rtc: add initial ...
46
  #	define MCP7941X_BIT_ST		0x80
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
47
48
  #define DS1307_REG_MIN		0x01	/* 00-59 */
  #define DS1307_REG_HOUR		0x02	/* 00-23, or 1-12{am,pm} */
c065f35c1   David Brownell   rtc-ds1307 become...
49
50
  #	define DS1307_BIT_12HR		0x40	/* in REG_HOUR */
  #	define DS1307_BIT_PM		0x20	/* in REG_HOUR */
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
51
52
53
  #	define DS1340_BIT_CENTURY_EN	0x80	/* in REG_HOUR */
  #	define DS1340_BIT_CENTURY	0x40	/* in REG_HOUR */
  #define DS1307_REG_WDAY		0x03	/* 01-07 */
43fcb8155   David Anders   rtc: add initial ...
54
  #	define MCP7941X_BIT_VBATEN	0x08
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
55
56
57
58
59
60
  #define DS1307_REG_MDAY		0x04	/* 01-31 */
  #define DS1307_REG_MONTH	0x05	/* 01-12 */
  #	define DS1337_BIT_CENTURY	0x80	/* in REG_MONTH */
  #define DS1307_REG_YEAR		0x06	/* 00-99 */
  
  /* Other registers (control, status, alarms, trickle charge, NVRAM, etc)
045e0e85f   David Brownell   rtc-ds1307 cleanups
61
62
   * start at 7, and they differ a LOT. Only control and status matter for
   * basic RTC date and time functionality; be careful using them.
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
63
   */
045e0e85f   David Brownell   rtc-ds1307 cleanups
64
  #define DS1307_REG_CONTROL	0x07		/* or ds1338 */
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
65
  #	define DS1307_BIT_OUT		0x80
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
66
  #	define DS1338_BIT_OSF		0x20
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
67
68
69
70
71
  #	define DS1307_BIT_SQWE		0x10
  #	define DS1307_BIT_RS1		0x02
  #	define DS1307_BIT_RS0		0x01
  #define DS1337_REG_CONTROL	0x0e
  #	define DS1337_BIT_nEOSC		0x80
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
72
  #	define DS1339_BIT_BBSQI		0x20
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
73
  #	define DS3231_BIT_BBSQW		0x40 /* same as BBSQI */
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
74
75
76
77
78
  #	define DS1337_BIT_RS2		0x10
  #	define DS1337_BIT_RS1		0x08
  #	define DS1337_BIT_INTCN		0x04
  #	define DS1337_BIT_A2IE		0x02
  #	define DS1337_BIT_A1IE		0x01
045e0e85f   David Brownell   rtc-ds1307 cleanups
79
80
81
82
83
  #define DS1340_REG_CONTROL	0x07
  #	define DS1340_BIT_OUT		0x80
  #	define DS1340_BIT_FT		0x40
  #	define DS1340_BIT_CALIB_SIGN	0x20
  #	define DS1340_M_CALIBRATION	0x1f
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
84
85
  #define DS1340_REG_FLAG		0x09
  #	define DS1340_BIT_OSF		0x80
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
86
87
88
89
  #define DS1337_REG_STATUS	0x0f
  #	define DS1337_BIT_OSF		0x80
  #	define DS1337_BIT_A2I		0x02
  #	define DS1337_BIT_A1I		0x01
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
90
  #define DS1339_REG_ALARM1_SECS	0x07
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
91
  #define DS1339_REG_TRICKLE	0x10
a21668581   Matthias Fuchs   rtc: add EPSON RX...
92
93
94
95
96
97
  #define RX8025_REG_CTRL1	0x0e
  #	define RX8025_BIT_2412		0x20
  #define RX8025_REG_CTRL2	0x0f
  #	define RX8025_BIT_PON		0x10
  #	define RX8025_BIT_VDET		0x40
  #	define RX8025_BIT_XST		0x20
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
98
99
100
  
  
  struct ds1307 {
33df2ee1b   Joakim Tjernlund   rtc: rtc-ds1307 a...
101
  	u8			offset; /* register's offset */
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
102
  	u8			regs[11];
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
103
  	enum ds_type		type;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
104
105
106
  	unsigned long		flags;
  #define HAS_NVRAM	0		/* bit 0 == sysfs file active */
  #define HAS_ALARM	1		/* bit 1 == irq claimed */
045e0e85f   David Brownell   rtc-ds1307 cleanups
107
  	struct i2c_client	*client;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
108
  	struct rtc_device	*rtc;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
109
  	struct work_struct	work;
0cc43a180   Jean Delvare   i2c: Constify i2c...
110
  	s32 (*read_block_data)(const struct i2c_client *client, u8 command,
30e7b039b   Ed Swierk   rtc-ds1307: true ...
111
  			       u8 length, u8 *values);
0cc43a180   Jean Delvare   i2c: Constify i2c...
112
  	s32 (*write_block_data)(const struct i2c_client *client, u8 command,
30e7b039b   Ed Swierk   rtc-ds1307: true ...
113
  				u8 length, const u8 *values);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
114
  };
045e0e85f   David Brownell   rtc-ds1307 cleanups
115
  struct chip_desc {
045e0e85f   David Brownell   rtc-ds1307 cleanups
116
117
  	unsigned		nvram56:1;
  	unsigned		alarm:1;
045e0e85f   David Brownell   rtc-ds1307 cleanups
118
  };
3760f7367   Jean Delvare   i2c: Convert most...
119
120
  static const struct chip_desc chips[] = {
  [ds_1307] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
121
  	.nvram56	= 1,
3760f7367   Jean Delvare   i2c: Convert most...
122
123
  },
  [ds_1337] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
124
  	.alarm		= 1,
3760f7367   Jean Delvare   i2c: Convert most...
125
126
  },
  [ds_1338] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
127
  	.nvram56	= 1,
3760f7367   Jean Delvare   i2c: Convert most...
128
129
  },
  [ds_1339] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
130
  	.alarm		= 1,
3760f7367   Jean Delvare   i2c: Convert most...
131
132
133
  },
  [ds_1340] = {
  },
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
134
135
136
  [ds_3231] = {
  	.alarm		= 1,
  },
3760f7367   Jean Delvare   i2c: Convert most...
137
  [m41t00] = {
a21668581   Matthias Fuchs   rtc: add EPSON RX...
138
  },
43fcb8155   David Anders   rtc: add initial ...
139
140
  [mcp7941x] = {
  },
a21668581   Matthias Fuchs   rtc: add EPSON RX...
141
  [rx_8025] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
142
  }, };
3760f7367   Jean Delvare   i2c: Convert most...
143
144
145
146
147
  static const struct i2c_device_id ds1307_id[] = {
  	{ "ds1307", ds_1307 },
  	{ "ds1337", ds_1337 },
  	{ "ds1338", ds_1338 },
  	{ "ds1339", ds_1339 },
33df2ee1b   Joakim Tjernlund   rtc: rtc-ds1307 a...
148
  	{ "ds1388", ds_1388 },
3760f7367   Jean Delvare   i2c: Convert most...
149
  	{ "ds1340", ds_1340 },
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
150
  	{ "ds3231", ds_3231 },
3760f7367   Jean Delvare   i2c: Convert most...
151
  	{ "m41t00", m41t00 },
43fcb8155   David Anders   rtc: add initial ...
152
  	{ "mcp7941x", mcp7941x },
31c1771cd   Priyanka Jain   drivers/rtc/rtc-d...
153
  	{ "pt7c4338", ds_1307 },
a21668581   Matthias Fuchs   rtc: add EPSON RX...
154
  	{ "rx8025", rx_8025 },
3760f7367   Jean Delvare   i2c: Convert most...
155
156
157
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, ds1307_id);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
158

cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
159
  /*----------------------------------------------------------------------*/
30e7b039b   Ed Swierk   rtc-ds1307: true ...
160
  #define BLOCK_DATA_MAX_TRIES 10
0cc43a180   Jean Delvare   i2c: Constify i2c...
161
162
  static s32 ds1307_read_block_data_once(const struct i2c_client *client,
  				       u8 command, u8 length, u8 *values)
30e7b039b   Ed Swierk   rtc-ds1307: true ...
163
164
165
166
167
168
169
170
171
172
173
  {
  	s32 i, data;
  
  	for (i = 0; i < length; i++) {
  		data = i2c_smbus_read_byte_data(client, command + i);
  		if (data < 0)
  			return data;
  		values[i] = data;
  	}
  	return i;
  }
0cc43a180   Jean Delvare   i2c: Constify i2c...
174
  static s32 ds1307_read_block_data(const struct i2c_client *client, u8 command,
30e7b039b   Ed Swierk   rtc-ds1307: true ...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  				  u8 length, u8 *values)
  {
  	u8 oldvalues[I2C_SMBUS_BLOCK_MAX];
  	s32 ret;
  	int tries = 0;
  
  	dev_dbg(&client->dev, "ds1307_read_block_data (length=%d)
  ", length);
  	ret = ds1307_read_block_data_once(client, command, length, values);
  	if (ret < 0)
  		return ret;
  	do {
  		if (++tries > BLOCK_DATA_MAX_TRIES) {
  			dev_err(&client->dev,
  				"ds1307_read_block_data failed
  ");
  			return -EIO;
  		}
  		memcpy(oldvalues, values, length);
  		ret = ds1307_read_block_data_once(client, command, length,
  						  values);
  		if (ret < 0)
  			return ret;
  	} while (memcmp(oldvalues, values, length));
  	return length;
  }
0cc43a180   Jean Delvare   i2c: Constify i2c...
201
  static s32 ds1307_write_block_data(const struct i2c_client *client, u8 command,
30e7b039b   Ed Swierk   rtc-ds1307: true ...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  				   u8 length, const u8 *values)
  {
  	u8 currvalues[I2C_SMBUS_BLOCK_MAX];
  	int tries = 0;
  
  	dev_dbg(&client->dev, "ds1307_write_block_data (length=%d)
  ", length);
  	do {
  		s32 i, ret;
  
  		if (++tries > BLOCK_DATA_MAX_TRIES) {
  			dev_err(&client->dev,
  				"ds1307_write_block_data failed
  ");
  			return -EIO;
  		}
  		for (i = 0; i < length; i++) {
  			ret = i2c_smbus_write_byte_data(client, command + i,
  							values[i]);
  			if (ret < 0)
  				return ret;
  		}
  		ret = ds1307_read_block_data_once(client, command, length,
  						  currvalues);
  		if (ret < 0)
  			return ret;
  	} while (memcmp(currvalues, values, length));
  	return length;
  }
  
  /*----------------------------------------------------------------------*/
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
  /*
   * The IRQ logic includes a "real" handler running in IRQ context just
   * long enough to schedule this workqueue entry.   We need a task context
   * to talk to the RTC, since I2C I/O calls require that; and disable the
   * IRQ until we clear its status on the chip, so that this handler can
   * work with any type of triggering (not just falling edge).
   *
   * The ds1337 and ds1339 both have two alarms, but we only use the first
   * one (with a "seconds" field).  For ds1337 we expect nINTA is our alarm
   * signal; ds1339 chips have only one alarm signal.
   */
  static void ds1307_work(struct work_struct *work)
  {
  	struct ds1307		*ds1307;
  	struct i2c_client	*client;
  	struct mutex		*lock;
  	int			stat, control;
  
  	ds1307 = container_of(work, struct ds1307, work);
  	client = ds1307->client;
  	lock = &ds1307->rtc->ops_lock;
  
  	mutex_lock(lock);
  	stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
  	if (stat < 0)
  		goto out;
  
  	if (stat & DS1337_BIT_A1I) {
  		stat &= ~DS1337_BIT_A1I;
  		i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, stat);
  
  		control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
  		if (control < 0)
  			goto out;
  
  		control &= ~DS1337_BIT_A1IE;
  		i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
270
  		rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
  	}
  
  out:
  	if (test_bit(HAS_ALARM, &ds1307->flags))
  		enable_irq(client->irq);
  	mutex_unlock(lock);
  }
  
  static irqreturn_t ds1307_irq(int irq, void *dev_id)
  {
  	struct i2c_client	*client = dev_id;
  	struct ds1307		*ds1307 = i2c_get_clientdata(client);
  
  	disable_irq_nosync(irq);
  	schedule_work(&ds1307->work);
  	return IRQ_HANDLED;
  }
  
  /*----------------------------------------------------------------------*/
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
290
291
292
293
  static int ds1307_get_time(struct device *dev, struct rtc_time *t)
  {
  	struct ds1307	*ds1307 = dev_get_drvdata(dev);
  	int		tmp;
045e0e85f   David Brownell   rtc-ds1307 cleanups
294
  	/* read the RTC date and time registers all at once */
30e7b039b   Ed Swierk   rtc-ds1307: true ...
295
  	tmp = ds1307->read_block_data(ds1307->client,
33df2ee1b   Joakim Tjernlund   rtc: rtc-ds1307 a...
296
  		ds1307->offset, 7, ds1307->regs);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
297
  	if (tmp != 7) {
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
298
299
300
301
302
303
304
305
306
307
308
309
  		dev_err(dev, "%s error %d
  ", "read", tmp);
  		return -EIO;
  	}
  
  	dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x
  ",
  			"read",
  			ds1307->regs[0], ds1307->regs[1],
  			ds1307->regs[2], ds1307->regs[3],
  			ds1307->regs[4], ds1307->regs[5],
  			ds1307->regs[6]);
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
310
311
  	t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);
  	t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
312
  	tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
313
314
315
  	t->tm_hour = bcd2bin(tmp);
  	t->tm_wday = bcd2bin(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;
  	t->tm_mday = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
316
  	tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
317
  	t->tm_mon = bcd2bin(tmp) - 1;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
318
319
  
  	/* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
320
  	t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
321
322
323
324
325
326
327
  
  	dev_dbg(dev, "%s secs=%d, mins=%d, "
  		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d
  ",
  		"read", t->tm_sec, t->tm_min,
  		t->tm_hour, t->tm_mday,
  		t->tm_mon, t->tm_year, t->tm_wday);
045e0e85f   David Brownell   rtc-ds1307 cleanups
328
329
  	/* initial clock setting can be undefined */
  	return rtc_valid_tm(t);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
330
331
332
333
334
335
336
337
338
339
340
341
  }
  
  static int ds1307_set_time(struct device *dev, struct rtc_time *t)
  {
  	struct ds1307	*ds1307 = dev_get_drvdata(dev);
  	int		result;
  	int		tmp;
  	u8		*buf = ds1307->regs;
  
  	dev_dbg(dev, "%s secs=%d, mins=%d, "
  		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d
  ",
11966adc3   Jeff Garzik   [PATCH] RTC: buil...
342
343
344
  		"write", t->tm_sec, t->tm_min,
  		t->tm_hour, t->tm_mday,
  		t->tm_mon, t->tm_year, t->tm_wday);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
345

fe20ba70a   Adrian Bunk   drivers/rtc/: use...
346
347
348
349
350
351
  	buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec);
  	buf[DS1307_REG_MIN] = bin2bcd(t->tm_min);
  	buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
  	buf[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
  	buf[DS1307_REG_MDAY] = bin2bcd(t->tm_mday);
  	buf[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
352
353
354
  
  	/* assume 20YY not 19YY */
  	tmp = t->tm_year - 100;
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
355
  	buf[DS1307_REG_YEAR] = bin2bcd(tmp);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
356

be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
357
358
359
  	switch (ds1307->type) {
  	case ds_1337:
  	case ds_1339:
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
360
  	case ds_3231:
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
361
  		buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
362
363
  		break;
  	case ds_1340:
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
364
365
  		buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
  				| DS1340_BIT_CENTURY;
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
366
  		break;
43fcb8155   David Anders   rtc: add initial ...
367
368
369
370
  	case mcp7941x:
  		buf[DS1307_REG_SECS] |= MCP7941X_BIT_ST;
  		buf[DS1307_REG_WDAY] |= MCP7941X_BIT_VBATEN;
  		break;
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
371
372
373
  	default:
  		break;
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
374

1abb0dc92   David Brownell   [PATCH] "RTC-fram...
375
376
377
378
  	dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x
  ",
  		"write", buf[0], buf[1], buf[2], buf[3],
  		buf[4], buf[5], buf[6]);
33df2ee1b   Joakim Tjernlund   rtc: rtc-ds1307 a...
379
380
  	result = ds1307->write_block_data(ds1307->client,
  		ds1307->offset, 7, buf);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
381
382
383
384
  	if (result < 0) {
  		dev_err(dev, "%s error %d
  ", "write", result);
  		return result;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
385
386
387
  	}
  	return 0;
  }
74d88eb29   Jüri Reitel   rtc-ds1307: remov...
388
  static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
389
390
391
392
393
394
395
396
397
  {
  	struct i2c_client       *client = to_i2c_client(dev);
  	struct ds1307		*ds1307 = i2c_get_clientdata(client);
  	int			ret;
  
  	if (!test_bit(HAS_ALARM, &ds1307->flags))
  		return -EINVAL;
  
  	/* read all ALARM1, ALARM2, and status registers at once */
30e7b039b   Ed Swierk   rtc-ds1307: true ...
398
  	ret = ds1307->read_block_data(client,
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
399
400
  			DS1339_REG_ALARM1_SECS, 9, ds1307->regs);
  	if (ret != 9) {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
  		dev_err(dev, "%s error %d
  ", "alarm read", ret);
  		return -EIO;
  	}
  
  	dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x
  ",
  			"alarm read",
  			ds1307->regs[0], ds1307->regs[1],
  			ds1307->regs[2], ds1307->regs[3],
  			ds1307->regs[4], ds1307->regs[5],
  			ds1307->regs[6], ds1307->regs[7],
  			ds1307->regs[8]);
  
  	/* report alarm time (ALARM1); assume 24 hour and day-of-month modes,
  	 * and that all four fields are checked matches
  	 */
  	t->time.tm_sec = bcd2bin(ds1307->regs[0] & 0x7f);
  	t->time.tm_min = bcd2bin(ds1307->regs[1] & 0x7f);
  	t->time.tm_hour = bcd2bin(ds1307->regs[2] & 0x3f);
  	t->time.tm_mday = bcd2bin(ds1307->regs[3] & 0x3f);
  	t->time.tm_mon = -1;
  	t->time.tm_year = -1;
  	t->time.tm_wday = -1;
  	t->time.tm_yday = -1;
  	t->time.tm_isdst = -1;
  
  	/* ... and status */
  	t->enabled = !!(ds1307->regs[7] & DS1337_BIT_A1IE);
  	t->pending = !!(ds1307->regs[8] & DS1337_BIT_A1I);
  
  	dev_dbg(dev, "%s secs=%d, mins=%d, "
  		"hours=%d, mday=%d, enabled=%d, pending=%d
  ",
  		"alarm read", t->time.tm_sec, t->time.tm_min,
  		t->time.tm_hour, t->time.tm_mday,
  		t->enabled, t->pending);
  
  	return 0;
  }
74d88eb29   Jüri Reitel   rtc-ds1307: remov...
441
  static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
  {
  	struct i2c_client       *client = to_i2c_client(dev);
  	struct ds1307		*ds1307 = i2c_get_clientdata(client);
  	unsigned char		*buf = ds1307->regs;
  	u8			control, status;
  	int			ret;
  
  	if (!test_bit(HAS_ALARM, &ds1307->flags))
  		return -EINVAL;
  
  	dev_dbg(dev, "%s secs=%d, mins=%d, "
  		"hours=%d, mday=%d, enabled=%d, pending=%d
  ",
  		"alarm set", t->time.tm_sec, t->time.tm_min,
  		t->time.tm_hour, t->time.tm_mday,
  		t->enabled, t->pending);
  
  	/* read current status of both alarms and the chip */
30e7b039b   Ed Swierk   rtc-ds1307: true ...
460
  	ret = ds1307->read_block_data(client,
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
461
462
  			DS1339_REG_ALARM1_SECS, 9, buf);
  	if (ret != 9) {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
  		dev_err(dev, "%s error %d
  ", "alarm write", ret);
  		return -EIO;
  	}
  	control = ds1307->regs[7];
  	status = ds1307->regs[8];
  
  	dev_dbg(dev, "%s: %02x %02x %02x %02x, %02x %02x %02x, %02x %02x
  ",
  			"alarm set (old status)",
  			ds1307->regs[0], ds1307->regs[1],
  			ds1307->regs[2], ds1307->regs[3],
  			ds1307->regs[4], ds1307->regs[5],
  			ds1307->regs[6], control, status);
  
  	/* set ALARM1, using 24 hour and day-of-month modes */
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
  	buf[0] = bin2bcd(t->time.tm_sec);
  	buf[1] = bin2bcd(t->time.tm_min);
  	buf[2] = bin2bcd(t->time.tm_hour);
  	buf[3] = bin2bcd(t->time.tm_mday);
  
  	/* set ALARM2 to non-garbage */
  	buf[4] = 0;
  	buf[5] = 0;
  	buf[6] = 0;
  
  	/* optionally enable ALARM1 */
  	buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE);
  	if (t->enabled) {
  		dev_dbg(dev, "alarm IRQ armed
  ");
  		buf[7] |= DS1337_BIT_A1IE;	/* only ALARM1 is used */
  	}
  	buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I);
30e7b039b   Ed Swierk   rtc-ds1307: true ...
497
  	ret = ds1307->write_block_data(client,
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
498
499
  			DS1339_REG_ALARM1_SECS, 9, buf);
  	if (ret < 0) {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
500
501
  		dev_err(dev, "can't set alarm time
  ");
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
502
  		return ret;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
503
504
505
506
  	}
  
  	return 0;
  }
16380c153   John Stultz   RTC: Convert rtc ...
507
  static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
508
509
510
511
  {
  	struct i2c_client	*client = to_i2c_client(dev);
  	struct ds1307		*ds1307 = i2c_get_clientdata(client);
  	int			ret;
16380c153   John Stultz   RTC: Convert rtc ...
512
513
  	if (!test_bit(HAS_ALARM, &ds1307->flags))
  		return -ENOTTY;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
514

16380c153   John Stultz   RTC: Convert rtc ...
515
516
517
  	ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
  	if (ret < 0)
  		return ret;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
518

16380c153   John Stultz   RTC: Convert rtc ...
519
  	if (enabled)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
520
  		ret |= DS1337_BIT_A1IE;
16380c153   John Stultz   RTC: Convert rtc ...
521
522
  	else
  		ret &= ~DS1337_BIT_A1IE;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
523

16380c153   John Stultz   RTC: Convert rtc ...
524
525
526
  	ret = i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, ret);
  	if (ret < 0)
  		return ret;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
527
528
529
  
  	return 0;
  }
ff8371ac9   David Brownell   [PATCH] constify ...
530
  static const struct rtc_class_ops ds13xx_rtc_ops = {
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
531
532
  	.read_time	= ds1307_get_time,
  	.set_time	= ds1307_set_time,
74d88eb29   Jüri Reitel   rtc-ds1307: remov...
533
534
  	.read_alarm	= ds1337_read_alarm,
  	.set_alarm	= ds1337_set_alarm,
16380c153   John Stultz   RTC: Convert rtc ...
535
  	.alarm_irq_enable = ds1307_alarm_irq_enable,
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
536
  };
682d73f68   David Brownell   rtc-ds1307 export...
537
538
539
540
541
  /*----------------------------------------------------------------------*/
  
  #define NVRAM_SIZE	56
  
  static ssize_t
2c3c8bea6   Chris Wright   sysfs: add struct...
542
543
  ds1307_nvram_read(struct file *filp, struct kobject *kobj,
  		struct bin_attribute *attr,
682d73f68   David Brownell   rtc-ds1307 export...
544
545
546
547
  		char *buf, loff_t off, size_t count)
  {
  	struct i2c_client	*client;
  	struct ds1307		*ds1307;
682d73f68   David Brownell   rtc-ds1307 export...
548
  	int			result;
fcd8db002   frederic Rodo   rtc ds1307: ds_13...
549
  	client = kobj_to_i2c_client(kobj);
682d73f68   David Brownell   rtc-ds1307 export...
550
551
552
553
554
555
556
557
  	ds1307 = i2c_get_clientdata(client);
  
  	if (unlikely(off >= NVRAM_SIZE))
  		return 0;
  	if ((off + count) > NVRAM_SIZE)
  		count = NVRAM_SIZE - off;
  	if (unlikely(!count))
  		return count;
30e7b039b   Ed Swierk   rtc-ds1307: true ...
558
  	result = ds1307->read_block_data(client, 8 + off, count, buf);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
559
  	if (result < 0)
682d73f68   David Brownell   rtc-ds1307 export...
560
561
  		dev_err(&client->dev, "%s error %d
  ", "nvram read", result);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
562
  	return result;
682d73f68   David Brownell   rtc-ds1307 export...
563
564
565
  }
  
  static ssize_t
2c3c8bea6   Chris Wright   sysfs: add struct...
566
567
  ds1307_nvram_write(struct file *filp, struct kobject *kobj,
  		struct bin_attribute *attr,
682d73f68   David Brownell   rtc-ds1307 export...
568
569
570
  		char *buf, loff_t off, size_t count)
  {
  	struct i2c_client	*client;
30e7b039b   Ed Swierk   rtc-ds1307: true ...
571
  	struct ds1307		*ds1307;
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
572
  	int			result;
682d73f68   David Brownell   rtc-ds1307 export...
573

fcd8db002   frederic Rodo   rtc ds1307: ds_13...
574
  	client = kobj_to_i2c_client(kobj);
30e7b039b   Ed Swierk   rtc-ds1307: true ...
575
  	ds1307 = i2c_get_clientdata(client);
682d73f68   David Brownell   rtc-ds1307 export...
576
577
578
579
580
581
582
  
  	if (unlikely(off >= NVRAM_SIZE))
  		return -EFBIG;
  	if ((off + count) > NVRAM_SIZE)
  		count = NVRAM_SIZE - off;
  	if (unlikely(!count))
  		return count;
30e7b039b   Ed Swierk   rtc-ds1307: true ...
583
  	result = ds1307->write_block_data(client, 8 + off, count, buf);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
584
585
586
587
588
589
  	if (result < 0) {
  		dev_err(&client->dev, "%s error %d
  ", "nvram write", result);
  		return result;
  	}
  	return count;
682d73f68   David Brownell   rtc-ds1307 export...
590
591
592
593
594
595
  }
  
  static struct bin_attribute nvram = {
  	.attr = {
  		.name	= "nvram",
  		.mode	= S_IRUGO | S_IWUSR,
682d73f68   David Brownell   rtc-ds1307 export...
596
597
598
599
600
601
602
603
  	},
  
  	.read	= ds1307_nvram_read,
  	.write	= ds1307_nvram_write,
  	.size	= NVRAM_SIZE,
  };
  
  /*----------------------------------------------------------------------*/
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
604
  static struct i2c_driver ds1307_driver;
d2653e927   Jean Delvare   i2c: Add support ...
605
606
  static int __devinit ds1307_probe(struct i2c_client *client,
  				  const struct i2c_device_id *id)
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
607
608
609
  {
  	struct ds1307		*ds1307;
  	int			err = -ENODEV;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
610
  	int			tmp;
3760f7367   Jean Delvare   i2c: Convert most...
611
  	const struct chip_desc	*chip = &chips[id->driver_data];
c065f35c1   David Brownell   rtc-ds1307 become...
612
  	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
613
  	int			want_irq = false;
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
614
  	unsigned char		*buf;
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
615
616
617
618
619
  	static const int	bbsqi_bitpos[] = {
  		[ds_1337] = 0,
  		[ds_1339] = DS1339_BIT_BBSQI,
  		[ds_3231] = DS3231_BIT_BBSQW,
  	};
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
620

30e7b039b   Ed Swierk   rtc-ds1307: true ...
621
622
  	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)
  	    && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
c065f35c1   David Brownell   rtc-ds1307 become...
623
624
625
626
  		return -EIO;
  
  	if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL)))
  		return -ENOMEM;
045e0e85f   David Brownell   rtc-ds1307 cleanups
627

1abb0dc92   David Brownell   [PATCH] "RTC-fram...
628
  	i2c_set_clientdata(client, ds1307);
33df2ee1b   Joakim Tjernlund   rtc: rtc-ds1307 a...
629
630
631
632
  
  	ds1307->client	= client;
  	ds1307->type	= id->driver_data;
  	ds1307->offset	= 0;
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
633
  	buf = ds1307->regs;
30e7b039b   Ed Swierk   rtc-ds1307: true ...
634
635
636
637
638
639
640
  	if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
  		ds1307->read_block_data = i2c_smbus_read_i2c_block_data;
  		ds1307->write_block_data = i2c_smbus_write_i2c_block_data;
  	} else {
  		ds1307->read_block_data = ds1307_read_block_data;
  		ds1307->write_block_data = ds1307_write_block_data;
  	}
045e0e85f   David Brownell   rtc-ds1307 cleanups
641
642
643
644
  
  	switch (ds1307->type) {
  	case ds_1337:
  	case ds_1339:
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
645
  	case ds_3231:
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
646
647
648
649
650
  		/* has IRQ? */
  		if (ds1307->client->irq > 0 && chip->alarm) {
  			INIT_WORK(&ds1307->work, ds1307_work);
  			want_irq = true;
  		}
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
651
  		/* get registers that the "rtc" read below won't read... */
30e7b039b   Ed Swierk   rtc-ds1307: true ...
652
  		tmp = ds1307->read_block_data(ds1307->client,
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
653
  				DS1337_REG_CONTROL, 2, buf);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
654
655
656
657
658
659
  		if (tmp != 2) {
  			pr_debug("read error %d
  ", tmp);
  			err = -EIO;
  			goto exit_free;
  		}
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
660
661
  		/* oscillator off?  turn it on, so clock can tick. */
  		if (ds1307->regs[0] & DS1337_BIT_nEOSC)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
662
663
664
  			ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
  
  		/* Using IRQ?  Disable the square wave and both alarms.
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
665
666
  		 * For some variants, be sure alarms can trigger when we're
  		 * running on Vbackup (BBSQI/BBSQW)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
667
668
  		 */
  		if (want_irq) {
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
669
670
  			ds1307->regs[0] |= DS1337_BIT_INTCN
  					| bbsqi_bitpos[ds1307->type];
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
671
672
673
674
675
  			ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
  		}
  
  		i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
  							ds1307->regs[0]);
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
676
677
678
679
680
681
682
  
  		/* oscillator fault?  clear flag, and warn */
  		if (ds1307->regs[1] & DS1337_BIT_OSF) {
  			i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
  				ds1307->regs[1] & ~DS1337_BIT_OSF);
  			dev_warn(&client->dev, "SET TIME!
  ");
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
683
  		}
045e0e85f   David Brownell   rtc-ds1307 cleanups
684
  		break;
a21668581   Matthias Fuchs   rtc: add EPSON RX...
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
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
747
748
749
750
751
752
753
754
755
  
  	case rx_8025:
  		tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
  				RX8025_REG_CTRL1 << 4 | 0x08, 2, buf);
  		if (tmp != 2) {
  			pr_debug("read error %d
  ", tmp);
  			err = -EIO;
  			goto exit_free;
  		}
  
  		/* oscillator off?  turn it on, so clock can tick. */
  		if (!(ds1307->regs[1] & RX8025_BIT_XST)) {
  			ds1307->regs[1] |= RX8025_BIT_XST;
  			i2c_smbus_write_byte_data(client,
  						  RX8025_REG_CTRL2 << 4 | 0x08,
  						  ds1307->regs[1]);
  			dev_warn(&client->dev,
  				 "oscillator stop detected - SET TIME!
  ");
  		}
  
  		if (ds1307->regs[1] & RX8025_BIT_PON) {
  			ds1307->regs[1] &= ~RX8025_BIT_PON;
  			i2c_smbus_write_byte_data(client,
  						  RX8025_REG_CTRL2 << 4 | 0x08,
  						  ds1307->regs[1]);
  			dev_warn(&client->dev, "power-on detected
  ");
  		}
  
  		if (ds1307->regs[1] & RX8025_BIT_VDET) {
  			ds1307->regs[1] &= ~RX8025_BIT_VDET;
  			i2c_smbus_write_byte_data(client,
  						  RX8025_REG_CTRL2 << 4 | 0x08,
  						  ds1307->regs[1]);
  			dev_warn(&client->dev, "voltage drop detected
  ");
  		}
  
  		/* make sure we are running in 24hour mode */
  		if (!(ds1307->regs[0] & RX8025_BIT_2412)) {
  			u8 hour;
  
  			/* switch to 24 hour mode */
  			i2c_smbus_write_byte_data(client,
  						  RX8025_REG_CTRL1 << 4 | 0x08,
  						  ds1307->regs[0] |
  						  RX8025_BIT_2412);
  
  			tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
  					RX8025_REG_CTRL1 << 4 | 0x08, 2, buf);
  			if (tmp != 2) {
  				pr_debug("read error %d
  ", tmp);
  				err = -EIO;
  				goto exit_free;
  			}
  
  			/* correct hour */
  			hour = bcd2bin(ds1307->regs[DS1307_REG_HOUR]);
  			if (hour == 12)
  				hour = 0;
  			if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  				hour += 12;
  
  			i2c_smbus_write_byte_data(client,
  						  DS1307_REG_HOUR << 4 | 0x08,
  						  hour);
  		}
  		break;
33df2ee1b   Joakim Tjernlund   rtc: rtc-ds1307 a...
756
757
758
  	case ds_1388:
  		ds1307->offset = 1; /* Seconds starts at 1 */
  		break;
045e0e85f   David Brownell   rtc-ds1307 cleanups
759
760
761
  	default:
  		break;
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
762
763
764
  
  read_rtc:
  	/* read RTC registers */
96fc3a45e   Joakim Tjernlund   rtc: fix ds1388 t...
765
  	tmp = ds1307->read_block_data(ds1307->client, ds1307->offset, 8, buf);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
766
  	if (tmp != 8) {
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
767
768
769
770
771
772
773
774
775
776
777
  		pr_debug("read error %d
  ", tmp);
  		err = -EIO;
  		goto exit_free;
  	}
  
  	/* minimal sanity checking; some chips (like DS1340) don't
  	 * specify the extra bits as must-be-zero, but there are
  	 * still a few values that are clearly out-of-range.
  	 */
  	tmp = ds1307->regs[DS1307_REG_SECS];
045e0e85f   David Brownell   rtc-ds1307 cleanups
778
779
  	switch (ds1307->type) {
  	case ds_1307:
045e0e85f   David Brownell   rtc-ds1307 cleanups
780
  	case m41t00:
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
781
  		/* clock halted?  turn it on, so clock can tick. */
045e0e85f   David Brownell   rtc-ds1307 cleanups
782
  		if (tmp & DS1307_BIT_CH) {
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
783
784
785
  			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
  			dev_warn(&client->dev, "SET TIME!
  ");
045e0e85f   David Brownell   rtc-ds1307 cleanups
786
  			goto read_rtc;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
787
  		}
045e0e85f   David Brownell   rtc-ds1307 cleanups
788
  		break;
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
789
790
  	case ds_1338:
  		/* clock halted?  turn it on, so clock can tick. */
045e0e85f   David Brownell   rtc-ds1307 cleanups
791
  		if (tmp & DS1307_BIT_CH)
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
792
793
794
795
796
  			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
  
  		/* oscillator fault?  clear flag, and warn */
  		if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
  			i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL,
bd16f9ebd   David Brownell   rtc-ds1307: typo ...
797
  					ds1307->regs[DS1307_REG_CONTROL]
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
798
799
800
801
802
  					& ~DS1338_BIT_OSF);
  			dev_warn(&client->dev, "SET TIME!
  ");
  			goto read_rtc;
  		}
045e0e85f   David Brownell   rtc-ds1307 cleanups
803
  		break;
fcd8db002   frederic Rodo   rtc ds1307: ds_13...
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
  	case ds_1340:
  		/* clock halted?  turn it on, so clock can tick. */
  		if (tmp & DS1340_BIT_nEOSC)
  			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
  
  		tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG);
  		if (tmp < 0) {
  			pr_debug("read error %d
  ", tmp);
  			err = -EIO;
  			goto exit_free;
  		}
  
  		/* oscillator fault?  clear flag, and warn */
  		if (tmp & DS1340_BIT_OSF) {
  			i2c_smbus_write_byte_data(client, DS1340_REG_FLAG, 0);
  			dev_warn(&client->dev, "SET TIME!
  ");
  		}
  		break;
43fcb8155   David Anders   rtc: add initial ...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
  	case mcp7941x:
  		/* make sure that the backup battery is enabled */
  		if (!(ds1307->regs[DS1307_REG_WDAY] & MCP7941X_BIT_VBATEN)) {
  			i2c_smbus_write_byte_data(client, DS1307_REG_WDAY,
  					ds1307->regs[DS1307_REG_WDAY]
  					| MCP7941X_BIT_VBATEN);
  		}
  
  		/* clock halted?  turn it on, so clock can tick. */
  		if (!(tmp & MCP7941X_BIT_ST)) {
  			i2c_smbus_write_byte_data(client, DS1307_REG_SECS,
  					MCP7941X_BIT_ST);
  			dev_warn(&client->dev, "SET TIME!
  ");
  			goto read_rtc;
  		}
  
  		break;
a21668581   Matthias Fuchs   rtc: add EPSON RX...
842
  	case rx_8025:
c065f35c1   David Brownell   rtc-ds1307 become...
843
844
  	case ds_1337:
  	case ds_1339:
33df2ee1b   Joakim Tjernlund   rtc: rtc-ds1307 a...
845
  	case ds_1388:
97f902b7b   Wolfram Sang   rtc: rtc-ds1307 a...
846
  	case ds_3231:
045e0e85f   David Brownell   rtc-ds1307 cleanups
847
  		break;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
848
  	}
045e0e85f   David Brownell   rtc-ds1307 cleanups
849

1abb0dc92   David Brownell   [PATCH] "RTC-fram...
850
  	tmp = ds1307->regs[DS1307_REG_HOUR];
c065f35c1   David Brownell   rtc-ds1307 become...
851
852
853
854
855
856
857
  	switch (ds1307->type) {
  	case ds_1340:
  	case m41t00:
  		/* NOTE: ignores century bits; fix before deploying
  		 * systems that will run through year 2100.
  		 */
  		break;
a21668581   Matthias Fuchs   rtc: add EPSON RX...
858
859
  	case rx_8025:
  		break;
c065f35c1   David Brownell   rtc-ds1307 become...
860
861
862
863
864
865
866
  	default:
  		if (!(tmp & DS1307_BIT_12HR))
  			break;
  
  		/* Be sure we're in 24 hour mode.  Multi-master systems
  		 * take note...
  		 */
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
867
  		tmp = bcd2bin(tmp & 0x1f);
c065f35c1   David Brownell   rtc-ds1307 become...
868
869
870
871
  		if (tmp == 12)
  			tmp = 0;
  		if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  			tmp += 12;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
872
  		i2c_smbus_write_byte_data(client,
96fc3a45e   Joakim Tjernlund   rtc: fix ds1388 t...
873
  				ds1307->offset + DS1307_REG_HOUR,
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
874
  				bin2bcd(tmp));
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
875
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
876
877
878
879
880
881
882
  	ds1307->rtc = rtc_device_register(client->name, &client->dev,
  				&ds13xx_rtc_ops, THIS_MODULE);
  	if (IS_ERR(ds1307->rtc)) {
  		err = PTR_ERR(ds1307->rtc);
  		dev_err(&client->dev,
  			"unable to register the class device
  ");
c065f35c1   David Brownell   rtc-ds1307 become...
883
  		goto exit_free;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
884
  	}
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
885
  	if (want_irq) {
43d15bcd4   Dmitry Eremin-Solenikov   rtc: ds1307 make ...
886
  		err = request_irq(client->irq, ds1307_irq, IRQF_SHARED,
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
887
888
889
890
891
892
893
  			  ds1307->rtc->name, client);
  		if (err) {
  			dev_err(&client->dev,
  				"unable to request IRQ!
  ");
  			goto exit_irq;
  		}
26b3c01f7   Anton Vorontsov   rtc: set wakeup c...
894
895
  
  		device_set_wakeup_capable(&client->dev, 1);
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
896
897
898
899
  		set_bit(HAS_ALARM, &ds1307->flags);
  		dev_dbg(&client->dev, "got IRQ %d
  ", client->irq);
  	}
682d73f68   David Brownell   rtc-ds1307 export...
900
901
902
  	if (chip->nvram56) {
  		err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
  		if (err == 0) {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
903
  			set_bit(HAS_NVRAM, &ds1307->flags);
682d73f68   David Brownell   rtc-ds1307 export...
904
905
906
907
  			dev_info(&client->dev, "56 bytes nvram
  ");
  		}
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
908
  	return 0;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
909
  exit_irq:
72445af88   Julia Lawall   drivers/rtc: corr...
910
  	rtc_device_unregister(ds1307->rtc);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
911
912
  exit_free:
  	kfree(ds1307);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
913
914
  	return err;
  }
c065f35c1   David Brownell   rtc-ds1307 become...
915
  static int __devexit ds1307_remove(struct i2c_client *client)
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
916
  {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
917
918
919
920
921
922
  	struct ds1307		*ds1307 = i2c_get_clientdata(client);
  
  	if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) {
  		free_irq(client->irq, client);
  		cancel_work_sync(&ds1307->work);
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
923

cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
924
  	if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
682d73f68   David Brownell   rtc-ds1307 export...
925
  		sysfs_remove_bin_file(&client->dev.kobj, &nvram);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
926
  	rtc_device_unregister(ds1307->rtc);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
927
928
929
930
931
932
  	kfree(ds1307);
  	return 0;
  }
  
  static struct i2c_driver ds1307_driver = {
  	.driver = {
c065f35c1   David Brownell   rtc-ds1307 become...
933
  		.name	= "rtc-ds1307",
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
934
935
  		.owner	= THIS_MODULE,
  	},
c065f35c1   David Brownell   rtc-ds1307 become...
936
937
  	.probe		= ds1307_probe,
  	.remove		= __devexit_p(ds1307_remove),
3760f7367   Jean Delvare   i2c: Convert most...
938
  	.id_table	= ds1307_id,
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
  };
  
  static int __init ds1307_init(void)
  {
  	return i2c_add_driver(&ds1307_driver);
  }
  module_init(ds1307_init);
  
  static void __exit ds1307_exit(void)
  {
  	i2c_del_driver(&ds1307_driver);
  }
  module_exit(ds1307_exit);
  
  MODULE_DESCRIPTION("RTC driver for DS1307 and similar chips");
  MODULE_LICENSE("GPL");