nvmem-reboot-mode.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) Vaisala Oyj. All rights reserved.
  4. */
  5. #include <linux/init.h>
  6. #include <linux/module.h>
  7. #include <linux/kernel.h>
  8. #include <linux/of.h>
  9. #include <linux/nvmem-consumer.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/reboot-mode.h>
  12. #include <linux/slab.h>
  13. struct nvmem_reboot_mode {
  14. struct reboot_mode_driver reboot;
  15. struct nvmem_cell *cell;
  16. };
  17. static int nvmem_reboot_mode_write(struct reboot_mode_driver *reboot,
  18. unsigned int magic)
  19. {
  20. struct nvmem_reboot_mode *nvmem_rbm;
  21. size_t buf_len;
  22. void *buf;
  23. int ret;
  24. nvmem_rbm = container_of(reboot, struct nvmem_reboot_mode, reboot);
  25. buf = nvmem_cell_read(nvmem_rbm->cell, &buf_len);
  26. if (IS_ERR(buf))
  27. return PTR_ERR(buf);
  28. kfree(buf);
  29. if (buf_len > sizeof(magic))
  30. return -EINVAL;
  31. ret = nvmem_cell_write(nvmem_rbm->cell, &magic, buf_len);
  32. if (ret < 0)
  33. dev_err(reboot->dev, "update reboot mode bits failed\n");
  34. return ret;
  35. }
  36. static int nvmem_reboot_mode_probe(struct platform_device *pdev)
  37. {
  38. int ret;
  39. struct nvmem_reboot_mode *nvmem_rbm;
  40. nvmem_rbm = devm_kzalloc(&pdev->dev, sizeof(*nvmem_rbm), GFP_KERNEL);
  41. if (!nvmem_rbm)
  42. return -ENOMEM;
  43. nvmem_rbm->reboot.dev = &pdev->dev;
  44. nvmem_rbm->reboot.write = nvmem_reboot_mode_write;
  45. nvmem_rbm->cell = devm_nvmem_cell_get(&pdev->dev, "reboot-mode");
  46. if (IS_ERR(nvmem_rbm->cell)) {
  47. return dev_err_probe(&pdev->dev, PTR_ERR(nvmem_rbm->cell),
  48. "failed to get the nvmem cell reboot-mode\n");
  49. }
  50. ret = devm_reboot_mode_register(&pdev->dev, &nvmem_rbm->reboot);
  51. if (ret)
  52. dev_err(&pdev->dev, "can't register reboot mode\n");
  53. return ret;
  54. }
  55. static const struct of_device_id nvmem_reboot_mode_of_match[] = {
  56. { .compatible = "nvmem-reboot-mode" },
  57. {}
  58. };
  59. MODULE_DEVICE_TABLE(of, nvmem_reboot_mode_of_match);
  60. static struct platform_driver nvmem_reboot_mode_driver = {
  61. .probe = nvmem_reboot_mode_probe,
  62. .driver = {
  63. .name = "nvmem-reboot-mode",
  64. .of_match_table = nvmem_reboot_mode_of_match,
  65. },
  66. };
  67. module_platform_driver(nvmem_reboot_mode_driver);
  68. MODULE_AUTHOR("Nandor Han <nandor.han@vaisala.com>");
  69. MODULE_DESCRIPTION("NVMEM reboot mode driver");
  70. MODULE_LICENSE("GPL");