Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp3365756ybb; Tue, 31 Mar 2020 03:53:47 -0700 (PDT) X-Google-Smtp-Source: ADFU+vvtu07dp67px2pApmyUYxR5Znf6Wpe1z+aiWugIKL7O0SEd2m5jcNr/rchOhSiGGRDaYKSO X-Received: by 2002:a05:6830:2318:: with SMTP id u24mr2615839ote.106.1585652026956; Tue, 31 Mar 2020 03:53:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1585652026; cv=none; d=google.com; s=arc-20160816; b=CF/tJreKCzOgwNuE+viklez2lvm4gfsCgQAMDNr6/gPoRj1a7fOXJ8107r5RGFAv19 KVHVhsC7qY4BmRL2GRN/nxyfUentUSdy5UxsBFlz+8GmNBjXifB3R9eHEhLc8JEjB0JV lOvJon/jJyvRusYd2Kkm3BO25rqAmAFAp6Ky0E3kz9rM2y13uHq5X2M78FfwLGBcZWVA KJRCEz6R7f5ek5t6ALSAj5bAKdLxDER2cyMDGqwJMwmDQBu+/lZx4Zofwmn1xa1YRjFc syrBj1e12aSyTbt/jh501JMuX38MUL3tnZ27AzY76liXAGKtKkZcN8ZF/mBsYMrThUVr 6KrA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:ironport-sdr:ironport-sdr; bh=6bXGjRO9+zT3/xKpRxo0l4msWlT52XWFlb1zd4AdKbg=; b=rKa4TekGI/WDiIW7GRx1AlO+vLcv8Si8iX5itlJ5zdVSCuiFC613jxplpLhmCkqbae bxiU76mS2iMNJj7JfNpuPyxEbnqOmrjxjesDv2eB030CoLFL3VGQeiRQopAs250NFLsP vcRYUlpX0aTP3Da40x0IkOHdjmbscFId2OQ2I9n5lX7UQFHzRefXA6uKwlPDT76Jp4// R0ZIfpTQVQn7DOE8gyu4eIvmUgzk4ARjBy85W9iskUcNmNrE2ce7SquRPmwnztxCPNxY 7JTFxFcn9kXZGr9olI4Ba6o3PysSBCoytd44I2YZN6e5ShjWWSqP3pKvohyBrBeDCcJo Uuqg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 5si6663875oin.43.2020.03.31.03.53.35; Tue, 31 Mar 2020 03:53:46 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730784AbgCaKws (ORCPT + 99 others); Tue, 31 Mar 2020 06:52:48 -0400 Received: from esa4.mentor.iphmx.com ([68.232.137.252]:43597 "EHLO esa4.mentor.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730760AbgCaKwo (ORCPT ); Tue, 31 Mar 2020 06:52:44 -0400 IronPort-SDR: 3KvejIdFQHpMsDY7FZPAlN8epkASGCIY19e47nHZ1fxOIBmLZ1aRPerAK5228hrS79WfDseQGd OSDSgvaykh1ymwLllkKkafWJZjRADVdhnp1pUbZg2nQu2blwrjXm13QlB5/smqJqh0Xegx8jAd uY/rSlx40sozhquqpBG9f/fRa5dVtiF/cpfXhK0cmRxnLGi1sLo7vOW4OIF8rhPql5DKat3dPq vwcch6IuI8Wjd87imI2WaHo4NiXmE4hfKzMgNEZuz6i4eRlgJ+hMW6CEugSgQBnhyfmLt4t7L8 lE0= X-IronPort-AV: E=Sophos;i="5.72,327,1580803200"; d="scan'208";a="47330792" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa4.mentor.iphmx.com with ESMTP; 31 Mar 2020 02:52:42 -0800 IronPort-SDR: GHMqegbnzZR40zkcteNJcyP3cCiDbs9j3JRgkaTmopQ0Z+Y0gCvQgYQmufgRZRPZV9/7f+ynG0 H94gheD3I1qDjDP4ThElATg/k8zwCECpP94/cqDYx3wgcAsMXJK1KcNaDY4IETNanqcj75F2Gx jaI2d6SKwMj6eLTdm1crBhznn11AmT2VnqRJ7c224waIs7YyFYKCLq788YadkORJnO7bLbwPnR 1bV2XJCz/OnwrKCPYOCWLEWW9fwU/prxQkvHvPUpZzINTAZ7II0lWn2R+7ShbnsLM0NeTvALVM Ebk= From: Jiada Wang To: , , , , CC: , , , , Subject: [PATCH v10 28/55] Input: atmel_mxt_ts - improve bootloader state machine handling Date: Tue, 31 Mar 2020 03:50:24 -0700 Message-ID: <20200331105051.58896-29-jiada_wang@mentor.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200331105051.58896-1-jiada_wang@mentor.com> References: <20200331105051.58896-1-jiada_wang@mentor.com> MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Nick Dyer The code is much clearer if we switch on the actual state the bootloader is in, rather than the state we want it to be in, and allows the removal of a goto retry tangle. Signed-off-by: Nick Dyer (cherry picked from ndyer/linux/for-upstream commit 463e15ee95ee6e6274017ff645839dbe34d75c99) [gdavis: Squash fix from George G. Davis: - input: atmel_mxt_ts - Fix 'mxt_send_bootloader_cmd' was not declared warning] Signed-off-by: George G. Davis [jiada: only wait on some status change, cleanup code style] Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 165 +++++++++++++---------- 1 file changed, 95 insertions(+), 70 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 71d5781d3539..0f1c0e5c6169 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -305,6 +305,9 @@ struct mxt_flash { size_t frame_size; unsigned int count; unsigned int retry; + u8 previous; + bool complete; + bool wait; }; /* Each client has this additional data */ @@ -583,15 +586,27 @@ static int mxt_probe_bootloader(struct mxt_data *data, bool alt_address) return 0; } -static int mxt_check_bootloader(struct mxt_data *data, unsigned int state, - bool wait) +static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock); + +static int mxt_write_firmware_frame(struct mxt_data *data, struct mxt_flash *f) +{ + f->frame = (struct mxt_fw_frame *)(f->fw->data + f->pos); + + /* Take account of CRC bytes */ + f->frame_size = __be16_to_cpu(f->frame->size) + 2U; + + /* Write one frame to device */ + return mxt_bootloader_write(data, f->fw->data + f->pos, + f->frame_size); +} + +static int mxt_check_bootloader(struct mxt_data *data, struct mxt_flash *f) { struct device *dev = &data->client->dev; - u8 val; + u8 state; int ret; -recheck: - if (wait) { + if (f->wait) { /* * In application update mode, the interrupt * line signals state transitions. We must wait for the @@ -607,40 +622,96 @@ static int mxt_check_bootloader(struct mxt_data *data, unsigned int state, * by writing length 0x000 to device (iff we are in * WAITING_FRAME_DATA state). */ - dev_err(dev, "Update wait error %d\n", ret); + dev_warn(dev, "Update wait error %d\n", ret); return ret; } } - ret = mxt_bootloader_read(data, &val, 1); + f->wait = false; + + ret = mxt_bootloader_read(data, &state, 1); if (ret) return ret; + /* Remove don't care bits */ + if (state & ~MXT_BOOT_STATUS_MASK) + state &= ~MXT_BOOT_STATUS_MASK; + switch (state) { case MXT_WAITING_BOOTLOAD_CMD: + dev_info(dev, "Unlocking bootloader\n"); + ret = mxt_send_bootloader_cmd(data, true); + if (ret) + return ret; + f->wait = true; + + break; + case MXT_WAITING_FRAME_DATA: - case MXT_APP_CRC_FAIL: - val &= ~MXT_BOOT_STATUS_MASK; + if (f->previous != MXT_WAITING_BOOTLOAD_CMD && + f->previous != MXT_FRAME_CRC_PASS && + f->previous != MXT_FRAME_CRC_FAIL) + goto unexpected; + + ret = mxt_write_firmware_frame(data, f); + if (ret) + return ret; + + f->wait = true; + + break; + + case MXT_FRAME_CRC_CHECK: + if (f->previous != MXT_WAITING_FRAME_DATA) + goto unexpected; + f->wait = true; break; + case MXT_FRAME_CRC_PASS: - if (val == MXT_FRAME_CRC_CHECK) { - goto recheck; - } else if (val == MXT_FRAME_CRC_FAIL) { - dev_err(dev, "Bootloader CRC fail\n"); - return -EINVAL; + if (f->previous != MXT_FRAME_CRC_CHECK) + goto unexpected; + + /* Next frame */ + f->retry = 0; + f->pos += f->frame_size; + f->count++; + f->wait = true; + + if (f->pos >= f->fw->size) { + f->complete = true; + dev_info(dev, "Sent %u frames, %zu bytes\n", + f->count, f->fw->size); + } else if (f->count % 50 == 0) { + dev_dbg(dev, "Sent %u frames, %lld/%zu bytes\n", + f->count, f->pos, f->fw->size); + } + + break; + + case MXT_FRAME_CRC_FAIL: + if (f->retry > 20) { + dev_err(dev, "Retry count exceeded\n"); + return -EIO; } + + /* Back off by 20ms per retry */ + dev_dbg(dev, "Bootloader frame CRC failure\n"); + f->retry++; + f->wait = true; + msleep(f->retry * 20); break; + default: return -EINVAL; } - if (val != state) { - dev_err(dev, "Invalid bootloader state %02X != %02X\n", - val, state); - return -EINVAL; - } + f->previous = state; return 0; + +unexpected: + dev_err(dev, "Unexpected state transition\n"); + return -EINVAL; } static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock) @@ -3301,57 +3372,13 @@ static int mxt_load_fw(struct device *dev) if (ret) goto release_firmware; - ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false); - if (ret) { - /* Bootloader may still be unlocked from previous attempt */ - ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, false); - if (ret) - goto disable_irq; - } else { - dev_info(dev, "Unlocking bootloader\n"); - - /* Unlock bootloader */ - ret = mxt_send_bootloader_cmd(data, true); + while (true) { + ret = mxt_check_bootloader(data, &f); if (ret) - goto disable_irq; - } - - while (f.pos < f.fw->size) { - f.frame = (struct mxt_fw_frame *)(f.fw->data + f.pos); - - ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA, true); - if (ret) - goto disable_irq; - - /* Take account of CRC bytes */ - f.frame_size = __be16_to_cpu(f.frame->size) + 2U; - - /* Write one frame to device */ - ret = mxt_bootloader_write(data, f.fw->data + f.pos, - f.frame_size); - if (ret) - goto disable_irq; - - ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS, true); - if (ret) { - f.retry++; - - /* Back off by 20ms per retry */ - msleep(f.retry * 20); - - if (f.retry > 20) { - dev_err(dev, "Retry count exceeded\n"); - goto disable_irq; - } - } else { - f.retry = 0; - f.pos += f.frame_size; - f.count++; - } + return ret; - if (f.count % 50 == 0) - dev_dbg(dev, "Sent %u frames, %lld/%zu bytes\n", - f.count, f.pos, f.fw->size); + if (f.complete) + break; } /* Wait for flash. */ @@ -3360,7 +3387,6 @@ static int mxt_load_fw(struct device *dev) if (ret) goto disable_irq; - dev_dbg(dev, "Sent %u frames, %lld bytes\n", f.count, f.pos); /* * Wait for device to reset. Some bootloader versions do not assert @@ -3370,7 +3396,6 @@ static int mxt_load_fw(struct device *dev) mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_RESET_TIME); data->in_bootloader = false; - disable_irq: disable_irq(data->irq); release_firmware: -- 2.17.1