nvmem.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * RTC subsystem, nvmem interface
  3. *
  4. * Copyright (C) 2017 Alexandre Belloni
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/err.h>
  11. #include <linux/types.h>
  12. #include <linux/nvmem-consumer.h>
  13. #include <linux/rtc.h>
  14. #include <linux/sysfs.h>
  15. /*
  16. * Deprecated ABI compatibility, this should be removed at some point
  17. */
  18. static const char nvram_warning[] = "Deprecated ABI, please use nvmem";
  19. static ssize_t
  20. rtc_nvram_read(struct file *filp, struct kobject *kobj,
  21. struct bin_attribute *attr,
  22. char *buf, loff_t off, size_t count)
  23. {
  24. struct rtc_device *rtc = attr->private;
  25. dev_warn_once(kobj_to_dev(kobj), nvram_warning);
  26. return nvmem_device_read(rtc->nvmem, off, count, buf);
  27. }
  28. static ssize_t
  29. rtc_nvram_write(struct file *filp, struct kobject *kobj,
  30. struct bin_attribute *attr,
  31. char *buf, loff_t off, size_t count)
  32. {
  33. struct rtc_device *rtc = attr->private;
  34. dev_warn_once(kobj_to_dev(kobj), nvram_warning);
  35. return nvmem_device_write(rtc->nvmem, off, count, buf);
  36. }
  37. static int rtc_nvram_register(struct rtc_device *rtc, size_t size)
  38. {
  39. int err;
  40. rtc->nvram = devm_kzalloc(rtc->dev.parent,
  41. sizeof(struct bin_attribute),
  42. GFP_KERNEL);
  43. if (!rtc->nvram)
  44. return -ENOMEM;
  45. rtc->nvram->attr.name = "nvram";
  46. rtc->nvram->attr.mode = 0644;
  47. rtc->nvram->private = rtc;
  48. sysfs_bin_attr_init(rtc->nvram);
  49. rtc->nvram->read = rtc_nvram_read;
  50. rtc->nvram->write = rtc_nvram_write;
  51. rtc->nvram->size = size;
  52. err = sysfs_create_bin_file(&rtc->dev.parent->kobj,
  53. rtc->nvram);
  54. if (err) {
  55. devm_kfree(rtc->dev.parent, rtc->nvram);
  56. rtc->nvram = NULL;
  57. }
  58. return err;
  59. }
  60. static void rtc_nvram_unregister(struct rtc_device *rtc)
  61. {
  62. sysfs_remove_bin_file(&rtc->dev.parent->kobj, rtc->nvram);
  63. }
  64. /*
  65. * New ABI, uses nvmem
  66. */
  67. int rtc_nvmem_register(struct rtc_device *rtc,
  68. struct nvmem_config *nvmem_config)
  69. {
  70. if (!IS_ERR_OR_NULL(rtc->nvmem))
  71. return -EBUSY;
  72. if (!nvmem_config)
  73. return -ENODEV;
  74. nvmem_config->dev = rtc->dev.parent;
  75. nvmem_config->owner = rtc->owner;
  76. rtc->nvmem = nvmem_register(nvmem_config);
  77. if (IS_ERR(rtc->nvmem))
  78. return PTR_ERR(rtc->nvmem);
  79. /* Register the old ABI */
  80. if (rtc->nvram_old_abi)
  81. rtc_nvram_register(rtc, nvmem_config->size);
  82. return 0;
  83. }
  84. EXPORT_SYMBOL_GPL(rtc_nvmem_register);
  85. void rtc_nvmem_unregister(struct rtc_device *rtc)
  86. {
  87. if (IS_ERR_OR_NULL(rtc->nvmem))
  88. return;
  89. /* unregister the old ABI */
  90. if (rtc->nvram)
  91. rtc_nvram_unregister(rtc);
  92. nvmem_unregister(rtc->nvmem);
  93. }