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-stk17ta8.c (9421B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * A RTC driver for the Simtek STK17TA8
      4 *
      5 * By Thomas Hommel <thomas.hommel@ge.com>
      6 *
      7 * Based on the DS1553 driver from
      8 * Atsushi Nemoto <anemo@mba.ocn.ne.jp>
      9 */
     10
     11#include <linux/bcd.h>
     12#include <linux/init.h>
     13#include <linux/kernel.h>
     14#include <linux/gfp.h>
     15#include <linux/delay.h>
     16#include <linux/jiffies.h>
     17#include <linux/interrupt.h>
     18#include <linux/rtc.h>
     19#include <linux/platform_device.h>
     20#include <linux/io.h>
     21#include <linux/module.h>
     22
     23#define RTC_REG_SIZE		0x20000
     24#define RTC_OFFSET		0x1fff0
     25
     26#define RTC_FLAGS		(RTC_OFFSET + 0)
     27#define RTC_CENTURY		(RTC_OFFSET + 1)
     28#define RTC_SECONDS_ALARM	(RTC_OFFSET + 2)
     29#define RTC_MINUTES_ALARM	(RTC_OFFSET + 3)
     30#define RTC_HOURS_ALARM		(RTC_OFFSET + 4)
     31#define RTC_DATE_ALARM		(RTC_OFFSET + 5)
     32#define RTC_INTERRUPTS		(RTC_OFFSET + 6)
     33#define RTC_WATCHDOG		(RTC_OFFSET + 7)
     34#define RTC_CALIBRATION		(RTC_OFFSET + 8)
     35#define RTC_SECONDS		(RTC_OFFSET + 9)
     36#define RTC_MINUTES		(RTC_OFFSET + 10)
     37#define RTC_HOURS		(RTC_OFFSET + 11)
     38#define RTC_DAY			(RTC_OFFSET + 12)
     39#define RTC_DATE		(RTC_OFFSET + 13)
     40#define RTC_MONTH		(RTC_OFFSET + 14)
     41#define RTC_YEAR		(RTC_OFFSET + 15)
     42
     43#define RTC_SECONDS_MASK	0x7f
     44#define RTC_DAY_MASK		0x07
     45#define RTC_CAL_MASK		0x3f
     46
     47/* Bits in the Calibration register */
     48#define RTC_STOP		0x80
     49
     50/* Bits in the Flags register */
     51#define RTC_FLAGS_AF		0x40
     52#define RTC_FLAGS_PF		0x20
     53#define RTC_WRITE		0x02
     54#define RTC_READ		0x01
     55
     56/* Bits in the Interrupts register */
     57#define RTC_INTS_AIE		0x40
     58
     59struct rtc_plat_data {
     60	struct rtc_device *rtc;
     61	void __iomem *ioaddr;
     62	unsigned long last_jiffies;
     63	int irq;
     64	unsigned int irqen;
     65	int alrm_sec;
     66	int alrm_min;
     67	int alrm_hour;
     68	int alrm_mday;
     69	spinlock_t lock;
     70};
     71
     72static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm)
     73{
     74	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
     75	void __iomem *ioaddr = pdata->ioaddr;
     76	u8 flags;
     77
     78	flags = readb(pdata->ioaddr + RTC_FLAGS);
     79	writeb(flags | RTC_WRITE, pdata->ioaddr + RTC_FLAGS);
     80
     81	writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
     82	writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
     83	writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
     84	writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
     85	writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
     86	writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
     87	writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
     88	writeb(bin2bcd((tm->tm_year + 1900) / 100), ioaddr + RTC_CENTURY);
     89
     90	writeb(flags & ~RTC_WRITE, pdata->ioaddr + RTC_FLAGS);
     91	return 0;
     92}
     93
     94static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm)
     95{
     96	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
     97	void __iomem *ioaddr = pdata->ioaddr;
     98	unsigned int year, month, day, hour, minute, second, week;
     99	unsigned int century;
    100	u8 flags;
    101
    102	/* give enough time to update RTC in case of continuous read */
    103	if (pdata->last_jiffies == jiffies)
    104		msleep(1);
    105	pdata->last_jiffies = jiffies;
    106
    107	flags = readb(pdata->ioaddr + RTC_FLAGS);
    108	writeb(flags | RTC_READ, ioaddr + RTC_FLAGS);
    109	second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
    110	minute = readb(ioaddr + RTC_MINUTES);
    111	hour = readb(ioaddr + RTC_HOURS);
    112	day = readb(ioaddr + RTC_DATE);
    113	week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
    114	month = readb(ioaddr + RTC_MONTH);
    115	year = readb(ioaddr + RTC_YEAR);
    116	century = readb(ioaddr + RTC_CENTURY);
    117	writeb(flags & ~RTC_READ, ioaddr + RTC_FLAGS);
    118	tm->tm_sec = bcd2bin(second);
    119	tm->tm_min = bcd2bin(minute);
    120	tm->tm_hour = bcd2bin(hour);
    121	tm->tm_mday = bcd2bin(day);
    122	tm->tm_wday = bcd2bin(week);
    123	tm->tm_mon = bcd2bin(month) - 1;
    124	/* year is 1900 + tm->tm_year */
    125	tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
    126
    127	return 0;
    128}
    129
    130static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata)
    131{
    132	void __iomem *ioaddr = pdata->ioaddr;
    133	unsigned long irqflags;
    134	u8 flags;
    135
    136	spin_lock_irqsave(&pdata->lock, irqflags);
    137
    138	flags = readb(ioaddr + RTC_FLAGS);
    139	writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS);
    140
    141	writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
    142	       0x80 : bin2bcd(pdata->alrm_mday),
    143	       ioaddr + RTC_DATE_ALARM);
    144	writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
    145	       0x80 : bin2bcd(pdata->alrm_hour),
    146	       ioaddr + RTC_HOURS_ALARM);
    147	writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
    148	       0x80 : bin2bcd(pdata->alrm_min),
    149	       ioaddr + RTC_MINUTES_ALARM);
    150	writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
    151	       0x80 : bin2bcd(pdata->alrm_sec),
    152	       ioaddr + RTC_SECONDS_ALARM);
    153	writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS);
    154	readb(ioaddr + RTC_FLAGS);	/* clear interrupts */
    155	writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS);
    156	spin_unlock_irqrestore(&pdata->lock, irqflags);
    157}
    158
    159static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
    160{
    161	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
    162
    163	if (pdata->irq <= 0)
    164		return -EINVAL;
    165	pdata->alrm_mday = alrm->time.tm_mday;
    166	pdata->alrm_hour = alrm->time.tm_hour;
    167	pdata->alrm_min = alrm->time.tm_min;
    168	pdata->alrm_sec = alrm->time.tm_sec;
    169	if (alrm->enabled)
    170		pdata->irqen |= RTC_AF;
    171	stk17ta8_rtc_update_alarm(pdata);
    172	return 0;
    173}
    174
    175static int stk17ta8_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
    176{
    177	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
    178
    179	if (pdata->irq <= 0)
    180		return -EINVAL;
    181	alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
    182	alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
    183	alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min;
    184	alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec;
    185	alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0;
    186	return 0;
    187}
    188
    189static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id)
    190{
    191	struct platform_device *pdev = dev_id;
    192	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
    193	void __iomem *ioaddr = pdata->ioaddr;
    194	unsigned long events = 0;
    195
    196	spin_lock(&pdata->lock);
    197	/* read and clear interrupt */
    198	if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF) {
    199		events = RTC_IRQF;
    200		if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
    201			events |= RTC_UF;
    202		else
    203			events |= RTC_AF;
    204		rtc_update_irq(pdata->rtc, 1, events);
    205	}
    206	spin_unlock(&pdata->lock);
    207	return events ? IRQ_HANDLED : IRQ_NONE;
    208}
    209
    210static int stk17ta8_rtc_alarm_irq_enable(struct device *dev,
    211	unsigned int enabled)
    212{
    213	struct rtc_plat_data *pdata = dev_get_drvdata(dev);
    214
    215	if (pdata->irq <= 0)
    216		return -EINVAL;
    217	if (enabled)
    218		pdata->irqen |= RTC_AF;
    219	else
    220		pdata->irqen &= ~RTC_AF;
    221	stk17ta8_rtc_update_alarm(pdata);
    222	return 0;
    223}
    224
    225static const struct rtc_class_ops stk17ta8_rtc_ops = {
    226	.read_time		= stk17ta8_rtc_read_time,
    227	.set_time		= stk17ta8_rtc_set_time,
    228	.read_alarm		= stk17ta8_rtc_read_alarm,
    229	.set_alarm		= stk17ta8_rtc_set_alarm,
    230	.alarm_irq_enable	= stk17ta8_rtc_alarm_irq_enable,
    231};
    232
    233static int stk17ta8_nvram_read(void *priv, unsigned int pos, void *val,
    234			       size_t bytes)
    235{
    236	struct rtc_plat_data *pdata = priv;
    237	void __iomem *ioaddr = pdata->ioaddr;
    238	u8 *buf = val;
    239
    240	for (; bytes; bytes--)
    241		*buf++ = readb(ioaddr + pos++);
    242	return 0;
    243}
    244
    245static int stk17ta8_nvram_write(void *priv, unsigned int pos, void *val,
    246				size_t bytes)
    247{
    248	struct rtc_plat_data *pdata = priv;
    249	void __iomem *ioaddr = pdata->ioaddr;
    250	u8 *buf = val;
    251
    252	for (; bytes; bytes--)
    253		writeb(*buf++, ioaddr + pos++);
    254	return 0;
    255}
    256
    257static int stk17ta8_rtc_probe(struct platform_device *pdev)
    258{
    259	unsigned int cal;
    260	unsigned int flags;
    261	struct rtc_plat_data *pdata;
    262	void __iomem *ioaddr;
    263	int ret = 0;
    264	struct nvmem_config nvmem_cfg = {
    265		.name = "stk17ta8_nvram",
    266		.word_size = 1,
    267		.stride = 1,
    268		.size = RTC_OFFSET,
    269		.reg_read = stk17ta8_nvram_read,
    270		.reg_write = stk17ta8_nvram_write,
    271	};
    272
    273	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
    274	if (!pdata)
    275		return -ENOMEM;
    276
    277	ioaddr = devm_platform_ioremap_resource(pdev, 0);
    278	if (IS_ERR(ioaddr))
    279		return PTR_ERR(ioaddr);
    280	pdata->ioaddr = ioaddr;
    281	pdata->irq = platform_get_irq(pdev, 0);
    282
    283	/* turn RTC on if it was not on */
    284	cal = readb(ioaddr + RTC_CALIBRATION);
    285	if (cal & RTC_STOP) {
    286		cal &= RTC_CAL_MASK;
    287		flags = readb(ioaddr + RTC_FLAGS);
    288		writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS);
    289		writeb(cal, ioaddr + RTC_CALIBRATION);
    290		writeb(flags & ~RTC_WRITE, ioaddr + RTC_FLAGS);
    291	}
    292	if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_PF)
    293		dev_warn(&pdev->dev, "voltage-low detected.\n");
    294
    295	spin_lock_init(&pdata->lock);
    296	pdata->last_jiffies = jiffies;
    297	platform_set_drvdata(pdev, pdata);
    298	if (pdata->irq > 0) {
    299		writeb(0, ioaddr + RTC_INTERRUPTS);
    300		if (devm_request_irq(&pdev->dev, pdata->irq,
    301				stk17ta8_rtc_interrupt,
    302				IRQF_SHARED,
    303				pdev->name, pdev) < 0) {
    304			dev_warn(&pdev->dev, "interrupt not available.\n");
    305			pdata->irq = 0;
    306		}
    307	}
    308
    309	pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
    310	if (IS_ERR(pdata->rtc))
    311		return PTR_ERR(pdata->rtc);
    312
    313	pdata->rtc->ops = &stk17ta8_rtc_ops;
    314
    315	nvmem_cfg.priv = pdata;
    316	ret = devm_rtc_nvmem_register(pdata->rtc, &nvmem_cfg);
    317	if (ret)
    318		return ret;
    319
    320	return devm_rtc_register_device(pdata->rtc);
    321}
    322
    323/* work with hotplug and coldplug */
    324MODULE_ALIAS("platform:stk17ta8");
    325
    326static struct platform_driver stk17ta8_rtc_driver = {
    327	.probe		= stk17ta8_rtc_probe,
    328	.driver		= {
    329		.name	= "stk17ta8",
    330	},
    331};
    332
    333module_platform_driver(stk17ta8_rtc_driver);
    334
    335MODULE_AUTHOR("Thomas Hommel <thomas.hommel@ge.com>");
    336MODULE_DESCRIPTION("Simtek STK17TA8 RTC driver");
    337MODULE_LICENSE("GPL");