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-pcf85363.c (10742B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * drivers/rtc/rtc-pcf85363.c
      4 *
      5 * Driver for NXP PCF85363 real-time clock.
      6 *
      7 * Copyright (C) 2017 Eric Nelson
      8 */
      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/of_device.h>
     19#include <linux/regmap.h>
     20
     21/*
     22 * Date/Time registers
     23 */
     24#define DT_100THS	0x00
     25#define DT_SECS		0x01
     26#define DT_MINUTES	0x02
     27#define DT_HOURS	0x03
     28#define DT_DAYS		0x04
     29#define DT_WEEKDAYS	0x05
     30#define DT_MONTHS	0x06
     31#define DT_YEARS	0x07
     32
     33/*
     34 * Alarm registers
     35 */
     36#define DT_SECOND_ALM1	0x08
     37#define DT_MINUTE_ALM1	0x09
     38#define DT_HOUR_ALM1	0x0a
     39#define DT_DAY_ALM1	0x0b
     40#define DT_MONTH_ALM1	0x0c
     41#define DT_MINUTE_ALM2	0x0d
     42#define DT_HOUR_ALM2	0x0e
     43#define DT_WEEKDAY_ALM2	0x0f
     44#define DT_ALARM_EN	0x10
     45
     46/*
     47 * Time stamp registers
     48 */
     49#define DT_TIMESTAMP1	0x11
     50#define DT_TIMESTAMP2	0x17
     51#define DT_TIMESTAMP3	0x1d
     52#define DT_TS_MODE	0x23
     53
     54/*
     55 * control registers
     56 */
     57#define CTRL_OFFSET	0x24
     58#define CTRL_OSCILLATOR	0x25
     59#define CTRL_BATTERY	0x26
     60#define CTRL_PIN_IO	0x27
     61#define CTRL_FUNCTION	0x28
     62#define CTRL_INTA_EN	0x29
     63#define CTRL_INTB_EN	0x2a
     64#define CTRL_FLAGS	0x2b
     65#define CTRL_RAMBYTE	0x2c
     66#define CTRL_WDOG	0x2d
     67#define CTRL_STOP_EN	0x2e
     68#define CTRL_RESETS	0x2f
     69#define CTRL_RAM	0x40
     70
     71#define ALRM_SEC_A1E	BIT(0)
     72#define ALRM_MIN_A1E	BIT(1)
     73#define ALRM_HR_A1E	BIT(2)
     74#define ALRM_DAY_A1E	BIT(3)
     75#define ALRM_MON_A1E	BIT(4)
     76#define ALRM_MIN_A2E	BIT(5)
     77#define ALRM_HR_A2E	BIT(6)
     78#define ALRM_DAY_A2E	BIT(7)
     79
     80#define INT_WDIE	BIT(0)
     81#define INT_BSIE	BIT(1)
     82#define INT_TSRIE	BIT(2)
     83#define INT_A2IE	BIT(3)
     84#define INT_A1IE	BIT(4)
     85#define INT_OIE		BIT(5)
     86#define INT_PIE		BIT(6)
     87#define INT_ILP		BIT(7)
     88
     89#define FLAGS_TSR1F	BIT(0)
     90#define FLAGS_TSR2F	BIT(1)
     91#define FLAGS_TSR3F	BIT(2)
     92#define FLAGS_BSF	BIT(3)
     93#define FLAGS_WDF	BIT(4)
     94#define FLAGS_A1F	BIT(5)
     95#define FLAGS_A2F	BIT(6)
     96#define FLAGS_PIF	BIT(7)
     97
     98#define PIN_IO_INTAPM	GENMASK(1, 0)
     99#define PIN_IO_INTA_CLK	0
    100#define PIN_IO_INTA_BAT	1
    101#define PIN_IO_INTA_OUT	2
    102#define PIN_IO_INTA_HIZ	3
    103
    104#define STOP_EN_STOP	BIT(0)
    105
    106#define RESET_CPR	0xa4
    107
    108#define NVRAM_SIZE	0x40
    109
    110struct pcf85363 {
    111	struct rtc_device	*rtc;
    112	struct regmap		*regmap;
    113};
    114
    115struct pcf85x63_config {
    116	struct regmap_config regmap;
    117	unsigned int num_nvram;
    118};
    119
    120static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm)
    121{
    122	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
    123	unsigned char buf[DT_YEARS + 1];
    124	int ret, len = sizeof(buf);
    125
    126	/* read the RTC date and time registers all at once */
    127	ret = regmap_bulk_read(pcf85363->regmap, DT_100THS, buf, len);
    128	if (ret) {
    129		dev_err(dev, "%s: error %d\n", __func__, ret);
    130		return ret;
    131	}
    132
    133	tm->tm_year = bcd2bin(buf[DT_YEARS]);
    134	/* adjust for 1900 base of rtc_time */
    135	tm->tm_year += 100;
    136
    137	tm->tm_wday = buf[DT_WEEKDAYS] & 7;
    138	buf[DT_SECS] &= 0x7F;
    139	tm->tm_sec = bcd2bin(buf[DT_SECS]);
    140	buf[DT_MINUTES] &= 0x7F;
    141	tm->tm_min = bcd2bin(buf[DT_MINUTES]);
    142	tm->tm_hour = bcd2bin(buf[DT_HOURS]);
    143	tm->tm_mday = bcd2bin(buf[DT_DAYS]);
    144	tm->tm_mon = bcd2bin(buf[DT_MONTHS]) - 1;
    145
    146	return 0;
    147}
    148
    149static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm)
    150{
    151	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
    152	unsigned char tmp[11];
    153	unsigned char *buf = &tmp[2];
    154	int ret;
    155
    156	tmp[0] = STOP_EN_STOP;
    157	tmp[1] = RESET_CPR;
    158
    159	buf[DT_100THS] = 0;
    160	buf[DT_SECS] = bin2bcd(tm->tm_sec);
    161	buf[DT_MINUTES] = bin2bcd(tm->tm_min);
    162	buf[DT_HOURS] = bin2bcd(tm->tm_hour);
    163	buf[DT_DAYS] = bin2bcd(tm->tm_mday);
    164	buf[DT_WEEKDAYS] = tm->tm_wday;
    165	buf[DT_MONTHS] = bin2bcd(tm->tm_mon + 1);
    166	buf[DT_YEARS] = bin2bcd(tm->tm_year % 100);
    167
    168	ret = regmap_bulk_write(pcf85363->regmap, CTRL_STOP_EN,
    169				tmp, 2);
    170	if (ret)
    171		return ret;
    172
    173	ret = regmap_bulk_write(pcf85363->regmap, DT_100THS,
    174				buf, sizeof(tmp) - 2);
    175	if (ret)
    176		return ret;
    177
    178	return regmap_write(pcf85363->regmap, CTRL_STOP_EN, 0);
    179}
    180
    181static int pcf85363_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
    182{
    183	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
    184	unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1];
    185	unsigned int val;
    186	int ret;
    187
    188	ret = regmap_bulk_read(pcf85363->regmap, DT_SECOND_ALM1, buf,
    189			       sizeof(buf));
    190	if (ret)
    191		return ret;
    192
    193	alrm->time.tm_sec = bcd2bin(buf[0]);
    194	alrm->time.tm_min = bcd2bin(buf[1]);
    195	alrm->time.tm_hour = bcd2bin(buf[2]);
    196	alrm->time.tm_mday = bcd2bin(buf[3]);
    197	alrm->time.tm_mon = bcd2bin(buf[4]) - 1;
    198
    199	ret = regmap_read(pcf85363->regmap, CTRL_INTA_EN, &val);
    200	if (ret)
    201		return ret;
    202
    203	alrm->enabled =  !!(val & INT_A1IE);
    204
    205	return 0;
    206}
    207
    208static int _pcf85363_rtc_alarm_irq_enable(struct pcf85363 *pcf85363, unsigned
    209					  int enabled)
    210{
    211	unsigned int alarm_flags = ALRM_SEC_A1E | ALRM_MIN_A1E | ALRM_HR_A1E |
    212				   ALRM_DAY_A1E | ALRM_MON_A1E;
    213	int ret;
    214
    215	ret = regmap_update_bits(pcf85363->regmap, DT_ALARM_EN, alarm_flags,
    216				 enabled ? alarm_flags : 0);
    217	if (ret)
    218		return ret;
    219
    220	ret = regmap_update_bits(pcf85363->regmap, CTRL_INTA_EN,
    221				 INT_A1IE, enabled ? INT_A1IE : 0);
    222
    223	if (ret || enabled)
    224		return ret;
    225
    226	/* clear current flags */
    227	return regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0);
    228}
    229
    230static int pcf85363_rtc_alarm_irq_enable(struct device *dev,
    231					 unsigned int enabled)
    232{
    233	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
    234
    235	return _pcf85363_rtc_alarm_irq_enable(pcf85363, enabled);
    236}
    237
    238static int pcf85363_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
    239{
    240	struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
    241	unsigned char buf[DT_MONTH_ALM1 - DT_SECOND_ALM1 + 1];
    242	int ret;
    243
    244	buf[0] = bin2bcd(alrm->time.tm_sec);
    245	buf[1] = bin2bcd(alrm->time.tm_min);
    246	buf[2] = bin2bcd(alrm->time.tm_hour);
    247	buf[3] = bin2bcd(alrm->time.tm_mday);
    248	buf[4] = bin2bcd(alrm->time.tm_mon + 1);
    249
    250	/*
    251	 * Disable the alarm interrupt before changing the value to avoid
    252	 * spurious interrupts
    253	 */
    254	ret = _pcf85363_rtc_alarm_irq_enable(pcf85363, 0);
    255	if (ret)
    256		return ret;
    257
    258	ret = regmap_bulk_write(pcf85363->regmap, DT_SECOND_ALM1, buf,
    259				sizeof(buf));
    260	if (ret)
    261		return ret;
    262
    263	return _pcf85363_rtc_alarm_irq_enable(pcf85363, alrm->enabled);
    264}
    265
    266static irqreturn_t pcf85363_rtc_handle_irq(int irq, void *dev_id)
    267{
    268	struct pcf85363 *pcf85363 = i2c_get_clientdata(dev_id);
    269	unsigned int flags;
    270	int err;
    271
    272	err = regmap_read(pcf85363->regmap, CTRL_FLAGS, &flags);
    273	if (err)
    274		return IRQ_NONE;
    275
    276	if (flags & FLAGS_A1F) {
    277		rtc_update_irq(pcf85363->rtc, 1, RTC_IRQF | RTC_AF);
    278		regmap_update_bits(pcf85363->regmap, CTRL_FLAGS, FLAGS_A1F, 0);
    279		return IRQ_HANDLED;
    280	}
    281
    282	return IRQ_NONE;
    283}
    284
    285static const struct rtc_class_ops rtc_ops = {
    286	.read_time	= pcf85363_rtc_read_time,
    287	.set_time	= pcf85363_rtc_set_time,
    288	.read_alarm	= pcf85363_rtc_read_alarm,
    289	.set_alarm	= pcf85363_rtc_set_alarm,
    290	.alarm_irq_enable = pcf85363_rtc_alarm_irq_enable,
    291};
    292
    293static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val,
    294			       size_t bytes)
    295{
    296	struct pcf85363 *pcf85363 = priv;
    297
    298	return regmap_bulk_read(pcf85363->regmap, CTRL_RAM + offset,
    299				val, bytes);
    300}
    301
    302static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val,
    303				size_t bytes)
    304{
    305	struct pcf85363 *pcf85363 = priv;
    306
    307	return regmap_bulk_write(pcf85363->regmap, CTRL_RAM + offset,
    308				 val, bytes);
    309}
    310
    311static int pcf85x63_nvram_read(void *priv, unsigned int offset, void *val,
    312			       size_t bytes)
    313{
    314	struct pcf85363 *pcf85363 = priv;
    315	unsigned int tmp_val;
    316	int ret;
    317
    318	ret = regmap_read(pcf85363->regmap, CTRL_RAMBYTE, &tmp_val);
    319	(*(unsigned char *) val) = (unsigned char) tmp_val;
    320
    321	return ret;
    322}
    323
    324static int pcf85x63_nvram_write(void *priv, unsigned int offset, void *val,
    325				size_t bytes)
    326{
    327	struct pcf85363 *pcf85363 = priv;
    328	unsigned char tmp_val;
    329
    330	tmp_val = *((unsigned char *)val);
    331	return regmap_write(pcf85363->regmap, CTRL_RAMBYTE,
    332				(unsigned int)tmp_val);
    333}
    334
    335static const struct pcf85x63_config pcf_85263_config = {
    336	.regmap = {
    337		.reg_bits = 8,
    338		.val_bits = 8,
    339		.max_register = 0x2f,
    340	},
    341	.num_nvram = 1
    342};
    343
    344static const struct pcf85x63_config pcf_85363_config = {
    345	.regmap = {
    346		.reg_bits = 8,
    347		.val_bits = 8,
    348		.max_register = 0x7f,
    349	},
    350	.num_nvram = 2
    351};
    352
    353static int pcf85363_probe(struct i2c_client *client,
    354			  const struct i2c_device_id *id)
    355{
    356	struct pcf85363 *pcf85363;
    357	const struct pcf85x63_config *config = &pcf_85363_config;
    358	const void *data = of_device_get_match_data(&client->dev);
    359	static struct nvmem_config nvmem_cfg[] = {
    360		{
    361			.name = "pcf85x63-",
    362			.word_size = 1,
    363			.stride = 1,
    364			.size = 1,
    365			.reg_read = pcf85x63_nvram_read,
    366			.reg_write = pcf85x63_nvram_write,
    367		}, {
    368			.name = "pcf85363-",
    369			.word_size = 1,
    370			.stride = 1,
    371			.size = NVRAM_SIZE,
    372			.reg_read = pcf85363_nvram_read,
    373			.reg_write = pcf85363_nvram_write,
    374		},
    375	};
    376	int ret, i;
    377
    378	if (data)
    379		config = data;
    380
    381	pcf85363 = devm_kzalloc(&client->dev, sizeof(struct pcf85363),
    382				GFP_KERNEL);
    383	if (!pcf85363)
    384		return -ENOMEM;
    385
    386	pcf85363->regmap = devm_regmap_init_i2c(client, &config->regmap);
    387	if (IS_ERR(pcf85363->regmap)) {
    388		dev_err(&client->dev, "regmap allocation failed\n");
    389		return PTR_ERR(pcf85363->regmap);
    390	}
    391
    392	i2c_set_clientdata(client, pcf85363);
    393
    394	pcf85363->rtc = devm_rtc_allocate_device(&client->dev);
    395	if (IS_ERR(pcf85363->rtc))
    396		return PTR_ERR(pcf85363->rtc);
    397
    398	pcf85363->rtc->ops = &rtc_ops;
    399	pcf85363->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
    400	pcf85363->rtc->range_max = RTC_TIMESTAMP_END_2099;
    401	clear_bit(RTC_FEATURE_ALARM, pcf85363->rtc->features);
    402
    403	if (client->irq > 0) {
    404		regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
    405		regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
    406				   PIN_IO_INTA_OUT, PIN_IO_INTAPM);
    407		ret = devm_request_threaded_irq(&client->dev, client->irq,
    408						NULL, pcf85363_rtc_handle_irq,
    409						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
    410						"pcf85363", client);
    411		if (ret)
    412			dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
    413		else
    414			set_bit(RTC_FEATURE_ALARM, pcf85363->rtc->features);
    415	}
    416
    417	ret = devm_rtc_register_device(pcf85363->rtc);
    418
    419	for (i = 0; i < config->num_nvram; i++) {
    420		nvmem_cfg[i].priv = pcf85363;
    421		devm_rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg[i]);
    422	}
    423
    424	return ret;
    425}
    426
    427static const __maybe_unused struct of_device_id dev_ids[] = {
    428	{ .compatible = "nxp,pcf85263", .data = &pcf_85263_config },
    429	{ .compatible = "nxp,pcf85363", .data = &pcf_85363_config },
    430	{ /* sentinel */ }
    431};
    432MODULE_DEVICE_TABLE(of, dev_ids);
    433
    434static struct i2c_driver pcf85363_driver = {
    435	.driver	= {
    436		.name	= "pcf85363",
    437		.of_match_table = of_match_ptr(dev_ids),
    438	},
    439	.probe	= pcf85363_probe,
    440};
    441
    442module_i2c_driver(pcf85363_driver);
    443
    444MODULE_AUTHOR("Eric Nelson");
    445MODULE_DESCRIPTION("pcf85263/pcf85363 I2C RTC driver");
    446MODULE_LICENSE("GPL");