// SPDX-License-Identifier: GPL-2.0-only /* * An I2C driver for the Intersil ISL 12022 * * Author: Roman Fietze <roman.fietze@telemotive.de> * * Based on the Philips PCF8563 RTC * by Alessandro Zummo <a.zummo@towertech.it>.
*/
/* * A user-initiated temperature conversion is not started by this function, * so the temperature is updated once every ~60 seconds.
*/ staticint isl12022_hwmon_read_temp(struct device *dev, long *mC)
{ struct regmap *regmap = dev_get_drvdata(dev); int temp, ret;
__le16 buf;
ret = regmap_bulk_read(regmap, ISL12022_REG_TEMP_L, &buf, sizeof(buf)); if (ret) return ret; /* * Temperature is represented as a 10-bit number, unit half-Kelvins.
*/
temp = le16_to_cpu(buf);
temp *= 500;
temp -= 273000;
*mC = temp;
return 0;
}
staticint isl12022_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{ if (type == hwmon_temp && attr == hwmon_temp_input) return isl12022_hwmon_read_temp(dev, val);
ret = regmap_update_bits(regmap, ISL12022_REG_BETA,
ISL12022_BETA_TSE, ISL12022_BETA_TSE); if (ret) {
dev_warn(dev, "unable to enable temperature sensor\n"); return;
}
hwmon = devm_hwmon_device_register_with_info(dev, "isl12022", regmap,
&isl12022_hwmon_chip_info,
NULL); if (IS_ERR(hwmon))
dev_warn(dev, "unable to register hwmon device: %pe\n", hwmon);
}
/* * In the routines that deal directly with the isl12022 hardware, we use * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
*/ staticint isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ struct isl12022 *isl12022 = dev_get_drvdata(dev); struct regmap *regmap = isl12022->regmap;
u8 buf[ISL12022_REG_INT + 1]; int ret;
ret = regmap_bulk_read(regmap, ISL12022_REG_SC, buf, sizeof(buf)); if (ret) return ret;
/* Ensure the write enable bit is set. */
ret = regmap_update_bits(regmap, ISL12022_REG_INT,
ISL12022_INT_WRTC, ISL12022_INT_WRTC); if (ret) return ret;
ret = regmap_bulk_read(regmap, ISL12022_ALARM, buf, sizeof(buf)); if (ret) {
dev_dbg(dev, "%s: reading ALARM registers failed\n",
__func__); return ret;
}
/* The alarm doesn't store the year so get it from the rtc section */
ret = regmap_read(regmap, ISL12022_REG_YR, &yr); if (ret) {
dev_dbg(dev, "%s: reading YR register failed\n", __func__); return ret;
}
ret = isl12022_rtc_read_time(dev, &rtc_tm); if (ret) return ret;
/* If the alarm time is before the current time disable the alarm */ if (!alarm->enabled || rtc_tm_sub(alarm_tm, &rtc_tm) <= 0)
enable = 0; else
enable = ISL12022_ALARM_ENABLE;
/* * Set non-matching day of the week to safeguard against early false * matching while setting all the alarm registers (this rtc lacks a * general alarm/irq enable/disable bit).
*/
ret = regmap_read(regmap, ISL12022_REG_DW, &dw); if (ret) {
dev_dbg(dev, "%s: reading DW failed\n", __func__); return ret;
} /* ~4 days into the future should be enough to avoid match */
dw = ((dw + 4) % 7) | ISL12022_ALARM_ENABLE;
ret = regmap_write(regmap, ISL12022_REG_DWA0, dw); if (ret) {
dev_dbg(dev, "%s: writing DWA0 failed\n", __func__); return ret;
}
/* Program the alarm and enable it for each setting */
regs[ISL12022_REG_SCA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_sec) | enable;
regs[ISL12022_REG_MNA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_min) | enable;
regs[ISL12022_REG_HRA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_hour) | enable;
regs[ISL12022_REG_DTA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_mday) | enable;
regs[ISL12022_REG_MOA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_mon + 1) | enable;
regs[ISL12022_REG_DWA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_wday & 7) | enable;
if (!device_property_present(dev, "#clock-cells")) { /* * Disabling the F_OUT pin reduces the power * consumption in battery mode by ~25%.
*/
regmap_update_bits(regmap, ISL12022_REG_INT, ISL12022_INT_FO_MASK,
ISL12022_INT_FO_OFF);
return 0;
}
if (!IS_ENABLED(CONFIG_COMMON_CLK)) return 0;
/* * For now, only support a fixed clock of 32768Hz (the reset default).
*/
ret = regmap_update_bits(regmap, ISL12022_REG_INT,
ISL12022_INT_FO_MASK, ISL12022_INT_FO_32K); if (ret) return ret;
ret = regmap_update_bits(regmap, ISL12022_REG_PWR_VBAT, mask, val); if (ret)
dev_warn(dev, "unable to set battery alarm levels: %d\n", ret);
/* * Force a write of the TSE bit in the BETA register, in order * to trigger an update of the LBAT75 and LBAT85 bits in the * status register. In battery backup mode, those bits have * another meaning, so without this, they may contain stale * values for up to a minute after power-on.
*/
regmap_write_bits(regmap, ISL12022_REG_BETA,
ISL12022_BETA_TSE, ISL12022_BETA_TSE);
}
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.