mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-10-27 01:58:19 +00:00 
			
		
		
		
	- Generally we just drop the #ifdef CONFIG_SYS_LONGHELP and endif lines and use U_BOOT_LONGHELP to declare the same variable name as before - In a few places, either rename the variable to follow convention or introduce the variable as it was being done inline before. Signed-off-by: Tom Rini <trini@konsulko.com> Reviewed-by: Simon Glass <sjg@chromium.org>
		
			
				
	
	
		
			163 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0+
 | |
| /*
 | |
|  * (C) Copyright 2022 Microsoft Corporation <www.microsoft.com>
 | |
|  * Stephen Carlson <stcarlso@linux.microsoft.com>
 | |
|  *
 | |
|  * PCI Express Maximum Packet Size (MPS) configuration
 | |
|  */
 | |
| 
 | |
| #include <common.h>
 | |
| #include <bootretry.h>
 | |
| #include <cli.h>
 | |
| #include <command.h>
 | |
| #include <console.h>
 | |
| #include <dm.h>
 | |
| #include <init.h>
 | |
| #include <asm/processor.h>
 | |
| #include <asm/io.h>
 | |
| #include <pci.h>
 | |
| 
 | |
| #define PCI_MPS_SAFE 0
 | |
| #define PCI_MPS_PEER2PEER 1
 | |
| 
 | |
| static int pci_mps_find_safe(struct udevice *bus, unsigned int *min_mps,
 | |
| 			     unsigned int *n)
 | |
| {
 | |
| 	struct udevice *dev;
 | |
| 	int res = 0, addr;
 | |
| 	unsigned int mpss;
 | |
| 	u32 regval;
 | |
| 
 | |
| 	if (!min_mps || !n)
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	for (device_find_first_child(bus, &dev);
 | |
| 	     dev;
 | |
| 	     device_find_next_child(&dev)) {
 | |
| 		addr = dm_pci_find_capability(dev, PCI_CAP_ID_EXP);
 | |
| 		if (addr <= 0)
 | |
| 			continue;
 | |
| 
 | |
| 		res = dm_pci_read_config32(dev, addr + PCI_EXP_DEVCAP,
 | |
| 					   ®val);
 | |
| 		if (res != 0)
 | |
| 			return res;
 | |
| 		mpss = (unsigned int)(regval & PCI_EXP_DEVCAP_PAYLOAD);
 | |
| 		*n += 1;
 | |
| 		if (mpss < *min_mps)
 | |
| 			*min_mps = mpss;
 | |
| 	}
 | |
| 
 | |
| 	return res;
 | |
| }
 | |
| 
 | |
| static int pci_mps_set_bus(struct udevice *bus, unsigned int target)
 | |
| {
 | |
| 	struct udevice *dev;
 | |
| 	u32 mpss, target_mps = (u32)(target << 5);
 | |
| 	u16 mps;
 | |
| 	int res = 0, addr;
 | |
| 
 | |
| 	for (device_find_first_child(bus, &dev);
 | |
| 	     dev && res == 0;
 | |
| 	     device_find_next_child(&dev)) {
 | |
| 		addr = dm_pci_find_capability(dev, PCI_CAP_ID_EXP);
 | |
| 		if (addr <= 0)
 | |
| 			continue;
 | |
| 
 | |
| 		res = dm_pci_read_config32(dev, addr + PCI_EXP_DEVCAP,
 | |
| 					   &mpss);
 | |
| 		if (res != 0)
 | |
| 			return res;
 | |
| 
 | |
| 		/* Do not set device above its maximum MPSS */
 | |
| 		mpss = (mpss & PCI_EXP_DEVCAP_PAYLOAD) << 5;
 | |
| 		if (target_mps < mpss)
 | |
| 			mps = (u16)target_mps;
 | |
| 		else
 | |
| 			mps = (u16)mpss;
 | |
| 		res = dm_pci_clrset_config16(dev, addr + PCI_EXP_DEVCTL,
 | |
| 					     PCI_EXP_DEVCTL_PAYLOAD, mps);
 | |
| 	}
 | |
| 
 | |
| 	return res;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Sets the MPS of each PCI Express device to the specified policy.
 | |
|  */
 | |
| static int pci_mps_set(int policy)
 | |
| {
 | |
| 	struct udevice *bus;
 | |
| 	int i, res = 0;
 | |
| 	/* 0 = 128B, min value for hotplug */
 | |
| 	unsigned int mps = 0;
 | |
| 
 | |
| 	if (policy == PCI_MPS_SAFE) {
 | |
| 		unsigned int min_mps = PCI_EXP_DEVCAP_PAYLOAD_4096B, n = 0;
 | |
| 
 | |
| 		/* Find maximum MPS supported by all devices */
 | |
| 		for (i = 0;
 | |
| 		     uclass_get_device_by_seq(UCLASS_PCI, i, &bus) == 0 &&
 | |
| 		     res == 0;
 | |
| 		     i++)
 | |
| 			res = pci_mps_find_safe(bus, &min_mps, &n);
 | |
| 
 | |
| 		/* If no devices were found, do not reconfigure */
 | |
| 		if (n == 0)
 | |
| 			return res;
 | |
| 		mps = min_mps;
 | |
| 	}
 | |
| 
 | |
| 	/* This message is checked by the sandbox test */
 | |
| 	printf("Setting MPS of all devices to %uB\n", 128U << mps);
 | |
| 	for (i = 0;
 | |
| 	     uclass_get_device_by_seq(UCLASS_PCI, i, &bus) == 0 && res == 0;
 | |
| 	     i++)
 | |
| 		res = pci_mps_set_bus(bus, mps);
 | |
| 
 | |
| 	return res;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * PCI MPS tuning commands
 | |
|  *
 | |
|  * Syntax:
 | |
|  *	pci_mps safe
 | |
|  *	pci_mps peer2peer
 | |
|  */
 | |
| static int do_pci_mps(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 | |
| {
 | |
| 	char cmd = 'u';
 | |
| 	int ret = 0;
 | |
| 
 | |
| 	if (argc > 1)
 | |
| 		cmd = argv[1][0];
 | |
| 
 | |
| 	switch (cmd) {
 | |
| 	case 's':		/* safe */
 | |
| 		ret = pci_mps_set(PCI_MPS_SAFE);
 | |
| 		break;
 | |
| 	case 'p':		/* peer2peer/hotplug */
 | |
| 		ret = pci_mps_set(PCI_MPS_PEER2PEER);
 | |
| 		break;
 | |
| 	default:		/* usage, help */
 | |
| 		goto usage;
 | |
| 	}
 | |
| 
 | |
| 	return ret;
 | |
| usage:
 | |
| 	return CMD_RET_USAGE;
 | |
| }
 | |
| 
 | |
| /***************************************************/
 | |
| 
 | |
| U_BOOT_LONGHELP(pci_mps,
 | |
| 	"safe\n"
 | |
| 	"    - Set PCI Express MPS of all devices to safe values\n"
 | |
| 	"pci_mps peer2peer\n"
 | |
| 	"    - Set PCI Express MPS of all devices to support hotplug and peer-to-peer DMA\n");
 | |
| 
 | |
| U_BOOT_CMD(pci_mps, 2, 0, do_pci_mps,
 | |
| 	   "configure PCI Express MPS", pci_mps_help_text);
 |