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 +#include +#include +#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 +#include +#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, +};