1313#include <cpu/amd/mtrr.h>
1414#include <cpu/cpu.h>
1515#include <cpu/x86/smm.h>
16+ #include <console/console.h>
1617#include <device/device.h>
1718#include <soc/amd/phoenix/chip.h>
1819#include <soc/aoac_defs.h>
@@ -85,8 +86,6 @@ static FCH_TC_USB_OEM_PLATFORM_TABLE usb_config = { 0 };
8586
8687#define NUM_XHCI_CONTROLLERS 4
8788#define NUM_USB4_CONTROLLERS 2
88- #define NUM_USB2_PORTS 8
89- #define NUM_USB3_PORTS 3
9089static void configure_usb (SIL_CONTEXT * SilContext )
9190{
9291 struct device * usb_ctrlr [NUM_XHCI_CONTROLLERS ] = {
@@ -107,7 +106,7 @@ static void configure_usb(SIL_CONTEXT *SilContext)
107106 };
108107
109108 /* In coreboot the USB4 ports are first in order, but openSIL expects the opposite */
110- struct device * usb2_ports [NUM_USB2_PORTS ] = {
109+ struct device * usb2_ports [USB2_PORT_COUNT ] = {
111110 DEV_PTR (usb2_port2 ),
112111 DEV_PTR (usb2_port3 ),
113112 DEV_PTR (usb2_port4 ),
@@ -118,7 +117,7 @@ static void configure_usb(SIL_CONTEXT *SilContext)
118117 DEV_PTR (usb2_port1 )
119118 };
120119
121- struct device * usb3_ports [NUM_USB3_PORTS ] = {
120+ struct device * usb3_ports [USB3_PORT_COUNT ] = {
122121 DEV_PTR (usb3_port2 ),
123122 DEV_PTR (usb3_port3 ),
124123 DEV_PTR (usb3_port7 )
@@ -129,6 +128,16 @@ static void configure_usb(SIL_CONTEXT *SilContext)
129128 DEV_PTR (usb3_port1 )
130129 };
131130
131+ const struct usb_port_map {
132+ uint8_t usb2_ports ;
133+ uint8_t usb3_ports ;
134+ } usb_port_map [NUM_XHCI_CONTROLLERS ] = {
135+ { 5 , 2 },
136+ { 1 , 1 },
137+ { 1 , 1 },
138+ { 1 , 1 }
139+ };
140+
132141 const struct soc_amd_phoenix_config * soc_config = config_of_soc ();
133142 const struct usb_phy_config * usb_phy = & soc_config -> usb_phy ;
134143
@@ -150,19 +159,36 @@ static void configure_usb(SIL_CONTEXT *SilContext)
150159 if (fch_usb_data -> Usb4Host [1 ].PcieAdpHidden )
151160 fch_usb_data -> Usb4Host [1 ].PcieTunnelingDisable = 1 ;
152161
162+ /*
163+ * XHCI_OC structure is broken, it tries to fit u32 and u16 into single u32.
164+ * It causes the memcpy to incorrectly assign USB3 OC pins. Also the OC pin map
165+ * is not separate from USB2 ports, but simply follows the USB2 OC pin map and
166+ * the offset depens on the port count,
167+ */
168+ uint32_t oc_pins , mask , shift ;
153169 for (int i = 0 ; i < NUM_XHCI_CONTROLLERS ; i ++ ) {
154- memcpy (& fch_usb_data -> XhciOCpinSelect [i ].Field .Usb20OcPin , & soc_config -> usb2_oc_pins [i ],
155- sizeof (fch_usb_data -> XhciOCpinSelect [i ].Field .Usb20OcPin ));
156- memcpy (& fch_usb_data -> XhciOCpinSelect [i ].Field .Usb31OcPin , & soc_config -> usb3_oc_pins [i ],
157- sizeof (fch_usb_data -> XhciOCpinSelect [i ].Field .Usb31OcPin ));
170+ oc_pins = 0xffffffff ;
171+ memcpy (& oc_pins , & soc_config -> usb2_oc_pins [i ], sizeof (soc_config -> usb2_oc_pins [i ]));
172+
173+ mask = (1 << (usb_port_map [i ].usb2_ports * 4 )) - 1 ;
174+ fch_usb_data -> XhciOCpinSelect [i ].OcPinSelect &= ~mask ;
175+ fch_usb_data -> XhciOCpinSelect [i ].OcPinSelect |= oc_pins & mask ;
176+
177+ oc_pins = 0xffffffff ;
178+ memcpy (& oc_pins , & soc_config -> usb3_oc_pins [i ], sizeof (soc_config -> usb3_oc_pins [i ]));
179+
180+ mask = (1 << (usb_port_map [i ].usb3_ports * 4 )) - 1 ;
181+ shift = usb_port_map [i ].usb2_ports * 4 ;
182+ fch_usb_data -> XhciOCpinSelect [i ].OcPinSelect &= ~(mask << shift );
183+ fch_usb_data -> XhciOCpinSelect [i ].OcPinSelect |= (oc_pins & mask ) << shift ;
158184 }
159185
160- for (int i = 0 ; i < (NUM_USB2_PORTS - NUM_USB4_CONTROLLERS ); i ++ ) {
186+ for (int i = 0 ; i < (USB2_PORT_COUNT - NUM_USB4_CONTROLLERS ); i ++ ) {
161187 if (!is_dev_enabled (usb2_ports [i ]))
162188 fch_usb_data -> XhciUsb2PortDisable |= (1 << i );
163189 }
164190
165- for (int i = 0 ; i < NUM_USB3_PORTS ; i ++ ) {
191+ for (int i = 0 ; i < USB3_PORT_COUNT ; i ++ ) {
166192 if (!is_dev_enabled (usb3_ports [i ]))
167193 fch_usb_data -> XhciUsb3PortDisable |= (1 << i );
168194 }
0 commit comments