This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 24132be56edaba09227f505a8ada2e03befd7803
Author: Justin Hammond <[email protected]>
AuthorDate: Sun Aug 16 16:03:55 2026 +0800

    drivers/usbhost: Read xHCI registers at the required access width.
    
    xHCI requires aligned accesses of each register's own size, and a
    controller may ignore narrower ones; QEMU's does.  volatile does not pin
    the access width: GCC 16.1.0 at -Os narrows a 32-bit load feeding a
    single bit test into a byte load, so polling USBSTS for HCH never
    observes the halted state.
    
    Launder each register value through a register with an empty asm, on
    loads and stores both, so the access is the width the source specifies.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Justin Hammond <[email protected]>
---
 drivers/usbhost/usbhost_xhci_pci.c | 46 +++++++++++++++++++++++++++++++-------
 1 file changed, 38 insertions(+), 8 deletions(-)

diff --git a/drivers/usbhost/usbhost_xhci_pci.c 
b/drivers/usbhost/usbhost_xhci_pci.c
index 03b40816887..68d5e06aa4e 100644
--- a/drivers/usbhost/usbhost_xhci_pci.c
+++ b/drivers/usbhost/usbhost_xhci_pci.c
@@ -519,6 +519,12 @@ static struct pci_driver_s g_pci_xhci_drv =
  * Private Functions
  ****************************************************************************/
 
+/* xHCI requires aligned accesses of each register's own size, and
+ * narrower ones may be ignored.  volatile does not pin the access width,
+ * so every accessor below launders the value through a register with an
+ * empty asm, on loads and stores both, to force the full-width access.
+ */
+
 /****************************************************************************
  * Name: xhci_capa_getreg
  *
@@ -530,8 +536,11 @@ static struct pci_driver_s g_pci_xhci_drv =
 static uint32_t xhci_capa_getreg(FAR struct usbhost_xhci_s *priv,
                                  unsigned int offset)
 {
-  uintptr_t addr = priv->capa_base + offset;
-  return *((FAR volatile uint32_t *)addr);
+  uintptr_t addr   = priv->capa_base + offset;
+  uint32_t  regval = *((FAR volatile uint32_t *)addr);
+
+  __asm__ __volatile__("" : "+r"(regval));
+  return regval;
 }
 
 /****************************************************************************
@@ -545,8 +554,11 @@ static uint32_t xhci_capa_getreg(FAR struct usbhost_xhci_s 
*priv,
 static uint8_t xhci_capa_getreg_1b(FAR struct usbhost_xhci_s *priv,
                                    unsigned int offset)
 {
-  uintptr_t addr = priv->capa_base + offset;
-  return *((FAR volatile uint8_t *)addr);
+  uintptr_t addr   = priv->capa_base + offset;
+  uint8_t   regval = *((FAR volatile uint8_t *)addr);
+
+  __asm__ __volatile__("" : "+r"(regval));
+  return regval;
 }
 
 /****************************************************************************
@@ -562,6 +574,8 @@ static void xhci_capa_putreg_1b(FAR struct usbhost_xhci_s 
*priv,
                                 uint8_t value)
 {
   uintptr_t addr = priv->capa_base + offset;
+
+  __asm__ __volatile__("" : "+r"(value));
   *((FAR volatile uint8_t *)addr) = value;
 }
 
@@ -576,8 +590,11 @@ static void xhci_capa_putreg_1b(FAR struct usbhost_xhci_s 
*priv,
 static uint32_t xhci_oper_getreg(FAR struct usbhost_xhci_s *priv,
                                  unsigned int offset)
 {
-  uintptr_t addr = priv->oper_base + offset;
-  return *((FAR volatile uint32_t *)addr);
+  uintptr_t addr   = priv->oper_base + offset;
+  uint32_t  regval = *((FAR volatile uint32_t *)addr);
+
+  __asm__ __volatile__("" : "+r"(regval));
+  return regval;
 }
 
 /****************************************************************************
@@ -593,6 +610,8 @@ static void xhci_oper_putreg(FAR struct usbhost_xhci_s 
*priv,
                              uint32_t value)
 {
   uintptr_t addr = priv->oper_base + offset;
+
+  __asm__ __volatile__("" : "+r"(value));
   *((FAR volatile uint32_t *)addr) = value;
 }
 
@@ -609,6 +628,8 @@ static void xhci_oper_putreg_8b(FAR struct usbhost_xhci_s 
*priv,
                                 uint64_t value)
 {
   uintptr_t addr = priv->oper_base + offset;
+
+  __asm__ __volatile__("" : "+r"(value));
   *((FAR volatile uint64_t *)addr) = value;
 }
 
@@ -623,8 +644,11 @@ static void xhci_oper_putreg_8b(FAR struct usbhost_xhci_s 
*priv,
 static uint32_t xhci_runt_getreg(FAR struct usbhost_xhci_s *priv,
                                  unsigned int offset)
 {
-  uintptr_t addr = priv->runt_base + offset;
-  return *((FAR volatile uint32_t *)addr);
+  uintptr_t addr   = priv->runt_base + offset;
+  uint32_t  regval = *((FAR volatile uint32_t *)addr);
+
+  __asm__ __volatile__("" : "+r"(regval));
+  return regval;
 }
 
 /****************************************************************************
@@ -640,6 +664,8 @@ static void xhci_runt_putreg(FAR struct usbhost_xhci_s 
*priv,
                              uint32_t value)
 {
   uintptr_t addr = priv->runt_base + offset;
+
+  __asm__ __volatile__("" : "+r"(value));
   *((FAR volatile uint32_t *)addr) = value;
 }
 
@@ -656,6 +682,8 @@ static void xhci_runt_putreg_8b(FAR struct usbhost_xhci_s 
*priv,
                                 uint64_t value)
 {
   uintptr_t addr = priv->runt_base + offset;
+
+  __asm__ __volatile__("" : "+r"(value));
   *((FAR volatile uint64_t *)addr) = value;
 }
 
@@ -672,6 +700,8 @@ static void xhci_door_putreg(FAR struct usbhost_xhci_s 
*priv,
                              uint32_t value)
 {
   uintptr_t addr = priv->door_base + offset;
+
+  __asm__ __volatile__("" : "+r"(value));
   *((FAR volatile uint32_t *)addr) = value;
 }
 

Reply via email to