Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168148892
D16419.id46093.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D16419.id46093.diff
View Options
Index: head/share/man/man9/nvmem.9
===================================================================
--- head/share/man/man9/nvmem.9
+++ head/share/man/man9/nvmem.9
@@ -0,0 +1,157 @@
+.\" Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 24, 2018
+.Dt nvmem 9
+.Os
+.Sh NAME
+.Nm nvmem
+.Nm nvmem_get_cell_len ,
+.Nm nvmem_read_cell_by_name ,
+.Nm nvmem_read_cell_by_idx ,
+.Nm nvmem_write_cell_by_name ,
+.Nm nvmem_write_cell_by_idx ,
+.Sh SYNOPSIS
+.Cd "options EXT_RESOURCES"
+.Cd "options FDT"
+.Cd "device nvmem"
+.In sys/extres/nvmem/nvmem.h
+.Ft int
+.Fn nvmem_get_cell_len "phandle_t node" "const char *name"
+.Ft int
+.Fn nvmem_read_cell_by_name "phandle_t node" "const char *name" "void *cell" "size_t buflen"
+.Ft int
+.Fn nvmem_read_cell_by_idx "phandle_t node" "int idx" "void *cell" "size_t buflen"
+.Ft int
+.Fn nvmem_write_cell_by_name "phandle_t node" "const char *name" "void *cell" "size_t buflen"
+.Ft int
+.Fn nvmem_write_cell_by_idx "phandle_t node" "int idx" "void *cell" "size_t buflen"
+.Sh DESCRIPTION
+On some embedded boards, the manufacturer stored some data on a NVMEM
+(Non-Volatile Memory), this is generally stored in some eeprom or fuses.
+.Pp
+The
+.Nm
+API consist of helpers functions for consumer and device methods for
+providers.
+.Sh FUNCTIONS
+.Bl -tag -width indent
+.It Fn nvmem_get_cell_len "phandle_t node" "const char *name"
+Get the size of the cell base on the reg property on the node.
+Return the size or ENOENT if the cell name wasn't found
+.It Fn nvmem_read_cell_by_name "phandle_t node" "const char *name" "void *cell" "size_t buflen"
+Get the cell content based on the name.
+Return 0 on sucess or ENOENT if the cell doesn't exists, ENXIO if no provider device was found,
+EINVAL if the size isn't correct.
+.It Fn nvmem_read_cell_by_idx "phandle_t node" "int idx" "void *cell" "size_t buflen"
+Get the cell content based on the id.
+Return 0 on sucess or ENOENT if the cell doesn't exists, ENXIO if no provider device was found,
+EINVAL if the size isn't correct.
+.It Fn nvmem_write_cell_by_name "phandle_t node" "const char *name" "void *cell" "size_t buflen"
+Write the cell content based on the name.
+Return 0 on sucess or ENOENT if the cell doesn't exists, ENXIO if no provider device was found,
+EINVAL if the size isn't correct.
+.It Fn nvmem_write_cell_by_idx "phandle_t node" "int idx" "void *cell" "size_t buflen"
+Write the cell content based on the id.
+Return 0 on sucess or ENOENT if the cell doesn't exists, ENXIO if no provider device was found,
+EINVAL if the size isn't correct.
+.El
+.Sh DEVICE METHODS
+.Bl -tag -width indent
+.It Fn nvmem_read "device_t dev" "uint32_t offset" "uint32_t size" "uint8_t *buffer"
+Provider device method to read a cell content.
+.It Fn nvmem_write "device_t dev" "uint32_t offset" "uint32_t size" "uint8_t *buffer"
+Provider device method to write a cell content.
+.El
+.Sh EXAMPLES
+Consider this DTS
+.Bd -literal
+/* Provider */
+eeprom: eeprom@20000 {
+ board_id: id@0 {
+ reg = <0x0 0x4>;
+ };
+};
+/* Consumer */
+device@30000 {
+ ...
+
+ nvmem-cells = <&board_id>
+ nvmem-cell-names = "boardid";
+};
+.Ed
+.Pp
+The device driver for eeprom@20000 needs to expose itself as a provider
+.Bd -literal
+#include "nvmem_if.h"
+
+int
+foo_nvmem_read(device_t dev, uint32_t offset, uint32_t size, uint8_t *buffer)
+{
+ /* Read the data */
+}
+
+int
+foo_attach(device_t dev)
+{
+ phandle_t node;
+
+ node = ofw_bus_get_node(dev);
+ ...
+ /* Registering the device so the consumers can find us */
+ OF_device_register_xref(OF_xref_from_node(node), dev);
+
+ ...
+}
+
+static device_method_t foo_methods[] = {
+ ...
+
+ /* nvmem interface */
+ DEVMETHOD(nvmem_read, foo_nvmem_read),
+
+ /* Terminate method list */
+ DEVMETHOD_END
+};
+.Ed
+.Pp
+The consumer device driver for device@30000 can now read the nvmem data
+.Bd -literal
+int
+bar_attach(device_t dev)
+{
+ phandle_t node;
+ uint32_t boardid;
+
+ ...
+ node = ofw_bus_get_node(dev);
+ nvmem_read_cell_by_name(node, "boardid", (void *)&boardid, sizeof(boardid));
+ ...
+}
+.Ed
+.Sh HISTORY
+The nvmem related function first appear in
+.Fx 12.0 .
+The nvmem interface and manual page was written by
+.An Emmanuel Vadot Aq Mt manu@FreeBSD.org .
Index: head/sys/arm/conf/GENERIC
===================================================================
--- head/sys/arm/conf/GENERIC
+++ head/sys/arm/conf/GENERIC
@@ -72,6 +72,7 @@
device clk
device phy
device hwreset
+device nvmem
device regulator
device syscon
Index: head/sys/arm64/conf/GENERIC
===================================================================
--- head/sys/arm64/conf/GENERIC
+++ head/sys/arm64/conf/GENERIC
@@ -251,6 +251,7 @@
device clk
device phy
device hwreset
+device nvmem
device regulator
device syscon
Index: head/sys/conf/files
===================================================================
--- head/sys/conf/files
+++ head/sys/conf/files
@@ -1750,6 +1750,8 @@
dev/extres/phy/phynode_if.m optional ext_resources phy fdt
dev/extres/hwreset/hwreset.c optional ext_resources hwreset fdt
dev/extres/hwreset/hwreset_if.m optional ext_resources hwreset fdt
+dev/extres/nvmem/nvmem.c optional ext_resources nvmem fdt
+dev/extres/nvmem/nvmem_if.m optional ext_resources nvmem fdt
dev/extres/regulator/regdev_if.m optional ext_resources regulator fdt
dev/extres/regulator/regnode_if.m optional ext_resources regulator fdt
dev/extres/regulator/regulator.c optional ext_resources regulator fdt
Index: head/sys/dev/extres/nvmem/nvmem.h
===================================================================
--- head/sys/dev/extres/nvmem/nvmem.h
+++ head/sys/dev/extres/nvmem/nvmem.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_EXTRES_NVMEM_H_
+#define _DEV_EXTRES_NVMEM_H_
+
+int nvmem_get_cell_len(phandle_t node, const char *name);
+int nvmem_read_cell_by_name(phandle_t node, const char *name, void *cell, size_t buflen);
+int nvmem_read_cell_by_idx(phandle_t node, int idx, void *cell, size_t buflen);
+int nvmem_write_cell_by_name(phandle_t node, const char *name, void *cell, size_t buflen);
+int nvmem_write_cell_by_idx(phandle_t node, int idx, void *cell, size_t buflen);
+
+#endif /* _DEV_EXTRES_NVMEM_H_ */
Index: head/sys/dev/extres/nvmem/nvmem.c
===================================================================
--- head/sys/dev/extres/nvmem/nvmem.c
+++ head/sys/dev/extres/nvmem/nvmem.c
@@ -0,0 +1,199 @@
+/*-
+ * Copyright 2018 Emmanuel Vadot <manu@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "nvmem.h"
+#include "nvmem_if.h"
+
+static int
+nvmem_get_cell_node(phandle_t node, int idx, phandle_t *cell)
+{
+ phandle_t *p_cell;
+ phandle_t cell_node;
+ int ncell;
+
+ if (!OF_hasprop(node, "nvmem-cells") ||
+ !OF_hasprop(node, "nvmem-cell-names"))
+ return (ENOENT);
+
+ ncell = OF_getencprop_alloc_multi(node, "nvmem-cells", sizeof(*p_cell), (void **)&p_cell);
+ if (ncell <= 0)
+ return (ENOENT);
+
+ cell_node = OF_node_from_xref(p_cell[idx]);
+ if (cell_node == p_cell[idx]) {
+ if (bootverbose)
+ printf("nvmem_get_node: Cannot resolve phandle %x\n",
+ p_cell[idx]);
+ OF_prop_free(p_cell);
+ return (ENOENT);
+ }
+
+ OF_prop_free(p_cell);
+ *cell = cell_node;
+
+ return (0);
+}
+
+int
+nvmem_get_cell_len(phandle_t node, const char *name)
+{
+ phandle_t cell_node;
+ uint32_t reg[2];
+ int rv, idx;
+
+ rv = ofw_bus_find_string_index(node, "nvmem-cell-names", name, &idx);
+ if (rv != 0)
+ return (rv);
+
+ rv = nvmem_get_cell_node(node, idx, &cell_node);
+ if (rv != 0)
+ return (rv);
+
+ if (OF_getencprop(cell_node, "reg", reg, sizeof(reg)) != sizeof(reg)) {
+ if (bootverbose)
+ printf("nvmem_get_cell_len: Cannot parse reg property of cell %s\n",
+ name);
+ return (ENOENT);
+ }
+
+ return (reg[1]);
+}
+
+int
+nvmem_read_cell_by_idx(phandle_t node, int idx, void *cell, size_t buflen)
+{
+ phandle_t cell_node;
+ device_t provider;
+ uint32_t reg[2];
+ int rv;
+
+ rv = nvmem_get_cell_node(node, idx, &cell_node);
+ if (rv != 0)
+ return (rv);
+
+ /* Validate the reg property */
+ if (OF_getencprop(cell_node, "reg", reg, sizeof(reg)) != sizeof(reg)) {
+ if (bootverbose)
+ printf("nvmem_get_cell_by_name: Cannot parse reg property of cell %d\n",
+ idx);
+ return (ENOENT);
+ }
+
+ if (buflen != reg[1])
+ return (EINVAL);
+
+ provider = OF_device_from_xref(OF_xref_from_node(OF_parent(cell_node)));
+ if (provider == NULL) {
+ if (bootverbose)
+ printf("nvmem_get_cell_by_idx: Cannot find the nvmem device\n");
+ return (ENXIO);
+ }
+
+ rv = NVMEM_READ(provider, reg[0], reg[1], cell);
+ if (rv != 0) {
+ return (rv);
+ }
+
+ return (0);
+}
+
+int
+nvmem_read_cell_by_name(phandle_t node, const char *name, void *cell, size_t buflen)
+{
+ int rv, idx;
+
+ rv = ofw_bus_find_string_index(node, "nvmem-cell-names", name, &idx);
+ if (rv != 0)
+ return (rv);
+
+ return (nvmem_read_cell_by_idx(node, idx, cell, buflen));
+}
+
+int
+nvmem_write_cell_by_idx(phandle_t node, int idx, void *cell, size_t buflen)
+{
+ phandle_t cell_node, prov_node;
+ device_t provider;
+ uint32_t reg[2];
+ int rv;
+
+ rv = nvmem_get_cell_node(node, idx, &cell_node);
+ if (rv != 0)
+ return (rv);
+
+ prov_node = OF_parent(cell_node);
+ if (OF_hasprop(prov_node, "read-only"))
+ return (ENXIO);
+
+ /* Validate the reg property */
+ if (OF_getencprop(cell_node, "reg", reg, sizeof(reg)) != sizeof(reg)) {
+ if (bootverbose)
+ printf("nvmem_get_cell_by_idx: Cannot parse reg property of cell %d\n",
+ idx);
+ return (ENXIO);
+ }
+
+ if (buflen != reg[1])
+ return (EINVAL);
+
+ provider = OF_device_from_xref(OF_xref_from_node(prov_node));
+ if (provider == NULL) {
+ if (bootverbose)
+ printf("nvmem_get_cell_by_idx: Cannot find the nvmem device\n");
+ return (ENXIO);
+ }
+
+ rv = NVMEM_WRITE(provider, reg[0], reg[1], cell);
+ if (rv != 0) {
+ return (rv);
+ }
+
+ return (0);
+}
+
+int
+nvmem_write_cell_by_name(phandle_t node, const char *name, void *cell, size_t buflen)
+{
+ int rv, idx;
+
+ rv = ofw_bus_find_string_index(node, "nvmem-cell-names", name, &idx);
+ if (rv != 0)
+ return (rv);
+
+ return (nvmem_write_cell_by_idx(node, idx, cell, buflen));
+}
Index: head/sys/dev/extres/nvmem/nvmem_if.m
===================================================================
--- head/sys/dev/extres/nvmem/nvmem_if.m
+++ head/sys/dev/extres/nvmem/nvmem_if.m
@@ -0,0 +1,67 @@
+#-
+# Copyright (c) 2018 Emmanuel Vadot <manu@FreeBSD.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+INTERFACE nvmem;
+
+#
+# Default implementations of some methods.
+#
+CODE {
+ static int
+ null_nvmem_read(device_t dev __unused, uint32_t offset __unused, uint32_t size __unused, uint8_t *buffer __unused)
+ {
+
+ return (ENXIO);
+ }
+
+ static int
+ null_nvmem_write(device_t dev __unused, uint32_t offset __unused, uint32_t size __unused, uint8_t *buffer __unused)
+ {
+
+ return (ENXIO);
+ }
+};
+
+#
+# Read
+#
+METHOD int read {
+ device_t dev;
+ uint32_t offset;
+ uint32_t size;
+ uint8_t *buffer;
+} DEFAULT null_nvmem_read;
+
+#
+# Write
+#
+METHOD int write {
+ device_t dev;
+ uint32_t offset;
+ uint32_t size;
+ uint8_t *buffer;
+} DEFAULT null_nvmem_write;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Aug 27, 2:44 PM (6 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37394255
Default Alt Text
D16419.id46093.diff (16 KB)
Attached To
Mode
D16419: nvmem: Add nvmem interface and helpers
Attached
Detach File
Event Timeline
Log In to Comment