drivers/intel/pmc_mux/con: Add new PMC MUX & CON chip drivers
The Tiger Lake PMC device has a MUX device which is expected to be
exposed in ACPI tables. The MUX device simply has a _HID and _DDN.
The CON devices link the USB-2 and USB-3 port numbers (from SoC
point of view) to the physical connector. They also have orientation
options for the sideband (SBU) and USB High Speed signals (HSL),
meaning that they can be fixed (i.e, another device besides the SoC
controls the orientation, and effectively the SoC is following only
CC1 or CC2 orientation), or they can follow the CC lines.
BUG=b:151646486
TEST=Tested with next patch in series (see TEST line there)
Change-Id: I8b5f275907601960410459aa669e257b80ff3dc2
Signed-off-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Signed-off-by: John Zhao <john.zhao@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/40862
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
diff --git a/src/drivers/intel/pmc_mux/con/Makefile.inc b/src/drivers/intel/pmc_mux/con/Makefile.inc
new file mode 100644
index 0000000..213e8fc
--- /dev/null
+++ b/src/drivers/intel/pmc_mux/con/Makefile.inc
@@ -0,0 +1 @@
+ramstage-$(CONFIG_DRIVERS_INTEL_PMC) += con.c
diff --git a/src/drivers/intel/pmc_mux/con/chip.h b/src/drivers/intel/pmc_mux/con/chip.h
new file mode 100644
index 0000000..02d018a
--- /dev/null
+++ b/src/drivers/intel/pmc_mux/con/chip.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __DRIVERS_INTEL_PMC_MUX_CON_H__
+#define __DRIVERS_INTEL_PMC_MUX_CON_H__
+
+enum typec_orientation {
+ /* The orientation of the signal follows the orientation of the CC lines. */
+ TYPEC_ORIENTATION_FOLLOW_CC = 0,
+ /* The orientation of the signal is fixed to follow CC1 */
+ TYPEC_ORIENTATION_NORMAL,
+ /* The orientation of the signal is fixed to follow CC2 */
+ TYPEC_ORIENTATION_REVERSE,
+};
+
+struct drivers_intel_pmc_mux_con_config {
+ /* 1-based port numbers (from SoC point of view) */
+ int usb2_port_number;
+ /* 1-based port numbers (from SoC point of view) */
+ int usb3_port_number;
+ /* Orientation of the sideband signals (SBU) */
+ enum typec_orientation sbu_orientation;
+ /* Orientation of the High Speed lines */
+ enum typec_orientation hsl_orientation;
+};
+
+#endif /* __DRIVERS_INTEL_PMC_MUX_CON_H__ */
diff --git a/src/drivers/intel/pmc_mux/con/con.c b/src/drivers/intel/pmc_mux/con/con.c
new file mode 100644
index 0000000..08c38e8
--- /dev/null
+++ b/src/drivers/intel/pmc_mux/con/con.c
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <acpi/acpigen.h>
+#include <console/console.h>
+#include <intelblocks/acpi.h>
+#include "chip.h"
+
+static const char *con_acpi_name(const struct device *dev)
+{
+ static char name[5];
+ snprintf(name, sizeof(name), "CON%1X", dev->path.generic.id);
+ return name;
+}
+
+static const char *orientation_to_str(enum typec_orientation ori)
+{
+ switch (ori) {
+ case TYPEC_ORIENTATION_NORMAL:
+ return "normal";
+ case TYPEC_ORIENTATION_REVERSE:
+ return "reverse";
+ case TYPEC_ORIENTATION_FOLLOW_CC: /* Intentional fallthrough */
+ default:
+ return "";
+ }
+}
+
+static void con_fill_ssdt(const struct device *dev)
+{
+ struct drivers_intel_pmc_mux_con_config *config = dev->chip_info;
+ struct acpi_dp *dsd;
+
+ if (!dev->enabled)
+ return;
+
+ /* Reference the existing scope and write CONx device */
+ acpigen_write_scope(acpi_device_scope(dev));
+ acpigen_write_device(acpi_device_name(dev));
+
+ acpigen_write_name_integer("_ADR", dev->path.generic.id);
+
+ /* _DSD, Device-Specific Data */
+ dsd = acpi_dp_new_table("_DSD");
+ acpi_dp_add_integer(dsd, "usb2-port-number", config->usb2_port_number);
+ acpi_dp_add_integer(dsd, "usb3-port-number", config->usb3_port_number);
+
+ /*
+ * The kernel assumes that these Type-C signals (SBUs and HSLs) follow the CC lines,
+ * unless they are explicitly called out otherwise.
+ */
+ if (config->sbu_orientation != TYPEC_ORIENTATION_FOLLOW_CC)
+ acpi_dp_add_string(dsd, "sbu-orientation",
+ orientation_to_str(config->sbu_orientation));
+
+ if (config->hsl_orientation != TYPEC_ORIENTATION_FOLLOW_CC)
+ acpi_dp_add_string(dsd, "hsl-orientation",
+ orientation_to_str(config->hsl_orientation));
+
+ acpi_dp_write(dsd);
+
+ acpigen_pop_len(); /* CONx Device */
+ acpigen_pop_len(); /* Scope */
+
+ printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), dev->chip_ops->name,
+ dev_path(dev));
+}
+
+static struct device_operations con_dev_ops = {
+ .read_resources = noop_read_resources,
+ .set_resources = noop_set_resources,
+ .acpi_name = con_acpi_name,
+ .acpi_fill_ssdt = con_fill_ssdt,
+};
+
+static void con_enable(struct device *dev)
+{
+ dev->ops = &con_dev_ops;
+}
+
+struct chip_operations drivers_intel_pmc_mux_con_ops = {
+ CHIP_NAME("Intel PMC MUX CON Driver")
+ .enable_dev = con_enable,
+};