mvebu: puzzle-mcu: add mcu write retry function

Avoid MCU getting "command reply receive timed out" message when LED
configuration setting trigger function is enabled in heartbeat mode.

Signed-off-by: Ian Chang <ianchang@ieiworld.com>
This commit is contained in:
Ian Chang 2023-04-11 16:07:24 +08:00 committed by Daniel Golle
parent 50f7c5af4a
commit 877ec78e23
2 changed files with 126 additions and 0 deletions

View File

@ -0,0 +1,63 @@
--- a/drivers/mfd/iei-wt61p803-puzzle.c
+++ b/drivers/mfd/iei-wt61p803-puzzle.c
@@ -241,6 +241,7 @@ int iei_wt61p803_puzzle_write_command(st
{
struct device *dev = &mcu->serdev->dev;
int ret;
+ int retries;
if (size <= 1 || size > IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH)
return -EINVAL;
@@ -252,24 +253,36 @@ int iei_wt61p803_puzzle_write_command(st
print_hex_dump_debug("puzzle-mcu tx: ", DUMP_PREFIX_NONE,
16, 1, cmd, size, false);
+ retries = 3;
/* Initialize reply struct */
- reinit_completion(&mcu->reply->received);
- mcu->reply->size = 0;
- usleep_range(2000, 10000);
- serdev_device_write_flush(mcu->serdev);
- ret = serdev_device_write_buf(mcu->serdev, cmd, size);
- if (ret < 0)
- goto exit;
-
- serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT);
- ret = wait_for_completion_timeout(&mcu->reply->received,
- IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT);
- if (ret == 0) {
- dev_err(dev, "Command reply receive timeout\n");
- ret = -ETIMEDOUT;
- goto exit;
+ while (retries) {
+ reinit_completion(&mcu->reply->received);
+ mcu->reply->size = 0;
+ usleep_range(2000, 10000);
+ serdev_device_write_flush(mcu->serdev);
+ ret = serdev_device_write_buf(mcu->serdev, cmd, size);
+ if (ret < 0)
+ goto exit;
+
+ serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT);
+ ret = wait_for_completion_timeout(&mcu->reply->received,
+ IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT);
+ retries--;
+ if (ret == 0) {
+ if (retries == 0) {
+ dev_err(dev, "Command reply receive timeout\n");
+ ret = -ETIMEDOUT;
+ goto exit;
+ }
+ }
+ else {
+ if (mcu->reply->data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START &&
+ mcu->reply->data[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK &&
+ mcu->reply->data[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK) {
+ break;
+ }
+ }
}
-
*reply_size = mcu->reply->size;
/* Copy the received data, as it will not be available after a new frame is received */
memcpy(reply_data, mcu->reply->data, mcu->reply->size);

View File

@ -0,0 +1,63 @@
--- a/drivers/mfd/iei-wt61p803-puzzle.c
+++ b/drivers/mfd/iei-wt61p803-puzzle.c
@@ -241,6 +241,7 @@ int iei_wt61p803_puzzle_write_command(st
{
struct device *dev = &mcu->serdev->dev;
int ret;
+ int retries;
if (size <= 1 || size > IEI_WT61P803_PUZZLE_MAX_COMMAND_LENGTH)
return -EINVAL;
@@ -252,24 +253,36 @@ int iei_wt61p803_puzzle_write_command(st
print_hex_dump_debug("puzzle-mcu tx: ", DUMP_PREFIX_NONE,
16, 1, cmd, size, false);
+ retries = 3;
/* Initialize reply struct */
- reinit_completion(&mcu->reply->received);
- mcu->reply->size = 0;
- usleep_range(2000, 10000);
- serdev_device_write_flush(mcu->serdev);
- ret = serdev_device_write_buf(mcu->serdev, cmd, size);
- if (ret < 0)
- goto exit;
-
- serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT);
- ret = wait_for_completion_timeout(&mcu->reply->received,
- IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT);
- if (ret == 0) {
- dev_err(dev, "Command reply receive timeout\n");
- ret = -ETIMEDOUT;
- goto exit;
+ while (retries) {
+ reinit_completion(&mcu->reply->received);
+ mcu->reply->size = 0;
+ usleep_range(2000, 10000);
+ serdev_device_write_flush(mcu->serdev);
+ ret = serdev_device_write_buf(mcu->serdev, cmd, size);
+ if (ret < 0)
+ goto exit;
+
+ serdev_device_wait_until_sent(mcu->serdev, IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT);
+ ret = wait_for_completion_timeout(&mcu->reply->received,
+ IEI_WT61P803_PUZZLE_GENERAL_TIMEOUT);
+ retries--;
+ if (ret == 0) {
+ if (retries == 0) {
+ dev_err(dev, "Command reply receive timeout\n");
+ ret = -ETIMEDOUT;
+ goto exit;
+ }
+ }
+ else {
+ if (mcu->reply->data[0] == IEI_WT61P803_PUZZLE_CMD_HEADER_START &&
+ mcu->reply->data[1] == IEI_WT61P803_PUZZLE_CMD_RESPONSE_OK &&
+ mcu->reply->data[2] == IEI_WT61P803_PUZZLE_CHECKSUM_RESPONSE_OK) {
+ break;
+ }
+ }
}
-
*reply_size = mcu->reply->size;
/* Copy the received data, as it will not be available after a new frame is received */
memcpy(reply_data, mcu->reply->data, mcu->reply->size);