nb/sandybridge,sb/bd82x6x: Configure USB from southbridge devicetree
Transfer all USB responsibilities to southbridge/intel/bd82x6x, using one set of USB port configuration supplied by mainboards in the southbridge section of their devicetree. For MRC raminit, export southbridge_fill_pei_data() as a hook for southbridge code to implement. With new code via this hook, bd82x6x fills pei_data based on this one set of USB port config. For native raminit, early_usb_init() now goes directly to the devicetree and no longer get passed an address to it. TEST=abuild passes for all affected boards. All USB ports still work on asus/p8x7x-series/v/p8z77-m. Change-Id: I38378c7ee0701abc434b030dd97873f2af63e6b0 Signed-off-by: Keith Hui <buurin@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/81881 Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
		| @@ -116,4 +116,5 @@ struct pei_data | |||||||
| 	int ddr_refresh_rate_config; | 	int ddr_refresh_rate_config; | ||||||
| } __packed; | } __packed; | ||||||
|  |  | ||||||
|  | void southbridge_fill_pei_data(struct pei_data *pei_data); | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -252,11 +252,6 @@ static bool do_pcie_init(void) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| static void southbridge_fill_pei_data(struct pei_data *pei_data) |  | ||||||
| { |  | ||||||
| 	/* This will move to southbridge later. */ |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void devicetree_fill_pei_data(struct pei_data *pei_data) | static void devicetree_fill_pei_data(struct pei_data *pei_data) | ||||||
| { | { | ||||||
| 	const struct northbridge_intel_sandybridge_config *cfg = config_of_soc(); | 	const struct northbridge_intel_sandybridge_config *cfg = config_of_soc(); | ||||||
| @@ -290,9 +285,6 @@ static void devicetree_fill_pei_data(struct pei_data *pei_data) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	memcpy(pei_data->ts_addresses,  cfg->ts_addresses,  sizeof(pei_data->ts_addresses)); | 	memcpy(pei_data->ts_addresses,  cfg->ts_addresses,  sizeof(pei_data->ts_addresses)); | ||||||
|  |  | ||||||
| 	memcpy(pei_data->usb_port_config, cfg->usb_port_config, |  | ||||||
| 	       sizeof(pei_data->usb_port_config)); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static void spd_fill_pei_data(struct pei_data *pei_data) | static void spd_fill_pei_data(struct pei_data *pei_data) | ||||||
| @@ -374,7 +366,7 @@ void perform_raminit(int s3resume) | |||||||
| 		.nmode          = cfg->nmode, | 		.nmode          = cfg->nmode, | ||||||
| 		.ddr_refresh_rate_config  = cfg->ddr_refresh_rate_config, | 		.ddr_refresh_rate_config  = cfg->ddr_refresh_rate_config, | ||||||
| 		.usb3.mode                = cfg->usb3.mode, | 		.usb3.mode                = cfg->usb3.mode, | ||||||
| 		.usb3.hs_port_switch_mask = cfg->usb3.hs_port_switch_mask, | 		/* .usb3.hs_port_switch_mask = native config->xhci_switchable_ports */ | ||||||
| 		.usb3.preboot_support     = cfg->usb3.preboot_support, | 		.usb3.preboot_support     = cfg->usb3.preboot_support, | ||||||
| 		.usb3.xhci_streams        = cfg->usb3.xhci_streams, | 		.usb3.xhci_streams        = cfg->usb3.xhci_streams, | ||||||
| 	}; | 	}; | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ void mainboard_romstage_entry(void) | |||||||
|  |  | ||||||
| 	/* When using MRC, USB is initialized by MRC */ | 	/* When using MRC, USB is initialized by MRC */ | ||||||
| 	if (CONFIG(USE_NATIVE_RAMINIT)) { | 	if (CONFIG(USE_NATIVE_RAMINIT)) { | ||||||
| 		early_usb_init(mainboard_usb_ports); | 		early_usb_init(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Perform some early chipset init needed before RAM initialization can work */ | 	/* Perform some early chipset init needed before RAM initialization can work */ | ||||||
|   | |||||||
| @@ -8,8 +8,9 @@ | |||||||
| #include <southbridge/intel/common/pmbase.h> | #include <southbridge/intel/common/pmbase.h> | ||||||
|  |  | ||||||
| #include "pch.h" | #include "pch.h" | ||||||
|  | #include "chip.h" | ||||||
|  |  | ||||||
| void early_usb_init(const struct southbridge_usb_port *portmap) | void early_usb_init(void) | ||||||
| { | { | ||||||
| 	u32 reg32; | 	u32 reg32; | ||||||
| 	const u32 rcba_dump[8] = { | 	const u32 rcba_dump[8] = { | ||||||
| @@ -23,6 +24,9 @@ void early_usb_init(const struct southbridge_usb_port *portmap) | |||||||
| 				 USBIR_TXRX_GAIN_DESKTOP6_LOW, USBIR_TXRX_GAIN_DESKTOP6_HIGH, | 				 USBIR_TXRX_GAIN_DESKTOP6_LOW, USBIR_TXRX_GAIN_DESKTOP6_HIGH, | ||||||
| 				 USBIR_TXRX_GAIN_DESKTOP7_LOW, USBIR_TXRX_GAIN_DESKTOP7_MED, | 				 USBIR_TXRX_GAIN_DESKTOP7_LOW, USBIR_TXRX_GAIN_DESKTOP7_MED, | ||||||
| 				 0x20000053, 0x2000055f, 0x20000f5f}; | 				 0x20000053, 0x2000055f, 0x20000f5f}; | ||||||
|  | 	const struct device *dev = pcidev_on_root(0x1d, 0); | ||||||
|  | 	const struct southbridge_intel_bd82x6x_config *config = dev->chip_info; | ||||||
|  | 	const struct southbridge_usb_port *portmap = config->usb_port_config; | ||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| 	/* Unlock registers.  */ | 	/* Unlock registers.  */ | ||||||
|   | |||||||
| @@ -3,6 +3,8 @@ | |||||||
| #include <device/pci_ops.h> | #include <device/pci_ops.h> | ||||||
| #include <device/pci_def.h> | #include <device/pci_def.h> | ||||||
| #include "pch.h" | #include "pch.h" | ||||||
|  | #include "chip.h" | ||||||
|  | #include <northbridge/intel/sandybridge/pei_data.h> | ||||||
|  |  | ||||||
| #define PCH_EHCI1_TEMP_BAR0 0xe8000000 | #define PCH_EHCI1_TEMP_BAR0 0xe8000000 | ||||||
| #define PCH_EHCI2_TEMP_BAR0 0xe8000400 | #define PCH_EHCI2_TEMP_BAR0 0xe8000400 | ||||||
| @@ -29,3 +31,63 @@ void enable_usb_bar(void) | |||||||
| 			   PCH_EHCI2_TEMP_BAR0); | 			   PCH_EHCI2_TEMP_BAR0); | ||||||
| 	pci_or_config16(usb1, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); | 	pci_or_config16(usb1, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Translate coreboot native USB port configuration in devicetree | ||||||
|  |  * into a format reference code expects: | ||||||
|  |  * | ||||||
|  |  * [MRC index] = .native_field // what for | ||||||
|  |  *         [0] = .enabled // enable | ||||||
|  |  *         [1] = .oc_pin // overcurrent pin | ||||||
|  |  *         [2] = .current // length | ||||||
|  |  * | ||||||
|  |  * For .current, use these native values for MRC settings 1-3, corresponding | ||||||
|  |  * to values of 0x40/0x80/0x130, which should produce the correct values | ||||||
|  |  * across all supported PCHs. | ||||||
|  |  * | ||||||
|  |  * PCH type    | 1 | 2 | 3 | ||||||
|  |  * ------------+---+---+--- | ||||||
|  |  * Mobile      | 0 | 1 | 2 | ||||||
|  |  * Desktop x6x | 6 | 1 | 7 | ||||||
|  |  * Desktop x7x | 8 | 9 | 2 | ||||||
|  |  * | ||||||
|  |  * See also: | ||||||
|  |  * northbridge/intel/sandybridge/pei_data.h | ||||||
|  |  * pch.h | ||||||
|  |  * early_usb.c | ||||||
|  |  */ | ||||||
|  | void southbridge_fill_pei_data(struct pei_data *pei_data) | ||||||
|  | { | ||||||
|  | 	const struct device *dev = pcidev_on_root(0x1d, 0); | ||||||
|  | 	const struct southbridge_intel_bd82x6x_config *config = dev->chip_info; | ||||||
|  | 	/* Native current -> MRC length map to get the same USBIRx register value */ | ||||||
|  | 	const uint16_t currents[] = { 0x40, 0x80, 0x130, | ||||||
|  | 				      0, 0, 0, /* 3-5 not seen in MRC */ | ||||||
|  | 				      0x40, 0x130, 0x40, 0x80}; | ||||||
|  | 	for (unsigned int port = 0; port < ARRAY_SIZE(config->usb_port_config); port++) { | ||||||
|  | 		uint16_t current = 0; | ||||||
|  | 		int ocp = config->usb_port_config[port].oc_pin; | ||||||
|  | 		if (ocp == -1) | ||||||
|  | 			ocp = (port < 8) ? 0 : 4; | ||||||
|  |  | ||||||
|  | 		if (config->usb_port_config[port].current < ARRAY_SIZE(currents)) | ||||||
|  | 			current = currents[config->usb_port_config[port].current]; | ||||||
|  |  | ||||||
|  | 		/* | ||||||
|  | 		 * Note for developers: If this message shows, your board uses a | ||||||
|  | 		 * current setting MRC.bin cannot produce. Choose a value as close | ||||||
|  | 		 * as possible and test all USB ports, or consider using native raminit. | ||||||
|  | 		 */ | ||||||
|  | 		if (current == 0) { | ||||||
|  | 			printk(BIOS_NOTICE, | ||||||
|  | 			       "%s: USB%02d: %d is an invalid setting for MRC.bin!\n", | ||||||
|  | 			       __func__, port, config->usb_port_config[port].current); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		pei_data->usb_port_config[port][0] = config->usb_port_config[port].enabled; | ||||||
|  | 		pei_data->usb_port_config[port][1] = ocp; | ||||||
|  | 		pei_data->usb_port_config[port][2] = current; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	pei_data->usb3.hs_port_switch_mask = config->xhci_switchable_ports; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ struct southbridge_usb_port | |||||||
| void pch_enable(struct device *dev); | void pch_enable(struct device *dev); | ||||||
| extern const struct southbridge_usb_port mainboard_usb_ports[14]; | extern const struct southbridge_usb_port mainboard_usb_ports[14]; | ||||||
|  |  | ||||||
| void early_usb_init(const struct southbridge_usb_port *portmap); | void early_usb_init(void); | ||||||
|  |  | ||||||
| /* PCI Configuration Space (D30:F0): PCI2PCI */ | /* PCI Configuration Space (D30:F0): PCI2PCI */ | ||||||
| #define PSTS	0x06 | #define PSTS	0x06 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user