--- 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);