Tim Wawrzynczak has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/38541 )
Change subject: ec/google/chromeec: Add SSDT generator for ChromeOS EC ......................................................................
ec/google/chromeec: Add SSDT generator for ChromeOS EC
Newer versions of the Linux kernel would like to consume information about the USB PD ports that are attached to the device. This information is obtained from the CrOS EC and exposed in the SSDT ACPI table.
Also, the device enable for this PCI device was moved from ec_lpc.c to ec.c, where this new generic code can live, and allows bus-specific code to still call functions on device enable (so that PnP enable for the LPC device still gets called).
BUG=b:146506369 BRANCH=none TEST=Verify the SSDT contains the expected information
Change-Id: I729caecd64d9320fb02c0404c8315122f010970b Signed-off-by: Tim Wawrzynczak twawrzynczak@chromium.org --- M src/ec/google/chromeec/ec.c M src/ec/google/chromeec/ec.h M src/ec/google/chromeec/ec_lpc.c 3 files changed, 177 insertions(+), 6 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/41/38541/1
diff --git a/src/ec/google/chromeec/ec.c b/src/ec/google/chromeec/ec.c index 7a4f27f..5548541 100644 --- a/src/ec/google/chromeec/ec.c +++ b/src/ec/google/chromeec/ec.c @@ -38,6 +38,9 @@
#define INVALID_HCMD 0xFF
+#define GOOGLE_CHROMEEC_USBC_DEVICE_HID "GOOG0014" +#define GOOGLE_CHROMEEC_USBC_DEVICE_NAME "USBC" + /* * Map UHEPI masks to non UHEPI commands in order to support old EC FW * which does not support UHEPI command. @@ -1568,3 +1571,169 @@
return 1; } + + + +#if !DEVTREE_EARLY +static const char *google_chromeec_acpi_name(const struct device *dev) +{ + return "EC0"; +} + +static const char *power_role_to_str(enum ec_pd_power_role_caps power_role) +{ + switch (power_role) { + case EC_PD_POWER_ROLE_SOURCE: + return "source"; + case EC_PD_POWER_ROLE_SINK: + return "sink"; + case EC_PD_POWER_ROLE_DUAL: + return "dual"; + default: + return "unknown"; + } +} + +static const char *try_power_role_to_str( + enum ec_pd_try_power_role_caps try_power_role) +{ + switch (try_power_role) { + case EC_PD_TRY_POWER_ROLE_NONE: + return "none"; + case EC_PD_TRY_POWER_ROLE_SINK: + return "sink"; + case EC_PD_TRY_POWER_ROLE_SOURCE: + return"source"; + default: + return "unknown"; + } +} + +static const char *data_role_to_str(enum ec_pd_data_role_caps data_role) +{ + switch (data_role) { + case EC_PD_DATA_ROLE_DFP: + return "dfp"; + case EC_PD_DATA_ROLE_UFP: + return "ufp"; + case EC_PD_DATA_ROLE_DUAL: + return "dual"; + default: + return "unknown"; + } +} + +static const char *port_location_to_str(enum ec_pd_port_location port_location) +{ + switch (port_location) { + case EC_PD_PORT_LOCATION_LEFT: + return "LEFT"; + case EC_PD_PORT_LOCATION_RIGHT: + return "RIGHT"; + case EC_PD_PORT_LOCATION_BACK: + return "BACK"; + case EC_PD_PORT_LOCATION_FRONT: + return "FRONT"; + case EC_PD_PORT_LOCATION_LEFT_FRONT: + return "LEFT_FRONT"; + case EC_PD_PORT_LOCATION_LEFT_BACK: + return "LEFT_BACK"; + case EC_PD_PORT_LOCATION_RIGHT_FRONT: + return "RIGHT_FRONT"; + case EC_PD_PORT_LOCATION_RIGHT_BACK: + return "RIGHT_BACK"; + case EC_PD_PORT_LOCATION_BACK_LEFT: + return "BACK_LEFT"; + case EC_PD_PORT_LOCATION_BACK_RIGHT: + return "BACK_RIGHT"; + case EC_PD_PORT_LOCATION_UNKNOWN: /* intentional fallthrough */ + default: + return "UNKNOWN"; + } +} + +static void google_chromeec_fill_ssdt_generator(struct device *dev) +{ + /*struct ec_response_usb_pd_power_info port_info;*/ + enum ec_pd_power_role_caps power_role_cap; + enum ec_pd_try_power_role_caps try_power_role_cap; + enum ec_pd_data_role_caps data_role_cap; + enum ec_pd_port_location port_location; + struct acpi_dp *dsd = NULL; + char con_name[] = "CON0"; + int rv; + int i; + int num_ports = 0; + const char *scope = acpi_device_path(dev); + + acpigen_write_scope(scope); + acpigen_write_device(GOOGLE_CHROMEEC_USBC_DEVICE_NAME); + acpigen_write_name_string("_HID", GOOGLE_CHROMEEC_USBC_DEVICE_HID); + acpigen_write_name_string("_DDN", "ChromeOS EC Embedded Controller " + "USB Type-C Control"); + + rv = google_chromeec_get_num_pd_ports(&num_ports); + if (rv) + return; + + for (i = 0; i < num_ports; ++i) { + rv = google_chromeec_get_pd_port_caps(i, + &power_role_cap, + &try_power_role_cap, + &data_role_cap, + &port_location); + if (rv) + continue; + + con_name[3] = (char)i + '0'; + acpigen_write_device(con_name); + acpigen_write_name_integer("_ADR", (uint64_t)i); + + /* _DSD */ + dsd = acpi_dp_new_table("_DSD"); + acpi_dp_add_integer(dsd, "port-number", (uint64_t)i); + acpi_dp_add_string(dsd, "power-role", + power_role_to_str(power_role_cap)); + + if (try_power_role_cap != EC_PD_TRY_POWER_ROLE_NONE) + acpi_dp_add_string(dsd, "try-power-role", + try_power_role_to_str(try_power_role_cap)); + + acpi_dp_add_string(dsd, "data-role", + data_role_to_str(data_role_cap)); + acpi_dp_add_string(dsd, "port-location", + port_location_to_str(port_location)); + + acpi_dp_write(dsd); + acpigen_pop_len(); /* Device */ + } + + acpigen_pop_len(); /* Device */ + acpigen_pop_len(); /* Scope */ +} + +__weak void google_ec_enable_extra(struct device *dev) +{ +} + +static struct device_operations ec_chromeec_ops = { +#if CONFIG(HAVE_ACPI_TABLES) + .acpi_name = google_chromeec_acpi_name, + .acpi_fill_ssdt_generator = google_chromeec_fill_ssdt_generator, +#endif /* #if CONFIG(HAVE_ACPI_TABLES) */ +}; +#endif /* #if !DEVTREE_EARLY */ + +static void google_chromeec_enable(struct device *dev) +{ +#if !DEVTREE_EARLY + dev->ops = &ec_chromeec_ops; +#endif + + google_ec_enable_extra(dev); +} + +struct chip_operations ec_google_chromeec_ops = { + CHIP_NAME("ChromeOS EC") + .enable_dev = google_chromeec_enable +}; diff --git a/src/ec/google/chromeec/ec.h b/src/ec/google/chromeec/ec.h index 8051486..adb961a 100644 --- a/src/ec/google/chromeec/ec.h +++ b/src/ec/google/chromeec/ec.h @@ -18,6 +18,7 @@ #ifndef _EC_GOOGLE_CHROMEEC_EC_H #define _EC_GOOGLE_CHROMEEC_EC_H #include <types.h> +#include <device/device.h> #include "ec_commands.h"
/* Fill in base and size of the IO port resources used. */ @@ -323,4 +324,10 @@ enum ec_pd_try_power_role_caps *try_power_role_cap, enum ec_pd_data_role_caps *data_role_cap, enum ec_pd_port_location *port_location); + +/** + * Allows bus-specific EC code to perform actions when the device is enabled. + */ +void google_ec_enable_extra(struct device *dev); + #endif /* _EC_GOOGLE_CHROMEEC_EC_H */ diff --git a/src/ec/google/chromeec/ec_lpc.c b/src/ec/google/chromeec/ec_lpc.c index 6bc4fbd..9afb1fd 100644 --- a/src/ec/google/chromeec/ec_lpc.c +++ b/src/ec/google/chromeec/ec_lpc.c @@ -458,16 +458,11 @@ { NULL, 0, 0, 0, } };
-static void enable_dev(struct device *dev) +void google_ec_enable_extra(struct device *dev) { pnp_enable_devices(dev, &ops, ARRAY_SIZE(pnp_dev_info), pnp_dev_info); }
-struct chip_operations ec_google_chromeec_ops = { - CHIP_NAME("Google Chrome EC") - .enable_dev = enable_dev, -}; - static int google_chromeec_data_ready(u16 port) { return google_chromeec_status_check(port, EC_LPC_CMDR_DATA,