|
@@ -52,6 +52,7 @@ I2C_CLIENT_INSMOD;
|
|
/* RTC registers don't differ much, except for the century flag */
|
|
/* RTC registers don't differ much, except for the century flag */
|
|
#define DS1307_REG_SECS 0x00 /* 00-59 */
|
|
#define DS1307_REG_SECS 0x00 /* 00-59 */
|
|
# define DS1307_BIT_CH 0x80
|
|
# define DS1307_BIT_CH 0x80
|
|
|
|
+# define DS1340_BIT_nEOSC 0x80
|
|
#define DS1307_REG_MIN 0x01 /* 00-59 */
|
|
#define DS1307_REG_MIN 0x01 /* 00-59 */
|
|
#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */
|
|
#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */
|
|
# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */
|
|
# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */
|
|
@@ -68,7 +69,7 @@ I2C_CLIENT_INSMOD;
|
|
*/
|
|
*/
|
|
#define DS1307_REG_CONTROL 0x07 /* or ds1338 */
|
|
#define DS1307_REG_CONTROL 0x07 /* or ds1338 */
|
|
# define DS1307_BIT_OUT 0x80
|
|
# define DS1307_BIT_OUT 0x80
|
|
-# define DS1338_BIT_STOP 0x20
|
|
|
|
|
|
+# define DS1338_BIT_OSF 0x20
|
|
# define DS1307_BIT_SQWE 0x10
|
|
# define DS1307_BIT_SQWE 0x10
|
|
# define DS1307_BIT_RS1 0x02
|
|
# define DS1307_BIT_RS1 0x02
|
|
# define DS1307_BIT_RS0 0x01
|
|
# define DS1307_BIT_RS0 0x01
|
|
@@ -84,8 +85,8 @@ I2C_CLIENT_INSMOD;
|
|
# define DS1340_BIT_FT 0x40
|
|
# define DS1340_BIT_FT 0x40
|
|
# define DS1340_BIT_CALIB_SIGN 0x20
|
|
# define DS1340_BIT_CALIB_SIGN 0x20
|
|
# define DS1340_M_CALIBRATION 0x1f
|
|
# define DS1340_M_CALIBRATION 0x1f
|
|
-#define DS1338_REG_FLAG 0x09
|
|
|
|
-# define DS1338_BIT_OSF 0x80
|
|
|
|
|
|
+#define DS1340_REG_FLAG 0x09
|
|
|
|
+# define DS1340_BIT_OSF 0x80
|
|
#define DS1337_REG_STATUS 0x0f
|
|
#define DS1337_REG_STATUS 0x0f
|
|
# define DS1337_BIT_OSF 0x80
|
|
# define DS1337_BIT_OSF 0x80
|
|
# define DS1337_BIT_A2I 0x02
|
|
# define DS1337_BIT_A2I 0x02
|
|
@@ -215,11 +216,18 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
|
|
tmp = t->tm_year - 100;
|
|
tmp = t->tm_year - 100;
|
|
buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
|
|
buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
|
|
|
|
|
|
- if (ds1307->type == ds_1337)
|
|
|
|
|
|
+ switch (ds1307->type) {
|
|
|
|
+ case ds_1337:
|
|
|
|
+ case ds_1339:
|
|
buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
|
|
buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
|
|
- else if (ds1307->type == ds_1340)
|
|
|
|
|
|
+ break;
|
|
|
|
+ case ds_1340:
|
|
buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
|
|
buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
|
|
| DS1340_BIT_CENTURY;
|
|
| DS1340_BIT_CENTURY;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
ds1307->msg[1].flags = 0;
|
|
ds1307->msg[1].flags = 0;
|
|
ds1307->msg[1].len = 8;
|
|
ds1307->msg[1].len = 8;
|
|
@@ -296,11 +304,10 @@ ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
|
|
switch (ds1307->type) {
|
|
switch (ds1307->type) {
|
|
case ds_1337:
|
|
case ds_1337:
|
|
case ds_1339:
|
|
case ds_1339:
|
|
- ds1307->type = ds_1337;
|
|
|
|
-
|
|
|
|
ds1307->reg_addr = DS1337_REG_CONTROL;
|
|
ds1307->reg_addr = DS1337_REG_CONTROL;
|
|
ds1307->msg[1].len = 2;
|
|
ds1307->msg[1].len = 2;
|
|
|
|
|
|
|
|
+ /* get registers that the "rtc" read below won't read... */
|
|
tmp = i2c_transfer(adapter, ds1307->msg, 2);
|
|
tmp = i2c_transfer(adapter, ds1307->msg, 2);
|
|
if (tmp != 2) {
|
|
if (tmp != 2) {
|
|
pr_debug("read error %d\n", tmp);
|
|
pr_debug("read error %d\n", tmp);
|
|
@@ -311,13 +318,16 @@ ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
|
|
ds1307->reg_addr = 0;
|
|
ds1307->reg_addr = 0;
|
|
ds1307->msg[1].len = sizeof(ds1307->regs);
|
|
ds1307->msg[1].len = sizeof(ds1307->regs);
|
|
|
|
|
|
- /* oscillator is off; need to turn it on */
|
|
|
|
- if ((ds1307->regs[0] & DS1337_BIT_nEOSC)
|
|
|
|
- || (ds1307->regs[1] & DS1337_BIT_OSF)) {
|
|
|
|
-no_osc_start:
|
|
|
|
- printk(KERN_ERR "no %s oscillator code\n",
|
|
|
|
- chip->name);
|
|
|
|
- goto exit_free;
|
|
|
|
|
|
+ /* oscillator off? turn it on, so clock can tick. */
|
|
|
|
+ if (ds1307->regs[0] & DS1337_BIT_nEOSC)
|
|
|
|
+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL,
|
|
|
|
+ ds1307->regs[0] & ~DS1337_BIT_nEOSC);
|
|
|
|
+
|
|
|
|
+ /* oscillator fault? clear flag, and warn */
|
|
|
|
+ if (ds1307->regs[1] & DS1337_BIT_OSF) {
|
|
|
|
+ i2c_smbus_write_byte_data(client, DS1337_REG_STATUS,
|
|
|
|
+ ds1307->regs[1] & ~DS1337_BIT_OSF);
|
|
|
|
+ dev_warn(&client->dev, "SET TIME!\n");
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
@@ -340,20 +350,33 @@ read_rtc:
|
|
*/
|
|
*/
|
|
tmp = ds1307->regs[DS1307_REG_SECS];
|
|
tmp = ds1307->regs[DS1307_REG_SECS];
|
|
switch (ds1307->type) {
|
|
switch (ds1307->type) {
|
|
|
|
+ case ds_1340:
|
|
|
|
+ /* FIXME read register with DS1340_BIT_OSF, use that to
|
|
|
|
+ * trigger the "set time" warning (*after* restarting the
|
|
|
|
+ * oscillator!) instead of this weaker ds1307/m41t00 test.
|
|
|
|
+ */
|
|
case ds_1307:
|
|
case ds_1307:
|
|
- case ds_1338:
|
|
|
|
case m41t00:
|
|
case m41t00:
|
|
|
|
+ /* clock halted? turn it on, so clock can tick. */
|
|
if (tmp & DS1307_BIT_CH) {
|
|
if (tmp & DS1307_BIT_CH) {
|
|
- i2c_smbus_write_byte_data(client, 0, 0);
|
|
|
|
- dev_warn(&client->dev,
|
|
|
|
- "oscillator started; SET TIME!\n");
|
|
|
|
|
|
+ i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
|
|
|
|
+ dev_warn(&client->dev, "SET TIME!\n");
|
|
goto read_rtc;
|
|
goto read_rtc;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
- case ds_1340:
|
|
|
|
- /* FIXME write code to start the oscillator */
|
|
|
|
|
|
+ case ds_1338:
|
|
|
|
+ /* clock halted? turn it on, so clock can tick. */
|
|
if (tmp & DS1307_BIT_CH)
|
|
if (tmp & DS1307_BIT_CH)
|
|
- goto no_osc_start;
|
|
|
|
|
|
+ i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0);
|
|
|
|
+
|
|
|
|
+ /* oscillator fault? clear flag, and warn */
|
|
|
|
+ if (ds1307->regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
|
|
|
|
+ i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL,
|
|
|
|
+ ds1307->regs[DS1337_REG_CONTROL]
|
|
|
|
+ & ~DS1338_BIT_OSF);
|
|
|
|
+ dev_warn(&client->dev, "SET TIME!\n");
|
|
|
|
+ goto read_rtc;
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
@@ -380,6 +403,7 @@ read_rtc:
|
|
*
|
|
*
|
|
* REVISIT forcing 24 hour mode can prevent multi-master
|
|
* REVISIT forcing 24 hour mode can prevent multi-master
|
|
* configs from sharing this RTC ... don't do this.
|
|
* configs from sharing this RTC ... don't do this.
|
|
|
|
+ * The clock needs to be reset after changing it, too...
|
|
*/
|
|
*/
|
|
tmp = ds1307->regs[DS1307_REG_HOUR];
|
|
tmp = ds1307->regs[DS1307_REG_HOUR];
|
|
if (tmp & (1 << 6)) {
|
|
if (tmp & (1 << 6)) {
|