1 /* SPDX-License-Identifier: GPL-2.0-or-later */
4 #include <acpi/acpi_device.h>
5 #include <acpi/acpi_pld.h>
6 #include <acpi/acpigen.h>
7 #include <acpi/acpigen_ps2_keybd.h>
8 #include <acpi/acpigen_usb.h>
9 #include <console/console.h>
10 #include <drivers/usb/acpi/chip.h>
11 #include <drivers/intel/usb4/retimer/retimer.h>
12 #include <ec/google/common/dptf.h>
16 #include "ec_commands.h"
18 #define GOOGLE_CHROMEEC_USBC_DEVICE_HID "GOOG0014"
19 #define GOOGLE_CHROMEEC_USBC_DEVICE_NAME "USBC"
22 * Boards using UCSI need the USB-C ports to match with cros_ec_ucsi, not
25 #define GOOGLE_CHROMEEC_USBC_UCSI_DEVICE_HID "GOOG0021"
27 const char *google_chromeec_acpi_name(const struct device
*dev
)
30 * Chrome EC device (CREC - GOOG0004) is really a child of EC device (EC - PNP0C09) in
31 * ACPI tables. However, in coreboot device tree, there is no separate chip/device for
32 * EC0. Thus, Chrome EC device needs to return "EC0.CREC" as the ACPI name so that the
33 * callers can get the correct acpi device path/scope for this device.
35 * If we ever enable a separate driver for generating AML for EC0 device, then this
36 * function needs to be updated to return "CREC".
42 * Helper for fill_ssdt_generator. This adds references to the USB
43 * port objects so that the consumer of this information can know
44 * whether the port supports USB2 and/or USB3.
46 static void get_usb_port_references(int port_number
, struct device
**usb2_port
,
47 struct device
**usb3_port
, struct device
**usb4_port
)
49 struct drivers_usb_acpi_config
*config
;
50 struct device
*port
= NULL
;
52 /* Search through the devicetree for matching USB Type-C ports */
53 while ((port
= dev_find_path(port
, DEVICE_PATH_USB
)) != NULL
) {
54 if (!port
->enabled
|| port
->path
.type
!= DEVICE_PATH_USB
)
57 config
= port
->chip_info
;
59 /* Look at only USB Type-C ports */
60 if ((config
->type
!= UPC_TYPE_C_USB2_ONLY
) &&
61 (config
->type
!= UPC_TYPE_C_USB2_SS_SWITCH
) &&
62 (config
->type
!= UPC_TYPE_C_USB2_SS
))
66 * Check for a matching port number (the 'token' field in 'group'). Note that
67 * 'port_number' is 0-based, whereas the 'token' field is 1-based.
70 if (config
->use_custom_pld
)
71 group_token
= config
->custom_pld
.group
.token
;
73 group_token
= config
->group
.token
;
74 if (group_token
!= (port_number
+ 1))
77 switch (port
->path
.usb
.port_type
) {
94 * Apparently these are supposed to be uppercase, in contrast to the other
97 static const char *port_location_to_str(enum ec_pd_port_location port_location
)
99 switch (port_location
) {
100 case EC_PD_PORT_LOCATION_LEFT
:
102 case EC_PD_PORT_LOCATION_RIGHT
:
104 case EC_PD_PORT_LOCATION_BACK
:
106 case EC_PD_PORT_LOCATION_FRONT
:
108 case EC_PD_PORT_LOCATION_LEFT_FRONT
:
110 case EC_PD_PORT_LOCATION_LEFT_BACK
:
112 case EC_PD_PORT_LOCATION_RIGHT_FRONT
:
113 return "RIGHT_FRONT";
114 case EC_PD_PORT_LOCATION_RIGHT_BACK
:
116 case EC_PD_PORT_LOCATION_BACK_LEFT
:
118 case EC_PD_PORT_LOCATION_BACK_RIGHT
:
120 case EC_PD_PORT_LOCATION_UNKNOWN
:
127 static struct usb_pd_port_caps port_caps
;
128 static void add_port_location(struct acpi_dp
*dsd
, int port_number
)
130 acpi_dp_add_string(dsd
, "port-location", port_location_to_str(port_caps
.port_location
));
133 static void get_pld_from_usb_ports(struct acpi_pld
*pld
,
134 struct device
*usb2_port
, struct device
*usb3_port
,
135 struct device
*usb4_port
)
137 struct drivers_usb_acpi_config
*config
= NULL
;
140 config
= usb4_port
->chip_info
;
142 config
= usb3_port
->chip_info
;
144 config
= usb2_port
->chip_info
;
147 if (config
->use_custom_pld
)
148 *pld
= config
->custom_pld
;
150 acpi_pld_fill_usb(pld
, config
->type
, &config
->group
);
154 static void fill_ssdt_typec_device(const struct device
*dev
)
156 struct ec_google_chromeec_config
*config
= dev
->chip_info
;
159 unsigned int num_ports
= 0;
160 struct device
*usb2_port
;
161 struct device
*usb3_port
;
162 struct device
*usb4_port
;
163 struct acpi_pld pld
= {0};
164 uint32_t pcap_mask
= 0;
166 rv
= google_chromeec_get_num_pd_ports(&num_ports
);
167 if (rv
|| num_ports
== 0)
170 /* If we can't get port caps, we shouldn't bother creating a device. */
171 rv
= google_chromeec_get_cmd_versions(EC_CMD_GET_PD_PORT_CAPS
, &pcap_mask
);
172 if (rv
|| pcap_mask
== 0)
175 acpigen_write_scope(acpi_device_path(dev
));
176 acpigen_write_device(GOOGLE_CHROMEEC_USBC_DEVICE_NAME
);
178 bool ucsi_platform
= google_chromeec_get_ucsi_enabled();
180 acpigen_write_name_string("_HID",
181 GOOGLE_CHROMEEC_USBC_UCSI_DEVICE_HID
);
182 acpigen_write_name_string("_DDN", "ChromeOS EC UCSI USB Type-C "
185 acpigen_write_name_string("_HID",
186 GOOGLE_CHROMEEC_USBC_DEVICE_HID
);
187 acpigen_write_name_string("_DDN", "ChromeOS EC Embedded "
188 "Controller USB Type-C Control");
191 for (i
= 0; i
< num_ports
; ++i
) {
192 rv
= google_chromeec_get_pd_port_caps(i
, &port_caps
);
199 get_usb_port_references(i
, &usb2_port
, &usb3_port
, &usb4_port
);
201 get_pld_from_usb_ports(&pld
, usb2_port
, usb3_port
, usb4_port
);
203 struct typec_connector_class_config typec_config
= {
204 .power_role
= (enum usb_typec_power_role
)port_caps
.power_role_cap
,
206 (enum usb_typec_try_power_role
)port_caps
.try_power_role_cap
,
207 .data_role
= (enum usb_typec_data_role
)port_caps
.data_role_cap
,
208 .usb2_port
= usb2_port
,
209 .usb3_port
= usb3_port
,
210 .usb4_port
= usb4_port
,
211 .orientation_switch
= config
->mux_conn
[i
],
212 .usb_role_switch
= config
->mux_conn
[i
],
213 .mode_switch
= config
->mux_conn
[i
],
214 .retimer_switch
= config
->retimer_conn
[i
],
218 acpigen_write_typec_connector(&typec_config
, i
, add_port_location
);
221 acpigen_pop_len(); /* Device GOOGLE_CHROMEEC_USBC_DEVICE_NAME */
222 acpigen_pop_len(); /* Scope */
225 static const enum ps2_action_key ps2_enum_val
[] = {
226 [TK_ABSENT
] = PS2_KEY_ABSENT
,
227 [TK_BACK
] = PS2_KEY_BACK
,
228 [TK_FORWARD
] = PS2_KEY_FORWARD
,
229 [TK_REFRESH
] = PS2_KEY_REFRESH
,
230 [TK_FULLSCREEN
] = PS2_KEY_FULLSCREEN
,
231 [TK_OVERVIEW
] = PS2_KEY_OVERVIEW
,
232 [TK_BRIGHTNESS_DOWN
] = PS2_KEY_BRIGHTNESS_DOWN
,
233 [TK_BRIGHTNESS_UP
] = PS2_KEY_BRIGHTNESS_UP
,
234 [TK_VOL_MUTE
] = PS2_KEY_VOL_MUTE
,
235 [TK_VOL_DOWN
] = PS2_KEY_VOL_DOWN
,
236 [TK_VOL_UP
] = PS2_KEY_VOL_UP
,
237 [TK_SNAPSHOT
] = PS2_KEY_SNAPSHOT
,
238 [TK_PRIVACY_SCRN_TOGGLE
] = PS2_KEY_PRIVACY_SCRN_TOGGLE
,
239 [TK_KBD_BKLIGHT_DOWN
] = PS2_KEY_KBD_BKLIGHT_DOWN
,
240 [TK_KBD_BKLIGHT_UP
] = PS2_KEY_KBD_BKLIGHT_UP
,
241 [TK_PLAY_PAUSE
] = PS2_KEY_PLAY_PAUSE
,
242 [TK_NEXT_TRACK
] = PS2_KEY_NEXT_TRACK
,
243 [TK_PREV_TRACK
] = PS2_KEY_PREV_TRACK
,
244 [TK_KBD_BKLIGHT_TOGGLE
] = PS2_KEY_KBD_BKLIGHT_TOGGLE
,
245 [TK_MICMUTE
] = PS2_KEY_MICMUTE
,
246 [TK_MENU
] = PS2_KEY_MENU
,
247 [TK_DICTATE
] = PS2_KEY_DICTATE
,
248 [TK_ACCESSIBILITY
] = PS2_KEY_ACCESSIBILITY
,
249 [TK_DONOTDISTURB
] = PS2_KEY_DO_NOT_DISTURB
,
252 static void fill_ssdt_ps2_keyboard(const struct device
*dev
)
255 struct ec_response_keybd_config keybd
= {};
256 enum ps2_action_key ps2_action_keys
[MAX_TOP_ROW_KEYS
] = {};
258 if (google_chromeec_get_keybd_config(&keybd
) ||
259 !keybd
.num_top_row_keys
||
260 keybd
.num_top_row_keys
> MAX_TOP_ROW_KEYS
) {
261 printk(BIOS_INFO
, "PS2K: Unsupported or bad resp from EC. Vivaldi disabled!\n");
265 /* Convert enum action_key values to enum ps2_action_key values */
266 for (i
= 0; i
< keybd
.num_top_row_keys
; i
++)
267 ps2_action_keys
[i
] = ps2_enum_val
[keybd
.action_keys
[i
]];
269 acpigen_ps2_keyboard_dsd("_SB.PCI0.PS2K", keybd
.num_top_row_keys
,
271 !!(keybd
.capabilities
& KEYBD_CAP_FUNCTION_KEYS
),
272 !!(keybd
.capabilities
& KEYBD_CAP_NUMERIC_KEYPAD
),
273 !!(keybd
.capabilities
& KEYBD_CAP_SCRNLOCK_KEY
),
274 !!(keybd
.capabilities
& KEYBD_CAP_ASSISTANT_KEY
),
278 static const char *ec_acpi_name(const struct device
*dev
)
283 static struct device_operations ec_ops
= {
284 .acpi_name
= ec_acpi_name
,
287 void google_chromeec_fill_ssdt_generator(const struct device
*dev
)
289 struct device_path path
;
292 /* Set up a minimal EC0 device to pass to the DPTF helpers */
293 path
.type
= DEVICE_PATH_GENERIC
;
295 path
.generic
.subid
= 0;
296 ec
= alloc_find_dev(dev
->upstream
, &path
);
299 if (CONFIG(DRIVERS_INTEL_DPTF
))
300 ec_fill_dptf_helpers(ec
, dev
);
302 fill_ssdt_typec_device(dev
);
303 fill_ssdt_ps2_keyboard(dev
);
306 const char *ec_retimer_fw_update_path(void)
308 return "\\_SB_.PCI0.LPCB.EC0_.RFWU";
311 void ec_retimer_fw_update(uint8_t data
)
313 const char *RFWU
= ec_retimer_fw_update_path();
316 * Write the EC RAM for Retimer Upgrade
319 acpigen_write_store();
320 acpigen_write_byte(data
);
321 acpigen_emit_namestring(RFWU
);