cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rtc-pcf8523.c (11915B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2012 Avionic Design GmbH
      4 */
      5
      6#include <linux/bcd.h>
      7#include <linux/bitfield.h>
      8#include <linux/i2c.h>
      9#include <linux/module.h>
     10#include <linux/regmap.h>
     11#include <linux/rtc.h>
     12#include <linux/of.h>
     13#include <linux/pm_wakeirq.h>
     14
     15#define PCF8523_REG_CONTROL1 0x00
     16#define PCF8523_CONTROL1_CAP_SEL BIT(7)
     17#define PCF8523_CONTROL1_STOP    BIT(5)
     18#define PCF8523_CONTROL1_AIE    BIT(1)
     19
     20#define PCF8523_REG_CONTROL2 0x01
     21#define PCF8523_CONTROL2_AF BIT(3)
     22
     23#define PCF8523_REG_CONTROL3 0x02
     24#define PCF8523_CONTROL3_PM  GENMASK(7,5)
     25#define PCF8523_PM_STANDBY   0x7
     26#define PCF8523_CONTROL3_BLF BIT(2) /* battery low bit, read-only */
     27#define PCF8523_CONTROL3_BSF BIT(3)
     28
     29#define PCF8523_REG_SECONDS  0x03
     30#define PCF8523_SECONDS_OS BIT(7)
     31
     32#define PCF8523_REG_MINUTES  0x04
     33#define PCF8523_REG_HOURS    0x05
     34#define PCF8523_REG_DAYS     0x06
     35#define PCF8523_REG_WEEKDAYS 0x07
     36#define PCF8523_REG_MONTHS   0x08
     37#define PCF8523_REG_YEARS    0x09
     38
     39#define PCF8523_REG_MINUTE_ALARM	0x0a
     40#define PCF8523_REG_HOUR_ALARM		0x0b
     41#define PCF8523_REG_DAY_ALARM		0x0c
     42#define PCF8523_REG_WEEKDAY_ALARM	0x0d
     43#define ALARM_DIS BIT(7)
     44
     45#define PCF8523_REG_OFFSET   0x0e
     46#define PCF8523_OFFSET_MODE BIT(7)
     47
     48#define PCF8523_TMR_CLKOUT_CTRL 0x0f
     49
     50struct pcf8523 {
     51	struct rtc_device *rtc;
     52	struct regmap *regmap;
     53};
     54
     55static int pcf8523_load_capacitance(struct pcf8523 *pcf8523, struct device_node *node)
     56{
     57	u32 load, value = 0;
     58
     59	load = 12500;
     60	of_property_read_u32(node, "quartz-load-femtofarads", &load);
     61
     62	switch (load) {
     63	default:
     64		dev_warn(&pcf8523->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500",
     65			 load);
     66		fallthrough;
     67	case 12500:
     68		value |= PCF8523_CONTROL1_CAP_SEL;
     69		break;
     70	case 7000:
     71		break;
     72	}
     73
     74	return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
     75				  PCF8523_CONTROL1_CAP_SEL, value);
     76}
     77
     78static irqreturn_t pcf8523_irq(int irq, void *dev_id)
     79{
     80	struct pcf8523 *pcf8523 = dev_id;
     81	u32 value;
     82	int err;
     83
     84	err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL2, &value);
     85	if (err < 0)
     86		return IRQ_HANDLED;
     87
     88	if (value & PCF8523_CONTROL2_AF) {
     89		value &= ~PCF8523_CONTROL2_AF;
     90		regmap_write(pcf8523->regmap, PCF8523_REG_CONTROL2, value);
     91		rtc_update_irq(pcf8523->rtc, 1, RTC_IRQF | RTC_AF);
     92
     93		return IRQ_HANDLED;
     94	}
     95
     96	return IRQ_NONE;
     97}
     98
     99static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
    100{
    101	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    102	u8 regs[7];
    103	int err;
    104
    105	err = regmap_bulk_read(pcf8523->regmap, PCF8523_REG_SECONDS, regs,
    106			       sizeof(regs));
    107	if (err < 0)
    108		return err;
    109
    110	if (regs[0] & PCF8523_SECONDS_OS)
    111		return -EINVAL;
    112
    113	tm->tm_sec = bcd2bin(regs[0] & 0x7f);
    114	tm->tm_min = bcd2bin(regs[1] & 0x7f);
    115	tm->tm_hour = bcd2bin(regs[2] & 0x3f);
    116	tm->tm_mday = bcd2bin(regs[3] & 0x3f);
    117	tm->tm_wday = regs[4] & 0x7;
    118	tm->tm_mon = bcd2bin(regs[5] & 0x1f) - 1;
    119	tm->tm_year = bcd2bin(regs[6]) + 100;
    120
    121	return 0;
    122}
    123
    124static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
    125{
    126	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    127	u8 regs[7];
    128	int err;
    129
    130	err = regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
    131				 PCF8523_CONTROL1_STOP, PCF8523_CONTROL1_STOP);
    132	if (err < 0)
    133		return err;
    134
    135	/* This will purposely overwrite PCF8523_SECONDS_OS */
    136	regs[0] = bin2bcd(tm->tm_sec);
    137	regs[1] = bin2bcd(tm->tm_min);
    138	regs[2] = bin2bcd(tm->tm_hour);
    139	regs[3] = bin2bcd(tm->tm_mday);
    140	regs[4] = tm->tm_wday;
    141	regs[5] = bin2bcd(tm->tm_mon + 1);
    142	regs[6] = bin2bcd(tm->tm_year - 100);
    143
    144	err = regmap_bulk_write(pcf8523->regmap, PCF8523_REG_SECONDS, regs,
    145				sizeof(regs));
    146	if (err < 0) {
    147		/*
    148		 * If the time cannot be set, restart the RTC anyway. Note
    149		 * that errors are ignored if the RTC cannot be started so
    150		 * that we have a chance to propagate the original error.
    151		 */
    152		regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
    153				   PCF8523_CONTROL1_STOP, 0);
    154		return err;
    155	}
    156
    157	return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
    158				 PCF8523_CONTROL1_STOP, 0);
    159}
    160
    161static int pcf8523_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
    162{
    163	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    164	u8 regs[4];
    165	u32 value;
    166	int err;
    167
    168	err = regmap_bulk_read(pcf8523->regmap, PCF8523_REG_MINUTE_ALARM, regs,
    169			       sizeof(regs));
    170	if (err < 0)
    171		return err;
    172
    173	tm->time.tm_sec = 0;
    174	tm->time.tm_min = bcd2bin(regs[0] & 0x7F);
    175	tm->time.tm_hour = bcd2bin(regs[1] & 0x3F);
    176	tm->time.tm_mday = bcd2bin(regs[2] & 0x3F);
    177	tm->time.tm_wday = bcd2bin(regs[3] & 0x7);
    178
    179	err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL1, &value);
    180	if (err < 0)
    181		return err;
    182	tm->enabled = !!(value & PCF8523_CONTROL1_AIE);
    183
    184	err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL2, &value);
    185	if (err < 0)
    186		return err;
    187	tm->pending = !!(value & PCF8523_CONTROL2_AF);
    188
    189	return 0;
    190}
    191
    192static int pcf8523_irq_enable(struct device *dev, unsigned int enabled)
    193{
    194	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    195
    196	return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL1,
    197				  PCF8523_CONTROL1_AIE, enabled ?
    198				  PCF8523_CONTROL1_AIE : 0);
    199}
    200
    201static int pcf8523_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
    202{
    203	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    204	u8 regs[5];
    205	int err;
    206
    207	err = pcf8523_irq_enable(dev, 0);
    208	if (err)
    209		return err;
    210
    211	err = regmap_write(pcf8523->regmap, PCF8523_REG_CONTROL2, 0);
    212	if (err < 0)
    213		return err;
    214
    215	regs[0] = bin2bcd(tm->time.tm_min);
    216	regs[1] = bin2bcd(tm->time.tm_hour);
    217	regs[2] = bin2bcd(tm->time.tm_mday);
    218	regs[3] = ALARM_DIS;
    219
    220	err = regmap_bulk_write(pcf8523->regmap, PCF8523_REG_MINUTE_ALARM, regs,
    221				sizeof(regs));
    222	if (err < 0)
    223		return err;
    224
    225	if (tm->enabled)
    226		return pcf8523_irq_enable(dev, tm->enabled);
    227
    228	return 0;
    229}
    230
    231static int pcf8523_param_get(struct device *dev, struct rtc_param *param)
    232{
    233	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    234	int ret;
    235	u32 value;
    236
    237	switch(param->param) {
    238
    239	case RTC_PARAM_BACKUP_SWITCH_MODE:
    240		ret = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL3, &value);
    241		if (ret < 0)
    242			return ret;
    243
    244		value = FIELD_GET(PCF8523_CONTROL3_PM, value);
    245
    246		switch(value) {
    247		case 0x0:
    248		case 0x4:
    249			param->uvalue = RTC_BSM_LEVEL;
    250			break;
    251		case 0x1:
    252		case 0x5:
    253			param->uvalue = RTC_BSM_DIRECT;
    254			break;
    255		case PCF8523_PM_STANDBY:
    256			param->uvalue = RTC_BSM_STANDBY;
    257			break;
    258		default:
    259			param->uvalue = RTC_BSM_DISABLED;
    260		}
    261
    262		break;
    263
    264	default:
    265		return -EINVAL;
    266	}
    267
    268	return 0;
    269}
    270
    271static int pcf8523_param_set(struct device *dev, struct rtc_param *param)
    272{
    273	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    274	u8 mode;
    275
    276	switch(param->param) {
    277	case RTC_PARAM_BACKUP_SWITCH_MODE:
    278		switch (param->uvalue) {
    279		case RTC_BSM_DISABLED:
    280			mode = 0x2;
    281			break;
    282		case RTC_BSM_DIRECT:
    283			mode = 0x1;
    284			break;
    285		case RTC_BSM_LEVEL:
    286			mode = 0x0;
    287			break;
    288		case RTC_BSM_STANDBY:
    289			mode = PCF8523_PM_STANDBY;
    290			break;
    291		default:
    292			return -EINVAL;
    293		}
    294
    295		return regmap_update_bits(pcf8523->regmap, PCF8523_REG_CONTROL3,
    296					  PCF8523_CONTROL3_PM,
    297					  FIELD_PREP(PCF8523_CONTROL3_PM, mode));
    298
    299		break;
    300
    301	default:
    302		return -EINVAL;
    303	}
    304
    305	return 0;
    306}
    307
    308static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
    309			     unsigned long arg)
    310{
    311	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    312	unsigned int flags = 0;
    313	u32 value;
    314	int ret;
    315
    316	switch (cmd) {
    317	case RTC_VL_READ:
    318		ret = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL3, &value);
    319		if (ret < 0)
    320			return ret;
    321
    322		if (value & PCF8523_CONTROL3_BLF)
    323			flags |= RTC_VL_BACKUP_LOW;
    324
    325		ret = regmap_read(pcf8523->regmap, PCF8523_REG_SECONDS, &value);
    326		if (ret < 0)
    327			return ret;
    328
    329		if (value & PCF8523_SECONDS_OS)
    330			flags |= RTC_VL_DATA_INVALID;
    331
    332		return put_user(flags, (unsigned int __user *)arg);
    333
    334	default:
    335		return -ENOIOCTLCMD;
    336	}
    337}
    338
    339static int pcf8523_rtc_read_offset(struct device *dev, long *offset)
    340{
    341	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    342	int err;
    343	u32 value;
    344	s8 val;
    345
    346	err = regmap_read(pcf8523->regmap, PCF8523_REG_OFFSET, &value);
    347	if (err < 0)
    348		return err;
    349
    350	/* sign extend the 7-bit offset value */
    351	val = value << 1;
    352	*offset = (value & PCF8523_OFFSET_MODE ? 4069 : 4340) * (val >> 1);
    353
    354	return 0;
    355}
    356
    357static int pcf8523_rtc_set_offset(struct device *dev, long offset)
    358{
    359	struct pcf8523 *pcf8523 = dev_get_drvdata(dev);
    360	long reg_m0, reg_m1;
    361	u32 value;
    362
    363	reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L);
    364	reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L);
    365
    366	if (abs(reg_m0 * 4340 - offset) < abs(reg_m1 * 4069 - offset))
    367		value = reg_m0 & 0x7f;
    368	else
    369		value = (reg_m1 & 0x7f) | PCF8523_OFFSET_MODE;
    370
    371	return regmap_write(pcf8523->regmap, PCF8523_REG_OFFSET, value);
    372}
    373
    374static const struct rtc_class_ops pcf8523_rtc_ops = {
    375	.read_time = pcf8523_rtc_read_time,
    376	.set_time = pcf8523_rtc_set_time,
    377	.read_alarm = pcf8523_rtc_read_alarm,
    378	.set_alarm = pcf8523_rtc_set_alarm,
    379	.alarm_irq_enable = pcf8523_irq_enable,
    380	.ioctl = pcf8523_rtc_ioctl,
    381	.read_offset = pcf8523_rtc_read_offset,
    382	.set_offset = pcf8523_rtc_set_offset,
    383	.param_get = pcf8523_param_get,
    384	.param_set = pcf8523_param_set,
    385};
    386
    387static const struct regmap_config regmap_config = {
    388        .reg_bits = 8,
    389        .val_bits = 8,
    390        .max_register = 0x13,
    391};
    392
    393static int pcf8523_probe(struct i2c_client *client,
    394			 const struct i2c_device_id *id)
    395{
    396	struct pcf8523 *pcf8523;
    397	struct rtc_device *rtc;
    398	bool wakeup_source = false;
    399	u32 value;
    400	int err;
    401
    402	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
    403		return -ENODEV;
    404
    405	pcf8523 = devm_kzalloc(&client->dev, sizeof(struct pcf8523), GFP_KERNEL);
    406	if (!pcf8523)
    407		return -ENOMEM;
    408
    409	pcf8523->regmap = devm_regmap_init_i2c(client, &regmap_config);
    410	if (IS_ERR(pcf8523->regmap))
    411		return PTR_ERR(pcf8523->regmap);
    412
    413	i2c_set_clientdata(client, pcf8523);
    414
    415	rtc = devm_rtc_allocate_device(&client->dev);
    416	if (IS_ERR(rtc))
    417		return PTR_ERR(rtc);
    418	pcf8523->rtc = rtc;
    419
    420	err = pcf8523_load_capacitance(pcf8523, client->dev.of_node);
    421	if (err < 0)
    422		dev_warn(&client->dev, "failed to set xtal load capacitance: %d",
    423			 err);
    424
    425	err = regmap_read(pcf8523->regmap, PCF8523_REG_SECONDS, &value);
    426	if (err < 0)
    427		return err;
    428
    429	if (value & PCF8523_SECONDS_OS) {
    430		err = regmap_read(pcf8523->regmap, PCF8523_REG_CONTROL3, &value);
    431		if (err < 0)
    432			return err;
    433
    434		if (FIELD_GET(PCF8523_CONTROL3_PM, value) == PCF8523_PM_STANDBY) {
    435			err = regmap_write(pcf8523->regmap, PCF8523_REG_CONTROL3,
    436					   value & ~PCF8523_CONTROL3_PM);
    437			if (err < 0)
    438				return err;
    439		}
    440	}
    441
    442	rtc->ops = &pcf8523_rtc_ops;
    443	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
    444	rtc->range_max = RTC_TIMESTAMP_END_2099;
    445	set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features);
    446	clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
    447
    448	if (client->irq > 0) {
    449		err = regmap_write(pcf8523->regmap, PCF8523_TMR_CLKOUT_CTRL, 0x38);
    450		if (err < 0)
    451			return err;
    452
    453		err = devm_request_threaded_irq(&client->dev, client->irq,
    454						NULL, pcf8523_irq,
    455						IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW,
    456						dev_name(&rtc->dev), pcf8523);
    457		if (err)
    458			return err;
    459
    460		dev_pm_set_wake_irq(&client->dev, client->irq);
    461	}
    462
    463	wakeup_source = of_property_read_bool(client->dev.of_node, "wakeup-source");
    464	if (client->irq > 0 || wakeup_source)
    465		device_init_wakeup(&client->dev, true);
    466
    467	return devm_rtc_register_device(rtc);
    468}
    469
    470static const struct i2c_device_id pcf8523_id[] = {
    471	{ "pcf8523", 0 },
    472	{ }
    473};
    474MODULE_DEVICE_TABLE(i2c, pcf8523_id);
    475
    476static const struct of_device_id pcf8523_of_match[] = {
    477	{ .compatible = "nxp,pcf8523" },
    478	{ .compatible = "microcrystal,rv8523" },
    479	{ }
    480};
    481MODULE_DEVICE_TABLE(of, pcf8523_of_match);
    482
    483static struct i2c_driver pcf8523_driver = {
    484	.driver = {
    485		.name = "rtc-pcf8523",
    486		.of_match_table = pcf8523_of_match,
    487	},
    488	.probe = pcf8523_probe,
    489	.id_table = pcf8523_id,
    490};
    491module_i2c_driver(pcf8523_driver);
    492
    493MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
    494MODULE_DESCRIPTION("NXP PCF8523 RTC driver");
    495MODULE_LICENSE("GPL v2");