.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Xilinx Zynq Ultrascale+ MPSoC Real Time Clock Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2015 Xilinx, Inc. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms and conditions of the GNU General Public License, |
---|
8 | | - * version 2, as published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | | - * more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License along with |
---|
16 | | - * this program. If not, see <http://www.gnu.org/licenses/>. |
---|
17 | 6 | * |
---|
18 | 7 | */ |
---|
19 | 8 | |
---|
.. | .. |
---|
49 | 38 | |
---|
50 | 39 | #define RTC_CALIB_DEF 0x198233 |
---|
51 | 40 | #define RTC_CALIB_MASK 0x1FFFFF |
---|
52 | | -#define RTC_SEC_MAX_VAL 0xFFFFFFFF |
---|
| 41 | +#define RTC_ALRM_MASK BIT(1) |
---|
| 42 | +#define RTC_MSEC 1000 |
---|
53 | 43 | |
---|
54 | 44 | struct xlnx_rtc_dev { |
---|
55 | 45 | struct rtc_device *rtc; |
---|
56 | 46 | void __iomem *reg_base; |
---|
57 | 47 | int alarm_irq; |
---|
58 | 48 | int sec_irq; |
---|
59 | | - int calibval; |
---|
| 49 | + unsigned int calibval; |
---|
60 | 50 | }; |
---|
61 | 51 | |
---|
62 | 52 | static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm) |
---|
.. | .. |
---|
70 | 60 | * to get the correct time on read. |
---|
71 | 61 | */ |
---|
72 | 62 | new_time = rtc_tm_to_time64(tm) + 1; |
---|
73 | | - |
---|
74 | | - if (new_time > RTC_SEC_MAX_VAL) |
---|
75 | | - return -EINVAL; |
---|
76 | 63 | |
---|
77 | 64 | /* |
---|
78 | 65 | * Writing into calibration register will clear the Tick Counter and |
---|
.. | .. |
---|
109 | 96 | * RTC has updated the CURRENT_TIME with the time written into |
---|
110 | 97 | * SET_TIME_WRITE register. |
---|
111 | 98 | */ |
---|
112 | | - rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm); |
---|
| 99 | + read_time = readl(xrtcdev->reg_base + RTC_CUR_TM); |
---|
113 | 100 | } else { |
---|
114 | 101 | /* |
---|
115 | 102 | * Time written in SET_TIME_WRITE has not yet updated into |
---|
.. | .. |
---|
119 | 106 | * reading. |
---|
120 | 107 | */ |
---|
121 | 108 | read_time = readl(xrtcdev->reg_base + RTC_SET_TM_RD) - 1; |
---|
122 | | - rtc_time64_to_tm(read_time, tm); |
---|
123 | 109 | } |
---|
| 110 | + rtc_time64_to_tm(read_time, tm); |
---|
124 | 111 | |
---|
125 | 112 | return 0; |
---|
126 | 113 | } |
---|
.. | .. |
---|
138 | 125 | static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled) |
---|
139 | 126 | { |
---|
140 | 127 | struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev); |
---|
| 128 | + unsigned int status; |
---|
| 129 | + ulong timeout; |
---|
141 | 130 | |
---|
142 | | - if (enabled) |
---|
| 131 | + timeout = jiffies + msecs_to_jiffies(RTC_MSEC); |
---|
| 132 | + |
---|
| 133 | + if (enabled) { |
---|
| 134 | + while (1) { |
---|
| 135 | + status = readl(xrtcdev->reg_base + RTC_INT_STS); |
---|
| 136 | + if (!((status & RTC_ALRM_MASK) == RTC_ALRM_MASK)) |
---|
| 137 | + break; |
---|
| 138 | + |
---|
| 139 | + if (time_after_eq(jiffies, timeout)) { |
---|
| 140 | + dev_err(dev, "Time out occur, while clearing alarm status bit\n"); |
---|
| 141 | + return -ETIMEDOUT; |
---|
| 142 | + } |
---|
| 143 | + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS); |
---|
| 144 | + } |
---|
| 145 | + |
---|
143 | 146 | writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN); |
---|
144 | | - else |
---|
| 147 | + } else { |
---|
145 | 148 | writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS); |
---|
| 149 | + } |
---|
146 | 150 | |
---|
147 | 151 | return 0; |
---|
148 | 152 | } |
---|
.. | .. |
---|
153 | 157 | unsigned long alarm_time; |
---|
154 | 158 | |
---|
155 | 159 | alarm_time = rtc_tm_to_time64(&alrm->time); |
---|
156 | | - |
---|
157 | | - if (alarm_time > RTC_SEC_MAX_VAL) |
---|
158 | | - return -EINVAL; |
---|
159 | 160 | |
---|
160 | 161 | writel((u32)alarm_time, (xrtcdev->reg_base + RTC_ALRM)); |
---|
161 | 162 | |
---|
.. | .. |
---|
201 | 202 | if (!(status & (RTC_INT_SEC | RTC_INT_ALRM))) |
---|
202 | 203 | return IRQ_NONE; |
---|
203 | 204 | |
---|
204 | | - /* Clear RTC_INT_ALRM interrupt only */ |
---|
205 | | - writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS); |
---|
| 205 | + /* Disable RTC_INT_ALRM interrupt only */ |
---|
| 206 | + writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS); |
---|
206 | 207 | |
---|
207 | 208 | if (status & RTC_INT_ALRM) |
---|
208 | 209 | rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF); |
---|
.. | .. |
---|
213 | 214 | static int xlnx_rtc_probe(struct platform_device *pdev) |
---|
214 | 215 | { |
---|
215 | 216 | struct xlnx_rtc_dev *xrtcdev; |
---|
216 | | - struct resource *res; |
---|
217 | 217 | int ret; |
---|
218 | 218 | |
---|
219 | 219 | xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL); |
---|
.. | .. |
---|
222 | 222 | |
---|
223 | 223 | platform_set_drvdata(pdev, xrtcdev); |
---|
224 | 224 | |
---|
225 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
| 225 | + xrtcdev->rtc = devm_rtc_allocate_device(&pdev->dev); |
---|
| 226 | + if (IS_ERR(xrtcdev->rtc)) |
---|
| 227 | + return PTR_ERR(xrtcdev->rtc); |
---|
226 | 228 | |
---|
227 | | - xrtcdev->reg_base = devm_ioremap_resource(&pdev->dev, res); |
---|
| 229 | + xrtcdev->rtc->ops = &xlnx_rtc_ops; |
---|
| 230 | + xrtcdev->rtc->range_max = U32_MAX; |
---|
| 231 | + |
---|
| 232 | + xrtcdev->reg_base = devm_platform_ioremap_resource(pdev, 0); |
---|
228 | 233 | if (IS_ERR(xrtcdev->reg_base)) |
---|
229 | 234 | return PTR_ERR(xrtcdev->reg_base); |
---|
230 | 235 | |
---|
231 | 236 | xrtcdev->alarm_irq = platform_get_irq_byname(pdev, "alarm"); |
---|
232 | | - if (xrtcdev->alarm_irq < 0) { |
---|
233 | | - dev_err(&pdev->dev, "no irq resource\n"); |
---|
| 237 | + if (xrtcdev->alarm_irq < 0) |
---|
234 | 238 | return xrtcdev->alarm_irq; |
---|
235 | | - } |
---|
236 | 239 | ret = devm_request_irq(&pdev->dev, xrtcdev->alarm_irq, |
---|
237 | 240 | xlnx_rtc_interrupt, 0, |
---|
238 | 241 | dev_name(&pdev->dev), xrtcdev); |
---|
.. | .. |
---|
242 | 245 | } |
---|
243 | 246 | |
---|
244 | 247 | xrtcdev->sec_irq = platform_get_irq_byname(pdev, "sec"); |
---|
245 | | - if (xrtcdev->sec_irq < 0) { |
---|
246 | | - dev_err(&pdev->dev, "no irq resource\n"); |
---|
| 248 | + if (xrtcdev->sec_irq < 0) |
---|
247 | 249 | return xrtcdev->sec_irq; |
---|
248 | | - } |
---|
249 | 250 | ret = devm_request_irq(&pdev->dev, xrtcdev->sec_irq, |
---|
250 | 251 | xlnx_rtc_interrupt, 0, |
---|
251 | 252 | dev_name(&pdev->dev), xrtcdev); |
---|
.. | .. |
---|
263 | 264 | |
---|
264 | 265 | device_init_wakeup(&pdev->dev, 1); |
---|
265 | 266 | |
---|
266 | | - xrtcdev->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, |
---|
267 | | - &xlnx_rtc_ops, THIS_MODULE); |
---|
268 | | - return PTR_ERR_OR_ZERO(xrtcdev->rtc); |
---|
| 267 | + return rtc_register_device(xrtcdev->rtc); |
---|
269 | 268 | } |
---|
270 | 269 | |
---|
271 | 270 | static int xlnx_rtc_remove(struct platform_device *pdev) |
---|