Skip to content

Commit

Permalink
drivers: i3c: add additional option to setdasa
Browse files Browse the repository at this point in the history
struct i3c_ccc_address is intended to match the output where the address
is left shifted by 1 for SETDASA and SETNEWDA. Require the operations calling
it to shift the data.

add an additional parameter for the setdasa function which will allow for the
da to be configured rather than being hard coded.

Signed-off-by: Ryan McClelland <[email protected]>
  • Loading branch information
XenuIsWatching committed Sep 14, 2024
1 parent 5f0e2ba commit 890454f
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 48 deletions.
38 changes: 3 additions & 35 deletions drivers/i3c/i3c_ccc.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,10 @@ int i3c_ccc_do_rstdaa_all(const struct device *controller)
return i3c_do_ccc(controller, &ccc_payload);
}

int i3c_ccc_do_setdasa(const struct i3c_device_desc *target)
int i3c_ccc_do_setdasa(const struct i3c_device_desc *target, struct i3c_ccc_address da)
{
struct i3c_driver_data *bus_data = (struct i3c_driver_data *)target->bus->data;
struct i3c_ccc_payload ccc_payload;
struct i3c_ccc_target_payload ccc_tgt_payload;
uint8_t dyn_addr;

__ASSERT_NO_MSG(target != NULL);
__ASSERT_NO_MSG(target->bus != NULL);
Expand All @@ -128,24 +126,9 @@ int i3c_ccc_do_setdasa(const struct i3c_device_desc *target)
return -EINVAL;
}

/*
* Note that the 7-bit address needs to start at bit 1
* (aka left-justified). So shift left by 1;
*/
dyn_addr = (target->init_dynamic_addr ?
target->init_dynamic_addr : target->static_addr) << 1;

/* check that initial dynamic address is free before setting it */
if ((target->init_dynamic_addr != 0) &&
(target->init_dynamic_addr != target->static_addr)) {
if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, dyn_addr >> 1)) {
return -EINVAL;
}
}

ccc_tgt_payload.addr = target->static_addr;
ccc_tgt_payload.rnw = 0;
ccc_tgt_payload.data = &dyn_addr;
ccc_tgt_payload.data = (uint8_t *)&da.addr;
ccc_tgt_payload.data_len = 1;

memset(&ccc_payload, 0, sizeof(ccc_payload));
Expand All @@ -158,10 +141,8 @@ int i3c_ccc_do_setdasa(const struct i3c_device_desc *target)

int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, struct i3c_ccc_address new_da)
{
struct i3c_driver_data *bus_data = (struct i3c_driver_data *)target->bus->data;
struct i3c_ccc_payload ccc_payload;
struct i3c_ccc_target_payload ccc_tgt_payload;
uint8_t new_dyn_addr;

__ASSERT_NO_MSG(target != NULL);
__ASSERT_NO_MSG(target->bus != NULL);
Expand All @@ -170,22 +151,9 @@ int i3c_ccc_do_setnewda(const struct i3c_device_desc *target, struct i3c_ccc_add
return -EINVAL;
}

/*
* Note that the 7-bit address needs to start at bit 1
* (aka left-justified). So shift left by 1;
*/
new_dyn_addr = new_da.addr << 1;

/* check that initial dynamic address is free before setting it */
if (target->dynamic_addr != new_da.addr) {
if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, new_da.addr)) {
return -EINVAL;
}
}

ccc_tgt_payload.addr = target->dynamic_addr;
ccc_tgt_payload.rnw = 0;
ccc_tgt_payload.data = &new_dyn_addr;
ccc_tgt_payload.data = (uint8_t *)&new_da.addr;
ccc_tgt_payload.data_len = 1;

memset(&ccc_payload, 0, sizeof(ccc_payload));
Expand Down
30 changes: 26 additions & 4 deletions drivers/i3c/i3c_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,8 @@ static int i3c_bus_setdasa(const struct device *dev,
/* Loop through the registered I3C devices */
for (i = 0; i < dev_list->num_i3c; i++) {
struct i3c_device_desc *desc = &dev_list->i3c[i];
struct i3c_driver_data *bus_data = (struct i3c_driver_data *)dev->data;
struct i3c_ccc_address dyn_addr;

/*
* A device without static address => need to do
Expand All @@ -778,10 +780,31 @@ static int i3c_bus_setdasa(const struct device *dev,

LOG_DBG("SETDASA for 0x%x", desc->static_addr);

ret = i3c_ccc_do_setdasa(desc);
/*
* check that initial dynamic address is free before setting it
* if configured
*/
if ((desc->init_dynamic_addr != 0) &&
(desc->init_dynamic_addr != desc->static_addr)) {
if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots,
desc->init_dynamic_addr)) {
if (i3c_detach_i3c_device(desc) != 0) {

Check notice on line 791 in drivers/i3c/i3c_common.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/i3c/i3c_common.c:791 - (desc->init_dynamic_addr != desc->static_addr)) { + (desc->init_dynamic_addr != desc->static_addr)) { if (!i3c_addr_slots_is_free(&bus_data->attached_dev.addr_slots, - desc->init_dynamic_addr)) { + desc->init_dynamic_addr)) {
LOG_ERR("Failed to detach %s", desc->dev->name);
}
continue;
}
}

/*
* Note that the 7-bit address needs to start at bit 1
* (aka left-justified). So shift left by 1;
*/
dyn_addr.addr = (desc->init_dynamic_addr ?
desc->init_dynamic_addr : desc->static_addr) << 1;

Check notice on line 804 in drivers/i3c/i3c_common.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/i3c/i3c_common.c:804 - dyn_addr.addr = (desc->init_dynamic_addr ? - desc->init_dynamic_addr : desc->static_addr) << 1; + dyn_addr.addr = + (desc->init_dynamic_addr ? desc->init_dynamic_addr : desc->static_addr) + << 1;
ret = i3c_ccc_do_setdasa(desc, dyn_addr);
if (ret == 0) {
desc->dynamic_addr = (desc->init_dynamic_addr ? desc->init_dynamic_addr
: desc->static_addr);
desc->dynamic_addr = dyn_addr.addr >> 1;
if (desc->dynamic_addr != desc->static_addr) {
if (i3c_reattach_i3c_device(desc, desc->static_addr) != 0) {
LOG_ERR("Failed to reattach %s (%d)", desc->dev->name, ret);
Expand All @@ -794,7 +817,6 @@ static int i3c_bus_setdasa(const struct device *dev,
}
LOG_ERR("SETDASA error on address 0x%x (%d)",
desc->static_addr, ret);
continue;
}
}

Expand Down
21 changes: 15 additions & 6 deletions drivers/i3c/i3c_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -691,11 +691,13 @@ static int cmd_i3c_ccc_setaasa(const struct shell *sh, size_t argc, char **argv)
return ret;
}

/* i3c ccc setdasa <device> <target> */
/* i3c ccc setdasa <device> <target> <dynamic address> */
static int cmd_i3c_ccc_setdasa(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev, *tdev;
struct i3c_device_desc *desc;
struct i3c_driver_data *data;
struct i3c_ccc_address da;
int ret;

dev = device_get_binding(argv[ARGV_DEV]);
Expand All @@ -714,7 +716,14 @@ static int cmd_i3c_ccc_setdasa(const struct shell *sh, size_t argc, char **argv)
return -ENODEV;
}

ret = i3c_ccc_do_setdasa(desc);
data = (struct i3c_driver_data *)dev->data;
da.addr = strtol(argv[3], NULL, 16) << 1;
/* check if the addressed is free */
if (!i3c_addr_slots_is_free(&data->attached_dev.addr_slots, da.addr)) {
shell_error(sh, "I3C: Address 0x%02x is already in use.", da.addr);
return -EINVAL;
}
ret = i3c_ccc_do_setdasa(desc, da);
if (ret < 0) {
shell_error(sh, "I3C: unable to send CCC SETDASA.");
return ret;
Expand All @@ -733,7 +742,7 @@ static int cmd_i3c_ccc_setdasa(const struct shell *sh, size_t argc, char **argv)
return ret;
}

/* i3c ccc setnewda <device> <target> <dynamic address>*/
/* i3c ccc setnewda <device> <target> <dynamic address> */
static int cmd_i3c_ccc_setnewda(const struct shell *sh, size_t argc, char **argv)
{
const struct device *dev, *tdev;
Expand All @@ -760,7 +769,7 @@ static int cmd_i3c_ccc_setnewda(const struct shell *sh, size_t argc, char **argv
}

data = (struct i3c_driver_data *)dev->data;
new_da.addr = strtol(argv[3], NULL, 16);
new_da.addr = strtol(argv[3], NULL, 16) << 1;
/* check if the addressed is free */
if (!i3c_addr_slots_is_free(&data->attached_dev.addr_slots, new_da.addr)) {
shell_error(sh, "I3C: Address 0x%02x is already in use.", new_da.addr);
Expand Down Expand Up @@ -2368,8 +2377,8 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
cmd_i3c_ccc_setaasa, 2, 0),
SHELL_CMD_ARG(setdasa, &dsub_i3c_device_attached_name,
"Send CCC SETDASA\n"
"Usage: ccc setdasa <device> <target>",
cmd_i3c_ccc_setdasa, 3, 0),
"Usage: ccc setdasa <device> <target> <dynamic address>",
cmd_i3c_ccc_setdasa, 4, 0),
SHELL_CMD_ARG(setnewda, &dsub_i3c_device_attached_name,
"Send CCC SETNEWDA\n"
"Usage: ccc setnewda <device> <target> <dynamic address>",
Expand Down
8 changes: 5 additions & 3 deletions include/zephyr/drivers/i3c/ccc.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ struct i3c_ccc_address {
* - For GETACCCR, the correct address of Secondary
* Controller.
*
* @note For SETDATA, SETNEWDA and SETGRAP,
* @note For SETDATA, SETNEWDA and SETGRPA,
* the address is left-shift by 1, and bit[0] is always 0.
*
* @note For SET GETACCCR, the address is left-shift by 1,
Expand Down Expand Up @@ -1354,10 +1354,12 @@ int i3c_ccc_do_rstdaa_all(const struct device *controller);
*
* @param[in] target Pointer to the target device descriptor where
* the device is configured with a static address.
* @param[in] da Struct of the Dynamic address
*
* @return @see i3c_do_ccc
*/
int i3c_ccc_do_setdasa(const struct i3c_device_desc *target);
int i3c_ccc_do_setdasa(const struct i3c_device_desc *target,
struct i3c_ccc_address da);

/**
* @brief Set New Dynamic Address for a target
Expand All @@ -1368,7 +1370,7 @@ int i3c_ccc_do_setdasa(const struct i3c_device_desc *target);
*
* @param[in] target Pointer to the target device descriptor where
* the device is configured with a static address.
* @param[in] new_da Pointer to the new_da struct.
* @param[in] new_da Struct of the Dynamic address
*
* @return @see i3c_do_ccc
*/
Expand Down

0 comments on commit 890454f

Please sign in to comment.