diff --git a/drivers/net/igb.c b/drivers/net/igb.c index 66b12f055f4..0c22215535e 100644 --- a/drivers/net/igb.c +++ b/drivers/net/igb.c @@ -274,6 +274,12 @@ static const struct netdev_ops_s g_igb_ops = * Private Functions *****************************************************************************/ +/* The device requires 32-bit register accesses, but volatile does not pin + * the access width: GCC 16 narrows a 32-bit load feeding a single bit test + * into a byte load. Launder the value through a register with an empty + * asm, on loads and stores both, to force the full-width access. + */ + /***************************************************************************** * Name: igb_getreg_mem *****************************************************************************/ @@ -281,8 +287,11 @@ static const struct netdev_ops_s g_igb_ops = static uint32_t igb_getreg_mem(FAR struct igb_driver_s *priv, unsigned int offset) { - uintptr_t addr = priv->base + offset; - return *((FAR volatile uint32_t *)addr); + uintptr_t addr = priv->base + offset; + uint32_t regval = *((FAR volatile uint32_t *)addr); + + __asm__ __volatile__("" : "+r"(regval)); + return regval; } /***************************************************************************** @@ -294,6 +303,8 @@ static void igb_putreg_mem(FAR struct igb_driver_s *priv, uint32_t value) { uintptr_t addr = priv->base + offset; + + __asm__ __volatile__("" : "+r"(value)); *((FAR volatile uint32_t *)addr) = value; }