1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * RTC subsystem, nvmem interface 4 * 5 * Copyright (C) 2017 Alexandre Belloni 6 */ 7 8 #include <linux/err.h> 9 #include <linux/types.h> 10 #include <linux/nvmem-consumer.h> 11 #include <linux/rtc.h> 12 #include <linux/slab.h> 13 #include <linux/sysfs.h> 14 15 /* 16 * Deprecated ABI compatibility, this should be removed at some point 17 */ 18 19 static const char nvram_warning[] = "Deprecated ABI, please use nvmem"; 20 21 static ssize_t 22 rtc_nvram_read(struct file *filp, struct kobject *kobj, 23 struct bin_attribute *attr, 24 char *buf, loff_t off, size_t count) 25 { 26 dev_warn_once(kobj_to_dev(kobj), nvram_warning); 27 28 return nvmem_device_read(attr->private, off, count, buf); 29 } 30 31 static ssize_t 32 rtc_nvram_write(struct file *filp, struct kobject *kobj, 33 struct bin_attribute *attr, 34 char *buf, loff_t off, size_t count) 35 { 36 dev_warn_once(kobj_to_dev(kobj), nvram_warning); 37 38 return nvmem_device_write(attr->private, off, count, buf); 39 } 40 41 static int rtc_nvram_register(struct rtc_device *rtc, 42 struct nvmem_device *nvmem, size_t size) 43 { 44 int err; 45 46 rtc->nvram = kzalloc(sizeof(*rtc->nvram), GFP_KERNEL); 47 if (!rtc->nvram) 48 return -ENOMEM; 49 50 rtc->nvram->attr.name = "nvram"; 51 rtc->nvram->attr.mode = 0644; 52 rtc->nvram->private = nvmem; 53 54 sysfs_bin_attr_init(rtc->nvram); 55 56 rtc->nvram->read = rtc_nvram_read; 57 rtc->nvram->write = rtc_nvram_write; 58 rtc->nvram->size = size; 59 60 err = sysfs_create_bin_file(&rtc->dev.parent->kobj, 61 rtc->nvram); 62 if (err) { 63 kfree(rtc->nvram); 64 rtc->nvram = NULL; 65 } 66 67 return err; 68 } 69 70 static void rtc_nvram_unregister(struct rtc_device *rtc) 71 { 72 sysfs_remove_bin_file(&rtc->dev.parent->kobj, rtc->nvram); 73 kfree(rtc->nvram); 74 rtc->nvram = NULL; 75 } 76 77 /* 78 * New ABI, uses nvmem 79 */ 80 int rtc_nvmem_register(struct rtc_device *rtc, 81 struct nvmem_config *nvmem_config) 82 { 83 struct nvmem_device *nvmem; 84 85 if (!nvmem_config) 86 return -ENODEV; 87 88 nvmem_config->dev = rtc->dev.parent; 89 nvmem_config->owner = rtc->owner; 90 nvmem = devm_nvmem_register(rtc->dev.parent, nvmem_config); 91 if (IS_ERR(nvmem)) 92 return PTR_ERR(nvmem); 93 94 /* Register the old ABI */ 95 if (rtc->nvram_old_abi) 96 rtc_nvram_register(rtc, nvmem, nvmem_config->size); 97 98 return 0; 99 } 100 EXPORT_SYMBOL_GPL(rtc_nvmem_register); 101 102 void rtc_nvmem_unregister(struct rtc_device *rtc) 103 { 104 /* unregister the old ABI */ 105 if (rtc->nvram) 106 rtc_nvram_unregister(rtc); 107 } 108