in rtc-fm3130.c [343:515]
static int fm3130_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct fm3130 *fm3130;
int err = -ENODEV;
int tmp;
struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter,
I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return -EIO;
fm3130 = devm_kzalloc(&client->dev, sizeof(struct fm3130), GFP_KERNEL);
if (!fm3130)
return -ENOMEM;
fm3130->client = client;
i2c_set_clientdata(client, fm3130);
fm3130->reg_addr_time = FM3130_RTC_SECONDS;
fm3130->reg_addr_alarm = FM3130_ALARM_SECONDS;
/* Messages to read time */
fm3130->msg[0].addr = client->addr;
fm3130->msg[0].flags = 0;
fm3130->msg[0].len = 1;
fm3130->msg[0].buf = &fm3130->reg_addr_time;
fm3130->msg[1].addr = client->addr;
fm3130->msg[1].flags = I2C_M_RD;
fm3130->msg[1].len = FM3130_CLOCK_REGS;
fm3130->msg[1].buf = &fm3130->regs[FM3130_RTC_SECONDS];
/* Messages to read alarm */
fm3130->msg[2].addr = client->addr;
fm3130->msg[2].flags = 0;
fm3130->msg[2].len = 1;
fm3130->msg[2].buf = &fm3130->reg_addr_alarm;
fm3130->msg[3].addr = client->addr;
fm3130->msg[3].flags = I2C_M_RD;
fm3130->msg[3].len = FM3130_ALARM_REGS;
fm3130->msg[3].buf = &fm3130->regs[FM3130_ALARM_SECONDS];
fm3130->alarm_valid = 0;
fm3130->data_valid = 0;
tmp = i2c_transfer(adapter, fm3130->msg, 4);
if (tmp != 4) {
dev_dbg(&client->dev, "read error %d\n", tmp);
err = -EIO;
goto exit_free;
}
fm3130->regs[FM3130_RTC_CONTROL] =
i2c_smbus_read_byte_data(client, FM3130_RTC_CONTROL);
fm3130->regs[FM3130_CAL_CONTROL] =
i2c_smbus_read_byte_data(client, FM3130_CAL_CONTROL);
/* Disabling calibration mode */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_CAL) {
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_CAL));
dev_warn(&client->dev, "Disabling calibration mode!\n");
}
/* Disabling read and write modes */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_WRITE ||
fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_READ) {
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_READ |
FM3130_RTC_CONTROL_BIT_WRITE));
dev_warn(&client->dev, "Disabling READ or WRITE mode!\n");
}
/* oscillator off? turn it on, so clock can tick. */
if (fm3130->regs[FM3130_CAL_CONTROL] & FM3130_CAL_CONTROL_BIT_nOSCEN)
i2c_smbus_write_byte_data(client, FM3130_CAL_CONTROL,
fm3130->regs[FM3130_CAL_CONTROL] &
~(FM3130_CAL_CONTROL_BIT_nOSCEN));
/* low battery? clear flag, and warn */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_LB) {
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~(FM3130_RTC_CONTROL_BIT_LB));
dev_warn(&client->dev, "Low battery!\n");
}
/* check if Power On Reset bit is set */
if (fm3130->regs[FM3130_RTC_CONTROL] & FM3130_RTC_CONTROL_BIT_POR) {
i2c_smbus_write_byte_data(client, FM3130_RTC_CONTROL,
fm3130->regs[FM3130_RTC_CONTROL] &
~FM3130_RTC_CONTROL_BIT_POR);
dev_dbg(&client->dev, "POR bit is set\n");
}
/* ACS is controlled by alarm */
i2c_smbus_write_byte_data(client, FM3130_ALARM_WP_CONTROL, 0x80);
/* alarm registers sanity check */
tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
if (tmp > 59)
goto bad_alarm;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
if (tmp > 59)
goto bad_alarm;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
if (tmp > 23)
goto bad_alarm;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
if (tmp == 0 || tmp > 31)
goto bad_alarm;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
if (tmp == 0 || tmp > 12)
goto bad_alarm;
fm3130->alarm_valid = 1;
bad_alarm:
/* clock registers sanity chek */
tmp = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
if (tmp > 59)
goto bad_clock;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
if (tmp > 59)
goto bad_clock;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_HOURS] & 0x3f);
if (tmp > 23)
goto bad_clock;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x7);
if (tmp == 0 || tmp > 7)
goto bad_clock;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
if (tmp == 0 || tmp > 31)
goto bad_clock;
tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
if (tmp == 0 || tmp > 12)
goto bad_clock;
fm3130->data_valid = 1;
bad_clock:
if (!fm3130->data_valid || !fm3130->alarm_valid)
dev_dbg(&client->dev, "%s: %15ph\n", "bogus registers",
fm3130->regs);
/* We won't bail out here because we just got invalid data.
Time setting from u-boot doesn't work anyway */
fm3130->rtc = devm_rtc_device_register(&client->dev, client->name,
&fm3130_rtc_ops, THIS_MODULE);
if (IS_ERR(fm3130->rtc)) {
err = PTR_ERR(fm3130->rtc);
dev_err(&client->dev,
"unable to register the class device\n");
goto exit_free;
}
return 0;
exit_free:
return err;
}