summaryrefslogtreecommitdiff
path: root/zephyr/emul/emul_bma255.c
diff options
context:
space:
mode:
authorTomasz Michalec <tm@semihalf.com>2021-09-02 17:23:34 +0200
committerCommit Bot <commit-bot@chromium.org>2021-09-03 15:35:24 +0000
commit2766160a4bcec633694492915b2a8d0c3068851f (patch)
tree5e5062f28c043ba04835496940e3b888bd6a0e46 /zephyr/emul/emul_bma255.c
parent7c543a2dc09f9302eaf4ae9a2f529a0fb9f88244 (diff)
downloadchrome-ec-2766160a4bcec633694492915b2a8d0c3068851f.tar.gz
zephyr: emul: Use common I2C code in emulators
Align following emulators to use common I2C code: - bb_retimer - bma255 - bmi (both 160 and 260) - smart_battery - tcs3400 BUG=none BRANCH=none TEST=make configure --test zephyr/test/drivers Signed-off-by: Tomasz Michalec <tm@semihalf.com> Change-Id: I7515407b867487574a29dcae3456d96920a24979 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3140202 Commit-Queue: Jeremy Bettis <jbettis@chromium.org> Reviewed-by: Jeremy Bettis <jbettis@chromium.org>
Diffstat (limited to 'zephyr/emul/emul_bma255.c')
-rw-r--r--zephyr/emul/emul_bma255.c385
1 files changed, 94 insertions, 291 deletions
diff --git a/zephyr/emul/emul_bma255.c b/zephyr/emul/emul_bma255.c
index 073e196df8..9b6c401d0d 100644
--- a/zephyr/emul/emul_bma255.c
+++ b/zephyr/emul/emul_bma255.c
@@ -14,29 +14,22 @@ LOG_MODULE_REGISTER(emul_bma255);
#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"
-/**
- * Describe if there is no ongoing I2C message or if there is message handled
- * at the moment (last message doesn't ended with stop or write is not followed
- * by read).
- */
-enum bma_emul_msg_state {
- BMA_EMUL_NONE_MSG,
- BMA_EMUL_IN_WRITE,
- BMA_EMUL_IN_READ
-};
+#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 {
- /** I2C emulator detail */
- struct i2c_emul emul;
- /** BMA255 device being emulated */
- const struct device *i2c;
- /** Configuration information */
- const struct bma_emul_cfg *cfg;
+ /** 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];
@@ -78,87 +71,9 @@ struct bma_emul_data {
bool lsb_x_read;
bool lsb_y_read;
bool lsb_z_read;
-
- /** Current state of I2C bus (if emulator is handling message) */
- enum bma_emul_msg_state msg_state;
- /** Number of already handled bytes in ongoing message */
- int msg_byte;
- /** Register selected in last write command */
- uint8_t cur_reg;
- /** Value of data byte in ongoing write message */
- uint8_t write_byte;
-
- /** Custom write function called on I2C write opperation */
- bma_emul_write_func write_func;
- /** Data passed to custom write function */
- void *write_func_data;
- /** Custom read function called on I2C read opperation */
- bma_emul_read_func read_func;
- /** Data passed to custom read function */
- void *read_func_data;
-
- /** Control if read should fail on given register */
- int read_fail_reg;
- /** Control if write should fail on given register */
- int write_fail_reg;
-
- /** Mutex used to control access to emulator data */
- struct k_mutex data_mtx;
-};
-
-/** Static configuration for the emulator */
-struct bma_emul_cfg {
- /** Label of the I2C bus this emulator connects to */
- const char *i2c_label;
- /** Pointer to run-time data */
- struct bma_emul_data *data;
- /** Address of BMA255 on i2c bus */
- uint16_t addr;
};
/** Check description in emul_bma255.h */
-int bma_emul_lock_data(struct i2c_emul *emul, k_timeout_t timeout)
-{
- struct bma_emul_data *data;
-
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
-
- return k_mutex_lock(&data->data_mtx, timeout);
-}
-
-/** Check description in emul_bma255.h */
-int bma_emul_unlock_data(struct i2c_emul *emul)
-{
- struct bma_emul_data *data;
-
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
-
- return k_mutex_unlock(&data->data_mtx);
-}
-
-/** Check description in emul_bma255.h */
-void bma_emul_set_write_func(struct i2c_emul *emul,
- bma_emul_write_func func, void *data)
-{
- struct bma_emul_data *emul_data;
-
- emul_data = CONTAINER_OF(emul, struct bma_emul_data, emul);
- emul_data->write_func = func;
- emul_data->write_func_data = data;
-}
-
-/** Check description in emul_bma255.h */
-void bma_emul_set_read_func(struct i2c_emul *emul,
- bma_emul_read_func func, void *data)
-{
- struct bma_emul_data *emul_data;
-
- emul_data = CONTAINER_OF(emul, struct bma_emul_data, emul);
- emul_data->read_func = func;
- emul_data->read_func_data = data;
-}
-
-/** 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;
@@ -167,7 +82,7 @@ void bma_emul_set_reg(struct i2c_emul *emul, int reg, uint8_t val)
return;
}
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
data->reg[reg] = val;
}
@@ -180,29 +95,11 @@ uint8_t bma_emul_get_reg(struct i2c_emul *emul, int reg)
return 0;
}
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
return data->reg[reg];
}
-/** Check description in emul_bma255.h */
-void bma_emul_set_read_fail_reg(struct i2c_emul *emul, int reg)
-{
- struct bma_emul_data *data;
-
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
- data->read_fail_reg = reg;
-}
-
-/** Check description in emul_bma255.h */
-void bma_emul_set_write_fail_reg(struct i2c_emul *emul, int reg)
-{
- struct bma_emul_data *data;
-
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
- data->write_fail_reg = reg;
-}
-
/**
* @brief Convert @p val to two's complement representation. It makes sure that
* bit representation is correct even on platforms which represent
@@ -289,7 +186,7 @@ int16_t bma_emul_get_off(struct i2c_emul *emul, int axis)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
switch (axis) {
case BMA_EMUL_AXIS_X:
@@ -308,7 +205,7 @@ void bma_emul_set_off(struct i2c_emul *emul, int axis, int16_t val)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
switch (axis) {
case BMA_EMUL_AXIS_X:
@@ -334,7 +231,7 @@ int16_t bma_emul_get_acc(struct i2c_emul *emul, int axis)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
switch (axis) {
case BMA_EMUL_AXIS_X:
@@ -353,7 +250,7 @@ void bma_emul_set_acc(struct i2c_emul *emul, int axis, int16_t val)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
switch (axis) {
case BMA_EMUL_AXIS_X:
@@ -373,7 +270,7 @@ void bma_emul_set_err_on_cal_nrdy(struct i2c_emul *emul, bool set)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
data->error_on_cal_trg_nrdy = set;
}
@@ -382,7 +279,7 @@ void bma_emul_set_err_on_cal_bad_range(struct i2c_emul *emul, bool set)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
data->error_on_cal_trg_bad_range = set;
}
@@ -391,7 +288,7 @@ void bma_emul_set_err_on_ro_write(struct i2c_emul *emul, bool set)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
data->error_on_ro_write = set;
}
@@ -400,7 +297,7 @@ void bma_emul_set_err_on_rsvd_write(struct i2c_emul *emul, bool set)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
data->error_on_rsvd_write = set;
}
@@ -409,7 +306,7 @@ void bma_emul_set_err_on_msb_first(struct i2c_emul *emul, bool set)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
data->error_on_msb_first = set;
}
@@ -491,7 +388,7 @@ static void bma_emul_restore_nvm(struct i2c_emul *emul)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
/* Restore registers values */
data->reg[BMA2x2_OFFSET_X_AXIS_ADDR] = data->nvm_x;
@@ -515,7 +412,7 @@ static void bma_emul_reset(struct i2c_emul *emul)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
data->reg[BMA2x2_CHIP_ID_ADDR] = 0xfa;
data->reg[0x01] = 0x00; /* Reserved */
@@ -622,7 +519,7 @@ static int bma_emul_handle_nvm_write(struct i2c_emul *emul, uint8_t val)
struct bma_emul_data *data;
uint8_t writes_rem;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
/* NVM not ready, ignore write/load requests */
if (!(data->reg[BMA2x2_EEPROM_CTRL_ADDR] & BMA2x2_EEPROM_RDY)) {
@@ -665,7 +562,7 @@ static void bma_emul_clear_int(struct i2c_emul *emul)
{
struct bma_emul_data *data;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
data->reg[BMA2x2_STAT1_ADDR] = 0x00;
data->reg[BMA2x2_STAT2_ADDR] = 0x00;
@@ -687,7 +584,7 @@ static int16_t bma_emul_get_target(struct i2c_emul *emul, int axis)
struct bma_emul_data *data;
uint8_t target;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
target = data->reg[BMA2x2_OFC_SETTING_ADDR] >>
BMA2x2_OFC_TARGET_AXIS(axis);
@@ -723,7 +620,7 @@ static int bma_emul_handle_off_comp(struct i2c_emul *emul, uint8_t val)
uint8_t trigger;
int16_t target;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
if (val & BMA2x2_OFFSET_RESET) {
data->off_x = 0;
@@ -775,37 +672,35 @@ static int bma_emul_handle_off_comp(struct i2c_emul *emul, uint8_t val)
* @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. Before any handling, custom function
- * is called if provided.
+ * commands are handled specialy.
*
* @param emul Pointer to BMA255 emulator
* @param reg Register which is written
- * @param val Value being written to @p reg
+ * @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, uint8_t val)
+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 = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
- if (data->write_func) {
- ret = data->write_func(emul, reg, val, data->write_func_data);
- if (ret < 0) {
- return -EIO;
- } else if (ret == 0) {
- return 0;
- }
- }
+ val = data->write_byte;
- if (data->write_fail_reg == reg ||
- data->write_fail_reg == BMA_EMUL_FAIL_ALL_REG) {
+ 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) {
@@ -907,7 +802,7 @@ static int bma_emul_get_acc_val(struct i2c_emul *emul, int lsb_reg,
int msb_reg;
int shift;
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
if (lsb) {
*lsb_read = 1;
@@ -941,46 +836,47 @@ static int bma_emul_get_acc_val(struct i2c_emul *emul, int lsb_reg,
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. Before default handler, custom
- * user read function is called if provided.
+ * computed using internal emulator state.
*
* @param emul Pointer to BMA255 emulator
* @param reg Register address to read
- * @param buf Pointer where resultat should be stored
+ * @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, char *buf)
+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 = CONTAINER_OF(emul, struct bma_emul_data, emul);
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
- if (reg > BMA2x2_FIFO_DATA_OUTPUT_ADDR) {
- reg = BMA2x2_FIFO_DATA_OUTPUT_ADDR;
- }
-
- if (data->read_func) {
- ret = data->read_func(emul, reg, data->read_func_data);
- if (ret < 0) {
- return -EIO;
- } else if (ret == 0) {
- /* Immediately return value set by custom function */
- *buf = data->reg[reg];
-
- return 0;
- }
- }
-
- if (data->read_fail_reg == reg ||
- data->read_fail_reg == BMA_EMUL_FAIL_ALL_REG) {
- return -EIO;
- }
+ reg = bma_emul_access_reg(emul, reg, bytes, true /* = read */);
switch (reg) {
case BMA2x2_X_AXIS_LSB_ADDR:
@@ -1024,126 +920,30 @@ static int bma_emul_handle_read(struct i2c_emul *emul, int reg, char *buf)
break;
}
- *buf = data->reg[reg];
+ *val = data->reg[reg];
return 0;
}
/**
- * @biref Emulate an I2C transfer to a BMA255 accelerometer
- *
- * This handles simple reads and writes
+ * @brief Handle I2C write message. Saves data that will be stored in register.
*
- * @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
+ * @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
*
- * @retval 0 If successful
- * @retval -EIO General input / output error
+ * @return 0 on success
+ * @return -EIO on error
*/
-static int bma_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs,
- int num_msgs, int addr)
+static int bma_emul_write_byte(struct i2c_emul *emul, int reg, uint8_t val,
+ int bytes)
{
- const struct bma_emul_cfg *cfg;
struct bma_emul_data *data;
- int ret, i, reg;
- bool read;
-
- data = CONTAINER_OF(emul, struct bma_emul_data, emul);
- cfg = data->cfg;
- if (cfg->addr != addr) {
- LOG_ERR("Address mismatch, expected %02x, got %02x", cfg->addr,
- addr);
- return -EIO;
- }
+ data = BMA_DATA_FROM_I2C_EMUL(emul);
- i2c_dump_msgs("emul", msgs, num_msgs, addr);
-
- for (; num_msgs > 0; num_msgs--, msgs++) {
- read = msgs->flags & I2C_MSG_READ;
-
- switch (data->msg_state) {
- case BMA_EMUL_NONE_MSG:
- data->msg_byte = 0;
- break;
- case BMA_EMUL_IN_WRITE:
- if (read) {
- /* Finish write command */
- if (data->msg_byte == 2) {
- k_mutex_lock(&data->data_mtx,
- K_FOREVER);
- ret = bma_emul_handle_write(emul,
- data->cur_reg,
- data->write_byte);
- k_mutex_unlock(&data->data_mtx);
- if (ret) {
- return -EIO;
- }
- }
- data->msg_byte = 0;
- }
- break;
- case BMA_EMUL_IN_READ:
- if (!read) {
- data->msg_byte = 0;
- }
- break;
- }
- data->msg_state = read ? BMA_EMUL_IN_READ : BMA_EMUL_IN_WRITE;
-
- if (msgs->flags & I2C_MSG_STOP) {
- data->msg_state = BMA_EMUL_NONE_MSG;
- }
-
- if (!read) {
- /* Dispatch wrtie command */
- for (i = 0; i < msgs->len; i++) {
- switch (data->msg_byte) {
- case 0:
- data->cur_reg = msgs->buf[i];
- break;
- case 1:
- data->write_byte = msgs->buf[i];
- break;
- default:
- data->msg_state = BMA_EMUL_NONE_MSG;
- LOG_ERR("Too long write command");
- return -EIO;
- }
- data->msg_byte++;
- }
-
- /* Execute write command */
- if (msgs->flags & I2C_MSG_STOP && data->msg_byte == 2) {
- k_mutex_lock(&data->data_mtx, K_FOREVER);
- ret = bma_emul_handle_write(emul, data->cur_reg,
- data->write_byte);
- k_mutex_unlock(&data->data_mtx);
- if (ret) {
- return -EIO;
- }
- }
- } else {
- /* Dispatch read command */
- for (i = 0; i < msgs->len; i++) {
- reg = data->cur_reg + data->msg_byte;
- if (reg > BMA2x2_FIFO_DATA_OUTPUT_ADDR) {
- reg = BMA2x2_FIFO_DATA_OUTPUT_ADDR;
- } else {
- data->msg_byte++;
- }
- k_mutex_lock(&data->data_mtx, K_FOREVER);
- ret = bma_emul_handle_read(emul, reg,
- &(msgs->buf[i]));
- k_mutex_unlock(&data->data_mtx);
- if (ret) {
- return -EIO;
- }
- }
- }
- }
+ data->write_byte = val;
return 0;
}
@@ -1151,7 +951,7 @@ static int bma_emul_transfer(struct i2c_emul *emul, struct i2c_msg *msgs,
/* Device instantiation */
static struct i2c_emul_api bma_emul_api = {
- .transfer = bma_emul_transfer,
+ .transfer = i2c_common_emul_transfer,
};
/**
@@ -1168,15 +968,15 @@ static struct i2c_emul_api bma_emul_api = {
static int bma_emul_init(const struct emul *emul,
const struct device *parent)
{
- const struct bma_emul_cfg *cfg = emul->cfg;
- struct bma_emul_data *data = cfg->data;
+ 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;
- k_mutex_init(&data->data_mtx);
+ i2c_common_emul_init(data);
ret = i2c_emul_register(parent, emul->dev_label, &data->emul);
@@ -1205,17 +1005,20 @@ static int bma_emul_init(const struct emul *emul,
.lsb_x_read = 0, \
.lsb_y_read = 0, \
.lsb_z_read = 0, \
- .msg_state = BMA_EMUL_NONE_MSG, \
- .cur_reg = 0, \
- .write_func = NULL, \
- .read_func = NULL, \
- .write_fail_reg = BMA_EMUL_NO_FAIL_REG, \
- .read_fail_reg = BMA_EMUL_NO_FAIL_REG, \
+ .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 bma_emul_cfg bma_emul_cfg_##n = { \
+ static const struct i2c_common_emul_cfg bma_emul_cfg_##n = { \
.i2c_label = DT_INST_BUS_LABEL(n), \
- .data = &bma_emul_data_##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)
@@ -1223,7 +1026,7 @@ static int bma_emul_init(const struct emul *emul,
DT_INST_FOREACH_STATUS_OKAY(BMA255_EMUL)
#define BMA255_EMUL_CASE(n) \
- case DT_INST_DEP_ORD(n): return &bma_emul_data_##n.emul;
+ 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)