bootcounter: add DM support for memory based bootcounter

add DM/DTS support for the memory based bootcounter
in drivers/bootcount/bootcount.c.

Let the old implementation in, so boards which have
not yet convert to DM/DTS do not break.

Signed-off-by: Heiko Schocher <hs@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Heiko Schocher 2020-03-02 15:43:59 +01:00
parent 27d483bfa3
commit 80e8b8add0
4 changed files with 121 additions and 0 deletions

View File

@ -0,0 +1,21 @@
U-Boot bootcounter Devicetree Binding
=====================================
The device tree node describes the U-Boot bootcounter
memory based device binding.
Required properties :
- compatible : "u-boot,bootcount";
- single-word : set this, if you have only one word space
for storing the bootcounter.
Example
-------
MPC83xx based board:
bootcount@0x13ff8 {
compatible = "u-boot,bootcount";
reg = <0x13ff8 0x08>;
};

View File

@ -106,6 +106,13 @@ config DM_BOOTCOUNT_I2C_EEPROM
pointing to the underlying i2c eeprom device) and an optional 'offset' pointing to the underlying i2c eeprom device) and an optional 'offset'
property are supported. property are supported.
config BOOTCOUNT_MEM
bool "Support memory based bootcounter"
help
Enabling Memory based bootcount, typically in a SoC register which
is not cleared on softreset.
compatible = "u-boot,bootcount";
endmenu endmenu
endif endif

View File

@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0+ # SPDX-License-Identifier: GPL-2.0+
obj-$(CONFIG_BOOTCOUNT_GENERIC) += bootcount.o obj-$(CONFIG_BOOTCOUNT_GENERIC) += bootcount.o
obj-$(CONFIG_BOOTCOUNT_MEM) += bootcount.o
obj-$(CONFIG_BOOTCOUNT_AT91) += bootcount_at91.o obj-$(CONFIG_BOOTCOUNT_AT91) += bootcount_at91.o
obj-$(CONFIG_BOOTCOUNT_AM33XX) += bootcount_davinci.o obj-$(CONFIG_BOOTCOUNT_AM33XX) += bootcount_davinci.o
obj-$(CONFIG_BOOTCOUNT_RAM) += bootcount_ram.o obj-$(CONFIG_BOOTCOUNT_RAM) += bootcount_ram.o

View File

@ -8,6 +8,7 @@
#include <cpu_func.h> #include <cpu_func.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#if !defined(CONFIG_DM_BOOTCOUNT)
/* Now implement the generic default functions */ /* Now implement the generic default functions */
__weak void bootcount_store(ulong a) __weak void bootcount_store(ulong a)
{ {
@ -49,3 +50,94 @@ __weak ulong bootcount_load(void)
return raw_bootcount_load(reg); return raw_bootcount_load(reg);
#endif /* defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD) */ #endif /* defined(CONFIG_SYS_BOOTCOUNT_SINGLEWORD) */
} }
#else
#include <dm.h>
/*
* struct bootcount_mem_priv - private bootcount mem driver data
*
* @base: base address used for bootcounter
* @singleword: if true use only one 32 bit word for bootcounter
*/
struct bootcount_mem_priv {
phys_addr_t base;
bool singleword;
};
static int bootcount_mem_get(struct udevice *dev, u32 *a)
{
struct bootcount_mem_priv *priv = dev_get_priv(dev);
void *reg = (void *)priv->base;
u32 magic = CONFIG_SYS_BOOTCOUNT_MAGIC;
if (priv->singleword) {
u32 tmp = raw_bootcount_load(reg);
if ((tmp & 0xffff0000) != (magic & 0xffff0000))
return -ENODEV;
*a = (tmp & 0x0000ffff);
} else {
if (raw_bootcount_load(reg + 4) != magic)
return -ENODEV;
*a = raw_bootcount_load(reg);
}
return 0;
};
static int bootcount_mem_set(struct udevice *dev, const u32 a)
{
struct bootcount_mem_priv *priv = dev_get_priv(dev);
void *reg = (void *)priv->base;
u32 magic = CONFIG_SYS_BOOTCOUNT_MAGIC;
uintptr_t flush_start = rounddown(priv->base,
CONFIG_SYS_CACHELINE_SIZE);
uintptr_t flush_end;
if (priv->singleword) {
raw_bootcount_store(reg, (magic & 0xffff0000) | a);
flush_end = roundup(priv->base + 4,
CONFIG_SYS_CACHELINE_SIZE);
} else {
raw_bootcount_store(reg, a);
raw_bootcount_store(reg + 4, magic);
flush_end = roundup(priv->base + 8,
CONFIG_SYS_CACHELINE_SIZE);
}
flush_dcache_range(flush_start, flush_end);
return 0;
};
static const struct bootcount_ops bootcount_mem_ops = {
.get = bootcount_mem_get,
.set = bootcount_mem_set,
};
static int bootcount_mem_probe(struct udevice *dev)
{
struct bootcount_mem_priv *priv = dev_get_priv(dev);
priv->base = (phys_addr_t)dev_read_addr(dev);
if (dev_read_bool(dev, "single-word"))
priv->singleword = true;
return 0;
}
static const struct udevice_id bootcount_mem_ids[] = {
{ .compatible = "u-boot,bootcount" },
{ }
};
U_BOOT_DRIVER(bootcount_mem) = {
.name = "bootcount-mem",
.id = UCLASS_BOOTCOUNT,
.priv_auto_alloc_size = sizeof(struct bootcount_mem_priv),
.probe = bootcount_mem_probe,
.of_match = bootcount_mem_ids,
.ops = &bootcount_mem_ops,
};
#endif