blob: 5a369c82f1c5e22d48aa7e498e0d5af38bf12a47 [file] [log] [blame]
Philipp Tomsichce860312018-11-27 23:00:18 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2018 Theobroma Systems Design und Consulting GmbH
4 */
5
Patrick Delaunay81313352021-04-27 11:02:19 +02006#define LOG_CATEGORY UCLASS_BOOTCOUNT
7
Philipp Tomsichce860312018-11-27 23:00:18 +01008#include <common.h>
9#include <dm.h>
10#include <errno.h>
11#include <bootcount.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060013#include <linux/printk.h>
Philipp Tomsichce860312018-11-27 23:00:18 +010014
15int dm_bootcount_get(struct udevice *dev, u32 *bootcount)
16{
17 struct bootcount_ops *ops = bootcount_get_ops(dev);
18
19 assert(ops);
20 if (!ops->get)
21 return -ENOSYS;
22 return ops->get(dev, bootcount);
23}
24
25int dm_bootcount_set(struct udevice *dev, const u32 bootcount)
26{
27 struct bootcount_ops *ops = bootcount_get_ops(dev);
28
29 assert(ops);
30 if (!ops->set)
31 return -ENOSYS;
32 return ops->set(dev, bootcount);
33}
34
35/* Now implement the generic default functions */
36void bootcount_store(ulong val)
37{
38 struct udevice *dev = NULL;
39 ofnode node;
40 const char *propname = "u-boot,bootcount-device";
41 int ret = -ENODEV;
42
43 /*
44 * If there's a preferred bootcount device selected by the user (by
45 * setting '/chosen/u-boot,bootcount-device' in the DTS), try to use
46 * it if available.
47 */
48 node = ofnode_get_chosen_node(propname);
49 if (ofnode_valid(node))
50 ret = uclass_get_device_by_ofnode(UCLASS_BOOTCOUNT, node, &dev);
51
52 /* If there was no user-selected device, use the first available one */
53 if (ret)
54 ret = uclass_get_device(UCLASS_BOOTCOUNT, 0, &dev);
55
56 if (dev)
57 ret = dm_bootcount_set(dev, val);
58
59 if (ret)
60 pr_debug("%s: failed to store 0x%lx\n", __func__, val);
61}
62
63ulong bootcount_load(void)
64{
65 struct udevice *dev = NULL;
66 ofnode node;
67 const char *propname = "u-boot,bootcount-device";
68 int ret = -ENODEV;
69 u32 val;
70
71 /*
72 * If there's a preferred bootcount device selected by the user (by
73 * setting '/chosen/u-boot,bootcount-device' in the DTS), try to use
74 * it if available.
75 */
76 node = ofnode_get_chosen_node(propname);
77 if (ofnode_valid(node))
78 ret = uclass_get_device_by_ofnode(UCLASS_BOOTCOUNT, node, &dev);
79
80 /* If there was no user-selected device, use the first available one */
81 if (ret)
82 ret = uclass_get_device(UCLASS_BOOTCOUNT, 0, &dev);
83
84 if (dev)
85 ret = dm_bootcount_get(dev, &val);
86
87 if (ret)
88 pr_debug("%s: failed to load bootcount\n", __func__);
89
90 /* Return the 0, if the call to dm_bootcount_get failed */
91 return ret ? 0 : val;
92}
93
94UCLASS_DRIVER(bootcount) = {
95 .name = "bootcount",
96 .id = UCLASS_BOOTCOUNT,
97};