{lynxpoint,broadwell}/hda_verb.c: Drop effect-free write
[coreboot.git] / src / acpi / acpigen_usb.c
blob7448b3b5696fbe4efab9538e8194b95767a43078
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <acpi/acpi.h>
4 #include <acpi/acpi_device.h>
5 #include <acpi/acpigen.h>
6 #include <acpi/acpigen_usb.h>
8 static const char *power_role_to_str(enum usb_typec_power_role power_role)
10 switch (power_role) {
11 case TYPEC_POWER_ROLE_SOURCE:
12 return "source";
13 case TYPEC_POWER_ROLE_SINK:
14 return "sink";
15 case TYPEC_POWER_ROLE_DUAL:
16 return "dual";
17 default:
18 return "unknown";
22 static const char *try_power_role_to_str(enum usb_typec_try_power_role try_power_role)
24 switch (try_power_role) {
25 case TYPEC_TRY_POWER_ROLE_NONE:
27 * This should never get returned; if there is no try-power role for a device,
28 * then the try-power-role field is not added to the DSD. Thus, this is just
29 * for completeness.
31 return "none";
32 case TYPEC_TRY_POWER_ROLE_SINK:
33 return "sink";
34 case TYPEC_TRY_POWER_ROLE_SOURCE:
35 return "source";
36 default:
37 return "unknown";
41 static const char *data_role_to_str(enum usb_typec_data_role data_role)
43 switch (data_role) {
44 case TYPEC_DATA_ROLE_DFP:
45 return "host";
46 case TYPEC_DATA_ROLE_UFP:
47 return "device";
48 case TYPEC_DATA_ROLE_DUAL:
49 return "dual";
50 default:
51 return "unknown";
55 /* Add port capabilities as DP properties */
56 static void add_port_caps(struct acpi_dp *dsd,
57 const struct typec_connector_class_config *config)
59 acpi_dp_add_string(dsd, "power-role", power_role_to_str(config->power_role));
60 acpi_dp_add_string(dsd, "data-role", data_role_to_str(config->data_role));
62 if (config->try_power_role != TYPEC_TRY_POWER_ROLE_NONE)
63 acpi_dp_add_string(dsd, "try-power-role",
64 try_power_role_to_str(config->try_power_role));
67 static void add_device_ref(struct acpi_dp *dsd,
68 const char *prop_name,
69 const struct device *dev)
71 const char *path;
72 char *fresh;
74 if (!dev || !dev->enabled)
75 return;
78 * Unfortunately, the acpi_dp_* API doesn't write out the data immediately, thus we need
79 * different storage areas for all of the strings, so strdup() is used for that. It is
80 * safe to use strdup() here, because the strings are generated at build-time and are
81 * guaranteed to be NUL-terminated (they come from the devicetree).
83 path = acpi_device_path(dev);
84 if (path) {
85 fresh = strdup(path);
86 if (fresh)
87 acpi_dp_add_reference(dsd, prop_name, fresh);
91 static void add_device_references(struct acpi_dp *dsd,
92 const struct typec_connector_class_config *config)
95 * Add references to the USB port objects so that the consumer of this information can
96 * know whether the port supports USB2, USB3, and/or USB4.
98 add_device_ref(dsd, "usb2-port", config->usb2_port);
99 add_device_ref(dsd, "usb3-port", config->usb3_port);
100 add_device_ref(dsd, "usb4-port", config->usb4_port);
103 * Add references to the ACPI device(s) which control the orientation, USB data role and
104 * data muxing.
106 add_device_ref(dsd, "orientation-switch", config->orientation_switch);
107 add_device_ref(dsd, "usb-role-switch", config->usb_role_switch);
108 add_device_ref(dsd, "mode-switch", config->mode_switch);
111 void acpigen_write_typec_connector(const struct typec_connector_class_config *config,
112 int port_number,
113 add_custom_dsd_property_cb add_custom_dsd_property)
115 struct acpi_dp *dsd;
116 char name[5];
118 /* Create a CONx device */
119 snprintf(name, sizeof(name), "CON%1X", port_number);
120 acpigen_write_device(name);
121 acpigen_write_name_integer("_ADR", port_number);
123 dsd = acpi_dp_new_table("_DSD");
125 /* Write out the _DSD table */
126 acpi_dp_add_integer(dsd, "port-number", port_number);
127 add_port_caps(dsd, config);
128 add_device_references(dsd, config);
130 /* Allow client to add custom properties if desired */
131 if (add_custom_dsd_property)
132 add_custom_dsd_property(dsd, port_number);
133 acpi_dp_write(dsd);
135 acpigen_pop_len(); /* Device */