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-bd70528.c (8960B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2//
      3// Copyright (C) 2018 ROHM Semiconductors
      4//
      5// RTC driver for ROHM BD71828 and BD71815 PMIC
      6
      7#include <linux/bcd.h>
      8#include <linux/mfd/rohm-bd71815.h>
      9#include <linux/mfd/rohm-bd71828.h>
     10#include <linux/module.h>
     11#include <linux/of.h>
     12#include <linux/platform_device.h>
     13#include <linux/regmap.h>
     14#include <linux/rtc.h>
     15
     16/*
     17 * On BD71828 and BD71815 the ALM0 MASK is 14 bytes after the ALM0
     18 * block start
     19 */
     20#define BD718XX_ALM_EN_OFFSET 14
     21
     22/*
     23 * We read regs RTC_SEC => RTC_YEAR
     24 * this struct is ordered according to chip registers.
     25 * Keep it u8 only (or packed) to avoid padding issues.
     26 */
     27struct bd70528_rtc_day {
     28	u8 sec;
     29	u8 min;
     30	u8 hour;
     31} __packed;
     32
     33struct bd70528_rtc_data {
     34	struct bd70528_rtc_day time;
     35	u8 week;
     36	u8 day;
     37	u8 month;
     38	u8 year;
     39} __packed;
     40
     41struct bd71828_rtc_alm {
     42	struct bd70528_rtc_data alm0;
     43	struct bd70528_rtc_data alm1;
     44	u8 alm_mask;
     45	u8 alm1_mask;
     46} __packed;
     47
     48struct bd70528_rtc {
     49	struct rohm_regmap_dev *parent;
     50	struct regmap *regmap;
     51	struct device *dev;
     52	u8 reg_time_start;
     53	u8 bd718xx_alm_block_start;
     54};
     55
     56static inline void tmday2rtc(struct rtc_time *t, struct bd70528_rtc_day *d)
     57{
     58	d->sec &= ~BD70528_MASK_RTC_SEC;
     59	d->min &= ~BD70528_MASK_RTC_MINUTE;
     60	d->hour &= ~BD70528_MASK_RTC_HOUR;
     61	d->sec |= bin2bcd(t->tm_sec);
     62	d->min |= bin2bcd(t->tm_min);
     63	d->hour |= bin2bcd(t->tm_hour);
     64}
     65
     66static inline void tm2rtc(struct rtc_time *t, struct bd70528_rtc_data *r)
     67{
     68	r->day &= ~BD70528_MASK_RTC_DAY;
     69	r->week &= ~BD70528_MASK_RTC_WEEK;
     70	r->month &= ~BD70528_MASK_RTC_MONTH;
     71	/*
     72	 * PM and 24H bits are not used by Wake - thus we clear them
     73	 * here and not in tmday2rtc() which is also used by wake.
     74	 */
     75	r->time.hour &= ~(BD70528_MASK_RTC_HOUR_PM | BD70528_MASK_RTC_HOUR_24H);
     76
     77	tmday2rtc(t, &r->time);
     78	/*
     79	 * We do always set time in 24H mode.
     80	 */
     81	r->time.hour |= BD70528_MASK_RTC_HOUR_24H;
     82	r->day |= bin2bcd(t->tm_mday);
     83	r->week |= bin2bcd(t->tm_wday);
     84	r->month |= bin2bcd(t->tm_mon + 1);
     85	r->year = bin2bcd(t->tm_year - 100);
     86}
     87
     88static inline void rtc2tm(struct bd70528_rtc_data *r, struct rtc_time *t)
     89{
     90	t->tm_sec = bcd2bin(r->time.sec & BD70528_MASK_RTC_SEC);
     91	t->tm_min = bcd2bin(r->time.min & BD70528_MASK_RTC_MINUTE);
     92	t->tm_hour = bcd2bin(r->time.hour & BD70528_MASK_RTC_HOUR);
     93	/*
     94	 * If RTC is in 12H mode, then bit BD70528_MASK_RTC_HOUR_PM
     95	 * is not BCD value but tells whether it is AM or PM
     96	 */
     97	if (!(r->time.hour & BD70528_MASK_RTC_HOUR_24H)) {
     98		t->tm_hour %= 12;
     99		if (r->time.hour & BD70528_MASK_RTC_HOUR_PM)
    100			t->tm_hour += 12;
    101	}
    102	t->tm_mday = bcd2bin(r->day & BD70528_MASK_RTC_DAY);
    103	t->tm_mon = bcd2bin(r->month & BD70528_MASK_RTC_MONTH) - 1;
    104	t->tm_year = 100 + bcd2bin(r->year & BD70528_MASK_RTC_YEAR);
    105	t->tm_wday = bcd2bin(r->week & BD70528_MASK_RTC_WEEK);
    106}
    107
    108static int bd71828_set_alarm(struct device *dev, struct rtc_wkalrm *a)
    109{
    110	int ret;
    111	struct bd71828_rtc_alm alm;
    112	struct bd70528_rtc *r = dev_get_drvdata(dev);
    113
    114	ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm,
    115			       sizeof(alm));
    116	if (ret) {
    117		dev_err(dev, "Failed to read alarm regs\n");
    118		return ret;
    119	}
    120
    121	tm2rtc(&a->time, &alm.alm0);
    122
    123	if (!a->enabled)
    124		alm.alm_mask &= ~BD70528_MASK_ALM_EN;
    125	else
    126		alm.alm_mask |= BD70528_MASK_ALM_EN;
    127
    128	ret = regmap_bulk_write(r->regmap, r->bd718xx_alm_block_start, &alm,
    129				sizeof(alm));
    130	if (ret)
    131		dev_err(dev, "Failed to set alarm time\n");
    132
    133	return ret;
    134
    135}
    136
    137static int bd71828_read_alarm(struct device *dev, struct rtc_wkalrm *a)
    138{
    139	int ret;
    140	struct bd71828_rtc_alm alm;
    141	struct bd70528_rtc *r = dev_get_drvdata(dev);
    142
    143	ret = regmap_bulk_read(r->regmap, r->bd718xx_alm_block_start, &alm,
    144			       sizeof(alm));
    145	if (ret) {
    146		dev_err(dev, "Failed to read alarm regs\n");
    147		return ret;
    148	}
    149
    150	rtc2tm(&alm.alm0, &a->time);
    151	a->time.tm_mday = -1;
    152	a->time.tm_mon = -1;
    153	a->time.tm_year = -1;
    154	a->enabled = !!(alm.alm_mask & BD70528_MASK_ALM_EN);
    155	a->pending = 0;
    156
    157	return 0;
    158}
    159
    160static int bd71828_set_time(struct device *dev, struct rtc_time *t)
    161{
    162	int ret;
    163	struct bd70528_rtc_data rtc_data;
    164	struct bd70528_rtc *r = dev_get_drvdata(dev);
    165
    166	ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,
    167			       sizeof(rtc_data));
    168	if (ret) {
    169		dev_err(dev, "Failed to read RTC time registers\n");
    170		return ret;
    171	}
    172	tm2rtc(t, &rtc_data);
    173
    174	ret = regmap_bulk_write(r->regmap, r->reg_time_start, &rtc_data,
    175				sizeof(rtc_data));
    176	if (ret)
    177		dev_err(dev, "Failed to set RTC time\n");
    178
    179	return ret;
    180}
    181
    182static int bd70528_get_time(struct device *dev, struct rtc_time *t)
    183{
    184	struct bd70528_rtc *r = dev_get_drvdata(dev);
    185	struct bd70528_rtc_data rtc_data;
    186	int ret;
    187
    188	/* read the RTC date and time registers all at once */
    189	ret = regmap_bulk_read(r->regmap, r->reg_time_start, &rtc_data,
    190			       sizeof(rtc_data));
    191	if (ret) {
    192		dev_err(dev, "Failed to read RTC time (err %d)\n", ret);
    193		return ret;
    194	}
    195
    196	rtc2tm(&rtc_data, t);
    197
    198	return 0;
    199}
    200
    201static int bd71828_alm_enable(struct device *dev, unsigned int enabled)
    202{
    203	int ret;
    204	struct bd70528_rtc *r = dev_get_drvdata(dev);
    205	unsigned int enableval = BD70528_MASK_ALM_EN;
    206
    207	if (!enabled)
    208		enableval = 0;
    209
    210	ret = regmap_update_bits(r->regmap, r->bd718xx_alm_block_start +
    211				 BD718XX_ALM_EN_OFFSET, BD70528_MASK_ALM_EN,
    212				 enableval);
    213	if (ret)
    214		dev_err(dev, "Failed to change alarm state\n");
    215
    216	return ret;
    217}
    218
    219static const struct rtc_class_ops bd71828_rtc_ops = {
    220	.read_time		= bd70528_get_time,
    221	.set_time		= bd71828_set_time,
    222	.read_alarm		= bd71828_read_alarm,
    223	.set_alarm		= bd71828_set_alarm,
    224	.alarm_irq_enable	= bd71828_alm_enable,
    225};
    226
    227static irqreturn_t alm_hndlr(int irq, void *data)
    228{
    229	struct rtc_device *rtc = data;
    230
    231	rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF | RTC_PF);
    232	return IRQ_HANDLED;
    233}
    234
    235static int bd70528_probe(struct platform_device *pdev)
    236{
    237	struct bd70528_rtc *bd_rtc;
    238	const struct rtc_class_ops *rtc_ops;
    239	const char *irq_name;
    240	int ret;
    241	struct rtc_device *rtc;
    242	int irq;
    243	unsigned int hr;
    244	u8 hour_reg;
    245	enum rohm_chip_type chip = platform_get_device_id(pdev)->driver_data;
    246
    247	bd_rtc = devm_kzalloc(&pdev->dev, sizeof(*bd_rtc), GFP_KERNEL);
    248	if (!bd_rtc)
    249		return -ENOMEM;
    250
    251	bd_rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
    252	if (!bd_rtc->regmap) {
    253		dev_err(&pdev->dev, "No regmap\n");
    254		return -EINVAL;
    255	}
    256
    257	bd_rtc->dev = &pdev->dev;
    258	rtc_ops = &bd71828_rtc_ops;
    259
    260	switch (chip) {
    261	case ROHM_CHIP_TYPE_BD71815:
    262		irq_name = "bd71815-rtc-alm-0";
    263		bd_rtc->reg_time_start = BD71815_REG_RTC_START;
    264
    265		/*
    266		 * See also BD718XX_ALM_EN_OFFSET:
    267		 * This works for BD71828 and BD71815 as they have same offset
    268		 * between ALM0 start and ALM0_MASK. If new ICs are to be
    269		 * added this requires proper check as ALM0_MASK is not located
    270		 * at the end of ALM0 block - but after all ALM blocks so if
    271		 * amount of ALMs differ the offset to enable/disable is likely
    272		 * to be incorrect and enable/disable must be given as own
    273		 * reg address here.
    274		 */
    275		bd_rtc->bd718xx_alm_block_start = BD71815_REG_RTC_ALM_START;
    276		hour_reg = BD71815_REG_HOUR;
    277		break;
    278	case ROHM_CHIP_TYPE_BD71828:
    279		irq_name = "bd71828-rtc-alm-0";
    280		bd_rtc->reg_time_start = BD71828_REG_RTC_START;
    281		bd_rtc->bd718xx_alm_block_start = BD71828_REG_RTC_ALM_START;
    282		hour_reg = BD71828_REG_RTC_HOUR;
    283		break;
    284	default:
    285		dev_err(&pdev->dev, "Unknown chip\n");
    286		return -ENOENT;
    287	}
    288
    289	irq = platform_get_irq_byname(pdev, irq_name);
    290
    291	if (irq < 0)
    292		return irq;
    293
    294	platform_set_drvdata(pdev, bd_rtc);
    295
    296	ret = regmap_read(bd_rtc->regmap, hour_reg, &hr);
    297
    298	if (ret) {
    299		dev_err(&pdev->dev, "Failed to reag RTC clock\n");
    300		return ret;
    301	}
    302
    303	if (!(hr & BD70528_MASK_RTC_HOUR_24H)) {
    304		struct rtc_time t;
    305
    306		ret = rtc_ops->read_time(&pdev->dev, &t);
    307
    308		if (!ret)
    309			ret = rtc_ops->set_time(&pdev->dev, &t);
    310
    311		if (ret) {
    312			dev_err(&pdev->dev,
    313				"Setting 24H clock for RTC failed\n");
    314			return ret;
    315		}
    316	}
    317
    318	device_set_wakeup_capable(&pdev->dev, true);
    319	device_wakeup_enable(&pdev->dev);
    320
    321	rtc = devm_rtc_allocate_device(&pdev->dev);
    322	if (IS_ERR(rtc)) {
    323		dev_err(&pdev->dev, "RTC device creation failed\n");
    324		return PTR_ERR(rtc);
    325	}
    326
    327	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
    328	rtc->range_max = RTC_TIMESTAMP_END_2099;
    329	rtc->ops = rtc_ops;
    330
    331	/* Request alarm IRQ prior to registerig the RTC */
    332	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, &alm_hndlr,
    333					IRQF_ONESHOT, "bd70528-rtc", rtc);
    334	if (ret)
    335		return ret;
    336
    337	return devm_rtc_register_device(rtc);
    338}
    339
    340static const struct platform_device_id bd718x7_rtc_id[] = {
    341	{ "bd71828-rtc", ROHM_CHIP_TYPE_BD71828 },
    342	{ "bd71815-rtc", ROHM_CHIP_TYPE_BD71815 },
    343	{ },
    344};
    345MODULE_DEVICE_TABLE(platform, bd718x7_rtc_id);
    346
    347static struct platform_driver bd70528_rtc = {
    348	.driver = {
    349		.name = "bd70528-rtc"
    350	},
    351	.probe = bd70528_probe,
    352	.id_table = bd718x7_rtc_id,
    353};
    354
    355module_platform_driver(bd70528_rtc);
    356
    357MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
    358MODULE_DESCRIPTION("ROHM BD71828 and BD71815 PMIC RTC driver");
    359MODULE_LICENSE("GPL");
    360MODULE_ALIAS("platform:bd70528-rtc");