Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | /* * Copyright 2021 Google LLC * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT zephyr_bbram_emul #include <zephyr/drivers/bbram.h> #include <string.h> #include <zephyr/logging/log.h> LOG_MODULE_REGISTER(bbram, CONFIG_BBRAM_LOG_LEVEL); /** Device config */ struct bbram_emul_config { /** BBRAM size (Unit:bytes) */ int size; }; /** Device data */ struct bbram_emul_data { /** Memory */ uint8_t *data; /** Status register */ struct { /** True if BBRAM is in an invalid state */ uint8_t is_invalid : 1; /** True if BBRAM incurred a standby power failure */ uint8_t standby_failure : 1; /** True if BBRAM incurred a power failure */ uint8_t power_failure : 1; } status; }; int bbram_emul_set_invalid(const struct device *dev, bool is_invalid) { struct bbram_emul_data *data = dev->data; data->status.is_invalid = is_invalid; return 0; } int bbram_emul_set_standby_power_state(const struct device *dev, bool failure) { struct bbram_emul_data *data = dev->data; data->status.standby_failure = failure; return 0; } int bbram_emul_set_power_state(const struct device *dev, bool failure) { struct bbram_emul_data *data = dev->data; data->status.power_failure = failure; return 0; } static int bbram_emul_check_invalid(const struct device *dev) { struct bbram_emul_data *data = dev->data; bool is_invalid = data->status.is_invalid; data->status.is_invalid = false; return is_invalid; } static int bbram_emul_check_standby_power(const struct device *dev) { struct bbram_emul_data *data = dev->data; bool failure = data->status.standby_failure; data->status.standby_failure = false; return failure; } static int bbram_emul_check_power(const struct device *dev) { struct bbram_emul_data *data = dev->data; bool failure = data->status.power_failure; data->status.power_failure = false; return failure; } static int bbram_emul_get_size(const struct device *dev, size_t *size) { const struct bbram_emul_config *config = dev->config; *size = config->size; return 0; } static int bbram_emul_read(const struct device *dev, size_t offset, size_t size, uint8_t *data) { const struct bbram_emul_config *config = dev->config; struct bbram_emul_data *dev_data = dev->data; if (size < 1 || offset + size > config->size || bbram_emul_check_invalid(dev)) { return -EFAULT; } memcpy(data, dev_data->data + offset, size); return 0; } static int bbram_emul_write(const struct device *dev, size_t offset, size_t size, const uint8_t *data) { const struct bbram_emul_config *config = dev->config; struct bbram_emul_data *dev_data = dev->data; if (size < 1 || offset + size > config->size || bbram_emul_check_invalid(dev)) { return -EFAULT; } memcpy(dev_data->data + offset, data, size); return 0; } static const struct bbram_driver_api bbram_emul_driver_api = { .check_invalid = bbram_emul_check_invalid, .check_standby_power = bbram_emul_check_standby_power, .check_power = bbram_emul_check_power, .get_size = bbram_emul_get_size, .read = bbram_emul_read, .write = bbram_emul_write, }; static int bbram_emul_init(const struct device *dev) { return 0; } #define BBRAM_INIT(inst) \ static uint8_t bbram_emul_mem_##inst[DT_INST_PROP(inst, size)]; \ static struct bbram_emul_data bbram_emul_data_##inst = { \ .data = bbram_emul_mem_##inst, \ }; \ static struct bbram_emul_config bbram_emul_config_##inst = { \ .size = DT_INST_PROP(inst, size), \ }; \ DEVICE_DT_INST_DEFINE(inst, &bbram_emul_init, NULL, &bbram_emul_data_##inst, \ &bbram_emul_config_##inst, PRE_KERNEL_1, CONFIG_BBRAM_INIT_PRIORITY, \ &bbram_emul_driver_api); DT_INST_FOREACH_STATUS_OKAY(BBRAM_INIT); |