File Index
Files and directories
Sign in
FILE

rtc-atcrtc100.c

File preview with syntax highlighting.

linux-6.19.14/drivers/rtc/rtc-atcrtc100.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Driver for Andes ATCRTC100 real time clock.
  4 *
  5 * Copyright (C) 2025 Andes Technology Corporation
  6 */
  7
  8#include <linux/bitfield.h>
  9#include <linux/delay.h>
 10#include <linux/interrupt.h>
 11#include <linux/math64.h>
 12#include <linux/module.h>
 13#include <linux/of.h>
 14#include <linux/platform_device.h>
 15#include <linux/pm_wakeirq.h>
 16#include <linux/regmap.h>
 17#include <linux/rtc.h>
 18#include <linux/workqueue.h>
 19
 20/* Register Offsets */
 21#define RTC_ID		0x00	/* ID and Revision Register */
 22#define RTC_RSV		0x04	/* Reserved Register */
 23#define RTC_CNT		0x10	/* Counter Register */
 24#define RTC_ALM		0x14	/* Alarm Register */
 25#define RTC_CR		0x18	/* Control Register */
 26#define RTC_STA		0x1C	/* Status Register */
 27#define RTC_TRIM	0x20	/* Digital Trimming Register */
 28
 29/* RTC_ID Register */
 30#define ID_MSK		GENMASK(31, 8)
 31#define ID_ATCRTC100	0x030110
 32
 33/* RTC_CNT and RTC_ALM Register Fields */
 34#define SEC_MSK		GENMASK(5, 0)
 35#define MIN_MSK		GENMASK(11, 6)
 36#define HOUR_MSK	GENMASK(16, 12)
 37#define DAY_MSK		GENMASK(31, 17)
 38#define RTC_SEC_GET(x)	FIELD_GET(SEC_MSK, x)
 39#define RTC_MIN_GET(x)	FIELD_GET(MIN_MSK, x)
 40#define RTC_HOUR_GET(x)	FIELD_GET(HOUR_MSK, x)
 41#define RTC_DAY_GET(x)	FIELD_GET(DAY_MSK, x)
 42#define RTC_SEC_SET(x)	FIELD_PREP(SEC_MSK, x)
 43#define RTC_MIN_SET(x)	FIELD_PREP(MIN_MSK, x)
 44#define RTC_HOUR_SET(x)	FIELD_PREP(HOUR_MSK, x)
 45#define RTC_DAY_SET(x)	FIELD_PREP(DAY_MSK, x)
 46
 47/* RTC_CR Register Bits */
 48#define RTC_EN		BIT(0)	/* RTC Enable */
 49#define ALARM_WAKEUP	BIT(1)	/* Alarm Wakeup Enable */
 50#define ALARM_INT	BIT(2)	/* Alarm Interrupt Enable */
 51#define DAY_INT		BIT(3)	/* Day Interrupt Enable */
 52#define HOUR_INT	BIT(4)	/* Hour Interrupt Enable */
 53#define MIN_INT		BIT(5)	/* Minute Interrupt Enable */
 54#define SEC_INT		BIT(6)	/* Second Periodic Interrupt Enable */
 55#define HSEC_INT	BIT(7)	/* Half-Second Periodic Interrupt Enable */
 56
 57/* RTC_STA Register Bits */
 58#define WRITE_DONE	BIT(16)	/* Register write completion status */
 59
 60/* Time conversion macro */
 61#define ATCRTC_TIME_TO_SEC(D, H, M, S)	\
 62	((time64_t)(D) * 86400 + (H) * 3600 + (M) * 60 + (S))
 63
 64/* Timeout for waiting for the write_done bit */
 65#define ATCRTC_TIMEOUT_US		1000000
 66#define ATCRTC_TIMEOUT_USLEEP_MIN	20
 67#define ATCRTC_TIMEOUT_USLEEP_MAX	30
 68
 69struct atcrtc_dev {
 70	struct rtc_device	*rtc_dev;
 71	struct regmap		*regmap;
 72	struct work_struct	rtc_work;
 73	unsigned int		alarm_irq;
 74	bool			alarm_en;
 75};
 76
 77static const struct regmap_config atcrtc_regmap_config = {
 78	.reg_bits = 32,
 79	.reg_stride = 4,
 80	.val_bits = 32,
 81	.max_register = RTC_TRIM,
 82	.cache_type = REGCACHE_NONE,
 83};
 84
 85/**
 86 * atcrtc_check_write_done - Wait for RTC registers to be synchronized.
 87 * @rtc: Pointer to the atcrtc_dev structure.
 88 *
 89 * The WriteDone bit in the status register indicates the synchronization
 90 * progress of RTC register updates. This bit is cleared to zero whenever
 91 * any RTC control register (Counter, Alarm, Control, etc.) is written.
 92 * It returns to one only after all previous updates have been fully
 93 * synchronized to the RTC clock domain. This function polls the WriteDone
 94 * bit with a timeout to ensure the device is ready for the next operation.
 95 *
 96 * Return: 0 on success, or -EBUSY on timeout.
 97 */
 98static int atcrtc_check_write_done(struct atcrtc_dev *rtc)
 99{
100	unsigned int val;
101
102	/*
103	 * Using read_poll_timeout is more efficient than a manual loop
104	 * with usleep_range.
105	 */
106	return regmap_read_poll_timeout(rtc->regmap, RTC_STA, val,
107					val & WRITE_DONE,
108					ATCRTC_TIMEOUT_USLEEP_MIN,
109					ATCRTC_TIMEOUT_US);
110}
111
112static irqreturn_t atcrtc_alarm_isr(int irq, void *dev)
113{
114	struct atcrtc_dev *rtc = dev;
115	unsigned int status;
116
117	regmap_read(rtc->regmap, RTC_STA, &status);
118	if (status & ALARM_INT) {
119		regmap_write(rtc->regmap, RTC_STA, ALARM_INT);
120		rtc->alarm_en = false;
121		schedule_work(&rtc->rtc_work);
122		rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
123		return IRQ_HANDLED;
124	}
125	return IRQ_NONE;
126}
127
128static int atcrtc_alarm_irq_enable(struct device *dev, unsigned int enable)
129{
130	struct atcrtc_dev *rtc = dev_get_drvdata(dev);
131	unsigned int mask;
132	int ret;
133
134	ret = atcrtc_check_write_done(rtc);
135	if (ret)
136		return ret;
137
138	mask = ALARM_WAKEUP | ALARM_INT;
139	regmap_update_bits(rtc->regmap, RTC_CR, mask, enable ? mask : 0);
140
141	return 0;
142}
143
144static void atcrtc_alarm_clear(struct work_struct *work)
145{
146	struct atcrtc_dev *rtc =
147		container_of(work, struct atcrtc_dev, rtc_work);
148	int ret;
149
150	rtc_lock(rtc->rtc_dev);
151
152	if (!rtc->alarm_en) {
153		ret = atcrtc_check_write_done(rtc);
154		if (ret)
155			dev_info(&rtc->rtc_dev->dev,
156				 "failed to sync before clearing alarm: %d\n",
157				 ret);
158		else
159			regmap_update_bits(rtc->regmap, RTC_CR,
160					   ALARM_WAKEUP | ALARM_INT, 0);
161	}
162	rtc_unlock(rtc->rtc_dev);
163}
164
165static int atcrtc_read_time(struct device *dev, struct rtc_time *tm)
166{
167	struct atcrtc_dev *rtc = dev_get_drvdata(dev);
168	time64_t time;
169	unsigned int rtc_cnt;
170
171	if (!regmap_test_bits(rtc->regmap, RTC_CR, RTC_EN))
172		return -EIO;
173
174	regmap_read(rtc->regmap, RTC_CNT, &rtc_cnt);
175	time = ATCRTC_TIME_TO_SEC(RTC_DAY_GET(rtc_cnt),
176				  RTC_HOUR_GET(rtc_cnt),
177				  RTC_MIN_GET(rtc_cnt),
178				  RTC_SEC_GET(rtc_cnt));
179	rtc_time64_to_tm(time, tm);
180
181	return 0;
182}
183
184static int atcrtc_set_time(struct device *dev, struct rtc_time *tm)
185{
186	struct atcrtc_dev *rtc = dev_get_drvdata(dev);
187	time64_t time;
188	unsigned int counter;
189	unsigned int day;
190	int ret;
191
192	time = rtc_tm_to_time64(tm);
193	day = div_s64(time, 86400);
194	counter = RTC_DAY_SET(day) |
195		  RTC_HOUR_SET(tm->tm_hour) |
196		  RTC_MIN_SET(tm->tm_min) |
197		  RTC_SEC_SET(tm->tm_sec);
198	ret = atcrtc_check_write_done(rtc);
199	if (ret)
200		return ret;
201	regmap_write(rtc->regmap, RTC_CNT, counter);
202
203	ret = atcrtc_check_write_done(rtc);
204	if (ret)
205		return ret;
206	regmap_update_bits(rtc->regmap, RTC_CR, RTC_EN, RTC_EN);
207
208	return 0;
209}
210
211static int atcrtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
212{
213	struct atcrtc_dev *rtc = dev_get_drvdata(dev);
214	struct rtc_time *tm = &wkalrm->time;
215	unsigned int rtc_alarm;
216
217	wkalrm->enabled = regmap_test_bits(rtc->regmap, RTC_CR, ALARM_INT);
218	regmap_read(rtc->regmap, RTC_ALM, &rtc_alarm);
219	tm->tm_hour = RTC_HOUR_GET(rtc_alarm);
220	tm->tm_min = RTC_MIN_GET(rtc_alarm);
221	tm->tm_sec = RTC_SEC_GET(rtc_alarm);
222
223	/* The RTC alarm does not support day/month/year fields */
224	tm->tm_mday = -1;
225	tm->tm_mon = -1;
226	tm->tm_year = -1;
227
228	return 0;
229}
230
231static int atcrtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
232{
233	struct atcrtc_dev *rtc = dev_get_drvdata(dev);
234	struct rtc_time *tm = &wkalrm->time;
235	unsigned int rtc_alarm;
236	int ret;
237
238	/* Disable alarm first before setting a new one */
239	ret = atcrtc_alarm_irq_enable(dev, 0);
240	if (ret)
241		return ret;
242
243	rtc->alarm_en = false;
244
245	rtc_alarm = RTC_SEC_SET(tm->tm_sec) |
246		    RTC_MIN_SET(tm->tm_min) |
247		    RTC_HOUR_SET(tm->tm_hour);
248
249	ret = atcrtc_check_write_done(rtc);
250	if (ret)
251		return ret;
252
253	regmap_write(rtc->regmap, RTC_ALM, rtc_alarm);
254
255	rtc->alarm_en = wkalrm->enabled;
256	ret = atcrtc_alarm_irq_enable(dev, wkalrm->enabled);
257
258	return ret;
259}
260
261static const struct rtc_class_ops rtc_ops = {
262	.read_time = atcrtc_read_time,
263	.set_time = atcrtc_set_time,
264	.read_alarm = atcrtc_read_alarm,
265	.set_alarm = atcrtc_set_alarm,
266	.alarm_irq_enable = atcrtc_alarm_irq_enable,
267};
268
269static int atcrtc_probe(struct platform_device *pdev)
270{
271	struct atcrtc_dev *atcrtc_dev;
272	void __iomem *reg_base;
273	unsigned int rtc_id;
274	int ret;
275
276	atcrtc_dev = devm_kzalloc(&pdev->dev, sizeof(*atcrtc_dev), GFP_KERNEL);
277	if (!atcrtc_dev)
278		return -ENOMEM;
279	platform_set_drvdata(pdev, atcrtc_dev);
280
281	reg_base = devm_platform_ioremap_resource(pdev, 0);
282	if (IS_ERR(reg_base))
283		return dev_err_probe(&pdev->dev, PTR_ERR(reg_base),
284				     "Failed to map I/O space\n");
285
286	atcrtc_dev->regmap = devm_regmap_init_mmio(&pdev->dev,
287						   reg_base,
288						   &atcrtc_regmap_config);
289	if (IS_ERR(atcrtc_dev->regmap))
290		return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->regmap),
291				     "Failed to initialize regmap\n");
292
293	regmap_read(atcrtc_dev->regmap, RTC_ID, &rtc_id);
294	if (FIELD_GET(ID_MSK, rtc_id) != ID_ATCRTC100)
295		return dev_err_probe(&pdev->dev, -ENODEV,
296				     "Failed to initialize RTC: unsupported hardware ID 0x%x\n",
297				     rtc_id);
298
299	ret = platform_get_irq(pdev, 1);
300	if (ret < 0)
301		return dev_err_probe(&pdev->dev, ret,
302				     "Failed to get IRQ for alarm\n");
303	atcrtc_dev->alarm_irq = ret;
304
305	ret = devm_request_irq(&pdev->dev,
306			       atcrtc_dev->alarm_irq,
307			       atcrtc_alarm_isr,
308			       0,
309			       "atcrtc_alarm",
310			       atcrtc_dev);
311	if (ret)
312		return dev_err_probe(&pdev->dev, ret,
313				     "Failed to request IRQ %d for alarm\n",
314				     atcrtc_dev->alarm_irq);
315
316	atcrtc_dev->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
317	if (IS_ERR(atcrtc_dev->rtc_dev))
318		return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->rtc_dev),
319				     "Failed to allocate RTC device\n");
320
321	set_bit(RTC_FEATURE_ALARM, atcrtc_dev->rtc_dev->features);
322	ret = device_init_wakeup(&pdev->dev, true);
323	if (ret)
324		return dev_err_probe(&pdev->dev, ret,
325				     "Failed to initialize wake capability\n");
326
327	ret = dev_pm_set_wake_irq(&pdev->dev, atcrtc_dev->alarm_irq);
328	if (ret) {
329		device_init_wakeup(&pdev->dev, false);
330		return dev_err_probe(&pdev->dev, ret,
331				     "Failed to set wake IRQ\n");
332	}
333
334	atcrtc_dev->rtc_dev->ops = &rtc_ops;
335
336	INIT_WORK(&atcrtc_dev->rtc_work, atcrtc_alarm_clear);
337	return devm_rtc_register_device(atcrtc_dev->rtc_dev);
338}
339
340static int atcrtc_resume(struct device *dev)
341{
342	struct atcrtc_dev *rtc = dev_get_drvdata(dev);
343
344	if (device_may_wakeup(dev))
345		disable_irq_wake(rtc->alarm_irq);
346
347	return 0;
348}
349
350static int atcrtc_suspend(struct device *dev)
351{
352	struct atcrtc_dev *rtc = dev_get_drvdata(dev);
353
354	if (device_may_wakeup(dev))
355		enable_irq_wake(rtc->alarm_irq);
356
357	return 0;
358}
359
360static DEFINE_SIMPLE_DEV_PM_OPS(atcrtc_pm_ops, atcrtc_suspend, atcrtc_resume);
361
362static const struct of_device_id atcrtc_dt_match[] = {
363	{ .compatible = "andestech,atcrtc100" },
364	{ },
365};
366MODULE_DEVICE_TABLE(of, atcrtc_dt_match);
367
368static struct platform_driver atcrtc_platform_driver = {
369	.driver = {
370		.name = "atcrtc100",
371		.of_match_table = atcrtc_dt_match,
372		.pm = pm_sleep_ptr(&atcrtc_pm_ops),
373	},
374	.probe = atcrtc_probe,
375};
376
377module_platform_driver(atcrtc_platform_driver);
378
379MODULE_AUTHOR("CL Wang <cl634@andestech.com>");
380MODULE_DESCRIPTION("Andes ATCRTC100 driver");
381MODULE_LICENSE("GPL");
~/ Read-only file preview.