aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/extres
diff options
context:
space:
mode:
authorEmmanuel Vadot <manu@FreeBSD.org>2018-07-31 19:08:24 +0000
committerEmmanuel Vadot <manu@FreeBSD.org>2018-07-31 19:08:24 +0000
commitcfe196fbed0284e4aaa744d53396755365f8bbaa (patch)
treee48514bac4588c4d72e1d9d5592381c6cdf337ce /sys/dev/extres
parent8608db1eb6d804e7dfa68ed1b14ef8fc5375a12f (diff)
Notes
Diffstat (limited to 'sys/dev/extres')
-rw-r--r--sys/dev/extres/nvmem/nvmem.c199
-rw-r--r--sys/dev/extres/nvmem/nvmem.h37
-rw-r--r--sys/dev/extres/nvmem/nvmem_if.m67
3 files changed, 303 insertions, 0 deletions
diff --git a/sys/dev/extres/nvmem/nvmem.c b/sys/dev/extres/nvmem/nvmem.c
new file mode 100644
index 0000000000000..c6f928dc35208
--- /dev/null
+++ b/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));
+}
diff --git a/sys/dev/extres/nvmem/nvmem.h b/sys/dev/extres/nvmem/nvmem.h
new file mode 100644
index 0000000000000..b711423152265
--- /dev/null
+++ b/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_ */
diff --git a/sys/dev/extres/nvmem/nvmem_if.m b/sys/dev/extres/nvmem/nvmem_if.m
new file mode 100644
index 0000000000000..769e07d9bc4f3
--- /dev/null
+++ b/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;