Commit d815461c authored by David Brownell's avatar David Brownell Committed by Linus Torvalds

rtc-rs5c372 becomes a new-style i2c driver

Convert rtc-rs5c372 to be a "new style" I2C driver, and update the
Kconfig text to be more complete..

Verified on an OMAP H4 development platform, along with a board
init patch to declare its rv5c387a device.

Only one defconfig -- powerpc/linkstation -- uses this driver; but
several other platforms use it, just without defconfig support.

Such platforms need to be converted so (a) their I2C adapter driver
supports new-style drivers, and (b) board init code declares this
I2C device.
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Cc: Voipio Riku <Riku.Voipio@movial.fi>
Acked-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: Martin Michlmayr <tbm@cyrius.com>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 045e0e85
...@@ -160,11 +160,11 @@ config RTC_DRV_MAX6900 ...@@ -160,11 +160,11 @@ config RTC_DRV_MAX6900
will be called rtc-max6900. will be called rtc-max6900.
config RTC_DRV_RS5C372 config RTC_DRV_RS5C372
tristate "Ricoh RS5C372A/B" tristate "Ricoh RS5C372A/B, RV5C386, RV5C387A"
depends on RTC_CLASS && I2C depends on RTC_CLASS && I2C
help help
If you say yes here you get support for the If you say yes here you get support for the
Ricoh RS5C372A and RS5C372B RTC chips. Ricoh RS5C372A, RS5C372B, RV5C386, and RV5C387A RTC chips.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-rs5c372. will be called rtc-rs5c372.
......
...@@ -13,13 +13,7 @@ ...@@ -13,13 +13,7 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#define DRV_VERSION "0.4" #define DRV_VERSION "0.5"
/* Addresses to scan */
static unsigned short normal_i2c[] = { /* 0x32,*/ I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD;
/* /*
...@@ -88,9 +82,6 @@ struct rs5c372 { ...@@ -88,9 +82,6 @@ struct rs5c372 {
unsigned has_irq:1; unsigned has_irq:1;
char buf[17]; char buf[17];
char *regs; char *regs;
/* on conversion to a "new style" i2c driver, this vanishes */
struct i2c_client dev;
}; };
static int rs5c_get_regs(struct rs5c372 *rs5c) static int rs5c_get_regs(struct rs5c372 *rs5c)
...@@ -483,25 +474,35 @@ static int rs5c_sysfs_register(struct device *dev) ...@@ -483,25 +474,35 @@ static int rs5c_sysfs_register(struct device *dev)
return err; 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 #else
static int rs5c_sysfs_register(struct device *dev) static int rs5c_sysfs_register(struct device *dev)
{ {
return 0; return 0;
} }
static void rs5c_sysfs_unregister(struct device *dev)
{
/* nothing */
}
#endif /* SYSFS */ #endif /* SYSFS */
static struct i2c_driver rs5c372_driver; 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)
{ {
int err = 0; int err = 0;
struct i2c_client *client;
struct rs5c372 *rs5c372; struct rs5c372 *rs5c372;
struct rtc_time tm; struct rtc_time tm;
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); dev_dbg(&client->dev, "%s\n", __FUNCTION__);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
err = -ENODEV; err = -ENODEV;
goto exit; goto exit;
} }
...@@ -514,35 +515,22 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) ...@@ -514,35 +515,22 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
/* we read registers 0x0f then 0x00-0x0f; skip the first one */ /* we read registers 0x0f then 0x00-0x0f; skip the first one */
rs5c372->regs=&rs5c372->buf[1]; 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; 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); i2c_set_clientdata(client, rs5c372);
/* Inform the i2c layer */
if ((err = i2c_attach_client(client)))
goto exit_kfree;
err = rs5c_get_regs(rs5c372); err = rs5c_get_regs(rs5c372);
if (err < 0) if (err < 0)
goto exit_detach; goto exit_kfree;
/* For "new style" drivers, irq is in i2c_client and chip type if (strcmp(client->name, "rs5c372a") == 0)
* info comes from i2c_client.dev.platform_data. Meanwhile: rs5c372->type = rtc_rs5c372a;
* else if (strcmp(client->name, "rs5c372b") == 0)
* STICK BOARD-SPECIFIC SETUP CODE RIGHT HERE rs5c372->type = rtc_rs5c372b;
*/ else if (strcmp(client->name, "rv5c386") == 0)
if (rs5c372->type == rtc_undef) { rs5c372->type = rtc_rv5c386;
else if (strcmp(client->name, "rv5c387a") == 0)
rs5c372->type = rtc_rv5c387a;
else {
rs5c372->type = rtc_rs5c372b; rs5c372->type = rtc_rs5c372b;
dev_warn(&client->dev, "assuming rs5c372b\n"); dev_warn(&client->dev, "assuming rs5c372b\n");
} }
...@@ -567,7 +555,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) ...@@ -567,7 +555,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
break; break;
default: default:
dev_err(&client->dev, "unknown RTC type\n"); 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 the oscillator lost power and no other software (like
...@@ -601,7 +589,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) ...@@ -601,7 +589,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
if ((i2c_master_send(client, buf, 3)) != 3) { if ((i2c_master_send(client, buf, 3)) != 3) {
dev_err(&client->dev, "setup error\n"); dev_err(&client->dev, "setup error\n");
goto exit_detach; goto exit_kfree;
} }
rs5c372->regs[RS5C_REG_CTRL1] = buf[1]; rs5c372->regs[RS5C_REG_CTRL1] = buf[1];
rs5c372->regs[RS5C_REG_CTRL2] = buf[2]; rs5c372->regs[RS5C_REG_CTRL2] = buf[2];
...@@ -621,14 +609,14 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) ...@@ -621,14 +609,14 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
rs5c372->time24 ? "24hr" : "am/pm" 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, rs5c372->rtc = rtc_device_register(rs5c372_driver.driver.name,
&client->dev, &rs5c372_rtc_ops, THIS_MODULE); &client->dev, &rs5c372_rtc_ops, THIS_MODULE);
if (IS_ERR(rs5c372->rtc)) { if (IS_ERR(rs5c372->rtc)) {
err = PTR_ERR(rs5c372->rtc); err = PTR_ERR(rs5c372->rtc);
goto exit_detach; goto exit_kfree;
} }
err = rs5c_sysfs_register(&client->dev); err = rs5c_sysfs_register(&client->dev);
...@@ -640,9 +628,6 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) ...@@ -640,9 +628,6 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
exit_devreg: exit_devreg:
rtc_device_unregister(rs5c372->rtc); rtc_device_unregister(rs5c372->rtc);
exit_detach:
i2c_detach_client(client);
exit_kfree: exit_kfree:
kfree(rs5c372); kfree(rs5c372);
...@@ -650,24 +635,12 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) ...@@ -650,24 +635,12 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
return err; 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); struct rs5c372 *rs5c372 = i2c_get_clientdata(client);
if (rs5c372->rtc) rtc_device_unregister(rs5c372->rtc);
rtc_device_unregister(rs5c372->rtc); rs5c_sysfs_unregister(&client->dev);
/* REVISIT properly destroy the sysfs files ... */
if ((err = i2c_detach_client(client)))
return err;
kfree(rs5c372); kfree(rs5c372);
return 0; return 0;
} }
...@@ -676,8 +649,8 @@ static struct i2c_driver rs5c372_driver = { ...@@ -676,8 +649,8 @@ static struct i2c_driver rs5c372_driver = {
.driver = { .driver = {
.name = "rtc-rs5c372", .name = "rtc-rs5c372",
}, },
.attach_adapter = &rs5c372_attach, .probe = rs5c372_probe,
.detach_client = &rs5c372_detach, .remove = rs5c372_remove,
}; };
static __init int rs5c372_init(void) static __init int rs5c372_init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment