summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/intel/pmc_mux/Kconfig7
-rw-r--r--src/drivers/intel/pmc_mux/Makefile.inc2
-rw-r--r--src/drivers/intel/pmc_mux/chip.h9
-rw-r--r--src/drivers/intel/pmc_mux/con/Makefile.inc1
-rw-r--r--src/drivers/intel/pmc_mux/con/chip.h26
-rw-r--r--src/drivers/intel/pmc_mux/con/con.c83
-rw-r--r--src/drivers/intel/pmc_mux/mux.c42
7 files changed, 170 insertions, 0 deletions
diff --git a/src/drivers/intel/pmc_mux/Kconfig b/src/drivers/intel/pmc_mux/Kconfig
new file mode 100644
index 0000000000..24eb1a19d3
--- /dev/null
+++ b/src/drivers/intel/pmc_mux/Kconfig
@@ -0,0 +1,7 @@
+config DRIVERS_INTEL_PMC
+ bool
+ default n
+ depends on HAVE_ACPI_TABLES
+ help
+ When enabled, driver/intel/pmc_mux will add support for mux
+ configuration of USB Type-C ports via the SoC's muxes.
diff --git a/src/drivers/intel/pmc_mux/Makefile.inc b/src/drivers/intel/pmc_mux/Makefile.inc
new file mode 100644
index 0000000000..f27f01444b
--- /dev/null
+++ b/src/drivers/intel/pmc_mux/Makefile.inc
@@ -0,0 +1,2 @@
+subdirs-y += con
+ramstage-$(CONFIG_DRIVERS_INTEL_PMC) += mux.c
diff --git a/src/drivers/intel/pmc_mux/chip.h b/src/drivers/intel/pmc_mux/chip.h
new file mode 100644
index 0000000000..dcca2a3ecc
--- /dev/null
+++ b/src/drivers/intel/pmc_mux/chip.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef __DRIVERS_INTEL_PMC_MUX_H__
+#define __DRIVERS_INTEL_PMC_MUX_H__
+
+struct drivers_intel_pmc_mux_config {
+};
+
+#endif /* __DRIVERS_INTEL_PMC_MUX_H__ */
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 0000000000..213e8fc7ec
--- /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 0000000000..02d018a2e9
--- /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 0000000000..08c38e8875
--- /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,
+};
diff --git a/src/drivers/intel/pmc_mux/mux.c b/src/drivers/intel/pmc_mux/mux.c
new file mode 100644
index 0000000000..29ed1a9603
--- /dev/null
+++ b/src/drivers/intel/pmc_mux/mux.c
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <acpi/acpigen.h>
+#include <device/device.h>
+#include "chip.h"
+
+#define TGL_PMC_MUX_HID "INTC105C"
+
+static const char *mux_acpi_name(const struct device *dev)
+{
+ return "MUX";
+}
+
+static void mux_fill_ssdt(const struct device *dev)
+{
+ acpigen_write_scope(acpi_device_scope(dev));
+ acpigen_write_device(acpi_device_name(dev));
+
+ acpigen_write_name_string("_HID", TGL_PMC_MUX_HID);
+ acpigen_write_name_string("_DDN", dev->chip_ops->name);
+
+ acpigen_pop_len(); /* Device */
+ acpigen_pop_len(); /* Scope */
+}
+
+static struct device_operations mux_dev_ops = {
+ .read_resources = noop_read_resources,
+ .set_resources = noop_set_resources,
+ .acpi_name = mux_acpi_name,
+ .acpi_fill_ssdt = mux_fill_ssdt,
+ .scan_bus = scan_static_bus,
+};
+
+static void mux_enable(struct device *dev)
+{
+ dev->ops = &mux_dev_ops;
+}
+
+struct chip_operations drivers_intel_pmc_mux_ops = {
+ CHIP_NAME("Intel PMC MUX Driver")
+ .enable_dev = mux_enable,
+};