brintos

brintos / linux-shallow public Read only

0
0
Text · 11.6 KiB · 540042b Raw
497 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * drivers/rtc/rtc-pcf85363.c4 *5 * Driver for NXP PCF85363 real-time clock.6 *7 * Copyright (C) 2017 Eric Nelson8 */9#include <linux/module.h>10#include <linux/i2c.h>11#include <linux/slab.h>12#include <linux/rtc.h>13#include <linux/init.h>14#include <linux/err.h>15#include <linux/errno.h>16#include <linux/bcd.h>17#include <linux/of.h>18#include <linux/regmap.h>19 20/*21 * Date/Time registers22 */23#define DT_100THS	0x0024#define DT_SECS		0x0125#define DT_MINUTES	0x0226#define DT_HOURS	0x0327#define DT_DAYS		0x0428#define DT_WEEKDAYS	0x0529#define DT_MONTHS	0x0630#define DT_YEARS	0x0731 32/*33 * Alarm registers34 */35#define DT_SECOND_ALM1	0x0836#define DT_MINUTE_ALM1	0x0937#define DT_HOUR_ALM1	0x0a38#define DT_DAY_ALM1	0x0b39#define DT_MONTH_ALM1	0x0c40#define DT_MINUTE_ALM2	0x0d41#define DT_HOUR_ALM2	0x0e42#define DT_WEEKDAY_ALM2	0x0f43#define DT_ALARM_EN	0x1044 45/*46 * Time stamp registers47 */48#define DT_TIMESTAMP1	0x1149#define DT_TIMESTAMP2	0x1750#define DT_TIMESTAMP3	0x1d51#define DT_TS_MODE	0x2352 53/*54 * control registers55 */56#define CTRL_OFFSET	0x2457#define CTRL_OSCILLATOR	0x2558#define CTRL_BATTERY	0x2659#define CTRL_PIN_IO	0x2760#define CTRL_FUNCTION	0x2861#define CTRL_INTA_EN	0x2962#define CTRL_INTB_EN	0x2a63#define CTRL_FLAGS	0x2b64#define CTRL_RAMBYTE	0x2c65#define CTRL_WDOG	0x2d66#define CTRL_STOP_EN	0x2e67#define CTRL_RESETS	0x2f68#define CTRL_RAM	0x4069 70#define ALRM_SEC_A1E	BIT(0)71#define ALRM_MIN_A1E	BIT(1)72#define ALRM_HR_A1E	BIT(2)73#define ALRM_DAY_A1E	BIT(3)74#define ALRM_MON_A1E	BIT(4)75#define ALRM_MIN_A2E	BIT(5)76#define ALRM_HR_A2E	BIT(6)77#define ALRM_DAY_A2E	BIT(7)78 79#define INT_WDIE	BIT(0)80#define INT_BSIE	BIT(1)81#define INT_TSRIE	BIT(2)82#define INT_A2IE	BIT(3)83#define INT_A1IE	BIT(4)84#define INT_OIE		BIT(5)85#define INT_PIE		BIT(6)86#define INT_ILP		BIT(7)87 88#define FLAGS_TSR1F	BIT(0)89#define FLAGS_TSR2F	BIT(1)90#define FLAGS_TSR3F	BIT(2)91#define FLAGS_BSF	BIT(3)92#define FLAGS_WDF	BIT(4)93#define FLAGS_A1F	BIT(5)94#define FLAGS_A2F	BIT(6)95#define FLAGS_PIF	BIT(7)96 97#define PIN_IO_INTAPM	GENMASK(1, 0)98#define PIN_IO_INTA_CLK	099#define PIN_IO_INTA_BAT	1100#define PIN_IO_INTA_OUT	2101#define PIN_IO_INTA_HIZ	3102 103#define OSC_CAP_SEL	GENMASK(1, 0)104#define OSC_CAP_6000	0x01105#define OSC_CAP_12500	0x02106 107#define STOP_EN_STOP	BIT(0)108 109#define RESET_CPR	0xa4110 111#define NVRAM_SIZE	0x40112 113struct pcf85363 {114	struct rtc_device	*rtc;115	struct regmap		*regmap;116};117 118struct pcf85x63_config {119	struct regmap_config regmap;120	unsigned int num_nvram;121};122 123static int pcf85363_load_capacitance(struct pcf85363 *pcf85363, struct device_node *node)124{125	u32 load = 7000;126	u8 value = 0;127 128	of_property_read_u32(node, "quartz-load-femtofarads", &load);129 130	switch (load) {131	default:132		dev_warn(&pcf85363->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 7000",133			 load);134		fallthrough;135	case 7000:136		break;137	case 6000:138		value = OSC_CAP_6000;139		break;140	case 12500:141		value = OSC_CAP_12500;142		break;143	}144 145	return regmap_update_bits(pcf85363->regmap, CTRL_OSCILLATOR,146				  OSC_CAP_SEL, value);147}148 149static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm)150{151	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);152	unsigned char buf[DT_YEARS + 1];153	int ret, len = sizeof(buf);154 155	/* read the RTC date and time registers all at once */156	ret = regmap_bulk_read(pcf85363->regmap, DT_100THS, buf, len);157	if (ret) {158		dev_err(dev, "%s: error %d\n", __func__, ret);159		return ret;160	}161 162	tm->tm_year = bcd2bin(buf[DT_YEARS]);163	/* adjust for 1900 base of rtc_time */164	tm->tm_year += 100;165 166	tm->tm_wday = buf[DT_WEEKDAYS] & 7;167	buf[DT_SECS] &= 0x7F;168	tm->tm_sec = bcd2bin(buf[DT_SECS]);169	buf[DT_MINUTES] &= 0x7F;170	tm->tm_min = bcd2bin(buf[DT_MINUTES]);171	tm->tm_hour = bcd2bin(buf[DT_HOURS]);172	tm->tm_mday = bcd2bin(buf[DT_DAYS]);173	tm->tm_mon = bcd2bin(buf[DT_MONTHS]) - 1;174 175	return 0;176}177 178static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm)179{180	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);181	unsigned char tmp[11];182	unsigned char *buf = &tmp[2];183	int ret;184 185	tmp[0] = STOP_EN_STOP;186	tmp[1] = RESET_CPR;187 188	buf[DT_100THS] = 0;189	buf[DT_SECS] = bin2bcd(tm->tm_sec);190	buf[DT_MINUTES] = bin2bcd(tm->tm_min);191	buf[DT_HOURS] = bin2bcd(tm->tm_hour);192	buf[DT_DAYS] = bin2bcd(tm->tm_mday);193	buf[DT_WEEKDAYS] = tm->tm_wday;194	buf[DT_MONTHS] = bin2bcd(tm->tm_mon + 1);195	buf[DT_YEARS] = bin2bcd(tm->tm_year % 100);196 197	ret = regmap_bulk_write(pcf85363->regmap, CTRL_STOP_EN,198				tmp, 2);199	if (ret)200		return ret;201 202	ret = regmap_bulk_write(pcf85363->regmap, DT_100THS,203				buf, sizeof(tmp) - 2);204	if (ret)205		return ret;206 207	return regmap_write(pcf85363->regmap, CTRL_STOP_EN, 0);208}209 210static int pcf85363_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)211{212	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);213	unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1];214	unsigned int val;215	int ret;216 217	ret = regmap_bulk_read(pcf85363->regmap, DT_SECOND_ALM1, buf,218			       sizeof(buf));219	if (ret)220		return ret;221 222	alrm->time.tm_sec = bcd2bin(buf[0]);223	alrm->time.tm_min = bcd2bin(buf[1]);224	alrm->time.tm_hour = bcd2bin(buf[2]);225	alrm->time.tm_mday = bcd2bin(buf[3]);226	alrm->time.tm_mon = bcd2bin(buf[4]) - 1;227 228	ret = regmap_read(pcf85363->regmap, CTRL_INTA_EN, &val);229	if (ret)230		return ret;231 232	alrm->enabled =  !!(val & INT_A1IE);233 234	return 0;235}236 237static int _pcf85363_rtc_alarm_irq_enable(struct pcf85363 *pcf85363, unsigned238					  int enabled)239{240	unsigned int alarm_flags = ALRM_SEC_A1E | ALRM_MIN_A1E | ALRM_HR_A1E |241				   ALRM_DAY_A1E | ALRM_MON_A1E;242	int ret;243 244	ret = regmap_update_bits(pcf85363->regmap, DT_ALARM_EN, alarm_flags,245				 enabled ? alarm_flags : 0);246	if (ret)247		return ret;248 249	ret = regmap_update_bits(pcf85363->regmap, CTRL_INTA_EN,250				 INT_A1IE, enabled ? INT_A1IE : 0);251 252	if (ret || enabled)253		return ret;254 255	/* clear current flags */256	return regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0);257}258 259static int pcf85363_rtc_alarm_irq_enable(struct device *dev,260					 unsigned int enabled)261{262	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);263 264	return _pcf85363_rtc_alarm_irq_enable(pcf85363, enabled);265}266 267static int pcf85363_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)268{269	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);270	unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1];271	int ret;272 273	buf[0] = bin2bcd(alrm->time.tm_sec);274	buf[1] = bin2bcd(alrm->time.tm_min);275	buf[2] = bin2bcd(alrm->time.tm_hour);276	buf[3] = bin2bcd(alrm->time.tm_mday);277	buf[4] = bin2bcd(alrm->time.tm_mon + 1);278 279	/*280	 * Disable the alarm interrupt before changing the value to avoid281	 * spurious interrupts282	 */283	ret = _pcf85363_rtc_alarm_irq_enable(pcf85363, 0);284	if (ret)285		return ret;286 287	ret = regmap_bulk_write(pcf85363->regmap, DT_SECOND_ALM1, buf,288				sizeof(buf));289	if (ret)290		return ret;291 292	return _pcf85363_rtc_alarm_irq_enable(pcf85363, alrm->enabled);293}294 295static irqreturn_t pcf85363_rtc_handle_irq(int irq, void *dev_id)296{297	struct pcf85363 *pcf85363 = i2c_get_clientdata(dev_id);298	unsigned int flags;299	int err;300 301	err = regmap_read(pcf85363->regmap, CTRL_FLAGS, &flags);302	if (err)303		return IRQ_NONE;304 305	if (flags & FLAGS_A1F) {306		rtc_update_irq(pcf85363->rtc, 1, RTC_IRQF | RTC_AF);307		regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0);308		return IRQ_HANDLED;309	}310 311	return IRQ_NONE;312}313 314static const struct rtc_class_ops rtc_ops = {315	.read_time	= pcf85363_rtc_read_time,316	.set_time	= pcf85363_rtc_set_time,317	.read_alarm	= pcf85363_rtc_read_alarm,318	.set_alarm	= pcf85363_rtc_set_alarm,319	.alarm_irq_enable = pcf85363_rtc_alarm_irq_enable,320};321 322static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val,323			       size_t bytes)324{325	struct pcf85363 *pcf85363 = priv;326 327	return regmap_bulk_read(pcf85363->regmap, CTRL_RAM + offset,328				val, bytes);329}330 331static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val,332				size_t bytes)333{334	struct pcf85363 *pcf85363 = priv;335 336	return regmap_bulk_write(pcf85363->regmap, CTRL_RAM + offset,337				 val, bytes);338}339 340static int pcf85x63_nvram_read(void *priv, unsigned int offset, void *val,341			       size_t bytes)342{343	struct pcf85363 *pcf85363 = priv;344	unsigned int tmp_val;345	int ret;346 347	ret = regmap_read(pcf85363->regmap, CTRL_RAMBYTE, &tmp_val);348	(*(unsigned char *) val) = (unsigned char) tmp_val;349 350	return ret;351}352 353static int pcf85x63_nvram_write(void *priv, unsigned int offset, void *val,354				size_t bytes)355{356	struct pcf85363 *pcf85363 = priv;357	unsigned char tmp_val;358 359	tmp_val = *((unsigned char *)val);360	return regmap_write(pcf85363->regmap, CTRL_RAMBYTE,361				(unsigned int)tmp_val);362}363 364static const struct pcf85x63_config pcf_85263_config = {365	.regmap = {366		.reg_bits = 8,367		.val_bits = 8,368		.max_register = 0x2f,369	},370	.num_nvram = 1371};372 373static const struct pcf85x63_config pcf_85363_config = {374	.regmap = {375		.reg_bits = 8,376		.val_bits = 8,377		.max_register = 0x7f,378	},379	.num_nvram = 2380};381 382static int pcf85363_probe(struct i2c_client *client)383{384	struct pcf85363 *pcf85363;385	const struct pcf85x63_config *config = &pcf_85363_config;386	const void *data = of_device_get_match_data(&client->dev);387	static struct nvmem_config nvmem_cfg[] = {388		{389			.name = "pcf85x63-",390			.word_size = 1,391			.stride = 1,392			.size = 1,393			.reg_read = pcf85x63_nvram_read,394			.reg_write = pcf85x63_nvram_write,395		}, {396			.name = "pcf85363-",397			.word_size = 1,398			.stride = 1,399			.size = NVRAM_SIZE,400			.reg_read = pcf85363_nvram_read,401			.reg_write = pcf85363_nvram_write,402		},403	};404	int ret, i, err;405	bool wakeup_source;406 407	if (data)408		config = data;409 410	pcf85363 = devm_kzalloc(&client->dev, sizeof(struct pcf85363),411				GFP_KERNEL);412	if (!pcf85363)413		return -ENOMEM;414 415	pcf85363->regmap = devm_regmap_init_i2c(client, &config->regmap);416	if (IS_ERR(pcf85363->regmap)) {417		dev_err(&client->dev, "regmap allocation failed\n");418		return PTR_ERR(pcf85363->regmap);419	}420 421	i2c_set_clientdata(client, pcf85363);422 423	pcf85363->rtc = devm_rtc_allocate_device(&client->dev);424	if (IS_ERR(pcf85363->rtc))425		return PTR_ERR(pcf85363->rtc);426 427	err = pcf85363_load_capacitance(pcf85363, client->dev.of_node);428	if (err < 0)429		dev_warn(&client->dev, "failed to set xtal load capacitance: %d",430			 err);431 432	pcf85363->rtc->ops = &rtc_ops;433	pcf85363->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;434	pcf85363->rtc->range_max = RTC_TIMESTAMP_END_2099;435 436	wakeup_source = device_property_read_bool(&client->dev,437						  "wakeup-source");438	if (client->irq > 0 || wakeup_source) {439		regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);440		regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,441				   PIN_IO_INTAPM, PIN_IO_INTA_OUT);442	}443 444	if (client->irq > 0) {445		unsigned long irqflags = IRQF_TRIGGER_LOW;446 447		if (dev_fwnode(&client->dev))448			irqflags = 0;449		ret = devm_request_threaded_irq(&client->dev, client->irq,450						NULL, pcf85363_rtc_handle_irq,451						irqflags | IRQF_ONESHOT,452						"pcf85363", client);453		if (ret) {454			dev_warn(&client->dev,455				 "unable to request IRQ, alarms disabled\n");456			client->irq = 0;457		}458	}459 460	if (client->irq > 0 || wakeup_source) {461		device_init_wakeup(&client->dev, true);462		set_bit(RTC_FEATURE_ALARM, pcf85363->rtc->features);463	} else {464		clear_bit(RTC_FEATURE_ALARM, pcf85363->rtc->features);465	}466 467	ret = devm_rtc_register_device(pcf85363->rtc);468 469	for (i = 0; i < config->num_nvram; i++) {470		nvmem_cfg[i].priv = pcf85363;471		devm_rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg[i]);472	}473 474	return ret;475}476 477static const __maybe_unused struct of_device_id dev_ids[] = {478	{ .compatible = "nxp,pcf85263", .data = &pcf_85263_config },479	{ .compatible = "nxp,pcf85363", .data = &pcf_85363_config },480	{ /* sentinel */ }481};482MODULE_DEVICE_TABLE(of, dev_ids);483 484static struct i2c_driver pcf85363_driver = {485	.driver	= {486		.name	= "pcf85363",487		.of_match_table = of_match_ptr(dev_ids),488	},489	.probe = pcf85363_probe,490};491 492module_i2c_driver(pcf85363_driver);493 494MODULE_AUTHOR("Eric Nelson");495MODULE_DESCRIPTION("pcf85263/pcf85363 I2C RTC driver");496MODULE_LICENSE("GPL");497