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-pl031.c (12310B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * drivers/rtc/rtc-pl031.c
      4 *
      5 * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC
      6 *
      7 * Author: Deepak Saxena <dsaxena@plexity.net>
      8 *
      9 * Copyright 2006 (c) MontaVista Software, Inc.
     10 *
     11 * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
     12 * Copyright 2010 (c) ST-Ericsson AB
     13 */
     14#include <linux/module.h>
     15#include <linux/rtc.h>
     16#include <linux/init.h>
     17#include <linux/interrupt.h>
     18#include <linux/amba/bus.h>
     19#include <linux/io.h>
     20#include <linux/bcd.h>
     21#include <linux/delay.h>
     22#include <linux/pm_wakeirq.h>
     23#include <linux/slab.h>
     24
     25/*
     26 * Register definitions
     27 */
     28#define	RTC_DR		0x00	/* Data read register */
     29#define	RTC_MR		0x04	/* Match register */
     30#define	RTC_LR		0x08	/* Data load register */
     31#define	RTC_CR		0x0c	/* Control register */
     32#define	RTC_IMSC	0x10	/* Interrupt mask and set register */
     33#define	RTC_RIS		0x14	/* Raw interrupt status register */
     34#define	RTC_MIS		0x18	/* Masked interrupt status register */
     35#define	RTC_ICR		0x1c	/* Interrupt clear register */
     36/* ST variants have additional timer functionality */
     37#define RTC_TDR		0x20	/* Timer data read register */
     38#define RTC_TLR		0x24	/* Timer data load register */
     39#define RTC_TCR		0x28	/* Timer control register */
     40#define RTC_YDR		0x30	/* Year data read register */
     41#define RTC_YMR		0x34	/* Year match register */
     42#define RTC_YLR		0x38	/* Year data load register */
     43
     44#define RTC_CR_EN	(1 << 0)	/* counter enable bit */
     45#define RTC_CR_CWEN	(1 << 26)	/* Clockwatch enable bit */
     46
     47#define RTC_TCR_EN	(1 << 1) /* Periodic timer enable bit */
     48
     49/* Common bit definitions for Interrupt status and control registers */
     50#define RTC_BIT_AI	(1 << 0) /* Alarm interrupt bit */
     51#define RTC_BIT_PI	(1 << 1) /* Periodic interrupt bit. ST variants only. */
     52
     53/* Common bit definations for ST v2 for reading/writing time */
     54#define RTC_SEC_SHIFT 0
     55#define RTC_SEC_MASK (0x3F << RTC_SEC_SHIFT) /* Second [0-59] */
     56#define RTC_MIN_SHIFT 6
     57#define RTC_MIN_MASK (0x3F << RTC_MIN_SHIFT) /* Minute [0-59] */
     58#define RTC_HOUR_SHIFT 12
     59#define RTC_HOUR_MASK (0x1F << RTC_HOUR_SHIFT) /* Hour [0-23] */
     60#define RTC_WDAY_SHIFT 17
     61#define RTC_WDAY_MASK (0x7 << RTC_WDAY_SHIFT) /* Day of Week [1-7] 1=Sunday */
     62#define RTC_MDAY_SHIFT 20
     63#define RTC_MDAY_MASK (0x1F << RTC_MDAY_SHIFT) /* Day of Month [1-31] */
     64#define RTC_MON_SHIFT 25
     65#define RTC_MON_MASK (0xF << RTC_MON_SHIFT) /* Month [1-12] 1=January */
     66
     67#define RTC_TIMER_FREQ 32768
     68
     69/**
     70 * struct pl031_vendor_data - per-vendor variations
     71 * @ops: the vendor-specific operations used on this silicon version
     72 * @clockwatch: if this is an ST Microelectronics silicon version with a
     73 *	clockwatch function
     74 * @st_weekday: if this is an ST Microelectronics silicon version that need
     75 *	the weekday fix
     76 * @irqflags: special IRQ flags per variant
     77 */
     78struct pl031_vendor_data {
     79	struct rtc_class_ops ops;
     80	bool clockwatch;
     81	bool st_weekday;
     82	unsigned long irqflags;
     83	time64_t range_min;
     84	timeu64_t range_max;
     85};
     86
     87struct pl031_local {
     88	struct pl031_vendor_data *vendor;
     89	struct rtc_device *rtc;
     90	void __iomem *base;
     91};
     92
     93static int pl031_alarm_irq_enable(struct device *dev,
     94	unsigned int enabled)
     95{
     96	struct pl031_local *ldata = dev_get_drvdata(dev);
     97	unsigned long imsc;
     98
     99	/* Clear any pending alarm interrupts. */
    100	writel(RTC_BIT_AI, ldata->base + RTC_ICR);
    101
    102	imsc = readl(ldata->base + RTC_IMSC);
    103
    104	if (enabled == 1)
    105		writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC);
    106	else
    107		writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC);
    108
    109	return 0;
    110}
    111
    112/*
    113 * Convert Gregorian date to ST v2 RTC format.
    114 */
    115static int pl031_stv2_tm_to_time(struct device *dev,
    116				 struct rtc_time *tm, unsigned long *st_time,
    117	unsigned long *bcd_year)
    118{
    119	int year = tm->tm_year + 1900;
    120	int wday = tm->tm_wday;
    121
    122	/* wday masking is not working in hardware so wday must be valid */
    123	if (wday < -1 || wday > 6) {
    124		dev_err(dev, "invalid wday value %d\n", tm->tm_wday);
    125		return -EINVAL;
    126	} else if (wday == -1) {
    127		/* wday is not provided, calculate it here */
    128		struct rtc_time calc_tm;
    129
    130		rtc_time64_to_tm(rtc_tm_to_time64(tm), &calc_tm);
    131		wday = calc_tm.tm_wday;
    132	}
    133
    134	*bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8);
    135
    136	*st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT)
    137			|	(tm->tm_mday << RTC_MDAY_SHIFT)
    138			|	((wday + 1) << RTC_WDAY_SHIFT)
    139			|	(tm->tm_hour << RTC_HOUR_SHIFT)
    140			|	(tm->tm_min << RTC_MIN_SHIFT)
    141			|	(tm->tm_sec << RTC_SEC_SHIFT);
    142
    143	return 0;
    144}
    145
    146/*
    147 * Convert ST v2 RTC format to Gregorian date.
    148 */
    149static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year,
    150	struct rtc_time *tm)
    151{
    152	tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100);
    153	tm->tm_mon  = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1;
    154	tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT);
    155	tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1;
    156	tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT);
    157	tm->tm_min  = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT);
    158	tm->tm_sec  = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT);
    159
    160	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
    161	tm->tm_year -= 1900;
    162
    163	return 0;
    164}
    165
    166static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm)
    167{
    168	struct pl031_local *ldata = dev_get_drvdata(dev);
    169
    170	pl031_stv2_time_to_tm(readl(ldata->base + RTC_DR),
    171			readl(ldata->base + RTC_YDR), tm);
    172
    173	return 0;
    174}
    175
    176static int pl031_stv2_set_time(struct device *dev, struct rtc_time *tm)
    177{
    178	unsigned long time;
    179	unsigned long bcd_year;
    180	struct pl031_local *ldata = dev_get_drvdata(dev);
    181	int ret;
    182
    183	ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year);
    184	if (ret == 0) {
    185		writel(bcd_year, ldata->base + RTC_YLR);
    186		writel(time, ldata->base + RTC_LR);
    187	}
    188
    189	return ret;
    190}
    191
    192static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
    193{
    194	struct pl031_local *ldata = dev_get_drvdata(dev);
    195	int ret;
    196
    197	ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR),
    198			readl(ldata->base + RTC_YMR), &alarm->time);
    199
    200	alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI;
    201	alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI;
    202
    203	return ret;
    204}
    205
    206static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
    207{
    208	struct pl031_local *ldata = dev_get_drvdata(dev);
    209	unsigned long time;
    210	unsigned long bcd_year;
    211	int ret;
    212
    213	ret = pl031_stv2_tm_to_time(dev, &alarm->time,
    214				    &time, &bcd_year);
    215	if (ret == 0) {
    216		writel(bcd_year, ldata->base + RTC_YMR);
    217		writel(time, ldata->base + RTC_MR);
    218
    219		pl031_alarm_irq_enable(dev, alarm->enabled);
    220	}
    221
    222	return ret;
    223}
    224
    225static irqreturn_t pl031_interrupt(int irq, void *dev_id)
    226{
    227	struct pl031_local *ldata = dev_id;
    228	unsigned long rtcmis;
    229	unsigned long events = 0;
    230
    231	rtcmis = readl(ldata->base + RTC_MIS);
    232	if (rtcmis & RTC_BIT_AI) {
    233		writel(RTC_BIT_AI, ldata->base + RTC_ICR);
    234		events |= (RTC_AF | RTC_IRQF);
    235		rtc_update_irq(ldata->rtc, 1, events);
    236
    237		return IRQ_HANDLED;
    238	}
    239
    240	return IRQ_NONE;
    241}
    242
    243static int pl031_read_time(struct device *dev, struct rtc_time *tm)
    244{
    245	struct pl031_local *ldata = dev_get_drvdata(dev);
    246
    247	rtc_time64_to_tm(readl(ldata->base + RTC_DR), tm);
    248
    249	return 0;
    250}
    251
    252static int pl031_set_time(struct device *dev, struct rtc_time *tm)
    253{
    254	struct pl031_local *ldata = dev_get_drvdata(dev);
    255
    256	writel(rtc_tm_to_time64(tm), ldata->base + RTC_LR);
    257
    258	return 0;
    259}
    260
    261static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
    262{
    263	struct pl031_local *ldata = dev_get_drvdata(dev);
    264
    265	rtc_time64_to_tm(readl(ldata->base + RTC_MR), &alarm->time);
    266
    267	alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI;
    268	alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI;
    269
    270	return 0;
    271}
    272
    273static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
    274{
    275	struct pl031_local *ldata = dev_get_drvdata(dev);
    276
    277	writel(rtc_tm_to_time64(&alarm->time), ldata->base + RTC_MR);
    278	pl031_alarm_irq_enable(dev, alarm->enabled);
    279
    280	return 0;
    281}
    282
    283static void pl031_remove(struct amba_device *adev)
    284{
    285	struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
    286
    287	dev_pm_clear_wake_irq(&adev->dev);
    288	device_init_wakeup(&adev->dev, false);
    289	if (adev->irq[0])
    290		free_irq(adev->irq[0], ldata);
    291	amba_release_regions(adev);
    292}
    293
    294static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
    295{
    296	int ret;
    297	struct pl031_local *ldata;
    298	struct pl031_vendor_data *vendor = id->data;
    299	struct rtc_class_ops *ops;
    300	unsigned long time, data;
    301
    302	ret = amba_request_regions(adev, NULL);
    303	if (ret)
    304		goto err_req;
    305
    306	ldata = devm_kzalloc(&adev->dev, sizeof(struct pl031_local),
    307			     GFP_KERNEL);
    308	ops = devm_kmemdup(&adev->dev, &vendor->ops, sizeof(vendor->ops),
    309			   GFP_KERNEL);
    310	if (!ldata || !ops) {
    311		ret = -ENOMEM;
    312		goto out;
    313	}
    314
    315	ldata->vendor = vendor;
    316	ldata->base = devm_ioremap(&adev->dev, adev->res.start,
    317				   resource_size(&adev->res));
    318	if (!ldata->base) {
    319		ret = -ENOMEM;
    320		goto out;
    321	}
    322
    323	amba_set_drvdata(adev, ldata);
    324
    325	dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev));
    326	dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev));
    327
    328	data = readl(ldata->base + RTC_CR);
    329	/* Enable the clockwatch on ST Variants */
    330	if (vendor->clockwatch)
    331		data |= RTC_CR_CWEN;
    332	else
    333		data |= RTC_CR_EN;
    334	writel(data, ldata->base + RTC_CR);
    335
    336	/*
    337	 * On ST PL031 variants, the RTC reset value does not provide correct
    338	 * weekday for 2000-01-01. Correct the erroneous sunday to saturday.
    339	 */
    340	if (vendor->st_weekday) {
    341		if (readl(ldata->base + RTC_YDR) == 0x2000) {
    342			time = readl(ldata->base + RTC_DR);
    343			if ((time &
    344			     (RTC_MON_MASK | RTC_MDAY_MASK | RTC_WDAY_MASK))
    345			    == 0x02120000) {
    346				time = time | (0x7 << RTC_WDAY_SHIFT);
    347				writel(0x2000, ldata->base + RTC_YLR);
    348				writel(time, ldata->base + RTC_LR);
    349			}
    350		}
    351	}
    352
    353	device_init_wakeup(&adev->dev, true);
    354	ldata->rtc = devm_rtc_allocate_device(&adev->dev);
    355	if (IS_ERR(ldata->rtc)) {
    356		ret = PTR_ERR(ldata->rtc);
    357		goto out;
    358	}
    359
    360	if (!adev->irq[0])
    361		clear_bit(RTC_FEATURE_ALARM, ldata->rtc->features);
    362
    363	ldata->rtc->ops = ops;
    364	ldata->rtc->range_min = vendor->range_min;
    365	ldata->rtc->range_max = vendor->range_max;
    366
    367	ret = devm_rtc_register_device(ldata->rtc);
    368	if (ret)
    369		goto out;
    370
    371	if (adev->irq[0]) {
    372		ret = request_irq(adev->irq[0], pl031_interrupt,
    373				  vendor->irqflags, "rtc-pl031", ldata);
    374		if (ret)
    375			goto out;
    376		dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
    377	}
    378	return 0;
    379
    380out:
    381	amba_release_regions(adev);
    382err_req:
    383
    384	return ret;
    385}
    386
    387/* Operations for the original ARM version */
    388static struct pl031_vendor_data arm_pl031 = {
    389	.ops = {
    390		.read_time = pl031_read_time,
    391		.set_time = pl031_set_time,
    392		.read_alarm = pl031_read_alarm,
    393		.set_alarm = pl031_set_alarm,
    394		.alarm_irq_enable = pl031_alarm_irq_enable,
    395	},
    396	.range_max = U32_MAX,
    397};
    398
    399/* The First ST derivative */
    400static struct pl031_vendor_data stv1_pl031 = {
    401	.ops = {
    402		.read_time = pl031_read_time,
    403		.set_time = pl031_set_time,
    404		.read_alarm = pl031_read_alarm,
    405		.set_alarm = pl031_set_alarm,
    406		.alarm_irq_enable = pl031_alarm_irq_enable,
    407	},
    408	.clockwatch = true,
    409	.st_weekday = true,
    410	.range_max = U32_MAX,
    411};
    412
    413/* And the second ST derivative */
    414static struct pl031_vendor_data stv2_pl031 = {
    415	.ops = {
    416		.read_time = pl031_stv2_read_time,
    417		.set_time = pl031_stv2_set_time,
    418		.read_alarm = pl031_stv2_read_alarm,
    419		.set_alarm = pl031_stv2_set_alarm,
    420		.alarm_irq_enable = pl031_alarm_irq_enable,
    421	},
    422	.clockwatch = true,
    423	.st_weekday = true,
    424	/*
    425	 * This variant shares the IRQ with another block and must not
    426	 * suspend that IRQ line.
    427	 * TODO check if it shares with IRQF_NO_SUSPEND user, else we can
    428	 * remove IRQF_COND_SUSPEND
    429	 */
    430	.irqflags = IRQF_SHARED | IRQF_COND_SUSPEND,
    431	.range_min = RTC_TIMESTAMP_BEGIN_0000,
    432	.range_max = RTC_TIMESTAMP_END_9999,
    433};
    434
    435static const struct amba_id pl031_ids[] = {
    436	{
    437		.id = 0x00041031,
    438		.mask = 0x000fffff,
    439		.data = &arm_pl031,
    440	},
    441	/* ST Micro variants */
    442	{
    443		.id = 0x00180031,
    444		.mask = 0x00ffffff,
    445		.data = &stv1_pl031,
    446	},
    447	{
    448		.id = 0x00280031,
    449		.mask = 0x00ffffff,
    450		.data = &stv2_pl031,
    451	},
    452	{0, 0},
    453};
    454
    455MODULE_DEVICE_TABLE(amba, pl031_ids);
    456
    457static struct amba_driver pl031_driver = {
    458	.drv = {
    459		.name = "rtc-pl031",
    460	},
    461	.id_table = pl031_ids,
    462	.probe = pl031_probe,
    463	.remove = pl031_remove,
    464};
    465
    466module_amba_driver(pl031_driver);
    467
    468MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
    469MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
    470MODULE_LICENSE("GPL");