]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.10/usb-typec-ucsi-clear-ucsi_cci_reset_complete-before-reset.patch
Fixes for 5.10
[thirdparty/kernel/stable-queue.git] / queue-5.10 / usb-typec-ucsi-clear-ucsi_cci_reset_complete-before-reset.patch
1 From 3de4f996a0b5412aa451729008130a488f71563e Mon Sep 17 00:00:00 2001
2 From: "Christian A. Ehrhardt" <lk@c--e.de>
3 Date: Wed, 20 Mar 2024 08:39:26 +0100
4 Subject: usb: typec: ucsi: Clear UCSI_CCI_RESET_COMPLETE before reset
5
6 From: Christian A. Ehrhardt <lk@c--e.de>
7
8 commit 3de4f996a0b5412aa451729008130a488f71563e upstream.
9
10 Check the UCSI_CCI_RESET_COMPLETE complete flag before starting
11 another reset. Use a UCSI_SET_NOTIFICATION_ENABLE command to clear
12 the flag if it is set.
13
14 Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
15 Cc: stable <stable@kernel.org>
16 Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
17 Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
18 Link: https://lore.kernel.org/r/20240320073927.1641788-6-lk@c--e.de
19 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20 ---
21 drivers/usb/typec/ucsi/ucsi.c | 36 +++++++++++++++++++++++++++++++++++-
22 1 file changed, 35 insertions(+), 1 deletion(-)
23
24 --- a/drivers/usb/typec/ucsi/ucsi.c
25 +++ b/drivers/usb/typec/ucsi/ucsi.c
26 @@ -852,13 +852,47 @@ static int ucsi_reset_connector(struct u
27
28 static int ucsi_reset_ppm(struct ucsi *ucsi)
29 {
30 - u64 command = UCSI_PPM_RESET;
31 + u64 command;
32 unsigned long tmo;
33 u32 cci;
34 int ret;
35
36 mutex_lock(&ucsi->ppm_lock);
37
38 + ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci));
39 + if (ret < 0)
40 + goto out;
41 +
42 + /*
43 + * If UCSI_CCI_RESET_COMPLETE is already set we must clear
44 + * the flag before we start another reset. Send a
45 + * UCSI_SET_NOTIFICATION_ENABLE command to achieve this.
46 + * Ignore a timeout and try the reset anyway if this fails.
47 + */
48 + if (cci & UCSI_CCI_RESET_COMPLETE) {
49 + command = UCSI_SET_NOTIFICATION_ENABLE;
50 + ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
51 + sizeof(command));
52 + if (ret < 0)
53 + goto out;
54 +
55 + tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS);
56 + do {
57 + ret = ucsi->ops->read(ucsi, UCSI_CCI,
58 + &cci, sizeof(cci));
59 + if (ret < 0)
60 + goto out;
61 + if (cci & UCSI_CCI_COMMAND_COMPLETE)
62 + break;
63 + if (time_is_before_jiffies(tmo))
64 + break;
65 + msleep(20);
66 + } while (1);
67 +
68 + WARN_ON(cci & UCSI_CCI_RESET_COMPLETE);
69 + }
70 +
71 + command = UCSI_PPM_RESET;
72 ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
73 sizeof(command));
74 if (ret < 0)