aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-m48t59.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-28 11:26:12 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-28 11:26:12 -0400
commit7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch)
treee730a4565e0318140d2fbd2f0415d18a339d7336 /drivers/rtc/rtc-m48t59.c
parent41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff)
parent0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff)
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'drivers/rtc/rtc-m48t59.c')
-rw-r--r--drivers/rtc/rtc-m48t59.c117
1 files changed, 76 insertions, 41 deletions
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 013e6c103b9c..04b63dab6932 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -24,8 +24,9 @@
24#define NO_IRQ (-1) 24#define NO_IRQ (-1)
25#endif 25#endif
26 26
27#define M48T59_READ(reg) pdata->read_byte(dev, reg) 27#define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg))
28#define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val) 28#define M48T59_WRITE(val, reg) \
29 (pdata->write_byte(dev, pdata->offset + reg, val))
29 30
30#define M48T59_SET_BITS(mask, reg) \ 31#define M48T59_SET_BITS(mask, reg) \
31 M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) 32 M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
@@ -34,7 +35,6 @@
34 35
35struct m48t59_private { 36struct m48t59_private {
36 void __iomem *ioaddr; 37 void __iomem *ioaddr;
37 unsigned int size; /* iomem size */
38 int irq; 38 int irq;
39 struct rtc_device *rtc; 39 struct rtc_device *rtc;
40 spinlock_t lock; /* serialize the NVRAM and RTC access */ 40 spinlock_t lock; /* serialize the NVRAM and RTC access */
@@ -76,21 +76,22 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
76 /* Issue the READ command */ 76 /* Issue the READ command */
77 M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); 77 M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
78 78
79 tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR)); 79 tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
80 /* tm_mon is 0-11 */ 80 /* tm_mon is 0-11 */
81 tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1; 81 tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
82 tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); 82 tm->tm_mday = bcd2bin(M48T59_READ(M48T59_MDAY));
83 83
84 val = M48T59_READ(M48T59_WDAY); 84 val = M48T59_READ(M48T59_WDAY);
85 if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { 85 if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
86 (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
86 dev_dbg(dev, "Century bit is enabled\n"); 87 dev_dbg(dev, "Century bit is enabled\n");
87 tm->tm_year += 100; /* one century */ 88 tm->tm_year += 100; /* one century */
88 } 89 }
89 90
90 tm->tm_wday = BCD2BIN(val & 0x07); 91 tm->tm_wday = bcd2bin(val & 0x07);
91 tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F); 92 tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F);
92 tm->tm_min = BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F); 93 tm->tm_min = bcd2bin(M48T59_READ(M48T59_MIN) & 0x7F);
93 tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F); 94 tm->tm_sec = bcd2bin(M48T59_READ(M48T59_SEC) & 0x7F);
94 95
95 /* Clear the READ bit */ 96 /* Clear the READ bit */
96 M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); 97 M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
@@ -118,17 +119,17 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
118 /* Issue the WRITE command */ 119 /* Issue the WRITE command */
119 M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL); 120 M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
120 121
121 M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC); 122 M48T59_WRITE((bin2bcd(tm->tm_sec) & 0x7F), M48T59_SEC);
122 M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN); 123 M48T59_WRITE((bin2bcd(tm->tm_min) & 0x7F), M48T59_MIN);
123 M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR); 124 M48T59_WRITE((bin2bcd(tm->tm_hour) & 0x3F), M48T59_HOUR);
124 M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY); 125 M48T59_WRITE((bin2bcd(tm->tm_mday) & 0x3F), M48T59_MDAY);
125 /* tm_mon is 0-11 */ 126 /* tm_mon is 0-11 */
126 M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); 127 M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
127 M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); 128 M48T59_WRITE(bin2bcd(tm->tm_year % 100), M48T59_YEAR);
128 129
129 if (tm->tm_year/100) 130 if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100))
130 val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); 131 val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
131 val |= (BIN2BCD(tm->tm_wday) & 0x07); 132 val |= (bin2bcd(tm->tm_wday) & 0x07);
132 M48T59_WRITE(val, M48T59_WDAY); 133 M48T59_WRITE(val, M48T59_WDAY);
133 134
134 /* Clear the WRITE bit */ 135 /* Clear the WRITE bit */
@@ -157,18 +158,18 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
157 /* Issue the READ command */ 158 /* Issue the READ command */
158 M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL); 159 M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
159 160
160 tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR)); 161 tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
161 /* tm_mon is 0-11 */ 162 /* tm_mon is 0-11 */
162 tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1; 163 tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
163 164
164 val = M48T59_READ(M48T59_WDAY); 165 val = M48T59_READ(M48T59_WDAY);
165 if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) 166 if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
166 tm->tm_year += 100; /* one century */ 167 tm->tm_year += 100; /* one century */
167 168
168 tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE)); 169 tm->tm_mday = bcd2bin(M48T59_READ(M48T59_ALARM_DATE));
169 tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR)); 170 tm->tm_hour = bcd2bin(M48T59_READ(M48T59_ALARM_HOUR));
170 tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN)); 171 tm->tm_min = bcd2bin(M48T59_READ(M48T59_ALARM_MIN));
171 tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC)); 172 tm->tm_sec = bcd2bin(M48T59_READ(M48T59_ALARM_SEC));
172 173
173 /* Clear the READ bit */ 174 /* Clear the READ bit */
174 M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL); 175 M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
@@ -200,18 +201,18 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
200 * 0xff means "always match" 201 * 0xff means "always match"
201 */ 202 */
202 mday = tm->tm_mday; 203 mday = tm->tm_mday;
203 mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff; 204 mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
204 if (mday == 0xff) 205 if (mday == 0xff)
205 mday = M48T59_READ(M48T59_MDAY); 206 mday = M48T59_READ(M48T59_MDAY);
206 207
207 hour = tm->tm_hour; 208 hour = tm->tm_hour;
208 hour = (hour < 24) ? BIN2BCD(hour) : 0x00; 209 hour = (hour < 24) ? bin2bcd(hour) : 0x00;
209 210
210 min = tm->tm_min; 211 min = tm->tm_min;
211 min = (min < 60) ? BIN2BCD(min) : 0x00; 212 min = (min < 60) ? bin2bcd(min) : 0x00;
212 213
213 sec = tm->tm_sec; 214 sec = tm->tm_sec;
214 sec = (sec < 60) ? BIN2BCD(sec) : 0x00; 215 sec = (sec < 60) ? bin2bcd(sec) : 0x00;
215 216
216 spin_lock_irqsave(&m48t59->lock, flags); 217 spin_lock_irqsave(&m48t59->lock, flags);
217 /* Issue the WRITE command */ 218 /* Issue the WRITE command */
@@ -310,6 +311,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = {
310 .proc = m48t59_rtc_proc, 311 .proc = m48t59_rtc_proc,
311}; 312};
312 313
314static const struct rtc_class_ops m48t02_rtc_ops = {
315 .read_time = m48t59_rtc_read_time,
316 .set_time = m48t59_rtc_set_time,
317};
318
313static ssize_t m48t59_nvram_read(struct kobject *kobj, 319static ssize_t m48t59_nvram_read(struct kobject *kobj,
314 struct bin_attribute *bin_attr, 320 struct bin_attribute *bin_attr,
315 char *buf, loff_t pos, size_t size) 321 char *buf, loff_t pos, size_t size)
@@ -321,7 +327,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj,
321 ssize_t cnt = 0; 327 ssize_t cnt = 0;
322 unsigned long flags; 328 unsigned long flags;
323 329
324 for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { 330 for (; size > 0 && pos < pdata->offset; cnt++, size--) {
325 spin_lock_irqsave(&m48t59->lock, flags); 331 spin_lock_irqsave(&m48t59->lock, flags);
326 *buf++ = M48T59_READ(cnt); 332 *buf++ = M48T59_READ(cnt);
327 spin_unlock_irqrestore(&m48t59->lock, flags); 333 spin_unlock_irqrestore(&m48t59->lock, flags);
@@ -341,7 +347,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj,
341 ssize_t cnt = 0; 347 ssize_t cnt = 0;
342 unsigned long flags; 348 unsigned long flags;
343 349
344 for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { 350 for (; size > 0 && pos < pdata->offset; cnt++, size--) {
345 spin_lock_irqsave(&m48t59->lock, flags); 351 spin_lock_irqsave(&m48t59->lock, flags);
346 M48T59_WRITE(*buf++, cnt); 352 M48T59_WRITE(*buf++, cnt);
347 spin_unlock_irqrestore(&m48t59->lock, flags); 353 spin_unlock_irqrestore(&m48t59->lock, flags);
@@ -354,11 +360,9 @@ static struct bin_attribute m48t59_nvram_attr = {
354 .attr = { 360 .attr = {
355 .name = "nvram", 361 .name = "nvram",
356 .mode = S_IRUGO | S_IWUSR, 362 .mode = S_IRUGO | S_IWUSR,
357 .owner = THIS_MODULE,
358 }, 363 },
359 .read = m48t59_nvram_read, 364 .read = m48t59_nvram_read,
360 .write = m48t59_nvram_write, 365 .write = m48t59_nvram_write,
361 .size = M48T59_NVRAM_SIZE,
362}; 366};
363 367
364static int __devinit m48t59_rtc_probe(struct platform_device *pdev) 368static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
@@ -367,6 +371,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
367 struct m48t59_private *m48t59 = NULL; 371 struct m48t59_private *m48t59 = NULL;
368 struct resource *res; 372 struct resource *res;
369 int ret = -ENOMEM; 373 int ret = -ENOMEM;
374 char *name;
375 const struct rtc_class_ops *ops;
370 376
371 /* This chip could be memory-mapped or I/O-mapped */ 377 /* This chip could be memory-mapped or I/O-mapped */
372 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 378 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -391,6 +397,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
391 /* Ensure we only kmalloc platform data once */ 397 /* Ensure we only kmalloc platform data once */
392 pdev->dev.platform_data = pdata; 398 pdev->dev.platform_data = pdata;
393 } 399 }
400 if (!pdata->type)
401 pdata->type = M48T59RTC_TYPE_M48T59;
394 402
395 /* Try to use the generic memory read/write ops */ 403 /* Try to use the generic memory read/write ops */
396 if (!pdata->write_byte) 404 if (!pdata->write_byte)
@@ -403,10 +411,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
403 if (!m48t59) 411 if (!m48t59)
404 return -ENOMEM; 412 return -ENOMEM;
405 413
406 m48t59->size = res->end - res->start + 1; 414 m48t59->ioaddr = pdata->ioaddr;
407 m48t59->ioaddr = ioremap(res->start, m48t59->size); 415
408 if (!m48t59->ioaddr) 416 if (!m48t59->ioaddr) {
409 goto out; 417 /* ioaddr not mapped externally */
418 m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1);
419 if (!m48t59->ioaddr)
420 goto out;
421 }
410 422
411 /* Try to get irq number. We also can work in 423 /* Try to get irq number. We also can work in
412 * the mode without IRQ. 424 * the mode without IRQ.
@@ -421,14 +433,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
421 if (ret) 433 if (ret)
422 goto out; 434 goto out;
423 } 435 }
436 switch (pdata->type) {
437 case M48T59RTC_TYPE_M48T59:
438 name = "m48t59";
439 ops = &m48t59_rtc_ops;
440 pdata->offset = 0x1ff0;
441 break;
442 case M48T59RTC_TYPE_M48T02:
443 name = "m48t02";
444 ops = &m48t02_rtc_ops;
445 pdata->offset = 0x7f0;
446 break;
447 case M48T59RTC_TYPE_M48T08:
448 name = "m48t08";
449 ops = &m48t02_rtc_ops;
450 pdata->offset = 0x1ff0;
451 break;
452 default:
453 dev_err(&pdev->dev, "Unknown RTC type\n");
454 ret = -ENODEV;
455 goto out;
456 }
424 457
425 m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, 458 m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE);
426 &m48t59_rtc_ops, THIS_MODULE);
427 if (IS_ERR(m48t59->rtc)) { 459 if (IS_ERR(m48t59->rtc)) {
428 ret = PTR_ERR(m48t59->rtc); 460 ret = PTR_ERR(m48t59->rtc);
429 goto out; 461 goto out;
430 } 462 }
431 463
464 m48t59_nvram_attr.size = pdata->offset;
465
432 ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); 466 ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
433 if (ret) 467 if (ret)
434 goto out; 468 goto out;
@@ -452,11 +486,12 @@ out:
452static int __devexit m48t59_rtc_remove(struct platform_device *pdev) 486static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
453{ 487{
454 struct m48t59_private *m48t59 = platform_get_drvdata(pdev); 488 struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
489 struct m48t59_plat_data *pdata = pdev->dev.platform_data;
455 490
456 sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); 491 sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
457 if (!IS_ERR(m48t59->rtc)) 492 if (!IS_ERR(m48t59->rtc))
458 rtc_device_unregister(m48t59->rtc); 493 rtc_device_unregister(m48t59->rtc);
459 if (m48t59->ioaddr) 494 if (m48t59->ioaddr && !pdata->ioaddr)
460 iounmap(m48t59->ioaddr); 495 iounmap(m48t59->ioaddr);
461 if (m48t59->irq != NO_IRQ) 496 if (m48t59->irq != NO_IRQ)
462 free_irq(m48t59->irq, &pdev->dev); 497 free_irq(m48t59->irq, &pdev->dev);
@@ -491,5 +526,5 @@ module_init(m48t59_rtc_init);
491module_exit(m48t59_rtc_exit); 526module_exit(m48t59_rtc_exit);
492 527
493MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); 528MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
494MODULE_DESCRIPTION("M48T59 RTC driver"); 529MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver");
495MODULE_LICENSE("GPL"); 530MODULE_LICENSE("GPL");