Blame view

drivers/rtc/rtc-ds1307.c 19.3 KB
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  /*
   * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips.
   *
   *  Copyright (C) 2005 James Chapman (ds1337 core)
   *  Copyright (C) 2006 David Brownell
   *
   * 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...
26
27
   */
  enum ds_type {
045e0e85f   David Brownell   rtc-ds1307 cleanups
28
29
30
31
32
33
  	ds_1307,
  	ds_1337,
  	ds_1338,
  	ds_1339,
  	ds_1340,
  	m41t00,
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
34
35
  	// rs5c372 too?  different address...
  };
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
36
37
38
39
  
  /* 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...
40
  #	define DS1340_BIT_nEOSC		0x80
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
41
42
  #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...
43
44
  #	define DS1307_BIT_12HR		0x40	/* in REG_HOUR */
  #	define DS1307_BIT_PM		0x20	/* in REG_HOUR */
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
45
46
47
48
49
50
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 */
  #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
54
55
   * 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...
56
   */
045e0e85f   David Brownell   rtc-ds1307 cleanups
57
  #define DS1307_REG_CONTROL	0x07		/* or ds1338 */
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
58
  #	define DS1307_BIT_OUT		0x80
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
59
  #	define DS1338_BIT_OSF		0x20
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
60
61
62
63
64
  #	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...
65
  #	define DS1339_BIT_BBSQI		0x20
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
66
67
68
69
70
  #	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
71
72
73
74
75
  #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...
76
77
  #define DS1340_REG_FLAG		0x09
  #	define DS1340_BIT_OSF		0x80
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
78
79
80
81
  #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...
82
  #define DS1339_REG_ALARM1_SECS	0x07
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
83
84
85
86
87
  #define DS1339_REG_TRICKLE	0x10
  
  
  
  struct ds1307 {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
88
  	u8			regs[11];
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
89
  	enum ds_type		type;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
90
91
92
  	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
93
  	struct i2c_client	*client;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
94
  	struct rtc_device	*rtc;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
95
  	struct work_struct	work;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
96
  };
045e0e85f   David Brownell   rtc-ds1307 cleanups
97
  struct chip_desc {
045e0e85f   David Brownell   rtc-ds1307 cleanups
98
99
  	unsigned		nvram56:1;
  	unsigned		alarm:1;
045e0e85f   David Brownell   rtc-ds1307 cleanups
100
  };
3760f7367   Jean Delvare   i2c: Convert most...
101
102
  static const struct chip_desc chips[] = {
  [ds_1307] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
103
  	.nvram56	= 1,
3760f7367   Jean Delvare   i2c: Convert most...
104
105
  },
  [ds_1337] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
106
  	.alarm		= 1,
3760f7367   Jean Delvare   i2c: Convert most...
107
108
  },
  [ds_1338] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
109
  	.nvram56	= 1,
3760f7367   Jean Delvare   i2c: Convert most...
110
111
  },
  [ds_1339] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
112
  	.alarm		= 1,
3760f7367   Jean Delvare   i2c: Convert most...
113
114
115
116
  },
  [ds_1340] = {
  },
  [m41t00] = {
045e0e85f   David Brownell   rtc-ds1307 cleanups
117
  }, };
3760f7367   Jean Delvare   i2c: Convert most...
118
119
120
121
122
123
124
125
126
127
  static const struct i2c_device_id ds1307_id[] = {
  	{ "ds1307", ds_1307 },
  	{ "ds1337", ds_1337 },
  	{ "ds1338", ds_1338 },
  	{ "ds1339", ds_1339 },
  	{ "ds1340", ds_1340 },
  	{ "m41t00", m41t00 },
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, ds1307_id);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
128

cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
  /*----------------------------------------------------------------------*/
  
  /*
   * 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);
  
  		/* rtc_update_irq() assumes that it is called
  		 * from IRQ-disabled context.
  		 */
  		local_irq_disable();
  		rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
  		local_irq_enable();
  	}
  
  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...
194
195
196
197
  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
198
  	/* read the RTC date and time registers all at once */
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
199
200
201
  	tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
  		DS1307_REG_SECS, 7, ds1307->regs);
  	if (tmp != 7) {
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
202
203
204
205
206
207
208
209
210
211
212
213
  		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...
214
215
  	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...
216
  	tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
217
218
219
  	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...
220
  	tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
221
  	t->tm_mon = bcd2bin(tmp) - 1;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
222
223
  
  	/* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
224
  	t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
225
226
227
228
229
230
231
  
  	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
232
233
  	/* initial clock setting can be undefined */
  	return rtc_valid_tm(t);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
234
235
236
237
238
239
240
241
242
243
244
245
  }
  
  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...
246
247
248
  		"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...
249

fe20ba70a   Adrian Bunk   drivers/rtc/: use...
250
251
252
253
254
255
  	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...
256
257
258
  
  	/* assume 20YY not 19YY */
  	tmp = t->tm_year - 100;
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
259
  	buf[DS1307_REG_YEAR] = bin2bcd(tmp);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
260

be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
261
262
263
  	switch (ds1307->type) {
  	case ds_1337:
  	case ds_1339:
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
264
  		buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
265
266
  		break;
  	case ds_1340:
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
267
268
  		buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
  				| DS1340_BIT_CENTURY;
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
269
270
271
272
  		break;
  	default:
  		break;
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
273

1abb0dc92   David Brownell   [PATCH] "RTC-fram...
274
275
276
277
  	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]);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
278
279
280
281
282
  	result = i2c_smbus_write_i2c_block_data(ds1307->client, 0, 7, buf);
  	if (result < 0) {
  		dev_err(dev, "%s error %d
  ", "write", result);
  		return result;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
283
284
285
  	}
  	return 0;
  }
74d88eb29   Jüri Reitel   rtc-ds1307: remov...
286
  static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
287
288
289
290
291
292
293
294
295
  {
  	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 */
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
296
297
298
  	ret = i2c_smbus_read_i2c_block_data(client,
  			DS1339_REG_ALARM1_SECS, 9, ds1307->regs);
  	if (ret != 9) {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  		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...
339
  static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  {
  	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 */
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
358
359
360
  	ret = i2c_smbus_read_i2c_block_data(client,
  			DS1339_REG_ALARM1_SECS, 9, buf);
  	if (ret != 9) {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  		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...
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
  	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);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
395
396
397
  	ret = i2c_smbus_write_i2c_block_data(client,
  			DS1339_REG_ALARM1_SECS, 9, buf);
  	if (ret < 0) {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
398
399
  		dev_err(dev, "can't set alarm time
  ");
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
400
  		return ret;
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
441
442
443
444
445
446
447
448
449
450
451
452
  	}
  
  	return 0;
  }
  
  static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
  {
  	struct i2c_client	*client = to_i2c_client(dev);
  	struct ds1307		*ds1307 = i2c_get_clientdata(client);
  	int			ret;
  
  	switch (cmd) {
  	case RTC_AIE_OFF:
  		if (!test_bit(HAS_ALARM, &ds1307->flags))
  			return -ENOTTY;
  
  		ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
  		if (ret < 0)
  			return ret;
  
  		ret &= ~DS1337_BIT_A1IE;
  
  		ret = i2c_smbus_write_byte_data(client,
  						DS1337_REG_CONTROL, ret);
  		if (ret < 0)
  			return ret;
  
  		break;
  
  	case RTC_AIE_ON:
  		if (!test_bit(HAS_ALARM, &ds1307->flags))
  			return -ENOTTY;
  
  		ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
  		if (ret < 0)
  			return ret;
  
  		ret |= DS1337_BIT_A1IE;
  
  		ret = i2c_smbus_write_byte_data(client,
  						DS1337_REG_CONTROL, ret);
  		if (ret < 0)
  			return ret;
  
  		break;
  
  	default:
  		return -ENOIOCTLCMD;
  	}
  
  	return 0;
  }
ff8371ac9   David Brownell   [PATCH] constify ...
453
  static const struct rtc_class_ops ds13xx_rtc_ops = {
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
454
455
  	.read_time	= ds1307_get_time,
  	.set_time	= ds1307_set_time,
74d88eb29   Jüri Reitel   rtc-ds1307: remov...
456
457
  	.read_alarm	= ds1337_read_alarm,
  	.set_alarm	= ds1337_set_alarm,
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
458
  	.ioctl		= ds1307_ioctl,
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
459
  };
682d73f68   David Brownell   rtc-ds1307 export...
460
461
462
463
464
465
466
467
468
469
  /*----------------------------------------------------------------------*/
  
  #define NVRAM_SIZE	56
  
  static ssize_t
  ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
  		char *buf, loff_t off, size_t count)
  {
  	struct i2c_client	*client;
  	struct ds1307		*ds1307;
682d73f68   David Brownell   rtc-ds1307 export...
470
  	int			result;
fcd8db002   frederic Rodo   rtc ds1307: ds_13...
471
  	client = kobj_to_i2c_client(kobj);
682d73f68   David Brownell   rtc-ds1307 export...
472
473
474
475
476
477
478
479
  	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;
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
480
481
  	result = i2c_smbus_read_i2c_block_data(client, 8 + off, count, buf);
  	if (result < 0)
682d73f68   David Brownell   rtc-ds1307 export...
482
483
  		dev_err(&client->dev, "%s error %d
  ", "nvram read", result);
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
484
  	return result;
682d73f68   David Brownell   rtc-ds1307 export...
485
486
487
488
489
490
491
  }
  
  static ssize_t
  ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
  		char *buf, loff_t off, size_t count)
  {
  	struct i2c_client	*client;
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
492
  	int			result;
682d73f68   David Brownell   rtc-ds1307 export...
493

fcd8db002   frederic Rodo   rtc ds1307: ds_13...
494
  	client = kobj_to_i2c_client(kobj);
682d73f68   David Brownell   rtc-ds1307 export...
495
496
497
498
499
500
501
  
  	if (unlikely(off >= NVRAM_SIZE))
  		return -EFBIG;
  	if ((off + count) > NVRAM_SIZE)
  		count = NVRAM_SIZE - off;
  	if (unlikely(!count))
  		return count;
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
502
503
504
505
506
507
508
  	result = i2c_smbus_write_i2c_block_data(client, 8 + off, count, buf);
  	if (result < 0) {
  		dev_err(&client->dev, "%s error %d
  ", "nvram write", result);
  		return result;
  	}
  	return count;
682d73f68   David Brownell   rtc-ds1307 export...
509
510
511
512
513
514
  }
  
  static struct bin_attribute nvram = {
  	.attr = {
  		.name	= "nvram",
  		.mode	= S_IRUGO | S_IWUSR,
682d73f68   David Brownell   rtc-ds1307 export...
515
516
517
518
519
520
521
522
  	},
  
  	.read	= ds1307_nvram_read,
  	.write	= ds1307_nvram_write,
  	.size	= NVRAM_SIZE,
  };
  
  /*----------------------------------------------------------------------*/
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
523
  static struct i2c_driver ds1307_driver;
d2653e927   Jean Delvare   i2c: Add support ...
524
525
  static int __devinit ds1307_probe(struct i2c_client *client,
  				  const struct i2c_device_id *id)
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
526
527
528
  {
  	struct ds1307		*ds1307;
  	int			err = -ENODEV;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
529
  	int			tmp;
3760f7367   Jean Delvare   i2c: Convert most...
530
  	const struct chip_desc	*chip = &chips[id->driver_data];
c065f35c1   David Brownell   rtc-ds1307 become...
531
  	struct i2c_adapter	*adapter = to_i2c_adapter(client->dev.parent);
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
532
  	int			want_irq = false;
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
533
  	unsigned char		*buf;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
534

c065f35c1   David Brownell   rtc-ds1307 become...
535
  	if (!i2c_check_functionality(adapter,
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
536
537
  			I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
  			I2C_FUNC_SMBUS_I2C_BLOCK))
c065f35c1   David Brownell   rtc-ds1307 become...
538
539
540
541
  		return -EIO;
  
  	if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL)))
  		return -ENOMEM;
045e0e85f   David Brownell   rtc-ds1307 cleanups
542
543
  
  	ds1307->client = client;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
544
  	i2c_set_clientdata(client, ds1307);
3760f7367   Jean Delvare   i2c: Convert most...
545
  	ds1307->type = id->driver_data;
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
546
  	buf = ds1307->regs;
045e0e85f   David Brownell   rtc-ds1307 cleanups
547
548
549
550
  
  	switch (ds1307->type) {
  	case ds_1337:
  	case ds_1339:
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
551
552
553
554
555
  		/* has IRQ? */
  		if (ds1307->client->irq > 0 && chip->alarm) {
  			INIT_WORK(&ds1307->work, ds1307_work);
  			want_irq = true;
  		}
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
556
  		/* get registers that the "rtc" read below won't read... */
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
557
558
  		tmp = i2c_smbus_read_i2c_block_data(ds1307->client,
  				DS1337_REG_CONTROL, 2, buf);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
559
560
561
562
563
564
  		if (tmp != 2) {
  			pr_debug("read error %d
  ", tmp);
  			err = -EIO;
  			goto exit_free;
  		}
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
565
566
  		/* oscillator off?  turn it on, so clock can tick. */
  		if (ds1307->regs[0] & DS1337_BIT_nEOSC)
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
567
568
569
570
571
572
573
574
575
576
577
578
579
580
  			ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
  
  		/* Using IRQ?  Disable the square wave and both alarms.
  		 * For ds1339, be sure alarms can trigger when we're
  		 * running on Vbackup (BBSQI); we assume ds1337 will
  		 * ignore that bit
  		 */
  		if (want_irq) {
  			ds1307->regs[0] |= DS1337_BIT_INTCN | DS1339_BIT_BBSQI;
  			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...
581
582
583
584
585
586
587
  
  		/* 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...
588
  		}
045e0e85f   David Brownell   rtc-ds1307 cleanups
589
590
591
592
  		break;
  	default:
  		break;
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
593
594
595
  
  read_rtc:
  	/* read RTC registers */
fed40b734   BARRE Sebastien   rtc-ds1307: SMBus...
596
597
  	tmp = i2c_smbus_read_i2c_block_data(ds1307->client, 0, 8, buf);
  	if (tmp != 8) {
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
598
599
600
601
602
603
604
605
606
607
608
  		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
609
610
  	switch (ds1307->type) {
  	case ds_1307:
045e0e85f   David Brownell   rtc-ds1307 cleanups
611
  	case m41t00:
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
612
  		/* clock halted?  turn it on, so clock can tick. */
045e0e85f   David Brownell   rtc-ds1307 cleanups
613
  		if (tmp & DS1307_BIT_CH) {
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
614
615
616
  			i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
  			dev_warn(&client->dev, "SET TIME!
  ");
045e0e85f   David Brownell   rtc-ds1307 cleanups
617
  			goto read_rtc;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
618
  		}
045e0e85f   David Brownell   rtc-ds1307 cleanups
619
  		break;
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
620
621
  	case ds_1338:
  		/* clock halted?  turn it on, so clock can tick. */
045e0e85f   David Brownell   rtc-ds1307 cleanups
622
  		if (tmp & DS1307_BIT_CH)
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
623
624
625
626
627
  			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 ...
628
  					ds1307->regs[DS1307_REG_CONTROL]
be5f59f4b   Rodolfo Giometti   rtc-ds1307: oscil...
629
630
631
632
633
  					& ~DS1338_BIT_OSF);
  			dev_warn(&client->dev, "SET TIME!
  ");
  			goto read_rtc;
  		}
045e0e85f   David Brownell   rtc-ds1307 cleanups
634
  		break;
fcd8db002   frederic Rodo   rtc ds1307: ds_13...
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
  	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;
c065f35c1   David Brownell   rtc-ds1307 become...
655
656
  	case ds_1337:
  	case ds_1339:
045e0e85f   David Brownell   rtc-ds1307 cleanups
657
  		break;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
658
  	}
045e0e85f   David Brownell   rtc-ds1307 cleanups
659

1abb0dc92   David Brownell   [PATCH] "RTC-fram...
660
  	tmp = ds1307->regs[DS1307_REG_HOUR];
c065f35c1   David Brownell   rtc-ds1307 become...
661
662
663
664
665
666
667
668
669
670
671
672
673
674
  	switch (ds1307->type) {
  	case ds_1340:
  	case m41t00:
  		/* NOTE: ignores century bits; fix before deploying
  		 * systems that will run through year 2100.
  		 */
  		break;
  	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...
675
  		tmp = bcd2bin(tmp & 0x1f);
c065f35c1   David Brownell   rtc-ds1307 become...
676
677
678
679
  		if (tmp == 12)
  			tmp = 0;
  		if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
  			tmp += 12;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
680
681
  		i2c_smbus_write_byte_data(client,
  				DS1307_REG_HOUR,
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
682
  				bin2bcd(tmp));
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
683
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
684
685
686
687
688
689
690
  	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...
691
  		goto exit_free;
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
692
  	}
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
693
694
695
696
697
698
699
700
701
702
703
704
705
  	if (want_irq) {
  		err = request_irq(client->irq, ds1307_irq, 0,
  			  ds1307->rtc->name, client);
  		if (err) {
  			dev_err(&client->dev,
  				"unable to request IRQ!
  ");
  			goto exit_irq;
  		}
  		set_bit(HAS_ALARM, &ds1307->flags);
  		dev_dbg(&client->dev, "got IRQ %d
  ", client->irq);
  	}
682d73f68   David Brownell   rtc-ds1307 export...
706
707
708
  	if (chip->nvram56) {
  		err = sysfs_create_bin_file(&client->dev.kobj, &nvram);
  		if (err == 0) {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
709
  			set_bit(HAS_NVRAM, &ds1307->flags);
682d73f68   David Brownell   rtc-ds1307 export...
710
711
712
713
  			dev_info(&client->dev, "56 bytes nvram
  ");
  		}
  	}
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
714
  	return 0;
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
715
716
717
  exit_irq:
  	if (ds1307->rtc)
  		rtc_device_unregister(ds1307->rtc);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
718
719
  exit_free:
  	kfree(ds1307);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
720
721
  	return err;
  }
c065f35c1   David Brownell   rtc-ds1307 become...
722
  static int __devexit ds1307_remove(struct i2c_client *client)
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
723
  {
cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
724
725
726
727
728
729
  	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...
730

cb49a5e9e   Rodolfo Giometti   rtc-ds1307: alarm...
731
  	if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
682d73f68   David Brownell   rtc-ds1307 export...
732
  		sysfs_remove_bin_file(&client->dev.kobj, &nvram);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
733
  	rtc_device_unregister(ds1307->rtc);
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
734
735
736
737
738
739
  	kfree(ds1307);
  	return 0;
  }
  
  static struct i2c_driver ds1307_driver = {
  	.driver = {
c065f35c1   David Brownell   rtc-ds1307 become...
740
  		.name	= "rtc-ds1307",
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
741
742
  		.owner	= THIS_MODULE,
  	},
c065f35c1   David Brownell   rtc-ds1307 become...
743
744
  	.probe		= ds1307_probe,
  	.remove		= __devexit_p(ds1307_remove),
3760f7367   Jean Delvare   i2c: Convert most...
745
  	.id_table	= ds1307_id,
1abb0dc92   David Brownell   [PATCH] "RTC-fram...
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
  };
  
  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");