Commit 3de4f996 authored by Christian A. Ehrhardt's avatar Christian A. Ehrhardt Committed by Greg Kroah-Hartman
Browse files

usb: typec: ucsi: Clear UCSI_CCI_RESET_COMPLETE before reset



Check the UCSI_CCI_RESET_COMPLETE complete flag before starting
another reset. Use a UCSI_SET_NOTIFICATION_ENABLE command to clear
the flag if it is set.

Signed-off-by: default avatarChristian A. Ehrhardt <lk@c--e.de>
Cc: stable <stable@kernel.org>
Reviewed-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
Link: https://lore.kernel.org/r/20240320073927.1641788-6-lk@c--e.de


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6aaceb7d
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -1264,13 +1264,47 @@ static int ucsi_reset_connector(struct ucsi_connector *con, bool hard)

static int ucsi_reset_ppm(struct ucsi *ucsi)
{
	u64 command = UCSI_PPM_RESET;
	u64 command;
	unsigned long tmo;
	u32 cci;
	int ret;

	mutex_lock(&ucsi->ppm_lock);

	ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci));
	if (ret < 0)
		goto out;

	/*
	 * If UCSI_CCI_RESET_COMPLETE is already set we must clear
	 * the flag before we start another reset. Send a
	 * UCSI_SET_NOTIFICATION_ENABLE command to achieve this.
	 * Ignore a timeout and try the reset anyway if this fails.
	 */
	if (cci & UCSI_CCI_RESET_COMPLETE) {
		command = UCSI_SET_NOTIFICATION_ENABLE;
		ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
					     sizeof(command));
		if (ret < 0)
			goto out;

		tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS);
		do {
			ret = ucsi->ops->read(ucsi, UCSI_CCI,
					      &cci, sizeof(cci));
			if (ret < 0)
				goto out;
			if (cci & UCSI_CCI_COMMAND_COMPLETE)
				break;
			if (time_is_before_jiffies(tmo))
				break;
			msleep(20);
		} while (1);

		WARN_ON(cci & UCSI_CCI_RESET_COMPLETE);
	}

	command = UCSI_PPM_RESET;
	ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
				     sizeof(command));
	if (ret < 0)