diff --git a/src/ec/google/wilco/acpi/ec.asl b/src/ec/google/wilco/acpi/ec.asl index 675ee3778e..4fa887b1b4 100644 --- a/src/ec/google/wilco/acpi/ec.asl +++ b/src/ec/google/wilco/acpi/ec.asl @@ -57,6 +57,9 @@ Device (EC0) If (\DPTE == One) { W (DWST, Arg1) } + + /* Initialize UCSI */ + ^UCSI.INIT () } /* @@ -165,6 +168,7 @@ Device (EC0) #include "lid.asl" #include "platform.asl" #include "vbtn.asl" + #include "ucsi.asl" #ifdef EC_ENABLE_DPTF #include "dptf.asl" #endif diff --git a/src/ec/google/wilco/acpi/ec_ram.asl b/src/ec/google/wilco/acpi/ec_ram.asl index 0de39475bc..47e9072dcb 100644 --- a/src/ec/google/wilco/acpi/ec_ram.asl +++ b/src/ec/google/wilco/acpi/ec_ram.asl @@ -143,3 +143,54 @@ Name (DWHY, Package () { 0x37, 0xff, WR }) /* DPTF: Write Hysteresis */ Name (DWTQ, Package () { 0x38, 0xff, WR }) /* DPTF: Write Trip Query */ Name (CSOS, Package () { 0xb8, 0xff, WR }) /* OS support for S0ix */ Name (CSEX, Package () { 0xb9, 0xff, WR }) /* OS enter(1)/exit(0) S0ix */ + +/* + * EC UCSI + */ +Name (UVR0, Package () { 0x80, 0xff, RD }) /* UCSI Version */ +Name (UVR1, Package () { 0x81, 0xff, RD }) /* UCSI Version */ +Name (UCI0, Package () { 0x84, 0xff, RD }) /* UCSI Change Indicator */ +Name (UCI1, Package () { 0x85, 0xff, RD }) /* UCSI Change Indicator */ +Name (UCI2, Package () { 0x86, 0xff, RD }) /* UCSI Change Indicator */ +Name (UCI3, Package () { 0x87, 0xff, RD }) /* UCSI Change Indicator */ +Name (UCL0, Package () { 0x88, 0xff, WR }) /* UCSI Control */ +Name (UCL1, Package () { 0x89, 0xff, WR }) /* UCSI Control */ +Name (UCL2, Package () { 0x8a, 0xff, WR }) /* UCSI Control */ +Name (UCL3, Package () { 0x8b, 0xff, WR }) /* UCSI Control */ +Name (UCL4, Package () { 0x8c, 0xff, WR }) /* UCSI Control */ +Name (UCL5, Package () { 0x8d, 0xff, WR }) /* UCSI Control */ +Name (UCL6, Package () { 0x8e, 0xff, WR }) /* UCSI Control */ +Name (UCL7, Package () { 0x8f, 0xff, WR }) /* UCSI Control */ +Name (UMI0, Package () { 0x90, 0xff, RD }) /* UCSI Message In */ +Name (UMI1, Package () { 0x91, 0xff, RD }) /* UCSI Message In */ +Name (UMI2, Package () { 0x92, 0xff, RD }) /* UCSI Message In */ +Name (UMI3, Package () { 0x93, 0xff, RD }) /* UCSI Message In */ +Name (UMI4, Package () { 0x94, 0xff, RD }) /* UCSI Message In */ +Name (UMI5, Package () { 0x95, 0xff, RD }) /* UCSI Message In */ +Name (UMI6, Package () { 0x96, 0xff, RD }) /* UCSI Message In */ +Name (UMI7, Package () { 0x97, 0xff, RD }) /* UCSI Message In */ +Name (UMI8, Package () { 0x98, 0xff, RD }) /* UCSI Message In */ +Name (UMI9, Package () { 0x99, 0xff, RD }) /* UCSI Message In */ +Name (UMIA, Package () { 0x9a, 0xff, RD }) /* UCSI Message In */ +Name (UMIB, Package () { 0x9b, 0xff, RD }) /* UCSI Message In */ +Name (UMIC, Package () { 0x9c, 0xff, RD }) /* UCSI Message In */ +Name (UMID, Package () { 0x9d, 0xff, RD }) /* UCSI Message In */ +Name (UMIE, Package () { 0x9e, 0xff, RD }) /* UCSI Message In */ +Name (UMIF, Package () { 0x9f, 0xff, RD }) /* UCSI Message In */ +Name (UMO0, Package () { 0xa0, 0xff, WR }) /* UCSI Message Out */ +Name (UMO1, Package () { 0xa1, 0xff, WR }) /* UCSI Message Out */ +Name (UMO2, Package () { 0xa2, 0xff, WR }) /* UCSI Message Out */ +Name (UMO3, Package () { 0xa3, 0xff, WR }) /* UCSI Message Out */ +Name (UMO4, Package () { 0xa4, 0xff, WR }) /* UCSI Message Out */ +Name (UMO5, Package () { 0xa5, 0xff, WR }) /* UCSI Message Out */ +Name (UMO6, Package () { 0xa6, 0xff, WR }) /* UCSI Message Out */ +Name (UMO7, Package () { 0xa7, 0xff, WR }) /* UCSI Message Out */ +Name (UMO8, Package () { 0xa8, 0xff, WR }) /* UCSI Message Out */ +Name (UMO9, Package () { 0xa9, 0xff, WR }) /* UCSI Message Out */ +Name (UMOA, Package () { 0xaa, 0xff, WR }) /* UCSI Message Out */ +Name (UMOB, Package () { 0xab, 0xff, WR }) /* UCSI Message Out */ +Name (UMOC, Package () { 0xac, 0xff, WR }) /* UCSI Message Out */ +Name (UMOD, Package () { 0xad, 0xff, WR }) /* UCSI Message Out */ +Name (UMOE, Package () { 0xae, 0xff, WR }) /* UCSI Message Out */ +Name (UMOF, Package () { 0xaf, 0xff, WR }) /* UCSI Message Out */ +Name (UCTL, Package () { 0xb0, 0xff, WR }) /* UCSI Control Register */ diff --git a/src/ec/google/wilco/acpi/event.asl b/src/ec/google/wilco/acpi/event.asl index fab4fc46c3..f6534d3773 100644 --- a/src/ec/google/wilco/acpi/event.asl +++ b/src/ec/google/wilco/acpi/event.asl @@ -145,3 +145,10 @@ Method (_Q66, 0, Serialized) ECQ4 (Local0) } } + +/* UCSI SCI uses a unique event code */ +Method (_Q79, 0, Serialized) +{ + Printf ("EC _Q79 UCSI Event") + Notify (^UCSI, 0x80) +} diff --git a/src/ec/google/wilco/acpi/ucsi.asl b/src/ec/google/wilco/acpi/ucsi.asl new file mode 100644 index 0000000000..f69e5924e7 --- /dev/null +++ b/src/ec/google/wilco/acpi/ucsi.asl @@ -0,0 +1,157 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2019 Google LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +Device (UCSI) +{ + Name (_HID, "GOOG000E") + Name (_CID, EisaId ("PNP0CA0")) + Name (_DDN, "Wilco EC UCSI") + Name (_UID, One) + Name (_ADR, Zero) + Name (_STA, 0xf) + + /* Value written to EC control register to start UCSI command */ + Name (UCMD, 0xE0) + + /* Shared memory fields are defined in the SSDT */ + External (VER0, FieldUnitObj) + External (VER1, FieldUnitObj) + External (CCI0, FieldUnitObj) + External (CCI1, FieldUnitObj) + External (CCI2, FieldUnitObj) + External (CCI3, FieldUnitObj) + External (CTL0, FieldUnitObj) + External (CTL1, FieldUnitObj) + External (CTL2, FieldUnitObj) + External (CTL3, FieldUnitObj) + External (CTL4, FieldUnitObj) + External (CTL5, FieldUnitObj) + External (CTL6, FieldUnitObj) + External (CTL7, FieldUnitObj) + External (MGI0, FieldUnitObj) + External (MGI1, FieldUnitObj) + External (MGI2, FieldUnitObj) + External (MGI3, FieldUnitObj) + External (MGI4, FieldUnitObj) + External (MGI5, FieldUnitObj) + External (MGI6, FieldUnitObj) + External (MGI7, FieldUnitObj) + External (MGI8, FieldUnitObj) + External (MGI9, FieldUnitObj) + External (MGIA, FieldUnitObj) + External (MGIB, FieldUnitObj) + External (MGIC, FieldUnitObj) + External (MGID, FieldUnitObj) + External (MGIE, FieldUnitObj) + External (MGIF, FieldUnitObj) + External (MGO0, FieldUnitObj) + External (MGO1, FieldUnitObj) + External (MGO2, FieldUnitObj) + External (MGO3, FieldUnitObj) + External (MGO4, FieldUnitObj) + External (MGO5, FieldUnitObj) + External (MGO6, FieldUnitObj) + External (MGO7, FieldUnitObj) + External (MGO8, FieldUnitObj) + External (MGO9, FieldUnitObj) + External (MGOA, FieldUnitObj) + External (MGOB, FieldUnitObj) + External (MGOC, FieldUnitObj) + External (MGOD, FieldUnitObj) + External (MGOE, FieldUnitObj) + External (MGOF, FieldUnitObj) + + Method (INIT) + { + /* Read UCSI version from EC into shared memory */ + ^VER0 = R (^^UVR0) + ^VER1 = R (^^UVR1) + } + + Method (_DSM, 4, Serialized) + { + If (Arg0 != ToUUID ("6f8398c2-7ca4-11e4-ad36-631042b5008f")) { + Return (Buffer (One) { Zero }) + } + + Switch (ToInteger (Arg2)) + { + Case (Zero) + { + Return (Buffer (One) { 0x07 }) + } + Case (One) + { + /* Write Message Out */ + W (^^UMO0, ^MGO0) + W (^^UMO1, ^MGO1) + W (^^UMO2, ^MGO2) + W (^^UMO3, ^MGO3) + W (^^UMO4, ^MGO4) + W (^^UMO5, ^MGO5) + W (^^UMO6, ^MGO6) + W (^^UMO7, ^MGO7) + W (^^UMO8, ^MGO8) + W (^^UMO9, ^MGO9) + W (^^UMOA, ^MGOA) + W (^^UMOB, ^MGOB) + W (^^UMOC, ^MGOC) + W (^^UMOD, ^MGOD) + W (^^UMOE, ^MGOE) + W (^^UMOF, ^MGOF) + + /* Write Control */ + W (^^UCL0, ^CTL0) + W (^^UCL1, ^CTL1) + W (^^UCL2, ^CTL2) + W (^^UCL3, ^CTL3) + W (^^UCL4, ^CTL4) + W (^^UCL5, ^CTL5) + W (^^UCL6, ^CTL6) + W (^^UCL7, ^CTL7) + + /* Start EC Command */ + W (^^UCTL, ^UCMD) + } + Case (2) + { + /* Read Message In */ + ^MGI0 = R (^^UMI0) + ^MGI1 = R (^^UMI1) + ^MGI2 = R (^^UMI2) + ^MGI3 = R (^^UMI3) + ^MGI4 = R (^^UMI4) + ^MGI5 = R (^^UMI5) + ^MGI6 = R (^^UMI6) + ^MGI7 = R (^^UMI7) + ^MGI8 = R (^^UMI8) + ^MGI9 = R (^^UMI9) + ^MGIA = R (^^UMIA) + ^MGIB = R (^^UMIB) + ^MGIC = R (^^UMIC) + ^MGID = R (^^UMID) + ^MGIE = R (^^UMIE) + ^MGIF = R (^^UMIF) + + /* Read Status */ + ^CCI0 = R (^^UCI0) + ^CCI1 = R (^^UCI1) + ^CCI2 = R (^^UCI2) + ^CCI3 = R (^^UCI3) + } + } + Return (Buffer (One) { Zero }) + } +} diff --git a/src/ec/google/wilco/chip.c b/src/ec/google/wilco/chip.c index 9b0be19f9a..09211f82ab 100644 --- a/src/ec/google/wilco/chip.c +++ b/src/ec/google/wilco/chip.c @@ -14,7 +14,10 @@ */ #include +#include +#include #include +#include #include #include #include @@ -25,6 +28,64 @@ #include "ec.h" #include "chip.h" +/* + * The UCSI fields are defined in the UCSI specification at + * https://www.intel.com/content/www/us/en/io/universal-serial-bus/usb-type-c-ucsi-spec.html + * https://www.intel.com/content/www/us/en/io/universal-serial-bus/bios-implementation-of-ucsi.html + */ + +static struct fieldlist ucsi_region_fields[] = { + FIELDLIST_NAMESTR("VER0", 8), + FIELDLIST_NAMESTR("VER1", 8), + FIELDLIST_NAMESTR("RSV0", 8), + FIELDLIST_NAMESTR("RSV1", 8), + FIELDLIST_NAMESTR("CCI0", 8), + FIELDLIST_NAMESTR("CCI1", 8), + FIELDLIST_NAMESTR("CCI2", 8), + FIELDLIST_NAMESTR("CCI3", 8), + FIELDLIST_NAMESTR("CTL0", 8), + FIELDLIST_NAMESTR("CTL1", 8), + FIELDLIST_NAMESTR("CTL2", 8), + FIELDLIST_NAMESTR("CTL3", 8), + FIELDLIST_NAMESTR("CTL4", 8), + FIELDLIST_NAMESTR("CTL5", 8), + FIELDLIST_NAMESTR("CTL6", 8), + FIELDLIST_NAMESTR("CTL7", 8), + FIELDLIST_NAMESTR("MGI0", 8), + FIELDLIST_NAMESTR("MGI1", 8), + FIELDLIST_NAMESTR("MGI2", 8), + FIELDLIST_NAMESTR("MGI3", 8), + FIELDLIST_NAMESTR("MGI4", 8), + FIELDLIST_NAMESTR("MGI5", 8), + FIELDLIST_NAMESTR("MGI6", 8), + FIELDLIST_NAMESTR("MGI7", 8), + FIELDLIST_NAMESTR("MGI8", 8), + FIELDLIST_NAMESTR("MGI9", 8), + FIELDLIST_NAMESTR("MGIA", 8), + FIELDLIST_NAMESTR("MGIB", 8), + FIELDLIST_NAMESTR("MGIC", 8), + FIELDLIST_NAMESTR("MGID", 8), + FIELDLIST_NAMESTR("MGIE", 8), + FIELDLIST_NAMESTR("MGIF", 8), + FIELDLIST_NAMESTR("MGO0", 8), + FIELDLIST_NAMESTR("MGO1", 8), + FIELDLIST_NAMESTR("MGO2", 8), + FIELDLIST_NAMESTR("MGO3", 8), + FIELDLIST_NAMESTR("MGO4", 8), + FIELDLIST_NAMESTR("MGO5", 8), + FIELDLIST_NAMESTR("MGO6", 8), + FIELDLIST_NAMESTR("MGO7", 8), + FIELDLIST_NAMESTR("MGO8", 8), + FIELDLIST_NAMESTR("MGO9", 8), + FIELDLIST_NAMESTR("MGOA", 8), + FIELDLIST_NAMESTR("MGOB", 8), + FIELDLIST_NAMESTR("MGOC", 8), + FIELDLIST_NAMESTR("MGOD", 8), + FIELDLIST_NAMESTR("MGOE", 8), + FIELDLIST_NAMESTR("MGOF", 8), +}; +static const size_t ucsi_region_len = ARRAY_SIZE(ucsi_region_fields); + static void wilco_ec_post_complete(void *unused) { wilco_ec_send(KB_BIOS_PROGRESS, BIOS_PROGRESS_POST_COMPLETE); @@ -111,11 +172,47 @@ static void wilco_ec_read_resources(struct device *dev) wilco_ec_resource(dev, 2, CONFIG_EC_BASE_PACKET, 16); } +static void wilco_ec_fill_ssdt_generator(struct device *dev) +{ + struct opregion opreg; + void *region_ptr; + + if (!dev->enabled) + return; + + region_ptr = cbmem_add(CBMEM_ID_ACPI_UCSI, ucsi_region_len); + if (!region_ptr) + return; + memset(region_ptr, 0, ucsi_region_len); + + opreg.name = "UCSM"; + opreg.regionspace = SYSTEMMEMORY; + opreg.regionoffset = (uintptr_t)region_ptr; + opreg.regionlen = ucsi_region_len; + + acpigen_write_scope(acpi_device_path_join(dev, "UCSI")); + acpigen_write_name("_CRS"); + acpigen_write_resourcetemplate_header(); + acpigen_write_mem32fixed(1, (uintptr_t)region_ptr, ucsi_region_len); + acpigen_write_resourcetemplate_footer(); + acpigen_write_opregion(&opreg); + acpigen_write_field(opreg.name, ucsi_region_fields, ucsi_region_len, + FIELD_ANYACC | FIELD_LOCK | FIELD_PRESERVE); + acpigen_pop_len(); /* Scope */ +} + +static const char *wilco_ec_acpi_name(const struct device *dev) +{ + return "EC0"; +} + static struct device_operations ops = { - .init = wilco_ec_init, - .read_resources = wilco_ec_read_resources, - .enable_resources = DEVICE_NOOP, - .set_resources = DEVICE_NOOP, + .init = wilco_ec_init, + .read_resources = wilco_ec_read_resources, + .enable_resources = DEVICE_NOOP, + .set_resources = DEVICE_NOOP, + .acpi_fill_ssdt_generator = wilco_ec_fill_ssdt_generator, + .acpi_name = wilco_ec_acpi_name, }; static struct pnp_info info[] = {