static int pcf8523_rtc_check_oscillator(struct i2c_client *client) { u8 value; int err; err = pcf8523_read(client, REG_SECONDS, &value); if (err < 0) return err; if (value & REG_SECONDS_OS) { /* * If the oscillator was stopped, try to clear the flag. Upon * power-up the flag is always set, but if we cannot clear it * the oscillator isn't running properly for some reason. The * sensible thing therefore is to return an error, signalling * that the clock cannot be assumed to be correct. */ value &= ~REG_SECONDS_OS; err = pcf8523_write(client, REG_SECONDS, value); if (err < 0) return err; err = pcf8523_read(client, REG_SECONDS, &value); if (err < 0) return err; if (value & REG_SECONDS_OS) return -EAGAIN; } return 0; }
static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); u8 start = REG_SECONDS, regs[7]; struct i2c_msg msgs[2]; int err; msgs[0].addr = client->addr; msgs[0].flags = 0; msgs[0].len = 1; msgs[0].buf = &start; msgs[1].addr = client->addr; msgs[1].flags = I2C_M_RD; msgs[1].len = sizeof(regs); msgs[1].buf = regs; err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); if (err < 0) return err; if (regs[0] & REG_SECONDS_OS) { /* * If the oscillator was stopped, try to clear the flag. Upon * power-up the flag is always set, but if we cannot clear it * the oscillator isn't running properly for some reason. The * sensible thing therefore is to return an error, signalling * that the clock cannot be assumed to be correct. */ regs[0] &= ~REG_SECONDS_OS; err = pcf8523_write(client, REG_SECONDS, regs[0]); if (err < 0) return err; err = pcf8523_read(client, REG_SECONDS, ®s[0]); if (err < 0) return err; if (regs[0] & REG_SECONDS_OS) return -EAGAIN; } tm->tm_sec = bcd2bin(regs[0] & 0x7f); tm->tm_min = bcd2bin(regs[1] & 0x7f); tm->tm_hour = bcd2bin(regs[2] & 0x3f); tm->tm_mday = bcd2bin(regs[3] & 0x3f); tm->tm_wday = regs[4] & 0x7; tm->tm_mon = bcd2bin(regs[5] & 0x1f); tm->tm_year = bcd2bin(regs[6]) + 100; return rtc_valid_tm(tm); }
static int pcf8523_switch_capacitance(struct i2c_client *client) { u8 value; int err; err = pcf8523_read(client, REG_CONTROL1, &value); if (err < 0) goto out; value ^= REG_CONTROL1_CAP_SEL; err = pcf8523_write(client, REG_CONTROL1, value); out: return err; }
static int pcf8523_start_rtc(struct i2c_client *client) { u8 value; int err; err = pcf8523_read(client, REG_CONTROL1, &value); if (err < 0) return err; value &= ~REG_CONTROL1_STOP; err = pcf8523_write(client, REG_CONTROL1, value); if (err < 0) return err; return 0; }
static int pcf8523_set_pm(struct i2c_client *client, u8 pm) { u8 value; int err; err = pcf8523_read(client, REG_CONTROL3, &value); if (err < 0) return err; value = (value & ~REG_CONTROL3_PM_MASK) | pm; err = pcf8523_write(client, REG_CONTROL3, value); if (err < 0) return err; return 0; }
static int pcf8523_select_capacitance(struct i2c_client *client, bool high) { u8 value; int err; err = pcf8523_read(client, REG_CONTROL1, &value); if (err < 0) return err; if (!high) value &= ~REG_CONTROL1_CAP_SEL; else value |= REG_CONTROL1_CAP_SEL; err = pcf8523_write(client, REG_CONTROL1, value); if (err < 0) return err; return err; }
static int pcf8523_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct pcf8523 *pcf; u8 value; int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL); if (!pcf) return -ENOMEM; /* Check whether the RTC reports battery low */ err = pcf8523_read(client, REG_CONTROL3, &value); if (err < 0) return err; if (value & REG_CONTROL3_BLF) dev_warn(&client->dev, "RTC reports battery is low\n"); err = pcf8523_enable_oscillator(client); if (err < 0) { dev_warn(&client->dev, "RTC reports oscillator is not running\n"); return err; } err = pcf8523_set_pm(client, 0); if (err < 0) return err; pcf->rtc = devm_rtc_device_register(&client->dev, DRIVER_NAME, &pcf8523_rtc_ops, THIS_MODULE); if (IS_ERR(pcf->rtc)) return PTR_ERR(pcf->rtc); i2c_set_clientdata(client, pcf); return 0; }
static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct i2c_client *client = to_i2c_client(dev); u8 value; int ret = 0, err; switch (cmd) { case RTC_VL_READ: err = pcf8523_read(client, REG_CONTROL3, &value); if (err < 0) return err; if (value & REG_CONTROL3_BLF) ret = 1; if (copy_to_user((void __user *)arg, &ret, sizeof(int))) return -EFAULT; return 0; default: return -ENOIOCTLCMD; } }