Received: by 2002:a25:d783:0:0:0:0:0 with SMTP id o125csp747818ybg; Thu, 19 Mar 2020 08:05:17 -0700 (PDT) X-Google-Smtp-Source: ADFU+vsZEnodwFwNGj8HzhEixHUq4YseYeHXHwDALKXxjKxyBONAakdAQia8x/htf50jjPfc84ky X-Received: by 2002:aca:4f57:: with SMTP id d84mr2574080oib.161.1584630317004; Thu, 19 Mar 2020 08:05:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1584630316; cv=none; d=google.com; s=arc-20160816; b=kFea0vYq6R0uO8HalPc1pbiaFN++oESB5PKjBps81uTyiSOR7A9A68g+FqNhr582SO pGEE6V6S2EQ68r6lk7MYYfGQevYJk07PxhRYJCUg1ukhfBjUOK0KaG/r6t3rWvQOXgyc nWRsI3ddJWZNOlTKYHpAm23E89Ebf2816KKxnRIRIHrULi2tM6uQEnkopXWriR41PBdh h5KFD70ngmOlpnYh/VAIILHIC6tmktIHY8htz1GGHCVgIjYeeRvu9Kj0z1l52TwnZP2K LzjtkEoXqg8BrWLVaoanoL2hafnkTEKN/4SYyQuo0bXQHu+f2r8QWQGWam1H2JSOR7DU Xp/g== 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=oyyStAIY6r5ITTJNpcDKhMsfgyt/wkiV1iyf0sWH2Ik=; b=qaLpOLovg00FKYuV2LoI2LcEhOeGLZiS7dMCzL2Ql26bvwnellBQx7Kij2NKi2Xuw2 BA5dN5aBcl7l+ZE2MtBETGdb/sihu7DsLq19uHhpp08HDYD/Dq0Szc5AuBMa5RZWbsWE djwm4+iEOCbQc3SB1RSdJKD79J50VnJHXcBwwVyukcJ44Ecn7exALfi9SNIiJqxq95VH mJLlVduFOU62+81dYCCu1U29aMsP0yTkgsnQDTDco3bojBEa2R86rnR2CLXq/ohZa2WO rRAbSKDw8m2wAHdFKiXTbWPI3zmFFbvPLtdAJH51hcOsYnIcLB7vWYiHpkQ2hQZfDbSw 7tqQ== 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 s11si1471470otp.95.2020.03.19.08.04.53; Thu, 19 Mar 2020 08:05:16 -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 S1728342AbgCSPC6 (ORCPT + 99 others); Thu, 19 Mar 2020 11:02:58 -0400 Received: from esa3.mentor.iphmx.com ([68.232.137.180]:32318 "EHLO esa3.mentor.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727755AbgCSPCJ (ORCPT ); Thu, 19 Mar 2020 11:02:09 -0400 IronPort-SDR: cj+kJ7WwwbDNnRmAbytJyGJueg4MWyKgXToi8mHW1SBtdMu/r8xVePixQWNCHPFqL4xKR7qLKU llCrKqmIemAdIDXRhMvIy5E9VbZ1Vy3hp+o2MrzhYS3cVJRs2l0p7obtuVUZK0IV3D3zTwxJkA j1CFSs6jO2rGZKFy+iinVVN0DCtLHncn4zqjNiOsSezl1lQDzsNAuTpsv3BlPPrC4DZbK2JQ/M F3tJwbCCBCi08G9mKUFpEi6UJiJuPig9MPboFE3QrUGH+lxF5CoAx9bzPyJ0ET5YDJTo0olcnu 22M= X-IronPort-AV: E=Sophos;i="5.70,572,1574150400"; d="scan'208";a="46890933" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 19 Mar 2020 07:02:00 -0800 IronPort-SDR: 00fadSNKOcGanxNOgACkAJ5jAfils4q1yKVSXJLCPt9jTO5eUXU17ifmDkUMWdN1++X0ars9ja jBPBWnOmPFy3ubdxdPxPYQXFLa7fd/9rWVuXMvE6bQWxubVM72IIBDHj7EFwVpyQUtiLeyXV93 yyNIV8cqp6XlQrHpHCJ30MIHW1g77AFS5wlzJ4hSxu/vOJoI3Q1AuqCiezXcgGIyQ1cbvV63au HTJYw6lZ9cYUndRG8vuSJg/T/zc+5e+WuAFiKLy3vaglL6RlkjkOmZqjWrD4+gFDRBv4loIv2N 1dQ= From: Jiada Wang To: , , , , , CC: , , , , Subject: [PATCH v8 25/52] Input: atmel_mxt_ts - improve bootloader state machine handling Date: Thu, 19 Mar 2020 07:59:49 -0700 Message-ID: <20200319150016.61398-26-jiada_wang@mentor.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200319150016.61398-1-jiada_wang@mentor.com> References: <20200319150016.61398-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 d3d6e4e60f67..c287ab3ebeac 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