Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: atcrtc100: Add ATCRTC100 RTC driver

RTC driver for Andes ATCRTC100 Real-Time Clock.

Signed-off-by: CL Wang <cl634@andestech.com>
Link: https://patch.msgid.link/20250915031439.2680364-4-cl634@andestech.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

CL Wang and committed by
Alexandre Belloni
7adca706 a603092d

+395
+15
drivers/rtc/Kconfig
··· 1063 1063 Direct support for the real-time clock found on every Alpha 1064 1064 system, specifically MC146818 compatibles. If in doubt, say Y. 1065 1065 1066 + config RTC_DRV_ATCRTC100 1067 + tristate "Andes ATCRTC100" 1068 + depends on ARCH_ANDES || COMPILE_TEST 1069 + select REGMAP_MMIO 1070 + help 1071 + If you say yes here you will get support for the Andes ATCRTC100 1072 + RTC driver. 1073 + 1074 + This driver provides support for the Andes ATCRTC100 real-time clock 1075 + device. It allows setting and retrieving the time and date, as well 1076 + as setting alarms. 1077 + 1078 + To compile this driver as a module, choose M here: the module will 1079 + be called rtc-atcrtc100. 1080 + 1066 1081 config RTC_DRV_DS1216 1067 1082 tristate "Dallas DS1216" 1068 1083 depends on SNI_RM
+1
drivers/rtc/Makefile
··· 34 34 obj-$(CONFIG_RTC_DRV_ASPEED) += rtc-aspeed.o 35 35 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o 36 36 obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o 37 + obj-$(CONFIG_RTC_DRV_ATCRTC100) += rtc-atcrtc100.o 37 38 obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o 38 39 obj-$(CONFIG_RTC_DRV_BBNSM) += rtc-nxp-bbnsm.o 39 40 obj-$(CONFIG_RTC_DRV_BD70528) += rtc-bd70528.o
+379
drivers/rtc/rtc-atcrtc100.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 + 69 + struct 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 + 77 + static 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 + */ 98 + static 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 + 112 + static 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 + 128 + static 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 + 144 + static 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 + 165 + static 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 + 184 + static 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 + 211 + static 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 + 231 + static 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 + 261 + static 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 + 269 + static 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 + atcrtc_dev->alarm_irq = platform_get_irq(pdev, 1); 300 + if (atcrtc_dev->alarm_irq < 0) 301 + return dev_err_probe(&pdev->dev, atcrtc_dev->alarm_irq, 302 + "Failed to get IRQ for alarm\n"); 303 + ret = devm_request_irq(&pdev->dev, 304 + atcrtc_dev->alarm_irq, 305 + atcrtc_alarm_isr, 306 + 0, 307 + "atcrtc_alarm", 308 + atcrtc_dev); 309 + if (ret) 310 + return dev_err_probe(&pdev->dev, ret, 311 + "Failed to request IRQ %d for alarm\n", 312 + atcrtc_dev->alarm_irq); 313 + 314 + atcrtc_dev->rtc_dev = devm_rtc_allocate_device(&pdev->dev); 315 + if (IS_ERR(atcrtc_dev->rtc_dev)) 316 + return dev_err_probe(&pdev->dev, PTR_ERR(atcrtc_dev->rtc_dev), 317 + "Failed to allocate RTC device\n"); 318 + 319 + set_bit(RTC_FEATURE_ALARM, atcrtc_dev->rtc_dev->features); 320 + ret = device_init_wakeup(&pdev->dev, true); 321 + if (ret) 322 + return dev_err_probe(&pdev->dev, ret, 323 + "Failed to initialize wake capability\n"); 324 + 325 + ret = dev_pm_set_wake_irq(&pdev->dev, atcrtc_dev->alarm_irq); 326 + if (ret) { 327 + device_init_wakeup(&pdev->dev, false); 328 + return dev_err_probe(&pdev->dev, ret, 329 + "Failed to set wake IRQ\n"); 330 + } 331 + 332 + atcrtc_dev->rtc_dev->ops = &rtc_ops; 333 + 334 + INIT_WORK(&atcrtc_dev->rtc_work, atcrtc_alarm_clear); 335 + return devm_rtc_register_device(atcrtc_dev->rtc_dev); 336 + } 337 + 338 + static int atcrtc_resume(struct device *dev) 339 + { 340 + struct atcrtc_dev *rtc = dev_get_drvdata(dev); 341 + 342 + if (device_may_wakeup(dev)) 343 + disable_irq_wake(rtc->alarm_irq); 344 + 345 + return 0; 346 + } 347 + 348 + static int atcrtc_suspend(struct device *dev) 349 + { 350 + struct atcrtc_dev *rtc = dev_get_drvdata(dev); 351 + 352 + if (device_may_wakeup(dev)) 353 + enable_irq_wake(rtc->alarm_irq); 354 + 355 + return 0; 356 + } 357 + 358 + static DEFINE_SIMPLE_DEV_PM_OPS(atcrtc_pm_ops, atcrtc_suspend, atcrtc_resume); 359 + 360 + static const struct of_device_id atcrtc_dt_match[] = { 361 + { .compatible = "andestech,atcrtc100" }, 362 + { }, 363 + }; 364 + MODULE_DEVICE_TABLE(of, atcrtc_dt_match); 365 + 366 + static struct platform_driver atcrtc_platform_driver = { 367 + .driver = { 368 + .name = "atcrtc100", 369 + .of_match_table = atcrtc_dt_match, 370 + .pm = pm_sleep_ptr(&atcrtc_pm_ops), 371 + }, 372 + .probe = atcrtc_probe, 373 + }; 374 + 375 + module_platform_driver(atcrtc_platform_driver); 376 + 377 + MODULE_AUTHOR("CL Wang <cl634@andestech.com>"); 378 + MODULE_DESCRIPTION("Andes ATCRTC100 driver"); 379 + MODULE_LICENSE("GPL");