Blame view
drivers/rtc/rtc-m48t86.c
5.48 KB
1d98af872 [PATCH] RTC subsy... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* * 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 |
f90a65060 [PATCH] RTC subsy... |
26 |
#define M48T86_REG_HOUR 0x04 |
1d98af872 [PATCH] RTC subsy... |
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#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; |
2d7b20c18 [PATCH] m48t86: i... |
50 |
reg = ops->readbyte(M48T86_REG_B); |
1d98af872 [PATCH] RTC subsy... |
51 52 53 |
if (reg & M48T86_REG_B_DM) { /* data (binary) mode */ |
2d7b20c18 [PATCH] m48t86: i... |
54 55 56 57 |
tm->tm_sec = ops->readbyte(M48T86_REG_SEC); tm->tm_min = ops->readbyte(M48T86_REG_MIN); tm->tm_hour = ops->readbyte(M48T86_REG_HOUR) & 0x3F; tm->tm_mday = ops->readbyte(M48T86_REG_DOM); |
1d98af872 [PATCH] RTC subsy... |
58 |
/* tm_mon is 0-11 */ |
2d7b20c18 [PATCH] m48t86: i... |
59 60 61 |
tm->tm_mon = ops->readbyte(M48T86_REG_MONTH) - 1; tm->tm_year = ops->readbyte(M48T86_REG_YEAR) + 100; tm->tm_wday = ops->readbyte(M48T86_REG_DOW); |
1d98af872 [PATCH] RTC subsy... |
62 63 |
} else { /* bcd mode */ |
fe20ba70a drivers/rtc/: use... |
64 65 66 67 |
tm->tm_sec = bcd2bin(ops->readbyte(M48T86_REG_SEC)); tm->tm_min = bcd2bin(ops->readbyte(M48T86_REG_MIN)); tm->tm_hour = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F); tm->tm_mday = bcd2bin(ops->readbyte(M48T86_REG_DOM)); |
1d98af872 [PATCH] RTC subsy... |
68 |
/* tm_mon is 0-11 */ |
fe20ba70a drivers/rtc/: use... |
69 70 71 |
tm->tm_mon = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1; tm->tm_year = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100; tm->tm_wday = bcd2bin(ops->readbyte(M48T86_REG_DOW)); |
1d98af872 [PATCH] RTC subsy... |
72 73 74 75 |
} /* correct the hour if the clock is in 12h mode */ if (!(reg & M48T86_REG_B_H24)) |
2d7b20c18 [PATCH] m48t86: i... |
76 |
if (ops->readbyte(M48T86_REG_HOUR) & 0x80) |
1d98af872 [PATCH] RTC subsy... |
77 |
tm->tm_hour += 12; |
52142ed41 rtc/m48t86: use r... |
78 |
return rtc_valid_tm(tm); |
1d98af872 [PATCH] RTC subsy... |
79 80 81 82 83 84 85 |
} 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; |
2d7b20c18 [PATCH] m48t86: i... |
86 |
reg = ops->readbyte(M48T86_REG_B); |
1d98af872 [PATCH] RTC subsy... |
87 88 89 |
/* update flag and 24h mode */ reg |= M48T86_REG_B_SET | M48T86_REG_B_H24; |
2d7b20c18 [PATCH] m48t86: i... |
90 |
ops->writebyte(reg, M48T86_REG_B); |
1d98af872 [PATCH] RTC subsy... |
91 92 93 |
if (reg & M48T86_REG_B_DM) { /* data (binary) mode */ |
2d7b20c18 [PATCH] m48t86: i... |
94 95 96 97 98 99 100 |
ops->writebyte(tm->tm_sec, M48T86_REG_SEC); ops->writebyte(tm->tm_min, M48T86_REG_MIN); ops->writebyte(tm->tm_hour, M48T86_REG_HOUR); ops->writebyte(tm->tm_mday, M48T86_REG_DOM); ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH); ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR); ops->writebyte(tm->tm_wday, M48T86_REG_DOW); |
1d98af872 [PATCH] RTC subsy... |
101 102 |
} else { /* bcd mode */ |
fe20ba70a drivers/rtc/: use... |
103 104 105 106 107 108 109 |
ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC); ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN); ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR); ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM); ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH); ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR); ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW); |
1d98af872 [PATCH] RTC subsy... |
110 111 112 113 |
} /* update ended */ reg &= ~M48T86_REG_B_SET; |
2d7b20c18 [PATCH] m48t86: i... |
114 |
ops->writebyte(reg, M48T86_REG_B); |
1d98af872 [PATCH] RTC subsy... |
115 116 117 118 119 120 121 122 123 |
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; |
2d7b20c18 [PATCH] m48t86: i... |
124 |
reg = ops->readbyte(M48T86_REG_B); |
1d98af872 [PATCH] RTC subsy... |
125 |
|
1d98af872 [PATCH] RTC subsy... |
126 127 128 |
seq_printf(seq, "mode\t\t: %s ", (reg & M48T86_REG_B_DM) ? "binary" : "bcd"); |
2d7b20c18 [PATCH] m48t86: i... |
129 |
reg = ops->readbyte(M48T86_REG_D); |
1d98af872 [PATCH] RTC subsy... |
130 131 132 133 134 135 136 |
seq_printf(seq, "battery\t\t: %s ", (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted"); return 0; } |
ff8371ac9 [PATCH] constify ... |
137 |
static const struct rtc_class_ops m48t86_rtc_ops = { |
1d98af872 [PATCH] RTC subsy... |
138 139 140 141 142 143 144 145 146 147 148 |
.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); |
d1d65b771 [PATCH] RTC subsy... |
149 |
if (IS_ERR(rtc)) |
1d98af872 [PATCH] RTC subsy... |
150 |
return PTR_ERR(rtc); |
1d98af872 [PATCH] RTC subsy... |
151 152 153 154 |
platform_set_drvdata(dev, rtc); /* read battery status */ |
2d7b20c18 [PATCH] m48t86: i... |
155 |
reg = ops->readbyte(M48T86_REG_D); |
1d98af872 [PATCH] RTC subsy... |
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
dev_info(&dev->dev, "battery %s ", (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), }; |
0c4eae665 rtc: convert driv... |
183 |
module_platform_driver(m48t86_rtc_platform_driver); |
1d98af872 [PATCH] RTC subsy... |
184 185 186 187 188 |
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>"); MODULE_DESCRIPTION("M48T86 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); |
ad28a07bc rtc: fix platform... |
189 |
MODULE_ALIAS("platform:rtc-m48t86"); |