aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2015-07-27 07:13:45 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-08-05 16:43:44 -0400
commite2a5402ec7c6d0442cca370a0097e75750f81398 (patch)
treef52d6cbb6926345bb556c0b14d4a639abc4f9cec
parent69aba7948cbe53f2f1827e84e9dd0ae470a5072e (diff)
nvmem: Add nvmem_device based consumer apis.
This patch adds read/write apis which are based on nvmem_device. It is common that the drivers like omap cape manager or qcom cpr driver to access bytes directly at particular offset in the eeprom and not from nvmem cell info in DT. These driver would need to get access to the nvmem directly, which is what these new APIS provide. These wrapper apis would help such users to avoid code duplication in there drivers and also avoid them reading a big eeprom blob and parsing it internally in there driver. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Tested-by: Stefan Wahren <stefan.wahren@i2se.com> Tested-by: Philipp Zabel <p.zabel@pengutronix.de> Tested-by: Rajendra Nayak <rnayak@codeaurora.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/nvmem/core.c258
-rw-r--r--include/linux/nvmem-consumer.h73
2 files changed, 331 insertions, 0 deletions
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 8c16ae2e1308..d3c6676b3c0c 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -445,6 +445,148 @@ static void __nvmem_device_put(struct nvmem_device *nvmem)
445 mutex_unlock(&nvmem_mutex); 445 mutex_unlock(&nvmem_mutex);
446} 446}
447 447
448static int nvmem_match(struct device *dev, void *data)
449{
450 return !strcmp(dev_name(dev), data);
451}
452
453static struct nvmem_device *nvmem_find(const char *name)
454{
455 struct device *d;
456
457 d = bus_find_device(&nvmem_bus_type, NULL, (void *)name, nvmem_match);
458
459 if (!d)
460 return NULL;
461
462 return to_nvmem_device(d);
463}
464
465#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
466/**
467 * of_nvmem_device_get() - Get nvmem device from a given id
468 *
469 * @dev node: Device tree node that uses the nvmem device
470 * @id: nvmem name from nvmem-names property.
471 *
472 * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
473 * on success.
474 */
475struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
476{
477
478 struct device_node *nvmem_np;
479 int index;
480
481 index = of_property_match_string(np, "nvmem-names", id);
482
483 nvmem_np = of_parse_phandle(np, "nvmem", index);
484 if (!nvmem_np)
485 return ERR_PTR(-EINVAL);
486
487 return __nvmem_device_get(nvmem_np, NULL, NULL);
488}
489EXPORT_SYMBOL_GPL(of_nvmem_device_get);
490#endif
491
492/**
493 * nvmem_device_get() - Get nvmem device from a given id
494 *
495 * @dev : Device that uses the nvmem device
496 * @id: nvmem name from nvmem-names property.
497 *
498 * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
499 * on success.
500 */
501struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
502{
503 if (dev->of_node) { /* try dt first */
504 struct nvmem_device *nvmem;
505
506 nvmem = of_nvmem_device_get(dev->of_node, dev_name);
507
508 if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
509 return nvmem;
510
511 }
512
513 return nvmem_find(dev_name);
514}
515EXPORT_SYMBOL_GPL(nvmem_device_get);
516
517static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
518{
519 struct nvmem_device **nvmem = res;
520
521 if (WARN_ON(!nvmem || !*nvmem))
522 return 0;
523
524 return *nvmem == data;
525}
526
527static void devm_nvmem_device_release(struct device *dev, void *res)
528{
529 nvmem_device_put(*(struct nvmem_device **)res);
530}
531
532/**
533 * devm_nvmem_device_put() - put alredy got nvmem device
534 *
535 * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
536 * that needs to be released.
537 */
538void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
539{
540 int ret;
541
542 ret = devres_release(dev, devm_nvmem_device_release,
543 devm_nvmem_device_match, nvmem);
544
545 WARN_ON(ret);
546}
547EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
548
549/**
550 * nvmem_device_put() - put alredy got nvmem device
551 *
552 * @nvmem: pointer to nvmem device that needs to be released.
553 */
554void nvmem_device_put(struct nvmem_device *nvmem)
555{
556 __nvmem_device_put(nvmem);
557}
558EXPORT_SYMBOL_GPL(nvmem_device_put);
559
560/**
561 * devm_nvmem_device_get() - Get nvmem cell of device form a given id
562 *
563 * @dev node: Device tree node that uses the nvmem cell
564 * @id: nvmem name in nvmems property.
565 *
566 * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
567 * on success. The nvmem_cell will be freed by the automatically once the
568 * device is freed.
569 */
570struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
571{
572 struct nvmem_device **ptr, *nvmem;
573
574 ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
575 if (!ptr)
576 return ERR_PTR(-ENOMEM);
577
578 nvmem = nvmem_device_get(dev, id);
579 if (!IS_ERR(nvmem)) {
580 *ptr = nvmem;
581 devres_add(dev, ptr);
582 } else {
583 devres_free(ptr);
584 }
585
586 return nvmem;
587}
588EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
589
448static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id) 590static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
449{ 591{
450 struct nvmem_cell *cell = NULL; 592 struct nvmem_cell *cell = NULL;
@@ -806,6 +948,122 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
806} 948}
807EXPORT_SYMBOL_GPL(nvmem_cell_write); 949EXPORT_SYMBOL_GPL(nvmem_cell_write);
808 950
951/**
952 * nvmem_device_cell_read() - Read a given nvmem device and cell
953 *
954 * @nvmem: nvmem device to read from.
955 * @info: nvmem cell info to be read.
956 * @buf: buffer pointer which will be populated on successful read.
957 *
958 * Return: length of successful bytes read on success and negative
959 * error code on error.
960 */
961ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
962 struct nvmem_cell_info *info, void *buf)
963{
964 struct nvmem_cell cell;
965 int rc;
966 ssize_t len;
967
968 if (!nvmem || !nvmem->regmap)
969 return -EINVAL;
970
971 rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
972 if (IS_ERR_VALUE(rc))
973 return rc;
974
975 rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
976 if (IS_ERR_VALUE(rc))
977 return rc;
978
979 return len;
980}
981EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
982
983/**
984 * nvmem_device_cell_write() - Write cell to a given nvmem device
985 *
986 * @nvmem: nvmem device to be written to.
987 * @info: nvmem cell info to be written
988 * @buf: buffer to be written to cell.
989 *
990 * Return: length of bytes written or negative error code on failure.
991 * */
992int nvmem_device_cell_write(struct nvmem_device *nvmem,
993 struct nvmem_cell_info *info, void *buf)
994{
995 struct nvmem_cell cell;
996 int rc;
997
998 if (!nvmem || !nvmem->regmap)
999 return -EINVAL;
1000
1001 rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
1002 if (IS_ERR_VALUE(rc))
1003 return rc;
1004
1005 return nvmem_cell_write(&cell, buf, cell.bytes);
1006}
1007EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
1008
1009/**
1010 * nvmem_device_read() - Read from a given nvmem device
1011 *
1012 * @nvmem: nvmem device to read from.
1013 * @offset: offset in nvmem device.
1014 * @bytes: number of bytes to read.
1015 * @buf: buffer pointer which will be populated on successful read.
1016 *
1017 * Return: length of successful bytes read on success and negative
1018 * error code on error.
1019 */
1020int nvmem_device_read(struct nvmem_device *nvmem,
1021 unsigned int offset,
1022 size_t bytes, void *buf)
1023{
1024 int rc;
1025
1026 if (!nvmem || !nvmem->regmap)
1027 return -EINVAL;
1028
1029 rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes);
1030
1031 if (IS_ERR_VALUE(rc))
1032 return rc;
1033
1034 return bytes;
1035}
1036EXPORT_SYMBOL_GPL(nvmem_device_read);
1037
1038/**
1039 * nvmem_device_write() - Write cell to a given nvmem device
1040 *
1041 * @nvmem: nvmem device to be written to.
1042 * @offset: offset in nvmem device.
1043 * @bytes: number of bytes to write.
1044 * @buf: buffer to be written.
1045 *
1046 * Return: length of bytes written or negative error code on failure.
1047 * */
1048int nvmem_device_write(struct nvmem_device *nvmem,
1049 unsigned int offset,
1050 size_t bytes, void *buf)
1051{
1052 int rc;
1053
1054 if (!nvmem || !nvmem->regmap)
1055 return -EINVAL;
1056
1057 rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes);
1058
1059 if (IS_ERR_VALUE(rc))
1060 return rc;
1061
1062
1063 return bytes;
1064}
1065EXPORT_SYMBOL_GPL(nvmem_device_write);
1066
809static int __init nvmem_init(void) 1067static int __init nvmem_init(void)
810{ 1068{
811 return bus_register(&nvmem_bus_type); 1069 return bus_register(&nvmem_bus_type);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 297cc67b7211..9bb77d3ed6e0 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -16,6 +16,7 @@ struct device;
16struct device_node; 16struct device_node;
17/* consumer cookie */ 17/* consumer cookie */
18struct nvmem_cell; 18struct nvmem_cell;
19struct nvmem_device;
19 20
20struct nvmem_cell_info { 21struct nvmem_cell_info {
21 const char *name; 22 const char *name;
@@ -35,6 +36,21 @@ void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
35void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len); 36void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
36int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len); 37int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
37 38
39/* direct nvmem device read/write interface */
40struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
41struct nvmem_device *devm_nvmem_device_get(struct device *dev,
42 const char *name);
43void nvmem_device_put(struct nvmem_device *nvmem);
44void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
45int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
46 size_t bytes, void *buf);
47int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
48 size_t bytes, void *buf);
49ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
50 struct nvmem_cell_info *info, void *buf);
51int nvmem_device_cell_write(struct nvmem_device *nvmem,
52 struct nvmem_cell_info *info, void *buf);
53
38#else 54#else
39 55
40static inline struct nvmem_cell *nvmem_cell_get(struct device *dev, 56static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
@@ -68,17 +84,74 @@ static inline int nvmem_cell_write(struct nvmem_cell *cell,
68{ 84{
69 return -ENOSYS; 85 return -ENOSYS;
70} 86}
87
88static inline struct nvmem_device *nvmem_device_get(struct device *dev,
89 const char *name)
90{
91 return ERR_PTR(-ENOSYS);
92}
93
94static inline struct nvmem_device *devm_nvmem_device_get(struct device *dev,
95 const char *name)
96{
97 return ERR_PTR(-ENOSYS);
98}
99
100static inline void nvmem_device_put(struct nvmem_device *nvmem)
101{
102}
103
104static inline void devm_nvmem_device_put(struct device *dev,
105 struct nvmem_device *nvmem)
106{
107}
108
109static inline ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
110 struct nvmem_cell_info *info,
111 void *buf)
112{
113 return -ENOSYS;
114}
115
116static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
117 struct nvmem_cell_info *info,
118 void *buf)
119{
120 return -ENOSYS;
121}
122
123static inline int nvmem_device_read(struct nvmem_device *nvmem,
124 unsigned int offset, size_t bytes,
125 void *buf)
126{
127 return -ENOSYS;
128}
129
130static inline int nvmem_device_write(struct nvmem_device *nvmem,
131 unsigned int offset, size_t bytes,
132 void *buf)
133{
134 return -ENOSYS;
135}
71#endif /* CONFIG_NVMEM */ 136#endif /* CONFIG_NVMEM */
72 137
73#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF) 138#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
74struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, 139struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
75 const char *name); 140 const char *name);
141struct nvmem_device *of_nvmem_device_get(struct device_node *np,
142 const char *name);
76#else 143#else
77static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, 144static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
78 const char *name) 145 const char *name)
79{ 146{
80 return ERR_PTR(-ENOSYS); 147 return ERR_PTR(-ENOSYS);
81} 148}
149
150static inline struct nvmem_device *of_nvmem_device_get(struct device_node *np,
151 const char *name)
152{
153 return ERR_PTR(-ENOSYS);
154}
82#endif /* CONFIG_NVMEM && CONFIG_OF */ 155#endif /* CONFIG_NVMEM && CONFIG_OF */
83 156
84#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */ 157#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */