Skip to content

Commit e2a5402

Browse files
Srinivas-Kandagatlagregkh
authored andcommitted
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 <[email protected]> Tested-by: Stefan Wahren <[email protected]> Tested-by: Philipp Zabel <[email protected]> Tested-by: Rajendra Nayak <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 69aba79 commit e2a5402

File tree

2 files changed

+331
-0
lines changed

2 files changed

+331
-0
lines changed

drivers/nvmem/core.c

+258
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,148 @@ static void __nvmem_device_put(struct nvmem_device *nvmem)
445445
mutex_unlock(&nvmem_mutex);
446446
}
447447

448+
static int nvmem_match(struct device *dev, void *data)
449+
{
450+
return !strcmp(dev_name(dev), data);
451+
}
452+
453+
static 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+
*/
475+
struct 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+
}
489+
EXPORT_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+
*/
501+
struct 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+
}
515+
EXPORT_SYMBOL_GPL(nvmem_device_get);
516+
517+
static 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+
527+
static 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+
*/
538+
void 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+
}
547+
EXPORT_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+
*/
554+
void nvmem_device_put(struct nvmem_device *nvmem)
555+
{
556+
__nvmem_device_put(nvmem);
557+
}
558+
EXPORT_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+
*/
570+
struct 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+
}
588+
EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
589+
448590
static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
449591
{
450592
struct nvmem_cell *cell = NULL;
@@ -806,6 +948,122 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
806948
}
807949
EXPORT_SYMBOL_GPL(nvmem_cell_write);
808950

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+
*/
961+
ssize_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+
}
981+
EXPORT_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+
* */
992+
int 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+
}
1007+
EXPORT_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+
*/
1020+
int 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+
}
1036+
EXPORT_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+
* */
1048+
int 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+
}
1065+
EXPORT_SYMBOL_GPL(nvmem_device_write);
1066+
8091067
static int __init nvmem_init(void)
8101068
{
8111069
return bus_register(&nvmem_bus_type);

include/linux/nvmem-consumer.h

+73
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct device;
1616
struct device_node;
1717
/* consumer cookie */
1818
struct nvmem_cell;
19+
struct nvmem_device;
1920

2021
struct nvmem_cell_info {
2122
const char *name;
@@ -35,6 +36,21 @@ void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
3536
void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
3637
int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
3738

39+
/* direct nvmem device read/write interface */
40+
struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
41+
struct nvmem_device *devm_nvmem_device_get(struct device *dev,
42+
const char *name);
43+
void nvmem_device_put(struct nvmem_device *nvmem);
44+
void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
45+
int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
46+
size_t bytes, void *buf);
47+
int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
48+
size_t bytes, void *buf);
49+
ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
50+
struct nvmem_cell_info *info, void *buf);
51+
int nvmem_device_cell_write(struct nvmem_device *nvmem,
52+
struct nvmem_cell_info *info, void *buf);
53+
3854
#else
3955

4056
static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
@@ -68,17 +84,74 @@ static inline int nvmem_cell_write(struct nvmem_cell *cell,
6884
{
6985
return -ENOSYS;
7086
}
87+
88+
static inline struct nvmem_device *nvmem_device_get(struct device *dev,
89+
const char *name)
90+
{
91+
return ERR_PTR(-ENOSYS);
92+
}
93+
94+
static inline struct nvmem_device *devm_nvmem_device_get(struct device *dev,
95+
const char *name)
96+
{
97+
return ERR_PTR(-ENOSYS);
98+
}
99+
100+
static inline void nvmem_device_put(struct nvmem_device *nvmem)
101+
{
102+
}
103+
104+
static inline void devm_nvmem_device_put(struct device *dev,
105+
struct nvmem_device *nvmem)
106+
{
107+
}
108+
109+
static 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+
116+
static 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+
123+
static 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+
130+
static inline int nvmem_device_write(struct nvmem_device *nvmem,
131+
unsigned int offset, size_t bytes,
132+
void *buf)
133+
{
134+
return -ENOSYS;
135+
}
71136
#endif /* CONFIG_NVMEM */
72137

73138
#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
74139
struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
75140
const char *name);
141+
struct nvmem_device *of_nvmem_device_get(struct device_node *np,
142+
const char *name);
76143
#else
77144
static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
78145
const char *name)
79146
{
80147
return ERR_PTR(-ENOSYS);
81148
}
149+
150+
static inline struct nvmem_device *of_nvmem_device_get(struct device_node *np,
151+
const char *name)
152+
{
153+
return ERR_PTR(-ENOSYS);
154+
}
82155
#endif /* CONFIG_NVMEM && CONFIG_OF */
83156

84157
#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */

0 commit comments

Comments
 (0)