nvmem.c 2.3 KB

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