aboutsummaryrefslogtreecommitdiff
path: root/drivers/rtc/rtc-x1205.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-x1205.c')
-rw-r--r--drivers/rtc/rtc-x1205.c471
1 files changed, 271 insertions, 200 deletions
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c
index b3fae357ca4..b1de58e0b3d 100644
--- a/drivers/rtc/rtc-x1205.c
+++ b/drivers/rtc/rtc-x1205.c
@@ -4,7 +4,7 @@
* Copyright 2005 Alessandro Zummo
*
* please send all reports to:
- * Karen Spearel <kas111 at gmail dot com>
+ * Karen Spearel <kas111 at gmail dot com>
* Alessandro Zummo <a.zummo@towertech.it>
*
* based on a lot of other RTC drivers.
@@ -21,21 +21,9 @@
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/delay.h>
+#include <linux/module.h>
-#define DRV_VERSION "1.0.7"
-
-/* Addresses to scan: none. This chip is located at
- * 0x6f and uses a two bytes register addressing.
- * Two bytes need to be written to read a single register,
- * while most other chips just require one and take the second
- * one as the data to be written. To prevent corrupting
- * unknown chips, the user must explicitly set the probe parameter.
- */
-
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD;
+#define DRV_VERSION "1.0.8"
/* offsets into CCR area */
@@ -84,6 +72,7 @@ I2C_CLIENT_INSMOD;
#define X1205_SR_RTCF 0x01 /* Clock failure */
#define X1205_SR_WEL 0x02 /* Write Enable Latch */
#define X1205_SR_RWEL 0x04 /* Register Write Enable */
+#define X1205_SR_AL0 0x20 /* Alarm 0 match */
#define X1205_DTR_DTR0 0x01
#define X1205_DTR_DTR1 0x02
@@ -91,19 +80,9 @@ I2C_CLIENT_INSMOD;
#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */
-/* Prototypes */
-static int x1205_attach(struct i2c_adapter *adapter);
-static int x1205_detach(struct i2c_client *client);
-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind);
+#define X1205_INT_AL0E 0x20 /* Alarm 0 enable */
-static struct i2c_driver x1205_driver = {
- .driver = {
- .name = "x1205",
- },
- .id = I2C_DRIVERID_X1205,
- .attach_adapter = &x1205_attach,
- .detach_client = &x1205_detach,
-};
+static struct i2c_driver x1205_driver;
/*
* In the routines that deal directly with the x1205 hardware, we use
@@ -114,39 +93,53 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
unsigned char reg_base)
{
unsigned char dt_addr[2] = { 0, reg_base };
-
unsigned char buf[8];
+ int i;
struct i2c_msg msgs[] = {
- { client->addr, 0, 2, dt_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 8, buf }, /* read date */
+ {/* setup read ptr */
+ .addr = client->addr,
+ .len = 2,
+ .buf = dt_addr
+ },
+ {/* read date */
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 8,
+ .buf = buf
+ },
};
/* read date registers */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
dev_dbg(&client->dev,
"%s: raw read data - sec=%02x, min=%02x, hr=%02x, "
"mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n",
- __FUNCTION__,
+ __func__,
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7]);
- tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
- tm->tm_min = BCD2BIN(buf[CCR_MIN]);
- tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
- tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
- tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
- tm->tm_year = BCD2BIN(buf[CCR_YEAR])
- + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900;
+ /* Mask out the enable bits if these are alarm registers */
+ if (reg_base < X1205_CCR_BASE)
+ for (i = 0; i <= 4; i++)
+ buf[i] &= 0x7F;
+
+ tm->tm_sec = bcd2bin(buf[CCR_SEC]);
+ tm->tm_min = bcd2bin(buf[CCR_MIN]);
+ tm->tm_hour = bcd2bin(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
+ tm->tm_mday = bcd2bin(buf[CCR_MDAY]);
+ tm->tm_mon = bcd2bin(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
+ tm->tm_year = bcd2bin(buf[CCR_YEAR])
+ + (bcd2bin(buf[CCR_Y2K]) * 100) - 1900;
tm->tm_wday = buf[CCR_WDAY];
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
- __FUNCTION__,
+ __func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
@@ -158,13 +151,22 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
struct i2c_msg msgs[] = {
- { client->addr, 0, 2, sr_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, sr }, /* read status */
+ { /* setup read ptr */
+ .addr = client->addr,
+ .len = 2,
+ .buf = sr_addr
+ },
+ { /* read status */
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = sr
+ },
};
/* read status register */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
@@ -172,10 +174,11 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
}
static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
- int datetoo, u8 reg_base)
+ u8 reg_base, unsigned char alm_enable)
{
int i, xfer;
- unsigned char buf[8];
+ unsigned char rdata[10] = { 0, reg_base };
+ unsigned char *buf = rdata + 2;
static const unsigned char wel[3] = { 0, X1205_REG_SR,
X1205_SR_WEL };
@@ -186,62 +189,91 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
dev_dbg(&client->dev,
- "%s: secs=%d, mins=%d, hours=%d\n",
- __FUNCTION__,
- tm->tm_sec, tm->tm_min, tm->tm_hour);
+ "%s: sec=%d min=%d hour=%d mday=%d mon=%d year=%d wday=%d\n",
+ __func__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday,
+ tm->tm_mon, tm->tm_year, tm->tm_wday);
- buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
- buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+ buf[CCR_SEC] = bin2bcd(tm->tm_sec);
+ buf[CCR_MIN] = bin2bcd(tm->tm_min);
/* set hour and 24hr bit */
- buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
+ buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL;
- /* should we also set the date? */
- if (datetoo) {
- dev_dbg(&client->dev,
- "%s: mday=%d, mon=%d, year=%d, wday=%d\n",
- __FUNCTION__,
- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+ buf[CCR_MDAY] = bin2bcd(tm->tm_mday);
- buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+ /* month, 1 - 12 */
+ buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1);
- /* month, 1 - 12 */
- buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1);
+ /* year, since the rtc epoch*/
+ buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
+ buf[CCR_WDAY] = tm->tm_wday & 0x07;
+ buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100);
- /* year, since the rtc epoch*/
- buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100);
- buf[CCR_WDAY] = tm->tm_wday & 0x07;
- buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
- }
+ /* If writing alarm registers, set compare bits on registers 0-4 */
+ if (reg_base < X1205_CCR_BASE)
+ for (i = 0; i <= 4; i++)
+ buf[i] |= 0x80;
/* this sequence is required to unlock the chip */
- if ((xfer = i2c_master_send(client, wel, 3)) != 3) {
- dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer);
+ xfer = i2c_master_send(client, wel, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer);
return -EIO;
}
- if ((xfer = i2c_master_send(client, rwel, 3)) != 3) {
- dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer);
+ xfer = i2c_master_send(client, rwel, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: rwel - %d\n", __func__, xfer);
return -EIO;
}
- /* write register's data */
- for (i = 0; i < (datetoo ? 8 : 3); i++) {
- unsigned char rdata[3] = { 0, reg_base + i, buf[i] };
+ xfer = i2c_master_send(client, rdata, sizeof(rdata));
+ if (xfer != sizeof(rdata)) {
+ dev_err(&client->dev,
+ "%s: result=%d addr=%02x, data=%02x\n",
+ __func__,
+ xfer, rdata[1], rdata[2]);
+ return -EIO;
+ }
+
+ /* If we wrote to the nonvolatile region, wait 10msec for write cycle*/
+ if (reg_base < X1205_CCR_BASE) {
+ unsigned char al0e[3] = { 0, X1205_REG_INT, 0 };
+
+ msleep(10);
+
+ /* ...and set or clear the AL0E bit in the INT register */
- xfer = i2c_master_send(client, rdata, 3);
+ /* Need to set RWEL again as the write has cleared it */
+ xfer = i2c_master_send(client, rwel, 3);
if (xfer != 3) {
dev_err(&client->dev,
- "%s: xfer=%d addr=%02x, data=%02x\n",
- __FUNCTION__,
- xfer, rdata[1], rdata[2]);
+ "%s: aloe rwel - %d\n",
+ __func__,
+ xfer);
return -EIO;
}
- };
+
+ if (alm_enable)
+ al0e[2] = X1205_INT_AL0E;
+
+ xfer = i2c_master_send(client, al0e, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev,
+ "%s: al0e - %d\n",
+ __func__,
+ xfer);
+ return -EIO;
+ }
+
+ /* and wait 10msec again for this write to complete */
+ msleep(10);
+ }
/* disable further writes */
- if ((xfer = i2c_master_send(client, diswe, 3)) != 3) {
- dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer);
+ xfer = i2c_master_send(client, diswe, 3);
+ if (xfer != 3) {
+ dev_err(&client->dev, "%s: diswe - %d\n", __func__, xfer);
return -EIO;
}
@@ -253,11 +285,11 @@ static int x1205_fix_osc(struct i2c_client *client)
int err;
struct rtc_time tm;
- tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+ memset(&tm, 0, sizeof(tm));
- if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0)
- dev_err(&client->dev,
- "unable to restart the oscillator\n");
+ err = x1205_set_datetime(client, &tm, X1205_CCR_BASE, 0);
+ if (err < 0)
+ dev_err(&client->dev, "unable to restart the oscillator\n");
return err;
}
@@ -268,17 +300,26 @@ static int x1205_get_dtrim(struct i2c_client *client, int *trim)
static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR };
struct i2c_msg msgs[] = {
- { client->addr, 0, 2, dtr_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */
+ { /* setup read ptr */
+ .addr = client->addr,
+ .len = 2,
+ .buf = dtr_addr
+ },
+ { /* read dtr */
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &dtr
+ },
};
/* read dtr register */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
- dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr);
+ dev_dbg(&client->dev, "%s: raw dtr=%x\n", __func__, dtr);
*trim = 0;
@@ -300,17 +341,26 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
static unsigned char atr_addr[2] = { 0, X1205_REG_ATR };
struct i2c_msg msgs[] = {
- { client->addr, 0, 2, atr_addr }, /* setup read ptr */
- { client->addr, I2C_M_RD, 1, &atr }, /* read atr */
+ {/* setup read ptr */
+ .addr = client->addr,
+ .len = 2,
+ .buf = atr_addr
+ },
+ {/* read atr */
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &atr
+ },
};
/* read atr register */
- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
}
- dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr);
+ dev_dbg(&client->dev, "%s: raw atr=%x\n", __func__, atr);
/* atr is a two's complement value on 6 bits,
* perform sign extension. The formula is
@@ -319,17 +369,16 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim)
if (atr & 0x20)
atr |= 0xC0;
- dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr);
+ dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __func__, atr, atr);
*trim = (atr * 250) + 11000;
- dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim);
+ dev_dbg(&client->dev, "%s: real=%d\n", __func__, *trim);
return 0;
}
-struct x1205_limit
-{
+struct x1205_limit {
unsigned char reg, mask, min, max;
};
@@ -370,14 +419,24 @@ static int x1205_validate_client(struct i2c_client *client)
unsigned char addr[2] = { 0, probe_zero_pattern[i] };
struct i2c_msg msgs[2] = {
- { client->addr, 0, 2, addr },
- { client->addr, I2C_M_RD, 1, &buf },
+ {
+ .addr = client->addr,
+ .len = 2,
+ .buf = addr
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &buf
+ },
};
- if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ xfer = i2c_transfer(client->adapter, msgs, 2);
+ if (xfer != 2) {
dev_err(&client->dev,
"%s: could not read register %x\n",
- __FUNCTION__, probe_zero_pattern[i]);
+ __func__, probe_zero_pattern[i]);
return -EIO;
}
@@ -385,7 +444,7 @@ static int x1205_validate_client(struct i2c_client *client)
if ((buf & probe_zero_pattern[i+1]) != 0) {
dev_err(&client->dev,
"%s: register=%02x, zero pattern=%d, value=%x\n",
- __FUNCTION__, probe_zero_pattern[i], i, buf);
+ __func__, probe_zero_pattern[i], i, buf);
return -ENODEV;
}
@@ -398,25 +457,35 @@ static int x1205_validate_client(struct i2c_client *client)
unsigned char addr[2] = { 0, probe_limits_pattern[i].reg };
struct i2c_msg msgs[2] = {
- { client->addr, 0, 2, addr },
- { client->addr, I2C_M_RD, 1, &reg },
+ {
+ .addr = client->addr,
+ .len = 2,
+ .buf = addr
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &reg
+ },
};
- if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) {
+ xfer = i2c_transfer(client->adapter, msgs, 2);
+ if (xfer != 2) {
dev_err(&client->dev,
"%s: could not read register %x\n",
- __FUNCTION__, probe_limits_pattern[i].reg);
+ __func__, probe_limits_pattern[i].reg);
return -EIO;
}
- value = BCD2BIN(reg & probe_limits_pattern[i].mask);
+ value = bcd2bin(reg & probe_limits_pattern[i].mask);
if (value > probe_limits_pattern[i].max ||
value < probe_limits_pattern[i].min) {
dev_dbg(&client->dev,
"%s: register=%x, lim pattern=%d, value=%d\n",
- __FUNCTION__, probe_limits_pattern[i].reg,
+ __func__, probe_limits_pattern[i].reg,
i, value);
return -ENODEV;
@@ -428,14 +497,43 @@ static int x1205_validate_client(struct i2c_client *client)
static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- return x1205_get_datetime(to_i2c_client(dev),
- &alrm->time, X1205_ALM0_BASE);
+ int err;
+ unsigned char intreg, status;
+ static unsigned char int_addr[2] = { 0, X1205_REG_INT };
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_msg msgs[] = {
+ { /* setup read ptr */
+ .addr = client->addr,
+ .len = 2,
+ .buf = int_addr
+ },
+ {/* read INT register */
+
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = &intreg
+ },
+ };
+
+ /* read interrupt register and status register */
+ if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __func__);
+ return -EIO;
+ }
+ err = x1205_get_status(client, &status);
+ if (err == 0) {
+ alrm->pending = (status & X1205_SR_AL0) ? 1 : 0;
+ alrm->enabled = (intreg & X1205_INT_AL0E) ? 1 : 0;
+ err = x1205_get_datetime(client, &alrm->time, X1205_ALM0_BASE);
+ }
+ return err;
}
static int x1205_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
return x1205_set_datetime(to_i2c_client(dev),
- &alrm->time, 1, X1205_ALM0_BASE);
+ &alrm->time, X1205_ALM0_BASE, alrm->enabled);
}
static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -447,17 +545,19 @@ static int x1205_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int x1205_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return x1205_set_datetime(to_i2c_client(dev),
- tm, 1, X1205_CCR_BASE);
+ tm, X1205_CCR_BASE, 0);
}
static int x1205_rtc_proc(struct device *dev, struct seq_file *seq)
{
int err, dtrim, atrim;
- if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0)
+ err = x1205_get_dtrim(to_i2c_client(dev), &dtrim);
+ if (!err)
seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim);
- if ((err = x1205_get_atrim(to_i2c_client(dev), &atrim)) == 0)
+ err = x1205_get_atrim(to_i2c_client(dev), &atrim);
+ if (!err)
seq_printf(seq, "analog_trim\t: %d.%02d pF\n",
atrim / 1000, atrim % 1000);
return 0;
@@ -497,63 +597,56 @@ static ssize_t x1205_sysfs_show_dtrim(struct device *dev,
}
static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL);
-static int x1205_attach(struct i2c_adapter *adapter)
+static int x1205_sysfs_register(struct device *dev)
+{
+ int err;
+
+ err = device_create_file(dev, &dev_attr_atrim);
+ if (err)
+ return err;
+
+ err = device_create_file(dev, &dev_attr_dtrim);
+ if (err)
+ device_remove_file(dev, &dev_attr_atrim);
+
+ return err;
+}
+
+static void x1205_sysfs_unregister(struct device *dev)
{
- return i2c_probe(adapter, &addr_data, x1205_probe);
+ device_remove_file(dev, &dev_attr_atrim);
+ device_remove_file(dev, &dev_attr_dtrim);
}
-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+
+static int x1205_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int err = 0;
unsigned char sr;
- struct i2c_client *client;
struct rtc_device *rtc;
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
- err = -ENODEV;
- goto exit;
- }
-
- if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
-
- /* I2C client */
- client->addr = address;
- client->driver = &x1205_driver;
- client->adapter = adapter;
-
- strlcpy(client->name, x1205_driver.driver.name, I2C_NAME_SIZE);
+ dev_dbg(&client->dev, "%s\n", __func__);
- /* Verify the chip is really an X1205 */
- if (kind < 0) {
- if (x1205_validate_client(client) < 0) {
- err = -ENODEV;
- goto exit_kfree;
- }
- }
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
- /* Inform the i2c layer */
- if ((err = i2c_attach_client(client)))
- goto exit_kfree;
+ if (x1205_validate_client(client) < 0)
+ return -ENODEV;
dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
- rtc = rtc_device_register(x1205_driver.driver.name, &client->dev,
- &x1205_rtc_ops, THIS_MODULE);
+ rtc = devm_rtc_device_register(&client->dev, x1205_driver.driver.name,
+ &x1205_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
- err = PTR_ERR(rtc);
- goto exit_detach;
- }
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
i2c_set_clientdata(client, rtc);
- /* Check for power failures and eventualy enable the osc */
- if ((err = x1205_get_status(client, &sr)) == 0) {
+ /* Check for power failures and eventually enable the osc */
+ err = x1205_get_status(client, &sr);
+ if (!err) {
if (sr & X1205_SR_RTCF) {
dev_err(&client->dev,
"power failure detected, "
@@ -561,58 +654,39 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
udelay(50);
x1205_fix_osc(client);
}
- }
- else
+ } else {
dev_err(&client->dev, "couldn't read status\n");
+ }
- err = device_create_file(&client->dev, &dev_attr_atrim);
- if (err) goto exit_devreg;
- err = device_create_file(&client->dev, &dev_attr_dtrim);
- if (err) goto exit_atrim;
+ err = x1205_sysfs_register(&client->dev);
+ if (err)
+ dev_err(&client->dev, "Unable to create sysfs entries\n");
return 0;
-
-exit_atrim:
- device_remove_file(&client->dev, &dev_attr_atrim);
-
-exit_devreg:
- rtc_device_unregister(rtc);
-
-exit_detach:
- i2c_detach_client(client);
-
-exit_kfree:
- kfree(client);
-
-exit:
- return err;
}
-static int x1205_detach(struct i2c_client *client)
+static int x1205_remove(struct i2c_client *client)
{
- int err;
- struct rtc_device *rtc = i2c_get_clientdata(client);
-
- if (rtc)
- rtc_device_unregister(rtc);
-
- if ((err = i2c_detach_client(client)))
- return err;
-
- kfree(client);
-
+ x1205_sysfs_unregister(&client->dev);
return 0;
}
-static int __init x1205_init(void)
-{
- return i2c_add_driver(&x1205_driver);
-}
+static const struct i2c_device_id x1205_id[] = {
+ { "x1205", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, x1205_id);
-static void __exit x1205_exit(void)
-{
- i2c_del_driver(&x1205_driver);
-}
+static struct i2c_driver x1205_driver = {
+ .driver = {
+ .name = "rtc-x1205",
+ },
+ .probe = x1205_probe,
+ .remove = x1205_remove,
+ .id_table = x1205_id,
+};
+
+module_i2c_driver(x1205_driver);
MODULE_AUTHOR(
"Karen Spearel <kas111 at gmail dot com>, "
@@ -620,6 +694,3 @@ MODULE_AUTHOR(
MODULE_DESCRIPTION("Xicor/Intersil X1205 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-
-module_init(x1205_init);
-module_exit(x1205_exit);