blob: caff166392db51de46154cc022bc965c84d63a0a [file] [log] [blame]
Tim Wawrzynczake184e392020-05-14 10:23:19 -06001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <acpi/acpigen.h>
Nick Vaccaro15066ba2021-10-01 13:15:26 -07004#include <boot/coreboot_tables.h>
Nick Vaccarod4c55352021-10-01 16:17:42 -07005#include <cbmem.h>
Tim Wawrzynczake184e392020-05-14 10:23:19 -06006#include <console/console.h>
7#include <intelblocks/acpi.h>
Nick Vaccaro15066ba2021-10-01 13:15:26 -07008
Tim Wawrzynczake184e392020-05-14 10:23:19 -06009#include "chip.h"
10
Nick Vaccarod4c55352021-10-01 16:17:42 -070011/* Number of registered connectors */
12static size_t total_conn_count;
13
14static void conn_init(struct device *dev)
15{
16 total_conn_count++;
17}
18
19static struct type_c_info *conn_get_cbmem_buffer(void)
20{
21 struct type_c_info *info;
22 size_t size;
23
24 info = cbmem_find(CBMEM_ID_TYPE_C_INFO);
25 if (info)
26 return info;
27
28 size = sizeof(struct type_c_info) + total_conn_count * sizeof(struct type_c_port_info);
29 info = cbmem_add(CBMEM_ID_TYPE_C_INFO, size);
30
31 if (!info)
32 return NULL;
33
34 memset(info, 0, size);
35 return info;
36}
37
38static void conn_write_cbmem_entry(struct device *dev)
39{
40 const struct drivers_intel_pmc_mux_conn_config *config = dev->chip_info;
41 struct type_c_port_info *port_info;
42 struct type_c_info *info;
43 size_t count;
44
45 /*
46 * Do not re-run this code on resume as the cbmem data is populated on boot-up
47 * (non-S3 path) and stays intact across S3 suspend/resume.
48 */
49 if (acpi_is_wakeup_s3())
50 return;
51
52 info = conn_get_cbmem_buffer();
53 if (!info || (info->port_count >= total_conn_count)) {
54 printk(BIOS_ERR, "ERROR: No space for Type-C port info!\n");
55 return;
56 }
57
58 count = info->port_count;
59 port_info = &info->port_info[count];
60 port_info->usb2_port_number = config->usb2_port_number;
61 port_info->usb3_port_number = config->usb3_port_number;
62 port_info->sbu_orientation = config->sbu_orientation;
63 port_info->data_orientation = config->hsl_orientation;
64
65 printk(BIOS_INFO, "added type-c port%ld info to cbmem: usb2:%d usb3:%d sbu:%d data:%d\n",
66 count, port_info->usb2_port_number, port_info->usb3_port_number,
67 port_info->sbu_orientation, port_info->data_orientation);
68
69 info->port_count++;
70}
71
Tim Wawrzynczake414ce42020-07-03 09:36:11 -060072static const char *conn_acpi_name(const struct device *dev)
Tim Wawrzynczake184e392020-05-14 10:23:19 -060073{
74 static char name[5];
75 snprintf(name, sizeof(name), "CON%1X", dev->path.generic.id);
76 return name;
77}
78
Nick Vaccaro15066ba2021-10-01 13:15:26 -070079static const char *orientation_to_str(enum type_c_orientation ori)
Tim Wawrzynczake184e392020-05-14 10:23:19 -060080{
81 switch (ori) {
82 case TYPEC_ORIENTATION_NORMAL:
83 return "normal";
84 case TYPEC_ORIENTATION_REVERSE:
85 return "reverse";
Nick Vaccaro15066ba2021-10-01 13:15:26 -070086 case TYPEC_ORIENTATION_NONE: /* Intentional fallthrough */
Tim Wawrzynczake184e392020-05-14 10:23:19 -060087 default:
88 return "";
89 }
90}
91
Tim Wawrzynczake414ce42020-07-03 09:36:11 -060092static void conn_fill_ssdt(const struct device *dev)
Tim Wawrzynczake184e392020-05-14 10:23:19 -060093{
Tim Wawrzynczake414ce42020-07-03 09:36:11 -060094 struct drivers_intel_pmc_mux_conn_config *config = dev->chip_info;
Tim Wawrzynczake184e392020-05-14 10:23:19 -060095 struct acpi_dp *dsd;
John Zhaoff4ead02020-06-26 08:53:54 -070096 const char *scope;
97 const char *name;
Tim Wawrzynczake184e392020-05-14 10:23:19 -060098
Tim Wawrzynczake184e392020-05-14 10:23:19 -060099 /* Reference the existing scope and write CONx device */
John Zhaoff4ead02020-06-26 08:53:54 -0700100 scope = acpi_device_scope(dev);
101 name = acpi_device_name(dev);
102 if (!scope || !name)
103 return;
104
105 acpigen_write_scope(scope);
106 acpigen_write_device(name);
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600107
108 acpigen_write_name_integer("_ADR", dev->path.generic.id);
109
110 /* _DSD, Device-Specific Data */
111 dsd = acpi_dp_new_table("_DSD");
112 acpi_dp_add_integer(dsd, "usb2-port-number", config->usb2_port_number);
113 acpi_dp_add_integer(dsd, "usb3-port-number", config->usb3_port_number);
114
115 /*
116 * The kernel assumes that these Type-C signals (SBUs and HSLs) follow the CC lines,
117 * unless they are explicitly called out otherwise.
118 */
Nick Vaccaro15066ba2021-10-01 13:15:26 -0700119 if (config->sbu_orientation != TYPEC_ORIENTATION_NONE)
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600120 acpi_dp_add_string(dsd, "sbu-orientation",
121 orientation_to_str(config->sbu_orientation));
122
Nick Vaccaro15066ba2021-10-01 13:15:26 -0700123 if (config->hsl_orientation != TYPEC_ORIENTATION_NONE)
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600124 acpi_dp_add_string(dsd, "hsl-orientation",
125 orientation_to_str(config->hsl_orientation));
126
127 acpi_dp_write(dsd);
128
129 acpigen_pop_len(); /* CONx Device */
130 acpigen_pop_len(); /* Scope */
131
132 printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), dev->chip_ops->name,
133 dev_path(dev));
134}
135
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600136static struct device_operations conn_dev_ops = {
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600137 .read_resources = noop_read_resources,
138 .set_resources = noop_set_resources,
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600139 .acpi_name = conn_acpi_name,
140 .acpi_fill_ssdt = conn_fill_ssdt,
Nick Vaccarod4c55352021-10-01 16:17:42 -0700141 .init = conn_init,
142 .final = conn_write_cbmem_entry,
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600143};
144
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600145static void conn_enable(struct device *dev)
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600146{
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600147 dev->ops = &conn_dev_ops;
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600148}
149
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600150struct chip_operations drivers_intel_pmc_mux_conn_ops = {
151 CHIP_NAME("Intel PMC MUX CONN Driver")
152 .enable_dev = conn_enable,
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600153};
Deepti Deshattyc146daf2021-05-20 21:01:52 +0530154
155bool intel_pmc_mux_conn_get_ports(const struct device *conn, unsigned int *usb2_port,
156 unsigned int *usb3_port)
157{
158 const struct drivers_intel_pmc_mux_conn_config *mux_config;
159
160 if (!conn->chip_info || conn->chip_ops != &drivers_intel_pmc_mux_conn_ops)
161 return false;
162
163 mux_config = conn->chip_info;
164 *usb2_port = mux_config->usb2_port_number;
165 *usb3_port = mux_config->usb3_port_number;
166
167 return true;
168};