aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris
diff options
context:
space:
mode:
authorJesper Nilsson <jesper.nilsson@axis.com>2008-01-17 09:17:07 -0500
committerJesper Nilsson <jesper.nilsson@axis.com>2008-02-08 05:06:29 -0500
commit34a8e501fe83f3b572eee56a6fca5111ab8cdf65 (patch)
treea4f0aa32e741dbb5386d898f6690c41bf7711204 /arch/cris
parente5d5cf2442038b8ad3e0f90b00e5acdd18d5fa98 (diff)
CRIS v10: Update driver for pcf8563
- Use mutex instead of spinlock, fixes kernel bugzilla report 8339. - Make sure that pcf8563_init can be called multiple times but only setup once. - Change RTC_VLOW_RD -> RTC_VL_READ, RTC_VLOW_SET -> RTC_VL_CLR - Cache the voltage low value at driver init so the battery status information does not get 'accidentally' cleared when setting the RTC time. - Add weekday handling. - Correct leapyear handling to include 100 and 400 year exceptions. - Correct whitespace and formatting errors. - Remove useless CVS id tag.
Diffstat (limited to 'arch/cris')
-rw-r--r--arch/cris/arch-v10/drivers/pcf8563.c393
1 files changed, 220 insertions, 173 deletions
diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c
index c263b8232dbc..52103d16dc6c 100644
--- a/arch/cris/arch-v10/drivers/pcf8563.c
+++ b/arch/cris/arch-v10/drivers/pcf8563.c
@@ -8,14 +8,13 @@
8 * low detector are also provided. All address and data are transferred 8 * low detector are also provided. All address and data are transferred
9 * serially via two-line bidirectional I2C-bus. Maximum bus speed is 9 * serially via two-line bidirectional I2C-bus. Maximum bus speed is
10 * 400 kbits/s. The built-in word address register is incremented 10 * 400 kbits/s. The built-in word address register is incremented
11 * automatically after each written or read bute. 11 * automatically after each written or read byte.
12 * 12 *
13 * Copyright (c) 2002, Axis Communications AB 13 * Copyright (c) 2002-2007, Axis Communications AB
14 * All rights reserved. 14 * All rights reserved.
15 * 15 *
16 * Author: Tobias Anderberg <tobiasa@axis.com>. 16 * Author: Tobias Anderberg <tobiasa@axis.com>.
17 * 17 *
18 * $Id: pcf8563.c,v 1.11 2005/03/07 13:13:07 starvik Exp $
19 */ 18 */
20 19
21#include <linux/module.h> 20#include <linux/module.h>
@@ -27,19 +26,19 @@
27#include <linux/ioctl.h> 26#include <linux/ioctl.h>
28#include <linux/delay.h> 27#include <linux/delay.h>
29#include <linux/bcd.h> 28#include <linux/bcd.h>
30#include <linux/capability.h> 29#include <linux/mutex.h>
31 30
32#include <asm/uaccess.h> 31#include <asm/uaccess.h>
33#include <asm/system.h> 32#include <asm/system.h>
34#include <asm/io.h> 33#include <asm/io.h>
35#include <asm/arch/svinto.h>
36#include <asm/rtc.h> 34#include <asm/rtc.h>
35
37#include "i2c.h" 36#include "i2c.h"
38 37
39#define PCF8563_MAJOR 121 /* Local major number. */ 38#define PCF8563_MAJOR 121 /* Local major number. */
40#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */ 39#define DEVICE_NAME "rtc" /* Name which is registered in /proc/devices. */
41#define PCF8563_NAME "PCF8563" 40#define PCF8563_NAME "PCF8563"
42#define DRIVER_VERSION "$Revision: 1.11 $" 41#define DRIVER_VERSION "$Revision: 1.24 $"
43 42
44/* I2C bus slave registers. */ 43/* I2C bus slave registers. */
45#define RTC_I2C_READ 0xa3 44#define RTC_I2C_READ 0xa3
@@ -49,71 +48,88 @@
49#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x) 48#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
50#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y) 49#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
51 50
52static DEFINE_SPINLOCK(rtc_lock); /* Protect state etc */ 51static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
53 52
54static const unsigned char days_in_month[] = 53static const unsigned char days_in_month[] =
55 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 54 { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
56 55
57int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long); 56int pcf8563_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
58 57
58/* Cache VL bit value read at driver init since writing the RTC_SECOND
59 * register clears the VL status.
60 */
61static int voltage_low;
62
59static const struct file_operations pcf8563_fops = { 63static const struct file_operations pcf8563_fops = {
60 .owner = THIS_MODULE, 64 .owner = THIS_MODULE,
61 .ioctl = pcf8563_ioctl, 65 .ioctl = pcf8563_ioctl,
62}; 66};
63 67
64unsigned char 68unsigned char
65pcf8563_readreg(int reg) 69pcf8563_readreg(int reg)
66{ 70{
67 unsigned char res = i2c_readreg(RTC_I2C_READ, reg); 71 unsigned char res = rtc_read(reg);
68 72
69 /* The PCF8563 does not return 0 for unimplemented bits */ 73 /* The PCF8563 does not return 0 for unimplemented bits. */
70 switch(reg) 74 switch (reg) {
71 { 75 case RTC_SECONDS:
72 case RTC_SECONDS: 76 case RTC_MINUTES:
73 case RTC_MINUTES: 77 res &= 0x7F;
74 res &= 0x7f; 78 break;
75 break; 79 case RTC_HOURS:
76 case RTC_HOURS: 80 case RTC_DAY_OF_MONTH:
77 case RTC_DAY_OF_MONTH: 81 res &= 0x3F;
78 res &= 0x3f; 82 break;
79 break; 83 case RTC_WEEKDAY:
80 case RTC_MONTH: 84 res &= 0x07;
81 res = (res & 0x1f) - 1; /* PCF8563 returns month in range 1-12 */ 85 break;
82 break; 86 case RTC_MONTH:
87 res &= 0x1F;
88 break;
89 case RTC_CONTROL1:
90 res &= 0xA8;
91 break;
92 case RTC_CONTROL2:
93 res &= 0x1F;
94 break;
95 case RTC_CLOCKOUT_FREQ:
96 case RTC_TIMER_CONTROL:
97 res &= 0x83;
98 break;
83 } 99 }
84 return res; 100 return res;
85} 101}
86 102
87void 103void
88pcf8563_writereg(int reg, unsigned char val) 104pcf8563_writereg(int reg, unsigned char val)
89{ 105{
90#ifdef CONFIG_ETRAX_RTC_READONLY
91 if (reg == RTC_CONTROL1 || (reg >= RTC_SECONDS && reg <= RTC_YEAR))
92 return;
93#endif
94
95 rtc_write(reg, val); 106 rtc_write(reg, val);
96} 107}
97 108
98void 109void
99get_rtc_time(struct rtc_time *tm) 110get_rtc_time(struct rtc_time *tm)
100{ 111{
101 tm->tm_sec = rtc_read(RTC_SECONDS); 112 tm->tm_sec = rtc_read(RTC_SECONDS);
102 tm->tm_min = rtc_read(RTC_MINUTES); 113 tm->tm_min = rtc_read(RTC_MINUTES);
103 tm->tm_hour = rtc_read(RTC_HOURS); 114 tm->tm_hour = rtc_read(RTC_HOURS);
104 tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH); 115 tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);
105 tm->tm_mon = rtc_read(RTC_MONTH); 116 tm->tm_wday = rtc_read(RTC_WEEKDAY);
117 tm->tm_mon = rtc_read(RTC_MONTH);
106 tm->tm_year = rtc_read(RTC_YEAR); 118 tm->tm_year = rtc_read(RTC_YEAR);
107 119
108 if (tm->tm_sec & 0x80) 120 if (tm->tm_sec & 0x80) {
109 printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME); 121 printk(KERN_ERR "%s: RTC Voltage Low - reliable date/time "
122 "information is no longer guaranteed!\n", PCF8563_NAME);
123 }
110 124
111 tm->tm_year = BCD_TO_BIN(tm->tm_year) + ((tm->tm_mon & 0x80) ? 100 : 0); 125 tm->tm_year = BCD_TO_BIN(tm->tm_year) +
112 tm->tm_sec &= 0x7f; 126 ((tm->tm_mon & 0x80) ? 100 : 0);
113 tm->tm_min &= 0x7f; 127 tm->tm_sec &= 0x7F;
114 tm->tm_hour &= 0x3f; 128 tm->tm_min &= 0x7F;
115 tm->tm_mday &= 0x3f; 129 tm->tm_hour &= 0x3F;
116 tm->tm_mon &= 0x1f; 130 tm->tm_mday &= 0x3F;
131 tm->tm_wday &= 0x07; /* Not coded in BCD. */
132 tm->tm_mon &= 0x1F;
117 133
118 BCD_TO_BIN(tm->tm_sec); 134 BCD_TO_BIN(tm->tm_sec);
119 BCD_TO_BIN(tm->tm_min); 135 BCD_TO_BIN(tm->tm_min);
@@ -126,17 +142,24 @@ get_rtc_time(struct rtc_time *tm)
126int __init 142int __init
127pcf8563_init(void) 143pcf8563_init(void)
128{ 144{
129 int ret; 145 static int res;
130 146 static int first = 1;
131 if ((ret = i2c_init())) { 147
132 printk(KERN_CRIT "pcf8563_init: failed to init i2c\n"); 148 if (!first)
133 return ret; 149 return res;
150 first = 0;
151
152 /* Initiate the i2c protocol. */
153 res = i2c_init();
154 if (res < 0) {
155 printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n");
156 return res;
134 } 157 }
135 158
136 /* 159 /*
137 * First of all we need to reset the chip. This is done by 160 * First of all we need to reset the chip. This is done by
138 * clearing control1, control2 and clk freq, clear the 161 * clearing control1, control2 and clk freq and resetting
139 * Voltage Low bit, and resetting all alarms. 162 * all alarms.
140 */ 163 */
141 if (rtc_write(RTC_CONTROL1, 0x00) < 0) 164 if (rtc_write(RTC_CONTROL1, 0x00) < 0)
142 goto err; 165 goto err;
@@ -147,34 +170,36 @@ pcf8563_init(void)
147 if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0) 170 if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
148 goto err; 171 goto err;
149 172
150 /* Clear the VL bit in the seconds register. */ 173 if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0)
151 ret = rtc_read(RTC_SECONDS);
152
153 if (rtc_write(RTC_SECONDS, (ret & 0x7f)) < 0)
154 goto err; 174 goto err;
155 175
156 /* Reset the alarms. */ 176 /* Reset the alarms. */
157 if (rtc_write(RTC_MINUTE_ALARM, 0x00) < 0) 177 if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0)
158 goto err; 178 goto err;
159 179
160 if (rtc_write(RTC_HOUR_ALARM, 0x00) < 0) 180 if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0)
161 goto err; 181 goto err;
162 182
163 if (rtc_write(RTC_DAY_ALARM, 0x00) < 0) 183 if (rtc_write(RTC_DAY_ALARM, 0x80) < 0)
164 goto err; 184 goto err;
165 185
166 if (rtc_write(RTC_WEEKDAY_ALARM, 0x00) < 0) 186 if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)
167 goto err; 187 goto err;
168 188
169 /* Check for low voltage, and warn about it.. */ 189 /* Check for low voltage, and warn about it. */
170 if (rtc_read(RTC_SECONDS) & 0x80) 190 if (rtc_read(RTC_SECONDS) & 0x80) {
171 printk(KERN_WARNING "%s: RTC Low Voltage - date/time is not reliable!\n", PCF8563_NAME); 191 voltage_low = 1;
172 192 printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
173 return 0; 193 "date/time information is no longer guaranteed!\n",
194 PCF8563_NAME);
195 }
196
197 return res;
174 198
175err: 199err:
176 printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME); 200 printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
177 return -1; 201 res = -1;
202 return res;
178} 203}
179 204
180void __exit 205void __exit
@@ -187,8 +212,8 @@ pcf8563_exit(void)
187 * ioctl calls for this driver. Why return -ENOTTY upon error? Because 212 * ioctl calls for this driver. Why return -ENOTTY upon error? Because
188 * POSIX says so! 213 * POSIX says so!
189 */ 214 */
190int 215int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
191pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 216 unsigned long arg)
192{ 217{
193 /* Some sanity checks. */ 218 /* Some sanity checks. */
194 if (_IOC_TYPE(cmd) != RTC_MAGIC) 219 if (_IOC_TYPE(cmd) != RTC_MAGIC)
@@ -198,124 +223,146 @@ pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned
198 return -ENOTTY; 223 return -ENOTTY;
199 224
200 switch (cmd) { 225 switch (cmd) {
201 case RTC_RD_TIME: 226 case RTC_RD_TIME:
202 { 227 {
203 struct rtc_time tm; 228 struct rtc_time tm;
204
205 spin_lock(&rtc_lock);
206 get_rtc_time(&tm);
207
208 if (copy_to_user((struct rtc_time *) arg, &tm, sizeof(struct rtc_time))) {
209 spin_unlock(&rtc_lock);
210 return -EFAULT;
211 }
212
213 spin_unlock(&rtc_lock);
214 return 0;
215 }
216 break;
217 case RTC_SET_TIME:
218 {
219#ifdef CONFIG_ETRAX_RTC_READONLY
220 return -EPERM;
221#else
222 int leap;
223 int century;
224 struct rtc_time tm;
225
226 memset(&tm, 0, sizeof (struct rtc_time));
227 if (!capable(CAP_SYS_TIME))
228 return -EPERM;
229
230 if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof(struct rtc_time)))
231 return -EFAULT;
232
233 /* Convert from struct tm to struct rtc_time. */
234 tm.tm_year += 1900;
235 tm.tm_mon += 1;
236
237 leap = ((tm.tm_mon == 2) && ((tm.tm_year % 4) == 0)) ? 1 : 0;
238
239 /* Perform some sanity checks. */
240 if ((tm.tm_year < 1970) ||
241 (tm.tm_mon > 12) ||
242 (tm.tm_mday == 0) ||
243 (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
244 (tm.tm_hour >= 24) ||
245 (tm.tm_min >= 60) ||
246 (tm.tm_sec >= 60))
247 return -EINVAL;
248
249 century = (tm.tm_year >= 2000) ? 0x80 : 0;
250 tm.tm_year = tm.tm_year % 100;
251
252 BIN_TO_BCD(tm.tm_year);
253 BIN_TO_BCD(tm.tm_mday);
254 BIN_TO_BCD(tm.tm_hour);
255 BIN_TO_BCD(tm.tm_min);
256 BIN_TO_BCD(tm.tm_sec);
257 tm.tm_mon |= century;
258
259 spin_lock(&rtc_lock);
260
261 rtc_write(RTC_YEAR, tm.tm_year);
262 rtc_write(RTC_MONTH, tm.tm_mon);
263 rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
264 rtc_write(RTC_HOURS, tm.tm_hour);
265 rtc_write(RTC_MINUTES, tm.tm_min);
266 rtc_write(RTC_SECONDS, tm.tm_sec);
267
268 spin_unlock(&rtc_lock);
269
270 return 0;
271#endif /* !CONFIG_ETRAX_RTC_READONLY */
272 }
273
274 case RTC_VLOW_RD:
275 {
276 int vl_bit = 0;
277
278 if (rtc_read(RTC_SECONDS) & 0x80) {
279 vl_bit = 1;
280 printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
281 "date/time information is no longer guaranteed!\n",
282 PCF8563_NAME);
283 }
284 if (copy_to_user((int *) arg, &vl_bit, sizeof(int)))
285 return -EFAULT;
286
287 return 0;
288 }
289 229
290 case RTC_VLOW_SET: 230 mutex_lock(&rtc_lock);
291 { 231 memset(&tm, 0, sizeof tm);
292 /* Clear the VL bit in the seconds register */ 232 get_rtc_time(&tm);
293 int ret = rtc_read(RTC_SECONDS);
294 233
295 rtc_write(RTC_SECONDS, (ret & 0x7F)); 234 if (copy_to_user((struct rtc_time *) arg, &tm,
235 sizeof tm)) {
236 spin_unlock(&rtc_lock);
237 return -EFAULT;
238 }
239
240 mutex_unlock(&rtc_lock);
296 241
297 return 0; 242 return 0;
243 }
244 case RTC_SET_TIME:
245 {
246 int leap;
247 int year;
248 int century;
249 struct rtc_time tm;
250
251 memset(&tm, 0, sizeof tm);
252 if (!capable(CAP_SYS_TIME))
253 return -EPERM;
254
255 if (copy_from_user(&tm, (struct rtc_time *) arg, sizeof tm))
256 return -EFAULT;
257
258 /* Convert from struct tm to struct rtc_time. */
259 tm.tm_year += 1900;
260 tm.tm_mon += 1;
261
262 /*
263 * Check if tm.tm_year is a leap year. A year is a leap
264 * year if it is divisible by 4 but not 100, except
265 * that years divisible by 400 _are_ leap years.
266 */
267 year = tm.tm_year;
268 leap = (tm.tm_mon == 2) &&
269 ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
270
271 /* Perform some sanity checks. */
272 if ((tm.tm_year < 1970) ||
273 (tm.tm_mon > 12) ||
274 (tm.tm_mday == 0) ||
275 (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
276 (tm.tm_wday >= 7) ||
277 (tm.tm_hour >= 24) ||
278 (tm.tm_min >= 60) ||
279 (tm.tm_sec >= 60))
280 return -EINVAL;
281
282 century = (tm.tm_year >= 2000) ? 0x80 : 0;
283 tm.tm_year = tm.tm_year % 100;
284
285 BIN_TO_BCD(tm.tm_year);
286 BIN_TO_BCD(tm.tm_mon);
287 BIN_TO_BCD(tm.tm_mday);
288 BIN_TO_BCD(tm.tm_hour);
289 BIN_TO_BCD(tm.tm_min);
290 BIN_TO_BCD(tm.tm_sec);
291 tm.tm_mon |= century;
292
293 mutex_lock(&rtc_lock);
294
295 rtc_write(RTC_YEAR, tm.tm_year);
296 rtc_write(RTC_MONTH, tm.tm_mon);
297 rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
298 rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
299 rtc_write(RTC_HOURS, tm.tm_hour);
300 rtc_write(RTC_MINUTES, tm.tm_min);
301 rtc_write(RTC_SECONDS, tm.tm_sec);
302
303 mutex_unlock(&rtc_lock);
304
305 return 0;
306 }
307 case RTC_VL_READ:
308 if (voltage_low) {
309 printk(KERN_ERR "%s: RTC Voltage Low - "
310 "reliable date/time information is no "
311 "longer guaranteed!\n", PCF8563_NAME);
298 } 312 }
299 313
300 default: 314 if (copy_to_user((int *) arg, &voltage_low, sizeof(int)))
301 return -ENOTTY; 315 return -EFAULT;
316 return 0;
317
318 case RTC_VL_CLR:
319 {
320 /* Clear the VL bit in the seconds register in case
321 * the time has not been set already (which would
322 * have cleared it). This does not really matter
323 * because of the cached voltage_low value but do it
324 * anyway for consistency. */
325
326 int ret = rtc_read(RTC_SECONDS);
327
328 rtc_write(RTC_SECONDS, (ret & 0x7F));
329
330 /* Clear the cached value. */
331 voltage_low = 0;
332
333 return 0;
334 }
335 default:
336 return -ENOTTY;
302 } 337 }
303 338
304 return 0; 339 return 0;
305} 340}
306 341
307static int __init 342static int __init pcf8563_register(void)
308pcf8563_register(void)
309{ 343{
310 pcf8563_init(); 344 if (pcf8563_init() < 0) {
345 printk(KERN_INFO "%s: Unable to initialize Real-Time Clock "
346 "Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
347 return -1;
348 }
349
311 if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) { 350 if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
312 printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n", 351 printk(KERN_INFO "%s: Unable to get major number %d for RTC device.\n",
313 PCF8563_NAME, PCF8563_MAJOR); 352 PCF8563_NAME, PCF8563_MAJOR);
314 return -1; 353 return -1;
315 } 354 }
316 355
317 printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME, DRIVER_VERSION); 356 printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME,
318 return 0; 357 DRIVER_VERSION);
358
359 /* Check for low voltage, and warn about it. */
360 if (voltage_low) {
361 printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
362 "information is no longer guaranteed!\n", PCF8563_NAME);
363 }
364
365 return 0;
319} 366}
320 367
321module_init(pcf8563_register); 368module_init(pcf8563_register);