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