-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 24344 b: refs/heads/master c: 1d98af8 h: refs/heads/master v: v3
- Loading branch information
Alessandro Zummo
authored and
Linus Torvalds
committed
Mar 27, 2006
1 parent
c36c2df
commit 75905f4
Showing
5 changed files
with
237 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: e842f1c8ff8a88f290e26d1139e89aad02c4e0c3 | ||
refs/heads/master: 1d98af87270cc08bb8251e004b9dc63cc838f24b |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
/* | ||
* ST M48T86 / Dallas DS12887 RTC driver | ||
* Copyright (c) 2006 Tower Technologies | ||
* | ||
* Author: Alessandro Zummo <a.zummo@towertech.it> | ||
* | ||
* 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. | ||
* | ||
* This drivers only supports the clock running in BCD and 24H mode. | ||
* If it will be ever adapted to binary and 12H mode, care must be taken | ||
* to not introduce bugs. | ||
*/ | ||
|
||
#include <linux/module.h> | ||
#include <linux/rtc.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/m48t86.h> | ||
#include <linux/bcd.h> | ||
|
||
#define M48T86_REG_SEC 0x00 | ||
#define M48T86_REG_SECALRM 0x01 | ||
#define M48T86_REG_MIN 0x02 | ||
#define M48T86_REG_MINALRM 0x03 | ||
#define M48T86_REG_HOUR 0x04 | ||
#define M48T86_REG_HOURALRM 0x05 | ||
#define M48T86_REG_DOW 0x06 /* 1 = sunday */ | ||
#define M48T86_REG_DOM 0x07 | ||
#define M48T86_REG_MONTH 0x08 /* 1 - 12 */ | ||
#define M48T86_REG_YEAR 0x09 /* 0 - 99 */ | ||
#define M48T86_REG_A 0x0A | ||
#define M48T86_REG_B 0x0B | ||
#define M48T86_REG_C 0x0C | ||
#define M48T86_REG_D 0x0D | ||
|
||
#define M48T86_REG_B_H24 (1 << 1) | ||
#define M48T86_REG_B_DM (1 << 2) | ||
#define M48T86_REG_B_SET (1 << 7) | ||
#define M48T86_REG_D_VRT (1 << 7) | ||
|
||
#define DRV_VERSION "0.1" | ||
|
||
|
||
static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
{ | ||
unsigned char reg; | ||
struct platform_device *pdev = to_platform_device(dev); | ||
struct m48t86_ops *ops = pdev->dev.platform_data; | ||
|
||
reg = ops->readb(M48T86_REG_B); | ||
|
||
if (reg & M48T86_REG_B_DM) { | ||
/* data (binary) mode */ | ||
tm->tm_sec = ops->readb(M48T86_REG_SEC); | ||
tm->tm_min = ops->readb(M48T86_REG_MIN); | ||
tm->tm_hour = ops->readb(M48T86_REG_HOUR) & 0x3F; | ||
tm->tm_mday = ops->readb(M48T86_REG_DOM); | ||
/* tm_mon is 0-11 */ | ||
tm->tm_mon = ops->readb(M48T86_REG_MONTH) - 1; | ||
tm->tm_year = ops->readb(M48T86_REG_YEAR) + 100; | ||
tm->tm_wday = ops->readb(M48T86_REG_DOW); | ||
} else { | ||
/* bcd mode */ | ||
tm->tm_sec = BCD2BIN(ops->readb(M48T86_REG_SEC)); | ||
tm->tm_min = BCD2BIN(ops->readb(M48T86_REG_MIN)); | ||
tm->tm_hour = BCD2BIN(ops->readb(M48T86_REG_HOUR) & 0x3F); | ||
tm->tm_mday = BCD2BIN(ops->readb(M48T86_REG_DOM)); | ||
/* tm_mon is 0-11 */ | ||
tm->tm_mon = BCD2BIN(ops->readb(M48T86_REG_MONTH)) - 1; | ||
tm->tm_year = BCD2BIN(ops->readb(M48T86_REG_YEAR)) + 100; | ||
tm->tm_wday = BCD2BIN(ops->readb(M48T86_REG_DOW)); | ||
} | ||
|
||
/* correct the hour if the clock is in 12h mode */ | ||
if (!(reg & M48T86_REG_B_H24)) | ||
if (ops->readb(M48T86_REG_HOUR) & 0x80) | ||
tm->tm_hour += 12; | ||
|
||
return 0; | ||
} | ||
|
||
static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
{ | ||
unsigned char reg; | ||
struct platform_device *pdev = to_platform_device(dev); | ||
struct m48t86_ops *ops = pdev->dev.platform_data; | ||
|
||
reg = ops->readb(M48T86_REG_B); | ||
|
||
/* update flag and 24h mode */ | ||
reg |= M48T86_REG_B_SET | M48T86_REG_B_H24; | ||
ops->writeb(reg, M48T86_REG_B); | ||
|
||
if (reg & M48T86_REG_B_DM) { | ||
/* data (binary) mode */ | ||
ops->writeb(tm->tm_sec, M48T86_REG_SEC); | ||
ops->writeb(tm->tm_min, M48T86_REG_MIN); | ||
ops->writeb(tm->tm_hour, M48T86_REG_HOUR); | ||
ops->writeb(tm->tm_mday, M48T86_REG_DOM); | ||
ops->writeb(tm->tm_mon + 1, M48T86_REG_MONTH); | ||
ops->writeb(tm->tm_year % 100, M48T86_REG_YEAR); | ||
ops->writeb(tm->tm_wday, M48T86_REG_DOW); | ||
} else { | ||
/* bcd mode */ | ||
ops->writeb(BIN2BCD(tm->tm_sec), M48T86_REG_SEC); | ||
ops->writeb(BIN2BCD(tm->tm_min), M48T86_REG_MIN); | ||
ops->writeb(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR); | ||
ops->writeb(BIN2BCD(tm->tm_mday), M48T86_REG_DOM); | ||
ops->writeb(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH); | ||
ops->writeb(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR); | ||
ops->writeb(BIN2BCD(tm->tm_wday), M48T86_REG_DOW); | ||
} | ||
|
||
/* update ended */ | ||
reg &= ~M48T86_REG_B_SET; | ||
ops->writeb(reg, M48T86_REG_B); | ||
|
||
return 0; | ||
} | ||
|
||
static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq) | ||
{ | ||
unsigned char reg; | ||
struct platform_device *pdev = to_platform_device(dev); | ||
struct m48t86_ops *ops = pdev->dev.platform_data; | ||
|
||
reg = ops->readb(M48T86_REG_B); | ||
|
||
seq_printf(seq, "24hr\t\t: %s\n", | ||
(reg & M48T86_REG_B_H24) ? "yes" : "no"); | ||
|
||
seq_printf(seq, "mode\t\t: %s\n", | ||
(reg & M48T86_REG_B_DM) ? "binary" : "bcd"); | ||
|
||
reg = ops->readb(M48T86_REG_D); | ||
|
||
seq_printf(seq, "battery\t\t: %s\n", | ||
(reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); | ||
|
||
return 0; | ||
} | ||
|
||
static struct rtc_class_ops m48t86_rtc_ops = { | ||
.read_time = m48t86_rtc_read_time, | ||
.set_time = m48t86_rtc_set_time, | ||
.proc = m48t86_rtc_proc, | ||
}; | ||
|
||
static int __devinit m48t86_rtc_probe(struct platform_device *dev) | ||
{ | ||
unsigned char reg; | ||
struct m48t86_ops *ops = dev->dev.platform_data; | ||
struct rtc_device *rtc = rtc_device_register("m48t86", | ||
&dev->dev, &m48t86_rtc_ops, THIS_MODULE); | ||
|
||
if (IS_ERR(rtc)) { | ||
dev_err(&dev->dev, "unable to register\n"); | ||
return PTR_ERR(rtc); | ||
} | ||
|
||
platform_set_drvdata(dev, rtc); | ||
|
||
/* read battery status */ | ||
reg = ops->readb(M48T86_REG_D); | ||
dev_info(&dev->dev, "battery %s\n", | ||
(reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); | ||
|
||
return 0; | ||
} | ||
|
||
static int __devexit m48t86_rtc_remove(struct platform_device *dev) | ||
{ | ||
struct rtc_device *rtc = platform_get_drvdata(dev); | ||
|
||
if (rtc) | ||
rtc_device_unregister(rtc); | ||
|
||
platform_set_drvdata(dev, NULL); | ||
|
||
return 0; | ||
} | ||
|
||
static struct platform_driver m48t86_rtc_platform_driver = { | ||
.driver = { | ||
.name = "rtc-m48t86", | ||
.owner = THIS_MODULE, | ||
}, | ||
.probe = m48t86_rtc_probe, | ||
.remove = __devexit_p(m48t86_rtc_remove), | ||
}; | ||
|
||
static int __init m48t86_rtc_init(void) | ||
{ | ||
return platform_driver_register(&m48t86_rtc_platform_driver); | ||
} | ||
|
||
static void __exit m48t86_rtc_exit(void) | ||
{ | ||
platform_driver_unregister(&m48t86_rtc_platform_driver); | ||
} | ||
|
||
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); | ||
MODULE_DESCRIPTION("M48T86 RTC driver"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_VERSION(DRV_VERSION); | ||
|
||
module_init(m48t86_rtc_init); | ||
module_exit(m48t86_rtc_exit); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* ST M48T86 / Dallas DS12887 RTC driver | ||
* Copyright (c) 2006 Tower Technologies | ||
* | ||
* Author: Alessandro Zummo <a.zummo@towertech.it> | ||
* | ||
* 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. | ||
*/ | ||
|
||
struct m48t86_ops | ||
{ | ||
void (*writeb)(unsigned char value, unsigned long addr); | ||
unsigned char (*readb)(unsigned long addr); | ||
}; |