#include <linux/rtc.h>
#include <linux/bcd.h>
-#define DRV_VERSION "0.4"
-
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
-
-/* Insmod parameters */
-I2C_CLIENT_INSMOD;
+#define DRV_VERSION "0.5"
/*
rtc_rv5c387a,
};
+static const struct i2c_device_id rs5c372_id[] = {
+ { "rs5c372a", rtc_rs5c372a },
+ { "rs5c372b", rtc_rs5c372b },
+ { "rv5c386", rtc_rv5c386 },
+ { "rv5c387a", rtc_rv5c387a },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rs5c372_id);
+
/* REVISIT: this assumes that:
* - we're in the 21st century, so it's safe to ignore the century
* bit for rv5c38[67] (REG_MONTH bit 7);
unsigned has_irq:1;
char buf[17];
char *regs;
-
- /* on conversion to a "new style" i2c driver, this vanishes */
- struct i2c_client dev;
};
static int rs5c_get_regs(struct rs5c372 *rs5c)
* least 80219 chips; this works around that bug.
*/
if ((i2c_transfer(client->adapter, msgs, 1)) != 1) {
- pr_debug("%s: can't read registers\n", rs5c->rtc->name);
+ dev_warn(&client->dev, "can't read registers\n");
return -EIO;
}
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);
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);
buf[7] = BIN2BCD(tm->tm_year - 100);
if ((i2c_master_send(client, buf, 8)) != 8) {
- dev_err(&client->dev, "%s: write error\n", __FUNCTION__);
+ dev_err(&client->dev, "%s: write error\n", __func__);
return -EIO;
}
*osc = (tmp & RS5C372_TRIM_XSL) ? 32000 : 32768;
if (trim) {
- dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, tmp);
+ dev_dbg(&client->dev, "%s: raw trim=%x\n", __func__, tmp);
tmp &= RS5C372_TRIM_MASK;
if (tmp & 0x3e) {
int t = tmp & 0x3f;
return err;
}
+static void rs5c_sysfs_unregister(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_trim);
+ device_remove_file(dev, &dev_attr_osc);
+}
+
#else
static int rs5c_sysfs_register(struct device *dev)
{
return 0;
}
+
+static void rs5c_sysfs_unregister(struct device *dev)
+{
+ /* nothing */
+}
#endif /* SYSFS */
static struct i2c_driver rs5c372_driver;
-static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
+static int rs5c372_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int err = 0;
- struct i2c_client *client;
struct rs5c372 *rs5c372;
struct rtc_time tm;
- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+ dev_dbg(&client->dev, "%s\n", __func__);
- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV;
goto exit;
}
goto exit;
}
- /* we read registers 0x0f then 0x00-0x0f; skip the first one */
- rs5c372->regs=&rs5c372->buf[1];
-
- /* On conversion to a "new style" i2c driver, we'll be handed
- * the i2c_client (we won't create it)
- */
- client = &rs5c372->dev;
rs5c372->client = client;
-
- /* I2C client */
- client->addr = address;
- client->driver = &rs5c372_driver;
- client->adapter = adapter;
-
- strlcpy(client->name, rs5c372_driver.driver.name, I2C_NAME_SIZE);
-
i2c_set_clientdata(client, rs5c372);
+ rs5c372->type = id->driver_data;
- /* Inform the i2c layer */
- if ((err = i2c_attach_client(client)))
- goto exit_kfree;
+ /* we read registers 0x0f then 0x00-0x0f; skip the first one */
+ rs5c372->regs = &rs5c372->buf[1];
err = rs5c_get_regs(rs5c372);
if (err < 0)
- goto exit_detach;
-
- /* For "new style" drivers, irq is in i2c_client and chip type
- * info comes from i2c_client.dev.platform_data. Meanwhile:
- *
- * STICK BOARD-SPECIFIC SETUP CODE RIGHT HERE
- */
- if (rs5c372->type == rtc_undef) {
- rs5c372->type = rtc_rs5c372b;
- dev_warn(&client->dev, "assuming rs5c372b\n");
- }
+ goto exit_kfree;
/* clock may be set for am/pm or 24 hr time */
switch (rs5c372->type) {
break;
default:
dev_err(&client->dev, "unknown RTC type\n");
- goto exit_detach;
+ goto exit_kfree;
}
/* if the oscillator lost power and no other software (like
if ((i2c_master_send(client, buf, 3)) != 3) {
dev_err(&client->dev, "setup error\n");
- goto exit_detach;
+ goto exit_kfree;
}
rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
rs5c372->time24 ? "24hr" : "am/pm"
);
- /* FIXME when client->irq exists, use it to register alarm irq */
+ /* REVISIT use client->irq to register alarm irq ... */
rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name,
&client->dev, &rs5c372_rtc_ops, THIS_MODULE);
if (IS_ERR(rs5c372->rtc)) {
err = PTR_ERR(rs5c372->rtc);
- goto exit_detach;
+ goto exit_kfree;
}
err = rs5c_sysfs_register(&client->dev);
exit_devreg:
rtc_device_unregister(rs5c372->rtc);
-exit_detach:
- i2c_detach_client(client);
-
exit_kfree:
kfree(rs5c372);
return err;
}
-static int rs5c372_attach(struct i2c_adapter *adapter)
+static int rs5c372_remove(struct i2c_client *client)
{
- return i2c_probe(adapter, &addr_data, rs5c372_probe);
-}
-
-static int rs5c372_detach(struct i2c_client *client)
-{
- int err;
struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
- if (rs5c372->rtc)
- rtc_device_unregister(rs5c372->rtc);
-
- /* REVISIT properly destroy the sysfs files ... */
-
- if ((err = i2c_detach_client(client)))
- return err;
-
+ rtc_device_unregister(rs5c372->rtc);
+ rs5c_sysfs_unregister(&client->dev);
kfree(rs5c372);
return 0;
}
.driver = {
.name = "rtc-rs5c372",
},
- .attach_adapter = &rs5c372_attach,
- .detach_client = &rs5c372_detach,
+ .probe = rs5c372_probe,
+ .remove = rs5c372_remove,
+ .id_table = rs5c372_id,
};
static __init int rs5c372_init(void)