mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-23 12:14:32 +08:00
bootcount: Add driver model I2C driver
This adds a generic I2C bootcounter adhering to driver model to replace the previously removed legacy implementation. There is no change in functionality, it can be used on any I2C device. The device tree configuration may look like this for example: bootcount { compatible = "u-boot,bootcount-i2c"; i2cbcdev = <&i2c_rtc>; offset = <0x11>; }; Signed-off-by: Philip Richard Oberfichtner <pro@denx.de> Reviewed-by: Heiko Schocher <hs@denx.de>
This commit is contained in:
parent
b483552773
commit
5b6ee512ce
@ -109,6 +109,16 @@ config DM_BOOTCOUNT_RTC
|
||||
Accesses to the backing store are performed using the write16
|
||||
and read16 ops of DM RTC devices.
|
||||
|
||||
config DM_BOOTCOUNT_I2C
|
||||
bool "Driver Model boot counter on I2C device"
|
||||
depends on DM_I2C
|
||||
help
|
||||
Enable support for the bootcounter on a generic i2c device, like a RTC
|
||||
or PMIC. The bootcounter is configured in the device tree using the
|
||||
"u-boot,bootcount-i2c" compatible string. It requires a phandle
|
||||
'i2cbcdev' for the i2c device and an 'offset' property used within the
|
||||
device.
|
||||
|
||||
config DM_BOOTCOUNT_I2C_EEPROM
|
||||
bool "Support i2c eeprom devices as a backing store for bootcount"
|
||||
depends on I2C_EEPROM
|
||||
|
@ -13,5 +13,6 @@ obj-$(CONFIG_DM_BOOTCOUNT) += bootcount-uclass.o
|
||||
obj-$(CONFIG_DM_BOOTCOUNT_PMIC_PFUZE100) += pmic_pfuze100.o
|
||||
obj-$(CONFIG_DM_BOOTCOUNT_RTC) += rtc.o
|
||||
obj-$(CONFIG_DM_BOOTCOUNT_I2C_EEPROM) += i2c-eeprom.o
|
||||
obj-$(CONFIG_DM_BOOTCOUNT_I2C) += bootcount_dm_i2c.o
|
||||
obj-$(CONFIG_DM_BOOTCOUNT_SPI_FLASH) += spi-flash.o
|
||||
obj-$(CONFIG_DM_BOOTCOUNT_SYSCON) += bootcount_syscon.o
|
||||
|
102
drivers/bootcount/bootcount_dm_i2c.c
Normal file
102
drivers/bootcount/bootcount_dm_i2c.c
Normal file
@ -0,0 +1,102 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2023
|
||||
* Philip Richard Oberfichtner <pro@denx.de>
|
||||
*
|
||||
* Based on previous work from Heiko Schocher (legacy bootcount_i2c.c driver)
|
||||
*/
|
||||
|
||||
#include <bootcount.h>
|
||||
#include <dm.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#define BC_MAGIC 0x55
|
||||
|
||||
struct bootcount_i2c_priv {
|
||||
struct udevice *bcdev;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
static int bootcount_i2c_set(struct udevice *dev, const u32 val)
|
||||
{
|
||||
int ret;
|
||||
struct bootcount_i2c_priv *priv = dev_get_priv(dev);
|
||||
|
||||
ret = dm_i2c_reg_write(priv->bcdev, priv->offset, BC_MAGIC);
|
||||
if (ret < 0)
|
||||
goto err_exit;
|
||||
|
||||
ret = dm_i2c_reg_write(priv->bcdev, priv->offset + 1, val & 0xff);
|
||||
if (ret < 0)
|
||||
goto err_exit;
|
||||
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
log_debug("%s: Error writing to I2C device (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bootcount_i2c_get(struct udevice *dev, u32 *val)
|
||||
{
|
||||
int ret;
|
||||
struct bootcount_i2c_priv *priv = dev_get_priv(dev);
|
||||
|
||||
ret = dm_i2c_reg_read(priv->bcdev, priv->offset);
|
||||
if (ret < 0)
|
||||
goto err_exit;
|
||||
|
||||
if ((ret & 0xff) != BC_MAGIC) {
|
||||
log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__);
|
||||
*val = 0;
|
||||
return bootcount_i2c_set(dev, 0);
|
||||
}
|
||||
|
||||
ret = dm_i2c_reg_read(priv->bcdev, priv->offset + 1);
|
||||
if (ret < 0)
|
||||
goto err_exit;
|
||||
|
||||
*val = ret;
|
||||
return 0;
|
||||
|
||||
err_exit:
|
||||
log_debug("%s: Error reading from I2C device (%d)\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bootcount_i2c_probe(struct udevice *dev)
|
||||
{
|
||||
struct bootcount_i2c_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = dev_read_u32(dev, "offset", &priv->offset);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
ret = i2c_get_chip_by_phandle(dev, "i2cbcdev", &priv->bcdev);
|
||||
|
||||
exit:
|
||||
if (ret)
|
||||
log_debug("%s failed, ret = %d\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct bootcount_ops bootcount_i2c_ops = {
|
||||
.get = bootcount_i2c_get,
|
||||
.set = bootcount_i2c_set,
|
||||
};
|
||||
|
||||
static const struct udevice_id bootcount_i2c_ids[] = {
|
||||
{ .compatible = "u-boot,bootcount-i2c" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(bootcount_i2c) = {
|
||||
.name = "bootcount-i2c",
|
||||
.id = UCLASS_BOOTCOUNT,
|
||||
.priv_auto = sizeof(struct bootcount_i2c_priv),
|
||||
.probe = bootcount_i2c_probe,
|
||||
.of_match = bootcount_i2c_ids,
|
||||
.ops = &bootcount_i2c_ops,
|
||||
};
|
Loading…
Reference in New Issue
Block a user