/** * rx6110_rtc_tm_to_data - convert rtc_time to native time encoding * * @tm: holds date and time * @data: holds the encoding in rx6110 native form
*/ staticint rx6110_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
{
pr_debug("%s: date %ptRr\n", __func__, tm);
/* * The year in the RTC is a value between 0 and 99. * Assume that this represents the current century * and disregard all other values.
*/ if (tm->tm_year < 100 || tm->tm_year >= 200) return -EINVAL;
/** * rx6110_data_to_rtc_tm - convert native time encoding to rtc_time * * @data: holds the encoding in rx6110 native form * @tm: holds date and time
*/ staticint rx6110_data_to_rtc_tm(u8 *data, struct rtc_time *tm)
{
tm->tm_sec = bcd2bin(data[RTC_SEC] & 0x7f);
tm->tm_min = bcd2bin(data[RTC_MIN] & 0x7f); /* only 24-hour clock */
tm->tm_hour = bcd2bin(data[RTC_HOUR] & 0x3f);
tm->tm_wday = ffs(data[RTC_WDAY] & 0x7f);
tm->tm_mday = bcd2bin(data[RTC_MDAY] & 0x3f);
tm->tm_mon = bcd2bin(data[RTC_MONTH] & 0x1f) - 1;
tm->tm_year = bcd2bin(data[RTC_YEAR]) + 100;
pr_debug("%s: date %ptRr\n", __func__, tm);
/* * The year in the RTC is a value between 0 and 99. * Assume that this represents the current century * and disregard all other values.
*/ if (tm->tm_year < 100 || tm->tm_year >= 200) return -EINVAL;
return 0;
}
/** * rx6110_set_time - set the current time in the rx6110 registers * * @dev: the rtc device in use * @tm: holds date and time * * BUG: The HW assumes every year that is a multiple of 4 to be a leap * year. Next time this is wrong is 2100, which will not be a leap year * * Note: If STOP is not set/cleared, the clock will start when the seconds * register is written *
*/ staticint rx6110_set_time(struct device *dev, struct rtc_time *tm)
{ struct rx6110_data *rx6110 = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME]; int ret;
ret = rx6110_rtc_tm_to_data(tm, data); if (ret < 0) return ret;
/* set STOP bit before changing clock/calendar */
ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
RX6110_BIT_CTRL_STOP, RX6110_BIT_CTRL_STOP); if (ret) return ret;
ret = regmap_bulk_write(rx6110->regmap, RX6110_REG_SEC, data,
RTC_NR_TIME); if (ret) return ret;
/* The time in the RTC is valid. Be sure to have VLF cleared. */
ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
RX6110_BIT_FLAG_VLF, 0); if (ret) return ret;
/* clear STOP bit after changing clock/calendar */
ret = regmap_update_bits(rx6110->regmap, RX6110_REG_CTRL,
RX6110_BIT_CTRL_STOP, 0);
return ret;
}
/** * rx6110_get_time - get the current time from the rx6110 registers * @dev: the rtc device in use * @tm: holds date and time
*/ staticint rx6110_get_time(struct device *dev, struct rtc_time *tm)
{ struct rx6110_data *rx6110 = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME]; int flags; int ret;
ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags); if (ret) return -EINVAL;
/* check for VLF Flag (set at power-on) */ if ((flags & RX6110_BIT_FLAG_VLF)) {
dev_warn(dev, "Voltage low, data is invalid.\n"); return -EINVAL;
}
/* read registers to date */
ret = regmap_bulk_read(rx6110->regmap, RX6110_REG_SEC, data,
RTC_NR_TIME); if (ret) return ret;
ret = rx6110_data_to_rtc_tm(data, tm); if (ret) return ret;
/** * rx6110_init - initialize the rx6110 registers * * @rx6110: pointer to the rx6110 struct in use *
*/ staticint rx6110_init(struct rx6110_data *rx6110)
{ struct rtc_device *rtc = rx6110->rtc; int flags; int ret;
ret = regmap_update_bits(rx6110->regmap, RX6110_REG_EXT,
RX6110_BIT_EXT_TE, 0); if (ret) return ret;
ret = regmap_register_patch(rx6110->regmap, rx6110_default_regs,
ARRAY_SIZE(rx6110_default_regs)); if (ret) return ret;
ret = regmap_read(rx6110->regmap, RX6110_REG_FLAG, &flags); if (ret) return ret;
/* check for VLF Flag (set at power-on) */ if ((flags & RX6110_BIT_FLAG_VLF))
dev_warn(&rtc->dev, "Voltage low, data loss detected.\n");
/* check for Alarm Flag */ if (flags & RX6110_BIT_FLAG_AF)
dev_warn(&rtc->dev, "An alarm may have been missed.\n");
/* check for Periodic Timer Flag */ if (flags & RX6110_BIT_FLAG_TF)
dev_warn(&rtc->dev, "Periodic timer was detected\n");
/* check for Update Timer Flag */ if (flags & RX6110_BIT_FLAG_UF)
dev_warn(&rtc->dev, "Update timer was detected\n");
/* clear all flags BUT VLF */
ret = regmap_update_bits(rx6110->regmap, RX6110_REG_FLAG,
RX6110_BIT_FLAG_AF |
RX6110_BIT_FLAG_UF |
RX6110_BIT_FLAG_TF,
0);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.