xref: /linux/drivers/rtc/rtc-x1205.c (revision 91046a8a693823d434f0aa70419c48ebeb8e1b11)
11fec7c66SAlessandro Zummo /*
21fec7c66SAlessandro Zummo  * An i2c driver for the Xicor/Intersil X1205 RTC
31fec7c66SAlessandro Zummo  * Copyright 2004 Karen Spearel
41fec7c66SAlessandro Zummo  * Copyright 2005 Alessandro Zummo
51fec7c66SAlessandro Zummo  *
61fec7c66SAlessandro Zummo  * please send all reports to:
71fec7c66SAlessandro Zummo  * 	Karen Spearel <kas111 at gmail dot com>
81fec7c66SAlessandro Zummo  *	Alessandro Zummo <a.zummo@towertech.it>
91fec7c66SAlessandro Zummo  *
101fec7c66SAlessandro Zummo  * based on a lot of other RTC drivers.
111fec7c66SAlessandro Zummo  *
121fec7c66SAlessandro Zummo  * This program is free software; you can redistribute it and/or modify
131fec7c66SAlessandro Zummo  * it under the terms of the GNU General Public License version 2 as
141fec7c66SAlessandro Zummo  * published by the Free Software Foundation.
151fec7c66SAlessandro Zummo  */
161fec7c66SAlessandro Zummo 
171fec7c66SAlessandro Zummo #include <linux/i2c.h>
181fec7c66SAlessandro Zummo #include <linux/bcd.h>
191fec7c66SAlessandro Zummo #include <linux/rtc.h>
201fec7c66SAlessandro Zummo #include <linux/delay.h>
211fec7c66SAlessandro Zummo 
22015aefbbSAlessandro Zummo #define DRV_VERSION "1.0.7"
231fec7c66SAlessandro Zummo 
241fec7c66SAlessandro Zummo /* Addresses to scan: none. This chip is located at
251fec7c66SAlessandro Zummo  * 0x6f and uses a two bytes register addressing.
261fec7c66SAlessandro Zummo  * Two bytes need to be written to read a single register,
271fec7c66SAlessandro Zummo  * while most other chips just require one and take the second
281fec7c66SAlessandro Zummo  * one as the data to be written. To prevent corrupting
291fec7c66SAlessandro Zummo  * unknown chips, the user must explicitely set the probe parameter.
301fec7c66SAlessandro Zummo  */
311fec7c66SAlessandro Zummo 
321fec7c66SAlessandro Zummo static unsigned short normal_i2c[] = { I2C_CLIENT_END };
331fec7c66SAlessandro Zummo 
341fec7c66SAlessandro Zummo /* Insmod parameters */
351fec7c66SAlessandro Zummo I2C_CLIENT_INSMOD;
361fec7c66SAlessandro Zummo 
371fec7c66SAlessandro Zummo /* offsets into CCR area */
381fec7c66SAlessandro Zummo 
391fec7c66SAlessandro Zummo #define CCR_SEC			0
401fec7c66SAlessandro Zummo #define CCR_MIN			1
411fec7c66SAlessandro Zummo #define CCR_HOUR		2
421fec7c66SAlessandro Zummo #define CCR_MDAY		3
431fec7c66SAlessandro Zummo #define CCR_MONTH		4
441fec7c66SAlessandro Zummo #define CCR_YEAR		5
451fec7c66SAlessandro Zummo #define CCR_WDAY		6
461fec7c66SAlessandro Zummo #define CCR_Y2K			7
471fec7c66SAlessandro Zummo 
481fec7c66SAlessandro Zummo #define X1205_REG_SR		0x3F	/* status register */
491fec7c66SAlessandro Zummo #define X1205_REG_Y2K		0x37
501fec7c66SAlessandro Zummo #define X1205_REG_DW		0x36
511fec7c66SAlessandro Zummo #define X1205_REG_YR		0x35
521fec7c66SAlessandro Zummo #define X1205_REG_MO		0x34
531fec7c66SAlessandro Zummo #define X1205_REG_DT		0x33
541fec7c66SAlessandro Zummo #define X1205_REG_HR		0x32
551fec7c66SAlessandro Zummo #define X1205_REG_MN		0x31
561fec7c66SAlessandro Zummo #define X1205_REG_SC		0x30
571fec7c66SAlessandro Zummo #define X1205_REG_DTR		0x13
581fec7c66SAlessandro Zummo #define X1205_REG_ATR		0x12
591fec7c66SAlessandro Zummo #define X1205_REG_INT		0x11
601fec7c66SAlessandro Zummo #define X1205_REG_0		0x10
611fec7c66SAlessandro Zummo #define X1205_REG_Y2K1		0x0F
621fec7c66SAlessandro Zummo #define X1205_REG_DWA1		0x0E
631fec7c66SAlessandro Zummo #define X1205_REG_YRA1		0x0D
641fec7c66SAlessandro Zummo #define X1205_REG_MOA1		0x0C
651fec7c66SAlessandro Zummo #define X1205_REG_DTA1		0x0B
661fec7c66SAlessandro Zummo #define X1205_REG_HRA1		0x0A
671fec7c66SAlessandro Zummo #define X1205_REG_MNA1		0x09
681fec7c66SAlessandro Zummo #define X1205_REG_SCA1		0x08
691fec7c66SAlessandro Zummo #define X1205_REG_Y2K0		0x07
701fec7c66SAlessandro Zummo #define X1205_REG_DWA0		0x06
711fec7c66SAlessandro Zummo #define X1205_REG_YRA0		0x05
721fec7c66SAlessandro Zummo #define X1205_REG_MOA0		0x04
731fec7c66SAlessandro Zummo #define X1205_REG_DTA0		0x03
741fec7c66SAlessandro Zummo #define X1205_REG_HRA0		0x02
751fec7c66SAlessandro Zummo #define X1205_REG_MNA0		0x01
761fec7c66SAlessandro Zummo #define X1205_REG_SCA0		0x00
771fec7c66SAlessandro Zummo 
781fec7c66SAlessandro Zummo #define X1205_CCR_BASE		0x30	/* Base address of CCR */
791fec7c66SAlessandro Zummo #define X1205_ALM0_BASE		0x00	/* Base address of ALARM0 */
801fec7c66SAlessandro Zummo 
811fec7c66SAlessandro Zummo #define X1205_SR_RTCF		0x01	/* Clock failure */
821fec7c66SAlessandro Zummo #define X1205_SR_WEL		0x02	/* Write Enable Latch */
831fec7c66SAlessandro Zummo #define X1205_SR_RWEL		0x04	/* Register Write Enable */
841fec7c66SAlessandro Zummo 
851fec7c66SAlessandro Zummo #define X1205_DTR_DTR0		0x01
861fec7c66SAlessandro Zummo #define X1205_DTR_DTR1		0x02
871fec7c66SAlessandro Zummo #define X1205_DTR_DTR2		0x04
881fec7c66SAlessandro Zummo 
891fec7c66SAlessandro Zummo #define X1205_HR_MIL		0x80	/* Set in ccr.hour for 24 hr mode */
901fec7c66SAlessandro Zummo 
911fec7c66SAlessandro Zummo /* Prototypes */
921fec7c66SAlessandro Zummo static int x1205_attach(struct i2c_adapter *adapter);
931fec7c66SAlessandro Zummo static int x1205_detach(struct i2c_client *client);
941fec7c66SAlessandro Zummo static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
951fec7c66SAlessandro Zummo 
961fec7c66SAlessandro Zummo static struct i2c_driver x1205_driver = {
971fec7c66SAlessandro Zummo 	.driver		= {
981fec7c66SAlessandro Zummo 		.name	= "x1205",
991fec7c66SAlessandro Zummo 	},
1001fec7c66SAlessandro Zummo 	.id		= I2C_DRIVERID_X1205,
1011fec7c66SAlessandro Zummo 	.attach_adapter = &x1205_attach,
1021fec7c66SAlessandro Zummo 	.detach_client	= &x1205_detach,
1031fec7c66SAlessandro Zummo };
1041fec7c66SAlessandro Zummo 
1051fec7c66SAlessandro Zummo /*
1061fec7c66SAlessandro Zummo  * In the routines that deal directly with the x1205 hardware, we use
1071fec7c66SAlessandro Zummo  * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
1081fec7c66SAlessandro Zummo  * Epoch is initialized as 2000. Time is set to UTC.
1091fec7c66SAlessandro Zummo  */
1101fec7c66SAlessandro Zummo static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
1111fec7c66SAlessandro Zummo 				unsigned char reg_base)
1121fec7c66SAlessandro Zummo {
1131fec7c66SAlessandro Zummo 	unsigned char dt_addr[2] = { 0, reg_base };
1141fec7c66SAlessandro Zummo 
1151fec7c66SAlessandro Zummo 	unsigned char buf[8];
1161fec7c66SAlessandro Zummo 
1171fec7c66SAlessandro Zummo 	struct i2c_msg msgs[] = {
1181fec7c66SAlessandro Zummo 		{ client->addr, 0, 2, dt_addr },	/* setup read ptr */
1191fec7c66SAlessandro Zummo 		{ client->addr, I2C_M_RD, 8, buf },	/* read date */
1201fec7c66SAlessandro Zummo 	};
1211fec7c66SAlessandro Zummo 
1221fec7c66SAlessandro Zummo 	/* read date registers */
1231fec7c66SAlessandro Zummo 	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
1241fec7c66SAlessandro Zummo 		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
1251fec7c66SAlessandro Zummo 		return -EIO;
1261fec7c66SAlessandro Zummo 	}
1271fec7c66SAlessandro Zummo 
1281fec7c66SAlessandro Zummo 	dev_dbg(&client->dev,
1291fec7c66SAlessandro Zummo 		"%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
1301fec7c66SAlessandro Zummo 		"mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
1311fec7c66SAlessandro Zummo 		__FUNCTION__,
1321fec7c66SAlessandro Zummo 		buf[0], buf[1], buf[2], buf[3],
1331fec7c66SAlessandro Zummo 		buf[4], buf[5], buf[6], buf[7]);
1341fec7c66SAlessandro Zummo 
1351fec7c66SAlessandro Zummo 	tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
1361fec7c66SAlessandro Zummo 	tm->tm_min = BCD2BIN(buf[CCR_MIN]);
1371fec7c66SAlessandro Zummo 	tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
1381fec7c66SAlessandro Zummo 	tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
1391fec7c66SAlessandro Zummo 	tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
1401fec7c66SAlessandro Zummo 	tm->tm_year = BCD2BIN(buf[CCR_YEAR])
1411fec7c66SAlessandro Zummo 			+ (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900;
1421fec7c66SAlessandro Zummo 	tm->tm_wday = buf[CCR_WDAY];
1431fec7c66SAlessandro Zummo 
1441fec7c66SAlessandro Zummo 	dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
1451fec7c66SAlessandro Zummo 		"mday=%d, mon=%d, year=%d, wday=%d\n",
1461fec7c66SAlessandro Zummo 		__FUNCTION__,
1471fec7c66SAlessandro Zummo 		tm->tm_sec, tm->tm_min, tm->tm_hour,
1481fec7c66SAlessandro Zummo 		tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
1491fec7c66SAlessandro Zummo 
1501fec7c66SAlessandro Zummo 	return 0;
1511fec7c66SAlessandro Zummo }
1521fec7c66SAlessandro Zummo 
1531fec7c66SAlessandro Zummo static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
1541fec7c66SAlessandro Zummo {
1551fec7c66SAlessandro Zummo 	static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
1561fec7c66SAlessandro Zummo 
1571fec7c66SAlessandro Zummo 	struct i2c_msg msgs[] = {
1581fec7c66SAlessandro Zummo 		{ client->addr, 0, 2, sr_addr },	/* setup read ptr */
1591fec7c66SAlessandro Zummo 		{ client->addr, I2C_M_RD, 1, sr },	/* read status */
1601fec7c66SAlessandro Zummo 	};
1611fec7c66SAlessandro Zummo 
1621fec7c66SAlessandro Zummo 	/* read status register */
1631fec7c66SAlessandro Zummo 	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
1641fec7c66SAlessandro Zummo 		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
1651fec7c66SAlessandro Zummo 		return -EIO;
1661fec7c66SAlessandro Zummo 	}
1671fec7c66SAlessandro Zummo 
1681fec7c66SAlessandro Zummo 	return 0;
1691fec7c66SAlessandro Zummo }
1701fec7c66SAlessandro Zummo 
1711fec7c66SAlessandro Zummo static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
1721fec7c66SAlessandro Zummo 				int datetoo, u8 reg_base)
1731fec7c66SAlessandro Zummo {
1741fec7c66SAlessandro Zummo 	int i, xfer;
1751fec7c66SAlessandro Zummo 	unsigned char buf[8];
1761fec7c66SAlessandro Zummo 
1771fec7c66SAlessandro Zummo 	static const unsigned char wel[3] = { 0, X1205_REG_SR,
1781fec7c66SAlessandro Zummo 						X1205_SR_WEL };
1791fec7c66SAlessandro Zummo 
1801fec7c66SAlessandro Zummo 	static const unsigned char rwel[3] = { 0, X1205_REG_SR,
1811fec7c66SAlessandro Zummo 						X1205_SR_WEL | X1205_SR_RWEL };
1821fec7c66SAlessandro Zummo 
1831fec7c66SAlessandro Zummo 	static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
1841fec7c66SAlessandro Zummo 
1851fec7c66SAlessandro Zummo 	dev_dbg(&client->dev,
1861fec7c66SAlessandro Zummo 		"%s: secs=%d, mins=%d, hours=%d\n",
1871fec7c66SAlessandro Zummo 		__FUNCTION__,
1881fec7c66SAlessandro Zummo 		tm->tm_sec, tm->tm_min, tm->tm_hour);
1891fec7c66SAlessandro Zummo 
1901fec7c66SAlessandro Zummo 	buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
1911fec7c66SAlessandro Zummo 	buf[CCR_MIN] = BIN2BCD(tm->tm_min);
1921fec7c66SAlessandro Zummo 
1931fec7c66SAlessandro Zummo 	/* set hour and 24hr bit */
1941fec7c66SAlessandro Zummo 	buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
1951fec7c66SAlessandro Zummo 
1961fec7c66SAlessandro Zummo 	/* should we also set the date? */
1971fec7c66SAlessandro Zummo 	if (datetoo) {
1981fec7c66SAlessandro Zummo 		dev_dbg(&client->dev,
1991fec7c66SAlessandro Zummo 			"%s: mday=%d, mon=%d, year=%d, wday=%d\n",
2001fec7c66SAlessandro Zummo 			__FUNCTION__,
2011fec7c66SAlessandro Zummo 			tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
2021fec7c66SAlessandro Zummo 
2031fec7c66SAlessandro Zummo 		buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
2041fec7c66SAlessandro Zummo 
2051fec7c66SAlessandro Zummo 		/* month, 1 - 12 */
2061fec7c66SAlessandro Zummo 		buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1);
2071fec7c66SAlessandro Zummo 
2081fec7c66SAlessandro Zummo 		/* year, since the rtc epoch*/
2091fec7c66SAlessandro Zummo 		buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100);
2101fec7c66SAlessandro Zummo 		buf[CCR_WDAY] = tm->tm_wday & 0x07;
2111fec7c66SAlessandro Zummo 		buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
2121fec7c66SAlessandro Zummo 	}
2131fec7c66SAlessandro Zummo 
2141fec7c66SAlessandro Zummo 	/* this sequence is required to unlock the chip */
2151fec7c66SAlessandro Zummo 	if ((xfer = i2c_master_send(client, wel, 3)) != 3) {
2161fec7c66SAlessandro Zummo 		dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
2171fec7c66SAlessandro Zummo 		return -EIO;
2181fec7c66SAlessandro Zummo 	}
2191fec7c66SAlessandro Zummo 
2201fec7c66SAlessandro Zummo 	if ((xfer = i2c_master_send(client, rwel, 3)) != 3) {
2211fec7c66SAlessandro Zummo 		dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
2221fec7c66SAlessandro Zummo 		return -EIO;
2231fec7c66SAlessandro Zummo 	}
2241fec7c66SAlessandro Zummo 
2251fec7c66SAlessandro Zummo 	/* write register's data */
2261fec7c66SAlessandro Zummo 	for (i = 0; i < (datetoo ? 8 : 3); i++) {
2271fec7c66SAlessandro Zummo 		unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
2281fec7c66SAlessandro Zummo 
2291fec7c66SAlessandro Zummo 		xfer = i2c_master_send(client, rdata, 3);
2301fec7c66SAlessandro Zummo 		if (xfer != 3) {
2311fec7c66SAlessandro Zummo 			dev_err(&client->dev,
2321fec7c66SAlessandro Zummo 				"%s: xfer=%d addr=%02x, data=%02x\n",
2331fec7c66SAlessandro Zummo 				__FUNCTION__,
2341fec7c66SAlessandro Zummo 				 xfer, rdata[1], rdata[2]);
2351fec7c66SAlessandro Zummo 			return -EIO;
2361fec7c66SAlessandro Zummo 		}
2371fec7c66SAlessandro Zummo 	};
2381fec7c66SAlessandro Zummo 
2391fec7c66SAlessandro Zummo 	/* disable further writes */
2401fec7c66SAlessandro Zummo 	if ((xfer = i2c_master_send(client, diswe, 3)) != 3) {
2411fec7c66SAlessandro Zummo 		dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
2421fec7c66SAlessandro Zummo 		return -EIO;
2431fec7c66SAlessandro Zummo 	}
2441fec7c66SAlessandro Zummo 
2451fec7c66SAlessandro Zummo 	return 0;
2461fec7c66SAlessandro Zummo }
2471fec7c66SAlessandro Zummo 
2481fec7c66SAlessandro Zummo static int x1205_fix_osc(struct i2c_client *client)
2491fec7c66SAlessandro Zummo {
2501fec7c66SAlessandro Zummo 	int err;
2511fec7c66SAlessandro Zummo 	struct rtc_time tm;
2521fec7c66SAlessandro Zummo 
2531fec7c66SAlessandro Zummo 	tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
2541fec7c66SAlessandro Zummo 
2551fec7c66SAlessandro Zummo 	if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0)
2561fec7c66SAlessandro Zummo 		dev_err(&client->dev,
2571fec7c66SAlessandro Zummo 			"unable to restart the oscillator\n");
2581fec7c66SAlessandro Zummo 
2591fec7c66SAlessandro Zummo 	return err;
2601fec7c66SAlessandro Zummo }
2611fec7c66SAlessandro Zummo 
2621fec7c66SAlessandro Zummo static int x1205_get_dtrim(struct i2c_client *client, int *trim)
2631fec7c66SAlessandro Zummo {
2641fec7c66SAlessandro Zummo 	unsigned char dtr;
2651fec7c66SAlessandro Zummo 	static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
2661fec7c66SAlessandro Zummo 
2671fec7c66SAlessandro Zummo 	struct i2c_msg msgs[] = {
2681fec7c66SAlessandro Zummo 		{ client->addr, 0, 2, dtr_addr },	/* setup read ptr */
2691fec7c66SAlessandro Zummo 		{ client->addr, I2C_M_RD, 1, &dtr }, 	/* read dtr */
2701fec7c66SAlessandro Zummo 	};
2711fec7c66SAlessandro Zummo 
2721fec7c66SAlessandro Zummo 	/* read dtr register */
2731fec7c66SAlessandro Zummo 	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
2741fec7c66SAlessandro Zummo 		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
2751fec7c66SAlessandro Zummo 		return -EIO;
2761fec7c66SAlessandro Zummo 	}
2771fec7c66SAlessandro Zummo 
2781fec7c66SAlessandro Zummo 	dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
2791fec7c66SAlessandro Zummo 
2801fec7c66SAlessandro Zummo 	*trim = 0;
2811fec7c66SAlessandro Zummo 
2821fec7c66SAlessandro Zummo 	if (dtr & X1205_DTR_DTR0)
2831fec7c66SAlessandro Zummo 		*trim += 20;
2841fec7c66SAlessandro Zummo 
2851fec7c66SAlessandro Zummo 	if (dtr & X1205_DTR_DTR1)
2861fec7c66SAlessandro Zummo 		*trim += 10;
2871fec7c66SAlessandro Zummo 
2881fec7c66SAlessandro Zummo 	if (dtr & X1205_DTR_DTR2)
2891fec7c66SAlessandro Zummo 		*trim = -*trim;
2901fec7c66SAlessandro Zummo 
2911fec7c66SAlessandro Zummo 	return 0;
2921fec7c66SAlessandro Zummo }
2931fec7c66SAlessandro Zummo 
2941fec7c66SAlessandro Zummo static int x1205_get_atrim(struct i2c_client *client, int *trim)
2951fec7c66SAlessandro Zummo {
2961fec7c66SAlessandro Zummo 	s8 atr;
2971fec7c66SAlessandro Zummo 	static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
2981fec7c66SAlessandro Zummo 
2991fec7c66SAlessandro Zummo 	struct i2c_msg msgs[] = {
3001fec7c66SAlessandro Zummo 		{ client->addr, 0, 2, atr_addr },	/* setup read ptr */
3011fec7c66SAlessandro Zummo 		{ client->addr, I2C_M_RD, 1, &atr }, 	/* read atr */
3021fec7c66SAlessandro Zummo 	};
3031fec7c66SAlessandro Zummo 
3041fec7c66SAlessandro Zummo 	/* read atr register */
3051fec7c66SAlessandro Zummo 	if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
3061fec7c66SAlessandro Zummo 		dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
3071fec7c66SAlessandro Zummo 		return -EIO;
3081fec7c66SAlessandro Zummo 	}
3091fec7c66SAlessandro Zummo 
3101fec7c66SAlessandro Zummo 	dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
3111fec7c66SAlessandro Zummo 
3121fec7c66SAlessandro Zummo 	/* atr is a two's complement value on 6 bits,
3131fec7c66SAlessandro Zummo 	 * perform sign extension. The formula is
3141fec7c66SAlessandro Zummo 	 * Catr = (atr * 0.25pF) + 11.00pF.
3151fec7c66SAlessandro Zummo 	 */
3161fec7c66SAlessandro Zummo 	if (atr & 0x20)
3171fec7c66SAlessandro Zummo 		atr |= 0xC0;
3181fec7c66SAlessandro Zummo 
3191fec7c66SAlessandro Zummo 	dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
3201fec7c66SAlessandro Zummo 
3211fec7c66SAlessandro Zummo 	*trim = (atr * 250) + 11000;
3221fec7c66SAlessandro Zummo 
3231fec7c66SAlessandro Zummo 	dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
3241fec7c66SAlessandro Zummo 
3251fec7c66SAlessandro Zummo 	return 0;
3261fec7c66SAlessandro Zummo }
3271fec7c66SAlessandro Zummo 
3281fec7c66SAlessandro Zummo struct x1205_limit
3291fec7c66SAlessandro Zummo {
3301fec7c66SAlessandro Zummo 	unsigned char reg, mask, min, max;
3311fec7c66SAlessandro Zummo };
3321fec7c66SAlessandro Zummo 
3331fec7c66SAlessandro Zummo static int x1205_validate_client(struct i2c_client *client)
3341fec7c66SAlessandro Zummo {
3351fec7c66SAlessandro Zummo 	int i, xfer;
3361fec7c66SAlessandro Zummo 
3371fec7c66SAlessandro Zummo 	/* Probe array. We will read the register at the specified
3381fec7c66SAlessandro Zummo 	 * address and check if the given bits are zero.
3391fec7c66SAlessandro Zummo 	 */
3401fec7c66SAlessandro Zummo 	static const unsigned char probe_zero_pattern[] = {
3411fec7c66SAlessandro Zummo 		/* register, mask */
3421fec7c66SAlessandro Zummo 		X1205_REG_SR,	0x18,
3431fec7c66SAlessandro Zummo 		X1205_REG_DTR,	0xF8,
3441fec7c66SAlessandro Zummo 		X1205_REG_ATR,	0xC0,
3451fec7c66SAlessandro Zummo 		X1205_REG_INT,	0x18,
3461fec7c66SAlessandro Zummo 		X1205_REG_0,	0xFF,
3471fec7c66SAlessandro Zummo 	};
3481fec7c66SAlessandro Zummo 
3491fec7c66SAlessandro Zummo 	static const struct x1205_limit probe_limits_pattern[] = {
3501fec7c66SAlessandro Zummo 		/* register, mask, min, max */
3511fec7c66SAlessandro Zummo 		{ X1205_REG_Y2K,	0xFF,	19,	20	},
3521fec7c66SAlessandro Zummo 		{ X1205_REG_DW,		0xFF,	0,	6	},
3531fec7c66SAlessandro Zummo 		{ X1205_REG_YR,		0xFF,	0,	99	},
3541fec7c66SAlessandro Zummo 		{ X1205_REG_MO,		0xFF,	0,	12	},
3551fec7c66SAlessandro Zummo 		{ X1205_REG_DT,		0xFF,	0,	31	},
3561fec7c66SAlessandro Zummo 		{ X1205_REG_HR,		0x7F,	0,	23	},
3571fec7c66SAlessandro Zummo 		{ X1205_REG_MN,		0xFF,	0,	59	},
3581fec7c66SAlessandro Zummo 		{ X1205_REG_SC,		0xFF,	0,	59	},
3591fec7c66SAlessandro Zummo 		{ X1205_REG_Y2K1,	0xFF,	19,	20	},
3601fec7c66SAlessandro Zummo 		{ X1205_REG_Y2K0,	0xFF,	19,	20	},
3611fec7c66SAlessandro Zummo 	};
3621fec7c66SAlessandro Zummo 
3631fec7c66SAlessandro Zummo 	/* check that registers have bits a 0 where expected */
3641fec7c66SAlessandro Zummo 	for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
3651fec7c66SAlessandro Zummo 		unsigned char buf;
3661fec7c66SAlessandro Zummo 
3671fec7c66SAlessandro Zummo 		unsigned char addr[2] = { 0, probe_zero_pattern[i] };
3681fec7c66SAlessandro Zummo 
3691fec7c66SAlessandro Zummo 		struct i2c_msg msgs[2] = {
3701fec7c66SAlessandro Zummo 			{ client->addr, 0, 2, addr },
3711fec7c66SAlessandro Zummo 			{ client->addr, I2C_M_RD, 1, &buf },
3721fec7c66SAlessandro Zummo 		};
3731fec7c66SAlessandro Zummo 
3741fec7c66SAlessandro Zummo 		if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
3751fec7c66SAlessandro Zummo 			dev_err(&client->adapter->dev,
3761fec7c66SAlessandro Zummo 				"%s: could not read register %x\n",
3771fec7c66SAlessandro Zummo 				__FUNCTION__, probe_zero_pattern[i]);
3781fec7c66SAlessandro Zummo 
3791fec7c66SAlessandro Zummo 			return -EIO;
3801fec7c66SAlessandro Zummo 		}
3811fec7c66SAlessandro Zummo 
3821fec7c66SAlessandro Zummo 		if ((buf & probe_zero_pattern[i+1]) != 0) {
3831fec7c66SAlessandro Zummo 			dev_err(&client->adapter->dev,
3841fec7c66SAlessandro Zummo 				"%s: register=%02x, zero pattern=%d, value=%x\n",
3851fec7c66SAlessandro Zummo 				__FUNCTION__, probe_zero_pattern[i], i, buf);
3861fec7c66SAlessandro Zummo 
3871fec7c66SAlessandro Zummo 			return -ENODEV;
3881fec7c66SAlessandro Zummo 		}
3891fec7c66SAlessandro Zummo 	}
3901fec7c66SAlessandro Zummo 
3911fec7c66SAlessandro Zummo 	/* check limits (only registers with bcd values) */
3921fec7c66SAlessandro Zummo 	for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
3931fec7c66SAlessandro Zummo 		unsigned char reg, value;
3941fec7c66SAlessandro Zummo 
3951fec7c66SAlessandro Zummo 		unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
3961fec7c66SAlessandro Zummo 
3971fec7c66SAlessandro Zummo 		struct i2c_msg msgs[2] = {
3981fec7c66SAlessandro Zummo 			{ client->addr, 0, 2, addr },
3991fec7c66SAlessandro Zummo 			{ client->addr, I2C_M_RD, 1, &reg },
4001fec7c66SAlessandro Zummo 		};
4011fec7c66SAlessandro Zummo 
4021fec7c66SAlessandro Zummo 		if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
4031fec7c66SAlessandro Zummo 			dev_err(&client->adapter->dev,
4041fec7c66SAlessandro Zummo 				"%s: could not read register %x\n",
4051fec7c66SAlessandro Zummo 				__FUNCTION__, probe_limits_pattern[i].reg);
4061fec7c66SAlessandro Zummo 
4071fec7c66SAlessandro Zummo 			return -EIO;
4081fec7c66SAlessandro Zummo 		}
4091fec7c66SAlessandro Zummo 
4101fec7c66SAlessandro Zummo 		value = BCD2BIN(reg & probe_limits_pattern[i].mask);
4111fec7c66SAlessandro Zummo 
4121fec7c66SAlessandro Zummo 		if (value > probe_limits_pattern[i].max ||
4131fec7c66SAlessandro Zummo 			value < probe_limits_pattern[i].min) {
4141fec7c66SAlessandro Zummo 			dev_dbg(&client->adapter->dev,
4151fec7c66SAlessandro Zummo 				"%s: register=%x, lim pattern=%d, value=%d\n",
4161fec7c66SAlessandro Zummo 				__FUNCTION__, probe_limits_pattern[i].reg,
4171fec7c66SAlessandro Zummo 				i, value);
4181fec7c66SAlessandro Zummo 
4191fec7c66SAlessandro Zummo 			return -ENODEV;
4201fec7c66SAlessandro Zummo 		}
4211fec7c66SAlessandro Zummo 	}
4221fec7c66SAlessandro Zummo 
4231fec7c66SAlessandro Zummo 	return 0;
4241fec7c66SAlessandro Zummo }
4251fec7c66SAlessandro Zummo 
4261fec7c66SAlessandro Zummo static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
4271fec7c66SAlessandro Zummo {
4281fec7c66SAlessandro Zummo 	return x1205_get_datetime(to_i2c_client(dev),
4291fec7c66SAlessandro Zummo 		&alrm->time, X1205_ALM0_BASE);
4301fec7c66SAlessandro Zummo }
4311fec7c66SAlessandro Zummo 
4321fec7c66SAlessandro Zummo static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
4331fec7c66SAlessandro Zummo {
4341fec7c66SAlessandro Zummo 	return x1205_set_datetime(to_i2c_client(dev),
4351fec7c66SAlessandro Zummo 		&alrm->time, 1, X1205_ALM0_BASE);
4361fec7c66SAlessandro Zummo }
4371fec7c66SAlessandro Zummo 
4381fec7c66SAlessandro Zummo static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
4391fec7c66SAlessandro Zummo {
4401fec7c66SAlessandro Zummo 	return x1205_get_datetime(to_i2c_client(dev),
4411fec7c66SAlessandro Zummo 		tm, X1205_CCR_BASE);
4421fec7c66SAlessandro Zummo }
4431fec7c66SAlessandro Zummo 
4441fec7c66SAlessandro Zummo static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm)
4451fec7c66SAlessandro Zummo {
4461fec7c66SAlessandro Zummo 	return x1205_set_datetime(to_i2c_client(dev),
4471fec7c66SAlessandro Zummo 		tm, 1, X1205_CCR_BASE);
4481fec7c66SAlessandro Zummo }
4491fec7c66SAlessandro Zummo 
4501fec7c66SAlessandro Zummo static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
4511fec7c66SAlessandro Zummo {
4521fec7c66SAlessandro Zummo 	int err, dtrim, atrim;
4531fec7c66SAlessandro Zummo 
4541fec7c66SAlessandro Zummo 	if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0)
4551fec7c66SAlessandro Zummo 		seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim);
4561fec7c66SAlessandro Zummo 
4571fec7c66SAlessandro Zummo 	if ((err = x1205_get_atrim(to_i2c_client(dev), &atrim)) == 0)
4581fec7c66SAlessandro Zummo 		seq_printf(seq, "analog_trim\t: %d.%02d pF\n",
4591fec7c66SAlessandro Zummo 			atrim / 1000, atrim % 1000);
4601fec7c66SAlessandro Zummo 	return 0;
4611fec7c66SAlessandro Zummo }
4621fec7c66SAlessandro Zummo 
463ff8371acSDavid Brownell static const struct rtc_class_ops x1205_rtc_ops = {
4641fec7c66SAlessandro Zummo 	.proc		= x1205_rtc_proc,
4651fec7c66SAlessandro Zummo 	.read_time	= x1205_rtc_read_time,
4661fec7c66SAlessandro Zummo 	.set_time	= x1205_rtc_set_time,
4671fec7c66SAlessandro Zummo 	.read_alarm	= x1205_rtc_read_alarm,
4681fec7c66SAlessandro Zummo 	.set_alarm	= x1205_rtc_set_alarm,
4691fec7c66SAlessandro Zummo };
4701fec7c66SAlessandro Zummo 
4711fec7c66SAlessandro Zummo static ssize_t x1205_sysfs_show_atrim(struct device *dev,
4721fec7c66SAlessandro Zummo 				struct device_attribute *attr, char *buf)
4731fec7c66SAlessandro Zummo {
474015aefbbSAlessandro Zummo 	int err, atrim;
4751fec7c66SAlessandro Zummo 
476015aefbbSAlessandro Zummo 	err = x1205_get_atrim(to_i2c_client(dev), &atrim);
477015aefbbSAlessandro Zummo 	if (err)
478015aefbbSAlessandro Zummo 		return err;
479015aefbbSAlessandro Zummo 
480015aefbbSAlessandro Zummo 	return sprintf(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000);
4811fec7c66SAlessandro Zummo }
4821fec7c66SAlessandro Zummo static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL);
4831fec7c66SAlessandro Zummo 
4841fec7c66SAlessandro Zummo static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
4851fec7c66SAlessandro Zummo 				struct device_attribute *attr, char *buf)
4861fec7c66SAlessandro Zummo {
487015aefbbSAlessandro Zummo 	int err, dtrim;
4881fec7c66SAlessandro Zummo 
489015aefbbSAlessandro Zummo 	err = x1205_get_dtrim(to_i2c_client(dev), &dtrim);
490015aefbbSAlessandro Zummo 	if (err)
491015aefbbSAlessandro Zummo 		return err;
492015aefbbSAlessandro Zummo 
4931fec7c66SAlessandro Zummo 	return sprintf(buf, "%d ppm\n", dtrim);
4941fec7c66SAlessandro Zummo }
4951fec7c66SAlessandro Zummo static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
4961fec7c66SAlessandro Zummo 
4971fec7c66SAlessandro Zummo static int x1205_attach(struct i2c_adapter *adapter)
4981fec7c66SAlessandro Zummo {
4991fec7c66SAlessandro Zummo 	return i2c_probe(adapter, &addr_data, x1205_probe);
5001fec7c66SAlessandro Zummo }
5011fec7c66SAlessandro Zummo 
5021fec7c66SAlessandro Zummo static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
5031fec7c66SAlessandro Zummo {
5041fec7c66SAlessandro Zummo 	int err = 0;
5051fec7c66SAlessandro Zummo 	unsigned char sr;
5061fec7c66SAlessandro Zummo 	struct i2c_client *client;
5071fec7c66SAlessandro Zummo 	struct rtc_device *rtc;
5081fec7c66SAlessandro Zummo 
5091fec7c66SAlessandro Zummo 	dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
5101fec7c66SAlessandro Zummo 
5111fec7c66SAlessandro Zummo 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
5121fec7c66SAlessandro Zummo 		err = -ENODEV;
5131fec7c66SAlessandro Zummo 		goto exit;
5141fec7c66SAlessandro Zummo 	}
5151fec7c66SAlessandro Zummo 
5161fec7c66SAlessandro Zummo 	if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
5171fec7c66SAlessandro Zummo 		err = -ENOMEM;
5181fec7c66SAlessandro Zummo 		goto exit;
5191fec7c66SAlessandro Zummo 	}
5201fec7c66SAlessandro Zummo 
5211fec7c66SAlessandro Zummo 	/* I2C client */
5221fec7c66SAlessandro Zummo 	client->addr = address;
5231fec7c66SAlessandro Zummo 	client->driver = &x1205_driver;
5241fec7c66SAlessandro Zummo 	client->adapter	= adapter;
5251fec7c66SAlessandro Zummo 
5261fec7c66SAlessandro Zummo 	strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE);
5271fec7c66SAlessandro Zummo 
5281fec7c66SAlessandro Zummo 	/* Verify the chip is really an X1205 */
5291fec7c66SAlessandro Zummo 	if (kind < 0) {
5301fec7c66SAlessandro Zummo 		if (x1205_validate_client(client) < 0) {
5311fec7c66SAlessandro Zummo 			err = -ENODEV;
5321fec7c66SAlessandro Zummo 			goto exit_kfree;
5331fec7c66SAlessandro Zummo 		}
5341fec7c66SAlessandro Zummo 	}
5351fec7c66SAlessandro Zummo 
5361fec7c66SAlessandro Zummo 	/* Inform the i2c layer */
5371fec7c66SAlessandro Zummo 	if ((err = i2c_attach_client(client)))
5381fec7c66SAlessandro Zummo 		goto exit_kfree;
5391fec7c66SAlessandro Zummo 
5401fec7c66SAlessandro Zummo 	dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
5411fec7c66SAlessandro Zummo 
5421fec7c66SAlessandro Zummo 	rtc = rtc_device_register(x1205_driver.driver.name, &client->dev,
5431fec7c66SAlessandro Zummo 				&x1205_rtc_ops, THIS_MODULE);
5441fec7c66SAlessandro Zummo 
5451fec7c66SAlessandro Zummo 	if (IS_ERR(rtc)) {
5461fec7c66SAlessandro Zummo 		err = PTR_ERR(rtc);
5471fec7c66SAlessandro Zummo 		goto exit_detach;
5481fec7c66SAlessandro Zummo 	}
5491fec7c66SAlessandro Zummo 
5501fec7c66SAlessandro Zummo 	i2c_set_clientdata(client, rtc);
5511fec7c66SAlessandro Zummo 
5521fec7c66SAlessandro Zummo 	/* Check for power failures and eventualy enable the osc */
5531fec7c66SAlessandro Zummo 	if ((err = x1205_get_status(client, &sr)) == 0) {
5541fec7c66SAlessandro Zummo 		if (sr & X1205_SR_RTCF) {
5551fec7c66SAlessandro Zummo 			dev_err(&client->dev,
5561fec7c66SAlessandro Zummo 				"power failure detected, "
5571fec7c66SAlessandro Zummo 				"please set the clock\n");
5581fec7c66SAlessandro Zummo 			udelay(50);
5591fec7c66SAlessandro Zummo 			x1205_fix_osc(client);
5601fec7c66SAlessandro Zummo 		}
5611fec7c66SAlessandro Zummo 	}
5621fec7c66SAlessandro Zummo 	else
5631fec7c66SAlessandro Zummo 		dev_err(&client->dev, "couldn't read status\n");
5641fec7c66SAlessandro Zummo 
565*91046a8aSJeff Garzik 	err = device_create_file(&client->dev, &dev_attr_atrim);
566*91046a8aSJeff Garzik 	if (err) goto exit_devreg;
567*91046a8aSJeff Garzik 	err = device_create_file(&client->dev, &dev_attr_dtrim);
568*91046a8aSJeff Garzik 	if (err) goto exit_atrim;
5691fec7c66SAlessandro Zummo 
5701fec7c66SAlessandro Zummo 	return 0;
5711fec7c66SAlessandro Zummo 
572*91046a8aSJeff Garzik exit_atrim:
573*91046a8aSJeff Garzik 	device_remove_file(&client->dev, &dev_attr_atrim);
574*91046a8aSJeff Garzik 
575*91046a8aSJeff Garzik exit_devreg:
576*91046a8aSJeff Garzik 	rtc_device_unregister(rtc);
577*91046a8aSJeff Garzik 
5781fec7c66SAlessandro Zummo exit_detach:
5791fec7c66SAlessandro Zummo 	i2c_detach_client(client);
5801fec7c66SAlessandro Zummo 
5811fec7c66SAlessandro Zummo exit_kfree:
5821fec7c66SAlessandro Zummo 	kfree(client);
5831fec7c66SAlessandro Zummo 
5841fec7c66SAlessandro Zummo exit:
5851fec7c66SAlessandro Zummo 	return err;
5861fec7c66SAlessandro Zummo }
5871fec7c66SAlessandro Zummo 
5881fec7c66SAlessandro Zummo static int x1205_detach(struct i2c_client *client)
5891fec7c66SAlessandro Zummo {
5901fec7c66SAlessandro Zummo 	int err;
5911fec7c66SAlessandro Zummo 	struct rtc_device *rtc = i2c_get_clientdata(client);
5921fec7c66SAlessandro Zummo 
5931fec7c66SAlessandro Zummo  	if (rtc)
5941fec7c66SAlessandro Zummo 		rtc_device_unregister(rtc);
5951fec7c66SAlessandro Zummo 
5961fec7c66SAlessandro Zummo 	if ((err = i2c_detach_client(client)))
5971fec7c66SAlessandro Zummo 		return err;
5981fec7c66SAlessandro Zummo 
5991fec7c66SAlessandro Zummo 	kfree(client);
6001fec7c66SAlessandro Zummo 
6011fec7c66SAlessandro Zummo 	return 0;
6021fec7c66SAlessandro Zummo }
6031fec7c66SAlessandro Zummo 
6041fec7c66SAlessandro Zummo static int __init x1205_init(void)
6051fec7c66SAlessandro Zummo {
6061fec7c66SAlessandro Zummo 	return i2c_add_driver(&x1205_driver);
6071fec7c66SAlessandro Zummo }
6081fec7c66SAlessandro Zummo 
6091fec7c66SAlessandro Zummo static void __exit x1205_exit(void)
6101fec7c66SAlessandro Zummo {
6111fec7c66SAlessandro Zummo 	i2c_del_driver(&x1205_driver);
6121fec7c66SAlessandro Zummo }
6131fec7c66SAlessandro Zummo 
6141fec7c66SAlessandro Zummo MODULE_AUTHOR(
6151fec7c66SAlessandro Zummo 	"Karen Spearel <kas111 at gmail dot com>, "
6161fec7c66SAlessandro Zummo 	"Alessandro Zummo <a.zummo@towertech.it>");
6171fec7c66SAlessandro Zummo MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver");
6181fec7c66SAlessandro Zummo MODULE_LICENSE("GPL");
6191fec7c66SAlessandro Zummo MODULE_VERSION(DRV_VERSION);
6201fec7c66SAlessandro Zummo 
6211fec7c66SAlessandro Zummo module_init(x1205_init);
6221fec7c66SAlessandro Zummo module_exit(x1205_exit);
623