1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21fec7c66SAlessandro Zummo /*
31fec7c66SAlessandro Zummo * An i2c driver for the Xicor/Intersil X1205 RTC
41fec7c66SAlessandro Zummo * Copyright 2004 Karen Spearel
51fec7c66SAlessandro Zummo * Copyright 2005 Alessandro Zummo
61fec7c66SAlessandro Zummo *
71fec7c66SAlessandro Zummo * please send all reports to:
81fec7c66SAlessandro Zummo * Karen Spearel <kas111 at gmail dot com>
91fec7c66SAlessandro Zummo * Alessandro Zummo <a.zummo@towertech.it>
101fec7c66SAlessandro Zummo *
111fec7c66SAlessandro Zummo * based on a lot of other RTC drivers.
121fec7c66SAlessandro Zummo *
13890e0375SJean Delvare * Information and datasheet:
14890e0375SJean Delvare * http://www.intersil.com/cda/deviceinfo/0,1477,X1205,00.html
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>
212113852bSPaul Gortmaker #include <linux/module.h>
2286e66604SMartin Kepplinger #include <linux/bitops.h>
231fec7c66SAlessandro Zummo
241fec7c66SAlessandro Zummo /* offsets into CCR area */
251fec7c66SAlessandro Zummo
261fec7c66SAlessandro Zummo #define CCR_SEC 0
271fec7c66SAlessandro Zummo #define CCR_MIN 1
281fec7c66SAlessandro Zummo #define CCR_HOUR 2
291fec7c66SAlessandro Zummo #define CCR_MDAY 3
301fec7c66SAlessandro Zummo #define CCR_MONTH 4
311fec7c66SAlessandro Zummo #define CCR_YEAR 5
321fec7c66SAlessandro Zummo #define CCR_WDAY 6
331fec7c66SAlessandro Zummo #define CCR_Y2K 7
341fec7c66SAlessandro Zummo
351fec7c66SAlessandro Zummo #define X1205_REG_SR 0x3F /* status register */
361fec7c66SAlessandro Zummo #define X1205_REG_Y2K 0x37
371fec7c66SAlessandro Zummo #define X1205_REG_DW 0x36
381fec7c66SAlessandro Zummo #define X1205_REG_YR 0x35
391fec7c66SAlessandro Zummo #define X1205_REG_MO 0x34
401fec7c66SAlessandro Zummo #define X1205_REG_DT 0x33
411fec7c66SAlessandro Zummo #define X1205_REG_HR 0x32
421fec7c66SAlessandro Zummo #define X1205_REG_MN 0x31
431fec7c66SAlessandro Zummo #define X1205_REG_SC 0x30
441fec7c66SAlessandro Zummo #define X1205_REG_DTR 0x13
451fec7c66SAlessandro Zummo #define X1205_REG_ATR 0x12
461fec7c66SAlessandro Zummo #define X1205_REG_INT 0x11
471fec7c66SAlessandro Zummo #define X1205_REG_0 0x10
481fec7c66SAlessandro Zummo #define X1205_REG_Y2K1 0x0F
491fec7c66SAlessandro Zummo #define X1205_REG_DWA1 0x0E
501fec7c66SAlessandro Zummo #define X1205_REG_YRA1 0x0D
511fec7c66SAlessandro Zummo #define X1205_REG_MOA1 0x0C
521fec7c66SAlessandro Zummo #define X1205_REG_DTA1 0x0B
531fec7c66SAlessandro Zummo #define X1205_REG_HRA1 0x0A
541fec7c66SAlessandro Zummo #define X1205_REG_MNA1 0x09
551fec7c66SAlessandro Zummo #define X1205_REG_SCA1 0x08
561fec7c66SAlessandro Zummo #define X1205_REG_Y2K0 0x07
571fec7c66SAlessandro Zummo #define X1205_REG_DWA0 0x06
581fec7c66SAlessandro Zummo #define X1205_REG_YRA0 0x05
591fec7c66SAlessandro Zummo #define X1205_REG_MOA0 0x04
601fec7c66SAlessandro Zummo #define X1205_REG_DTA0 0x03
611fec7c66SAlessandro Zummo #define X1205_REG_HRA0 0x02
621fec7c66SAlessandro Zummo #define X1205_REG_MNA0 0x01
631fec7c66SAlessandro Zummo #define X1205_REG_SCA0 0x00
641fec7c66SAlessandro Zummo
651fec7c66SAlessandro Zummo #define X1205_CCR_BASE 0x30 /* Base address of CCR */
661fec7c66SAlessandro Zummo #define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */
671fec7c66SAlessandro Zummo
681fec7c66SAlessandro Zummo #define X1205_SR_RTCF 0x01 /* Clock failure */
691fec7c66SAlessandro Zummo #define X1205_SR_WEL 0x02 /* Write Enable Latch */
701fec7c66SAlessandro Zummo #define X1205_SR_RWEL 0x04 /* Register Write Enable */
71471d47e3SMichael Hamel #define X1205_SR_AL0 0x20 /* Alarm 0 match */
721fec7c66SAlessandro Zummo
731fec7c66SAlessandro Zummo #define X1205_DTR_DTR0 0x01
741fec7c66SAlessandro Zummo #define X1205_DTR_DTR1 0x02
751fec7c66SAlessandro Zummo #define X1205_DTR_DTR2 0x04
761fec7c66SAlessandro Zummo
771fec7c66SAlessandro Zummo #define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
781fec7c66SAlessandro Zummo
79471d47e3SMichael Hamel #define X1205_INT_AL0E 0x20 /* Alarm 0 enable */
80471d47e3SMichael Hamel
814edac2b4SAlessandro Zummo static struct i2c_driver x1205_driver;
821fec7c66SAlessandro Zummo
831fec7c66SAlessandro Zummo /*
841fec7c66SAlessandro Zummo * In the routines that deal directly with the x1205 hardware, we use
851fec7c66SAlessandro Zummo * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch
861fec7c66SAlessandro Zummo * Epoch is initialized as 2000. Time is set to UTC.
871fec7c66SAlessandro Zummo */
x1205_get_datetime(struct i2c_client * client,struct rtc_time * tm,unsigned char reg_base)881fec7c66SAlessandro Zummo static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
891fec7c66SAlessandro Zummo unsigned char reg_base)
901fec7c66SAlessandro Zummo {
911fec7c66SAlessandro Zummo unsigned char dt_addr[2] = { 0, reg_base };
921fec7c66SAlessandro Zummo unsigned char buf[8];
93471d47e3SMichael Hamel int i;
941fec7c66SAlessandro Zummo
951fec7c66SAlessandro Zummo struct i2c_msg msgs[] = {
96c3fe92b7SShubhrajyoti D {/* setup read ptr */
97c3fe92b7SShubhrajyoti D .addr = client->addr,
98c3fe92b7SShubhrajyoti D .len = 2,
99c3fe92b7SShubhrajyoti D .buf = dt_addr
100c3fe92b7SShubhrajyoti D },
101c3fe92b7SShubhrajyoti D {/* read date */
102c3fe92b7SShubhrajyoti D .addr = client->addr,
103c3fe92b7SShubhrajyoti D .flags = I2C_M_RD,
104c3fe92b7SShubhrajyoti D .len = 8,
105c3fe92b7SShubhrajyoti D .buf = buf
106c3fe92b7SShubhrajyoti D },
1071fec7c66SAlessandro Zummo };
1081fec7c66SAlessandro Zummo
1091fec7c66SAlessandro Zummo /* read date registers */
110471d47e3SMichael Hamel if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
1112a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: read error\n", __func__);
1121fec7c66SAlessandro Zummo return -EIO;
1131fec7c66SAlessandro Zummo }
1141fec7c66SAlessandro Zummo
1151fec7c66SAlessandro Zummo dev_dbg(&client->dev,
1161fec7c66SAlessandro Zummo "%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
1171fec7c66SAlessandro Zummo "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
1182a4e2b87SHarvey Harrison __func__,
1191fec7c66SAlessandro Zummo buf[0], buf[1], buf[2], buf[3],
1201fec7c66SAlessandro Zummo buf[4], buf[5], buf[6], buf[7]);
1211fec7c66SAlessandro Zummo
122471d47e3SMichael Hamel /* Mask out the enable bits if these are alarm registers */
123471d47e3SMichael Hamel if (reg_base < X1205_CCR_BASE)
124471d47e3SMichael Hamel for (i = 0; i <= 4; i++)
125471d47e3SMichael Hamel buf[i] &= 0x7F;
126471d47e3SMichael Hamel
127fe20ba70SAdrian Bunk tm->tm_sec = bcd2bin(buf[CCR_SEC]);
128fe20ba70SAdrian Bunk tm->tm_min = bcd2bin(buf[CCR_MIN]);
129fe20ba70SAdrian Bunk tm->tm_hour = bcd2bin(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
130fe20ba70SAdrian Bunk tm->tm_mday = bcd2bin(buf[CCR_MDAY]);
131fe20ba70SAdrian Bunk tm->tm_mon = bcd2bin(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
132fe20ba70SAdrian Bunk tm->tm_year = bcd2bin(buf[CCR_YEAR])
133fe20ba70SAdrian Bunk + (bcd2bin(buf[CCR_Y2K]) * 100) - 1900;
1341fec7c66SAlessandro Zummo tm->tm_wday = buf[CCR_WDAY];
1351fec7c66SAlessandro Zummo
1361fec7c66SAlessandro Zummo dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
1371fec7c66SAlessandro Zummo "mday=%d, mon=%d, year=%d, wday=%d\n",
1382a4e2b87SHarvey Harrison __func__,
1391fec7c66SAlessandro Zummo tm->tm_sec, tm->tm_min, tm->tm_hour,
1401fec7c66SAlessandro Zummo tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
1411fec7c66SAlessandro Zummo
1421fec7c66SAlessandro Zummo return 0;
1431fec7c66SAlessandro Zummo }
1441fec7c66SAlessandro Zummo
x1205_get_status(struct i2c_client * client,unsigned char * sr)1451fec7c66SAlessandro Zummo static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
1461fec7c66SAlessandro Zummo {
1471fec7c66SAlessandro Zummo static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
1481fec7c66SAlessandro Zummo
1491fec7c66SAlessandro Zummo struct i2c_msg msgs[] = {
150c3fe92b7SShubhrajyoti D { /* setup read ptr */
151c3fe92b7SShubhrajyoti D .addr = client->addr,
152c3fe92b7SShubhrajyoti D .len = 2,
153c3fe92b7SShubhrajyoti D .buf = sr_addr
154c3fe92b7SShubhrajyoti D },
155c3fe92b7SShubhrajyoti D { /* read status */
156c3fe92b7SShubhrajyoti D .addr = client->addr,
157c3fe92b7SShubhrajyoti D .flags = I2C_M_RD,
158c3fe92b7SShubhrajyoti D .len = 1,
159c3fe92b7SShubhrajyoti D .buf = sr
160c3fe92b7SShubhrajyoti D },
1611fec7c66SAlessandro Zummo };
1621fec7c66SAlessandro Zummo
1631fec7c66SAlessandro Zummo /* read status register */
164471d47e3SMichael Hamel if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
1652a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: read error\n", __func__);
1661fec7c66SAlessandro Zummo return -EIO;
1671fec7c66SAlessandro Zummo }
1681fec7c66SAlessandro Zummo
1691fec7c66SAlessandro Zummo return 0;
1701fec7c66SAlessandro Zummo }
1711fec7c66SAlessandro Zummo
x1205_set_datetime(struct i2c_client * client,struct rtc_time * tm,u8 reg_base,unsigned char alm_enable)1721fec7c66SAlessandro Zummo static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
173d973b632SJohannes Weiner u8 reg_base, unsigned char alm_enable)
1741fec7c66SAlessandro Zummo {
175d973b632SJohannes Weiner int i, xfer;
176471d47e3SMichael Hamel unsigned char rdata[10] = { 0, reg_base };
177d973b632SJohannes Weiner unsigned char *buf = rdata + 2;
1781fec7c66SAlessandro Zummo
1791fec7c66SAlessandro Zummo static const unsigned char wel[3] = { 0, X1205_REG_SR,
1801fec7c66SAlessandro Zummo X1205_SR_WEL };
1811fec7c66SAlessandro Zummo
1821fec7c66SAlessandro Zummo static const unsigned char rwel[3] = { 0, X1205_REG_SR,
1831fec7c66SAlessandro Zummo X1205_SR_WEL | X1205_SR_RWEL };
1841fec7c66SAlessandro Zummo
1851fec7c66SAlessandro Zummo static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
1861fec7c66SAlessandro Zummo
1871fec7c66SAlessandro Zummo dev_dbg(&client->dev,
188d973b632SJohannes Weiner "%s: sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d\n",
189d973b632SJohannes Weiner __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday,
190d973b632SJohannes Weiner tm->tm_mon, tm->tm_year, tm->tm_wday);
1911fec7c66SAlessandro Zummo
192fe20ba70SAdrian Bunk buf[CCR_SEC] = bin2bcd(tm->tm_sec);
193fe20ba70SAdrian Bunk buf[CCR_MIN] = bin2bcd(tm->tm_min);
1941fec7c66SAlessandro Zummo
1951fec7c66SAlessandro Zummo /* set hour and 24hr bit */
196fe20ba70SAdrian Bunk buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL;
1971fec7c66SAlessandro Zummo
198fe20ba70SAdrian Bunk buf[CCR_MDAY] = bin2bcd(tm->tm_mday);
1991fec7c66SAlessandro Zummo
2001fec7c66SAlessandro Zummo /* month, 1 - 12 */
201fe20ba70SAdrian Bunk buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1);
2021fec7c66SAlessandro Zummo
2031fec7c66SAlessandro Zummo /* year, since the rtc epoch*/
204fe20ba70SAdrian Bunk buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
2051fec7c66SAlessandro Zummo buf[CCR_WDAY] = tm->tm_wday & 0x07;
20648a7f774SJohannes Weiner buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100);
2071fec7c66SAlessandro Zummo
208471d47e3SMichael Hamel /* If writing alarm registers, set compare bits on registers 0-4 */
209471d47e3SMichael Hamel if (reg_base < X1205_CCR_BASE)
210471d47e3SMichael Hamel for (i = 0; i <= 4; i++)
211471d47e3SMichael Hamel buf[i] |= 0x80;
212471d47e3SMichael Hamel
2131fec7c66SAlessandro Zummo /* this sequence is required to unlock the chip */
21466e3f10cSSachin Kamat xfer = i2c_master_send(client, wel, 3);
21566e3f10cSSachin Kamat if (xfer != 3) {
2162a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer);
2171fec7c66SAlessandro Zummo return -EIO;
2181fec7c66SAlessandro Zummo }
2191fec7c66SAlessandro Zummo
22066e3f10cSSachin Kamat xfer = i2c_master_send(client, rwel, 3);
22166e3f10cSSachin Kamat if (xfer != 3) {
2222a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: rwel - %d\n", __func__, xfer);
2231fec7c66SAlessandro Zummo return -EIO;
2241fec7c66SAlessandro Zummo }
2251fec7c66SAlessandro Zummo
226d973b632SJohannes Weiner xfer = i2c_master_send(client, rdata, sizeof(rdata));
227d973b632SJohannes Weiner if (xfer != sizeof(rdata)) {
2281fec7c66SAlessandro Zummo dev_err(&client->dev,
229471d47e3SMichael Hamel "%s: result=%d addr=%02x, data=%02x\n",
2302a4e2b87SHarvey Harrison __func__,
2311fec7c66SAlessandro Zummo xfer, rdata[1], rdata[2]);
2321fec7c66SAlessandro Zummo return -EIO;
2331fec7c66SAlessandro Zummo }
234471d47e3SMichael Hamel
235471d47e3SMichael Hamel /* If we wrote to the nonvolatile region, wait 10msec for write cycle*/
236471d47e3SMichael Hamel if (reg_base < X1205_CCR_BASE) {
237471d47e3SMichael Hamel unsigned char al0e[3] = { 0, X1205_REG_INT, 0 };
238471d47e3SMichael Hamel
239471d47e3SMichael Hamel msleep(10);
240471d47e3SMichael Hamel
241471d47e3SMichael Hamel /* ...and set or clear the AL0E bit in the INT register */
242471d47e3SMichael Hamel
243471d47e3SMichael Hamel /* Need to set RWEL again as the write has cleared it */
244471d47e3SMichael Hamel xfer = i2c_master_send(client, rwel, 3);
245471d47e3SMichael Hamel if (xfer != 3) {
246471d47e3SMichael Hamel dev_err(&client->dev,
247471d47e3SMichael Hamel "%s: aloe rwel - %d\n",
248471d47e3SMichael Hamel __func__,
249471d47e3SMichael Hamel xfer);
250471d47e3SMichael Hamel return -EIO;
251471d47e3SMichael Hamel }
252471d47e3SMichael Hamel
253471d47e3SMichael Hamel if (alm_enable)
254471d47e3SMichael Hamel al0e[2] = X1205_INT_AL0E;
255471d47e3SMichael Hamel
256471d47e3SMichael Hamel xfer = i2c_master_send(client, al0e, 3);
257471d47e3SMichael Hamel if (xfer != 3) {
258471d47e3SMichael Hamel dev_err(&client->dev,
259471d47e3SMichael Hamel "%s: al0e - %d\n",
260471d47e3SMichael Hamel __func__,
261471d47e3SMichael Hamel xfer);
262471d47e3SMichael Hamel return -EIO;
263471d47e3SMichael Hamel }
264471d47e3SMichael Hamel
265471d47e3SMichael Hamel /* and wait 10msec again for this write to complete */
266471d47e3SMichael Hamel msleep(10);
267471d47e3SMichael Hamel }
2681fec7c66SAlessandro Zummo
2691fec7c66SAlessandro Zummo /* disable further writes */
27066e3f10cSSachin Kamat xfer = i2c_master_send(client, diswe, 3);
27166e3f10cSSachin Kamat if (xfer != 3) {
2722a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: diswe - %d\n", __func__, xfer);
2731fec7c66SAlessandro Zummo return -EIO;
2741fec7c66SAlessandro Zummo }
2751fec7c66SAlessandro Zummo
2761fec7c66SAlessandro Zummo return 0;
2771fec7c66SAlessandro Zummo }
2781fec7c66SAlessandro Zummo
x1205_fix_osc(struct i2c_client * client)2791fec7c66SAlessandro Zummo static int x1205_fix_osc(struct i2c_client *client)
2801fec7c66SAlessandro Zummo {
2811fec7c66SAlessandro Zummo int err;
2821fec7c66SAlessandro Zummo struct rtc_time tm;
2831fec7c66SAlessandro Zummo
284cb8799eeSJohannes Weiner memset(&tm, 0, sizeof(tm));
2851fec7c66SAlessandro Zummo
286d973b632SJohannes Weiner err = x1205_set_datetime(client, &tm, X1205_CCR_BASE, 0);
287471d47e3SMichael Hamel if (err < 0)
288471d47e3SMichael Hamel dev_err(&client->dev, "unable to restart the oscillator\n");
2891fec7c66SAlessandro Zummo
2901fec7c66SAlessandro Zummo return err;
2911fec7c66SAlessandro Zummo }
2921fec7c66SAlessandro Zummo
x1205_get_dtrim(struct i2c_client * client,int * trim)2931fec7c66SAlessandro Zummo static int x1205_get_dtrim(struct i2c_client *client, int *trim)
2941fec7c66SAlessandro Zummo {
2951fec7c66SAlessandro Zummo unsigned char dtr;
2961fec7c66SAlessandro Zummo static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
2971fec7c66SAlessandro Zummo
2981fec7c66SAlessandro Zummo struct i2c_msg msgs[] = {
299c3fe92b7SShubhrajyoti D { /* setup read ptr */
300c3fe92b7SShubhrajyoti D .addr = client->addr,
301c3fe92b7SShubhrajyoti D .len = 2,
302c3fe92b7SShubhrajyoti D .buf = dtr_addr
303c3fe92b7SShubhrajyoti D },
304c3fe92b7SShubhrajyoti D { /* read dtr */
305c3fe92b7SShubhrajyoti D .addr = client->addr,
306c3fe92b7SShubhrajyoti D .flags = I2C_M_RD,
307c3fe92b7SShubhrajyoti D .len = 1,
308c3fe92b7SShubhrajyoti D .buf = &dtr
309c3fe92b7SShubhrajyoti D },
3101fec7c66SAlessandro Zummo };
3111fec7c66SAlessandro Zummo
3121fec7c66SAlessandro Zummo /* read dtr register */
313471d47e3SMichael Hamel if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
3142a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: read error\n", __func__);
3151fec7c66SAlessandro Zummo return -EIO;
3161fec7c66SAlessandro Zummo }
3171fec7c66SAlessandro Zummo
3182a4e2b87SHarvey Harrison dev_dbg(&client->dev, "%s: raw dtr=%x\n", __func__, dtr);
3191fec7c66SAlessandro Zummo
3201fec7c66SAlessandro Zummo *trim = 0;
3211fec7c66SAlessandro Zummo
3221fec7c66SAlessandro Zummo if (dtr & X1205_DTR_DTR0)
3231fec7c66SAlessandro Zummo *trim += 20;
3241fec7c66SAlessandro Zummo
3251fec7c66SAlessandro Zummo if (dtr & X1205_DTR_DTR1)
3261fec7c66SAlessandro Zummo *trim += 10;
3271fec7c66SAlessandro Zummo
3281fec7c66SAlessandro Zummo if (dtr & X1205_DTR_DTR2)
3291fec7c66SAlessandro Zummo *trim = -*trim;
3301fec7c66SAlessandro Zummo
3311fec7c66SAlessandro Zummo return 0;
3321fec7c66SAlessandro Zummo }
3331fec7c66SAlessandro Zummo
x1205_get_atrim(struct i2c_client * client,int * trim)3341fec7c66SAlessandro Zummo static int x1205_get_atrim(struct i2c_client *client, int *trim)
3351fec7c66SAlessandro Zummo {
3361fec7c66SAlessandro Zummo s8 atr;
3371fec7c66SAlessandro Zummo static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
3381fec7c66SAlessandro Zummo
3391fec7c66SAlessandro Zummo struct i2c_msg msgs[] = {
340c3fe92b7SShubhrajyoti D {/* setup read ptr */
341c3fe92b7SShubhrajyoti D .addr = client->addr,
342c3fe92b7SShubhrajyoti D .len = 2,
343c3fe92b7SShubhrajyoti D .buf = atr_addr
344c3fe92b7SShubhrajyoti D },
345c3fe92b7SShubhrajyoti D {/* read atr */
346c3fe92b7SShubhrajyoti D .addr = client->addr,
347c3fe92b7SShubhrajyoti D .flags = I2C_M_RD,
348c3fe92b7SShubhrajyoti D .len = 1,
349c3fe92b7SShubhrajyoti D .buf = &atr
350c3fe92b7SShubhrajyoti D },
3511fec7c66SAlessandro Zummo };
3521fec7c66SAlessandro Zummo
3531fec7c66SAlessandro Zummo /* read atr register */
354471d47e3SMichael Hamel if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
3552a4e2b87SHarvey Harrison dev_err(&client->dev, "%s: read error\n", __func__);
3561fec7c66SAlessandro Zummo return -EIO;
3571fec7c66SAlessandro Zummo }
3581fec7c66SAlessandro Zummo
3592a4e2b87SHarvey Harrison dev_dbg(&client->dev, "%s: raw atr=%x\n", __func__, atr);
3601fec7c66SAlessandro Zummo
3611fec7c66SAlessandro Zummo /* atr is a two's complement value on 6 bits,
3621fec7c66SAlessandro Zummo * perform sign extension. The formula is
3631fec7c66SAlessandro Zummo * Catr = (atr * 0.25pF) + 11.00pF.
3641fec7c66SAlessandro Zummo */
36586e66604SMartin Kepplinger atr = sign_extend32(atr, 5);
3661fec7c66SAlessandro Zummo
3672a4e2b87SHarvey Harrison dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __func__, atr, atr);
3681fec7c66SAlessandro Zummo
3691fec7c66SAlessandro Zummo *trim = (atr * 250) + 11000;
3701fec7c66SAlessandro Zummo
3712a4e2b87SHarvey Harrison dev_dbg(&client->dev, "%s: real=%d\n", __func__, *trim);
3721fec7c66SAlessandro Zummo
3731fec7c66SAlessandro Zummo return 0;
3741fec7c66SAlessandro Zummo }
3751fec7c66SAlessandro Zummo
37666e3f10cSSachin Kamat struct x1205_limit {
3771fec7c66SAlessandro Zummo unsigned char reg, mask, min, max;
3781fec7c66SAlessandro Zummo };
3791fec7c66SAlessandro Zummo
x1205_validate_client(struct i2c_client * client)3801fec7c66SAlessandro Zummo static int x1205_validate_client(struct i2c_client *client)
3811fec7c66SAlessandro Zummo {
3821fec7c66SAlessandro Zummo int i, xfer;
3831fec7c66SAlessandro Zummo
3841fec7c66SAlessandro Zummo /* Probe array. We will read the register at the specified
3851fec7c66SAlessandro Zummo * address and check if the given bits are zero.
3861fec7c66SAlessandro Zummo */
3871fec7c66SAlessandro Zummo static const unsigned char probe_zero_pattern[] = {
3881fec7c66SAlessandro Zummo /* register, mask */
3891fec7c66SAlessandro Zummo X1205_REG_SR, 0x18,
3901fec7c66SAlessandro Zummo X1205_REG_DTR, 0xF8,
3911fec7c66SAlessandro Zummo X1205_REG_ATR, 0xC0,
3921fec7c66SAlessandro Zummo X1205_REG_INT, 0x18,
3931fec7c66SAlessandro Zummo X1205_REG_0, 0xFF,
3941fec7c66SAlessandro Zummo };
3951fec7c66SAlessandro Zummo
3961fec7c66SAlessandro Zummo static const struct x1205_limit probe_limits_pattern[] = {
3971fec7c66SAlessandro Zummo /* register, mask, min, max */
3981fec7c66SAlessandro Zummo { X1205_REG_Y2K, 0xFF, 19, 20 },
3991fec7c66SAlessandro Zummo { X1205_REG_DW, 0xFF, 0, 6 },
4001fec7c66SAlessandro Zummo { X1205_REG_YR, 0xFF, 0, 99 },
4011fec7c66SAlessandro Zummo { X1205_REG_MO, 0xFF, 0, 12 },
4021fec7c66SAlessandro Zummo { X1205_REG_DT, 0xFF, 0, 31 },
4031fec7c66SAlessandro Zummo { X1205_REG_HR, 0x7F, 0, 23 },
4041fec7c66SAlessandro Zummo { X1205_REG_MN, 0xFF, 0, 59 },
4051fec7c66SAlessandro Zummo { X1205_REG_SC, 0xFF, 0, 59 },
4061fec7c66SAlessandro Zummo { X1205_REG_Y2K1, 0xFF, 19, 20 },
4071fec7c66SAlessandro Zummo { X1205_REG_Y2K0, 0xFF, 19, 20 },
4081fec7c66SAlessandro Zummo };
4091fec7c66SAlessandro Zummo
4101fec7c66SAlessandro Zummo /* check that registers have bits a 0 where expected */
4111fec7c66SAlessandro Zummo for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) {
4121fec7c66SAlessandro Zummo unsigned char buf;
4131fec7c66SAlessandro Zummo
4141fec7c66SAlessandro Zummo unsigned char addr[2] = { 0, probe_zero_pattern[i] };
4151fec7c66SAlessandro Zummo
4161fec7c66SAlessandro Zummo struct i2c_msg msgs[2] = {
417c3fe92b7SShubhrajyoti D {
418c3fe92b7SShubhrajyoti D .addr = client->addr,
419c3fe92b7SShubhrajyoti D .len = 2,
420c3fe92b7SShubhrajyoti D .buf = addr
421c3fe92b7SShubhrajyoti D },
422c3fe92b7SShubhrajyoti D {
423c3fe92b7SShubhrajyoti D .addr = client->addr,
424c3fe92b7SShubhrajyoti D .flags = I2C_M_RD,
425c3fe92b7SShubhrajyoti D .len = 1,
426c3fe92b7SShubhrajyoti D .buf = &buf
427c3fe92b7SShubhrajyoti D },
4281fec7c66SAlessandro Zummo };
4291fec7c66SAlessandro Zummo
43066e3f10cSSachin Kamat xfer = i2c_transfer(client->adapter, msgs, 2);
43166e3f10cSSachin Kamat if (xfer != 2) {
432a14e1893SDavid Brownell dev_err(&client->dev,
4331fec7c66SAlessandro Zummo "%s: could not read register %x\n",
4342a4e2b87SHarvey Harrison __func__, probe_zero_pattern[i]);
4351fec7c66SAlessandro Zummo
4361fec7c66SAlessandro Zummo return -EIO;
4371fec7c66SAlessandro Zummo }
4381fec7c66SAlessandro Zummo
4391fec7c66SAlessandro Zummo if ((buf & probe_zero_pattern[i+1]) != 0) {
440a14e1893SDavid Brownell dev_err(&client->dev,
4411fec7c66SAlessandro Zummo "%s: register=%02x, zero pattern=%d, value=%x\n",
4422a4e2b87SHarvey Harrison __func__, probe_zero_pattern[i], i, buf);
4431fec7c66SAlessandro Zummo
4441fec7c66SAlessandro Zummo return -ENODEV;
4451fec7c66SAlessandro Zummo }
4461fec7c66SAlessandro Zummo }
4471fec7c66SAlessandro Zummo
4481fec7c66SAlessandro Zummo /* check limits (only registers with bcd values) */
4491fec7c66SAlessandro Zummo for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) {
4501fec7c66SAlessandro Zummo unsigned char reg, value;
4511fec7c66SAlessandro Zummo
4521fec7c66SAlessandro Zummo unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
4531fec7c66SAlessandro Zummo
4541fec7c66SAlessandro Zummo struct i2c_msg msgs[2] = {
455c3fe92b7SShubhrajyoti D {
456c3fe92b7SShubhrajyoti D .addr = client->addr,
457c3fe92b7SShubhrajyoti D .len = 2,
458c3fe92b7SShubhrajyoti D .buf = addr
459c3fe92b7SShubhrajyoti D },
460c3fe92b7SShubhrajyoti D {
461c3fe92b7SShubhrajyoti D .addr = client->addr,
462c3fe92b7SShubhrajyoti D .flags = I2C_M_RD,
463c3fe92b7SShubhrajyoti D .len = 1,
464c3fe92b7SShubhrajyoti D .buf = ®
465c3fe92b7SShubhrajyoti D },
4661fec7c66SAlessandro Zummo };
4671fec7c66SAlessandro Zummo
46866e3f10cSSachin Kamat xfer = i2c_transfer(client->adapter, msgs, 2);
46966e3f10cSSachin Kamat if (xfer != 2) {
470a14e1893SDavid Brownell dev_err(&client->dev,
4711fec7c66SAlessandro Zummo "%s: could not read register %x\n",
4722a4e2b87SHarvey Harrison __func__, probe_limits_pattern[i].reg);
4731fec7c66SAlessandro Zummo
4741fec7c66SAlessandro Zummo return -EIO;
4751fec7c66SAlessandro Zummo }
4761fec7c66SAlessandro Zummo
477fe20ba70SAdrian Bunk value = bcd2bin(reg & probe_limits_pattern[i].mask);
4781fec7c66SAlessandro Zummo
4791fec7c66SAlessandro Zummo if (value > probe_limits_pattern[i].max ||
4801fec7c66SAlessandro Zummo value < probe_limits_pattern[i].min) {
481a14e1893SDavid Brownell dev_dbg(&client->dev,
4821fec7c66SAlessandro Zummo "%s: register=%x, lim pattern=%d, value=%d\n",
4832a4e2b87SHarvey Harrison __func__, probe_limits_pattern[i].reg,
4841fec7c66SAlessandro Zummo i, value);
4851fec7c66SAlessandro Zummo
4861fec7c66SAlessandro Zummo return -ENODEV;
4871fec7c66SAlessandro Zummo }
4881fec7c66SAlessandro Zummo }
4891fec7c66SAlessandro Zummo
4901fec7c66SAlessandro Zummo return 0;
4911fec7c66SAlessandro Zummo }
4921fec7c66SAlessandro Zummo
x1205_rtc_read_alarm(struct device * dev,struct rtc_wkalrm * alrm)4931fec7c66SAlessandro Zummo static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
4941fec7c66SAlessandro Zummo {
495471d47e3SMichael Hamel int err;
496471d47e3SMichael Hamel unsigned char intreg, status;
497471d47e3SMichael Hamel static unsigned char int_addr[2] = { 0, X1205_REG_INT };
498471d47e3SMichael Hamel struct i2c_client *client = to_i2c_client(dev);
499471d47e3SMichael Hamel struct i2c_msg msgs[] = {
500c3fe92b7SShubhrajyoti D { /* setup read ptr */
501c3fe92b7SShubhrajyoti D .addr = client->addr,
502c3fe92b7SShubhrajyoti D .len = 2,
503c3fe92b7SShubhrajyoti D .buf = int_addr
504c3fe92b7SShubhrajyoti D },
505c3fe92b7SShubhrajyoti D {/* read INT register */
506c3fe92b7SShubhrajyoti D
507c3fe92b7SShubhrajyoti D .addr = client->addr,
508c3fe92b7SShubhrajyoti D .flags = I2C_M_RD,
509c3fe92b7SShubhrajyoti D .len = 1,
510c3fe92b7SShubhrajyoti D .buf = &intreg
511c3fe92b7SShubhrajyoti D },
512471d47e3SMichael Hamel };
513471d47e3SMichael Hamel
514471d47e3SMichael Hamel /* read interrupt register and status register */
515471d47e3SMichael Hamel if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
516471d47e3SMichael Hamel dev_err(&client->dev, "%s: read error\n", __func__);
517471d47e3SMichael Hamel return -EIO;
518471d47e3SMichael Hamel }
519471d47e3SMichael Hamel err = x1205_get_status(client, &status);
520471d47e3SMichael Hamel if (err == 0) {
521471d47e3SMichael Hamel alrm->pending = (status & X1205_SR_AL0) ? 1 : 0;
522471d47e3SMichael Hamel alrm->enabled = (intreg & X1205_INT_AL0E) ? 1 : 0;
523471d47e3SMichael Hamel err = x1205_get_datetime(client, &alrm->time, X1205_ALM0_BASE);
524471d47e3SMichael Hamel }
525471d47e3SMichael Hamel return err;
5261fec7c66SAlessandro Zummo }
5271fec7c66SAlessandro Zummo
x1205_rtc_set_alarm(struct device * dev,struct rtc_wkalrm * alrm)5281fec7c66SAlessandro Zummo static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
5291fec7c66SAlessandro Zummo {
5301fec7c66SAlessandro Zummo return x1205_set_datetime(to_i2c_client(dev),
531d973b632SJohannes Weiner &alrm->time, X1205_ALM0_BASE, alrm->enabled);
5321fec7c66SAlessandro Zummo }
5331fec7c66SAlessandro Zummo
x1205_rtc_read_time(struct device * dev,struct rtc_time * tm)5341fec7c66SAlessandro Zummo static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
5351fec7c66SAlessandro Zummo {
5361fec7c66SAlessandro Zummo return x1205_get_datetime(to_i2c_client(dev),
5371fec7c66SAlessandro Zummo tm, X1205_CCR_BASE);
5381fec7c66SAlessandro Zummo }
5391fec7c66SAlessandro Zummo
x1205_rtc_set_time(struct device * dev,struct rtc_time * tm)5401fec7c66SAlessandro Zummo static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm)
5411fec7c66SAlessandro Zummo {
5421fec7c66SAlessandro Zummo return x1205_set_datetime(to_i2c_client(dev),
543d973b632SJohannes Weiner tm, X1205_CCR_BASE, 0);
5441fec7c66SAlessandro Zummo }
5451fec7c66SAlessandro Zummo
x1205_rtc_proc(struct device * dev,struct seq_file * seq)5461fec7c66SAlessandro Zummo static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
5471fec7c66SAlessandro Zummo {
5481fec7c66SAlessandro Zummo int err, dtrim, atrim;
5491fec7c66SAlessandro Zummo
55066e3f10cSSachin Kamat err = x1205_get_dtrim(to_i2c_client(dev), &dtrim);
55166e3f10cSSachin Kamat if (!err)
5521fec7c66SAlessandro Zummo seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim);
5531fec7c66SAlessandro Zummo
55466e3f10cSSachin Kamat err = x1205_get_atrim(to_i2c_client(dev), &atrim);
55566e3f10cSSachin Kamat if (!err)
5561fec7c66SAlessandro Zummo seq_printf(seq, "analog_trim\t: %d.%02d pF\n",
5571fec7c66SAlessandro Zummo atrim / 1000, atrim % 1000);
5581fec7c66SAlessandro Zummo return 0;
5591fec7c66SAlessandro Zummo }
5601fec7c66SAlessandro Zummo
561ff8371acSDavid Brownell static const struct rtc_class_ops x1205_rtc_ops = {
5621fec7c66SAlessandro Zummo .proc = x1205_rtc_proc,
5631fec7c66SAlessandro Zummo .read_time = x1205_rtc_read_time,
5641fec7c66SAlessandro Zummo .set_time = x1205_rtc_set_time,
5651fec7c66SAlessandro Zummo .read_alarm = x1205_rtc_read_alarm,
5661fec7c66SAlessandro Zummo .set_alarm = x1205_rtc_set_alarm,
5671fec7c66SAlessandro Zummo };
5681fec7c66SAlessandro Zummo
x1205_sysfs_show_atrim(struct device * dev,struct device_attribute * attr,char * buf)5691fec7c66SAlessandro Zummo static ssize_t x1205_sysfs_show_atrim(struct device *dev,
5701fec7c66SAlessandro Zummo struct device_attribute *attr, char *buf)
5711fec7c66SAlessandro Zummo {
572015aefbbSAlessandro Zummo int err, atrim;
5731fec7c66SAlessandro Zummo
574015aefbbSAlessandro Zummo err = x1205_get_atrim(to_i2c_client(dev), &atrim);
575015aefbbSAlessandro Zummo if (err)
576015aefbbSAlessandro Zummo return err;
577015aefbbSAlessandro Zummo
578015aefbbSAlessandro Zummo return sprintf(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000);
5791fec7c66SAlessandro Zummo }
5801fec7c66SAlessandro Zummo static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL);
5811fec7c66SAlessandro Zummo
x1205_sysfs_show_dtrim(struct device * dev,struct device_attribute * attr,char * buf)5821fec7c66SAlessandro Zummo static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
5831fec7c66SAlessandro Zummo struct device_attribute *attr, char *buf)
5841fec7c66SAlessandro Zummo {
585015aefbbSAlessandro Zummo int err, dtrim;
5861fec7c66SAlessandro Zummo
587015aefbbSAlessandro Zummo err = x1205_get_dtrim(to_i2c_client(dev), &dtrim);
588015aefbbSAlessandro Zummo if (err)
589015aefbbSAlessandro Zummo return err;
590015aefbbSAlessandro Zummo
5911fec7c66SAlessandro Zummo return sprintf(buf, "%d ppm\n", dtrim);
5921fec7c66SAlessandro Zummo }
5931fec7c66SAlessandro Zummo static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
5941fec7c66SAlessandro Zummo
x1205_sysfs_register(struct device * dev)5954edac2b4SAlessandro Zummo static int x1205_sysfs_register(struct device *dev)
5961fec7c66SAlessandro Zummo {
5974edac2b4SAlessandro Zummo int err;
5984edac2b4SAlessandro Zummo
5994edac2b4SAlessandro Zummo err = device_create_file(dev, &dev_attr_atrim);
6004edac2b4SAlessandro Zummo if (err)
6014edac2b4SAlessandro Zummo return err;
6024edac2b4SAlessandro Zummo
6034edac2b4SAlessandro Zummo err = device_create_file(dev, &dev_attr_dtrim);
6044edac2b4SAlessandro Zummo if (err)
6054edac2b4SAlessandro Zummo device_remove_file(dev, &dev_attr_atrim);
6064edac2b4SAlessandro Zummo
6074edac2b4SAlessandro Zummo return err;
6081fec7c66SAlessandro Zummo }
6091fec7c66SAlessandro Zummo
x1205_sysfs_unregister(struct device * dev)6104edac2b4SAlessandro Zummo static void x1205_sysfs_unregister(struct device *dev)
6114edac2b4SAlessandro Zummo {
6124edac2b4SAlessandro Zummo device_remove_file(dev, &dev_attr_atrim);
6134edac2b4SAlessandro Zummo device_remove_file(dev, &dev_attr_dtrim);
6144edac2b4SAlessandro Zummo }
6154edac2b4SAlessandro Zummo
6164edac2b4SAlessandro Zummo
x1205_probe(struct i2c_client * client)6173f4a3322SStephen Kitt static int x1205_probe(struct i2c_client *client)
6181fec7c66SAlessandro Zummo {
6191fec7c66SAlessandro Zummo int err = 0;
6201fec7c66SAlessandro Zummo unsigned char sr;
6211fec7c66SAlessandro Zummo struct rtc_device *rtc;
6221fec7c66SAlessandro Zummo
6234edac2b4SAlessandro Zummo dev_dbg(&client->dev, "%s\n", __func__);
6241fec7c66SAlessandro Zummo
6254edac2b4SAlessandro Zummo if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
6264edac2b4SAlessandro Zummo return -ENODEV;
6271fec7c66SAlessandro Zummo
6284edac2b4SAlessandro Zummo if (x1205_validate_client(client) < 0)
6294edac2b4SAlessandro Zummo return -ENODEV;
6301fec7c66SAlessandro Zummo
63117581718SJingoo Han rtc = devm_rtc_device_register(&client->dev, x1205_driver.driver.name,
6321fec7c66SAlessandro Zummo &x1205_rtc_ops, THIS_MODULE);
6331fec7c66SAlessandro Zummo
6344edac2b4SAlessandro Zummo if (IS_ERR(rtc))
6354edac2b4SAlessandro Zummo return PTR_ERR(rtc);
6361fec7c66SAlessandro Zummo
6371fec7c66SAlessandro Zummo i2c_set_clientdata(client, rtc);
6381fec7c66SAlessandro Zummo
63925985edcSLucas De Marchi /* Check for power failures and eventually enable the osc */
64066e3f10cSSachin Kamat err = x1205_get_status(client, &sr);
64166e3f10cSSachin Kamat if (!err) {
6421fec7c66SAlessandro Zummo if (sr & X1205_SR_RTCF) {
6431fec7c66SAlessandro Zummo dev_err(&client->dev,
6441fec7c66SAlessandro Zummo "power failure detected, "
6451fec7c66SAlessandro Zummo "please set the clock\n");
6461fec7c66SAlessandro Zummo udelay(50);
6471fec7c66SAlessandro Zummo x1205_fix_osc(client);
6481fec7c66SAlessandro Zummo }
64966e3f10cSSachin Kamat } else {
6501fec7c66SAlessandro Zummo dev_err(&client->dev, "couldn't read status\n");
65166e3f10cSSachin Kamat }
6521fec7c66SAlessandro Zummo
6534edac2b4SAlessandro Zummo err = x1205_sysfs_register(&client->dev);
6544edac2b4SAlessandro Zummo if (err)
6554071ea25SAlessandro Zummo dev_err(&client->dev, "Unable to create sysfs entries\n");
6561fec7c66SAlessandro Zummo
6571fec7c66SAlessandro Zummo return 0;
6581fec7c66SAlessandro Zummo }
6591fec7c66SAlessandro Zummo
x1205_remove(struct i2c_client * client)660ed5c2f5fSUwe Kleine-König static void x1205_remove(struct i2c_client *client)
6611fec7c66SAlessandro Zummo {
6624edac2b4SAlessandro Zummo x1205_sysfs_unregister(&client->dev);
6631fec7c66SAlessandro Zummo }
6641fec7c66SAlessandro Zummo
6653760f736SJean Delvare static const struct i2c_device_id x1205_id[] = {
666*a47d377eSUwe Kleine-König { "x1205" },
6673760f736SJean Delvare { }
6683760f736SJean Delvare };
6693760f736SJean Delvare MODULE_DEVICE_TABLE(i2c, x1205_id);
6703760f736SJean Delvare
6716875404fSLinus Walleij static const struct of_device_id x1205_dt_ids[] = {
6726875404fSLinus Walleij { .compatible = "xircom,x1205", },
6736875404fSLinus Walleij {},
6746875404fSLinus Walleij };
6756875404fSLinus Walleij MODULE_DEVICE_TABLE(of, x1205_dt_ids);
6766875404fSLinus Walleij
6774edac2b4SAlessandro Zummo static struct i2c_driver x1205_driver = {
6784edac2b4SAlessandro Zummo .driver = {
6794edac2b4SAlessandro Zummo .name = "rtc-x1205",
6806875404fSLinus Walleij .of_match_table = x1205_dt_ids,
6814edac2b4SAlessandro Zummo },
68231b0cecbSUwe Kleine-König .probe = x1205_probe,
6834edac2b4SAlessandro Zummo .remove = x1205_remove,
6843760f736SJean Delvare .id_table = x1205_id,
6854edac2b4SAlessandro Zummo };
6864edac2b4SAlessandro Zummo
6870abc9201SAxel Lin module_i2c_driver(x1205_driver);
6881fec7c66SAlessandro Zummo
6891fec7c66SAlessandro Zummo MODULE_AUTHOR(
6901fec7c66SAlessandro Zummo "Karen Spearel <kas111 at gmail dot com>, "
6911fec7c66SAlessandro Zummo "Alessandro Zummo <a.zummo@towertech.it>");
6921fec7c66SAlessandro Zummo MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver");
6931fec7c66SAlessandro Zummo MODULE_LICENSE("GPL");
694