1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #define __SIMPLE_DEVICE__
6 #include <console/console.h>
7 #include <device/pci.h>
8 #include <intelblocks/p2sb.h>
9 #include <intelblocks/pcr.h>
10 #include <intelblocks/pmc_ipc.h>
11 #include <intelblocks/systemagent.h>
12 #include <intelblocks/tcss.h>
15 #include <security/vboot/vboot_common.h>
16 #include <soc/pci_devs.h>
17 #include <soc/pcr_ids.h>
19 #include <drivers/intel/pmc_mux/conn/chip.h>
21 #define WAIT_FOR_DISPLAYPORT_TIMEOUT_MS 1000
22 #define WAIT_FOR_DP_MODE_ENTRY_TIMEOUT_MS 1500
23 #define WAIT_FOR_HPD_TIMEOUT_MS 3000
25 static uint32_t tcss_make_conn_cmd(int u
, int u3
, int u2
, int ufp
, int hsl
,
28 return TCSS_CD_FIELD(USAGE
, u
) |
29 TCSS_CD_FIELD(USB3
, u3
) |
30 TCSS_CD_FIELD(USB2
, u2
) |
31 TCSS_CD_FIELD(UFP
, ufp
) |
32 TCSS_CD_FIELD(HSL
, hsl
) |
33 TCSS_CD_FIELD(SBU
, sbu
) |
34 TCSS_CD_FIELD(ACC
, acc
);
37 static uint32_t tcss_make_alt_mode_cmd_buf_0(int u
, int u3
, int m
)
39 return TCSS_ALT_FIELD(USAGE
, u
) |
40 TCSS_ALT_FIELD(USB3
, u3
) |
41 TCSS_ALT_FIELD(MODE
, m
);
44 static uint32_t tcss_make_alt_mode_cmd_buf_1(int p
, int c
, int ufp
, int dp
)
46 return TCSS_ALT_FIELD(POLARITY
, p
) |
47 TCSS_ALT_FIELD(CABLE
, c
) |
48 TCSS_ALT_FIELD(UFP
, ufp
) |
49 TCSS_ALT_FIELD(DP_MODE
, dp
);
52 static uint32_t tcss_make_safe_mode_cmd(int u
, int u3
)
54 return TCSS_CD_FIELD(USAGE
, u
) |
55 TCSS_CD_FIELD(USB3
, u3
);
59 static uint32_t tcss_make_hpd_mode_cmd(int u
, int u3
, int hpd_lvl
, int hpd_irq
)
61 return TCSS_HPD_FIELD(USAGE
, u
) |
62 TCSS_HPD_FIELD(USB3
, u3
) |
63 TCSS_HPD_FIELD(LVL
, hpd_lvl
) |
64 TCSS_HPD_FIELD(IRQ
, hpd_irq
);
67 static int send_pmc_req(int cmd_type
, const struct pmc_ipc_buffer
*req
,
68 struct pmc_ipc_buffer
*res
, uint32_t size
)
75 cmd_reg
= pmc_make_ipc_cmd(PMC_IPC_USBC_CMD_ID
, PMC_IPC_USBC_SUBCMD_ID
,
78 printk(BIOS_DEBUG
, "Raw Buffer output 0 %08" PRIx32
"\n", req
->buf
[0]);
79 printk(BIOS_DEBUG
, "Raw Buffer output 1 %08" PRIx32
"\n", req
->buf
[1]);
82 r
= pmc_send_ipc_cmd(cmd_reg
, req
, res
);
84 printk(BIOS_ERR
, "pmc_send_ipc_cmd failed\n");
88 res_reg
= res
->buf
[0];
89 if (cmd_type
== CONNECT_REQ
) {
90 if (!TCSS_CONN_STATUS_HAS_FAILED(res_reg
)) {
91 printk(BIOS_DEBUG
, "pmc_send_ipc_cmd succeeded\n");
95 if (TCSS_CONN_STATUS_IS_FATAL(res_reg
)) {
96 printk(BIOS_ERR
, "pmc_send_ipc_cmd status: fatal\n");
100 if (!TCSS_STATUS_HAS_FAILED(res_reg
)) {
101 printk(BIOS_DEBUG
, "pmc_send_ipc_cmd succeeded\n");
105 if (TCSS_STATUS_IS_FATAL(res_reg
)) {
106 printk(BIOS_ERR
, "pmc_send_ipc_cmd status: fatal\n");
110 } while (--tries
>= 0);
112 printk(BIOS_ERR
, "pmc_send_ipc_cmd failed after retries\n");
116 static int send_pmc_disconnect_request(int port
, const struct tcss_port_map
*port_map
)
119 struct pmc_ipc_buffer req
= { 0 };
120 struct pmc_ipc_buffer rsp
;
122 cmd
= tcss_make_conn_cmd(PMC_IPC_TCSS_DISC_REQ_RES
, port_map
->usb3_port
,
123 port_map
->usb2_port
, 0, 0, 0, 0);
127 printk(BIOS_DEBUG
, "port C%d DISC req: usage %d usb3 %d usb2 %d\n",
129 GET_TCSS_CD_FIELD(USAGE
, cmd
),
130 GET_TCSS_CD_FIELD(USB3
, cmd
),
131 GET_TCSS_CD_FIELD(USB2
, cmd
));
133 return send_pmc_req(CONNECT_REQ
, &req
, &rsp
, PMC_IPC_DISC_REQ_SIZE
);
136 static int send_pmc_connect_request(int port
, const struct usbc_mux_info
*mux_data
,
137 const struct tcss_port_map
*port_map
)
140 struct pmc_ipc_buffer req
= { 0 };
141 struct pmc_ipc_buffer rsp
;
143 cmd
= tcss_make_conn_cmd(
144 PMC_IPC_TCSS_CONN_REQ_RES
,
154 printk(BIOS_DEBUG
, "port C%d CONN req: usage %d usb3 %d usb2 %d "
155 "ufp %d ori_hsl %d ori_sbu %d dbg_acc %d\n",
157 GET_TCSS_CD_FIELD(USAGE
, cmd
),
158 GET_TCSS_CD_FIELD(USB3
, cmd
),
159 GET_TCSS_CD_FIELD(USB2
, cmd
),
160 GET_TCSS_CD_FIELD(UFP
, cmd
),
161 GET_TCSS_CD_FIELD(HSL
, cmd
),
162 GET_TCSS_CD_FIELD(SBU
, cmd
),
163 GET_TCSS_CD_FIELD(ACC
, cmd
));
165 return send_pmc_req(CONNECT_REQ
, &req
, &rsp
, PMC_IPC_CONN_REQ_SIZE
);
168 static int send_pmc_safe_mode_request(int port
, const struct usbc_mux_info
*mux_data
,
169 const struct tcss_port_map
*port_map
)
172 struct pmc_ipc_buffer req
= { 0 };
173 struct pmc_ipc_buffer rsp
;
175 cmd
= tcss_make_safe_mode_cmd(PMC_IPC_TCSS_SAFE_MODE_REQ_RES
, port_map
->usb3_port
);
179 printk(BIOS_DEBUG
, "port C%d SAFE req: usage %d usb3 %d\n",
181 GET_TCSS_CD_FIELD(USAGE
, cmd
),
182 GET_TCSS_CD_FIELD(USB3
, cmd
));
184 return send_pmc_req(SAFE_REQ
, &req
, &rsp
, PMC_IPC_SAFE_REQ_SIZE
);
187 static int send_pmc_dp_hpd_request(int port
, const struct usbc_mux_info
*mux_data
,
188 const struct tcss_port_map
*port_map
)
190 struct pmc_ipc_buffer req
= { 0 };
191 struct pmc_ipc_buffer rsp
;
194 cmd
= tcss_make_hpd_mode_cmd(
195 PMC_IPC_TCSS_HPD_REQ_RES
,
202 return send_pmc_req(HPD_REQ
, &req
, &rsp
, PMC_IPC_HPD_REQ_SIZE
);
205 static uint8_t get_dp_mode(uint8_t dp_pin_mode
)
207 switch (dp_pin_mode
) {
214 return log2(dp_pin_mode
) + 1;
220 static int send_pmc_dp_mode_request(int port
, const struct usbc_mux_info
*mux_data
,
221 const struct tcss_port_map
*port_map
)
227 struct pmc_ipc_buffer req
= { 0 };
228 struct pmc_ipc_buffer rsp
;
230 cmd
= tcss_make_alt_mode_cmd_buf_0(
231 PMC_IPC_TCSS_ALTMODE_REQ_RES
,
237 printk(BIOS_DEBUG
, "port C%d ALT_1 req: usage %d usb3 %d dp_mode %d\n",
239 GET_TCSS_ALT_FIELD(USAGE
, cmd
),
240 GET_TCSS_ALT_FIELD(USB3
, cmd
),
241 GET_TCSS_ALT_FIELD(MODE
, cmd
));
243 dp_mode
= get_dp_mode(mux_data
->dp_pin_mode
);
244 cmd
= tcss_make_alt_mode_cmd_buf_1(
247 0, /* ufp is not supported in DP ALT Mode request */
250 printk(BIOS_DEBUG
, "port C%d ALT_2 req: polarity %d cable %d ufp %d "
253 GET_TCSS_ALT_FIELD(POLARITY
, cmd
),
254 GET_TCSS_ALT_FIELD(CABLE
, cmd
),
255 GET_TCSS_ALT_FIELD(UFP
, cmd
),
256 GET_TCSS_ALT_FIELD(DP_MODE
, cmd
));
260 ret
= send_pmc_req(DP_REQ
, &req
, &rsp
, PMC_IPC_ALT_REQ_SIZE
);
264 send_pmc_dp_hpd_request(port
, mux_data
, port_map
);
268 static void disconnect_tcss_devices(int port
, const struct tcss_port_map
*port_map
)
272 ret
= send_pmc_disconnect_request(port
, port_map
);
274 printk(BIOS_ERR
, "Failed to setup port:%d to initial state\n", port
);
277 static void tcss_configure_dp_mode(const struct tcss_port_map
*port_map
, size_t num_ports
)
279 int ret
, port_bitmask
;
281 const struct usbc_ops
*ops
;
282 struct usbc_mux_info mux_info
;
283 const struct tcss_port_map
*port_info
;
285 if (!display_init_required())
288 ops
= usbc_get_ops();
292 port_bitmask
= ops
->dp_ops
.wait_for_connection(WAIT_FOR_DISPLAYPORT_TIMEOUT_MS
);
293 if (!port_bitmask
) /* No DP device is connected */
296 for (i
= 0; i
< num_ports
; i
++) {
297 if (!(port_bitmask
& BIT(i
)))
300 ret
= ops
->dp_ops
.enter_dp_mode(i
);
304 ret
= ops
->dp_ops
.wait_for_dp_mode_entry(i
, WAIT_FOR_DP_MODE_ENTRY_TIMEOUT_MS
);
308 ret
= ops
->dp_ops
.wait_for_hpd(i
, WAIT_FOR_HPD_TIMEOUT_MS
);
312 ret
= ops
->mux_ops
.get_mux_info(i
, &mux_info
);
316 port_info
= &port_map
[i
];
318 ret
= send_pmc_connect_request(i
, &mux_info
, port_info
);
320 printk(BIOS_ERR
, "Port %zu connect request failed\n", i
);
323 ret
= send_pmc_safe_mode_request(i
, &mux_info
, port_info
);
325 printk(BIOS_ERR
, "Port %zu safe mode request failed\n", i
);
329 ret
= send_pmc_dp_mode_request(i
, &mux_info
, port_info
);
331 printk(BIOS_ERR
, "Port C%zu mux set failed with error %d\n", i
, ret
);
333 printk(BIOS_INFO
, "Port C%zu is configured to DP mode!\n", i
);
339 static void tcss_configure_usb_mode(const struct tcss_port_map
*port_map
, size_t num_ports
)
343 const struct usbc_ops
*ops
;
344 struct usbc_mux_info mux_info
;
345 const struct tcss_port_map
*port_info
;
347 ops
= usbc_get_ops();
351 for (i
= 0; i
< num_ports
; i
++) {
352 ret
= ops
->mux_ops
.get_mux_info(i
, &mux_info
);
353 if ((ret
< 0) || !mux_info
.usb
|| (mux_info
.dp
&& mux_info
.hpd_lvl
))
356 port_info
= &port_map
[i
];
357 ret
= send_pmc_connect_request(i
, &mux_info
, port_info
);
359 printk(BIOS_ERR
, "Port %zu connect request failed\n", i
);
365 static uint32_t calc_bias_ctrl_reg_value(gpio_t pad
)
367 unsigned int vw_index
, vw_bit
;
368 const unsigned int cpu_pid
= gpio_get_pad_cpu_portid(pad
);
369 if (!gpio_get_vw_info(pad
, &vw_index
, &vw_bit
) || !cpu_pid
)
372 return vw_index
<< BIAS_CTRL_VW_INDEX_SHIFT
|
373 vw_bit
<< BIAS_CTRL_BIT_POS_SHIFT
|
377 void tcss_configure_aux_bias_pads_regbar(
378 const struct typec_aux_bias_pads
*pads
)
380 for (size_t i
= 0; i
< MAX_TYPE_C_PORTS
; i
++) {
381 if (pads
[i
].pad_auxn_dc
&& pads
[i
].pad_auxp_dc
) {
382 REGBAR32(PID_IOM
, IOM_AUX_BIAS_CTRL_PULLUP_OFFSET(i
)) =
383 calc_bias_ctrl_reg_value(pads
[i
].pad_auxp_dc
);
384 REGBAR32(PID_IOM
, IOM_AUX_BIAS_CTRL_PULLDOWN_OFFSET(i
)) =
385 calc_bias_ctrl_reg_value(pads
[i
].pad_auxn_dc
);
390 void ioe_tcss_configure_aux_bias_pads_sbi(
391 const struct typec_aux_bias_pads
*pads
)
393 for (size_t i
= 0; i
< MAX_TYPE_C_PORTS
; i
++) {
394 if (pads
[i
].pad_auxn_dc
&& pads
[i
].pad_auxp_dc
) {
395 ioe_p2sb_sbi_write(PID_IOM
, IOM_AUX_BIAS_CTRL_PULLUP_OFFSET(i
),
396 calc_bias_ctrl_reg_value(pads
[i
].pad_auxp_dc
));
397 ioe_p2sb_sbi_write(PID_IOM
, IOM_AUX_BIAS_CTRL_PULLDOWN_OFFSET(i
),
398 calc_bias_ctrl_reg_value(pads
[i
].pad_auxn_dc
));
403 const struct tcss_port_map
*tcss_get_port_info(size_t *num_ports
)
405 static struct tcss_port_map port_map
[MAX_TYPE_C_PORTS
];
406 size_t active_ports
= 0;
409 for (port
= 0; port
< MAX_TYPE_C_PORTS
; port
++) {
410 const struct device_path conn_path
[] = {
411 {.type
= DEVICE_PATH_PCI
, .pci
.devfn
= PCH_DEVFN_PMC
},
412 {.type
= DEVICE_PATH_GENERIC
, .generic
.id
= 0, .generic
.subid
= 0},
413 {.type
= DEVICE_PATH_GENERIC
, .generic
.id
= port
},
415 const struct device
*conn
= find_dev_nested_path(pci_root_bus(), conn_path
,
416 ARRAY_SIZE(conn_path
));
417 unsigned int usb2_port
, usb3_port
;
419 if (!is_dev_enabled(conn
))
422 if (CONFIG(DRIVERS_INTEL_PMC
) &&
423 intel_pmc_mux_conn_get_ports(conn
, &usb2_port
, &usb3_port
)) {
424 port_map
[active_ports
].usb2_port
= usb2_port
;
425 port_map
[active_ports
].usb3_port
= usb3_port
;
430 *num_ports
= active_ports
;
434 void tcss_configure(const struct typec_aux_bias_pads aux_bias_pads
[MAX_TYPE_C_PORTS
])
436 const struct tcss_port_map
*port_map
;
440 port_map
= tcss_get_port_info(&num_ports
);
441 if ((port_map
== NULL
) || platform_is_resuming())
444 if (CONFIG(TCSS_HAS_USBC_OPS
))
445 for (i
= 0; i
< num_ports
; i
++)
446 disconnect_tcss_devices(i
, &port_map
[i
]);
448 /* This should be performed before alternate modes are entered */
449 if (tcss_ops
.configure_aux_bias_pads
)
450 tcss_ops
.configure_aux_bias_pads(aux_bias_pads
);
452 if (CONFIG(ENABLE_TCSS_DISPLAY_DETECTION
))
453 tcss_configure_dp_mode(port_map
, num_ports
);
455 if (CONFIG(ENABLE_TCSS_USB_DETECTION
))
456 tcss_configure_usb_mode(port_map
, num_ports
);
459 bool tcss_valid_tbt_auth(void)
461 return REGBAR32(PID_IOM
, IOM_CSME_IMR_TBT_STATUS
) & TBT_VALID_AUTHENTICATION
;