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/version.h>
18 #include <linux/kernel.h>
19 #include <linux/platform_device.h>
20 #include <linux/device.h>
21 #include <linux/init.h>
22 #include <linux/rtc.h>
23 #include <linux/spi/spi.h>
24 #include <linux/bcd.h>
25 #include <linux/delay.h>
26 #include <linux/bitops.h>
28 #define RSECCNT 0x00 /* Second Counter */
29 #define RMINCNT 0x01 /* Minute Counter */
30 #define RHRCNT 0x02 /* Hour Counter */
31 #define RWKCNT 0x03 /* Week Counter */
32 #define RDAYCNT 0x04 /* Day Counter */
33 #define RMONCNT 0x05 /* Month Counter */
34 #define RYRCNT 0x06 /* Year Counter */
35 #define R100CNT 0x07 /* Y100 Counter */
36 #define RMINAR 0x08 /* Minute Alarm */
37 #define RHRAR 0x09 /* Hour Alarm */
38 #define RWKAR 0x0a /* Week/Day Alarm */
39 #define RTIMCNT 0x0c /* Interval Timer */
40 #define REXT 0x0d /* Extension Register */
41 #define RFLAG 0x0e /* RTC Flag Register */
42 #define RCR 0x0f /* RTC Control Register */
44 static int write_reg(struct device
*dev
, int address
, unsigned char data
)
46 struct spi_device
*spi
= to_spi_device(dev
);
49 buf
[0] = address
& 0x7f;
52 return spi_write(spi
, buf
, ARRAY_SIZE(buf
));
55 static int read_regs(struct device
*dev
, unsigned char *regs
, int no_regs
)
57 struct spi_device
*spi
= to_spi_device(dev
);
58 u8 txbuf
[1], rxbuf
[1];
63 for (k
= 0; ret
== 0 && k
< no_regs
; k
++) {
64 txbuf
[0] = 0x80 | regs
[k
];
65 ret
= spi_write_then_read(spi
, txbuf
, 1, rxbuf
, 1);
72 static int r9701_get_datetime(struct device
*dev
, struct rtc_time
*dt
)
75 unsigned char buf
[] = { RSECCNT
, RMINCNT
, RHRCNT
,
76 RDAYCNT
, RMONCNT
, RYRCNT
};
78 ret
= read_regs(dev
, buf
, ARRAY_SIZE(buf
));
82 memset(dt
, 0, sizeof(*dt
));
84 dt
->tm_sec
= BCD2BIN(buf
[0]); /* RSECCNT */
85 dt
->tm_min
= BCD2BIN(buf
[1]); /* RMINCNT */
86 dt
->tm_hour
= BCD2BIN(buf
[2]); /* RHRCNT */
88 dt
->tm_mday
= BCD2BIN(buf
[3]); /* RDAYCNT */
89 dt
->tm_mon
= BCD2BIN(buf
[4]) - 1; /* RMONCNT */
90 dt
->tm_year
= BCD2BIN(buf
[5]) + 100; /* RYRCNT */
92 /* the rtc device may contain illegal values on power up
93 * according to the data sheet. make sure they are valid.
96 return rtc_valid_tm(dt
);
99 static int r9701_set_datetime(struct device
*dev
, struct rtc_time
*dt
)
103 year
= dt
->tm_year
+ 1900;
104 if (year
>= 2100 || year
< 2000)
107 ret
= write_reg(dev
, RHRCNT
, BIN2BCD(dt
->tm_hour
));
108 ret
= ret
? ret
: write_reg(dev
, RMINCNT
, BIN2BCD(dt
->tm_min
));
109 ret
= ret
? ret
: write_reg(dev
, RSECCNT
, BIN2BCD(dt
->tm_sec
));
110 ret
= ret
? ret
: write_reg(dev
, RDAYCNT
, BIN2BCD(dt
->tm_mday
));
111 ret
= ret
? ret
: write_reg(dev
, RMONCNT
, BIN2BCD(dt
->tm_mon
+ 1));
112 ret
= ret
? ret
: write_reg(dev
, RYRCNT
, BIN2BCD(dt
->tm_year
- 100));
113 ret
= ret
? ret
: write_reg(dev
, RWKCNT
, 1 << dt
->tm_wday
);
118 static const struct rtc_class_ops r9701_rtc_ops
= {
119 .read_time
= r9701_get_datetime
,
120 .set_time
= r9701_set_datetime
,
123 static int __devinit
r9701_probe(struct spi_device
*spi
)
125 struct rtc_device
*rtc
;
129 rtc
= rtc_device_register("r9701",
130 &spi
->dev
, &r9701_rtc_ops
, THIS_MODULE
);
134 dev_set_drvdata(&spi
->dev
, rtc
);
137 res
= read_regs(&spi
->dev
, &tmp
, 1);
138 if (res
|| tmp
!= 0x20) {
139 rtc_device_unregister(rtc
);
146 static int __devexit
r9701_remove(struct spi_device
*spi
)
148 struct rtc_device
*rtc
= dev_get_drvdata(&spi
->dev
);
150 rtc_device_unregister(rtc
);
154 static struct spi_driver r9701_driver
= {
157 .owner
= THIS_MODULE
,
159 .probe
= r9701_probe
,
160 .remove
= __devexit_p(r9701_remove
),
163 static __init
int r9701_init(void)
165 return spi_register_driver(&r9701_driver
);
167 module_init(r9701_init
);
169 static __exit
void r9701_exit(void)
171 spi_unregister_driver(&r9701_driver
);
173 module_exit(r9701_exit
);
175 MODULE_DESCRIPTION("r9701 spi RTC driver");
176 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
177 MODULE_LICENSE("GPL");