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