Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

power: reset: nvmem-reboot-mode: use NVMEM as reboot mode write interface

Add a new reboot mode write interface that is using an NVMEM cell
to store the reboot mode magic.

Signed-off-by: Nandor Han <nandor.han@vaisala.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

authored by

Han Nandor and committed by
Sebastian Reichel
7a78a7f7 cba155e5

+86
+9
drivers/power/reset/Kconfig
··· 245 245 PMICs includes the SC2720, SC2721, SC2723, SC2730 246 246 and SC2731 chips. 247 247 248 + config NVMEM_REBOOT_MODE 249 + tristate "Generic NVMEM reboot mode driver" 250 + select REBOOT_MODE 251 + help 252 + Say y here will enable reboot mode driver. This will 253 + get reboot mode arguments and store it in a NVMEM cell, 254 + then the bootloader can read it and take different 255 + action according to the mode. 256 + 248 257 endif 249 258
+1
drivers/power/reset/Makefile
··· 29 29 obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o 30 30 obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o 31 31 obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o 32 + obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
+76
drivers/power/reset/nvmem-reboot-mode.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (c) Vaisala Oyj. All rights reserved. 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/module.h> 8 + #include <linux/kernel.h> 9 + #include <linux/of.h> 10 + #include <linux/nvmem-consumer.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/reboot-mode.h> 13 + 14 + struct nvmem_reboot_mode { 15 + struct reboot_mode_driver reboot; 16 + struct nvmem_cell *cell; 17 + }; 18 + 19 + static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot, 20 + unsigned int magic) 21 + { 22 + int ret; 23 + struct nvmem_reboot_mode *nvmem_rbm; 24 + 25 + nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot); 26 + 27 + ret = nvmem_cell_write(nvmem_rbm->cell, &magic, sizeof(magic)); 28 + if (ret < 0) 29 + dev_err(reboot->dev, "update reboot mode bits failed\n"); 30 + 31 + return ret; 32 + } 33 + 34 + static int nvmem_reboot_mode_probe(struct platform_device *pdev) 35 + { 36 + int ret; 37 + struct nvmem_reboot_mode *nvmem_rbm; 38 + 39 + nvmem_rbm = devm_kzalloc(&pdev->dev, sizeof(*nvmem_rbm), GFP_KERNEL); 40 + if (!nvmem_rbm) 41 + return -ENOMEM; 42 + 43 + nvmem_rbm->reboot.dev = &pdev->dev; 44 + nvmem_rbm->reboot.write = nvmem_reboot_mode_write; 45 + 46 + nvmem_rbm->cell = devm_nvmem_cell_get(&pdev->dev, "reboot-mode"); 47 + if (IS_ERR(nvmem_rbm->cell)) { 48 + dev_err(&pdev->dev, "failed to get the nvmem cell reboot-mode\n"); 49 + return PTR_ERR(nvmem_rbm->cell); 50 + } 51 + 52 + ret = devm_reboot_mode_register(&pdev->dev, &nvmem_rbm->reboot); 53 + if (ret) 54 + dev_err(&pdev->dev, "can't register reboot mode\n"); 55 + 56 + return ret; 57 + } 58 + 59 + static const struct of_device_id nvmem_reboot_mode_of_match[] = { 60 + { .compatible = "nvmem-reboot-mode" }, 61 + {} 62 + }; 63 + MODULE_DEVICE_TABLE(of, nvmem_reboot_mode_of_match); 64 + 65 + static struct platform_driver nvmem_reboot_mode_driver = { 66 + .probe = nvmem_reboot_mode_probe, 67 + .driver = { 68 + .name = "nvmem-reboot-mode", 69 + .of_match_table = nvmem_reboot_mode_of_match, 70 + }, 71 + }; 72 + module_platform_driver(nvmem_reboot_mode_driver); 73 + 74 + MODULE_AUTHOR("Nandor Han <nandor.han@vaisala.com>"); 75 + MODULE_DESCRIPTION("NVMEM reboot mode driver"); 76 + MODULE_LICENSE("GPL");