xref: /openbmc/linux/drivers/rtc/rtc-m41t93.c (revision 95c96174)
1 /*
2  *
3  * Driver for ST M41T93 SPI RTC
4  *
5  * (c) 2010 Nikolaus Voss, Weinmann Medical GmbH
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 
12 #include <linux/bcd.h>
13 #include <linux/kernel.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/rtc.h>
17 #include <linux/spi/spi.h>
18 
19 #define M41T93_REG_SSEC			0
20 #define M41T93_REG_ST_SEC		1
21 #define M41T93_REG_MIN			2
22 #define M41T93_REG_CENT_HOUR		3
23 #define M41T93_REG_WDAY			4
24 #define M41T93_REG_DAY			5
25 #define M41T93_REG_MON			6
26 #define M41T93_REG_YEAR			7
27 
28 
29 #define M41T93_REG_ALM_HOUR_HT		0xc
30 #define M41T93_REG_FLAGS		0xf
31 
32 #define M41T93_FLAG_ST			(1 << 7)
33 #define M41T93_FLAG_OF			(1 << 2)
34 #define M41T93_FLAG_BL			(1 << 4)
35 #define M41T93_FLAG_HT			(1 << 6)
36 
37 static inline int m41t93_set_reg(struct spi_device *spi, u8 addr, u8 data)
38 {
39 	u8 buf[2];
40 
41 	/* MSB must be '1' to write */
42 	buf[0] = addr | 0x80;
43 	buf[1] = data;
44 
45 	return spi_write(spi, buf, sizeof(buf));
46 }
47 
48 static int m41t93_set_time(struct device *dev, struct rtc_time *tm)
49 {
50 	struct spi_device *spi = to_spi_device(dev);
51 	u8 buf[9] = {0x80};        /* write cmd + 8 data bytes */
52 	u8 * const data = &buf[1]; /* ptr to first data byte */
53 
54 	dev_dbg(dev, "%s secs=%d, mins=%d, "
55 		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
56 		"write", tm->tm_sec, tm->tm_min,
57 		tm->tm_hour, tm->tm_mday,
58 		tm->tm_mon, tm->tm_year, tm->tm_wday);
59 
60 	if (tm->tm_year < 100) {
61 		dev_warn(&spi->dev, "unsupported date (before 2000-01-01).\n");
62 		return -EINVAL;
63 	}
64 
65 	data[M41T93_REG_SSEC]		= 0;
66 	data[M41T93_REG_ST_SEC]		= bin2bcd(tm->tm_sec);
67 	data[M41T93_REG_MIN]		= bin2bcd(tm->tm_min);
68 	data[M41T93_REG_CENT_HOUR]	= bin2bcd(tm->tm_hour) |
69 						((tm->tm_year/100-1) << 6);
70 	data[M41T93_REG_DAY]		= bin2bcd(tm->tm_mday);
71 	data[M41T93_REG_WDAY]		= bin2bcd(tm->tm_wday + 1);
72 	data[M41T93_REG_MON]		= bin2bcd(tm->tm_mon + 1);
73 	data[M41T93_REG_YEAR]		= bin2bcd(tm->tm_year % 100);
74 
75 	return spi_write(spi, buf, sizeof(buf));
76 }
77 
78 
79 static int m41t93_get_time(struct device *dev, struct rtc_time *tm)
80 {
81 	struct spi_device *spi = to_spi_device(dev);
82 	const u8 start_addr = 0;
83 	u8 buf[8];
84 	int century_after_1900;
85 	int tmp;
86 	int ret = 0;
87 
88 	/* Check status of clock. Two states must be considered:
89 	   1. halt bit (HT) is set: the clock is running but update of readout
90 	      registers has been disabled due to power failure. This is normal
91 	      case after poweron. Time is valid after resetting HT bit.
92 	   2. oscillator fail bit (OF) is set. Oscillator has be stopped and
93 	      time is invalid:
94 	      a) OF can be immeditely reset.
95 	      b) OF cannot be immediately reset: oscillator has to be restarted.
96 	*/
97 	tmp = spi_w8r8(spi, M41T93_REG_ALM_HOUR_HT);
98 	if (tmp < 0)
99 		return tmp;
100 
101 	if (tmp & M41T93_FLAG_HT) {
102 		dev_dbg(&spi->dev, "HT bit is set, reenable clock update.\n");
103 		m41t93_set_reg(spi, M41T93_REG_ALM_HOUR_HT,
104 			       tmp & ~M41T93_FLAG_HT);
105 	}
106 
107 	tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
108 	if (tmp < 0)
109 		return tmp;
110 
111 	if (tmp & M41T93_FLAG_OF) {
112 		ret = -EINVAL;
113 		dev_warn(&spi->dev, "OF bit is set, resetting.\n");
114 		m41t93_set_reg(spi, M41T93_REG_FLAGS, tmp & ~M41T93_FLAG_OF);
115 
116 		tmp = spi_w8r8(spi, M41T93_REG_FLAGS);
117 		if (tmp < 0)
118 			return tmp;
119 		else if (tmp & M41T93_FLAG_OF) {
120 			u8 reset_osc = buf[M41T93_REG_ST_SEC] | M41T93_FLAG_ST;
121 
122 			dev_warn(&spi->dev,
123 				 "OF bit is still set, kickstarting clock.\n");
124 			m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
125 			reset_osc &= ~M41T93_FLAG_ST;
126 			m41t93_set_reg(spi, M41T93_REG_ST_SEC, reset_osc);
127 		}
128 	}
129 
130 	if (tmp & M41T93_FLAG_BL)
131 		dev_warn(&spi->dev, "BL bit is set, replace battery.\n");
132 
133 	/* read actual time/date */
134 	tmp = spi_write_then_read(spi, &start_addr, 1, buf, sizeof(buf));
135 	if (tmp < 0)
136 		return tmp;
137 
138 	tm->tm_sec	= bcd2bin(buf[M41T93_REG_ST_SEC]);
139 	tm->tm_min	= bcd2bin(buf[M41T93_REG_MIN]);
140 	tm->tm_hour	= bcd2bin(buf[M41T93_REG_CENT_HOUR] & 0x3f);
141 	tm->tm_mday	= bcd2bin(buf[M41T93_REG_DAY]);
142 	tm->tm_mon	= bcd2bin(buf[M41T93_REG_MON]) - 1;
143 	tm->tm_wday	= bcd2bin(buf[M41T93_REG_WDAY] & 0x0f) - 1;
144 
145 	century_after_1900 = (buf[M41T93_REG_CENT_HOUR] >> 6) + 1;
146 	tm->tm_year = bcd2bin(buf[M41T93_REG_YEAR]) + century_after_1900 * 100;
147 
148 	dev_dbg(dev, "%s secs=%d, mins=%d, "
149 		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
150 		"read", tm->tm_sec, tm->tm_min,
151 		tm->tm_hour, tm->tm_mday,
152 		tm->tm_mon, tm->tm_year, tm->tm_wday);
153 
154 	return ret < 0 ? ret : rtc_valid_tm(tm);
155 }
156 
157 
158 static const struct rtc_class_ops m41t93_rtc_ops = {
159 	.read_time	= m41t93_get_time,
160 	.set_time	= m41t93_set_time,
161 };
162 
163 static struct spi_driver m41t93_driver;
164 
165 static int __devinit m41t93_probe(struct spi_device *spi)
166 {
167 	struct rtc_device *rtc;
168 	int res;
169 
170 	spi->bits_per_word = 8;
171 	spi_setup(spi);
172 
173 	res = spi_w8r8(spi, M41T93_REG_WDAY);
174 	if (res < 0 || (res & 0xf8) != 0) {
175 		dev_err(&spi->dev, "not found 0x%x.\n", res);
176 		return -ENODEV;
177 	}
178 
179 	rtc = rtc_device_register(m41t93_driver.driver.name,
180 		&spi->dev, &m41t93_rtc_ops, THIS_MODULE);
181 	if (IS_ERR(rtc))
182 		return PTR_ERR(rtc);
183 
184 	dev_set_drvdata(&spi->dev, rtc);
185 
186 	return 0;
187 }
188 
189 
190 static int __devexit m41t93_remove(struct spi_device *spi)
191 {
192 	struct rtc_device *rtc = spi_get_drvdata(spi);
193 
194 	if (rtc)
195 		rtc_device_unregister(rtc);
196 
197 	return 0;
198 }
199 
200 static struct spi_driver m41t93_driver = {
201 	.driver = {
202 		.name	= "rtc-m41t93",
203 		.owner	= THIS_MODULE,
204 	},
205 	.probe	= m41t93_probe,
206 	.remove = __devexit_p(m41t93_remove),
207 };
208 
209 module_spi_driver(m41t93_driver);
210 
211 MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>");
212 MODULE_DESCRIPTION("Driver for ST M41T93 SPI RTC");
213 MODULE_LICENSE("GPL");
214 MODULE_ALIAS("spi:rtc-m41t93");
215