brintos

brintos / linux-shallow public Read only

0
0
Text · 14.9 KiB · 02f7d07 Raw
596 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Real Time Clock driver for AB-RTCMC-32.768kHz-EOZ9 chip.4 * Copyright (C) 2019 Orolia5 *6 */7 8#include <linux/module.h>9#include <linux/rtc.h>10#include <linux/i2c.h>11#include <linux/bcd.h>12#include <linux/of.h>13#include <linux/regmap.h>14#include <linux/bitfield.h>15#include <linux/hwmon.h>16#include <linux/hwmon-sysfs.h>17 18#define ABEOZ9_REG_CTRL1		0x0019#define ABEOZ9_REG_CTRL1_MASK		GENMASK(7, 0)20#define ABEOZ9_REG_CTRL1_WE		BIT(0)21#define ABEOZ9_REG_CTRL1_TE		BIT(1)22#define ABEOZ9_REG_CTRL1_TAR		BIT(2)23#define ABEOZ9_REG_CTRL1_EERE		BIT(3)24#define ABEOZ9_REG_CTRL1_SRON		BIT(4)25#define ABEOZ9_REG_CTRL1_TD0		BIT(5)26#define ABEOZ9_REG_CTRL1_TD1		BIT(6)27#define ABEOZ9_REG_CTRL1_CLKINT		BIT(7)28 29#define ABEOZ9_REG_CTRL_INT		0x0130#define ABEOZ9_REG_CTRL_INT_AIE		BIT(0)31#define ABEOZ9_REG_CTRL_INT_TIE		BIT(1)32#define ABEOZ9_REG_CTRL_INT_V1IE	BIT(2)33#define ABEOZ9_REG_CTRL_INT_V2IE	BIT(3)34#define ABEOZ9_REG_CTRL_INT_SRIE	BIT(4)35 36#define ABEOZ9_REG_CTRL_INT_FLAG	0x0237#define ABEOZ9_REG_CTRL_INT_FLAG_AF	BIT(0)38#define ABEOZ9_REG_CTRL_INT_FLAG_TF	BIT(1)39#define ABEOZ9_REG_CTRL_INT_FLAG_V1IF	BIT(2)40#define ABEOZ9_REG_CTRL_INT_FLAG_V2IF	BIT(3)41#define ABEOZ9_REG_CTRL_INT_FLAG_SRF	BIT(4)42 43#define ABEOZ9_REG_CTRL_STATUS		0x0344#define ABEOZ9_REG_CTRL_STATUS_V1F	BIT(2)45#define ABEOZ9_REG_CTRL_STATUS_V2F	BIT(3)46#define ABEOZ9_REG_CTRL_STATUS_SR	BIT(4)47#define ABEOZ9_REG_CTRL_STATUS_PON	BIT(5)48#define ABEOZ9_REG_CTRL_STATUS_EEBUSY	BIT(7)49 50#define ABEOZ9_REG_SEC			0x0851#define ABEOZ9_REG_MIN			0x0952#define ABEOZ9_REG_HOURS		0x0A53#define ABEOZ9_HOURS_PM			BIT(6)54#define ABEOZ9_REG_DAYS			0x0B55#define ABEOZ9_REG_WEEKDAYS		0x0C56#define ABEOZ9_REG_MONTHS		0x0D57#define ABEOZ9_REG_YEARS		0x0E58 59#define ABEOZ9_SEC_LEN			760 61#define ABEOZ9_REG_ALARM_SEC		0x1062#define ABEOZ9_BIT_ALARM_SEC		GENMASK(6, 0)63#define ABEOZ9_REG_ALARM_MIN		0x1164#define ABEOZ9_BIT_ALARM_MIN		GENMASK(6, 0)65#define ABEOZ9_REG_ALARM_HOURS		0x1266#define ABEOZ9_BIT_ALARM_HOURS_PM	BIT(5)67#define ABEOZ9_BIT_ALARM_HOURS		GENMASK(4, 0)68#define ABEOZ9_REG_ALARM_DAYS		0x1369#define ABEOZ9_BIT_ALARM_DAYS		GENMASK(5, 0)70#define ABEOZ9_REG_ALARM_WEEKDAYS	0x1471#define ABEOZ9_BIT_ALARM_WEEKDAYS	GENMASK(2, 0)72#define ABEOZ9_REG_ALARM_MONTHS		0x1573#define ABEOZ9_BIT_ALARM_MONTHS		GENMASK(4, 0)74#define ABEOZ9_REG_ALARM_YEARS		0x1675 76#define ABEOZ9_ALARM_LEN		777#define ABEOZ9_BIT_ALARM_AE		BIT(7)78 79#define ABEOZ9_REG_REG_TEMP		0x2080#define ABEOZ953_TEMP_MAX		12081#define ABEOZ953_TEMP_MIN		-6082 83#define ABEOZ9_REG_EEPROM		0x3084#define ABEOZ9_REG_EEPROM_MASK		GENMASK(8, 0)85#define ABEOZ9_REG_EEPROM_THP		BIT(0)86#define ABEOZ9_REG_EEPROM_THE		BIT(1)87#define ABEOZ9_REG_EEPROM_FD0		BIT(2)88#define ABEOZ9_REG_EEPROM_FD1		BIT(3)89#define ABEOZ9_REG_EEPROM_R1K		BIT(4)90#define ABEOZ9_REG_EEPROM_R5K		BIT(5)91#define ABEOZ9_REG_EEPROM_R20K		BIT(6)92#define ABEOZ9_REG_EEPROM_R80K		BIT(7)93 94struct abeoz9_rtc_data {95	struct rtc_device *rtc;96	struct regmap *regmap;97	struct device *hwmon_dev;98};99 100static int abeoz9_check_validity(struct device *dev)101{102	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);103	struct regmap *regmap = data->regmap;104	int ret;105	int val;106 107	ret = regmap_read(regmap, ABEOZ9_REG_CTRL_STATUS, &val);108	if (ret < 0) {109		dev_err(dev,110			"unable to get CTRL_STATUS register (%d)\n", ret);111		return ret;112	}113 114	if (val & ABEOZ9_REG_CTRL_STATUS_PON) {115		dev_warn(dev, "power-on reset detected, date is invalid\n");116		return -EINVAL;117	}118 119	if (val & ABEOZ9_REG_CTRL_STATUS_V1F) {120		dev_warn(dev,121			 "voltage drops below VLOW1 threshold, date is invalid\n");122		return -EINVAL;123	}124 125	if ((val & ABEOZ9_REG_CTRL_STATUS_V2F)) {126		dev_warn(dev,127			 "voltage drops below VLOW2 threshold, date is invalid\n");128		return -EINVAL;129	}130 131	return 0;132}133 134static int abeoz9_reset_validity(struct regmap *regmap)135{136	return regmap_update_bits(regmap, ABEOZ9_REG_CTRL_STATUS,137				  ABEOZ9_REG_CTRL_STATUS_V1F |138				  ABEOZ9_REG_CTRL_STATUS_V2F |139				  ABEOZ9_REG_CTRL_STATUS_PON,140				  0);141}142 143static int abeoz9_rtc_get_time(struct device *dev, struct rtc_time *tm)144{145	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);146	u8 regs[ABEOZ9_SEC_LEN];147	int ret;148 149	ret = abeoz9_check_validity(dev);150	if (ret)151		return ret;152 153	ret = regmap_bulk_read(data->regmap, ABEOZ9_REG_SEC,154			       regs,155			       sizeof(regs));156	if (ret) {157		dev_err(dev, "reading RTC time failed (%d)\n", ret);158		return ret;159	}160 161	tm->tm_sec = bcd2bin(regs[ABEOZ9_REG_SEC - ABEOZ9_REG_SEC] & 0x7F);162	tm->tm_min = bcd2bin(regs[ABEOZ9_REG_MIN - ABEOZ9_REG_SEC] & 0x7F);163 164	if (regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC] & ABEOZ9_HOURS_PM) {165		tm->tm_hour =166			bcd2bin(regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC] & 0x1f);167		if (regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC] & ABEOZ9_HOURS_PM)168			tm->tm_hour += 12;169	} else {170		tm->tm_hour = bcd2bin(regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC]);171	}172 173	tm->tm_mday = bcd2bin(regs[ABEOZ9_REG_DAYS - ABEOZ9_REG_SEC]);174	tm->tm_wday = bcd2bin(regs[ABEOZ9_REG_WEEKDAYS - ABEOZ9_REG_SEC]);175	tm->tm_mon  = bcd2bin(regs[ABEOZ9_REG_MONTHS - ABEOZ9_REG_SEC]) - 1;176	tm->tm_year = bcd2bin(regs[ABEOZ9_REG_YEARS - ABEOZ9_REG_SEC]) + 100;177 178	return ret;179}180 181static int abeoz9_rtc_set_time(struct device *dev, struct rtc_time *tm)182{183	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);184	struct regmap *regmap = data->regmap;185	u8 regs[ABEOZ9_SEC_LEN];186	int ret;187 188	regs[ABEOZ9_REG_SEC - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_sec);189	regs[ABEOZ9_REG_MIN - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_min);190	regs[ABEOZ9_REG_HOURS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_hour);191	regs[ABEOZ9_REG_DAYS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_mday);192	regs[ABEOZ9_REG_WEEKDAYS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_wday);193	regs[ABEOZ9_REG_MONTHS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_mon + 1);194	regs[ABEOZ9_REG_YEARS - ABEOZ9_REG_SEC] = bin2bcd(tm->tm_year - 100);195 196	ret = regmap_bulk_write(data->regmap, ABEOZ9_REG_SEC,197				regs,198				sizeof(regs));199 200	if (ret) {201		dev_err(dev, "set RTC time failed (%d)\n", ret);202		return ret;203	}204 205	return abeoz9_reset_validity(regmap);206}207 208static int abeoz9_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)209{210	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);211	struct regmap *regmap = data->regmap;212	u8 regs[ABEOZ9_ALARM_LEN];213	u8 val[2];214	int ret;215 216	ret = abeoz9_check_validity(dev);217	if (ret)218		return ret;219 220	ret = regmap_bulk_read(regmap, ABEOZ9_REG_CTRL_INT, val, sizeof(val));221	if (ret)222		return ret;223 224	alarm->enabled = val[0] & ABEOZ9_REG_CTRL_INT_AIE;225	alarm->pending = val[1] & ABEOZ9_REG_CTRL_INT_FLAG_AF;226 227	ret = regmap_bulk_read(regmap, ABEOZ9_REG_ALARM_SEC, regs, sizeof(regs));228	if (ret)229		return ret;230 231	alarm->time.tm_sec = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_SEC, regs[0]));232	alarm->time.tm_min = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_MIN, regs[1]));233	alarm->time.tm_hour = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_HOURS, regs[2]));234	if (FIELD_GET(ABEOZ9_BIT_ALARM_HOURS_PM, regs[2]))235		alarm->time.tm_hour += 12;236 237	alarm->time.tm_mday = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_DAYS, regs[3]));238 239	return 0;240}241 242static int abeoz9_rtc_alarm_irq_enable(struct device *dev, u32 enable)243{244	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);245 246	return regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT,247				  ABEOZ9_REG_CTRL_INT_AIE,248				  FIELD_PREP(ABEOZ9_REG_CTRL_INT_AIE, enable));249}250 251static int abeoz9_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)252{253	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);254	u8 regs[ABEOZ9_ALARM_LEN] = {0};255	int ret;256 257	ret = regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG,258				 ABEOZ9_REG_CTRL_INT_FLAG_AF, 0);259	if (ret)260		return ret;261 262	regs[0] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_SEC,263						   bin2bcd(alarm->time.tm_sec));264	regs[1] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_MIN,265						   bin2bcd(alarm->time.tm_min));266	regs[2] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_HOURS,267						   bin2bcd(alarm->time.tm_hour));268	regs[3] = ABEOZ9_BIT_ALARM_AE | FIELD_PREP(ABEOZ9_BIT_ALARM_DAYS,269						   bin2bcd(alarm->time.tm_mday));270 271	ret = regmap_bulk_write(data->regmap, ABEOZ9_REG_ALARM_SEC, regs,272				sizeof(regs));273	if (ret)274		return ret;275 276	return abeoz9_rtc_alarm_irq_enable(dev, alarm->enabled);277}278 279static irqreturn_t abeoz9_rtc_irq(int irq, void *dev)280{281	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);282	unsigned int val;283	int ret;284 285	ret = regmap_read(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG, &val);286	if (ret)287		return IRQ_NONE;288 289	if (!FIELD_GET(ABEOZ9_REG_CTRL_INT_FLAG_AF, val))290		return IRQ_NONE;291 292	regmap_update_bits(data->regmap, ABEOZ9_REG_CTRL_INT_FLAG,293			   ABEOZ9_REG_CTRL_INT_FLAG_AF, 0);294 295	rtc_update_irq(data->rtc, 1, RTC_IRQF | RTC_AF);296 297	return IRQ_HANDLED;298}299 300static int abeoz9_trickle_parse_dt(struct device_node *node)301{302	u32 ohms = 0;303 304	if (of_property_read_u32(node, "trickle-resistor-ohms", &ohms))305		return 0;306 307	switch (ohms) {308	case 1000:309		return ABEOZ9_REG_EEPROM_R1K;310	case 5000:311		return ABEOZ9_REG_EEPROM_R5K;312	case 20000:313		return ABEOZ9_REG_EEPROM_R20K;314	case 80000:315		return ABEOZ9_REG_EEPROM_R80K;316	default:317		return 0;318	}319}320 321static int abeoz9_rtc_setup(struct device *dev, struct device_node *node)322{323	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);324	struct regmap *regmap = data->regmap;325	int ret;326 327	/* Enable Self Recovery, Clock for Watch and EEPROM refresh functions */328	ret = regmap_update_bits(regmap, ABEOZ9_REG_CTRL1,329				 ABEOZ9_REG_CTRL1_MASK,330				 ABEOZ9_REG_CTRL1_WE |331				 ABEOZ9_REG_CTRL1_EERE |332				 ABEOZ9_REG_CTRL1_SRON);333	if (ret < 0) {334		dev_err(dev, "unable to set CTRL_1 register (%d)\n", ret);335		return ret;336	}337 338	ret = regmap_write(regmap, ABEOZ9_REG_CTRL_INT, 0);339	if (ret < 0) {340		dev_err(dev,341			"unable to set control CTRL_INT register (%d)\n",342			ret);343		return ret;344	}345 346	ret = regmap_write(regmap, ABEOZ9_REG_CTRL_INT_FLAG, 0);347	if (ret < 0) {348		dev_err(dev,349			"unable to set control CTRL_INT_FLAG register (%d)\n",350			ret);351		return ret;352	}353 354	ret = abeoz9_trickle_parse_dt(node);355 356	/* Enable built-in termometer */357	ret |= ABEOZ9_REG_EEPROM_THE;358 359	ret = regmap_update_bits(regmap, ABEOZ9_REG_EEPROM,360				 ABEOZ9_REG_EEPROM_MASK,361				 ret);362	if (ret < 0) {363		dev_err(dev, "unable to set EEPROM register (%d)\n", ret);364		return ret;365	}366 367	return ret;368}369 370static const struct rtc_class_ops rtc_ops = {371	.read_time = abeoz9_rtc_get_time,372	.set_time = abeoz9_rtc_set_time,373	.read_alarm = abeoz9_rtc_read_alarm,374	.set_alarm = abeoz9_rtc_set_alarm,375	.alarm_irq_enable = abeoz9_rtc_alarm_irq_enable,376};377 378static const struct regmap_config abeoz9_rtc_regmap_config = {379	.reg_bits = 8,380	.val_bits = 8,381	.max_register = 0x3f,382};383 384#if IS_REACHABLE(CONFIG_HWMON)385 386static int abeoz9z3_temp_read(struct device *dev,387			      enum hwmon_sensor_types type,388			      u32 attr, int channel, long *temp)389{390	struct abeoz9_rtc_data *data = dev_get_drvdata(dev);391	struct regmap *regmap = data->regmap;392	int ret;393	unsigned int val;394 395	ret = regmap_read(regmap, ABEOZ9_REG_CTRL_STATUS, &val);396	if (ret < 0)397		return ret;398 399	if ((val & ABEOZ9_REG_CTRL_STATUS_V1F) ||400	    (val & ABEOZ9_REG_CTRL_STATUS_V2F)) {401		dev_err(dev,402			"thermometer might be disabled due to low voltage\n");403		return -EINVAL;404	}405 406	switch (attr) {407	case hwmon_temp_input:408		ret = regmap_read(regmap, ABEOZ9_REG_REG_TEMP, &val);409		if (ret < 0)410			return ret;411		*temp = 1000 * (val + ABEOZ953_TEMP_MIN);412		return 0;413	case hwmon_temp_max:414		*temp = 1000 * ABEOZ953_TEMP_MAX;415		return 0;416	case hwmon_temp_min:417		*temp = 1000 * ABEOZ953_TEMP_MIN;418		return 0;419	default:420		return -EOPNOTSUPP;421	}422}423 424static umode_t abeoz9_is_visible(const void *data,425				 enum hwmon_sensor_types type,426				 u32 attr, int channel)427{428	switch (attr) {429	case hwmon_temp_input:430	case hwmon_temp_max:431	case hwmon_temp_min:432		return 0444;433	default:434		return 0;435	}436}437 438static const u32 abeoz9_chip_config[] = {439	HWMON_C_REGISTER_TZ,440	0441};442 443static const struct hwmon_channel_info abeoz9_chip = {444	.type = hwmon_chip,445	.config = abeoz9_chip_config,446};447 448static const u32 abeoz9_temp_config[] = {449	HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN,450	0451};452 453static const struct hwmon_channel_info abeoz9_temp = {454	.type = hwmon_temp,455	.config = abeoz9_temp_config,456};457 458static const struct hwmon_channel_info * const abeoz9_info[] = {459	&abeoz9_chip,460	&abeoz9_temp,461	NULL462};463 464static const struct hwmon_ops abeoz9_hwmon_ops = {465	.is_visible = abeoz9_is_visible,466	.read = abeoz9z3_temp_read,467};468 469static const struct hwmon_chip_info abeoz9_chip_info = {470	.ops = &abeoz9_hwmon_ops,471	.info = abeoz9_info,472};473 474static void abeoz9_hwmon_register(struct device *dev,475				  struct abeoz9_rtc_data *data)476{477	data->hwmon_dev =478		devm_hwmon_device_register_with_info(dev,479						     "abeoz9",480						     data,481						     &abeoz9_chip_info,482						     NULL);483	if (IS_ERR(data->hwmon_dev)) {484		dev_warn(dev, "unable to register hwmon device %ld\n",485			 PTR_ERR(data->hwmon_dev));486	}487}488 489#else490 491static void abeoz9_hwmon_register(struct device *dev,492				  struct abeoz9_rtc_data *data)493{494}495 496#endif497 498static int abeoz9_probe(struct i2c_client *client)499{500	struct abeoz9_rtc_data *data = NULL;501	struct device *dev = &client->dev;502	struct regmap *regmap;503	int ret;504 505	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |506				     I2C_FUNC_SMBUS_BYTE_DATA |507				     I2C_FUNC_SMBUS_I2C_BLOCK))508		return -ENODEV;509 510	regmap = devm_regmap_init_i2c(client, &abeoz9_rtc_regmap_config);511	if (IS_ERR(regmap)) {512		ret = PTR_ERR(regmap);513		dev_err(dev, "regmap allocation failed: %d\n", ret);514		return ret;515	}516 517	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);518	if (!data)519		return -ENOMEM;520 521	data->regmap = regmap;522	dev_set_drvdata(dev, data);523 524	ret = abeoz9_rtc_setup(dev, client->dev.of_node);525	if (ret)526		return ret;527 528	data->rtc = devm_rtc_allocate_device(dev);529	ret = PTR_ERR_OR_ZERO(data->rtc);530	if (ret)531		return ret;532 533	data->rtc->ops = &rtc_ops;534	data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;535	data->rtc->range_max = RTC_TIMESTAMP_END_2099;536	clear_bit(RTC_FEATURE_ALARM, data->rtc->features);537 538	if (client->irq > 0) {539		unsigned long irqflags = IRQF_TRIGGER_LOW;540 541		if (dev_fwnode(&client->dev))542			irqflags = 0;543 544		ret = devm_request_threaded_irq(dev, client->irq, NULL,545						abeoz9_rtc_irq,546						irqflags | IRQF_ONESHOT,547						dev_name(dev), dev);548		if (ret) {549			dev_err(dev, "failed to request alarm irq\n");550			return ret;551		}552	} else {553		clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, data->rtc->features);554	}555 556	if (client->irq > 0 || device_property_read_bool(dev, "wakeup-source")) {557		ret = device_init_wakeup(dev, true);558		set_bit(RTC_FEATURE_ALARM, data->rtc->features);559	}560 561	ret = devm_rtc_register_device(data->rtc);562	if (ret)563		return ret;564 565	abeoz9_hwmon_register(dev, data);566	return 0;567}568 569#ifdef CONFIG_OF570static const struct of_device_id abeoz9_dt_match[] = {571	{ .compatible = "abracon,abeoz9" },572	{ },573};574MODULE_DEVICE_TABLE(of, abeoz9_dt_match);575#endif576 577static const struct i2c_device_id abeoz9_id[] = {578	{ "abeoz9" },579	{ }580};581 582static struct i2c_driver abeoz9_driver = {583	.driver = {584		.name = "rtc-ab-eoz9",585		.of_match_table = of_match_ptr(abeoz9_dt_match),586	},587	.probe = abeoz9_probe,588	.id_table = abeoz9_id,589};590 591module_i2c_driver(abeoz9_driver);592 593MODULE_AUTHOR("Artem Panfilov <panfilov.artyom@gmail.com>");594MODULE_DESCRIPTION("Abracon AB-RTCMC-32.768kHz-EOZ9 RTC driver");595MODULE_LICENSE("GPL");596