bootcount-uclass.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2018 Theobroma Systems Design und Consulting GmbH
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <errno.h>
  8. #include <bootcount.h>
  9. #include <log.h>
  10. int dm_bootcount_get(struct udevice *dev, u32 *bootcount)
  11. {
  12. struct bootcount_ops *ops = bootcount_get_ops(dev);
  13. assert(ops);
  14. if (!ops->get)
  15. return -ENOSYS;
  16. return ops->get(dev, bootcount);
  17. }
  18. int dm_bootcount_set(struct udevice *dev, const u32 bootcount)
  19. {
  20. struct bootcount_ops *ops = bootcount_get_ops(dev);
  21. assert(ops);
  22. if (!ops->set)
  23. return -ENOSYS;
  24. return ops->set(dev, bootcount);
  25. }
  26. /* Now implement the generic default functions */
  27. void bootcount_store(ulong val)
  28. {
  29. struct udevice *dev = NULL;
  30. ofnode node;
  31. const char *propname = "u-boot,bootcount-device";
  32. int ret = -ENODEV;
  33. /*
  34. * If there's a preferred bootcount device selected by the user (by
  35. * setting '/chosen/u-boot,bootcount-device' in the DTS), try to use
  36. * it if available.
  37. */
  38. node = ofnode_get_chosen_node(propname);
  39. if (ofnode_valid(node))
  40. ret = uclass_get_device_by_ofnode(UCLASS_BOOTCOUNT, node, &dev);
  41. /* If there was no user-selected device, use the first available one */
  42. if (ret)
  43. ret = uclass_get_device(UCLASS_BOOTCOUNT, 0, &dev);
  44. if (dev)
  45. ret = dm_bootcount_set(dev, val);
  46. if (ret)
  47. pr_debug("%s: failed to store 0x%lx\n", __func__, val);
  48. }
  49. ulong bootcount_load(void)
  50. {
  51. struct udevice *dev = NULL;
  52. ofnode node;
  53. const char *propname = "u-boot,bootcount-device";
  54. int ret = -ENODEV;
  55. u32 val;
  56. /*
  57. * If there's a preferred bootcount device selected by the user (by
  58. * setting '/chosen/u-boot,bootcount-device' in the DTS), try to use
  59. * it if available.
  60. */
  61. node = ofnode_get_chosen_node(propname);
  62. if (ofnode_valid(node))
  63. ret = uclass_get_device_by_ofnode(UCLASS_BOOTCOUNT, node, &dev);
  64. /* If there was no user-selected device, use the first available one */
  65. if (ret)
  66. ret = uclass_get_device(UCLASS_BOOTCOUNT, 0, &dev);
  67. if (dev)
  68. ret = dm_bootcount_get(dev, &val);
  69. if (ret)
  70. pr_debug("%s: failed to load bootcount\n", __func__);
  71. /* Return the 0, if the call to dm_bootcount_get failed */
  72. return ret ? 0 : val;
  73. }
  74. UCLASS_DRIVER(bootcount) = {
  75. .name = "bootcount",
  76. .id = UCLASS_BOOTCOUNT,
  77. };