summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteffen Trumtrar <s.trumtrar@pengutronix.de>2016-01-04 12:04:35 -0500
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-03-14 12:08:10 -0400
commit68298c2dac96c75ed6950f059bbb1368c21da2a3 (patch)
tree499dd8e10006ebf0f5d6a954834ff10996eb4b42
parentcfe941628a04b572b0dba7a20fd4570edad74c81 (diff)
rtc: add driver for RX6110SA real time clock
The RX6110 comes in two different variants: SPI and I2C. This driver only supports the SPI variant. If the need ever arises to also support the I2C variant, this driver could easily be refactored to support both cases. Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-rw-r--r--drivers/rtc/Kconfig9
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-rx6110.c402
3 files changed, 412 insertions, 0 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index d47ad96132bf..ec6a25324525 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -743,6 +743,15 @@ config RTC_DRV_RX4581
743 This driver can also be built as a module. If so the module 743 This driver can also be built as a module. If so the module
744 will be called rtc-rx4581. 744 will be called rtc-rx4581.
745 745
746config RTC_DRV_RX6110
747 tristate "Epson RX-6110"
748 select REGMAP_SPI
749 help
750 If you say yes here you will get support for the Epson RX-6610.
751
752 This driver can also be built as a module. If so the module
753 will be called rtc-rx6110.
754
746config RTC_DRV_MCP795 755config RTC_DRV_MCP795
747 tristate "Microchip MCP795" 756 tristate "Microchip MCP795"
748 help 757 help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index ed4519efa3ca..c8a21479deea 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -127,6 +127,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
127obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o 127obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
128obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o 128obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
129obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o 129obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
130obj-$(CONFIG_RTC_DRV_RX6110) += rtc-rx6110.o
130obj-$(CONFIG_RTC_DRV_RX8010) += rtc-rx8010.o 131obj-$(CONFIG_RTC_DRV_RX8010) += rtc-rx8010.o
131obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o 132obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
132obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o 133obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
diff --git a/drivers/rtc/rtc-rx6110.c b/drivers/rtc/rtc-rx6110.c
new file mode 100644
index 000000000000..bbad00b233bc
--- /dev/null
+++ b/drivers/rtc/rtc-rx6110.c
@@ -0,0 +1,402 @@
1/*
2 * Driver for the Epson RTC module RX-6110 SA
3 *
4 * Copyright(C) 2015 Pengutronix, Steffen Trumtrar <kernel@pengutronix.de>
5 * Copyright(C) SEIKO EPSON CORPORATION 2013. All rights reserved.
6 *
7 * This driver software is distributed as is, without any warranty of any kind,
8 * either express or implied as further specified in the GNU Public License.
9 * This software may be used and distributed according to the terms of the GNU
10 * Public License, version 2 as published by the Free Software Foundation.
11 * See the file COPYING in the main directory of this archive for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/bcd.h>
18#include <linux/init.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/of_gpio.h>
22#include <linux/regmap.h>
23#include <linux/rtc.h>
24#include <linux/spi/spi.h>
25
26/* RX-6110 Register definitions */
27#define RX6110_REG_SEC 0x10
28#define RX6110_REG_MIN 0x11
29#define RX6110_REG_HOUR 0x12
30#define RX6110_REG_WDAY 0x13
31#define RX6110_REG_MDAY 0x14
32#define RX6110_REG_MONTH 0x15
33#define RX6110_REG_YEAR 0x16
34#define RX6110_REG_RES1 0x17
35#define RX6110_REG_ALMIN 0x18
36#define RX6110_REG_ALHOUR 0x19
37#define RX6110_REG_ALWDAY 0x1A
38#define RX6110_REG_TCOUNT0 0x1B
39#define RX6110_REG_TCOUNT1 0x1C
40#define RX6110_REG_EXT 0x1D
41#define RX6110_REG_FLAG 0x1E
42#define RX6110_REG_CTRL 0x1F
43#define RX6110_REG_USER0 0x20
44#define RX6110_REG_USER1 0x21
45#define RX6110_REG_USER2 0x22
46#define RX6110_REG_USER3 0x23
47#define RX6110_REG_USER4 0x24
48#define RX6110_REG_USER5 0x25
49#define RX6110_REG_USER6 0x26
50#define RX6110_REG_USER7 0x27
51#define RX6110_REG_USER8 0x28
52#define RX6110_REG_USER9 0x29
53#define RX6110_REG_USERA 0x2A
54#define RX6110_REG_USERB 0x2B
55#define RX6110_REG_USERC 0x2C
56#define RX6110_REG_USERD 0x2D
57#define RX6110_REG_USERE 0x2E
58#define RX6110_REG_USERF 0x2F
59#define RX6110_REG_RES2 0x30
60#define RX6110_REG_RES3 0x31
61#define RX6110_REG_IRQ 0x32
62
63#define RX6110_BIT_ALARM_EN BIT(7)
64
65/* Extension Register (1Dh) bit positions */
66#define RX6110_BIT_EXT_TSEL0 BIT(0)
67#define RX6110_BIT_EXT_TSEL1 BIT(1)
68#define RX6110_BIT_EXT_TSEL2 BIT(2)
69#define RX6110_BIT_EXT_WADA BIT(3)
70#define RX6110_BIT_EXT_TE BIT(4)
71#define RX6110_BIT_EXT_USEL BIT(5)
72#define RX6110_BIT_EXT_FSEL0 BIT(6)
73#define RX6110_BIT_EXT_FSEL1 BIT(7)
74
75/* Flag Register (1Eh) bit positions */
76#define RX6110_BIT_FLAG_VLF BIT(1)
77#define RX6110_BIT_FLAG_AF BIT(3)
78#define RX6110_BIT_FLAG_TF BIT(4)
79#define RX6110_BIT_FLAG_UF BIT(5)
80
81/* Control Register (1Fh) bit positions */
82#define RX6110_BIT_CTRL_TBKE BIT(0)
83#define RX6110_BIT_CTRL_TBKON BIT(1)
84#define RX6110_BIT_CTRL_TSTP BIT(2)
85#define RX6110_BIT_CTRL_AIE BIT(3)
86#define RX6110_BIT_CTRL_TIE BIT(4)
87#define RX6110_BIT_CTRL_UIE BIT(5)
88#define RX6110_BIT_CTRL_STOP BIT(6)
89#define RX6110_BIT_CTRL_TEST BIT(7)
90
91enum {
92 RTC_SEC = 0,
93 RTC_MIN,
94 RTC_HOUR,
95 RTC_WDAY,
96 RTC_MDAY,
97 RTC_MONTH,
98 RTC_YEAR,
99 RTC_NR_TIME
100};
101
102#define RX6110_DRIVER_NAME "rx6110"
103
104struct rx6110_data {
105 struct rtc_device *rtc;
106 struct regmap *regmap;
107};
108
109/**
110 * rx6110_rtc_tm_to_data - convert rtc_time to native time encoding
111 *
112 * @tm: holds date and time
113 * @data: holds the encoding in rx6110 native form
114 */
115static int rx6110_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
116{
117 pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
118 tm->tm_sec, tm->tm_min, tm->tm_hour,
119 tm->tm_mday, tm->tm_mon, tm->tm_year);
120
121 /*
122 * The year in the RTC is a value between 0 and 99.
123 * Assume that this represents the current century
124 * and disregard all other values.
125 */
126 if (tm->tm_year < 100 || tm->tm_year >= 200)
127 return -EINVAL;
128
129 data[RTC_SEC] = bin2bcd(tm->tm_sec);
130 data[RTC_MIN] = bin2bcd(tm->tm_min);
131 data[RTC_HOUR] = bin2bcd(tm->tm_hour);
132 data[RTC_WDAY] = BIT(bin2bcd(tm->tm_wday));
133 data[RTC_MDAY] = bin2bcd(tm->tm_mday);
134 data[RTC_MONTH] = bin2bcd(tm->tm_mon + 1);
135 data[RTC_YEAR] = bin2bcd(tm->tm_year % 100);
136
137 return 0;
138}
139
140/**
141 * rx6110_data_to_rtc_tm - convert native time encoding to rtc_time
142 *
143 * @data: holds the encoding in rx6110 native form
144 * @tm: holds date and time
145 */
146static int rx6110_data_to_rtc_tm(u8 *data, struct rtc_time *tm)
147{
148 tm->tm_sec = bcd2bin(data[RTC_SEC] & 0x7f);
149 tm->tm_min = bcd2bin(data[RTC_MIN] & 0x7f);
150 /* only 24-hour clock */
151 tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f);
152 tm->tm_wday = ffs(data[RTC_WDAY] & 0x7f);
153 tm->tm_mday = bcd2bin(data[RTC_MDAY] & 0x3f);
154 tm->tm_mon = bcd2bin(data[RTC_MONTH] & 0x1f) - 1;
155 tm->tm_year = bcd2bin(data[RTC_YEAR]) + 100;
156
157 pr_debug("%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
158 tm->tm_sec, tm->tm_min, tm->tm_hour,
159 tm->tm_mday, tm->tm_mon, tm->tm_year);
160
161 /*
162 * The year in the RTC is a value between 0 and 99.
163 * Assume that this represents the current century
164 * and disregard all other values.
165 */
166 if (tm->tm_year < 100 || tm->tm_year >= 200)
167 return -EINVAL;
168
169 return 0;
170}
171
172/**
173 * rx6110_set_time - set the current time in the rx6110 registers
174 *
175 * @dev: the rtc device in use
176 * @tm: holds date and time
177 *
178 * BUG: The HW assumes every year that is a multiple of 4 to be a leap
179 * year. Next time this is wrong is 2100, which will not be a leap year
180 *
181 * Note: If STOP is not set/cleared, the clock will start when the seconds
182 * register is written
183 *
184 */
185static int rx6110_set_time(struct device *dev, struct rtc_time *tm)
186{
187 struct rx6110_data *rx6110 = dev_get_drvdata(dev);
188 u8 data[RTC_NR_TIME];
189 int ret;
190
191 ret = rx6110_rtc_tm_to_data(tm, data);
192 if (ret < 0)
193 return ret;
194
195 /* set STOP bit before changing clock/calendar */
196 ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
197 RX6110_BIT_CTRL_STOP, RX6110_BIT_CTRL_STOP);
198 if (ret)
199 return ret;
200
201 ret = regmap_bulk_write(rx6110->regmap, RX6110_REG_SEC, data,
202 RTC_NR_TIME);
203 if (ret)
204 return ret;
205
206 /* The time in the RTC is valid. Be sure to have VLF cleared. */
207 ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
208 RX6110_BIT_FLAG_VLF, 0);
209 if (ret)
210 return ret;
211
212 /* clear STOP bit after changing clock/calendar */
213 ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
214 RX6110_BIT_CTRL_STOP, 0);
215
216 return ret;
217}
218
219/**
220 * rx6110_get_time - get the current time from the rx6110 registers
221 * @dev: the rtc device in use
222 * @tm: holds date and time
223 */
224static int rx6110_get_time(struct device *dev, struct rtc_time *tm)
225{
226 struct rx6110_data *rx6110 = dev_get_drvdata(dev);
227 u8 data[RTC_NR_TIME];
228 int flags;
229 int ret;
230
231 ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags);
232 if (ret)
233 return -EINVAL;
234
235 /* check for VLF Flag (set at power-on) */
236 if ((flags & RX6110_BIT_FLAG_VLF)) {
237 dev_warn(dev, "Voltage low, data is invalid.\n");
238 return -EINVAL;
239 }
240
241 /* read registers to date */
242 ret = regmap_bulk_read(rx6110->regmap, RX6110_REG_SEC, data,
243 RTC_NR_TIME);
244 if (ret)
245 return ret;
246
247 ret = rx6110_data_to_rtc_tm(data, tm);
248 if (ret)
249 return ret;
250
251 dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
252 tm->tm_sec, tm->tm_min, tm->tm_hour,
253 tm->tm_mday, tm->tm_mon, tm->tm_year);
254
255 return rtc_valid_tm(tm);
256}
257
258static const struct reg_sequence rx6110_default_regs[] = {
259 { RX6110_REG_RES1, 0xB8 },
260 { RX6110_REG_RES2, 0x00 },
261 { RX6110_REG_RES3, 0x10 },
262 { RX6110_REG_IRQ, 0x00 },
263 { RX6110_REG_ALMIN, 0x00 },
264 { RX6110_REG_ALHOUR, 0x00 },
265 { RX6110_REG_ALWDAY, 0x00 },
266};
267
268/**
269 * rx6110_init - initialize the rx6110 registers
270 *
271 * @rx6110: pointer to the rx6110 struct in use
272 *
273 */
274static int rx6110_init(struct rx6110_data *rx6110)
275{
276 struct rtc_device *rtc = rx6110->rtc;
277 int flags;
278 int ret;
279
280 ret = regmap_update_bits(rx6110->regmap, RX6110_REG_EXT,
281 RX6110_BIT_EXT_TE, 0);
282 if (ret)
283 return ret;
284
285 ret = regmap_register_patch(rx6110->regmap, rx6110_default_regs,
286 ARRAY_SIZE(rx6110_default_regs));
287 if (ret)
288 return ret;
289
290 ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags);
291 if (ret)
292 return ret;
293
294 /* check for VLF Flag (set at power-on) */
295 if ((flags & RX6110_BIT_FLAG_VLF))
296 dev_warn(&rtc->dev, "Voltage low, data loss detected.\n");
297
298 /* check for Alarm Flag */
299 if (flags & RX6110_BIT_FLAG_AF)
300 dev_warn(&rtc->dev, "An alarm may have been missed.\n");
301
302 /* check for Periodic Timer Flag */
303 if (flags & RX6110_BIT_FLAG_TF)
304 dev_warn(&rtc->dev, "Periodic timer was detected\n");
305
306 /* check for Update Timer Flag */
307 if (flags & RX6110_BIT_FLAG_UF)
308 dev_warn(&rtc->dev, "Update timer was detected\n");
309
310 /* clear all flags BUT VLF */
311 ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
312 RX6110_BIT_FLAG_AF |
313 RX6110_BIT_FLAG_UF |
314 RX6110_BIT_FLAG_TF,
315 0);
316
317 return ret;
318}
319
320static struct rtc_class_ops rx6110_rtc_ops = {
321 .read_time = rx6110_get_time,
322 .set_time = rx6110_set_time,
323};
324
325static struct regmap_config regmap_spi_config = {
326 .reg_bits = 8,
327 .val_bits = 8,
328 .max_register = RX6110_REG_IRQ,
329 .read_flag_mask = 0x80,
330};
331
332/**
333 * rx6110_probe - initialize rtc driver
334 * @spi: pointer to spi device
335 */
336static int rx6110_probe(struct spi_device *spi)
337{
338 struct rx6110_data *rx6110;
339 int err;
340
341 if ((spi->bits_per_word && spi->bits_per_word != 8) ||
342 (spi->max_speed_hz > 2000000) ||
343 (spi->mode != (SPI_CS_HIGH | SPI_CPOL | SPI_CPHA))) {
344 dev_warn(&spi->dev, "SPI settings: bits_per_word: %d, max_speed_hz: %d, mode: %xh\n",
345 spi->bits_per_word, spi->max_speed_hz, spi->mode);
346 dev_warn(&spi->dev, "driving device in an unsupported mode");
347 }
348
349 rx6110 = devm_kzalloc(&spi->dev, sizeof(*rx6110), GFP_KERNEL);
350 if (!rx6110)
351 return -ENOMEM;
352
353 rx6110->regmap = devm_regmap_init_spi(spi, &regmap_spi_config);
354 if (IS_ERR(rx6110->regmap)) {
355 dev_err(&spi->dev, "regmap init failed for rtc rx6110\n");
356 return PTR_ERR(rx6110->regmap);
357 }
358
359 spi_set_drvdata(spi, rx6110);
360
361 rx6110->rtc = devm_rtc_device_register(&spi->dev,
362 RX6110_DRIVER_NAME,
363 &rx6110_rtc_ops, THIS_MODULE);
364
365 if (IS_ERR(rx6110->rtc))
366 return PTR_ERR(rx6110->rtc);
367
368 err = rx6110_init(rx6110);
369 if (err)
370 return err;
371
372 rx6110->rtc->max_user_freq = 1;
373
374 return 0;
375}
376
377static int rx6110_remove(struct spi_device *spi)
378{
379 return 0;
380}
381
382static const struct spi_device_id rx6110_id[] = {
383 { "rx6110", 0 },
384 { }
385};
386MODULE_DEVICE_TABLE(spi, rx6110_id);
387
388static struct spi_driver rx6110_driver = {
389 .driver = {
390 .name = RX6110_DRIVER_NAME,
391 .owner = THIS_MODULE,
392 },
393 .probe = rx6110_probe,
394 .remove = rx6110_remove,
395 .id_table = rx6110_id,
396};
397
398module_spi_driver(rx6110_driver);
399
400MODULE_AUTHOR("Val Krutov <val.krutov@erd.epson.com>");
401MODULE_DESCRIPTION("RX-6110 SA RTC driver");
402MODULE_LICENSE("GPL");