X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Frtc%2Frtc-pcf8563.c;h=a41681d26eba80ae58df5b0090ae603fbab519fe;hb=affc23d11631a47d35dfd552ded8ca255c001490;hp=a760cf69af90de24bb80782fbdbf3a393d08777c;hpb=7ff3e52cf2947ebd38c84159af68e5a29d228f6c;p=linux-2.6 diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index a760cf69af..a41681d26e 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -18,17 +18,7 @@ #include #include -#define DRV_VERSION "0.4.2" - -/* Addresses to scan: none - * This chip cannot be reliably autodetected. An empty eeprom - * located at 0x51 will pass the validation routine due to - * the way the registers are implemented. - */ -static unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -/* Module parameters */ -I2C_CLIENT_INSMOD; +#define DRV_VERSION "0.4.3" #define PCF8563_REG_ST1 0x00 /* status */ #define PCF8563_REG_ST2 0x01 @@ -53,8 +43,26 @@ I2C_CLIENT_INSMOD; #define PCF8563_SC_LV 0x80 /* low voltage */ #define PCF8563_MO_C 0x80 /* century */ -static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind); -static int pcf8563_detach(struct i2c_client *client); +static struct i2c_driver pcf8563_driver; + +struct pcf8563 { + struct rtc_device *rtc; + /* + * The meaning of MO_C bit varies by the chip type. + * From PCF8563 datasheet: this bit is toggled when the years + * register overflows from 99 to 00 + * 0 indicates the century is 20xx + * 1 indicates the century is 19xx + * From RTC8564 datasheet: this bit indicates change of + * century. When the year digit data overflows from 99 to 00, + * this bit is set. By presetting it to 0 while still in the + * 20th century, it will be set in year 2000, ... + * There seems no reliable way to know how the system use this + * bit. So let's do it heuristically, assuming we are live in + * 1970...2069. + */ + int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ +}; /* * In the routines that deal directly with the pcf8563 hardware, we use @@ -62,6 +70,7 @@ static int pcf8563_detach(struct i2c_client *client); */ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) { + struct pcf8563 *pcf8563 = i2c_get_clientdata(client); unsigned char buf[13] = { PCF8563_REG_ST1 }; struct i2c_msg msgs[] = { @@ -71,7 +80,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) /* read registers */ if ((i2c_transfer(client->adapter, msgs, 2)) != 2) { - dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + dev_err(&client->dev, "%s: read error\n", __func__); return -EIO; } @@ -82,7 +91,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) dev_dbg(&client->dev, "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, " "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", - __FUNCTION__, + __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]); @@ -94,12 +103,16 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F); tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ - tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]) - + (buf[PCF8563_REG_MO] & PCF8563_MO_C ? 0 : 100); + tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]); + if (tm->tm_year < 70) + tm->tm_year += 100; /* assume we are in 1970...2069 */ + /* detect the polarity heuristically. see note above. */ + pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ? + (tm->tm_year >= 100) : (tm->tm_year < 100); 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); @@ -114,12 +127,13 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) { + struct pcf8563 *pcf8563 = i2c_get_clientdata(client); int i, err; unsigned char buf[9]; dev_dbg(&client->dev, "%s: 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); @@ -135,7 +149,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) /* year and century */ buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100); - if (tm->tm_year < 100) + if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100)) buf[PCF8563_REG_MO] |= PCF8563_MO_C; buf[PCF8563_REG_DW] = tm->tm_wday & 0x07; @@ -149,7 +163,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) if (err != sizeof(data)) { dev_err(&client->dev, "%s: err=%d addr=%02x, data=%02x\n", - __FUNCTION__, err, data[0], data[1]); + __func__, err, data[0], data[1]); return -EIO; } }; @@ -192,9 +206,9 @@ static int pcf8563_validate_client(struct i2c_client *client) xfer = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (xfer != ARRAY_SIZE(msgs)) { - dev_err(&client->adapter->dev, + dev_err(&client->dev, "%s: could not read register 0x%02X\n", - __FUNCTION__, pattern[i].reg); + __func__, pattern[i].reg); return -EIO; } @@ -203,10 +217,10 @@ static int pcf8563_validate_client(struct i2c_client *client) if (value > pattern[i].max || value < pattern[i].min) { - dev_dbg(&client->adapter->dev, + dev_dbg(&client->dev, "%s: pattern=%d, reg=%x, mask=0x%02x, min=%d, " "max=%d, value=%d, raw=0x%02X\n", - __FUNCTION__, i, pattern[i].reg, pattern[i].mask, + __func__, i, pattern[i].reg, pattern[i].mask, pattern[i].min, pattern[i].max, value, buf); @@ -232,97 +246,67 @@ static const struct rtc_class_ops pcf8563_rtc_ops = { .set_time = pcf8563_rtc_set_time, }; -static int pcf8563_attach(struct i2c_adapter *adapter) -{ - return i2c_probe(adapter, &addr_data, pcf8563_probe); -} - -static struct i2c_driver pcf8563_driver = { - .driver = { - .name = "pcf8563", - }, - .id = I2C_DRIVERID_PCF8563, - .attach_adapter = &pcf8563_attach, - .detach_client = &pcf8563_detach, -}; - -static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) +static int pcf8563_probe(struct i2c_client *client) { - struct i2c_client *client; - struct rtc_device *rtc; + struct pcf8563 *pcf8563; int err = 0; - dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); + dev_dbg(&client->dev, "%s\n", __func__); - 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; - } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; - client->addr = address; - client->driver = &pcf8563_driver; - client->adapter = adapter; - - strlcpy(client->name, pcf8563_driver.driver.name, I2C_NAME_SIZE); + pcf8563 = kzalloc(sizeof(struct pcf8563), GFP_KERNEL); + if (!pcf8563) + return -ENOMEM; /* Verify the chip is really an PCF8563 */ - if (kind < 0) { - if (pcf8563_validate_client(client) < 0) { - err = -ENODEV; - goto exit_kfree; - } - } - - /* Inform the i2c layer */ - if ((err = i2c_attach_client(client))) + if (pcf8563_validate_client(client) < 0) { + err = -ENODEV; goto exit_kfree; + } dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); - rtc = rtc_device_register(pcf8563_driver.driver.name, &client->dev, - &pcf8563_rtc_ops, THIS_MODULE); + pcf8563->rtc = rtc_device_register(pcf8563_driver.driver.name, + &client->dev, &pcf8563_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - err = PTR_ERR(rtc); - goto exit_detach; + if (IS_ERR(pcf8563->rtc)) { + err = PTR_ERR(pcf8563->rtc); + goto exit_kfree; } - i2c_set_clientdata(client, rtc); + i2c_set_clientdata(client, pcf8563); return 0; -exit_detach: - i2c_detach_client(client); - exit_kfree: - kfree(client); + kfree(pcf8563); -exit: return err; } -static int pcf8563_detach(struct i2c_client *client) +static int pcf8563_remove(struct i2c_client *client) { - int err; - struct rtc_device *rtc = i2c_get_clientdata(client); + struct pcf8563 *pcf8563 = i2c_get_clientdata(client); - if (rtc) - rtc_device_unregister(rtc); + if (pcf8563->rtc) + rtc_device_unregister(pcf8563->rtc); - if ((err = i2c_detach_client(client))) - return err; - - kfree(client); + kfree(pcf8563); return 0; } +static struct i2c_driver pcf8563_driver = { + .driver = { + .name = "rtc-pcf8563", + }, + .probe = pcf8563_probe, + .remove = pcf8563_remove, +}; + static int __init pcf8563_init(void) { return i2c_add_driver(&pcf8563_driver);