blob: c2c719991be86922a438df97f3da5eabf680fe58 [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
Reka Normand448f8c2021-12-09 12:09:27 +110019static unsigned int get_usb_port_number(const struct device *usb_port)
20{
21 return usb_port->path.usb.port_id + 1;
22}
23
Nick Vaccarod4c55352021-10-01 16:17:42 -070024static struct type_c_info *conn_get_cbmem_buffer(void)
25{
26 struct type_c_info *info;
27 size_t size;
28
29 info = cbmem_find(CBMEM_ID_TYPE_C_INFO);
30 if (info)
31 return info;
32
33 size = sizeof(struct type_c_info) + total_conn_count * sizeof(struct type_c_port_info);
34 info = cbmem_add(CBMEM_ID_TYPE_C_INFO, size);
35
36 if (!info)
37 return NULL;
38
39 memset(info, 0, size);
40 return info;
41}
42
43static void conn_write_cbmem_entry(struct device *dev)
44{
45 const struct drivers_intel_pmc_mux_conn_config *config = dev->chip_info;
46 struct type_c_port_info *port_info;
47 struct type_c_info *info;
48 size_t count;
49
50 /*
51 * Do not re-run this code on resume as the cbmem data is populated on boot-up
52 * (non-S3 path) and stays intact across S3 suspend/resume.
53 */
54 if (acpi_is_wakeup_s3())
55 return;
56
57 info = conn_get_cbmem_buffer();
58 if (!info || (info->port_count >= total_conn_count)) {
Julius Wernere9665952022-01-21 17:06:20 -080059 printk(BIOS_ERR, "No space for Type-C port info!\n");
Nick Vaccarod4c55352021-10-01 16:17:42 -070060 return;
61 }
62
63 count = info->port_count;
64 port_info = &info->port_info[count];
Reka Normand448f8c2021-12-09 12:09:27 +110065 port_info->usb2_port_number = get_usb_port_number(config->usb2_port);
66 port_info->usb3_port_number = get_usb_port_number(config->usb3_port);
Nick Vaccarod4c55352021-10-01 16:17:42 -070067 port_info->sbu_orientation = config->sbu_orientation;
68 port_info->data_orientation = config->hsl_orientation;
69
Arthur Heymans141163d2022-02-18 13:23:35 +010070 printk(BIOS_INFO, "added type-c port%zu info to cbmem: usb2:%d usb3:%d sbu:%d data:%d\n",
Nick Vaccarod4c55352021-10-01 16:17:42 -070071 count, port_info->usb2_port_number, port_info->usb3_port_number,
72 port_info->sbu_orientation, port_info->data_orientation);
73
74 info->port_count++;
75}
76
Tim Wawrzynczake414ce42020-07-03 09:36:11 -060077static const char *conn_acpi_name(const struct device *dev)
Tim Wawrzynczake184e392020-05-14 10:23:19 -060078{
79 static char name[5];
80 snprintf(name, sizeof(name), "CON%1X", dev->path.generic.id);
81 return name;
82}
83
Nick Vaccaro15066ba2021-10-01 13:15:26 -070084static const char *orientation_to_str(enum type_c_orientation ori)
Tim Wawrzynczake184e392020-05-14 10:23:19 -060085{
86 switch (ori) {
87 case TYPEC_ORIENTATION_NORMAL:
88 return "normal";
89 case TYPEC_ORIENTATION_REVERSE:
90 return "reverse";
Nick Vaccaro15066ba2021-10-01 13:15:26 -070091 case TYPEC_ORIENTATION_NONE: /* Intentional fallthrough */
Tim Wawrzynczake184e392020-05-14 10:23:19 -060092 default:
93 return "";
94 }
95}
96
Tim Wawrzynczake414ce42020-07-03 09:36:11 -060097static void conn_fill_ssdt(const struct device *dev)
Tim Wawrzynczake184e392020-05-14 10:23:19 -060098{
Tim Wawrzynczake414ce42020-07-03 09:36:11 -060099 struct drivers_intel_pmc_mux_conn_config *config = dev->chip_info;
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600100 struct acpi_dp *dsd;
John Zhaoff4ead02020-06-26 08:53:54 -0700101 const char *scope;
102 const char *name;
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600103
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600104 /* Reference the existing scope and write CONx device */
John Zhaoff4ead02020-06-26 08:53:54 -0700105 scope = acpi_device_scope(dev);
106 name = acpi_device_name(dev);
107 if (!scope || !name)
108 return;
109
110 acpigen_write_scope(scope);
111 acpigen_write_device(name);
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600112
113 acpigen_write_name_integer("_ADR", dev->path.generic.id);
114
115 /* _DSD, Device-Specific Data */
116 dsd = acpi_dp_new_table("_DSD");
Reka Normand448f8c2021-12-09 12:09:27 +1100117 acpi_dp_add_integer(dsd, "usb2-port-number", get_usb_port_number(config->usb2_port));
118 acpi_dp_add_integer(dsd, "usb3-port-number", get_usb_port_number(config->usb3_port));
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600119
120 /*
121 * The kernel assumes that these Type-C signals (SBUs and HSLs) follow the CC lines,
122 * unless they are explicitly called out otherwise.
123 */
Nick Vaccaro15066ba2021-10-01 13:15:26 -0700124 if (config->sbu_orientation != TYPEC_ORIENTATION_NONE)
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600125 acpi_dp_add_string(dsd, "sbu-orientation",
126 orientation_to_str(config->sbu_orientation));
127
Nick Vaccaro15066ba2021-10-01 13:15:26 -0700128 if (config->hsl_orientation != TYPEC_ORIENTATION_NONE)
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600129 acpi_dp_add_string(dsd, "hsl-orientation",
130 orientation_to_str(config->hsl_orientation));
131
132 acpi_dp_write(dsd);
133
134 acpigen_pop_len(); /* CONx Device */
135 acpigen_pop_len(); /* Scope */
136
137 printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), dev->chip_ops->name,
138 dev_path(dev));
139}
140
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600141static struct device_operations conn_dev_ops = {
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600142 .read_resources = noop_read_resources,
143 .set_resources = noop_set_resources,
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600144 .acpi_name = conn_acpi_name,
145 .acpi_fill_ssdt = conn_fill_ssdt,
Nick Vaccarod4c55352021-10-01 16:17:42 -0700146 .init = conn_init,
147 .final = conn_write_cbmem_entry,
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600148};
149
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600150static void conn_enable(struct device *dev)
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600151{
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600152 dev->ops = &conn_dev_ops;
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600153}
154
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600155struct chip_operations drivers_intel_pmc_mux_conn_ops = {
Nicholas Sudsgaardbfb11be2024-01-30 09:53:46 +0900156 .name = "Intel PMC MUX CONN Driver",
Tim Wawrzynczake414ce42020-07-03 09:36:11 -0600157 .enable_dev = conn_enable,
Tim Wawrzynczake184e392020-05-14 10:23:19 -0600158};
Deepti Deshattyc146daf2021-05-20 21:01:52 +0530159
160bool intel_pmc_mux_conn_get_ports(const struct device *conn, unsigned int *usb2_port,
161 unsigned int *usb3_port)
162{
163 const struct drivers_intel_pmc_mux_conn_config *mux_config;
164
165 if (!conn->chip_info || conn->chip_ops != &drivers_intel_pmc_mux_conn_ops)
166 return false;
167
168 mux_config = conn->chip_info;
Reka Normand448f8c2021-12-09 12:09:27 +1100169 *usb2_port = get_usb_port_number(mux_config->usb2_port);
170 *usb3_port = get_usb_port_number(mux_config->usb3_port);
Deepti Deshattyc146daf2021-05-20 21:01:52 +0530171
172 return true;
173};