Branch data Line data Source code
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 : 0 : 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 : 0 : dev_warn_once(kobj_to_dev(kobj), nvram_warning); 27 : : 28 : 0 : return nvmem_device_read(attr->private, off, count, buf); 29 : : } 30 : : 31 : : static ssize_t 32 : 0 : 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 : 0 : dev_warn_once(kobj_to_dev(kobj), nvram_warning); 37 : : 38 : 0 : return nvmem_device_write(attr->private, off, count, buf); 39 : : } 40 : : 41 : 0 : static int rtc_nvram_register(struct rtc_device *rtc, 42 : : struct nvmem_device *nvmem, size_t size) 43 : : { 44 : : int err; 45 : : 46 : 0 : rtc->nvram = kzalloc(sizeof(*rtc->nvram), GFP_KERNEL); 47 : 0 : if (!rtc->nvram) 48 : : return -ENOMEM; 49 : : 50 : 0 : rtc->nvram->attr.name = "nvram"; 51 : 0 : rtc->nvram->attr.mode = 0644; 52 : 0 : rtc->nvram->private = nvmem; 53 : : 54 : : sysfs_bin_attr_init(rtc->nvram); 55 : : 56 : 0 : rtc->nvram->read = rtc_nvram_read; 57 : 0 : rtc->nvram->write = rtc_nvram_write; 58 : 0 : rtc->nvram->size = size; 59 : : 60 : 0 : err = sysfs_create_bin_file(&rtc->dev.parent->kobj, 61 : 0 : rtc->nvram); 62 : 0 : if (err) { 63 : 0 : kfree(rtc->nvram); 64 : 0 : rtc->nvram = NULL; 65 : : } 66 : : 67 : 0 : return err; 68 : : } 69 : : 70 : 0 : static void rtc_nvram_unregister(struct rtc_device *rtc) 71 : : { 72 : 0 : sysfs_remove_bin_file(&rtc->dev.parent->kobj, rtc->nvram); 73 : 0 : kfree(rtc->nvram); 74 : 0 : rtc->nvram = NULL; 75 : 0 : } 76 : : 77 : : /* 78 : : * New ABI, uses nvmem 79 : : */ 80 : 0 : int rtc_nvmem_register(struct rtc_device *rtc, 81 : : struct nvmem_config *nvmem_config) 82 : : { 83 : : struct nvmem_device *nvmem; 84 : : 85 : 0 : if (!nvmem_config) 86 : : return -ENODEV; 87 : : 88 : 0 : nvmem_config->dev = rtc->dev.parent; 89 : 0 : nvmem_config->owner = rtc->owner; 90 : 0 : nvmem = devm_nvmem_register(rtc->dev.parent, nvmem_config); 91 : 0 : if (IS_ERR(nvmem)) 92 : 0 : return PTR_ERR(nvmem); 93 : : 94 : : /* Register the old ABI */ 95 : 0 : if (rtc->nvram_old_abi) 96 : 0 : rtc_nvram_register(rtc, nvmem, nvmem_config->size); 97 : : 98 : : return 0; 99 : : } 100 : : EXPORT_SYMBOL_GPL(rtc_nvmem_register); 101 : : 102 : 0 : void rtc_nvmem_unregister(struct rtc_device *rtc) 103 : : { 104 : : /* unregister the old ABI */ 105 : 0 : if (rtc->nvram) 106 : 0 : rtc_nvram_unregister(rtc); 107 : 0 : }