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-pcap.c (4599B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  pcap rtc code for Motorola EZX phones
      4 *
      5 *  Copyright (c) 2008 guiming zhuo <gmzhuo@gmail.com>
      6 *  Copyright (c) 2009 Daniel Ribeiro <drwyrm@gmail.com>
      7 *
      8 *  Based on Motorola's rtc.c Copyright (c) 2003-2005 Motorola
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/init.h>
     14#include <linux/mfd/ezx-pcap.h>
     15#include <linux/rtc.h>
     16#include <linux/slab.h>
     17#include <linux/platform_device.h>
     18
     19struct pcap_rtc {
     20	struct pcap_chip *pcap;
     21	struct rtc_device *rtc;
     22};
     23
     24static irqreturn_t pcap_rtc_irq(int irq, void *_pcap_rtc)
     25{
     26	struct pcap_rtc *pcap_rtc = _pcap_rtc;
     27	unsigned long rtc_events;
     28
     29	if (irq == pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ))
     30		rtc_events = RTC_IRQF | RTC_UF;
     31	else if (irq == pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA))
     32		rtc_events = RTC_IRQF | RTC_AF;
     33	else
     34		rtc_events = 0;
     35
     36	rtc_update_irq(pcap_rtc->rtc, 1, rtc_events);
     37	return IRQ_HANDLED;
     38}
     39
     40static int pcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
     41{
     42	struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
     43	struct rtc_time *tm = &alrm->time;
     44	unsigned long secs;
     45	u32 tod;	/* time of day, seconds since midnight */
     46	u32 days;	/* days since 1/1/1970 */
     47
     48	ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_TODA, &tod);
     49	secs = tod & PCAP_RTC_TOD_MASK;
     50
     51	ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_DAYA, &days);
     52	secs += (days & PCAP_RTC_DAY_MASK) * SEC_PER_DAY;
     53
     54	rtc_time64_to_tm(secs, tm);
     55
     56	return 0;
     57}
     58
     59static int pcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
     60{
     61	struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
     62	unsigned long secs = rtc_tm_to_time64(&alrm->time);
     63	u32 tod, days;
     64
     65	tod = secs % SEC_PER_DAY;
     66	ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_TODA, tod);
     67
     68	days = secs / SEC_PER_DAY;
     69	ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_DAYA, days);
     70
     71	return 0;
     72}
     73
     74static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
     75{
     76	struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
     77	unsigned long secs;
     78	u32 tod, days;
     79
     80	ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_TOD, &tod);
     81	secs = tod & PCAP_RTC_TOD_MASK;
     82
     83	ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_DAY, &days);
     84	secs += (days & PCAP_RTC_DAY_MASK) * SEC_PER_DAY;
     85
     86	rtc_time64_to_tm(secs, tm);
     87
     88	return 0;
     89}
     90
     91static int pcap_rtc_set_time(struct device *dev, struct rtc_time *tm)
     92{
     93	struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
     94	unsigned long secs = rtc_tm_to_time64(tm);
     95	u32 tod, days;
     96
     97	tod = secs % SEC_PER_DAY;
     98	ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_TOD, tod);
     99
    100	days = secs / SEC_PER_DAY;
    101	ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_DAY, days);
    102
    103	return 0;
    104}
    105
    106static int pcap_rtc_irq_enable(struct device *dev, int pirq, unsigned int en)
    107{
    108	struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
    109
    110	if (en)
    111		enable_irq(pcap_to_irq(pcap_rtc->pcap, pirq));
    112	else
    113		disable_irq(pcap_to_irq(pcap_rtc->pcap, pirq));
    114
    115	return 0;
    116}
    117
    118static int pcap_rtc_alarm_irq_enable(struct device *dev, unsigned int en)
    119{
    120	return pcap_rtc_irq_enable(dev, PCAP_IRQ_TODA, en);
    121}
    122
    123static const struct rtc_class_ops pcap_rtc_ops = {
    124	.read_time = pcap_rtc_read_time,
    125	.set_time = pcap_rtc_set_time,
    126	.read_alarm = pcap_rtc_read_alarm,
    127	.set_alarm = pcap_rtc_set_alarm,
    128	.alarm_irq_enable = pcap_rtc_alarm_irq_enable,
    129};
    130
    131static int __init pcap_rtc_probe(struct platform_device *pdev)
    132{
    133	struct pcap_rtc *pcap_rtc;
    134	int timer_irq, alarm_irq;
    135	int err = -ENOMEM;
    136
    137	pcap_rtc = devm_kzalloc(&pdev->dev, sizeof(struct pcap_rtc),
    138				GFP_KERNEL);
    139	if (!pcap_rtc)
    140		return err;
    141
    142	pcap_rtc->pcap = dev_get_drvdata(pdev->dev.parent);
    143
    144	platform_set_drvdata(pdev, pcap_rtc);
    145
    146	pcap_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
    147	if (IS_ERR(pcap_rtc->rtc))
    148		return PTR_ERR(pcap_rtc->rtc);
    149
    150	pcap_rtc->rtc->ops = &pcap_rtc_ops;
    151	pcap_rtc->rtc->range_max = (1 << 14) * 86400ULL - 1;
    152
    153	timer_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ);
    154	alarm_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA);
    155
    156	err = devm_request_irq(&pdev->dev, timer_irq, pcap_rtc_irq, 0,
    157				"RTC Timer", pcap_rtc);
    158	if (err)
    159		return err;
    160
    161	err = devm_request_irq(&pdev->dev, alarm_irq, pcap_rtc_irq, 0,
    162				"RTC Alarm", pcap_rtc);
    163	if (err)
    164		return err;
    165
    166	return devm_rtc_register_device(pcap_rtc->rtc);
    167}
    168
    169static int __exit pcap_rtc_remove(struct platform_device *pdev)
    170{
    171	return 0;
    172}
    173
    174static struct platform_driver pcap_rtc_driver = {
    175	.remove = __exit_p(pcap_rtc_remove),
    176	.driver = {
    177		.name  = "pcap-rtc",
    178	},
    179};
    180
    181module_platform_driver_probe(pcap_rtc_driver, pcap_rtc_probe);
    182
    183MODULE_DESCRIPTION("Motorola pcap rtc driver");
    184MODULE_AUTHOR("guiming zhuo <gmzhuo@gmail.com>");
    185MODULE_LICENSE("GPL");