"Das U-Boot" Source Tree
at master 102 lines 2.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * (C) Copyright 2023 4 * Philip Richard Oberfichtner <pro@denx.de> 5 * 6 * Based on previous work from Heiko Schocher (legacy bootcount_i2c.c driver) 7 */ 8 9#include <bootcount.h> 10#include <dm.h> 11#include <i2c.h> 12 13#define BC_MAGIC 0x55 14 15struct bootcount_i2c_priv { 16 struct udevice *bcdev; 17 unsigned int offset; 18}; 19 20static int bootcount_i2c_set(struct udevice *dev, const u32 val) 21{ 22 int ret; 23 struct bootcount_i2c_priv *priv = dev_get_priv(dev); 24 25 ret = dm_i2c_reg_write(priv->bcdev, priv->offset, BC_MAGIC); 26 if (ret < 0) 27 goto err_exit; 28 29 ret = dm_i2c_reg_write(priv->bcdev, priv->offset + 1, val & 0xff); 30 if (ret < 0) 31 goto err_exit; 32 33 return 0; 34 35err_exit: 36 log_debug("%s: Error writing to I2C device (%d)\n", __func__, ret); 37 return ret; 38} 39 40static int bootcount_i2c_get(struct udevice *dev, u32 *val) 41{ 42 int ret; 43 struct bootcount_i2c_priv *priv = dev_get_priv(dev); 44 45 ret = dm_i2c_reg_read(priv->bcdev, priv->offset); 46 if (ret < 0) 47 goto err_exit; 48 49 if ((ret & 0xff) != BC_MAGIC) { 50 log_debug("%s: Invalid Magic, reset bootcounter.\n", __func__); 51 *val = 0; 52 return bootcount_i2c_set(dev, 0); 53 } 54 55 ret = dm_i2c_reg_read(priv->bcdev, priv->offset + 1); 56 if (ret < 0) 57 goto err_exit; 58 59 *val = ret; 60 return 0; 61 62err_exit: 63 log_debug("%s: Error reading from I2C device (%d)\n", __func__, ret); 64 return ret; 65} 66 67static int bootcount_i2c_probe(struct udevice *dev) 68{ 69 struct bootcount_i2c_priv *priv = dev_get_priv(dev); 70 int ret; 71 72 ret = dev_read_u32(dev, "offset", &priv->offset); 73 if (ret) 74 goto exit; 75 76 ret = i2c_get_chip_by_phandle(dev, "i2cbcdev", &priv->bcdev); 77 78exit: 79 if (ret) 80 log_debug("%s failed, ret = %d\n", __func__, ret); 81 82 return ret; 83} 84 85static const struct bootcount_ops bootcount_i2c_ops = { 86 .get = bootcount_i2c_get, 87 .set = bootcount_i2c_set, 88}; 89 90static const struct udevice_id bootcount_i2c_ids[] = { 91 { .compatible = "u-boot,bootcount-i2c" }, 92 { } 93}; 94 95U_BOOT_DRIVER(bootcount_i2c) = { 96 .name = "bootcount-i2c", 97 .id = UCLASS_BOOTCOUNT, 98 .priv_auto = sizeof(struct bootcount_i2c_priv), 99 .probe = bootcount_i2c_probe, 100 .of_match = bootcount_i2c_ids, 101 .ops = &bootcount_i2c_ops, 102};