Linux Input Archive on lore.kernel.org
 help / color / Atom feed
From: Jiada Wang <jiada_wang@mentor.com>
To: <jikos@kernel.org>, <benjamin.tissoires@redhat.com>,
	<rydberg@bitmath.org>, <dmitry.torokhov@gmail.com>,
	<nick@shmanahar.org>
Cc: <linux-input@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<erosca@de.adit-jv.com>, <Andrew_Gabbasov@mentor.com>,
	<jiada_wang@mentor.com>
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> (raw)
In-Reply-To: <20191122082402.18173-1-jiada_wang@mentor.com>

From: Nick Dyer <nick.dyer@itdev.co.uk>

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 <nick.dyer@itdev.co.uk>
(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 <george_davis@mentor.com>
---
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 <jiada_wang@mentor.com>
---
 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


  parent reply index

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-22  8:23 [PATCH v6 00/48] atmel_mxt_ts misc Jiada Wang
2019-11-22  8:23 ` [PATCH v6 01/48] Input: introduce input_mt_report_slot_inactive Jiada Wang
2019-11-22  8:23 ` [PATCH v6 02/48] Input: atmel_mxt_ts - rework sysfs init/remove Jiada Wang
2019-11-22  8:23 ` [PATCH v6 03/48] Input: atmel_mxt_ts - only read messages in mxt_acquire_irq() when necessary Jiada Wang
2019-11-22  8:23 ` [PATCH v6 04/48] Input: atmel_mxt_ts - split large i2c transfers into blocks Jiada Wang
2019-11-22  8:23 ` [PATCH v6 05/48] Input: atmel_mxt_ts - output status from T48 Noise Supression Jiada Wang
2019-11-22  8:23 ` [PATCH v6 06/48] Input: atmel_mxt_ts - output status from T42 Touch Suppression Jiada Wang
2019-11-22  8:23 ` [PATCH v6 07/48] Input: atmel_mxt_ts - implement T9 vector/orientation support Jiada Wang
2019-11-22  8:23 ` [PATCH v6 08/48] Input: atmel_mxt_ts - implement T15 Key Array support Jiada Wang
2019-11-22  8:23 ` [PATCH v6 09/48] Input: atmel_mxt_ts - handle reports from T47 Stylus object Jiada Wang
2019-11-22  8:23 ` [PATCH v6 10/48] Input: atmel_mxt_ts - implement support for T107 active stylus Jiada Wang
2019-11-22  8:23 ` [PATCH v6 11/48] Input: atmel_mxt_ts - add debug for T92 gesture and T93 touch seq msgs Jiada Wang
2019-11-22  8:23 ` [PATCH v6 12/48] Input: atmel_mxt_ts - release touch state during suspend Jiada Wang
2019-11-22  8:23 ` [PATCH v6 13/48] Input: atmel_mxt_ts - add regulator control support Jiada Wang
2019-11-22  8:23 ` [PATCH v6 14/48] Input: atmel_mxt_ts - report failures in suspend/resume Jiada Wang
2019-11-22  8:23 ` [PATCH v6 15/48] Input: atmel_mxt_ts - allow specification of firmware file name Jiada Wang
2019-11-22  8:23 ` [PATCH v6 16/48] Input: atmel_mxt_ts - handle cfg filename via pdata/sysfs Jiada Wang
2019-11-22  8:23 ` [PATCH v6 17/48] Input: atmel_mxt_ts - allow input name to be specified in platform data Jiada Wang
2019-11-22  8:23 ` [PATCH v6 18/48] Input: atmel_mxt_ts - add config checksum attribute to sysfs Jiada Wang
2019-11-22  8:23 ` [PATCH v6 19/48] Input: atmel_mxt_ts - refactor firmware flash to extract context into struct Jiada Wang
2019-11-22  8:23 ` [PATCH v6 20/48] Input: atmel_mxt_ts - refactor code to enter bootloader into separate func Jiada Wang
2019-11-22  8:23 ` [PATCH v6 21/48] Input: atmel_mxt_ts - combine bootloader version query with probe Jiada Wang
2019-11-22  8:23 ` Jiada Wang [this message]
2019-11-22  8:23 ` [PATCH v6 23/48] Input: atmel_mxt_ts - rename bl_completion to chg_completion Jiada Wang
2019-11-22  8:23 ` [PATCH v6 24/48] Input: atmel_mxt_ts - make bootloader interrupt driven Jiada Wang
2019-11-22  8:23 ` [PATCH v6 25/48] Input: atmel_mxt_ts - delay enabling IRQ when not using regulators Jiada Wang
2019-11-22  8:23 ` [PATCH v6 26/48] Input: atmel_mxt_ts - implement I2C retries Jiada Wang
2019-11-22  8:23 ` [PATCH v6 27/48] Input: atmel_mxt_ts - orientation is not present in hover Jiada Wang
2019-11-22  8:23 ` [PATCH v6 28/48] Input: atmel_mxt_ts - implement debug output for messages Jiada Wang
2019-11-22  8:23 ` [PATCH v6 29/48] Input: atmel_mxt_ts - implement improved debug message interface Jiada Wang
2019-11-22  8:23 ` [PATCH v6 30/48] Input: atmel_mxt_ts - eliminate data->raw_info_block Jiada Wang
2019-11-22  8:23 ` [PATCH v6 31/48] Input: atmel_mxt_ts - Change call-points of mxt_free_* functions Jiada Wang
2019-11-22  8:23 ` [PATCH v6 32/48] Input: atmel_mxt_ts - rely on calculated_crc rather than file config_crc Jiada Wang
2019-11-22  8:23 ` [PATCH v6 33/48] input: atmel_mxt_ts: export GPIO reset line via sysfs Jiada Wang
2019-11-22  8:23 ` [PATCH v6 34/48] input: atmel_mxt_ts: Add Missing Delay for reset handling of Atmel touch panel controller in detachable displays Jiada Wang
2019-11-22  8:23 ` [PATCH v6 35/48] Input: atmel_mxt_ts: Add support for run self-test routine Jiada Wang
2019-11-22  8:23 ` [PATCH v6 36/48] Input: atmel_mxt_ts: Limit the max bytes transferred in an i2c transaction Jiada Wang
2019-11-22  8:23 ` [PATCH v6 37/48] Input: atmel_mxt_ts: return error from mxt_process_messages_until_invalid() Jiada Wang
2019-11-22  8:23 ` [PATCH v6 38/48] Input: Atmel: improve error handling in mxt_start() Jiada Wang
2019-11-22  8:23 ` [PATCH v6 39/48] Input: Atmel: improve error handling in mxt_initialize() Jiada Wang
2019-11-22  8:23 ` [PATCH v6 40/48] Input: Atmel: improve error handling in mxt_update_cfg() Jiada Wang
2019-11-22  8:23 ` [PATCH v6 41/48] Input: Atmel: Improve error handling in mxt_initialize_input_device() Jiada Wang
2019-11-22  8:23 ` [PATCH v6 42/48] Input: Atmel: handle ReportID "0x00" while processing T5 messages Jiada Wang
2019-11-22  8:23 ` [PATCH v6 43/48] Input: Atmel: use T44 object to process " Jiada Wang
2019-11-22  8:23 ` [PATCH v6 44/48] Input: atmel_mxt_ts: use gpiod_set_value_cansleep for reset pin Jiada Wang
2019-11-22  8:23 ` [PATCH v6 45/48] input: touchscreen: atmel_mxt_ts: Added sysfs entry for touchscreen status Jiada Wang
2019-11-22  8:24 ` [PATCH v6 46/48] input: atmel_mxt_ts: added sysfs interface to update atmel T38 data Jiada Wang
2019-11-22  8:24 ` [PATCH v6 47/48] Input: atmel_mxt_ts: Implement synchronization during various operation Jiada Wang
2019-11-22  8:24 ` [PATCH v6 48/48] Input: atmel_mxt_ts - Fix compilation warning Jiada Wang
2020-01-10 12:04 ` [PATCH v6 00/48] atmel_mxt_ts misc Jiada Wang

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191122082402.18173-23-jiada_wang@mentor.com \
    --to=jiada_wang@mentor.com \
    --cc=Andrew_Gabbasov@mentor.com \
    --cc=benjamin.tissoires@redhat.com \
    --cc=dmitry.torokhov@gmail.com \
    --cc=erosca@de.adit-jv.com \
    --cc=jikos@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nick@shmanahar.org \
    --cc=rydberg@bitmath.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux Input Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-input/0 linux-input/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-input linux-input/ https://lore.kernel.org/linux-input \
		linux-input@vger.kernel.org
	public-inbox-index linux-input

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-input


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git