usb-c stack goes to nmi when receiving a PDO capabilities list for a second time

I am in the process of bringing up a custom board with an nrf5340 and a FUSB302B USB-C PHY-controller.

As a driver for the FUSB203B, I am using this project as an OOT-module: https://github.com/ottojo/zephyr_fusb302b/tree/main

With a Lenovo laptop PSU everything (i.e. requesting source capabilities, receiving the PDO list and selecting a PDO) is working fine, but only once. If I unplug and re-plug the PSU, the usb-c subsystem jumps to the nmi-handler. Certain other power sources seem to send the PDO list twice, which has the same effect. The backtrace looks like this:

#0  z_SysNmiOnReset () at /home/ali/ncs/zephyr/arch/arm/core/nmi_on_reset.S:27
#1  0x0000cd22 in z_arm_nmi () at /home/ali/ncs/zephyr/arch/arm/core/nmi.c:58
#2  0x00003668 in smf_execute_all_exit_actions (topmost=<optimized out>, ctx=0x20000c28 <prl_tx_0>) at /home/ali/ncs/zephyr/lib/smf/smf.c:203
#3  smf_set_state (ctx=0x20000c28 <prl_tx_0>, new_state=0xfb60 <prl_tx_states+16>) at /home/ali/ncs/zephyr/lib/smf/smf.c:300
#4  0x0000363a in smf_set_state (ctx=0x20000c28 <prl_tx_0>, new_state=0xfb50 <prl_tx_states>) at /home/ali/ncs/zephyr/lib/smf/smf.c:341
#5  0x000040a2 in prl_tx_set_state (state=state@entry=PRL_TX_PHY_LAYER_RESET, dev=0xf3f4 <__device_dts_ord_41>) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_prl.c:403
#6  0x000041b6 in prl_hr_reset_layer_entry (obj=0x20000bc8 <prl_hr_0>) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_prl.c:1044
#7  0x0000363a in smf_set_state (ctx=0x20000bc8 <prl_hr_0>, new_state=0xfb10 <prl_hr_states+16>) at /home/ali/ncs/zephyr/lib/smf/smf.c:341
#8  0x0000408e in prl_hr_set_state (state=state@entry=PRL_HR_RESET_LAYER, dev=0xf3f4 <__device_dts_ord_41>) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_prl.c:415
#9  0x0000db84 in prl_execute_hard_reset (dev=dev@entry=0xf3f4 <__device_dts_ord_41>) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_prl.c:163
#10 0x000047ee in pe_snk_hard_reset_entry (obj=0x20000de8 <pe_0>) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_pe_snk_states.c:544
#11 0x0000363a in smf_set_state (ctx=0x20000de8 <pe_0>, new_state=0xf980 <pe_states+112>) at /home/ali/ncs/zephyr/lib/smf/smf.c:341
#12 0x00003ed8 in pe_set_state (dev=0xf3f4 <__device_dts_ord_41>, state=<optimized out>) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_pe_common.c:427
#13 0x0000cec4 in smf_run_state (ctx=0x20000de8 <pe_0>) at /home/ali/ncs/zephyr/lib/smf/smf.c:399
#14 0x0000d38c in pe_run (dev=dev@entry=0xf3f4 <__device_dts_ord_41>, dpm_request=dpm_request@entry=0) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_pe_common.c:165
#15 0x0000d03e in usbc_handler (port_dev=0xf3f4 <__device_dts_ord_41>) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_stack.c:32
#16 run_usbc_0 (port_dev=0xf3f4 <__device_dts_ord_41>, unused1=<optimized out>, unused2=<optimized out>) at /home/ali/ncs/zephyr/subsys/usb/usb_c/usbc_stack.c:95
#17 0x000010fa in z_thread_entry (entry=0xf3f4 <__device_dts_ord_41>, p1=0x200000b0 <usbc_port_data_0>, p2=0x0 <i2c_dump_msgs_rw>, p3=0x0 <i2c_dump_msgs_rw>)
    at /home/ali/ncs/zephyr/lib/os/thread_entry.c:48
#18 0x000010fa in z_thread_entry (entry=0xf3f4 <__device_dts_ord_41>, p1=0x200000b0 <usbc_port_data_0>, p2=0x0 <i2c_dump_msgs_rw>, p3=0x0 <i2c_dump_msgs_rw>)
    at /home/ali/ncs/zephyr/lib/os/thread_entry.c:48

I am unsure if this is even an issue with my code or the driver I am using, or if it may be a bug in zephyr's usb-c subsystem.

What can I do to find out if there is something missing from the driver, and if so, what?

If all else fails, there is always a way to bypass the zephyr usb-c subsystem completely, and do the PDO negotiation in user space, but I'd prefer to do it "the proper way".

Related