diff options
Diffstat (limited to 'zephyr/emul')
-rw-r--r-- | zephyr/emul/CMakeLists.txt | 17 | ||||
-rw-r--r-- | zephyr/emul/Kconfig | 72 | ||||
-rw-r--r-- | zephyr/emul/Kconfig.i2c_mock | 22 | ||||
-rw-r--r-- | zephyr/emul/Kconfig.lis2dw12 | 23 | ||||
-rw-r--r-- | zephyr/emul/Kconfig.ln9310 | 22 | ||||
-rw-r--r-- | zephyr/emul/emul_bb_retimer.c | 365 | ||||
-rw-r--r-- | zephyr/emul/emul_bma255.c | 1042 | ||||
-rw-r--r-- | zephyr/emul/emul_bmi.c | 1116 | ||||
-rw-r--r-- | zephyr/emul/emul_bmi160.c | 770 | ||||
-rw-r--r-- | zephyr/emul/emul_bmi260.c | 571 | ||||
-rw-r--r-- | zephyr/emul/emul_common_i2c.c | 432 | ||||
-rw-r--r-- | zephyr/emul/emul_lis2dw12.c | 161 | ||||
-rw-r--r-- | zephyr/emul/emul_ln9310.c | 388 | ||||
-rw-r--r-- | zephyr/emul/emul_pi3usb9201.c | 195 | ||||
-rw-r--r-- | zephyr/emul/emul_smart_battery.c | 893 | ||||
-rw-r--r-- | zephyr/emul/emul_syv682x.c | 219 | ||||
-rw-r--r-- | zephyr/emul/emul_tcs3400.c | 650 | ||||
-rw-r--r-- | zephyr/emul/i2c_mock.c | 70 |
18 files changed, 0 insertions, 7028 deletions
diff --git a/zephyr/emul/CMakeLists.txt b/zephyr/emul/CMakeLists.txt deleted file mode 100644 index 02b176b942..0000000000 --- a/zephyr/emul/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -zephyr_library_sources_ifdef(CONFIG_EMUL_COMMON_I2C emul_common_i2c.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_SMART_BATTERY emul_smart_battery.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_BMA255 emul_bma255.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_BC12_DETECT_PI3USB9201 emul_pi3usb9201.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_PPC_SYV682X emul_syv682x.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_BMI emul_bmi.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_BMI emul_bmi160.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_BMI emul_bmi260.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_TCS3400 emul_tcs3400.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_BB_RETIMER emul_bb_retimer.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_LN9310 emul_ln9310.c) -zephyr_library_sources_ifdef(CONFIG_EMUL_LIS2DW12 emul_lis2dw12.c) -zephyr_library_sources_ifdef(CONFIG_I2C_MOCK i2c_mock.c) diff --git a/zephyr/emul/Kconfig b/zephyr/emul/Kconfig deleted file mode 100644 index 8d9c8e42ea..0000000000 --- a/zephyr/emul/Kconfig +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -config EMUL_COMMON_I2C - bool "Common handler for I2C emulator messages" - help - Enable common code that is used by many emulators of devices on I2C - bus. It allows to share code for handling I2C messages, locking and - custom user handlers between these emulators. - -config EMUL_SMART_BATTERY - bool "Smart Battery emulator" - select EMUL_COMMON_I2C - help - Enable the Smart Battery emulator. This driver use emulated I2C bus. - -config EMUL_BMA255 - bool "BMA255 emulator" - select EMUL_COMMON_I2C - help - Enable the BMA255 emulator. This driver use emulated I2C bus. - It is used to test bma2x2 driver. Emulators API is available in - zephyr/include/emul/emul_bma255.h - -config EMUL_BC12_DETECT_PI3USB9201 - bool "PI3USB9201 emulator" - help - Enable the PI3USB9201 emulator. PI3USB9201 is a BC1.2 charger - detector/advertiser. The emulator supports reading and writing the - 4 I2C registers of the PI3USB9201 using the emulated I2C bus. - -config EMUL_PPC_SYV682X - bool "Silergy SYV682x PPC emulator" - select PLATFORM_EC_USBC_PPC_SYV682X - help - Enable the SYV682x emulator. SYV682 is a USB Type-C PPC. This driver - uses the emulated I2C bus. - -config EMUL_BMI - bool "BMI emulator" - select EMUL_COMMON_I2C - help - Enable the BMI emulator. This driver use emulated I2C bus. - It is used to test bmi 160 and 260 drivers. Emulators API is - available in zephyr/include/emul/emul_bmi.h - -config EMUL_TCS3400 - bool "TCS3400 emulator" - select EMUL_COMMON_I2C - help - Enable the TCS3400 light sensor. This driver use emulated I2C bus. - It is used to test als_tcs3400 driver. It supports reading sensor - values which are correctly scaled using current gain and integration - time configuration, switching between IR and clear sensor and - clearing status register using clear interrupt registers. Other - TCS3400 registers support read and write with optional checking - of proper access to reserved bits. Emulators API is available in - zephyr/include/emul/emul_tcs3400.h - -config EMUL_BB_RETIMER - bool "BB retimer emulator" - select EMUL_COMMON_I2C - help - Enable the BB (Burnside Bridge) retimer emulator. This driver use - emulated I2C bus. It is used to test bb_retimer driver. It supports - reads and writes to all emulator registers. Emulators API is - available in zephyr/include/emul/emul_bb_retimer.h - -rsource "Kconfig.ln9310" -rsource "Kconfig.lis2dw12" -rsource "Kconfig.i2c_mock" diff --git a/zephyr/emul/Kconfig.i2c_mock b/zephyr/emul/Kconfig.i2c_mock deleted file mode 100644 index 6c98a32739..0000000000 --- a/zephyr/emul/Kconfig.i2c_mock +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -DT_COMPAT_I2C_MOCK := cros,i2c-mock - -menuconfig I2C_MOCK - bool "Mock implementation of an I2C device" - default $(dt_compat_enabled,$(DT_COMPAT_I2C_MOCK)) - depends on I2C_EMUL - help - Enable the I2C mock. This driver is a pure mock and does nothing by - default. It is used to test common i2c code. Mock API is available in - zephyr/include/emul/i2c_mock.h - -if I2C_MOCK - -module = I2C_MOCK -module-str = i2c_mock -source "subsys/logging/Kconfig.template.log_config" - -endif # I2C_MOCK diff --git a/zephyr/emul/Kconfig.lis2dw12 b/zephyr/emul/Kconfig.lis2dw12 deleted file mode 100644 index 2263255418..0000000000 --- a/zephyr/emul/Kconfig.lis2dw12 +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -DT_COMPAT_LIS2DW12_EMUL := cros,lis2dw12-emul - -menuconfig EMUL_LIS2DW12 - bool "LIS2DW12 accelerometer emulator" - default $(dt_compat_enabled,$(DT_COMPAT_LIS2DW12_EMUL)) - depends on I2C_EMUL - select PLATFORM_EC_ACCEL_LIS2DW12 - help - Enable the LIS2DW12 emulator. This driver uses the emulated I2C bus. - It is used to test the lis2dw12 driver. Emulator API is available in - zephyr/include/emul/emul_lis2dw12.h - -if EMUL_LIS2DW12 - -module = LIS2DW12_EMUL -module-str = lis2dw12_emul -source "subsys/logging/Kconfig.template.log_config" - -endif # EMUL_LIS2DW12 diff --git a/zephyr/emul/Kconfig.ln9310 b/zephyr/emul/Kconfig.ln9310 deleted file mode 100644 index 5773cf3721..0000000000 --- a/zephyr/emul/Kconfig.ln9310 +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2021 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -DT_COMPAT_LN9310_EMUL := cros,ln9310-emul - -menuconfig EMUL_LN9310 - bool "LN9310 switchcap emulator" - default $(dt_compat_enabled,$(DT_COMPAT_LN9310_EMUL)) - depends on I2C_EMUL - help - Enable the LN9310 emulator. This driver uses the emulated I2C bus. It - is used to test the ln9310 driver. Emulator API is available in - zephyr/include/emul/emul_ln9310.h - -if EMUL_LN9310 - -module = LN9310_EMUL -module-str = ln9310_emul -source "subsys/logging/Kconfig.template.log_config" - -endif # EMUL_LN9310 diff --git a/zephyr/emul/emul_bb_retimer.c b/zephyr/emul/emul_bb_retimer.c deleted file mode 100644 index b391070b1f..0000000000 --- a/zephyr/emul/emul_bb_retimer.c +++ /dev/null @@ -1,365 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT cros_bb_retimer_emul - -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(emul_bb_retimer); - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_common_i2c.h" -#include "emul/emul_bb_retimer.h" - -#include "driver/retimer/bb_retimer.h" - -#define BB_DATA_FROM_I2C_EMUL(_emul) \ - CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \ - struct bb_emul_data, common) - -/** Run-time data used by the emulator */ -struct bb_emul_data { - /** Common I2C data */ - struct i2c_common_emul_data common; - - /** Current state of all emulated BB retimer registers */ - uint32_t reg[BB_RETIMER_REG_COUNT]; - - /** Vendor ID of emulated device */ - uint32_t vendor_id; - - /** Return error when trying to write to RO register */ - bool error_on_ro_write; - /** Return error when trying to write 1 to reserved bit */ - bool error_on_rsvd_write; - - /** Value of data dword in ongoing i2c message */ - uint32_t data_dword; -}; - -/** Check description in emul_bb_retimer.h */ -void bb_emul_set_reg(struct i2c_emul *emul, int reg, uint32_t val) -{ - struct bb_emul_data *data; - - if (reg < 0 || reg > BB_RETIMER_REG_COUNT) { - return; - } - - data = BB_DATA_FROM_I2C_EMUL(emul); - data->reg[reg] = val; -} - -/** Check description in emul_bb_retimer.h */ -uint32_t bb_emul_get_reg(struct i2c_emul *emul, int reg) -{ - struct bb_emul_data *data; - - if (reg < 0 || reg > BB_RETIMER_REG_COUNT) { - return 0; - } - - data = BB_DATA_FROM_I2C_EMUL(emul); - - return data->reg[reg]; -} - -/** Check description in emul_bb_retimer.h */ -void bb_emul_set_err_on_ro_write(struct i2c_emul *emul, bool set) -{ - struct bb_emul_data *data; - - data = BB_DATA_FROM_I2C_EMUL(emul); - data->error_on_ro_write = set; -} - -/** Check description in emul_bb_retimer.h */ -void bb_emul_set_err_on_rsvd_write(struct i2c_emul *emul, bool set) -{ - struct bb_emul_data *data; - - data = BB_DATA_FROM_I2C_EMUL(emul); - data->error_on_rsvd_write = set; -} - -/** Mask reserved bits in each register of BB retimer */ -static const uint32_t bb_emul_rsvd_mask[] = { - [BB_RETIMER_REG_VENDOR_ID] = 0x00000000, - [BB_RETIMER_REG_DEVICE_ID] = 0x00000000, - [0x02] = 0xffffffff, /* Reserved */ - [0x03] = 0xffffffff, /* Reserved */ - [BB_RETIMER_REG_CONNECTION_STATE] = 0xc0201000, - [BB_RETIMER_REG_TBT_CONTROL] = 0xffffdfff, - [0x06] = 0xffffffff, /* Reserved */ - [BB_RETIMER_REG_EXT_CONNECTION_MODE] = 0x08007f00, -}; - -/** - * @brief Reset registers to default values - * - * @param emul Pointer to BB retimer emulator - */ -static void bb_emul_reset(struct i2c_emul *emul) -{ - struct bb_emul_data *data; - - data = BB_DATA_FROM_I2C_EMUL(emul); - - data->reg[BB_RETIMER_REG_VENDOR_ID] = data->vendor_id; - data->reg[BB_RETIMER_REG_DEVICE_ID] = BB_RETIMER_DEVICE_ID; - data->reg[0x02] = 0x00; /* Reserved */ - data->reg[0x03] = 0x00; /* Reserved */ - data->reg[BB_RETIMER_REG_CONNECTION_STATE] = 0x00; - data->reg[BB_RETIMER_REG_TBT_CONTROL] = 0x00; - data->reg[0x06] = 0x00; /* Reserved */ - data->reg[BB_RETIMER_REG_EXT_CONNECTION_MODE] = 0x00; -} - -/** - * @brief Handle I2C write message. It is checked if accessed register isn't RO - * and reserved bits are set to 0. Write set value of reg field of BB - * retimer emulator data ignoring reserved bits and write only bits. - * - * @param emul Pointer to BB retimer emulator - * @param reg Register which is written - * @param msg_len Length of handled I2C message - * - * @return 0 on success - * @return -EIO on error - */ -static int bb_emul_handle_write(struct i2c_emul *emul, int reg, int msg_len) -{ - struct bb_emul_data *data; - uint32_t val; - - data = BB_DATA_FROM_I2C_EMUL(emul); - - /* This write only selected register for I2C read message */ - if (msg_len < 2) { - return 0; - } - - val = data->data_dword; - - /* - * BB retimer ignores data bytes above 4 and use zeros if there is less - * then 4 data bytes. Emulator prints warning in that case. - */ - if (msg_len != 6) { - LOG_WRN("Got %d bytes of WR data, expected 4", msg_len - 2); - } - - if (reg <= BB_RETIMER_REG_DEVICE_ID || - reg >= BB_RETIMER_REG_COUNT || - reg == BB_RETIMER_REG_TBT_CONTROL) { - if (data->error_on_ro_write) { - LOG_ERR("Writing to reg 0x%x which is RO", reg); - return -EIO; - } - - return 0; - } - - if (data->error_on_rsvd_write && bb_emul_rsvd_mask[reg] & val) { - LOG_ERR("Writing 0x%x to reg 0x%x with rsvd bits mask 0x%x", - val, reg, bb_emul_rsvd_mask[reg]); - return -EIO; - } - - /* Ignore all reserved bits */ - val &= ~bb_emul_rsvd_mask[reg]; - val |= data->reg[reg] & bb_emul_rsvd_mask[reg]; - - data->reg[reg] = val; - - return 0; -} - -/** - * @brief Handle I2C read message. Response is obtained from reg field of bb - * emul data. - * - * @param emul Pointer to BB retimer emulator - * @param reg Register address to read - * - * @return 0 on success - * @return -EIO on error - */ -static int bb_emul_handle_read(struct i2c_emul *emul, int reg) -{ - struct bb_emul_data *data; - - data = BB_DATA_FROM_I2C_EMUL(emul); - - if (reg >= BB_RETIMER_REG_COUNT) { - LOG_ERR("Read unknown register 0x%x", reg); - - return -EIO; - } - - data->data_dword = data->reg[reg]; - - return 0; -} - -/** - * @brief Function called for each byte of write message. Data are stored - * in data_dword field of bb_emul_data - * - * @param emul Pointer to BB retimer emulator - * @param reg First byte of write message - * @param val Received byte of write message - * @param bytes Number of bytes already received - * - * @return 0 on success - */ -static int bb_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val, - int bytes) -{ - struct bb_emul_data *data; - - data = BB_DATA_FROM_I2C_EMUL(emul); - - if (bytes == 1) { - data->data_dword = 0; - if (val != 4) { - LOG_WRN("Invalid write size"); - } - } else if (bytes < 6) { - data->data_dword |= val << (8 * (bytes - 2)); - } - - return 0; -} - -/** - * @brief Function called for each byte of read message. data_dword is converted - * to read message response. - * - * @param emul Pointer to BB retimer emulator - * @param reg First byte of last write message - * @param val Pointer where byte to read should be stored - * @param bytes Number of bytes already readed - * - * @return 0 on success - */ -static int bb_emul_read_byte(struct i2c_emul *emul, int reg, uint8_t *val, - int bytes) -{ - struct bb_emul_data *data; - - data = BB_DATA_FROM_I2C_EMUL(emul); - - /* First byte of read message is read size which is always 4 */ - if (bytes == 0) { - *val = 4; - return 0; - } - - *val = data->data_dword & 0xff; - data->data_dword >>= 8; - - return 0; -} - -/** - * @brief Get currently accessed register, which always equals to selected - * register. - * - * @param emul Pointer to BB retimer emulator - * @param reg First byte of last write message - * @param bytes Number of bytes already handled from current message - * @param read If currently handled is read message - * - * @return Currently accessed register - */ -static int bb_emul_access_reg(struct i2c_emul *emul, int reg, int bytes, - bool read) -{ - return reg; -} - -/* Device instantiation */ - -static struct i2c_emul_api bb_emul_api = { - .transfer = i2c_common_emul_transfer, -}; - -/** - * @brief Set up a new BB retimer emulator - * - * This should be called for each BB retimer device that needs to be - * emulated. It registers it with the I2C emulation controller. - * - * @param emul Emulation information - * @param parent Device to emulate - * - * @return 0 indicating success (always) - */ -static int bb_emul_init(const struct emul *emul, - const struct device *parent) -{ - const struct i2c_common_emul_cfg *cfg = emul->cfg; - struct i2c_common_emul_data *data = cfg->data; - int ret; - - data->emul.api = &bb_emul_api; - data->emul.addr = cfg->addr; - data->i2c = parent; - data->cfg = cfg; - i2c_common_emul_init(data); - - ret = i2c_emul_register(parent, emul->dev_label, &data->emul); - - bb_emul_reset(&data->emul); - - return ret; -} - -#define BB_RETIMER_EMUL(n) \ - static struct bb_emul_data bb_emul_data_##n = { \ - .vendor_id = DT_STRING_TOKEN(DT_DRV_INST(n), vendor), \ - .error_on_ro_write = DT_INST_PROP(n, error_on_ro_write),\ - .error_on_rsvd_write = DT_INST_PROP(n, \ - error_on_reserved_bit_write), \ - .common = { \ - .start_write = NULL, \ - .write_byte = bb_emul_write_byte, \ - .finish_write = bb_emul_handle_write, \ - .start_read = bb_emul_handle_read, \ - .read_byte = bb_emul_read_byte, \ - .finish_read = NULL, \ - .access_reg = bb_emul_access_reg, \ - }, \ - }; \ - \ - static const struct i2c_common_emul_cfg bb_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .dev_label = DT_INST_LABEL(n), \ - .data = &bb_emul_data_##n.common, \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - EMUL_DEFINE(bb_emul_init, DT_DRV_INST(n), &bb_emul_cfg_##n, \ - &bb_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(BB_RETIMER_EMUL) - -#define BB_RETIMER_EMUL_CASE(n) \ - case DT_INST_DEP_ORD(n): return &bb_emul_data_##n.common.emul; - -/** Check description in emul_bb_emulator.h */ -struct i2c_emul *bb_emul_get(int ord) -{ - switch (ord) { - DT_INST_FOREACH_STATUS_OKAY(BB_RETIMER_EMUL_CASE) - - default: - return NULL; - } -} diff --git a/zephyr/emul/emul_bma255.c b/zephyr/emul/emul_bma255.c deleted file mode 100644 index 77b1f5246c..0000000000 --- a/zephyr/emul/emul_bma255.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT zephyr_bma255 - -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(emul_bma255); - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_common_i2c.h" -#include "emul/emul_bma255.h" - -#include "driver/accel_bma2x2.h" - -#define BMA_DATA_FROM_I2C_EMUL(_emul) \ - CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \ - struct bma_emul_data, common) - -/** Run-time data used by the emulator */ -struct bma_emul_data { - /** Common I2C data */ - struct i2c_common_emul_data common; - - /** Value of data byte in ongoing write message */ - uint8_t write_byte; - - /** Current state of all emulated BMA255 registers */ - uint8_t reg[0x40]; - /** Current state of NVM where offset and GP0/1 can be saved */ - uint8_t nvm_x; - uint8_t nvm_y; - uint8_t nvm_z; - uint8_t nvm_gp0; - uint8_t nvm_gp1; - /** Internal offset values used in calculations */ - int16_t off_x; - int16_t off_y; - int16_t off_z; - /** Internal values of accelerometr */ - int16_t acc_x; - int16_t acc_y; - int16_t acc_z; - - /** - * Return error when trying to start offset compensation when not ready - * flag is set. - */ - bool error_on_cal_trg_nrdy; - /** - * Return error when trying to start offset compensation with range - * set to value different than 2G. - */ - bool error_on_cal_trg_bad_range; - /** Return error when trying to write to RO register */ - bool error_on_ro_write; - /** Return error when trying to write 1 to reserved bit */ - bool error_on_rsvd_write; - /** Return error when trying to access MSB before LSB */ - bool error_on_msb_first; - /** - * Flag set when LSB register is accessed and cleared when MSB is - * accessed. Allows to track order of accessing acc registers - */ - bool lsb_x_read; - bool lsb_y_read; - bool lsb_z_read; -}; - -/** Check description in emul_bma255.h */ -void bma_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val) -{ - struct bma_emul_data *data; - - if (reg < 0 || reg > BMA2x2_FIFO_DATA_OUTPUT_ADDR) { - return; - } - - data = BMA_DATA_FROM_I2C_EMUL(emul); - data->reg[reg] = val; -} - -/** Check description in emul_bma255.h */ -uint8_t bma_emul_get_reg(struct i2c_emul *emul, int reg) -{ - struct bma_emul_data *data; - - if (reg < 0 || reg > BMA2x2_FIFO_DATA_OUTPUT_ADDR) { - return 0; - } - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - return data->reg[reg]; -} - -/** - * @brief Convert @p val to two's complement representation. It makes sure that - * bit representation is correct even on platforms which represent - * signed inteager in different format. Unsigned bit representation - * allows to use well defined bitwise operations on returned value. - * - * @param val Inteager that is converted - * - * @return two's complement representation of @p val - */ -static uint16_t bma_emul_val_to_twos_comp(int16_t val) -{ - uint16_t twos_comp_val; - - /* Make sure that value is converted to twos compliment format */ - if (val < 0) { - twos_comp_val = (uint16_t)(-val); - twos_comp_val = ~twos_comp_val + 1; - } else { - twos_comp_val = (uint16_t)val; - } - - return twos_comp_val; -} - -/** - * @brief Convert value from NVM format (8bit, 0x01 == 7.8mg) to internal - * offset format (16bit, 0x01 == 0.97mg). - * - * @param nvm Value in NVM format (8bit, 0x01 == 7.8mg). This is binary - * representation of two's complement signed number. - * - * @return offset Internal representation of @p nvm (16bit, 0x01 == 0.97mg) - */ -static int16_t bma_emul_nvm_to_off(uint8_t nvm) -{ - int16_t offset; - int8_t sign; - - if (nvm & BIT(7)) { - sign = -1; - /* NVM value is in two's complement format */ - nvm = ~nvm + 1; - } else { - sign = 1; - } - - offset = (int16_t)nvm; - /* LSB in NVM is 7.8mg, while LSB in internal offset is 0.97mg */ - offset *= sign * 8; - - return offset; -} - -/** - * @brief Convert value from internal offset format (16bit, 0x01 == 0.97mg) to - * NVM format (8bit, 0x01 == 7.8mg). Function makes sure that NVM value - * is representation of two's complement signed number. - * - * @param val Value in internal offset format (16bit, 0x01 == 0.97mg). - * - * @return nvm NVM format representation of @p val (8bit, 0x01 == 7.8mg) - */ -static uint8_t bma_emul_off_to_nvm(int16_t off) -{ - uint16_t twos_comp_val; - uint8_t nvm = 0; - - twos_comp_val = bma_emul_val_to_twos_comp(off); - - /* - * LSB in internal representation has value 0.97mg, while in NVM - * LSB is 7.8mg. Skip 0.97mg, 1.9mg and 3.9mg bits. - */ - nvm |= (twos_comp_val >> 3) & 0x7f; - /* Set sign bit */ - nvm |= (twos_comp_val & BIT(15)) ? BIT(7) : 0x00; - - return nvm; -} - -/** Check description in emul_bma255.h */ -int16_t bma_emul_get_off(struct i2c_emul *emul, int axis) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case BMA_EMUL_AXIS_X: - return data->off_x; - case BMA_EMUL_AXIS_Y: - return data->off_y; - case BMA_EMUL_AXIS_Z: - return data->off_z; - } - - return 0; -} - -/** Check description in emul_bma255.h */ -void bma_emul_set_off(struct i2c_emul *emul, int axis, int16_t val) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case BMA_EMUL_AXIS_X: - data->off_x = val; - data->reg[BMA2x2_OFFSET_X_AXIS_ADDR] = bma_emul_off_to_nvm( - data->off_x); - break; - case BMA_EMUL_AXIS_Y: - data->off_y = val; - data->reg[BMA2x2_OFFSET_Y_AXIS_ADDR] = bma_emul_off_to_nvm( - data->off_y); - break; - case BMA_EMUL_AXIS_Z: - data->off_z = val; - data->reg[BMA2x2_OFFSET_Z_AXIS_ADDR] = bma_emul_off_to_nvm( - data->off_z); - break; - } -} - -/** Check description in emul_bma255.h */ -int16_t bma_emul_get_acc(struct i2c_emul *emul, int axis) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case BMA_EMUL_AXIS_X: - return data->acc_x; - case BMA_EMUL_AXIS_Y: - return data->acc_y; - case BMA_EMUL_AXIS_Z: - return data->acc_z; - } - - return 0; -} - -/** Check description in emul_bma255.h */ -void bma_emul_set_acc(struct i2c_emul *emul, int axis, int16_t val) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case BMA_EMUL_AXIS_X: - data->acc_x = val; - break; - case BMA_EMUL_AXIS_Y: - data->acc_y = val; - break; - case BMA_EMUL_AXIS_Z: - data->acc_z = val; - break; - } -} - -/** Check description in emul_bma255.h */ -void bma_emul_set_err_on_cal_nrdy(struct i2c_emul *emul, bool set) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - data->error_on_cal_trg_nrdy = set; -} - -/** Check description in emul_bma255.h */ -void bma_emul_set_err_on_cal_bad_range(struct i2c_emul *emul, bool set) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - data->error_on_cal_trg_bad_range = set; -} - -/** Check description in emul_bma255.h */ -void bma_emul_set_err_on_ro_write(struct i2c_emul *emul, bool set) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - data->error_on_ro_write = set; -} - -/** Check description in emul_bma255.h */ -void bma_emul_set_err_on_rsvd_write(struct i2c_emul *emul, bool set) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - data->error_on_rsvd_write = set; -} - -/** Check description in emul_bma255.h */ -void bma_emul_set_err_on_msb_first(struct i2c_emul *emul, bool set) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - data->error_on_msb_first = set; -} - -/** Mask reserved bits in each register of BMA255 */ -static const uint8_t bma_emul_rsvd_mask[] = { - [BMA2x2_CHIP_ID_ADDR] = 0x00, - [0x01] = 0xff, /* Reserved */ - [BMA2x2_X_AXIS_LSB_ADDR] = 0x0e, - [BMA2x2_X_AXIS_MSB_ADDR] = 0x00, - [BMA2x2_Y_AXIS_LSB_ADDR] = 0x0e, - [BMA2x2_Y_AXIS_MSB_ADDR] = 0x00, - [BMA2x2_Z_AXIS_LSB_ADDR] = 0x0e, - [BMA2x2_Z_AXIS_MSB_ADDR] = 0x00, - [BMA2x2_TEMP_ADDR] = 0x00, - [BMA2x2_STAT1_ADDR] = 0x00, - [BMA2x2_STAT2_ADDR] = 0x1f, - [BMA2x2_STAT_TAP_SLOPE_ADDR] = 0x00, - [BMA2x2_STAT_ORIENT_HIGH_ADDR] = 0x00, - [0x0d] = 0xff, /* Reserved */ - [BMA2x2_STAT_FIFO_ADDR] = 0x00, - [BMA2x2_RANGE_SELECT_ADDR] = 0xf0, - [BMA2x2_BW_SELECT_ADDR] = 0xe0, - [BMA2x2_MODE_CTRL_ADDR] = 0x01, - [BMA2x2_LOW_NOISE_CTRL_ADDR] = 0x9f, - [BMA2x2_DATA_CTRL_ADDR] = 0x3f, - [BMA2x2_RST_ADDR] = 0x00, - [0x15] = 0xff, /* Reserved */ - [BMA2x2_INTR_ENABLE1_ADDR] = 0x08, - [BMA2x2_INTR_ENABLE2_ADDR] = 0x80, - [BMA2x2_INTR_SLOW_NO_MOTION_ADDR] = 0xf0, - [BMA2x2_INTR1_PAD_SELECT_ADDR] = 0x00, - [BMA2x2_INTR_DATA_SELECT_ADDR] = 0x18, - [BMA2x2_INTR2_PAD_SELECT_ADDR] = 0x00, - [0x1c] = 0xff, /* Reserved */ - [0x1d] = 0xff, /* Reserved */ - [BMA2x2_INTR_SOURCE_ADDR] = 0xc0, - [0x1f] = 0xff, /* Reserved */ - [BMA2x2_INTR_SET_ADDR] = 0xf0, - [BMA2x2_INTR_CTRL_ADDR] = 0x70, - [BMA2x2_LOW_DURN_ADDR] = 0x00, - [BMA2x2_LOW_THRES_ADDR] = 0x00, - [BMA2x2_LOW_HIGH_HYST_ADDR] = 0x38, - [BMA2x2_HIGH_DURN_ADDR] = 0x00, - [BMA2x2_HIGH_THRES_ADDR] = 0x00, - [BMA2x2_SLOPE_DURN_ADDR] = 0x00, - [BMA2x2_SLOPE_THRES_ADDR] = 0x00, - [BMA2x2_SLOW_NO_MOTION_THRES_ADDR] = 0x00, - [BMA2x2_TAP_PARAM_ADDR] = 0x38, - [BMA2x2_TAP_THRES_ADDR] = 0x20, - [BMA2x2_ORIENT_PARAM_ADDR] = 0x80, - [BMA2x2_THETA_BLOCK_ADDR] = 0x80, - [BMA2x2_THETA_FLAT_ADDR] = 0xc0, - [BMA2x2_FLAT_HOLD_TIME_ADDR] = 0xc8, - [BMA2x2_FIFO_WML_TRIG] = 0xc0, - [0x31] = 0xff, /* Reserved */ - [BMA2x2_SELFTEST_ADDR] = 0xf8, - [BMA2x2_EEPROM_CTRL_ADDR] = 0x00, - [BMA2x2_SERIAL_CTRL_ADDR] = 0xf8, - [0x35] = 0xff, /* Reserved */ - [BMA2x2_OFFSET_CTRL_ADDR] = 0x08, - [BMA2x2_OFC_SETTING_ADDR] = 0x80, - [BMA2x2_OFFSET_X_AXIS_ADDR] = 0x00, - [BMA2x2_OFFSET_Y_AXIS_ADDR] = 0x00, - [BMA2x2_OFFSET_Z_AXIS_ADDR] = 0x00, - [BMA2x2_GP0_ADDR] = 0x00, - [BMA2x2_GP1_ADDR] = 0x00, - [0x3d] = 0xff, /* Reserved */ - [BMA2x2_FIFO_MODE_ADDR] = 0x3c, - [BMA2x2_FIFO_DATA_OUTPUT_ADDR] = 0x00, -}; - -/** - * @brief Reset register values and internal representation of offset and two - * general purpose registers - * - * @param emul Pointer to BMA255 emulator - */ -static void bma_emul_restore_nvm(struct i2c_emul *emul) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - /* Restore registers values */ - data->reg[BMA2x2_OFFSET_X_AXIS_ADDR] = data->nvm_x; - data->reg[BMA2x2_OFFSET_Y_AXIS_ADDR] = data->nvm_y; - data->reg[BMA2x2_OFFSET_Z_AXIS_ADDR] = data->nvm_z; - data->reg[BMA2x2_GP0_ADDR] = data->nvm_gp0; - data->reg[BMA2x2_GP1_ADDR] = data->nvm_gp1; - - /* Restore internal offset values */ - data->off_x = bma_emul_nvm_to_off(data->nvm_x); - data->off_y = bma_emul_nvm_to_off(data->nvm_y); - data->off_z = bma_emul_nvm_to_off(data->nvm_z); -} - -/** - * @brief Reset registers to default values and restore registers backed by NVM - * - * @param emul Pointer to BMA255 emulator - */ -static void bma_emul_reset(struct i2c_emul *emul) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - data->reg[BMA2x2_CHIP_ID_ADDR] = 0xfa; - data->reg[0x01] = 0x00; /* Reserved */ - data->reg[BMA2x2_X_AXIS_LSB_ADDR] = 0x00; - data->reg[BMA2x2_X_AXIS_MSB_ADDR] = 0x00; - data->reg[BMA2x2_Y_AXIS_LSB_ADDR] = 0x00; - data->reg[BMA2x2_Y_AXIS_MSB_ADDR] = 0x00; - data->reg[BMA2x2_Z_AXIS_LSB_ADDR] = 0x00; - data->reg[BMA2x2_Z_AXIS_MSB_ADDR] = 0x00; - data->reg[BMA2x2_TEMP_ADDR] = 0x00; - data->reg[BMA2x2_STAT1_ADDR] = 0x00; - data->reg[BMA2x2_STAT2_ADDR] = 0x00; - data->reg[BMA2x2_STAT_TAP_SLOPE_ADDR] = 0x00; - data->reg[BMA2x2_STAT_ORIENT_HIGH_ADDR] = 0x00; - data->reg[0x0d] = 0xff; /* Reserved */ - data->reg[BMA2x2_STAT_FIFO_ADDR] = 0x00; - data->reg[BMA2x2_RANGE_SELECT_ADDR] = 0x03; - data->reg[BMA2x2_BW_SELECT_ADDR] = 0x0f; - data->reg[BMA2x2_MODE_CTRL_ADDR] = 0x00; - data->reg[BMA2x2_LOW_NOISE_CTRL_ADDR] = 0x00; - data->reg[BMA2x2_DATA_CTRL_ADDR] = 0x00; - data->reg[BMA2x2_RST_ADDR] = 0x00; - data->reg[0x15] = 0xff; /* Reserved */ - data->reg[BMA2x2_INTR_ENABLE1_ADDR] = 0x00; - data->reg[BMA2x2_INTR_ENABLE2_ADDR] = 0x00; - data->reg[BMA2x2_INTR_SLOW_NO_MOTION_ADDR] = 0x00; - data->reg[BMA2x2_INTR1_PAD_SELECT_ADDR] = 0x00; - data->reg[BMA2x2_INTR_DATA_SELECT_ADDR] = 0x00; - data->reg[BMA2x2_INTR2_PAD_SELECT_ADDR] = 0x00; - data->reg[0x1c] = 0xff; /* Reserved */ - data->reg[0x1d] = 0xff; /* Reserved */ - data->reg[BMA2x2_INTR_SOURCE_ADDR] = 0x00; - data->reg[0x1f] = 0xff; /* Reserved */ - data->reg[BMA2x2_INTR_SET_ADDR] = 0x05; - data->reg[BMA2x2_INTR_CTRL_ADDR] = 0x00; - data->reg[BMA2x2_LOW_DURN_ADDR] = 0x09; - data->reg[BMA2x2_LOW_THRES_ADDR] = 0x30; - data->reg[BMA2x2_LOW_HIGH_HYST_ADDR] = 0x81; - data->reg[BMA2x2_HIGH_DURN_ADDR] = 0x0f; - data->reg[BMA2x2_HIGH_THRES_ADDR] = 0xc0; - data->reg[BMA2x2_SLOPE_DURN_ADDR] = 0x00; - data->reg[BMA2x2_SLOPE_THRES_ADDR] = 0x14; - data->reg[BMA2x2_SLOW_NO_MOTION_THRES_ADDR] = 0x14; - data->reg[BMA2x2_TAP_PARAM_ADDR] = 0x04; - data->reg[BMA2x2_TAP_THRES_ADDR] = 0x0a; - data->reg[BMA2x2_ORIENT_PARAM_ADDR] = 0x18; - data->reg[BMA2x2_THETA_BLOCK_ADDR] = 0x48; - data->reg[BMA2x2_THETA_FLAT_ADDR] = 0x08; - data->reg[BMA2x2_FLAT_HOLD_TIME_ADDR] = 0x11; - data->reg[BMA2x2_FIFO_WML_TRIG] = 0x00; - data->reg[0x31] = 0xff; /* Reserved */ - data->reg[BMA2x2_SELFTEST_ADDR] = 0x00; - data->reg[BMA2x2_EEPROM_CTRL_ADDR] = 0xf0; - data->reg[BMA2x2_SERIAL_CTRL_ADDR] = 0x00; - data->reg[0x35] = 0x00; /* Reserved */ - data->reg[BMA2x2_OFFSET_CTRL_ADDR] = 0x10; - data->reg[BMA2x2_OFC_SETTING_ADDR] = 0x00; - data->reg[0x3d] = 0xff; /* Reserved */ - data->reg[BMA2x2_FIFO_MODE_ADDR] = 0x00; - data->reg[BMA2x2_FIFO_DATA_OUTPUT_ADDR] = 0x00; - - /* Restore registers backed in NVM */ - bma_emul_restore_nvm(emul); -} - -/** - * @brief Convert range in format of RANGE_SELECT register to number of bits - * that should be shifted right to obtain 12 bit reported accelerometer - * value from internal 16 bit value - * - * @param range Value of RANGE_SELECT register - * - * @return shift Number of LSB that should be ignored from internal - * accelerometer value - */ -static int bma_emul_range_to_shift(uint8_t range) -{ - switch (range & BMA2x2_RANGE_SELECT_MSK) { - case BMA2x2_RANGE_2G: - return 0; - case BMA2x2_RANGE_4G: - return 1; - case BMA2x2_RANGE_8G: - return 2; - case BMA2x2_RANGE_16G: - return 3; - default: - return -1; - } -} - -/** - * @brief Handle write requests to NVM control register. Allows to load/store - * NVM only when ready in current NVM control register is set. Load and - * stores to NVM are backed in bma_emul_data structure - * - * @param emul Pointer to BMA255 emulator - * @param val Value that is being written to NVM contorl register - * - * @return 0 on success - */ -static int bma_emul_handle_nvm_write(struct i2c_emul *emul, uint8_t val) -{ - struct bma_emul_data *data; - uint8_t writes_rem; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - /* NVM not ready, ignore write/load requests */ - if (!(data->reg[BMA2x2_EEPROM_CTRL_ADDR] & BMA2x2_EEPROM_RDY)) { - return 0; - } - - /* Restore data from NVM */ - if (val & BMA2x2_EEPROM_LOAD) { - bma_emul_restore_nvm(emul); - } - - writes_rem = (data->reg[BMA2x2_EEPROM_CTRL_ADDR] & - BMA2x2_EEPROM_REMAIN_MSK) >> BMA2x2_EEPROM_REMAIN_OFF; - /* Trigger write is set, write is unlocked and writes remaining */ - if (val & BMA2x2_EEPROM_PROG && - data->reg[BMA2x2_EEPROM_CTRL_ADDR] & BMA2x2_EEPROM_PROG_EN && - writes_rem > 0) { - data->nvm_x = data->reg[BMA2x2_OFFSET_X_AXIS_ADDR]; - data->nvm_y = data->reg[BMA2x2_OFFSET_Y_AXIS_ADDR]; - data->nvm_z = data->reg[BMA2x2_OFFSET_Z_AXIS_ADDR]; - data->nvm_gp0 = data->reg[BMA2x2_GP0_ADDR]; - data->nvm_gp1 = data->reg[BMA2x2_GP1_ADDR]; - /* Decrement number of remaining writes and save it in reg */ - writes_rem--; - data->reg[BMA2x2_EEPROM_CTRL_ADDR] &= - ~BMA2x2_EEPROM_REMAIN_MSK; - data->reg[BMA2x2_EEPROM_CTRL_ADDR] |= - writes_rem << BMA2x2_EEPROM_REMAIN_OFF; - } - - return 0; -} - -/** - * @brief Clear all interrupt registers - * - * @param emul Pointer to BMA255 emulator - */ -static void bma_emul_clear_int(struct i2c_emul *emul) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - data->reg[BMA2x2_STAT1_ADDR] = 0x00; - data->reg[BMA2x2_STAT2_ADDR] = 0x00; - data->reg[BMA2x2_STAT_TAP_SLOPE_ADDR] = 0x00; - data->reg[BMA2x2_STAT_ORIENT_HIGH_ADDR] = 0x00; -} - -/** - * @brief Get target value from offset compensation setting register for given - * @p axis - * - * @param emul Pointer to BMA255 emulator - * @param axis Axis to access: 0 - X, 1 - Y, 2 - Z - * - * @return target Value to which offset compensation should be calculated - */ -static int16_t bma_emul_get_target(struct i2c_emul *emul, int axis) -{ - struct bma_emul_data *data; - uint8_t target; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - target = data->reg[BMA2x2_OFC_SETTING_ADDR] >> - BMA2x2_OFC_TARGET_AXIS(axis); - switch (target) { - case BMA2x2_OFC_TARGET_0G: - return 0; - case BMA2x2_OFC_TARGET_PLUS_1G: - return BMA_EMUL_1G; - case BMA2x2_OFC_TARGET_MINUS_1G: - return -((int)BMA_EMUL_1G); - } - - return 0; -} - -/** - * @brief Handle writes to offset compensation control register. It allows to - * reset offset registers. It check if offset compenstation is ready - * and if range is set to 2G (required for fast compensation according - * to BMA255 documentation). If fast compensation is successfully - * triggered, internal offset value is set to - * (target - internal accelerometer value). - * - * @param emul Pointer to BMA255 emulator - * @param val Value being written to offset compensation control register - * - * @return 0 on success - * @return -EIO when trying to start fast compensation in wrong emulator state - */ -static int bma_emul_handle_off_comp(struct i2c_emul *emul, uint8_t val) -{ - struct bma_emul_data *data; - uint8_t trigger; - int16_t target; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - if (val & BMA2x2_OFFSET_RESET) { - data->off_x = 0; - data->off_y = 0; - data->off_z = 0; - data->reg[BMA2x2_OFFSET_X_AXIS_ADDR] = 0; - data->reg[BMA2x2_OFFSET_Y_AXIS_ADDR] = 0; - data->reg[BMA2x2_OFFSET_Z_AXIS_ADDR] = 0; - } - - - trigger = (val & BMA2x2_OFFSET_TRIGGER_MASK) >> - BMA2x2_OFFSET_TRIGGER_OFF; - - if (!(data->reg[BMA2x2_OFFSET_CTRL_ADDR] & BMA2x2_OFFSET_CAL_READY)) { - if (data->error_on_cal_trg_nrdy && trigger) { - LOG_ERR("Trying to start offset comp when not ready"); - return -EIO; - } - - return 0; - } - - if (bma_emul_range_to_shift(data->reg[BMA2x2_RANGE_SELECT_ADDR]) != 0 && - trigger && data->error_on_cal_trg_bad_range) { - LOG_ERR("Trying to start offset comp with range other than 2G"); - return -EIO; - } - - switch (trigger) { - case 1: - target = bma_emul_get_target(emul, BMA_EMUL_AXIS_X); - bma_emul_set_off(emul, BMA_EMUL_AXIS_X, target - data->acc_x); - break; - case 2: - target = bma_emul_get_target(emul, BMA_EMUL_AXIS_Y); - bma_emul_set_off(emul, BMA_EMUL_AXIS_Y, target - data->acc_y); - break; - case 3: - target = bma_emul_get_target(emul, BMA_EMUL_AXIS_Z); - bma_emul_set_off(emul, BMA_EMUL_AXIS_Z, target - data->acc_z); - break; - } - - return 0; -} - -/** - * @brief Handle I2C write message. It is checked if accessed register isn't RO - * and reserved bits are set to 0. Write set value of reg field of bma - * emulator data ignoring reserved bits and write only bits. Some - * commands are handled specialy. - * - * @param emul Pointer to BMA255 emulator - * @param reg Register which is written - * @param bytes Number of bytes in I2C write message - * - * @return 0 on success - * @return -EIO on error - */ -static int bma_emul_handle_write(struct i2c_emul *emul, int reg, int bytes) -{ - struct bma_emul_data *data; - uint8_t val; - int ret; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - val = data->write_byte; - - if (bytes > 2) { - LOG_ERR("Too long write command"); - return -EIO; - } - - /* This write only selected register for I2C read message */ - if (bytes < 2) { - return 0; - } - - if (reg <= BMA2x2_STAT_FIFO_ADDR || - reg >= BMA2x2_FIFO_DATA_OUTPUT_ADDR) { - if (data->error_on_ro_write) { - LOG_ERR("Writing to reg 0x%x which is RO", reg); - return -EIO; - } - - return 0; - } - - if (data->error_on_rsvd_write && bma_emul_rsvd_mask[reg] & val) { - LOG_ERR("Writing 0x%x to reg 0x%x with rsvd bits mask 0x%x", - val, reg, bma_emul_rsvd_mask[reg]); - return -EIO; - } - - - switch (reg) { - case BMA2x2_RST_ADDR: - if (val == BMA2x2_CMD_SOFT_RESET) { - bma_emul_reset(emul); - } - return 0; - case BMA2x2_INTR_CTRL_ADDR: - if (val & BMA2x2_INTR_CTRL_RST_INT) { - bma_emul_clear_int(emul); - } - /* Don't set write only bit in register */ - val &= ~BMA2x2_INTR_CTRL_RST_INT; - break; - case BMA2x2_EEPROM_CTRL_ADDR: - bma_emul_handle_nvm_write(emul, val); - /* Only programing enable bit is RW */ - val &= BMA2x2_EEPROM_PROG_EN; - val |= data->reg[reg] & ~BMA2x2_EEPROM_PROG_EN; - break; - case BMA2x2_OFFSET_CTRL_ADDR: - ret = bma_emul_handle_off_comp(emul, val); - if (ret) { - return -EIO; - } - /* Only slow compensation bits are RW */ - val &= BMA2x2_OFFSET_CAL_SLOW_X | BMA2x2_OFFSET_CAL_SLOW_Y | - BMA2x2_OFFSET_CAL_SLOW_Z; - val |= data->reg[reg] & ~(BMA2x2_OFFSET_CAL_SLOW_X | - BMA2x2_OFFSET_CAL_SLOW_Y | - BMA2x2_OFFSET_CAL_SLOW_Z); - break; - /* Change internal offset to value set in I2C message */ - case BMA2x2_OFFSET_X_AXIS_ADDR: - data->off_x = bma_emul_nvm_to_off(val); - break; - case BMA2x2_OFFSET_Y_AXIS_ADDR: - data->off_y = bma_emul_nvm_to_off(val); - break; - case BMA2x2_OFFSET_Z_AXIS_ADDR: - data->off_z = bma_emul_nvm_to_off(val); - break; - case BMA2x2_RANGE_SELECT_ADDR: - ret = bma_emul_range_to_shift(val); - if (ret < 0) { - LOG_ERR("Unknown range select value 0x%x", val); - return -EIO; - } - break; - } - - /* Ignore all reserved bits */ - val &= ~bma_emul_rsvd_mask[reg]; - val |= data->reg[reg] & bma_emul_rsvd_mask[reg]; - - data->reg[reg] = val; - - return 0; -} - -/** - * @brief Get set accelerometer value for given register using internal axis - * state @p val. In case of accessing MSB with enabled shadowing, - * check if LSB was accessed first. - * - * @param emul Pointer to BMA255 emulator - * @param lsb_reg LSB register address (BMA2x2_X_AXIS_LSB_ADDR, - * BMA2x2_Y_AXIS_LSB_ADDR, BMA2x2_Z_AXIS_LSB_ADDR) - * @param lsb_read Pointer to variable which represent if last access to this - * accelerometer value was through LSB register - * @param lsb True if now accessing LSB, Flase if now accessing MSB - * @param val Internal value of accessed accelerometer axis - * - * @return 0 on success - * @return -EIO when accessing MSB before LSB with enabled shadowing - */ -static int bma_emul_get_acc_val(struct i2c_emul *emul, int lsb_reg, - bool *lsb_read, bool lsb, int16_t val) -{ - struct bma_emul_data *data; - uint16_t twos_comp_val; - uint8_t new_data; - int msb_reg; - int shift; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - if (lsb) { - *lsb_read = 1; - } else if (!(data->reg[BMA2x2_DATA_CTRL_ADDR] & - BMA2x2_DATA_SHADOW_DIS)) { - /* - * If shadowing is enabled, error on first accessing MSB and - * LSB wasn't accessed before, then return error. - */ - if (data->error_on_msb_first && !(*lsb_read)) { - return -EIO; - } - *lsb_read = 0; - /* If shadowing is enabled, LSB read should set correct value */ - return 0; - } - - twos_comp_val = bma_emul_val_to_twos_comp(val); - msb_reg = lsb_reg + 1; - shift = bma_emul_range_to_shift(data->reg[BMA2x2_RANGE_SELECT_ADDR]); - - /* Save new data bit from register */ - new_data = data->reg[lsb_reg] & BMA2x2_AXIS_LSB_NEW_DATA; - /* Shift 16 bit value to 12 bit set in range register */ - twos_comp_val >>= shift; - /* Set [3:0] bits in first register */ - data->reg[lsb_reg] = ((twos_comp_val << 4) & 0xf0) | new_data; - /* Set [11:4] bits in second register */ - data->reg[msb_reg] = (twos_comp_val >> 4) & 0xff; - - return 0; -} - -/** Check description in emul_bma255.h */ -int bma_emul_access_reg(struct i2c_emul *emul, int reg, int bytes, bool read) -{ - /* - * Exclude first byte (select register) from total number of bytes - * in I2C write message - */ - if (!read) { - bytes--; - } - - if (reg <= BMA2x2_FIFO_DATA_OUTPUT_ADDR && - reg + bytes >= BMA2x2_FIFO_DATA_OUTPUT_ADDR) { - return BMA2x2_FIFO_DATA_OUTPUT_ADDR; - } - - return reg + bytes; -} - -/** - * @brief Handle I2C read message. Response is obtained from reg field of bma - * emul data. When accessing accelerometer value, register data is first - * computed using internal emulator state. - * - * @param emul Pointer to BMA255 emulator - * @param reg Register address to read - * @param val Pointer where resultat should be stored - * @param bytes Number of bytes in I2C read message - * - * @return 0 on success - * @return -EIO on error - */ -static int bma_emul_handle_read(struct i2c_emul *emul, int reg, uint8_t *val, - int bytes) -{ - struct bma_emul_data *data; - int ret; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - reg = bma_emul_access_reg(emul, reg, bytes, true /* = read */); - - switch (reg) { - case BMA2x2_X_AXIS_LSB_ADDR: - /* Shouldn't fail for LSB */ - ret = bma_emul_get_acc_val(emul, reg, &data->lsb_x_read, true, - data->acc_x + data->off_x); - break; - case BMA2x2_X_AXIS_MSB_ADDR: - ret = bma_emul_get_acc_val(emul, reg - 1, &data->lsb_x_read, - false, data->acc_x + data->off_x); - if (ret) { - LOG_ERR("MSB X readed before LSB X"); - return -EIO; - } - break; - case BMA2x2_Y_AXIS_LSB_ADDR: - /* Shouldn't fail for LSB */ - ret = bma_emul_get_acc_val(emul, reg, &data->lsb_y_read, true, - data->acc_y + data->off_y); - break; - case BMA2x2_Y_AXIS_MSB_ADDR: - ret = bma_emul_get_acc_val(emul, reg - 1, &data->lsb_y_read, - false, data->acc_y + data->off_y); - if (ret) { - LOG_ERR("MSB Y readed before LSB Y"); - return -EIO; - } - break; - case BMA2x2_Z_AXIS_LSB_ADDR: - /* Shouldn't fail for LSB */ - ret = bma_emul_get_acc_val(emul, reg, &data->lsb_z_read, true, - data->acc_z + data->off_z); - break; - case BMA2x2_Z_AXIS_MSB_ADDR: - ret = bma_emul_get_acc_val(emul, reg - 1, &data->lsb_z_read, - false, data->acc_z + data->off_z); - if (ret) { - LOG_ERR("MSB Z readed before LSB Z"); - return -EIO; - } - break; - } - - *val = data->reg[reg]; - - return 0; -} - -/** - * @brief Handle I2C write message. Saves data that will be stored in register. - * - * @param emul Pointer to BMA emulator - * @param reg Register address that is accessed - * @param val Data to write to the register - * @param bytes Number of bytes already handled in this read message - * - * @return 0 on success - * @return -EIO on error - */ -static int bma_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val, - int bytes) -{ - struct bma_emul_data *data; - - data = BMA_DATA_FROM_I2C_EMUL(emul); - - data->write_byte = val; - - return 0; -} - -/* Device instantiation */ - -static struct i2c_emul_api bma_emul_api = { - .transfer = i2c_common_emul_transfer, -}; - -/** - * @brief Set up a new BMA255 emulator - * - * This should be called for each BMA255 device that needs to be - * emulated. It registers it with the I2C emulation controller. - * - * @param emul Emulation information - * @param parent Device to emulate - * - * @return 0 indicating success (always) - */ -static int bma_emul_init(const struct emul *emul, - const struct device *parent) -{ - const struct i2c_common_emul_cfg *cfg = emul->cfg; - struct i2c_common_emul_data *data = cfg->data; - int ret; - - data->emul.api = &bma_emul_api; - data->emul.addr = cfg->addr; - data->i2c = parent; - data->cfg = cfg; - i2c_common_emul_init(data); - - ret = i2c_emul_register(parent, emul->dev_label, &data->emul); - - bma_emul_reset(&data->emul); - - return ret; -} - -#define BMA255_EMUL(n) \ - static struct bma_emul_data bma_emul_data_##n = { \ - .nvm_x = DT_INST_PROP(n, nvm_off_x), \ - .nvm_y = DT_INST_PROP(n, nvm_off_y), \ - .nvm_z = DT_INST_PROP(n, nvm_off_z), \ - .nvm_gp0 = DT_INST_PROP(n, nvm_gp0), \ - .nvm_gp1 = DT_INST_PROP(n, nvm_gp1), \ - .acc_x = DT_INST_PROP(n, nvm_acc_x), \ - .acc_y = DT_INST_PROP(n, nvm_acc_y), \ - .acc_z = DT_INST_PROP(n, nvm_acc_z), \ - .error_on_cal_trg_nrdy = DT_INST_PROP(n, \ - error_on_compensation_not_ready), \ - .error_on_ro_write = DT_INST_PROP(n, error_on_ro_write),\ - .error_on_rsvd_write = DT_INST_PROP(n, \ - error_on_reserved_bit_write), \ - .error_on_msb_first = DT_INST_PROP(n, \ - error_on_msb_first_access), \ - .lsb_x_read = 0, \ - .lsb_y_read = 0, \ - .lsb_z_read = 0, \ - .common = { \ - .start_write = NULL, \ - .write_byte = bma_emul_write_byte, \ - .finish_write = bma_emul_handle_write, \ - .start_read = NULL, \ - .read_byte = bma_emul_handle_read, \ - .finish_read = NULL, \ - .access_reg = bma_emul_access_reg, \ - }, \ - }; \ - \ - static const struct i2c_common_emul_cfg bma_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .dev_label = DT_INST_LABEL(n), \ - .data = &bma_emul_data_##n.common, \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - EMUL_DEFINE(bma_emul_init, DT_DRV_INST(n), &bma_emul_cfg_##n, \ - &bma_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(BMA255_EMUL) - -#define BMA255_EMUL_CASE(n) \ - case DT_INST_DEP_ORD(n): return &bma_emul_data_##n.common.emul; - -/** Check description in emul_bma255.h */ -struct i2c_emul *bma_emul_get(int ord) -{ - switch (ord) { - DT_INST_FOREACH_STATUS_OKAY(BMA255_EMUL_CASE) - - default: - return NULL; - } -} diff --git a/zephyr/emul/emul_bmi.c b/zephyr/emul/emul_bmi.c deleted file mode 100644 index 7923fe0eb5..0000000000 --- a/zephyr/emul/emul_bmi.c +++ /dev/null @@ -1,1116 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT zephyr_bmi - -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(emul_bmi); - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_common_i2c.h" -#include "emul/emul_bmi.h" - -#include "driver/accelgyro_bmi160.h" -#include "driver/accelgyro_bmi260.h" -#include "driver/accelgyro_bmi_common.h" - -#define BMI_DATA_FROM_I2C_EMUL(_emul) \ - CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \ - struct bmi_emul_data, common) - -/** Run-time data used by the emulator */ -struct bmi_emul_data { - /** Common I2C data */ - struct i2c_common_emul_data common; - - /** Current state of all emulated BMI registers */ - uint8_t reg[BMI_EMUL_MAX_REG]; - /** Internal offset values used in calculations */ - int16_t off_acc_x; - int16_t off_acc_y; - int16_t off_acc_z; - int16_t off_gyr_x; - int16_t off_gyr_y; - int16_t off_gyr_z; - /** Internal values of sensors */ - int32_t acc_x; - int32_t acc_y; - int32_t acc_z; - int32_t gyr_x; - int32_t gyr_y; - int32_t gyr_z; - /** Current state of NVM where offset and configuration can be saved */ - uint8_t nvm[BMI_EMUL_MAX_NVM_REGS]; - - /** Return error when trying to write to RO register */ - bool error_on_ro_write; - /** Return error when trying to write 1 to reserved bit */ - bool error_on_rsvd_write; - /** - * If effect of command is vissable after simulated time from issuing - * command - */ - bool simulate_command_exec_time; - /** Return error when trying to read WO register */ - bool error_on_wo_read; - - /** Value of data byte in ongoing write message */ - uint8_t write_byte; - - /** List of FIFO frames */ - struct bmi_emul_frame *fifo_frame; - /** First FIFO frame in byte format */ - uint8_t fifo[21]; - /** Number of FIFO frames that were skipped */ - uint8_t fifo_skip; - /** Currently accessed byte of first frame */ - int fifo_frame_byte; - /** Length of first frame */ - int fifo_frame_len; - - /** Last time when emulator was resetted in sensor time units */ - int64_t zero_time; - /** Time when current command should end */ - uint32_t cmd_end_time; - - /** Emulated model of BMI */ - int type; - /** Pointer to data specific for emulated model of BMI */ - const struct bmi_emul_type_data *type_data; -}; - -/** Check description in emul_bmi.h */ -void bmi_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val) -{ - struct bmi_emul_data *data; - - if (reg < 0 || reg > BMI_EMUL_MAX_REG) { - return; - } - - data = BMI_DATA_FROM_I2C_EMUL(emul); - data->reg[reg] = val; -} - -/** Check description in emul_bmi.h */ -uint8_t bmi_emul_get_reg(struct i2c_emul *emul, int reg) -{ - struct bmi_emul_data *data; - - if (reg < 0 || reg > BMI_EMUL_MAX_REG) { - return 0; - } - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - return data->reg[reg]; -} - -/** - * @brief Convert @p val to two's complement representation. It makes sure that - * bit representation is correct even on platforms which represent - * signed inteager in different format. Unsigned bit representation - * allows to use well defined bitwise operations on returned value. - * - * @param val Inteager that is converted - * - * @return two's complement representation of @p val - */ -static uint32_t bmi_emul_val_to_twos_comp(int32_t val) -{ - uint32_t twos_comp_val; - - /* Make sure that value is converted to twos compliment format */ - if (val < 0) { - twos_comp_val = (uint32_t)(-val); - twos_comp_val = ~twos_comp_val + 1; - } else { - twos_comp_val = (uint32_t)val; - } - - return twos_comp_val; -} - -/** - * @brief Convert accelerometer value from NVM format (8bit, 0x01 == 3.9mg) - * to internal offset format (16bit, 0x01 == 0.061mg). - * - * @param nvm Value in NVM format (8bit, 0x01 == 3.9mg). This is binary - * representation of two's complement signed number. - * - * @return offset Internal representation of @p nvm (16bit, 0x01 == 0.061mg) - */ -static int16_t bmi_emul_acc_nvm_to_off(uint8_t nvm) -{ - int16_t offset; - int8_t sign; - - if (nvm & BIT(7)) { - sign = -1; - /* NVM value is in two's complement format */ - nvm = ~nvm + 1; - } else { - sign = 1; - } - - offset = (int16_t)nvm; - /* LSB in NVM is 3.9mg, while LSB in internal offset is 0.061mg */ - offset *= sign * 64; - - return offset; -} - -/** - * @brief Convert gyroscope value from NVM format (10bit, 0x01 == 0.061 °/s) - * to internal offset format (16bit, 0x01 == 0.0038 °/s) - * - * @param nvm Value in NVM format (10bit, 0x01 == 0.061 °/s). This is binary - * representation of two's complement signed number. - * - * @return offset Internal representation of @p nvm (16bit, 0x01 == 0.0038 °/s) - */ -static int16_t bmi_emul_gyr_nvm_to_off(uint16_t nvm) -{ - int16_t offset; - int8_t sign; - - if (nvm & BIT(9)) { - sign = -1; - /* NVM value is in two's complement format */ - nvm = ~nvm + 1; - } else { - sign = 1; - } - - /* Mask 10 bits which holds value */ - nvm &= 0x3ff; - - offset = (int16_t)nvm; - /* LSB in NVM is 0.061°/s, while LSB in internal offset is 0.0038°/s */ - offset *= sign * 16; - - return offset; -} - -/** - * @brief Convert accelerometer value from internal offset format - * (16bit, 0x01 == 0.061mg) to NVM format (8bit, 0x01 == 7.8mg). - * Function makes sure that NVM value is representation of two's - * complement signed number. - * - * @param val Value in internal offset format (16bit, 0x01 == 0.061mg). - * - * @return nvm NVM format representation of @p val (8bit, 0x01 == 3.9mg) - */ -static uint8_t bmi_emul_acc_off_to_nvm(int16_t off) -{ - uint32_t twos_comp_val; - uint8_t nvm = 0; - - twos_comp_val = bmi_emul_val_to_twos_comp(off); - - /* - * LSB in internal representation has value 0.061mg, while in NVM - * LSB is 3.9mg. Skip 0.06mg, 0.12mg, 0.24mg, 0.48mg, 0.97mg and - * 1.9mg bits. - */ - nvm |= (twos_comp_val >> 6) & 0x7f; - /* Set sign bit */ - nvm |= (twos_comp_val & BIT(31)) ? BIT(7) : 0x00; - - return nvm; -} - -/** - * @brief Convert gyroscope value from internal offset format - * (16bit, 0x01 == 0.0038°/s) to NVM format (10bit, 0x01 == 0.061°/s). - * Function makes sure that NVM value is representation of two's - * complement signed number. - * - * @param val Value in internal offset format (16bit, 0x01 == 0.0038°/s). - * - * @return nvm NVM format representation of @p val (10bit, 0x01 == 0.061°/s) - */ -static uint16_t bmi_emul_gyr_off_to_nvm(int16_t off) -{ - uint32_t twos_comp_val; - uint16_t nvm = 0; - - twos_comp_val = bmi_emul_val_to_twos_comp(off); - - /* - * LSB in internal representation has value 0.0038°/s, while in NVM - * LSB is 0.061°/s. Skip 0.0038°/s, 0.0076°/s, 0.015°/s, and - * 0.03°/s bits. - */ - nvm |= (twos_comp_val >> 4) & 0x1ff; - /* Set sign bit */ - nvm |= (twos_comp_val & BIT(31)) ? BIT(9) : 0x00; - - return nvm; -} - -/** Check description in emul_bmi.h */ -int16_t bmi_emul_get_off(struct i2c_emul *emul, enum bmi_emul_axis axis) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case BMI_EMUL_ACC_X: - return data->off_acc_x; - case BMI_EMUL_ACC_Y: - return data->off_acc_y; - case BMI_EMUL_ACC_Z: - return data->off_acc_z; - case BMI_EMUL_GYR_X: - return data->off_gyr_x; - case BMI_EMUL_GYR_Y: - return data->off_gyr_y; - case BMI_EMUL_GYR_Z: - return data->off_gyr_z; - } - - return 0; -} - -/** Check description in emul_bmi.h */ -void bmi_emul_set_off(struct i2c_emul *emul, enum bmi_emul_axis axis, - int16_t val) -{ - struct bmi_emul_data *data; - uint16_t gyr_off; - uint8_t gyr98_shift; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case BMI_EMUL_ACC_X: - data->off_acc_x = val; - data->reg[data->type_data->acc_off_reg] = - bmi_emul_acc_off_to_nvm(data->off_acc_x); - break; - case BMI_EMUL_ACC_Y: - data->off_acc_y = val; - data->reg[data->type_data->acc_off_reg + 1] = - bmi_emul_acc_off_to_nvm(data->off_acc_y); - break; - case BMI_EMUL_ACC_Z: - data->off_acc_z = val; - data->reg[data->type_data->acc_off_reg + 2] = - bmi_emul_acc_off_to_nvm(data->off_acc_z); - break; - case BMI_EMUL_GYR_X: - data->off_gyr_x = val; - gyr_off = bmi_emul_gyr_off_to_nvm(data->off_gyr_x); - data->reg[data->type_data->gyr_off_reg] = gyr_off & 0xff; - gyr98_shift = 0; - data->reg[data->type_data->gyr98_off_reg] &= - ~(0x3 << gyr98_shift); - data->reg[data->type_data->gyr98_off_reg] |= - (gyr_off & 0x300) >> (8 - gyr98_shift); - break; - case BMI_EMUL_GYR_Y: - data->off_gyr_y = val; - gyr_off = bmi_emul_gyr_off_to_nvm(data->off_gyr_y); - data->reg[data->type_data->gyr_off_reg + 1] = gyr_off & 0xff; - gyr98_shift = 2; - data->reg[data->type_data->gyr98_off_reg] &= - ~(0x3 << gyr98_shift); - data->reg[data->type_data->gyr98_off_reg] |= - (gyr_off & 0x300) >> (8 - gyr98_shift); - break; - case BMI_EMUL_GYR_Z: - data->off_gyr_z = val; - gyr_off = bmi_emul_gyr_off_to_nvm(data->off_gyr_z); - data->reg[data->type_data->gyr_off_reg + 2] = gyr_off & 0xff; - gyr98_shift = 4; - data->reg[data->type_data->gyr98_off_reg] &= - ~(0x3 << gyr98_shift); - data->reg[data->type_data->gyr98_off_reg] |= - (gyr_off & 0x300) >> (8 - gyr98_shift); - break; - } -} - -/** Check description in emul_bmi.h */ -int32_t bmi_emul_get_value(struct i2c_emul *emul, enum bmi_emul_axis axis) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case BMI_EMUL_ACC_X: - return data->acc_x; - case BMI_EMUL_ACC_Y: - return data->acc_y; - case BMI_EMUL_ACC_Z: - return data->acc_z; - case BMI_EMUL_GYR_X: - return data->gyr_x; - case BMI_EMUL_GYR_Y: - return data->gyr_y; - case BMI_EMUL_GYR_Z: - return data->gyr_z; - } - - return 0; -} - -/** Check description in emul_bmi.h */ -void bmi_emul_set_value(struct i2c_emul *emul, enum bmi_emul_axis axis, - int32_t val) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case BMI_EMUL_ACC_X: - data->acc_x = val; - break; - case BMI_EMUL_ACC_Y: - data->acc_y = val; - break; - case BMI_EMUL_ACC_Z: - data->acc_z = val; - break; - case BMI_EMUL_GYR_X: - data->gyr_x = val; - break; - case BMI_EMUL_GYR_Y: - data->gyr_y = val; - break; - case BMI_EMUL_GYR_Z: - data->gyr_z = val; - break; - } -} - -/** Check description in emul_bmi.h */ -void bmi_emul_set_err_on_ro_write(struct i2c_emul *emul, bool set) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - data->error_on_ro_write = set; -} - -/** Check description in emul_bmi.h */ -void bmi_emul_set_err_on_rsvd_write(struct i2c_emul *emul, bool set) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - data->error_on_rsvd_write = set; -} - -/** Check description in emul_bmi.h */ -void bmi_emul_set_err_on_wo_read(struct i2c_emul *emul, bool set) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - data->error_on_wo_read = set; -} - -/** Check description in emul_bmi.h */ -void bmi_emul_simulate_cmd_exec_time(struct i2c_emul *emul, bool set) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - data->simulate_command_exec_time = set; -} - -/** Check description in emul_bmi.h */ -void bmi_emul_set_skipped_frames(struct i2c_emul *emul, uint8_t skip) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - data->fifo_skip = skip; -} - -/** - * @brief Convert current time to sensor time (39 us units) - * - * @return time in 39 us units - */ -static int64_t bmi_emul_get_sensortime(void) -{ - return k_uptime_ticks() * 1000000 / 39 / CONFIG_SYS_CLOCK_TICKS_PER_SEC; -} - -/** - * @brief Set registers at address @p reg with sensor time that elapsed since - * last reset of emulator - * - * @param emul Pointer to BMI emulator - * @param reg Pointer to 3 byte array, where current sensor time should be - * stored - */ -static void bmi_emul_set_sensortime_reg(struct i2c_emul *emul, uint8_t *reg) -{ - struct bmi_emul_data *data; - uint32_t twos_comp_val; - int64_t time; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - time = bmi_emul_get_sensortime(); - - twos_comp_val = bmi_emul_val_to_twos_comp(time - data->zero_time); - - *reg = twos_comp_val & 0xff; - *(reg + 1) = (twos_comp_val >> 8) & 0xff; - *(reg + 2) = (twos_comp_val >> 16) & 0xff; -} - -/** - * @brief Convert given sensor axis @p val from internal units to register - * units. It shifts value by @p shift bits to the right to account - * range set in emulator's registers. Result is saved at address @p reg - * - * @param emul Pointer to BMI emulator - * @param val Accelerometer or gyroscope value in internal units - * @param reg Pointer to 2 byte array, where sensor value should be stored - * @param shift How many bits should be shift to the right - */ -static void bmi_emul_set_data_reg(struct i2c_emul *emul, int32_t val, - uint8_t *reg, int shift) -{ - struct bmi_emul_data *data; - uint32_t twos_comp_val; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - twos_comp_val = bmi_emul_val_to_twos_comp(val); - - /* Shift unused bits because of selected range */ - twos_comp_val >>= shift; - - *reg = twos_comp_val & 0xff; - *(reg + 1) = (twos_comp_val >> 8) & 0xff; -} - -/** - * @brief Compute length of given FIFO @p frame. If frame is null then length - * of empty frame is returned. - * - * @param emul Pointer to BMI emulator - * @param frame Pointer to FIFO frame - * @param tag_time Indicate if sensor time should be included in empty frame - * @param header Indicate if header should be included in frame - * - * @return length of frame - */ -static uint8_t bmi_emul_get_frame_len(struct i2c_emul *emul, - struct bmi_emul_frame *frame, - bool tag_time, bool header) -{ - struct bmi_emul_data *data; - int len; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - /* Empty FIFO frame */ - if (frame == NULL) { - if (tag_time && header) { - /* Header of sensortime + sensortime + empty FIFO */ - return 5; - } - - /* Empty fifo */ - return 1; - } - - /* Config FIFO frame */ - if (frame->type & BMI_EMUL_FRAME_CONFIG) { - if (header) { - /* Header + byte of data */ - len = 2; - if (data->type_data->sensortime_follow_config_frame) { - /* Sensortime data */ - len += 3; - } - - return len; - } - - /* This frame doesn't exist in headerless mode */ - return 0; - } - - /* Sensor data FIFO frame */ - if (header) { - len = 1; - } else { - len = 0; - } - - if (frame->type & BMI_EMUL_FRAME_ACC) { - len += 6; - } - if (frame->type & BMI_EMUL_FRAME_MAG) { - len += 8; - } - if (frame->type & BMI_EMUL_FRAME_GYR) { - len += 6; - } - - return len; -} - -/** - * @brief Set given FIFO @p frame as current frame in fifo field of emulator - * data structure - * - * @param emul Pointer to BMI emulator - * @param frame Pointer to FIFO frame - * @param tag_time Indicate if sensor time should be included in empty frame - * @param header Indicate if header should be included in frame - * @param acc_shift How many bits should be right shifted from accelerometer - * data - * @param gyr_shift How many bits should be right shifted from gyroscope data - */ -static void bmi_emul_set_current_frame(struct i2c_emul *emul, - struct bmi_emul_frame *frame, - bool tag_time, bool header, - int acc_shift, int gyr_shift) -{ - struct bmi_emul_data *data; - int i = 0; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - data->fifo_frame_byte = 0; - data->fifo_frame_len = bmi_emul_get_frame_len(emul, frame, tag_time, - header); - /* Empty FIFO frame */ - if (frame == NULL) { - if (tag_time && header) { - /* Header */ - data->fifo[0] = BMI_EMUL_FIFO_HEAD_TIME; - bmi_emul_set_sensortime_reg(emul, &(data->fifo[1])); - i = 4; - } - - /* Empty header */ - data->fifo[i] = BMI_EMUL_FIFO_HEAD_EMPTY; - - return; - } - - /* Config FIFO frame */ - if (frame->type & BMI_EMUL_FRAME_CONFIG) { - /* Header */ - data->fifo[0] = BMI_EMUL_FIFO_HEAD_CONFIG; - data->fifo[1] = frame->config; - if (data->type_data->sensortime_follow_config_frame) { - bmi_emul_set_sensortime_reg(emul, &(data->fifo[2])); - } - - return; - } - - /* Sensor data FIFO frame */ - if (header) { - data->fifo[0] = BMI_EMUL_FIFO_HEAD_DATA; - data->fifo[0] |= frame->type & BMI_EMUL_FRAME_MAG ? - BMI_EMUL_FIFO_HEAD_DATA_MAG : 0; - data->fifo[0] |= frame->type & BMI_EMUL_FRAME_GYR ? - BMI_EMUL_FIFO_HEAD_DATA_GYR : 0; - data->fifo[0] |= frame->type & BMI_EMUL_FRAME_ACC ? - BMI_EMUL_FIFO_HEAD_DATA_ACC : 0; - data->fifo[0] |= frame->tag & BMI_EMUL_FIFO_HEAD_DATA_TAG_MASK; - i = 1; - } - - if (frame->type & BMI_EMUL_FRAME_MAG) { - bmi_emul_set_data_reg(emul, frame->mag_x, &(data->fifo[i]), 0); - i += 2; - bmi_emul_set_data_reg(emul, frame->mag_y, &(data->fifo[i]), 0); - i += 2; - bmi_emul_set_data_reg(emul, frame->mag_z, &(data->fifo[i]), 0); - i += 2; - bmi_emul_set_data_reg(emul, frame->rhall, &(data->fifo[i]), 0); - i += 2; - } - - if (frame->type & BMI_EMUL_FRAME_GYR) { - bmi_emul_set_data_reg(emul, frame->gyr_x, &(data->fifo[i]), - gyr_shift); - i += 2; - bmi_emul_set_data_reg(emul, frame->gyr_y, &(data->fifo[i]), - gyr_shift); - i += 2; - bmi_emul_set_data_reg(emul, frame->gyr_z, &(data->fifo[i]), - gyr_shift); - i += 2; - } - - if (frame->type & BMI_EMUL_FRAME_ACC) { - bmi_emul_set_data_reg(emul, frame->acc_x, &(data->fifo[i]), - acc_shift); - i += 2; - bmi_emul_set_data_reg(emul, frame->acc_y, &(data->fifo[i]), - acc_shift); - i += 2; - bmi_emul_set_data_reg(emul, frame->acc_z, &(data->fifo[i]), - acc_shift); - i += 2; - } -} - -/** - * @brief Update internal sensors offset values using values from emulated - * registers. - * - * @param emul Pointer to BMI emulator - */ -static void bmi_emul_updata_int_off(struct i2c_emul *emul) -{ - struct bmi_emul_data *data; - uint16_t gyr_nvm; - uint8_t gyr98; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - data->off_acc_x = bmi_emul_acc_nvm_to_off( - data->reg[data->type_data->acc_off_reg]); - data->off_acc_y = bmi_emul_acc_nvm_to_off( - data->reg[data->type_data->acc_off_reg + 1]); - data->off_acc_z = bmi_emul_acc_nvm_to_off( - data->reg[data->type_data->acc_off_reg + 2]); - - gyr98 = data->reg[data->type_data->gyr98_off_reg]; - - gyr_nvm = data->reg[data->type_data->gyr_off_reg]; - gyr_nvm |= (gyr98 & 0x3) << 8; - data->off_gyr_x = bmi_emul_gyr_nvm_to_off(gyr_nvm); - gyr_nvm = data->reg[data->type_data->gyr_off_reg + 1]; - gyr_nvm |= (gyr98 & 0xc) << 6; - data->off_gyr_y = bmi_emul_gyr_nvm_to_off(gyr_nvm); - gyr_nvm = data->reg[data->type_data->gyr_off_reg + 2]; - gyr_nvm |= (gyr98 & 0x30) << 4; - data->off_gyr_z = bmi_emul_gyr_nvm_to_off(gyr_nvm); -} - -/** - * @brief Restore registers backed in NVM to emulator's registers. Each model - * of BMI may have different set of NVM backed registers. - * - * @param emul Pointer to BMI emulator - */ -static void bmi_emul_restore_nvm(struct i2c_emul *emul) -{ - struct bmi_emul_data *data; - int i; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - ASSERT(data->type_data->nvm_len <= BMI_EMUL_MAX_NVM_REGS); - - /* Restore registers values */ - for (i = 0; i < data->type_data->nvm_len; i++) { - data->reg[data->type_data->nvm_reg[i]] = data->nvm[i]; - } - - bmi_emul_updata_int_off(emul); -} - -/** Check description in emul_bmi.h */ -void bmi_emul_flush_fifo(struct i2c_emul *emul, bool tag_time, bool header) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - data->fifo_skip = 0; - data->fifo_frame = NULL; - /* - * Gyroscope and accelerometer shift (last two arguments) - * are not important for NULL (empty) FIFO frame. - */ - bmi_emul_set_current_frame(emul, NULL, tag_time, header, 0, 0); -} - -/** Check description in emul_bmi.h */ -void bmi_emul_reset_common(struct i2c_emul *emul, bool tag_time, bool header) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - /* Restore registers backed in NVM */ - bmi_emul_restore_nvm(emul); - - /* Flush FIFO */ - bmi_emul_flush_fifo(emul, tag_time, header); - - /* Reset sensor timer */ - data->zero_time = bmi_emul_get_sensortime(); -} - -/** Check description in emul_bmi.h */ -void bmi_emul_set_cmd_end_time(struct i2c_emul *emul, int time) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - data->cmd_end_time = k_uptime_get_32() + time; -} - -/** Check description in emul_bmi.h */ -bool bmi_emul_is_cmd_end(struct i2c_emul *emul) -{ - struct bmi_emul_data *data; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - /* We are simulating command execution time and it doesn't expired */ - if (data->simulate_command_exec_time && - data->cmd_end_time > k_uptime_get_32()) { - return false; - } - - return true; -} - -/** - * @brief Handle I2C write message. BMI model specific write function is called. - * It is checked if accessed register isn't RO and reserved bits are set - * to 0. Write set value of reg field of bmi emulator data ignoring - * reserved bits. If required internal sensor offset values are updated. - * - * @param emul Pointer to BMI emulator - * @param reg Register which is written - * @param val Value being written to @p reg - * @param byte Number of handled bytes in this write command - * - * @return 0 on success - * @return -EIO on error - */ -static int bmi_emul_handle_write(struct i2c_emul *emul, int reg, uint8_t val, - int byte) -{ - struct bmi_emul_data *data; - uint8_t rsvd_mask; - int ret; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - ret = data->type_data->handle_write(data->reg, emul, reg, byte, val); - reg = data->type_data->access_reg(emul, reg, byte, false /* = read */); - if (ret != 0) { - if (ret == BMI_EMUL_ACCESS_E) { - if (!data->error_on_ro_write) { - return 0; - } - LOG_ERR("Writing to reg 0x%x which is RO", reg); - } - - return -EIO; - } - - rsvd_mask = data->type_data->rsvd_mask[reg]; - - if (data->error_on_rsvd_write && rsvd_mask & val) { - LOG_ERR("Writing 0x%x to reg 0x%x with rsvd bits mask 0x%x", - val, reg, rsvd_mask); - return -EIO; - } - - /* Ignore all reserved bits */ - val &= ~rsvd_mask; - val |= data->reg[reg] & rsvd_mask; - - data->reg[reg] = val; - - if ((reg >= data->type_data->acc_off_reg && - reg <= data->type_data->acc_off_reg + 2) || - (reg >= data->type_data->gyr_off_reg && - reg <= data->type_data->gyr_off_reg + 2) || - reg == data->type_data->gyr98_off_reg) { - /* - * Internal offset value should be updated to new value of - * offset registers - */ - bmi_emul_updata_int_off(emul); - } - - return 0; -} - -/** Check description in emul_bmi.h */ -void bmi_emul_state_to_reg(struct i2c_emul *emul, int acc_shift, - int gyr_shift, int acc_reg, int gyr_reg, - int sensortime_reg, bool acc_off_en, - bool gyr_off_en) -{ - struct bmi_emul_data *data; - int32_t val[3]; - int i; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - if (gyr_off_en) { - val[0] = data->gyr_x - data->off_gyr_x; - val[1] = data->gyr_y - data->off_gyr_y; - val[2] = data->gyr_z - data->off_gyr_z; - } else { - val[0] = data->gyr_x; - val[1] = data->gyr_y; - val[2] = data->gyr_z; - } - - for (i = 0; i < 3; i++) { - bmi_emul_set_data_reg(emul, val[i], - &(data->reg[gyr_reg + i * 2]), gyr_shift); - } - - if (acc_off_en) { - val[0] = data->acc_x - data->off_acc_x; - val[1] = data->acc_y - data->off_acc_y; - val[2] = data->acc_z - data->off_acc_z; - } else { - val[0] = data->acc_x; - val[1] = data->acc_y; - val[2] = data->acc_z; - } - - for (i = 0; i < 3; i++) { - bmi_emul_set_data_reg(emul, val[i], - &(data->reg[acc_reg + i * 2]), acc_shift); - } - - bmi_emul_set_sensortime_reg(emul, &(data->reg[sensortime_reg])); -} - -/** Check description in emul_bmi.h */ -void bmi_emul_append_frame(struct i2c_emul *emul, struct bmi_emul_frame *frame) -{ - struct bmi_emul_data *data; - struct bmi_emul_frame *tmp_frame; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - if (data->fifo_frame == NULL) { - data->fifo_frame = frame; - } else { - tmp_frame = data->fifo_frame; - while (tmp_frame->next != NULL) { - tmp_frame = tmp_frame->next; - } - tmp_frame->next = frame; - } -} - -/** Check description in emul_bmi.h */ -uint16_t bmi_emul_fifo_len(struct i2c_emul *emul, bool tag_time, bool header) -{ - struct bmi_emul_frame *frame; - struct bmi_emul_data *data; - uint16_t len = 0; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - if (data->fifo_skip != 0 && header) { - len += 2; - } - - frame = data->fifo_frame; - while (frame != NULL) { - len += bmi_emul_get_frame_len(emul, frame, tag_time, header); - frame = frame->next; - } - - len += bmi_emul_get_frame_len(emul, NULL, tag_time, header); - /* Do not count last empty frame byte */ - len--; - - return len; -} - -/** Check description in emul_bmi.h */ -uint8_t bmi_emul_get_fifo_data(struct i2c_emul *emul, int byte, - bool tag_time, bool header, int acc_shift, - int gyr_shift) -{ - struct bmi_emul_data *data; - int ret; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - if (byte == 0) { - /* Repeat uncompleated read of frame */ - bmi_emul_set_current_frame(emul, data->fifo_frame, tag_time, - header, acc_shift, gyr_shift); - - /* Return header for skip frame */ - if (data->fifo_skip != 0 && header) { - return BMI_EMUL_FIFO_HEAD_SKIP; - } - } - - if (data->fifo_skip != 0 && byte == 1 && header) { - /* Return number of skipped frames */ - ret = data->fifo_skip; - data->fifo_skip = 0; - - return ret; - } - - /* Get next valid frame */ - while (data->fifo_frame_byte >= data->fifo_frame_len) { - /* No data */ - if (data->fifo_frame == NULL) { - return 0; - } - data->fifo_frame = data->fifo_frame->next; - bmi_emul_set_current_frame(emul, data->fifo_frame, tag_time, - header, acc_shift, gyr_shift); - } - - return data->fifo[data->fifo_frame_byte++]; -} - -/** - * @brief Handle I2C read message. BMI model specific read function is called. - * It is checked if accessed register isn't WO. - * - * @param emul Pointer to BMI emulator - * @param reg Register address to read - * @param buf Pointer where result should be stored - * @param byte Byte which is accessed during block read - * - * @return 0 on success - * @return -EIO on error - */ -static int bmi_emul_handle_read(struct i2c_emul *emul, int reg, uint8_t *buf, - int byte) -{ - struct bmi_emul_data *data; - int ret; - - data = BMI_DATA_FROM_I2C_EMUL(emul); - - ret = data->type_data->handle_read(data->reg, emul, reg, byte, buf); - reg = data->type_data->access_reg(emul, reg, byte, true /* = read */); - if (ret == BMI_EMUL_ACCESS_E && data->error_on_wo_read) { - LOG_ERR("Reading reg 0x%x which is WO", reg); - } else if (ret != 0) { - return ret; - } - - return 0; -} - -/* Device instantiation */ - -static struct i2c_emul_api bmi_emul_api = { - .transfer = i2c_common_emul_transfer, -}; - -/** - * @brief Set up a new BMI emulator - * - * This should be called for each BMI device that needs to be - * emulated. It registers it with the I2C emulation controller. - * - * @param emul Emulation information - * @param parent Device to emulate - * - * @return 0 indicating success (always) - */ -static int bmi_emul_init(const struct emul *emul, - const struct device *parent) -{ - const struct i2c_common_emul_cfg *cfg = emul->cfg; - struct i2c_common_emul_data *data = cfg->data; - struct bmi_emul_data *bmi_data; - int ret; - - data->emul.api = &bmi_emul_api; - data->emul.addr = cfg->addr; - data->i2c = parent; - data->cfg = cfg; - i2c_common_emul_init(data); - - bmi_data = CONTAINER_OF(data, struct bmi_emul_data, common); - - switch (bmi_data->type) { - case BMI_EMUL_160: - bmi_data->type_data = get_bmi160_emul_type_data(); - break; - case BMI_EMUL_260: - bmi_data->type_data = get_bmi260_emul_type_data(); - break; - } - - /* Set callback access_reg to type specific function */ - data->access_reg = bmi_data->type_data->access_reg; - - ret = i2c_emul_register(parent, emul->dev_label, &data->emul); - - bmi_data->type_data->reset(bmi_data->reg, &data->emul); - - return ret; -} - -#define BMI_EMUL(n) \ - static struct bmi_emul_data bmi_emul_data_##n = { \ - .error_on_ro_write = DT_INST_PROP(n, error_on_ro_write),\ - .error_on_wo_read = DT_INST_PROP(n, error_on_wo_read), \ - .error_on_rsvd_write = DT_INST_PROP(n, \ - error_on_reserved_bit_write), \ - .simulate_command_exec_time = DT_INST_PROP(n, \ - simulate_command_exec_time), \ - .type = DT_STRING_TOKEN(DT_DRV_INST(n), device_model), \ - .common = { \ - .start_write = NULL, \ - .write_byte = bmi_emul_handle_write, \ - .finish_write = NULL, \ - .start_read = NULL, \ - .read_byte = bmi_emul_handle_read, \ - .finish_read = NULL, \ - .access_reg = NULL, \ - }, \ - }; \ - \ - static const struct i2c_common_emul_cfg bmi_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .dev_label = DT_INST_LABEL(n), \ - .data = &bmi_emul_data_##n.common, \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - EMUL_DEFINE(bmi_emul_init, DT_DRV_INST(n), &bmi_emul_cfg_##n, \ - &bmi_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(BMI_EMUL) - -#define BMI_EMUL_CASE(n) \ - case DT_INST_DEP_ORD(n): return &bmi_emul_data_##n.common.emul; - -/** Check description in emul_bmi.h */ -struct i2c_emul *bmi_emul_get(int ord) -{ - switch (ord) { - DT_INST_FOREACH_STATUS_OKAY(BMI_EMUL_CASE) - - default: - return NULL; - } -} diff --git a/zephyr/emul/emul_bmi160.c b/zephyr/emul/emul_bmi160.c deleted file mode 100644 index 2a68b688ff..0000000000 --- a/zephyr/emul/emul_bmi160.c +++ /dev/null @@ -1,770 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT zephyr_bmi - -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(emul_bmi160); - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_bmi.h" - -#include "driver/accelgyro_bmi160.h" -#include "driver/accelgyro_bmi_common.h" - -/** Mask reserved bits in each register of BMI160 */ -static const uint8_t bmi_emul_160_rsvd_mask[] = { - [BMI160_CHIP_ID] = 0x00, - [0x01] = 0xff, /* Reserved */ - [BMI160_ERR_REG] = 0x00, - [BMI160_PMU_STATUS] = 0xc0, - [BMI160_MAG_X_L_G] = 0x00, - [BMI160_MAG_X_H_G] = 0x00, - [BMI160_MAG_Y_L_G] = 0x00, - [BMI160_MAG_Y_H_G] = 0x00, - [BMI160_MAG_Z_L_G] = 0x00, - [BMI160_MAG_Z_H_G] = 0x00, - [BMI160_RHALL_L_G] = 0x00, - [BMI160_RHALL_H_G] = 0x00, - [BMI160_GYR_X_L_G] = 0x00, - [BMI160_GYR_X_H_G] = 0x00, - [BMI160_GYR_Y_L_G] = 0x00, - [BMI160_GYR_Y_H_G] = 0x00, - [BMI160_GYR_Z_L_G] = 0x00, - [BMI160_GYR_Z_H_G] = 0x00, - [BMI160_ACC_X_L_G] = 0x00, - [BMI160_ACC_X_H_G] = 0x00, - [BMI160_ACC_Y_L_G] = 0x00, - [BMI160_ACC_Y_H_G] = 0x00, - [BMI160_ACC_Z_L_G] = 0x00, - [BMI160_ACC_Z_H_G] = 0x00, - [BMI160_SENSORTIME_0] = 0x00, - [BMI160_SENSORTIME_1] = 0x00, - [BMI160_SENSORTIME_2] = 0x00, - [BMI160_STATUS] = 0x01, - [BMI160_INT_STATUS_0] = 0x00, - [BMI160_INT_STATUS_1] = 0x03, - [BMI160_INT_STATUS_2] = 0x00, - [BMI160_INT_STATUS_3] = 0x00, - [BMI160_TEMPERATURE_0] = 0x00, - [BMI160_TEMPERATURE_1] = 0x00, - [BMI160_FIFO_LENGTH_0] = 0x00, - [BMI160_FIFO_LENGTH_1] = 0xf8, - [BMI160_FIFO_DATA] = 0x00, - [0x25 ... 0x3f] = 0xff, /* Reserved */ - [BMI160_ACC_CONF] = 0x00, - [BMI160_ACC_RANGE] = 0xf0, - [BMI160_GYR_CONF] = 0xc0, - [BMI160_GYR_RANGE] = 0xf8, - [BMI160_MAG_CONF] = 0xf0, - [BMI160_FIFO_DOWNS] = 0x00, - [BMI160_FIFO_CONFIG_0] = 0x00, - [BMI160_FIFO_CONFIG_1] = 0x01, - [0x48 ... 0x4a] = 0xff, /* Reserved */ - [BMI160_MAG_IF_0] = 0x01, - [BMI160_MAG_IF_1] = 0x40, - [BMI160_MAG_IF_2] = 0x00, - [BMI160_MAG_IF_3] = 0x00, - [BMI160_MAG_IF_4] = 0x00, - [BMI160_INT_EN_0] = 0x08, - [BMI160_INT_EN_1] = 0x80, - [BMI160_INT_EN_2] = 0xf0, - [BMI160_INT_OUT_CTRL] = 0x00, - [BMI160_INT_LATCH] = 0xc0, - [BMI160_INT_MAP_0] = 0x00, - [BMI160_INT_MAP_1] = 0x00, - [BMI160_INT_MAP_2] = 0x00, - [BMI160_INT_DATA_0] = 0x77, - [BMI160_INT_DATA_1] = 0x7f, - [BMI160_INT_LOW_HIGH_0] = 0x00, - [BMI160_INT_LOW_HIGH_1] = 0x00, - [BMI160_INT_LOW_HIGH_2] = 0x3c, - [BMI160_INT_LOW_HIGH_3] = 0x00, - [BMI160_INT_LOW_HIGH_4] = 0x00, - [BMI160_INT_MOTION_0] = 0x00, - [BMI160_INT_MOTION_1] = 0x00, - [BMI160_INT_MOTION_2] = 0x00, - [BMI160_INT_MOTION_3] = 0xc0, - [BMI160_INT_TAP_0] = 0x38, - [BMI160_INT_TAP_1] = 0xe0, - [BMI160_INT_ORIENT_0] = 0x00, - [BMI160_INT_ORIENT_1] = 0x00, - [BMI160_INT_FLAT_0] = 0xc0, - [BMI160_INT_FLAT_1] = 0xc8, - [BMI160_FOC_CONF] = 0x80, - [BMI160_CONF] = 0xfd, - [BMI160_IF_CONF] = 0xce, - [BMI160_PMU_TRIGGER] = 0x80, - [BMI160_SELF_TEST] = 0xe0, - [0x6e] = 0xff, /* Reserved */ - [0x6f] = 0xff, /* Reserved */ - [BMI160_NV_CONF] = 0xf0, - [BMI160_OFFSET_ACC70] = 0x00, - [BMI160_OFFSET_ACC70 + 1] = 0x00, - [BMI160_OFFSET_ACC70 + 2] = 0x00, - [BMI160_OFFSET_GYR70] = 0x00, - [BMI160_OFFSET_GYR70 + 1] = 0x00, - [BMI160_OFFSET_GYR70 + 2] = 0x00, - [BMI160_OFFSET_EN_GYR98] = 0x00, - [BMI160_STEP_CNT_0] = 0x00, - [BMI160_STEP_CNT_1] = 0x00, - [BMI160_STEP_CONF_0] = 0x00, - [BMI160_STEP_CONF_1] = 0xf0, - [0x7c] = 0xff, /* Reserved */ - [0x7d] = 0xff, /* Reserved */ - [BMI160_CMD_REG] = 0x00, -}; - -/** - * @brief Convert range in format of ACC_RANGE register to number of bits - * that should be shifted right to obtain 16 bit reported accelerometer - * value from internal 32 bit value - * - * @param range Value of ACC_RANGE register - * - * @return shift Number of LSB that should be ignored from internal - * accelerometer value - */ -static int bmi160_emul_acc_range_to_shift(uint8_t range) -{ - switch (range & 0xf) { - case BMI160_GSEL_2G: - return 0; - case BMI160_GSEL_4G: - return 1; - case BMI160_GSEL_8G: - return 2; - case BMI160_GSEL_16G: - return 3; - default: - return 0; - } -} - -/** - * @brief Convert range in format of GYR_RANGE register to number of bits - * that should be shifted right to obtain 16 bit reported gyroscope - * value from internal 32 bit value - * - * @param range Value of GYR_RANGE register - * - * @return shift Number of LSB that should be ignored from internal - * gyroscope value - */ -static int bmi160_emul_gyr_range_to_shift(uint8_t range) -{ - switch (range & 0x7) { - case BMI160_DPS_SEL_2000: - return 4; - case BMI160_DPS_SEL_1000: - return 3; - case BMI160_DPS_SEL_500: - return 2; - case BMI160_DPS_SEL_250: - return 1; - case BMI160_DPS_SEL_125: - return 0; - default: - return 0; - } -} - -/** - * @brief Reset registers to default values and restore registers backed by NVM - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - */ -static void bmi160_emul_reset(uint8_t *regs, struct i2c_emul *emul) -{ - bool tag_time; - bool header; - - regs[BMI160_CHIP_ID] = 0xd1; - regs[BMI160_ERR_REG] = 0x00; - regs[BMI160_PMU_STATUS] = 0x00; - regs[BMI160_MAG_X_L_G] = 0x00; - regs[BMI160_MAG_X_H_G] = 0x00; - regs[BMI160_MAG_Y_L_G] = 0x00; - regs[BMI160_MAG_Y_H_G] = 0x00; - regs[BMI160_MAG_Z_L_G] = 0x00; - regs[BMI160_MAG_Z_H_G] = 0x00; - regs[BMI160_RHALL_L_G] = 0x00; - regs[BMI160_RHALL_H_G] = 0x00; - regs[BMI160_GYR_X_L_G] = 0x00; - regs[BMI160_GYR_X_H_G] = 0x00; - regs[BMI160_GYR_Y_L_G] = 0x00; - regs[BMI160_GYR_Y_H_G] = 0x00; - regs[BMI160_GYR_Z_L_G] = 0x00; - regs[BMI160_GYR_Z_H_G] = 0x00; - regs[BMI160_ACC_X_L_G] = 0x00; - regs[BMI160_ACC_X_H_G] = 0x00; - regs[BMI160_ACC_Y_L_G] = 0x00; - regs[BMI160_ACC_Y_H_G] = 0x00; - regs[BMI160_ACC_Z_L_G] = 0x00; - regs[BMI160_ACC_Z_H_G] = 0x00; - regs[BMI160_SENSORTIME_0] = 0x00; - regs[BMI160_SENSORTIME_1] = 0x00; - regs[BMI160_SENSORTIME_2] = 0x00; - regs[BMI160_STATUS] = 0x01; - regs[BMI160_INT_STATUS_0] = 0x00; - regs[BMI160_INT_STATUS_1] = 0x00; - regs[BMI160_INT_STATUS_2] = 0x00; - regs[BMI160_INT_STATUS_3] = 0x00; - regs[BMI160_TEMPERATURE_0] = 0x00; - regs[BMI160_TEMPERATURE_1] = 0x00; - regs[BMI160_FIFO_LENGTH_0] = 0x00; - regs[BMI160_FIFO_LENGTH_1] = 0x00; - regs[BMI160_FIFO_DATA] = 0x00; - regs[BMI160_ACC_CONF] = 0x28; - regs[BMI160_ACC_RANGE] = 0x03; - regs[BMI160_GYR_CONF] = 0x28; - regs[BMI160_GYR_RANGE] = 0x00; - regs[BMI160_MAG_CONF] = 0x0b; - regs[BMI160_FIFO_DOWNS] = 0x88; - regs[BMI160_FIFO_CONFIG_0] = 0x80; - regs[BMI160_FIFO_CONFIG_1] = 0x10; - regs[BMI160_MAG_IF_0] = 0x20; - regs[BMI160_MAG_IF_1] = 0x80; - regs[BMI160_MAG_IF_2] = 0x42; - regs[BMI160_MAG_IF_3] = 0x4c; - regs[BMI160_MAG_IF_4] = 0x00; - regs[BMI160_INT_EN_0] = 0x00; - regs[BMI160_INT_EN_1] = 0x00; - regs[BMI160_INT_EN_2] = 0x00; - regs[BMI160_INT_OUT_CTRL] = 0x00; - regs[BMI160_INT_LATCH] = 0x00; - regs[BMI160_INT_MAP_0] = 0x00; - regs[BMI160_INT_MAP_1] = 0x00; - regs[BMI160_INT_MAP_2] = 0x00; - regs[BMI160_INT_DATA_0] = 0x00; - regs[BMI160_INT_DATA_1] = 0x00; - regs[BMI160_INT_LOW_HIGH_0] = 0x07; - regs[BMI160_INT_LOW_HIGH_1] = 0x30; - regs[BMI160_INT_LOW_HIGH_2] = 0x81; - regs[BMI160_INT_LOW_HIGH_3] = 0xdb; - regs[BMI160_INT_LOW_HIGH_4] = 0xc0; - regs[BMI160_INT_MOTION_0] = 0x00; - regs[BMI160_INT_MOTION_1] = 0x14; - regs[BMI160_INT_MOTION_2] = 0x14; - regs[BMI160_INT_MOTION_3] = 0x24; - regs[BMI160_INT_TAP_0] = 0x04; - regs[BMI160_INT_TAP_1] = 0xda; - regs[BMI160_INT_ORIENT_0] = 0x18; - regs[BMI160_INT_ORIENT_1] = 0x48; - regs[BMI160_INT_FLAT_0] = 0x08; - regs[BMI160_INT_FLAT_1] = 0x11; - regs[BMI160_FOC_CONF] = 0x00; - regs[BMI160_CONF] = 0x00; - regs[BMI160_IF_CONF] = 0x00; - regs[BMI160_PMU_TRIGGER] = 0x00; - regs[BMI160_SELF_TEST] = 0x00; - regs[BMI160_STEP_CNT_0] = 0x00; - regs[BMI160_STEP_CNT_1] = 0x00; - regs[BMI160_STEP_CONF_0] = 0x00; - regs[BMI160_STEP_CONF_1] = 0x15; - regs[BMI160_CMD_REG] = 0x03; - - /* Call generic reset */ - tag_time = regs[BMI160_FIFO_CONFIG_1] & BMI160_FIFO_TAG_TIME_EN; - header = regs[BMI160_FIFO_CONFIG_1] & BMI160_FIFO_HEADER_EN; - bmi_emul_reset_common(emul, tag_time, header); -} - -/** - * @brief Clear all interrupt registers - * - * @param regs Pointer to array of emulator's registers - */ -static void bmi160_emul_clear_int(uint8_t *regs) -{ - regs[BMI160_INT_STATUS_0] = 0x00; - regs[BMI160_INT_STATUS_1] = 0x00; - regs[BMI160_INT_STATUS_2] = 0x00; - regs[BMI160_INT_STATUS_3] = 0x00; -} - -/** - * @brief Get offset value for given gyroscope value. If gyroscope value is - * above maximum (belowe minimum), then minimum -31,25°/s - * (maximum 31,25°/s) offset value is returned. - * - * @param gyr Gyroscope value - */ -static int16_t bmi160_emul_get_gyr_target_off(int32_t gyr) -{ - if (gyr > (int32_t)BMI_EMUL_125_DEG_S / 4) { - return -((int32_t)BMI_EMUL_125_DEG_S / 4); - } - - if (gyr < -((int32_t)BMI_EMUL_125_DEG_S / 4)) { - return BMI_EMUL_125_DEG_S / 4; - } - - return -gyr; -} - -/** - * @brief Get offset value for given accelerometer value. If accelerometer - * value - target is above maximum (belowe minimum), then minimum -0.5g - * (maximum 0.5g) offset value is returned. - * - * @param acc Accelerometer value - * @param target Target value in FOC configuration register format - */ -static int16_t bmi160_emul_get_acc_target_off(int32_t acc, uint8_t target) -{ - switch (target) { - case BMI160_FOC_ACC_PLUS_1G: - acc -= BMI_EMUL_1G; - break; - case BMI160_FOC_ACC_MINUS_1G: - acc += BMI_EMUL_1G; - break; - } - - if (acc > (int32_t)BMI_EMUL_1G / 2) { - return -((int32_t)BMI_EMUL_1G / 2); - } - - if (acc < -((int32_t)BMI_EMUL_1G / 2)) { - return BMI_EMUL_1G / 2; - } - - return -acc; -} - -/** - * @brief Handle fast offset compensation. Check FOC configuration register - * and sets gyroscope and/or accelerometer offset using current emulator - * state. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - */ -static void bmi160_emul_handle_off_comp(uint8_t *regs, struct i2c_emul *emul) -{ - uint8_t target; - int16_t off; - int32_t val; - - if (regs[BMI160_FOC_CONF] & BMI160_FOC_GYRO_EN) { - val = bmi_emul_get_value(emul, BMI_EMUL_GYR_X); - off = bmi160_emul_get_gyr_target_off(val); - bmi_emul_set_off(emul, BMI_EMUL_GYR_X, off); - val = bmi_emul_get_value(emul, BMI_EMUL_GYR_Y); - off = bmi160_emul_get_gyr_target_off(val); - bmi_emul_set_off(emul, BMI_EMUL_GYR_Y, off); - val = bmi_emul_get_value(emul, BMI_EMUL_GYR_Z); - off = bmi160_emul_get_gyr_target_off(val); - bmi_emul_set_off(emul, BMI_EMUL_GYR_Z, off); - } - - target = (regs[BMI160_FOC_CONF] >> BMI160_FOC_ACC_X_OFFSET) & 0x3; - if (target) { - val = bmi_emul_get_value(emul, BMI_EMUL_ACC_X); - off = bmi160_emul_get_acc_target_off(val, target); - bmi_emul_set_off(emul, BMI_EMUL_ACC_X, off); - } - - target = (regs[BMI160_FOC_CONF] >> BMI160_FOC_ACC_Y_OFFSET) & 0x3; - if (target) { - val = bmi_emul_get_value(emul, BMI_EMUL_ACC_Y); - off = bmi160_emul_get_acc_target_off(val, target); - bmi_emul_set_off(emul, BMI_EMUL_ACC_Y, off); - } - - target = (regs[BMI160_FOC_CONF] >> BMI160_FOC_ACC_Z_OFFSET) & 0x3; - if (target) { - val = bmi_emul_get_value(emul, BMI_EMUL_ACC_Z); - off = bmi160_emul_get_acc_target_off(val, target); - bmi_emul_set_off(emul, BMI_EMUL_ACC_Z, off); - } -} - -/** - * @brief Execute first part of command. Emulate state of device which is - * during handling command (status bits etc). This function save time - * on which command should end. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - * @param cmd Command that is starting - * - * @return 0 on success - * @return -EIO on failure - */ -static int bmi160_emul_start_cmd(uint8_t *regs, struct i2c_emul *emul, int cmd) -{ - int time; - - switch (cmd) { - case BMI160_CMD_SOFT_RESET: - time = 1; - break; - case BMI160_CMD_START_FOC: - if ((regs[BMI160_FOC_CONF] & BMI160_FOC_GYRO_EN) && - ((regs[BMI160_PMU_STATUS] & - (0x3 << BMI160_PMU_GYR_OFFSET)) != - BMI160_PMU_NORMAL << BMI160_PMU_GYR_OFFSET)) { - LOG_ERR("Starting gyroscope FOC in low power mode"); - return -EIO; - } - - if ((regs[BMI160_FOC_CONF] & ~BMI160_FOC_GYRO_EN) && - ((regs[BMI160_PMU_STATUS] & - (0x3 << BMI160_PMU_ACC_OFFSET)) != - BMI160_PMU_NORMAL << BMI160_PMU_ACC_OFFSET)) { - LOG_ERR("Starting accelerometer FOC in low power mode"); - return -EIO; - } - - regs[BMI160_STATUS] &= ~BMI160_FOC_RDY; - time = 250; - break; - case BMI160_CMD_ACC_MODE_SUSP: - case BMI160_CMD_GYR_MODE_SUSP: - case BMI160_CMD_MAG_MODE_SUSP: - time = 0; - break; - /* Real hardware probably switch faster if not in suspend mode */ - case BMI160_CMD_ACC_MODE_NORMAL: - case BMI160_CMD_ACC_MODE_LOWPOWER: - time = 4; - break; - case BMI160_CMD_GYR_MODE_NORMAL: - case BMI160_CMD_GYR_MODE_FAST_STARTUP: - time = 80; - break; - case BMI160_CMD_MAG_MODE_NORMAL: - case BMI160_CMD_MAG_MODE_LOWPOWER: - time = 1; - break; - case BMI160_CMD_FIFO_FLUSH: - time = 0; - break; - case BMI160_CMD_INT_RESET: - time = 0; - break; - default: - LOG_ERR("Unknown command 0x%x", cmd); - return -EIO; - } - - regs[BMI160_CMD_REG] = cmd; - bmi_emul_set_cmd_end_time(emul, time); - - return 0; -} - -/** - * @brief Emulate end of ongoing command. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - */ -static void bmi160_emul_end_cmd(uint8_t *regs, struct i2c_emul *emul) -{ - uint8_t pmu_status; - bool tag_time; - bool header; - int cmd; - - pmu_status = regs[BMI160_PMU_STATUS]; - cmd = regs[BMI160_CMD_REG]; - regs[BMI160_CMD_REG] = BMI160_CMD_NOOP; - tag_time = regs[BMI160_FIFO_CONFIG_1] & BMI160_FIFO_TAG_TIME_EN; - header = regs[BMI160_FIFO_CONFIG_1] & BMI160_FIFO_HEADER_EN; - - switch (cmd) { - case BMI160_CMD_SOFT_RESET: - bmi160_emul_reset(regs, emul); - break; - case BMI160_CMD_START_FOC: - bmi160_emul_handle_off_comp(regs, emul); - regs[BMI160_STATUS] |= BMI160_FOC_RDY; - break; - case BMI160_CMD_ACC_MODE_SUSP: - pmu_status &= ~(0x3 << BMI160_PMU_ACC_OFFSET); - pmu_status |= BMI160_PMU_SUSPEND << BMI160_PMU_ACC_OFFSET; - break; - case BMI160_CMD_ACC_MODE_NORMAL: - pmu_status &= ~(0x3 << BMI160_PMU_ACC_OFFSET); - pmu_status |= BMI160_PMU_NORMAL << BMI160_PMU_ACC_OFFSET; - break; - case BMI160_CMD_ACC_MODE_LOWPOWER: - pmu_status &= ~(0x3 << BMI160_PMU_ACC_OFFSET); - pmu_status |= BMI160_PMU_LOW_POWER << BMI160_PMU_ACC_OFFSET; - break; - case BMI160_CMD_GYR_MODE_SUSP: - pmu_status &= ~(0x3 << BMI160_PMU_GYR_OFFSET); - pmu_status |= BMI160_PMU_SUSPEND << BMI160_PMU_GYR_OFFSET; - break; - case BMI160_CMD_GYR_MODE_NORMAL: - pmu_status &= ~(0x3 << BMI160_PMU_GYR_OFFSET); - pmu_status |= BMI160_PMU_NORMAL << BMI160_PMU_GYR_OFFSET; - break; - case BMI160_CMD_GYR_MODE_FAST_STARTUP: - pmu_status &= ~(0x3 << BMI160_PMU_GYR_OFFSET); - pmu_status |= BMI160_PMU_FAST_STARTUP << BMI160_PMU_GYR_OFFSET; - break; - case BMI160_CMD_MAG_MODE_SUSP: - pmu_status &= ~(0x3 << BMI160_PMU_MAG_OFFSET); - pmu_status |= BMI160_PMU_SUSPEND << BMI160_PMU_MAG_OFFSET; - break; - case BMI160_CMD_MAG_MODE_NORMAL: - pmu_status &= ~(0x3 << BMI160_PMU_MAG_OFFSET); - pmu_status |= BMI160_PMU_NORMAL << BMI160_PMU_MAG_OFFSET; - break; - case BMI160_CMD_MAG_MODE_LOWPOWER: - pmu_status &= ~(0x3 << BMI160_PMU_MAG_OFFSET); - pmu_status |= BMI160_PMU_LOW_POWER << BMI160_PMU_MAG_OFFSET; - break; - case BMI160_CMD_FIFO_FLUSH: - bmi_emul_flush_fifo(emul, tag_time, header); - break; - case BMI160_CMD_INT_RESET: - bmi160_emul_clear_int(regs); - break; - } - - /* Clear FIFO on sensor on/off in headerless mode */ - if (pmu_status != regs[BMI160_PMU_STATUS] && !header) { - bmi_emul_flush_fifo(emul, tag_time, header); - } - - regs[BMI160_PMU_STATUS] = pmu_status; -} - -/** - * @brief BMI160 specific write function. It doesn't handle block writes. - * Check if read only register is not accessed. Before writing value, - * ongoing command is finished if possible. Write to CMD register is - * handled by BMI160 specific function. On changing of FIFO - * header/headerless mode, FIFO is flushed. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - * @param reg Register address that is accessed - * @param byte Number of handled bytes in this write command - * @param val Value that is being written - * - * @return 0 on success - * @return BMI_EMUL_ACCESS_E on RO register access - * @return -EIO on error - */ -static int bmi160_emul_handle_write(uint8_t *regs, struct i2c_emul *emul, - int reg, int byte, uint8_t val) -{ - bool tag_time; - bool header; - - if (byte > 1) { - LOG_ERR("Block writes are not allowed"); - return -EIO; - } - - if (reg <= BMI160_FIFO_DATA || - (reg >= BMI160_STEP_CNT_0 && reg <= BMI160_STEP_CNT_1)) { - return BMI_EMUL_ACCESS_E; - } - - /* Stop on going command if required */ - if (regs[BMI160_CMD_REG] != BMI160_CMD_NOOP && - bmi_emul_is_cmd_end(emul)) { - bmi160_emul_end_cmd(regs, emul); - } - - switch (reg) { - case BMI160_CMD_REG: - if (regs[BMI160_CMD_REG] != BMI160_CMD_NOOP) { - LOG_ERR("Issued command before previous end"); - return -EIO; - } - - return bmi160_emul_start_cmd(regs, emul, val); - case BMI160_FIFO_CONFIG_1: - tag_time = regs[BMI160_FIFO_CONFIG_1] & BMI160_FIFO_TAG_TIME_EN; - header = regs[BMI160_FIFO_CONFIG_1] & BMI160_FIFO_HEADER_EN; - /* - * Clear FIFO on transition between headerless and - * header mode - */ - if (!!(val & BMI160_FIFO_HEADER_EN) != header) { - bmi_emul_flush_fifo(emul, tag_time, header); - } - break; - } - - return 0; -} - -/** - * @brief Get currently accessed register. It is first register plus number of - * handled bytes for all registers except BMI160_FIFO_DATA for which - * address incrementation is disabled. - * - * @param emul Pointer to BMI emulator - * @param reg First byte of last write message - * @param bytes Number of bytes already handled from current message - * @param read If currently handled is read message - * - * @return Currently accessed register - */ -static int bmi160_emul_access_reg(struct i2c_emul *emul, int reg, int byte, - bool read) -{ - if (!read) { - return reg; - } - - /* - * If register is FIFO data, then read data from FIFO. - * Else block read access subsequent registers. - */ - if (reg <= BMI160_FIFO_DATA && reg + byte >= BMI160_FIFO_DATA) { - return BMI160_FIFO_DATA; - } - - return reg + byte; -} - -/** - * @brief BMI160 specific read function. It handle block reads but only if - * device is not suspended. FIFO data register is trap register, so - * after reaching it, register address is not increased on block reads. - * Before reading value, ongoing command is finished if possible. - * Read of sensor data traps current emulator state in registers. - * Read of FIFO length and FIFO data triggers default BMI functions. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - * @param reg Register address that is accessed - * @param byte Byte which is accessed during block read - * @param buf Pointer where read byte should be stored - * - * @return 0 on success - * @return BMI_EMUL_ACCESS_E on WO register access - * @return -EIO on other error - */ -static int bmi160_emul_handle_read(uint8_t *regs, struct i2c_emul *emul, - int reg, int byte, char *buf) -{ - uint16_t fifo_len; - bool acc_off_en; - bool gyr_off_en; - bool tag_time; - bool header; - int gyr_shift; - int acc_shift; - int fifo_byte; - - /* Get number of bytes readed from FIFO */ - fifo_byte = byte - (reg - BMI160_FIFO_DATA); - - reg = bmi160_emul_access_reg(emul, reg, byte, true /* = read */); - - /* Stop on going command if required */ - if (regs[BMI160_CMD_REG] != BMI160_CMD_NOOP && - bmi_emul_is_cmd_end(emul)) { - bmi160_emul_end_cmd(regs, emul); - } - - /* Burst reads are not supported if all sensors are in suspend mode */ - if ((regs[BMI160_PMU_STATUS] & 0x3f) == 0 && byte > 0) { - LOG_ERR("Block reads are not supported in suspend mode"); - return -EIO; - } - - tag_time = regs[BMI160_FIFO_CONFIG_1] & BMI160_FIFO_TAG_TIME_EN; - header = regs[BMI160_FIFO_CONFIG_1] & BMI160_FIFO_HEADER_EN; - acc_off_en = regs[BMI160_OFFSET_EN_GYR98] & BMI160_OFFSET_ACC_EN; - gyr_off_en = regs[BMI160_OFFSET_EN_GYR98] & BMI160_OFFSET_GYRO_EN; - gyr_shift = bmi160_emul_gyr_range_to_shift(regs[BMI160_GYR_RANGE]); - acc_shift = bmi160_emul_acc_range_to_shift(regs[BMI160_ACC_RANGE]); - - switch (reg) { - case BMI160_GYR_X_L_G: - case BMI160_GYR_X_H_G: - case BMI160_GYR_Y_L_G: - case BMI160_GYR_Y_H_G: - case BMI160_GYR_Z_L_G: - case BMI160_GYR_Z_H_G: - case BMI160_ACC_X_L_G: - case BMI160_ACC_X_H_G: - case BMI160_ACC_Y_L_G: - case BMI160_ACC_Y_H_G: - case BMI160_ACC_Z_L_G: - case BMI160_ACC_Z_H_G: - case BMI160_SENSORTIME_0: - case BMI160_SENSORTIME_1: - case BMI160_SENSORTIME_2: - /* - * Snapshot of current emulator state is created on data read - * and shouldn't be changed until next I2C operation - */ - if (byte == 0) { - bmi_emul_state_to_reg(emul, acc_shift, gyr_shift, - BMI160_ACC_X_L_G, - BMI160_GYR_X_L_G, - BMI160_SENSORTIME_0, - acc_off_en, gyr_off_en); - } - break; - case BMI160_FIFO_LENGTH_0: - case BMI160_FIFO_LENGTH_1: - if (byte == 0) { - fifo_len = bmi_emul_fifo_len(emul, tag_time, header); - regs[BMI160_FIFO_LENGTH_0] = fifo_len & 0xff; - regs[BMI160_FIFO_LENGTH_1] = (fifo_len >> 8) & 0x7; - } - break; - case BMI160_FIFO_DATA: - regs[reg] = bmi_emul_get_fifo_data(emul, fifo_byte, tag_time, - header, acc_shift, - gyr_shift); - break; - } - - *buf = regs[reg]; - - return 0; -} - -/** Registers backed in NVM by BMI160 */ -const int bmi160_nvm_reg[] = {BMI160_NV_CONF, - BMI160_OFFSET_ACC70, - BMI160_OFFSET_ACC70 + 1, - BMI160_OFFSET_ACC70 + 2, - BMI160_OFFSET_GYR70, - BMI160_OFFSET_GYR70 + 1, - BMI160_OFFSET_GYR70 + 2, - BMI160_OFFSET_EN_GYR98}; - -/** Confguration of BMI160 */ -struct bmi_emul_type_data bmi160_emul = { - .sensortime_follow_config_frame = false, - .handle_write = bmi160_emul_handle_write, - .handle_read = bmi160_emul_handle_read, - .access_reg = bmi160_emul_access_reg, - .reset = bmi160_emul_reset, - .rsvd_mask = bmi_emul_160_rsvd_mask, - .nvm_reg = bmi160_nvm_reg, - .nvm_len = ARRAY_SIZE(bmi160_nvm_reg), - .gyr_off_reg = BMI160_OFFSET_GYR70, - .acc_off_reg = BMI160_OFFSET_ACC70, - .gyr98_off_reg = BMI160_OFFSET_EN_GYR98, -}; - -/** Check description in emul_bmi.h */ -const struct bmi_emul_type_data *get_bmi160_emul_type_data(void) -{ - return &bmi160_emul; -} diff --git a/zephyr/emul/emul_bmi260.c b/zephyr/emul/emul_bmi260.c deleted file mode 100644 index 235b1e219e..0000000000 --- a/zephyr/emul/emul_bmi260.c +++ /dev/null @@ -1,571 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT zephyr_bmi - -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(emul_bmi260); - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_bmi.h" - -#include "driver/accelgyro_bmi260.h" -#include "driver/accelgyro_bmi_common.h" - -/** Mask reserved bits in each register of BMI260 */ -static const uint8_t bmi_emul_260_rsvd_mask[] = { - [BMI260_CHIP_ID] = 0x00, - [0x01] = 0xff, /* Reserved */ - [BMI260_ERR_REG] = 0x20, - [BMI260_STATUS] = 0x0b, - [BMI260_AUX_X_L_G] = 0x00, - [BMI260_AUX_X_H_G] = 0x00, - [BMI260_AUX_Y_L_G] = 0x00, - [BMI260_AUX_Y_H_G] = 0x00, - [BMI260_AUX_Z_L_G] = 0x00, - [BMI260_AUX_Z_H_G] = 0x00, - [BMI260_AUX_R_L_G] = 0x00, - [BMI260_AUX_R_H_G] = 0x00, - [BMI260_ACC_X_L_G] = 0x00, - [BMI260_ACC_X_H_G] = 0x00, - [BMI260_ACC_Y_L_G] = 0x00, - [BMI260_ACC_Y_H_G] = 0x00, - [BMI260_ACC_Z_L_G] = 0x00, - [BMI260_ACC_Z_H_G] = 0x00, - [BMI260_GYR_X_L_G] = 0x00, - [BMI260_GYR_X_H_G] = 0x00, - [BMI260_GYR_Y_L_G] = 0x00, - [BMI260_GYR_Y_H_G] = 0x00, - [BMI260_GYR_Z_L_G] = 0x00, - [BMI260_GYR_Z_H_G] = 0x00, - [BMI260_SENSORTIME_0] = 0x00, - [BMI260_SENSORTIME_1] = 0x00, - [BMI260_SENSORTIME_2] = 0x00, - [BMI260_EVENT] = 0xe2, - [BMI260_INT_STATUS_0] = 0x00, - [BMI260_INT_STATUS_1] = 0x18, - [BMI260_SC_OUT_0] = 0x00, - [BMI260_SC_OUT_1] = 0x00, - [BMI260_ORIENT_ACT] = 0xe0, - [BMI260_INTERNAL_STATUS] = 0x00, - [BMI260_TEMPERATURE_0] = 0x00, - [BMI260_TEMPERATURE_1] = 0x00, - [BMI260_FIFO_LENGTH_0] = 0x00, - [BMI260_FIFO_LENGTH_1] = 0xc0, - [BMI160_FIFO_DATA] = 0x00, - [0x27 ... 0x2e] = 0xff, /* Reserved */ - [BMI260_FEAT_PAGE] = 0xf8, - [0x30 ... 0x3f] = 0x00, /* Features */ - [BMI260_ACC_CONF] = 0x00, - [BMI260_ACC_RANGE] = 0xfc, - [BMI260_GYR_CONF] = 0x00, - [BMI260_GYR_RANGE] = 0xf0, - [BMI260_AUX_CONF] = 0x00, - [BMI260_FIFO_DOWNS] = 0x00, - [BMI260_FIFO_WTM_0] = 0x00, - [BMI260_FIFO_WTM_1] = 0xe0, - [BMI260_FIFO_CONFIG_0] = 0xfc, - [BMI260_FIFO_CONFIG_1] = 0x00, - [BMI260_SATURATION] = 0xc0, - [BMI260_AUX_DEV_ID] = 0x01, - [BMI260_AUX_IF_CONF] = 0x30, - [BMI260_AUX_RD_ADDR] = 0x00, - [BMI260_AUX_WR_ADDR] = 0x00, - [BMI260_AUX_WR_DATA] = 0x00, - [0x50 ... 0x51] = 0xff, /* Reserved */ - [BMI260_ERR_REG_MSK] = 0x20, - [BMI260_INT1_IO_CTRL] = 0xe1, - [BMI260_INT2_IO_CTRL] = 0xe1, - [BMI260_INT_LATCH] = 0xfe, - [BMI260_INT1_MAP_FEAT] = 0x00, - [BMI260_INT2_MAP_FEAT] = 0x00, - [BMI260_INT_MAP_DATA] = 0x00, - [BMI260_INIT_CTRL] = 0x00, - [0x5a] = 0xff, /* Reserved */ - [BMI260_INIT_ADDR_0] = 0xf0, - [BMI260_INIT_ADDR_1] = 0x00, - [0x5d] = 0xff, /* Reserved */ - [BMI260_INIT_DATA] = 0x00, - [BMI260_INTERNAL_ERROR] = 0xe9, - [0x60 ... 0x67] = 0xff, /* Reserved */ - [BMI260_AUX_IF_TRIM] = 0xf8, - [BMI260_GYR_CRT_CONF] = 0xf2, - [BMI260_NVM_CONF] = 0xfd, - [BMI260_IF_CONF] = 0xcc, - [BMI260_DRV] = 0x00, - [BMI260_ACC_SELF_TEST] = 0xf2, - [BMI260_GYR_SELF_TEST_AXES] = 0xf0, - [0x6f] = 0xff, /* Reserved */ - [BMI260_NV_CONF] = 0xf0, - [BMI260_OFFSET_ACC70] = 0x00, - [BMI260_OFFSET_ACC70 + 1] = 0x00, - [BMI260_OFFSET_ACC70 + 2] = 0x00, - [BMI260_OFFSET_GYR70] = 0x00, - [BMI260_OFFSET_GYR70 + 1] = 0x00, - [BMI260_OFFSET_GYR70 + 2] = 0x00, - [BMI160_OFFSET_EN_GYR98] = 0x00, - [0x78 ... 0x7b] = 0xff, /* Reserved */ - [BMI260_PWR_CONF] = 0xf8, - [BMI260_PWR_CTRL] = 0xf0, - [BMI260_CMD_REG] = 0x00, -}; - -/** - * @brief Reset registers to default values and restore registers backed by NVM - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - */ -static void bmi260_emul_reset(uint8_t *regs, struct i2c_emul *emul) -{ - bool tag_time; - bool header; - - regs[BMI260_CHIP_ID] = 0x27; - regs[BMI260_ERR_REG] = 0x00; - regs[BMI260_STATUS] = 0x10; - regs[BMI260_AUX_X_L_G] = 0x00; - regs[BMI260_AUX_X_H_G] = 0x00; - regs[BMI260_AUX_Y_L_G] = 0x00; - regs[BMI260_AUX_Y_H_G] = 0x00; - regs[BMI260_AUX_Z_L_G] = 0x00; - regs[BMI260_AUX_Z_H_G] = 0x00; - regs[BMI260_AUX_R_L_G] = 0x00; - regs[BMI260_AUX_R_H_G] = 0x00; - regs[BMI260_ACC_X_L_G] = 0x00; - regs[BMI260_ACC_X_H_G] = 0x00; - regs[BMI260_ACC_Y_L_G] = 0x00; - regs[BMI260_ACC_Y_H_G] = 0x00; - regs[BMI260_ACC_Z_L_G] = 0x00; - regs[BMI260_ACC_Z_H_G] = 0x00; - regs[BMI260_GYR_X_L_G] = 0x00; - regs[BMI260_GYR_X_H_G] = 0x00; - regs[BMI260_GYR_Y_L_G] = 0x00; - regs[BMI260_GYR_Y_H_G] = 0x00; - regs[BMI260_GYR_Z_L_G] = 0x00; - regs[BMI260_GYR_Z_H_G] = 0x00; - regs[BMI260_SENSORTIME_0] = 0x00; - regs[BMI260_SENSORTIME_1] = 0x00; - regs[BMI260_SENSORTIME_2] = 0x00; - regs[BMI260_EVENT] = 0x01; - regs[BMI260_INT_STATUS_0] = 0x00; - regs[BMI260_INT_STATUS_1] = 0x00; - regs[BMI260_SC_OUT_0] = 0x00; - regs[BMI260_SC_OUT_1] = 0x00; - regs[BMI260_ORIENT_ACT] = 0x00; - regs[BMI260_INTERNAL_STATUS] = 0x00; - regs[BMI260_TEMPERATURE_0] = 0x00; - regs[BMI260_TEMPERATURE_1] = 0x80; - regs[BMI260_FIFO_LENGTH_0] = 0x00; - regs[BMI260_FIFO_LENGTH_1] = 0x00; - regs[BMI160_FIFO_DATA] = 0x00; - regs[BMI260_FEAT_PAGE] = 0x00; - regs[BMI260_ACC_CONF] = 0xa8; - regs[BMI260_ACC_RANGE] = 0x02; - regs[BMI260_GYR_CONF] = 0xa9; - regs[BMI260_GYR_RANGE] = 0x00; - regs[BMI260_AUX_CONF] = 0x46; - regs[BMI260_FIFO_DOWNS] = 0x88; - regs[BMI260_FIFO_WTM_0] = 0x00; - regs[BMI260_FIFO_WTM_1] = 0x02; - regs[BMI260_FIFO_CONFIG_0] = 0x02; - regs[BMI260_FIFO_CONFIG_1] = 0x10; - regs[BMI260_SATURATION] = 0x00; - regs[BMI260_AUX_DEV_ID] = 0x20; - regs[BMI260_AUX_IF_CONF] = 0x83; - regs[BMI260_AUX_RD_ADDR] = 0x42; - regs[BMI260_AUX_WR_ADDR] = 0x4c; - regs[BMI260_AUX_WR_DATA] = 0x02; - regs[BMI260_ERR_REG_MSK] = 0x00; - regs[BMI260_INT1_IO_CTRL] = 0x00; - regs[BMI260_INT2_IO_CTRL] = 0x00; - regs[BMI260_INT_LATCH] = 0x00; - regs[BMI260_INT1_MAP_FEAT] = 0x00; - regs[BMI260_INT2_MAP_FEAT] = 0x00; - regs[BMI260_INT_MAP_DATA] = 0x00; - regs[BMI260_INIT_CTRL] = 0x00; - regs[BMI260_INIT_ADDR_0] = 0x00; - regs[BMI260_INIT_ADDR_1] = 0x00; - regs[BMI260_INIT_DATA] = 0x00; - regs[BMI260_INTERNAL_ERROR] = 0x00; - regs[BMI260_AUX_IF_TRIM] = 0x01; - regs[BMI260_GYR_CRT_CONF] = 0x00; - regs[BMI260_NVM_CONF] = 0x00; - regs[BMI260_IF_CONF] = 0x00; - regs[BMI260_DRV] = 0xff; - regs[BMI260_ACC_SELF_TEST] = 0x00; - regs[BMI260_GYR_SELF_TEST_AXES] = 0x00; - regs[BMI260_PWR_CONF] = 0x03; - regs[BMI260_PWR_CTRL] = 0x00; - regs[BMI260_CMD_REG] = 0x00; - - /* Call generic reset */ - tag_time = regs[BMI260_FIFO_CONFIG_0] & BMI260_FIFO_TIME_EN; - header = regs[BMI260_FIFO_CONFIG_1] & BMI260_FIFO_HEADER_EN; - bmi_emul_reset_common(emul, tag_time, header); -} - -/** - * @brief Convert range in format of ACC_RANGE register to number of bits - * that should be shifted right to obtain 16 bit reported accelerometer - * value from internal 32 bit value - * - * @param range Value of ACC_RANGE register - * - * @return shift Number of LSB that should be ignored from internal - * accelerometer value - */ -static int bmi260_emul_acc_range_to_shift(uint8_t range) -{ - switch (range & 0xf) { - case BMI260_GSEL_2G: - return 0; - case BMI260_GSEL_4G: - return 1; - case BMI260_GSEL_8G: - return 2; - case BMI260_GSEL_16G: - return 3; - default: - return 0; - } -} - -/** - * @brief Convert range in format of GYR_RANGE register to number of bits - * that should be shifted right to obtain 16 bit reported gyroscope - * value from internal 32 bit value - * - * @param range Value of GYR_RANGE register - * - * @return shift Number of LSB that should be ignored from internal - * gyroscope value - */ -static int bmi260_emul_gyr_range_to_shift(uint8_t range) -{ - switch (range & 0x7) { - case BMI260_DPS_SEL_2000: - return 4; - case BMI260_DPS_SEL_1000: - return 3; - case BMI260_DPS_SEL_500: - return 2; - case BMI260_DPS_SEL_250: - return 1; - case BMI260_DPS_SEL_125: - return 0; - default: - return 0; - } -} - -/** - * @brief Execute first part of command. Emulate state of device which is - * during handling command (status bits etc). This function save time - * on which command should end. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - * @param cmd Command that is starting - * - * @return 0 on success - * @return -EIO on failure - */ -static int bmi260_emul_start_cmd(uint8_t *regs, struct i2c_emul *emul, int cmd) -{ - int time; - - switch (cmd) { - case BMI260_CMD_SOFT_RESET: - time = 1; - break; - case BMI260_CMD_FIFO_FLUSH: - time = 0; - break; - default: - LOG_ERR("Unknown command 0x%x", cmd); - return -EIO; - } - - regs[BMI260_CMD_REG] = cmd; - bmi_emul_set_cmd_end_time(emul, time); - - return 0; -} - -/** - * @brief Emulate end of ongoing command. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - */ -static void bmi260_emul_end_cmd(uint8_t *regs, struct i2c_emul *emul) -{ - bool tag_time; - bool header; - int cmd; - - cmd = regs[BMI260_CMD_REG]; - regs[BMI260_CMD_REG] = 0; - tag_time = regs[BMI260_FIFO_CONFIG_0] & BMI260_FIFO_TIME_EN; - header = regs[BMI260_FIFO_CONFIG_1] & BMI260_FIFO_HEADER_EN; - - switch (cmd) { - case BMI160_CMD_SOFT_RESET: - bmi260_emul_reset(regs, emul); - break; - case BMI160_CMD_FIFO_FLUSH: - bmi_emul_flush_fifo(emul, tag_time, header); - break; - } -} - -/** - * @brief Get currently accessed register. It is first register plus number of - * handled bytes for all registers except BMI260_FIFO_DATA and - * BMI260_INIT_DATA for which address incrementation is disabled. - * - * @param emul Pointer to BMI emulator - * @param reg First byte of last write message - * @param bytes Number of bytes already handled from current message - * @param read If currently handled is read message - * - * @return Currently accessed register - */ -static int bmi260_emul_access_reg(struct i2c_emul *emul, int reg, int byte, - bool read) -{ - /* Ignore first byte which sets starting register */ - if (!read) { - byte -= 1; - } - - /* - * If register is FIFO data, then read data from FIFO. - * Init data is also block, but it is not implemented in emulator. - * Else block read access subsequent registers. - */ - if (reg <= BMI260_FIFO_DATA && reg + byte >= BMI260_FIFO_DATA) { - return BMI260_FIFO_DATA; - } else if (reg <= BMI260_INIT_DATA && - reg + byte >= BMI260_INIT_DATA) { - return BMI260_INIT_DATA; - } - - return reg + byte; -} - -/** - * @brief BMI260 specific write function. It handle block writes. Init data - * register is trap register, so after reaching it, register address - * is not increased on block writes. Check if read only register is not - * accessed. Before writing value, ongoing command is finished if - * possible. Write to CMD register is handled by BMI260 specific - * function. On changing of FIFO header/headerless mode or - * enabling/disabling sensor in headerless mode FIFO is flushed. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - * @param reg Register address that is accessed - * @param byte Number of handled bytes in this write command - * @param val Value that is being written - * - * @return 0 on success - * @return BMI_EMUL_ACCESS_E on RO register access - * @return -EIO on error - */ -static int bmi260_emul_handle_write(uint8_t *regs, struct i2c_emul *emul, - int reg, int byte, uint8_t val) -{ - uint8_t mask; - bool tag_time; - bool header; - - reg = bmi260_emul_access_reg(emul, reg, byte, false /* = read */); - - if (reg <= BMI260_FIFO_DATA || reg == BMI260_GYR_SELF_TEST_AXES || - reg == BMI260_INTERNAL_ERROR || reg == BMI260_SATURATION) { - return BMI_EMUL_ACCESS_E; - } - - - /* Stop on going command if required */ - if (regs[BMI260_CMD_REG] != 0 && bmi_emul_is_cmd_end(emul)) { - bmi260_emul_end_cmd(regs, emul); - } - - tag_time = regs[BMI260_FIFO_CONFIG_0] & BMI260_FIFO_TIME_EN; - header = regs[BMI260_FIFO_CONFIG_1] & BMI260_FIFO_HEADER_EN; - - switch (reg) { - case BMI260_CMD_REG: - if (regs[BMI260_CMD_REG] != 0) { - LOG_ERR("Issued command before previous end"); - return -EIO; - } - - return bmi260_emul_start_cmd(regs, emul, val); - case BMI260_FIFO_CONFIG_1: - /* - * Clear FIFO on transition between headerless and - * header mode - */ - if (!!(val & BMI260_FIFO_HEADER_EN) != header) { - bmi_emul_flush_fifo(emul, tag_time, header); - } - break; - case BMI260_PWR_CTRL: - /* - * Clear FIFO on enabling/disabling sensors in headerless - * mode - */ - mask = BMI260_AUX_EN & BMI260_GYR_EN & BMI260_ACC_EN; - if ((val & mask) != (regs[BMI260_PWR_CTRL] & mask) && !header) { - bmi_emul_flush_fifo(emul, tag_time, header); - } - break; - } - - return 0; -} - -/** - * @brief BMI260 specific read function. It handle block reads. FIFO data - * register and init data register are trap registers, so - * after reaching it, register address is not increased on block reads. - * Before reading value, ongoing command is finished if possible. - * Read of sensor data traps current emulator state in registers. - * Read of FIFO length and FIFO data triggers default BMI functions. - * - * @param regs Pointer to array of emulator's registers - * @param emul Pointer to BMI emulator - * @param reg Register address that is accessed - * @param byte Byte which is accessed during block read - * @param buf Pointer where read byte should be stored - * - * @return 0 on success - * @return BMI_EMUL_ACCESS_E on WO register access - * @return -EIO on other error - */ -static int bmi260_emul_handle_read(uint8_t *regs, struct i2c_emul *emul, - int reg, int byte, char *buf) -{ - uint16_t fifo_len; - bool acc_off_en; - bool gyr_off_en; - bool tag_time; - bool header; - int gyr_shift; - int acc_shift; - int fifo_byte; - - /* Get number of bytes readed from FIFO */ - fifo_byte = byte - (reg - BMI260_FIFO_DATA); - - reg = bmi260_emul_access_reg(emul, reg, byte, true /* = read */); - - if (reg == BMI260_CMD_REG) { - *buf = 0; - - return BMI_EMUL_ACCESS_E; - } - - /* Stop on going command if required */ - if (regs[BMI260_CMD_REG] != 0 && bmi_emul_is_cmd_end(emul)) { - bmi260_emul_end_cmd(regs, emul); - } - - tag_time = regs[BMI260_FIFO_CONFIG_0] & BMI260_FIFO_TIME_EN; - header = regs[BMI260_FIFO_CONFIG_1] & BMI260_FIFO_HEADER_EN; - acc_off_en = regs[BMI260_NV_CONF] & BMI260_ACC_OFFSET_EN; - gyr_off_en = regs[BMI260_OFFSET_EN_GYR98] & BMI260_OFFSET_GYRO_EN; - gyr_shift = bmi260_emul_gyr_range_to_shift(regs[BMI260_GYR_RANGE]); - acc_shift = bmi260_emul_acc_range_to_shift(regs[BMI260_ACC_RANGE]); - - switch (reg) { - case BMI260_GYR_X_L_G: - case BMI260_GYR_X_H_G: - case BMI260_GYR_Y_L_G: - case BMI260_GYR_Y_H_G: - case BMI260_GYR_Z_L_G: - case BMI260_GYR_Z_H_G: - case BMI260_ACC_X_L_G: - case BMI260_ACC_X_H_G: - case BMI260_ACC_Y_L_G: - case BMI260_ACC_Y_H_G: - case BMI260_ACC_Z_L_G: - case BMI260_ACC_Z_H_G: - case BMI260_SENSORTIME_0: - case BMI260_SENSORTIME_1: - case BMI260_SENSORTIME_2: - /* - * Snapshot of current emulator state is created on data read - * and shouldn't be changed until next I2C operation - */ - if (byte == 0) { - bmi_emul_state_to_reg(emul, acc_shift, gyr_shift, - BMI260_ACC_X_L_G, - BMI260_GYR_X_L_G, - BMI260_SENSORTIME_0, - acc_off_en, gyr_off_en); - } - break; - case BMI260_FIFO_LENGTH_0: - case BMI260_FIFO_LENGTH_1: - if (byte == 0) { - fifo_len = bmi_emul_fifo_len(emul, tag_time, header); - regs[BMI260_FIFO_LENGTH_0] = fifo_len & 0xff; - regs[BMI260_FIFO_LENGTH_1] = (fifo_len >> 8) & 0x7; - } - break; - case BMI260_FIFO_DATA: - regs[reg] = bmi_emul_get_fifo_data(emul, fifo_byte, tag_time, - header, acc_shift, - gyr_shift); - break; - } - - *buf = regs[reg]; - - return 0; -} - -/** Registers backed in NVM by BMI260 */ -const int bmi260_nvm_reg[] = {BMI260_AUX_IF_TRIM, - BMI260_NV_CONF, - BMI260_DRV, - BMI260_OFFSET_ACC70, - BMI260_OFFSET_ACC70 + 1, - BMI260_OFFSET_ACC70 + 2, - BMI260_OFFSET_GYR70, - BMI260_OFFSET_GYR70 + 1, - BMI260_OFFSET_GYR70 + 2, - BMI260_OFFSET_EN_GYR98}; - -/** Confguration of BMI260 */ -struct bmi_emul_type_data bmi260_emul = { - .sensortime_follow_config_frame = true, - .handle_write = bmi260_emul_handle_write, - .handle_read = bmi260_emul_handle_read, - .access_reg = bmi260_emul_access_reg, - .reset = bmi260_emul_reset, - .rsvd_mask = bmi_emul_260_rsvd_mask, - .nvm_reg = bmi260_nvm_reg, - .nvm_len = ARRAY_SIZE(bmi260_nvm_reg), - .gyr_off_reg = BMI260_OFFSET_GYR70, - .acc_off_reg = BMI260_OFFSET_ACC70, - .gyr98_off_reg = BMI260_OFFSET_EN_GYR98, -}; - -/** Check description in emul_bmi.h */ -const struct bmi_emul_type_data *get_bmi260_emul_type_data(void) -{ - return &bmi260_emul; -} diff --git a/zephyr/emul/emul_common_i2c.c b/zephyr/emul/emul_common_i2c.c deleted file mode 100644 index bd811f1424..0000000000 --- a/zephyr/emul/emul_common_i2c.c +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(emul_common_i2c); - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_common_i2c.h" - -/** Check description in emul_common_i2c.h */ -int i2c_common_emul_lock_data(struct i2c_emul *emul, k_timeout_t timeout) -{ - struct i2c_common_emul_data *data; - - data = CONTAINER_OF(emul, struct i2c_common_emul_data, emul); - - return k_mutex_lock(&data->data_mtx, timeout); -} - -/** Check description in emul_common_i2c.h */ -int i2c_common_emul_unlock_data(struct i2c_emul *emul) -{ - struct i2c_common_emul_data *data; - - data = CONTAINER_OF(emul, struct i2c_common_emul_data, emul); - - return k_mutex_unlock(&data->data_mtx); -} - -/** Check description in emul_common_i2c.h */ -void i2c_common_emul_set_write_func(struct i2c_emul *emul, - i2c_common_emul_write_func func, void *data) -{ - struct i2c_common_emul_data *emul_data; - - emul_data = CONTAINER_OF(emul, struct i2c_common_emul_data, emul); - emul_data->write_func = func; - emul_data->write_func_data = data; -} - -/** Check description in emul_common_i2c.h */ -void i2c_common_emul_set_read_func(struct i2c_emul *emul, - i2c_common_emul_read_func func, void *data) -{ - struct i2c_common_emul_data *emul_data; - - emul_data = CONTAINER_OF(emul, struct i2c_common_emul_data, emul); - emul_data->read_func = func; - emul_data->read_func_data = data; -} - -/** Check description in emul_common_i2c.h */ -void i2c_common_emul_set_read_fail_reg(struct i2c_emul *emul, int reg) -{ - struct i2c_common_emul_data *data; - - data = CONTAINER_OF(emul, struct i2c_common_emul_data, emul); - data->read_fail_reg = reg; -} - -/** Check description in emul_common_i2c.h */ -void i2c_common_emul_set_write_fail_reg(struct i2c_emul *emul, int reg) -{ - struct i2c_common_emul_data *data; - - data = CONTAINER_OF(emul, struct i2c_common_emul_data, emul); - data->write_fail_reg = reg; -} - -/** - * @brief Call start_write emulator callback if set. It handles first byte - * of I2C write message. - * - * @param emul Pointer to emulator - * @param data Pointer to emulator data - * - * @retval start_write emulator callback return code - */ -static int i2c_common_emul_start_write(struct i2c_emul *emul, - struct i2c_common_emul_data *data) -{ - int ret = 0; - - data->msg_byte = 0; - - if (data->start_write) { - k_mutex_lock(&data->data_mtx, K_FOREVER); - ret = data->start_write(emul, data->cur_reg); - k_mutex_unlock(&data->data_mtx); - } - - return ret; -} - -/** - * @brief Call finish_write emulator callback if set. It is called after last - * byte of I2C write message. - * - * @param emul Pointer to emulator - * @param data Pointer to emulator data - * - * @retval finish_write emulator callback return code - */ -static int i2c_common_emul_finish_write(struct i2c_emul *emul, - struct i2c_common_emul_data *data) -{ - int ret = 0; - - if (data->finish_write) { - k_mutex_lock(&data->data_mtx, K_FOREVER); - ret = data->finish_write(emul, data->cur_reg, data->msg_byte); - k_mutex_unlock(&data->data_mtx); - } - - return ret; -} - -/** - * @brief Call start_read emulator callback if set. It prepares emulator at - * the beginning of I2C read message. - * - * @param emul Pointer to emulator - * @param data Pointer to emulator data - * - * @retval start_read emulator callback return code - */ -static int i2c_common_emul_start_read(struct i2c_emul *emul, - struct i2c_common_emul_data *data) -{ - int ret = 0; - - data->msg_byte = 0; - - if (data->start_read) { - k_mutex_lock(&data->data_mtx, K_FOREVER); - ret = data->start_read(emul, data->cur_reg); - k_mutex_unlock(&data->data_mtx); - } - - return ret; -} - -/** - * @brief Call finish_read emulator callback if set. It is called after last - * byte of I2C read message. - * - * @param emul Pointer to emulator - * @param data Pointer to emulator data - * - * @retval finish_read emulator callback return code - */ -static int i2c_common_emul_finish_read(struct i2c_emul *emul, - struct i2c_common_emul_data *data) -{ - int ret = 0; - - if (data->finish_read) { - k_mutex_lock(&data->data_mtx, K_FOREVER); - ret = data->finish_read(emul, data->cur_reg, data->msg_byte); - k_mutex_unlock(&data->data_mtx); - } - - return ret; -} - -/** - * @brief Handle byte from I2C write message. First custom user handler is - * called (if set). Next accessed register is compared with selected - * by user fail register. Lastly, specific I2C device emulator handler - * is called. - * - * @param emul Pointer to emulator - * @param data Pointer to emulator data - * @param val Value of current byte - * - * @retval 0 If successful - * @retval -EIO General input / output error - */ -static int i2c_common_emul_write_byte(struct i2c_emul *emul, - struct i2c_common_emul_data *data, - uint8_t val) -{ - int reg, ret; - - /* Custom user handler */ - if (data->write_func) { - ret = data->write_func(emul, data->cur_reg, val, data->msg_byte, - data->write_func_data); - if (ret < 0) { - return -EIO; - } else if (ret == 0) { - return 0; - } - } - /* Check if user wants to fail on accessed register */ - if (data->access_reg) { - reg = data->access_reg(emul, data->cur_reg, data->msg_byte, - false /* = read */); - } else { - /* Ignore first (register address) byte */ - reg = data->cur_reg + data->msg_byte - 1; - } - - if (data->write_fail_reg == reg || - data->write_fail_reg == I2C_COMMON_EMUL_FAIL_ALL_REG) { - return -EIO; - } - /* Emulator handler */ - if (data->write_byte) { - k_mutex_lock(&data->data_mtx, K_FOREVER); - ret = data->write_byte(emul, data->cur_reg, val, - data->msg_byte); - k_mutex_unlock(&data->data_mtx); - if (ret) { - return -EIO; - } - } - - return 0; -} - -/** - * @brief Handle byte from I2C read message. First custom user handler is - * called (if set). Next accessed register is compared with selected - * by user fail register. Lastly, specific I2C device emulator handler - * is called. - * - * @param emul Pointer to emulator - * @param data Pointer to emulator data - * @param val Pointer to buffer where current response byte should be stored - * - * @retval 0 If successful - * @retval -EIO General input / output error - */ -static int i2c_common_emul_read_byte(struct i2c_emul *emul, - struct i2c_common_emul_data *data, - uint8_t *val) -{ - int reg, ret; - - /* Custom user handler */ - if (data->read_func) { - ret = data->read_func(emul, data->cur_reg, val, data->msg_byte, - data->read_func_data); - if (ret < 0) { - return -EIO; - } else if (ret == 0) { - return 0; - } - } - /* Check if user wants to fail on accessed register */ - if (data->access_reg) { - reg = data->access_reg(emul, data->cur_reg, data->msg_byte, - true /* = read */); - } else { - reg = data->cur_reg + data->msg_byte; - } - - if (data->read_fail_reg == reg || - data->read_fail_reg == I2C_COMMON_EMUL_FAIL_ALL_REG) { - return -EIO; - } - /* Emulator handler */ - if (data->read_byte) { - k_mutex_lock(&data->data_mtx, K_FOREVER); - ret = data->read_byte(emul, data->cur_reg, val, data->msg_byte); - k_mutex_unlock(&data->data_mtx); - if (ret) { - return -EIO; - } - } - - return 0; -} - -/** Check description in emul_common_i2c.h */ -int i2c_common_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs, - int num_msgs, int addr) -{ - const struct i2c_common_emul_cfg *cfg; - struct i2c_common_emul_data *data; - bool read, stop; - int ret, i; - - data = CONTAINER_OF(emul, struct i2c_common_emul_data, emul); - cfg = data->cfg; - - if (cfg->addr != addr) { - LOG_ERR("Address mismatch, expected %02x, got %02x", cfg->addr, - addr); - return -EIO; - } - - i2c_dump_msgs(cfg->dev_label, msgs, num_msgs, addr); - - for (; num_msgs > 0; num_msgs--, msgs++) { - read = msgs->flags & I2C_MSG_READ; - stop = msgs->flags & I2C_MSG_STOP; - - switch (data->msg_state) { - case I2C_COMMON_EMUL_IN_WRITE: - if (read) { - data->msg_state = I2C_COMMON_EMUL_NONE_MSG; - ret = i2c_common_emul_finish_write(emul, data); - if (ret) { - return ret; - } - ret = i2c_common_emul_start_read(emul, data); - if (ret) { - return ret; - } - } - break; - case I2C_COMMON_EMUL_IN_READ: - if (!read) { - data->msg_state = I2C_COMMON_EMUL_NONE_MSG; - ret = i2c_common_emul_finish_read(emul, data); - if (ret) { - return ret; - } - /* Wait for write message with acctual data */ - if (msgs->len == 0) { - continue; - } - /* Dispatch command/register address */ - data->cur_reg = msgs->buf[0]; - ret = i2c_common_emul_start_write(emul, data); - if (ret) { - return ret; - } - } - break; - case I2C_COMMON_EMUL_NONE_MSG: - if (read) { - ret = i2c_common_emul_start_read(emul, data); - if (ret) { - return ret; - } - } else { - /* Wait for write message with acctual data */ - if (msgs->len == 0) { - continue; - } - /* Dispatch command/register address */ - data->cur_reg = msgs->buf[0]; - ret = i2c_common_emul_start_write(emul, data); - if (ret) { - return ret; - } - } - } - - data->msg_state = read ? I2C_COMMON_EMUL_IN_READ - : I2C_COMMON_EMUL_IN_WRITE; - - if (stop) { - data->msg_state = I2C_COMMON_EMUL_NONE_MSG; - } - - if (!read) { - /* - * All current emulators use first byte of write message - * as command/register address for following write bytes - * or read message. Skip first byte which was dispatched - * already. - */ - if (data->msg_byte == 0) { - data->msg_byte = 1; - i = 1; - } else { - i = 0; - } - /* Dispatch write command */ - for (; i < msgs->len; i++, data->msg_byte++) { - ret = i2c_common_emul_write_byte(emul, data, - msgs->buf[i]); - if (ret) { - return ret; - } - } - /* Finish write command */ - if (stop) { - ret = i2c_common_emul_finish_write(emul, data); - if (ret) { - return ret; - } - } - } else { - /* Dispatch read command */ - for (i = 0; i < msgs->len; i++, data->msg_byte++) { - ret = i2c_common_emul_read_byte(emul, data, - &(msgs->buf[i])); - if (ret) { - return ret; - } - } - - /* Finish read command */ - if (stop) { - ret = i2c_common_emul_finish_read(emul, data); - if (ret) { - return ret; - } - } - } - } - - return 0; -} - -/** Check description in emul_common_i2c.h */ -void i2c_common_emul_init(struct i2c_common_emul_data *data) -{ - data->msg_state = I2C_COMMON_EMUL_NONE_MSG; - data->msg_byte = 0; - data->cur_reg = 0; - - data->write_func = NULL; - data->read_func = NULL; - - data->write_fail_reg = I2C_COMMON_EMUL_NO_FAIL_REG; - data->read_fail_reg = I2C_COMMON_EMUL_NO_FAIL_REG; - - k_mutex_init(&data->data_mtx); -} diff --git a/zephyr/emul/emul_lis2dw12.c b/zephyr/emul/emul_lis2dw12.c deleted file mode 100644 index 6fa8b31cc9..0000000000 --- a/zephyr/emul/emul_lis2dw12.c +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT cros_lis2dw12_emul - -#include <device.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> -#include <emul.h> -#include <errno.h> -#include <sys/__assert.h> - -#include "driver/accel_lis2dw12.h" -#include "emul/emul_common_i2c.h" -#include "emul/emul_lis2dw12.h" -#include "i2c.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(lis2dw12_emul, CONFIG_LIS2DW12_EMUL_LOG_LEVEL); - -#define LIS2DW12_DATA_FROM_I2C_EMUL(_emul) \ - CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \ - struct lis2dw12_emul_data, common) - -struct lis2dw12_emul_data { - /** Common I2C data */ - struct i2c_common_emul_data common; - /** Emulated who-am-i register */ - uint8_t who_am_i_reg; - /** Emulated ctrl2 register */ - uint8_t ctrl2_reg; - /** Soft reset count */ - uint32_t soft_reset_count; -}; - -struct lis2dw12_emul_cfg { - /** Common I2C config */ - struct i2c_common_emul_cfg common; -}; - -struct i2c_emul *lis2dw12_emul_to_i2c_emul(const struct emul *emul) -{ - struct lis2dw12_emul_data *data = emul->data; - - return &(data->common.emul); -} - -void lis2dw12_emul_reset(const struct emul *emul) -{ - struct lis2dw12_emul_data *data = emul->data; - struct i2c_emul *i2c_emul = lis2dw12_emul_to_i2c_emul(emul); - - i2c_common_emul_set_read_fail_reg(i2c_emul, - I2C_COMMON_EMUL_NO_FAIL_REG); - i2c_common_emul_set_write_fail_reg(i2c_emul, - I2C_COMMON_EMUL_NO_FAIL_REG); - i2c_common_emul_set_read_func(i2c_emul, NULL, NULL); - i2c_common_emul_set_write_func(i2c_emul, NULL, NULL); - data->who_am_i_reg = LIS2DW12_WHO_AM_I; - data->ctrl2_reg = 0; - data->soft_reset_count = 0; -} - -void lis2dw12_emul_set_who_am_i(const struct emul *emul, uint8_t who_am_i) -{ - struct lis2dw12_emul_data *data = emul->data; - - data->who_am_i_reg = who_am_i; -} - -uint32_t lis2dw12_emul_get_soft_reset_count(const struct emul *emul) -{ - struct lis2dw12_emul_data *data = emul->data; - - return data->soft_reset_count; -} - -static int lis2dw12_emul_read_byte(struct i2c_emul *emul, int reg, uint8_t *val, - int bytes) -{ - struct lis2dw12_emul_data *data = LIS2DW12_DATA_FROM_I2C_EMUL(emul); - - switch (reg) { - case LIS2DW12_WHO_AM_I_REG: - __ASSERT_NO_MSG(bytes == 0); - *val = data->who_am_i_reg; - break; - case LIS2DW12_CTRL2_ADDR: - __ASSERT_NO_MSG(bytes == 0); - *val = data->ctrl2_reg; - break; - default: - return -EINVAL; - } - return 0; -} - -static int lis2dw12_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val, - int bytes) -{ - struct lis2dw12_emul_data *data = LIS2DW12_DATA_FROM_I2C_EMUL(emul); - - switch (reg) { - case LIS2DW12_WHO_AM_I_REG: - LOG_ERR("Can't write to who-am-i register"); - return -EINVAL; - case LIS2DW12_CTRL2_ADDR: - __ASSERT_NO_MSG(bytes == 1); - if ((val & LIS2DW12_SOFT_RESET_MASK) != 0) { - /* Soft reset */ - data->soft_reset_count++; - } - data->ctrl2_reg = val & ~LIS2DW12_SOFT_RESET_MASK; - break; - default: - return -EINVAL; - } - return 0; -} - -static struct i2c_emul_api lis2dw12_emul_api_i2c = { - .transfer = i2c_common_emul_transfer, -}; - -static int emul_lis2dw12_init(const struct emul *emul, - const struct device *parent) -{ - const struct lis2dw12_emul_cfg *lis2dw12_cfg = emul->cfg; - const struct i2c_common_emul_cfg *cfg = &(lis2dw12_cfg->common); - struct lis2dw12_emul_data *data = emul->data; - - data->common.emul.api = &lis2dw12_emul_api_i2c; - data->common.emul.addr = cfg->addr; - data->common.emul.parent = emul; - data->common.i2c = parent; - data->common.cfg = cfg; - i2c_common_emul_init(&data->common); - - return i2c_emul_register(parent, emul->dev_label, &data->common.emul); -} - -#define INIT_LIS2DW12(n) \ - static struct lis2dw12_emul_data lis2dw12_emul_data_##n = { \ - .common = { \ - .write_byte = lis2dw12_emul_write_byte, \ - .read_byte = lis2dw12_emul_read_byte, \ - }, \ - }; \ - static const struct lis2dw12_emul_cfg lis2dw12_emul_cfg_##n = { \ - .common = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .dev_label = DT_INST_LABEL(n), \ - .addr = DT_INST_REG_ADDR(n), \ - }, \ - }; \ - EMUL_DEFINE(emul_lis2dw12_init, DT_DRV_INST(n), \ - &lis2dw12_emul_cfg_##n, &lis2dw12_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(INIT_LIS2DW12) diff --git a/zephyr/emul/emul_ln9310.c b/zephyr/emul/emul_ln9310.c deleted file mode 100644 index d4eaa8e38d..0000000000 --- a/zephyr/emul/emul_ln9310.c +++ /dev/null @@ -1,388 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT cros_ln9310_emul - -#include <device.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> -#include <emul.h> -#include <errno.h> -#include <sys/__assert.h> - -#include "driver/ln9310.h" -#include "emul/emul_common_i2c.h" -#include "emul/emul_ln9310.h" -#include "i2c.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(ln9310_emul, CONFIG_LN9310_EMUL_LOG_LEVEL); - -#define LN9310_DATA_FROM_I2C_EMUL(_emul) \ - CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \ - struct ln9310_emul_data, common) - -struct ln9310_emul_data { - /** Common I2C data */ - struct i2c_common_emul_data common; - /** The current emulated battery cell type */ - enum battery_cell_type battery_cell_type; - /** Emulated INT1 MSK register */ - uint8_t int1_msk_reg; - /** Emulated Lion control register */ - uint8_t lion_ctrl_reg; - /** Emulated startup control register */ - uint8_t startup_ctrl_reg; - /** Emulated BC STST B register */ - uint8_t bc_sts_b_reg; - /** Emulated BC STST C register */ - uint8_t bc_sts_c_reg; - /** Emulated cfg 0 register */ - uint8_t cfg_0_reg; - /** Emulated cfg 4 register */ - uint8_t cfg_4_reg; - /** Emulated cfg 5 register */ - uint8_t cfg_5_reg; - /** Emulated power control register */ - uint8_t power_ctrl_reg; - /** Emulated timer control register */ - uint8_t timer_ctrl_reg; - /** Emulated lower bound (LB) control register */ - uint8_t lower_bound_ctrl_reg; - /** Emulated spare 0 register */ - uint8_t spare_0_reg; - /** Emulated swap control 0 register */ - uint8_t swap_ctrl_0_reg; - /** Emulated swap control 1 register */ - uint8_t swap_ctrl_1_reg; - /** Emulated swap control 2 register */ - uint8_t swap_ctrl_2_reg; - /** Emulated swap control 3 register */ - uint8_t swap_ctrl_3_reg; - /** Emulated track control register */ - uint8_t track_ctrl_reg; - /** Emulated mode change register */ - uint8_t mode_change_reg; - /** Emulated system control register */ - uint8_t sys_ctrl_reg; -}; - -static const struct emul *singleton; - -void ln9310_emul_set_context(const struct emul *emulator) -{ - singleton = emulator; -} - -void ln9310_emul_reset(const struct emul *emulator) -{ - struct ln9310_emul_data *data = emulator->data; - - data->lion_ctrl_reg = 0; - data->startup_ctrl_reg = 0; - data->bc_sts_b_reg = 0; - data->cfg_0_reg = 0; - data->cfg_4_reg = 0; - data->cfg_5_reg = 0; - data->power_ctrl_reg = 0; - data->timer_ctrl_reg = 0; - data->lower_bound_ctrl_reg = 0; - data->spare_0_reg = 0; - data->swap_ctrl_0_reg = 0; - data->swap_ctrl_1_reg = 0; - data->swap_ctrl_2_reg = 0; - data->swap_ctrl_3_reg = 0; - data->track_ctrl_reg = 0; - data->mode_change_reg = 0; - data->sys_ctrl_reg = 0; -} - -void ln9310_emul_set_battery_cell_type(const struct emul *emulator, - enum battery_cell_type type) -{ - struct ln9310_emul_data *data = emulator->data; - - data->battery_cell_type = type; -} - -void ln9310_emul_set_version(const struct emul *emulator, int version) -{ - struct ln9310_emul_data *data = emulator->data; - - data->bc_sts_c_reg |= version & LN9310_BC_STS_C_CHIP_REV_MASK; -} - -void ln9310_emul_set_vin_gt_10v(const struct emul *emulator, bool is_gt_10v) -{ - struct ln9310_emul_data *data = emulator->data; - - if (is_gt_10v) - data->bc_sts_b_reg |= LN9310_BC_STS_B_INFET_OUT_SWITCH_OK; - else - data->bc_sts_b_reg &= ~LN9310_BC_STS_B_INFET_OUT_SWITCH_OK; -} - -bool ln9310_emul_is_init(const struct emul *emulator) -{ - struct ln9310_emul_data *data = emulator->data; - - return (data->int1_msk_reg & LN9310_INT1_MODE) == 0; -} - -enum battery_cell_type board_get_battery_cell_type(void) -{ - struct ln9310_emul_data *data = singleton->data; - - return data->battery_cell_type; -} - -static struct i2c_emul_api ln9310_emul_api_i2c = { - .transfer = i2c_common_emul_transfer, -}; - -static int ln9310_emul_start_write(struct i2c_emul *emul, int reg) -{ - return 0; -} - -static int ln9310_emul_finish_write(struct i2c_emul *emul, int reg, int bytes) -{ - return 0; -} - -static int ln9310_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val, - int bytes) -{ - struct ln9310_emul_data *data = LN9310_DATA_FROM_I2C_EMUL(emul); - - switch (reg) { - case LN9310_REG_INT1_MSK: - __ASSERT_NO_MSG(bytes == 1); - data->int1_msk_reg = val; - break; - case LN9310_REG_STARTUP_CTRL: - __ASSERT_NO_MSG(bytes == 1); - data->startup_ctrl_reg = val; - break; - case LN9310_REG_LION_CTRL: - __ASSERT_NO_MSG(bytes == 1); - data->lion_ctrl_reg = val; - break; - case LN9310_REG_BC_STS_B: - __ASSERT_NO_MSG(bytes == 1); - data->bc_sts_b_reg = val; - break; - case LN9310_REG_BC_STS_C: - LOG_ERR("Can't write to BC STS C register"); - return -EINVAL; - case LN9310_REG_CFG_0: - __ASSERT_NO_MSG(bytes == 1); - data->cfg_0_reg = val; - break; - case LN9310_REG_CFG_4: - __ASSERT_NO_MSG(bytes == 1); - data->cfg_4_reg = val; - break; - case LN9310_REG_CFG_5: - __ASSERT_NO_MSG(bytes == 1); - data->cfg_5_reg = val; - break; - case LN9310_REG_PWR_CTRL: - __ASSERT_NO_MSG(bytes == 1); - data->power_ctrl_reg = val; - break; - case LN9310_REG_TIMER_CTRL: - __ASSERT_NO_MSG(bytes == 1); - data->timer_ctrl_reg = val; - break; - case LN9310_REG_LB_CTRL: - __ASSERT_NO_MSG(bytes = 1); - data->lower_bound_ctrl_reg = val; - break; - case LN9310_REG_SPARE_0: - __ASSERT_NO_MSG(bytes == 1); - data->spare_0_reg = val; - break; - case LN9310_REG_SWAP_CTRL_0: - __ASSERT_NO_MSG(bytes == 1); - data->swap_ctrl_0_reg = val; - break; - case LN9310_REG_SWAP_CTRL_1: - __ASSERT_NO_MSG(bytes == 1); - data->swap_ctrl_1_reg = val; - break; - case LN9310_REG_SWAP_CTRL_2: - __ASSERT_NO_MSG(bytes == 1); - data->swap_ctrl_2_reg = val; - break; - case LN9310_REG_SWAP_CTRL_3: - __ASSERT_NO_MSG(bytes == 1); - data->swap_ctrl_3_reg = val; - break; - case LN9310_REG_TRACK_CTRL: - __ASSERT_NO_MSG(bytes == 1); - data->track_ctrl_reg = val; - break; - case LN9310_REG_MODE_CHANGE_CFG: - __ASSERT_NO_MSG(bytes == 1); - data->mode_change_reg = val; - break; - case LN9310_REG_SYS_CTRL: - __ASSERT_NO_MSG(bytes == 1); - data->sys_ctrl_reg = val; - break; - default: - return -EINVAL; - } - return 0; -} - -static int ln9310_emul_start_read(struct i2c_emul *emul, int reg) -{ - return 0; -} - -static int ln9310_emul_finish_read(struct i2c_emul *emul, int reg, int bytes) -{ - return 0; -} - -static int ln9310_emul_read_byte(struct i2c_emul *emul, int reg, uint8_t *val, - int bytes) -{ - struct ln9310_emul_data *data = LN9310_DATA_FROM_I2C_EMUL(emul); - - switch (reg) { - case LN9310_REG_INT1_MSK: - __ASSERT_NO_MSG(bytes == 0); - *val = data->int1_msk_reg; - break; - case LN9310_REG_STARTUP_CTRL: - __ASSERT_NO_MSG(bytes == 0); - *val = data->startup_ctrl_reg; - break; - case LN9310_REG_LION_CTRL: - __ASSERT_NO_MSG(bytes == 0); - *val = data->lion_ctrl_reg; - break; - case LN9310_REG_BC_STS_B: - __ASSERT_NO_MSG(bytes == 0); - *val = data->bc_sts_b_reg; - break; - case LN9310_REG_BC_STS_C: - __ASSERT_NO_MSG(bytes == 0); - *val = data->bc_sts_c_reg; - break; - case LN9310_REG_CFG_0: - __ASSERT_NO_MSG(bytes == 0); - *val = data->cfg_0_reg; - break; - case LN9310_REG_CFG_4: - __ASSERT_NO_MSG(bytes == 0); - *val = data->cfg_4_reg; - break; - case LN9310_REG_CFG_5: - __ASSERT_NO_MSG(bytes == 0); - *val = data->cfg_5_reg; - break; - case LN9310_REG_PWR_CTRL: - __ASSERT_NO_MSG(bytes == 0); - *val = data->power_ctrl_reg; - break; - case LN9310_REG_TIMER_CTRL: - __ASSERT_NO_MSG(bytes == 0); - *val = data->timer_ctrl_reg; - break; - case LN9310_REG_LB_CTRL: - __ASSERT_NO_MSG(bytes == 0); - *val = data->lower_bound_ctrl_reg; - break; - case LN9310_REG_SPARE_0: - __ASSERT_NO_MSG(bytes == 0); - *val = data->spare_0_reg; - break; - case LN9310_REG_SWAP_CTRL_0: - __ASSERT_NO_MSG(bytes == 0); - *val = data->swap_ctrl_0_reg; - break; - case LN9310_REG_SWAP_CTRL_1: - __ASSERT_NO_MSG(bytes == 0); - *val = data->swap_ctrl_1_reg; - break; - case LN9310_REG_SWAP_CTRL_2: - __ASSERT_NO_MSG(bytes == 0); - *val = data->swap_ctrl_2_reg; - break; - case LN9310_REG_SWAP_CTRL_3: - __ASSERT_NO_MSG(bytes == 0); - *val = data->swap_ctrl_3_reg; - break; - case LN9310_REG_TRACK_CTRL: - __ASSERT_NO_MSG(bytes == 0); - *val = data->track_ctrl_reg; - break; - case LN9310_REG_MODE_CHANGE_CFG: - __ASSERT_NO_MSG(bytes == 0); - *val = data->mode_change_reg; - break; - case LN9310_REG_SYS_CTRL: - __ASSERT_NO_MSG(bytes == 0); - *val = data->sys_ctrl_reg; - break; - default: - return -EINVAL; - } - return 0; -} - -static int ln9310_emul_access_reg(struct i2c_emul *emul, int reg, int bytes, - bool read) -{ - return 0; -} - -static int emul_ln9310_init(const struct emul *emul, - const struct device *parent) -{ - const struct i2c_common_emul_cfg *cfg = emul->cfg; - struct ln9310_emul_data *data = emul->data; - - data->common.emul.api = &ln9310_emul_api_i2c; - data->common.emul.addr = cfg->addr; - data->common.emul.parent = emul; - data->common.i2c = parent; - data->common.cfg = cfg; - i2c_common_emul_init(&data->common); - - singleton = emul; - - return i2c_emul_register(parent, emul->dev_label, &data->common.emul); -} - -#define INIT_LN9310(n) \ - const struct ln9310_config_t ln9310_config = { \ - .i2c_port = NAMED_I2C(power), \ - .i2c_addr_flags = DT_INST_REG_ADDR(n), \ - }; \ - static struct ln9310_emul_data ln9310_emul_data_##n = { \ - .common = { \ - .start_write = ln9310_emul_start_write, \ - .write_byte = ln9310_emul_write_byte, \ - .finish_write = ln9310_emul_finish_write, \ - .start_read = ln9310_emul_start_read, \ - .read_byte = ln9310_emul_read_byte, \ - .finish_read = ln9310_emul_finish_read, \ - .access_reg = ln9310_emul_access_reg, \ - }, \ - }; \ - static const struct i2c_common_emul_cfg ln9310_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .dev_label = DT_INST_LABEL(n), \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - EMUL_DEFINE(emul_ln9310_init, DT_DRV_INST(n), &ln9310_emul_cfg_##n, \ - &ln9310_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(INIT_LN9310) diff --git a/zephyr/emul/emul_pi3usb9201.c b/zephyr/emul/emul_pi3usb9201.c deleted file mode 100644 index babef58c75..0000000000 --- a/zephyr/emul/emul_pi3usb9201.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT zephyr_pi3usb9201_emul - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_pi3usb9201.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(emul_pi3usb9201, LOG_LEVEL_DBG); - -#define EMUL_REG_COUNT (PI3USB9201_REG_HOST_STS + 1) -#define EMUL_REG_IS_VALID(reg) (reg >= 0 && reg < EMUL_REG_COUNT) - -/** Run-time data used by the emulator */ -struct pi3usb9201_emul_data { - /** I2C emulator detail */ - struct i2c_emul emul; - /** pi3usb9201 device being emulated */ - const struct device *i2c; - /** Configuration information */ - const struct pi3usb9201_emul_cfg *cfg; - /** Current state of all emulated pi3usb9201 registers */ - uint8_t reg[EMUL_REG_COUNT]; -}; - -/** Static configuration for the emulator */ -struct pi3usb9201_emul_cfg { - /** Label of the I2C bus this emulator connects to */ - const char *i2c_label; - /** Pointer to run-time data */ - struct pi3usb9201_emul_data *data; - /** Address of pi3usb9201 on i2c bus */ - uint16_t addr; -}; - -int pi3usb9201_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val) -{ - struct pi3usb9201_emul_data *data; - - if (!EMUL_REG_IS_VALID(reg)) - return -EIO; - - data = CONTAINER_OF(emul, struct pi3usb9201_emul_data, emul); - data->reg[reg] = val; - - return 0; -} - -int pi3usb9201_emul_get_reg(struct i2c_emul *emul, int reg, uint8_t *val) -{ - struct pi3usb9201_emul_data *data; - - if (!EMUL_REG_IS_VALID(reg)) - return -EIO; - - data = CONTAINER_OF(emul, struct pi3usb9201_emul_data, emul); - *val = data->reg[reg]; - - return 0; -} - -static void pi3usb9201_emul_reset(struct i2c_emul *emul) -{ - struct pi3usb9201_emul_data *data; - - data = CONTAINER_OF(emul, struct pi3usb9201_emul_data, emul); - - data->reg[PI3USB9201_REG_CTRL_1] = 0; - data->reg[PI3USB9201_REG_CTRL_2] = 0; - data->reg[PI3USB9201_REG_CLIENT_STS] = 0; - data->reg[PI3USB9201_REG_HOST_STS] = 0; -} - -/** - * Emulate an I2C transfer to a pi3usb9201 - * - * This handles simple reads and writes - * - * @param emul I2C emulation information - * @param msgs List of messages to process - * @param num_msgs Number of messages to process - * @param addr Address of the I2C target device - * - * @retval 0 If successful - * @retval -EIO General input / output error - */ -static int pi3usb9201_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs, - int num_msgs, int addr) -{ - const struct pi3usb9201_emul_cfg *cfg; - struct pi3usb9201_emul_data *data; - - data = CONTAINER_OF(emul, struct pi3usb9201_emul_data, emul); - cfg = data->cfg; - - if (cfg->addr != addr) { - LOG_ERR("Address mismatch, expected %02x, got %02x", cfg->addr, - addr); - return -EIO; - } - - i2c_dump_msgs("emul", msgs, num_msgs, addr); - - if (num_msgs == 1) { - if (!(((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) - && (msgs[0].len == 2))) { - LOG_ERR("Unexpected write msgs"); - return -EIO; - } - return pi3usb9201_emul_set_reg(emul, msgs[0].buf[0], - msgs[0].buf[1]); - } else if (num_msgs == 2) { - if (!(((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) - && (msgs[0].len == 1) - && ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) - && (msgs[1].len == 1))) { - LOG_ERR("Unexpected read msgs"); - return -EIO; - } - return pi3usb9201_emul_get_reg(emul, msgs[0].buf[0], - &(msgs[1].buf[0])); - } else { - LOG_ERR("Unexpected num_msgs"); - return -EIO; - } - -} - -/* Device instantiation */ - -static struct i2c_emul_api pi3usb9201_emul_api = { - .transfer = pi3usb9201_emul_transfer, -}; - -/** - * @brief Set up a new pi3usb9201 emulator - * - * This should be called for each pi3usb9201 device that needs to be - * emulated. It registers it with the I2C emulation controller. - * - * @param emul Emulation information - * @param parent Device to emulate - * - * @return 0 indicating success (always) - */ -static int pi3usb9201_emul_init(const struct emul *emul, - const struct device *parent) -{ - const struct pi3usb9201_emul_cfg *cfg = emul->cfg; - struct pi3usb9201_emul_data *data = cfg->data; - int ret; - - data->emul.api = &pi3usb9201_emul_api; - data->emul.addr = cfg->addr; - data->i2c = parent; - data->cfg = cfg; - - ret = i2c_emul_register(parent, emul->dev_label, &data->emul); - - pi3usb9201_emul_reset(&data->emul); - - return ret; -} - -#define PI3USB9201_EMUL(n) \ - static struct pi3usb9201_emul_data pi3usb9201_emul_data_##n = {}; \ - static const struct pi3usb9201_emul_cfg pi3usb9201_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .data = &pi3usb9201_emul_data_##n, \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - EMUL_DEFINE(pi3usb9201_emul_init, DT_DRV_INST(n), \ - &pi3usb9201_emul_cfg_##n, &pi3usb9201_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(PI3USB9201_EMUL) - -#define PI3USB9201_EMUL_CASE(n) \ - case DT_INST_DEP_ORD(n): return &pi3usb9201_emul_data_##n.emul; - -struct i2c_emul *pi3usb9201_emul_get(int ord) -{ - switch (ord) { - DT_INST_FOREACH_STATUS_OKAY(PI3USB9201_EMUL_CASE) - - default: - return NULL; - } -} diff --git a/zephyr/emul/emul_smart_battery.c b/zephyr/emul/emul_smart_battery.c deleted file mode 100644 index 4b1d87336e..0000000000 --- a/zephyr/emul/emul_smart_battery.c +++ /dev/null @@ -1,893 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT zephyr_smart_battery - -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(smart_battery); - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_common_i2c.h" -#include "emul/emul_smart_battery.h" - -#include "crc8.h" -#include "battery_smart.h" - -#define SBAT_DATA_FROM_I2C_EMUL(_emul) \ - CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \ - struct sbat_emul_data, common) - -/** Run-time data used by the emulator */ -struct sbat_emul_data { - /** Common I2C data */ - struct i2c_common_emul_data common; - - /** Data required to simulate battery */ - struct sbat_emul_bat_data bat; - /** Command that should be handled next */ - int cur_cmd; - /** Message buffer which is used to handle smb transactions */ - uint8_t msg_buf[MSG_BUF_LEN]; - /** Total bytes that were generated in response to smb read operation */ - int num_to_read; -}; - -/** Check description in emul_smart_battery.h */ -struct sbat_emul_bat_data *sbat_emul_get_bat_data(struct i2c_emul *emul) -{ - struct sbat_emul_data *data; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - - return &data->bat; -} - -/** Check description in emul_smart_battery.h */ -uint16_t sbat_emul_date_to_word(unsigned int day, unsigned int month, - unsigned int year) -{ - year -= MANUFACTURE_DATE_YEAR_OFFSET; - year <<= MANUFACTURE_DATE_YEAR_SHIFT; - year &= MANUFACTURE_DATE_YEAR_MASK; - month <<= MANUFACTURE_DATE_MONTH_SHIFT; - month &= MANUFACTURE_DATE_MONTH_MASK; - day <<= MANUFACTURE_DATE_DAY_SHIFT; - day &= MANUFACTURE_DATE_DAY_MASK; - - return day | month | year; -} - -/** - * @brief Compute CRC from the beginning of the message - * - * @param addr Smart battery address on SMBus - * @param read If message for which CRC is computed is read. For read message - * byte command and repeated address is added to CRC - * @param cmd Command used in read message - * - * @return pec CRC from first bytes of message - */ -static uint8_t sbat_emul_pec_head(uint8_t addr, int read, uint8_t cmd) -{ - uint8_t pec; - - addr <<= 1; - - pec = cros_crc8(&addr, 1); - if (!read) { - return pec; - } - - pec = cros_crc8_arg(&cmd, 1, pec); - addr |= I2C_MSG_READ; - pec = cros_crc8_arg(&addr, 1, pec); - - return pec; -} - -/** - * @brief Convert from 10mW power units to mA current under given mV voltage - * - * @param mw Power in 10mW units - * @param mv Voltage in mV units - * - * @return Current in mA units - */ -static uint16_t sbat_emul_10mw_to_ma(int mw, int mv) -{ - /* Smart battery use 10mW units, convert to mW */ - mw *= 10; - /* Multiple by 1000 to get mA instead of A */ - return 1000 * mw/mv; -} - -/** - * @brief Convert from mA current to 10mW power under given mV voltage - * - * @param ma Current in mA units - * @param mv Voltage in mV units - * - * @return Power in 10mW units - */ -static uint16_t sbat_emul_ma_to_10mw(int ma, int mv) -{ - int mw; - /* Divide by 1000 to get mW instead of uW */ - mw = ma * mv / 1000; - /* Smart battery use 10mW units, convert to 10mW */ - return mw / 10; -} - -/** - * @brief Get time in minutes how long it will take to get given amount of - * charge at given current flow - * - * @param bat Pointer to battery data to set error code in case of - * over/under flow in time calculation - * @param rate Rate of current in mAh - * @param cap Required amount of charge in mA - * @param time Pointer to memory where calculated time will be stored - * - * @return 0 on success - * @return -EINVAL when over or under flow occurred - */ -static int sbat_emul_get_time_to_complete(struct sbat_emul_bat_data *bat, - int rate, int cap, uint16_t *ret_time) -{ - int time; - - /* At negative rate process never ends, return maximum value */ - if (rate <= 0) { - *ret_time = UINT16_MAX; - - return 0; - } - /* Convert capacity from mAh to mAmin */ - time = cap * 60 / rate; - /* Check overflow */ - if (time >= UINT16_MAX) { - *ret_time = UINT16_MAX; - bat->error_code = STATUS_CODE_OVERUNDERFLOW; - - return -EINVAL; - } - /* Check underflow */ - if (time < 0) { - *ret_time = 0; - bat->error_code = STATUS_CODE_OVERUNDERFLOW; - - return -EINVAL; - } - - *ret_time = time; - - return 0; -} - -/** - * @brief Get time in minutes how long it will take to charge battery - * - * @param bat Pointer to battery data - * @param rate Rate of charging current in mAh - * @param time Pointer to memory where calculated time will be stored - * - * @return 0 on success - * @return -EINVAL when over or under flow occurred - */ -static int sbat_emul_time_to_full(struct sbat_emul_bat_data *bat, int rate, - uint16_t *time) -{ - int cap; - - cap = bat->full_cap - bat->cap; - return sbat_emul_get_time_to_complete(bat, rate, cap, time); -} - -/** - * @brief Get time in minutes how long it will take to discharge battery. Note, - * that rate should be negative to indicate discharging. - * - * @param bat Pointer to battery data - * @param rate Rate of charging current in mAh - * @param time Pointer to memory where calculated time will be stored - * - * @return 0 on success - * @return -EINVAL when over or under flow occurred - */ -static int sbat_emul_time_to_empty(struct sbat_emul_bat_data *bat, int rate, - uint16_t *time) -{ - int cap; - - /* Reverse to have discharging rate instead of charging rate */ - rate = -rate; - cap = bat->cap; - return sbat_emul_get_time_to_complete(bat, rate, cap, time); -} - -/** - * @brief Check if battery can supply for 10 seconds additional power/current - * set in at_rate register. - * - * @param bat Pointer to battery data - * @param rate Rate of charging current in mAh - * @param ok Pointer to memory where 0 is written if battery is able to supply - * additional power/curent or 1 is written if battery is unable - * to do so. - * - * @return 0 on success - */ -static int sbat_emul_read_at_rate_ok(struct sbat_emul_bat_data *bat, - uint16_t *ok) -{ - int rem_time_s; - int rate; - - rate = bat->at_rate; - if (bat->mode & MODE_CAPACITY) { - rate = sbat_emul_10mw_to_ma(rate, bat->design_mv); - } - - /* Add current battery usage */ - rate += bat->cur; - if (rate >= 0) { - /* Battery will be charged */ - *ok = 1; - - return 0; - } - /* Reverse to have discharging rate instead of charging rate */ - rate = -rate; - - rem_time_s = bat->cap * 3600 / rate; - if (rem_time_s > 10) { - /* - * Battery can support 10 seconds of additional at_rate - * current/power - */ - *ok = 1; - } else { - *ok = 0; - } - - return 0; -} - -/** - * @brief Get battery status. This function use emulated status register and - * set or clear some of the flags based on other properties of emulated - * smart battery. Discharge bit, capacity alarm, time alarm, fully - * discharged bit and error code are controlled by battery properties. - * Terminate charge/discharge/overcharge alarms are set only if they are - * set in emulated status register and battery is charging/discharging, - * so they are partialy controlled by emulated status register. - * Other bits are controlled by emulated status register - * - * @param emul Pointer to smart battery emulator - * - * @return value which equals to computed status register - */ -static uint16_t sbat_emul_read_status(struct i2c_emul *emul) -{ - uint16_t status, cap, rem_time, charge_percent; - struct sbat_emul_bat_data *bat; - struct sbat_emul_data *data; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - bat = &data->bat; - - status = bat->status; - - /* - * Over charged and terminate charger alarm cannot appear when battery - * is not charged - */ - if (bat->cur <= 0) { - status &= ~(STATUS_TERMINATE_CHARGE_ALARM | - STATUS_OVERCHARGED_ALARM); - status |= STATUS_DISCHARGING; - } - /* Terminate discharge alarm cannot appear when battery is charged */ - if (bat->cur >= 0) { - status &= ~(STATUS_TERMINATE_DISCHARGE_ALARM | - STATUS_DISCHARGING); - } - - sbat_emul_get_word_val(emul, SB_REMAINING_CAPACITY, &cap); - if (bat->cap_alarm && cap < bat->cap_alarm) { - status |= STATUS_REMAINING_CAPACITY_ALARM; - } else { - status &= ~STATUS_REMAINING_CAPACITY_ALARM; - } - - sbat_emul_get_word_val(emul, SB_AVERAGE_TIME_TO_EMPTY, &rem_time); - if (bat->time_alarm && rem_time < bat->time_alarm) { - status |= STATUS_REMAINING_TIME_ALARM; - } else { - status &= ~STATUS_REMAINING_TIME_ALARM; - } - - /* Unset fully discharged bit when charge is grater than 20% */ - sbat_emul_get_word_val(emul, SB_RELATIVE_STATE_OF_CHARGE, - &charge_percent); - if (charge_percent > 20) { - status &= ~STATUS_FULLY_DISCHARGED; - } else { - status |= STATUS_FULLY_DISCHARGED; - } - - status |= bat->error_code & STATUS_ERR_CODE_MASK; - - return status; -} - -/** Check description in emul_smart_battery.h */ -int sbat_emul_get_word_val(struct i2c_emul *emul, int cmd, uint16_t *val) -{ - struct sbat_emul_bat_data *bat; - struct sbat_emul_data *data; - int mode_mw; - int rate; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - bat = &data->bat; - mode_mw = bat->mode & MODE_CAPACITY; - - switch (cmd) { - case SB_MANUFACTURER_ACCESS: - *val = bat->mf_access; - return 0; - case SB_REMAINING_CAPACITY_ALARM: - *val = bat->cap_alarm; - return 0; - case SB_REMAINING_TIME_ALARM: - *val = bat->time_alarm; - return 0; - case SB_BATTERY_MODE: - *val = bat->mode; - return 0; - case SB_AT_RATE: - *val = bat->at_rate; - return 0; - case SB_AT_RATE_TIME_TO_FULL: - /* Support for reporting time to full in mW mode is optional */ - if (mode_mw && !bat->at_rate_full_mw_support) { - bat->error_code = STATUS_CODE_OVERUNDERFLOW; - *val = UINT16_MAX; - - return -EINVAL; - } - - rate = bat->at_rate; - if (mode_mw) { - rate = sbat_emul_10mw_to_ma(rate, bat->design_mv); - } - return sbat_emul_time_to_full(bat, rate, val); - - case SB_AT_RATE_TIME_TO_EMPTY: - rate = bat->at_rate; - if (mode_mw) { - rate = sbat_emul_10mw_to_ma(rate, bat->design_mv); - } - return sbat_emul_time_to_empty(bat, rate, val); - - case SB_AT_RATE_OK: - return sbat_emul_read_at_rate_ok(bat, val); - case SB_TEMPERATURE: - *val = bat->temp; - return 0; - case SB_VOLTAGE: - *val = bat->volt; - return 0; - case SB_CURRENT: - *val = bat->cur; - return 0; - case SB_AVERAGE_CURRENT: - *val = bat->avg_cur; - return 0; - case SB_MAX_ERROR: - *val = bat->max_error; - return 0; - case SB_RELATIVE_STATE_OF_CHARGE: - /* Percent of charge according to full capacity */ - *val = 100 * bat->cap / bat->full_cap; - return 0; - case SB_ABSOLUTE_STATE_OF_CHARGE: - /* Percent of charge according to design capacity */ - *val = 100 * bat->cap / bat->design_cap; - return 0; - case SB_REMAINING_CAPACITY: - if (mode_mw) { - *val = sbat_emul_ma_to_10mw(bat->cap, bat->design_mv); - } else { - *val = bat->cap; - } - return 0; - case SB_FULL_CHARGE_CAPACITY: - if (mode_mw) { - *val = sbat_emul_ma_to_10mw(bat->full_cap, - bat->design_mv); - } else { - *val = bat->full_cap; - } - return 0; - case SB_RUN_TIME_TO_EMPTY: - rate = bat->cur; - return sbat_emul_time_to_empty(bat, rate, val); - case SB_AVERAGE_TIME_TO_EMPTY: - rate = bat->avg_cur; - return sbat_emul_time_to_empty(bat, rate, val); - case SB_AVERAGE_TIME_TO_FULL: - rate = bat->avg_cur; - return sbat_emul_time_to_full(bat, rate, val); - case SB_CHARGING_CURRENT: - *val = bat->desired_charg_cur; - return 0; - case SB_CHARGING_VOLTAGE: - *val = bat->desired_charg_volt; - return 0; - case SB_BATTERY_STATUS: - *val = sbat_emul_read_status(emul); - return 0; - case SB_CYCLE_COUNT: - *val = bat->cycle_count; - return 0; - case SB_DESIGN_CAPACITY: - if (mode_mw) { - *val = sbat_emul_ma_to_10mw(bat->design_cap, - bat->design_mv); - } else { - *val = bat->design_cap; - } - return 0; - case SB_DESIGN_VOLTAGE: - *val = bat->design_mv; - return 0; - case SB_SPECIFICATION_INFO: - *val = bat->spec_info; - return 0; - case SB_MANUFACTURE_DATE: - *val = bat->mf_date; - return 0; - case SB_SERIAL_NUMBER: - *val = bat->sn; - return 0; - default: - /* Unknown command or return value is not word */ - return 1; - } -} - -/** Check description in emul_smart_battery.h */ -int sbat_emul_get_block_data(struct i2c_emul *emul, int cmd, uint8_t **blk, - int *len) -{ - struct sbat_emul_bat_data *bat; - struct sbat_emul_data *data; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - bat = &data->bat; - - switch (cmd) { - case SB_MANUFACTURER_NAME: - *blk = bat->mf_name; - *len = bat->mf_name_len; - return 0; - case SB_DEVICE_NAME: - *blk = bat->dev_name; - *len = bat->dev_name_len; - return 0; - case SB_DEVICE_CHEMISTRY: - *blk = bat->dev_chem; - *len = bat->dev_chem_len; - return 0; - case SB_MANUFACTURER_DATA: - *blk = bat->mf_data; - *len = bat->mf_data_len; - return 0; - default: - /* Unknown command or return value is not word */ - return 1; - } -} - -/** - * @brief Append PEC to read command response if battery support it - * - * @param data Pointer to smart battery emulator data - * @param cmd Command for which PEC is calculated - */ -static void sbat_emul_append_pec(struct sbat_emul_data *data, int cmd) -{ - uint8_t pec; - - if (BATTERY_SPEC_VERSION(data->bat.spec_info) == - BATTERY_SPEC_VER_1_1_WITH_PEC) { - pec = sbat_emul_pec_head(data->common.cfg->addr, 1, cmd); - pec = cros_crc8_arg(data->msg_buf, data->num_to_read, pec); - data->msg_buf[data->num_to_read] = pec; - data->num_to_read++; - } -} - -/** Check description in emul_smart_battery.h */ -void sbat_emul_set_response(struct i2c_emul *emul, int cmd, uint8_t *buf, - int len, bool fail) -{ - struct sbat_emul_data *data; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - - if (fail) { - data->bat.error_code = STATUS_CODE_UNKNOWN_ERROR; - data->num_to_read = 0; - return; - } - - data->num_to_read = MIN(len, MSG_BUF_LEN - 1); - memcpy(data->msg_buf, buf, data->num_to_read); - data->bat.error_code = STATUS_CODE_OK; - sbat_emul_append_pec(data, cmd); -} - -/** - * @brief Function which handles read messages. It expects that data->cur_cmd - * is set to command number which should be handled. It guarantee that - * data->num_to_read is set to number of bytes in data->msg_buf on - * successful handling read request. On error, data->num_to_read is - * always set to 0. - * - * @param emul Pointer to smart battery emulator - * @param reg Command selected by last write message. If data->cur_cmd is - * different than SBAT_EMUL_NO_CMD, then reg should equal to - * data->cur_cmd - * - * @return 0 on success - * @return -EIO on error - */ -static int sbat_emul_handle_read_msg(struct i2c_emul *emul, int reg) -{ - struct sbat_emul_data *data; - uint16_t word; - uint8_t *blk; - int ret, len; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - - if (data->cur_cmd == SBAT_EMUL_NO_CMD) { - /* Unexpected read message without preceding command select */ - data->bat.error_code = STATUS_CODE_UNKNOWN_ERROR; - return -EIO; - } - data->cur_cmd = SBAT_EMUL_NO_CMD; - data->num_to_read = 0; - - /* Handle commands which return word */ - ret = sbat_emul_get_word_val(emul, reg, &word); - if (ret < 0) { - return -EIO; - } - if (ret == 0) { - data->num_to_read = 2; - data->msg_buf[0] = word & 0xff; - data->msg_buf[1] = (word >> 8) & 0xff; - data->bat.error_code = STATUS_CODE_OK; - sbat_emul_append_pec(data, reg); - - return 0; - } - - /* Handle commands which return block */ - ret = sbat_emul_get_block_data(emul, reg, &blk, &len); - if (ret != 0) { - if (ret == 1) { - data->bat.error_code = STATUS_CODE_UNSUPPORTED; - LOG_ERR("Unknown read command (0x%x)", reg); - } - - return -EIO; - } - - data->num_to_read = len + 1; - data->msg_buf[0] = len; - memcpy(&data->msg_buf[1], blk, len); - data->bat.error_code = STATUS_CODE_OK; - sbat_emul_append_pec(data, reg); - - return 0; -} - -/** - * @brief Function which finalize write messages. - * - * @param emul Pointer to smart battery emulator - * @param reg First byte of write message, usually selected command - * @param bytes Number of bytes received in data->msg_buf - * - * @return 0 on success - * @return -EIO on error - */ -static int sbat_emul_finalize_write_msg(struct i2c_emul *emul, int reg, - int bytes) -{ - struct sbat_emul_bat_data *bat; - struct sbat_emul_data *data; - uint16_t word; - uint8_t pec; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - bat = &data->bat; - - /* - * Fail if: - * - there are no bytes to handle - * - there are too many bytes - * - there is command byte and only one data byte - */ - if (bytes <= 0 || bytes > 4 || bytes == 2) { - data->bat.error_code = STATUS_CODE_BADSIZE; - LOG_ERR("wrong write message size (%d)", bytes); - - return -EIO; - } - - /* There is only command for read */ - if (bytes == 1) { - data->cur_cmd = reg; - return 0; - } - - /* Handle PEC */ - data->msg_buf[0] = reg; - if (bytes == 4) { - if (BATTERY_SPEC_VERSION(data->bat.spec_info) != - BATTERY_SPEC_VER_1_1_WITH_PEC) { - data->bat.error_code = STATUS_CODE_BADSIZE; - LOG_ERR("Unexpected PEC; No support in this version"); - - return -EIO; - } - pec = sbat_emul_pec_head(data->common.cfg->addr, 0, 0); - pec = cros_crc8_arg(data->msg_buf, 3, pec); - if (pec != data->msg_buf[3]) { - data->bat.error_code = STATUS_CODE_UNKNOWN_ERROR; - LOG_ERR("Wrong PEC 0x%x != 0x%x", - pec, data->msg_buf[3]); - - return -EIO; - } - } - - word = ((int)data->msg_buf[2] << 8) | data->msg_buf[1]; - - switch (data->msg_buf[0]) { - case SB_MANUFACTURER_ACCESS: - bat->mf_access = word; - break; - case SB_REMAINING_CAPACITY_ALARM: - bat->cap_alarm = word; - break; - case SB_REMAINING_TIME_ALARM: - bat->time_alarm = word; - break; - case SB_BATTERY_MODE: - /* Allow to set only upper byte */ - bat->mode &= 0xff; - bat->mode |= word & 0xff00; - break; - case SB_AT_RATE: - bat->at_rate = word; - break; - default: - data->bat.error_code = STATUS_CODE_ACCESS_DENIED; - LOG_ERR("Unknown write command (0x%x)", data->msg_buf[0]); - - return -EIO; - } - - data->bat.error_code = STATUS_CODE_OK; - - return 0; -} - -/** - * @brief Function called for each byte of write message which is saved in - * data->msg_buf - * - * @param emul Pointer to smart battery emulator - * @param reg First byte of write message, usually selected command - * @param val Received byte of write message - * @param bytes Number of bytes already received - * - * @return 0 on success - */ -static int sbat_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val, - int bytes) -{ - struct sbat_emul_data *data; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - - if (bytes < MSG_BUF_LEN) { - data->msg_buf[bytes] = val; - } - - return 0; -} - -/** - * @brief Function called for each byte of read message. Byte from data->msg_buf - * is copied to read message response. - * - * @param emul Pointer to smart battery emulator - * @param reg First byte of last write message, usually selected command - * @param val Pointer where byte to read should be stored - * @param bytes Number of bytes already readed - * - * @return 0 on success - */ -static int sbat_emul_read_byte(struct i2c_emul *emul, int reg, uint8_t *val, - int bytes) -{ - struct sbat_emul_data *data; - - data = SBAT_DATA_FROM_I2C_EMUL(emul); - - if (bytes < data->num_to_read) { - *val = data->msg_buf[bytes]; - } - - return 0; -} - -/** - * @brief Get currently accessed register, which always equals to selected - * command. - * - * @param emul Pointer to smart battery emulator - * @param reg First byte of last write message, usually selected command - * @param bytes Number of bytes already handled from current message - * @param read If currently handled is read message - * - * @return Currently accessed register - */ -static int sbat_emul_access_reg(struct i2c_emul *emul, int reg, int bytes, - bool read) -{ - return reg; -} - -/* Device instantiation */ - -static struct i2c_emul_api sbat_emul_api = { - .transfer = i2c_common_emul_transfer, -}; - -/** - * @brief Set up a new Smart Battery emulator - * - * This should be called for each Smart Battery device that needs to be - * emulated. It registers it with the I2C emulation controller. - * - * @param emul Emulation information - * @param parent Device to emulate - * - * @return 0 indicating success (always) - */ -static int sbat_emul_init(const struct emul *emul, - const struct device *parent) -{ - const struct i2c_common_emul_cfg *cfg = emul->cfg; - struct i2c_common_emul_data *data = cfg->data; - int ret; - - data->emul.api = &sbat_emul_api; - data->emul.addr = cfg->addr; - data->i2c = parent; - data->cfg = cfg; - i2c_common_emul_init(data); - - ret = i2c_emul_register(parent, emul->dev_label, &data->emul); - - return ret; -} - -#define SMART_BATTERY_EMUL(n) \ - static struct sbat_emul_data sbat_emul_data_##n = { \ - .bat = { \ - .mf_access = DT_INST_PROP(n, mf_access), \ - .at_rate_full_mw_support = DT_INST_PROP(n, \ - at_rate_full_mw_support), \ - .spec_info = ((DT_STRING_TOKEN(DT_DRV_INST(n), \ - version) << \ - BATTERY_SPEC_VERSION_SHIFT) & \ - BATTERY_SPEC_VERSION_MASK) | \ - ((DT_INST_PROP(n, vscale) << \ - BATTERY_SPEC_VSCALE_SHIFT) & \ - BATTERY_SPEC_VSCALE_MASK) | \ - ((DT_INST_PROP(n, ipscale) << \ - BATTERY_SPEC_IPSCALE_SHIFT) & \ - BATTERY_SPEC_IPSCALE_MASK) | \ - BATTERY_SPEC_REVISION_1, \ - .mode = (DT_INST_PROP(n, \ - int_charge_controller) * \ - MODE_INTERNAL_CHARGE_CONTROLLER) | \ - (DT_INST_PROP(n, primary_battery) * \ - MODE_PRIMARY_BATTERY_SUPPORT), \ - .design_mv = DT_INST_PROP(n, design_mv), \ - .design_cap = DT_INST_PROP(n, design_cap), \ - .temp = DT_INST_PROP(n, temperature), \ - .volt = DT_INST_PROP(n, volt), \ - .cur = DT_INST_PROP(n, cur), \ - .avg_cur = DT_INST_PROP(n, avg_cur), \ - .max_error = DT_INST_PROP(n, max_error), \ - .cap = DT_INST_PROP(n, cap), \ - .full_cap = DT_INST_PROP(n, full_cap), \ - .desired_charg_cur = DT_INST_PROP(n, \ - desired_charg_cur), \ - .desired_charg_volt = DT_INST_PROP(n, \ - desired_charg_volt), \ - .cycle_count = DT_INST_PROP(n, cycle_count), \ - .sn = DT_INST_PROP(n, serial_number), \ - .mf_name = DT_INST_PROP(n, mf_name), \ - .mf_name_len = sizeof( \ - DT_INST_PROP(n, mf_name)) - 1, \ - .mf_data = DT_INST_PROP(n, mf_data), \ - .mf_data_len = sizeof( \ - DT_INST_PROP(n, mf_data)) - 1, \ - .dev_name = DT_INST_PROP(n, dev_name), \ - .dev_name_len = sizeof( \ - DT_INST_PROP(n, dev_name)) - 1, \ - .dev_chem = DT_INST_PROP(n, dev_chem), \ - .dev_chem_len = sizeof( \ - DT_INST_PROP(n, dev_chem)) - 1, \ - .mf_date = 0, \ - .cap_alarm = 0, \ - .time_alarm = 0, \ - .at_rate = 0, \ - .status = STATUS_INITIALIZED, \ - .error_code = STATUS_CODE_OK, \ - }, \ - .cur_cmd = SBAT_EMUL_NO_CMD, \ - .common = { \ - .start_write = NULL, \ - .write_byte = sbat_emul_write_byte, \ - .finish_write = sbat_emul_finalize_write_msg, \ - .start_read = sbat_emul_handle_read_msg, \ - .read_byte = sbat_emul_read_byte, \ - .finish_read = NULL, \ - .access_reg = sbat_emul_access_reg, \ - }, \ - }; \ - \ - static const struct i2c_common_emul_cfg sbat_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .dev_label = DT_INST_LABEL(n), \ - .data = &sbat_emul_data_##n.common, \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - EMUL_DEFINE(sbat_emul_init, DT_DRV_INST(n), &sbat_emul_cfg_##n, \ - &sbat_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(SMART_BATTERY_EMUL) - -#define SMART_BATTERY_EMUL_CASE(n) \ - case DT_INST_DEP_ORD(n): return &sbat_emul_data_##n.common.emul; - -/** Check description in emul_smart_battery.h */ -struct i2c_emul *sbat_emul_get_ptr(int ord) -{ - switch (ord) { - DT_INST_FOREACH_STATUS_OKAY(SMART_BATTERY_EMUL_CASE) - - default: - return NULL; - } -} diff --git a/zephyr/emul/emul_syv682x.c b/zephyr/emul/emul_syv682x.c deleted file mode 100644 index 3d76d10492..0000000000 --- a/zephyr/emul/emul_syv682x.c +++ /dev/null @@ -1,219 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT zephyr_syv682x_emul - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(syv682x); -#include <stdint.h> -#include <string.h> - -#include "emul/emul_syv682x.h" - -#define EMUL_REG_COUNT (SYV682X_CONTROL_4_REG + 1) -#define EMUL_REG_IS_VALID(reg) (reg >= 0 && reg < EMUL_REG_COUNT) - -struct syv682x_emul_data { - /** I2C emulator detail */ - struct i2c_emul emul; - /** Smart battery device being emulated */ - const struct device *i2c; - /** Configuration information */ - const struct syv682x_emul_cfg *cfg; - /** Current state of all emulated SYV682x registers */ - uint8_t reg[EMUL_REG_COUNT]; - /** - * Current state of conditions affecting interrupt bits, as distinct - * from the current values of those bits stored in reg. - */ - uint8_t status_cond; - uint8_t control_4_cond; -}; - -/** Static configuration for the emulator */ -struct syv682x_emul_cfg { - /** Label of the I2C bus this emulator connects to */ - const char *i2c_label; - /** Address of smart battery on i2c bus */ - uint16_t addr; - /** Pointer to runtime data */ - struct syv682x_emul_data *data; -}; - -int syv682x_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val) -{ - struct syv682x_emul_data *data; - - if (!EMUL_REG_IS_VALID(reg)) - return -EIO; - - data = CONTAINER_OF(emul, struct syv682x_emul_data, emul); - data->reg[reg] = val; - - return 0; -} - -void syv682x_emul_set_status(struct i2c_emul *emul, uint8_t val) -{ - struct syv682x_emul_data *data; - - data = CONTAINER_OF(emul, struct syv682x_emul_data, emul); - data->status_cond = val; - data->reg[SYV682X_STATUS_REG] |= val; -} - -int syv682x_emul_get_reg(struct i2c_emul *emul, int reg, uint8_t *val) -{ - struct syv682x_emul_data *data; - - if (!EMUL_REG_IS_VALID(reg)) - return -EIO; - - data = CONTAINER_OF(emul, struct syv682x_emul_data, emul); - *val = data->reg[reg]; - - return 0; -} - -/** - * Emulate an I2C transfer to an SYV682x. This handles simple reads and writes. - * - * @param emul I2C emulation information - * @param msgs List of messages to process. For 'read' messages, this function - * updates the 'buf' member with the data that was read - * @param num_msgs Number of messages to process - * @param addr Address of the I2C target device. - * - * @return 0 on success, -EIO on general input / output error - */ -static int syv682x_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs, - int num_msgs, int addr) -{ - const struct syv682x_emul_cfg *cfg; - struct syv682x_emul_data *data; - data = CONTAINER_OF(emul, struct syv682x_emul_data, emul); - cfg = data->cfg; - - if (cfg->addr != addr) { - LOG_ERR("Address mismatch, expected %02x, got %02x", cfg->addr, - addr); - return -EIO; - } - - i2c_dump_msgs("emul", msgs, num_msgs, addr); - - if (num_msgs == 1) { - if (!((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE - && msgs[0].len == 2)) { - LOG_ERR("Unexpected write msgs"); - return -EIO; - } - return syv682x_emul_set_reg(emul, msgs[0].buf[0], - msgs[0].buf[1]); - } else if (num_msgs == 2) { - int ret; - int reg; - uint8_t *buf; - - if (!((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE - && msgs[0].len == 1 - && (msgs[1].flags & I2C_MSG_RW_MASK) == - I2C_MSG_READ - && (msgs[1].len == 1))) { - LOG_ERR("Unexpected read msgs"); - return -EIO; - } - - reg = msgs[0].buf[0]; - buf = &msgs[1].buf[0]; - ret = syv682x_emul_get_reg(emul, reg, buf); - - switch (reg) { - /* - * These registers are clear-on-read (if the underlying - * condition has cleared). - */ - case SYV682X_STATUS_REG: - syv682x_emul_set_reg(emul, reg, data->status_cond); - break; - case SYV682X_CONTROL_4_REG: - syv682x_emul_set_reg(emul, reg, data->control_4_cond); - break; - default: - break; - } - - return ret; - } else { - LOG_ERR("Unexpected num_msgs"); - return -EIO; - } -} - -/* Device instantiation */ - -static struct i2c_emul_api syv682x_emul_api = { - .transfer = syv682x_emul_transfer, -}; - -/** - * @brief Set up a new SYV682x emulator - * - * This should be called for each SYV682x device that needs to be emulated. It - * registers it with the I2C emulation controller. - * - * @param emul Emulation information - * @param parent Device to emulate - * - * @return 0 indicating success (always) - */ -static int syv682x_emul_init(const struct emul *emul, - const struct device *parent) -{ - const struct syv682x_emul_cfg *cfg = emul->cfg; - struct syv682x_emul_data *data = cfg->data; - int ret; - - data->emul.api = &syv682x_emul_api; - data->emul.addr = cfg->addr; - data->i2c = parent; - data->cfg = cfg; - memset(data->reg, 0, sizeof(data->reg)); - - ret = i2c_emul_register(parent, emul->dev_label, &data->emul); - - return ret; -} - -#define SYV682X_EMUL(n) \ - static struct syv682x_emul_data syv682x_emul_data_##n = {}; \ - static const struct syv682x_emul_cfg syv682x_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .data = &syv682x_emul_data_##n, \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - EMUL_DEFINE(syv682x_emul_init, DT_DRV_INST(n), &syv682x_emul_cfg_##n, \ - &syv682x_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(SYV682X_EMUL) - -#define SYV682X_EMUL_CASE(n) \ - case DT_INST_DEP_ORD(n): return &syv682x_emul_data_##n.emul; - - -struct i2c_emul *syv682x_emul_get(int ord) -{ - switch (ord) { - DT_INST_FOREACH_STATUS_OKAY(SYV682X_EMUL_CASE) - - default: - return NULL; - } -} diff --git a/zephyr/emul/emul_tcs3400.c b/zephyr/emul/emul_tcs3400.c deleted file mode 100644 index 0fc432e9ff..0000000000 --- a/zephyr/emul/emul_tcs3400.c +++ /dev/null @@ -1,650 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT zephyr_tcs3400 - -#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL -#include <logging/log.h> -LOG_MODULE_REGISTER(emul_tcs); - -#include <device.h> -#include <emul.h> -#include <drivers/i2c.h> -#include <drivers/i2c_emul.h> - -#include "emul/emul_common_i2c.h" -#include "emul/emul_tcs3400.h" - -#include "driver/als_tcs3400.h" - -#define TCS_DATA_FROM_I2C_EMUL(_emul) \ - CONTAINER_OF(CONTAINER_OF(_emul, struct i2c_common_emul_data, emul), \ - struct tcs_emul_data, common) - -/** Run-time data used by the emulator */ -struct tcs_emul_data { - /** Common I2C data */ - struct i2c_common_emul_data common; - - /** Value of data byte in ongoing write message */ - uint8_t write_byte; - - /** Current state of emulated TCS3400 registers */ - uint8_t reg[TCS_EMUL_REG_COUNT]; - /** Return IR value instead of clear */ - bool ir_select; - /** Internal values of light sensor registers */ - int red; - int green; - int blue; - int clear; - int ir; - - /** ID registers value */ - uint8_t revision; - uint8_t id; - - /** Return error when trying to write to RO register */ - bool error_on_ro_write; - /** Return error when trying to write 1 to reserved bit */ - bool error_on_rsvd_write; - /** Return error when trying to access MSB before LSB */ - bool error_on_msb_first; - /** - * Flag set when LSB register is accessed and cleared when MSB is - * accessed. Allows to track order of accessing data registers - */ - bool lsb_r_read; - bool lsb_g_read; - bool lsb_b_read; - bool lsb_c_ir_read; -}; - -/** Check description in emul_tcs3400.h */ -void tcs_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val) -{ - struct tcs_emul_data *data; - - if (reg < TCS_EMUL_FIRST_REG || reg > TCS_EMUL_LAST_REG) { - return; - } - - reg -= TCS_EMUL_FIRST_REG; - data = TCS_DATA_FROM_I2C_EMUL(emul); - data->reg[reg] = val; -} - -/** Check description in emul_tcs3400.h */ -uint8_t tcs_emul_get_reg(struct i2c_emul *emul, int reg) -{ - struct tcs_emul_data *data; - - if (reg < TCS_EMUL_FIRST_REG || reg > TCS_EMUL_LAST_REG) { - return 0; - } - - data = TCS_DATA_FROM_I2C_EMUL(emul); - reg -= TCS_EMUL_FIRST_REG; - - return data->reg[reg]; -} - -/** Check description in emul_tcs3400.h */ -int tcs_emul_get_val(struct i2c_emul *emul, enum tcs_emul_axis axis) -{ - struct tcs_emul_data *data; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case TCS_EMUL_R: - return data->red; - case TCS_EMUL_G: - return data->green; - case TCS_EMUL_B: - return data->blue; - case TCS_EMUL_C: - return data->clear; - case TCS_EMUL_IR: - return data->ir; - } - - return 0; -} - -/** Check description in emul_tcs3400.h */ -void tcs_emul_set_val(struct i2c_emul *emul, enum tcs_emul_axis axis, int val) -{ - struct tcs_emul_data *data; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - - switch (axis) { - case TCS_EMUL_R: - data->red = val; - break; - case TCS_EMUL_G: - data->green = val; - break; - case TCS_EMUL_B: - data->blue = val; - break; - case TCS_EMUL_C: - data->clear = val; - break; - case TCS_EMUL_IR: - data->ir = val; - break; - } -} - -/** Check description in emul_tcs3400.h */ -void tcs_emul_set_err_on_ro_write(struct i2c_emul *emul, bool set) -{ - struct tcs_emul_data *data; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - data->error_on_ro_write = set; -} - -/** Check description in emul_tcs3400.h */ -void tcs_emul_set_err_on_rsvd_write(struct i2c_emul *emul, bool set) -{ - struct tcs_emul_data *data; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - data->error_on_rsvd_write = set; -} - -/** Check description in emul_tcs3400.h */ -void tcs_emul_set_err_on_msb_first(struct i2c_emul *emul, bool set) -{ - struct tcs_emul_data *data; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - data->error_on_msb_first = set; -} - -/** Mask reserved bits in registers of TCS3400 */ -static const uint8_t tcs_emul_rsvd_mask[] = { - [TCS_I2C_ENABLE - TCS_EMUL_FIRST_REG] = 0xa4, - [TCS_I2C_ATIME - TCS_EMUL_FIRST_REG] = 0x00, - [0x2] = 0xff, /* Reserved */ - [TCS_I2C_WTIME - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_AILTL - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_AILTH - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_AIHTL - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_AIHTH - TCS_EMUL_FIRST_REG] = 0x00, - [0x8 ... 0xb] = 0xff, /* Reserved */ - [TCS_I2C_PERS - TCS_EMUL_FIRST_REG] = 0xf0, - [TCS_I2C_CONFIG - TCS_EMUL_FIRST_REG] = 0x81, - [0xe] = 0xff, /* Reserved */ - [TCS_I2C_CONTROL - TCS_EMUL_FIRST_REG] = 0xfc, - [TCS_I2C_AUX - TCS_EMUL_FIRST_REG] = 0xdf, - [TCS_I2C_REVID - TCS_EMUL_FIRST_REG] = 0xf0, - [TCS_I2C_ID - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_STATUS - TCS_EMUL_FIRST_REG] = 0x6e, - [TCS_I2C_CDATAL - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_CDATAH - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_RDATAL - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_RDATAH - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_GDATAL - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_GDATAH - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_BDATAL - TCS_EMUL_FIRST_REG] = 0x00, - [TCS_I2C_BDATAH - TCS_EMUL_FIRST_REG] = 0x00, -}; - -/** - * @brief Reset registers to default values - * - * @param emul Pointer to TCS3400 emulator - */ -static void tcs_emul_reset(struct i2c_emul *emul) -{ - struct tcs_emul_data *data; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - - data->reg[TCS_I2C_ENABLE - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_ATIME - TCS_EMUL_FIRST_REG] = 0xff; - data->reg[TCS_I2C_WTIME - TCS_EMUL_FIRST_REG] = 0xff; - data->reg[TCS_I2C_AILTL - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_AILTH - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_AIHTL - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_AIHTH - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_PERS - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_CONFIG - TCS_EMUL_FIRST_REG] = 0x40; - data->reg[TCS_I2C_CONTROL - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_AUX - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_REVID - TCS_EMUL_FIRST_REG] = data->revision; - data->reg[TCS_I2C_ID - TCS_EMUL_FIRST_REG] = data->id; - data->reg[TCS_I2C_STATUS - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_CDATAL - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_CDATAH - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_RDATAL - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_RDATAH - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_GDATAL - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_GDATAH - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_BDATAL - TCS_EMUL_FIRST_REG] = 0x00; - data->reg[TCS_I2C_BDATAH - TCS_EMUL_FIRST_REG] = 0x00; - - data->ir_select = false; -} - -/** - * @brief Convert gain in format of CONTROL register to multiplyer - * - * @param control Value of CONTROL register - * - * @return gain by which messured value should be multiplied - */ -static int tcs_emul_get_gain(uint8_t control) -{ - switch (control & TCS_I2C_CONTROL_MASK) { - case 0: - return 1; - case 1: - return 4; - case 2: - return 16; - case 3: - return 64; - default: - return -1; - } -} - -/** - * @brief Convert number of cycles in format of ATIME register - * - * @param atime Value of ATIME register - * - * @return cycles count that should be used to obtain light sensor values - */ -static int tcs_emul_get_cycles(uint8_t atime) -{ - return TCS_EMUL_MAX_CYCLES - (int)atime; -} - -/** - * @brief Clear all interrupt registers - * - * @param emul Pointer to TCS3400 emulator - */ -static void tcs_emul_clear_int(struct i2c_emul *emul) -{ - struct tcs_emul_data *data; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - - data->reg[TCS_I2C_STATUS - TCS_EMUL_FIRST_REG] = 0x00; -} - -/** - * @brief Handle I2C write message. It is checked if accessed register isn't RO - * and reserved bits are set to 0. Write set value of reg field of TCS - * emulator data ignoring reserved bits and write only bits. Some - * commands are handled specialy. - * - * @param emul Pointer to TCS3400 emulator - * @param reg Register which is written - * @param bytes Number of bytes received in this write message - * - * @return 0 on success - * @return -EIO on error - */ -static int tcs_emul_handle_write(struct i2c_emul *emul, int reg, int bytes) -{ - struct tcs_emul_data *data; - uint8_t val; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - - /* This write only selected register for I2C read message */ - if (bytes < 2) { - return 0; - } - - val = data->write_byte; - - /* Register is in data->reg */ - if (reg >= TCS_EMUL_FIRST_REG && reg <= TCS_EMUL_LAST_REG) { - if (reg >= TCS_I2C_REVID && reg <= TCS_I2C_BDATAH) { - if (data->error_on_ro_write) { - LOG_ERR("Writing to reg 0x%x which is RO", reg); - return -EIO; - } - - return 0; - } - - if (reg == TCS_I2C_CONFIG && data->error_on_rsvd_write && - !(BIT(6) & val)) { - LOG_ERR("CONFIG reg bit 6 is write as 6 (writing 0x%x)", - val); - return -EIO; - } - - reg -= TCS_EMUL_FIRST_REG; - if (data->error_on_rsvd_write && - tcs_emul_rsvd_mask[reg] & val) { - LOG_ERR("Writing 0x%x to reg 0x%x with rsvd mask 0x%x", - val, reg + TCS_EMUL_FIRST_REG, - tcs_emul_rsvd_mask[reg]); - return -EIO; - } - - /* Ignore all reserved bits */ - val &= ~tcs_emul_rsvd_mask[reg]; - val |= data->reg[reg] & tcs_emul_rsvd_mask[reg]; - - data->reg[reg] = val; - - return 0; - } - - switch (reg) { - case TCS_I2C_IR: - if (data->error_on_rsvd_write && 0x7f & val) { - LOG_ERR("Writing 0x%x to reg 0x%x with rsvd mask 0x7f", - val, reg); - return -EIO; - } - data->ir_select = !!(val & BIT(7)); - break; - case TCS_I2C_IFORCE: - /* Interrupt generate is not supported */ - break; - case TCS_I2C_CICLEAR: - case TCS_I2C_AICLEAR: - tcs_emul_clear_int(emul); - break; - default: - /* Assume that other registers are RO */ - if (data->error_on_ro_write) { - LOG_ERR("Writing to reg 0x%x which is RO (unknown)", - reg); - return -EIO; - } - } - - return 0; -} - -/** - * @brief Get set light sensor value for given register using internal - * state @p val. In case of accessing MSB check if LSB was accessed first - * - * @param emul Pointer to TCS3400 emulator - * @param reg LSB or MSB register address. LSB has to be aligned to 2 - * @param lsb_read Pointer to variable which represent if last access to this - * accelerometer value was through LSB register - * @param lsb True if now accessing LSB, Flase if now accessing MSB - * @param val Internal value of accessed light sensor - * - * @return 0 on success - * @return -EIO when accessing MSB before LSB - */ -static int tcs_emul_get_reg_val(struct i2c_emul *emul, int reg, - bool *lsb_read, bool lsb, unsigned int val) -{ - struct tcs_emul_data *data; - uint64_t reg_val; - int msb_reg; - int lsb_reg; - int cycles; - int gain; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - - if (lsb) { - *lsb_read = 1; - } else { - /* - * If error on first accessing MSB is set and LSB wasn't - * accessed before, then return error. - */ - if (data->error_on_msb_first && !(*lsb_read)) { - return -EIO; - } - *lsb_read = 0; - /* LSB read should set correct value */ - return 0; - } - - lsb_reg = (reg - TCS_EMUL_FIRST_REG) & ~(0x1); - msb_reg = (reg - TCS_EMUL_FIRST_REG) | 0x1; - - gain = tcs_emul_get_gain(data->reg[TCS_I2C_CONTROL - - TCS_EMUL_FIRST_REG]); - cycles = tcs_emul_get_cycles(data->reg[TCS_I2C_ATIME - - TCS_EMUL_FIRST_REG]); - /* - * Internal value is with 256 cycles and x64 gain, so divide it to get - * registers value - */ - reg_val = (uint64_t)val * cycles * gain / TCS_EMUL_MAX_CYCLES / - TCS_EMUL_MAX_GAIN; - - if (reg_val > UINT16_MAX) { - reg_val = UINT16_MAX; - } - - data->reg[lsb_reg] = reg_val & 0xff; - data->reg[msb_reg] = (reg_val >> 8) & 0xff; - - return 0; -} - -/** - * @brief Handle I2C read message. Response is obtained from reg field of TCS - * emul data. When accessing light sensor value, register data is first - * computed using internal emulator state. - * - * @param emul Pointer to TCS3400 emulator - * @param reg First register address that is accessed in this read message - * @param buf Pointer where result should be stored - * @param bytes Number of bytes already handled in this read message - * - * @return 0 on success - * @return -EIO on error - */ -static int tcs_emul_handle_read(struct i2c_emul *emul, int reg, uint8_t *buf, - int bytes) -{ - struct tcs_emul_data *data; - unsigned int c_ir; - int ret; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - - reg += bytes; - - if ((reg < TCS_EMUL_FIRST_REG || reg > TCS_EMUL_LAST_REG) && - reg != TCS_I2C_IR) { - LOG_ERR("Accessing register 0x%x which cannot be read", reg); - return -EIO; - } - - switch (reg) { - case TCS_I2C_CDATAL: - /* Shouldn't fail for LSB */ - c_ir = data->ir_select ? data->ir : data->clear; - ret = tcs_emul_get_reg_val(emul, reg, &data->lsb_c_ir_read, - true, c_ir); - break; - case TCS_I2C_CDATAH: - c_ir = data->ir_select ? data->ir : data->clear; - ret = tcs_emul_get_reg_val(emul, reg, &data->lsb_c_ir_read, - false, c_ir); - if (ret) { - LOG_ERR("MSB C read before LSB C"); - return -EIO; - } - break; - case TCS_I2C_RDATAL: - /* Shouldn't fail for LSB */ - ret = tcs_emul_get_reg_val(emul, reg, &data->lsb_r_read, - true, data->red); - break; - case TCS_I2C_RDATAH: - ret = tcs_emul_get_reg_val(emul, reg, &data->lsb_r_read, - false, data->red); - if (ret) { - LOG_ERR("MSB R read before LSB R"); - return -EIO; - } - break; - case TCS_I2C_GDATAL: - /* Shouldn't fail for LSB */ - ret = tcs_emul_get_reg_val(emul, reg, &data->lsb_g_read, - true, data->green); - break; - case TCS_I2C_GDATAH: - ret = tcs_emul_get_reg_val(emul, reg, &data->lsb_g_read, - false, data->green); - if (ret) { - LOG_ERR("MSB G read before LSB G"); - return -EIO; - } - break; - case TCS_I2C_BDATAL: - /* Shouldn't fail for LSB */ - ret = tcs_emul_get_reg_val(emul, reg, &data->lsb_b_read, - true, data->blue); - break; - case TCS_I2C_BDATAH: - ret = tcs_emul_get_reg_val(emul, reg, &data->lsb_b_read, - false, data->blue); - if (ret) { - LOG_ERR("MSB B read before LSB B"); - return -EIO; - } - break; - case TCS_I2C_IR: - *buf = data->ir_select ? BIT(7) : 0; - - return 0; - } - - *buf = data->reg[reg - TCS_EMUL_FIRST_REG]; - - return 0; -} - -/** - * @brief Handle I2C write message. Check if message is not too long and saves - * data that will be stored in register - * - * @param emul Pointer to TCS3400 emulator - * @param reg Register address that is accessed - * @param val Data to write to the register - * @param bytes Number of bytes already handled in this read message - * - * @return 0 on success - * @return -EIO on error - */ -static int tcs_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val, - int bytes) -{ - struct tcs_emul_data *data; - - data = TCS_DATA_FROM_I2C_EMUL(emul); - - if (bytes > 1) { - LOG_ERR("Too long write command"); - return -EIO; - } - - data->write_byte = val; - - return 0; -} - -/* Device instantiation */ - -static struct i2c_emul_api tcs_emul_api = { - .transfer = i2c_common_emul_transfer, -}; - -/** - * @brief Set up a new TCS3400 emulator - * - * This should be called for each TCS3400 device that needs to be - * emulated. It registers it with the I2C emulation controller. - * - * @param emul Emulation information - * @param parent Device to emulate - * - * @return 0 indicating success (always) - */ -static int tcs_emul_init(const struct emul *emul, - const struct device *parent) -{ - const struct i2c_common_emul_cfg *cfg = emul->cfg; - struct i2c_common_emul_data *data = cfg->data; - int ret; - - data->emul.api = &tcs_emul_api; - data->emul.addr = cfg->addr; - data->i2c = parent; - data->cfg = cfg; - i2c_common_emul_init(data); - - ret = i2c_emul_register(parent, emul->dev_label, &data->emul); - - tcs_emul_reset(&data->emul); - - return ret; -} - -#define TCS3400_EMUL(n) \ - static struct tcs_emul_data tcs_emul_data_##n = { \ - .revision = DT_INST_PROP(n, revision), \ - .id = DT_STRING_TOKEN(DT_DRV_INST(n), device_id), \ - .error_on_ro_write = DT_INST_PROP(n, error_on_ro_write),\ - .error_on_rsvd_write = DT_INST_PROP(n, \ - error_on_reserved_bit_write), \ - .error_on_msb_first = DT_INST_PROP(n, \ - error_on_msb_first_access), \ - .lsb_c_ir_read = 0, \ - .lsb_r_read = 0, \ - .lsb_g_read = 0, \ - .lsb_b_read = 0, \ - .common = { \ - .start_write = NULL, \ - .write_byte = tcs_emul_write_byte, \ - .finish_write = tcs_emul_handle_write, \ - .start_read = NULL, \ - .read_byte = tcs_emul_handle_read, \ - .finish_read = NULL, \ - .access_reg = NULL, \ - }, \ - }; \ - \ - static const struct i2c_common_emul_cfg tcs_emul_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .dev_label = DT_INST_LABEL(n), \ - .data = &tcs_emul_data_##n.common, \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - EMUL_DEFINE(tcs_emul_init, DT_DRV_INST(n), &tcs_emul_cfg_##n, \ - &tcs_emul_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(TCS3400_EMUL) - -#define TCS3400_EMUL_CASE(n) \ - case DT_INST_DEP_ORD(n): return &tcs_emul_data_##n.common.emul; - -/** Check description in emul_tcs3400.h */ -struct i2c_emul *tcs_emul_get(int ord) -{ - switch (ord) { - DT_INST_FOREACH_STATUS_OKAY(TCS3400_EMUL_CASE) - - default: - return NULL; - } -} diff --git a/zephyr/emul/i2c_mock.c b/zephyr/emul/i2c_mock.c deleted file mode 100644 index 7c3722ad2e..0000000000 --- a/zephyr/emul/i2c_mock.c +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright 2021 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define DT_DRV_COMPAT cros_i2c_mock - -#include <device.h> -#include "emul/emul_common_i2c.h" - -#include <logging/log.h> -LOG_MODULE_REGISTER(i2c_mock, CONFIG_I2C_MOCK_LOG_LEVEL); - -struct i2c_emul *i2c_mock_to_i2c_emul(const struct emul *emul) -{ - struct i2c_common_emul_data *data = emul->data; - - return &(data->emul); -} - -void i2c_mock_reset(const struct emul *emul) -{ - struct i2c_emul *i2c_emul = i2c_mock_to_i2c_emul(emul); - - i2c_common_emul_set_read_fail_reg(i2c_emul, - I2C_COMMON_EMUL_NO_FAIL_REG); - i2c_common_emul_set_write_fail_reg(i2c_emul, - I2C_COMMON_EMUL_NO_FAIL_REG); - i2c_common_emul_set_read_func(i2c_emul, NULL, NULL); - i2c_common_emul_set_write_func(i2c_emul, NULL, NULL); -} - -uint16_t i2c_mock_get_addr(const struct emul *emul) -{ - const struct i2c_common_emul_cfg *cfg = emul->cfg; - - return cfg->addr; -} - -static const struct i2c_emul_api i2c_mock_api = { - .transfer = i2c_common_emul_transfer, -}; - -static int i2c_mock_init(const struct emul *emul, - const struct device *parent) -{ - const struct i2c_common_emul_cfg *cfg = emul->cfg; - struct i2c_common_emul_data *data = emul->data; - - data->emul.api = &i2c_mock_api; - data->emul.addr = cfg->addr; - data->emul.parent = emul; - data->i2c = parent; - data->cfg = cfg; - i2c_common_emul_init(data); - - return i2c_emul_register(parent, emul->dev_label, &data->emul); -} - -#define INIT_I2C_MOCK(n) \ - static const struct i2c_common_emul_cfg i2c_mock_cfg_##n = { \ - .i2c_label = DT_INST_BUS_LABEL(n), \ - .dev_label = DT_INST_LABEL(n), \ - .addr = DT_INST_REG_ADDR(n), \ - }; \ - static struct i2c_common_emul_data i2c_mock_data_##n; \ - EMUL_DEFINE(i2c_mock_init, DT_DRV_INST(n), &i2c_mock_cfg_##n, \ - &i2c_mock_data_##n) - -DT_INST_FOREACH_STATUS_OKAY(INIT_I2C_MOCK) |