diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rtc/rtc-pcf8563.c | 40 |
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 | ||
56 | struct 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 | |||
56 | static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind); | 75 | static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind); |
57 | static int pcf8563_detach(struct i2c_client *client); | 76 | static int pcf8563_detach(struct i2c_client *client); |
58 | 77 | ||
@@ -62,6 +81,7 @@ static int pcf8563_detach(struct i2c_client *client); | |||
62 | */ | 81 | */ |
63 | static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | 82 | static 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 | ||
115 | static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) | 139 | static 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 | ||
249 | static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) | 274 | static 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 | ||
303 | exit_kfree: | 330 | exit_kfree: |
304 | kfree(client); | 331 | kfree(pcf8563); |
305 | 332 | ||
306 | exit: | 333 | exit: |
307 | return err; | 334 | return err; |
@@ -309,6 +336,7 @@ exit: | |||
309 | 336 | ||
310 | static int pcf8563_detach(struct i2c_client *client) | 337 | static 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 | } |