Hi Greg,
Here are some nvmem patches bit more than usual for 6.4 that includes
- Support for nvmem layouts modules, post-processing, thanks to Michael and
Miquel for being patience and driving this effort.
- Enhancements in dt core to support nvmem layout modules and some
changes in other drivers to support this enhancements. All of these
are acked/reviwed by respective maintainers.
- Updated to qfprom bindings to include various Qualcomm SoCs.
- sl28vpd and onie layout providers.
- u-boot-env post processing support.
- move imx provider to use new layout apis
- few minor fixes across core and providers drivers.
Can you please queue them up for 6.4.
Thanks,
Srini
AngeloGioacchino Del Regno (1):
nvmem: mtk-efuse: Support postprocessing for GPU speed binning data
Colin Ian King (1):
dt-bindings: nvmem: Fix spelling mistake "platforn" -> "platform"
Johan Hovold (1):
dt-bindings: nvmem: qcom,spmi-sdam: fix example 'reg' property
Konrad Dybcio (2):
dt-bindings: nvmem: Add compatible for SM6350
dt-bindings: nvmem: Add compatible for SM6375
Krzysztof Kozlowski (1):
nvmem: stm32-romem: mark OF related data as maybe unused
Michael Walle (8):
nvmem: core: introduce NVMEM layouts
nvmem: core: add per-cell post processing
nvmem: core: allow to modify a cell before adding it
nvmem: imx-ocotp: replace global post processing with layouts
nvmem: cell: drop global cell_post_process
nvmem: core: provide own priv pointer in post process callback
nvmem: layouts: sl28vpd: Add new layout driver
MAINTAINERS: add myself as sl28vpd nvmem layout driver
Miquel Raynal (15):
of: Fix modalias string generation
of: Update of_device_get_modalias()
of: Rename of_modalias_node()
of: Move of_modalias() to module.c
of: Move the request module helper logic to module.c
usb: ulpi: Use of_request_module()
of: device: Kill of_device_request_module()
nvmem: core: handle the absence of expected layouts
nvmem: core: request layout modules loading
nvmem: layouts: onie-tlv: Add new layout driver
MAINTAINERS: Add myself as ONIE tlv NVMEM layout maintainer
nvmem: Add macro to register nvmem layout drivers
nvmem: layouts: sl28vpd: Use module_nvmem_layout_driver()
nvmem: layouts: onie-tlv: Use module_nvmem_layout_driver()
nvmem: layouts: onie-tlv: Drop wrong module alias
Neil Armstrong (2):
dt-bindings: nvmem: convert amlogic-meson-mx-efuse.txt to dt-schema
dt-bindings: nvmem: convert amlogic-efuse.txt to dt-schema
Nick Alcock (1):
nvmem: xilinx: zynqmp: make modular
Rafał Miłecki (3):
dt-bindings: nvmem: u-boot,env: add MAC's #nvmem-cell-cells
nvmem: core: support specifying both: cell raw data & post read
lengths
nvmem: u-boot-env: post-process "ethaddr" env variable
Rob Herring (1):
dt-bindings: nvmem: Drop unneeded quotes
Tom Rix (1):
nvmem: layouts: sl28vpd: set varaiable sl28vpd_layout
storage-class-specifier to static
Yang Li (3):
nvmem: bcm-ocotp: Use devm_platform_ioremap_resource()
nvmem: nintendo-otp: Use devm_platform_ioremap_resource()
nvmem: vf610-ocotp: Use devm_platform_get_and_ioremap_resource()
.../nvmem/allwinner,sun4i-a10-sid.yaml | 2 +-
.../nvmem/amlogic,meson-gxbb-efuse.yaml | 57 ++++
.../bindings/nvmem/amlogic,meson6-efuse.yaml | 57 ++++
.../bindings/nvmem/amlogic-efuse.txt | 48 ----
.../bindings/nvmem/amlogic-meson-mx-efuse.txt | 22 --
.../bindings/nvmem/apple,efuses.yaml | 2 +-
.../devicetree/bindings/nvmem/brcm,nvram.yaml | 2 +-
.../bindings/nvmem/fsl,layerscape-sfp.yaml | 2 +-
.../devicetree/bindings/nvmem/imx-iim.yaml | 2 +-
.../devicetree/bindings/nvmem/imx-ocotp.yaml | 2 +-
.../bindings/nvmem/ingenic,jz4780-efuse.yaml | 2 +-
.../nvmem/layouts/onie,tlv-layout.yaml | 2 +-
.../bindings/nvmem/mediatek,efuse.yaml | 2 +-
.../nvmem/microchip,sama7g5-otpc.yaml | 2 +-
.../devicetree/bindings/nvmem/mxs-ocotp.yaml | 2 +-
.../bindings/nvmem/nintendo-otp.yaml | 2 +-
.../bindings/nvmem/qcom,qfprom.yaml | 4 +-
.../bindings/nvmem/qcom,spmi-sdam.yaml | 33 ++-
.../devicetree/bindings/nvmem/rmem.yaml | 2 +-
.../bindings/nvmem/rockchip-efuse.yaml | 2 +-
.../nvmem/socionext,uniphier-efuse.yaml | 2 +-
.../bindings/nvmem/st,stm32-romem.yaml | 2 +-
.../bindings/nvmem/sunplus,sp7021-ocotp.yaml | 2 +-
.../devicetree/bindings/nvmem/u-boot,env.yaml | 7 +-
Documentation/driver-api/nvmem.rst | 15 ++
MAINTAINERS | 12 +
drivers/acpi/bus.c | 7 +-
drivers/gpu/drm/drm_mipi_dsi.c | 2 +-
drivers/hsi/hsi_core.c | 2 +-
drivers/i2c/busses/i2c-powermac.c | 2 +-
drivers/i2c/i2c-core-of.c | 2 +-
drivers/nvmem/Kconfig | 7 +-
drivers/nvmem/Makefile | 1 +
drivers/nvmem/bcm-ocotp.c | 4 +-
drivers/nvmem/core.c | 169 +++++++++++-
drivers/nvmem/imx-ocotp.c | 30 ++-
drivers/nvmem/layouts/Kconfig | 23 ++
drivers/nvmem/layouts/Makefile | 7 +
drivers/nvmem/layouts/onie-tlv.c | 244 ++++++++++++++++++
drivers/nvmem/layouts/sl28vpd.c | 153 +++++++++++
drivers/nvmem/mtk-efuse.c | 53 +++-
drivers/nvmem/nintendo-otp.c | 4 +-
drivers/nvmem/stm32-romem.c | 2 +-
drivers/nvmem/u-boot-env.c | 26 ++
drivers/nvmem/vf610-ocotp.c | 3 +-
drivers/of/Makefile | 2 +-
drivers/of/base.c | 18 +-
drivers/of/device.c | 75 +-----
drivers/of/module.c | 74 ++++++
drivers/spi/spi.c | 4 +-
drivers/usb/common/ulpi.c | 2 +-
include/linux/nvmem-consumer.h | 7 +
include/linux/nvmem-provider.h | 74 +++++-
include/linux/of.h | 18 +-
include/linux/of_device.h | 6 -
55 files changed, 1081 insertions(+), 229 deletions(-)
create mode 100644 Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml
create mode 100644 Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml
delete mode 100644 Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt
delete mode 100644 Documentation/devicetree/bindings/nvmem/amlogic-meson-mx-efuse.txt
create mode 100644 drivers/nvmem/layouts/Kconfig
create mode 100644 drivers/nvmem/layouts/Makefile
create mode 100644 drivers/nvmem/layouts/onie-tlv.c
create mode 100644 drivers/nvmem/layouts/sl28vpd.c
create mode 100644 drivers/of/module.c
--
2.25.1
From: Johan Hovold <[email protected]>
The SPMI PMIC register region width is fixed and should not be encoded
in the devicetree.
Amend the example with a parent pmic node with the expected
'#address-cells' and '#size-cells' and fix up the 'reg' property.
Fixes: 9664a6b54c57 ("dt-bindings: nvmem: add binding for QTI SPMI SDAM")
Signed-off-by: Johan Hovold <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
.../bindings/nvmem/qcom,spmi-sdam.yaml | 31 +++++++++++--------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml b/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
index e08504ef3b6e..4702f10ecca2 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
@@ -42,17 +42,22 @@ unevaluatedProperties: false
examples:
- |
- sdam_1: nvram@b000 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,spmi-sdam";
- reg = <0xb000 0x100>;
- ranges = <0 0xb000 0x100>;
-
- /* Data cells */
- restart_reason: restart@50 {
- reg = <0x50 0x1>;
- bits = <6 2>;
- };
- };
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ sdam_1: nvram@b000 {
+ compatible = "qcom,spmi-sdam";
+ reg = <0xb000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0xb000 0x100>;
+
+ /* Data cells */
+ restart_reason: restart@50 {
+ reg = <0x50 0x1>;
+ bits = <6 2>;
+ };
+ };
+ };
...
--
2.25.1
From: Nick Alcock <[email protected]>
This driver has a MODULE_LICENSE but is not tristate so cannot be
built as a module, unlike all its peers: make it modular to match.
Signed-off-by: Nick Alcock <[email protected]>
Suggested-by: Michal Simek <[email protected]>
Cc: Luis Chamberlain <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: Hitomi Hasegawa <[email protected]>
Cc: Srinivas Kandagatla <[email protected]>
Cc: Michal Simek <[email protected]>
Cc: [email protected]
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 6dec38805041..3b3832f4dfad 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -368,7 +368,7 @@ config NVMEM_VF610_OCOTP
be called nvmem-vf610-ocotp.
config NVMEM_ZYNQMP
- bool "Xilinx ZYNQMP SoC nvmem firmware support"
+ tristate "Xilinx ZYNQMP SoC nvmem firmware support"
depends on ARCH_ZYNQMP
help
This is a driver to access hardware related data like
--
2.25.1
From: Miquel Raynal <[email protected]>
The helper generating an OF based modalias (of_device_get_modalias())
works fine, but due to the use of snprintf() internally it needs a
buffer one byte longer than what should be needed just for the entire
string (excluding the '\0'). Most users of this helper are sysfs hooks
providing the modalias string to users. They all provide a PAGE_SIZE
buffer which is way above the number of bytes required to fit the
modalias string and hence do not suffer from this issue.
There is another user though, of_device_request_module(), which is only
called by drivers/usb/common/ulpi.c. This request module function is
faulty, but maybe because in most cases there is an alternative, ULPI
driver users have not noticed it.
In this function, of_device_get_modalias() is called twice. The first
time without buffer just to get the number of bytes required by the
modalias string (excluding the null byte), and a second time, after
buffer allocation, to fill the buffer. The allocation asks for an
additional byte, in order to store the trailing '\0'. However, the
buffer *length* provided to of_device_get_modalias() excludes this extra
byte. The internal use of snprintf() with a length that is exactly the
number of bytes to be written has the effect of using the last available
byte to store a '\0', which then smashes the last character of the
modalias string.
Provide the actual size of the buffer to of_device_get_modalias() to fix
this issue.
Note: the "str[size - 1] = '\0';" line is not really needed as snprintf
will anyway end the string with a null byte, but there is a possibility
that this function might be called on a struct device_node without
compatible, in this case snprintf() would not be executed. So we keep it
just to avoid possible unbounded strings.
Cc: Stephen Boyd <[email protected]>
Cc: Peter Chen <[email protected]>
Fixes: 9c829c097f2f ("of: device: Support loading a module with OF based modalias")
Signed-off-by: Miquel Raynal <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/of/device.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 955bfb3d1a83..c91bb5899256 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -297,12 +297,15 @@ int of_device_request_module(struct device *dev)
if (size < 0)
return size;
- str = kmalloc(size + 1, GFP_KERNEL);
+ /* Reserve an additional byte for the trailing '\0' */
+ size++;
+
+ str = kmalloc(size, GFP_KERNEL);
if (!str)
return -ENOMEM;
of_device_get_modalias(dev, str, size);
- str[size] = '\0';
+ str[size - 1] = '\0';
ret = request_module(str);
kfree(str);
--
2.25.1
From: Neil Armstrong <[email protected]>
Convert the Amlogic Meson6 eFuse bindings to dt-schema.
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Neil Armstrong <[email protected]>
Reviewed-by: Martin Blumenstingl <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
.../bindings/nvmem/amlogic,meson6-efuse.yaml | 57 +++++++++++++++++++
.../bindings/nvmem/amlogic-meson-mx-efuse.txt | 22 -------
2 files changed, 57 insertions(+), 22 deletions(-)
create mode 100644 Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml
delete mode 100644 Documentation/devicetree/bindings/nvmem/amlogic-meson-mx-efuse.txt
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml b/Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml
new file mode 100644
index 000000000000..84b3dfd21e09
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/amlogic,meson6-efuse.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/amlogic,meson6-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic Meson6 eFuse
+
+maintainers:
+ - Neil Armstrong <[email protected]>
+ - Martin Blumenstingl <[email protected]>
+
+allOf:
+ - $ref: nvmem.yaml#
+
+properties:
+ compatible:
+ enum:
+ - amlogic,meson6-efuse
+ - amlogic,meson8-efuse
+ - amlogic,meson8b-efuse
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: core
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ efuse: efuse@0 {
+ compatible = "amlogic,meson6-efuse";
+ reg = <0x0 0x2000>;
+ clocks = <&clk_efuse>;
+ clock-names = "core";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ethernet_mac_address: mac@1b4 {
+ reg = <0x1b4 0x6>;
+ };
+
+ temperature_calib: calib@1f4 {
+ reg = <0x1f4 0x4>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic-meson-mx-efuse.txt b/Documentation/devicetree/bindings/nvmem/amlogic-meson-mx-efuse.txt
deleted file mode 100644
index a3c63954a1a4..000000000000
--- a/Documentation/devicetree/bindings/nvmem/amlogic-meson-mx-efuse.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Amlogic Meson6/Meson8/Meson8b efuse
-
-Required Properties:
-- compatible: depending on the SoC this should be one of:
- - "amlogic,meson6-efuse"
- - "amlogic,meson8-efuse"
- - "amlogic,meson8b-efuse"
-- reg: base address and size of the efuse registers
-- clocks: a reference to the efuse core gate clock
-- clock-names: must be "core"
-
-All properties and sub-nodes as well as the consumer bindings
-defined in nvmem.txt in this directory are also supported.
-
-
-Example:
- efuse: nvmem@0 {
- compatible = "amlogic,meson8-efuse";
- reg = <0x0 0x2000>;
- clocks = <&clkc CLKID_EFUSE>;
- clock-names = "core";
- };
--
2.25.1
From: Neil Armstrong <[email protected]>
Convert the Amlogic Meson GX eFuse bindings to dt-schema.
Take in account the used variant with amlogic,meson-gx-efuse.
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Reviewed-by: Martin Blumenstingl <[email protected]>
Signed-off-by: Neil Armstrong <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
.../nvmem/amlogic,meson-gxbb-efuse.yaml | 57 +++++++++++++++++++
.../bindings/nvmem/amlogic-efuse.txt | 48 ----------------
2 files changed, 57 insertions(+), 48 deletions(-)
create mode 100644 Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml
delete mode 100644 Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml b/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml
new file mode 100644
index 000000000000..e49c2754ff55
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/amlogic,meson-gxbb-efuse.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/amlogic,meson-gxbb-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic Meson GX eFuse
+
+maintainers:
+ - Neil Armstrong <[email protected]>
+
+allOf:
+ - $ref: nvmem.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - const: amlogic,meson-gxbb-efuse
+ - items:
+ - const: amlogic,meson-gx-efuse
+ - const: amlogic,meson-gxbb-efuse
+
+ clocks:
+ maxItems: 1
+
+ secure-monitor:
+ description: phandle to the secure-monitor node
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+required:
+ - compatible
+ - clocks
+ - secure-monitor
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ efuse: efuse {
+ compatible = "amlogic,meson-gxbb-efuse";
+ clocks = <&clk_efuse>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ secure-monitor = <&sm>;
+
+ sn: sn@14 {
+ reg = <0x14 0x10>;
+ };
+
+ eth_mac: mac@34 {
+ reg = <0x34 0x10>;
+ };
+
+ bid: bid@46 {
+ reg = <0x46 0x30>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt b/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt
deleted file mode 100644
index f7b3ed74db54..000000000000
--- a/Documentation/devicetree/bindings/nvmem/amlogic-efuse.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-= Amlogic Meson GX eFuse device tree bindings =
-
-Required properties:
-- compatible: should be "amlogic,meson-gxbb-efuse"
-- clocks: phandle to the efuse peripheral clock provided by the
- clock controller.
-- secure-monitor: phandle to the secure-monitor node
-
-= Data cells =
-Are child nodes of eFuse, bindings of which as described in
-bindings/nvmem/nvmem.txt
-
-Example:
-
- efuse: efuse {
- compatible = "amlogic,meson-gxbb-efuse";
- clocks = <&clkc CLKID_EFUSE>;
- #address-cells = <1>;
- #size-cells = <1>;
- secure-monitor = <&sm>;
-
- sn: sn@14 {
- reg = <0x14 0x10>;
- };
-
- eth_mac: eth_mac@34 {
- reg = <0x34 0x10>;
- };
-
- bid: bid@46 {
- reg = <0x46 0x30>;
- };
- };
-
- sm: secure-monitor {
- compatible = "amlogic,meson-gxbb-sm";
- };
-
-= Data consumers =
-Are device nodes which consume nvmem data cells.
-
-For example:
-
- eth_mac {
- ...
- nvmem-cells = <ð_mac>;
- nvmem-cell-names = "eth_mac";
- };
--
2.25.1
From: Colin Ian King <[email protected]>
There is a spelling mistake in platforn-name. Fix it.
Signed-off-by: Colin Ian King <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
.../devicetree/bindings/nvmem/layouts/onie,tlv-layout.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/nvmem/layouts/onie,tlv-layout.yaml b/Documentation/devicetree/bindings/nvmem/layouts/onie,tlv-layout.yaml
index 5a0e7671aa3f..714a6538cc7c 100644
--- a/Documentation/devicetree/bindings/nvmem/layouts/onie,tlv-layout.yaml
+++ b/Documentation/devicetree/bindings/nvmem/layouts/onie,tlv-layout.yaml
@@ -61,7 +61,7 @@ properties:
type: object
additionalProperties: false
- platforn-name:
+ platform-name:
type: object
additionalProperties: false
--
2.25.1
From: Miquel Raynal <[email protected]>
This function only needs a "struct device_node" to work, but for
convenience the author (and only user) of this helper did use a "struct
device" and put it in device.c.
Let's convert this helper to take a "struct device node" instead. This
change asks for two additional changes: renaming it "of_modalias()"
to fit the current naming, and moving it outside of device.c which will
be done in a follow-up commit.
Signed-off-by: Miquel Raynal <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/of/device.c | 29 +++++++++++++++++------------
1 file changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index c91bb5899256..351c505ecb50 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -248,7 +248,7 @@ const void *of_device_get_match_data(const struct device *dev)
}
EXPORT_SYMBOL(of_device_get_match_data);
-static ssize_t of_device_get_modalias(const struct device *dev, char *str, ssize_t len)
+static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
{
const char *compat;
char *c;
@@ -256,19 +256,16 @@ static ssize_t of_device_get_modalias(const struct device *dev, char *str, ssize
ssize_t csize;
ssize_t tsize;
- if ((!dev) || (!dev->of_node) || dev->of_node_reused)
- return -ENODEV;
-
/* Name & Type */
/* %p eats all alphanum characters, so %c must be used here */
- csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T',
- of_node_get_device_type(dev->of_node));
+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
+ of_node_get_device_type(np));
tsize = csize;
len -= csize;
if (str)
str += csize;
- of_property_for_each_string(dev->of_node, "compatible", p, compat) {
+ of_property_for_each_string(np, "compatible", p, compat) {
csize = strlen(compat) + 1;
tsize += csize;
if (csize > len)
@@ -293,7 +290,10 @@ int of_device_request_module(struct device *dev)
ssize_t size;
int ret;
- size = of_device_get_modalias(dev, NULL, 0);
+ if (!dev || !dev->of_node)
+ return -ENODEV;
+
+ size = of_modalias(dev->of_node, NULL, 0);
if (size < 0)
return size;
@@ -304,7 +304,7 @@ int of_device_request_module(struct device *dev)
if (!str)
return -ENOMEM;
- of_device_get_modalias(dev, str, size);
+ of_modalias(dev->of_node, str, size);
str[size - 1] = '\0';
ret = request_module(str);
kfree(str);
@@ -321,7 +321,12 @@ EXPORT_SYMBOL_GPL(of_device_request_module);
*/
ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len)
{
- ssize_t sl = of_device_get_modalias(dev, str, len - 2);
+ ssize_t sl;
+
+ if (!dev || !dev->of_node || dev->of_node_reused)
+ return -ENODEV;
+
+ sl = of_modalias(dev->of_node, str, len - 2);
if (sl < 0)
return sl;
if (sl > len - 2)
@@ -386,8 +391,8 @@ int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *
if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM;
- sl = of_device_get_modalias(dev, &env->buf[env->buflen-1],
- sizeof(env->buf) - env->buflen);
+ sl = of_modalias(dev->of_node, &env->buf[env->buflen-1],
+ sizeof(env->buf) - env->buflen);
if (sl < 0)
return sl;
if (sl >= (sizeof(env->buf) - env->buflen))
--
2.25.1
From: Miquel Raynal <[email protected]>
This helper does not produce a real modalias, but tries to get the
"product" compatible part of the "vendor,product" compatibles only. It
is far from creating a purely useful modalias string and does not seem
to be used like that directly anyway, so let's try to give this helper a
more meaningful name before moving there a real modalias helper (already
existing under of/device.c).
Also update the various documentations to refer to the strings as
"aliases" rather than "modaliases" which has a real meaning in the Linux
kernel.
There is no functional change.
Cc: Rafael J. Wysocki <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Maarten Lankhorst <[email protected]>
Cc: Maxime Ripard <[email protected]>
Cc: Thomas Zimmermann <[email protected]>
Cc: Sebastian Reichel <[email protected]>
Cc: Wolfram Sang <[email protected]>
Cc: Mark Brown <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Acked-by: Mark Brown <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/acpi/bus.c | 7 ++++---
drivers/gpu/drm/drm_mipi_dsi.c | 2 +-
drivers/hsi/hsi_core.c | 2 +-
drivers/i2c/busses/i2c-powermac.c | 2 +-
drivers/i2c/i2c-core-of.c | 2 +-
drivers/of/base.c | 18 +++++++++++-------
drivers/spi/spi.c | 4 ++--
include/linux/of.h | 3 ++-
8 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 9531dd0fef50..fc74c786a867 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -817,9 +817,10 @@ static bool acpi_of_modalias(struct acpi_device *adev,
* @modalias: Pointer to buffer that modalias value will be copied into
* @len: Length of modalias buffer
*
- * This is a counterpart of of_modalias_node() for struct acpi_device objects.
- * If there is a compatible string for @adev, it will be copied to @modalias
- * with the vendor prefix stripped; otherwise, @default_id will be used.
+ * This is a counterpart of of_alias_from_compatible() for struct acpi_device
+ * objects. If there is a compatible string for @adev, it will be copied to
+ * @modalias with the vendor prefix stripped; otherwise, @default_id will be
+ * used.
*/
void acpi_set_modalias(struct acpi_device *adev, const char *default_id,
char *modalias, size_t len)
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index b41aaf2bb9f1..b62f5e4425f4 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -160,7 +160,7 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
int ret;
u32 reg;
- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
+ if (of_alias_from_compatible(node, info.type, sizeof(info.type)) < 0) {
drm_err(host, "modalias failure on %pOF\n", node);
return ERR_PTR(-EINVAL);
}
diff --git a/drivers/hsi/hsi_core.c b/drivers/hsi/hsi_core.c
index 8fda8f1d064d..acbf82f755a8 100644
--- a/drivers/hsi/hsi_core.c
+++ b/drivers/hsi/hsi_core.c
@@ -207,7 +207,7 @@ static void hsi_add_client_from_dt(struct hsi_port *port,
if (!cl)
return;
- err = of_modalias_node(client, name, sizeof(name));
+ err = of_alias_from_compatible(client, name, sizeof(name));
if (err)
goto err;
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 2e74747eec9c..ec706a3aba26 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -284,7 +284,7 @@ static bool i2c_powermac_get_type(struct i2c_adapter *adap,
*/
/* First try proper modalias */
- if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
+ if (of_alias_from_compatible(node, tmp, sizeof(tmp)) >= 0) {
snprintf(type, type_size, "MAC,%s", tmp);
return true;
}
diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c
index bce6b796e04c..8941a30574e3 100644
--- a/drivers/i2c/i2c-core-of.c
+++ b/drivers/i2c/i2c-core-of.c
@@ -27,7 +27,7 @@ int of_i2c_get_board_info(struct device *dev, struct device_node *node,
memset(info, 0, sizeof(*info));
- if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
+ if (of_alias_from_compatible(node, info->type, sizeof(info->type)) < 0) {
dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
return -EINVAL;
}
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ac6fde53342f..161fe3192c46 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1208,19 +1208,23 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
EXPORT_SYMBOL(of_find_matching_node_and_match);
/**
- * of_modalias_node - Lookup appropriate modalias for a device node
+ * of_alias_from_compatible - Lookup appropriate alias for a device node
+ * depending on compatible
* @node: pointer to a device tree node
- * @modalias: Pointer to buffer that modalias value will be copied into
- * @len: Length of modalias value
+ * @alias: Pointer to buffer that alias value will be copied into
+ * @len: Length of alias value
*
* Based on the value of the compatible property, this routine will attempt
- * to choose an appropriate modalias value for a particular device tree node.
+ * to choose an appropriate alias value for a particular device tree node.
* It does this by stripping the manufacturer prefix (as delimited by a ',')
* from the first entry in the compatible list property.
*
+ * Note: The matching on just the "product" side of the compatible is a relic
+ * from I2C and SPI. Please do not add any new user.
+ *
* Return: This routine returns 0 on success, <0 on failure.
*/
-int of_modalias_node(struct device_node *node, char *modalias, int len)
+int of_alias_from_compatible(const struct device_node *node, char *alias, int len)
{
const char *compatible, *p;
int cplen;
@@ -1229,10 +1233,10 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
if (!compatible || strlen(compatible) > cplen)
return -ENODEV;
p = strchr(compatible, ',');
- strscpy(modalias, p ? p + 1 : compatible, len);
+ strscpy(alias, p ? p + 1 : compatible, len);
return 0;
}
-EXPORT_SYMBOL_GPL(of_modalias_node);
+EXPORT_SYMBOL_GPL(of_alias_from_compatible);
/**
* of_find_node_by_phandle - Find a node given a phandle
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 44b85a8d47f1..3bbdc5fe3b99 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2354,8 +2354,8 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
}
/* Select device driver */
- rc = of_modalias_node(nc, spi->modalias,
- sizeof(spi->modalias));
+ rc = of_alias_from_compatible(nc, spi->modalias,
+ sizeof(spi->modalias));
if (rc < 0) {
dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc);
goto err_out;
diff --git a/include/linux/of.h b/include/linux/of.h
index 0af611307db2..b1eea8569043 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -373,7 +373,8 @@ extern int of_n_addr_cells(struct device_node *np);
extern int of_n_size_cells(struct device_node *np);
extern const struct of_device_id *of_match_node(
const struct of_device_id *matches, const struct device_node *node);
-extern int of_modalias_node(struct device_node *node, char *modalias, int len);
+extern int of_alias_from_compatible(const struct device_node *node, char *alias,
+ int len);
extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
extern int __of_parse_phandle_with_args(const struct device_node *np,
const char *list_name, const char *cells_name, int cell_count,
--
2.25.1
From: Miquel Raynal <[email protected]>
Create a specific .c file for OF related module handling.
Move of_modalias() inside as a first step.
The helper is exposed through of.h even though it is only used by core
files because the users from device.c will soon be split into an OF-only
helper in module.c as well as a device-oriented inline helper in
of_device.h. Putting this helper in of_private.h would require to
include of_private.h from of_device.h, which is not acceptable.
Suggested-by: Rob Herring <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/of/Makefile | 2 +-
drivers/of/device.c | 37 -------------------------------------
drivers/of/module.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/of.h | 9 +++++++++
4 files changed, 54 insertions(+), 38 deletions(-)
create mode 100644 drivers/of/module.c
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index e0360a44306e..ae9923fd2940 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y = base.o device.o platform.o property.o
+obj-y = base.o device.o module.o platform.o property.o
obj-$(CONFIG_OF_KOBJ) += kobj.o
obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
obj-$(CONFIG_OF_FLATTREE) += fdt.o
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 351c505ecb50..7183cfd754db 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -248,42 +247,6 @@ const void *of_device_get_match_data(const struct device *dev)
}
EXPORT_SYMBOL(of_device_get_match_data);
-static ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
-{
- const char *compat;
- char *c;
- struct property *p;
- ssize_t csize;
- ssize_t tsize;
-
- /* Name & Type */
- /* %p eats all alphanum characters, so %c must be used here */
- csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
- of_node_get_device_type(np));
- tsize = csize;
- len -= csize;
- if (str)
- str += csize;
-
- of_property_for_each_string(np, "compatible", p, compat) {
- csize = strlen(compat) + 1;
- tsize += csize;
- if (csize > len)
- continue;
-
- csize = snprintf(str, len, "C%s", compat);
- for (c = str; c; ) {
- c = strchr(c, ' ');
- if (c)
- *c++ = '_';
- }
- len -= csize;
- str += csize;
- }
-
- return tsize;
-}
-
int of_device_request_module(struct device *dev)
{
char *str;
diff --git a/drivers/of/module.c b/drivers/of/module.c
new file mode 100644
index 000000000000..4c59752bc8d6
--- /dev/null
+++ b/drivers/of/module.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Linux kernel module helpers.
+ */
+
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
+{
+ const char *compat;
+ char *c;
+ struct property *p;
+ ssize_t csize;
+ ssize_t tsize;
+
+ /* Name & Type */
+ /* %p eats all alphanum characters, so %c must be used here */
+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
+ of_node_get_device_type(np));
+ tsize = csize;
+ len -= csize;
+ if (str)
+ str += csize;
+
+ of_property_for_each_string(np, "compatible", p, compat) {
+ csize = strlen(compat) + 1;
+ tsize += csize;
+ if (csize > len)
+ continue;
+
+ csize = snprintf(str, len, "C%s", compat);
+ for (c = str; c; ) {
+ c = strchr(c, ' ');
+ if (c)
+ *c++ = '_';
+ }
+ len -= csize;
+ str += csize;
+ }
+
+ return tsize;
+}
diff --git a/include/linux/of.h b/include/linux/of.h
index b1eea8569043..be26c7e8ef9e 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -385,6 +385,9 @@ extern int of_parse_phandle_with_args_map(const struct device_node *np,
extern int of_count_phandle_with_args(const struct device_node *np,
const char *list_name, const char *cells_name);
+/* module functions */
+extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len);
+
/* phandle iterator functions */
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
const struct device_node *np,
@@ -742,6 +745,12 @@ static inline int of_count_phandle_with_args(const struct device_node *np,
return -ENOSYS;
}
+static inline ssize_t of_modalias(const struct device_node *np, char *str,
+ ssize_t len)
+{
+ return -ENODEV;
+}
+
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
const struct device_node *np,
const char *list_name,
--
2.25.1
From: Miquel Raynal <[email protected]>
Depending on device.c for pure OF handling is considered
backwards. Let's extract the content of of_device_request_module() to
have the real logic under module.c.
The next step will be to convert users of of_device_request_module() to
use the new helper.
Signed-off-by: Miquel Raynal <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/of/device.c | 25 ++-----------------------
drivers/of/module.c | 30 ++++++++++++++++++++++++++++++
include/linux/of.h | 6 ++++++
3 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 7183cfd754db..874a2e1f6308 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -8,7 +8,6 @@
#include <linux/dma-direct.h> /* for bus_dma_region */
#include <linux/dma-map-ops.h>
#include <linux/init.h>
-#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
@@ -249,30 +248,10 @@ EXPORT_SYMBOL(of_device_get_match_data);
int of_device_request_module(struct device *dev)
{
- char *str;
- ssize_t size;
- int ret;
-
- if (!dev || !dev->of_node)
+ if (!dev)
return -ENODEV;
- size = of_modalias(dev->of_node, NULL, 0);
- if (size < 0)
- return size;
-
- /* Reserve an additional byte for the trailing '\0' */
- size++;
-
- str = kmalloc(size, GFP_KERNEL);
- if (!str)
- return -ENOMEM;
-
- of_modalias(dev->of_node, str, size);
- str[size - 1] = '\0';
- ret = request_module(str);
- kfree(str);
-
- return ret;
+ return of_request_module(dev->of_node);
}
EXPORT_SYMBOL_GPL(of_device_request_module);
diff --git a/drivers/of/module.c b/drivers/of/module.c
index 4c59752bc8d6..0e8aa974f0f2 100644
--- a/drivers/of/module.c
+++ b/drivers/of/module.c
@@ -4,6 +4,7 @@
*/
#include <linux/of.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
@@ -42,3 +43,32 @@ ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
return tsize;
}
+
+int of_request_module(const struct device_node *np)
+{
+ char *str;
+ ssize_t size;
+ int ret;
+
+ if (!np)
+ return -ENODEV;
+
+ size = of_modalias(np, NULL, 0);
+ if (size < 0)
+ return size;
+
+ /* Reserve an additional byte for the trailing '\0' */
+ size++;
+
+ str = kmalloc(size, GFP_KERNEL);
+ if (!str)
+ return -ENOMEM;
+
+ of_modalias(np, str, size);
+ str[size - 1] = '\0';
+ ret = request_module(str);
+ kfree(str);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(of_request_module);
diff --git a/include/linux/of.h b/include/linux/of.h
index be26c7e8ef9e..9b7a99499ef3 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -387,6 +387,7 @@ extern int of_count_phandle_with_args(const struct device_node *np,
/* module functions */
extern ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len);
+extern int of_request_module(const struct device_node *np);
/* phandle iterator functions */
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
@@ -751,6 +752,11 @@ static inline ssize_t of_modalias(const struct device_node *np, char *str,
return -ENODEV;
}
+static inline int of_request_module(const struct device_node *np)
+{
+ return -ENODEV;
+}
+
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
const struct device_node *np,
const char *list_name,
--
2.25.1
From: Miquel Raynal <[email protected]>
There is a new helper supposed to replace of_device_request_module(),
called of_request_module(). They are both strictly equivalent, besides
the fact the latter receives a "struct device_node" directly. Use it.
Cc: Heikki Krogerus <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Acked-by: Rob Herring <[email protected]>
Acked-by: Heikki Krogerus <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/usb/common/ulpi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index a98b2108376a..6977cf380838 100644
--- a/drivers/usb/common/ulpi.c
+++ b/drivers/usb/common/ulpi.c
@@ -229,7 +229,7 @@ static int ulpi_read_id(struct ulpi *ulpi)
request_module("ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product);
return 0;
err:
- of_device_request_module(&ulpi->dev);
+ of_request_module(ulpi->dev.of_node);
return 0;
}
--
2.25.1
From: Miquel Raynal <[email protected]>
A new helper has been introduced, of_request_module(). Users have been
converted, this helper can now be deleted.
Signed-off-by: Miquel Raynal <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/of/device.c | 9 ---------
include/linux/of_device.h | 6 ------
2 files changed, 15 deletions(-)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 874a2e1f6308..0f00f1b80708 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -246,15 +246,6 @@ const void *of_device_get_match_data(const struct device *dev)
}
EXPORT_SYMBOL(of_device_get_match_data);
-int of_device_request_module(struct device *dev)
-{
- if (!dev)
- return -ENODEV;
-
- return of_request_module(dev->of_node);
-}
-EXPORT_SYMBOL_GPL(of_device_request_module);
-
/**
* of_device_modalias - Fill buffer with newline terminated modalias string
* @dev: Calling device
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index f4b57614979d..ce20d8b00b3e 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -33,7 +33,6 @@ extern void of_device_unregister(struct platform_device *ofdev);
extern const void *of_device_get_match_data(const struct device *dev);
extern ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len);
-extern int of_device_request_module(struct device *dev);
extern void of_device_uevent(const struct device *dev, struct kobj_uevent_env *env);
extern int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *env);
@@ -78,11 +77,6 @@ static inline int of_device_modalias(struct device *dev,
return -ENODEV;
}
-static inline int of_device_request_module(struct device *dev)
-{
- return -ENODEV;
-}
-
static inline int of_device_uevent_modalias(const struct device *dev,
struct kobj_uevent_env *env)
{
--
2.25.1
From: Michael Walle <[email protected]>
NVMEM layouts are used to generate NVMEM cells during runtime. Think of
an EEPROM with a well-defined conent. For now, the content can be
described by a device tree or a board file. But this only works if the
offsets and lengths are static and don't change. One could also argue
that putting the layout of the EEPROM in the device tree is the wrong
place. Instead, the device tree should just have a specific compatible
string.
Right now there are two use cases:
(1) The NVMEM cell needs special processing. E.g. if it only specifies
a base MAC address offset and you need to add an offset, or it
needs to parse a MAC from ASCII format or some proprietary format.
(Post processing of cells is added in a later commit).
(2) u-boot environment parsing. The cells don't have a particular
offset but it needs parsing the content to determine the offsets
and length.
Co-developed-by: Miquel Raynal <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
Documentation/driver-api/nvmem.rst | 15 ++++
drivers/nvmem/Kconfig | 4 +
drivers/nvmem/Makefile | 1 +
drivers/nvmem/core.c | 120 +++++++++++++++++++++++++++++
drivers/nvmem/layouts/Kconfig | 5 ++
drivers/nvmem/layouts/Makefile | 4 +
include/linux/nvmem-consumer.h | 7 ++
include/linux/nvmem-provider.h | 51 ++++++++++++
8 files changed, 207 insertions(+)
create mode 100644 drivers/nvmem/layouts/Kconfig
create mode 100644 drivers/nvmem/layouts/Makefile
diff --git a/Documentation/driver-api/nvmem.rst b/Documentation/driver-api/nvmem.rst
index e3366322d46c..de221e91c8e3 100644
--- a/Documentation/driver-api/nvmem.rst
+++ b/Documentation/driver-api/nvmem.rst
@@ -185,3 +185,18 @@ ex::
=====================
See Documentation/devicetree/bindings/nvmem/nvmem.txt
+
+8. NVMEM layouts
+================
+
+NVMEM layouts are yet another mechanism to create cells. With the device
+tree binding it is possible to specify simple cells by using an offset
+and a length. Sometimes, the cells doesn't have a static offset, but
+the content is still well defined, e.g. tag-length-values. In this case,
+the NVMEM device content has to be first parsed and the cells need to
+be added accordingly. Layouts let you read the content of the NVMEM device
+and let you add cells dynamically.
+
+Another use case for layouts is the post processing of cells. With layouts,
+it is possible to associate a custom post processing hook to a cell. It
+even possible to add this hook to cells not created by the layout itself.
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 3b3832f4dfad..a2afba11c890 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -21,6 +21,10 @@ config NVMEM_SYSFS
This interface is mostly used by userspace applications to
read/write directly into nvmem.
+# Layouts
+
+source "drivers/nvmem/layouts/Kconfig"
+
# Devices
config NVMEM_APPLE_EFUSES
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 6a1efffa88f0..f82431ec8aef 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -5,6 +5,7 @@
obj-$(CONFIG_NVMEM) += nvmem_core.o
nvmem_core-y := core.o
+obj-y += layouts/
# Devices
obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 22024b830788..b9be1faeb7be 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -40,6 +40,7 @@ struct nvmem_device {
nvmem_reg_write_t reg_write;
nvmem_cell_post_process_t cell_post_process;
struct gpio_desc *wp_gpio;
+ struct nvmem_layout *layout;
void *priv;
};
@@ -74,6 +75,9 @@ static LIST_HEAD(nvmem_lookup_list);
static BLOCKING_NOTIFIER_HEAD(nvmem_notifier);
+static DEFINE_SPINLOCK(nvmem_layout_lock);
+static LIST_HEAD(nvmem_layouts);
+
static int __nvmem_reg_read(struct nvmem_device *nvmem, unsigned int offset,
void *val, size_t bytes)
{
@@ -728,6 +732,101 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
return 0;
}
+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner)
+{
+ layout->owner = owner;
+
+ spin_lock(&nvmem_layout_lock);
+ list_add(&layout->node, &nvmem_layouts);
+ spin_unlock(&nvmem_layout_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__nvmem_layout_register);
+
+void nvmem_layout_unregister(struct nvmem_layout *layout)
+{
+ spin_lock(&nvmem_layout_lock);
+ list_del(&layout->node);
+ spin_unlock(&nvmem_layout_lock);
+}
+EXPORT_SYMBOL_GPL(nvmem_layout_unregister);
+
+static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
+{
+ struct device_node *layout_np, *np = nvmem->dev.of_node;
+ struct nvmem_layout *l, *layout = NULL;
+
+ layout_np = of_get_child_by_name(np, "nvmem-layout");
+ if (!layout_np)
+ return NULL;
+
+ spin_lock(&nvmem_layout_lock);
+
+ list_for_each_entry(l, &nvmem_layouts, node) {
+ if (of_match_node(l->of_match_table, layout_np)) {
+ if (try_module_get(l->owner))
+ layout = l;
+
+ break;
+ }
+ }
+
+ spin_unlock(&nvmem_layout_lock);
+ of_node_put(layout_np);
+
+ return layout;
+}
+
+static void nvmem_layout_put(struct nvmem_layout *layout)
+{
+ if (layout)
+ module_put(layout->owner);
+}
+
+static int nvmem_add_cells_from_layout(struct nvmem_device *nvmem)
+{
+ struct nvmem_layout *layout = nvmem->layout;
+ int ret;
+
+ if (layout && layout->add_cells) {
+ ret = layout->add_cells(&nvmem->dev, nvmem, layout);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+#if IS_ENABLED(CONFIG_OF)
+/**
+ * of_nvmem_layout_get_container() - Get OF node to layout container.
+ *
+ * @nvmem: nvmem device.
+ *
+ * Return: a node pointer with refcount incremented or NULL if no
+ * container exists. Use of_node_put() on it when done.
+ */
+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem)
+{
+ return of_get_child_by_name(nvmem->dev.of_node, "nvmem-layout");
+}
+EXPORT_SYMBOL_GPL(of_nvmem_layout_get_container);
+#endif
+
+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
+ struct nvmem_layout *layout)
+{
+ struct device_node __maybe_unused *layout_np;
+ const struct of_device_id *match;
+
+ layout_np = of_nvmem_layout_get_container(nvmem);
+ match = of_match_node(layout->of_match_table, layout_np);
+
+ return match ? match->data : NULL;
+}
+EXPORT_SYMBOL_GPL(nvmem_layout_get_match_data);
+
/**
* nvmem_register() - Register a nvmem device for given nvmem_config.
* Also creates a binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
@@ -834,6 +933,12 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
goto err_put_device;
}
+ /*
+ * If the driver supplied a layout by config->layout, the module
+ * pointer will be NULL and nvmem_layout_put() will be a noop.
+ */
+ nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
+
if (config->cells) {
rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
if (rval)
@@ -854,12 +959,17 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
if (rval)
goto err_remove_cells;
+ rval = nvmem_add_cells_from_layout(nvmem);
+ if (rval)
+ goto err_remove_cells;
+
blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
return nvmem;
err_remove_cells:
nvmem_device_remove_all_cells(nvmem);
+ nvmem_layout_put(nvmem->layout);
if (config->compat)
nvmem_sysfs_remove_compat(nvmem, config);
err_put_device:
@@ -881,6 +991,7 @@ static void nvmem_device_release(struct kref *kref)
device_remove_bin_file(nvmem->base_dev, &nvmem->eeprom);
nvmem_device_remove_all_cells(nvmem);
+ nvmem_layout_put(nvmem->layout);
device_unregister(&nvmem->dev);
}
@@ -1246,6 +1357,15 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
return ERR_PTR(-EINVAL);
}
+ /* nvmem layouts produce cells within the nvmem-layout container */
+ if (of_node_name_eq(nvmem_np, "nvmem-layout")) {
+ nvmem_np = of_get_next_parent(nvmem_np);
+ if (!nvmem_np) {
+ of_node_put(cell_np);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
of_node_put(nvmem_np);
if (IS_ERR(nvmem)) {
diff --git a/drivers/nvmem/layouts/Kconfig b/drivers/nvmem/layouts/Kconfig
new file mode 100644
index 000000000000..9ad3911d1605
--- /dev/null
+++ b/drivers/nvmem/layouts/Kconfig
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
+menu "Layout Types"
+
+endmenu
diff --git a/drivers/nvmem/layouts/Makefile b/drivers/nvmem/layouts/Makefile
new file mode 100644
index 000000000000..6fdb3c60a4fa
--- /dev/null
+++ b/drivers/nvmem/layouts/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for nvmem layouts.
+#
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 1f62f7ba71ca..fa030d93b768 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -239,6 +239,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
const char *id);
struct nvmem_device *of_nvmem_device_get(struct device_node *np,
const char *name);
+struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem);
#else
static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
const char *id)
@@ -251,6 +252,12 @@ static inline struct nvmem_device *of_nvmem_device_get(struct device_node *np,
{
return ERR_PTR(-EOPNOTSUPP);
}
+
+static inline struct device_node *
+of_nvmem_layout_get_container(struct nvmem_device *nvmem)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
#endif /* CONFIG_NVMEM && CONFIG_OF */
#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 0262b86194eb..535c5f9f3309 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -88,6 +88,7 @@ struct nvmem_cell_info {
* @stride: Minimum read/write access stride.
* @priv: User context passed to read/write callbacks.
* @ignore_wp: Write Protect pin is managed by the provider.
+ * @layout: Fixed layout associated with this nvmem device.
*
* Note: A default "nvmem<id>" name will be assigned to the device if
* no name is specified in its configuration. In such case "<id>" is
@@ -109,6 +110,7 @@ struct nvmem_config {
bool read_only;
bool root_only;
bool ignore_wp;
+ struct nvmem_layout *layout;
struct device_node *of_node;
bool no_of_node;
nvmem_reg_read_t reg_read;
@@ -142,6 +144,33 @@ struct nvmem_cell_table {
struct list_head node;
};
+/**
+ * struct nvmem_layout - NVMEM layout definitions
+ *
+ * @name: Layout name.
+ * @of_match_table: Open firmware match table.
+ * @add_cells: Will be called if a nvmem device is found which
+ * has this layout. The function will add layout
+ * specific cells with nvmem_add_one_cell().
+ * @owner: Pointer to struct module.
+ * @node: List node.
+ *
+ * A nvmem device can hold a well defined structure which can just be
+ * evaluated during runtime. For example a TLV list, or a list of "name=val"
+ * pairs. A nvmem layout can parse the nvmem device and add appropriate
+ * cells.
+ */
+struct nvmem_layout {
+ const char *name;
+ const struct of_device_id *of_match_table;
+ int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
+ struct nvmem_layout *layout);
+
+ /* private */
+ struct module *owner;
+ struct list_head node;
+};
+
#if IS_ENABLED(CONFIG_NVMEM)
struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
@@ -156,6 +185,14 @@ void nvmem_del_cell_table(struct nvmem_cell_table *table);
int nvmem_add_one_cell(struct nvmem_device *nvmem,
const struct nvmem_cell_info *info);
+int __nvmem_layout_register(struct nvmem_layout *layout, struct module *owner);
+#define nvmem_layout_register(layout) \
+ __nvmem_layout_register(layout, THIS_MODULE)
+void nvmem_layout_unregister(struct nvmem_layout *layout);
+
+const void *nvmem_layout_get_match_data(struct nvmem_device *nvmem,
+ struct nvmem_layout *layout);
+
#else
static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
@@ -179,5 +216,19 @@ static inline int nvmem_add_one_cell(struct nvmem_device *nvmem,
return -EOPNOTSUPP;
}
+static inline int nvmem_layout_register(struct nvmem_layout *layout)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void nvmem_layout_unregister(struct nvmem_layout *layout) {}
+
+static inline const void *
+nvmem_layout_get_match_data(struct nvmem_device *nvmem,
+ struct nvmem_layout *layout)
+{
+ return NULL;
+}
+
#endif /* CONFIG_NVMEM */
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
--
2.25.1
From: Michael Walle <[email protected]>
Instead of relying on the name the consumer is using for the cell, like
it is done for the nvmem .cell_post_process configuration parameter,
provide a per-cell post processing hook. This can then be populated by
the NVMEM provider (or the NVMEM layout) when adding the cell.
Signed-off-by: Michael Walle <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/core.c | 17 +++++++++++++++++
include/linux/nvmem-provider.h | 3 +++
2 files changed, 20 insertions(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 49b4bbaf59e8..0708f9f27898 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
int bytes;
int bit_offset;
int nbits;
+ nvmem_cell_post_process_t read_post_process;
struct device_node *np;
struct nvmem_device *nvmem;
struct list_head node;
@@ -470,6 +471,7 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem,
cell->offset = info->offset;
cell->bytes = info->bytes;
cell->name = info->name;
+ cell->read_post_process = info->read_post_process;
cell->bit_offset = info->bit_offset;
cell->nbits = info->nbits;
@@ -1563,6 +1565,13 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
if (cell->bit_offset || cell->nbits)
nvmem_shift_read_buffer_in_place(cell, buf);
+ if (cell->read_post_process) {
+ rc = cell->read_post_process(nvmem->priv, id, index,
+ cell->offset, buf, cell->bytes);
+ if (rc)
+ return rc;
+ }
+
if (nvmem->cell_post_process) {
rc = nvmem->cell_post_process(nvmem->priv, id, index,
cell->offset, buf, cell->bytes);
@@ -1671,6 +1680,14 @@ static int __nvmem_cell_entry_write(struct nvmem_cell_entry *cell, void *buf, si
(cell->bit_offset == 0 && len != cell->bytes))
return -EINVAL;
+ /*
+ * Any cells which have a read_post_process hook are read-only because
+ * we cannot reverse the operation and it might affect other cells,
+ * too.
+ */
+ if (cell->read_post_process)
+ return -EINVAL;
+
if (cell->bit_offset || cell->nbits) {
buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
if (IS_ERR(buf))
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 535c5f9f3309..3bfc23553a9e 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -54,6 +54,8 @@ struct nvmem_keepout {
* @bit_offset: Bit offset if cell is smaller than a byte.
* @nbits: Number of bits.
* @np: Optional device_node pointer.
+ * @read_post_process: Callback for optional post processing of cell data
+ * on reads.
*/
struct nvmem_cell_info {
const char *name;
@@ -62,6 +64,7 @@ struct nvmem_cell_info {
unsigned int bit_offset;
unsigned int nbits;
struct device_node *np;
+ nvmem_cell_post_process_t read_post_process;
};
/**
--
2.25.1
From: Miquel Raynal <[email protected]>
When a storage device like an eeprom or an mtd device probes, it
registers an nvmem device if the nvmem subsystem has been enabled (bool
symbol). During nvmem registration, if the device is using layouts to
expose dynamic nvmem cells, the core will first try to get a reference
over the layout driver callbacks. In practice there is not relationship
that can be described between the storage driver and the nvmem
layout. So there is no way we can enforce both drivers will be built-in
or both will be modules. If the storage device driver is built-in but
the layout is built as a module, instead of badly failing with an
endless probe deferral loop, lets just make a modprobe call in case the
driver was made available in an initramfs with
of_device_node_request_module(), and offer a fully functional system to
the user.
Signed-off-by: Miquel Raynal <[email protected]>
Tested-by: Michael Walle <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/core.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 51fd792b8d70..49b4bbaf59e8 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -17,6 +17,7 @@
#include <linux/nvmem-provider.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/slab.h>
struct nvmem_device {
@@ -761,6 +762,13 @@ static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
if (!layout_np)
return NULL;
+ /*
+ * In case the nvmem device was built-in while the layout was built as a
+ * module, we shall manually request the layout driver loading otherwise
+ * we'll never have any match.
+ */
+ of_request_module(layout_np);
+
spin_lock(&nvmem_layout_lock);
list_for_each_entry(l, &nvmem_layouts, node) {
--
2.25.1
From: Michael Walle <[email protected]>
Provide a way to modify a cell before it will get added. This is useful
to attach a custom post processing hook via a layout.
Signed-off-by: Michael Walle <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/core.c | 4 ++++
include/linux/nvmem-provider.h | 5 +++++
2 files changed, 9 insertions(+)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 0708f9f27898..f43025ad315b 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -695,6 +695,7 @@ static int nvmem_validate_keepouts(struct nvmem_device *nvmem)
static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
{
+ struct nvmem_layout *layout = nvmem->layout;
struct device *dev = &nvmem->dev;
struct device_node *child;
const __be32 *addr;
@@ -724,6 +725,9 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
info.np = of_node_get(child);
+ if (layout && layout->fixup_cell_info)
+ layout->fixup_cell_info(nvmem, layout, &info);
+
ret = nvmem_add_one_cell(nvmem, &info);
kfree(info.name);
if (ret) {
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 3bfc23553a9e..be81cc88eabc 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -155,6 +155,8 @@ struct nvmem_cell_table {
* @add_cells: Will be called if a nvmem device is found which
* has this layout. The function will add layout
* specific cells with nvmem_add_one_cell().
+ * @fixup_cell_info: Will be called before a cell is added. Can be
+ * used to modify the nvmem_cell_info.
* @owner: Pointer to struct module.
* @node: List node.
*
@@ -168,6 +170,9 @@ struct nvmem_layout {
const struct of_device_id *of_match_table;
int (*add_cells)(struct device *dev, struct nvmem_device *nvmem,
struct nvmem_layout *layout);
+ void (*fixup_cell_info)(struct nvmem_device *nvmem,
+ struct nvmem_layout *layout,
+ struct nvmem_cell_info *cell);
/* private */
struct module *owner;
--
2.25.1
From: Miquel Raynal <[email protected]>
Make nvmem_layout_get() return -EPROBE_DEFER while the expected layout
is not available. This condition cannot be triggered today as nvmem
layout drivers are initialed as part of an early init call, but soon
these drivers will be converted into modules and be initialized with a
standard priority, so the unavailability of the drivers might become a
reality that must be taken care of.
Let's anticipate this by telling the caller the layout might not yet be
available. A probe deferral is requested in this case.
Please note this does not affect any nvmem device not using layouts,
because an early check against the "nvmem-layout" container presence
will return NULL in this case.
Signed-off-by: Miquel Raynal <[email protected]>
Tested-by: Michael Walle <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/core.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index b9be1faeb7be..51fd792b8d70 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -755,7 +755,7 @@ EXPORT_SYMBOL_GPL(nvmem_layout_unregister);
static struct nvmem_layout *nvmem_layout_get(struct nvmem_device *nvmem)
{
struct device_node *layout_np, *np = nvmem->dev.of_node;
- struct nvmem_layout *l, *layout = NULL;
+ struct nvmem_layout *l, *layout = ERR_PTR(-EPROBE_DEFER);
layout_np = of_get_child_by_name(np, "nvmem-layout");
if (!layout_np)
@@ -938,6 +938,13 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
* pointer will be NULL and nvmem_layout_put() will be a noop.
*/
nvmem->layout = config->layout ?: nvmem_layout_get(nvmem);
+ if (IS_ERR(nvmem->layout)) {
+ rval = PTR_ERR(nvmem->layout);
+ nvmem->layout = NULL;
+
+ if (rval == -EPROBE_DEFER)
+ goto err_teardown_compat;
+ }
if (config->cells) {
rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
@@ -970,6 +977,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
err_remove_cells:
nvmem_device_remove_all_cells(nvmem);
nvmem_layout_put(nvmem->layout);
+err_teardown_compat:
if (config->compat)
nvmem_sysfs_remove_compat(nvmem, config);
err_put_device:
--
2.25.1
From: Michael Walle <[email protected]>
In preparation of retiring the global post processing hook change this
driver to use layouts. The layout will be supplied during registration
and will be used to add the post processing hook to all added cells.
Signed-off-by: Michael Walle <[email protected]>
Tested-by: Michael Walle <[email protected]> # on kontron-pitx-imx8m
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/imx-ocotp.c | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
index e9b52ecb3f72..ac0edb6398f1 100644
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -225,18 +225,13 @@ static int imx_ocotp_read(void *context, unsigned int offset,
static int imx_ocotp_cell_pp(void *context, const char *id, int index,
unsigned int offset, void *data, size_t bytes)
{
- struct ocotp_priv *priv = context;
+ u8 *buf = data;
+ int i;
/* Deal with some post processing of nvmem cell data */
- if (id && !strcmp(id, "mac-address")) {
- if (priv->params->reverse_mac_address) {
- u8 *buf = data;
- int i;
-
- for (i = 0; i < bytes/2; i++)
- swap(buf[i], buf[bytes - i - 1]);
- }
- }
+ if (id && !strcmp(id, "mac-address"))
+ for (i = 0; i < bytes / 2; i++)
+ swap(buf[i], buf[bytes - i - 1]);
return 0;
}
@@ -488,7 +483,6 @@ static struct nvmem_config imx_ocotp_nvmem_config = {
.stride = 1,
.reg_read = imx_ocotp_read,
.reg_write = imx_ocotp_write,
- .cell_post_process = imx_ocotp_cell_pp,
};
static const struct ocotp_params imx6q_params = {
@@ -595,6 +589,17 @@ static const struct of_device_id imx_ocotp_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, imx_ocotp_dt_ids);
+static void imx_ocotp_fixup_cell_info(struct nvmem_device *nvmem,
+ struct nvmem_layout *layout,
+ struct nvmem_cell_info *cell)
+{
+ cell->read_post_process = imx_ocotp_cell_pp;
+}
+
+struct nvmem_layout imx_ocotp_layout = {
+ .fixup_cell_info = imx_ocotp_fixup_cell_info,
+};
+
static int imx_ocotp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -619,6 +624,9 @@ static int imx_ocotp_probe(struct platform_device *pdev)
imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
imx_ocotp_nvmem_config.dev = dev;
imx_ocotp_nvmem_config.priv = priv;
+ if (priv->params->reverse_mac_address)
+ imx_ocotp_nvmem_config.layout = &imx_ocotp_layout;
+
priv->config = &imx_ocotp_nvmem_config;
clk_prepare_enable(priv->clk);
--
2.25.1
From: Michael Walle <[email protected]>
It doesn't make any more sense to have a opaque pointer set up by the
nvmem device. Usually, the layout isn't associated with a particular
nvmem device. Instead, let the caller who set the post process callback
provide the priv pointer.
Signed-off-by: Michael Walle <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/core.c | 4 +++-
include/linux/nvmem-provider.h | 5 ++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index fccb2728193a..212c5ba5789f 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -54,6 +54,7 @@ struct nvmem_cell_entry {
int bit_offset;
int nbits;
nvmem_cell_post_process_t read_post_process;
+ void *priv;
struct device_node *np;
struct nvmem_device *nvmem;
struct list_head node;
@@ -471,6 +472,7 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem,
cell->bytes = info->bytes;
cell->name = info->name;
cell->read_post_process = info->read_post_process;
+ cell->priv = info->priv;
cell->bit_offset = info->bit_offset;
cell->nbits = info->nbits;
@@ -1568,7 +1570,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
nvmem_shift_read_buffer_in_place(cell, buf);
if (cell->read_post_process) {
- rc = cell->read_post_process(nvmem->priv, id, index,
+ rc = cell->read_post_process(cell->priv, id, index,
cell->offset, buf, cell->bytes);
if (rc)
return rc;
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index d3d7af86a283..0cf9f9490514 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -20,7 +20,8 @@ typedef int (*nvmem_reg_write_t)(void *priv, unsigned int offset,
void *val, size_t bytes);
/* used for vendor specific post processing of cell data */
typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, int index,
- unsigned int offset, void *buf, size_t bytes);
+ unsigned int offset, void *buf,
+ size_t bytes);
enum nvmem_type {
NVMEM_TYPE_UNKNOWN = 0,
@@ -56,6 +57,7 @@ struct nvmem_keepout {
* @np: Optional device_node pointer.
* @read_post_process: Callback for optional post processing of cell data
* on reads.
+ * @priv: Opaque data passed to the read_post_process hook.
*/
struct nvmem_cell_info {
const char *name;
@@ -65,6 +67,7 @@ struct nvmem_cell_info {
unsigned int nbits;
struct device_node *np;
nvmem_cell_post_process_t read_post_process;
+ void *priv;
};
/**
--
2.25.1
From: Michael Walle <[email protected]>
There are no users anymore for the global cell_post_process callback
anymore. New users should use proper nvmem layouts.
Signed-off-by: Michael Walle <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/core.c | 9 ---------
include/linux/nvmem-provider.h | 2 --
2 files changed, 11 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index f43025ad315b..fccb2728193a 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -39,7 +39,6 @@ struct nvmem_device {
unsigned int nkeepout;
nvmem_reg_read_t reg_read;
nvmem_reg_write_t reg_write;
- nvmem_cell_post_process_t cell_post_process;
struct gpio_desc *wp_gpio;
struct nvmem_layout *layout;
void *priv;
@@ -903,7 +902,6 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
nvmem->type = config->type;
nvmem->reg_read = config->reg_read;
nvmem->reg_write = config->reg_write;
- nvmem->cell_post_process = config->cell_post_process;
nvmem->keepout = config->keepout;
nvmem->nkeepout = config->nkeepout;
if (config->of_node)
@@ -1576,13 +1574,6 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
return rc;
}
- if (nvmem->cell_post_process) {
- rc = nvmem->cell_post_process(nvmem->priv, id, index,
- cell->offset, buf, cell->bytes);
- if (rc)
- return rc;
- }
-
if (len)
*len = cell->bytes;
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index be81cc88eabc..d3d7af86a283 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -85,7 +85,6 @@ struct nvmem_cell_info {
* @no_of_node: Device should not use the parent's of_node even if it's !NULL.
* @reg_read: Callback to read data.
* @reg_write: Callback to write data.
- * @cell_post_process: Callback for vendor specific post processing of cell data
* @size: Device size.
* @word_size: Minimum read/write access granularity.
* @stride: Minimum read/write access stride.
@@ -118,7 +117,6 @@ struct nvmem_config {
bool no_of_node;
nvmem_reg_read_t reg_read;
nvmem_reg_write_t reg_write;
- nvmem_cell_post_process_t cell_post_process;
int size;
int word_size;
int stride;
--
2.25.1
From: Michael Walle <[email protected]>
This layout applies to the VPD of the Kontron sl28 boards. The VPD only
contains a base MAC address. Therefore, we have to add an individual
offset to it. This is done by taking the second argument of the nvmem
phandle into account. Also this let us checking the VPD version and the
checksum.
Signed-off-by: Michael Walle <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/layouts/Kconfig | 9 ++
drivers/nvmem/layouts/Makefile | 2 +
drivers/nvmem/layouts/sl28vpd.c | 165 ++++++++++++++++++++++++++++++++
3 files changed, 176 insertions(+)
create mode 100644 drivers/nvmem/layouts/sl28vpd.c
diff --git a/drivers/nvmem/layouts/Kconfig b/drivers/nvmem/layouts/Kconfig
index 9ad3911d1605..fd161347c129 100644
--- a/drivers/nvmem/layouts/Kconfig
+++ b/drivers/nvmem/layouts/Kconfig
@@ -2,4 +2,13 @@
menu "Layout Types"
+config NVMEM_LAYOUT_SL28_VPD
+ tristate "Kontron sl28 VPD layout support"
+ select CRC8
+ help
+ Say Y here if you want to support the VPD layout of the Kontron
+ SMARC-sAL28 boards.
+
+ If unsure, say N.
+
endmenu
diff --git a/drivers/nvmem/layouts/Makefile b/drivers/nvmem/layouts/Makefile
index 6fdb3c60a4fa..fc617b9e87d0 100644
--- a/drivers/nvmem/layouts/Makefile
+++ b/drivers/nvmem/layouts/Makefile
@@ -2,3 +2,5 @@
#
# Makefile for nvmem layouts.
#
+
+obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
diff --git a/drivers/nvmem/layouts/sl28vpd.c b/drivers/nvmem/layouts/sl28vpd.c
new file mode 100644
index 000000000000..9370e41bad73
--- /dev/null
+++ b/drivers/nvmem/layouts/sl28vpd.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/crc8.h>
+#include <linux/etherdevice.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <uapi/linux/if_ether.h>
+
+#define SL28VPD_MAGIC 'V'
+
+struct sl28vpd_header {
+ u8 magic;
+ u8 version;
+} __packed;
+
+struct sl28vpd_v1 {
+ struct sl28vpd_header header;
+ char serial_number[15];
+ u8 base_mac_address[ETH_ALEN];
+ u8 crc8;
+} __packed;
+
+static int sl28vpd_mac_address_pp(void *priv, const char *id, int index,
+ unsigned int offset, void *buf,
+ size_t bytes)
+{
+ if (bytes != ETH_ALEN)
+ return -EINVAL;
+
+ if (index < 0)
+ return -EINVAL;
+
+ if (!is_valid_ether_addr(buf))
+ return -EINVAL;
+
+ eth_addr_add(buf, index);
+
+ return 0;
+}
+
+static const struct nvmem_cell_info sl28vpd_v1_entries[] = {
+ {
+ .name = "serial-number",
+ .offset = offsetof(struct sl28vpd_v1, serial_number),
+ .bytes = sizeof_field(struct sl28vpd_v1, serial_number),
+ },
+ {
+ .name = "base-mac-address",
+ .offset = offsetof(struct sl28vpd_v1, base_mac_address),
+ .bytes = sizeof_field(struct sl28vpd_v1, base_mac_address),
+ .read_post_process = sl28vpd_mac_address_pp,
+ },
+};
+
+static int sl28vpd_v1_check_crc(struct device *dev, struct nvmem_device *nvmem)
+{
+ struct sl28vpd_v1 data_v1;
+ u8 table[CRC8_TABLE_SIZE];
+ int ret;
+ u8 crc;
+
+ crc8_populate_msb(table, 0x07);
+
+ ret = nvmem_device_read(nvmem, 0, sizeof(data_v1), &data_v1);
+ if (ret < 0)
+ return ret;
+ else if (ret != sizeof(data_v1))
+ return -EIO;
+
+ crc = crc8(table, (void *)&data_v1, sizeof(data_v1) - 1, 0);
+
+ if (crc != data_v1.crc8) {
+ dev_err(dev,
+ "Checksum is invalid (got %02x, expected %02x).\n",
+ crc, data_v1.crc8);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int sl28vpd_add_cells(struct device *dev, struct nvmem_device *nvmem,
+ struct nvmem_layout *layout)
+{
+ const struct nvmem_cell_info *pinfo;
+ struct nvmem_cell_info info = {0};
+ struct device_node *layout_np;
+ struct sl28vpd_header hdr;
+ int ret, i;
+
+ /* check header */
+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
+ if (ret < 0)
+ return ret;
+ else if (ret != sizeof(hdr))
+ return -EIO;
+
+ if (hdr.magic != SL28VPD_MAGIC) {
+ dev_err(dev, "Invalid magic value (%02x)\n", hdr.magic);
+ return -EINVAL;
+ }
+
+ if (hdr.version != 1) {
+ dev_err(dev, "Version %d is unsupported.\n", hdr.version);
+ return -EINVAL;
+ }
+
+ ret = sl28vpd_v1_check_crc(dev, nvmem);
+ if (ret)
+ return ret;
+
+ layout_np = of_nvmem_layout_get_container(nvmem);
+ if (!layout_np)
+ return -ENOENT;
+
+ for (i = 0; i < ARRAY_SIZE(sl28vpd_v1_entries); i++) {
+ pinfo = &sl28vpd_v1_entries[i];
+
+ info.name = pinfo->name;
+ info.offset = pinfo->offset;
+ info.bytes = pinfo->bytes;
+ info.read_post_process = pinfo->read_post_process;
+ info.np = of_get_child_by_name(layout_np, pinfo->name);
+
+ ret = nvmem_add_one_cell(nvmem, &info);
+ if (ret) {
+ of_node_put(layout_np);
+ return ret;
+ }
+ }
+
+ of_node_put(layout_np);
+
+ return 0;
+}
+
+static const struct of_device_id sl28vpd_of_match_table[] = {
+ { .compatible = "kontron,sl28-vpd" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
+
+struct nvmem_layout sl28vpd_layout = {
+ .name = "sl28-vpd",
+ .of_match_table = sl28vpd_of_match_table,
+ .add_cells = sl28vpd_add_cells,
+};
+
+static int __init sl28vpd_init(void)
+{
+ return nvmem_layout_register(&sl28vpd_layout);
+}
+
+static void __exit sl28vpd_exit(void)
+{
+ nvmem_layout_unregister(&sl28vpd_layout);
+}
+
+module_init(sl28vpd_init);
+module_exit(sl28vpd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Walle <[email protected]>");
+MODULE_DESCRIPTION("NVMEM layout driver for the VPD of Kontron sl28 boards");
--
2.25.1
From: Michael Walle <[email protected]>
Add myself as a maintainer for the new sl28vpd nvmem layout driver.
Signed-off-by: Michael Walle <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 4d4f778ede5d..a7763063ffa3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19175,6 +19175,12 @@ F: drivers/irqchip/irq-sl28cpld.c
F: drivers/pwm/pwm-sl28cpld.c
F: drivers/watchdog/sl28cpld_wdt.c
+SL28 VPD NVMEM LAYOUT DRIVER
+M: Michael Walle <[email protected]>
+S: Maintained
+F: Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml
+F: drivers/nvmem/layouts/sl28vpd.c
+
SLAB ALLOCATOR
M: Christoph Lameter <[email protected]>
M: Pekka Enberg <[email protected]>
--
2.25.1
From: Rob Herring <[email protected]>
Cleanup bindings dropping unneeded quotes. Once all these are fixed,
checking for this can be enabled in yamllint.
Signed-off-by: Rob Herring <[email protected]>
Acked-by: Jernej Skrabec <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
.../devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/apple,efuses.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/imx-iim.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml | 2 +-
.../devicetree/bindings/nvmem/ingenic,jz4780-efuse.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml | 2 +-
.../devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/rmem.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml | 2 +-
.../devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml | 2 +-
Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml | 2 +-
.../devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml | 2 +-
18 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml b/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
index 14c170c6a86e..296001e7f498 100644
--- a/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
@@ -11,7 +11,7 @@ maintainers:
- Maxime Ripard <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/apple,efuses.yaml b/Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
index 5ec8f2bdb3a5..e0860b6b85f3 100644
--- a/Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
+++ b/Documentation/devicetree/bindings/nvmem/apple,efuses.yaml
@@ -15,7 +15,7 @@ maintainers:
- Sven Peter <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml b/Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml
index 25033de3ef6b..36def7128fca 100644
--- a/Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml
+++ b/Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml
@@ -20,7 +20,7 @@ maintainers:
- Rafał Miłecki <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml b/Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml
index 3b4e6e94cb81..70fb2ad25103 100644
--- a/Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml
@@ -14,7 +14,7 @@ description: |
unique identifier per part.
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/imx-iim.yaml b/Documentation/devicetree/bindings/nvmem/imx-iim.yaml
index 7aac1995cfaf..e9d9d8df4811 100644
--- a/Documentation/devicetree/bindings/nvmem/imx-iim.yaml
+++ b/Documentation/devicetree/bindings/nvmem/imx-iim.yaml
@@ -14,7 +14,7 @@ description: |
i.MX25, i.MX27, i.MX31, i.MX35, i.MX51 and i.MX53 SoCs.
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
index d0a239d7e199..9876243ff1e8 100644
--- a/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml
@@ -15,7 +15,7 @@ description: |
i.MX7D/S, i.MX7ULP, i.MX8MQ, i.MX8MM, i.MX8MN and i.MX8MP SoCs.
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/ingenic,jz4780-efuse.yaml b/Documentation/devicetree/bindings/nvmem/ingenic,jz4780-efuse.yaml
index fe2cd7f1afba..e89fd879c968 100644
--- a/Documentation/devicetree/bindings/nvmem/ingenic,jz4780-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/ingenic,jz4780-efuse.yaml
@@ -10,7 +10,7 @@ maintainers:
- PrasannaKumar Muralidharan <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml
index 75e0a516e59a..d16d42fb98b6 100644
--- a/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml
@@ -15,7 +15,7 @@ maintainers:
- Lala Lin <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml b/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
index c3c96fd0baac..a296d348adb4 100644
--- a/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
+++ b/Documentation/devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml
@@ -15,7 +15,7 @@ description: |
settings, chip identifiers) or user specific data could be stored.
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml
index ff317fd7c15b..8938eec22b52 100644
--- a/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml
@@ -10,7 +10,7 @@ maintainers:
- Anson Huang <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml b/Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml
index f93bc50c40d7..6c26800f8b79 100644
--- a/Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml
@@ -17,7 +17,7 @@ maintainers:
- Emmanuel Gil Peyrot <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
index 2173fe82317d..e952907ad1d5 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
@@ -10,7 +10,7 @@ maintainers:
- Srinivas Kandagatla <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml b/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
index 4702f10ecca2..dce0c7d84ce7 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml
@@ -15,7 +15,7 @@ description: |
to/from the PBUS.
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/rmem.yaml b/Documentation/devicetree/bindings/nvmem/rmem.yaml
index a4a755dcfc43..38a39c9b8c1c 100644
--- a/Documentation/devicetree/bindings/nvmem/rmem.yaml
+++ b/Documentation/devicetree/bindings/nvmem/rmem.yaml
@@ -10,7 +10,7 @@ maintainers:
- Nicolas Saenz Julienne <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
index febee8129aa9..c5403e149080 100644
--- a/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml
@@ -10,7 +10,7 @@ maintainers:
- Heiko Stuebner <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml b/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
index dc790d2cd9f0..b8bca0599c45 100644
--- a/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml
@@ -11,7 +11,7 @@ maintainers:
- Kunihiko Hayashi <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
"#address-cells": true
diff --git a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml
index 172597cc5c63..a69de3e92282 100644
--- a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml
+++ b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml
@@ -16,7 +16,7 @@ maintainers:
- Fabrice Gasnier <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml b/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
index a7644ebbc2ca..8877c2283e9e 100644
--- a/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml
@@ -11,7 +11,7 @@ maintainers:
- Vincent Shih <[email protected]>
allOf:
- - $ref: "nvmem.yaml#"
+ - $ref: nvmem.yaml#
properties:
compatible:
--
2.25.1
From: Krzysztof Kozlowski <[email protected]>
The driver can be compile tested with !CONFIG_OF making certain data
unused:
drivers/nvmem/stm32-romem.c:271:34: error: ‘stm32_romem_of_match’ defined but not used [-Werror=unused-const-variable=]
Signed-off-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/stm32-romem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvmem/stm32-romem.c b/drivers/nvmem/stm32-romem.c
index ba779e26937a..38d0bf557129 100644
--- a/drivers/nvmem/stm32-romem.c
+++ b/drivers/nvmem/stm32-romem.c
@@ -268,7 +268,7 @@ static const struct stm32_romem_cfg stm32mp13_bsec_cfg = {
.ta = true,
};
-static const struct of_device_id stm32_romem_of_match[] = {
+static const struct of_device_id stm32_romem_of_match[] __maybe_unused = {
{ .compatible = "st,stm32f4-otp", }, {
.compatible = "st,stm32mp15-bsec",
.data = (void *)&stm32mp15_bsec_cfg,
--
2.25.1
From: AngeloGioacchino Del Regno <[email protected]>
On some MediaTek SoCs GPU speed binning data is available for read
in the SoC's eFuse array but it has a format that is incompatible
with what the OPP API expects, as we read a number from 0 to 7 but
opp-supported-hw is expecting a bitmask to enable an OPP entry:
being what we read limited to 0-7, it's straightforward to simply
convert the value to BIT(value) as a post-processing action.
So, introduce post-processing support and enable it by evaluating
the newly introduced platform data's `uses_post_processing` member,
currently enabled only for MT8186.
Signed-off-by: AngeloGioacchino Del Regno <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/mtk-efuse.c | 53 +++++++++++++++++++++++++++++++++++++--
1 file changed, 51 insertions(+), 2 deletions(-)
diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
index a08e0aedd21c..b36cd0dcc8c7 100644
--- a/drivers/nvmem/mtk-efuse.c
+++ b/drivers/nvmem/mtk-efuse.c
@@ -10,6 +10,11 @@
#include <linux/io.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
+
+struct mtk_efuse_pdata {
+ bool uses_post_processing;
+};
struct mtk_efuse_priv {
void __iomem *base;
@@ -29,6 +34,37 @@ static int mtk_reg_read(void *context,
return 0;
}
+static int mtk_efuse_gpu_speedbin_pp(void *context, const char *id, int index,
+ unsigned int offset, void *data, size_t bytes)
+{
+ u8 *val = data;
+
+ if (val[0] < 8)
+ val[0] = BIT(val[0]);
+
+ return 0;
+}
+
+static void mtk_efuse_fixup_cell_info(struct nvmem_device *nvmem,
+ struct nvmem_layout *layout,
+ struct nvmem_cell_info *cell)
+{
+ size_t sz = strlen(cell->name);
+
+ /*
+ * On some SoCs, the GPU speedbin is not read as bitmask but as
+ * a number with range [0-7] (max 3 bits): post process to use
+ * it in OPP tables to describe supported-hw.
+ */
+ if (cell->nbits <= 3 &&
+ strncmp(cell->name, "gpu-speedbin", min(sz, strlen("gpu-speedbin"))) == 0)
+ cell->read_post_process = mtk_efuse_gpu_speedbin_pp;
+}
+
+static struct nvmem_layout mtk_efuse_layout = {
+ .fixup_cell_info = mtk_efuse_fixup_cell_info,
+};
+
static int mtk_efuse_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -36,6 +72,7 @@ static int mtk_efuse_probe(struct platform_device *pdev)
struct nvmem_device *nvmem;
struct nvmem_config econfig = {};
struct mtk_efuse_priv *priv;
+ const struct mtk_efuse_pdata *pdata;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -45,20 +82,32 @@ static int mtk_efuse_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
+ pdata = device_get_match_data(dev);
econfig.stride = 1;
econfig.word_size = 1;
econfig.reg_read = mtk_reg_read;
econfig.size = resource_size(res);
econfig.priv = priv;
econfig.dev = dev;
+ if (pdata->uses_post_processing)
+ econfig.layout = &mtk_efuse_layout;
nvmem = devm_nvmem_register(dev, &econfig);
return PTR_ERR_OR_ZERO(nvmem);
}
+static const struct mtk_efuse_pdata mtk_mt8186_efuse_pdata = {
+ .uses_post_processing = true,
+};
+
+static const struct mtk_efuse_pdata mtk_efuse_pdata = {
+ .uses_post_processing = false,
+};
+
static const struct of_device_id mtk_efuse_of_match[] = {
- { .compatible = "mediatek,mt8173-efuse",},
- { .compatible = "mediatek,efuse",},
+ { .compatible = "mediatek,mt8173-efuse", .data = &mtk_efuse_pdata },
+ { .compatible = "mediatek,mt8186-efuse", .data = &mtk_mt8186_efuse_pdata },
+ { .compatible = "mediatek,efuse", .data = &mtk_efuse_pdata },
{/* sentinel */},
};
MODULE_DEVICE_TABLE(of, mtk_efuse_of_match);
--
2.25.1
From: Miquel Raynal <[email protected]>
Following the introduction of the bindings for this NVMEM parser and the
layout driver, add myself as maintainer.
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index a7763063ffa3..de05ac9b58ca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15547,6 +15547,12 @@ L: [email protected]
S: Maintained
F: drivers/hwmon/oxp-sensors.c
+ONIE TLV NVMEM LAYOUT DRIVER
+M: Miquel Raynal <[email protected]>
+S: Maintained
+F: Documentation/devicetree/bindings/nvmem/layouts/onie,tlv-layout.yaml
+F: drivers/nvmem/layouts/onie-tlv.c
+
ONION OMEGA2+ BOARD
M: Harvey Hunt <[email protected]>
L: [email protected]
--
2.25.1
From: Konrad Dybcio <[email protected]>
Docuemnt the QFPROM on SM6350.
Signed-off-by: Konrad Dybcio <[email protected]>
Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
index e952907ad1d5..c20bd9bdcea4 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
@@ -32,6 +32,7 @@ properties:
- qcom,sdm670-qfprom
- qcom,sdm845-qfprom
- qcom,sm6115-qfprom
+ - qcom,sm6350-qfprom
- qcom,sm8150-qfprom
- qcom,sm8250-qfprom
- const: qcom,qfprom
--
2.25.1
From: Miquel Raynal <[email protected]>
This layout applies on top of any non volatile storage device containing
an ONIE table factory flashed. This table follows the tlv
(type-length-value) organization described in the link below. We cannot
afford using regular parsers because the content of these tables is
manufacturer specific and must be dynamically discovered.
Link: https://opencomputeproject.github.io/onie/design-spec/hw_requirements.html
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/layouts/Kconfig | 9 ++
drivers/nvmem/layouts/Makefile | 1 +
drivers/nvmem/layouts/onie-tlv.c | 257 +++++++++++++++++++++++++++++++
3 files changed, 267 insertions(+)
create mode 100644 drivers/nvmem/layouts/onie-tlv.c
diff --git a/drivers/nvmem/layouts/Kconfig b/drivers/nvmem/layouts/Kconfig
index fd161347c129..7ff1ee1c1f05 100644
--- a/drivers/nvmem/layouts/Kconfig
+++ b/drivers/nvmem/layouts/Kconfig
@@ -11,4 +11,13 @@ config NVMEM_LAYOUT_SL28_VPD
If unsure, say N.
+config NVMEM_LAYOUT_ONIE_TLV
+ tristate "ONIE tlv support"
+ select CRC32
+ help
+ Say Y here if you want to support the Open Compute Project ONIE
+ Type-Length-Value standard table.
+
+ If unsure, say N.
+
endmenu
diff --git a/drivers/nvmem/layouts/Makefile b/drivers/nvmem/layouts/Makefile
index fc617b9e87d0..2974bd7d33ed 100644
--- a/drivers/nvmem/layouts/Makefile
+++ b/drivers/nvmem/layouts/Makefile
@@ -4,3 +4,4 @@
#
obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
+obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
diff --git a/drivers/nvmem/layouts/onie-tlv.c b/drivers/nvmem/layouts/onie-tlv.c
new file mode 100644
index 000000000000..d45b7301a69d
--- /dev/null
+++ b/drivers/nvmem/layouts/onie-tlv.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ONIE tlv NVMEM cells provider
+ *
+ * Copyright (C) 2022 Open Compute Group ONIE
+ * Author: Miquel Raynal <[email protected]>
+ * Based on the nvmem driver written by: Vadym Kochan <[email protected]>
+ * Inspired by the first layout written by: Rafał Miłecki <[email protected]>
+ */
+
+#include <linux/crc32.h>
+#include <linux/etherdevice.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+
+#define ONIE_TLV_MAX_LEN 2048
+#define ONIE_TLV_CRC_FIELD_SZ 6
+#define ONIE_TLV_CRC_SZ 4
+#define ONIE_TLV_HDR_ID "TlvInfo"
+
+struct onie_tlv_hdr {
+ u8 id[8];
+ u8 version;
+ __be16 data_len;
+} __packed;
+
+struct onie_tlv {
+ u8 type;
+ u8 len;
+} __packed;
+
+static const char *onie_tlv_cell_name(u8 type)
+{
+ switch (type) {
+ case 0x21:
+ return "product-name";
+ case 0x22:
+ return "part-number";
+ case 0x23:
+ return "serial-number";
+ case 0x24:
+ return "mac-address";
+ case 0x25:
+ return "manufacture-date";
+ case 0x26:
+ return "device-version";
+ case 0x27:
+ return "label-revision";
+ case 0x28:
+ return "platform-name";
+ case 0x29:
+ return "onie-version";
+ case 0x2A:
+ return "num-macs";
+ case 0x2B:
+ return "manufacturer";
+ case 0x2C:
+ return "country-code";
+ case 0x2D:
+ return "vendor";
+ case 0x2E:
+ return "diag-version";
+ case 0x2F:
+ return "service-tag";
+ case 0xFD:
+ return "vendor-extension";
+ case 0xFE:
+ return "crc32";
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static int onie_tlv_mac_read_cb(void *priv, const char *id, int index,
+ unsigned int offset, void *buf,
+ size_t bytes)
+{
+ eth_addr_add(buf, index);
+
+ return 0;
+}
+
+static nvmem_cell_post_process_t onie_tlv_read_cb(u8 type, u8 *buf)
+{
+ switch (type) {
+ case 0x24:
+ return &onie_tlv_mac_read_cb;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static int onie_tlv_add_cells(struct device *dev, struct nvmem_device *nvmem,
+ size_t data_len, u8 *data)
+{
+ struct nvmem_cell_info cell = {};
+ struct device_node *layout;
+ struct onie_tlv tlv;
+ unsigned int hdr_len = sizeof(struct onie_tlv_hdr);
+ unsigned int offset = 0;
+ int ret;
+
+ layout = of_nvmem_layout_get_container(nvmem);
+ if (!layout)
+ return -ENOENT;
+
+ while (offset < data_len) {
+ memcpy(&tlv, data + offset, sizeof(tlv));
+ if (offset + tlv.len >= data_len) {
+ dev_err(dev, "Out of bounds field (0x%x bytes at 0x%x)\n",
+ tlv.len, hdr_len + offset);
+ break;
+ }
+
+ cell.name = onie_tlv_cell_name(tlv.type);
+ if (!cell.name)
+ continue;
+
+ cell.offset = hdr_len + offset + sizeof(tlv.type) + sizeof(tlv.len);
+ cell.bytes = tlv.len;
+ cell.np = of_get_child_by_name(layout, cell.name);
+ cell.read_post_process = onie_tlv_read_cb(tlv.type, data + offset + sizeof(tlv));
+
+ ret = nvmem_add_one_cell(nvmem, &cell);
+ if (ret) {
+ of_node_put(layout);
+ return ret;
+ }
+
+ offset += sizeof(tlv) + tlv.len;
+ }
+
+ of_node_put(layout);
+
+ return 0;
+}
+
+static bool onie_tlv_hdr_is_valid(struct device *dev, struct onie_tlv_hdr *hdr)
+{
+ if (memcmp(hdr->id, ONIE_TLV_HDR_ID, sizeof(hdr->id))) {
+ dev_err(dev, "Invalid header\n");
+ return false;
+ }
+
+ if (hdr->version != 0x1) {
+ dev_err(dev, "Invalid version number\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool onie_tlv_crc_is_valid(struct device *dev, size_t table_len, u8 *table)
+{
+ struct onie_tlv crc_hdr;
+ u32 read_crc, calc_crc;
+ __be32 crc_be;
+
+ memcpy(&crc_hdr, table + table_len - ONIE_TLV_CRC_FIELD_SZ, sizeof(crc_hdr));
+ if (crc_hdr.type != 0xfe || crc_hdr.len != ONIE_TLV_CRC_SZ) {
+ dev_err(dev, "Invalid CRC field\n");
+ return false;
+ }
+
+ /* The table contains a JAMCRC, which is XOR'ed compared to the original
+ * CRC32 implementation as known in the Ethernet world.
+ */
+ memcpy(&crc_be, table + table_len - ONIE_TLV_CRC_SZ, ONIE_TLV_CRC_SZ);
+ read_crc = be32_to_cpu(crc_be);
+ calc_crc = crc32(~0, table, table_len - ONIE_TLV_CRC_SZ) ^ 0xFFFFFFFF;
+ if (read_crc != calc_crc) {
+ dev_err(dev, "Invalid CRC read: 0x%08x, expected: 0x%08x\n",
+ read_crc, calc_crc);
+ return false;
+ }
+
+ return true;
+}
+
+static int onie_tlv_parse_table(struct device *dev, struct nvmem_device *nvmem,
+ struct nvmem_layout *layout)
+{
+ struct onie_tlv_hdr hdr;
+ size_t table_len, data_len, hdr_len;
+ u8 *table, *data;
+ int ret;
+
+ ret = nvmem_device_read(nvmem, 0, sizeof(hdr), &hdr);
+ if (ret < 0)
+ return ret;
+
+ if (!onie_tlv_hdr_is_valid(dev, &hdr)) {
+ dev_err(dev, "Invalid ONIE TLV header\n");
+ return -EINVAL;
+ }
+
+ hdr_len = sizeof(hdr.id) + sizeof(hdr.version) + sizeof(hdr.data_len);
+ data_len = be16_to_cpu(hdr.data_len);
+ table_len = hdr_len + data_len;
+ if (table_len > ONIE_TLV_MAX_LEN) {
+ dev_err(dev, "Invalid ONIE TLV data length\n");
+ return -EINVAL;
+ }
+
+ table = devm_kmalloc(dev, table_len, GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ ret = nvmem_device_read(nvmem, 0, table_len, table);
+ if (ret != table_len)
+ return ret;
+
+ if (!onie_tlv_crc_is_valid(dev, table_len, table))
+ return -EINVAL;
+
+ data = table + hdr_len;
+ ret = onie_tlv_add_cells(dev, nvmem, data_len, data);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct of_device_id onie_tlv_of_match_table[] = {
+ { .compatible = "onie,tlv-layout", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, onie_tlv_of_match_table);
+
+static struct nvmem_layout onie_tlv_layout = {
+ .name = "ONIE tlv layout",
+ .of_match_table = onie_tlv_of_match_table,
+ .add_cells = onie_tlv_parse_table,
+};
+
+static int __init onie_tlv_init(void)
+{
+ return nvmem_layout_register(&onie_tlv_layout);
+}
+
+static void __exit onie_tlv_exit(void)
+{
+ nvmem_layout_unregister(&onie_tlv_layout);
+}
+
+module_init(onie_tlv_init);
+module_exit(onie_tlv_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Miquel Raynal <[email protected]>");
+MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
+MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
--
2.25.1
From: Yang Li <[email protected]>
According to commit 890cc39a8799 ("drivers: provide
devm_platform_get_and_ioremap_resource()"), convert
platform_get_resource(), devm_ioremap_resource() to a single
call to devm_platform_get_and_ioremap_resource(), as this is exactly
what this function does.
Signed-off-by: Yang Li <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/vf610-ocotp.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/nvmem/vf610-ocotp.c b/drivers/nvmem/vf610-ocotp.c
index 5b6cad16892f..ee9c61ae727d 100644
--- a/drivers/nvmem/vf610-ocotp.c
+++ b/drivers/nvmem/vf610-ocotp.c
@@ -219,8 +219,7 @@ static int vf610_ocotp_probe(struct platform_device *pdev)
if (!ocotp_dev)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ocotp_dev->base = devm_ioremap_resource(dev, res);
+ ocotp_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(ocotp_dev->base))
return PTR_ERR(ocotp_dev->base);
--
2.25.1
From: Yang Li <[email protected]>
According to commit 7945f929f1a7 ("drivers: provide
devm_platform_ioremap_resource()"), convert platform_get_resource(),
devm_ioremap_resource() to a single call to use
devm_platform_ioremap_resource(), as this is exactly what this function
does.
Signed-off-by: Yang Li <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/nintendo-otp.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/nvmem/nintendo-otp.c b/drivers/nvmem/nintendo-otp.c
index 33961b17f9f1..355e7f1fc6d5 100644
--- a/drivers/nvmem/nintendo-otp.c
+++ b/drivers/nvmem/nintendo-otp.c
@@ -76,7 +76,6 @@ static int nintendo_otp_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
const struct of_device_id *of_id =
of_match_device(nintendo_otp_of_table, dev);
- struct resource *res;
struct nvmem_device *nvmem;
struct nintendo_otp_priv *priv;
@@ -92,8 +91,7 @@ static int nintendo_otp_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->regs = devm_ioremap_resource(dev, res);
+ priv->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->regs))
return PTR_ERR(priv->regs);
--
2.25.1
From: Rafał Miłecki <[email protected]>
U-Boot's "ethaddr" environment variable is very often used to store
*base* MAC address. It's used as a base for calculating addresses for
multiple interfaces. It's done by adding proper values. Actual offsets
are picked by manufacturers and vary across devices.
Signed-off-by: Rafał Miłecki <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
Documentation/devicetree/bindings/nvmem/u-boot,env.yaml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml b/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
index cbc5c69fd405..36d97fb87865 100644
--- a/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
+++ b/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
@@ -50,7 +50,11 @@ properties:
ethaddr:
type: object
- description: Ethernet interface's MAC address
+ description: Ethernet interfaces base MAC address.
+ properties:
+ "#nvmem-cell-cells":
+ description: The first argument is a MAC address offset.
+ const: 1
additionalProperties: false
@@ -72,6 +76,7 @@ examples:
reg = <0x40000 0x10000>;
mac: ethaddr {
+ #nvmem-cell-cells = <1>;
};
};
};
--
2.25.1
From: Yang Li <[email protected]>
According to commit 7945f929f1a7 ("drivers: provide
devm_platform_ioremap_resource()"), convert platform_get_resource(),
devm_ioremap_resource() to a single call to use
devm_platform_ioremap_resource(), as this is exactly what this function
does.
Signed-off-by: Yang Li <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/bcm-ocotp.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/nvmem/bcm-ocotp.c b/drivers/nvmem/bcm-ocotp.c
index a128c7f5e351..0c1fa0c4feb2 100644
--- a/drivers/nvmem/bcm-ocotp.c
+++ b/drivers/nvmem/bcm-ocotp.c
@@ -244,7 +244,6 @@ MODULE_DEVICE_TABLE(acpi, bcm_otpc_acpi_ids);
static int bcm_otpc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct resource *res;
struct otpc_priv *priv;
struct nvmem_device *nvmem;
int err;
@@ -259,8 +258,7 @@ static int bcm_otpc_probe(struct platform_device *pdev)
return -ENODEV;
/* Get OTP base address register. */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->base = devm_ioremap_resource(dev, res);
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base)) {
dev_err(dev, "unable to map I/O memory\n");
return PTR_ERR(priv->base);
--
2.25.1
From: Rafał Miłecki <[email protected]>
U-Boot environment variables are stored in ASCII format so "ethaddr"
requires parsing into binary to make it work with Ethernet interfaces.
This includes support for indexes to support #nvmem-cell-cells = <1>.
Signed-off-by: Rafał Miłecki <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/Kconfig | 1 +
drivers/nvmem/u-boot-env.c | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index a2afba11c890..b291b27048c7 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -340,6 +340,7 @@ config NVMEM_U_BOOT_ENV
tristate "U-Boot environment variables support"
depends on OF && MTD
select CRC32
+ select GENERIC_NET_UTILS
help
U-Boot stores its setup as environment variables. This driver adds
support for verifying & exporting such data. It also exposes variables
diff --git a/drivers/nvmem/u-boot-env.c b/drivers/nvmem/u-boot-env.c
index 29b1d87a3c51..ee9fd9989b6e 100644
--- a/drivers/nvmem/u-boot-env.c
+++ b/drivers/nvmem/u-boot-env.c
@@ -4,6 +4,8 @@
*/
#include <linux/crc32.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h>
@@ -70,6 +72,25 @@ static int u_boot_env_read(void *context, unsigned int offset, void *val,
return 0;
}
+static int u_boot_env_read_post_process_ethaddr(void *context, const char *id, int index,
+ unsigned int offset, void *buf, size_t bytes)
+{
+ u8 mac[ETH_ALEN];
+
+ if (bytes != 3 * ETH_ALEN - 1)
+ return -EINVAL;
+
+ if (!mac_pton(buf, mac))
+ return -EINVAL;
+
+ if (index)
+ eth_addr_add(mac, index);
+
+ ether_addr_copy(buf, mac);
+
+ return 0;
+}
+
static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf,
size_t data_offset, size_t data_len)
{
@@ -101,6 +122,11 @@ static int u_boot_env_add_cells(struct u_boot_env *priv, uint8_t *buf,
priv->cells[idx].offset = data_offset + value - data;
priv->cells[idx].bytes = strlen(value);
priv->cells[idx].np = of_get_child_by_name(dev->of_node, priv->cells[idx].name);
+ if (!strcmp(var, "ethaddr")) {
+ priv->cells[idx].raw_len = strlen(value);
+ priv->cells[idx].bytes = ETH_ALEN;
+ priv->cells[idx].read_post_process = u_boot_env_read_post_process_ethaddr;
+ }
}
if (WARN_ON(idx != priv->ncells))
--
2.25.1
From: Konrad Dybcio <[email protected]>
Docuemnt the QFPROM on SM6375.
Signed-off-by: Konrad Dybcio <[email protected]>
Acked-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
index c20bd9bdcea4..8d8503dd934b 100644
--- a/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
+++ b/Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml
@@ -33,6 +33,7 @@ properties:
- qcom,sdm845-qfprom
- qcom,sm6115-qfprom
- qcom,sm6350-qfprom
+ - qcom,sm6375-qfprom
- qcom,sm8150-qfprom
- qcom,sm8250-qfprom
- const: qcom,qfprom
--
2.25.1
From: Miquel Raynal <[email protected]>
Stop open-coding the module init/exit functions. Use the
module_nvmem_layout_driver() instead.
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/layouts/sl28vpd.c | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/drivers/nvmem/layouts/sl28vpd.c b/drivers/nvmem/layouts/sl28vpd.c
index 9370e41bad73..9cc1715c2fd5 100644
--- a/drivers/nvmem/layouts/sl28vpd.c
+++ b/drivers/nvmem/layouts/sl28vpd.c
@@ -146,19 +146,7 @@ struct nvmem_layout sl28vpd_layout = {
.of_match_table = sl28vpd_of_match_table,
.add_cells = sl28vpd_add_cells,
};
-
-static int __init sl28vpd_init(void)
-{
- return nvmem_layout_register(&sl28vpd_layout);
-}
-
-static void __exit sl28vpd_exit(void)
-{
- nvmem_layout_unregister(&sl28vpd_layout);
-}
-
-module_init(sl28vpd_init);
-module_exit(sl28vpd_exit);
+module_nvmem_layout_driver(sl28vpd_layout);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michael Walle <[email protected]>");
--
2.25.1
From: Miquel Raynal <[email protected]>
Provide a module_nvmem_layout_driver() macro at the end of the
nvmem-provider.h header to reduce the boilerplate when registering nvmem
layout drivers.
Suggested-by: Srinivas Kandagatla <[email protected]>
Signed-off-by: Miquel Raynal <[email protected]>
Acked-by: Rafał Miłecki <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
include/linux/nvmem-provider.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 8ffb42ba0f62..dae26295e6be 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -9,6 +9,7 @@
#ifndef _LINUX_NVMEM_PROVIDER_H
#define _LINUX_NVMEM_PROVIDER_H
+#include <linux/device/driver.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/gpio/consumer.h>
@@ -242,4 +243,9 @@ nvmem_layout_get_match_data(struct nvmem_device *nvmem,
}
#endif /* CONFIG_NVMEM */
+
+#define module_nvmem_layout_driver(__layout_driver) \
+ module_driver(__layout_driver, nvmem_layout_register, \
+ nvmem_layout_unregister)
+
#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
--
2.25.1
From: Miquel Raynal <[email protected]>
Stop open-coding the module init/exit functions. Use the
module_nvmem_layout_driver() instead.
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/layouts/onie-tlv.c | 14 +-------------
1 file changed, 1 insertion(+), 13 deletions(-)
diff --git a/drivers/nvmem/layouts/onie-tlv.c b/drivers/nvmem/layouts/onie-tlv.c
index d45b7301a69d..661093de33b4 100644
--- a/drivers/nvmem/layouts/onie-tlv.c
+++ b/drivers/nvmem/layouts/onie-tlv.c
@@ -237,19 +237,7 @@ static struct nvmem_layout onie_tlv_layout = {
.of_match_table = onie_tlv_of_match_table,
.add_cells = onie_tlv_parse_table,
};
-
-static int __init onie_tlv_init(void)
-{
- return nvmem_layout_register(&onie_tlv_layout);
-}
-
-static void __exit onie_tlv_exit(void)
-{
- nvmem_layout_unregister(&onie_tlv_layout);
-}
-
-module_init(onie_tlv_init);
-module_exit(onie_tlv_exit);
+module_nvmem_layout_driver(onie_tlv_layout);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Miquel Raynal <[email protected]>");
--
2.25.1
From: Rafał Miłecki <[email protected]>
Callback .read_post_process() is designed to modify raw cell content
before providing it to the consumer. So far we were dealing with
modifications that didn't affect cell size (length). In some cases
however cell content needs to be reformatted and resized.
It's required e.g. to provide properly formatted MAC address in case
it's stored in a non-binary format (e.g. using ASCII).
There were few discussions how to optimally handle that. Following
possible solutions were considered:
1. Allow .read_post_process() to realloc (resize) content buffer
2. Allow .read_post_process() to adjust (decrease) just buffer length
3. Register NVMEM cells using post-read sizes
The preferred solution was the last one. The problem is that simply
adjusting "bytes" in NVMEM providers would result in core code NOT
passing whole raw data to .read_post_process() callbacks. It means
callback functions couldn't do their job without somehow manually
reading original cell content on their own.
This patch deals with that by registering NVMEM cells with both lengths:
raw content one and post read one. It allows:
1. Core code to read whole raw cell content
2. Callbacks to return content they want
Signed-off-by: Rafał Miłecki <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/core.c | 11 +++++++----
include/linux/nvmem-provider.h | 2 ++
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 212c5ba5789f..a62973d010ff 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -50,6 +50,7 @@ struct nvmem_device {
struct nvmem_cell_entry {
const char *name;
int offset;
+ size_t raw_len;
int bytes;
int bit_offset;
int nbits;
@@ -469,6 +470,7 @@ static int nvmem_cell_info_to_nvmem_cell_entry_nodup(struct nvmem_device *nvmem,
{
cell->nvmem = nvmem;
cell->offset = info->offset;
+ cell->raw_len = info->raw_len ?: info->bytes;
cell->bytes = info->bytes;
cell->name = info->name;
cell->read_post_process = info->read_post_process;
@@ -1560,7 +1562,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
{
int rc;
- rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->bytes);
+ rc = nvmem_reg_read(nvmem, cell->offset, buf, cell->raw_len);
if (rc)
return rc;
@@ -1571,7 +1573,7 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
if (cell->read_post_process) {
rc = cell->read_post_process(cell->priv, id, index,
- cell->offset, buf, cell->bytes);
+ cell->offset, buf, cell->raw_len);
if (rc)
return rc;
}
@@ -1594,14 +1596,15 @@ static int __nvmem_cell_read(struct nvmem_device *nvmem,
*/
void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
{
- struct nvmem_device *nvmem = cell->entry->nvmem;
+ struct nvmem_cell_entry *entry = cell->entry;
+ struct nvmem_device *nvmem = entry->nvmem;
u8 *buf;
int rc;
if (!nvmem)
return ERR_PTR(-EINVAL);
- buf = kzalloc(cell->entry->bytes, GFP_KERNEL);
+ buf = kzalloc(max_t(size_t, entry->raw_len, entry->bytes), GFP_KERNEL);
if (!buf)
return ERR_PTR(-ENOMEM);
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 0cf9f9490514..8ffb42ba0f62 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -51,6 +51,7 @@ struct nvmem_keepout {
* struct nvmem_cell_info - NVMEM cell description
* @name: Name.
* @offset: Offset within the NVMEM device.
+ * @raw_len: Length of raw data (without post processing).
* @bytes: Length of the cell.
* @bit_offset: Bit offset if cell is smaller than a byte.
* @nbits: Number of bits.
@@ -62,6 +63,7 @@ struct nvmem_keepout {
struct nvmem_cell_info {
const char *name;
unsigned int offset;
+ size_t raw_len;
unsigned int bytes;
unsigned int bit_offset;
unsigned int nbits;
--
2.25.1
From: Miquel Raynal <[email protected]>
The MODULE_ALIAS macro is misused here as it carries the
description. There is currently no relevant alias to provide so let's
just drop it.
Signed-off-by: Miquel Raynal <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/layouts/onie-tlv.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/nvmem/layouts/onie-tlv.c b/drivers/nvmem/layouts/onie-tlv.c
index 661093de33b4..59fc87ccfcff 100644
--- a/drivers/nvmem/layouts/onie-tlv.c
+++ b/drivers/nvmem/layouts/onie-tlv.c
@@ -242,4 +242,3 @@ module_nvmem_layout_driver(onie_tlv_layout);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Miquel Raynal <[email protected]>");
MODULE_DESCRIPTION("NVMEM layout driver for Onie TLV table parsing");
-MODULE_ALIAS("NVMEM layout driver for Onie TLV table parsing");
--
2.25.1
From: Tom Rix <[email protected]>
smatch reports
drivers/nvmem/layouts/sl28vpd.c:144:21: warning: symbol
'sl28vpd_layout' was not declared. Should it be static?
This variable is only used in one file so it should be static.
Signed-off-by: Tom Rix <[email protected]>
Signed-off-by: Srinivas Kandagatla <[email protected]>
---
drivers/nvmem/layouts/sl28vpd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/nvmem/layouts/sl28vpd.c b/drivers/nvmem/layouts/sl28vpd.c
index 9cc1715c2fd5..05671371f631 100644
--- a/drivers/nvmem/layouts/sl28vpd.c
+++ b/drivers/nvmem/layouts/sl28vpd.c
@@ -141,7 +141,7 @@ static const struct of_device_id sl28vpd_of_match_table[] = {
};
MODULE_DEVICE_TABLE(of, sl28vpd_of_match_table);
-struct nvmem_layout sl28vpd_layout = {
+static struct nvmem_layout sl28vpd_layout = {
.name = "sl28-vpd",
.of_match_table = sl28vpd_of_match_table,
.add_cells = sl28vpd_add_cells,
--
2.25.1
Dne torek, 04. april 2023 ob 19:21:33 CEST je Srinivas Kandagatla napisal(a):
> From: Rob Herring <[email protected]>
>
> Cleanup bindings dropping unneeded quotes. Once all these are fixed,
> checking for this can be enabled in yamllint.
>
> Signed-off-by: Rob Herring <[email protected]>
> Acked-by: Jernej Skrabec <[email protected]>
> Reviewed-by: Krzysztof Kozlowski <[email protected]>
> Signed-off-by: Srinivas Kandagatla <[email protected]>
> ---
> .../devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml | 2 +-
For Allwinner:
Acked-By: Jernej Skrabec <[email protected]>
Best regards,
Jernej
> Documentation/devicetree/bindings/nvmem/apple,efuses.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/brcm,nvram.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/imx-iim.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/imx-ocotp.yaml | 2 +-
> .../devicetree/bindings/nvmem/ingenic,jz4780-efuse.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/mediatek,efuse.yaml | 2 +-
> .../devicetree/bindings/nvmem/microchip,sama7g5-otpc.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/mxs-ocotp.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/nintendo-otp.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/qcom,qfprom.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/qcom,spmi-sdam.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/rmem.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/rockchip-efuse.yaml | 2 +-
> .../devicetree/bindings/nvmem/socionext,uniphier-efuse.yaml | 2 +-
> Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml | 2 +-
> .../devicetree/bindings/nvmem/sunplus,sp7021-ocotp.yaml | 2 +-
> 18 files changed, 18 insertions(+), 18 deletions(-)
Hi,
On Tue, Apr 04, 2023 at 06:21:16PM +0100, Srinivas Kandagatla wrote:
> From: Miquel Raynal <[email protected]>
>
> This helper does not produce a real modalias, but tries to get the
> "product" compatible part of the "vendor,product" compatibles only. It
> is far from creating a purely useful modalias string and does not seem
> to be used like that directly anyway, so let's try to give this helper a
> more meaningful name before moving there a real modalias helper (already
> existing under of/device.c).
>
> Also update the various documentations to refer to the strings as
> "aliases" rather than "modaliases" which has a real meaning in the Linux
> kernel.
>
> There is no functional change.
>
> Cc: Rafael J. Wysocki <[email protected]>
> Cc: Len Brown <[email protected]>
> Cc: Maarten Lankhorst <[email protected]>
> Cc: Maxime Ripard <[email protected]>
> Cc: Thomas Zimmermann <[email protected]>
> Cc: Sebastian Reichel <[email protected]>
> Cc: Wolfram Sang <[email protected]>
> Cc: Mark Brown <[email protected]>
> Signed-off-by: Miquel Raynal <[email protected]>
> Reviewed-by: Rob Herring <[email protected]>
> Acked-by: Mark Brown <[email protected]>
Acked-by: Sebastian Reichel <[email protected]>
-- Sebastian
> Signed-off-by: Srinivas Kandagatla <[email protected]>
> ---
> drivers/acpi/bus.c | 7 ++++---
> drivers/gpu/drm/drm_mipi_dsi.c | 2 +-
> drivers/hsi/hsi_core.c | 2 +-
> drivers/i2c/busses/i2c-powermac.c | 2 +-
> drivers/i2c/i2c-core-of.c | 2 +-
> drivers/of/base.c | 18 +++++++++++-------
> drivers/spi/spi.c | 4 ++--
> include/linux/of.h | 3 ++-
> 8 files changed, 23 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
> index 9531dd0fef50..fc74c786a867 100644
> --- a/drivers/acpi/bus.c
> +++ b/drivers/acpi/bus.c
> @@ -817,9 +817,10 @@ static bool acpi_of_modalias(struct acpi_device *adev,
> * @modalias: Pointer to buffer that modalias value will be copied into
> * @len: Length of modalias buffer
> *
> - * This is a counterpart of of_modalias_node() for struct acpi_device objects.
> - * If there is a compatible string for @adev, it will be copied to @modalias
> - * with the vendor prefix stripped; otherwise, @default_id will be used.
> + * This is a counterpart of of_alias_from_compatible() for struct acpi_device
> + * objects. If there is a compatible string for @adev, it will be copied to
> + * @modalias with the vendor prefix stripped; otherwise, @default_id will be
> + * used.
> */
> void acpi_set_modalias(struct acpi_device *adev, const char *default_id,
> char *modalias, size_t len)
> diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
> index b41aaf2bb9f1..b62f5e4425f4 100644
> --- a/drivers/gpu/drm/drm_mipi_dsi.c
> +++ b/drivers/gpu/drm/drm_mipi_dsi.c
> @@ -160,7 +160,7 @@ of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
> int ret;
> u32 reg;
>
> - if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
> + if (of_alias_from_compatible(node, info.type, sizeof(info.type)) < 0) {
> drm_err(host, "modalias failure on %pOF\n", node);
> return ERR_PTR(-EINVAL);
> }
> diff --git a/drivers/hsi/hsi_core.c b/drivers/hsi/hsi_core.c
> index 8fda8f1d064d..acbf82f755a8 100644
> --- a/drivers/hsi/hsi_core.c
> +++ b/drivers/hsi/hsi_core.c
> @@ -207,7 +207,7 @@ static void hsi_add_client_from_dt(struct hsi_port *port,
> if (!cl)
> return;
>
> - err = of_modalias_node(client, name, sizeof(name));
> + err = of_alias_from_compatible(client, name, sizeof(name));
> if (err)
> goto err;
>
> diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
> index 2e74747eec9c..ec706a3aba26 100644
> --- a/drivers/i2c/busses/i2c-powermac.c
> +++ b/drivers/i2c/busses/i2c-powermac.c
> @@ -284,7 +284,7 @@ static bool i2c_powermac_get_type(struct i2c_adapter *adap,
> */
>
> /* First try proper modalias */
> - if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
> + if (of_alias_from_compatible(node, tmp, sizeof(tmp)) >= 0) {
> snprintf(type, type_size, "MAC,%s", tmp);
> return true;
> }
> diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c
> index bce6b796e04c..8941a30574e3 100644
> --- a/drivers/i2c/i2c-core-of.c
> +++ b/drivers/i2c/i2c-core-of.c
> @@ -27,7 +27,7 @@ int of_i2c_get_board_info(struct device *dev, struct device_node *node,
>
> memset(info, 0, sizeof(*info));
>
> - if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
> + if (of_alias_from_compatible(node, info->type, sizeof(info->type)) < 0) {
> dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
> return -EINVAL;
> }
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index ac6fde53342f..161fe3192c46 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -1208,19 +1208,23 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
> EXPORT_SYMBOL(of_find_matching_node_and_match);
>
> /**
> - * of_modalias_node - Lookup appropriate modalias for a device node
> + * of_alias_from_compatible - Lookup appropriate alias for a device node
> + * depending on compatible
> * @node: pointer to a device tree node
> - * @modalias: Pointer to buffer that modalias value will be copied into
> - * @len: Length of modalias value
> + * @alias: Pointer to buffer that alias value will be copied into
> + * @len: Length of alias value
> *
> * Based on the value of the compatible property, this routine will attempt
> - * to choose an appropriate modalias value for a particular device tree node.
> + * to choose an appropriate alias value for a particular device tree node.
> * It does this by stripping the manufacturer prefix (as delimited by a ',')
> * from the first entry in the compatible list property.
> *
> + * Note: The matching on just the "product" side of the compatible is a relic
> + * from I2C and SPI. Please do not add any new user.
> + *
> * Return: This routine returns 0 on success, <0 on failure.
> */
> -int of_modalias_node(struct device_node *node, char *modalias, int len)
> +int of_alias_from_compatible(const struct device_node *node, char *alias, int len)
> {
> const char *compatible, *p;
> int cplen;
> @@ -1229,10 +1233,10 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
> if (!compatible || strlen(compatible) > cplen)
> return -ENODEV;
> p = strchr(compatible, ',');
> - strscpy(modalias, p ? p + 1 : compatible, len);
> + strscpy(alias, p ? p + 1 : compatible, len);
> return 0;
> }
> -EXPORT_SYMBOL_GPL(of_modalias_node);
> +EXPORT_SYMBOL_GPL(of_alias_from_compatible);
>
> /**
> * of_find_node_by_phandle - Find a node given a phandle
> diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
> index 44b85a8d47f1..3bbdc5fe3b99 100644
> --- a/drivers/spi/spi.c
> +++ b/drivers/spi/spi.c
> @@ -2354,8 +2354,8 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc)
> }
>
> /* Select device driver */
> - rc = of_modalias_node(nc, spi->modalias,
> - sizeof(spi->modalias));
> + rc = of_alias_from_compatible(nc, spi->modalias,
> + sizeof(spi->modalias));
> if (rc < 0) {
> dev_err(&ctlr->dev, "cannot find modalias for %pOF\n", nc);
> goto err_out;
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 0af611307db2..b1eea8569043 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -373,7 +373,8 @@ extern int of_n_addr_cells(struct device_node *np);
> extern int of_n_size_cells(struct device_node *np);
> extern const struct of_device_id *of_match_node(
> const struct of_device_id *matches, const struct device_node *node);
> -extern int of_modalias_node(struct device_node *node, char *modalias, int len);
> +extern int of_alias_from_compatible(const struct device_node *node, char *alias,
> + int len);
> extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
> extern int __of_parse_phandle_with_args(const struct device_node *np,
> const char *list_name, const char *cells_name, int cell_count,
> --
> 2.25.1
>