1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Nuvoton NCT6694 RTC driver based on USB interface. 4 * 5 * Copyright (C) 2025 Nuvoton Technology Corp. 6 */ 7 8 #include <linux/bcd.h> 9 #include <linux/irqdomain.h> 10 #include <linux/kernel.h> 11 #include <linux/mfd/nct6694.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/rtc.h> 15 #include <linux/slab.h> 16 17 /* 18 * USB command module type for NCT6694 RTC controller. 19 * This defines the module type used for communication with the NCT6694 20 * RTC controller over the USB interface. 21 */ 22 #define NCT6694_RTC_MOD 0x08 23 24 /* Command 00h - RTC Time */ 25 #define NCT6694_RTC_TIME 0x0000 26 #define NCT6694_RTC_TIME_SEL 0x00 27 28 /* Command 01h - RTC Alarm */ 29 #define NCT6694_RTC_ALARM 0x01 30 #define NCT6694_RTC_ALARM_SEL 0x00 31 32 /* Command 02h - RTC Status */ 33 #define NCT6694_RTC_STATUS 0x02 34 #define NCT6694_RTC_STATUS_SEL 0x00 35 36 #define NCT6694_RTC_IRQ_INT_EN BIT(0) /* Transmit a USB INT-in when RTC alarm */ 37 #define NCT6694_RTC_IRQ_GPO_EN BIT(5) /* Trigger a GPO Low Pulse when RTC alarm */ 38 39 #define NCT6694_RTC_IRQ_EN (NCT6694_RTC_IRQ_INT_EN | NCT6694_RTC_IRQ_GPO_EN) 40 #define NCT6694_RTC_IRQ_STS BIT(0) /* Write 1 clear IRQ status */ 41 42 struct __packed nct6694_rtc_time { 43 u8 sec; 44 u8 min; 45 u8 hour; 46 u8 week; 47 u8 day; 48 u8 month; 49 u8 year; 50 }; 51 52 struct __packed nct6694_rtc_alarm { 53 u8 sec; 54 u8 min; 55 u8 hour; 56 u8 alarm_en; 57 u8 alarm_pend; 58 }; 59 60 struct __packed nct6694_rtc_status { 61 u8 irq_en; 62 u8 irq_pend; 63 }; 64 65 union __packed nct6694_rtc_msg { 66 struct nct6694_rtc_time time; 67 struct nct6694_rtc_alarm alarm; 68 struct nct6694_rtc_status sts; 69 }; 70 71 struct nct6694_rtc_data { 72 struct nct6694 *nct6694; 73 struct rtc_device *rtc; 74 union nct6694_rtc_msg *msg; 75 int irq; 76 }; 77 78 static int nct6694_rtc_read_time(struct device *dev, struct rtc_time *tm) 79 { 80 struct nct6694_rtc_data *data = dev_get_drvdata(dev); 81 struct nct6694_rtc_time *time = &data->msg->time; 82 static const struct nct6694_cmd_header cmd_hd = { 83 .mod = NCT6694_RTC_MOD, 84 .cmd = NCT6694_RTC_TIME, 85 .sel = NCT6694_RTC_TIME_SEL, 86 .len = cpu_to_le16(sizeof(*time)) 87 }; 88 int ret; 89 90 ret = nct6694_read_msg(data->nct6694, &cmd_hd, time); 91 if (ret) 92 return ret; 93 94 tm->tm_sec = bcd2bin(time->sec); /* tm_sec expect 0 ~ 59 */ 95 tm->tm_min = bcd2bin(time->min); /* tm_min expect 0 ~ 59 */ 96 tm->tm_hour = bcd2bin(time->hour); /* tm_hour expect 0 ~ 23 */ 97 tm->tm_wday = bcd2bin(time->week) - 1; /* tm_wday expect 0 ~ 6 */ 98 tm->tm_mday = bcd2bin(time->day); /* tm_mday expect 1 ~ 31 */ 99 tm->tm_mon = bcd2bin(time->month) - 1; /* tm_month expect 0 ~ 11 */ 100 tm->tm_year = bcd2bin(time->year) + 100; /* tm_year expect since 1900 */ 101 102 return ret; 103 } 104 105 static int nct6694_rtc_set_time(struct device *dev, struct rtc_time *tm) 106 { 107 struct nct6694_rtc_data *data = dev_get_drvdata(dev); 108 struct nct6694_rtc_time *time = &data->msg->time; 109 static const struct nct6694_cmd_header cmd_hd = { 110 .mod = NCT6694_RTC_MOD, 111 .cmd = NCT6694_RTC_TIME, 112 .sel = NCT6694_RTC_TIME_SEL, 113 .len = cpu_to_le16(sizeof(*time)) 114 }; 115 116 time->sec = bin2bcd(tm->tm_sec); 117 time->min = bin2bcd(tm->tm_min); 118 time->hour = bin2bcd(tm->tm_hour); 119 time->week = bin2bcd(tm->tm_wday + 1); 120 time->day = bin2bcd(tm->tm_mday); 121 time->month = bin2bcd(tm->tm_mon + 1); 122 time->year = bin2bcd(tm->tm_year - 100); 123 124 return nct6694_write_msg(data->nct6694, &cmd_hd, time); 125 } 126 127 static int nct6694_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 128 { 129 struct nct6694_rtc_data *data = dev_get_drvdata(dev); 130 struct nct6694_rtc_alarm *alarm = &data->msg->alarm; 131 static const struct nct6694_cmd_header cmd_hd = { 132 .mod = NCT6694_RTC_MOD, 133 .cmd = NCT6694_RTC_ALARM, 134 .sel = NCT6694_RTC_ALARM_SEL, 135 .len = cpu_to_le16(sizeof(*alarm)) 136 }; 137 int ret; 138 139 ret = nct6694_read_msg(data->nct6694, &cmd_hd, alarm); 140 if (ret) 141 return ret; 142 143 alrm->time.tm_sec = bcd2bin(alarm->sec); 144 alrm->time.tm_min = bcd2bin(alarm->min); 145 alrm->time.tm_hour = bcd2bin(alarm->hour); 146 alrm->enabled = alarm->alarm_en; 147 alrm->pending = alarm->alarm_pend; 148 149 return ret; 150 } 151 152 static int nct6694_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 153 { 154 struct nct6694_rtc_data *data = dev_get_drvdata(dev); 155 struct nct6694_rtc_alarm *alarm = &data->msg->alarm; 156 static const struct nct6694_cmd_header cmd_hd = { 157 .mod = NCT6694_RTC_MOD, 158 .cmd = NCT6694_RTC_ALARM, 159 .sel = NCT6694_RTC_ALARM_SEL, 160 .len = cpu_to_le16(sizeof(*alarm)) 161 }; 162 163 alarm->sec = bin2bcd(alrm->time.tm_sec); 164 alarm->min = bin2bcd(alrm->time.tm_min); 165 alarm->hour = bin2bcd(alrm->time.tm_hour); 166 alarm->alarm_en = alrm->enabled ? NCT6694_RTC_IRQ_EN : 0; 167 alarm->alarm_pend = 0; 168 169 return nct6694_write_msg(data->nct6694, &cmd_hd, alarm); 170 } 171 172 static int nct6694_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 173 { 174 struct nct6694_rtc_data *data = dev_get_drvdata(dev); 175 struct nct6694_rtc_status *sts = &data->msg->sts; 176 static const struct nct6694_cmd_header cmd_hd = { 177 .mod = NCT6694_RTC_MOD, 178 .cmd = NCT6694_RTC_STATUS, 179 .sel = NCT6694_RTC_STATUS_SEL, 180 .len = cpu_to_le16(sizeof(*sts)) 181 }; 182 183 if (enabled) 184 sts->irq_en |= NCT6694_RTC_IRQ_EN; 185 else 186 sts->irq_en &= ~NCT6694_RTC_IRQ_EN; 187 188 sts->irq_pend = 0; 189 190 return nct6694_write_msg(data->nct6694, &cmd_hd, sts); 191 } 192 193 static const struct rtc_class_ops nct6694_rtc_ops = { 194 .read_time = nct6694_rtc_read_time, 195 .set_time = nct6694_rtc_set_time, 196 .read_alarm = nct6694_rtc_read_alarm, 197 .set_alarm = nct6694_rtc_set_alarm, 198 .alarm_irq_enable = nct6694_rtc_alarm_irq_enable, 199 }; 200 201 static irqreturn_t nct6694_irq(int irq, void *dev_id) 202 { 203 struct nct6694_rtc_data *data = dev_id; 204 struct nct6694_rtc_status *sts = &data->msg->sts; 205 static const struct nct6694_cmd_header cmd_hd = { 206 .mod = NCT6694_RTC_MOD, 207 .cmd = NCT6694_RTC_STATUS, 208 .sel = NCT6694_RTC_STATUS_SEL, 209 .len = cpu_to_le16(sizeof(*sts)) 210 }; 211 int ret; 212 213 rtc_lock(data->rtc); 214 215 sts->irq_en = NCT6694_RTC_IRQ_EN; 216 sts->irq_pend = NCT6694_RTC_IRQ_STS; 217 ret = nct6694_write_msg(data->nct6694, &cmd_hd, sts); 218 if (ret) { 219 rtc_unlock(data->rtc); 220 return IRQ_NONE; 221 } 222 223 rtc_update_irq(data->rtc, 1, RTC_IRQF | RTC_AF); 224 225 rtc_unlock(data->rtc); 226 227 return IRQ_HANDLED; 228 } 229 230 static void nct6694_irq_dispose_mapping(void *d) 231 { 232 struct nct6694_rtc_data *data = d; 233 234 irq_dispose_mapping(data->irq); 235 } 236 237 static int nct6694_rtc_probe(struct platform_device *pdev) 238 { 239 struct nct6694_rtc_data *data; 240 struct nct6694 *nct6694 = dev_get_drvdata(pdev->dev.parent); 241 int ret; 242 243 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 244 if (!data) 245 return -ENOMEM; 246 247 data->msg = devm_kzalloc(&pdev->dev, sizeof(union nct6694_rtc_msg), 248 GFP_KERNEL); 249 if (!data->msg) 250 return -ENOMEM; 251 252 data->irq = irq_create_mapping(nct6694->domain, NCT6694_IRQ_RTC); 253 if (!data->irq) 254 return -EINVAL; 255 256 ret = devm_add_action_or_reset(&pdev->dev, nct6694_irq_dispose_mapping, 257 data); 258 if (ret) 259 return ret; 260 261 ret = devm_device_init_wakeup(&pdev->dev); 262 if (ret) 263 return dev_err_probe(&pdev->dev, ret, "Failed to init wakeup\n"); 264 265 data->rtc = devm_rtc_allocate_device(&pdev->dev); 266 if (IS_ERR(data->rtc)) 267 return PTR_ERR(data->rtc); 268 269 data->nct6694 = nct6694; 270 data->rtc->ops = &nct6694_rtc_ops; 271 data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; 272 data->rtc->range_max = RTC_TIMESTAMP_END_2099; 273 274 platform_set_drvdata(pdev, data); 275 276 ret = devm_request_threaded_irq(&pdev->dev, data->irq, NULL, 277 nct6694_irq, IRQF_ONESHOT, 278 "rtc-nct6694", data); 279 if (ret < 0) 280 return dev_err_probe(&pdev->dev, ret, "Failed to request irq\n"); 281 282 return devm_rtc_register_device(data->rtc); 283 } 284 285 static struct platform_driver nct6694_rtc_driver = { 286 .driver = { 287 .name = "nct6694-rtc", 288 }, 289 .probe = nct6694_rtc_probe, 290 }; 291 292 module_platform_driver(nct6694_rtc_driver); 293 294 MODULE_DESCRIPTION("USB-RTC driver for NCT6694"); 295 MODULE_AUTHOR("Ming Yu <tmyu0@nuvoton.com>"); 296 MODULE_LICENSE("GPL"); 297 MODULE_ALIAS("platform:nct6694-rtc"); 298