1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2022 Microchip. 4 */ 5 6 #include <linux/device.h> 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/rtc.h> 10 #include <linux/tee_drv.h> 11 12 #define RTC_INFO_VERSION 0x1 13 14 #define TA_CMD_RTC_GET_INFO 0x0 15 #define TA_CMD_RTC_GET_TIME 0x1 16 #define TA_CMD_RTC_SET_TIME 0x2 17 #define TA_CMD_RTC_GET_OFFSET 0x3 18 #define TA_CMD_RTC_SET_OFFSET 0x4 19 20 #define TA_RTC_FEATURE_CORRECTION BIT(0) 21 22 struct optee_rtc_time { 23 u32 tm_sec; 24 u32 tm_min; 25 u32 tm_hour; 26 u32 tm_mday; 27 u32 tm_mon; 28 u32 tm_year; 29 u32 tm_wday; 30 }; 31 32 struct optee_rtc_info { 33 u64 version; 34 u64 features; 35 struct optee_rtc_time range_min; 36 struct optee_rtc_time range_max; 37 }; 38 39 /** 40 * struct optee_rtc - OP-TEE RTC private data 41 * @dev: OP-TEE based RTC device. 42 * @ctx: OP-TEE context handler. 43 * @session_id: RTC TA session identifier. 44 * @shm: Memory pool shared with RTC device. 45 * @features: Bitfield of RTC features 46 */ 47 struct optee_rtc { 48 struct device *dev; 49 struct tee_context *ctx; 50 u32 session_id; 51 struct tee_shm *shm; 52 u64 features; 53 }; 54 55 static int optee_rtc_readtime(struct device *dev, struct rtc_time *tm) 56 { 57 struct optee_rtc *priv = dev_get_drvdata(dev); 58 struct tee_ioctl_invoke_arg inv_arg = {0}; 59 struct optee_rtc_time *optee_tm; 60 struct tee_param param[4] = {0}; 61 int ret; 62 63 inv_arg.func = TA_CMD_RTC_GET_TIME; 64 inv_arg.session = priv->session_id; 65 inv_arg.num_params = 4; 66 67 /* Fill invoke cmd params */ 68 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; 69 param[0].u.memref.shm = priv->shm; 70 param[0].u.memref.size = sizeof(struct optee_rtc_time); 71 72 ret = tee_client_invoke_func(priv->ctx, &inv_arg, param); 73 if (ret < 0 || inv_arg.ret != 0) 74 return ret ? ret : -EPROTO; 75 76 optee_tm = tee_shm_get_va(priv->shm, 0); 77 if (IS_ERR(optee_tm)) 78 return PTR_ERR(optee_tm); 79 80 if (param[0].u.memref.size != sizeof(*optee_tm)) 81 return -EPROTO; 82 83 tm->tm_sec = optee_tm->tm_sec; 84 tm->tm_min = optee_tm->tm_min; 85 tm->tm_hour = optee_tm->tm_hour; 86 tm->tm_mday = optee_tm->tm_mday; 87 tm->tm_mon = optee_tm->tm_mon; 88 tm->tm_year = optee_tm->tm_year - 1900; 89 tm->tm_wday = optee_tm->tm_wday; 90 tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); 91 92 return 0; 93 } 94 95 static int optee_rtc_settime(struct device *dev, struct rtc_time *tm) 96 { 97 struct optee_rtc *priv = dev_get_drvdata(dev); 98 struct tee_ioctl_invoke_arg inv_arg = {0}; 99 struct tee_param param[4] = {0}; 100 struct optee_rtc_time optee_tm; 101 void *rtc_data; 102 int ret; 103 104 optee_tm.tm_sec = tm->tm_sec; 105 optee_tm.tm_min = tm->tm_min; 106 optee_tm.tm_hour = tm->tm_hour; 107 optee_tm.tm_mday = tm->tm_mday; 108 optee_tm.tm_mon = tm->tm_mon; 109 optee_tm.tm_year = tm->tm_year + 1900; 110 optee_tm.tm_wday = tm->tm_wday; 111 112 inv_arg.func = TA_CMD_RTC_SET_TIME; 113 inv_arg.session = priv->session_id; 114 inv_arg.num_params = 4; 115 116 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; 117 param[0].u.memref.shm = priv->shm; 118 param[0].u.memref.size = sizeof(struct optee_rtc_time); 119 120 rtc_data = tee_shm_get_va(priv->shm, 0); 121 if (IS_ERR(rtc_data)) 122 return PTR_ERR(rtc_data); 123 124 memcpy(rtc_data, &optee_tm, sizeof(struct optee_rtc_time)); 125 126 ret = tee_client_invoke_func(priv->ctx, &inv_arg, param); 127 if (ret < 0 || inv_arg.ret != 0) 128 return ret ? ret : -EPROTO; 129 130 return 0; 131 } 132 133 static int optee_rtc_readoffset(struct device *dev, long *offset) 134 { 135 struct optee_rtc *priv = dev_get_drvdata(dev); 136 struct tee_ioctl_invoke_arg inv_arg = {0}; 137 struct tee_param param[4] = {0}; 138 int ret; 139 140 if (!(priv->features & TA_RTC_FEATURE_CORRECTION)) 141 return -EOPNOTSUPP; 142 143 inv_arg.func = TA_CMD_RTC_GET_OFFSET; 144 inv_arg.session = priv->session_id; 145 inv_arg.num_params = 4; 146 147 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT; 148 149 ret = tee_client_invoke_func(priv->ctx, &inv_arg, param); 150 if (ret < 0 || inv_arg.ret != 0) 151 return ret ? ret : -EPROTO; 152 153 *offset = param[0].u.value.a; 154 155 return 0; 156 } 157 158 static int optee_rtc_setoffset(struct device *dev, long offset) 159 { 160 struct optee_rtc *priv = dev_get_drvdata(dev); 161 struct tee_ioctl_invoke_arg inv_arg = {0}; 162 struct tee_param param[4] = {0}; 163 int ret; 164 165 if (!(priv->features & TA_RTC_FEATURE_CORRECTION)) 166 return -EOPNOTSUPP; 167 168 inv_arg.func = TA_CMD_RTC_SET_OFFSET; 169 inv_arg.session = priv->session_id; 170 inv_arg.num_params = 4; 171 172 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT; 173 param[0].u.value.a = offset; 174 175 ret = tee_client_invoke_func(priv->ctx, &inv_arg, param); 176 if (ret < 0 || inv_arg.ret != 0) 177 return ret ? ret : -EPROTO; 178 179 return 0; 180 } 181 182 static const struct rtc_class_ops optee_rtc_ops = { 183 .read_time = optee_rtc_readtime, 184 .set_time = optee_rtc_settime, 185 .set_offset = optee_rtc_setoffset, 186 .read_offset = optee_rtc_readoffset, 187 }; 188 189 static int optee_rtc_read_info(struct device *dev, struct rtc_device *rtc, 190 u64 *features) 191 { 192 struct optee_rtc *priv = dev_get_drvdata(dev); 193 struct tee_ioctl_invoke_arg inv_arg = {0}; 194 struct tee_param param[4] = {0}; 195 struct optee_rtc_info *info; 196 struct optee_rtc_time *tm; 197 int ret; 198 199 inv_arg.func = TA_CMD_RTC_GET_INFO; 200 inv_arg.session = priv->session_id; 201 inv_arg.num_params = 4; 202 203 param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; 204 param[0].u.memref.shm = priv->shm; 205 param[0].u.memref.size = sizeof(*info); 206 207 ret = tee_client_invoke_func(priv->ctx, &inv_arg, param); 208 if (ret < 0 || inv_arg.ret != 0) 209 return ret ? ret : -EPROTO; 210 211 info = tee_shm_get_va(priv->shm, 0); 212 if (IS_ERR(info)) 213 return PTR_ERR(info); 214 215 if (param[0].u.memref.size != sizeof(*info)) 216 return -EPROTO; 217 218 if (info->version != RTC_INFO_VERSION) 219 return -EPROTO; 220 221 *features = info->features; 222 223 tm = &info->range_min; 224 rtc->range_min = mktime64(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, 225 tm->tm_sec); 226 tm = &info->range_max; 227 rtc->range_max = mktime64(tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, 228 tm->tm_sec); 229 230 return 0; 231 } 232 233 static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data) 234 { 235 if (ver->impl_id == TEE_IMPL_ID_OPTEE) 236 return 1; 237 else 238 return 0; 239 } 240 241 static int optee_rtc_probe(struct device *dev) 242 { 243 struct tee_client_device *rtc_device = to_tee_client_device(dev); 244 struct tee_ioctl_open_session_arg sess_arg; 245 struct optee_rtc *priv; 246 struct rtc_device *rtc; 247 struct tee_shm *shm; 248 int ret, err; 249 250 memset(&sess_arg, 0, sizeof(sess_arg)); 251 252 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 253 if (!priv) 254 return -ENOMEM; 255 256 rtc = devm_rtc_allocate_device(dev); 257 if (IS_ERR(rtc)) 258 return PTR_ERR(rtc); 259 260 /* Open context with TEE driver */ 261 priv->ctx = tee_client_open_context(NULL, optee_ctx_match, NULL, NULL); 262 if (IS_ERR(priv->ctx)) 263 return -ENODEV; 264 265 /* Open session with rtc Trusted App */ 266 export_uuid(sess_arg.uuid, &rtc_device->id.uuid); 267 sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL; 268 269 ret = tee_client_open_session(priv->ctx, &sess_arg, NULL); 270 if (ret < 0 || sess_arg.ret != 0) { 271 dev_err(dev, "tee_client_open_session failed, err: %x\n", sess_arg.ret); 272 err = -EINVAL; 273 goto out_ctx; 274 } 275 priv->session_id = sess_arg.session; 276 277 shm = tee_shm_alloc_kernel_buf(priv->ctx, sizeof(struct optee_rtc_info)); 278 if (IS_ERR(shm)) { 279 dev_err(priv->dev, "tee_shm_alloc_kernel_buf failed\n"); 280 err = PTR_ERR(shm); 281 goto out_sess; 282 } 283 284 priv->shm = shm; 285 priv->dev = dev; 286 dev_set_drvdata(dev, priv); 287 288 rtc->ops = &optee_rtc_ops; 289 290 err = optee_rtc_read_info(dev, rtc, &priv->features); 291 if (err) { 292 dev_err(dev, "Failed to get RTC features from OP-TEE\n"); 293 goto out_shm; 294 } 295 296 err = devm_rtc_register_device(rtc); 297 if (err) 298 goto out_shm; 299 300 /* 301 * We must clear this bit after registering because rtc_register_device 302 * will set it if it sees that .set_offset is provided. 303 */ 304 if (!(priv->features & TA_RTC_FEATURE_CORRECTION)) 305 clear_bit(RTC_FEATURE_CORRECTION, rtc->features); 306 307 return 0; 308 309 out_shm: 310 tee_shm_free(priv->shm); 311 out_sess: 312 tee_client_close_session(priv->ctx, priv->session_id); 313 out_ctx: 314 tee_client_close_context(priv->ctx); 315 316 return err; 317 } 318 319 static int optee_rtc_remove(struct device *dev) 320 { 321 struct optee_rtc *priv = dev_get_drvdata(dev); 322 323 tee_client_close_session(priv->ctx, priv->session_id); 324 tee_client_close_context(priv->ctx); 325 326 return 0; 327 } 328 329 static const struct tee_client_device_id optee_rtc_id_table[] = { 330 {UUID_INIT(0xf389f8c8, 0x845f, 0x496c, 331 0x8b, 0xbe, 0xd6, 0x4b, 0xd2, 0x4c, 0x92, 0xfd)}, 332 {} 333 }; 334 335 MODULE_DEVICE_TABLE(tee, optee_rtc_id_table); 336 337 static struct tee_client_driver optee_rtc_driver = { 338 .id_table = optee_rtc_id_table, 339 .driver = { 340 .name = "optee_rtc", 341 .bus = &tee_bus_type, 342 .probe = optee_rtc_probe, 343 .remove = optee_rtc_remove, 344 }, 345 }; 346 347 static int __init optee_rtc_mod_init(void) 348 { 349 return driver_register(&optee_rtc_driver.driver); 350 } 351 352 static void __exit optee_rtc_mod_exit(void) 353 { 354 driver_unregister(&optee_rtc_driver.driver); 355 } 356 357 module_init(optee_rtc_mod_init); 358 module_exit(optee_rtc_mod_exit); 359 360 MODULE_LICENSE("GPL v2"); 361 MODULE_AUTHOR("Clément Léger <clement.leger@bootlin.com>"); 362 MODULE_DESCRIPTION("OP-TEE based RTC driver"); 363