usb: typec: ucsi: Clear UCSI_CCI_RESET_COMPLETE before reset
commit 3de4f996a0b5412aa451729008130a488f71563e upstream. 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: Christian A. Ehrhardt <lk@c--e.de> Cc: stable <stable@kernel.org> Reviewed-by: Heikki 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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
e9042f4e71
commit
db0f08a6b6
@@ -852,13 +852,47 @@ static int ucsi_reset_connector(struct ucsi_connector *con, bool hard)
|
|||||||
|
|
||||||
static int ucsi_reset_ppm(struct ucsi *ucsi)
|
static int ucsi_reset_ppm(struct ucsi *ucsi)
|
||||||
{
|
{
|
||||||
u64 command = UCSI_PPM_RESET;
|
u64 command;
|
||||||
unsigned long tmo;
|
unsigned long tmo;
|
||||||
u32 cci;
|
u32 cci;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&ucsi->ppm_lock);
|
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,
|
ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
|
||||||
sizeof(command));
|
sizeof(command));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
Reference in New Issue
Block a user