blob: ebdfe8e3a1a0417235e91e30b824e51c5c7d8020 [file] [log] [blame]
Alexandre Belloni697e5a42017-07-06 11:42:02 +02001/*
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
11#include <linux/err.h>
12#include <linux/types.h>
13#include <linux/nvmem-consumer.h>
14#include <linux/rtc.h>
15#include <linux/sysfs.h>
16
Alexandre Belloni697e5a42017-07-06 11:42:02 +020017/*
18 * Deprecated ABI compatibility, this should be removed at some point
19 */
20
21static const char nvram_warning[] = "Deprecated ABI, please use nvmem";
22
23static ssize_t
24rtc_nvram_read(struct file *filp, struct kobject *kobj,
25 struct bin_attribute *attr,
26 char *buf, loff_t off, size_t count)
27{
Alexandre Belloni697e5a42017-07-06 11:42:02 +020028 dev_warn_once(kobj_to_dev(kobj), nvram_warning);
29
Alexandre Belloni41c9e132018-11-10 21:29:03 +010030 return nvmem_device_read(attr->private, off, count, buf);
Alexandre Belloni697e5a42017-07-06 11:42:02 +020031}
32
33static ssize_t
34rtc_nvram_write(struct file *filp, struct kobject *kobj,
35 struct bin_attribute *attr,
36 char *buf, loff_t off, size_t count)
37{
Alexandre Belloni697e5a42017-07-06 11:42:02 +020038 dev_warn_once(kobj_to_dev(kobj), nvram_warning);
39
Alexandre Belloni41c9e132018-11-10 21:29:03 +010040 return nvmem_device_write(attr->private, off, count, buf);
Alexandre Belloni697e5a42017-07-06 11:42:02 +020041}
42
Alexandre Belloni41c9e132018-11-10 21:29:03 +010043static int rtc_nvram_register(struct rtc_device *rtc,
44 struct nvmem_device *nvmem, size_t size)
Alexandre Belloni697e5a42017-07-06 11:42:02 +020045{
46 int err;
47
48 rtc->nvram = devm_kzalloc(rtc->dev.parent,
49 sizeof(struct bin_attribute),
50 GFP_KERNEL);
51 if (!rtc->nvram)
52 return -ENOMEM;
53
54 rtc->nvram->attr.name = "nvram";
55 rtc->nvram->attr.mode = 0644;
Alexandre Belloni41c9e132018-11-10 21:29:03 +010056 rtc->nvram->private = nvmem;
Alexandre Belloni697e5a42017-07-06 11:42:02 +020057
58 sysfs_bin_attr_init(rtc->nvram);
59
60 rtc->nvram->read = rtc_nvram_read;
61 rtc->nvram->write = rtc_nvram_write;
Alexandre Belloni4cce9d32018-02-12 23:47:16 +010062 rtc->nvram->size = size;
Alexandre Belloni697e5a42017-07-06 11:42:02 +020063
64 err = sysfs_create_bin_file(&rtc->dev.parent->kobj,
65 rtc->nvram);
66 if (err) {
67 devm_kfree(rtc->dev.parent, rtc->nvram);
68 rtc->nvram = NULL;
69 }
70
71 return err;
72}
73
74static void rtc_nvram_unregister(struct rtc_device *rtc)
75{
76 sysfs_remove_bin_file(&rtc->dev.parent->kobj, rtc->nvram);
77}
78
79/*
80 * New ABI, uses nvmem
81 */
Alexandre Belloni2cc82122018-02-12 23:47:17 +010082int rtc_nvmem_register(struct rtc_device *rtc,
83 struct nvmem_config *nvmem_config)
Alexandre Belloni697e5a42017-07-06 11:42:02 +020084{
Alexandre Belloni41c9e132018-11-10 21:29:03 +010085 struct nvmem_device *nvmem;
Alexandre Belloniab3ea362018-02-12 23:47:18 +010086
Alexandre Belloni4cce9d32018-02-12 23:47:16 +010087 if (!nvmem_config)
Alexandre Belloni2cc82122018-02-12 23:47:17 +010088 return -ENODEV;
Alexandre Belloni697e5a42017-07-06 11:42:02 +020089
Alexandre Belloniac757792018-02-28 21:58:02 +010090 nvmem_config->dev = rtc->dev.parent;
Alexandre Belloni4cce9d32018-02-12 23:47:16 +010091 nvmem_config->owner = rtc->owner;
Alexandre Belloni41c9e132018-11-10 21:29:03 +010092 nvmem = devm_nvmem_register(rtc->dev.parent, nvmem_config);
93 if (IS_ERR(nvmem))
94 return PTR_ERR(nvmem);
Alexandre Belloni697e5a42017-07-06 11:42:02 +020095
96 /* Register the old ABI */
97 if (rtc->nvram_old_abi)
Alexandre Belloni41c9e132018-11-10 21:29:03 +010098 rtc_nvram_register(rtc, nvmem, nvmem_config->size);
Alexandre Belloni2cc82122018-02-12 23:47:17 +010099
100 return 0;
Alexandre Belloni697e5a42017-07-06 11:42:02 +0200101}
Alexandre Bellonifd5cd212018-02-12 23:47:19 +0100102EXPORT_SYMBOL_GPL(rtc_nvmem_register);
Alexandre Belloni697e5a42017-07-06 11:42:02 +0200103
104void rtc_nvmem_unregister(struct rtc_device *rtc)
105{
Alexandre Belloni697e5a42017-07-06 11:42:02 +0200106 /* unregister the old ABI */
107 if (rtc->nvram)
108 rtc_nvram_unregister(rtc);
Alexandre Belloni697e5a42017-07-06 11:42:02 +0200109}