lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 19 Jan 2024 14:25:19 +0100
From: Oleksij Rempel <o.rempel@...gutronix.de>
To: Sebastian Reichel <sre@...nel.org>,
	Rob Herring <robh+dt@...nel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
	Conor Dooley <conor+dt@...nel.org>,
	Srinivas Kandagatla <srinivas.kandagatla@...aro.org>
Cc: Oleksij Rempel <o.rempel@...gutronix.de>,
	kernel@...gutronix.de,
	linux-kernel@...r.kernel.org,
	Liam Girdwood <lgirdwood@...il.com>,
	Mark Brown <broonie@...nel.org>,
	"Rafael J. Wysocki" <rafael@...nel.org>,
	Daniel Lezcano <daniel.lezcano@...aro.org>,
	Zhang Rui <rui.zhang@...el.com>,
	Lukasz Luba <lukasz.luba@....com>,
	linux-pm@...r.kernel.org,
	devicetree@...r.kernel.org,
	Søren Andersen <san@...v.dk>
Subject: [RFC PATCH v1 5/7] power: reset: add PSCR NVMEM Driver for Storing Power State Change Reasons

This driver utilizes the Power State Change Reasons (PSCR) framework to
store specific power state change information, such as shutdown or
reboot reasons, into a designated non-volatile memory (NVMEM) cell.

Signed-off-by: Oleksij Rempel <o.rempel@...gutronix.de>
---
 drivers/power/reset/Kconfig      |  11 ++++
 drivers/power/reset/Makefile     |   1 +
 drivers/power/reset/pscr-nvmem.c | 100 +++++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+)
 create mode 100644 drivers/power/reset/pscr-nvmem.c

diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index da76e84302b9..a110dff599af 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -324,3 +324,14 @@ menuconfig PSCR
       timeouts.
 
       If unsure, say N.
+
+if PSCR
+
+config PSCR_NVMEM
+	tristate "Generic NVMEM-based Power State Change Reason Tracking"
+	depends on OF
+	help
+	  Enabling this option adds support for storing power state change
+	  reasons in a NVMEM cell.
+
+endif
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index d9d744302c68..e7985d81ac8a 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_POWER_RESET_SYSCON) += syscon-reboot.o
 obj-$(CONFIG_POWER_RESET_SYSCON_POWEROFF) += syscon-poweroff.o
 obj-$(CONFIG_POWER_RESET_RMOBILE) += rmobile-reset.o
 obj-$(CONFIG_PSCR) += pscr.o
+obj-$(CONFIG_PSCR_NVMEM) += pscr-nvmem.o
 obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o
 obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
 obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
diff --git a/drivers/power/reset/pscr-nvmem.c b/drivers/power/reset/pscr-nvmem.c
new file mode 100644
index 000000000000..74048341b7d7
--- /dev/null
+++ b/drivers/power/reset/pscr-nvmem.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) Vaisala Oyj. All rights reserved.
+// Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@...gutronix.de>
+/*
+ * Based on drivers/power/reset/nvmem-reboot-mode.c
+ * Copyright (c) Vaisala Oyj. All rights reserved.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pscr.h>
+
+struct pscr_nvmem {
+	struct pscr_driver pscr_drv;
+	struct nvmem_cell *cell;
+	size_t max_magic_bytes;
+};
+
+static int pscr_nvmem_write(struct pscr_driver *pscr_drv, u32 magic)
+{
+	struct pscr_nvmem *priv = container_of(pscr_drv, struct pscr_nvmem,
+					       pscr_drv);
+	size_t size = min(priv->max_magic_bytes, sizeof(magic));
+	int ret;
+
+	ret = nvmem_cell_write(priv->cell, &magic, size);
+	if (ret < 0)
+		dev_err(pscr_drv->dev, "update reason bits failed: %pe\n",
+			ERR_PTR(ret));
+
+	return ret;
+}
+
+static int pscr_nvmem_probe(struct platform_device *pdev)
+{
+	const char *pscr = "pscr";
+	struct pscr_nvmem *priv;
+	size_t bytes, bits, magic_bits;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->pscr_drv.dev = &pdev->dev;
+	priv->pscr_drv.write = pscr_nvmem_write;
+
+	priv->cell = devm_nvmem_cell_get(&pdev->dev, pscr);
+	if (IS_ERR(priv->cell))
+		return dev_err_probe(&pdev->dev, PTR_ERR(priv->cell),
+				     "failed to get the nvmem %s cell\n", pscr);
+
+	ret = nvmem_cell_get_size(priv->cell, &bytes, &bits);
+	if (ret < 0)
+		return dev_err_probe(&pdev->dev, ret, "failed to get the nvmem %s size\n",
+				     pscr);
+
+	if (!bytes || bytes > sizeof(u32) || bits > 32)
+		return dev_err_probe(&pdev->dev, -EINVAL, "invalid nvmem %s size. bytes: %zu, bits: %zu\n",
+				     pscr, bytes, bits);
+
+	ret = devm_pscr_register(&pdev->dev, &priv->pscr_drv);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "failed to register pscr driver\n");
+
+	magic_bits = fls(priv->pscr_drv.max_magic);
+	priv->max_magic_bytes = DIV_ROUND_UP(magic_bits, 8);
+
+	if (!bits)
+		bits = bytes * 8;
+
+	if (magic_bits > bits)
+		return dev_err_probe(&pdev->dev, -EINVAL, "provided magic can't fit into nvmem %s. bytes: %zu, bits: %zu, magic_bits: %zu\n",
+				     pscr, bytes, bits, magic_bits); 
+
+	return ret;
+}
+
+static const struct of_device_id pscr_nvmem_of_match[] = {
+	{ .compatible = "pscr-nvmem" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, pscr_nvmem_of_match);
+
+static struct platform_driver pscr_nvmem_driver = {
+	.probe = pscr_nvmem_probe,
+	.driver = {
+		.name = "pscr-nvmem",
+		.of_match_table = pscr_nvmem_of_match,
+	},
+};
+module_platform_driver(pscr_nvmem_driver);
+
+MODULE_AUTHOR("Oleksij Rempel <o.rempel@...gutronix.de>");
+MODULE_DESCRIPTION("NVMEM Driver for Power State Change Reason Tracking");
+MODULE_LICENSE("GPL v2");
-- 
2.39.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ