soc/intel/elkhartlake: Update FSP-S UPD RP & USB related configs

Further add initial Silicon UPD settings for:
- PCIe root ports
- USB

Signed-off-by: Lean Sheng Tan <lean.sheng.tan@intel.com>
Change-Id: I60afb78a7997b8465dd6318f3abee28f95a65100
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55034
Reviewed-by: Mario Scheithauer <mario.scheithauer@siemens.com>
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/mainboard/intel/elkhartlake_crb/variants/ehlcrb/devicetree.cb b/src/mainboard/intel/elkhartlake_crb/variants/ehlcrb/devicetree.cb
index fa82a68..be2b6c9 100644
--- a/src/mainboard/intel/elkhartlake_crb/variants/ehlcrb/devicetree.cb
+++ b/src/mainboard/intel/elkhartlake_crb/variants/ehlcrb/devicetree.cb
@@ -27,10 +27,27 @@
 	# Enable DDC for DDI ports C
 	register "DdiPortCDdc" = "1"
 
+	# USB related UPDs
+	register "usb2_ports[0]" = "USB2_PORT_MID(OC3)"	# USB3/2 Type A port1
+	register "usb2_ports[1]" = "USB2_PORT_MID(OC3)"	# USB2 WWAN
+	register "usb2_ports[2]" = "USB2_PORT_MID(OC_SKIP)"	# USB2 Bluetooth
+	register "usb2_ports[3]" = "USB2_PORT_MID(OC3)"	# Type-C Port1
+	register "usb2_ports[4]" = "USB2_PORT_MID(OC3)"	# Type-C Port2
+	register "usb2_ports[5]" = "USB2_PORT_MID(OC_SKIP)"	# Type-C Port3
+	register "usb2_ports[6]" = "USB2_PORT_MID(OC_SKIP)"	# Type-C Port4
+	register "usb2_ports[7]" = "USB2_PORT_MID(OC_SKIP)"	# USB3/2 Type A port2
+	register "usb2_ports[8]" = "USB2_PORT_MID(OC_SKIP)"	# USB2 Type A port1
+	register "usb2_ports[9]" = "USB2_PORT_MID(OC_SKIP)"	# USB2 Type A port2
+
+	register "usb3_ports[0]" = "USB3_PORT_DEFAULT(OC3)"	# USB3/2 Type A port1
+	register "usb3_ports[1]" = "USB3_PORT_DEFAULT(OC3)"	# USB3/2 Type A port2
+	register "usb3_ports[2]" = "USB3_PORT_DEFAULT(OC3)"	# USB3 WLAN
+	register "usb3_ports[3]" = "USB3_PORT_DEFAULT(OC3)"	# UNUSED
+
 	# Skip the CPU repalcement check
 	register "SkipCpuReplacementCheck" = "1"
 
-	# Enable All Root Ports (1-7)
+	# PCIe root ports related UPDs
 	register "PcieRpEnable[0]" = "1"
 	register "PcieRpEnable[1]" = "1"
 	register "PcieRpEnable[2]" = "1"
diff --git a/src/soc/intel/elkhartlake/chip.h b/src/soc/intel/elkhartlake/chip.h
index 6b36792..ebe14d5 100644
--- a/src/soc/intel/elkhartlake/chip.h
+++ b/src/soc/intel/elkhartlake/chip.h
@@ -80,8 +80,8 @@
 	uint8_t RMT;
 
 	/* USB related */
-	struct usb2_port_config usb2_ports[16];
-	struct usb3_port_config usb3_ports[10];
+	struct usb2_port_config usb2_ports[10];
+	struct usb3_port_config usb3_ports[4];
 	/* Wake Enable Bitmap for USB2 ports */
 	uint16_t usb2_wake_enable_bitmap;
 	/* Wake Enable Bitmap for USB3 ports */
@@ -103,16 +103,29 @@
 
 	/* PCIe Root Ports */
 	uint8_t PcieRpEnable[CONFIG_MAX_ROOT_PORTS];
+	uint8_t PcieRpHotPlug[CONFIG_MAX_ROOT_PORTS];
+
 	/* PCIe output clocks type to PCIe devices.
 	 * 0-23: PCH rootport, 0x70: LAN, 0x80: unspecified but in use,
 	 * 0xFF: not used */
 	uint8_t PcieClkSrcUsage[CONFIG_MAX_PCIE_CLOCK_SRC];
+
 	/* PCIe ClkReq-to-ClkSrc mapping, number of clkreq signal assigned to
 	 * clksrc. */
 	uint8_t PcieClkSrcClkReq[CONFIG_MAX_PCIE_CLOCK_SRC];
 
+/* Enable PCIe Precision Time Measurement for Root Ports (disabled by default) */
+	uint8_t PciePtm[CONFIG_MAX_ROOT_PORTS];
+
+	/* Probe CLKREQ# signal before enabling CLKREQ# based power management.
+	 * Enable - Default (0) / Disable (1) */
+	uint8_t PcieRpClkReqDetectDisable[CONFIG_MAX_ROOT_PORTS];
+
 	/* Probe CLKREQ# signal before enabling CLKREQ# based power management.*/
-	uint8_t PcieRpClkReqDetect[CONFIG_MAX_ROOT_PORTS];
+	uint8_t PcieRpAdvancedErrorReportingDisable[CONFIG_MAX_ROOT_PORTS];
+
+	/* PCIe LTR: Enable - Default (0) / Disable (1) */
+	uint8_t PcieRpLtrDisable[CONFIG_MAX_ROOT_PORTS];
 
 	/* PCIe RP L1 substate */
 	enum L1_substates_control PcieRpL1Substates[CONFIG_MAX_ROOT_PORTS];
diff --git a/src/soc/intel/elkhartlake/fsp_params.c b/src/soc/intel/elkhartlake/fsp_params.c
index 88e7d06..98c939f 100644
--- a/src/soc/intel/elkhartlake/fsp_params.c
+++ b/src/soc/intel/elkhartlake/fsp_params.c
@@ -15,6 +15,25 @@
 #include <soc/soc_chip.h>
 #include <string.h>
 
+/*
+ * Chip config parameter PcieRpL1Substates uses (UPD value + 1)
+ * because UPD value of 0 for PcieRpL1Substates means disabled for FSP.
+ * In order to ensure that mainboard setting does not disable L1 substates
+ * incorrectly, chip config parameter values are offset by 1 with 0 meaning
+ * use FSP UPD default. get_l1_substate_control() ensures that the right UPD
+ * value is set in fsp_params.
+ * 0: Use FSP UPD default
+ * 1: Disable L1 substates
+ * 2: Use L1.1
+ * 3: Use L1.2 (FSP UPD default)
+ */
+static int get_l1_substate_control(enum L1_substates_control ctl)
+{
+	if ((ctl > L1_SS_L1_2) || (ctl == L1_SS_FSP_DEFAULT))
+		ctl = L1_SS_L1_2;
+	return ctl - 1;
+}
+
 static const pci_devfn_t serial_io_dev[] = {
 	PCH_DEVFN_I2C0,
 	PCH_DEVFN_I2C1,
@@ -99,6 +118,7 @@
 /* UPD parameters to be initialized before SiliconInit */
 void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd)
 {
+	unsigned int i;
 	struct device *dev;
 	FSP_S_CONFIG *params = &supd->FspsConfig;
 	struct soc_intel_elkhartlake_config *config = config_of_soc();
@@ -154,6 +174,63 @@
 	/* HECI */
 	params->Heci3Enabled = config->Heci3Enable;
 
+	/* USB configuration */
+	for (i = 0; i < ARRAY_SIZE(config->usb2_ports); i++) {
+		params->PortUsb20Enable[i] = config->usb2_ports[i].enable;
+		params->Usb2PhyPetxiset[i] = config->usb2_ports[i].pre_emp_bias;
+		params->Usb2PhyTxiset[i] = config->usb2_ports[i].tx_bias;
+		params->Usb2PhyPredeemp[i] = config->usb2_ports[i].tx_emp_enable;
+		params->Usb2PhyPehalfbit[i] = config->usb2_ports[i].pre_emp_bit;
+		params->Usb2OverCurrentPin[i] = config->usb2_ports[i].enable ?
+			config->usb2_ports[i].ocpin : 0xff;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(config->usb3_ports); i++) {
+		params->PortUsb30Enable[i] = config->usb3_ports[i].enable;
+		params->Usb3OverCurrentPin[i] = config->usb3_ports[i].enable ?
+			config->usb3_ports[i].ocpin : 0xff;
+		if (config->usb3_ports[i].tx_de_emp) {
+			params->Usb3HsioTxDeEmphEnable[i] = 1;
+			params->Usb3HsioTxDeEmph[i] = config->usb3_ports[i].tx_de_emp;
+		}
+		if (config->usb3_ports[i].tx_downscale_amp) {
+			params->Usb3HsioTxDownscaleAmpEnable[i] = 1;
+			params->Usb3HsioTxDownscaleAmp[i] =
+				config->usb3_ports[i].tx_downscale_amp;
+		}
+	}
+
+	params->UsbClockGatingEnable = 1;
+	params->UsbPowerGatingEnable = 1;
+
+	/* Enable xDCI controller if enabled in devicetree and allowed */
+	dev = pcidev_path_on_root(PCH_DEVFN_USBOTG);
+	if (dev) {
+		if (!xdci_can_enable())
+			dev->enabled = 0;
+
+		params->XdciEnable = dev->enabled;
+	} else {
+		params->XdciEnable = 0;
+	}
+
+	/* PCIe root ports config */
+	for (i = 0; i < CONFIG_MAX_ROOT_PORTS; i++) {
+		params->PcieRpClkReqDetect[i] =
+			!config->PcieRpClkReqDetectDisable[i];
+		params->PcieRpL1Substates[i] =
+			get_l1_substate_control(config->PcieRpL1Substates[i]);
+		params->PcieRpLtrEnable[i] = !config->PcieRpLtrDisable[i];
+		params->PcieRpAdvancedErrorReporting[i] =
+			!config->PcieRpAdvancedErrorReportingDisable[i];
+		params->PcieRpHotPlug[i] = config->PcieRpHotPlug[i];
+		params->PciePtm[i] = config->PciePtm[i];
+		params->PcieRpLtrMaxNoSnoopLatency[i] = 0x1003;
+		params->PcieRpLtrMaxSnoopLatency[i] = 0x1003;
+		/* Virtual Channel 1 to Traffic Class mapping */
+		params->PcieRpVc1TcMap[i] = 0x60;
+	}
+
 	/* Override/Fill FSP Silicon Param for mainboard */
 	mainboard_silicon_init_params(params);
 }