Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp4317232ybc; Fri, 22 Nov 2019 00:30:56 -0800 (PST) X-Google-Smtp-Source: APXvYqzfV506XZ3Pxtui6Q2I8/vL8Y02nQwsR6fnLKday7NRgWKDClWaySRB+SR/Ur5gABcHSqnV X-Received: by 2002:a1c:a9cb:: with SMTP id s194mr15786012wme.92.1574411456490; Fri, 22 Nov 2019 00:30:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1574411456; cv=none; d=google.com; s=arc-20160816; b=o3RbkCDHY6VSVEpfm9MESXmWWjtQHAKzSglfdcF50VHduyF0E1IGQK+npnIbrXmqpe tJ82kmr2pxTTz6XaLj8vUJBHcAwtVDyGYy2XlzPBresjh1DWg4UH6OjTti3kPElxj2S2 OJ2drxGniZ3DD34PcifsIUuh8hyCgrePtkmGHMk2pZKOc0SSiHEqSvB154Xc/t4EvNEi E/bLQXx79WWLjhYPFSbbKkZyQ3f6Ap825LekXr8ruQiShbaPieF5brl3nz+j+o5mFsVI BGom1dNPqBNvov8iVsEjm4gB2TcMErJzGPRy3OfwmXcX6S3t18Kl+eFhb1kXnz91J7Hq PZww== 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=GAdAPhKuTEAu9EdUh/adF3F8xXLZdLMB0ORzMjYKnnE=; b=uhrNrEQnXKkAH/jHXGSMd1mr9g9hxero3uGHGEc5BRj5a9h3wyZ7i5IVLMMh/CpLuG b6jxGGS/l4odbwFCx3NCoJM2c3+zNWbunREUupR4Tt2nDGrZkGY0RwoH1AgNh5DYrqfi nogCjt00pvEQv/H2EC72P9MyOvzlOMrz1cfprsPWf2Wx7tcGAzi0PZ/fXdrvs8HnO6+q IYzuj6R3tIivqjhLzpUQtmmy2wiw3benekDg42Tftu1HcN+ZpJnsrwsQggsrRJs9l/Pp qymaTtYMc6FPJy5rvsBHnJoYSxgPZS4cJbU14M7cHQEwkvqJvSg0lZl8lwocjbTV/1O3 ycTw== 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 p38si959892edc.163.2019.11.22.00.30.31; Fri, 22 Nov 2019 00:30:56 -0800 (PST) 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 S1727133AbfKVI1T (ORCPT + 99 others); Fri, 22 Nov 2019 03:27:19 -0500 Received: from esa2.mentor.iphmx.com ([68.232.141.98]:52499 "EHLO esa2.mentor.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727443AbfKVIZ1 (ORCPT ); Fri, 22 Nov 2019 03:25:27 -0500 IronPort-SDR: bh+MaslaAVfRQi0k67EIbqcqu1OxmVgAlhwYusR7Jkwdz4KBqZEpS03P5dVDehpkPa6xodNTEm TJ3WJzsEggfmXmsYA6UlVzN8sL2mtnM4VjKnRHYHA9Sb+6aCGJIH2jZbUpTy0cQYp0CU+Ypk4l 9yCCdeeDp0YqYLkeu5SvgfGSz3+lkZo+XybHOUctB8ciB/6I1KAiRsWLz/D9ki471ZwXy+MFNL Jgs3O1CMUHzrFRIEMpriqTuuhAb3+XUd6zP/hpABhQRyTEVDG+RFKKZsjt/zlLvdv/6HBQk7lU Eug= X-IronPort-AV: E=Sophos;i="5.69,229,1571731200"; d="scan'208";a="43358928" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 22 Nov 2019 00:25:26 -0800 IronPort-SDR: t7eGIw7uBRTj5X2ePYPkNnuYxEWjbImNenuNhWUosVILv1BKZ9qQzID7JTKc6GfMzg9Ic7QTj+ 9Nuxu/D6+HtMIePcI2a/zE/aHW1yrDuiSh/Nj8GF1MNm/rY5qW4p1fOdRE1twINtdnYy/y+yGN lLN6wCeNp/ktps6yT9hQ0Vtnz1lK/BMOwohug8w7imPDXP9b1o8vR7FHLu9fU0/9+NTfGmTPc7 AVpdYXUE/PxEPtOxwKmcUT320cxCwIgmK63GnT9uYYP+3F0ZVJ3a+clFbXHpZNgljtL4QwaBsd vSU= From: Jiada Wang To: , , , , CC: , , , , Subject: [PATCH v6 22/48] Input: atmel_mxt_ts - improve bootloader state machine handling Date: Fri, 22 Nov 2019 17:23:36 +0900 Message-ID: <20191122082402.18173-23-jiada_wang@mentor.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191122082402.18173-1-jiada_wang@mentor.com> References: <20191122082402.18173-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 --- Notes: - Squash fix from George G. Davis: + input: atmel_mxt_ts - Fix 'mxt_send_bootloader_cmd' was not declared warning The following sparse warning was introduced by ndyer/linux/for-upstream commit 463e15ee95ee ("Input: atmel_mxt_ts - improve bootloader state machine handling"): drivers/input/touchscreen/atmel_mxt_ts.c:888:5: warning: symbol 'mxt_send_bootloader_cmd' was not declared. Should it be static? Fix the above sparse warning by restoring the 'mxt_send_bootloader_cmd' static declaration which was errantly removed by ndyer/linux/for-upstream commit 463e15ee95ee ("Input: atmel_mxt_ts - improve bootloader state machine handling"). Signed-off-by: Jiada Wang --- drivers/input/touchscreen/atmel_mxt_ts.c | 183 ++++++++++++----------- 1 file changed, 98 insertions(+), 85 deletions(-) diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index d38ae9525e35..1c5230f7a9af 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -305,6 +305,8 @@ struct mxt_flash { size_t frame_size; unsigned int count; unsigned int retry; + u8 previous; + bool complete; }; /* Each client has this additional data */ @@ -583,64 +585,121 @@ 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) { + /* + * In application update mode, the interrupt + * line signals state transitions. We must wait for the + * CHG assertion before reading the status byte. + * Once the status byte has been read, the line is deasserted. + */ + ret = mxt_wait_for_completion(data, &data->bl_completion, + MXT_FW_CHG_TIMEOUT); + if (ret) { /* - * In application update mode, the interrupt - * line signals state transitions. We must wait for the - * CHG assertion before reading the status byte. - * Once the status byte has been read, the line is deasserted. + * TODO: handle -ERESTARTSYS better by terminating + * fw update process before returning to userspace + * by writing length 0x000 to device (iff we are in + * WAITING_FRAME_DATA state). */ - ret = mxt_wait_for_completion(data, &data->bl_completion, - MXT_FW_CHG_TIMEOUT); - if (ret) { - /* - * TODO: handle -ERESTARTSYS better by terminating - * fw update process before returning to userspace - * by writing length 0x000 to device (iff we are in - * WAITING_FRAME_DATA state). - */ - dev_err(dev, "Update wait error %d\n", ret); - return ret; - } + dev_warn(dev, "Update wait error %d\n", ret); } - ret = mxt_bootloader_read(data, &val, 1); + 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; + + 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; + + break; + + case MXT_FRAME_CRC_CHECK: + if (f->previous != MXT_WAITING_FRAME_DATA) + goto unexpected; 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++; + + 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++; + 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 +3360,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 +3375,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 +3384,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