mb/google/brya/var/uldrenite: update gpio settings
[coreboot2.git] / src / drivers / intel / usb4 / retimer / retimer.c
blob3769fc9193f1d090ab85c27501a48c7939e881ee
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <acpi/acpigen.h>
4 #include <acpi/acpi_device.h>
5 #include <acpi/acpi_pld.h>
6 #include <console/console.h>
7 #include <device/device.h>
8 #include <drivers/usb/acpi/chip.h>
9 #include <gpio.h>
10 #include <stdio.h>
12 #include "chip.h"
13 #include "retimer.h"
15 /* Unique ID for the retimer _DSM. */
16 #define INTEL_USB4_RETIMER_DSM_UUID "E0053122-795B-4122-8A5E-57BE1D26ACB3"
18 static const char *usb4_retimer_scope;
19 static const char *usb4_retimer_path_arg(const char *arg)
21 /* \\_SB.PCI0.TDMx.ARG */
22 static char name[DEVICE_PATH_MAX];
23 snprintf(name, sizeof(name), "%s%c%s", usb4_retimer_scope, '.', arg);
24 return name;
27 /* Each polling cycle takes up to 25 ms with a total of 12 of these iterations */
28 #define USB4_RETIMER_ITERATION_NUM 12
29 #define USB4_RETIMER_POLL_CYCLE_MS 25
30 static void usb4_retimer_execute_ec_cmd(uint8_t port, uint8_t cmd, uint8_t expected_value,
31 struct acpi_gpio *power_gpio)
33 const char *RFWU = ec_retimer_fw_update_path();
34 const uint8_t data = cmd << USB_RETIMER_FW_UPDATE_OP_SHIFT | port;
36 /* Invoke EC Retimer firmware update command execution */
37 ec_retimer_fw_update(data);
38 /* If RFWU has return value 0xfe, return error -1 */
39 acpigen_write_if_lequal_namestr_int(RFWU, USB_RETIMER_FW_UPDATE_ERROR);
40 acpigen_disable_tx_gpio(power_gpio);
41 acpigen_write_return_integer(-1);
42 acpigen_pop_len(); /* If */
44 acpigen_write_store_int_to_op(USB4_RETIMER_ITERATION_NUM, LOCAL2_OP);
45 acpigen_emit_byte(WHILE_OP);
46 acpigen_write_len_f();
47 acpigen_emit_byte(LGREATER_OP);
48 acpigen_emit_byte(LOCAL2_OP);
49 acpigen_emit_byte(ZERO_OP);
50 acpigen_write_if_lequal_namestr_int(RFWU, expected_value);
51 acpigen_emit_byte(BREAK_OP);
52 acpigen_pop_len(); /* If */
54 if (cmd == USB_RETIMER_FW_UPDATE_GET_MUX) {
55 acpigen_write_if_lequal_namestr_int(RFWU, USB_RETIMER_FW_UPDATE_INVALID_MUX);
56 acpigen_write_sleep(USB4_RETIMER_POLL_CYCLE_MS);
57 acpigen_emit_byte(DECREMENT_OP);
58 acpigen_emit_byte(LOCAL2_OP);
59 acpigen_emit_byte(CONTINUE_OP);
60 acpigen_pop_len(); /* If */
62 acpigen_emit_byte(AND_OP);
63 acpigen_emit_namestring(RFWU);
64 acpigen_write_integer(USB_RETIMER_FW_UPDATE_MUX_MASK);
65 acpigen_emit_byte(LOCAL3_OP);
66 acpigen_write_if();
67 acpigen_emit_byte(LNOT_OP);
68 acpigen_emit_byte(LEQUAL_OP);
69 acpigen_emit_byte(LOCAL3_OP);
70 acpigen_emit_byte(0);
71 acpigen_disable_tx_gpio(power_gpio);
72 acpigen_write_return_integer(-1);
73 acpigen_pop_len(); /* If */
74 } else if (cmd == USB_RETIMER_FW_UPDATE_SET_TBT) {
76 * EC return either USB_PD_MUX_USB4_ENABLED or USB_PD_MUX_TBT_COMPAT_ENABLED
77 * to RFWU after the USB_RETIMER_FW_UPDATE_SET_TBT command execution. It is
78 * needed to add additional check for USB_PD_MUX_TBT_COMPAT_ENABLED.
80 acpigen_write_if_lequal_namestr_int(RFWU, USB_PD_MUX_TBT_COMPAT_ENABLED);
81 acpigen_emit_byte(BREAK_OP);
82 acpigen_pop_len(); /* If */
85 acpigen_write_sleep(USB4_RETIMER_POLL_CYCLE_MS);
86 acpigen_emit_byte(DECREMENT_OP);
87 acpigen_emit_byte(LOCAL2_OP);
88 acpigen_pop_len(); /* While */
91 * Check whether there is timeout error
92 * Return: -1 if timeout error occurring
94 acpigen_write_if_lequal_op_int(LOCAL2_OP, 0);
95 acpigen_disable_tx_gpio(power_gpio);
96 acpigen_write_return_integer(-1);
97 acpigen_pop_len(); /* If */
100 static void enable_retimer_online_state(uint8_t port, struct acpi_gpio *power_gpio)
102 uint8_t expected_value;
105 * Enable_retimer_online_state under NDA
106 * 1. Force power on
107 * 2. Check if there is a device connected
108 * 3. Suspend PD
109 * 4. Set Mux to USB mode
110 * 5. Set Mux to Safe mode
111 * 6. Set Mux to TBT mode
114 /* Force power on for the retimer on the port */
115 acpigen_enable_tx_gpio(power_gpio);
118 * Get MUX mode state
119 * Return -1 if there is a device connected on the port.
120 * Otherwise proceed Retimer firmware upgrade operation.
122 expected_value = USB_PD_MUX_NONE;
123 usb4_retimer_execute_ec_cmd(port, USB_RETIMER_FW_UPDATE_GET_MUX, expected_value,
124 power_gpio);
127 * Suspend PD
128 * Command: USB_RETIMER_FW_UPDATE_SUSPEND_PD
129 * Expect return value: 0
131 expected_value = 0;
132 usb4_retimer_execute_ec_cmd(port, USB_RETIMER_FW_UPDATE_SUSPEND_PD, expected_value,
133 power_gpio);
136 * Set MUX USB Mode
137 * Command: USB_RETIMER_FW_UPDATE_SUSPEND_PD
138 * Expect return value: USB_PD_MUX_USB_ENABLED
140 expected_value = USB_PD_MUX_USB_ENABLED;
141 usb4_retimer_execute_ec_cmd(port, USB_RETIMER_FW_UPDATE_SET_USB, expected_value,
142 power_gpio);
145 * Set MUX Safe Mode
146 * Command: USB_RETIMER_FW_UPDATE_SET_SAFE
147 * Expect return value: USB_PD_MUX_SAFE_MODE
149 expected_value = USB_PD_MUX_SAFE_MODE;
150 usb4_retimer_execute_ec_cmd(port, USB_RETIMER_FW_UPDATE_SET_SAFE, expected_value,
151 power_gpio);
154 * Set MUX TBT Mode
155 * Command: USB_RETIMER_FW_UPDATE_SET_TBT
156 * Expect return value: USB_PD_MUX_USB4_ENABLED or USB_PD_MUX_TBT_COMPAT_ENABLED
158 expected_value = USB_PD_MUX_USB4_ENABLED;
159 usb4_retimer_execute_ec_cmd(port, USB_RETIMER_FW_UPDATE_SET_TBT, expected_value,
160 power_gpio);
163 static void disable_retimer_online_state(uint8_t port, struct acpi_gpio *power_gpio)
165 uint8_t expected_value;
168 * Disable_retimer_online_state
169 * 1. Set Mux to disconnect mode
170 * 2. Resume PD
171 * 3. Force power off
175 * Set MUX Disconnect Mode
176 * Command: USB_RETIMER_FW_UPDATE_DISCONNECT
177 * Expect return value: 0
179 expected_value = 0;
180 usb4_retimer_execute_ec_cmd(port, USB_RETIMER_FW_UPDATE_DISCONNECT, expected_value,
181 power_gpio);
184 * Resume PD
185 * Command: USB_RETIMER_FW_UPDATE_RESUME_PD
186 * Expect return value: 1
188 expected_value = 1;
189 usb4_retimer_execute_ec_cmd(port, USB_RETIMER_FW_UPDATE_RESUME_PD, expected_value,
190 power_gpio);
192 /* Force power off */
193 acpigen_disable_tx_gpio(power_gpio);
197 * Arg0: UUID e0053122-795b-4122-8a5e-57be1d26acb3
198 * Arg1: Revision ID (set to 1)
199 * Arg2: Function Index
200 * 0: Query command implemented
201 * 1: Get power state
202 * 2: Set power state
203 * Arg3: A package containing parameters for the function specified
204 * by the UUID, revision ID, function index and port index.
206 static void usb4_retimer_cb_standard_query(uint8_t port, void *arg)
209 * ToInteger (Arg1, Local1)
210 * If (Local1 == 1) {
211 * Return(Buffer() {0x7})
213 * Return (Buffer() {0x01})
215 acpigen_write_to_integer(ARG1_OP, LOCAL1_OP);
217 /* Revision 1 supports 2 Functions beyond the standard query */
218 acpigen_write_if_lequal_op_int(LOCAL1_OP, 1);
219 acpigen_write_return_singleton_buffer(0x7);
220 acpigen_pop_len(); /* If */
222 /* Other revisions support no additional functions */
223 acpigen_write_return_singleton_buffer(0x1);
226 static void usb4_retimer_cb_get_power_state(uint8_t port, void *arg)
228 const char *PWR;
229 char pwr[DEVICE_PATH_MAX];
231 snprintf(pwr, sizeof(pwr), "HR.DFP%1d.PWR", port);
232 PWR = usb4_retimer_path_arg(pwr);
235 * If (PWR > 0) {
236 * Return (1)
239 acpigen_write_if();
240 acpigen_emit_byte(LGREATER_OP);
241 acpigen_emit_namestring(PWR);
242 acpigen_emit_byte(0);
243 acpigen_write_return_integer(1);
246 * Else {
247 * Return (0)
250 acpigen_write_else();
251 acpigen_write_return_integer(0);
252 acpigen_pop_len();
255 static void usb4_retimer_cb_set_power_state(uint8_t port, void *arg)
257 struct acpi_gpio *power_gpio = arg;
258 const char *PWR;
259 char pwr[DEVICE_PATH_MAX];
261 snprintf(pwr, sizeof(pwr), "HR.DFP%1d.PWR", port);
262 PWR = usb4_retimer_path_arg(pwr);
265 * Get information to set retimer power state from Arg3[0]
266 * Local1 = DeRefOf (Arg3[0])
268 acpigen_get_package_op_element(ARG3_OP, 0, LOCAL1_OP);
271 * If ((Local1 == 0) && (PWR > 0)) {
272 * PWR--
273 * If (PWR == 0) {
274 * // Disable retimer online state
278 acpigen_write_if();
279 acpigen_emit_byte(LAND_OP);
280 acpigen_emit_byte(LEQUAL_OP);
281 acpigen_emit_byte(LOCAL1_OP);
282 acpigen_emit_byte(0);
283 acpigen_emit_byte(LGREATER_OP);
284 acpigen_emit_namestring(PWR);
285 acpigen_emit_byte(0);
286 /* PWR-- */
287 acpigen_emit_byte(DECREMENT_OP);
288 acpigen_emit_namestring(PWR);
289 acpigen_write_if_lequal_namestr_int(PWR, 0); /* If (PWR == 0) */
290 disable_retimer_online_state(port, power_gpio);
291 acpigen_pop_len(); /* If (PWR == 0) */
294 * Else If ((Local1 == 1) && (PWR == 0)) {
295 * // Enable retimer online state
296 * PWR++
299 acpigen_write_else();
300 acpigen_write_if();
301 acpigen_emit_byte(LAND_OP);
302 acpigen_emit_byte(LEQUAL_OP);
303 acpigen_emit_byte(LOCAL1_OP);
304 acpigen_emit_byte(1);
305 acpigen_emit_byte(LEQUAL_OP);
306 acpigen_emit_namestring(PWR);
307 acpigen_emit_byte(0);
308 enable_retimer_online_state(port, power_gpio);
309 /* PWR++ */
310 acpigen_emit_byte(INCREMENT_OP);
311 acpigen_emit_namestring(PWR);
314 * Else {
315 * Return (0)
318 acpigen_write_else();
319 acpigen_write_return_integer(0);
320 acpigen_pop_len(); /* Else */
321 acpigen_pop_len(); /* If */
324 * If (PWR == 1) {
325 * Return (1)
328 acpigen_write_if_lequal_namestr_int(PWR, 1);
329 acpigen_write_return_integer(1);
332 * Else {
333 * Return (0)
336 acpigen_write_else();
337 acpigen_write_return_integer(0);
338 acpigen_pop_len();
341 static void (*usb4_retimer_callbacks[3])(uint8_t port, void *) = {
342 usb4_retimer_cb_standard_query, /* Function 0 */
343 usb4_retimer_cb_get_power_state, /* Function 1 */
344 usb4_retimer_cb_set_power_state, /* Function 2 */
347 static void usb4_retimer_write_dsm(uint8_t port, const char *uuid,
348 void (**callbacks)(uint8_t port, void *), size_t count, void *arg)
350 struct usb4_retimer_dsm_uuid id = DSM_UUID(uuid, callbacks, count, arg);
351 size_t i;
353 acpigen_write_to_integer(ARG2_OP, LOCAL0_OP);
355 for (i = 0; i < id.count; i++) {
356 /* If (LEqual (Local0, i)) */
357 acpigen_write_if_lequal_op_int(LOCAL0_OP, i);
359 /* Callback to write if handler. */
360 if (id.callbacks[i])
361 id.callbacks[i](port, id.arg);
363 acpigen_pop_len(); /* If */
367 static void usb4_retimer_fill_ssdt(const struct device *dev)
369 struct drivers_intel_usb4_retimer_config *config = dev->chip_info;
370 const struct device *usb_device;
371 static char dfp[DEVICE_PATH_MAX];
372 struct acpi_pld pld;
373 uint8_t dfp_port, usb_port;
374 int ec_port = 0;
376 usb4_retimer_scope = acpi_device_scope(dev);
377 if (!usb4_retimer_scope || !config)
378 return;
380 /* Scope */
381 acpigen_write_scope(usb4_retimer_scope);
383 /* Host router */
384 acpigen_write_device("HR");
385 acpigen_write_ADR(0);
386 acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
388 for (dfp_port = 0; dfp_port < DFP_NUM_MAX; dfp_port++) {
389 if (!config->dfp[dfp_port].power_gpio.pin_count) {
390 printk(BIOS_WARNING, "%s: No DFP%1d power GPIO for %s\n",
391 __func__, dfp_port, dev_path(dev));
392 continue;
395 usb_device = config->dfp[dfp_port].typec_port;
396 usb_port = usb_device->path.usb.port_id;
398 ec_port = retimer_get_index_for_typec(usb_port);
399 if (ec_port == -1) {
400 printk(BIOS_ERR, "%s: No relative EC port found for TC port %d\n",
401 __func__, usb_port);
402 continue;
404 /* DFPx */
405 snprintf(dfp, sizeof(dfp), "DFP%1d", ec_port);
406 acpigen_write_device(dfp);
407 /* _ADR part is for the lane adapter */
408 acpigen_write_ADR(dfp_port*2 + 1);
410 /* Fill _PLD with the same USB 3.x object on the Type-C connector */
411 if (CONFIG(DRIVERS_USB_ACPI)) {
412 if (usb_acpi_get_pld(usb_device, &pld))
413 acpigen_write_pld(&pld);
414 else
415 printk(BIOS_ERR, "Error retrieving PLD for USB Type-C %d\n",
416 usb_port);
419 /* Power online reference counter(_PWR) */
420 acpigen_write_name("PWR");
421 acpigen_write_zero();
423 /* Method (_DSM, 4, Serialized) */
424 acpigen_write_method_serialized("_DSM", 0x4);
425 /* ToBuffer (Arg0, Local0) */
426 acpigen_write_to_buffer(ARG0_OP, LOCAL0_OP);
427 acpigen_write_if(); /* If (UUID != INTEL_USB4_RETIMER_DSM_UUID) */
428 acpigen_emit_byte(LNOT_OP);
429 acpigen_emit_byte(LEQUAL_OP);
430 acpigen_emit_byte(LOCAL0_OP);
431 acpigen_write_uuid(INTEL_USB4_RETIMER_DSM_UUID);
432 /* Return (Buffer (One) { 0x0 }) */
433 acpigen_write_return_singleton_buffer(0x0);
434 acpigen_pop_len();
435 usb4_retimer_write_dsm(ec_port, INTEL_USB4_RETIMER_DSM_UUID,
436 usb4_retimer_callbacks, ARRAY_SIZE(usb4_retimer_callbacks),
437 (void *)&config->dfp[dfp_port].power_gpio);
438 /* Default case: Return (Buffer (One) { 0x0 }) */
439 acpigen_write_return_singleton_buffer(0x0);
441 acpigen_pop_len(); /* Method _DSM */
442 acpigen_pop_len(); /* DFP */
444 acpigen_pop_len(); /* Host Router */
445 acpigen_pop_len(); /* Scope */
447 printk(BIOS_INFO, "%s.HR: %s at %s\n", usb4_retimer_scope, dev->chip_ops->name,
448 dev_path(dev));
451 static struct device_operations usb4_retimer_dev_ops = {
452 .read_resources = noop_read_resources,
453 .set_resources = noop_set_resources,
454 .acpi_fill_ssdt = usb4_retimer_fill_ssdt,
457 static void usb4_retimer_enable(struct device *dev)
459 dev->ops = &usb4_retimer_dev_ops;
462 struct chip_operations drivers_intel_usb4_retimer_ops = {
463 .name = "Intel USB4 Retimer",
464 .enable_dev = usb4_retimer_enable
467 __weak const char *ec_retimer_fw_update_path(void)
469 return NULL;
472 __weak void ec_retimer_fw_update(uint8_t data)
477 * This function will convert CPU physical port mapping to abstract
478 * EC port mapping.
479 * For example, board might have enabled TCSS port 1 and 3 as per physical
480 * port mapping. Since only 2 TCSS ports are enabled EC will index it as port 0
481 * and port 1. So there will be an issue when coreboot sends command to EC for
482 * port 3 (with coreboot index of 2). EC will produce an error due to wrong index.
484 * Note: Each SoC code using retimer driver needs to implement this function
485 * since SoC will have physical port details.
487 __weak int retimer_get_index_for_typec(uint8_t typec_port)
489 /* By default assume that retimer port index = Type C port */
490 return (int)typec_port;