xref: /OK3568_Linux_fs/kernel/drivers/rtc/rtc-rx4581.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /* drivers/rtc/rtc-rx4581.c
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * written by Torben Hohn <torbenh@linutronix.de>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Based on:
7*4882a593Smuzhiyun  * drivers/rtc/rtc-max6902.c
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  * Copyright (C) 2006 8D Technologies inc.
10*4882a593Smuzhiyun  * Copyright (C) 2004 Compulab Ltd.
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * Driver for MAX6902 spi RTC
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * and based on:
15*4882a593Smuzhiyun  * drivers/rtc/rtc-rx8581.c
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * An I2C driver for the Epson RX8581 RTC
18*4882a593Smuzhiyun  *
19*4882a593Smuzhiyun  * Author: Martyn Welch <martyn.welch@ge.com>
20*4882a593Smuzhiyun  * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
21*4882a593Smuzhiyun  *
22*4882a593Smuzhiyun  * Based on: rtc-pcf8563.c (An I2C driver for the Philips PCF8563 RTC)
23*4882a593Smuzhiyun  * Copyright 2005-06 Tower Technologies
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #include <linux/module.h>
27*4882a593Smuzhiyun #include <linux/kernel.h>
28*4882a593Smuzhiyun #include <linux/platform_device.h>
29*4882a593Smuzhiyun #include <linux/init.h>
30*4882a593Smuzhiyun #include <linux/rtc.h>
31*4882a593Smuzhiyun #include <linux/spi/spi.h>
32*4882a593Smuzhiyun #include <linux/bcd.h>
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define RX4581_REG_SC		0x00 /* Second in BCD */
35*4882a593Smuzhiyun #define RX4581_REG_MN		0x01 /* Minute in BCD */
36*4882a593Smuzhiyun #define RX4581_REG_HR		0x02 /* Hour in BCD */
37*4882a593Smuzhiyun #define RX4581_REG_DW		0x03 /* Day of Week */
38*4882a593Smuzhiyun #define RX4581_REG_DM		0x04 /* Day of Month in BCD */
39*4882a593Smuzhiyun #define RX4581_REG_MO		0x05 /* Month in BCD */
40*4882a593Smuzhiyun #define RX4581_REG_YR		0x06 /* Year in BCD */
41*4882a593Smuzhiyun #define RX4581_REG_RAM		0x07 /* RAM */
42*4882a593Smuzhiyun #define RX4581_REG_AMN		0x08 /* Alarm Min in BCD*/
43*4882a593Smuzhiyun #define RX4581_REG_AHR		0x09 /* Alarm Hour in BCD */
44*4882a593Smuzhiyun #define RX4581_REG_ADM		0x0A
45*4882a593Smuzhiyun #define RX4581_REG_ADW		0x0A
46*4882a593Smuzhiyun #define RX4581_REG_TMR0		0x0B
47*4882a593Smuzhiyun #define RX4581_REG_TMR1		0x0C
48*4882a593Smuzhiyun #define RX4581_REG_EXT		0x0D /* Extension Register */
49*4882a593Smuzhiyun #define RX4581_REG_FLAG		0x0E /* Flag Register */
50*4882a593Smuzhiyun #define RX4581_REG_CTRL		0x0F /* Control Register */
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun /* Flag Register bit definitions */
54*4882a593Smuzhiyun #define RX4581_FLAG_UF		0x20 /* Update */
55*4882a593Smuzhiyun #define RX4581_FLAG_TF		0x10 /* Timer */
56*4882a593Smuzhiyun #define RX4581_FLAG_AF		0x08 /* Alarm */
57*4882a593Smuzhiyun #define RX4581_FLAG_VLF		0x02 /* Voltage Low */
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun /* Control Register bit definitions */
60*4882a593Smuzhiyun #define RX4581_CTRL_UIE		0x20 /* Update Interrupt Enable */
61*4882a593Smuzhiyun #define RX4581_CTRL_TIE		0x10 /* Timer Interrupt Enable */
62*4882a593Smuzhiyun #define RX4581_CTRL_AIE		0x08 /* Alarm Interrupt Enable */
63*4882a593Smuzhiyun #define RX4581_CTRL_STOP	0x02 /* STOP bit */
64*4882a593Smuzhiyun #define RX4581_CTRL_RESET	0x01 /* RESET bit */
65*4882a593Smuzhiyun 
rx4581_set_reg(struct device * dev,unsigned char address,unsigned char data)66*4882a593Smuzhiyun static int rx4581_set_reg(struct device *dev, unsigned char address,
67*4882a593Smuzhiyun 				unsigned char data)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	struct spi_device *spi = to_spi_device(dev);
70*4882a593Smuzhiyun 	unsigned char buf[2];
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	/* high nibble must be '0' to write */
73*4882a593Smuzhiyun 	buf[0] = address & 0x0f;
74*4882a593Smuzhiyun 	buf[1] = data;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	return spi_write_then_read(spi, buf, 2, NULL, 0);
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
rx4581_get_reg(struct device * dev,unsigned char address,unsigned char * data)79*4882a593Smuzhiyun static int rx4581_get_reg(struct device *dev, unsigned char address,
80*4882a593Smuzhiyun 				unsigned char *data)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	struct spi_device *spi = to_spi_device(dev);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	/* Set MSB to indicate read */
85*4882a593Smuzhiyun 	*data = address | 0x80;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	return spi_write_then_read(spi, data, 1, data, 1);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun  * In the routines that deal directly with the rx8581 hardware, we use
92*4882a593Smuzhiyun  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
93*4882a593Smuzhiyun  */
rx4581_get_datetime(struct device * dev,struct rtc_time * tm)94*4882a593Smuzhiyun static int rx4581_get_datetime(struct device *dev, struct rtc_time *tm)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct spi_device *spi = to_spi_device(dev);
97*4882a593Smuzhiyun 	unsigned char date[7];
98*4882a593Smuzhiyun 	unsigned char data;
99*4882a593Smuzhiyun 	int err;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	/* First we ensure that the "update flag" is not set, we read the
102*4882a593Smuzhiyun 	 * time and date then re-read the "update flag". If the update flag
103*4882a593Smuzhiyun 	 * has been set, we know that the time has changed during the read so
104*4882a593Smuzhiyun 	 * we repeat the whole process again.
105*4882a593Smuzhiyun 	 */
106*4882a593Smuzhiyun 	err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data);
107*4882a593Smuzhiyun 	if (err != 0) {
108*4882a593Smuzhiyun 		dev_err(dev, "Unable to read device flags\n");
109*4882a593Smuzhiyun 		return -EIO;
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	do {
113*4882a593Smuzhiyun 		/* If update flag set, clear it */
114*4882a593Smuzhiyun 		if (data & RX4581_FLAG_UF) {
115*4882a593Smuzhiyun 			err = rx4581_set_reg(dev,
116*4882a593Smuzhiyun 				RX4581_REG_FLAG, (data & ~RX4581_FLAG_UF));
117*4882a593Smuzhiyun 			if (err != 0) {
118*4882a593Smuzhiyun 				dev_err(dev, "Unable to write device "
119*4882a593Smuzhiyun 					"flags\n");
120*4882a593Smuzhiyun 				return -EIO;
121*4882a593Smuzhiyun 			}
122*4882a593Smuzhiyun 		}
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 		/* Now read time and date */
125*4882a593Smuzhiyun 		date[0] = 0x80;
126*4882a593Smuzhiyun 		err = spi_write_then_read(spi, date, 1, date, 7);
127*4882a593Smuzhiyun 		if (err < 0) {
128*4882a593Smuzhiyun 			dev_err(dev, "Unable to read date\n");
129*4882a593Smuzhiyun 			return -EIO;
130*4882a593Smuzhiyun 		}
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 		/* Check flag register */
133*4882a593Smuzhiyun 		err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data);
134*4882a593Smuzhiyun 		if (err != 0) {
135*4882a593Smuzhiyun 			dev_err(dev, "Unable to read device flags\n");
136*4882a593Smuzhiyun 			return -EIO;
137*4882a593Smuzhiyun 		}
138*4882a593Smuzhiyun 	} while (data & RX4581_FLAG_UF);
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	if (data & RX4581_FLAG_VLF)
141*4882a593Smuzhiyun 		dev_info(dev,
142*4882a593Smuzhiyun 			"low voltage detected, date/time is not reliable.\n");
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	dev_dbg(dev,
145*4882a593Smuzhiyun 		"%s: raw data is sec=%02x, min=%02x, hr=%02x, "
146*4882a593Smuzhiyun 		"wday=%02x, mday=%02x, mon=%02x, year=%02x\n",
147*4882a593Smuzhiyun 		__func__,
148*4882a593Smuzhiyun 		date[0], date[1], date[2], date[3], date[4], date[5], date[6]);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	tm->tm_sec = bcd2bin(date[RX4581_REG_SC] & 0x7F);
151*4882a593Smuzhiyun 	tm->tm_min = bcd2bin(date[RX4581_REG_MN] & 0x7F);
152*4882a593Smuzhiyun 	tm->tm_hour = bcd2bin(date[RX4581_REG_HR] & 0x3F); /* rtc hr 0-23 */
153*4882a593Smuzhiyun 	tm->tm_wday = ilog2(date[RX4581_REG_DW] & 0x7F);
154*4882a593Smuzhiyun 	tm->tm_mday = bcd2bin(date[RX4581_REG_DM] & 0x3F);
155*4882a593Smuzhiyun 	tm->tm_mon = bcd2bin(date[RX4581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
156*4882a593Smuzhiyun 	tm->tm_year = bcd2bin(date[RX4581_REG_YR]);
157*4882a593Smuzhiyun 	if (tm->tm_year < 70)
158*4882a593Smuzhiyun 		tm->tm_year += 100;	/* assume we are in 1970...2069 */
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
162*4882a593Smuzhiyun 		"mday=%d, mon=%d, year=%d, wday=%d\n",
163*4882a593Smuzhiyun 		__func__,
164*4882a593Smuzhiyun 		tm->tm_sec, tm->tm_min, tm->tm_hour,
165*4882a593Smuzhiyun 		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	return 0;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
rx4581_set_datetime(struct device * dev,struct rtc_time * tm)170*4882a593Smuzhiyun static int rx4581_set_datetime(struct device *dev, struct rtc_time *tm)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	struct spi_device *spi = to_spi_device(dev);
173*4882a593Smuzhiyun 	int err;
174*4882a593Smuzhiyun 	unsigned char buf[8], data;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
177*4882a593Smuzhiyun 		"mday=%d, mon=%d, year=%d, wday=%d\n",
178*4882a593Smuzhiyun 		__func__,
179*4882a593Smuzhiyun 		tm->tm_sec, tm->tm_min, tm->tm_hour,
180*4882a593Smuzhiyun 		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	buf[0] = 0x00;
183*4882a593Smuzhiyun 	/* hours, minutes and seconds */
184*4882a593Smuzhiyun 	buf[RX4581_REG_SC+1] = bin2bcd(tm->tm_sec);
185*4882a593Smuzhiyun 	buf[RX4581_REG_MN+1] = bin2bcd(tm->tm_min);
186*4882a593Smuzhiyun 	buf[RX4581_REG_HR+1] = bin2bcd(tm->tm_hour);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	buf[RX4581_REG_DM+1] = bin2bcd(tm->tm_mday);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/* month, 1 - 12 */
191*4882a593Smuzhiyun 	buf[RX4581_REG_MO+1] = bin2bcd(tm->tm_mon + 1);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	/* year and century */
194*4882a593Smuzhiyun 	buf[RX4581_REG_YR+1] = bin2bcd(tm->tm_year % 100);
195*4882a593Smuzhiyun 	buf[RX4581_REG_DW+1] = (0x1 << tm->tm_wday);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/* Stop the clock */
198*4882a593Smuzhiyun 	err = rx4581_get_reg(dev, RX4581_REG_CTRL, &data);
199*4882a593Smuzhiyun 	if (err != 0) {
200*4882a593Smuzhiyun 		dev_err(dev, "Unable to read control register\n");
201*4882a593Smuzhiyun 		return -EIO;
202*4882a593Smuzhiyun 	}
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	err = rx4581_set_reg(dev, RX4581_REG_CTRL,
205*4882a593Smuzhiyun 		(data | RX4581_CTRL_STOP));
206*4882a593Smuzhiyun 	if (err != 0) {
207*4882a593Smuzhiyun 		dev_err(dev, "Unable to write control register\n");
208*4882a593Smuzhiyun 		return -EIO;
209*4882a593Smuzhiyun 	}
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/* write register's data */
212*4882a593Smuzhiyun 	err = spi_write_then_read(spi, buf, 8, NULL, 0);
213*4882a593Smuzhiyun 	if (err != 0) {
214*4882a593Smuzhiyun 		dev_err(dev, "Unable to write to date registers\n");
215*4882a593Smuzhiyun 		return -EIO;
216*4882a593Smuzhiyun 	}
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	/* get VLF and clear it */
219*4882a593Smuzhiyun 	err = rx4581_get_reg(dev, RX4581_REG_FLAG, &data);
220*4882a593Smuzhiyun 	if (err != 0) {
221*4882a593Smuzhiyun 		dev_err(dev, "Unable to read flag register\n");
222*4882a593Smuzhiyun 		return -EIO;
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	err = rx4581_set_reg(dev, RX4581_REG_FLAG,
226*4882a593Smuzhiyun 		(data & ~(RX4581_FLAG_VLF)));
227*4882a593Smuzhiyun 	if (err != 0) {
228*4882a593Smuzhiyun 		dev_err(dev, "Unable to write flag register\n");
229*4882a593Smuzhiyun 		return -EIO;
230*4882a593Smuzhiyun 	}
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	/* Restart the clock */
233*4882a593Smuzhiyun 	err = rx4581_get_reg(dev, RX4581_REG_CTRL, &data);
234*4882a593Smuzhiyun 	if (err != 0) {
235*4882a593Smuzhiyun 		dev_err(dev, "Unable to read control register\n");
236*4882a593Smuzhiyun 		return -EIO;
237*4882a593Smuzhiyun 	}
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	err = rx4581_set_reg(dev, RX4581_REG_CTRL,
240*4882a593Smuzhiyun 		(data & ~(RX4581_CTRL_STOP)));
241*4882a593Smuzhiyun 	if (err != 0) {
242*4882a593Smuzhiyun 		dev_err(dev, "Unable to write control register\n");
243*4882a593Smuzhiyun 		return -EIO;
244*4882a593Smuzhiyun 	}
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun static const struct rtc_class_ops rx4581_rtc_ops = {
250*4882a593Smuzhiyun 	.read_time	= rx4581_get_datetime,
251*4882a593Smuzhiyun 	.set_time	= rx4581_set_datetime,
252*4882a593Smuzhiyun };
253*4882a593Smuzhiyun 
rx4581_probe(struct spi_device * spi)254*4882a593Smuzhiyun static int rx4581_probe(struct spi_device *spi)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	struct rtc_device *rtc;
257*4882a593Smuzhiyun 	unsigned char tmp;
258*4882a593Smuzhiyun 	int res;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	res = rx4581_get_reg(&spi->dev, RX4581_REG_SC, &tmp);
261*4882a593Smuzhiyun 	if (res != 0)
262*4882a593Smuzhiyun 		return res;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	rtc = devm_rtc_device_register(&spi->dev, "rx4581",
265*4882a593Smuzhiyun 				&rx4581_rtc_ops, THIS_MODULE);
266*4882a593Smuzhiyun 	if (IS_ERR(rtc))
267*4882a593Smuzhiyun 		return PTR_ERR(rtc);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	spi_set_drvdata(spi, rtc);
270*4882a593Smuzhiyun 	return 0;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun static const struct spi_device_id rx4581_id[] = {
274*4882a593Smuzhiyun 	{ "rx4581", 0 },
275*4882a593Smuzhiyun 	{ }
276*4882a593Smuzhiyun };
277*4882a593Smuzhiyun MODULE_DEVICE_TABLE(spi, rx4581_id);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun static struct spi_driver rx4581_driver = {
280*4882a593Smuzhiyun 	.driver = {
281*4882a593Smuzhiyun 		.name	= "rtc-rx4581",
282*4882a593Smuzhiyun 	},
283*4882a593Smuzhiyun 	.probe	= rx4581_probe,
284*4882a593Smuzhiyun 	.id_table = rx4581_id,
285*4882a593Smuzhiyun };
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun module_spi_driver(rx4581_driver);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun MODULE_DESCRIPTION("rx4581 spi RTC driver");
290*4882a593Smuzhiyun MODULE_AUTHOR("Torben Hohn");
291*4882a593Smuzhiyun MODULE_LICENSE("GPL");
292*4882a593Smuzhiyun MODULE_ALIAS("spi:rtc-rx4581");
293