aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2007-02-08 17:20:24 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-09 12:25:46 -0500
commitcbb9450234fb28f60fea36520cd710a988ac5812 (patch)
tree341a4886dce7a4fd91b651d55a309ed69d6ff262 /drivers/rtc
parent68a696a01f482859a9fe937249e8b3d44252b610 (diff)
[PATCH] rtc-pcf8563: detect polarity of century bit automatically
The usage of the century bit was inverted on 2.6.19 following to PCF8563's description, but it was not match to usage suggested by RTC8564's datasheet. Anyway what MO_C=1 means can vary on each platform. This patch is to detect its polarity in get_datetime routine. The default value of c_polarity is 0 (MO_C=1 means 19xx) so that this patch does not change current behavior even if get_datetime was not called before set_datetime. Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Cc: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@teamlog.com> Cc: <stable@kernel.org> Cc: David Brownell <dbrownell@users.sourceforge.net> Cc: Alessandro Zummo <a.zummo@towertech.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-pcf8563.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 4b72b8ef5d66..038118bbfaea 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -53,6 +53,25 @@ I2C_CLIENT_INSMOD;
53#define PCF8563_SC_LV 0x80 /* low voltage */ 53#define PCF8563_SC_LV 0x80 /* low voltage */
54#define PCF8563_MO_C 0x80 /* century */ 54#define PCF8563_MO_C 0x80 /* century */
55 55
56struct pcf8563 {
57 struct i2c_client client;
58 /*
59 * The meaning of MO_C bit varies by the chip type.
60 * From PCF8563 datasheet: this bit is toggled when the years
61 * register overflows from 99 to 00
62 * 0 indicates the century is 20xx
63 * 1 indicates the century is 19xx
64 * From RTC8564 datasheet: this bit indicates change of
65 * century. When the year digit data overflows from 99 to 00,
66 * this bit is set. By presetting it to 0 while still in the
67 * 20th century, it will be set in year 2000, ...
68 * There seems no reliable way to know how the system use this
69 * bit. So let's do it heuristically, assuming we are live in
70 * 1970...2069.
71 */
72 int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
73};
74
56static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind); 75static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind);
57static int pcf8563_detach(struct i2c_client *client); 76static int pcf8563_detach(struct i2c_client *client);
58 77
@@ -62,6 +81,7 @@ static int pcf8563_detach(struct i2c_client *client);
62 */ 81 */
63static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) 82static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
64{ 83{
84 struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
65 unsigned char buf[13] = { PCF8563_REG_ST1 }; 85 unsigned char buf[13] = { PCF8563_REG_ST1 };
66 86
67 struct i2c_msg msgs[] = { 87 struct i2c_msg msgs[] = {
@@ -94,8 +114,12 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
94 tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F); 114 tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F);
95 tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; 115 tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
96 tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ 116 tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
97 tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]) 117 tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]);
98 + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 0 : 100); 118 if (tm->tm_year < 70)
119 tm->tm_year += 100; /* assume we are in 1970...2069 */
120 /* detect the polarity heuristically. see note above. */
121 pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
122 (tm->tm_year >= 100) : (tm->tm_year < 100);
99 123
100 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " 124 dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
101 "mday=%d, mon=%d, year=%d, wday=%d\n", 125 "mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -114,6 +138,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
114 138
115static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) 139static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
116{ 140{
141 struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
117 int i, err; 142 int i, err;
118 unsigned char buf[9]; 143 unsigned char buf[9];
119 144
@@ -135,7 +160,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
135 160
136 /* year and century */ 161 /* year and century */
137 buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100); 162 buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100);
138 if (tm->tm_year < 100) 163 if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
139 buf[PCF8563_REG_MO] |= PCF8563_MO_C; 164 buf[PCF8563_REG_MO] |= PCF8563_MO_C;
140 165
141 buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; 166 buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
@@ -248,6 +273,7 @@ static struct i2c_driver pcf8563_driver = {
248 273
249static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) 274static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
250{ 275{
276 struct pcf8563 *pcf8563;
251 struct i2c_client *client; 277 struct i2c_client *client;
252 struct rtc_device *rtc; 278 struct rtc_device *rtc;
253 279
@@ -260,11 +286,12 @@ static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
260 goto exit; 286 goto exit;
261 } 287 }
262 288
263 if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) { 289 if (!(pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL))) {
264 err = -ENOMEM; 290 err = -ENOMEM;
265 goto exit; 291 goto exit;
266 } 292 }
267 293
294 client = &pcf8563->client;
268 client->addr = address; 295 client->addr = address;
269 client->driver = &pcf8563_driver; 296 client->driver = &pcf8563_driver;
270 client->adapter = adapter; 297 client->adapter = adapter;
@@ -301,7 +328,7 @@ exit_detach:
301 i2c_detach_client(client); 328 i2c_detach_client(client);
302 329
303exit_kfree: 330exit_kfree:
304 kfree(client); 331 kfree(pcf8563);
305 332
306exit: 333exit:
307 return err; 334 return err;
@@ -309,6 +336,7 @@ exit:
309 336
310static int pcf8563_detach(struct i2c_client *client) 337static int pcf8563_detach(struct i2c_client *client)
311{ 338{
339 struct pcf8563 *pcf8563 = container_of(client, struct pcf8563, client);
312 int err; 340 int err;
313 struct rtc_device *rtc = i2c_get_clientdata(client); 341 struct rtc_device *rtc = i2c_get_clientdata(client);
314 342
@@ -318,7 +346,7 @@ static int pcf8563_detach(struct i2c_client *client)
318 if ((err = i2c_detach_client(client))) 346 if ((err = i2c_detach_client(client)))
319 return err; 347 return err;
320 348
321 kfree(client); 349 kfree(pcf8563);
322 350
323 return 0; 351 return 0;
324} 352}