Blame view

drivers/rtc/rtc-pcf8563.c 8.49 KB
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  /*
   * An I2C driver for the Philips PCF8563 RTC
   * Copyright 2005-06 Tower Technologies
   *
   * Author: Alessandro Zummo <a.zummo@towertech.it>
   * Maintainers: http://www.nslu2-linux.org/
   *
   * based on the other drivers in this same directory.
   *
   * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf
   *
   * 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/i2c.h>
  #include <linux/bcd.h>
  #include <linux/rtc.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/slab.h>
2113852b2   Paul Gortmaker   rtc: Add module.h...
21
  #include <linux/module.h>
8dccaf060   Nick Bowler   drivers/rtc/rtc-p...
22
  #include <linux/of.h>
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
23

e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
24
  #define DRV_VERSION "0.4.3"
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  
  #define PCF8563_REG_ST1		0x00 /* status */
  #define PCF8563_REG_ST2		0x01
  
  #define PCF8563_REG_SC		0x02 /* datetime */
  #define PCF8563_REG_MN		0x03
  #define PCF8563_REG_HR		0x04
  #define PCF8563_REG_DM		0x05
  #define PCF8563_REG_DW		0x06
  #define PCF8563_REG_MO		0x07
  #define PCF8563_REG_YR		0x08
  
  #define PCF8563_REG_AMN		0x09 /* alarm */
  #define PCF8563_REG_AHR		0x0A
  #define PCF8563_REG_ADM		0x0B
  #define PCF8563_REG_ADW		0x0C
  
  #define PCF8563_REG_CLKO	0x0D /* clock out */
  #define PCF8563_REG_TMRC	0x0E /* timer control */
  #define PCF8563_REG_TMR		0x0F /* timer */
  
  #define PCF8563_SC_LV		0x80 /* low voltage */
  #define PCF8563_MO_C		0x80 /* century */
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
48
  static struct i2c_driver pcf8563_driver;
cbb945023   Atsushi Nemoto   [PATCH] rtc-pcf85...
49
  struct pcf8563 {
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
50
  	struct rtc_device *rtc;
cbb945023   Atsushi Nemoto   [PATCH] rtc-pcf85...
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  	/*
  	 * The meaning of MO_C bit varies by the chip type.
  	 * From PCF8563 datasheet: this bit is toggled when the years
  	 * register overflows from 99 to 00
  	 *   0 indicates the century is 20xx
  	 *   1 indicates the century is 19xx
  	 * From RTC8564 datasheet: this bit indicates change of
  	 * century. When the year digit data overflows from 99 to 00,
  	 * this bit is set. By presetting it to 0 while still in the
  	 * 20th century, it will be set in year 2000, ...
  	 * There seems no reliable way to know how the system use this
  	 * bit.  So let's do it heuristically, assuming we are live in
  	 * 1970...2069.
  	 */
  	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
0f20b767e   Alexander Stein   drivers/rtc/rtc-p...
66
  	int voltage_low; /* incicates if a low_voltage was detected */
cbb945023   Atsushi Nemoto   [PATCH] rtc-pcf85...
67
  };
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
68
69
70
71
72
73
  /*
   * In the routines that deal directly with the pcf8563 hardware, we use
   * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
   */
  static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
  {
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
74
  	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
75
76
77
  	unsigned char buf[13] = { PCF8563_REG_ST1 };
  
  	struct i2c_msg msgs[] = {
755e4a4bd   Shubhrajyoti D   drivers/rtc/rtc-p...
78
79
80
81
82
83
84
85
86
87
88
  		{/* setup read ptr */
  			.addr = client->addr,
  			.len = 1,
  			.buf = buf
  		},
  		{/* read status + date */
  			.addr = client->addr,
  			.flags = I2C_M_RD,
  			.len = 13,
  			.buf = buf
  		},
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
89
90
91
92
  	};
  
  	/* read registers */
  	if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
2a4e2b878   Harvey Harrison   rtc: replace rema...
93
94
  		dev_err(&client->dev, "%s: read error
  ", __func__);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
95
96
  		return -EIO;
  	}
0f20b767e   Alexander Stein   drivers/rtc/rtc-p...
97
98
  	if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
  		pcf8563->voltage_low = 1;
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
99
100
101
  		dev_info(&client->dev,
  			"low voltage detected, date/time is not reliable.
  ");
0f20b767e   Alexander Stein   drivers/rtc/rtc-p...
102
  	}
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
103
104
105
106
107
  
  	dev_dbg(&client->dev,
  		"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
  		"mday=%02x, wday=%02x, mon=%02x, year=%02x
  ",
2a4e2b878   Harvey Harrison   rtc: replace rema...
108
  		__func__,
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
109
110
111
  		buf[0], buf[1], buf[2], buf[3],
  		buf[4], buf[5], buf[6], buf[7],
  		buf[8]);
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
112
113
114
115
  	tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
  	tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
  	tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
  	tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
116
  	tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
117
118
  	tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
  	tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
cbb945023   Atsushi Nemoto   [PATCH] rtc-pcf85...
119
120
121
122
123
  	if (tm->tm_year < 70)
  		tm->tm_year += 100;	/* assume we are in 1970...2069 */
  	/* detect the polarity heuristically. see note above. */
  	pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
  		(tm->tm_year >= 100) : (tm->tm_year < 100);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
124
125
126
127
  
  	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
  		"mday=%d, mon=%d, year=%d, wday=%d
  ",
2a4e2b878   Harvey Harrison   rtc: replace rema...
128
  		__func__,
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
  		tm->tm_sec, tm->tm_min, tm->tm_hour,
  		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
  
  	/* the clock can give out invalid datetime, but we cannot return
  	 * -EINVAL otherwise hwclock will refuse to set the time on bootup.
  	 */
  	if (rtc_valid_tm(tm) < 0)
  		dev_err(&client->dev, "retrieved date/time is not valid.
  ");
  
  	return 0;
  }
  
  static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
  {
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
144
  	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
145
146
147
148
149
150
  	int i, err;
  	unsigned char buf[9];
  
  	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
  		"mday=%d, mon=%d, year=%d, wday=%d
  ",
2a4e2b878   Harvey Harrison   rtc: replace rema...
151
  		__func__,
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
152
153
154
155
  		tm->tm_sec, tm->tm_min, tm->tm_hour,
  		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
  
  	/* hours, minutes and seconds */
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
156
157
158
  	buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
  	buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
  	buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
159

fe20ba70a   Adrian Bunk   drivers/rtc/: use...
160
  	buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
161
162
  
  	/* month, 1 - 12 */
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
163
  	buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
164
165
  
  	/* year and century */
fe20ba70a   Adrian Bunk   drivers/rtc/: use...
166
  	buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
cbb945023   Atsushi Nemoto   [PATCH] rtc-pcf85...
167
  	if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  		buf[PCF8563_REG_MO] |= PCF8563_MO_C;
  
  	buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
  
  	/* write register's data */
  	for (i = 0; i < 7; i++) {
  		unsigned char data[2] = { PCF8563_REG_SC + i,
  						buf[PCF8563_REG_SC + i] };
  
  		err = i2c_master_send(client, data, sizeof(data));
  		if (err != sizeof(data)) {
  			dev_err(&client->dev,
  				"%s: err=%d addr=%02x, data=%02x
  ",
2a4e2b878   Harvey Harrison   rtc: replace rema...
182
  				__func__, err, data[0], data[1]);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
183
184
  			return -EIO;
  		}
0b7e03924   Peter Senna Tschudin   drivers/rtc: remo...
185
  	}
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
186
187
188
  
  	return 0;
  }
0f20b767e   Alexander Stein   drivers/rtc/rtc-p...
189
190
191
192
193
194
195
196
197
198
199
200
201
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
  #ifdef CONFIG_RTC_INTF_DEV
  static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
  {
  	struct pcf8563 *pcf8563 = i2c_get_clientdata(to_i2c_client(dev));
  	struct rtc_time tm;
  
  	switch (cmd) {
  	case RTC_VL_READ:
  		if (pcf8563->voltage_low)
  			dev_info(dev, "low voltage detected, date/time is not reliable.
  ");
  
  		if (copy_to_user((void __user *)arg, &pcf8563->voltage_low,
  					sizeof(int)))
  			return -EFAULT;
  		return 0;
  	case RTC_VL_CLR:
  		/*
  		 * Clear the VL bit in the seconds register in case
  		 * the time has not been set already (which would
  		 * have cleared it). This does not really matter
  		 * because of the cached voltage_low value but do it
  		 * anyway for consistency.
  		 */
  		if (pcf8563_get_datetime(to_i2c_client(dev), &tm))
  			pcf8563_set_datetime(to_i2c_client(dev), &tm);
  
  		/* Clear the cached value. */
  		pcf8563->voltage_low = 0;
  
  		return 0;
  	default:
  		return -ENOIOCTLCMD;
  	}
  }
  #else
  #define pcf8563_rtc_ioctl NULL
  #endif
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
227
228
229
230
231
232
233
234
235
  static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
  {
  	return pcf8563_get_datetime(to_i2c_client(dev), tm);
  }
  
  static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
  {
  	return pcf8563_set_datetime(to_i2c_client(dev), tm);
  }
ff8371ac9   David Brownell   [PATCH] constify ...
236
  static const struct rtc_class_ops pcf8563_rtc_ops = {
0f20b767e   Alexander Stein   drivers/rtc/rtc-p...
237
  	.ioctl		= pcf8563_rtc_ioctl,
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
238
239
240
  	.read_time	= pcf8563_rtc_read_time,
  	.set_time	= pcf8563_rtc_set_time,
  };
d2653e927   Jean Delvare   i2c: Add support ...
241
242
  static int pcf8563_probe(struct i2c_client *client,
  				const struct i2c_device_id *id)
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
243
  {
cbb945023   Atsushi Nemoto   [PATCH] rtc-pcf85...
244
  	struct pcf8563 *pcf8563;
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
245
246
  
  	int err = 0;
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
247
248
  	dev_dbg(&client->dev, "%s
  ", __func__);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
249

e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
250
251
  	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
  		return -ENODEV;
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
252

e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
253
254
255
  	pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL);
  	if (!pcf8563)
  		return -ENOMEM;
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
256

b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
257
258
  	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "
  ");
b74d2caa6   Alessandro Zummo   rtc: fix driver d...
259
  	i2c_set_clientdata(client, pcf8563);
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
260
261
  	pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name,
  				&client->dev, &pcf8563_rtc_ops, THIS_MODULE);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
262

e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
263
264
265
  	if (IS_ERR(pcf8563->rtc)) {
  		err = PTR_ERR(pcf8563->rtc);
  		goto exit_kfree;
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
266
  	}
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
267
  	return 0;
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
268
  exit_kfree:
cbb945023   Atsushi Nemoto   [PATCH] rtc-pcf85...
269
  	kfree(pcf8563);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
270

b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
271
272
  	return err;
  }
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
273
  static int pcf8563_remove(struct i2c_client *client)
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
274
  {
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
275
  	struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
276

e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
277
278
  	if (pcf8563->rtc)
  		rtc_device_unregister(pcf8563->rtc);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
279

cbb945023   Atsushi Nemoto   [PATCH] rtc-pcf85...
280
  	kfree(pcf8563);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
281
282
283
  
  	return 0;
  }
3760f7367   Jean Delvare   i2c: Convert most...
284
285
  static const struct i2c_device_id pcf8563_id[] = {
  	{ "pcf8563", 0 },
8ea9212cb   Jon Smirl   rtc-pcf8563: add ...
286
  	{ "rtc8564", 0 },
3760f7367   Jean Delvare   i2c: Convert most...
287
288
289
  	{ }
  };
  MODULE_DEVICE_TABLE(i2c, pcf8563_id);
8dccaf060   Nick Bowler   drivers/rtc/rtc-p...
290
  #ifdef CONFIG_OF
5a167f454   Greg Kroah-Hartman   Drivers: rtc: rem...
291
  static const struct of_device_id pcf8563_of_match[] = {
8dccaf060   Nick Bowler   drivers/rtc/rtc-p...
292
293
294
295
296
  	{ .compatible = "nxp,pcf8563" },
  	{}
  };
  MODULE_DEVICE_TABLE(of, pcf8563_of_match);
  #endif
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
297
298
299
  static struct i2c_driver pcf8563_driver = {
  	.driver		= {
  		.name	= "rtc-pcf8563",
0a25bf40d   Nick Bowler   drivers/rtc/rtc-p...
300
  		.owner	= THIS_MODULE,
8dccaf060   Nick Bowler   drivers/rtc/rtc-p...
301
  		.of_match_table = of_match_ptr(pcf8563_of_match),
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
302
303
304
  	},
  	.probe		= pcf8563_probe,
  	.remove		= pcf8563_remove,
3760f7367   Jean Delvare   i2c: Convert most...
305
  	.id_table	= pcf8563_id,
e5fc9cc02   Alessandro Zummo   rtc-pcf8563: new ...
306
  };
0abc92011   Axel Lin   rtc: convert rtc ...
307
  module_i2c_driver(pcf8563_driver);
b5a82d628   Alessandro Zummo   [PATCH] RTC subsy...
308
309
310
311
312
  
  MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
  MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
  MODULE_LICENSE("GPL");
  MODULE_VERSION(DRV_VERSION);