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 __devinit
r9701_probe(struct spi_device
*spi
)
124 struct rtc_device
*rtc
;
128 rtc
= rtc_device_register("r9701",
129 &spi
->dev
, &r9701_rtc_ops
, THIS_MODULE
);
133 dev_set_drvdata(&spi
->dev
, rtc
);
136 res
= read_regs(&spi
->dev
, &tmp
, 1);
137 if (res
|| tmp
!= 0x20) {
138 rtc_device_unregister(rtc
);
145 static int __devexit
r9701_remove(struct spi_device
*spi
)
147 struct rtc_device
*rtc
= dev_get_drvdata(&spi
->dev
);
149 rtc_device_unregister(rtc
);
153 static struct spi_driver r9701_driver
= {
156 .owner
= THIS_MODULE
,
158 .probe
= r9701_probe
,
159 .remove
= __devexit_p(r9701_remove
),
162 static __init
int r9701_init(void)
164 return spi_register_driver(&r9701_driver
);
166 module_init(r9701_init
);
168 static __exit
void r9701_exit(void)
170 spi_unregister_driver(&r9701_driver
);
172 module_exit(r9701_exit
);
174 MODULE_DESCRIPTION("r9701 spi RTC driver");
175 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
176 MODULE_LICENSE("GPL");