diff options
Diffstat (limited to 'target/linux/generic/backport-5.10/801-v5.11-0001-nvmem-core-Add-support-for-keepout-regions.patch')
-rw-r--r-- | target/linux/generic/backport-5.10/801-v5.11-0001-nvmem-core-Add-support-for-keepout-regions.patch | 267 |
1 files changed, 0 insertions, 267 deletions
diff --git a/target/linux/generic/backport-5.10/801-v5.11-0001-nvmem-core-Add-support-for-keepout-regions.patch b/target/linux/generic/backport-5.10/801-v5.11-0001-nvmem-core-Add-support-for-keepout-regions.patch deleted file mode 100644 index a0f8c4715e..0000000000 --- a/target/linux/generic/backport-5.10/801-v5.11-0001-nvmem-core-Add-support-for-keepout-regions.patch +++ /dev/null @@ -1,267 +0,0 @@ -From fd3bb8f54a88107570334c156efb0c724a261003 Mon Sep 17 00:00:00 2001 -From: Evan Green <evgreen@chromium.org> -Date: Fri, 27 Nov 2020 10:28:34 +0000 -Subject: [PATCH] nvmem: core: Add support for keepout regions - -Introduce support into the nvmem core for arrays of register ranges -that should not result in actual device access. For these regions a -constant byte (repeated) is returned instead on read, and writes are -quietly ignored and returned as successful. - -This is useful for instance if certain efuse regions are protected -from access by Linux because they contain secret info to another part -of the system (like an integrated modem). - -Signed-off-by: Evan Green <evgreen@chromium.org> -Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> -Link: https://lore.kernel.org/r/20201127102837.19366-3-srinivas.kandagatla@linaro.org -Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> ---- - drivers/nvmem/core.c | 153 ++++++++++++++++++++++++++++++++- - include/linux/nvmem-provider.h | 17 ++++ - 2 files changed, 166 insertions(+), 4 deletions(-) - ---- a/drivers/nvmem/core.c -+++ b/drivers/nvmem/core.c -@@ -34,6 +34,8 @@ struct nvmem_device { - struct bin_attribute eeprom; - struct device *base_dev; - struct list_head cells; -+ const struct nvmem_keepout *keepout; -+ unsigned int nkeepout; - nvmem_reg_read_t reg_read; - nvmem_reg_write_t reg_write; - struct gpio_desc *wp_gpio; -@@ -66,8 +68,8 @@ static LIST_HEAD(nvmem_lookup_list); - - static BLOCKING_NOTIFIER_HEAD(nvmem_notifier); - --static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, -- void *val, size_t bytes) -+static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, -+ void *val, size_t bytes) - { - if (nvmem->reg_read) - return nvmem->reg_read(nvmem->priv, offset, val, bytes); -@@ -75,8 +77,8 @@ static int nvmem_reg_read(struct nvmem_d - return -EINVAL; - } - --static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset, -- void *val, size_t bytes) -+static int __nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset, -+ void *val, size_t bytes) - { - int ret; - -@@ -90,6 +92,88 @@ static int nvmem_reg_write(struct nvmem_ - return -EINVAL; - } - -+static int nvmem_access_with_keepouts(struct nvmem_device *nvmem, -+ unsigned int offset, void *val, -+ size_t bytes, int write) -+{ -+ -+ unsigned int end = offset + bytes; -+ unsigned int kend, ksize; -+ const struct nvmem_keepout *keepout = nvmem->keepout; -+ const struct nvmem_keepout *keepoutend = keepout + nvmem->nkeepout; -+ int rc; -+ -+ /* -+ * Skip all keepouts before the range being accessed. -+ * Keepouts are sorted. -+ */ -+ while ((keepout < keepoutend) && (keepout->end <= offset)) -+ keepout++; -+ -+ while ((offset < end) && (keepout < keepoutend)) { -+ /* Access the valid portion before the keepout. */ -+ if (offset < keepout->start) { -+ kend = min(end, keepout->start); -+ ksize = kend - offset; -+ if (write) -+ rc = __nvmem_reg_write(nvmem, offset, val, ksize); -+ else -+ rc = __nvmem_reg_read(nvmem, offset, val, ksize); -+ -+ if (rc) -+ return rc; -+ -+ offset += ksize; -+ val += ksize; -+ } -+ -+ /* -+ * Now we're aligned to the start of this keepout zone. Go -+ * through it. -+ */ -+ kend = min(end, keepout->end); -+ ksize = kend - offset; -+ if (!write) -+ memset(val, keepout->value, ksize); -+ -+ val += ksize; -+ offset += ksize; -+ keepout++; -+ } -+ -+ /* -+ * If we ran out of keepouts but there's still stuff to do, send it -+ * down directly -+ */ -+ if (offset < end) { -+ ksize = end - offset; -+ if (write) -+ return __nvmem_reg_write(nvmem, offset, val, ksize); -+ else -+ return __nvmem_reg_read(nvmem, offset, val, ksize); -+ } -+ -+ return 0; -+} -+ -+static int nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset, -+ void *val, size_t bytes) -+{ -+ if (!nvmem->nkeepout) -+ return __nvmem_reg_read(nvmem, offset, val, bytes); -+ -+ return nvmem_access_with_keepouts(nvmem, offset, val, bytes, false); -+} -+ -+static int nvmem_reg_write(struct nvmem_device *nvmem, unsigned int offset, -+ void *val, size_t bytes) -+{ -+ if (!nvmem->nkeepout) -+ return __nvmem_reg_write(nvmem, offset, val, bytes); -+ -+ return nvmem_access_with_keepouts(nvmem, offset, val, bytes, true); -+} -+ - #ifdef CONFIG_NVMEM_SYSFS - static const char * const nvmem_type_str[] = { - [NVMEM_TYPE_UNKNOWN] = "Unknown", -@@ -535,6 +619,59 @@ nvmem_find_cell_by_name(struct nvmem_dev - return cell; - } - -+static int nvmem_validate_keepouts(struct nvmem_device *nvmem) -+{ -+ unsigned int cur = 0; -+ const struct nvmem_keepout *keepout = nvmem->keepout; -+ const struct nvmem_keepout *keepoutend = keepout + nvmem->nkeepout; -+ -+ while (keepout < keepoutend) { -+ /* Ensure keepouts are sorted and don't overlap. */ -+ if (keepout->start < cur) { -+ dev_err(&nvmem->dev, -+ "Keepout regions aren't sorted or overlap.\n"); -+ -+ return -ERANGE; -+ } -+ -+ if (keepout->end < keepout->start) { -+ dev_err(&nvmem->dev, -+ "Invalid keepout region.\n"); -+ -+ return -EINVAL; -+ } -+ -+ /* -+ * Validate keepouts (and holes between) don't violate -+ * word_size constraints. -+ */ -+ if ((keepout->end - keepout->start < nvmem->word_size) || -+ ((keepout->start != cur) && -+ (keepout->start - cur < nvmem->word_size))) { -+ -+ dev_err(&nvmem->dev, -+ "Keepout regions violate word_size constraints.\n"); -+ -+ return -ERANGE; -+ } -+ -+ /* Validate keepouts don't violate stride (alignment). */ -+ if (!IS_ALIGNED(keepout->start, nvmem->stride) || -+ !IS_ALIGNED(keepout->end, nvmem->stride)) { -+ -+ dev_err(&nvmem->dev, -+ "Keepout regions violate stride.\n"); -+ -+ return -EINVAL; -+ } -+ -+ cur = keepout->end; -+ keepout++; -+ } -+ -+ return 0; -+} -+ - static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) - { - struct device_node *parent, *child; -@@ -656,6 +793,8 @@ struct nvmem_device *nvmem_register(cons - nvmem->type = config->type; - nvmem->reg_read = config->reg_read; - nvmem->reg_write = config->reg_write; -+ nvmem->keepout = config->keepout; -+ nvmem->nkeepout = config->nkeepout; - if (!config->no_of_node) - nvmem->dev.of_node = config->dev->of_node; - -@@ -703,6 +842,12 @@ struct nvmem_device *nvmem_register(cons - if (rval) - goto err_remove_cells; - -+ if (nvmem->nkeepout) { -+ rval = nvmem_validate_keepouts(nvmem); -+ if (rval) -+ goto err_put_device; -+ } -+ - dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name); - - rval = device_add(&nvmem->dev); ---- a/include/linux/nvmem-provider.h -+++ b/include/linux/nvmem-provider.h -@@ -31,6 +31,19 @@ enum nvmem_type { - #define NVMEM_DEVID_AUTO (-2) - - /** -+ * struct nvmem_keepout - NVMEM register keepout range. -+ * -+ * @start: The first byte offset to avoid. -+ * @end: One beyond the last byte offset to avoid. -+ * @value: The byte to fill reads with for this region. -+ */ -+struct nvmem_keepout { -+ unsigned int start; -+ unsigned int end; -+ unsigned char value; -+}; -+ -+/** - * struct nvmem_config - NVMEM device configuration - * - * @dev: Parent device. -@@ -39,6 +52,8 @@ enum nvmem_type { - * @owner: Pointer to exporter module. Used for refcounting. - * @cells: Optional array of pre-defined NVMEM cells. - * @ncells: Number of elements in cells. -+ * @keepout: Optional array of keepout ranges (sorted ascending by start). -+ * @nkeepout: Number of elements in the keepout array. - * @type: Type of the nvmem storage - * @read_only: Device is read-only. - * @root_only: Device is accessibly to root only. -@@ -65,6 +80,8 @@ struct nvmem_config { - struct module *owner; - const struct nvmem_cell_info *cells; - int ncells; -+ const struct nvmem_keepout *keepout; -+ unsigned int nkeepout; - enum nvmem_type type; - bool read_only; - bool root_only; |