Version:  2.0.40 2.2.26 2.4.37 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7

Linux/drivers/rtc/rtc-m48t86.c

  1 /*
  2  * ST M48T86 / Dallas DS12887 RTC driver
  3  * Copyright (c) 2006 Tower Technologies
  4  *
  5  * Author: Alessandro Zummo <a.zummo@towertech.it>
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License version 2 as
  9  * published by the Free Software Foundation.
 10  *
 11  * This drivers only supports the clock running in BCD and 24H mode.
 12  * If it will be ever adapted to binary and 12H mode, care must be taken
 13  * to not introduce bugs.
 14  */
 15 
 16 #include <linux/module.h>
 17 #include <linux/rtc.h>
 18 #include <linux/platform_device.h>
 19 #include <linux/m48t86.h>
 20 #include <linux/bcd.h>
 21 
 22 #define M48T86_REG_SEC          0x00
 23 #define M48T86_REG_SECALRM      0x01
 24 #define M48T86_REG_MIN          0x02
 25 #define M48T86_REG_MINALRM      0x03
 26 #define M48T86_REG_HOUR         0x04
 27 #define M48T86_REG_HOURALRM     0x05
 28 #define M48T86_REG_DOW          0x06 /* 1 = sunday */
 29 #define M48T86_REG_DOM          0x07
 30 #define M48T86_REG_MONTH        0x08 /* 1 - 12 */
 31 #define M48T86_REG_YEAR         0x09 /* 0 - 99 */
 32 #define M48T86_REG_A            0x0A
 33 #define M48T86_REG_B            0x0B
 34 #define M48T86_REG_C            0x0C
 35 #define M48T86_REG_D            0x0D
 36 
 37 #define M48T86_REG_B_H24        (1 << 1)
 38 #define M48T86_REG_B_DM         (1 << 2)
 39 #define M48T86_REG_B_SET        (1 << 7)
 40 #define M48T86_REG_D_VRT        (1 << 7)
 41 
 42 static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
 43 {
 44         unsigned char reg;
 45         struct platform_device *pdev = to_platform_device(dev);
 46         struct m48t86_ops *ops = dev_get_platdata(&pdev->dev);
 47 
 48         reg = ops->readbyte(M48T86_REG_B);
 49 
 50         if (reg & M48T86_REG_B_DM) {
 51                 /* data (binary) mode */
 52                 tm->tm_sec      = ops->readbyte(M48T86_REG_SEC);
 53                 tm->tm_min      = ops->readbyte(M48T86_REG_MIN);
 54                 tm->tm_hour     = ops->readbyte(M48T86_REG_HOUR) & 0x3F;
 55                 tm->tm_mday     = ops->readbyte(M48T86_REG_DOM);
 56                 /* tm_mon is 0-11 */
 57                 tm->tm_mon      = ops->readbyte(M48T86_REG_MONTH) - 1;
 58                 tm->tm_year     = ops->readbyte(M48T86_REG_YEAR) + 100;
 59                 tm->tm_wday     = ops->readbyte(M48T86_REG_DOW);
 60         } else {
 61                 /* bcd mode */
 62                 tm->tm_sec      = bcd2bin(ops->readbyte(M48T86_REG_SEC));
 63                 tm->tm_min      = bcd2bin(ops->readbyte(M48T86_REG_MIN));
 64                 tm->tm_hour     = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
 65                 tm->tm_mday     = bcd2bin(ops->readbyte(M48T86_REG_DOM));
 66                 /* tm_mon is 0-11 */
 67                 tm->tm_mon      = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1;
 68                 tm->tm_year     = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100;
 69                 tm->tm_wday     = bcd2bin(ops->readbyte(M48T86_REG_DOW));
 70         }
 71 
 72         /* correct the hour if the clock is in 12h mode */
 73         if (!(reg & M48T86_REG_B_H24))
 74                 if (ops->readbyte(M48T86_REG_HOUR) & 0x80)
 75                         tm->tm_hour += 12;
 76 
 77         return rtc_valid_tm(tm);
 78 }
 79 
 80 static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
 81 {
 82         unsigned char reg;
 83         struct platform_device *pdev = to_platform_device(dev);
 84         struct m48t86_ops *ops = dev_get_platdata(&pdev->dev);
 85 
 86         reg = ops->readbyte(M48T86_REG_B);
 87 
 88         /* update flag and 24h mode */
 89         reg |= M48T86_REG_B_SET | M48T86_REG_B_H24;
 90         ops->writebyte(reg, M48T86_REG_B);
 91 
 92         if (reg & M48T86_REG_B_DM) {
 93                 /* data (binary) mode */
 94                 ops->writebyte(tm->tm_sec, M48T86_REG_SEC);
 95                 ops->writebyte(tm->tm_min, M48T86_REG_MIN);
 96                 ops->writebyte(tm->tm_hour, M48T86_REG_HOUR);
 97                 ops->writebyte(tm->tm_mday, M48T86_REG_DOM);
 98                 ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH);
 99                 ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR);
100                 ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
101         } else {
102                 /* bcd mode */
103                 ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC);
104                 ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN);
105                 ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
106                 ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM);
107                 ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
108                 ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
109                 ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW);
110         }
111 
112         /* update ended */
113         reg &= ~M48T86_REG_B_SET;
114         ops->writebyte(reg, M48T86_REG_B);
115 
116         return 0;
117 }
118 
119 static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
120 {
121         unsigned char reg;
122         struct platform_device *pdev = to_platform_device(dev);
123         struct m48t86_ops *ops = dev_get_platdata(&pdev->dev);
124 
125         reg = ops->readbyte(M48T86_REG_B);
126 
127         seq_printf(seq, "mode\t\t: %s\n",
128                  (reg & M48T86_REG_B_DM) ? "binary" : "bcd");
129 
130         reg = ops->readbyte(M48T86_REG_D);
131 
132         seq_printf(seq, "battery\t\t: %s\n",
133                  (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
134 
135         return 0;
136 }
137 
138 static const struct rtc_class_ops m48t86_rtc_ops = {
139         .read_time      = m48t86_rtc_read_time,
140         .set_time       = m48t86_rtc_set_time,
141         .proc           = m48t86_rtc_proc,
142 };
143 
144 static int m48t86_rtc_probe(struct platform_device *dev)
145 {
146         unsigned char reg;
147         struct m48t86_ops *ops = dev_get_platdata(&dev->dev);
148         struct rtc_device *rtc;
149 
150         rtc = devm_rtc_device_register(&dev->dev, "m48t86",
151                                 &m48t86_rtc_ops, THIS_MODULE);
152 
153         if (IS_ERR(rtc))
154                 return PTR_ERR(rtc);
155 
156         platform_set_drvdata(dev, rtc);
157 
158         /* read battery status */
159         reg = ops->readbyte(M48T86_REG_D);
160         dev_info(&dev->dev, "battery %s\n",
161                 (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
162 
163         return 0;
164 }
165 
166 static struct platform_driver m48t86_rtc_platform_driver = {
167         .driver         = {
168                 .name   = "rtc-m48t86",
169         },
170         .probe          = m48t86_rtc_probe,
171 };
172 
173 module_platform_driver(m48t86_rtc_platform_driver);
174 
175 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
176 MODULE_DESCRIPTION("M48T86 RTC driver");
177 MODULE_LICENSE("GPL");
178 MODULE_ALIAS("platform:rtc-m48t86");
179 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us