[PATCH v2 2/3] drivers: pci: sandbox: Add stub sandbox PCI MPS support

2023-03-10 Thread stcarlso
From: Stephen Carlson 

Reports the sandbox swapcase PCI Express device to support a 256 byte
Maximum Payload Size for MPS tuning tests.

Signed-off-by: Stephen Carlson 
---
 drivers/misc/swap_case.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c
index 7093ad1cd4..ee5c12bd0a 100644
--- a/drivers/misc/swap_case.c
+++ b/drivers/misc/swap_case.c
@@ -165,6 +165,9 @@ static int sandbox_swap_case_read_config(const struct 
udevice *emul,
case PCI_CAP_ID_EXP_OFFSET + PCI_CAP_LIST_NEXT:
*valuep = PCI_CAP_ID_MSIX_OFFSET;
break;
+   case PCI_CAP_ID_EXP_OFFSET + PCI_EXP_DEVCAP:
+   *valuep = PCI_EXP_DEVCAP_PAYLOAD_256B;
+   break;
case PCI_CAP_ID_MSIX_OFFSET:
if (sandbox_swap_case_use_ea(emul))
*valuep = (PCI_CAP_ID_EA_OFFSET << 8) | PCI_CAP_ID_MSIX;
-- 
2.25.1



[PATCH v2 1/3] cmd: pci: Add command to set MPS of all PCIe devices

2023-03-10 Thread stcarlso
From: Stephen Carlson 

Enable tuning of the PCI Express MPS (Maximum Payload Size) of
each device. The Maximum Read Request Size is not altered.

The SAFE method uses the largest MPS value supported by all devices in the
system for each device. This method is the same algorithm as used by Linux
pci=pcie_bus_safe.

The PEER2PEER method sets all devices to the minimal (128 byte) MPS, which
allows hot plug of devices later that might only support the minimum size,
and ensures compatibility of DMA between two devices on the bus.

Signed-off-by: Stephen Carlson 
---
 cmd/Kconfig   |  10 +++
 cmd/Makefile  |   1 +
 cmd/pci_mps.c | 164 ++
 include/pci.h |   7 +++
 4 files changed, 182 insertions(+)
 create mode 100644 cmd/pci_mps.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index dc0446e02e..632c5c45db 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1390,6 +1390,16 @@ config CMD_PCI
  peripherals. Sub-commands allow bus enumeration, displaying and
  changing configuration space and a few other features.
 
+config CMD_PCI_MPS
+   bool "pci_mps - Configure PCI device MPS"
+   depends on PCI
+   help
+ Enables PCI Express Maximum Packet Size (MPS) tuning. This
+ command configures the PCI Express MPS of each endpoint to the
+ largest value supported by all devices below the root complex.
+ The Maximum Read Request Size will not be altered. This method is
+ the same algorithm as used by Linux pci=pcie_bus_safe.
+
 config CMD_PINMUX
bool "pinmux - show pins muxing"
depends on PINCTRL
diff --git a/cmd/Makefile b/cmd/Makefile
index 7b6ff73186..3365634843 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -133,6 +133,7 @@ obj-$(CONFIG_CMD_PART) += part.o
 obj-$(CONFIG_CMD_PCAP) += pcap.o
 ifdef CONFIG_PCI
 obj-$(CONFIG_CMD_PCI) += pci.o
+obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o
 endif
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PMC) += pmc.o
diff --git a/cmd/pci_mps.c b/cmd/pci_mps.c
new file mode 100644
index 00..555a5fdd8e
--- /dev/null
+++ b/cmd/pci_mps.c
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 Microsoft Corporation 
+ * Stephen Carlson 
+ *
+ * PCI Express Maximum Packet Size (MPS) configuration
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#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;
+  

[PATCH v2 3/3] test: Add test for new command pci_mps

2023-03-10 Thread stcarlso
From: Stephen Carlson 

Adds a test for the new pci_mps command to ensure that it can set the
Maximum Payload Size (MPS) of all devices to 256 bytes in the sandbox
environment. Enables the pci_mps command in the sandbox environment so
that this test can be run.

Signed-off-by: Stephen Carlson 
---
 MAINTAINERS   |  6 ++
 configs/sandbox_defconfig |  1 +
 include/test/suites.h |  2 ++
 test/cmd/Makefile |  3 +++
 test/cmd/pci_mps.c| 42 +++
 test/cmd_ut.c |  6 ++
 6 files changed, 60 insertions(+)
 create mode 100644 test/cmd/pci_mps.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 3e8e193ecc..c432b0d83b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1242,6 +1242,12 @@ M:   Heiko Schocher 
 S: Maintained
 F: drivers/pci/pci_mpc85xx.c
 
+PCI MPS
+M: Stephen Carlson 
+S: Maintained
+F: cmd/pci_mps.c
+F: test/cmd/pci_mps.c
+
 POWER
 M: Jaehoon Chung 
 S: Maintained
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 34c342b6f5..cd6bb8e2c4 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -77,6 +77,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_MUX=y
 CONFIG_CMD_OSD=y
 CONFIG_CMD_PCI=y
+CONFIG_CMD_PCI_MPS=y
 CONFIG_CMD_READ=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
diff --git a/include/test/suites.h b/include/test/suites.h
index 9ce49cbb03..f69adfeba4 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -48,6 +48,8 @@ int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char 
*const argv[]);
 int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc,
  char *const argv[]);
+int do_ut_pci_mps(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
 int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc,
  char *const argv[]);
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 09e410ec30..1bbff6899c 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -14,6 +14,9 @@ obj-$(CONFIG_CMD_FDT) += fdt.o
 obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o
 obj-$(CONFIG_CMD_LOADM) += loadm.o
 obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
+ifdef CONFIG_CMD_PCI
+obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o
+endif
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PWM) += pwm.o
 ifdef CONFIG_SANDBOX
diff --git a/test/cmd/pci_mps.c b/test/cmd/pci_mps.c
new file mode 100644
index 00..fd96f4fba6
--- /dev/null
+++ b/test/cmd/pci_mps.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests that the PCI Maximum Payload Size (MPS) command can set the sandbox
+ * PCI Express device to safe mode and determine the correct payload size.
+ *
+ * Copyright 2023 Microsoft
+ * Written by Stephen Carlson 
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define PCI_MPS_TEST(_name, _flags) UNIT_TEST(_name, _flags, pci_mps_test)
+
+/* Test "pci_mps" command in safe "s" mode */
+static int test_pci_mps_safe(struct unit_test_state *uts)
+{
+   /* Enumerate PCI Express first */
+   ut_assertok(run_command("pci e", 0));
+   ut_assert_console_end();
+
+   /* Test pci_mps s */
+   ut_assertok(run_command("pci_mps s", 0));
+   ut_assert_nextline("Setting MPS of all devices to 256B");
+   ut_assert_console_end();
+
+   return 0;
+}
+
+PCI_MPS_TEST(test_pci_mps_safe, UT_TESTF_CONSOLE_REC);
+
+int do_ut_pci_mps(struct cmd_tbl *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+   struct unit_test *tests = UNIT_TEST_SUITE_START(pci_mps_test);
+   const int n = UNIT_TEST_SUITE_COUNT(pci_mps_test);
+
+   return cmd_ut_category("cmd_pci_mps", "pci_mps_test_", tests, n,
+  argc, argv);
+}
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 1713d0d1c8..6be07c6040 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -110,6 +110,9 @@ static struct cmd_tbl cmd_ut_sub[] = {
 #ifdef CONFIG_CMD_LOADM
U_BOOT_CMD_MKENT(loadm, CONFIG_SYS_MAXARGS, 1, do_ut_loadm, "", ""),
 #endif
+#ifdef CONFIG_CMD_PCI_MPS
+   U_BOOT_CMD_MKENT(pci_mps, CONFIG_SYS_MAXARGS, 1, do_ut_pci_mps, "", ""),
+#endif
 };
 
 static int do_ut_all(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -206,6 +209,9 @@ static char ut_help_text[] =
 #endif
 #ifdef CONFIG_UT_OVERLAY
"\noverlay - device tree overlays"
+#endif
+#ifdef CONFIG_CMD_PCI_MPS
+   "\npci_mps - PCI Express Maximum Payload Size"
 #endif
"\nprint  - printing things to the console"
"\nsetexpr - setexpr command"
-- 
2.25.1



[PATCH 3/3] test: Add test for new command pci_mps

2023-03-07 Thread stcarlso
From: Stephen Carlson 

Adds a test for the new pci_mps command to ensure that it can set the
Maximum Payload Size (MPS) of all devices to 256 bytes in the sandbox
environment. Enables the pci_mps command in the sandbox environment so
that this test can be run.

Signed-off-by: Stephen Carlson 
---
 MAINTAINERS   |  6 ++
 configs/sandbox_defconfig |  1 +
 test/py/tests/test_pci_mps.py | 13 +
 3 files changed, 20 insertions(+)
 create mode 100644 test/py/tests/test_pci_mps.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 3e8e193ecc..83948b6aa7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1242,6 +1242,12 @@ M:   Heiko Schocher 
 S: Maintained
 F: drivers/pci/pci_mpc85xx.c
 
+PCI MPS
+M: Stephen Carlson 
+S: Maintained
+F: cmd/pci_mps.c
+F: test/py/tests/test_pci_mps.py
+
 POWER
 M: Jaehoon Chung 
 S: Maintained
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 34c342b6f5..cd6bb8e2c4 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -77,6 +77,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_MUX=y
 CONFIG_CMD_OSD=y
 CONFIG_CMD_PCI=y
+CONFIG_CMD_PCI_MPS=y
 CONFIG_CMD_READ=y
 CONFIG_CMD_REMOTEPROC=y
 CONFIG_CMD_SPI=y
diff --git a/test/py/tests/test_pci_mps.py b/test/py/tests/test_pci_mps.py
new file mode 100644
index 00..8d33490f9f
--- /dev/null
+++ b/test/py/tests/test_pci_mps.py
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+import pytest
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('cmd_pci')
+@pytest.mark.buildconfigspec('cmd_pci_mps')
+def test_pci_mps_safe(u_boot_console):
+"""Tests that PCI MPS can be set to safe mode and uses 256 bytes."""
+
+response = u_boot_console.run_command('pci e; pci_mps s')
+expected_response = 'to 256B'
+assert(expected_response in response)
-- 
2.25.1



[PATCH 1/3] cmd: pci: Add command to set MPS of all PCIe devices

2023-03-07 Thread stcarlso
From: Stephen Carlson 

Enable tuning of the PCI Express MPS (Maximum Payload Size) of
each device. The Maximum Read Request Size is not altered.

The SAFE method uses the largest MPS value supported by all devices in the
system for each device. This method is the same algorithm as used by Linux
pci=pcie_bus_safe.

The PEER2PEER method sets all devices to the minimal (128 byte) MPS, which
allows hot plug of devices later that might only support the minimum size,
and ensures compatibility of DMA between two devices on the bus.

Signed-off-by: Stephen Carlson 
---
 cmd/Kconfig   |  10 +++
 cmd/Makefile  |   1 +
 cmd/pci_mps.c | 167 ++
 include/pci.h |   7 +++
 4 files changed, 185 insertions(+)
 create mode 100644 cmd/pci_mps.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index dc0446e02e..632c5c45db 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1390,6 +1390,16 @@ config CMD_PCI
  peripherals. Sub-commands allow bus enumeration, displaying and
  changing configuration space and a few other features.
 
+config CMD_PCI_MPS
+   bool "pci_mps - Configure PCI device MPS"
+   depends on PCI
+   help
+ Enables PCI Express Maximum Packet Size (MPS) tuning. This
+ command configures the PCI Express MPS of each endpoint to the
+ largest value supported by all devices below the root complex.
+ The Maximum Read Request Size will not be altered. This method is
+ the same algorithm as used by Linux pci=pcie_bus_safe.
+
 config CMD_PINMUX
bool "pinmux - show pins muxing"
depends on PINCTRL
diff --git a/cmd/Makefile b/cmd/Makefile
index 7b6ff73186..3365634843 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -133,6 +133,7 @@ obj-$(CONFIG_CMD_PART) += part.o
 obj-$(CONFIG_CMD_PCAP) += pcap.o
 ifdef CONFIG_PCI
 obj-$(CONFIG_CMD_PCI) += pci.o
+obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o
 endif
 obj-$(CONFIG_CMD_PINMUX) += pinmux.o
 obj-$(CONFIG_CMD_PMC) += pmc.o
diff --git a/cmd/pci_mps.c b/cmd/pci_mps.c
new file mode 100644
index 00..c67d007838
--- /dev/null
+++ b/cmd/pci_mps.c
@@ -0,0 +1,167 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2022 Microsoft Corporation 
+ * Stephen Carlson 
+ *
+ * PCI Express Maximum Packet Size (MPS) configuration
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#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;
+   int busnum = dev_seq(bus);
+
+   for (device_find_first_child(bus, &dev);
+dev && res == 0;
+device_find_next_child(&dev)) {
+   struct pci_child_plat *pplat;
+
+   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 maxi

[PATCH 0/3] Add command to set MPS of all PCI Express devices

2023-03-07 Thread stcarlso
From: Stephen Carlson 

This patch set adds support for configuring the Maximum Payload Size
(MPS) for attached PCI Express devices. Modifying the MPS can increase
PCI Express performance or ensure compatibility with hot-plugged
devices.

New config CONFIG_CMD_PCI_MPS. If enabled, a new "pci_mps" command will
be added that accepts an argument describing a strategy to configure the
PCI Express payload size for devices that are currently attached. Two
strategies are currently supported:

"safe" emulates the Linux kernel's pci=pcie_bus_safe and sets all devices
to the minimum MPS supported by all devices.

"peer2peer" sets all devices to an MPS of 128 bytes, the only size which
must be supported by all compliant PCI Express devices, to ensure that
all devices can directly communicate with each other and with devices that
are hotplugged later.

A test for the sandbox environment is also added by advertising a
larger supported Maximum Payload Size in the swapcase device and
verifying that the pci_mps command can read and configure the MPS.

Stephen Carlson (3):
  cmd: pci: Add command to set MPS of all PCIe devices
  drivers: pci: sandbox: Add stub sandbox PCI MPS support
  test: Add test for new command pci_mps

 MAINTAINERS   |   6 ++
 cmd/Kconfig   |  10 ++
 cmd/Makefile  |   1 +
 cmd/pci_mps.c | 167 ++
 configs/sandbox_defconfig |   1 +
 drivers/misc/swap_case.c  |   3 +
 include/pci.h |   7 ++
 test/py/tests/test_pci_mps.py |  13 +++
 8 files changed, 208 insertions(+)
 create mode 100644 cmd/pci_mps.c
 create mode 100644 test/py/tests/test_pci_mps.py

-- 
2.25.1



[PATCH 2/3] drivers: pci: sandbox: Add stub sandbox PCI MPS support

2023-03-07 Thread stcarlso
From: Stephen Carlson 

Reports the sandbox swapcase PCI Express device to support a 256 byte
Maximum Payload Size for MPS tuning tests.

Signed-off-by: Stephen Carlson 
---
 drivers/misc/swap_case.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/misc/swap_case.c b/drivers/misc/swap_case.c
index 7093ad1cd4..ee5c12bd0a 100644
--- a/drivers/misc/swap_case.c
+++ b/drivers/misc/swap_case.c
@@ -165,6 +165,9 @@ static int sandbox_swap_case_read_config(const struct 
udevice *emul,
case PCI_CAP_ID_EXP_OFFSET + PCI_CAP_LIST_NEXT:
*valuep = PCI_CAP_ID_MSIX_OFFSET;
break;
+   case PCI_CAP_ID_EXP_OFFSET + PCI_EXP_DEVCAP:
+   *valuep = PCI_EXP_DEVCAP_PAYLOAD_256B;
+   break;
case PCI_CAP_ID_MSIX_OFFSET:
if (sandbox_swap_case_use_ea(emul))
*valuep = (PCI_CAP_ID_EA_OFFSET << 8) | PCI_CAP_ID_MSIX;
-- 
2.25.1



[PATCH] armv8/fsl-lsch3: Suppress spurious warning on Layerscape CPUs

2022-03-29 Thread stcarlso
From: Stephen Carlson 

NXP/Freescale Layerscape CPUs support high-speed serial interfaces (SERDES)
that can be configured for the application. Interfaces not used by the
application can be set to protocol 0 to turn them off and save power, but
U-Boot would emit a warning that 0 was invalid for a SERDES protocol on
boot. Replace the warning text with a notice that the SERDES is disabled.

Signed-off-by: Stephen Carlson 
Cc: Priyanka Jain 
---
 arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c 
b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
index fad7a93566..181bd9c1b4 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
@@ -147,10 +147,14 @@ void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 
sd_prctl_mask,
cfg >>= sd_prctl_shift;
 
cfg = serdes_get_number(sd, cfg);
-   printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
+   if (cfg == 0) {
+   printf("SERDES%d is disabled\n", sd + 1);
+   } else {
+   printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, 
cfg);
 
-   if (!is_serdes_prtcl_valid(sd, cfg))
-   printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
+   if (!is_serdes_prtcl_valid(sd, cfg))
+   printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, 
cfg);
+   }
 
for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
-- 
2.17.1



[PATCH 1/2] drivers: mmc: Add wait_dat0 support for Freescale eSDHC driver

2021-08-17 Thread stcarlso
From: Stephen Carlson 

Adds an implementation of the wait_dat0 MMC operation for the Freescale
eSHDC driver, allowing the driver to continue when the card is ready
rather than waiting for the worst case time on each MMC switch operation.

Signed-off-by: Stephen Carlson 
---
 drivers/mmc/fsl_esdhc.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 1d98fa65c4..f74289a677 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -1145,6 +1146,20 @@ int fsl_esdhc_hs400_prepare_ddr(struct udevice *dev)
return 0;
 }
 
+static int fsl_esdhc_wait_dat0(struct udevice *dev, int state,
+  int timeout_us)
+{
+   int ret;
+   u32 tmp;
+   struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+   struct fsl_esdhc *regs = priv->esdhc_regs;
+
+   ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp,
+!!(tmp & PRSSTAT_DAT0) == !!state,
+timeout_us);
+   return ret;
+}
+
 static const struct dm_mmc_ops fsl_esdhc_ops = {
.get_cd = fsl_esdhc_get_cd,
.send_cmd   = fsl_esdhc_send_cmd,
@@ -1154,6 +1169,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops = {
 #endif
.reinit = fsl_esdhc_reinit,
.hs400_prepare_ddr = fsl_esdhc_hs400_prepare_ddr,
+   .wait_dat0 = fsl_esdhc_wait_dat0,
 };
 
 static const struct udevice_id fsl_esdhc_ids[] = {
-- 
2.17.1



[PATCH 0/2] drivers: mmc: Add wait_dat0 support for more devices

2021-08-17 Thread stcarlso
From: Stephen Carlson 

This patch adds eMMC driver support for polling the DAT0 data connection
on the Freescale LX devices and SDHCI compatible devices.

Polling until the card reports it is no longer busy increases eMMC
driver performance over the default behavior, which is to wait for the
worst case timeout specified by the card upon each mmc_switch operation.

This change has been tested on the Broadcom NS3 series (SDHCI) and
LX2160A series (Freescale/NXP eSDHC). U-Boot boot time savings depend on
the eMMC memory used, but can range from 100 to 500 ms or more.

Stephen Carlson (2):
  drivers: mmc: Add wait_dat0 support for Freescale eSDHC driver
  drivers: mmc: Add wait_dat0 support for sdhci driver

 drivers/mmc/fsl_esdhc.c | 16 
 drivers/mmc/sdhci.c | 20 
 include/sdhci.h |  2 ++
 3 files changed, 38 insertions(+)

-- 
2.17.1



[PATCH 2/2] drivers: mmc: Add wait_dat0 support for sdhci driver

2021-08-17 Thread stcarlso
From: Stephen Carlson 

Adds an implementation of the wait_dat0 MMC operation for the DM SDHCI
driver, allowing the driver to continue when the card is ready rather
than waiting for the worst case time on each MMC switch operation.

Signed-off-by: Stephen Carlson 
---
 drivers/mmc/sdhci.c | 20 
 include/sdhci.h |  2 ++
 2 files changed, 22 insertions(+)

diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index eea4701d8a..bb55e00ef5 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -775,6 +775,25 @@ static int sdhci_get_cd(struct udevice *dev)
return value;
 }
 
+static int sdhci_wait_dat0(struct udevice *dev, int state,
+  int timeout_us)
+{
+   int tmp;
+   struct mmc *mmc = mmc_get_mmc_dev(dev);
+   struct sdhci_host *host = mmc->priv;
+   unsigned long timeout = timer_get_us() + timeout_us;
+
+   // readx_poll_timeout is unsuitable because sdhci_readl accepts
+   // two arguments
+   do {
+   tmp = sdhci_readl(host, SDHCI_PRESENT_STATE);
+   if (!!(tmp & SDHCI_DATA_0_LVL_MASK) == !!state)
+   return 0;
+   } while (!timeout_us || !time_after(timer_get_us(), timeout));
+
+   return -ETIMEDOUT;
+}
+
 const struct dm_mmc_ops sdhci_ops = {
.send_cmd   = sdhci_send_command,
.set_ios= sdhci_set_ios,
@@ -783,6 +802,7 @@ const struct dm_mmc_ops sdhci_ops = {
 #ifdef MMC_SUPPORTS_TUNING
.execute_tuning = sdhci_execute_tuning,
 #endif
+   .wait_dat0  = sdhci_wait_dat0,
 };
 #else
 static const struct mmc_ops sdhci_ops = {
diff --git a/include/sdhci.h b/include/sdhci.h
index 0ae9471ad7..dd4eb41442 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -65,6 +65,8 @@
 #define  SDHCI_CARD_STATE_STABLE   BIT(17)
 #define  SDHCI_CARD_DETECT_PIN_LEVEL   BIT(18)
 #define  SDHCI_WRITE_PROTECT   BIT(19)
+#define  SDHCI_DATA_LVL_MASK   0x00F0
+#define   SDHCI_DATA_0_LVL_MASK BIT(20)
 
 #define SDHCI_HOST_CONTROL 0x28
 #define  SDHCI_CTRL_LEDBIT(0)
-- 
2.17.1