diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
index 21a24218fc..af1fed1bc4 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
@@ -3,6 +3,7 @@
     Usb Bus Driver Binding and Bus IO Protocol.
 
 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -15,6 +16,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/Usb2HostController.h>
 #include <Protocol/UsbHostController.h>
 #include <Protocol/UsbIo.h>
+#include <Protocol/UsbAssociationIo.h>
 #include <Protocol/DevicePath.h>
 
 #include <Library/BaseLib.h>
@@ -29,10 +31,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include <IndustryStandard/Usb.h>
 
-typedef struct _USB_DEVICE     USB_DEVICE;
-typedef struct _USB_INTERFACE  USB_INTERFACE;
-typedef struct _USB_BUS        USB_BUS;
-typedef struct _USB_HUB_API    USB_HUB_API;
+typedef struct _USB_DEVICE       USB_DEVICE;
+typedef struct _USB_INTERFACE    USB_INTERFACE;
+typedef struct _USB_BUS          USB_BUS;
+typedef struct _USB_HUB_API      USB_HUB_API;
+typedef struct _USB_ASSOCIATION  USB_ASSOCIATION;
 
 #include "UsbUtility.h"
 #include "UsbDesc.h"
@@ -132,8 +135,9 @@ typedef struct _USB_HUB_API    USB_HUB_API;
 //
 #define  USB_BUS_TPL  TPL_NOTIFY
 
-#define  USB_INTERFACE_SIGNATURE  SIGNATURE_32 ('U', 'S', 'B', 'I')
-#define  USB_BUS_SIGNATURE        SIGNATURE_32 ('U', 'S', 'B', 'B')
+#define  USB_INTERFACE_SIGNATURE    SIGNATURE_32 ('U', 'S', 'B', 'I')
+#define  USB_BUS_SIGNATURE          SIGNATURE_32 ('U', 'S', 'B', 'B')
+#define  USB_ASSOCIATION_SIGNATURE  SIGNATURE_32 ('U', 'S', 'B', 'A')
 
 #define USB_BIT(a)                 ((UINTN)(1 << (a)))
 #define USB_BIT_IS_SET(Data, Bit)  ((BOOLEAN)(((Data) & (Bit)) == (Bit)))
@@ -141,6 +145,9 @@ typedef struct _USB_HUB_API    USB_HUB_API;
 #define USB_INTERFACE_FROM_USBIO(a) \
           CR(a, USB_INTERFACE, UsbIo, USB_INTERFACE_SIGNATURE)
 
+#define USB_ASSOCIATION_FROM_USBIA(a) \
+          CR(a, USB_ASSOCIATION, UsbIaProtocol, USB_ASSOCIATION_SIGNATURE)
+
 #define USB_BUS_FROM_THIS(a) \
           CR(a, USB_BUS, BusId, USB_BUS_SIGNATURE)
 
@@ -176,6 +183,9 @@ struct _USB_DEVICE {
   UINT16                                LangId[USB_MAX_LANG_ID];
   UINT16                                TotalLangId;
 
+  UINT8                                 NumOfAssociation;
+  USB_ASSOCIATION                       *Associations[USB_MAX_ASSOCIATION];
+
   UINT8                                 NumOfInterface;
   USB_INTERFACE                         *Interfaces[USB_MAX_INTERFACE];
 
@@ -230,6 +240,23 @@ struct _USB_INTERFACE {
   UINT8                       MaxSpeed;
 };
 
+//
+// Stands for a function implemented using interface association
+//
+struct _USB_ASSOCIATION {
+  UINTN                                       Signature;
+  USB_DEVICE                                  *Device;
+  USB_INTERFACE_ASSOCIATION_DESC              *IaDesc;
+
+  //
+  // Handles and protocols
+  //
+  EFI_HANDLE                                  Handle;
+  EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL    UsbIaProtocol;
+  EFI_DEVICE_PATH_PROTOCOL                    *DevicePath;
+  BOOLEAN                                     IsManaged;
+};
+
 //
 // Stands for the current USB Bus
 //
@@ -751,9 +778,10 @@ UsbBusControllerDriverStop (
   IN EFI_HANDLE                   *ChildHandleBuffer
   );
 
-extern EFI_USB_IO_PROTOCOL           mUsbIoProtocol;
-extern EFI_DRIVER_BINDING_PROTOCOL   mUsbBusDriverBinding;
-extern EFI_COMPONENT_NAME_PROTOCOL   mUsbBusComponentName;
-extern EFI_COMPONENT_NAME2_PROTOCOL  mUsbBusComponentName2;
+extern EFI_USB_IO_PROTOCOL                       mUsbIoProtocol;
+extern EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL  mUsbIaProtocol;
+extern EFI_DRIVER_BINDING_PROTOCOL               mUsbBusDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL               mUsbBusComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL              mUsbBusComponentName2;
 
 #endif
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
index dd85894346..2b866fc204 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
@@ -2,6 +2,7 @@
 #  The Usb Bus Dxe driver is used to enumerate and manage all attached usb devices.
 #
 #  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -40,10 +41,11 @@
   UsbUtility.c
   UsbDesc.h
   UsbBus.h
+  UsbIntfAssoc.c
 
 [Packages]
   MdePkg/MdePkg.dec
-
+  MdeModulePkg/MdeModulePkg.dec
 
 [LibraryClasses]
   MemoryAllocationLib
@@ -58,6 +60,7 @@
 
 [Protocols]
   gEfiUsbIoProtocolGuid                         ## BY_START
+  gEdkiiUsbInterfaceAssociationProtocolGuid
   ## TO_START
   ## BY_START
   gEfiDevicePathProtocolGuid
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
index 8b078e7e49..c57038ec56 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.c
@@ -3,6 +3,7 @@
     Manage Usb Descriptor List
 
 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -46,6 +47,24 @@ UsbFreeInterfaceDesc (
   FreePool (Setting);
 }
 
+/**
+  Free the interface association descriptor
+
+  @param  Iad               The interface association descriptor to free.
+
+**/
+VOID
+UsbFreeInterfaceAssociationDesc (
+  IN USB_INTERFACE_ASSOCIATION_DESC  *Iad
+  )
+{
+  if (Iad->Interfaces != NULL) {
+    FreePool (Iad->Interfaces);
+  }
+
+  FreePool (Iad);
+}
+
 /**
   Free a configuration descriptor with its interface
   descriptors. It may be initialized partially.
@@ -167,6 +186,11 @@ UsbCreateDesc (
       CtrlLen = sizeof (USB_ENDPOINT_DESC);
       break;
 
+    case USB_DESC_TYPE_INTERFACE_ASSOCIATION:
+      DescLen = sizeof (EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR);
+      CtrlLen = sizeof (USB_INTERFACE_ASSOCIATION_DESC);
+      break;
+
     default:
       ASSERT (FALSE);
       return NULL;
@@ -231,6 +255,7 @@ UsbCreateDesc (
     return NULL;
   }
 
+  ASSERT (CtrlLen >= DescLen);
   CopyMem (Desc, Head, (UINTN)DescLen);
 
   *Consumed = Offset;
@@ -319,6 +344,85 @@ ON_ERROR:
   return NULL;
 }
 
+/**
+  Parse an interface association and its interfaces.
+
+  @param  DescBuf               The buffer of raw interface association descriptor.
+  @param  Len                   The length of the raw descriptor buffer.
+  @param  Config                The device configuration buffer.
+  @param  Consumed              The number of raw descriptor consumed.
+
+  @return The created interface association descriptor or NULL if failed.
+
+**/
+USB_INTERFACE_ASSOCIATION_DESC *
+UsbParseInterfaceAssociationDesc (
+  IN UINT8            *DescBuf,
+  IN UINTN            Len,
+  IN USB_CONFIG_DESC  *Config,
+  OUT UINTN           *Consumed
+  )
+{
+  USB_INTERFACE_ASSOCIATION_DESC  *Iad;
+  UINT8                           Index;
+  UINT8                           IfIndex;
+  UINT8                           i;
+  UINTN                           NumIf;
+  UINTN                           Used;
+
+  *Consumed = 0;
+  Iad       = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_INTERFACE_ASSOCIATION, &Used);
+
+  if (Iad == NULL) {
+    return NULL;
+  }
+
+  //
+  // Create an array to hold the association's interfaces
+  //
+  NumIf = Iad->Desc.InterfaceCount;
+
+  DEBUG ((
+    DEBUG_INFO,
+    "UsbParseInterfaceAssociationDesc: interface association has %d interfaces\n",
+    (UINT32)NumIf
+    ));
+
+  ASSERT (NumIf > 0);
+  if (NumIf == 0) {
+    DEBUG ((DEBUG_ERROR, "UsbParseInterfaceAssociationDesc: no interfaces are reported for this association.\n"));
+    goto ON_ERROR;
+  }
+
+  Iad->Interfaces = AllocateZeroPool (sizeof (USB_INTERFACE_DESC *) * NumIf);
+
+  //
+  // Populate interfaces for this association
+  //
+  IfIndex = 0;
+  for (Index = Iad->Desc.FirstInterface; Index < (UINT8)(Iad->Desc.FirstInterface + Iad->Desc.InterfaceCount); Index++) {
+    for (i = 0; i < Config->Desc.NumInterfaces; i++) {
+      if (Index == Config->Interfaces[i]->Settings[0]->Desc.InterfaceNumber) {
+        break;
+      }
+    }
+
+    if (i == Config->Desc.NumInterfaces) {
+      DEBUG ((DEBUG_ERROR, "UsbParseInterfaceAssociationDesc: interface %d not found.\n", Index));
+      goto ON_ERROR;
+    }
+
+    Iad->Interfaces[IfIndex++] = Config->Interfaces[i];
+  }
+
+  *Consumed = Used;
+  return Iad;
+
+ON_ERROR:
+  UsbFreeInterfaceAssociationDesc (Iad);
+  return NULL;
+}
+
 /**
   Parse the configuration descriptor and its interfaces.
 
@@ -334,16 +438,22 @@ UsbParseConfigDesc (
   IN UINTN  Len
   )
 {
-  USB_CONFIG_DESC        *Config;
-  USB_INTERFACE_SETTING  *Setting;
-  USB_INTERFACE_DESC     *Interface;
-  UINTN                  Index;
-  UINTN                  NumIf;
-  UINTN                  Consumed;
+  USB_CONFIG_DESC                 *Config;
+  USB_INTERFACE_SETTING           *Setting;
+  USB_INTERFACE_DESC              *Interface;
+  UINTN                           Index;
+  UINTN                           NumIf;
+  UINTN                           Consumed;
+  UINT8                           *Buffer;
+  UINTN                           Length;
+  USB_INTERFACE_ASSOCIATION_DESC  *Iad;
 
   ASSERT (DescBuf != NULL);
 
-  Config = UsbCreateDesc (DescBuf, Len, USB_DESC_TYPE_CONFIG, &Consumed);
+  Buffer = DescBuf;
+  Length = Len;
+
+  Config = UsbCreateDesc (Buffer, Length, USB_DESC_TYPE_CONFIG, &Consumed);
 
   if (Config == NULL) {
     return NULL;
@@ -384,15 +494,15 @@ UsbParseConfigDesc (
   // setting 1|interface 1, setting 0|interface 2, setting 0|. Check
   // USB2.0 spec, page 267.
   //
-  DescBuf += Consumed;
-  Len     -= Consumed;
+  Buffer += Consumed;
+  Length -= Consumed;
 
   //
   // Make allowances for devices that return extra data at the
   // end of their config descriptors
   //
-  while (Len >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) {
-    Setting = UsbParseInterfaceDesc (DescBuf, Len, &Consumed);
+  while (Length >= sizeof (EFI_USB_INTERFACE_DESCRIPTOR)) {
+    Setting = UsbParseInterfaceDesc (Buffer, Length, &Consumed);
 
     if (Setting == NULL) {
       DEBUG ((DEBUG_ERROR, "UsbParseConfigDesc: warning: failed to get interface setting, stop parsing now.\n"));
@@ -416,8 +526,36 @@ UsbParseConfigDesc (
     Interface->Settings[Interface->NumOfSetting] = Setting;
     Interface->NumOfSetting++;
 
-    DescBuf += Consumed;
-    Len     -= Consumed;
+    Buffer += Consumed;
+    Length -= Consumed;
+  }
+
+  //
+  // Process interface association descriptors.
+  //
+  Buffer = DescBuf;
+  Length = Len;
+
+  while (Length >= sizeof (EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR)) {
+    Iad = UsbParseInterfaceAssociationDesc (Buffer, Length, Config, &Consumed);
+
+    if (Iad == NULL) {
+      break;
+    }
+
+    //
+    // Insert the association descriptor to the corresponding set.
+    //
+    if (Config->NumOfIads >= USB_MAX_ASSOCIATION) {
+      DEBUG ((DEBUG_ERROR, "UsbParseConfigDesc: too many interface association descriptors in this configuration.\n"));
+      goto ON_ERROR;
+    }
+
+    Config->Iads[Config->NumOfIads] = Iad;
+    Config->NumOfIads++;
+
+    Buffer += Consumed;
+    Length -= Consumed;
   }
 
   return Config;
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h
index ce205e706d..03f38c7afa 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbDesc.h
@@ -3,6 +3,7 @@
     Manage Usb Descriptor List
 
 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -11,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define _USB_DESCRIPTOR_H_
 
 #define USB_MAX_INTERFACE_SETTING  256
+#define USB_MAX_ASSOCIATION        16
 
 //
 // The RequestType in EFI_USB_DEVICE_REQUEST is composed of
@@ -62,8 +64,15 @@ typedef struct {
 } USB_INTERFACE_DESC;
 
 typedef struct {
-  EFI_USB_CONFIG_DESCRIPTOR    Desc;
-  USB_INTERFACE_DESC           **Interfaces;
+  EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR    Desc;
+  USB_INTERFACE_DESC                          **Interfaces;
+} USB_INTERFACE_ASSOCIATION_DESC;
+
+typedef struct {
+  EFI_USB_CONFIG_DESCRIPTOR         Desc;
+  USB_INTERFACE_ASSOCIATION_DESC    *Iads[USB_MAX_ASSOCIATION];
+  UINT8                             NumOfIads;
+  USB_INTERFACE_DESC                **Interfaces;
 } USB_CONFIG_DESC;
 
 typedef struct {
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
index b3a40639f2..f6e5418931 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
@@ -3,6 +3,7 @@
     Usb bus enumeration support.
 
 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -41,6 +42,41 @@ UsbGetEndpointDesc (
   return NULL;
 }
 
+/**
+  Check if given Usb interface is a part of Usb association.
+
+  @param[in]  Device    The device may have the interface association descriptor.
+  @param[in]  IfDesc    The interface descriptor to check for.
+  @param[out] IfAssoc   The USB association device pointer.
+
+  @retval EFI_SUCCESS   IfDesc is found within associations, IfAssoc has valid pointer.
+  @retval EFI_NOT_FOUND IfDesc does no belong to any association.
+
+**/
+EFI_STATUS
+GetInterfaceAssociation (
+  IN USB_DEVICE          *Device,
+  IN USB_INTERFACE_DESC  *IfDesc,
+  OUT USB_ASSOCIATION    **IfAssoc
+  )
+{
+  UINTN            Index;
+  UINTN            i;
+  USB_ASSOCIATION  *Ia;
+
+  for (Index = 0; Index < Device->NumOfAssociation; Index++) {
+    Ia = Device->Associations[Index];
+    for (i = 0; i < Ia->IaDesc->Desc.InterfaceCount; i++) {
+      if (IfDesc->Settings[0]->Desc.InterfaceNumber == Ia->IaDesc->Interfaces[i]->Settings[0]->Desc.InterfaceNumber) {
+        *IfAssoc = Ia;
+        return EFI_SUCCESS;
+      }
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
 /**
   Free the resource used by USB interface.
 
@@ -54,9 +90,25 @@ UsbFreeInterface (
   IN USB_INTERFACE  *UsbIf
   )
 {
-  EFI_STATUS  Status;
+  EFI_STATUS       Status;
+  USB_ASSOCIATION  *UsbIa;
 
-  UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+  Status = GetInterfaceAssociation (UsbIf->Device, UsbIf->IfDesc, &UsbIa);
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // Close USB Interface Association Protocol by Child
+    //
+    Status = gBS->CloseProtocol (
+                    UsbIa->Handle,
+                    &gEdkiiUsbInterfaceAssociationProtocolGuid,
+                    mUsbBusDriverBinding.DriverBindingHandle,
+                    UsbIf->Handle
+                    );
+    DEBUG ((DEBUG_INFO, "UsbFreeInterface: close IAD protocol by child, %r\n", Status));
+  } else {
+    UsbCloseHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+  }
 
   Status = gBS->UninstallMultipleProtocolInterfaces (
                   UsbIf->Handle,
@@ -73,7 +125,66 @@ UsbFreeInterface (
 
     FreePool (UsbIf);
   } else {
-    UsbOpenHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+    Status = GetInterfaceAssociation (UsbIf->Device, UsbIf->IfDesc, &UsbIa);
+
+    if (!EFI_ERROR (Status)) {
+      //
+      // Reopen USB Interface Assiciation Protocol by Child
+      //
+      Status = gBS->OpenProtocol (
+                      UsbIa->Handle,
+                      &gEdkiiUsbInterfaceAssociationProtocolGuid,
+                      (VOID **)&UsbIa,
+                      mUsbBusDriverBinding.DriverBindingHandle,
+                      UsbIf->Handle,
+                      EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                      );
+      DEBUG ((DEBUG_INFO, "UsbFreeInterface: reopen IAD for child, Status = %r\n", Status));
+    } else {
+      //
+      // Reopen USB Host Controller Protocol by Child
+      //
+      Status = UsbOpenHostProtoByChild (UsbIf->Device->Bus, UsbIf->Handle);
+      DEBUG ((DEBUG_INFO, "UsbFreeInterface: reopen host controller for child, Status = %r\n", Status));
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Free the resource used by USB association.
+
+  @param  UsbIa                 The USB association to free.
+
+  @retval EFI_ACCESS_DENIED     The Usb association resource is still occupied.
+  @retval EFI_SUCCESS           The Usb association resource is freed.
+
+**/
+EFI_STATUS
+UsbFreeAssociation (
+  IN USB_ASSOCIATION  *UsbIa
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  UsbIa->Handle,
+                  &gEfiDevicePathProtocolGuid,
+                  UsbIa->DevicePath,
+                  &gEdkiiUsbInterfaceAssociationProtocolGuid,
+                  &UsbIa->UsbIaProtocol,
+                  NULL
+                  );
+
+  if (!EFI_ERROR (Status)) {
+    if (UsbIa->DevicePath != NULL) {
+      FreePool (UsbIa->DevicePath);
+    }
+
+    FreePool (UsbIa);
+  } else {
+    UsbOpenHostProtoByChild (UsbIa->Device->Bus, UsbIa->Handle);
   }
 
   return Status;
@@ -82,6 +193,7 @@ UsbFreeInterface (
 /**
   Create an interface for the descriptor IfDesc. Each
   device's configuration can have several interfaces.
+  Interface may belong to interface association.
 
   @param  Device                The device has the interface descriptor.
   @param  IfDesc                The interface descriptor.
@@ -95,10 +207,12 @@ UsbCreateInterface (
   IN USB_INTERFACE_DESC  *IfDesc
   )
 {
-  USB_DEVICE_PATH  UsbNode;
-  USB_INTERFACE    *UsbIf;
-  USB_INTERFACE    *HubIf;
-  EFI_STATUS       Status;
+  USB_DEVICE_PATH           UsbNode;
+  USB_INTERFACE             *UsbIf;
+  USB_INTERFACE             *HubIf;
+  USB_ASSOCIATION           *UsbIa;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePathProtocol;
+  EFI_STATUS                Status;
 
   UsbIf = AllocateZeroPool (sizeof (USB_INTERFACE));
 
@@ -128,10 +242,17 @@ UsbCreateInterface (
 
   SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
 
-  HubIf = Device->ParentIf;
-  ASSERT (HubIf != NULL);
+  Status = GetInterfaceAssociation (Device, IfDesc, &UsbIa);
+
+  if (!EFI_ERROR (Status)) {
+    DevicePathProtocol = UsbIa->DevicePath;
+  } else {
+    HubIf = Device->ParentIf;
+    ASSERT (HubIf != NULL);
+    DevicePathProtocol = HubIf->DevicePath;
+  }
 
-  UsbIf->DevicePath = AppendDevicePathNode (HubIf->DevicePath, &UsbNode.Header);
+  UsbIf->DevicePath = AppendDevicePathNode (DevicePathProtocol, &UsbNode.Header);
 
   if (UsbIf->DevicePath == NULL) {
     DEBUG ((DEBUG_ERROR, "UsbCreateInterface: failed to create device path\n"));
@@ -154,10 +275,28 @@ UsbCreateInterface (
     goto ON_ERROR;
   }
 
-  //
-  // Open USB Host Controller Protocol by Child
-  //
-  Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);
+  Status = GetInterfaceAssociation (Device, IfDesc, &UsbIa);
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // Open USB Interface Assiciation Protocol by Child
+    //
+    Status = gBS->OpenProtocol (
+                    UsbIa->Handle,
+                    &gEdkiiUsbInterfaceAssociationProtocolGuid,
+                    (VOID **)&UsbIa,
+                    mUsbBusDriverBinding.DriverBindingHandle,
+                    UsbIf->Handle,
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+                    );
+    DEBUG ((DEBUG_INFO, "UsbCreateInterface: open IAD for child, Status = %r\n", Status));
+  } else {
+    //
+    // Open USB Host Controller Protocol by Child
+    //
+    Status = UsbOpenHostProtoByChild (Device->Bus, UsbIf->Handle);
+    DEBUG ((DEBUG_INFO, "UsbCreateInterface: open host controller for child, Status = %r\n", Status));
+  }
 
   if (EFI_ERROR (Status)) {
     gBS->UninstallMultipleProtocolInterfaces (
@@ -184,6 +323,112 @@ ON_ERROR:
   return NULL;
 }
 
+/**
+  Create an interface association instance and install protocols to manage it.
+
+  @param  Device        The Usb device that has the interface association.
+  @param  Index         The interface association index within Device.
+  @param  IfAssocDesc   The interface association descriptor.
+
+  @return The created USB interface association, or NULL.
+
+**/
+USB_ASSOCIATION *
+UsbCreateAssociation (
+  IN USB_DEVICE                      *Device,
+  IN UINT8                           Index,
+  IN USB_INTERFACE_ASSOCIATION_DESC  *IfAssocDesc
+  )
+{
+  USB_DEVICE_PATH  UsbNode;
+  USB_ASSOCIATION  *UsbAssoc;
+  EFI_STATUS       Status;
+
+  UsbAssoc = AllocateZeroPool (sizeof (USB_ASSOCIATION));
+
+  if (UsbAssoc == NULL) {
+    return NULL;
+  }
+
+  UsbAssoc->Signature = USB_ASSOCIATION_SIGNATURE;
+  UsbAssoc->Device    = Device;
+  UsbAssoc->IaDesc    = IfAssocDesc;
+
+  CopyMem (
+    &(UsbAssoc->UsbIaProtocol),
+    &mUsbIaProtocol,
+    sizeof (EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL)
+    );
+
+  //
+  // Install USB association protocols
+  //
+  // Device path protocol for the association has the USB node similar to the
+  // one installed for USB interface.
+  //
+
+  UsbNode.Header.Type      = MESSAGING_DEVICE_PATH;
+  UsbNode.Header.SubType   = MSG_USB_DP;
+  UsbNode.ParentPortNumber = Device->ParentPort;
+  UsbNode.InterfaceNumber  = Index;
+
+  SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
+
+  ASSERT (Device->ParentIf != NULL);
+
+  UsbAssoc->DevicePath = AppendDevicePathNode (Device->ParentIf->DevicePath, &UsbNode.Header);
+
+  if (UsbAssoc->DevicePath == NULL) {
+    DEBUG ((DEBUG_ERROR, "UsbCreateAssociation: failed to create device path\n"));
+
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_ERROR;
+  }
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &UsbAssoc->Handle,
+                  &gEfiDevicePathProtocolGuid,
+                  UsbAssoc->DevicePath,
+                  &gEdkiiUsbInterfaceAssociationProtocolGuid,
+                  &UsbAssoc->UsbIaProtocol,
+                  NULL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "UsbCreateAssociation: failed to install UsbIad - %r\n", Status));
+    goto ON_ERROR;
+  }
+
+  //
+  // Open USB Host Controller Protocol by Child
+  //
+  Status = UsbOpenHostProtoByChild (Device->Bus, UsbAssoc->Handle);
+
+  if (EFI_ERROR (Status)) {
+    gBS->UninstallMultipleProtocolInterfaces (
+           UsbAssoc->Handle,
+           &gEfiDevicePathProtocolGuid,
+           UsbAssoc->DevicePath,
+           &gEdkiiUsbInterfaceAssociationProtocolGuid,
+           &UsbAssoc->UsbIaProtocol,
+           NULL
+           );
+
+    DEBUG ((DEBUG_ERROR, "UsbCreateAssociation: failed to open host for child - %r\n", Status));
+    goto ON_ERROR;
+  }
+
+  return UsbAssoc;
+
+ON_ERROR:
+  if (UsbAssoc->DevicePath != NULL) {
+    FreePool (UsbAssoc->DevicePath);
+  }
+
+  FreePool (UsbAssoc);
+  return NULL;
+}
+
 /**
   Free the resource used by this USB device.
 
@@ -236,6 +481,41 @@ UsbCreateDevice (
   return Device;
 }
 
+/**
+  Connect USB controller at TPL_CALLBACK
+
+  This function is called in both UsbIoControlTransfer and
+  the timer callback in hub enumeration. So, at least it is
+  called at TPL_CALLBACK. Some driver sitting on USB has
+  twisted TPL used. It should be no problem for us to connect
+  or disconnect at CALLBACK.
+
+  @param  Handle        Controller handle to be connected
+
+**/
+EFI_STATUS
+UsbConnectController (
+  EFI_HANDLE  Handle
+  )
+{
+  EFI_STATUS  Status;
+  EFI_TPL     OldTpl;
+
+  OldTpl = UsbGetCurrentTpl ();
+  DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL before connect is %d, %p\n", (UINT32)OldTpl, Handle));
+
+  gBS->RestoreTPL (TPL_CALLBACK);
+
+  Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
+
+  DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl ()));
+  ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
+
+  gBS->RaiseTPL (OldTpl);
+
+  return Status;
+}
+
 /**
   Connect the USB interface with its driver. EFI USB bus will
   create a USB interface for each separate interface descriptor.
@@ -252,7 +532,6 @@ UsbConnectDriver (
   )
 {
   EFI_STATUS  Status;
-  EFI_TPL     OldTpl;
 
   Status = EFI_SUCCESS;
 
@@ -264,30 +543,12 @@ UsbConnectDriver (
     DEBUG ((DEBUG_INFO, "UsbConnectDriver: found a hub device\n"));
     Status = mUsbHubApi.Init (UsbIf);
   } else {
-    //
-    // This function is called in both UsbIoControlTransfer and
-    // the timer callback in hub enumeration. So, at least it is
-    // called at TPL_CALLBACK. Some driver sitting on USB has
-    // twisted TPL used. It should be no problem for us to connect
-    // or disconnect at CALLBACK.
-    //
-
     //
     // Only recursively wanted usb child device
     //
     if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {
-      OldTpl = UsbGetCurrentTpl ();
-      DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL before connect is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
-
-      gBS->RestoreTPL (TPL_CALLBACK);
-
-      Status           = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
+      Status           = UsbConnectController (UsbIf->Handle);
       UsbIf->IsManaged = (BOOLEAN) !EFI_ERROR (Status);
-
-      DEBUG ((DEBUG_INFO, "UsbConnectDriver: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl ()));
-      ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
-
-      gBS->RaiseTPL (OldTpl);
     }
   }
 
@@ -378,6 +639,7 @@ UsbSelectConfig (
   USB_INTERFACE       *UsbIf;
   EFI_STATUS          Status;
   UINT8               Index;
+  USB_ASSOCIATION     *UsbIa;
 
   //
   // Locate the active config, then set the device's pointer
@@ -393,7 +655,7 @@ UsbSelectConfig (
     }
   }
 
-  if (Index == DevDesc->Desc.NumConfigurations) {
+  if ((ConfigDesc == NULL) || (Index == DevDesc->Desc.NumConfigurations)) {
     return EFI_NOT_FOUND;
   }
 
@@ -406,6 +668,19 @@ UsbSelectConfig (
     Device->Address
     ));
 
+  //
+  // Create interfaces for each USB interface association descriptor.
+  //
+  Device->NumOfAssociation = ConfigDesc->NumOfIads;
+
+  for (Index = 0; Index < ConfigDesc->NumOfIads; Index++) {
+    DEBUG ((DEBUG_INFO, "UsbSelectConfig: process IAD %d\n", Index));
+
+    UsbIa = UsbCreateAssociation (Device, Index, ConfigDesc->Iads[Index]);
+    ASSERT (Index < USB_MAX_ASSOCIATION);
+    Device->Associations[Index] = UsbIa;
+  }
+
   //
   // Create interfaces for each USB interface descriptor.
   //
@@ -448,9 +723,55 @@ UsbSelectConfig (
 
   Device->NumOfInterface = Index;
 
+  //
+  // Connect association device drivers. Connection may fail if if device driver has been already
+  // started for any UsbIo that belongs to the association.
+  //
+  for (Index = 0; Index < Device->NumOfAssociation; Index++) {
+    Status                                 = gBS->ConnectController (Device->Associations[Index]->Handle, NULL, NULL, TRUE);
+    Device->Associations[Index]->IsManaged = (BOOLEAN) !EFI_ERROR (Status);
+
+    DEBUG ((DEBUG_INFO, "UsbSelectConfig: association driver connect: %r\n", Status));
+  }
+
   return EFI_SUCCESS;
 }
 
+/**
+  Disconnect USB controller at TPL_CALLBACK
+
+  This function is called in both UsbIoControlTransfer and
+  the timer callback in hub enumeration. So, at least it is
+  called at TPL_CALLBACK. Some driver sitting on USB has
+  twisted TPL used. It should be no problem for us to connect
+  or disconnect at CALLBACK.
+
+  @param  Handle        Controller handle to be disconnected
+
+**/
+EFI_STATUS
+UsbDisconnectController (
+  EFI_HANDLE  Handle
+  )
+{
+  EFI_TPL     OldTpl;
+  EFI_STATUS  Status;
+
+  OldTpl = UsbGetCurrentTpl ();
+  DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: old TPL is %d, %p\n", (UINT32)OldTpl, Handle));
+
+  gBS->RestoreTPL (TPL_CALLBACK);
+
+  Status = gBS->DisconnectController (Handle, NULL, NULL);
+
+  DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl (), Status));
+  ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
+
+  gBS->RaiseTPL (OldTpl);
+
+  return Status;
+}
+
 /**
   Disconnect the USB interface with its driver.
 
@@ -462,7 +783,6 @@ UsbDisconnectDriver (
   IN USB_INTERFACE  *UsbIf
   )
 {
-  EFI_TPL     OldTpl;
   EFI_STATUS  Status;
 
   //
@@ -473,27 +793,11 @@ UsbDisconnectDriver (
   if (UsbIf->IsHub) {
     Status = UsbIf->HubApi->Release (UsbIf);
   } else if (UsbIf->IsManaged) {
-    //
-    // This function is called in both UsbIoControlTransfer and
-    // the timer callback in hub enumeration. So, at least it is
-    // called at TPL_CALLBACK. Some driver sitting on USB has
-    // twisted TPL used. It should be no problem for us to connect
-    // or disconnect at CALLBACK.
-    //
-    OldTpl = UsbGetCurrentTpl ();
-    DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: old TPL is %d, %p\n", (UINT32)OldTpl, UsbIf->Handle));
+    Status = UsbDisconnectController (UsbIf->Handle);
 
-    gBS->RestoreTPL (TPL_CALLBACK);
-
-    Status = gBS->DisconnectController (UsbIf->Handle, NULL, NULL);
     if (!EFI_ERROR (Status)) {
       UsbIf->IsManaged = FALSE;
     }
-
-    DEBUG ((DEBUG_INFO, "UsbDisconnectDriver: TPL after disconnect is %d, %d\n", (UINT32)UsbGetCurrentTpl (), Status));
-    ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
-
-    gBS->RaiseTPL (OldTpl);
   }
 
   return Status;
@@ -510,10 +814,11 @@ UsbRemoveConfig (
   IN USB_DEVICE  *Device
   )
 {
-  USB_INTERFACE  *UsbIf;
-  UINTN          Index;
-  EFI_STATUS     Status;
-  EFI_STATUS     ReturnStatus;
+  USB_INTERFACE    *UsbIf;
+  USB_ASSOCIATION  *UsbIa;
+  UINTN            Index;
+  EFI_STATUS       Status;
+  EFI_STATUS       ReturnStatus;
 
   //
   // Remove each interface of the device
@@ -543,6 +848,35 @@ UsbRemoveConfig (
   }
 
   Device->ActiveConfig = NULL;
+
+  if (EFI_ERROR (ReturnStatus)) {
+    return ReturnStatus;
+  }
+
+  // ReturnStatus is EFI_SUCCESS
+
+  //
+  // Remove each interface association
+  //
+  for (Index = 0; Index < Device->NumOfAssociation; Index++) {
+    UsbIa = Device->Associations[Index];
+
+    Status = UsbDisconnectController (UsbIa->Handle);
+    if (!EFI_ERROR (Status)) {
+      Status = UsbFreeAssociation (UsbIa);
+      DEBUG ((DEBUG_INFO, "UsbRemoveConfig: free association: %r\n", Status));
+      if (EFI_ERROR (Status)) {
+        UsbConnectController (UsbIa->Handle);
+      }
+    }
+
+    if (!EFI_ERROR (Status)) {
+      Device->Associations[Index] = NULL;
+    } else {
+      ReturnStatus = Status;
+    }
+  }
+
   return ReturnStatus;
 }
 
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbIntfAssoc.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbIntfAssoc.c
new file mode 100644
index 0000000000..15ea41dce9
--- /dev/null
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbIntfAssoc.c
@@ -0,0 +1,153 @@
+/** @file
+
+  Usb Interface Association Protocol implementation.
+
+Copyright (c) 2025, American Megatrends International, LLC. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UsbBus.h"
+
+/**
+  Get the interface from interface association.
+
+  @param[in]  UsbIa   A pointer to the interface association data.
+  @param[in]  InterfaceNumber Interface to look for inside the association.
+
+  @retval A pointer to the interface data
+  @retval NULL  Interface is not found in the association.
+
+**/
+USB_INTERFACE_DESC *
+UsbAssocFindInterface (
+  IN USB_ASSOCIATION  *UsbIa,
+  IN UINT8            InterfaceNumber
+  )
+{
+  UINT8  Index;
+  UINT8  Intrf;
+
+  Intrf = UsbIa->IaDesc->Desc.FirstInterface;
+  for (Index = 0; Index < UsbIa->IaDesc->Desc.InterfaceCount; Index++) {
+    if (InterfaceNumber == Intrf) {
+      return UsbIa->IaDesc->Interfaces[Index];
+    }
+
+    Intrf++;
+  }
+
+  DEBUG ((DEBUG_ERROR, "UsbAssocFindInterface: interface 0x%x does not belong to this association\n", InterfaceNumber));
+  return NULL;
+}
+
+/**
+  Get the USB Interface Association Descriptor from the current USB configuration.
+
+  @param[in] This              A pointer to the EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL instance.
+  @param[out] Descriptor       A pointer to the caller allocated USB Interface Association Descriptor.
+
+  @retval EFI_SUCCESS           The descriptor was retrieved successfully.
+  @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbIaGetAssociationDescriptor (
+  IN  EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL  *This,
+  OUT EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR  *Descriptor
+  )
+{
+  USB_ASSOCIATION  *UsbIa;
+  EFI_TPL          OldTpl;
+  EFI_STATUS       Status;
+
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
+
+  Status = EFI_SUCCESS;
+
+  ASSERT (Descriptor != NULL);
+  if (Descriptor == NULL) {
+    Status = EFI_INVALID_PARAMETER;
+    goto ON_EXIT;
+  }
+
+  UsbIa = USB_ASSOCIATION_FROM_USBIA (This);
+  CopyMem (Descriptor, &(UsbIa->IaDesc->Desc), sizeof (EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR));
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+/**
+  Retrieve the details of the requested interface that belongs to USB association.
+
+  @param[in] This              A pointer to the EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL instance.
+  @param[in] InterfaceNumber   Interface number.
+  @param[out] UsbIo            A pointer to the caller allocated UsbIo protocol.
+  @param[out] SettingsCount    A pointer to the caller allocated number of settings for this interface.
+
+  @retval EFI_SUCCESS           Output parameters were updated successfully.
+  @retval EFI_INVALID_PARAMETER UsbIo or SettuntsCount is NULL.
+  @retval EFI_NOT_FOUND         Interface does not belong to this interface association.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbIaGetAssociateSettings (
+  IN  EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL  *This,
+  IN  UINT8                                     InterfaceNumber,
+  OUT EFI_USB_IO_PROTOCOL                       **UsbIo,
+  OUT UINTN                                     *SettingsCount
+  )
+{
+  USB_ASSOCIATION     *UsbIa;
+  EFI_TPL             OldTpl;
+  UINT8               Index;
+  EFI_STATUS          Status;
+  USB_DEVICE          *Device;
+  USB_INTERFACE_DESC  *IfDesc;
+
+  OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
+
+  ASSERT ((UsbIo != NULL) && (SettingsCount != NULL));
+  if ((UsbIo == NULL) || (SettingsCount == NULL)) {
+    Status =  EFI_INVALID_PARAMETER;
+    goto  ON_EXIT;
+  }
+
+  UsbIa = USB_ASSOCIATION_FROM_USBIA (This);
+
+  IfDesc = UsbAssocFindInterface (UsbIa, InterfaceNumber);
+  if (IfDesc == NULL) {
+    Status = EFI_NOT_FOUND;
+    goto ON_EXIT;
+  }
+
+  *SettingsCount = IfDesc->NumOfSetting - 1;
+
+  //
+  // Find UsbIo protocol for this interface
+  //
+  Device = UsbIa->Device;
+  Status = EFI_NOT_FOUND;
+
+  for (Index = 0; Index < Device->NumOfInterface; Index++) {
+    if (Device->Interfaces[Index]->IfSetting->Desc.InterfaceNumber == InterfaceNumber) {
+      *UsbIo = &Device->Interfaces[Index]->UsbIo;
+      Status = EFI_SUCCESS;
+      break;
+    }
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL  mUsbIaProtocol = {
+  UsbIaGetAssociationDescriptor,
+  UsbIaGetAssociateSettings
+};
diff --git a/MdeModulePkg/Include/Protocol/UsbAssociationIo.h b/MdeModulePkg/Include/Protocol/UsbAssociationIo.h
new file mode 100644
index 0000000000..2835dab5c0
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/UsbAssociationIo.h
@@ -0,0 +1,81 @@
+/** @file
+  EFI Usb Interface Association protocol.
+
+  This protocol is used by USB drivers, running in the EFI boot services
+  environment to access USB devices that implement their configurations
+  using interface association: USB cameras, USB audio devices, USB modems, etc.
+
+  Copyright (c) 2025, American Megatrends International LLC. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __USB_ASSOCIATION_IO_H__
+#define __USB_ASSOCIATION_IO_H__
+
+#include <IndustryStandard/Usb.h>
+#include <Protocol/UsbIo.h>
+
+typedef USB_INTERFACE_ASSOCIATION_DESCRIPTOR EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR;
+
+//
+// Global ID for the USB IAD Protocol
+//
+#define EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL_GUID \
+  { \
+    0xf4279fb1, 0xef1e, 0x4346, { 0xab, 0x32, 0x3f, 0xe3, 0x86, 0xee, 0xb4, 0x52 } \
+  }
+
+typedef struct _EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL;
+
+/**
+  Get the USB Interface Association Descriptor from the current USB configuration.
+
+  @param[in]  This              A pointer to the EFI_USB_IA_PROTOCOL instance.
+  @param[out]  Descriptor       A pointer to the caller allocated USB Interface Association Descriptor.
+
+  @retval EFI_SUCCESS           The descriptor was retrieved successfully.
+  @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_USB_IA_GET_ASSOCIATION_DESCRIPTOR)(
+  IN  EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL  *This,
+  OUT EFI_USB_INTERFACE_ASSOCIATION_DESCRIPTOR  *Descriptor
+  );
+
+/**
+  Retrieve the details of the requested interface that belongs to USB association.
+
+  @param[in] This              A pointer to the EFI_USB_IA_PROTOCOL instance.
+  @param[in] InterfaceNumber   Interface number.
+  @param[out] UsbIo            A pointer to the caller allocated UsbIo protocol.
+  @param[out] SettingsCount    A pointer to the caller allocated number of settings for this interface.
+
+  @retval EFI_SUCCESS           Output parameters were updated successfully.
+  @retval EFI_INVALID_PARAMETER UsbIo or SettuntsCount is NULL.
+  @retval EFI_NOT_FOUND         Interface does not belong to this interface association.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_USB_IA_GET_ASSOCIATE_SETTINGS)(
+  IN  EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL  *This,
+  IN  UINT8                                     InterfaceNumber,
+  OUT EFI_USB_IO_PROTOCOL                       **UsbIo,
+  OUT UINTN                                     *SettingsCount
+  );
+
+/**
+  USB interface association protocol functions.
+
+**/
+struct _EDKII_USB_INTERFACE_ASSOCIATION_PROTOCOL {
+  EDKII_USB_IA_GET_ASSOCIATION_DESCRIPTOR    UsbIaGetAssociationDescriptor;
+  EDKII_USB_IA_GET_ASSOCIATE_SETTINGS        UsbIaGetAssociateSettings;
+};
+
+extern EFI_GUID  gEdkiiUsbInterfaceAssociationProtocolGuid;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index b9bc7041f2..8bf118161c 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -10,6 +10,7 @@
 # Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 # Copyright (c) Microsoft Corporation.<BR>
 # Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (C) 2025 American Megatrends International, LLC. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -735,6 +736,9 @@
   ## Include/Protocol/PlatformBootManager.h
   gEdkiiPlatformBootManagerProtocolGuid = { 0xaa17add4, 0x756c, 0x460d, { 0x94, 0xb8, 0x43, 0x88, 0xd7, 0xfb, 0x3e, 0x59 } }
 
+  ## Include/Protocol/UsbAssociationIo.h
+  gEdkiiUsbInterfaceAssociationProtocolGuid = { 0xf4279fb1, 0xef1e, 0x4346, { 0xab, 0x32, 0x3f, 0xe3, 0x86, 0xee, 0xb4, 0x52 }}
+
 #
 # [Error.gEfiMdeModulePkgTokenSpaceGuid]
 #   0x80000001 | Invalid value provided.
