2 * Driver for Epson RTC-9701JE
4 * Copyright (C) 2008 Magnus Damm
6 * Based on rtc-max6902.c
8 * Copyright (C) 2006 8D Technologies inc.
9 * Copyright (C) 2004 Compulab Ltd.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/platform_device.h>
19 #include <linux/device.h>
20 #include <linux/init.h>
21 #include <linux/rtc.h>
22 #include <linux/spi/spi.h>
23 #include <linux/bcd.h>
24 #include <linux/delay.h>
25 #include <linux/bitops.h>
27 #define RSECCNT 0x00 /* Second Counter */
28 #define RMINCNT 0x01 /* Minute Counter */
29 #define RHRCNT 0x02 /* Hour Counter */
30 #define RWKCNT 0x03 /* Week Counter */
31 #define RDAYCNT 0x04 /* Day Counter */
32 #define RMONCNT 0x05 /* Month Counter */
33 #define RYRCNT 0x06 /* Year Counter */
34 #define R100CNT 0x07 /* Y100 Counter */
35 #define RMINAR 0x08 /* Minute Alarm */
36 #define RHRAR 0x09 /* Hour Alarm */
37 #define RWKAR 0x0a /* Week/Day Alarm */
38 #define RTIMCNT 0x0c /* Interval Timer */
39 #define REXT 0x0d /* Extension Register */
40 #define RFLAG 0x0e /* RTC Flag Register */
41 #define RCR 0x0f /* RTC Control Register */
43 static int write_reg(struct device
*dev
, int address
, unsigned char data
)
45 struct spi_device
*spi
= to_spi_device(dev
);
48 buf
[0] = address
& 0x7f;
51 return spi_write(spi
, buf
, ARRAY_SIZE(buf
));
54 static int read_regs(struct device
*dev
, unsigned char *regs
, int no_regs
)
56 struct spi_device
*spi
= to_spi_device(dev
);
57 u8 txbuf
[1], rxbuf
[1];
62 for (k
= 0; ret
== 0 && k
< no_regs
; k
++) {
63 txbuf
[0] = 0x80 | regs
[k
];
64 ret
= spi_write_then_read(spi
, txbuf
, 1, rxbuf
, 1);
71 static int r9701_get_datetime(struct device
*dev
, struct rtc_time
*dt
)
74 unsigned char buf
[] = { RSECCNT
, RMINCNT
, RHRCNT
,
75 RDAYCNT
, RMONCNT
, RYRCNT
};
77 ret
= read_regs(dev
, buf
, ARRAY_SIZE(buf
));
81 memset(dt
, 0, sizeof(*dt
));
83 dt
->tm_sec
= bcd2bin(buf
[0]); /* RSECCNT */
84 dt
->tm_min
= bcd2bin(buf
[1]); /* RMINCNT */
85 dt
->tm_hour
= bcd2bin(buf
[2]); /* RHRCNT */
87 dt
->tm_mday
= bcd2bin(buf
[3]); /* RDAYCNT */
88 dt
->tm_mon
= bcd2bin(buf
[4]) - 1; /* RMONCNT */
89 dt
->tm_year
= bcd2bin(buf
[5]) + 100; /* RYRCNT */
91 /* the rtc device may contain illegal values on power up
92 * according to the data sheet. make sure they are valid.
95 return rtc_valid_tm(dt
);
98 static int r9701_set_datetime(struct device
*dev
, struct rtc_time
*dt
)
102 year
= dt
->tm_year
+ 1900;
103 if (year
>= 2100 || year
< 2000)
106 ret
= write_reg(dev
, RHRCNT
, bin2bcd(dt
->tm_hour
));
107 ret
= ret
? ret
: write_reg(dev
, RMINCNT
, bin2bcd(dt
->tm_min
));
108 ret
= ret
? ret
: write_reg(dev
, RSECCNT
, bin2bcd(dt
->tm_sec
));
109 ret
= ret
? ret
: write_reg(dev
, RDAYCNT
, bin2bcd(dt
->tm_mday
));
110 ret
= ret
? ret
: write_reg(dev
, RMONCNT
, bin2bcd(dt
->tm_mon
+ 1));
111 ret
= ret
? ret
: write_reg(dev
, RYRCNT
, bin2bcd(dt
->tm_year
- 100));
112 ret
= ret
? ret
: write_reg(dev
, RWKCNT
, 1 << dt
->tm_wday
);
117 static const struct rtc_class_ops r9701_rtc_ops
= {
118 .read_time
= r9701_get_datetime
,
119 .set_time
= r9701_set_datetime
,
122 static int r9701_probe(struct spi_device
*spi
)
124 struct rtc_device
*rtc
;
130 res
= read_regs(&spi
->dev
, &tmp
, 1);
131 if (res
|| tmp
!= 0x20) {
132 dev_err(&spi
->dev
, "cannot read RTC register\n");
137 * The device seems to be present. Now check if the registers
138 * contain invalid values. If so, try to write a default date:
141 if (r9701_get_datetime(&spi
->dev
, &dt
)) {
142 dev_info(&spi
->dev
, "trying to repair invalid date/time\n");
150 if (r9701_set_datetime(&spi
->dev
, &dt
) ||
151 r9701_get_datetime(&spi
->dev
, &dt
)) {
152 dev_err(&spi
->dev
, "cannot repair RTC register\n");
157 rtc
= devm_rtc_device_register(&spi
->dev
, "r9701",
158 &r9701_rtc_ops
, THIS_MODULE
);
162 spi_set_drvdata(spi
, rtc
);
167 static int r9701_remove(struct spi_device
*spi
)
172 static struct spi_driver r9701_driver
= {
175 .owner
= THIS_MODULE
,
177 .probe
= r9701_probe
,
178 .remove
= r9701_remove
,
181 module_spi_driver(r9701_driver
);
183 MODULE_DESCRIPTION("r9701 spi RTC driver");
184 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
185 MODULE_LICENSE("GPL");
186 MODULE_ALIAS("spi:rtc-r9701");