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-ds1553.c (9303B)


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