1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * virtio_rtc RTC class driver 4 * 5 * Copyright (C) 2023 OpenSynergy GmbH 6 * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. 7 */ 8 9 #include <linux/math64.h> 10 #include <linux/overflow.h> 11 #include <linux/rtc.h> 12 #include <linux/time64.h> 13 14 #include <uapi/linux/virtio_rtc.h> 15 16 #include "virtio_rtc_internal.h" 17 18 /** 19 * struct viortc_class - RTC class wrapper 20 * @viortc: virtio_rtc device data 21 * @rtc: RTC device 22 * @vio_clk_id: virtio_rtc clock id 23 * @stopped: Whether RTC ops are disallowed. Access protected by rtc_lock(). 24 */ 25 struct viortc_class { 26 struct viortc_dev *viortc; 27 struct rtc_device *rtc; 28 u16 vio_clk_id; 29 bool stopped; 30 }; 31 32 /** 33 * viortc_class_get_locked() - get RTC class wrapper, if ops allowed 34 * @dev: virtio device 35 * 36 * Gets the RTC class wrapper from the virtio device, if it is available and 37 * ops are allowed. 38 * 39 * Context: Caller must hold rtc_lock(). 40 * Return: RTC class wrapper if available and ops allowed, ERR_PTR otherwise. 41 */ 42 static struct viortc_class *viortc_class_get_locked(struct device *dev) 43 { 44 struct viortc_class *viortc_class; 45 46 viortc_class = viortc_class_from_dev(dev); 47 if (IS_ERR(viortc_class)) 48 return viortc_class; 49 50 if (viortc_class->stopped) 51 return ERR_PTR(-EBUSY); 52 53 return viortc_class; 54 } 55 56 /** 57 * viortc_class_read_time() - RTC class op read_time 58 * @dev: virtio device 59 * @tm: read time 60 * 61 * Context: Process context. 62 * Return: Zero on success, negative error code otherwise. 63 */ 64 static int viortc_class_read_time(struct device *dev, struct rtc_time *tm) 65 { 66 struct viortc_class *viortc_class; 67 time64_t sec; 68 int ret; 69 u64 ns; 70 71 viortc_class = viortc_class_get_locked(dev); 72 if (IS_ERR(viortc_class)) 73 return PTR_ERR(viortc_class); 74 75 ret = viortc_read(viortc_class->viortc, viortc_class->vio_clk_id, &ns); 76 if (ret) 77 return ret; 78 79 sec = div_u64(ns, NSEC_PER_SEC); 80 81 rtc_time64_to_tm(sec, tm); 82 83 return 0; 84 } 85 86 /** 87 * viortc_class_read_alarm() - RTC class op read_alarm 88 * @dev: virtio device 89 * @alrm: alarm read out 90 * 91 * Context: Process context. 92 * Return: Zero on success, negative error code otherwise. 93 */ 94 static int viortc_class_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) 95 { 96 struct viortc_class *viortc_class; 97 time64_t alarm_time_sec; 98 u64 alarm_time_ns; 99 bool enabled; 100 int ret; 101 102 viortc_class = viortc_class_get_locked(dev); 103 if (IS_ERR(viortc_class)) 104 return PTR_ERR(viortc_class); 105 106 ret = viortc_read_alarm(viortc_class->viortc, viortc_class->vio_clk_id, 107 &alarm_time_ns, &enabled); 108 if (ret) 109 return ret; 110 111 alarm_time_sec = div_u64(alarm_time_ns, NSEC_PER_SEC); 112 rtc_time64_to_tm(alarm_time_sec, &alrm->time); 113 114 alrm->enabled = enabled; 115 116 return 0; 117 } 118 119 /** 120 * viortc_class_set_alarm() - RTC class op set_alarm 121 * @dev: virtio device 122 * @alrm: alarm to set 123 * 124 * Context: Process context. 125 * Return: Zero on success, negative error code otherwise. 126 */ 127 static int viortc_class_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 128 { 129 struct viortc_class *viortc_class; 130 time64_t alarm_time_sec; 131 u64 alarm_time_ns; 132 133 viortc_class = viortc_class_get_locked(dev); 134 if (IS_ERR(viortc_class)) 135 return PTR_ERR(viortc_class); 136 137 alarm_time_sec = rtc_tm_to_time64(&alrm->time); 138 139 if (alarm_time_sec < 0) 140 return -EINVAL; 141 142 if (check_mul_overflow((u64)alarm_time_sec, (u64)NSEC_PER_SEC, 143 &alarm_time_ns)) 144 return -EINVAL; 145 146 return viortc_set_alarm(viortc_class->viortc, viortc_class->vio_clk_id, 147 alarm_time_ns, alrm->enabled); 148 } 149 150 /** 151 * viortc_class_alarm_irq_enable() - RTC class op alarm_irq_enable 152 * @dev: virtio device 153 * @enabled: enable or disable alarm IRQ 154 * 155 * Context: Process context. 156 * Return: Zero on success, negative error code otherwise. 157 */ 158 static int viortc_class_alarm_irq_enable(struct device *dev, 159 unsigned int enabled) 160 { 161 struct viortc_class *viortc_class; 162 163 viortc_class = viortc_class_get_locked(dev); 164 if (IS_ERR(viortc_class)) 165 return PTR_ERR(viortc_class); 166 167 return viortc_set_alarm_enabled(viortc_class->viortc, 168 viortc_class->vio_clk_id, enabled); 169 } 170 171 static const struct rtc_class_ops viortc_class_ops = { 172 .read_time = viortc_class_read_time, 173 .read_alarm = viortc_class_read_alarm, 174 .set_alarm = viortc_class_set_alarm, 175 .alarm_irq_enable = viortc_class_alarm_irq_enable, 176 }; 177 178 /** 179 * viortc_class_alarm() - propagate alarm notification as alarm interrupt 180 * @viortc_class: RTC class wrapper 181 * @vio_clk_id: virtio_rtc clock id 182 * 183 * Context: Any context. 184 */ 185 void viortc_class_alarm(struct viortc_class *viortc_class, u16 vio_clk_id) 186 { 187 if (vio_clk_id != viortc_class->vio_clk_id) { 188 dev_warn_ratelimited(&viortc_class->rtc->dev, 189 "ignoring alarm for clock id %d, expected id %d\n", 190 vio_clk_id, viortc_class->vio_clk_id); 191 return; 192 } 193 194 rtc_update_irq(viortc_class->rtc, 1, RTC_AF | RTC_IRQF); 195 } 196 197 /** 198 * viortc_class_stop() - disallow RTC class ops 199 * @viortc_class: RTC class wrapper 200 * 201 * Context: Process context. Caller must NOT hold rtc_lock(). 202 */ 203 void viortc_class_stop(struct viortc_class *viortc_class) 204 { 205 rtc_lock(viortc_class->rtc); 206 207 viortc_class->stopped = true; 208 209 rtc_unlock(viortc_class->rtc); 210 } 211 212 /** 213 * viortc_class_register() - register RTC class device 214 * @viortc_class: RTC class wrapper 215 * 216 * Context: Process context. 217 * Return: Zero on success, negative error code otherwise. 218 */ 219 int viortc_class_register(struct viortc_class *viortc_class) 220 { 221 return devm_rtc_register_device(viortc_class->rtc); 222 } 223 224 /** 225 * viortc_class_init() - init RTC class wrapper and device 226 * @viortc: device data 227 * @vio_clk_id: virtio_rtc clock id 228 * @have_alarm: have alarm feature 229 * @parent_dev: virtio device 230 * 231 * Context: Process context. 232 * Return: RTC class wrapper on success, ERR_PTR otherwise. 233 */ 234 struct viortc_class *viortc_class_init(struct viortc_dev *viortc, 235 u16 vio_clk_id, bool have_alarm, 236 struct device *parent_dev) 237 { 238 struct viortc_class *viortc_class; 239 struct rtc_device *rtc; 240 241 viortc_class = 242 devm_kzalloc(parent_dev, sizeof(*viortc_class), GFP_KERNEL); 243 if (!viortc_class) 244 return ERR_PTR(-ENOMEM); 245 246 rtc = devm_rtc_allocate_device(parent_dev); 247 if (IS_ERR(rtc)) 248 return ERR_CAST(rtc); 249 250 viortc_class->viortc = viortc; 251 viortc_class->rtc = rtc; 252 viortc_class->vio_clk_id = vio_clk_id; 253 254 if (!have_alarm) 255 clear_bit(RTC_FEATURE_ALARM, rtc->features); 256 clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features); 257 258 rtc->ops = &viortc_class_ops; 259 rtc->range_max = div_u64(U64_MAX, NSEC_PER_SEC); 260 261 return viortc_class; 262 } 263